From 5f42ea7a1f16cffff1598680ccbfb7cc3a9bc81b Mon Sep 17 00:00:00 2001 From: Kolezhniuk Date: Fri, 3 Apr 2026 18:18:51 +0700 Subject: [PATCH 1/8] fix: update blake2b import path in multiple files refactor: change logger parameter to unused in exportFFlonkVk function fix: initialize variables pB and pS in zkey_new.js style: format code for consistency in witness_calculator.cjs test: update test timeouts to use beforeAll and afterAll hooks feat: add Groth16 test suite for zkSNARK verification feat: implement smart contract verifiers for Groth16, PLONK, and FFlonk chore: add Vite configuration for building and testing --- .eslintrc.cjs | 33 - .github/workflows/tests.yml | 91 +- .gitignore | 8 + browser_tests/package-lock.json | 1606 - browser_tests/package.json | 13 - browser_tests/test/groth16.html | 79 - browser_tests/test/launch-groth16.js | 47 - build/browser.esm.js | 22935 +++-------- build/cli.cjs | 25550 ++++++------ build/main.cjs | 20677 ++++------ build/snarkjs.js | 34275 ---------------- build/snarkjs.min.js | 194 +- cli.js | 2 +- config/rollup.browser.esm.config.js | 53 - config/rollup.cjs.config.js | 19 - config/rollup.cli.config.js | 20 - config/rollup.iife.config.js | 56 - config/rollup.iife_min.config.js | 15 - eslint.config.js | 34 + hardhat.config.js | 26 + package-lock.json | 4742 ++- package.json | 57 +- smart_contract_tests/.gitignore | 11 - smart_contract_tests/hardhat.config.cjs | 39 - smart_contract_tests/package-lock.json | 7832 ---- smart_contract_tests/package.json | 19 - .../test/smart_contracts.test.js | 245 - src/Keccak256Transcript.js | 2 +- src/clprocessor.js | 2 +- src/fflonk_export_calldata.js | 8 +- src/groth16_prove.js | 4 +- src/keypair.js | 2 +- src/misc.js | 5 +- src/plonk_equation.js | 2 +- src/plonk_exportsoliditycalldata.js | 8 +- src/plonk_prove.js | 2 +- src/plonk_setup.js | 6 +- src/polynomial/polynomial.js | 174 +- src/powersoftau_beacon.js | 2 +- src/powersoftau_challenge_contribute.js | 2 +- src/powersoftau_contribute.js | 2 +- src/powersoftau_convert.js | 3 +- src/powersoftau_export_challenge.js | 2 +- src/powersoftau_import.js | 2 +- src/powersoftau_new.js | 2 +- src/powersoftau_preparephase2.js | 4 +- src/powersoftau_utils.js | 2 +- src/powersoftau_verify.js | 2 +- src/taskmanager.js | 232 - src/zkey_beacon.js | 2 +- src/zkey_bellman_contribute.js | 2 +- src/zkey_contribute.js | 2 +- src/zkey_export_verificationkey.js | 2 +- src/zkey_new.js | 6 +- src/zkey_verify_frominit.js | 2 +- test/circuit2/circuit_js/generate_witness.cjs | 14 +- .../circuit_js/witness_calculator.cjs | 216 +- test/fflonk.test.js | 10 +- test/fullprocess.js | 6 +- test/groth16.test.js | 96 + test/keypar_test.js | 6 +- test/polynomial.test.js | 6 +- test/smart_contracts.test.js | 233 + vite.config.js | 162 + 64 files changed, 29139 insertions(+), 90774 deletions(-) delete mode 100644 .eslintrc.cjs delete mode 100644 browser_tests/package-lock.json delete mode 100644 browser_tests/package.json delete mode 100644 browser_tests/test/groth16.html delete mode 100644 browser_tests/test/launch-groth16.js mode change 100755 => 100644 build/cli.cjs delete mode 100644 build/snarkjs.js delete mode 100644 config/rollup.browser.esm.config.js delete mode 100644 config/rollup.cjs.config.js delete mode 100644 config/rollup.cli.config.js delete mode 100644 config/rollup.iife.config.js delete mode 100644 config/rollup.iife_min.config.js create mode 100644 eslint.config.js create mode 100644 hardhat.config.js delete mode 100644 smart_contract_tests/.gitignore delete mode 100644 smart_contract_tests/hardhat.config.cjs delete mode 100644 smart_contract_tests/package-lock.json delete mode 100644 smart_contract_tests/package.json delete mode 100644 smart_contract_tests/test/smart_contracts.test.js delete mode 100644 src/taskmanager.js create mode 100644 test/groth16.test.js create mode 100644 test/smart_contracts.test.js create mode 100644 vite.config.js diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index 2a39d0d1..00000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,33 +0,0 @@ -module.exports = { - "globals": { - "globalThis": false, // means it is not writeable - }, - "env": { - "es6": true, - "node": true, - "mocha": true - }, - "parserOptions": { - "ecmaVersion": 2022, - "sourceType": "module" - }, - "extends": "eslint:recommended", - "rules": { - "indent": [ - "error", - 4 - ], - "linebreak-style": [ - "error", - "unix" - ], - "quotes": [ - "error", - "double" - ], - "semi": [ - "error", - "always" - ] - } -}; diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 115b4389..79054ce0 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,98 +1,27 @@ name: Continuous Integration -on: - push: - branches: - - main - pull_request: +on: [push, pull_request] jobs: test: name: Test - runs-on: ${{ matrix.os }} - timeout-minutes: 30 - - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - node-version: [lts/*, lts/-1] + timeout-minutes: 15 + runs-on: ubuntu-latest steps: - name: Checkout project - uses: actions/checkout@v2 + uses: actions/checkout@v6 - - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 + - name: Setup Node.js + uses: actions/setup-node@v6 with: - node-version: ${{ matrix.node-version }} - check-latest: true + node-version: "lts/*" cache: "npm" - name: Install dependencies run: npm ci - - name: Run tests - run: npm test - - test-contracts: - name: Test verifier contracts - runs-on: ${{ matrix.os }} - timeout-minutes: 30 - - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest] - node-version: [lts/*] - - steps: - - name: Checkout project - uses: actions/checkout@v2 + - name: Install Playwright dependencies + run: npx playwright install - - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - check-latest: true - cache: "npm" - - - name: Install dependencies - run: npm ci - - - name: Install hardhat dependencies - working-directory: smart_contract_tests - run: npm ci - - - name: Run hardhat tests - working-directory: smart_contract_tests - run: npm test - - test-browser: - name: Test browser - runs-on: ${{ matrix.os }} - timeout-minutes: 30 - - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest] - node-version: [lts/*] - - steps: - - name: Checkout project - uses: actions/checkout@v2 - - - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - check-latest: true - cache: "npm" - - - name: Install browser dependencies - working-directory: browser_tests - run: npm ci - - - name: Run browser tests - working-directory: browser_tests + - name: Run tests run: npm test diff --git a/.gitignore b/.gitignore index aea8ef9b..1dd3c09e 100644 --- a/.gitignore +++ b/.gitignore @@ -68,3 +68,11 @@ tmp .DS_Store stats.html + +credentialAtomicQueryV3OnChain +generate.sh + +# Hardhat build outputs +contracts/ +cache/ +artifacts/ diff --git a/browser_tests/package-lock.json b/browser_tests/package-lock.json deleted file mode 100644 index 25fcd9f6..00000000 --- a/browser_tests/package-lock.json +++ /dev/null @@ -1,1606 +0,0 @@ -{ - "name": "snarkjs-browser-tests", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "snarkjs-browser-tests", - "devDependencies": { - "ffjavascript": "^0.3.0", - "puppeteer": "^23.5.3", - "st": "3.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.24.7", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@puppeteer/browsers": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.4.0.tgz", - "integrity": "sha512-x8J1csfIygOwf6D6qUAZ0ASk3z63zPb7wkNeHRerCMh82qWKUrOgkuP005AJC8lDL6/evtXETGEJVcwykKT4/g==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "debug": "^4.3.6", - "extract-zip": "^2.0.1", - "progress": "^2.0.3", - "proxy-agent": "^6.4.0", - "semver": "^7.6.3", - "tar-fs": "^3.0.6", - "unbzip2-stream": "^1.4.3", - "yargs": "^17.7.2" - }, - "bin": { - "browsers": "lib/cjs/main-cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@tootallnate/quickjs-emscripten": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "22.7.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", - "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "undici-types": "~6.19.2" - } - }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/ast-types": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", - "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/async-cache": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/async-cache/-/async-cache-1.1.0.tgz", - "integrity": "sha512-YDQc4vBn5NFhY6g6HhVshyi3Fy9+SQ5ePnE7JLDJn1DoL+i7ER+vMwtTNOYk9leZkYMnOwpBCWqyLDPw8Aig8g==", - "deprecated": "No longer maintained. Use [lru-cache](http://npm.im/lru-cache) version 7.6 or higher, and provide an asynchronous `fetchMethod` option.", - "dev": true, - "dependencies": { - "lru-cache": "^4.0.0" - } - }, - "node_modules/b4a": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", - "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/bare-events": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz", - "integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==", - "dev": true, - "license": "Apache-2.0", - "optional": true - }, - "node_modules/bare-fs": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.1.4.tgz", - "integrity": "sha512-r8+26Voz8dGX3AYpJdFb1ZPaUSM8XOLCZvy+YGpRTmwPHIxA7Z3Jov/oMPtV7hfRQbOnH8qGlLTzQAbgtdNN0Q==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "bare-events": "^2.5.4", - "bare-path": "^3.0.0", - "bare-stream": "^2.6.4" - }, - "engines": { - "bare": ">=1.16.0" - }, - "peerDependencies": { - "bare-buffer": "*" - }, - "peerDependenciesMeta": { - "bare-buffer": { - "optional": true - } - } - }, - "node_modules/bare-os": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.1.tgz", - "integrity": "sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "engines": { - "bare": ">=1.14.0" - } - }, - "node_modules/bare-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", - "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "bare-os": "^3.0.1" - } - }, - "node_modules/bare-stream": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.6.5.tgz", - "integrity": "sha512-jSmxKJNJmHySi6hC42zlZnq00rga4jjxcgNZjY9N5WlOe/iOoGRtdwGsHzQv2RlH2KOYMwGUXhf2zXd32BA9RA==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "streamx": "^2.21.0" - }, - "peerDependencies": { - "bare-buffer": "*", - "bare-events": "*" - }, - "peerDependenciesMeta": { - "bare-buffer": { - "optional": true - }, - "bare-events": { - "optional": true - } - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/basic-ftp": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", - "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/bl": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", - "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", - "dev": true, - "dependencies": { - "buffer": "^6.0.3", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chromium-bidi": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.8.0.tgz", - "integrity": "sha512-uJydbGdTw0DEUjhoogGveneJVWX/9YuqkWePzMmkBYwtdAqo5d3J/ovNKFr+/2hWXYmYCr6it8mSSTIj6SS6Ug==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "mitt": "3.0.1", - "urlpattern-polyfill": "10.0.0", - "zod": "3.23.8" - }, - "peerDependencies": { - "devtools-protocol": "*" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/cosmiconfig": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", - "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", - "dev": true, - "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/data-uri-to-buffer": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", - "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/degenerator": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", - "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ast-types": "^0.13.4", - "escodegen": "^2.1.0", - "esprima": "^4.0.1" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/devtools-protocol": { - "version": "0.0.1342118", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1342118.tgz", - "integrity": "sha512-75fMas7PkYNDTmDyb6PRJCH7ILmHLp+BhrZGeMsa4bCh40DTxgCz2NRy5UDzII4C5KuD0oBMZ9vXKhEl6UD/3w==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, - "node_modules/fast-fifo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/fd": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/fd/-/fd-0.0.3.tgz", - "integrity": "sha512-iAHrIslQb3U68OcMSP0kkNWabp7sSN6d2TBSb2JO3gcLJVDd4owr/hKM4SFJovFOUeeXeItjYgouEDTMWiVAnA==", - "dev": true - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/ffjavascript": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.3.0.tgz", - "integrity": "sha512-l7sR5kmU3gRwDy8g0Z2tYBXy5ttmafRPFOqY7S6af5cq51JqJWt5eQ/lSR/rs2wQNbDYaYlQr5O+OSUf/oMLoQ==", - "dev": true, - "dependencies": { - "wasmbuilder": "0.0.16", - "wasmcurves": "0.2.2", - "web-worker": "1.2.0" - } - }, - "node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-uri": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz", - "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==", - "dev": true, - "license": "MIT", - "dependencies": { - "basic-ftp": "^5.0.2", - "data-uri-to-buffer": "^6.0.2", - "debug": "^4.3.4", - "fs-extra": "^11.2.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/mitt": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", - "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", - "dev": true, - "license": "MIT" - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/pac-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz", - "integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==", - "dev": true, - "license": "MIT", - "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.5", - "pac-resolver": "^7.0.1", - "socks-proxy-agent": "^8.0.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-resolver": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", - "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", - "dev": true, - "license": "MIT", - "dependencies": { - "degenerator": "^5.0.0", - "netmask": "^2.0.2" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "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" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true, - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", - "dev": true - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/proxy-agent": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", - "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", - "dev": true, - "license": "MIT", - "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" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/proxy-agent/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true, - "license": "MIT" - }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/puppeteer": { - "version": "23.5.3", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-23.5.3.tgz", - "integrity": "sha512-FghmfBsr/UUpe48OiCg1gV3W4vVfQJKjQehbF07SjnQvEpWcvPTah1nykfGWdOQQ1ydJPIXcajzWN7fliCU3zw==", - "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@puppeteer/browsers": "2.4.0", - "chromium-bidi": "0.8.0", - "cosmiconfig": "^9.0.0", - "devtools-protocol": "0.0.1342118", - "puppeteer-core": "23.5.3", - "typed-query-selector": "^2.12.0" - }, - "bin": { - "puppeteer": "lib/cjs/puppeteer/node/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/puppeteer-core": { - "version": "23.5.3", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.5.3.tgz", - "integrity": "sha512-V58MZD/B3CwkYsqSEQlHKbavMJptF04fzhMdUpiCRCmUVhwZNwSGEPhaiZ1f8I3ABQUirg3VNhXVB6Z1ubHXtQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@puppeteer/browsers": "2.4.0", - "chromium-bidi": "0.8.0", - "debug": "^4.3.7", - "devtools-protocol": "0.0.1342118", - "typed-query-selector": "^2.12.0", - "ws": "^8.18.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", - "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", - "dev": true, - "license": "MIT", - "dependencies": { - "ip-address": "^9.0.5", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.8.3" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/st": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/st/-/st-3.0.0.tgz", - "integrity": "sha512-UEUi8P8Y5GOewlJbE5vrhsaQRwmbNVMUr6PLxRZHH4Cwz8CkHhnBqlqGtE3egXQd+ceUwNxdOVjsC/IsgN2Pww==", - "dev": true, - "dependencies": { - "async-cache": "^1.1.0", - "bl": "^5.0.0", - "fd": "~0.0.3", - "mime": "^2.5.2", - "negotiator": "~0.6.2" - }, - "bin": { - "st": "bin/server.js" - }, - "optionalDependencies": { - "graceful-fs": "^4.2.3" - } - }, - "node_modules/streamx": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.0.tgz", - "integrity": "sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-fifo": "^1.3.2", - "text-decoder": "^1.1.0" - }, - "optionalDependencies": { - "bare-events": "^2.2.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/tar-fs": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.8.tgz", - "integrity": "sha512-ZoROL70jptorGAlgAYiLoBLItEKw/fUxg9BSYK/dF/GAGYFJOJJJMvjPAKDJraCXFwadD456FCuvLWgfhMsPwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0", - "tar-stream": "^3.1.5" - }, - "optionalDependencies": { - "bare-fs": "^4.0.1", - "bare-path": "^3.0.0" - } - }, - "node_modules/tar-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", - "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" - } - }, - "node_modules/text-decoder": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.0.tgz", - "integrity": "sha512-n1yg1mOj9DNpk3NeZOx7T6jchTbyJS3i3cucbNN6FcdPriMZx7NsgrGpWWdWZZGxD7ES1XB+3uoqHMgOKaN+fg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "b4a": "^1.6.4" - } - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true, - "license": "MIT" - }, - "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", - "dev": true, - "license": "0BSD" - }, - "node_modules/typed-query-selector": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz", - "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==", - "dev": true, - "license": "MIT" - }, - "node_modules/unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^5.2.1", - "through": "^2.3.8" - } - }, - "node_modules/unbzip2-stream/node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/urlpattern-polyfill": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", - "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", - "dev": true, - "license": "MIT" - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/wasmbuilder": { - "version": "0.0.16", - "resolved": "https://registry.npmjs.org/wasmbuilder/-/wasmbuilder-0.0.16.tgz", - "integrity": "sha512-Qx3lEFqaVvp1cEYW7Bfi+ebRJrOiwz2Ieu7ZG2l7YyeSJIok/reEQCQCuicj/Y32ITIJuGIM9xZQppGx5LrQdA==", - "dev": true - }, - "node_modules/wasmcurves": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/wasmcurves/-/wasmcurves-0.2.2.tgz", - "integrity": "sha512-JRY908NkmKjFl4ytnTu5ED6AwPD+8VJ9oc94kdq7h5bIwbj0L4TDJ69mG+2aLs2SoCmGfqIesMWTEJjtYsoQXQ==", - "dev": true, - "dependencies": { - "wasmbuilder": "0.0.16" - } - }, - "node_modules/web-worker": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.2.0.tgz", - "integrity": "sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "license": "MIT", - "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" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/zod": { - "version": "3.23.8", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", - "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - } - } -} diff --git a/browser_tests/package.json b/browser_tests/package.json deleted file mode 100644 index 7dafe878..00000000 --- a/browser_tests/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "snarkjs-browser-tests", - "private": true, - "type": "module", - "scripts": { - "test": "node test/launch-groth16.js" - }, - "devDependencies": { - "puppeteer": "^23.5.3", - "ffjavascript": "^0.3.0", - "st": "3.0.0" - } -} diff --git a/browser_tests/test/groth16.html b/browser_tests/test/groth16.html deleted file mode 100644 index b6448181..00000000 --- a/browser_tests/test/groth16.html +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - Document - - - - - - - - - - - diff --git a/browser_tests/test/launch-groth16.js b/browser_tests/test/launch-groth16.js deleted file mode 100644 index d5a13360..00000000 --- a/browser_tests/test/launch-groth16.js +++ /dev/null @@ -1,47 +0,0 @@ -import puppeteer from "puppeteer"; -import st from "st"; -import http from "http"; -import url from "url"; - -const projectRoot = new URL("../..", import.meta.url); - -const mount = st({ path: url.fileURLToPath(projectRoot), passthrough: true }); - -const server = http - .createServer((req, res) => { - mount(req, res, () => res.end()); - }) - .listen(1337); - -const browser = await puppeteer.launch({ - headless: true, - args: [ - // Necessary to have WebCrypto on localhost - "--allow-insecure-localhost", - // Necessary to download the PTAU file from AWS within the tests - "--disable-web-security", - // Disable the sandbox to run in GHA - "--no-sandbox", - - ], -}); -const page = await browser.newPage(); - -page.on("console", (msg) => { - if (msg.type === "assert") { - throw new Error(msg.text()); - } else { - console.log(msg.text()); - } -}); - -page.on("pageerror", (err) => { - throw err; -}); - -await page.exposeFunction("shutdown", async () => { - await browser.close(); - server.close(); -}); - -await page.goto("http://localhost:1337/browser_tests/test/groth16.html"); diff --git a/build/browser.esm.js b/build/browser.esm.js index 49db18b3..413a3419 100644 --- a/build/browser.esm.js +++ b/build/browser.esm.js @@ -1,17395 +1,5556 @@ -import { Scalar, BigBuffer, buildBn128, buildBls12381, ChaCha, F1Field, utils, getCurveFromR as getCurveFromR$1 } from 'ffjavascript'; -import { constants } from 'node:fs'; - -var fs = {}; - -async function open$2(fileName, openFlags, cacheSize, pageSize) { - cacheSize = cacheSize || 4096*64; - if (typeof openFlags !== "number" && ["w+", "wx+", "r", "ax+", "a+"].indexOf(openFlags) <0) - throw new Error("Invalid open option"); - const fd =await fs.promises.open(fileName, openFlags); - - const stats = await fd.stat(); - - return new FastFile$2(fd, stats, cacheSize, pageSize, fileName); -} - - -class FastFile$2 { - - constructor(fd, stats, cacheSize, pageSize, fileName) { - this.fileName = fileName; - this.fd = fd; - this.pos = 0; - this.pageSize = pageSize || (1 << 8); - while (this.pageSize < stats.blksize) { - this.pageSize *= 2; - } - this.totalSize = stats.size; - this.totalPages = Math.floor((stats.size -1) / this.pageSize)+1; - this.maxPagesLoaded = Math.floor( cacheSize / this.pageSize)+1; - this.pages = {}; - this.pendingLoads = []; - this.writing = false; - this.reading = false; - this.avBuffs = []; - this.history = {}; - } - - _loadPage(p) { - const self = this; - const P = new Promise((resolve, reject)=> { - self.pendingLoads.push({ - page: p, - resolve: resolve, - reject: reject - }); - }); - self.__statusPage("After Load request: ", p); - return P; - } - - __statusPage(s, p) { - const logEntry = []; - const self=this; - if (!self.logHistory) return; - logEntry.push("==" + s+ " " +p); - let S = ""; - for (let i=0; i " + self.history[p][i][j]); - } - } - } - - - - _triggerLoad() { - const self = this; - - if (self.reading) return; - if (self.pendingLoads.length==0) return; - - const pageIdxs = Object.keys(self.pages); - - const deletablePages = []; - for (let i=0; i0) && - ( (typeof self.pages[self.pendingLoads[0].page] != "undefined" ) - ||( (freePages>0) - ||(deletablePages.length>0)))) { - const load = self.pendingLoads.shift(); - if (typeof self.pages[load.page] != "undefined") { - self.pages[load.page].pendingOps ++; - const idx = deletablePages.indexOf(load.page); - if (idx>=0) deletablePages.splice(idx, 1); - if (self.pages[load.page].loading) { - self.pages[load.page].loading.push(load); - } else { - load.resolve(); - } - self.__statusPage("After Load (cached): ", load.page); - - } else { - if (freePages) { - freePages--; - } else { - const fp = deletablePages.shift(); - self.__statusPage("Before Unload: ", fp); - self.avBuffs.unshift(self.pages[fp]); - delete self.pages[fp]; - self.__statusPage("After Unload: ", fp); - } - - if (load.page>=self.totalPages) { - self.pages[load.page] = getNewPage(); - load.resolve(); - self.__statusPage("After Load (new): ", load.page); - } else { - self.reading = true; - self.pages[load.page] = getNewPage(); - self.pages[load.page].loading = [load]; - ops.push(self.fd.read(self.pages[load.page].buff, 0, self.pageSize, load.page*self.pageSize).then((res)=> { - self.pages[load.page].size = res.bytesRead; - const loading = self.pages[load.page].loading; - delete self.pages[load.page].loading; - for (let i=0; i { - load.reject(err); - })); - self.__statusPage("After Load (loading): ", load.page); - } - } - } - // if (ops.length>1) console.log(ops.length); - - Promise.all(ops).then( () => { - self.reading = false; - if (self.pendingLoads.length>0) setImmediate(self._triggerLoad.bind(self)); - self._tryClose(); - }); - - function getNewPage() { - if (self.avBuffs.length>0) { - const p = self.avBuffs.shift(); - p.dirty = false; - p.pendingOps = 1; - p.size =0; - return p; - } else { - return { - dirty: false, - buff: new Uint8Array(self.pageSize), - pendingOps: 1, - size: 0 - }; - } - } - - } - - - _triggerWrite() { - const self = this; - if (self.writing) return; - - const pageIdxs = Object.keys(self.pages); - - const ops = []; - - for (let i=0; i { - page.writing = false; - return; - }, (err) => { - console.log("ERROR Writing: "+err); - self.error = err; - self._tryClose(); - })); - } - } - - if (self.writing) { - Promise.all(ops).then( () => { - self.writing = false; - setImmediate(self._triggerWrite.bind(self)); - self._tryClose(); - if (self.pendingLoads.length>0) setImmediate(self._triggerLoad.bind(self)); - }); - } - } - - _getDirtyPage() { - for (let p in this.pages) { - if (this.pages[p].dirty) return p; - } - return -1; - } - - async write(buff, pos) { - if (buff.byteLength == 0) return; - const self = this; - /* - if (buff.byteLength > self.pageSize*self.maxPagesLoaded*0.8) { - const cacheSize = Math.floor(buff.byteLength * 1.1); - this.maxPagesLoaded = Math.floor( cacheSize / self.pageSize)+1; - } - */ - if (typeof pos == "undefined") pos = self.pos; - self.pos = pos+buff.byteLength; - if (self.totalSize < pos + buff.byteLength) self.totalSize = pos + buff.byteLength; - if (self.pendingClose) - throw new Error("Writing a closing file"); - const firstPage = Math.floor(pos / self.pageSize); - const lastPage = Math.floor((pos + buff.byteLength -1) / self.pageSize); - - const pagePromises = []; - for (let i=firstPage; i<=lastPage; i++) pagePromises.push(self._loadPage(i)); - self._triggerLoad(); - - let p = firstPage; - let o = pos % self.pageSize; - let r = buff.byteLength; - while (r>0) { - await pagePromises[p-firstPage]; - const l = (o+r > self.pageSize) ? (self.pageSize -o) : r; - const srcView = buff.slice( buff.byteLength - r, buff.byteLength - r + l); - const dstView = new Uint8Array(self.pages[p].buff.buffer, o, l); - dstView.set(srcView); - self.pages[p].dirty = true; - self.pages[p].pendingOps --; - self.pages[p].size = Math.max(o+l, self.pages[p].size); - if (p>=self.totalPages) { - self.totalPages = p+1; - } - r = r-l; - p ++; - o = 0; - if (!self.writing) setImmediate(self._triggerWrite.bind(self)); - } - } - - async read(len, pos) { - const self = this; - let buff = new Uint8Array(len); - await self.readToBuffer(buff, 0, len, pos); - - return buff; - } - - async readToBuffer(buffDst, offset, len, pos) { - if (len == 0) { - return; - } - const self = this; - if (len > self.pageSize*self.maxPagesLoaded*0.8) { - const cacheSize = Math.floor(len * 1.1); - this.maxPagesLoaded = Math.floor( cacheSize / self.pageSize)+1; - } - if (typeof pos == "undefined") pos = self.pos; - self.pos = pos+len; - if (self.pendingClose) - throw new Error("Reading a closing file"); - const firstPage = Math.floor(pos / self.pageSize); - const lastPage = Math.floor((pos + len -1) / self.pageSize); - - const pagePromises = []; - for (let i=firstPage; i<=lastPage; i++) pagePromises.push(self._loadPage(i)); - - self._triggerLoad(); - - let p = firstPage; - let o = pos % self.pageSize; - // Remaining bytes to read - let r = pos + len > self.totalSize ? len - (pos + len - self.totalSize): len; - while (r>0) { - await pagePromises[p - firstPage]; - self.__statusPage("After Await (read): ", p); - - // bytes to copy from this page - const l = (o+r > self.pageSize) ? (self.pageSize -o) : r; - const srcView = new Uint8Array(self.pages[p].buff.buffer, self.pages[p].buff.byteOffset + o, l); - buffDst.set(srcView, offset+len-r); - self.pages[p].pendingOps --; - - self.__statusPage("After Op done: ", p); - - r = r-l; - p ++; - o = 0; - if (self.pendingLoads.length>0) setImmediate(self._triggerLoad.bind(self)); - } - - this.pos = pos + len; - - } - - - _tryClose() { - const self = this; - if (!self.pendingClose) return; - if (self.error) { - self.pendingCloseReject(self.error); - } - const p = self._getDirtyPage(); - if ((p>=0) || (self.writing) || (self.reading) || (self.pendingLoads.length>0)) return; - self.pendingClose(); - } - - close() { - const self = this; - if (self.pendingClose) - throw new Error("Closing the file twice"); - return new Promise((resolve, reject) => { - self.pendingClose = resolve; - self.pendingCloseReject = reject; - self._tryClose(); - }).then(()=> { - self.fd.close(); - }, (err) => { - self.fd.close(); - throw (err); - }); - } - - async discard() { - const self = this; - await self.close(); - await fs.promises.unlink(this.fileName); - } - - async writeULE32(v, pos) { - const self = this; - const tmpBuff32 = new Uint8Array(4); - const tmpBuff32v = new DataView(tmpBuff32.buffer); - - tmpBuff32v.setUint32(0, v, true); - - await self.write(tmpBuff32, pos); - } - - async writeUBE32(v, pos) { - const self = this; - - const tmpBuff32 = new Uint8Array(4); - const tmpBuff32v = new DataView(tmpBuff32.buffer); - - tmpBuff32v.setUint32(0, v, false); - - await self.write(tmpBuff32, pos); - } - - - async writeULE64(v, pos) { - const self = this; - - const tmpBuff64 = new Uint8Array(8); - const tmpBuff64v = new DataView(tmpBuff64.buffer); - - tmpBuff64v.setUint32(0, v & 0xFFFFFFFF, true); - tmpBuff64v.setUint32(4, Math.floor(v / 0x100000000) , true); - - await self.write(tmpBuff64, pos); - } - - async readULE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new Uint32Array(b.buffer); - - return view[0]; - } - - async readUBE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new DataView(b.buffer); - - return view.getUint32(0, false); - } - - async readULE64(pos) { - const self = this; - const b = await self.read(8, pos); - - const view = new Uint32Array(b.buffer); - - return view[1] * 0x100000000 + view[0]; - } - - async readString(pos) { - const self = this; - - if (self.pendingClose) { - throw new Error("Reading a closing file"); - } - - let currentPosition = typeof pos == "undefined" ? self.pos : pos; - let currentPage = Math.floor(currentPosition / self.pageSize); - - let endOfStringFound = false; - let str = ""; - - while (!endOfStringFound) { - //Read page - let pagePromise = self._loadPage(currentPage); - self._triggerLoad(); - await pagePromise; - self.__statusPage("After Await (read): ", currentPage); - - let offsetOnPage = currentPosition % self.pageSize; - - const dataArray = new Uint8Array( - self.pages[currentPage].buff.buffer, - self.pages[currentPage].buff.byteOffset + offsetOnPage, - self.pageSize - offsetOnPage - ); - - let indexEndOfString = dataArray.findIndex(element => element === 0); - endOfStringFound = indexEndOfString !== -1; - - if (endOfStringFound) { - str += new TextDecoder().decode(dataArray.slice(0, indexEndOfString)); - self.pos = currentPage * this.pageSize + offsetOnPage + indexEndOfString + 1; - } else { - str += new TextDecoder().decode(dataArray); - self.pos = currentPage * this.pageSize + offsetOnPage + dataArray.length; - } - - self.pages[currentPage].pendingOps--; - self.__statusPage("After Op done: ", currentPage); - - currentPosition = self.pos; - currentPage++; - - if (self.pendingLoads.length > 0) setImmediate(self._triggerLoad.bind(self)); - } - - return str; - } -} - -function createNew$3(o) { - const initialSize = o.initialSize || 1<<20; - const fd = new MemFile$2(); - fd.o = o; - fd.o.data = new Uint8Array(initialSize); - fd.allocSize = initialSize; - fd.totalSize = 0; - fd.readOnly = false; - fd.pos = 0; - return fd; -} - -function readExisting$8(o) { - const fd = new MemFile$2(); - fd.o = o; - fd.allocSize = o.data.byteLength; - fd.totalSize = o.data.byteLength; - fd.readOnly = true; - fd.pos = 0; - return fd; -} - -const tmpBuff32$5 = new Uint8Array(4); -const tmpBuff32v$5 = new DataView(tmpBuff32$5.buffer); -const tmpBuff64$5 = new Uint8Array(8); -const tmpBuff64v$5 = new DataView(tmpBuff64$5.buffer); - -class MemFile$2 { - - constructor() { - this.pageSize = 1 << 14; // for compatibility - } - - _resizeIfNeeded(newLen) { - if (newLen > this.allocSize) { - const newAllocSize = Math.max( - this.allocSize + (1 << 20), - Math.floor(this.allocSize * 1.1), - newLen - ); - const newData = new Uint8Array(newAllocSize); - newData.set(this.o.data); - this.o.data = newData; - this.allocSize = newAllocSize; - } - } - - async write(buff, pos) { - const self =this; - if (typeof pos == "undefined") pos = self.pos; - if (this.readOnly) throw new Error("Writing a read only file"); - - this._resizeIfNeeded(pos + buff.byteLength); - - this.o.data.set(buff.slice(), pos); - - if (pos + buff.byteLength > this.totalSize) this.totalSize = pos + buff.byteLength; - - this.pos = pos + buff.byteLength; - } - - async readToBuffer(buffDest, offset, len, pos) { - const self = this; - if (typeof pos == "undefined") pos = self.pos; - if (this.readOnly) { - if (pos + len > this.totalSize) throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos + len); - - const buffSrc = new Uint8Array(this.o.data.buffer, this.o.data.byteOffset + pos, len); - - buffDest.set(buffSrc, offset); - - this.pos = pos + len; - } - - async read(len, pos) { - const self = this; - - const buff = new Uint8Array(len); - await self.readToBuffer(buff, 0, len, pos); - - return buff; - } - - close() { - if (this.o.data.byteLength != this.totalSize) { - this.o.data = this.o.data.slice(0, this.totalSize); - } - } - - async discard() { - } - - - async writeULE32(v, pos) { - const self = this; - - tmpBuff32v$5.setUint32(0, v, true); - - await self.write(tmpBuff32$5, pos); - } - - async writeUBE32(v, pos) { - const self = this; - - tmpBuff32v$5.setUint32(0, v, false); - - await self.write(tmpBuff32$5, pos); - } - - - async writeULE64(v, pos) { - const self = this; - - tmpBuff64v$5.setUint32(0, v & 0xFFFFFFFF, true); - tmpBuff64v$5.setUint32(4, Math.floor(v / 0x100000000) , true); - - await self.write(tmpBuff64$5, pos); - } - - - async readULE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new Uint32Array(b.buffer); - - return view[0]; - } - - async readUBE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new DataView(b.buffer); - - return view.getUint32(0, false); - } - - async readULE64(pos) { - const self = this; - const b = await self.read(8, pos); - - const view = new Uint32Array(b.buffer); - - return view[1] * 0x100000000 + view[0]; - } - - async readString(pos) { - const self = this; - - let currentPosition = typeof pos == "undefined" ? self.pos : pos; - - if (currentPosition > this.totalSize) { - if (this.readOnly) { - throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos); - } - const dataArray = new Uint8Array( - self.o.data.buffer, - currentPosition, - this.totalSize - currentPosition - ); - - let indexEndOfString = dataArray.findIndex(element => element === 0); - let endOfStringFound = indexEndOfString !== -1; - - let str = ""; - if (endOfStringFound) { - str = new TextDecoder().decode(dataArray.slice(0, indexEndOfString)); - self.pos = currentPosition + indexEndOfString + 1; - } else { - self.pos = currentPosition; - } - return str; - } -} - -const PAGE_SIZE$2 = 1<<22; - -function createNew$2(o) { - const initialSize = o.initialSize || 0; - const fd = new BigMemFile$2(); - fd.o = o; - const nPages = initialSize ? Math.floor((initialSize - 1) / PAGE_SIZE$2)+1 : 0; - fd.o.data = []; - for (let i=0; i0) { - const l = (o+r > PAGE_SIZE$2) ? (PAGE_SIZE$2 -o) : r; - const srcView = buff.slice(buff.byteLength - r, buff.byteLength - r + l); - const dstView = new Uint8Array(self.o.data[p].buffer, o, l); - dstView.set(srcView); - r = r-l; - p ++; - o = 0; - } - - this.pos = pos + buff.byteLength; - } - - async readToBuffer(buffDst, offset, len, pos) { - const self = this; - if (typeof pos == "undefined") pos = self.pos; - if (this.readOnly) { - if (pos + len > this.totalSize) throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos + len); - - const firstPage = Math.floor(pos / PAGE_SIZE$2); - - let p = firstPage; - let o = pos % PAGE_SIZE$2; - // Remaining bytes to read - let r = len; - while (r>0) { - // bytes to copy from this page - const l = (o+r > PAGE_SIZE$2) ? (PAGE_SIZE$2 -o) : r; - const srcView = new Uint8Array(self.o.data[p].buffer, o, l); - buffDst.set(srcView, offset+len-r); - r = r-l; - p ++; - o = 0; - } - - this.pos = pos + len; - } - - async read(len, pos) { - const self = this; - const buff = new Uint8Array(len); - - await self.readToBuffer(buff, 0, len, pos); - - return buff; - } - - close() { - } - - async discard() { - } - - - async writeULE32(v, pos) { - const self = this; - - tmpBuff32v$4.setUint32(0, v, true); - - await self.write(tmpBuff32$4, pos); - } - - async writeUBE32(v, pos) { - const self = this; - - tmpBuff32v$4.setUint32(0, v, false); - - await self.write(tmpBuff32$4, pos); - } - - - async writeULE64(v, pos) { - const self = this; - - tmpBuff64v$4.setUint32(0, v & 0xFFFFFFFF, true); - tmpBuff64v$4.setUint32(4, Math.floor(v / 0x100000000) , true); - - await self.write(tmpBuff64$4, pos); - } - - - async readULE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new Uint32Array(b.buffer); - - return view[0]; - } - - async readUBE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new DataView(b.buffer); - - return view.getUint32(0, false); - } - - async readULE64(pos) { - const self = this; - const b = await self.read(8, pos); - - const view = new Uint32Array(b.buffer); - - return view[1] * 0x100000000 + view[0]; - } - - async readString(pos) { - const self = this; - const fixedSize = 2048; - - let currentPosition = typeof pos == "undefined" ? self.pos : pos; - - if (currentPosition > this.totalSize) { - if (this.readOnly) { - throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos); - } - - let endOfStringFound = false; - let str = ""; - - while (!endOfStringFound) { - let currentPage = Math.floor(currentPosition / PAGE_SIZE$2); - let offsetOnPage = currentPosition % PAGE_SIZE$2; - - if (self.o.data[currentPage] === undefined) { - throw new Error("ERROR"); - } - - let readLength = Math.min(fixedSize, self.o.data[currentPage].length - offsetOnPage); - const dataArray = new Uint8Array(self.o.data[currentPage].buffer, offsetOnPage, readLength); - - let indexEndOfString = dataArray.findIndex(element => element === 0); - endOfStringFound = indexEndOfString !== -1; - - if (endOfStringFound) { - str += new TextDecoder().decode(dataArray.slice(0, indexEndOfString)); - self.pos = currentPage * PAGE_SIZE$2 + offsetOnPage + indexEndOfString + 1; - } else { - str += new TextDecoder().decode(dataArray); - self.pos = currentPage * PAGE_SIZE$2 + offsetOnPage + dataArray.length; - } - - currentPosition = self.pos; - } - return str; - } -} - -const { O_TRUNC: O_TRUNC$1, O_CREAT: O_CREAT$1, O_RDWR: O_RDWR$1, O_EXCL, O_RDONLY: O_RDONLY$1 } = constants; - -const DEFAULT_CACHE_SIZE$1 = (1 << 16); -const DEFAULT_PAGE_SIZE$1 = (1 << 13); - - -async function createOverride$1(o, b, c) { - if (typeof o === "string") { - o = { - type: "file", - fileName: o, - cacheSize: b || DEFAULT_CACHE_SIZE$1, - pageSize: c || DEFAULT_PAGE_SIZE$1 - }; - } - if (o.type == "file") { - return await open$2(o.fileName, O_TRUNC$1 | O_CREAT$1 | O_RDWR$1, o.cacheSize, o.pageSize); - } else if (o.type == "mem") { - return createNew$3(o); - } else if (o.type == "bigMem") { - return createNew$2(o); - } else { - throw new Error("Invalid FastFile type: "+o.type); - } -} - -async function readExisting$6(o, b, c) { - if (o instanceof Uint8Array) { - o = { - type: "mem", - data: o - }; - } - { - if (typeof o === "string") { - const buff = await fetch(o).then( function(res) { - return res.arrayBuffer(); - }).then(function (ab) { - return new Uint8Array(ab); - }); - o = { - type: "mem", - data: buff - }; - } - } - if (o.type == "file") { - return await open$2(o.fileName, O_RDONLY$1, o.cacheSize, o.pageSize); - } else if (o.type == "mem") { - return await readExisting$8(o); - } else if (o.type == "bigMem") { - return await readExisting$7(o); - } else { - throw new Error("Invalid FastFile type: "+o.type); - } -} - -const MAX_BUFFER_SIZE = ( typeof Buffer !== "undefined" && Buffer.constants && Buffer.constants.MAX_LENGTH ) ? Buffer.constants.MAX_LENGTH : (1 << 30); - -async function readBinFile$1(fileName, type, maxVersion, cacheSize, pageSize) { - - const fd = await readExisting$6(fileName); - - const b = await fd.read(4); - let readedType = ""; - for (let i=0; i<4; i++) readedType += String.fromCharCode(b[i]); - - if (readedType != type) throw new Error(fileName + ": Invalid File format"); - - let v = await fd.readULE32(); - - if (v>maxVersion) throw new Error("Version not supported"); - - const nSections = await fd.readULE32(); - - // Scan sections - let sections = []; - for (let i=0; i1) throw new Error(fd.fileName +": Section Duplicated " +idSection); - - fd.pos = sections[idSection][0].p; - - fd.readingSection = sections[idSection][0]; -} - -async function endReadSection$1(fd, noCheck) { - if (typeof fd.readingSection === "undefined") throw new Error("Not reading a section"); - if (!noCheck) { - if (fd.pos-fd.readingSection.p != fd.readingSection.size) throw new Error("Invalid section size reading"); - } - delete fd.readingSection; -} - -async function writeBigInt(fd, n, n8, pos) { - const buff = new Uint8Array(n8); - Scalar.toRprLE(buff, 0, n, n8); - await fd.write(buff, pos); -} - -async function readBigInt$1(fd, n8, pos) { - const buff = await fd.read(n8, pos); - return Scalar.fromRprLE(buff, 0, n8); -} - -async function copySection(fdFrom, sections, fdTo, sectionId, size) { - if (typeof size === "undefined") { - size = sections[sectionId][0].size; - } - const chunkSize = fdFrom.pageSize; - await startReadUniqueSection$1(fdFrom, sections, sectionId); - await startWriteSection(fdTo, sectionId); - for (let p=0; p= 0) { - curve = await buildBn128(singleThread); - } else if (["BLS12381"].indexOf(normName) >= 0) { - curve = await buildBls12381(singleThread); - } else { - throw new Error(`Curve not supported: ${name}`); - } - return curve; - - function normalizeName(n) { - return n.toUpperCase().match(/[A-Za-z0-9]+/g).join(""); - } - -} - -var curves = /*#__PURE__*/Object.freeze({ - __proto__: null, - getCurveFromR: getCurveFromR, - getCurveFromQ: getCurveFromQ, - getCurveFromName: getCurveFromName +import * as e from "@iden3/binfileutils"; +import { createBinFile as t, endWriteSection as n, readBinFile as r, readSection as i, startWriteSection as a, writeBigInt as o } from "@iden3/binfileutils"; +import { BigBuffer as s, ChaCha as c, F1Field as l, Scalar as u, buildBls12381 as d, buildBn128 as f, utils as p } from "ffjavascript"; +import { readR1cs as m, readR1csFd as h, readR1csHeader as g } from "r1csfile"; +//#region \0rolldown/runtime.js +var _ = Object.defineProperty, v = (e, t) => () => (t || e((t = { exports: {} }).exports, t), t.exports), y = (e, t) => { + let n = {}; + for (var r in e) _(n, r, { + get: e[r], + enumerable: !0 + }); + return t || _(n, Symbol.toStringTag, { value: "Module" }), n; +}, b = /* @__PURE__ */ y({ + getCurveFromName: () => D, + getCurveFromQ: () => E, + getCurveFromR: () => T +}), x = u.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16), S = u.e("21888242871839275222246405745257275088548364400416034343698204186575808495617"), C = u.e("1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", 16), w = u.e("21888242871839275222246405745257275088696311157297823662689037894645226208583"); +async function T(e, t) { + let n, r = t && t.singleThread; + if (u.eq(e, S)) n = await f(r); + else if (u.eq(e, x)) n = await d(r); + else throw Error(`Curve not supported: ${u.toString(e)}`); + return n; +} +async function E(e, t) { + let n, r = t && t.singleThread; + if (u.eq(e, w)) n = await f(r); + else if (u.eq(e, C)) n = await d(r); + else throw Error(`Curve not supported: ${u.toString(e)}`); + return n; +} +async function D(e, t) { + let n, r = t && t.singleThread, i = a(e); + if ([ + "BN128", + "BN254", + "ALTBN128" + ].indexOf(i) >= 0) n = await f(r); + else if (["BLS12381"].indexOf(i) >= 0) n = await d(r); + else throw Error(`Curve not supported: ${e}`); + return n; + function a(e) { + return e.toUpperCase().match(/[A-Za-z0-9]+/g).join(""); + } +} +//#endregion +//#region node_modules/@noble/hashes/utils.js +function O(e) { + return e instanceof Uint8Array || ArrayBuffer.isView(e) && e.constructor.name === "Uint8Array"; +} +function k(e, t = "") { + if (!Number.isSafeInteger(e) || e < 0) { + let n = t && `"${t}" `; + throw Error(`${n}expected integer >= 0, got ${e}`); + } +} +function A(e, t, n = "") { + let r = O(e), i = e?.length, a = t !== void 0; + if (!r || a && i !== t) { + let o = n && `"${n}" `, s = a ? ` of length ${t}` : "", c = r ? `length=${i}` : `type=${typeof e}`; + throw Error(o + "expected Uint8Array" + s + ", got " + c); + } + return e; +} +function j(e, t = !0) { + if (e.destroyed) throw Error("Hash instance has been destroyed"); + if (t && e.finished) throw Error("Hash#digest() has already been called"); +} +function M(e, t) { + A(e, void 0, "digestInto() output"); + let n = t.outputLen; + if (e.length < n) throw Error("\"digestInto() output\" expected to be of length >=" + n); +} +function N(e) { + return new Uint32Array(e.buffer, e.byteOffset, Math.floor(e.byteLength / 4)); +} +function P(...e) { + for (let t = 0; t < e.length; t++) e[t].fill(0); +} +var F = new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68; +function I(e) { + return e << 24 & 4278190080 | e << 8 & 16711680 | e >>> 8 & 65280 | e >>> 24 & 255; +} +var L = F ? (e) => e : (e) => I(e); +function ee(e) { + for (let t = 0; t < e.length; t++) e[t] = I(e[t]); + return e; +} +var R = F ? (e) => e : ee; +typeof Uint8Array.from([]).toHex == "function" && Uint8Array.fromHex; +function z(e, t = {}) { + let n = (t, n) => e(n).update(t).digest(), r = e(void 0); + return n.outputLen = r.outputLen, n.blockLen = r.blockLen, n.create = (t) => e(t), Object.assign(n, t), Object.freeze(n); +} +//#endregion +//#region node_modules/@noble/hashes/_blake.js +var B = /* @__PURE__ */ Uint8Array.from([ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 14, + 10, + 4, + 8, + 9, + 15, + 13, + 6, + 1, + 12, + 0, + 2, + 11, + 7, + 5, + 3, + 11, + 8, + 12, + 0, + 5, + 2, + 15, + 13, + 10, + 14, + 3, + 6, + 7, + 1, + 9, + 4, + 7, + 9, + 3, + 1, + 13, + 12, + 11, + 14, + 2, + 6, + 5, + 10, + 4, + 0, + 15, + 8, + 9, + 0, + 5, + 7, + 2, + 4, + 10, + 15, + 14, + 1, + 11, + 12, + 6, + 8, + 3, + 13, + 2, + 12, + 6, + 10, + 0, + 11, + 8, + 3, + 4, + 13, + 7, + 5, + 15, + 14, + 1, + 9, + 12, + 5, + 1, + 15, + 14, + 13, + 4, + 10, + 0, + 7, + 6, + 3, + 9, + 2, + 8, + 11, + 13, + 11, + 7, + 14, + 12, + 1, + 3, + 9, + 5, + 0, + 15, + 4, + 8, + 6, + 2, + 10, + 6, + 15, + 14, + 9, + 11, + 3, + 0, + 8, + 12, + 2, + 13, + 7, + 1, + 4, + 10, + 5, + 10, + 2, + 8, + 4, + 7, + 6, + 1, + 5, + 15, + 11, + 9, + 14, + 3, + 12, + 13, + 0, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 14, + 10, + 4, + 8, + 9, + 15, + 13, + 6, + 1, + 12, + 0, + 2, + 11, + 7, + 5, + 3, + 11, + 8, + 12, + 0, + 5, + 2, + 15, + 13, + 10, + 14, + 3, + 6, + 7, + 1, + 9, + 4, + 7, + 9, + 3, + 1, + 13, + 12, + 11, + 14, + 2, + 6, + 5, + 10, + 4, + 0, + 15, + 8, + 9, + 0, + 5, + 7, + 2, + 4, + 10, + 15, + 14, + 1, + 11, + 12, + 6, + 8, + 3, + 13, + 2, + 12, + 6, + 10, + 0, + 11, + 8, + 3, + 4, + 13, + 7, + 5, + 15, + 14, + 1, + 9 +]), V = /* @__PURE__ */ BigInt(2 ** 32 - 1), te = /* @__PURE__ */ BigInt(32); +function H(e, t = !1) { + return t ? { + h: Number(e & V), + l: Number(e >> te & V) + } : { + h: Number(e >> te & V) | 0, + l: Number(e & V) | 0 + }; +} +function U(e, t = !1) { + let n = e.length, r = new Uint32Array(n), i = new Uint32Array(n); + for (let a = 0; a < n; a++) { + let { h: n, l: o } = H(e[a], t); + [r[a], i[a]] = [n, o]; + } + return [r, i]; +} +var ne = (e, t, n) => e >>> n | t << 32 - n, re = (e, t, n) => e << 32 - n | t >>> n, ie = (e, t, n) => e << 64 - n | t >>> n - 32, ae = (e, t, n) => e >>> n - 32 | t << 64 - n, oe = (e, t) => t, se = (e, t) => e, ce = (e, t, n) => e << n | t >>> 32 - n, le = (e, t, n) => t << n | e >>> 32 - n, ue = (e, t, n) => t << n - 32 | e >>> 64 - n, de = (e, t, n) => e << n - 32 | t >>> 64 - n; +function fe(e, t, n, r) { + let i = (t >>> 0) + (r >>> 0); + return { + h: e + n + (i / 2 ** 32 | 0) | 0, + l: i | 0 + }; +} +var pe = (e, t, n) => (e >>> 0) + (t >>> 0) + (n >>> 0), me = (e, t, n, r) => t + n + r + (e / 2 ** 32 | 0) | 0, W = /* @__PURE__ */ Uint32Array.from([ + 4089235720, + 1779033703, + 2227873595, + 3144134277, + 4271175723, + 1013904242, + 1595750129, + 2773480762, + 2917565137, + 1359893119, + 725511199, + 2600822924, + 4215389547, + 528734635, + 327033209, + 1541459225 +]), G = /* @__PURE__ */ new Uint32Array(32); +function he(e, t, n, r, i, a) { + let o = i[a], s = i[a + 1], c = G[2 * e], l = G[2 * e + 1], u = G[2 * t], d = G[2 * t + 1], f = G[2 * n], p = G[2 * n + 1], m = G[2 * r], h = G[2 * r + 1], g = pe(c, u, o); + l = me(g, l, d, s), c = g | 0, {Dh: h, Dl: m} = { + Dh: h ^ l, + Dl: m ^ c + }, {Dh: h, Dl: m} = { + Dh: oe(h, m), + Dl: se(h, m) + }, {h: p, l: f} = fe(p, f, h, m), {Bh: d, Bl: u} = { + Bh: d ^ p, + Bl: u ^ f + }, {Bh: d, Bl: u} = { + Bh: ne(d, u, 24), + Bl: re(d, u, 24) + }, G[2 * e] = c, G[2 * e + 1] = l, G[2 * t] = u, G[2 * t + 1] = d, G[2 * n] = f, G[2 * n + 1] = p, G[2 * r] = m, G[2 * r + 1] = h; +} +function ge(e, t, n, r, i, a) { + let o = i[a], s = i[a + 1], c = G[2 * e], l = G[2 * e + 1], u = G[2 * t], d = G[2 * t + 1], f = G[2 * n], p = G[2 * n + 1], m = G[2 * r], h = G[2 * r + 1], g = pe(c, u, o); + l = me(g, l, d, s), c = g | 0, {Dh: h, Dl: m} = { + Dh: h ^ l, + Dl: m ^ c + }, {Dh: h, Dl: m} = { + Dh: ne(h, m, 16), + Dl: re(h, m, 16) + }, {h: p, l: f} = fe(p, f, h, m), {Bh: d, Bl: u} = { + Bh: d ^ p, + Bl: u ^ f + }, {Bh: d, Bl: u} = { + Bh: ie(d, u, 63), + Bl: ae(d, u, 63) + }, G[2 * e] = c, G[2 * e + 1] = l, G[2 * t] = u, G[2 * t + 1] = d, G[2 * n] = f, G[2 * n + 1] = p, G[2 * r] = m, G[2 * r + 1] = h; +} +function _e(e, t = {}, n, r, i) { + if (k(n), e < 0 || e > n) throw Error("outputLen bigger than keyLen"); + let { key: a, salt: o, personalization: s } = t; + if (a !== void 0 && (a.length < 1 || a.length > n)) throw Error("\"key\" expected to be undefined or of length=1.." + n); + o !== void 0 && A(o, r, "salt"), s !== void 0 && A(s, i, "personalization"); +} +var ve = class { + buffer; + buffer32; + finished = !1; + destroyed = !1; + length = 0; + pos = 0; + blockLen; + outputLen; + constructor(e, t) { + k(e), k(t), this.blockLen = e, this.outputLen = t, this.buffer = new Uint8Array(e), this.buffer32 = N(this.buffer); + } + update(e) { + j(this), A(e); + let { blockLen: t, buffer: n, buffer32: r } = this, i = e.length, a = e.byteOffset, o = e.buffer; + for (let s = 0; s < i;) { + this.pos === t && (R(r), this.compress(r, 0, !1), R(r), this.pos = 0); + let c = Math.min(t - this.pos, i - s), l = a + s; + if (c === t && !(l % 4) && s + c < i) { + let e = new Uint32Array(o, l, Math.floor((i - s) / 4)); + R(e); + for (let n = 0; s + t < i; n += r.length, s += t) this.length += t, this.compress(e, n, !1); + R(e); + continue; + } + n.set(e.subarray(s, s + c), this.pos), this.pos += c, this.length += c, s += c; + } + return this; + } + digestInto(e) { + j(this), M(e, this); + let { pos: t, buffer32: n } = this; + this.finished = !0, P(this.buffer.subarray(t)), R(n), this.compress(n, 0, !0), R(n); + let r = N(e); + this.get().forEach((e, t) => r[t] = L(e)); + } + digest() { + let { buffer: e, outputLen: t } = this; + this.digestInto(e); + let n = e.slice(0, t); + return this.destroy(), n; + } + _cloneInto(e) { + let { buffer: t, length: n, finished: r, destroyed: i, outputLen: a, pos: o } = this; + return e ||= new this.constructor({ dkLen: a }), e.set(...this.get()), e.buffer.set(t), e.destroyed = i, e.finished = r, e.length = n, e.pos = o, e.outputLen = a, e; + } + clone() { + return this._cloneInto(); + } +}, ye = class extends ve { + v0l = W[0] | 0; + v0h = W[1] | 0; + v1l = W[2] | 0; + v1h = W[3] | 0; + v2l = W[4] | 0; + v2h = W[5] | 0; + v3l = W[6] | 0; + v3h = W[7] | 0; + v4l = W[8] | 0; + v4h = W[9] | 0; + v5l = W[10] | 0; + v5h = W[11] | 0; + v6l = W[12] | 0; + v6h = W[13] | 0; + v7l = W[14] | 0; + v7h = W[15] | 0; + constructor(e = {}) { + let t = e.dkLen === void 0 ? 64 : e.dkLen; + super(128, t), _e(t, e, 64, 16, 16); + let { key: n, personalization: r, salt: i } = e, a = 0; + if (n !== void 0 && (A(n, void 0, "key"), a = n.length), this.v0l ^= this.outputLen | a << 8 | 16842752, i !== void 0) { + A(i, void 0, "salt"); + let e = N(i); + this.v4l ^= L(e[0]), this.v4h ^= L(e[1]), this.v5l ^= L(e[2]), this.v5h ^= L(e[3]); + } + if (r !== void 0) { + A(r, void 0, "personalization"); + let e = N(r); + this.v6l ^= L(e[0]), this.v6h ^= L(e[1]), this.v7l ^= L(e[2]), this.v7h ^= L(e[3]); + } + if (n !== void 0) { + let e = new Uint8Array(this.blockLen); + e.set(n), this.update(e); + } + } + get() { + let { v0l: e, v0h: t, v1l: n, v1h: r, v2l: i, v2h: a, v3l: o, v3h: s, v4l: c, v4h: l, v5l: u, v5h: d, v6l: f, v6h: p, v7l: m, v7h: h } = this; + return [ + e, + t, + n, + r, + i, + a, + o, + s, + c, + l, + u, + d, + f, + p, + m, + h + ]; + } + set(e, t, n, r, i, a, o, s, c, l, u, d, f, p, m, h) { + this.v0l = e | 0, this.v0h = t | 0, this.v1l = n | 0, this.v1h = r | 0, this.v2l = i | 0, this.v2h = a | 0, this.v3l = o | 0, this.v3h = s | 0, this.v4l = c | 0, this.v4h = l | 0, this.v5l = u | 0, this.v5h = d | 0, this.v6l = f | 0, this.v6h = p | 0, this.v7l = m | 0, this.v7h = h | 0; + } + compress(e, t, n) { + this.get().forEach((e, t) => G[t] = e), G.set(W, 16); + let { h: r, l: i } = H(BigInt(this.length)); + G[24] = W[8] ^ i, G[25] = W[9] ^ r, n && (G[28] = ~G[28], G[29] = ~G[29]); + let a = 0, o = B; + for (let n = 0; n < 12; n++) he(0, 4, 8, 12, e, t + 2 * o[a++]), ge(0, 4, 8, 12, e, t + 2 * o[a++]), he(1, 5, 9, 13, e, t + 2 * o[a++]), ge(1, 5, 9, 13, e, t + 2 * o[a++]), he(2, 6, 10, 14, e, t + 2 * o[a++]), ge(2, 6, 10, 14, e, t + 2 * o[a++]), he(3, 7, 11, 15, e, t + 2 * o[a++]), ge(3, 7, 11, 15, e, t + 2 * o[a++]), he(0, 5, 10, 15, e, t + 2 * o[a++]), ge(0, 5, 10, 15, e, t + 2 * o[a++]), he(1, 6, 11, 12, e, t + 2 * o[a++]), ge(1, 6, 11, 12, e, t + 2 * o[a++]), he(2, 7, 8, 13, e, t + 2 * o[a++]), ge(2, 7, 8, 13, e, t + 2 * o[a++]), he(3, 4, 9, 14, e, t + 2 * o[a++]), ge(3, 4, 9, 14, e, t + 2 * o[a++]); + this.v0l ^= G[0] ^ G[16], this.v0h ^= G[1] ^ G[17], this.v1l ^= G[2] ^ G[18], this.v1h ^= G[3] ^ G[19], this.v2l ^= G[4] ^ G[20], this.v2h ^= G[5] ^ G[21], this.v3l ^= G[6] ^ G[22], this.v3h ^= G[7] ^ G[23], this.v4l ^= G[8] ^ G[24], this.v4h ^= G[9] ^ G[25], this.v5l ^= G[10] ^ G[26], this.v5h ^= G[11] ^ G[27], this.v6l ^= G[12] ^ G[28], this.v6h ^= G[13] ^ G[29], this.v7l ^= G[14] ^ G[30], this.v7h ^= G[15] ^ G[31], P(G); + } + destroy() { + this.destroyed = !0, P(this.buffer32), this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + } +}, K = /* @__PURE__ */ z((e) => new ye(e)); +(/* @__PURE__ */ v(((e, t) => { + t.exports = {}; +})))(); +var be = []; +for (let e = 0; e < 256; e++) be[e] = xe(e, 8); +function xe(e, t) { + let n = 0, r = e; + for (let e = 0; e < t; e++) n <<= 1, n |= r & 1, r >>= 1; + return n; +} +function Se(e) { + return (e & 4294901760 ? (e &= 4294901760, 16) : 0) | (e & 4278255360 ? (e &= 4278255360, 8) : 0) | (e & 4042322160 ? (e &= 4042322160, 4) : 0) | (e & 3435973836 ? (e &= 3435973836, 2) : 0) | (e & 2863311530) != 0; +} +function q(e, t) { + let n = new DataView(e.buffer, e.byteOffset, e.byteLength), r = ""; + for (let e = 0; e < 4; e++) { + e > 0 && (r += "\n"), r += " "; + for (let t = 0; t < 4; t++) t > 0 && (r += " "), r += n.getUint32(e * 16 + t * 4).toString(16).padStart(8, "0"); + } + return t && (r = t + "\n" + r), r; +} +function Ce(e, t) { + if (e.byteLength != t.byteLength) return !1; + for (var n = new Int8Array(e), r = new Int8Array(t), i = 0; i != e.byteLength; i++) if (n[i] != r[i]) return !1; + return !0; +} +function we(e) { + return e.clone(); +} +function Te(e) { + let t = e.subarray(0, 128), n = N(e.subarray(128)), r = K.create({ dkLen: 64 }); + r.buffer.set(t), r.v0l = n[0] | 0, r.v0h = n[1] | 0, r.v1l = n[2] | 0, r.v1h = n[3] | 0, r.v2l = n[4] | 0, r.v2h = n[5] | 0, r.v3l = n[6] | 0, r.v3h = n[7] | 0, r.v4l = n[8] | 0, r.v4h = n[9] | 0, r.v5l = n[10] | 0, r.v5h = n[11] | 0, r.v6l = n[12] | 0, r.v6h = n[13] | 0, r.v7l = n[14] | 0, r.v7h = n[15] | 0; + let i = 2 ** 32, a = n[16] + n[17] * i, o = n[18] + n[19] * i; + return r.length = a + o, r.pos = o, r; +} +function Ee(e) { + let t = new Uint8Array(216), n = N(t.subarray(128)); + return t.set(e.buffer), n[0] = e.v0l, n[1] = e.v0h, n[2] = e.v1l, n[3] = e.v1h, n[4] = e.v2l, n[5] = e.v2h, n[6] = e.v3l, n[7] = e.v3h, n[8] = e.v4l, n[9] = e.v4h, n[10] = e.v5l, n[11] = e.v5h, n[12] = e.v6l, n[13] = e.v6h, n[14] = e.v7l, n[15] = e.v7h, n[18] = e.pos, n[16] = e.length - e.pos, t; +} +async function De(e, t, n, r, i) { + return e.G1.isZero(t) || e.G1.isZero(n) || e.G2.isZero(r) || e.G2.isZero(i) ? !1 : await e.pairingEq(t, i, e.G1.neg(n), r); +} +function Oe() { + return window.prompt("Enter a random text. (Entropy): ", ""); +} +function ke(e) { + let t = new Uint8Array(e); + return globalThis.crypto.getRandomValues(t), t; +} +async function Ae(e) { + { + let t = await globalThis.crypto.subtle.digest("SHA-256", e.buffer); + return new Uint8Array(t); + } +} +function je(e, t) { + return new DataView(e.buffer).getUint32(t, !1); +} +async function Me(e) { + for (; !e;) e = await Oe(); + let t = K.create(64); + t.update(ke(64)); + let n = new TextEncoder(); + t.update(n.encode(e)); + let r = t.digest(), i = []; + for (let e = 0; e < 8; e++) i[e] = je(r, e * 4); + return new c(i); +} +async function Ne(e, t) { + let n, r; + t < 32 ? (n = 1 << t >>> 0, r = 1) : (n = 4294967296, r = 1 << t - 32 >>> 0); + let i = e; + for (let e = 0; e < r; e++) for (let e = 0; e < n; e++) i = await Ae(i); + let a = new DataView(i.buffer, i.byteOffset, i.byteLength), o = []; + for (let e = 0; e < 8; e++) o[e] = a.getUint32(e * 4, !1); + return new c(o); +} +function Pe(e) { + return e instanceof Uint8Array ? e : (e.slice(0, 2) == "0x" && (e = e.slice(2)), new Uint8Array(e.match(/[\da-f]{2}/gi).map(function(e) { + return parseInt(e, 16); + }))); +} +function Fe(e) { + return Array.prototype.map.call(e, function(e) { + return ("0" + (e & 255).toString(16)).slice(-2); + }).join(""); +} +function Ie(e, t) { + if (t instanceof Uint8Array) return e.toString(t); + if (Array.isArray(t)) return t.map(Ie.bind(null, e)); + if (typeof t == "object") { + let n = {}; + return Object.keys(t).forEach((r) => { + n[r] = Ie(e, t[r]); + }), n; + } else if (typeof t == "bigint" || t.eq !== void 0) return t.toString(10); + else return t; +} +//#endregion +//#region src/zkey_utils.js +async function Le(t, n) { + await e.startWriteSection(t, 1), await t.writeULE32(1), await e.endWriteSection(t); + let r = await E(n.q); + await e.startWriteSection(t, 2); + let i = r.q, a = (Math.floor((u.bitLength(i) - 1) / 64) + 1) * 8, o = r.r, s = (Math.floor((u.bitLength(o) - 1) / 64) + 1) * 8; + await t.writeULE32(a), await e.writeBigInt(t, i, a), await t.writeULE32(s), await e.writeBigInt(t, o, s), await t.writeULE32(n.nVars), await t.writeULE32(n.nPublic), await t.writeULE32(n.domainSize), await Re(t, r, n.vk_alpha_1), await Re(t, r, n.vk_beta_1), await ze(t, r, n.vk_beta_2), await ze(t, r, n.vk_gamma_2), await Re(t, r, n.vk_delta_1), await ze(t, r, n.vk_delta_2), await e.endWriteSection(t); +} +async function Re(e, t, n) { + let r = new Uint8Array(t.G1.F.n8 * 2); + t.G1.toRprLEM(r, 0, n), await e.write(r); +} +async function ze(e, t, n) { + let r = new Uint8Array(t.G2.F.n8 * 2); + t.G2.toRprLEM(r, 0, n), await e.write(r); +} +async function J(e, t, n) { + let r = await e.read(t.G1.F.n8 * 2), i = t.G1.fromRprLEM(r, 0); + return n ? t.G1.toObject(i) : i; +} +async function Be(e, t, n) { + let r = await e.read(t.G2.F.n8 * 2), i = t.G2.fromRprLEM(r, 0); + return n ? t.G2.toObject(i) : i; +} +async function Ve(t, n, r, i) { + await e.startReadUniqueSection(t, n, 1); + let a = await t.readULE32(); + if (await e.endReadSection(t), a === 1) return await He(t, n, r, i); + if (a === 2) return await Ue(t, n, r, i); + if (a === 10) return await We(t, n, r, i); + throw Error("Protocol not supported: "); +} +async function He(t, n, r, i) { + let a = {}; + a.protocol = "groth16", await e.startReadUniqueSection(t, n, 2); + let o = await t.readULE32(); + a.n8q = o, a.q = await e.readBigInt(t, o); + let s = await t.readULE32(); + return a.n8r = s, a.r = await e.readBigInt(t, s), a.curve = await E(a.q, i), a.nVars = await t.readULE32(), a.nPublic = await t.readULE32(), a.domainSize = await t.readULE32(), a.power = Se(a.domainSize), a.vk_alpha_1 = await J(t, a.curve, r), a.vk_beta_1 = await J(t, a.curve, r), a.vk_beta_2 = await Be(t, a.curve, r), a.vk_gamma_2 = await Be(t, a.curve, r), a.vk_delta_1 = await J(t, a.curve, r), a.vk_delta_2 = await Be(t, a.curve, r), await e.endReadSection(t), a; +} +async function Ue(t, n, r, i) { + let a = {}; + a.protocol = "plonk", await e.startReadUniqueSection(t, n, 2); + let o = await t.readULE32(); + a.n8q = o, a.q = await e.readBigInt(t, o); + let s = await t.readULE32(); + return a.n8r = s, a.r = await e.readBigInt(t, s), a.curve = await E(a.q, i), a.nVars = await t.readULE32(), a.nPublic = await t.readULE32(), a.domainSize = await t.readULE32(), a.power = Se(a.domainSize), a.nAdditions = await t.readULE32(), a.nConstraints = await t.readULE32(), a.k1 = await t.read(s), a.k2 = await t.read(s), a.Qm = await J(t, a.curve, r), a.Ql = await J(t, a.curve, r), a.Qr = await J(t, a.curve, r), a.Qo = await J(t, a.curve, r), a.Qc = await J(t, a.curve, r), a.S1 = await J(t, a.curve, r), a.S2 = await J(t, a.curve, r), a.S3 = await J(t, a.curve, r), a.X_2 = await Be(t, a.curve, r), await e.endReadSection(t), a; +} +async function We(t, n, r, i) { + let a = {}; + a.protocol = "fflonk", a.protocolId = 10, await e.startReadUniqueSection(t, n, 2); + let o = await t.readULE32(); + a.n8q = o, a.q = await e.readBigInt(t, o), a.curve = await E(a.q, i); + let s = await t.readULE32(); + return a.n8r = s, a.r = await e.readBigInt(t, s), a.nVars = await t.readULE32(), a.nPublic = await t.readULE32(), a.domainSize = await t.readULE32(), a.power = Se(a.domainSize), a.nAdditions = await t.readULE32(), a.nConstraints = await t.readULE32(), a.k1 = await t.read(s), a.k2 = await t.read(s), a.w3 = await t.read(s), a.w4 = await t.read(s), a.w8 = await t.read(s), a.wr = await t.read(s), a.X_2 = await Be(t, a.curve, r), a.C0 = await J(t, a.curve, r), await e.endReadSection(t), a; +} +async function Ge(t, n) { + let { fd: r, sections: i } = await e.readBinFile(t, "zkey", 1), a = await Ve(r, i, n), o = new l(a.r), s = u.mod(u.shl(1, a.n8r * 8), a.r), c = o.inv(s), d = o.mul(c, c), f = await E(a.q); + await e.startReadUniqueSection(r, i, 3), a.IC = []; + for (let e = 0; e <= a.nPublic; e++) { + let e = await J(r, f, n); + a.IC.push(e); + } + await e.endReadSection(r), await e.startReadUniqueSection(r, i, 4); + let p = await r.readULE32(); + a.ccoefs = []; + for (let e = 0; e < p; e++) { + let e = await r.readULE32(), t = await r.readULE32(), i = await r.readULE32(), o = await m(n); + a.ccoefs.push({ + matrix: e, + constraint: t, + signal: i, + value: o + }); + } + await e.endReadSection(r), await e.startReadUniqueSection(r, i, 5), a.A = []; + for (let e = 0; e < a.nVars; e++) { + let t = await J(r, f, n); + a.A[e] = t; + } + await e.endReadSection(r), await e.startReadUniqueSection(r, i, 6), a.B1 = []; + for (let e = 0; e < a.nVars; e++) { + let t = await J(r, f, n); + a.B1[e] = t; + } + await e.endReadSection(r), await e.startReadUniqueSection(r, i, 7), a.B2 = []; + for (let e = 0; e < a.nVars; e++) { + let t = await Be(r, f, n); + a.B2[e] = t; + } + await e.endReadSection(r), await e.startReadUniqueSection(r, i, 8), a.C = []; + for (let e = a.nPublic + 1; e < a.nVars; e++) { + let t = await J(r, f, n); + a.C[e] = t; + } + await e.endReadSection(r), await e.startReadUniqueSection(r, i, 9), a.hExps = []; + for (let e = 0; e < a.domainSize; e++) { + let e = await J(r, f, n); + a.hExps.push(e); + } + return await e.endReadSection(r), await r.close(), a; + async function m() { + let t = await e.readBigInt(r, a.n8r); + return o.mul(t, d); + } +} +async function Ke(e, t, n) { + let r = { delta: {} }; + r.deltaAfter = await J(e, t, n), r.delta.g1_s = await J(e, t, n), r.delta.g1_sx = await J(e, t, n), r.delta.g2_spx = await Be(e, t, n), r.transcript = await e.read(64), r.type = await e.readULE32(); + let i = await e.readULE32(), a = e.pos, o = 0; + for (; e.pos - a < i;) { + let t = await e.read(1); + if (t[0] <= o) throw Error("Parameters in the contribution must be sorted"); + if (o = t[0], t[0] == 1) { + let t = await e.read(1), n = await e.read(t[0]); + r.name = new TextDecoder().decode(n); + } else if (t[0] == 2) r.numIterationsExp = (await e.read(1))[0]; + else if (t[0] == 3) { + let t = await e.read(1); + r.beaconHash = await e.read(t[0]); + } else throw Error("Parameter not recognized"); + } + if (e.pos != a + i) throw Error("Parameters do not match"); + return r; +} +async function qe(t, n, r) { + await e.startReadUniqueSection(t, r, 10); + let i = { contributions: [] }; + i.csHash = await t.read(64); + let a = await t.readULE32(); + for (let e = 0; e < a; e++) { + let e = await Ke(t, n); + i.contributions.push(e); + } + return await e.endReadSection(t), i; +} +async function Je(e, t, n) { + await Re(e, t, n.deltaAfter), await Re(e, t, n.delta.g1_s), await Re(e, t, n.delta.g1_sx), await ze(e, t, n.delta.g2_spx), await e.write(n.transcript), await e.writeULE32(n.type || 0); + let r = []; + if (n.name) { + r.push(1); + let e = new TextEncoder("utf-8").encode(n.name.substring(0, 64)); + r.push(e.byteLength); + for (let t = 0; t < e.byteLength; t++) r.push(e[t]); + } + if (n.type == 1) { + r.push(2), r.push(n.numIterationsExp), r.push(3), r.push(n.beaconHash.byteLength); + for (let e = 0; e < n.beaconHash.byteLength; e++) r.push(n.beaconHash[e]); + } + if (r.length > 0) { + let t = new Uint8Array(r); + await e.writeULE32(t.byteLength), await e.write(t); + } else await e.writeULE32(0); +} +async function Ye(t, n, r) { + await e.startWriteSection(t, 10), await t.write(r.csHash), await t.writeULE32(r.contributions.length); + for (let e = 0; e < r.contributions.length; e++) await Je(t, n, r.contributions[e]); + await e.endWriteSection(t); +} +function Xe(e, t, n) { + let r = new Uint8Array(t.G1.F.n8 * 2); + t.G1.toRprUncompressed(r, 0, n), e.update(r); +} +function Ze(e, t, n) { + let r = new Uint8Array(t.G2.F.n8 * 2); + t.G2.toRprUncompressed(r, 0, n), e.update(r); +} +function Qe(e, t, n) { + Xe(e, t, n.deltaAfter), Xe(e, t, n.delta.g1_s), Xe(e, t, n.delta.g1_sx), Ze(e, t, n.delta.g2_spx), e.update(n.transcript); +} +//#endregion +//#region src/wtns_utils.js +async function $e(t, n, r) { + await e.startWriteSection(t, 1); + let i = (Math.floor((u.bitLength(r) - 1) / 64) + 1) * 8; + await t.writeULE32(i), await e.writeBigInt(t, r, i), await t.writeULE32(n.length), await e.endWriteSection(t), await e.startWriteSection(t, 2); + for (let r = 0; r < n.length; r++) await e.writeBigInt(t, n[r], i); + await e.endWriteSection(t, 2); +} +async function et(t, n, r) { + await e.startWriteSection(t, 1); + let i = (Math.floor((u.bitLength(r) - 1) / 64) + 1) * 8; + if (await t.writeULE32(i), await e.writeBigInt(t, r, i), n.byteLength % i != 0) throw Error("Invalid witness length"); + await t.writeULE32(n.byteLength / i), await e.endWriteSection(t), await e.startWriteSection(t, 2), await t.write(n), await e.endWriteSection(t); +} +async function tt(t, n) { + await e.startReadUniqueSection(t, n, 1); + let r = await t.readULE32(), i = await e.readBigInt(t, r), a = await t.readULE32(); + return await e.endReadSection(t), { + n8: r, + q: i, + nWitness: a + }; +} +async function nt(t) { + let { fd: n, sections: r } = await e.readBinFile(t, "wtns", 2), { n8: i, nWitness: a } = await tt(n, r); + await e.startReadUniqueSection(n, r, 2); + let o = []; + for (let t = 0; t < a; t++) { + let t = await e.readBigInt(n, i); + o.push(t); + } + return await e.endReadSection(n), await n.close(), o; +} +//#endregion +//#region src/groth16_prove.js +var { stringifyBigInts: rt } = p; +async function it(t, n, r, i) { + r && ut(r, 50); + let { fd: a, sections: o } = await e.readBinFile(n, "wtns", 2, 1 << 25, 1 << 23), s = await tt(a, o), { fd: c, sections: l } = await e.readBinFile(t, "zkey", 2, 1 << 25, 1 << 23), d = await Ve(c, l, void 0, i); + if (d.protocol != "groth16") throw Error("zkey file is not groth16"); + if (!u.eq(d.r, s.q)) throw Error("Curve of the witness does not match the curve of the proving key"); + if (s.nWitness != d.nVars) throw Error(`Invalid witness length. Circuit: ${d.nVars}, witness: ${s.nWitness}`); + let f = d.curve, p = f.Fr, m = f.G1, h = f.G2, g = Se(d.domainSize); + r && r.debug("Reading Wtns"); + let _ = await e.readSection(a, o, 2), v, y, b, x = (async function() { + let t, n, a; + await (async function() { + r && r.debug("Reading Coeffs"), console.time("buildABC_outer"); + let o = await e.readSection(c, l, 4); + r && r.debug("Building ABC"), i ||= {}, i && i.buildABC === "wasm" ? [t, n, a] = await ot(f, d, _, o, r) : i && i.buildABC === "wasm1" ? [t, n, a] = await st(f, d, _, o, r) : [t, n, a] = await at(f, d, _, o, r), console.timeEnd("buildABC_outer"); + })(), console.time("abcPromise"), globalThis.gc && globalThis.gc(); + let o = g === p.s ? f.Fr.shift : f.Fr.w[g + 1], s; + await (async function() { + let e = await p.ifft(t, "", "", r, "IFFT_A"); + t = null; + let n = await p.batchApplyKey(e, p.e(1), o); + s = await p.fft(n, "", "", r, "FFT_A"); + })(); + let u; + await (async function() { + let e = await p.ifft(n, "", "", r, "IFFT_B"); + n = null; + let t = await p.batchApplyKey(e, p.e(1), o); + u = await p.fft(t, "", "", r, "FFT_B"); + })(); + let m; + await (async function() { + let e = await p.ifft(a, "", "", r, "IFFT_C"); + a = null; + let t = await p.batchApplyKey(e, p.e(1), o); + m = await p.fft(t, "", "", r, "FFT_C"); + })(), r && r.debug("Join ABC"), b = await ct(f, d, s, u, m, r), r && r.debug("Join ABC finished"), s = null, u = null, m = null, globalThis.gc && globalThis.gc(), console.timeEnd("abcPromise"); + })(), S = {}; + async function C() { + r && r.debug("Reading A Points"); + let t = await e.readSection(c, l, 5); + console.time("Calculate PiA"), S.pi_a = await f.G1.multiExpAffine(t, _, r, "multiexp A"), console.timeEnd("Calculate PiA"); + } + let w = C(), T; + async function E() { + r && r.debug("Reading B1 Points"); + let t = await e.readSection(c, l, 6); + console.time("Calculate PiB1"), T = await f.G1.multiExpAffine(t, _, r, "multiexp B1"), console.timeEnd("Calculate PiB1"); + } + let D = E(); + async function O() { + r && r.debug("Reading B2 Points"); + let t = await e.readSection(c, l, 7); + console.time("Calculate PiB"), S.pi_b = await f.G2.multiExpAffine(t, _, r, "multiexp B2"), console.timeEnd("Calculate PiB"); + } + let k = O(), A = (async function() { + r && r.debug("Reading C Points"); + let t = await e.readSection(c, l, 8); + console.time("Calculate PiC"), S.pi_c = await f.G1.multiExpAffine(t, _.slice((d.nPublic + 1) * f.Fr.n8), r, "multiexp C"), console.timeEnd("Calculate PiC"); + })(); + y = (async function() { + r && r.debug("Reading H Points"), await x, console.time("resHPromise"); + let t = await e.readSection(c, l, 9); + v = await f.G1.multiExpAffine(t, b, r, "multiexp H"), console.timeEnd("resHPromise"); + })(); + let j = f.Fr.random(), M = f.Fr.random(); + await w, S.pi_a = m.add(S.pi_a, d.vk_alpha_1), S.pi_a = m.add(S.pi_a, m.timesFr(d.vk_delta_1, j)), await k, S.pi_b = h.add(S.pi_b, d.vk_beta_2), S.pi_b = h.add(S.pi_b, h.timesFr(d.vk_delta_2, M)), await D, T = m.add(T, d.vk_beta_1), T = m.add(T, m.timesFr(d.vk_delta_1, M)), await Promise.all([A, y]), S.pi_c = m.add(S.pi_c, v), S.pi_c = m.add(S.pi_c, m.timesFr(S.pi_a, M)), S.pi_c = m.add(S.pi_c, m.timesFr(T, j)), S.pi_c = m.add(S.pi_c, m.timesFr(d.vk_delta_1, p.neg(p.mul(j, M)))); + let N = []; + for (let e = 1; e <= d.nPublic; e++) { + let t = _.slice(e * p.n8, e * p.n8 + p.n8); + N.push(u.fromRprLE(t)); + } + return S.pi_a = m.toObject(m.toAffine(S.pi_a)), S.pi_b = h.toObject(h.toAffine(S.pi_b)), S.pi_c = m.toObject(m.toAffine(S.pi_c)), S.protocol = "groth16", S.curve = f.name, await c.close(), await a.close(), S = rt(S), N = rt(N), { + proof: S, + publicSignals: N + }; +} +async function at(e, t, n, r, i) { + let a = e.Fr.n8, o = 12 + t.n8r, c = (r.byteLength - 4) / o, l = new s(t.domainSize * a), u = new s(t.domainSize * a), d = new s(t.domainSize * a), f = [l, u]; + for (let t = 0; t < c; t++) { + i && t % 1e6 == 0 && i.debug(`QAP AB: ${t}/${c}`); + let s, l; + if (r.buffer) { + let e = 4 + t * o; + s = new DataView(r.buffer, r.byteOffset + e, o), l = new Uint8Array(r.buffer, r.byteOffset + e + 12, a); + } else { + let e = r.slice(4 + t * o, 4 + t * o + o); + s = new DataView(e.buffer), l = e.slice(12, 12 + a); + } + let u = s.getUint32(0, !0), d = s.getUint32(4, !0), p = s.getUint32(8, !0); + f[u].set(e.Fr.add(f[u].slice(d * a, d * a + a), e.Fr.mul(l, n.slice(p * a, p * a + a))), d * a), t % 1e6 == 0 && i && lt(i); + } + for (let n = 0; n < t.domainSize; n++) i && n % 1e6 == 0 && i.debug(`QAP C: ${n}/${t.domainSize}`), d.set(e.Fr.mul(l.slice(n * a, n * a + a), u.slice(n * a, n * a + a)), n * a); + return [ + l, + u, + d + ]; +} +async function ot(e, t, n, r, i) { + let a = e.tm.concurrency, o = 12 + t.n8r, c; + if (r instanceof s) { + let e = [], t = r.buffers[0].length; + for (let t = 0; t < r.buffers.length; t++) e.push(new DataView(r.buffers[t].buffer)); + c = function(n) { + return e[Math.floor(n / t)].getUint32(n % t, !0); + }; + } else { + let e = new DataView(r.buffer, r.byteOffset, r.byteLength); + c = function(t) { + return e.getUint32(t, !0); + }; + } + let l = Math.floor(t.domainSize / a); + for (console.log("@@@ elementsPerChunk", l); l > 2 ** 16;) a *= 2, l = Math.floor(t.domainSize / a); + console.log("@@@ new elementsPerChunk", l); + let u = [], d = []; + for (let e = 0; e < a; e++) d.push(y(Math.floor(e * l))); + d.push(r.byteLength); + let f = 2 ** 26; + for (let s = 0; s < t.nVars; s += f) { + i && i.debug(`QAP ${s}: ${s}/${t.nVars}`); + let c = Math.min(t.nVars - s, f); + for (let i = 0; i < a; i++) { + let f; + if (f = i < a - 1 ? l : t.domainSize - i * l, f == 0) continue; + let p = []; + p.push({ + cmd: "ALLOCSET", + var: 0, + buff: r.slice(d[i], d[i + 1]) + }), p.push({ + cmd: "ALLOCSET", + var: 1, + buff: n.slice(s * e.Fr.n8, (s + c) * e.Fr.n8) + }), p.push({ + cmd: "ALLOC", + var: 2, + len: f * e.Fr.n8 + }), p.push({ + cmd: "ALLOC", + var: 3, + len: f * e.Fr.n8 + }), p.push({ + cmd: "ALLOC", + var: 4, + len: f * e.Fr.n8 + }), p.push({ + cmd: "CALL", + fnName: "qap_buildABC", + params: [ + { var: 0 }, + { val: (d[i + 1] - d[i]) / o }, + { var: 1 }, + { var: 2 }, + { var: 3 }, + { var: 4 }, + { val: i * l }, + { val: f }, + { val: s }, + { val: c } + ] + }), p.push({ + cmd: "GET", + out: 0, + var: 2, + len: f * e.Fr.n8 + }), p.push({ + cmd: "GET", + out: 1, + var: 3, + len: f * e.Fr.n8 + }), p.push({ + cmd: "GET", + out: 2, + var: 4, + len: f * e.Fr.n8 + }), u.push(e.tm.queueAction(p)); + } + } + let p = await Promise.all(u), m = p.length / a; + if (m > 1) { + let t = []; + for (let n = 0; n < a; n++) { + let r = []; + r.push({ + cmd: "ALLOC", + var: 0, + len: p[n][0].byteLength + }), r.push({ + cmd: "ALLOC", + var: 1, + len: p[n][0].byteLength + }); + for (let t = 0; t < 3; t++) { + r.push({ + cmd: "SET", + var: 0, + buff: p[n][t] + }); + for (let i = 1; i < m; i++) r.push({ + cmd: "SET", + var: 1, + buff: p[i * a + n][t] + }), r.push({ + cmd: "CALL", + fnName: "qap_batchAdd", + params: [ + { var: 0 }, + { var: 1 }, + { val: p[n][t].length / e.Fr.n8 }, + { var: 0 } + ] + }); + r.push({ + cmd: "GET", + out: t, + var: 0, + len: p[n][t].length + }); + } + t.push(e.tm.queueAction(r)); + } + p = await Promise.all(t); + } + let h = new s(t.domainSize * e.Fr.n8), g = new s(t.domainSize * e.Fr.n8), _ = new s(t.domainSize * e.Fr.n8), v = 0; + for (let e = 0; e < p.length; e++) h.set(p[e][0], v), g.set(p[e][1], v), _.set(p[e][2], v), v += p[e][0].byteLength; + return [ + h, + g, + _ + ]; + function y(e) { + let t = 0, n = c(0); + for (; t < n;) { + var r = Math.floor((n + t) / 2); + let i = c(4 + r * o + 4); + i > e ? n = r - 1 : i < e ? t = r + 1 : n = r; + } + return 4 + t * o; + } +} +async function st(e, t, n, r, i) { + console.time("buildABC"); + let a = 12 + t.n8r, o; + if (r instanceof s) { + let e = [], t = r.buffers[0].length; + for (let t = 0; t < r.buffers.length; t++) e.push(new DataView(r.buffers[t].buffer)); + o = function(n) { + return e[Math.floor(n / t)].getUint32(n % t, !0); + }; + } else { + let e = new DataView(r.buffer, r.byteOffset, r.byteLength); + o = function(t) { + return e.getUint32(t, !0); + }; + } + let c = Math.floor((t.domainSize - 1) / 1) + 1, l = [], u = []; + for (let e = 0; e < 1; e++) u.push(y(Math.floor(e * c))); + u.push(r.byteLength); + let d = c; + console.log("zkey.domainSize", t.domainSize), console.log("concurrency", 1), console.log("elementsPerChunk", c), console.log("chunkSize", d); + for (let o = 0; o < t.nVars; o += d) { + i && i.debug(`QAP: ${o}/${t.nVars}`); + let s = Math.min(t.nVars - o, d); + console.log("ns", s); + for (let i = 0; i < 1; i++) { + let d; + if (d = i < 0 ? c : t.domainSize - i * c, d === 0) continue; + let f = [], p = r.slice(u[i], u[i + 1]), m = n.slice(o * e.Fr.n8, (o + s) * e.Fr.n8); + f.push({ + cmd: "ALLOCSET", + var: 0, + buff: p + }), f.push({ + cmd: "ALLOCSET", + var: 1, + buff: m + }), f.push({ + cmd: "ALLOC", + var: 2, + len: d * e.Fr.n8 + }), f.push({ + cmd: "ALLOC", + var: 3, + len: d * e.Fr.n8 + }), f.push({ + cmd: "ALLOC", + var: 4, + len: d * e.Fr.n8 + }), f.push({ + cmd: "CALL", + fnName: "qap_buildABC", + params: [ + { var: 0 }, + { val: (u[i + 1] - u[i]) / a }, + { var: 1 }, + { var: 2 }, + { var: 3 }, + { var: 4 }, + { val: i * c }, + { val: d }, + { val: o }, + { val: s } + ] + }), f.push({ + cmd: "GET", + out: 0, + var: 2, + len: d * e.Fr.n8 + }), f.push({ + cmd: "GET", + out: 1, + var: 3, + len: d * e.Fr.n8 + }), f.push({ + cmd: "GET", + out: 2, + var: 4, + len: d * e.Fr.n8 + }), l.push(e.tm.queueAction(f, [p.buffer, m.buffer])); + } + } + let f = await Promise.all(l); + console.log("result.length", f.length), console.log("result", f); + let p = f.length / 1; + console.log("nGroups", p); + let m; + if (p > 1) { + let t = []; + for (let n = 0; n < 1; n++) { + let r = []; + r.push({ + cmd: "ALLOC", + var: 0, + len: f[n][0].byteLength + }), r.push({ + cmd: "ALLOC", + var: 1, + len: f[n][0].byteLength + }); + for (let t = 0; t < 3; t++) { + r.push({ + cmd: "SET", + var: 0, + buff: f[n][t] + }); + for (let i = 1; i < p; i++) r.push({ + cmd: "SET", + var: 1, + buff: f[i * 1 + n][t] + }), r.push({ + cmd: "CALL", + fnName: "qap_batchAdd", + params: [ + { var: 0 }, + { var: 1 }, + { val: f[n][t].length / e.Fr.n8 }, + { var: 0 } + ] + }); + r.push({ + cmd: "GET", + out: t, + var: 0, + len: f[n][t].length + }); + } + console.log("task.length", r.length), t.push(e.tm.queueAction(r, f.buffer)); + } + console.log("promises2.length", t.length), m = await Promise.all(t), f = m; + } + let h = new s(t.domainSize * e.Fr.n8), g = new s(t.domainSize * e.Fr.n8), _ = new s(t.domainSize * e.Fr.n8), v = 0; + for (let e = 0; e < f.length; e++) h.set(f[e][0], v), g.set(f[e][1], v), _.set(f[e][2], v), v += f[e][0].byteLength; + return console.timeEnd("buildABC"), [ + h, + g, + _ + ]; + function y(e) { + let t = 0, n = o(0); + for (; t < n;) { + let r = Math.floor((n + t) / 2), i = o(4 + r * a + 4); + i > e ? n = r - 1 : i < e ? t = r + 1 : n = r; + } + return 4 + t * a; + } +} +async function ct(e, t, n, r, i, a) { + console.time("joinABC"); + let o = 65536, c = e.Fr.n8, l = Math.floor(n.byteLength / e.Fr.n8), u = []; + for (let t = 0; t < l; t += o) { + a && a.debug(`JoinABC: ${t}/${l}`); + let s = Math.min(l - t, o), d = [], f = n.slice(t * c, (t + s) * c), p = r.slice(t * c, (t + s) * c), m = i.slice(t * c, (t + s) * c); + d.push({ + cmd: "ALLOCSET", + var: 0, + buff: f + }), d.push({ + cmd: "ALLOCSET", + var: 1, + buff: p + }), d.push({ + cmd: "ALLOCSET", + var: 2, + buff: m + }), d.push({ + cmd: "ALLOC", + var: 3, + len: s * c + }), d.push({ + cmd: "CALL", + fnName: "qap_joinABC", + params: [ + { var: 0 }, + { var: 1 }, + { var: 2 }, + { val: s }, + { var: 3 } + ] + }), d.push({ + cmd: "CALL", + fnName: "frm_batchFromMontgomery", + params: [ + { var: 3 }, + { val: s }, + { var: 3 } + ] + }), d.push({ + cmd: "GET", + out: 0, + var: 3, + len: s * c + }), u.push(e.tm.queueAction(d, [ + f.buffer, + p.buffer, + m.buffer + ])); + } + let d = await Promise.all(u), f; + f = n instanceof s ? new s(n.byteLength) : new Uint8Array(n.byteLength); + let p = 0; + for (let e = 0; e < d.length; e++) f.set(d[e][0], p), p += d[e][0].byteLength; + return console.timeEnd("joinABC"), f; +} +function lt(e) { + if (!e) return; + let t = process.memoryUsage(); + e.debug(" ", "\x1B[0m Heap:\x1B[32m", `${Math.round(t.heapUsed / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m / \x1B[32m", `${Math.round(t.heapTotal / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m RSS:\x1B[32m", `${Math.round(t.rss / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m External:\x1B[32m", `${Math.round(t.external / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m ArrBuffers:\x1B[32m", `${Math.round(t.arrayBuffers / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m"); +} +function ut(e, t = 5e3) { + return setInterval(() => { + lt(e); + }, t); +} +//#endregion +//#region node_modules/fastfile/build/browser/browser.esm.js +function dt(e) { + let t = e.initialSize || 1 << 20, n = new _t(); + return n.o = e, n.o.data = new Uint8Array(t), n.allocSize = t, n.totalSize = 0, n.readOnly = !1, n.pos = 0, n; +} +function ft(e) { + let t = new _t(); + return t.o = e, t.allocSize = e.data.byteLength, t.totalSize = e.data.byteLength, t.readOnly = !0, t.pos = 0, t; +} +var pt = new Uint8Array(4), mt = new DataView(pt.buffer), ht = new Uint8Array(8), gt = new DataView(ht.buffer), _t = class { + constructor() { + this.pageSize = 16384; + } + _resizeIfNeeded(e) { + if (e > this.allocSize) { + let t = Math.max(this.allocSize + (1 << 20), Math.floor(this.allocSize * 1.1), e), n = new Uint8Array(t); + n.set(this.o.data), this.o.data = n, this.allocSize = t; + } + } + async write(e, t) { + if (t === void 0 && (t = this.pos), this.readOnly) throw Error("Writing a read only file"); + this._resizeIfNeeded(t + e.byteLength), this.o.data.set(e.slice(), t), t + e.byteLength > this.totalSize && (this.totalSize = t + e.byteLength), this.pos = t + e.byteLength; + } + async readToBuffer(e, t, n, r) { + if (r === void 0 && (r = this.pos), this.readOnly && r + n > this.totalSize) throw Error("Reading out of bounds"); + this._resizeIfNeeded(r + n); + let i = new Uint8Array(this.o.data.buffer, this.o.data.byteOffset + r, n); + e.set(i, t), this.pos = r + n; + } + async read(e, t) { + let n = this, r = new Uint8Array(e); + return await n.readToBuffer(r, 0, e, t), r; + } + close() { + this.o.data.byteLength != this.totalSize && (this.o.data = this.o.data.slice(0, this.totalSize)); + } + async discard() {} + async writeULE32(e, t) { + let n = this; + mt.setUint32(0, e, !0), await n.write(pt, t); + } + async writeUBE32(e, t) { + let n = this; + mt.setUint32(0, e, !1), await n.write(pt, t); + } + async writeULE64(e, t) { + let n = this; + gt.setUint32(0, e & 4294967295, !0), gt.setUint32(4, Math.floor(e / 4294967296), !0), await n.write(ht, t); + } + async readULE32(e) { + let t = await this.read(4, e); + return new Uint32Array(t.buffer)[0]; + } + async readUBE32(e) { + let t = await this.read(4, e); + return new DataView(t.buffer).getUint32(0, !1); + } + async readULE64(e) { + let t = await this.read(8, e), n = new Uint32Array(t.buffer); + return n[1] * 4294967296 + n[0]; + } + async readString(e) { + let t = this, n = e === void 0 ? t.pos : e; + if (n > this.totalSize) { + if (this.readOnly) throw Error("Reading out of bounds"); + this._resizeIfNeeded(e); + } + let r = new Uint8Array(t.o.data.buffer, n, this.totalSize - n), i = r.findIndex((e) => e === 0), a = i !== -1, o = ""; + return a ? (o = new TextDecoder().decode(r.slice(0, i)), t.pos = n + i + 1) : t.pos = n, o; + } +}, Y = 1 << 22; +function vt(e) { + let t = e.initialSize || 0, n = new wt(); + n.o = e; + let r = t ? Math.floor((t - 1) / Y) + 1 : 0; + n.o.data = []; + for (let e = 0; e < r - 1; e++) n.o.data.push(new Uint8Array(Y)); + return r && n.o.data.push(new Uint8Array(t - Y * (r - 1))), n.totalSize = 0, n.readOnly = !1, n.pos = 0, n; +} +function yt(e) { + let t = new wt(); + return t.o = e, t.totalSize = (e.data.length - 1) * Y + e.data[e.data.length - 1].byteLength, t.readOnly = !0, t.pos = 0, t; +} +var bt = new Uint8Array(4), xt = new DataView(bt.buffer), St = new Uint8Array(8), Ct = new DataView(St.buffer), wt = class { + constructor() { + this.pageSize = 16384; + } + _resizeIfNeeded(e) { + if (e <= this.totalSize) return; + if (this.readOnly) throw Error("Reading out of file bounds"); + let t = Math.floor((e - 1) / Y) + 1; + for (let n = Math.max(this.o.data.length - 1, 0); n < t; n++) { + let r = n < t - 1 ? Y : e - (t - 1) * Y, i = new Uint8Array(r); + n == this.o.data.length - 1 && i.set(this.o.data[n]), this.o.data[n] = i; + } + this.totalSize = e; + } + async write(e, t) { + let n = this; + if (t === void 0 && (t = n.pos), this.readOnly) throw Error("Writing a read only file"); + this._resizeIfNeeded(t + e.byteLength); + let r = Math.floor(t / Y), i = t % Y, a = e.byteLength; + for (; a > 0;) { + let t = i + a > Y ? Y - i : a, o = e.slice(e.byteLength - a, e.byteLength - a + t); + new Uint8Array(n.o.data[r].buffer, i, t).set(o), a -= t, r++, i = 0; + } + this.pos = t + e.byteLength; + } + async readToBuffer(e, t, n, r) { + let i = this; + if (r === void 0 && (r = i.pos), this.readOnly && r + n > this.totalSize) throw Error("Reading out of bounds"); + this._resizeIfNeeded(r + n); + let a = Math.floor(r / Y), o = r % Y, s = n; + for (; s > 0;) { + let r = o + s > Y ? Y - o : s, c = new Uint8Array(i.o.data[a].buffer, o, r); + e.set(c, t + n - s), s -= r, a++, o = 0; + } + this.pos = r + n; + } + async read(e, t) { + let n = this, r = new Uint8Array(e); + return await n.readToBuffer(r, 0, e, t), r; + } + close() {} + async discard() {} + async writeULE32(e, t) { + let n = this; + xt.setUint32(0, e, !0), await n.write(bt, t); + } + async writeUBE32(e, t) { + let n = this; + xt.setUint32(0, e, !1), await n.write(bt, t); + } + async writeULE64(e, t) { + let n = this; + Ct.setUint32(0, e & 4294967295, !0), Ct.setUint32(4, Math.floor(e / 4294967296), !0), await n.write(St, t); + } + async readULE32(e) { + let t = await this.read(4, e); + return new Uint32Array(t.buffer)[0]; + } + async readUBE32(e) { + let t = await this.read(4, e); + return new DataView(t.buffer).getUint32(0, !1); + } + async readULE64(e) { + let t = await this.read(8, e), n = new Uint32Array(t.buffer); + return n[1] * 4294967296 + n[0]; + } + async readString(e) { + let t = this, n = e === void 0 ? t.pos : e; + if (n > this.totalSize) { + if (this.readOnly) throw Error("Reading out of bounds"); + this._resizeIfNeeded(e); + } + let r = !1, i = ""; + for (; !r;) { + let e = Math.floor(n / Y), a = n % Y; + if (t.o.data[e] === void 0) throw Error("ERROR"); + let o = Math.min(2048, t.o.data[e].length - a), s = new Uint8Array(t.o.data[e].buffer, a, o), c = s.findIndex((e) => e === 0); + r = c !== -1, r ? (i += new TextDecoder().decode(s.slice(0, c)), t.pos = e * Y + a + c + 1) : (i += new TextDecoder().decode(s), t.pos = e * Y + a + s.length), n = t.pos; + } + return i; + } +}, Tt = 65536; +function Et() { + throw Error("File I/O is not supported in the browser"); +} +function Dt(e, t) { + return e instanceof Uint8Array ? { + type: "mem", + data: e + } : typeof e == "string" ? { + type: "mem", + initialSize: t || Tt + } : e; +} +async function Ot(e) { + let t = await fetch(e).then((e) => e.arrayBuffer()); + return { + type: "mem", + data: new Uint8Array(t) + }; +} +function kt(e, t, n) { + if (e.type === "file" && Et(), e.type === "mem") return t(e); + if (e.type === "bigMem") return n(e); + throw Error("Invalid FastFile type: " + e.type); +} +function At(e, t) { + return kt(Dt(e, t), dt, vt); +} +async function jt(e) { + return e = typeof e == "string" ? await Ot(e) : Dt(e), kt(e, ft, yt); +} +//#endregion +//#region node_modules/circom_runtime/js/utils.js +function Mt(e) { + let t = []; + return n(t, e), t; + function n(e, t) { + if (Array.isArray(t)) for (let r = 0; r < t.length; r++) n(e, t[r]); + else e.push(t); + } +} +function Nt(e, t) { + let n = BigInt(e) % t; + return n < 0 && (n += t), n; +} +function Pt(e) { + let t = BigInt(2) ** BigInt(64), n = BigInt("0xCBF29CE484222325"); + for (let r = 0; r < e.length; r++) n ^= BigInt(e[r].charCodeAt(0)), n *= BigInt(1099511628211), n %= t; + let r = n.toString(16), i = 16 - r.length; + return r = "0".repeat(i).concat(r), r; +} +function Ft(e, t) { + let n = [], r = BigInt(e), i = BigInt(4294967296); + for (; r;) n.unshift(Number(r % i)), r /= i; + if (t) { + let e = t - n.length; + for (; e > 0;) n.unshift(0), e--; + } + return n; +} +//#endregion +//#region node_modules/circom_runtime/js/witness_calculator.js +async function It(e, t) { + let n, r, i; + t ||= {}; + let a = 1, o = 0, s = 0, c = !1; + if (e instanceof WebAssembly.Instance) n = e, c = !0; + else { + let c = 32767; + if (t.memorySize && (c = parseInt(t.memorySize), c < 0)) throw Error("Invalid memory size"); + let l = !1; + for (; !l;) try { + i = new WebAssembly.Memory({ initial: c }), l = !0; + } catch (e) { + if (c <= 1) throw e; + console.warn("Could not allocate " + c * 1024 * 64 + " bytes. This may cause severe instability. Trying with " + c * 1024 * 64 / 2 + " bytes"), c = Math.floor(c / 2); + } + let p = await WebAssembly.compile(e), m = "", h = ""; + n = await WebAssembly.instantiate(p, { + env: { memory: i }, + runtime: { + printDebug: function(e) { + console.log("printDebug:", e); + }, + exceptionHandler: function(e) { + let t; + throw t = e === 1 ? "Signal not found. " : e === 2 ? "Too many signals set. " : e === 3 ? "Signal already set. " : e === 4 ? "Assert Failed. " : e === 5 ? "Not enough memory. " : e === 6 ? "Input signal array access exceeds the size. " : "Unknown error. ", console.error("ERROR: ", e, m), Error(t + m); + }, + printErrorMessage: function() { + m += d() + "\n"; + }, + writeBufferMessage: function() { + let e = d(); + e === "\n" ? (console.log(h), h = "") : (h !== "" && (h += " "), h += e); + }, + showSharedRWMemory: function() { + let e = n.exports.getFieldNumLen32(), t = new Uint32Array(e); + for (let r = 0; r < e; r++) t[e - 1 - r] = n.exports.readSharedRWMemory(r); + if (a >= 2 && (o >= 1 || s >= 7)) { + h !== "" && (h += " "); + let e = u.fromArray(t, 4294967296).toString(); + h += e; + } else console.log(u.fromArray(t, 4294967296)); + }, + error: function(e, n, i, a, o, s) { + let c; + throw c = e === 7 ? f(n) + " " + r.getFr(a).toString() + " != " + r.getFr(o).toString() + " " + f(s) : e === 9 ? f(n) + " " + r.getFr(a).toString() + " " + f(o) : e === 5 && t.sym ? f(n) + " " + t.sym.labelIdx2Name[o] : f(n) + " " + i + " " + a + " " + o + " " + s, console.log("ERROR: ", e, c), Error(c); + }, + log: function(e) { + console.log(r.getFr(e).toString()); + }, + logGetSignal: function(e, n) { + t.logGetSignal && t.logGetSignal(e, r.getFr(n)); + }, + logSetSignal: function(e, n) { + t.logSetSignal && t.logSetSignal(e, r.getFr(n)); + }, + logStartComponent: function(e) { + t.logStartComponent && t.logStartComponent(e); + }, + logFinishComponent: function(e) { + t.logFinishComponent && t.logFinishComponent(e); + } + } + }); + } + typeof n.exports.getVersion == "function" && (a = n.exports.getVersion()), typeof n.exports.getMinorVersion == "function" && (o = n.exports.getMinorVersion()), typeof n.exports.getPatchVersion == "function" && (s = n.exports.getPatchVersion()); + let l = t && (t.sanityCheck || t.logGetSignal || t.logSetSignal || t.logStartComponent || t.logFinishComponent); + if (a === 2) r = new Rt(n, l); + else if (a === 1) { + if (c) throw Error("Loading code from WebAssembly instance is not supported for circom version 1"); + r = new Lt(i, n, l); + } else throw Error(`Unsupported circom version: ${a}`); + return r; + function d() { + let e = "", t = n.exports.getMessageChar(); + for (; t !== 0;) e += String.fromCharCode(t), t = n.exports.getMessageChar(); + return e; + } + function f(e) { + let t = new Uint8Array(i.buffer), n = []; + for (let r = 0; t[e + r] > 0; r++) n.push(t[e + r]); + return String.fromCharCode.apply(null, n); + } +} +var Lt = class { + constructor(e, t, n) { + this.memory = e, this.i32 = new Uint32Array(e.buffer), this.instance = t, this.n32 = (this.instance.exports.getFrLen() >> 2) - 2; + let r = this.instance.exports.getPRawPrime(), i = Array(this.n32); + for (let e = 0; e < this.n32; e++) i[this.n32 - 1 - e] = this.i32[(r >> 2) + e]; + this.prime = u.fromArray(i, 4294967296), this.Fr = new l(this.prime), this.mask32 = u.fromString("FFFFFFFF", 16), this.NVars = this.instance.exports.getNVars(), this.n64 = Math.floor((this.Fr.bitLength - 1) / 64) + 1, this.R = this.Fr.e(u.shiftLeft(1, this.n64 * 64)), this.RInv = this.Fr.inv(this.R), this.sanityCheck = n; + } + circom_version() { + return 1; + } + async _doCalculateWitness(e, t) { + this.instance.exports.init(this.sanityCheck || t ? 1 : 0); + let n = this.allocInt(), r = this.allocFr(); + Object.keys(e).forEach((t) => { + let i = Pt(t), a = parseInt(i.slice(0, 8), 16), o = parseInt(i.slice(8, 16), 16); + try { + this.instance.exports.getSignalOffset32(n, 0, a, o); + } catch { + throw Error(`Signal ${t} is not an input of the circuit.`); + } + let s = this.getInt(n), c = Mt(e[t]); + for (let e = 0; e < c.length; e++) this.setFr(r, c[e]), this.instance.exports.setSignal(0, 0, s + e, r); + }); + } + async calculateWitness(e, t) { + let n = this, r = n.i32[0], i = []; + await n._doCalculateWitness(e, t); + for (let e = 0; e < n.NVars; e++) { + let t = n.instance.exports.getPWitness(e); + i.push(n.getFr(t)); + } + return n.i32[0] = r, i; + } + async calculateBinWitness(e, t) { + let n = this, r = n.i32[0]; + await n._doCalculateWitness(e, t); + let i = n.instance.exports.getWitnessBuffer(); + n.i32[0] = r; + let a = n.memory.buffer.slice(i, i + n.NVars * n.n64 * 8); + return new Uint8Array(a); + } + allocInt() { + let e = this.i32[0]; + return this.i32[0] = e + 8, e; + } + allocFr() { + let e = this.i32[0]; + return this.i32[0] = e + this.n32 * 4 + 8, e; + } + getInt(e) { + return this.i32[e >> 2]; + } + setInt(e, t) { + this.i32[e >> 2] = t; + } + getFr(e) { + let t = this, n = e >> 2; + if (t.i32[n + 1] & 2147483648) { + let e = Array(t.n32); + for (let r = 0; r < t.n32; r++) e[t.n32 - 1 - r] = t.i32[n + 2 + r]; + let i = t.Fr.e(u.fromArray(e, 4294967296)); + return t.i32[n + 1] & 1073741824 ? r(i) : i; + } else if (t.i32[n] & 2147483648) return t.Fr.e(t.i32[n] - 4294967296); + else return t.Fr.e(t.i32[n]); + function r(e) { + return t.Fr.mul(t.RInv, e); + } + } + setFr(e, t) { + let n = this; + t = n.Fr.e(t); + let r = n.Fr.neg(n.Fr.e("80000000", 16)), i = n.Fr.e("7FFFFFFF", 16); + if (n.Fr.geq(t, r) && n.Fr.leq(t, i)) { + let i; + n.Fr.geq(t, n.Fr.zero) ? i = u.toNumber(t) : (i = u.toNumber(n.Fr.sub(t, r)), i -= 2147483648, i = 4294967296 + i), n.i32[e >> 2] = i, n.i32[(e >> 2) + 1] = 0; + return; + } + n.i32[e >> 2] = 0, n.i32[(e >> 2) + 1] = 2147483648; + let a = u.toArray(t, 4294967296); + for (let t = 0; t < n.n32; t++) { + let r = a.length - 1 - t; + r >= 0 ? n.i32[(e >> 2) + 2 + t] = a[r] : n.i32[(e >> 2) + 2 + t] = 0; + } + } +}, Rt = class { + constructor(e, t) { + this.instance = e, this.version = this.instance.exports.getVersion(), this.n32 = this.instance.exports.getFieldNumLen32(), this.instance.exports.getRawPrime(); + let n = new Uint32Array(this.n32); + for (let e = 0; e < this.n32; e++) n[this.n32 - 1 - e] = this.instance.exports.readSharedRWMemory(e); + this.prime = u.fromArray(n, 4294967296), this.witnessSize = this.instance.exports.getWitnessSize(), this.sanityCheck = t; + } + circom_version() { + return this.instance.exports.getVersion(); + } + async _doCalculateWitness(e, t) { + this.instance.exports.init(this.sanityCheck || t ? 1 : 0); + let n = Object.keys(e), r = 0; + if (n.forEach((t) => { + let n = Pt(t), i = parseInt(n.slice(0, 8), 16), a = parseInt(n.slice(8, 16), 16), o = Mt(e[t]); + if (typeof this.instance.exports.getInputSignalSize == "function") { + let e = this.instance.exports.getInputSignalSize(i, a); + if (e < 0) throw Error(`Signal ${t} not found\n`); + if (o.length < e) throw Error(`Not enough values for input signal ${t}\n`); + if (o.length > e) throw Error(`Too many values for input signal ${t}\n`); + } + for (let e = 0; e < o.length; e++) { + let t = Ft(Nt(o[e], this.prime), this.n32); + for (let e = 0; e < this.n32; e++) this.instance.exports.writeSharedRWMemory(e, t[this.n32 - 1 - e]); + try { + this.instance.exports.setInputSignal(i, a, e), r++; + } catch (e) { + throw Error(e); + } + } + }), r < this.instance.exports.getInputSize()) throw Error(`Not all inputs have been set. Only ${r} out of ${this.instance.exports.getInputSize()}`); + } + async calculateWitness(e, t) { + let n = []; + await this._doCalculateWitness(e, t); + for (let e = 0; e < this.witnessSize; e++) { + this.instance.exports.getWitness(e); + let t = new Uint32Array(this.n32); + for (let e = 0; e < this.n32; e++) t[this.n32 - 1 - e] = this.instance.exports.readSharedRWMemory(e); + n.push(u.fromArray(t, 4294967296)); + } + return n; + } + async calculateWTNSBin(e, t) { + let n = new Uint32Array(this.witnessSize * this.n32 + this.n32 + 11), r = new Uint8Array(n.buffer); + await this._doCalculateWitness(e, t), r[0] = 119, r[1] = 116, r[2] = 110, r[3] = 115, n[1] = 2, n[2] = 2, n[3] = 1; + let i = this.n32 * 4, a = (8 + i).toString(16); + n[4] = parseInt(a.slice(0, 8), 16), n[5] = parseInt(a.slice(8, 16), 16), n[6] = i, this.instance.exports.getRawPrime(); + let o = 7; + for (let e = 0; e < this.n32; e++) n[o + e] = this.instance.exports.readSharedRWMemory(e); + o += this.n32, n[o] = this.witnessSize, o++, n[o] = 2, o++; + let s = (i * this.witnessSize).toString(16); + n[o] = parseInt(s.slice(0, 8), 16), n[o + 1] = parseInt(s.slice(8, 16), 16), o += 2; + for (let e = 0; e < this.witnessSize; e++) { + this.instance.exports.getWitness(e); + for (let e = 0; e < this.n32; e++) n[o + e] = this.instance.exports.readSharedRWMemory(e); + o += this.n32; + } + return r; + } +}, { unstringifyBigInts: zt } = p; +async function Bt(t, n, r, i) { + let a = zt(t), o = await jt(n), s = await o.read(o.totalSize); + await o.close(); + let c = await It(s, i); + if (c.circom_version() === 1) { + let t = await c.calculateBinWitness(a), n = await e.createBinFile(r, "wtns", 2, 2); + await et(n, t, c.prime), await n.close(); + } else { + let e = await At(r), t = await c.calculateWTNSBin(a); + await e.write(t), await e.close(); + } +} +//#endregion +//#region src/groth16_fullprove.js +var { unstringifyBigInts: Vt } = p; +async function Ht(e, t, n, r, i, a) { + let o = Vt(e), s = { type: "mem" }; + return await Bt(o, t, s, i), await it(n, s, r, a); +} +//#endregion +//#region src/groth16_verify.js +var { unstringifyBigInts: Ut } = p; +async function Wt(e, t, n, r) { + let i = Ut(e), a = Ut(n), o = Ut(t), s = await D(i.curve), c = s.G1.fromObject(i.IC[0]), l = new Uint8Array(s.G1.F.n8 * 2 * o.length), d = new Uint8Array(s.Fr.n8 * o.length); + if (!qt(s, o)) return r && r.error("Public inputs are not valid."), !1; + for (let e = 0; e < o.length; e++) { + let t = s.G1.fromObject(i.IC[e + 1]); + l.set(t, e * s.G1.F.n8 * 2), u.toRprLE(d, s.Fr.n8 * e, o[e], s.Fr.n8); + } + let f = await s.G1.multiExpAffine(l, d); + f = s.G1.add(f, c); + let p = s.G1.fromObject(a.pi_a), m = s.G2.fromObject(a.pi_b), h = s.G1.fromObject(a.pi_c); + if (!Gt(s, { + pi_a: p, + pi_b: m, + pi_c: h + })) return r && r.error("Proof commitments are not valid."), !1; + let g = s.G2.fromObject(i.vk_gamma_2), _ = s.G2.fromObject(i.vk_delta_2), v = s.G1.fromObject(i.vk_alpha_1), y = s.G2.fromObject(i.vk_beta_2); + return await s.pairingEq(s.G1.neg(p), m, f, g, h, _, v, y) ? (r && r.info("OK!"), !0) : (r && r.error("Invalid proof"), !1); +} +function Gt(e, t) { + let n = e.G1, r = e.G2; + return n.isValid(t.pi_a) && r.isValid(t.pi_b) && n.isValid(t.pi_c); +} +function Kt(e, t) { + return u.geq(t, 0) && u.lt(t, e.r); +} +function qt(e, t) { + for (let n = 0; n < t.length; n++) if (!Kt(e, t[n])) return !1; + return !0; +} +//#endregion +//#region src/groth16_exportsoliditycalldata.js +var { unstringifyBigInts: Jt } = p; +function Yt(e) { + let t = e.toString(16); + for (; t.length < 64;) t = "0" + t; + return t = `"0x${t}"`, t; +} +async function Xt(e, t) { + let n = Jt(e), r = Jt(t), i = ""; + for (let e = 0; e < r.length; e++) i != "" && (i += ","), i += Yt(r[e]); + let a; + return a = `[${Yt(n.pi_a[0])}, ${Yt(n.pi_a[1])}],[[${Yt(n.pi_b[0][1])}, ${Yt(n.pi_b[0][0])}],[${Yt(n.pi_b[1][1])}, ${Yt(n.pi_b[1][0])}]],[${Yt(n.pi_c[0])}, ${Yt(n.pi_c[1])}],[${i}]`, a; +} +//#endregion +//#region src/groth16.js +var Zt = /* @__PURE__ */ y({ + exportSolidityCallData: () => Xt, + fullProve: () => Ht, + prove: () => it, + verify: () => Wt }); - -/** - * Internal assertion helpers. - * @module - */ -/** Asserts something is positive integer. */ -function anumber(n) { - if (!Number.isSafeInteger(n) || n < 0) - throw new Error('positive integer expected, got ' + n); -} -/** Is number an Uint8Array? Copied from utils for perf. */ -function isBytes(a) { - return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array'); -} -/** Asserts something is Uint8Array. */ -function abytes(b, ...lengths) { - if (!isBytes(b)) - throw new Error('Uint8Array expected'); - if (lengths.length > 0 && !lengths.includes(b.length)) - throw new Error('Uint8Array expected of length ' + lengths + ', got length=' + b.length); -} -/** Asserts a hash instance has not been destroyed / finished */ -function aexists(instance, checkFinished = true) { - if (instance.destroyed) - throw new Error('Hash instance has been destroyed'); - if (checkFinished && instance.finished) - throw new Error('Hash#digest() has already been called'); -} -/** Asserts output is properly-sized byte array */ -function aoutput(out, instance) { - abytes(out); - const min = instance.outputLen; - if (out.length < min) { - throw new Error('digestInto() expects output buffer of length at least ' + min); - } -} - -/** - * Utilities for hex, bytes, CSPRNG. - * @module - */ -function u32(arr) { - return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4)); -} -/** Is current platform little-endian? Most are. Big-Endian platform: IBM */ -const isLE = /* @__PURE__ */ (() => new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44)(); -// The byte swap operation for uint32 -function byteSwap(word) { - return (((word << 24) & 0xff000000) | - ((word << 8) & 0xff0000) | - ((word >>> 8) & 0xff00) | - ((word >>> 24) & 0xff)); -} -/** Conditionally byte swap if on a big-endian platform */ -const byteSwapIfBE = isLE - ? (n) => n - : (n) => byteSwap(n); -/** In place byte swap for Uint32Array */ -function byteSwap32(arr) { - for (let i = 0; i < arr.length; i++) { - arr[i] = byteSwap(arr[i]); - } -} -/** - * Convert JS string to byte array. - * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99]) - */ -function utf8ToBytes(str) { - if (typeof str !== 'string') - throw new Error('utf8ToBytes expected string, got ' + typeof str); - return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809 -} -/** - * Normalizes (non-hex) string or Uint8Array to Uint8Array. - * Warning: when Uint8Array is passed, it would NOT get copied. - * Keep in mind for future mutable operations. - */ -function toBytes(data) { - if (typeof data === 'string') - data = utf8ToBytes(data); - abytes(data); - return data; -} -/** For runtime check if class implements interface */ -class Hash { - // Safe version that clones internal state - clone() { - return this._cloneInto(); - } -} -/** Wraps hash function, creating an interface on top of it */ -function wrapConstructor(hashCons) { - const hashC = (msg) => hashCons().update(toBytes(msg)).digest(); - const tmp = hashCons(); - hashC.outputLen = tmp.outputLen; - hashC.blockLen = tmp.blockLen; - hashC.create = () => hashCons(); - return hashC; -} -function wrapConstructorWithOpts(hashCons) { - const hashC = (msg, opts) => hashCons(opts).update(toBytes(msg)).digest(); - const tmp = hashCons({}); - hashC.outputLen = tmp.outputLen; - hashC.blockLen = tmp.blockLen; - hashC.create = (opts) => hashCons(opts); - return hashC; -} - -/** - * Internal helpers for blake hash. - * @module - */ -/** - * Internal blake variable. - * For BLAKE2b, the two extra permutations for rounds 10 and 11 are SIGMA[10..11] = SIGMA[0..1]. - */ -// prettier-ignore -const SIGMA = /* @__PURE__ */ new Uint8Array([ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3, - 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4, - 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8, - 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13, - 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9, - 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11, - 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10, - 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5, - 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3, - // Blake1, unused in others - 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4, - 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8, - 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13, - 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9, -]); -/** Class, from which others are subclassed. */ -class BLAKE extends Hash { - constructor(blockLen, outputLen, opts = {}, keyLen, saltLen, persLen) { - super(); - this.blockLen = blockLen; - this.outputLen = outputLen; - this.length = 0; - this.pos = 0; - this.finished = false; - this.destroyed = false; - anumber(blockLen); - anumber(outputLen); - anumber(keyLen); - if (outputLen < 0 || outputLen > keyLen) - throw new Error('outputLen bigger than keyLen'); - if (opts.key !== undefined && (opts.key.length < 1 || opts.key.length > keyLen)) - throw new Error('key length must be undefined or 1..' + keyLen); - if (opts.salt !== undefined && opts.salt.length !== saltLen) - throw new Error('salt must be undefined or ' + saltLen); - if (opts.personalization !== undefined && opts.personalization.length !== persLen) - throw new Error('personalization must be undefined or ' + persLen); - this.buffer = new Uint8Array(blockLen); - this.buffer32 = u32(this.buffer); - } - update(data) { - aexists(this); - // Main difference with other hashes: there is flag for last block, - // so we cannot process current block before we know that there - // is the next one. This significantly complicates logic and reduces ability - // to do zero-copy processing - const { blockLen, buffer, buffer32 } = this; - data = toBytes(data); - const len = data.length; - const offset = data.byteOffset; - const buf = data.buffer; - for (let pos = 0; pos < len;) { - // If buffer is full and we still have input (don't process last block, same as blake2s) - if (this.pos === blockLen) { - if (!isLE) - byteSwap32(buffer32); - this.compress(buffer32, 0, false); - if (!isLE) - byteSwap32(buffer32); - this.pos = 0; - } - const take = Math.min(blockLen - this.pos, len - pos); - const dataOffset = offset + pos; - // full block && aligned to 4 bytes && not last in input - if (take === blockLen && !(dataOffset % 4) && pos + take < len) { - const data32 = new Uint32Array(buf, dataOffset, Math.floor((len - pos) / 4)); - if (!isLE) - byteSwap32(data32); - for (let pos32 = 0; pos + blockLen < len; pos32 += buffer32.length, pos += blockLen) { - this.length += blockLen; - this.compress(data32, pos32, false); - } - if (!isLE) - byteSwap32(data32); - continue; - } - buffer.set(data.subarray(pos, pos + take), this.pos); - this.pos += take; - this.length += take; - pos += take; - } - return this; - } - digestInto(out) { - aexists(this); - aoutput(out, this); - const { pos, buffer32 } = this; - this.finished = true; - // Padding - this.buffer.subarray(pos).fill(0); - if (!isLE) - byteSwap32(buffer32); - this.compress(buffer32, 0, true); - if (!isLE) - byteSwap32(buffer32); - const out32 = u32(out); - this.get().forEach((v, i) => (out32[i] = byteSwapIfBE(v))); - } - digest() { - const { buffer, outputLen } = this; - this.digestInto(buffer); - const res = buffer.slice(0, outputLen); - this.destroy(); - return res; - } - _cloneInto(to) { - const { buffer, length, finished, destroyed, outputLen, pos } = this; - to || (to = new this.constructor({ dkLen: outputLen })); - to.set(...this.get()); - to.length = length; - to.finished = finished; - to.destroyed = destroyed; - to.outputLen = outputLen; - to.buffer.set(buffer); - to.pos = pos; - return to; - } -} - -/** - * Internal helpers for u64. BigUint64Array is too slow as per 2025, so we implement it using Uint32Array. - * @todo re-check https://issues.chromium.org/issues/42212588 - * @module - */ -const U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1); -const _32n = /* @__PURE__ */ BigInt(32); -function fromBig(n, le = false) { - if (le) - return { h: Number(n & U32_MASK64), l: Number((n >> _32n) & U32_MASK64) }; - return { h: Number((n >> _32n) & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 }; -} -function split(lst, le = false) { - let Ah = new Uint32Array(lst.length); - let Al = new Uint32Array(lst.length); - for (let i = 0; i < lst.length; i++) { - const { h, l } = fromBig(lst[i], le); - [Ah[i], Al[i]] = [h, l]; - } - return [Ah, Al]; -} -const toBig = (h, l) => (BigInt(h >>> 0) << _32n) | BigInt(l >>> 0); -// for Shift in [0, 32) -const shrSH = (h, _l, s) => h >>> s; -const shrSL = (h, l, s) => (h << (32 - s)) | (l >>> s); -// Right rotate for Shift in [1, 32) -const rotrSH = (h, l, s) => (h >>> s) | (l << (32 - s)); -const rotrSL = (h, l, s) => (h << (32 - s)) | (l >>> s); -// Right rotate for Shift in (32, 64), NOTE: 32 is special case. -const rotrBH = (h, l, s) => (h << (64 - s)) | (l >>> (s - 32)); -const rotrBL = (h, l, s) => (h >>> (s - 32)) | (l << (64 - s)); -// Right rotate for shift===32 (just swaps l&h) -const rotr32H = (_h, l) => l; -const rotr32L = (h, _l) => h; -// Left rotate for Shift in [1, 32) -const rotlSH = (h, l, s) => (h << s) | (l >>> (32 - s)); -const rotlSL = (h, l, s) => (l << s) | (h >>> (32 - s)); -// Left rotate for Shift in (32, 64), NOTE: 32 is special case. -const rotlBH = (h, l, s) => (l << (s - 32)) | (h >>> (64 - s)); -const rotlBL = (h, l, s) => (h << (s - 32)) | (l >>> (64 - s)); -// JS uses 32-bit signed integers for bitwise operations which means we cannot -// simple take carry out of low bit sum by shift, we need to use division. -function add(Ah, Al, Bh, Bl) { - const l = (Al >>> 0) + (Bl >>> 0); - return { h: (Ah + Bh + ((l / 2 ** 32) | 0)) | 0, l: l | 0 }; -} -// Addition with more than 2 elements -const add3L = (Al, Bl, Cl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0); -const add3H = (low, Ah, Bh, Ch) => (Ah + Bh + Ch + ((low / 2 ** 32) | 0)) | 0; -const add4L = (Al, Bl, Cl, Dl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0); -const add4H = (low, Ah, Bh, Ch, Dh) => (Ah + Bh + Ch + Dh + ((low / 2 ** 32) | 0)) | 0; -const add5L = (Al, Bl, Cl, Dl, El) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0); -const add5H = (low, Ah, Bh, Ch, Dh, Eh) => (Ah + Bh + Ch + Dh + Eh + ((low / 2 ** 32) | 0)) | 0; -// prettier-ignore -const u64 = { - fromBig, split, toBig, - shrSH, shrSL, - rotrSH, rotrSL, rotrBH, rotrBL, - rotr32H, rotr32L, - rotlSH, rotlSL, rotlBH, rotlBL, - add, add3L, add3H, add4L, add4H, add5H, add5L, -}; -var u64$1 = u64; - -/** - * Blake2b hash function. Focuses on 64-bit platforms, but in JS speed different from Blake2s is negligible. - * @module - */ -// Same as SHA-512 but LE -// prettier-ignore -const B2B_IV = /* @__PURE__ */ new Uint32Array([ - 0xf3bcc908, 0x6a09e667, 0x84caa73b, 0xbb67ae85, 0xfe94f82b, 0x3c6ef372, 0x5f1d36f1, 0xa54ff53a, - 0xade682d1, 0x510e527f, 0x2b3e6c1f, 0x9b05688c, 0xfb41bd6b, 0x1f83d9ab, 0x137e2179, 0x5be0cd19 -]); -// Temporary buffer -const BBUF = /* @__PURE__ */ new Uint32Array(32); -// Mixing function G splitted in two halfs -function G1b(a, b, c, d, msg, x) { - // NOTE: V is LE here - const Xl = msg[x], Xh = msg[x + 1]; // prettier-ignore - let Al = BBUF[2 * a], Ah = BBUF[2 * a + 1]; // prettier-ignore - let Bl = BBUF[2 * b], Bh = BBUF[2 * b + 1]; // prettier-ignore - let Cl = BBUF[2 * c], Ch = BBUF[2 * c + 1]; // prettier-ignore - let Dl = BBUF[2 * d], Dh = BBUF[2 * d + 1]; // prettier-ignore - // v[a] = (v[a] + v[b] + x) | 0; - let ll = u64$1.add3L(Al, Bl, Xl); - Ah = u64$1.add3H(ll, Ah, Bh, Xh); - Al = ll | 0; - // v[d] = rotr(v[d] ^ v[a], 32) - ({ Dh, Dl } = { Dh: Dh ^ Ah, Dl: Dl ^ Al }); - ({ Dh, Dl } = { Dh: u64$1.rotr32H(Dh, Dl), Dl: u64$1.rotr32L(Dh, Dl) }); - // v[c] = (v[c] + v[d]) | 0; - ({ h: Ch, l: Cl } = u64$1.add(Ch, Cl, Dh, Dl)); - // v[b] = rotr(v[b] ^ v[c], 24) - ({ Bh, Bl } = { Bh: Bh ^ Ch, Bl: Bl ^ Cl }); - ({ Bh, Bl } = { Bh: u64$1.rotrSH(Bh, Bl, 24), Bl: u64$1.rotrSL(Bh, Bl, 24) }); - (BBUF[2 * a] = Al), (BBUF[2 * a + 1] = Ah); - (BBUF[2 * b] = Bl), (BBUF[2 * b + 1] = Bh); - (BBUF[2 * c] = Cl), (BBUF[2 * c + 1] = Ch); - (BBUF[2 * d] = Dl), (BBUF[2 * d + 1] = Dh); -} -function G2b(a, b, c, d, msg, x) { - // NOTE: V is LE here - const Xl = msg[x], Xh = msg[x + 1]; // prettier-ignore - let Al = BBUF[2 * a], Ah = BBUF[2 * a + 1]; // prettier-ignore - let Bl = BBUF[2 * b], Bh = BBUF[2 * b + 1]; // prettier-ignore - let Cl = BBUF[2 * c], Ch = BBUF[2 * c + 1]; // prettier-ignore - let Dl = BBUF[2 * d], Dh = BBUF[2 * d + 1]; // prettier-ignore - // v[a] = (v[a] + v[b] + x) | 0; - let ll = u64$1.add3L(Al, Bl, Xl); - Ah = u64$1.add3H(ll, Ah, Bh, Xh); - Al = ll | 0; - // v[d] = rotr(v[d] ^ v[a], 16) - ({ Dh, Dl } = { Dh: Dh ^ Ah, Dl: Dl ^ Al }); - ({ Dh, Dl } = { Dh: u64$1.rotrSH(Dh, Dl, 16), Dl: u64$1.rotrSL(Dh, Dl, 16) }); - // v[c] = (v[c] + v[d]) | 0; - ({ h: Ch, l: Cl } = u64$1.add(Ch, Cl, Dh, Dl)); - // v[b] = rotr(v[b] ^ v[c], 63) - ({ Bh, Bl } = { Bh: Bh ^ Ch, Bl: Bl ^ Cl }); - ({ Bh, Bl } = { Bh: u64$1.rotrBH(Bh, Bl, 63), Bl: u64$1.rotrBL(Bh, Bl, 63) }); - (BBUF[2 * a] = Al), (BBUF[2 * a + 1] = Ah); - (BBUF[2 * b] = Bl), (BBUF[2 * b + 1] = Bh); - (BBUF[2 * c] = Cl), (BBUF[2 * c + 1] = Ch); - (BBUF[2 * d] = Dl), (BBUF[2 * d + 1] = Dh); -} -class BLAKE2b extends BLAKE { - constructor(opts = {}) { - super(128, opts.dkLen === undefined ? 64 : opts.dkLen, opts, 64, 16, 16); - // Same as SHA-512, but LE - this.v0l = B2B_IV[0] | 0; - this.v0h = B2B_IV[1] | 0; - this.v1l = B2B_IV[2] | 0; - this.v1h = B2B_IV[3] | 0; - this.v2l = B2B_IV[4] | 0; - this.v2h = B2B_IV[5] | 0; - this.v3l = B2B_IV[6] | 0; - this.v3h = B2B_IV[7] | 0; - this.v4l = B2B_IV[8] | 0; - this.v4h = B2B_IV[9] | 0; - this.v5l = B2B_IV[10] | 0; - this.v5h = B2B_IV[11] | 0; - this.v6l = B2B_IV[12] | 0; - this.v6h = B2B_IV[13] | 0; - this.v7l = B2B_IV[14] | 0; - this.v7h = B2B_IV[15] | 0; - const keyLength = opts.key ? opts.key.length : 0; - this.v0l ^= this.outputLen | (keyLength << 8) | (0x01 << 16) | (0x01 << 24); - if (opts.salt) { - const salt = u32(toBytes(opts.salt)); - this.v4l ^= byteSwapIfBE(salt[0]); - this.v4h ^= byteSwapIfBE(salt[1]); - this.v5l ^= byteSwapIfBE(salt[2]); - this.v5h ^= byteSwapIfBE(salt[3]); - } - if (opts.personalization) { - const pers = u32(toBytes(opts.personalization)); - this.v6l ^= byteSwapIfBE(pers[0]); - this.v6h ^= byteSwapIfBE(pers[1]); - this.v7l ^= byteSwapIfBE(pers[2]); - this.v7h ^= byteSwapIfBE(pers[3]); - } - if (opts.key) { - // Pad to blockLen and update - const tmp = new Uint8Array(this.blockLen); - tmp.set(toBytes(opts.key)); - this.update(tmp); - } - } - // prettier-ignore - get() { - let { v0l, v0h, v1l, v1h, v2l, v2h, v3l, v3h, v4l, v4h, v5l, v5h, v6l, v6h, v7l, v7h } = this; - return [v0l, v0h, v1l, v1h, v2l, v2h, v3l, v3h, v4l, v4h, v5l, v5h, v6l, v6h, v7l, v7h]; - } - // prettier-ignore - set(v0l, v0h, v1l, v1h, v2l, v2h, v3l, v3h, v4l, v4h, v5l, v5h, v6l, v6h, v7l, v7h) { - this.v0l = v0l | 0; - this.v0h = v0h | 0; - this.v1l = v1l | 0; - this.v1h = v1h | 0; - this.v2l = v2l | 0; - this.v2h = v2h | 0; - this.v3l = v3l | 0; - this.v3h = v3h | 0; - this.v4l = v4l | 0; - this.v4h = v4h | 0; - this.v5l = v5l | 0; - this.v5h = v5h | 0; - this.v6l = v6l | 0; - this.v6h = v6h | 0; - this.v7l = v7l | 0; - this.v7h = v7h | 0; - } - compress(msg, offset, isLast) { - this.get().forEach((v, i) => (BBUF[i] = v)); // First half from state. - BBUF.set(B2B_IV, 16); // Second half from IV. - let { h, l } = u64$1.fromBig(BigInt(this.length)); - BBUF[24] = B2B_IV[8] ^ l; // Low word of the offset. - BBUF[25] = B2B_IV[9] ^ h; // High word. - // Invert all bits for last block - if (isLast) { - BBUF[28] = ~BBUF[28]; - BBUF[29] = ~BBUF[29]; - } - let j = 0; - const s = SIGMA; - for (let i = 0; i < 12; i++) { - G1b(0, 4, 8, 12, msg, offset + 2 * s[j++]); - G2b(0, 4, 8, 12, msg, offset + 2 * s[j++]); - G1b(1, 5, 9, 13, msg, offset + 2 * s[j++]); - G2b(1, 5, 9, 13, msg, offset + 2 * s[j++]); - G1b(2, 6, 10, 14, msg, offset + 2 * s[j++]); - G2b(2, 6, 10, 14, msg, offset + 2 * s[j++]); - G1b(3, 7, 11, 15, msg, offset + 2 * s[j++]); - G2b(3, 7, 11, 15, msg, offset + 2 * s[j++]); - G1b(0, 5, 10, 15, msg, offset + 2 * s[j++]); - G2b(0, 5, 10, 15, msg, offset + 2 * s[j++]); - G1b(1, 6, 11, 12, msg, offset + 2 * s[j++]); - G2b(1, 6, 11, 12, msg, offset + 2 * s[j++]); - G1b(2, 7, 8, 13, msg, offset + 2 * s[j++]); - G2b(2, 7, 8, 13, msg, offset + 2 * s[j++]); - G1b(3, 4, 9, 14, msg, offset + 2 * s[j++]); - G2b(3, 4, 9, 14, msg, offset + 2 * s[j++]); - } - this.v0l ^= BBUF[0] ^ BBUF[16]; - this.v0h ^= BBUF[1] ^ BBUF[17]; - this.v1l ^= BBUF[2] ^ BBUF[18]; - this.v1h ^= BBUF[3] ^ BBUF[19]; - this.v2l ^= BBUF[4] ^ BBUF[20]; - this.v2h ^= BBUF[5] ^ BBUF[21]; - this.v3l ^= BBUF[6] ^ BBUF[22]; - this.v3h ^= BBUF[7] ^ BBUF[23]; - this.v4l ^= BBUF[8] ^ BBUF[24]; - this.v4h ^= BBUF[9] ^ BBUF[25]; - this.v5l ^= BBUF[10] ^ BBUF[26]; - this.v5h ^= BBUF[11] ^ BBUF[27]; - this.v6l ^= BBUF[12] ^ BBUF[28]; - this.v6h ^= BBUF[13] ^ BBUF[29]; - this.v7l ^= BBUF[14] ^ BBUF[30]; - this.v7h ^= BBUF[15] ^ BBUF[31]; - BBUF.fill(0); - } - destroy() { - this.destroyed = true; - this.buffer32.fill(0); - this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - } -} -/** - * Blake2b hash function. Focuses on 64-bit platforms, but in JS speed different from Blake2s is negligible. - * @param msg - message that would be hashed - * @param opts - dkLen output length, key for MAC mode, salt, personalization - */ -const blake2b = /* @__PURE__ */ wrapConstructorWithOpts((opts) => new BLAKE2b(opts)); - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - - -function log2( V ) -{ - return( ( ( V & 0xFFFF0000 ) !== 0 ? ( V &= 0xFFFF0000, 16 ) : 0 ) | ( ( V & 0xFF00FF00 ) !== 0 ? ( V &= 0xFF00FF00, 8 ) : 0 ) | ( ( V & 0xF0F0F0F0 ) !== 0 ? ( V &= 0xF0F0F0F0, 4 ) : 0 ) | ( ( V & 0xCCCCCCCC ) !== 0 ? ( V &= 0xCCCCCCCC, 2 ) : 0 ) | ( ( V & 0xAAAAAAAA ) !== 0 ) ); -} - - -function formatHash(b, title) { - const a = new DataView(b.buffer, b.byteOffset, b.byteLength); - let S = ""; - for (let i=0; i<4; i++) { - if (i>0) S += "\n"; - S += "\t\t"; - for (let j=0; j<4; j++) { - if (j>0) S += " "; - S += a.getUint32(i*16+j*4).toString(16).padStart(8, "0"); - } - } - if (title) S = title + "\n" + S; - return S; -} - -function hashIsEqual(h1, h2) { - if (h1.byteLength != h2.byteLength) return false; - var dv1 = new Int8Array(h1); - var dv2 = new Int8Array(h2); - for (var i = 0 ; i != h1.byteLength ; i++) - { - if (dv1[i] != dv2[i]) return false; - } - return true; -} - -function cloneHasher(h) { - return h.clone(); -} - -function fromPartialHash(partial) { - // NOTE: this is unsafe and uses internal API - const buf = partial.subarray(0, 128); - const rest = u32(partial.subarray(128)); - const res = blake2b.create({ dkLen: 64 }); - res.buffer.set(buf); - (res.v0l = rest[0] | 0), (res.v0h = rest[1] | 0); - (res.v1l = rest[2] | 0), (res.v1h = rest[3] | 0); - (res.v2l = rest[4] | 0), (res.v2h = rest[5] | 0); - (res.v3l = rest[6] | 0), (res.v3h = rest[7] | 0); - (res.v4l = rest[8] | 0), (res.v4h = rest[9] | 0); - (res.v5l = rest[10] | 0), (res.v5h = rest[11] | 0); - (res.v6l = rest[12] | 0), (res.v6h = rest[13] | 0); - (res.v7l = rest[14] | 0), (res.v7h = rest[15] | 0); - const shift = 2 ** 32; - const len = rest[16] + rest[17] * shift; - const pos = rest[18] + rest[19] * shift; - res.length = len + pos; - res.pos = pos; - return res; -} - -function toPartialHash(hash){ - // NOTE: this is unsafe and uses internal API - const res = new Uint8Array(216); - const res32 = u32(res.subarray(128)); - res.set(hash.buffer); - (res32[0] = hash.v0l), (res32[1] = hash.v0h); - (res32[2] = hash.v1l), (res32[3] = hash.v1h); - (res32[4] = hash.v2l), (res32[5] = hash.v2h); - (res32[6] = hash.v3l), (res32[7] = hash.v3h); - (res32[8] = hash.v4l), (res32[9] = hash.v4h); - (res32[10] = hash.v5l), (res32[11] = hash.v5h); - (res32[12] = hash.v6l), (res32[13] = hash.v6h); - (res32[14] = hash.v7l), (res32[15] = hash.v7h); - res32[18] = hash.pos; - res32[16] = hash.length-hash.pos; - return res; -} - -async function sameRatio$2(curve, g1s, g1sx, g2s, g2sx) { - if (curve.G1.isZero(g1s)) return false; - if (curve.G1.isZero(g1sx)) return false; - if (curve.G2.isZero(g2s)) return false; - if (curve.G2.isZero(g2sx)) return false; - // return curve.F12.eq(curve.pairing(g1s, g2sx), curve.pairing(g1sx, g2s)); - const res = await curve.pairingEq(g1s, g2sx, curve.G1.neg(g1sx), g2s); - return res; -} - - -function askEntropy() { - { - return window.prompt("Enter a random text. (Entropy): ", ""); - } -} - -function getRandomBytes(n) { - let array = new Uint8Array(n); - { // Supported - globalThis.crypto.getRandomValues(array); - } - return array; -} - -async function sha256digest(data) { - { // Supported - const buffer = await globalThis.crypto.subtle.digest("SHA-256", data.buffer); - return new Uint8Array(buffer); - } -} - -/** - * @param {Uint8Array} data - * @param {number} offset - */ -function readUInt32BE(data, offset) { - return new DataView(data.buffer).getUint32(offset, false); -} - -async function getRandomRng(entropy) { - // Generate a random Rng - while (!entropy) { - entropy = await askEntropy(); - } - const hasher = blake2b.create(64); - hasher.update(getRandomBytes(64)); - const enc = new TextEncoder(); // always utf-8 - hasher.update(enc.encode(entropy)); - const hash = hasher.digest(); - - const seed = []; - for (let i=0;i<8;i++) { - seed[i] = readUInt32BE(hash, i*4); - } - const rng = new ChaCha(seed); - return rng; -} - -async function rngFromBeaconParams(beaconHash, numIterationsExp) { - let nIterationsInner; - let nIterationsOuter; - if (numIterationsExp<32) { - nIterationsInner = (1 << numIterationsExp) >>> 0; - nIterationsOuter = 1; - } else { - nIterationsInner = 0x100000000; - nIterationsOuter = (1 << (numIterationsExp-32)) >>> 0; - } - - let curHash = beaconHash; - for (let i=0; i { - res[k] = stringifyBigIntsWithField(Fr, o[k]); - }); - return res; - } else if ((typeof(o) == "bigint") || o.eq !== undefined) { - return o.toString(10); - } else { - return o; - } -} - -const HEADER_ZKEY_SECTION = 1; - -const GROTH16_PROTOCOL_ID = 1; -const PLONK_PROTOCOL_ID = 2; -const FFLONK_PROTOCOL_ID = 10; - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -// FFlonk constants -const FF_T_POL_DEG_MIN = 3; - -// ZKEY constants -const ZKEY_FF_NSECTIONS = 17; - -const ZKEY_FF_HEADER_SECTION = 2; -const ZKEY_FF_ADDITIONS_SECTION = 3; -const ZKEY_FF_A_MAP_SECTION = 4; -const ZKEY_FF_B_MAP_SECTION = 5; -const ZKEY_FF_C_MAP_SECTION = 6; -const ZKEY_FF_QL_SECTION = 7; -const ZKEY_FF_QR_SECTION = 8; -const ZKEY_FF_QM_SECTION = 9; -const ZKEY_FF_QO_SECTION = 10; -const ZKEY_FF_QC_SECTION = 11; -const ZKEY_FF_SIGMA1_SECTION = 12; -const ZKEY_FF_SIGMA2_SECTION = 13; -const ZKEY_FF_SIGMA3_SECTION = 14; -const ZKEY_FF_LAGRANGE_SECTION = 15; -const ZKEY_FF_PTAU_SECTION = 16; -const ZKEY_FF_C0_SECTION = 17; - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -async function writeHeader(fd, zkey) { - - // Write the header - /////////// - await startWriteSection(fd, 1); - await fd.writeULE32(1); // Groth - await endWriteSection(fd); - - // Write the Groth header section - /////////// - - const curve = await getCurveFromQ(zkey.q); - - await startWriteSection(fd, 2); - const primeQ = curve.q; - const n8q = (Math.floor( (Scalar.bitLength(primeQ) - 1) / 64) +1)*8; - - const primeR = curve.r; - const n8r = (Math.floor( (Scalar.bitLength(primeR) - 1) / 64) +1)*8; - - await fd.writeULE32(n8q); - await writeBigInt(fd, primeQ, n8q); - await fd.writeULE32(n8r); - await writeBigInt(fd, primeR, n8r); - await fd.writeULE32(zkey.nVars); // Total number of bars - await fd.writeULE32(zkey.nPublic); // Total number of public vars (not including ONE) - await fd.writeULE32(zkey.domainSize); // domainSize - await writeG1(fd, curve, zkey.vk_alpha_1); - await writeG1(fd, curve, zkey.vk_beta_1); - await writeG2(fd, curve, zkey.vk_beta_2); - await writeG2(fd, curve, zkey.vk_gamma_2); - await writeG1(fd, curve, zkey.vk_delta_1); - await writeG2(fd, curve, zkey.vk_delta_2); - - await endWriteSection(fd); - - -} - -async function writeG1(fd, curve, p) { - const buff = new Uint8Array(curve.G1.F.n8*2); - curve.G1.toRprLEM(buff, 0, p); - await fd.write(buff); -} - -async function writeG2(fd, curve, p) { - const buff = new Uint8Array(curve.G2.F.n8*2); - curve.G2.toRprLEM(buff, 0, p); - await fd.write(buff); -} - -async function readG1(fd, curve, toObject) { - const buff = await fd.read(curve.G1.F.n8*2); - const res = curve.G1.fromRprLEM(buff, 0); - return toObject ? curve.G1.toObject(res) : res; -} - -async function readG2(fd, curve, toObject) { - const buff = await fd.read(curve.G2.F.n8*2); - const res = curve.G2.fromRprLEM(buff, 0); - return toObject ? curve.G2.toObject(res) : res; -} - - -async function readHeader$1(fd, sections, toObject, options) { - // Read Header - ///////////////////// - await startReadUniqueSection$1(fd, sections, 1); - const protocolId = await fd.readULE32(); - await endReadSection$1(fd); - - if (protocolId === GROTH16_PROTOCOL_ID) { - return await readHeaderGroth16(fd, sections, toObject, options); - } else if (protocolId === PLONK_PROTOCOL_ID) { - return await readHeaderPlonk(fd, sections, toObject, options); - } else if (protocolId === FFLONK_PROTOCOL_ID) { - return await readHeaderFFlonk(fd, sections, toObject, options); - } else { - throw new Error("Protocol not supported: "); - } -} - - - - -async function readHeaderGroth16(fd, sections, toObject, options) { - const zkey = {}; - - zkey.protocol = "groth16"; - - // Read Groth Header - ///////////////////// - await startReadUniqueSection$1(fd, sections, 2); - const n8q = await fd.readULE32(); - zkey.n8q = n8q; - zkey.q = await readBigInt$1(fd, n8q); - - const n8r = await fd.readULE32(); - zkey.n8r = n8r; - zkey.r = await readBigInt$1(fd, n8r); - zkey.curve = await getCurveFromQ(zkey.q, options); - zkey.nVars = await fd.readULE32(); - zkey.nPublic = await fd.readULE32(); - zkey.domainSize = await fd.readULE32(); - zkey.power = log2(zkey.domainSize); - zkey.vk_alpha_1 = await readG1(fd, zkey.curve, toObject); - zkey.vk_beta_1 = await readG1(fd, zkey.curve, toObject); - zkey.vk_beta_2 = await readG2(fd, zkey.curve, toObject); - zkey.vk_gamma_2 = await readG2(fd, zkey.curve, toObject); - zkey.vk_delta_1 = await readG1(fd, zkey.curve, toObject); - zkey.vk_delta_2 = await readG2(fd, zkey.curve, toObject); - await endReadSection$1(fd); - - return zkey; - -} - -async function readHeaderPlonk(fd, sections, toObject, options) { - const zkey = {}; - - zkey.protocol = "plonk"; - - // Read Plonk Header - ///////////////////// - await startReadUniqueSection$1(fd, sections, 2); - const n8q = await fd.readULE32(); - zkey.n8q = n8q; - zkey.q = await readBigInt$1(fd, n8q); - - const n8r = await fd.readULE32(); - zkey.n8r = n8r; - zkey.r = await readBigInt$1(fd, n8r); - zkey.curve = await getCurveFromQ(zkey.q, options); - zkey.nVars = await fd.readULE32(); - zkey.nPublic = await fd.readULE32(); - zkey.domainSize = await fd.readULE32(); - zkey.power = log2(zkey.domainSize); - zkey.nAdditions = await fd.readULE32(); - zkey.nConstraints = await fd.readULE32(); - zkey.k1 = await fd.read(n8r); - zkey.k2 = await fd.read(n8r); - - zkey.Qm = await readG1(fd, zkey.curve, toObject); - zkey.Ql = await readG1(fd, zkey.curve, toObject); - zkey.Qr = await readG1(fd, zkey.curve, toObject); - zkey.Qo = await readG1(fd, zkey.curve, toObject); - zkey.Qc = await readG1(fd, zkey.curve, toObject); - zkey.S1 = await readG1(fd, zkey.curve, toObject); - zkey.S2 = await readG1(fd, zkey.curve, toObject); - zkey.S3 = await readG1(fd, zkey.curve, toObject); - zkey.X_2 = await readG2(fd, zkey.curve, toObject); - - await endReadSection$1(fd); - - return zkey; -} - -async function readHeaderFFlonk(fd, sections, toObject, options) { - const zkey = {}; - - zkey.protocol = "fflonk"; - zkey.protocolId = FFLONK_PROTOCOL_ID; - - await startReadUniqueSection$1(fd, sections, ZKEY_FF_HEADER_SECTION); - const n8q = await fd.readULE32(); - zkey.n8q = n8q; - zkey.q = await readBigInt$1(fd, n8q); - zkey.curve = await getCurveFromQ(zkey.q, options); - - const n8r = await fd.readULE32(); - zkey.n8r = n8r; - zkey.r = await readBigInt$1(fd, n8r); - - zkey.nVars = await fd.readULE32(); - zkey.nPublic = await fd.readULE32(); - zkey.domainSize = await fd.readULE32(); - zkey.power = log2(zkey.domainSize); - zkey.nAdditions = await fd.readULE32(); - zkey.nConstraints = await fd.readULE32(); - - zkey.k1 = await fd.read(n8r); - zkey.k2 = await fd.read(n8r); - - zkey.w3 = await fd.read(n8r); - zkey.w4 = await fd.read(n8r); - zkey.w8 = await fd.read(n8r); - zkey.wr = await fd.read(n8r); - - zkey.X_2 = await readG2(fd, zkey.curve, toObject); - - zkey.C0 = await readG1(fd, zkey.curve, toObject); - - await endReadSection$1(fd); - - return zkey; -} - -async function readZKey(fileName, toObject) { - const {fd, sections} = await readBinFile$1(fileName, "zkey", 1); - - const zkey = await readHeader$1(fd, sections, toObject); - - const Fr = new F1Field(zkey.r); - const Rr = Scalar.mod(Scalar.shl(1, zkey.n8r*8), zkey.r); - const Rri = Fr.inv(Rr); - const Rri2 = Fr.mul(Rri, Rri); - - let curve = await getCurveFromQ(zkey.q); - - // Read IC Section - /////////// - await startReadUniqueSection$1(fd, sections, 3); - zkey.IC = []; - for (let i=0; i<= zkey.nPublic; i++) { - const P = await readG1(fd, curve, toObject); - zkey.IC.push(P); - } - await endReadSection$1(fd); - - - // Read Coefs - /////////// - await startReadUniqueSection$1(fd, sections, 4); - const nCCoefs = await fd.readULE32(); - zkey.ccoefs = []; - for (let i=0; i0) { - const paramsBuff = new Uint8Array(params); - await fd.writeULE32(paramsBuff.byteLength); - await fd.write(paramsBuff); - } else { - await fd.writeULE32(0); - } - -} - -async function writeMPCParams(fd, curve, mpcParams) { - await startWriteSection(fd, 10); - await fd.write(mpcParams.csHash); - await fd.writeULE32(mpcParams.contributions.length); - for (let i=0; i. -*/ - - -async function write(fd, witness, prime) { - - await startWriteSection(fd, 1); - const n8 = (Math.floor( (Scalar.bitLength(prime) - 1) / 64) +1)*8; - await fd.writeULE32(n8); - await writeBigInt(fd, prime, n8); - await fd.writeULE32(witness.length); - await endWriteSection(fd); - - await startWriteSection(fd, 2); - for (let i=0; i. -*/ -const {stringifyBigInts: stringifyBigInts$4} = utils; - -async function groth16Prove(zkeyFileName, witnessFileName, logger, options) { - - if (logger) monitorMemoryUsage(logger, 50); - const {fd: fdWtns, sections: sectionsWtns} = await readBinFile$1(witnessFileName, "wtns", 2); - - const wtns = await readHeader(fdWtns, sectionsWtns); - - const {fd: fdZKey, sections: sectionsZKey} = await readBinFile$1(zkeyFileName, "zkey", 2); - - const zkey = await readHeader$1(fdZKey, sectionsZKey, undefined, options); - - if (zkey.protocol != "groth16") { - throw new Error("zkey file is not groth16"); - } - - if (!Scalar.eq(zkey.r, wtns.q)) { - throw new Error("Curve of the witness does not match the curve of the proving key"); - } - - if (wtns.nWitness != zkey.nVars) { - throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}`); - } - - const curve = zkey.curve; - const Fr = curve.Fr; - const G1 = curve.G1; - const G2 = curve.G2; - - const power = log2(zkey.domainSize); - - if (logger) logger.debug("Reading Wtns"); - const buffWitness = await readSection$1(fdWtns, sectionsWtns, 2); - - let resH; - let resHPromise; - let buffPodd_T; - - let abcPromise = (async function (){ - let buffA_T, buffB_T, buffC_T; - - await (async function (){ - if (logger) logger.debug("Reading Coeffs"); - console.time("buildABC_outer"); - const buffCoeffs = await readSection$1(fdZKey, sectionsZKey, 4); - - if (logger) logger.debug("Building ABC"); - - options = options || {}; - //options.buildABC="wasm1"; // for testing - - if (options && options.buildABC==="wasm") { - // build ABC in WASM - [buffA_T, buffB_T, buffC_T] = await buildABC(curve, zkey, buffWitness, buffCoeffs, logger); - } else if (options && options.buildABC==="wasm1") { - // build ABC in WASM - [buffA_T, buffB_T, buffC_T] = await buildABCWASM1(curve, zkey, buffWitness, buffCoeffs, logger); - } else { - // default, build ABC in JS - [buffA_T, buffB_T, buffC_T] = await buildABC1(curve, zkey, buffWitness, buffCoeffs, logger); - } - console.timeEnd("buildABC_outer"); - })(); - - console.time("abcPromise"); - - if (globalThis.gc) {globalThis.gc();} - - const inc = power === Fr.s ? curve.Fr.shift : curve.Fr.w[power+1]; - - let buffAodd_T; - await (async function () { - let buffA = await Fr.ifft(buffA_T, "", "", logger, "IFFT_A"); - buffA_T = null; - const buffAodd = await Fr.batchApplyKey(buffA, Fr.e(1), inc); - buffAodd_T = await Fr.fft(buffAodd, "", "", logger, "FFT_A"); - })(); - - let buffBodd_T; - await (async function () { - const buffB = await Fr.ifft(buffB_T, "", "", logger, "IFFT_B"); - buffB_T = null; - const buffBodd = await Fr.batchApplyKey(buffB, Fr.e(1), inc); - buffBodd_T = await Fr.fft(buffBodd, "", "", logger, "FFT_B"); - })(); - - let buffCodd_T; - await (async function () { - const buffC = await Fr.ifft(buffC_T, "", "", logger, "IFFT_C"); - buffC_T = null; - const buffCodd = await Fr.batchApplyKey(buffC, Fr.e(1), inc); - buffCodd_T = await Fr.fft(buffCodd, "", "", logger, "FFT_C"); - })(); - - if (logger) logger.debug("Join ABC"); - buffPodd_T = await joinABC(curve, zkey, buffAodd_T, buffBodd_T, buffCodd_T, logger); - if (logger) logger.debug("Join ABC finished"); - buffAodd_T = null; - buffBodd_T = null; - buffCodd_T = null; - - if (globalThis.gc) {globalThis.gc();} - console.timeEnd("abcPromise"); - })(); - //await abcPromise; - - let proof = {}; - - async function calcPiA(){ - if (logger) logger.debug("Reading A Points"); - const buffBasesA = await readSection$1(fdZKey, sectionsZKey, 5); - console.time("Calculate PiA"); - proof.pi_a = await curve.G1.multiExpAffine(buffBasesA, buffWitness, logger, "multiexp A"); - console.timeEnd("Calculate PiA"); - } - - let piaPromise = calcPiA(); - //await piaPromise; - - let pib1; - - async function calcPiB1() { - if (logger) logger.debug("Reading B1 Points"); - const buffBasesB1 = await readSection$1(fdZKey, sectionsZKey, 6); - console.time("Calculate PiB1"); - pib1 = await curve.G1.multiExpAffine(buffBasesB1, buffWitness, logger, "multiexp B1"); - console.timeEnd("Calculate PiB1"); - } - - let pib1Promise = calcPiB1(); - //await pib1Promise; - - async function calcPiB() { - if (logger) logger.debug("Reading B2 Points"); - const buffBasesB2 = await readSection$1(fdZKey, sectionsZKey, 7); - console.time("Calculate PiB"); - proof.pi_b = await curve.G2.multiExpAffine(buffBasesB2, buffWitness, logger, "multiexp B2"); - console.timeEnd("Calculate PiB"); - } - - let pibPromise = calcPiB(); - //await pibPromise; - - let picPromise = (async function (){ - if (logger) logger.debug("Reading C Points"); - const buffBasesC = await readSection$1(fdZKey, sectionsZKey, 8); - console.time("Calculate PiC"); - proof.pi_c = await curve.G1.multiExpAffine(buffBasesC, buffWitness.slice((zkey.nPublic+1)*curve.Fr.n8), logger, "multiexp C"); - console.timeEnd("Calculate PiC"); - })(); - //await picPromise; - - - resHPromise = (async function (){ - if (logger) logger.debug("Reading H Points"); - await abcPromise; - console.time("resHPromise"); - const buffBasesH = await readSection$1(fdZKey, sectionsZKey, 9); - //await Promise.all([abcPromise, piaPromise, pib1Promise, pibPromise, picPromise]); - resH = await curve.G1.multiExpAffine(buffBasesH, buffPodd_T, logger, "multiexp H"); - //buffPodd_T = null; - console.timeEnd("resHPromise"); - })(); - //await resHPromise; - - - const r = curve.Fr.random(); - const s = curve.Fr.random(); - - await piaPromise; - proof.pi_a = G1.add( proof.pi_a, zkey.vk_alpha_1 ); - proof.pi_a = G1.add( proof.pi_a, G1.timesFr( zkey.vk_delta_1, r )); - - await pibPromise; - proof.pi_b = G2.add( proof.pi_b, zkey.vk_beta_2 ); - proof.pi_b = G2.add( proof.pi_b, G2.timesFr( zkey.vk_delta_2, s )); - - await pib1Promise; - pib1 = G1.add( pib1, zkey.vk_beta_1 ); - pib1 = G1.add( pib1, G1.timesFr( zkey.vk_delta_1, s )); - - await Promise.all([picPromise, resHPromise]); - proof.pi_c = G1.add(proof.pi_c, resH); - - - proof.pi_c = G1.add( proof.pi_c, G1.timesFr( proof.pi_a, s )); - proof.pi_c = G1.add( proof.pi_c, G1.timesFr( pib1, r )); - proof.pi_c = G1.add( proof.pi_c, G1.timesFr( zkey.vk_delta_1, Fr.neg(Fr.mul(r,s) ))); - - - let publicSignals = []; - - for (let i=1; i<= zkey.nPublic; i++) { - const b = buffWitness.slice(i*Fr.n8, i*Fr.n8+Fr.n8); - publicSignals.push(Scalar.fromRprLE(b)); - } - - proof.pi_a = G1.toObject(G1.toAffine(proof.pi_a)); - proof.pi_b = G2.toObject(G2.toAffine(proof.pi_b)); - proof.pi_c = G1.toObject(G1.toAffine(proof.pi_c)); - - proof.protocol = "groth16"; - proof.curve = curve.name; - - await fdZKey.close(); - await fdWtns.close(); - - proof = stringifyBigInts$4(proof); - publicSignals = stringifyBigInts$4(publicSignals); - - return {proof, publicSignals}; -} - - -async function buildABC1(curve, zkey, witness, coeffs, logger) { - const n8 = curve.Fr.n8; - const sCoef = 4*3 + zkey.n8r; - const nCoef = (coeffs.byteLength-4) / sCoef; - - const outBuffA = new BigBuffer(zkey.domainSize * n8); - const outBuffB = new BigBuffer(zkey.domainSize * n8); - const outBuffC = new BigBuffer(zkey.domainSize * n8); - - const outBuf = [ outBuffA, outBuffB ]; - for (let i=0; i 2**16) { - concurrency*=2; - elementsPerChunk = Math.floor(zkey.domainSize/concurrency); - } - console.log("@@@ new elementsPerChunk", elementsPerChunk); - - - const promises = []; - - const cutPoints = []; - for (let i=0; i1) { - const promises2 = []; - for (let i=0; i v) { - n = k - 1; - } else if (va < v) { - m = k + 1; - } else { - n = k; - } - } - return 4 + m*sCoef; - } -} - - -// buildABCWASM1 is single-threaded implementation of buildABS using wasm -// It has much better memory usage than multithreaded wasm implementation. -// It's much faster than pure js one, but uses much more memory. -async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { - console.time("buildABC"); - const concurrency = 1;//curve.tm.concurrency; - const sCoef = 4 * 3 + zkey.n8r; - - let getUint32; - - if (coeffs instanceof BigBuffer) { - const coeffsDV = []; - const PAGE_LEN = coeffs.buffers[0].length; - for (let i = 0; i < coeffs.buffers.length; i++) { - coeffsDV.push(new DataView(coeffs.buffers[i].buffer)); - } - getUint32 = function (pos) { - return coeffsDV[Math.floor(pos / PAGE_LEN)].getUint32(pos % PAGE_LEN, true); - }; - } else { - const coeffsDV = new DataView(coeffs.buffer, coeffs.byteOffset, coeffs.byteLength); - getUint32 = function (pos) { - return coeffsDV.getUint32(pos, true); - }; - } - - const elementsPerChunk = Math.floor((zkey.domainSize - 1) / concurrency) + 1; - const promises = []; - - const cutPoints = []; - for (let i = 0; i < concurrency; i++) { - cutPoints.push(getCutPoint(Math.floor(i * elementsPerChunk))); - } - cutPoints.push(coeffs.byteLength); - - //const chunkSize = 2**18; - const chunkSize = elementsPerChunk; - - console.log("zkey.domainSize", zkey.domainSize); - console.log("concurrency", concurrency); - console.log("elementsPerChunk", elementsPerChunk); - console.log("chunkSize", chunkSize); - - for (let s = 0; s < zkey.nVars; s += chunkSize) { - if (logger) logger.debug(`QAP: ${s}/${zkey.nVars}`); - const ns = Math.min(zkey.nVars - s, chunkSize); - - console.log("ns", ns); - - //let i=0; - for (let i = 0; i < concurrency; i++) { - let n; - if (i < concurrency - 1) { - n = elementsPerChunk; - } else { - n = zkey.domainSize - i * elementsPerChunk; - } - if (n === 0) continue; - - const task = []; - - const coeffsBuff = coeffs.slice(cutPoints[i], cutPoints[i + 1]); - const witnessBuff = witness.slice(s * curve.Fr.n8, (s + ns) * curve.Fr.n8); - - task.push({cmd: "ALLOCSET", var: 0, buff: coeffsBuff}); - task.push({cmd: "ALLOCSET", var: 1, buff: witnessBuff}); - task.push({cmd: "ALLOC", var: 2, len: n * curve.Fr.n8}); - task.push({cmd: "ALLOC", var: 3, len: n * curve.Fr.n8}); - task.push({cmd: "ALLOC", var: 4, len: n * curve.Fr.n8}); - task.push({ - cmd: "CALL", fnName: "qap_buildABC", params: [ - {var: 0}, - {val: (cutPoints[i + 1] - cutPoints[i]) / sCoef}, - {var: 1}, - {var: 2}, - {var: 3}, - {var: 4}, - {val: i * elementsPerChunk}, - {val: n}, - {val: s}, - {val: ns} - ] - }); - task.push({cmd: "GET", out: 0, var: 2, len: n * curve.Fr.n8}); - task.push({cmd: "GET", out: 1, var: 3, len: n * curve.Fr.n8}); - task.push({cmd: "GET", out: 2, var: 4, len: n * curve.Fr.n8}); - //task.push({cmd: "TERMINATE"}); // to free memory immediately - //promises.push(curve.tm.queueAction(task)); - promises.push(curve.tm.queueAction(task, [coeffsBuff.buffer, witnessBuff.buffer])); - } - } - - let result = await Promise.all(promises); - - - console.log("result.length", result.length); - console.log("result", result); - - const nGroups = result.length / concurrency; - - console.log("nGroups", nGroups); - let result2; - if (nGroups > 1) { - const promises2 = []; - for (let i = 0; i < concurrency; i++) { - const task = []; - task.push({cmd: "ALLOC", var: 0, len: result[i][0].byteLength}); - task.push({cmd: "ALLOC", var: 1, len: result[i][0].byteLength}); - for (let m = 0; m < 3; m++) { - task.push({cmd: "SET", var: 0, buff: result[i][m]}); - //transfers.push(result[i][m].buffer); - for (let s = 1; s < nGroups; s++) { - task.push({cmd: "SET", var: 1, buff: result[s * concurrency + i][m]}); - //transfers.push(result[s*concurrency + i][m].buffer); - task.push({ - cmd: "CALL", fnName: "qap_batchAdd", params: [ - {var: 0}, - {var: 1}, - {val: result[i][m].length / curve.Fr.n8}, - {var: 0} - ] - }); - } - task.push({cmd: "GET", out: m, var: 0, len: result[i][m].length}); - //task.push({cmd: "TERMINATE"}); // to free memory immediately - } - console.log("task.length", task.length); - //promises2.push(curve.tm.queueAction(task)); - promises2.push(curve.tm.queueAction(task, result.buffer)); - } - console.log("promises2.length", promises2.length); - result2 = await Promise.all(promises2); - result = result2; - } - - //console.log("result", result); - //console.log("result2", result2); - //result = result2 || result; - - const outBuffA = new BigBuffer(zkey.domainSize * curve.Fr.n8); - const outBuffB = new BigBuffer(zkey.domainSize * curve.Fr.n8); - const outBuffC = new BigBuffer(zkey.domainSize * curve.Fr.n8); - let p = 0; - for (let i = 0; i < result.length; i++) { - outBuffA.set(result[i][0], p); - outBuffB.set(result[i][1], p); - outBuffC.set(result[i][2], p); - p += result[i][0].byteLength; - } - - console.timeEnd("buildABC"); - - return [outBuffA, outBuffB, outBuffC]; - - function getCutPoint(v) { - let m = 0; - let n = getUint32(0); - while (m < n) { - let k = Math.floor((n + m) / 2); - const va = getUint32(4 + k * sCoef + 4); - if (va > v) { - n = k - 1; - } else if (va < v) { - m = k + 1; - } else { - n = k; - } - } - return 4 + m * sCoef; - } -} - - -async function joinABC(curve, zkey, a, b, c, logger) { - console.time("joinABC"); - const MAX_CHUNK_SIZE = 1 << 16; - - const n8 = curve.Fr.n8; - const nElements = Math.floor(a.byteLength / curve.Fr.n8); - - const promises = []; - - for (let i=0; i { - memUsage(logger); - }, interval); -} - -async function open$1(fileName, openFlags, cacheSize, pageSize) { - cacheSize = cacheSize || 4096*64; - if (typeof openFlags !== "number" && ["w+", "wx+", "r", "ax+", "a+"].indexOf(openFlags) <0) - throw new Error("Invalid open option"); - const fd =await fs.promises.open(fileName, openFlags); - - const stats = await fd.stat(); - - return new FastFile$1(fd, stats, cacheSize, pageSize, fileName); -} - - -class FastFile$1 { - - constructor(fd, stats, cacheSize, pageSize, fileName) { - this.fileName = fileName; - this.fd = fd; - this.pos = 0; - this.pageSize = pageSize || (1 << 8); - while (this.pageSize < stats.blksize) { - this.pageSize *= 2; - } - this.totalSize = stats.size; - this.totalPages = Math.floor((stats.size -1) / this.pageSize)+1; - this.maxPagesLoaded = Math.floor( cacheSize / this.pageSize)+1; - this.pages = {}; - this.pendingLoads = []; - this.writing = false; - this.reading = false; - this.avBuffs = []; - this.history = {}; - } - - _loadPage(p) { - const self = this; - const P = new Promise((resolve, reject)=> { - self.pendingLoads.push({ - page: p, - resolve: resolve, - reject: reject - }); - }); - self.__statusPage("After Load request: ", p); - return P; - } - - __statusPage(s, p) { - const logEntry = []; - const self=this; - if (!self.logHistory) return; - logEntry.push("==" + s+ " " +p); - let S = ""; - for (let i=0; i " + self.history[p][i][j]); - } - } - } - - - - _triggerLoad() { - const self = this; - - if (self.reading) return; - if (self.pendingLoads.length==0) return; - - const pageIdxs = Object.keys(self.pages); - - const deletablePages = []; - for (let i=0; i0) && - ( (typeof self.pages[self.pendingLoads[0].page] != "undefined" ) - ||( (freePages>0) - ||(deletablePages.length>0)))) { - const load = self.pendingLoads.shift(); - if (typeof self.pages[load.page] != "undefined") { - self.pages[load.page].pendingOps ++; - const idx = deletablePages.indexOf(load.page); - if (idx>=0) deletablePages.splice(idx, 1); - if (self.pages[load.page].loading) { - self.pages[load.page].loading.push(load); - } else { - load.resolve(); - } - self.__statusPage("After Load (cached): ", load.page); - - } else { - if (freePages) { - freePages--; - } else { - const fp = deletablePages.shift(); - self.__statusPage("Before Unload: ", fp); - self.avBuffs.unshift(self.pages[fp]); - delete self.pages[fp]; - self.__statusPage("After Unload: ", fp); - } - - if (load.page>=self.totalPages) { - self.pages[load.page] = getNewPage(); - load.resolve(); - self.__statusPage("After Load (new): ", load.page); - } else { - self.reading = true; - self.pages[load.page] = getNewPage(); - self.pages[load.page].loading = [load]; - ops.push(self.fd.read(self.pages[load.page].buff, 0, self.pageSize, load.page*self.pageSize).then((res)=> { - self.pages[load.page].size = res.bytesRead; - const loading = self.pages[load.page].loading; - delete self.pages[load.page].loading; - for (let i=0; i { - load.reject(err); - })); - self.__statusPage("After Load (loading): ", load.page); - } - } - } - // if (ops.length>1) console.log(ops.length); - - Promise.all(ops).then( () => { - self.reading = false; - if (self.pendingLoads.length>0) setImmediate(self._triggerLoad.bind(self)); - self._tryClose(); - }); - - function getNewPage() { - if (self.avBuffs.length>0) { - const p = self.avBuffs.shift(); - p.dirty = false; - p.pendingOps = 1; - p.size =0; - return p; - } else { - return { - dirty: false, - buff: new Uint8Array(self.pageSize), - pendingOps: 1, - size: 0 - }; - } - } - - } - - - _triggerWrite() { - const self = this; - if (self.writing) return; - - const pageIdxs = Object.keys(self.pages); - - const ops = []; - - for (let i=0; i { - page.writing = false; - return; - }, (err) => { - console.log("ERROR Writing: "+err); - self.error = err; - self._tryClose(); - })); - } - } - - if (self.writing) { - Promise.all(ops).then( () => { - self.writing = false; - setImmediate(self._triggerWrite.bind(self)); - self._tryClose(); - if (self.pendingLoads.length>0) setImmediate(self._triggerLoad.bind(self)); - }); - } - } - - _getDirtyPage() { - for (let p in this.pages) { - if (this.pages[p].dirty) return p; - } - return -1; - } - - async write(buff, pos) { - if (buff.byteLength == 0) return; - const self = this; -/* - if (buff.byteLength > self.pageSize*self.maxPagesLoaded*0.8) { - const cacheSize = Math.floor(buff.byteLength * 1.1); - this.maxPagesLoaded = Math.floor( cacheSize / self.pageSize)+1; - } -*/ - if (typeof pos == "undefined") pos = self.pos; - self.pos = pos+buff.byteLength; - if (self.totalSize < pos + buff.byteLength) self.totalSize = pos + buff.byteLength; - if (self.pendingClose) - throw new Error("Writing a closing file"); - const firstPage = Math.floor(pos / self.pageSize); - const lastPage = Math.floor((pos + buff.byteLength -1) / self.pageSize); - - const pagePromises = []; - for (let i=firstPage; i<=lastPage; i++) pagePromises.push(self._loadPage(i)); - self._triggerLoad(); - - let p = firstPage; - let o = pos % self.pageSize; - let r = buff.byteLength; - while (r>0) { - await pagePromises[p-firstPage]; - const l = (o+r > self.pageSize) ? (self.pageSize -o) : r; - const srcView = buff.slice( buff.byteLength - r, buff.byteLength - r + l); - const dstView = new Uint8Array(self.pages[p].buff.buffer, o, l); - dstView.set(srcView); - self.pages[p].dirty = true; - self.pages[p].pendingOps --; - self.pages[p].size = Math.max(o+l, self.pages[p].size); - if (p>=self.totalPages) { - self.totalPages = p+1; - } - r = r-l; - p ++; - o = 0; - if (!self.writing) setImmediate(self._triggerWrite.bind(self)); - } - } - - async read(len, pos) { - const self = this; - let buff = new Uint8Array(len); - await self.readToBuffer(buff, 0, len, pos); - - return buff; - } - - async readToBuffer(buffDst, offset, len, pos) { - if (len == 0) { - return; - } - const self = this; - if (len > self.pageSize*self.maxPagesLoaded*0.8) { - const cacheSize = Math.floor(len * 1.1); - this.maxPagesLoaded = Math.floor( cacheSize / self.pageSize)+1; - } - if (typeof pos == "undefined") pos = self.pos; - self.pos = pos+len; - if (self.pendingClose) - throw new Error("Reading a closing file"); - const firstPage = Math.floor(pos / self.pageSize); - const lastPage = Math.floor((pos + len -1) / self.pageSize); - - const pagePromises = []; - for (let i=firstPage; i<=lastPage; i++) pagePromises.push(self._loadPage(i)); - - self._triggerLoad(); - - let p = firstPage; - let o = pos % self.pageSize; - // Remaining bytes to read - let r = pos + len > self.totalSize ? len - (pos + len - self.totalSize): len; - while (r>0) { - await pagePromises[p - firstPage]; - self.__statusPage("After Await (read): ", p); - - // bytes to copy from this page - const l = (o+r > self.pageSize) ? (self.pageSize -o) : r; - const srcView = new Uint8Array(self.pages[p].buff.buffer, self.pages[p].buff.byteOffset + o, l); - buffDst.set(srcView, offset+len-r); - self.pages[p].pendingOps --; - - self.__statusPage("After Op done: ", p); - - r = r-l; - p ++; - o = 0; - if (self.pendingLoads.length>0) setImmediate(self._triggerLoad.bind(self)); - } - - this.pos = pos + len; - - } - - - _tryClose() { - const self = this; - if (!self.pendingClose) return; - if (self.error) { - self.pendingCloseReject(self.error); - } - const p = self._getDirtyPage(); - if ((p>=0) || (self.writing) || (self.reading) || (self.pendingLoads.length>0)) return; - self.pendingClose(); - } - - close() { - const self = this; - if (self.pendingClose) - throw new Error("Closing the file twice"); - return new Promise((resolve, reject) => { - self.pendingClose = resolve; - self.pendingCloseReject = reject; - self._tryClose(); - }).then(()=> { - self.fd.close(); - }, (err) => { - self.fd.close(); - throw (err); - }); - } - - async discard() { - const self = this; - await self.close(); - await fs.promises.unlink(this.fileName); - } - - async writeULE32(v, pos) { - const self = this; - const tmpBuff32 = new Uint8Array(4); - const tmpBuff32v = new DataView(tmpBuff32.buffer); - - tmpBuff32v.setUint32(0, v, true); - - await self.write(tmpBuff32, pos); - } - - async writeUBE32(v, pos) { - const self = this; - - const tmpBuff32 = new Uint8Array(4); - const tmpBuff32v = new DataView(tmpBuff32.buffer); - - tmpBuff32v.setUint32(0, v, false); - - await self.write(tmpBuff32, pos); - } - - - async writeULE64(v, pos) { - const self = this; - - const tmpBuff64 = new Uint8Array(8); - const tmpBuff64v = new DataView(tmpBuff64.buffer); - - tmpBuff64v.setUint32(0, v & 0xFFFFFFFF, true); - tmpBuff64v.setUint32(4, Math.floor(v / 0x100000000) , true); - - await self.write(tmpBuff64, pos); - } - - async readULE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new Uint32Array(b.buffer); - - return view[0]; - } - - async readUBE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new DataView(b.buffer); - - return view.getUint32(0, false); - } - - async readULE64(pos) { - const self = this; - const b = await self.read(8, pos); - - const view = new Uint32Array(b.buffer); - - return view[1] * 0x100000000 + view[0]; - } - - async readString(pos) { - const self = this; - - if (self.pendingClose) { - throw new Error("Reading a closing file"); - } - - let currentPosition = typeof pos == "undefined" ? self.pos : pos; - let currentPage = Math.floor(currentPosition / self.pageSize); - - let endOfStringFound = false; - let str = ""; - - while (!endOfStringFound) { - //Read page - let pagePromise = self._loadPage(currentPage); - self._triggerLoad(); - await pagePromise; - self.__statusPage("After Await (read): ", currentPage); - - let offsetOnPage = currentPosition % self.pageSize; - - const dataArray = new Uint8Array( - self.pages[currentPage].buff.buffer, - self.pages[currentPage].buff.byteOffset + offsetOnPage, - self.pageSize - offsetOnPage - ); - - let indexEndOfString = dataArray.findIndex(element => element === 0); - endOfStringFound = indexEndOfString !== -1; - - if (endOfStringFound) { - str += new TextDecoder().decode(dataArray.slice(0, indexEndOfString)); - self.pos = currentPage * this.pageSize + offsetOnPage + indexEndOfString + 1; - } else { - str += new TextDecoder().decode(dataArray); - self.pos = currentPage * this.pageSize + offsetOnPage + dataArray.length; - } - - self.pages[currentPage].pendingOps--; - self.__statusPage("After Op done: ", currentPage); - - currentPosition = self.pos; - currentPage++; - - if (self.pendingLoads.length > 0) setImmediate(self._triggerLoad.bind(self)); - } - - return str; - } -} - -function createNew$1(o) { - const initialSize = o.initialSize || 1<<20; - const fd = new MemFile$1(); - fd.o = o; - fd.o.data = new Uint8Array(initialSize); - fd.allocSize = initialSize; - fd.totalSize = 0; - fd.readOnly = false; - fd.pos = 0; - return fd; -} - -function readExisting$5(o) { - const fd = new MemFile$1(); - fd.o = o; - fd.allocSize = o.data.byteLength; - fd.totalSize = o.data.byteLength; - fd.readOnly = true; - fd.pos = 0; - return fd; -} - -const tmpBuff32$3 = new Uint8Array(4); -const tmpBuff32v$3 = new DataView(tmpBuff32$3.buffer); -const tmpBuff64$3 = new Uint8Array(8); -const tmpBuff64v$3 = new DataView(tmpBuff64$3.buffer); - -class MemFile$1 { - - constructor() { - this.pageSize = 1 << 14; // for compatibility - } - - _resizeIfNeeded(newLen) { - if (newLen > this.allocSize) { - const newAllocSize = Math.max( - this.allocSize + (1 << 20), - Math.floor(this.allocSize * 1.1), - newLen - ); - const newData = new Uint8Array(newAllocSize); - newData.set(this.o.data); - this.o.data = newData; - this.allocSize = newAllocSize; - } - } - - async write(buff, pos) { - const self =this; - if (typeof pos == "undefined") pos = self.pos; - if (this.readOnly) throw new Error("Writing a read only file"); - - this._resizeIfNeeded(pos + buff.byteLength); - - this.o.data.set(buff.slice(), pos); - - if (pos + buff.byteLength > this.totalSize) this.totalSize = pos + buff.byteLength; - - this.pos = pos + buff.byteLength; - } - - async readToBuffer(buffDest, offset, len, pos) { - const self = this; - if (typeof pos == "undefined") pos = self.pos; - if (this.readOnly) { - if (pos + len > this.totalSize) throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos + len); - - const buffSrc = new Uint8Array(this.o.data.buffer, this.o.data.byteOffset + pos, len); - - buffDest.set(buffSrc, offset); - - this.pos = pos + len; - } - - async read(len, pos) { - const self = this; - - const buff = new Uint8Array(len); - await self.readToBuffer(buff, 0, len, pos); - - return buff; - } - - close() { - if (this.o.data.byteLength != this.totalSize) { - this.o.data = this.o.data.slice(0, this.totalSize); - } - } - - async discard() { - } - - - async writeULE32(v, pos) { - const self = this; - - tmpBuff32v$3.setUint32(0, v, true); - - await self.write(tmpBuff32$3, pos); - } - - async writeUBE32(v, pos) { - const self = this; - - tmpBuff32v$3.setUint32(0, v, false); - - await self.write(tmpBuff32$3, pos); - } - - - async writeULE64(v, pos) { - const self = this; - - tmpBuff64v$3.setUint32(0, v & 0xFFFFFFFF, true); - tmpBuff64v$3.setUint32(4, Math.floor(v / 0x100000000) , true); - - await self.write(tmpBuff64$3, pos); - } - - - async readULE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new Uint32Array(b.buffer); - - return view[0]; - } - - async readUBE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new DataView(b.buffer); - - return view.getUint32(0, false); - } - - async readULE64(pos) { - const self = this; - const b = await self.read(8, pos); - - const view = new Uint32Array(b.buffer); - - return view[1] * 0x100000000 + view[0]; - } - - async readString(pos) { - const self = this; - - let currentPosition = typeof pos == "undefined" ? self.pos : pos; - - if (currentPosition > this.totalSize) { - if (this.readOnly) { - throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos); - } - const dataArray = new Uint8Array( - self.o.data.buffer, - currentPosition, - this.totalSize - currentPosition - ); - - let indexEndOfString = dataArray.findIndex(element => element === 0); - let endOfStringFound = indexEndOfString !== -1; - - let str = ""; - if (endOfStringFound) { - str = new TextDecoder().decode(dataArray.slice(0, indexEndOfString)); - self.pos = currentPosition + indexEndOfString + 1; - } else { - self.pos = currentPosition; - } - return str; - } -} - -const PAGE_SIZE$1 = 1<<22; - -function createNew(o) { - const initialSize = o.initialSize || 0; - const fd = new BigMemFile$1(); - fd.o = o; - const nPages = initialSize ? Math.floor((initialSize - 1) / PAGE_SIZE$1)+1 : 0; - fd.o.data = []; - for (let i=0; i0) { - const l = (o+r > PAGE_SIZE$1) ? (PAGE_SIZE$1 -o) : r; - const srcView = buff.slice(buff.byteLength - r, buff.byteLength - r + l); - const dstView = new Uint8Array(self.o.data[p].buffer, o, l); - dstView.set(srcView); - r = r-l; - p ++; - o = 0; - } - - this.pos = pos + buff.byteLength; - } - - async readToBuffer(buffDst, offset, len, pos) { - const self = this; - if (typeof pos == "undefined") pos = self.pos; - if (this.readOnly) { - if (pos + len > this.totalSize) throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos + len); - - const firstPage = Math.floor(pos / PAGE_SIZE$1); - - let p = firstPage; - let o = pos % PAGE_SIZE$1; - // Remaining bytes to read - let r = len; - while (r>0) { - // bytes to copy from this page - const l = (o+r > PAGE_SIZE$1) ? (PAGE_SIZE$1 -o) : r; - const srcView = new Uint8Array(self.o.data[p].buffer, o, l); - buffDst.set(srcView, offset+len-r); - r = r-l; - p ++; - o = 0; - } - - this.pos = pos + len; - } - - async read(len, pos) { - const self = this; - const buff = new Uint8Array(len); - - await self.readToBuffer(buff, 0, len, pos); - - return buff; - } - - close() { - } - - async discard() { - } - - - async writeULE32(v, pos) { - const self = this; - - tmpBuff32v$2.setUint32(0, v, true); - - await self.write(tmpBuff32$2, pos); - } - - async writeUBE32(v, pos) { - const self = this; - - tmpBuff32v$2.setUint32(0, v, false); - - await self.write(tmpBuff32$2, pos); - } - - - async writeULE64(v, pos) { - const self = this; - - tmpBuff64v$2.setUint32(0, v & 0xFFFFFFFF, true); - tmpBuff64v$2.setUint32(4, Math.floor(v / 0x100000000) , true); - - await self.write(tmpBuff64$2, pos); - } - - - async readULE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new Uint32Array(b.buffer); - - return view[0]; - } - - async readUBE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new DataView(b.buffer); - - return view.getUint32(0, false); - } - - async readULE64(pos) { - const self = this; - const b = await self.read(8, pos); - - const view = new Uint32Array(b.buffer); - - return view[1] * 0x100000000 + view[0]; - } - - async readString(pos) { - const self = this; - const fixedSize = 2048; - - let currentPosition = typeof pos == "undefined" ? self.pos : pos; - - if (currentPosition > this.totalSize) { - if (this.readOnly) { - throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos); - } - - let endOfStringFound = false; - let str = ""; - - while (!endOfStringFound) { - let currentPage = Math.floor(currentPosition / PAGE_SIZE$1); - let offsetOnPage = currentPosition % PAGE_SIZE$1; - - if (self.o.data[currentPage] === undefined) { - throw new Error("ERROR"); - } - - let readLength = Math.min(fixedSize, self.o.data[currentPage].length - offsetOnPage); - const dataArray = new Uint8Array(self.o.data[currentPage].buffer, offsetOnPage, readLength); - - let indexEndOfString = dataArray.findIndex(element => element === 0); - endOfStringFound = indexEndOfString !== -1; - - if (endOfStringFound) { - str += new TextDecoder().decode(dataArray.slice(0, indexEndOfString)); - self.pos = currentPage * PAGE_SIZE$1 + offsetOnPage + indexEndOfString + 1; - } else { - str += new TextDecoder().decode(dataArray); - self.pos = currentPage * PAGE_SIZE$1 + offsetOnPage + dataArray.length; - } - - currentPosition = self.pos; - } - return str; - } -} - -const O_TRUNC = 512; -const O_CREAT = 64; -const O_RDWR = 2; -const O_RDONLY = 0; - -/* global fetch */ - -const DEFAULT_CACHE_SIZE = (1 << 16); -const DEFAULT_PAGE_SIZE = (1 << 13); - - -async function createOverride(o, b, c) { - if (typeof o === "string") { - o = { - type: "file", - fileName: o, - cacheSize: b || DEFAULT_CACHE_SIZE, - pageSize: c || DEFAULT_PAGE_SIZE - }; - } - if (o.type == "file") { - return await open$1(o.fileName, O_TRUNC | O_CREAT | O_RDWR, o.cacheSize, o.pageSize); - } else if (o.type == "mem") { - return createNew$1(o); - } else if (o.type == "bigMem") { - return createNew(o); - } else { - throw new Error("Invalid FastFile type: "+o.type); - } -} - -async function readExisting$3(o, b, c) { - if (o instanceof Uint8Array) { - o = { - type: "mem", - data: o - }; - } - { - if (typeof o === "string") { - const buff = await fetch(o).then( function(res) { - return res.arrayBuffer(); - }).then(function (ab) { - return new Uint8Array(ab); - }); - o = { - type: "mem", - data: buff - }; - } - } - if (o.type == "file") { - return await open$1(o.fileName, O_RDONLY, o.cacheSize, o.pageSize); - } else if (o.type == "mem") { - return await readExisting$5(o); - } else if (o.type == "bigMem") { - return await readExisting$4(o); - } else { - throw new Error("Invalid FastFile type: "+o.type); - } -} - -/* - -Copyright 2020 0KIMS association. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -*/ - -function flatArray(a) { - let res = []; - fillArray(res, a); - return res; - - function fillArray(res, a) { - if (Array.isArray(a)) { - for (let i = 0; i < a.length; i++) { - fillArray(res, a[i]); - } - } else { - res.push(a); - } - } -} - -// Ref https://github.com/iden3/circom/commit/ec6388cf6eb62463539cb4c40cc3ceae9826de19 -function normalize(n, prime) { - let res = BigInt(n) % prime; - if (res < 0) res += prime; - return res; -} - -function fnvHash(str) { - const uint64_max = BigInt(2) ** BigInt(64); - let hash = BigInt("0xCBF29CE484222325"); - for (let i = 0; i < str.length; i++) { - hash ^= BigInt(str[i].charCodeAt(0)); - hash *= BigInt(0x100000001B3); - hash %= uint64_max; - } - let shash = hash.toString(16); - let n = 16 - shash.length; - shash = "0".repeat(n).concat(shash); - return shash; -} - -// Note that this pads zeros -function toArray32(s, size) { - const res = []; //new Uint32Array(size); //has no unshift - let rem = BigInt(s); - const radix = BigInt(0x100000000); - while (rem) { - res.unshift(Number(rem % radix)); - rem = rem / radix; - } - if (size) { - let i = size - res.length; - while (i > 0) { - res.unshift(0); - i--; - } - } - return res; -} - -/* globals WebAssembly */ - -async function builder(code, options) { - let instance; - let wc; - let memory; - options = options || {}; - - // Only circom 2 implements version lookup through exports in the WASM - // We default to `1` and update if we see the `getVersion` export (major version) - // These are updated after the instance is instantiated, assuming the functions are available - let majorVersion = 1; - // After Circom 2.0.7, Blaine added exported functions for getting minor and patch versions - let minorVersion = 0; - // If we can't look up the patch version, assume the lowest - let patchVersion = 0; - - let codeIsWebAssemblyInstance = false; - - // If code is already prepared WebAssembly.Instance, we use it directly - if (code instanceof WebAssembly.Instance) { - instance = code; - codeIsWebAssemblyInstance = true; - } else { - let memorySize = 32767; - - if (options.memorySize) { - // make sure we have int - memorySize = parseInt(options.memorySize); - if (memorySize < 0) { - throw new Error("Invalid memory size"); - } - } - - let memoryAllocated = false; - while (!memoryAllocated) { - try { - memory = new WebAssembly.Memory({initial: memorySize}); - memoryAllocated = true; - } catch (err) { - if (memorySize <= 1) { - throw err; - } - console.warn("Could not allocate " + memorySize * 1024 * 64 + " bytes. This may cause severe instability. Trying with " + memorySize * 1024 * 64 / 2 + " bytes"); - memorySize = Math.floor(memorySize / 2); - } - } - - const wasmModule = await WebAssembly.compile(code); - - let errStr = ""; - let msgStr = ""; - - instance = await WebAssembly.instantiate(wasmModule, { - env: { - "memory": memory - }, - runtime: { - printDebug : function(value) { - console.log("printDebug:", value); - }, - exceptionHandler: function (code) { - let err; - if (code === 1) { - err = "Signal not found. "; - } else if (code === 2) { - err = "Too many signals set. "; - } else if (code === 3) { - err = "Signal already set. "; - } else if (code === 4) { - err = "Assert Failed. "; - } else if (code === 5) { - err = "Not enough memory. "; - } else if (code === 6) { - err = "Input signal array access exceeds the size. "; - } else { - err = "Unknown error. "; - } - console.error("ERROR: ", code, errStr); - throw new Error(err + errStr); - }, - // A new way of logging messages was added in Circom 2.0.7 that requires 2 new imports - // `printErrorMessage` and `writeBufferMessage`. - printErrorMessage: function () { - errStr += getMessage() + "\n"; - }, - writeBufferMessage: function () { - const msg = getMessage(); - // Any calls to `log()` will always end with a `\n`, so that's when we print and reset - if (msg === "\n") { - console.log(msgStr); - msgStr = ""; - } else { - // If we've buffered other content, put a space in between the items - if (msgStr !== "") { - msgStr += " "; - } - // Then append the message to the message we are creating - msgStr += msg; - } - }, - showSharedRWMemory: function () { - const shared_rw_memory_size = instance.exports.getFieldNumLen32(); - const arr = new Uint32Array(shared_rw_memory_size); - for (let j = 0; j < shared_rw_memory_size; j++) { - arr[shared_rw_memory_size - 1 - j] = instance.exports.readSharedRWMemory(j); - } - - // In circom 2.0.7, they changed the log() function to allow strings and changed the - // output API. This smoothes over the breaking change. - if (majorVersion >= 2 && (minorVersion >= 1 || patchVersion >= 7)) { - // If we've buffered other content, put a space in between the items - if (msgStr !== "") { - msgStr += " "; - } - // Then append the value to the message we are creating - const msg = (Scalar.fromArray(arr, 0x100000000).toString()); - msgStr += msg; - } else { - console.log(Scalar.fromArray(arr, 0x100000000)); - } - }, - error: function (code, pstr, a, b, c, d) { - let errStr; - if (code === 7) { - errStr = p2str(pstr) + " " + wc.getFr(b).toString() + " != " + wc.getFr(c).toString() + " " + p2str(d); - } else if (code === 9) { - errStr = p2str(pstr) + " " + wc.getFr(b).toString() + " " + p2str(c); - } else if ((code === 5) && (options.sym)) { - errStr = p2str(pstr) + " " + options.sym.labelIdx2Name[c]; - } else { - errStr = p2str(pstr) + " " + a + " " + b + " " + c + " " + d; - } - console.log("ERROR: ", code, errStr); - throw new Error(errStr); - }, - log: function (a) { - console.log(wc.getFr(a).toString()); - }, - logGetSignal: function (signal, pVal) { - if (options.logGetSignal) { - options.logGetSignal(signal, wc.getFr(pVal)); - } - }, - logSetSignal: function (signal, pVal) { - if (options.logSetSignal) { - options.logSetSignal(signal, wc.getFr(pVal)); - } - }, - logStartComponent: function (cIdx) { - if (options.logStartComponent) { - options.logStartComponent(cIdx); - } - }, - logFinishComponent: function (cIdx) { - if (options.logFinishComponent) { - options.logFinishComponent(cIdx); - } - } - } - }); - } - - if (typeof instance.exports.getVersion == "function") { - majorVersion = instance.exports.getVersion(); - } - if (typeof instance.exports.getMinorVersion == "function") { - minorVersion = instance.exports.getMinorVersion(); - } - if (typeof instance.exports.getPatchVersion == "function") { - patchVersion = instance.exports.getPatchVersion(); - } - - const sanityCheck = - options && - ( - options.sanityCheck || - options.logGetSignal || - options.logSetSignal || - options.logStartComponent || - options.logFinishComponent - ); - - // We explicitly check for major version 2 in case there's a circom v3 in the future - if (majorVersion === 2) { - wc = new WitnessCalculatorCircom2(instance, sanityCheck); - } else if (majorVersion === 1) { - if (codeIsWebAssemblyInstance) { - throw new Error('Loading code from WebAssembly instance is not supported for circom version 1'); - } - wc = new WitnessCalculatorCircom1(memory, instance, sanityCheck); - } else { - throw new Error(`Unsupported circom version: ${majorVersion}`); - } - return wc; - - function getMessage() { - let message = ""; - let c = instance.exports.getMessageChar(); - while (c !== 0) { - message += String.fromCharCode(c); - c = instance.exports.getMessageChar(); - } - return message; - } - - function p2str(p) { - const i8 = new Uint8Array(memory.buffer); - - const bytes = []; - - for (let i = 0; i8[p + i] > 0; i++) bytes.push(i8[p + i]); - - return String.fromCharCode.apply(null, bytes); - } -} - -class WitnessCalculatorCircom1 { - constructor(memory, instance, sanityCheck) { - this.memory = memory; - this.i32 = new Uint32Array(memory.buffer); - this.instance = instance; - - this.n32 = (this.instance.exports.getFrLen() >> 2) - 2; - const pRawPrime = this.instance.exports.getPRawPrime(); - - const arr = new Array(this.n32); - for (let i = 0; i < this.n32; i++) { - arr[this.n32 - 1 - i] = this.i32[(pRawPrime >> 2) + i]; - } - - this.prime = Scalar.fromArray(arr, 0x100000000); - - this.Fr = new F1Field(this.prime); - - this.mask32 = Scalar.fromString("FFFFFFFF", 16); - this.NVars = this.instance.exports.getNVars(); - this.n64 = Math.floor((this.Fr.bitLength - 1) / 64) + 1; - this.R = this.Fr.e(Scalar.shiftLeft(1, this.n64 * 64)); - this.RInv = this.Fr.inv(this.R); - this.sanityCheck = sanityCheck; - } - - circom_version() { - return 1; - } - - async _doCalculateWitness(input, sanityCheck) { - this.instance.exports.init((this.sanityCheck || sanityCheck) ? 1 : 0); - const pSigOffset = this.allocInt(); - const pFr = this.allocFr(); - const keys = Object.keys(input); - keys.forEach((k) => { - const h = fnvHash(k); - const hMSB = parseInt(h.slice(0, 8), 16); - const hLSB = parseInt(h.slice(8, 16), 16); - try { - this.instance.exports.getSignalOffset32(pSigOffset, 0, hMSB, hLSB); - } catch (err) { - throw new Error(`Signal ${k} is not an input of the circuit.`); - } - const sigOffset = this.getInt(pSigOffset); - const fArr = flatArray(input[k]); - for (let i = 0; i < fArr.length; i++) { - this.setFr(pFr, fArr[i]); - this.instance.exports.setSignal(0, 0, sigOffset + i, pFr); - } - }); - } - - async calculateWitness(input, sanityCheck) { - const self = this; - - const old0 = self.i32[0]; - const w = []; - - await self._doCalculateWitness(input, sanityCheck); - - for (let i = 0; i < self.NVars; i++) { - const pWitness = self.instance.exports.getPWitness(i); - w.push(self.getFr(pWitness)); - } - - self.i32[0] = old0; - return w; - } - - async calculateBinWitness(input, sanityCheck) { - const self = this; - - const old0 = self.i32[0]; - - await self._doCalculateWitness(input, sanityCheck); - - const pWitnessBuffer = self.instance.exports.getWitnessBuffer(); - - self.i32[0] = old0; - - const buff = self.memory.buffer.slice(pWitnessBuffer, pWitnessBuffer + (self.NVars * self.n64 * 8)); - return new Uint8Array(buff); - } - - allocInt() { - const p = this.i32[0]; - this.i32[0] = p + 8; - return p; - } - - allocFr() { - const p = this.i32[0]; - this.i32[0] = p + this.n32 * 4 + 8; - return p; - } - - getInt(p) { - return this.i32[p >> 2]; - } - - setInt(p, v) { - this.i32[p >> 2] = v; - } - - getFr(p) { - const self = this; - const idx = (p >> 2); - - if (self.i32[idx + 1] & 0x80000000) { - const arr = new Array(self.n32); - for (let i = 0; i < self.n32; i++) { - arr[self.n32 - 1 - i] = self.i32[idx + 2 + i]; - } - const res = self.Fr.e(Scalar.fromArray(arr, 0x100000000)); - if (self.i32[idx + 1] & 0x40000000) { - return fromMontgomery(res); - } else { - return res; - } - - } else { - if (self.i32[idx] & 0x80000000) { - return self.Fr.e(self.i32[idx] - 0x100000000); - } else { - return self.Fr.e(self.i32[idx]); - } - } - - function fromMontgomery(n) { - return self.Fr.mul(self.RInv, n); - } - - } - - - setFr(p, v) { - const self = this; - - v = self.Fr.e(v); - - const minShort = self.Fr.neg(self.Fr.e("80000000", 16)); - const maxShort = self.Fr.e("7FFFFFFF", 16); - - if ((self.Fr.geq(v, minShort)) - && (self.Fr.leq(v, maxShort))) { - let a; - if (self.Fr.geq(v, self.Fr.zero)) { - a = Scalar.toNumber(v); - } else { - a = Scalar.toNumber(self.Fr.sub(v, minShort)); - a = a - 0x80000000; - a = 0x100000000 + a; - } - self.i32[(p >> 2)] = a; - self.i32[(p >> 2) + 1] = 0; - return; - } - - self.i32[(p >> 2)] = 0; - self.i32[(p >> 2) + 1] = 0x80000000; - const arr = Scalar.toArray(v, 0x100000000); - for (let i = 0; i < self.n32; i++) { - const idx = arr.length - 1 - i; - - if (idx >= 0) { - self.i32[(p >> 2) + 2 + i] = arr[idx]; - } else { - self.i32[(p >> 2) + 2 + i] = 0; - } - } - } -} - -class WitnessCalculatorCircom2 { - constructor(instance, sanityCheck) { - this.instance = instance; - - this.version = this.instance.exports.getVersion(); - this.n32 = this.instance.exports.getFieldNumLen32(); - - this.instance.exports.getRawPrime(); - const arr = new Uint32Array(this.n32); - for (let i = 0; i < this.n32; i++) { - arr[this.n32 - 1 - i] = this.instance.exports.readSharedRWMemory(i); - } - this.prime = Scalar.fromArray(arr, 0x100000000); - - this.witnessSize = this.instance.exports.getWitnessSize(); - - this.sanityCheck = sanityCheck; - } - - circom_version() { - return this.instance.exports.getVersion(); - } - - async _doCalculateWitness(input, sanityCheck) { - //input is assumed to be a map from signals to arrays of bigints - this.instance.exports.init((this.sanityCheck || sanityCheck) ? 1 : 0); - const keys = Object.keys(input); - let input_counter = 0; - keys.forEach((k) => { - const h = fnvHash(k); - const hMSB = parseInt(h.slice(0, 8), 16); - const hLSB = parseInt(h.slice(8, 16), 16); - const fArr = flatArray(input[k]); - // Slight deviation from https://github.com/iden3/circom/blob/v2.1.6/code_producers/src/wasm_elements/common/witness_calculator.js - // because I don't know when this exported function was added - if (typeof this.instance.exports.getInputSignalSize === "function") { - let signalSize = this.instance.exports.getInputSignalSize(hMSB, hLSB); - if (signalSize < 0) { - throw new Error(`Signal ${k} not found\n`); - } - if (fArr.length < signalSize) { - throw new Error(`Not enough values for input signal ${k}\n`); - } - if (fArr.length > signalSize) { - throw new Error(`Too many values for input signal ${k}\n`); - } - } - for (let i = 0; i < fArr.length; i++) { - const arrFr = toArray32(normalize(fArr[i], this.prime), this.n32); - for (let j = 0; j < this.n32; j++) { - this.instance.exports.writeSharedRWMemory(j, arrFr[this.n32 - 1 - j]); - } - try { - this.instance.exports.setInputSignal(hMSB, hLSB, i); - input_counter++; - } catch (err) { - // console.log(`After adding signal ${i} of ${k}`) - throw new Error(err); - } - } - - }); - if (input_counter < this.instance.exports.getInputSize()) { - throw new Error(`Not all inputs have been set. Only ${input_counter} out of ${this.instance.exports.getInputSize()}`); - } - } - - async calculateWitness(input, sanityCheck) { - const w = []; - - await this._doCalculateWitness(input, sanityCheck); - - for (let i = 0; i < this.witnessSize; i++) { - this.instance.exports.getWitness(i); - const arr = new Uint32Array(this.n32); - for (let j = 0; j < this.n32; j++) { - arr[this.n32 - 1 - j] = this.instance.exports.readSharedRWMemory(j); - } - w.push(Scalar.fromArray(arr, 0x100000000)); - } - - return w; - } - - async calculateWTNSBin(input, sanityCheck) { - const buff32 = new Uint32Array(this.witnessSize * this.n32 + this.n32 + 11); - const buff = new Uint8Array(buff32.buffer); - await this._doCalculateWitness(input, sanityCheck); - - //"wtns" - buff[0] = "w".charCodeAt(0); - buff[1] = "t".charCodeAt(0); - buff[2] = "n".charCodeAt(0); - buff[3] = "s".charCodeAt(0); - - //version 2 - buff32[1] = 2; - - //number of sections: 2 - buff32[2] = 2; - - //id section 1 - buff32[3] = 1; - - const n8 = this.n32 * 4; - //id section 1 length in 64bytes - const idSection1length = 8 + n8; - const idSection1lengthHex = idSection1length.toString(16); - buff32[4] = parseInt(idSection1lengthHex.slice(0, 8), 16); - buff32[5] = parseInt(idSection1lengthHex.slice(8, 16), 16); - - //this.n32 - buff32[6] = n8; - - //prime number - this.instance.exports.getRawPrime(); - - let pos = 7; - for (let j = 0; j < this.n32; j++) { - buff32[pos + j] = this.instance.exports.readSharedRWMemory(j); - } - pos += this.n32; - - // witness size - buff32[pos] = this.witnessSize; - pos++; - - //id section 2 - buff32[pos] = 2; - pos++; - - // section 2 length - const idSection2length = n8 * this.witnessSize; - const idSection2lengthHex = idSection2length.toString(16); - buff32[pos] = parseInt(idSection2lengthHex.slice(0, 8), 16); - buff32[pos + 1] = parseInt(idSection2lengthHex.slice(8, 16), 16); - - pos += 2; - for (let i = 0; i < this.witnessSize; i++) { - this.instance.exports.getWitness(i); - for (let j = 0; j < this.n32; j++) { - buff32[pos + j] = this.instance.exports.readSharedRWMemory(j); - } - pos += this.n32; - } - - return buff; - } - -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ -const { unstringifyBigInts: unstringifyBigInts$b} = utils; - -async function wtnsCalculate(_input, wasmFileName, wtnsFileName, options) { - const input = unstringifyBigInts$b(_input); - - const fdWasm = await readExisting$3(wasmFileName); - const wasm = await fdWasm.read(fdWasm.totalSize); - await fdWasm.close(); - - const wc = await builder(wasm, options); - if (wc.circom_version() === 1) { - const w = await wc.calculateBinWitness(input); - - const fdWtns = await createBinFile(wtnsFileName, "wtns", 2, 2); - - await writeBin(fdWtns, w, wc.prime); - await fdWtns.close(); - } else { - const fdWtns = await createOverride(wtnsFileName); - - const w = await wc.calculateWTNSBin(input); - - await fdWtns.write(w); - await fdWtns.close(); - } -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ -const {unstringifyBigInts: unstringifyBigInts$a} = utils; - -async function groth16FullProve(_input, wasmFile, zkeyFileName, logger, wtnsCalcOptions, proverOptions) { - const input = unstringifyBigInts$a(_input); - - const wtns= { - type: "mem" - }; - await wtnsCalculate(input, wasmFile, wtns, wtnsCalcOptions); - return await groth16Prove(zkeyFileName, wtns, logger, proverOptions); -} - -/* - Copyright 2018 0kims association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ -const {unstringifyBigInts: unstringifyBigInts$9} = utils; - -async function groth16Verify(_vk_verifier, _publicSignals, _proof, logger) { -/* - let cpub = vk_verifier.IC[0]; - for (let s= 0; s< vk_verifier.nPublic; s++) { - cpub = G1.add( cpub, G1.timesScalar( vk_verifier.IC[s+1], publicSignals[s])); - } -*/ - - const vk_verifier = unstringifyBigInts$9(_vk_verifier); - const proof = unstringifyBigInts$9(_proof); - const publicSignals = unstringifyBigInts$9(_publicSignals); - - const curve = await getCurveFromName(vk_verifier.curve); - - const IC0 = curve.G1.fromObject(vk_verifier.IC[0]); - const IC = new Uint8Array(curve.G1.F.n8*2 * publicSignals.length); - const w = new Uint8Array(curve.Fr.n8 * publicSignals.length); - - if (!publicInputsAreValid$2(curve, publicSignals)) { - if (logger) logger.error("Public inputs are not valid."); - return false; - } - - for (let i=0; i. -*/ -const { unstringifyBigInts: unstringifyBigInts$8} = utils; - -function p256$2(n) { - let nstr = n.toString(16); - while (nstr.length < 64) nstr = "0"+nstr; - nstr = `"0x${nstr}"`; - return nstr; -} - -async function groth16ExportSolidityCallData(_proof, _pub) { - const proof = unstringifyBigInts$8(_proof); - const pub = unstringifyBigInts$8(_pub); - - let inputs = ""; - for (let i=0; i. -*/ - -var groth16 = /*#__PURE__*/Object.freeze({ - __proto__: null, - fullProve: groth16FullProve, - prove: groth16Prove, - verify: groth16Verify, - exportSolidityCallData: groth16ExportSolidityCallData +//#endregion +//#region src/keypair.js +function Qt(e, t) { + let n = new DataView(t.buffer, t.byteOffset, t.byteLength), r = []; + for (let e = 0; e < 8; e++) r[e] = n.getUint32(e * 4); + let i = new c(r); + return e.G2.fromRng(i); +} +function $t(e, t, n, r, i) { + let a = K.create({ dkLen: 64 }), o = new Uint8Array([t]); + a.update(o), a.update(n); + let s = e.G1.toUncompressed(r); + a.update(s); + let c = e.G1.toUncompressed(i); + return a.update(c), Qt(e, a.digest()); +} +function en(e, t, n, r, i) { + return e.g1_s = t.G1.toAffine(t.G1.fromRng(i)), e.g1_sx = t.G1.toAffine(t.G1.timesFr(e.g1_s, e.prvKey)), e.g2_sp = t.G2.toAffine($t(t, n, r, e.g1_s, e.g1_sx)), e.g2_spx = t.G2.toAffine(t.G2.timesFr(e.g2_sp, e.prvKey)), e; +} +function tn(e, t, n) { + let r = { + tau: {}, + alpha: {}, + beta: {} + }; + return r.tau.prvKey = e.Fr.fromRng(n), r.alpha.prvKey = e.Fr.fromRng(n), r.beta.prvKey = e.Fr.fromRng(n), en(r.tau, e, 0, t, n), en(r.alpha, e, 1, t, n), en(r.beta, e, 2, t, n), r; +} +//#endregion +//#region src/powersoftau_utils.js +async function nn(e, t, n, r) { + r ||= n, await e.writeULE32(1); + let i = e.pos; + await e.writeULE64(0), await e.writeULE32(t.F1.n64 * 8); + let a = new Uint8Array(t.F1.n8); + u.toRprLE(a, 0, t.q, t.F1.n8), await e.write(a), await e.writeULE32(n), await e.writeULE32(r); + let o = e.pos - i - 8, s = e.pos; + await e.writeULE64(o, i), e.pos = s; +} +async function rn(e, t) { + if (!t[1]) throw Error(e.fileName + ": File has no header"); + if (t[1].length > 1) throw Error(e.fileName + ": File has more than one header"); + e.pos = t[1][0].p; + let n = await e.readULE32(), r = await e.read(n), i = await E(u.fromRprLE(r)); + if (i.F1.n64 * 8 != n) throw Error(e.fileName + ": Invalid size"); + let a = await e.readULE32(), o = await e.readULE32(); + if (e.pos - t[1][0].p != t[1][0].size) throw Error("Invalid PTau header size"); + return { + curve: i, + power: a, + ceremonyPower: o + }; +} +async function an(e, t, n) { + return on(await e.read(t.F1.n8 * 2 * 6 + t.F2.n8 * 2 * 3), 0, t, n); +} +function on(e, t, n, r) { + let i = { + tau: {}, + alpha: {}, + beta: {} + }; + return i.tau.g1_s = a(), i.tau.g1_sx = a(), i.alpha.g1_s = a(), i.alpha.g1_sx = a(), i.beta.g1_s = a(), i.beta.g1_sx = a(), i.tau.g2_spx = o(), i.alpha.g2_spx = o(), i.beta.g2_spx = o(), i; + function a() { + let i; + return i = r ? n.G1.fromRprLEM(e, t) : n.G1.fromRprUncompressed(e, t), t += n.G1.F.n8 * 2, i; + } + function o() { + let i; + return i = r ? n.G2.fromRprLEM(e, t) : n.G2.fromRprUncompressed(e, t), t += n.G2.F.n8 * 2, i; + } +} +function sn(e, t, n, r, i) { + a(r.tau.g1_s), a(r.tau.g1_sx), a(r.alpha.g1_s), a(r.alpha.g1_sx), a(r.beta.g1_s), a(r.beta.g1_sx), o(r.tau.g2_spx), o(r.alpha.g2_spx), o(r.beta.g2_spx); + async function a(r) { + i ? n.G1.toRprLEM(e, t, r) : n.G1.toRprUncompressed(e, t, r), t += n.F1.n8 * 2; + } + async function o(r) { + i ? n.G2.toRprLEM(e, t, r) : n.G2.toRprUncompressed(e, t, r), t += n.F2.n8 * 2; + } + return e; +} +async function cn(e, t, n, r) { + let i = new Uint8Array(t.F1.n8 * 2 * 6 + t.F2.n8 * 2 * 3); + sn(i, 0, t, n, r), await e.write(i); +} +async function ln(e, t) { + let n = {}; + n.tauG1 = await c(), n.tauG2 = await l(), n.alphaG1 = await c(), n.betaG1 = await c(), n.betaG2 = await l(), n.key = await an(e, t, !0), n.partialHash = await e.read(216), n.nextChallenge = await e.read(64), n.type = await e.readULE32(); + let r = new Uint8Array(t.G1.F.n8 * 2 * 6 + t.G2.F.n8 * 2 * 3); + sn(r, 0, t, n.key, !1); + let i = Te(n.partialHash); + i.update(r), n.responseHash = i.digest(); + let a = await e.readULE32(), o = e.pos, s = 0; + for (; e.pos - o < a;) { + let e = await u(1); + if (e[0] <= s) throw Error("Parameters in the contribution must be sorted"); + if (s = e[0], e[0] == 1) { + let e = await u((await u(1))[0]); + n.name = new TextDecoder().decode(e); + } else if (e[0] == 2) n.numIterationsExp = (await u(1))[0]; + else if (e[0] == 3) n.beaconHash = await u((await u(1))[0]); + else throw Error("Parameter not recognized"); + } + if (e.pos != o + a) throw Error("Parameters do not match"); + return n; + async function c() { + let n = await e.read(t.G1.F.n8 * 2); + return t.G1.fromRprLEM(n); + } + async function l() { + let n = await e.read(t.G2.F.n8 * 2); + return t.G2.fromRprLEM(n); + } + async function u(t) { + let n = await e.read(t); + return new Uint8Array(n); + } +} +async function un(e, t, n) { + if (!n[7]) throw Error(e.fileName + ": File has no contributions"); + if (n[7][0].length > 1) throw Error(e.fileName + ": File has more than one contributions section"); + e.pos = n[7][0].p; + let r = await e.readULE32(), i = []; + for (let n = 0; n < r; n++) { + let r = await ln(e, t); + r.id = n + 1, i.push(r); + } + if (e.pos - n[7][0].p != n[7][0].size) throw Error("Invalid contribution section size"); + return i; +} +async function dn(e, t, n) { + let r = new Uint8Array(t.F1.n8 * 2), i = new Uint8Array(t.F2.n8 * 2); + await o(n.tauG1), await s(n.tauG2), await o(n.alphaG1), await o(n.betaG1), await s(n.betaG2), await cn(e, t, n.key, !0), await e.write(n.partialHash), await e.write(n.nextChallenge), await e.writeULE32(n.type || 0); + let a = []; + if (n.name) { + a.push(1); + let e = new TextEncoder("utf-8").encode(n.name.substring(0, 64)); + a.push(e.byteLength); + for (let t = 0; t < e.byteLength; t++) a.push(e[t]); + } + if (n.type == 1) { + a.push(2), a.push(n.numIterationsExp), a.push(3), a.push(n.beaconHash.byteLength); + for (let e = 0; e < n.beaconHash.byteLength; e++) a.push(n.beaconHash[e]); + } + if (a.length > 0) { + let t = new Uint8Array(a); + await e.writeULE32(t.byteLength), await e.write(t); + } else await e.writeULE32(0); + async function o(n) { + t.G1.toRprLEM(r, 0, n), await e.write(r); + } + async function s(n) { + t.G2.toRprLEM(i, 0, n), await e.write(i); + } +} +async function fn(e, t, n) { + await e.writeULE32(7); + let r = e.pos; + await e.writeULE64(0), await e.writeULE32(n.length); + for (let r = 0; r < n.length; r++) await dn(e, t, n[r]); + let i = e.pos - r - 8, a = e.pos; + await e.writeULE64(i, r), e.pos = a; +} +function pn(e, t, n) { + n && n.debug("Calculating First Challenge Hash"); + let r = K.create({ dkLen: 64 }), i = new Uint8Array(e.G1.F.n8 * 2), a = new Uint8Array(e.G2.F.n8 * 2); + e.G1.toRprUncompressed(i, 0, e.G1.g), e.G2.toRprUncompressed(a, 0, e.G2.g), r.update(K.create({ dkLen: 64 }).digest()); + let o; + return o = 2 ** t * 2 - 1, n && n.debug("Calculate Initial Hash: tauG1"), s(i, o), o = 2 ** t, n && n.debug("Calculate Initial Hash: tauG2"), s(a, o), n && n.debug("Calculate Initial Hash: alphaTauG1"), s(i, o), n && n.debug("Calculate Initial Hash: betaTauG1"), s(i, o), r.update(a), r.digest(); + function s(e, t) { + let i = 341e3, a = Math.floor(t / i), o = t % i, s = new Uint8Array(i * e.byteLength); + for (let t = 0; t < i; t++) s.set(e, t * e.byteLength); + for (let e = 0; e < a; e++) r.update(s), n && n.debug("Initial hash: " + e * i); + for (let t = 0; t < o; t++) r.update(e); + } +} +async function mn(e, t, n, r) { + return tn(e, t, await Ne(n, r)); +} +//#endregion +//#region src/powersoftau_new.js +async function hn(t, n, r, i) { + let a = await e.createBinFile(r, "ptau", 1, 7); + await nn(a, t, n, 0); + let o = t.G1.oneAffine, s = t.G2.oneAffine; + await e.startWriteSection(a, 2); + let c = 2 ** n * 2 - 1; + for (let e = 0; e < c; e++) await a.write(o), i && e % 1e5 == 0 && e && i.log("tauG1: " + e); + await e.endWriteSection(a), await e.startWriteSection(a, 3); + let l = 2 ** n; + for (let e = 0; e < l; e++) await a.write(s), i && e % 1e5 == 0 && e && i.log("tauG2: " + e); + await e.endWriteSection(a), await e.startWriteSection(a, 4); + let u = 2 ** n; + for (let e = 0; e < u; e++) await a.write(o), i && e % 1e5 == 0 && e && i.log("alphaTauG1: " + e); + await e.endWriteSection(a), await e.startWriteSection(a, 5); + let d = 2 ** n; + for (let e = 0; e < d; e++) await a.write(o), i && e % 1e5 == 0 && e && i.log("betaTauG1: " + e); + await e.endWriteSection(a), await e.startWriteSection(a, 6), await a.write(s), await e.endWriteSection(a), await e.startWriteSection(a, 7), await a.writeULE32(0), await e.endWriteSection(a), await a.close(); + let f = pn(t, n, i); + return i && i.debug(q(K.create({ dkLen: 64 }).digest(), "Blank Contribution Hash:")), i && i.info(q(f, "First Contribution Hash:")), f; +} +//#endregion +//#region src/powersoftau_export_challenge.js +async function gn(t, n, r) { + let { fd: i, sections: a } = await e.readBinFile(t, "ptau", 1), { curve: o, power: s } = await rn(i, a), c = await un(i, o, a), l, u; + c.length == 0 ? (l = K.create({ dkLen: 64 }).digest(), u = pn(o, s)) : (l = c[c.length - 1].responseHash, u = c[c.length - 1].nextChallenge), r && r.info(q(l, "Last Response Hash: ")), r && r.info(q(u, "New Challenge Hash: ")); + let d = await At(n), f = K.create({ dkLen: 64 }); + await d.write(l), f.update(l), await m(2, "G1", 2 ** s * 2 - 1, "tauG1"), await m(3, "G2", 2 ** s, "tauG2"), await m(4, "G1", 2 ** s, "alphaTauG1"), await m(5, "G1", 2 ** s, "betaTauG1"), await m(6, "G2", 1, "betaG2"), await i.close(), await d.close(); + let p = f.digest(); + if (!Ce(u, p)) throw r && r.info(q(p, "Calc Curret Challenge Hash: ")), r && r.error("PTau file is corrupted. Calculated new challenge hash does not match with the eclared one"), Error("PTau file is corrupted. Calculated new challenge hash does not match with the eclared one"); + return u; + async function m(t, n, s, c) { + let l = o[n], u = l.F.n8 * 2, p = Math.floor((1 << 24) / u); + await e.startReadUniqueSection(i, a, t); + for (let e = 0; e < s; e += p) { + r && r.debug(`Exporting ${c}: ${e}/${s}`); + let t = Math.min(s - e, p), n; + n = await i.read(t * u), n = await l.batchLEMtoU(n), await d.write(n), f.update(n); + } + await e.endReadSection(i); + } +} +//#endregion +//#region src/powersoftau_import.js +async function _n(t, n, r, i, a, o) { + let s = new Uint8Array(64); + for (let e = 0; e < 64; e++) s[e] = 255; + let { fd: c, sections: l } = await e.readBinFile(t, "ptau", 1), { curve: u, power: d } = await rn(c, l), f = await un(c, u, l), p = {}; + i && (p.name = i); + let m = u.F1.n8 * 2, h = u.F1.n8, g = u.F2.n8 * 2, _ = u.F2.n8, v = await jt(n); + if (v.totalSize != 64 + (2 ** d * 2 - 1) * h + 2 ** d * _ + 2 ** d * h + 2 ** d * h + _ + m * 6 + g * 3) throw Error("Size of the contribution is invalid"); + let y; + y = f.length > 0 ? f[f.length - 1].nextChallenge : pn(u, d, o); + let b = await e.createBinFile(r, "ptau", 1, a ? 7 : 2); + await nn(b, u, d); + let x = await v.read(64); + if (Ce(s, y) && (y = x, f[f.length - 1].nextChallenge = y), !Ce(x, y)) throw Error("Wrong contribution. This contribution is not based on the previous hash"); + let S = K.create({ dkLen: 64 }); + S.update(x); + let C = [], w; + w = await D(v, b, "G1", 2, 2 ** d * 2 - 1, [1], "tauG1"), p.tauG1 = w[0], w = await D(v, b, "G2", 3, 2 ** d, [1], "tauG2"), p.tauG2 = w[0], w = await D(v, b, "G1", 4, 2 ** d, [0], "alphaG1"), p.alphaG1 = w[0], w = await D(v, b, "G1", 5, 2 ** d, [0], "betaG1"), p.betaG1 = w[0], w = await D(v, b, "G2", 6, 1, [0], "betaG2"), p.betaG2 = w[0], p.partialHash = Ee(S); + let T = await v.read(u.F1.n8 * 2 * 6 + u.F2.n8 * 2 * 3); + p.key = on(T, 0, u, !1), S.update(new Uint8Array(T)); + let E = S.digest(); + if (o && o.info(q(E, "Contribution Response Hash imported: ")), a) { + let e = K.create({ dkLen: 64 }); + e.update(E), await A(e, b, "G1", 2, 2 ** d * 2 - 1, "tauG1", o), await A(e, b, "G2", 3, 2 ** d, "tauG2", o), await A(e, b, "G1", 4, 2 ** d, "alphaTauG1", o), await A(e, b, "G1", 5, 2 ** d, "betaTauG1", o), await A(e, b, "G2", 6, 1, "betaG2", o), p.nextChallenge = e.digest(), o && o.info(q(p.nextChallenge, "Next Challenge Hash: ")); + } else p.nextChallenge = s; + return f.push(p), await fn(b, u, f), await v.close(), await b.close(), await c.close(), p.nextChallenge; + async function D(e, t, n, r, i, o, s) { + return a ? await O(e, t, n, r, i, o, s) : await k(e, t, n, r, i, o, s); + } + async function O(t, n, r, i, a, s, c) { + let l = u[r], d = l.F.n8, f = l.F.n8 * 2, p = []; + await e.startWriteSection(n, i); + let m = Math.floor((1 << 24) / f); + C[i] = n.pos; + for (let e = 0; e < a; e += m) { + o && o.debug(`Importing ${c}: ${e}/${a}`); + let r = Math.min(a - e, m), i = await t.read(r * d); + S.update(i); + let u = await l.batchCtoLEM(i); + await n.write(u); + for (let t = 0; t < s.length; t++) { + let n = s[t]; + if (n >= e && n < e + r) { + let t = l.fromRprLEM(u, (n - e) * f); + p.push(t); + } + } + } + return await e.endWriteSection(n), p; + } + async function k(e, t, n, r, i, a, s) { + let c = u[n], l = c.F.n8, d = [], f = Math.floor((1 << 24) / l); + for (let t = 0; t < i; t += f) { + o && o.debug(`Importing ${s}: ${t}/${i}`); + let n = Math.min(i - t, f), r = await e.read(n * l); + S.update(r); + for (let e = 0; e < a.length; e++) { + let i = a[e]; + if (i >= t && i < t + n) { + let e = c.fromRprCompressed(r, (i - t) * l); + d.push(e); + } + } + } + return d; + } + async function A(e, t, n, r, i, a, o) { + let s = u[n], c = s.F.n8 * 2, l = Math.floor((1 << 24) / c), d = t.pos; + t.pos = C[r]; + for (let n = 0; n < i; n += l) { + o && o.debug(`Hashing ${a}: ${n}/${i}`); + let r = Math.min(i - n, l), u = await t.read(r * c), d = await s.batchLEMtoU(u); + e.update(d); + } + t.pos = d; + } +} +//#endregion +//#region src/powersoftau_verify.js +var vn = De; +async function yn(e, t, n, r) { + let i; + if (t.type == 1) { + let i = await mn(e, n.nextChallenge, t.beaconHash, t.numIterationsExp); + if (!e.G1.eq(t.key.tau.g1_s, i.tau.g1_s)) return r && r.error(`BEACON key (tauG1_s) is not generated correctly in challenge #${t.id} ${t.name || ""}`), !1; + if (!e.G1.eq(t.key.tau.g1_sx, i.tau.g1_sx)) return r && r.error(`BEACON key (tauG1_sx) is not generated correctly in challenge #${t.id} ${t.name || ""}`), !1; + if (!e.G2.eq(t.key.tau.g2_spx, i.tau.g2_spx)) return r && r.error(`BEACON key (tauG2_spx) is not generated correctly in challenge #${t.id} ${t.name || ""}`), !1; + if (!e.G1.eq(t.key.alpha.g1_s, i.alpha.g1_s)) return r && r.error(`BEACON key (alphaG1_s) is not generated correctly in challenge #${t.id} ${t.name || ""}`), !1; + if (!e.G1.eq(t.key.alpha.g1_sx, i.alpha.g1_sx)) return r && r.error(`BEACON key (alphaG1_sx) is not generated correctly in challenge #${t.id} ${t.name || ""}`), !1; + if (!e.G2.eq(t.key.alpha.g2_spx, i.alpha.g2_spx)) return r && r.error(`BEACON key (alphaG2_spx) is not generated correctly in challenge #${t.id} ${t.name || ""}`), !1; + if (!e.G1.eq(t.key.beta.g1_s, i.beta.g1_s)) return r && r.error(`BEACON key (betaG1_s) is not generated correctly in challenge #${t.id} ${t.name || ""}`), !1; + if (!e.G1.eq(t.key.beta.g1_sx, i.beta.g1_sx)) return r && r.error(`BEACON key (betaG1_sx) is not generated correctly in challenge #${t.id} ${t.name || ""}`), !1; + if (!e.G2.eq(t.key.beta.g2_spx, i.beta.g2_spx)) return r && r.error(`BEACON key (betaG2_spx) is not generated correctly in challenge #${t.id} ${t.name || ""}`), !1; + } + return t.key.tau.g2_sp = e.G2.toAffine($t(e, 0, n.nextChallenge, t.key.tau.g1_s, t.key.tau.g1_sx)), t.key.alpha.g2_sp = e.G2.toAffine($t(e, 1, n.nextChallenge, t.key.alpha.g1_s, t.key.alpha.g1_sx)), t.key.beta.g2_sp = e.G2.toAffine($t(e, 2, n.nextChallenge, t.key.beta.g1_s, t.key.beta.g1_sx)), i = await vn(e, t.key.tau.g1_s, t.key.tau.g1_sx, t.key.tau.g2_sp, t.key.tau.g2_spx), i === !0 ? (i = await vn(e, t.key.alpha.g1_s, t.key.alpha.g1_sx, t.key.alpha.g2_sp, t.key.alpha.g2_spx), i === !0 ? (i = await vn(e, t.key.beta.g1_s, t.key.beta.g1_sx, t.key.beta.g2_sp, t.key.beta.g2_spx), i === !0 ? (i = await vn(e, n.tauG1, t.tauG1, t.key.tau.g2_sp, t.key.tau.g2_spx), i === !0 ? (i = await vn(e, t.key.tau.g1_s, t.key.tau.g1_sx, n.tauG2, t.tauG2), i === !0 ? (i = await vn(e, n.alphaG1, t.alphaG1, t.key.alpha.g2_sp, t.key.alpha.g2_spx), i === !0 ? (i = await vn(e, n.betaG1, t.betaG1, t.key.beta.g2_sp, t.key.beta.g2_spx), i === !0 ? (i = await vn(e, t.key.beta.g1_s, t.key.beta.g1_sx, n.betaG2, t.betaG2), i === !0 ? (r && r.info("Powers Of tau file OK!"), !0) : (r && r.error("INVALID beta*G2. challenge #" + t.id + "It does not follow the previous contribution"), !1)) : (r && r.error("INVALID beta*G1. challenge #" + t.id + " It does not follow the previous contribution"), !1)) : (r && r.error("INVALID alpha*G1. challenge #" + t.id + " It does not follow the previous contribution"), !1)) : (r && r.error("INVALID tau*G2. challenge #" + t.id + " It does not follow the previous contribution"), !1)) : (r && r.error("INVALID tau*G1. challenge #" + t.id + " It does not follow the previous contribution"), !1)) : (r && r.error("INVALID key (beta) in challenge #" + t.id), !1)) : (r && r.error("INVALID key (alpha) in challenge #" + t.id), !1)) : (r && r.error("INVALID key (tau) in challenge #" + t.id), !1); +} +async function bn(t, n) { + let r, { fd: i, sections: a } = await e.readBinFile(t, "ptau", 1), { curve: o, power: l, ceremonyPower: u } = await rn(i, a), d = await un(i, o, a); + n && n.debug("power: 2**" + l), n && n.debug("Computing initial contribution hash"); + let f = { + tauG1: o.G1.g, + tauG2: o.G2.g, + alphaG1: o.G1.g, + betaG1: o.G1.g, + betaG2: o.G2.g, + nextChallenge: pn(o, u, n), + responseHash: K.create({ dkLen: 64 }).digest() + }; + if (d.length == 0) return n && n.error("This file has no contribution! It cannot be used in production"), !1; + let p; + p = d.length > 1 ? d[d.length - 2] : f; + let m = d[d.length - 1]; + if (n && n.debug("Validating contribution #" + d[d.length - 1].id), !await yn(o, m, p, n)) return !1; + let h = K.create({ dkLen: 64 }); + h.update(m.responseHash), n && n.debug("Verifying powers in tau*G1 section"); + let g = await w(2, "G1", "tauG1", 2 ** l * 2 - 1, [0, 1], n); + if (r = await vn(o, g.R1, g.R2, o.G2.g, m.tauG2), r !== !0) return n && n.error("tauG1 section. Powers do not match"), !1; + if (!o.G1.eq(o.G1.g, g.singularPoints[0])) return n && n.error("First element of tau*G1 section must be the generator"), !1; + if (!o.G1.eq(m.tauG1, g.singularPoints[1])) return n && n.error("Second element of tau*G1 section does not match the one in the contribution section"), !1; + n && n.debug("Verifying powers in tau*G2 section"); + let _ = await w(3, "G2", "tauG2", 2 ** l, [0, 1], n); + if (r = await vn(o, o.G1.g, m.tauG1, _.R1, _.R2), r !== !0) return n && n.error("tauG2 section. Powers do not match"), !1; + if (!o.G2.eq(o.G2.g, _.singularPoints[0])) return n && n.error("First element of tau*G2 section must be the generator"), !1; + if (!o.G2.eq(m.tauG2, _.singularPoints[1])) return n && n.error("Second element of tau*G2 section does not match the one in the contribution section"), !1; + n && n.debug("Verifying powers in alpha*tau*G1 section"); + let v = await w(4, "G1", "alphatauG1", 2 ** l, [0], n); + if (r = await vn(o, v.R1, v.R2, o.G2.g, m.tauG2), r !== !0) return n && n.error("alphaTauG1 section. Powers do not match"), !1; + if (!o.G1.eq(m.alphaG1, v.singularPoints[0])) return n && n.error("First element of alpha*tau*G1 section (alpha*G1) does not match the one in the contribution section"), !1; + n && n.debug("Verifying powers in beta*tau*G1 section"); + let y = await w(5, "G1", "betatauG1", 2 ** l, [0], n); + if (r = await vn(o, y.R1, y.R2, o.G2.g, m.tauG2), r !== !0) return n && n.error("betaTauG1 section. Powers do not match"), !1; + if (!o.G1.eq(m.betaG1, y.singularPoints[0])) return n && n.error("First element of beta*tau*G1 section (beta*G1) does not match the one in the contribution section"), !1; + let b = await C(n); + if (!o.G2.eq(m.betaG2, b)) return n && n.error("betaG2 element in betaG2 section does not match the one in the contribution section"), !1; + let x = h.digest(); + if (l == u && !Ce(x, m.nextChallenge)) return n && n.error("Hash of the values does not match the next challenge of the last contributor in the contributions section"), !1; + n && n.info(q(x, "Next challenge hash: ")), S(m, p); + for (let e = d.length - 2; e >= 0; e--) { + let t = d[e], r = e > 0 ? d[e - 1] : f; + if (!await yn(o, t, r, n)) return !1; + S(t, r, n); + } + if (n && n.info("-----------------------------------------------------"), !a[12] || !a[13] || !a[14] || !a[15]) n && n.warn("this file does not contain phase2 precalculated values. Please run: \n snarkjs \"powersoftau preparephase2\" to prepare this file to be used in the phase2 ceremony."); + else { + let e; + if (e = await T("G1", 2, 12, "tauG1", n), !e || (e = await T("G2", 3, 13, "tauG2", n), !e) || (e = await T("G1", 4, 14, "alphaTauG1", n), !e) || (e = await T("G1", 5, 15, "betaTauG1", n), !e)) return !1; + } + return await i.close(), n && n.info("Powers of Tau Ok!"), !0; + function S(e, t) { + if (!n) return; + n.info("-----------------------------------------------------"), n.info(`Contribution #${e.id}: ${e.name || ""}`), n.info(q(e.nextChallenge, "Next Challenge: ")); + let r = new Uint8Array(o.G1.F.n8 * 2 * 6 + o.G2.F.n8 * 2 * 3); + sn(r, 0, o, e.key, !1); + let i = Te(e.partialHash); + i.update(r); + let a = i.digest(); + n.info(q(a, "Response Hash:")), n.info(q(t.nextChallenge, "Response Hash:")), e.type == 1 && (n.info(`Beacon generator: ${Fe(e.beaconHash)}`), n.info(`Beacon iterations Exp: ${e.numIterationsExp}`)); + } + async function C(e) { + let t = o.G2, n = t.F.n8 * 2, r = new Uint8Array(n); + if (!a[6]) throw e.error("File has no BetaG2 section"), Error("File has no BetaG2 section"); + if (a[6].length > 1) throw e.error("File has no BetaG2 section"), Error("File has more than one GetaG2 section"); + i.pos = a[6][0].p; + let s = await i.read(n), c = t.fromRprLEM(s); + return t.toRprUncompressed(r, 0, c), h.update(r), c; + } + async function w(t, n, r, s, c, l) { + let u = 65536, d = o[n], f = d.F.n8 * 2; + await e.startReadUniqueSection(i, a, t); + let p = [], m = d.zero, g = d.zero, _ = d.zero; + for (let e = 0; e < s; e += u) { + l && l.debug(`points relations: ${r}: ${e}/${s} `); + let t = Math.min(s - e, u), n = await i.read(t * f), a = await d.batchLEMtoU(n); + h.update(a); + let o = ke(4 * (t - 1)); + if (e > 0) { + let e = d.fromRprLEM(n, 0), t = je(ke(4), 0); + m = d.add(m, d.timesScalar(_, t)), g = d.add(g, d.timesScalar(e, t)); + } + let v = await d.multiExpAffine(n.slice(0, (t - 1) * f), o), y = await d.multiExpAffine(n.slice(f), o); + m = d.add(m, v), g = d.add(g, y), _ = d.fromRprLEM(n, (t - 1) * f); + for (let r = 0; r < c.length; r++) { + let i = c[r]; + if (i >= e && i < e + t) { + let t = d.fromRprLEM(n, (i - e) * f); + p.push(t); + } + } + } + return await e.endReadSection(i), { + R1: m, + R2: g, + singularPoints: p + }; + } + async function T(t, n, r, u, d) { + d && d.debug(`Verifying phase2 calculated values ${u}...`); + let f = o[t], p = f.F.n8 * 2, m = Array(8); + for (let e = 0; e < 8; e++) m[e] = je(ke(4), 0); + for (let e = 0; e <= l; e++) if (!await h(e)) return !1; + if (n == 2 && !await h(l + 1)) return !1; + return !0; + async function h(t) { + d && d.debug(`Power ${t}...`); + let h = o.Fr.n8, g = 2 ** t, _ = new Uint32Array(g), v, y = new c(m); + d && d.debug(`Creating random numbers Powers${t}...`); + for (let e = 0; e < g; e++) t == l + 1 && e == g - 1 ? _[e] = 0 : _[e] = y.nextU32(); + _ = new Uint8Array(_.buffer, _.byteOffset, _.byteLength), d && d.debug(`reading points Powers${t}...`), await e.startReadUniqueSection(i, a, n), v = new s(g * p), t == l + 1 ? (await i.readToBuffer(v, 0, (g - 1) * p), v.set(o.G1.zeroAffine, (g - 1) * p)) : await i.readToBuffer(v, 0, g * p), await e.endReadSection(i, !0); + let b = await f.multiExpAffine(v, _, d, u + "_" + t); + _ = new s(g * h), y = new c(m); + let x = new Uint8Array(4), S = new DataView(x.buffer); + d && d.debug(`Creating random numbers Powers${t}...`); + for (let e = 0; e < g; e++) (e != g - 1 || t != l + 1) && (S.setUint32(0, y.nextU32(), !0), _.set(x, e * h)); + d && d.debug(`batchToMontgomery ${t}...`), _ = await o.Fr.batchToMontgomery(_), d && d.debug(`fft ${t}...`), _ = await o.Fr.fft(_), d && d.debug(`batchFromMontgomery ${t}...`), _ = await o.Fr.batchFromMontgomery(_), d && d.debug(`reading points Lagrange${t}...`), await e.startReadUniqueSection(i, a, r), i.pos += p * (2 ** t - 1), await i.readToBuffer(v, 0, g * p), await e.endReadSection(i, !0); + let C = await f.multiExpAffine(v, _, d, u + "_" + t + "_transformed"); + return f.eq(b, C) ? !0 : (d && d.error("Phase2 caclutation does not match with powers of tau"), !1); + } + } +} +//#endregion +//#region src/mpc_applykey.js +async function xn(t, n, r, i, a, o, s, c, l, u) { + let d = 65536, f = a[o], p = f.F.n8 * 2, m = n[i][0].size / p; + await e.startReadUniqueSection(t, n, i), await e.startWriteSection(r, i); + let h = s; + for (let e = 0; e < m; e += d) { + u && u.debug(`Applying key: ${l}: ${e}/${m}`); + let n = Math.min(m - e, d), i; + i = await t.read(n * p), i = await f.batchApplyKey(i, h, c), await r.write(i), h = a.Fr.mul(h, a.Fr.exp(c, n)); + } + await e.endWriteSection(r), await e.endReadSection(t); +} +async function Sn(e, t, n, r, i, a, o, s, c, l, u) { + let d = r[i], f = d.F.n8 * 2, p = Math.floor((1 << 20) / f), m = o; + for (let i = 0; i < a; i += p) { + u && u.debug(`Applying key ${l}: ${i}/${a}`); + let o = Math.min(a - i, p), h = await e.read(o * f), g = await d.batchUtoLEM(h), _ = await d.batchApplyKey(g, m, s), v; + v = c == "COMPRESSED" ? await d.batchLEMtoC(_) : await d.batchLEMtoU(_), n && n.update(v), await t.write(v), m = r.Fr.mul(m, r.Fr.exp(s, o)); + } +} +//#endregion +//#region src/powersoftau_challenge_contribute.js +async function Cn(e, t, n, r, i) { + let a = await jt(t), o = e.F1.n64 * 8 * 2, s = e.F2.n64 * 8 * 2, c = (a.totalSize + o - 64 - s) / (4 * o + s), l = c, u = 0; + for (; l > 1;) l /= 2, u += 1; + if (2 ** u != c) throw Error("Invalid file size"); + i && i.debug("Power to tau size: " + u); + let d = await Me(r), f = await At(n), p = K.create({ dkLen: 64 }); + for (let e = 0; e < a.totalSize; e += a.pageSize) { + i && i.debug(`Hashing challenge ${e}/${a.totalSize}`); + let t = Math.min(a.totalSize - e, a.pageSize), n = await a.read(t); + p.update(n); + } + let m = await a.read(64, 0); + i && i.info(q(m, "Claimed Previous Response Hash: ")); + let h = p.digest(); + i && i.info(q(h, "Current Challenge Hash: ")); + let g = tn(e, h, d); + i && [ + "tau", + "alpha", + "beta" + ].forEach((t) => { + i.debug(t + ".g1_s: " + e.G1.toString(g[t].g1_s, 16)), i.debug(t + ".g1_sx: " + e.G1.toString(g[t].g1_sx, 16)), i.debug(t + ".g2_sp: " + e.G2.toString(g[t].g2_sp, 16)), i.debug(t + ".g2_spx: " + e.G2.toString(g[t].g2_spx, 16)), i.debug(""); + }); + let _ = K.create({ dkLen: 64 }); + await f.write(h), _.update(h), await Sn(a, f, _, e, "G1", 2 ** u * 2 - 1, e.Fr.one, g.tau.prvKey, "COMPRESSED", "tauG1", i), await Sn(a, f, _, e, "G2", 2 ** u, e.Fr.one, g.tau.prvKey, "COMPRESSED", "tauG2", i), await Sn(a, f, _, e, "G1", 2 ** u, g.alpha.prvKey, g.tau.prvKey, "COMPRESSED", "alphaTauG1", i), await Sn(a, f, _, e, "G1", 2 ** u, g.beta.prvKey, g.tau.prvKey, "COMPRESSED", "betaTauG1", i), await Sn(a, f, _, e, "G2", 1, g.beta.prvKey, g.tau.prvKey, "COMPRESSED", "betaTauG2", i); + let v = new Uint8Array(e.F1.n8 * 2 * 6 + e.F2.n8 * 2 * 3); + sn(v, 0, e, g, !1), await f.write(v), _.update(v); + let y = _.digest(); + i && i.info(q(y, "Contribution Response Hash: ")), await f.close(), await a.close(); +} +//#endregion +//#region src/powersoftau_beacon.js +async function wn(t, n, r, i, a, o) { + let s = Pe(i); + if (s.byteLength == 0 || s.byteLength * 2 != i.length) return o && o.error("Invalid Beacon Hash. (It must be a valid hexadecimal sequence)"), !1; + if (s.length >= 256) return o && o.error("Maximum length of beacon hash is 255 bytes"), !1; + if (a = parseInt(a), a < 10 || a > 63) return o && o.error("Invalid numIterationsExp. (Must be between 10 and 63)"), !1; + let { fd: c, sections: l } = await e.readBinFile(t, "ptau", 1), { curve: u, power: d, ceremonyPower: f } = await rn(c, l); + if (d != f) return o && o.error("This file has been reduced. You cannot contribute into a reduced file."), !1; + l[12] && o && o.warn("Contributing into a file that has phase2 calculated. You will have to prepare phase2 again."); + let p = await un(c, u, l), m = { + name: r, + type: 1, + numIterationsExp: a, + beaconHash: s + }, h; + h = p.length > 0 ? p[p.length - 1].nextChallenge : pn(u, d, o), m.key = await mn(u, h, s, a); + let g = K.create({ dkLen: 64 }); + g.update(h); + let _ = await e.createBinFile(n, "ptau", 1, 7); + await nn(_, u, d); + let v = [], y; + y = await C(2, "G1", 2 ** d * 2 - 1, u.Fr.e(1), m.key.tau.prvKey, "tauG1", o), m.tauG1 = y[1], y = await C(3, "G2", 2 ** d, u.Fr.e(1), m.key.tau.prvKey, "tauG2", o), m.tauG2 = y[1], y = await C(4, "G1", 2 ** d, m.key.alpha.prvKey, m.key.tau.prvKey, "alphaTauG1", o), m.alphaG1 = y[0], y = await C(5, "G1", 2 ** d, m.key.beta.prvKey, m.key.tau.prvKey, "betaTauG1", o), m.betaG1 = y[0], y = await C(6, "G2", 1, m.key.beta.prvKey, m.key.tau.prvKey, "betaTauG2", o), m.betaG2 = y[0], m.partialHash = Ee(g); + let b = new Uint8Array(u.F1.n8 * 2 * 6 + u.F2.n8 * 2 * 3); + sn(b, 0, u, m.key, !1), g.update(new Uint8Array(b)); + let x = g.digest(); + o && o.info(q(x, "Contribution Response Hash imported: ")); + let S = K.create({ dkLen: 64 }); + return S.update(x), await w(_, "G1", 2, 2 ** d * 2 - 1, "tauG1", o), await w(_, "G2", 3, 2 ** d, "tauG2", o), await w(_, "G1", 4, 2 ** d, "alphaTauG1", o), await w(_, "G1", 5, 2 ** d, "betaTauG1", o), await w(_, "G2", 6, 1, "betaG2", o), m.nextChallenge = S.digest(), o && o.info(q(m.nextChallenge, "Next Challenge Hash: ")), p.push(m), await fn(_, u, p), await c.close(), await _.close(), x; + async function C(t, n, r, i, a, o, s) { + let d = []; + c.pos = l[t][0].p, await e.startWriteSection(_, t), v[t] = _.pos; + let f = u[n], p = f.F.n8 * 2, m = Math.floor((1 << 20) / p), h = i; + for (let e = 0; e < r; e += m) { + s && s.debug(`applying key${o}: ${e}/${r}`); + let t = Math.min(r - e, m), n = await c.read(t * p), i = await f.batchApplyKey(n, h, a), l = _.write(i), v = await f.batchLEMtoC(i); + if (g.update(v), await l, e == 0) for (let e = 0; e < Math.min(2, r); e++) d.push(f.fromRprLEM(i, e * p)); + h = u.Fr.mul(h, u.Fr.exp(a, t)); + } + return await e.endWriteSection(_), d; + } + async function w(e, t, n, r, i, a) { + let o = u[t], s = o.F.n8 * 2, c = Math.floor((1 << 24) / s), l = e.pos; + e.pos = v[n]; + for (let t = 0; t < r; t += c) { + a && a.debug(`Hashing ${i}: ${t}/${r}`); + let n = Math.min(r - t, c), l = await e.read(n * s), u = await o.batchLEMtoU(l); + S.update(u); + } + e.pos = l; + } +} +//#endregion +//#region src/powersoftau_contribute.js +async function Tn(t, n, r, i, a) { + let { fd: o, sections: s } = await e.readBinFile(t, "ptau", 1), { curve: c, power: l, ceremonyPower: u } = await rn(o, s); + if (l != u) throw a && a.error("This file has been reduced. You cannot contribute into a reduced file."), Error("This file has been reduced. You cannot contribute into a reduced file."); + s[12] && a && a.warn("WARNING: Contributing into a file that has phase2 calculated. You will have to prepare phase2 again."); + let d = await un(o, c, s), f = { + name: r, + type: 0 + }, p, m = await Me(i); + p = d.length > 0 ? d[d.length - 1].nextChallenge : pn(c, l, a), f.key = tn(c, p, m); + let h = K.create({ dkLen: 64 }); + h.update(p); + let g = await e.createBinFile(n, "ptau", 1, 7); + await nn(g, c, l); + let _ = [], v; + v = await S(2, "G1", 2 ** l * 2 - 1, c.Fr.e(1), f.key.tau.prvKey, "tauG1"), f.tauG1 = v[1], v = await S(3, "G2", 2 ** l, c.Fr.e(1), f.key.tau.prvKey, "tauG2"), f.tauG2 = v[1], v = await S(4, "G1", 2 ** l, f.key.alpha.prvKey, f.key.tau.prvKey, "alphaTauG1"), f.alphaG1 = v[0], v = await S(5, "G1", 2 ** l, f.key.beta.prvKey, f.key.tau.prvKey, "betaTauG1"), f.betaG1 = v[0], v = await S(6, "G2", 1, f.key.beta.prvKey, f.key.tau.prvKey, "betaTauG2"), f.betaG2 = v[0], f.partialHash = Ee(h); + let y = new Uint8Array(c.F1.n8 * 2 * 6 + c.F2.n8 * 2 * 3); + sn(y, 0, c, f.key, !1), h.update(new Uint8Array(y)); + let b = h.digest(); + a && a.info(q(b, "Contribution Response Hash imported: ")); + let x = K.create({ dkLen: 64 }); + return x.update(b), await C(g, "G1", 2, 2 ** l * 2 - 1, "tauG1"), await C(g, "G2", 3, 2 ** l, "tauG2"), await C(g, "G1", 4, 2 ** l, "alphaTauG1"), await C(g, "G1", 5, 2 ** l, "betaTauG1"), await C(g, "G2", 6, 1, "betaG2"), f.nextChallenge = x.digest(), a && a.info(q(f.nextChallenge, "Next Challenge Hash: ")), d.push(f), await fn(g, c, d), await o.close(), await g.close(), b; + async function S(t, n, r, i, l, u) { + let d = []; + o.pos = s[t][0].p, await e.startWriteSection(g, t), _[t] = g.pos; + let f = c[n], p = f.F.n8 * 2, m = Math.floor((1 << 20) / p), v = i; + for (let e = 0; e < r; e += m) { + a && a.debug(`processing: ${u}: ${e}/${r}`); + let t = Math.min(r - e, m), n = await o.read(t * p), i = await f.batchApplyKey(n, v, l), s = g.write(i), _ = await f.batchLEMtoC(i); + if (h.update(_), await s, e == 0) for (let e = 0; e < Math.min(2, r); e++) d.push(f.fromRprLEM(i, e * p)); + v = c.Fr.mul(v, c.Fr.exp(l, t)); + } + return await e.endWriteSection(g), d; + } + async function C(e, t, n, r, i) { + let o = c[t], s = o.F.n8 * 2, l = Math.floor((1 << 24) / s), u = e.pos; + e.pos = _[n]; + for (let t = 0; t < r; t += l) { + a && t && a.debug(`Hashing ${i}: ` + t); + let n = Math.min(r - t, l), c = await e.read(n * s), u = await o.batchLEMtoU(c); + x.update(u); + } + e.pos = u; + } +} +//#endregion +//#region src/powersoftau_preparephase2.js +async function En(t, n, r) { + let { fd: i, sections: a } = await e.readBinFile(t, "ptau", 1), { curve: o, power: c } = await rn(i, a), l = await e.createBinFile(n, "ptau", 1, 11); + await nn(l, o, c), await e.copySection(i, a, l, 2), await e.copySection(i, a, l, 3), await e.copySection(i, a, l, 4), await e.copySection(i, a, l, 5), await e.copySection(i, a, l, 6), await e.copySection(i, a, l, 7), await u(2, 12, "G1", "tauG1"), await u(3, 13, "G2", "tauG2"), await u(4, 14, "G1", "alphaTauG1"), await u(5, 15, "G1", "betaTauG1"), await i.close(), await l.close(); + return; + async function u(t, n, u, d) { + r && r.debug("Starting section: " + d), await e.startWriteSection(l, n); + for (let e = 0; e <= c; e++) await f(e); + t == 2 && await f(c + 1), await e.endWriteSection(l); + async function f(n) { + let f = 2 ** n, p = o[u], m = p.F.n8 * 2, h; + h = new s(f * m), await e.startReadUniqueSection(i, a, t), t == 2 && n == c + 1 ? (await i.readToBuffer(h, 0, (f - 1) * m), h.set(o.G1.zeroAffine, (f - 1) * m)) : await i.readToBuffer(h, 0, f * m), await e.endReadSection(i, !0), h = await p.lagrangeEvaluations(h, "affine", "affine", r, d), await l.write(h); + } + } +} +//#endregion +//#region src/powersoftau_truncate.js +async function Dn(t, n, r) { + let { fd: i, sections: a } = await e.readBinFile(t, "ptau", 1), { curve: o, power: s, ceremonyPower: c } = await rn(i, a), l = o.G1.F.n8 * 2, u = o.G2.F.n8 * 2; + for (let e = 1; e < s; e++) await d(e); + return await i.close(), !0; + async function d(t) { + let s = t.toString(); + for (; s.length < 2;) s = "0" + s; + r && r.debug("Writing Power: " + s); + let d = await e.createBinFile(n + s + ".ptau", "ptau", 1, 11); + await nn(d, o, t, c), await e.copySection(i, a, d, 2, (2 ** t * 2 - 1) * l), await e.copySection(i, a, d, 3, 2 ** t * u), await e.copySection(i, a, d, 4, 2 ** t * l), await e.copySection(i, a, d, 5, 2 ** t * l), await e.copySection(i, a, d, 6, u), await e.copySection(i, a, d, 7), await e.copySection(i, a, d, 12, (2 ** (t + 1) * 2 - 1) * l), await e.copySection(i, a, d, 13, (2 ** t * 2 - 1) * u), await e.copySection(i, a, d, 14, (2 ** t * 2 - 1) * l), await e.copySection(i, a, d, 15, (2 ** t * 2 - 1) * l), await d.close(); + } +} +//#endregion +//#region src/powersoftau_convert.js +async function On(t, n, r) { + let { fd: i, sections: a } = await e.readBinFile(t, "ptau", 1), { curve: o, power: c } = await rn(i, a), l = await e.createBinFile(n, "ptau", 1, 11); + await nn(l, o, c), await e.copySection(i, a, l, 2), await e.copySection(i, a, l, 3), await e.copySection(i, a, l, 4), await e.copySection(i, a, l, 5), await e.copySection(i, a, l, 6), await e.copySection(i, a, l, 7), await u(2, 12, "G1", "tauG1"), await e.copySection(i, a, l, 13), await e.copySection(i, a, l, 14), await e.copySection(i, a, l, 15), await i.close(), await l.close(); + return; + async function u(t, n, u, d) { + r && r.debug("Starting section: " + d), await e.startWriteSection(l, n); + let f = a[n][0].size, p = i.pageSize; + await e.startReadUniqueSection(i, a, n); + for (let e = 0; e < f; e += p) { + let t = Math.min(f - e, p), n = await i.read(t); + await l.write(n); + } + await e.endReadSection(i), t == 2 && await m(c + 1), await e.endWriteSection(l); + async function m(n) { + let f = 2 ** n, p = o[u], m = p.F.n8 * 2, h; + h = new s(f * m), await e.startReadUniqueSection(i, a, t), t == 2 && n == c + 1 ? (await i.readToBuffer(h, 0, (f - 1) * m), h.set(o.G1.zeroAffine, (f - 1) * m)) : await i.readToBuffer(h, 0, f * m), await e.endReadSection(i, !0), h = await p.lagrangeEvaluations(h, "affine", "affine", r, d), await l.write(h); + } + } +} +//#endregion +//#region src/powersoftau_export_json.js +async function kn(t, n) { + let { fd: r, sections: i } = await e.readBinFile(t, "ptau", 1), { curve: a, power: o } = await rn(r, i), s = {}; + return s.q = a.q, s.power = o, s.contributions = await un(r, a, i), s.tauG1 = await c(2, "G1", 2 ** o * 2 - 1, "tauG1"), s.tauG2 = await c(3, "G2", 2 ** o, "tauG2"), s.alphaTauG1 = await c(4, "G1", 2 ** o, "alphaTauG1"), s.betaTauG1 = await c(5, "G1", 2 ** o, "betaTauG1"), s.betaG2 = await c(6, "G2", 1, "betaG2"), s.lTauG1 = await l(12, "G1", "lTauG1"), s.lTauG2 = await l(13, "G2", "lTauG2"), s.lAlphaTauG1 = await l(14, "G1", "lAlphaTauG2"), s.lBetaTauG1 = await l(15, "G1", "lBetaTauG2"), await r.close(), Ie(a.Fr, s); + async function c(t, o, s, c) { + let l = a[o], u = l.F.n8 * 2, d = []; + await e.startReadUniqueSection(r, i, t); + for (let e = 0; e < s; e++) { + n && e && e % 1e4 == 0 && console.log(`${c}: ` + e); + let t = await r.read(u); + d.push(l.fromRprLEM(t, 0)); + } + return await e.endReadSection(r), d; + } + async function l(t, s, c) { + let l = a[s], u = l.F.n8 * 2, d = []; + await e.startReadUniqueSection(r, i, t); + for (let e = 0; e <= o; e++) { + n && console.log(`${c}: Power: ${e}`), d[e] = []; + let t = 2 ** e; + for (let i = 0; i < t; i++) { + n && i && i % 1e4 == 0 && console.log(`${c}: ${i}/${t}`); + let a = await r.read(u); + d[e].push(l.fromRprLEM(a, 0)); + } + } + return await e.endReadSection(r, !0), d; + } +} +//#endregion +//#region src/powersoftau.js +var An = /* @__PURE__ */ y({ + beacon: () => wn, + challengeContribute: () => Cn, + contribute: () => Tn, + convert: () => On, + exportChallenge: () => gn, + exportJson: () => kn, + importResponse: () => _n, + newAccumulator: () => hn, + preparePhase2: () => En, + truncate: () => Dn, + verify: () => bn }); - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -function hashToG2(curve, hash) { - const hashV = new DataView(hash.buffer, hash.byteOffset, hash.byteLength); - const seed = []; - for (let i=0; i<8; i++) { - seed[i] = hashV.getUint32(i*4); - } - - const rng = new ChaCha(seed); - - const g2_sp = curve.G2.fromRng(rng); - - return g2_sp; -} - -function getG2sp(curve, persinalization, challenge, g1s, g1sx) { - - const h = blake2b.create({ dkLen: 64 }); - const b1 = new Uint8Array([persinalization]); - h.update(b1); - h.update(challenge); - const b3 = curve.G1.toUncompressed(g1s); - h.update( b3); - const b4 = curve.G1.toUncompressed(g1sx); - h.update( b4); - const hash =h.digest(); - - return hashToG2(curve, hash); -} - -function calculatePubKey(k, curve, personalization, challengeHash, rng ) { - k.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); - k.g1_sx = curve.G1.toAffine(curve.G1.timesFr(k.g1_s, k.prvKey)); - k.g2_sp = curve.G2.toAffine(getG2sp(curve, personalization, challengeHash, k.g1_s, k.g1_sx)); - k.g2_spx = curve.G2.toAffine(curve.G2.timesFr(k.g2_sp, k.prvKey)); - return k; -} - -function createPTauKey(curve, challengeHash, rng) { - const key = { - tau: {}, - alpha: {}, - beta: {} - }; - key.tau.prvKey = curve.Fr.fromRng(rng); - key.alpha.prvKey = curve.Fr.fromRng(rng); - key.beta.prvKey = curve.Fr.fromRng(rng); - calculatePubKey(key.tau, curve, 0, challengeHash, rng); - calculatePubKey(key.alpha, curve, 1, challengeHash, rng); - calculatePubKey(key.beta, curve, 2, challengeHash, rng); - return key; -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -async function writePTauHeader(fd, curve, power, ceremonyPower) { - // Write the header - /////////// - - if (! ceremonyPower) ceremonyPower = power; - await fd.writeULE32(1); // Header type - const pHeaderSize = fd.pos; - await fd.writeULE64(0); // Temporally set to 0 length - - await fd.writeULE32(curve.F1.n64*8); - - const buff = new Uint8Array(curve.F1.n8); - Scalar.toRprLE(buff, 0, curve.q, curve.F1.n8); - await fd.write(buff); - await fd.writeULE32(power); // power - await fd.writeULE32(ceremonyPower); // power - - const headerSize = fd.pos - pHeaderSize - 8; - - const oldPos = fd.pos; - - await fd.writeULE64(headerSize, pHeaderSize); - - fd.pos = oldPos; -} - -async function readPTauHeader(fd, sections) { - if (!sections[1]) throw new Error(fd.fileName + ": File has no header"); - if (sections[1].length>1) throw new Error(fd.fileName +": File has more than one header"); - - fd.pos = sections[1][0].p; - const n8 = await fd.readULE32(); - const buff = await fd.read(n8); - const q = Scalar.fromRprLE(buff); - - const curve = await getCurveFromQ(q); - - if (curve.F1.n64*8 != n8) throw new Error(fd.fileName +": Invalid size"); - - const power = await fd.readULE32(); - const ceremonyPower = await fd.readULE32(); - - if (fd.pos-sections[1][0].p != sections[1][0].size) throw new Error("Invalid PTau header size"); - - return {curve, power, ceremonyPower}; -} - - -async function readPtauPubKey(fd, curve, montgomery) { - - const buff = await fd.read(curve.F1.n8*2*6 + curve.F2.n8*2*3); - - return fromPtauPubKeyRpr(buff, 0, curve, montgomery); -} - -function fromPtauPubKeyRpr(buff, pos, curve, montgomery) { - - const key = { - tau: {}, - alpha: {}, - beta: {} - }; - - key.tau.g1_s = readG1(); - key.tau.g1_sx = readG1(); - key.alpha.g1_s = readG1(); - key.alpha.g1_sx = readG1(); - key.beta.g1_s = readG1(); - key.beta.g1_sx = readG1(); - key.tau.g2_spx = readG2(); - key.alpha.g2_spx = readG2(); - key.beta.g2_spx = readG2(); - - return key; - - function readG1() { - let p; - if (montgomery) { - p = curve.G1.fromRprLEM( buff, pos ); - } else { - p = curve.G1.fromRprUncompressed( buff, pos ); - } - pos += curve.G1.F.n8*2; - return p; - } - - function readG2() { - let p; - if (montgomery) { - p = curve.G2.fromRprLEM( buff, pos ); - } else { - p = curve.G2.fromRprUncompressed( buff, pos ); - } - pos += curve.G2.F.n8*2; - return p; - } -} - -function toPtauPubKeyRpr(buff, pos, curve, key, montgomery) { - - writeG1(key.tau.g1_s); - writeG1(key.tau.g1_sx); - writeG1(key.alpha.g1_s); - writeG1(key.alpha.g1_sx); - writeG1(key.beta.g1_s); - writeG1(key.beta.g1_sx); - writeG2(key.tau.g2_spx); - writeG2(key.alpha.g2_spx); - writeG2(key.beta.g2_spx); - - async function writeG1(p) { - if (montgomery) { - curve.G1.toRprLEM(buff, pos, p); - } else { - curve.G1.toRprUncompressed(buff, pos, p); - } - pos += curve.F1.n8*2; - } - - async function writeG2(p) { - if (montgomery) { - curve.G2.toRprLEM(buff, pos, p); - } else { - curve.G2.toRprUncompressed(buff, pos, p); - } - pos += curve.F2.n8*2; - } - - return buff; -} - -async function writePtauPubKey(fd, curve, key, montgomery) { - const buff = new Uint8Array(curve.F1.n8*2*6 + curve.F2.n8*2*3); - toPtauPubKeyRpr(buff, 0, curve, key, montgomery); - await fd.write(buff); -} - -async function readContribution(fd, curve) { - const c = {}; - - c.tauG1 = await readG1(); - c.tauG2 = await readG2(); - c.alphaG1 = await readG1(); - c.betaG1 = await readG1(); - c.betaG2 = await readG2(); - c.key = await readPtauPubKey(fd, curve, true); - c.partialHash = await fd.read(216); - c.nextChallenge = await fd.read(64); - c.type = await fd.readULE32(); - - const buffV = new Uint8Array(curve.G1.F.n8*2*6+curve.G2.F.n8*2*3); - toPtauPubKeyRpr(buffV, 0, curve, c.key, false); - - const responseHasher = fromPartialHash(c.partialHash); - responseHasher.update(buffV); - c.responseHash = responseHasher.digest(); - - const paramLength = await fd.readULE32(); - const curPos = fd.pos; - let lastType =0; - while (fd.pos-curPos < paramLength) { - const buffType = await readDV(1); - if (buffType[0]<= lastType) throw new Error("Parameters in the contribution must be sorted"); - lastType = buffType[0]; - if (buffType[0]==1) { // Name - const buffLen = await readDV(1); - const buffStr = await readDV(buffLen[0]); - c.name = new TextDecoder().decode(buffStr); - } else if (buffType[0]==2) { - const buffExp = await readDV(1); - c.numIterationsExp = buffExp[0]; - } else if (buffType[0]==3) { - const buffLen = await readDV(1); - c.beaconHash = await readDV(buffLen[0]); - } else { - throw new Error("Parameter not recognized"); - } - } - if (fd.pos != curPos + paramLength) { - throw new Error("Parameters do not match"); - } - - return c; - - async function readG1() { - const pBuff = await fd.read(curve.G1.F.n8*2); - return curve.G1.fromRprLEM( pBuff ); - } - - async function readG2() { - const pBuff = await fd.read(curve.G2.F.n8*2); - return curve.G2.fromRprLEM( pBuff ); - } - - async function readDV(n) { - const b = await fd.read(n); - return new Uint8Array(b); - } -} - -async function readContributions(fd, curve, sections) { - if (!sections[7]) throw new Error(fd.fileName + ": File has no contributions"); - if (sections[7][0].length>1) throw new Error(fd.fileName +": File has more than one contributions section"); - - fd.pos = sections[7][0].p; - const nContributions = await fd.readULE32(); - const contributions = []; - for (let i=0; i0) { - const paramsBuff = new Uint8Array(params); - await fd.writeULE32(paramsBuff.byteLength); - await fd.write(paramsBuff); - } else { - await fd.writeULE32(0); - } - - - async function writeG1(p) { - curve.G1.toRprLEM(buffG1, 0, p); - await fd.write(buffG1); - } - - async function writeG2(p) { - curve.G2.toRprLEM(buffG2, 0, p); - await fd.write(buffG2); - } - -} - -async function writeContributions(fd, curve, contributions) { - - await fd.writeULE32(7); // Header type - const pContributionsSize = fd.pos; - await fd.writeULE64(0); // Temporally set to 0 length - - await fd.writeULE32(contributions.length); - for (let i=0; i< contributions.length; i++) { - await writeContribution(fd, curve, contributions[i]); - } - const contributionsSize = fd.pos - pContributionsSize - 8; - - const oldPos = fd.pos; - - await fd.writeULE64(contributionsSize, pContributionsSize); - fd.pos = oldPos; -} - -function calculateFirstChallengeHash(curve, power, logger) { - if (logger) logger.debug("Calculating First Challenge Hash"); - - const hasher = blake2b.create({ dkLen: 64 }); - - const vG1 = new Uint8Array(curve.G1.F.n8*2); - const vG2 = new Uint8Array(curve.G2.F.n8*2); - curve.G1.toRprUncompressed(vG1, 0, curve.G1.g); - curve.G2.toRprUncompressed(vG2, 0, curve.G2.g); - - hasher.update(blake2b.create({ dkLen: 64 }).digest()); - - let n; - - n=(2 ** power)*2 -1; - if (logger) logger.debug("Calculate Initial Hash: tauG1"); - hashBlock(vG1, n); - n= 2 ** power; - if (logger) logger.debug("Calculate Initial Hash: tauG2"); - hashBlock(vG2, n); - if (logger) logger.debug("Calculate Initial Hash: alphaTauG1"); - hashBlock(vG1, n); - if (logger) logger.debug("Calculate Initial Hash: betaTauG1"); - hashBlock(vG1, n); - hasher.update(vG2); - - return hasher.digest(); - - function hashBlock(buff, n) { - // this block size is a good compromise between speed and the maximum - // input size of the Blake2b update method (65,535,720 bytes). - const blockSize = 341000; - const nBlocks = Math.floor(n / blockSize); - const rem = n % blockSize; - const bigBuff = new Uint8Array(blockSize * buff.byteLength); - for (let i=0; i. -*/ - -async function newAccumulator(curve, power, fileName, logger) { - - const fd = await createBinFile(fileName, "ptau", 1, 7); - - await writePTauHeader(fd, curve, power, 0); - - const buffG1 = curve.G1.oneAffine; - const buffG2 = curve.G2.oneAffine; - - // Write tauG1 - /////////// - await startWriteSection(fd, 2); - const nTauG1 = (2 ** power) * 2 -1; - for (let i=0; i< nTauG1; i++) { - await fd.write(buffG1); - if ((logger)&&((i%100000) == 0)&&i) logger.log("tauG1: " + i); - } - await endWriteSection(fd); - - // Write tauG2 - /////////// - await startWriteSection(fd, 3); - const nTauG2 = (2 ** power); - for (let i=0; i< nTauG2; i++) { - await fd.write(buffG2); - if ((logger)&&((i%100000) == 0)&&i) logger.log("tauG2: " + i); - } - await endWriteSection(fd); - - // Write alphaTauG1 - /////////// - await startWriteSection(fd, 4); - const nAlfaTauG1 = (2 ** power); - for (let i=0; i< nAlfaTauG1; i++) { - await fd.write(buffG1); - if ((logger)&&((i%100000) == 0)&&i) logger.log("alphaTauG1: " + i); - } - await endWriteSection(fd); - - // Write betaTauG1 - /////////// - await startWriteSection(fd, 5); - const nBetaTauG1 = (2 ** power); - for (let i=0; i< nBetaTauG1; i++) { - await fd.write(buffG1); - if ((logger)&&((i%100000) == 0)&&i) logger.log("betaTauG1: " + i); - } - await endWriteSection(fd); - - // Write betaG2 - /////////// - await startWriteSection(fd, 6); - await fd.write(buffG2); - await endWriteSection(fd); - - // Contributions - /////////// - await startWriteSection(fd, 7); - await fd.writeULE32(0); // 0 Contributions - await endWriteSection(fd); - - await fd.close(); - - const firstChallengeHash = calculateFirstChallengeHash(curve, power, logger); - - if (logger) logger.debug(formatHash(blake2b.create({ dkLen: 64 }).digest(), "Blank Contribution Hash:")); - - if (logger) logger.info(formatHash(firstChallengeHash, "First Contribution Hash:")); - - return firstChallengeHash; - -} - -// Format of the outpu - -async function exportChallenge(pTauFilename, challengeFilename, logger) { - const {fd: fdFrom, sections} = await readBinFile$1(pTauFilename, "ptau", 1); - - const {curve, power} = await readPTauHeader(fdFrom, sections); - - const contributions = await readContributions(fdFrom, curve, sections); - let lastResponseHash, curChallengeHash; - if (contributions.length == 0) { - lastResponseHash = blake2b.create({ dkLen: 64 }).digest(); - curChallengeHash = calculateFirstChallengeHash(curve, power); - } else { - lastResponseHash = contributions[contributions.length-1].responseHash; - curChallengeHash = contributions[contributions.length-1].nextChallenge; - } - - if (logger) logger.info(formatHash(lastResponseHash, "Last Response Hash: ")); - - if (logger) logger.info(formatHash(curChallengeHash, "New Challenge Hash: ")); - - - const fdTo = await createOverride(challengeFilename); - - const toHash = blake2b.create({ dkLen: 64 }); - await fdTo.write(lastResponseHash); - toHash.update(lastResponseHash); - - await exportSection(2, "G1", (2 ** power) * 2 -1, "tauG1"); - await exportSection(3, "G2", (2 ** power) , "tauG2"); - await exportSection(4, "G1", (2 ** power) , "alphaTauG1"); - await exportSection(5, "G1", (2 ** power) , "betaTauG1"); - await exportSection(6, "G2", 1 , "betaG2"); - - await fdFrom.close(); - await fdTo.close(); - - const calcCurChallengeHash = toHash.digest(); - - if (!hashIsEqual (curChallengeHash, calcCurChallengeHash)) { - if (logger) logger.info(formatHash(calcCurChallengeHash, "Calc Curret Challenge Hash: ")); - - if (logger) logger.error("PTau file is corrupted. Calculated new challenge hash does not match with the eclared one"); - throw new Error("PTau file is corrupted. Calculated new challenge hash does not match with the eclared one"); - } - - return curChallengeHash; - - async function exportSection(sectionId, groupName, nPoints, sectionName) { - const G = curve[groupName]; - const sG = G.F.n8*2; - const nPointsChunk = Math.floor((1<<24)/sG); - - await startReadUniqueSection$1(fdFrom, sections, sectionId); - for (let i=0; i< nPoints; i+= nPointsChunk) { - if (logger) logger.debug(`Exporting ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints-i, nPointsChunk); - let buff; - buff = await fdFrom.read(n*sG); - buff = await G.batchLEMtoU(buff); - await fdTo.write(buff); - toHash.update(buff); - } - await endReadSection$1(fdFrom); - } - - -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -async function importResponse(oldPtauFilename, contributionFilename, newPTauFilename, name, importPoints, logger) { - - const noHash = new Uint8Array(64); - for (let i=0; i<64; i++) noHash[i] = 0xFF; - - const {fd: fdOld, sections} = await readBinFile$1(oldPtauFilename, "ptau", 1); - const {curve, power} = await readPTauHeader(fdOld, sections); - const contributions = await readContributions(fdOld, curve, sections); - const currentContribution = {}; - - if (name) currentContribution.name = name; - - const sG1 = curve.F1.n8*2; - const scG1 = curve.F1.n8; // Compressed size - const sG2 = curve.F2.n8*2; - const scG2 = curve.F2.n8; // Compressed size - - const fdResponse = await readExisting$3(contributionFilename); - - if (fdResponse.totalSize != - 64 + // Old Hash - ((2 ** power)*2-1)*scG1 + - (2 ** power)*scG2 + - (2 ** power)*scG1 + - (2 ** power)*scG1 + - scG2 + - sG1*6 + sG2*3) - throw new Error("Size of the contribution is invalid"); - - let lastChallengeHash; - - if (contributions.length>0) { - lastChallengeHash = contributions[contributions.length-1].nextChallenge; - } else { - lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); - } - - const fdNew = await createBinFile(newPTauFilename, "ptau", 1, importPoints ? 7: 2); - await writePTauHeader(fdNew, curve, power); - - const contributionPreviousHash = await fdResponse.read(64); - - if (hashIsEqual(noHash,lastChallengeHash)) { - lastChallengeHash = contributionPreviousHash; - contributions[contributions.length-1].nextChallenge = lastChallengeHash; - } - - if(!hashIsEqual(contributionPreviousHash,lastChallengeHash)) - throw new Error("Wrong contribution. This contribution is not based on the previous hash"); - - const hasherResponse = blake2b.create({ dkLen: 64 }); - hasherResponse.update(contributionPreviousHash); - - const startSections = []; - let res; - res = await processSection(fdResponse, fdNew, "G1", 2, (2 ** power) * 2 -1, [1], "tauG1"); - currentContribution.tauG1 = res[0]; - res = await processSection(fdResponse, fdNew, "G2", 3, (2 ** power) , [1], "tauG2"); - currentContribution.tauG2 = res[0]; - res = await processSection(fdResponse, fdNew, "G1", 4, (2 ** power) , [0], "alphaG1"); - currentContribution.alphaG1 = res[0]; - res = await processSection(fdResponse, fdNew, "G1", 5, (2 ** power) , [0], "betaG1"); - currentContribution.betaG1 = res[0]; - res = await processSection(fdResponse, fdNew, "G2", 6, 1 , [0], "betaG2"); - currentContribution.betaG2 = res[0]; - - currentContribution.partialHash = toPartialHash(hasherResponse); - - - const buffKey = await fdResponse.read(curve.F1.n8*2*6+curve.F2.n8*2*3); - - currentContribution.key = fromPtauPubKeyRpr(buffKey, 0, curve, false); - - hasherResponse.update(new Uint8Array(buffKey)); - const hashResponse = hasherResponse.digest(); - - if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); - - if (importPoints) { - const nextChallengeHasher = blake2b.create({ dkLen: 64 }); - nextChallengeHasher.update(hashResponse); - - await hashSection(nextChallengeHasher, fdNew, "G1", 2, (2 ** power) * 2 -1, "tauG1", logger); - await hashSection(nextChallengeHasher, fdNew, "G2", 3, (2 ** power) , "tauG2", logger); - await hashSection(nextChallengeHasher, fdNew, "G1", 4, (2 ** power) , "alphaTauG1", logger); - await hashSection(nextChallengeHasher, fdNew, "G1", 5, (2 ** power) , "betaTauG1", logger); - await hashSection(nextChallengeHasher, fdNew, "G2", 6, 1 , "betaG2", logger); - - currentContribution.nextChallenge = nextChallengeHasher.digest(); - - if (logger) logger.info(formatHash(currentContribution.nextChallenge, "Next Challenge Hash: ")); - } else { - currentContribution.nextChallenge = noHash; - } - - contributions.push(currentContribution); - - await writeContributions(fdNew, curve, contributions); - - await fdResponse.close(); - await fdNew.close(); - await fdOld.close(); - - return currentContribution.nextChallenge; - - async function processSection(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { - if (importPoints) { - return await processSectionImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName); - } else { - return await processSectionNoImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName); - } - } - - async function processSectionImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { - - const G = curve[groupName]; - const scG = G.F.n8; - const sG = G.F.n8*2; - - const singularPoints = []; - - await startWriteSection(fdTo, sectionId); - const nPointsChunk = Math.floor((1<<24)/sG); - - startSections[sectionId] = fdTo.pos; - - for (let i=0; i< nPoints; i += nPointsChunk) { - if (logger) logger.debug(`Importing ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints-i, nPointsChunk); - - const buffC = await fdFrom.read(n * scG); - hasherResponse.update(buffC); - - const buffLEM = await G.batchCtoLEM(buffC); - - await fdTo.write(buffLEM); - for (let j=0; j=i) && (sp < i+n)) { - const P = G.fromRprLEM(buffLEM, (sp-i)*sG); - singularPoints.push(P); - } - } - } - - await endWriteSection(fdTo); - - return singularPoints; - } - - - async function processSectionNoImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { - - const G = curve[groupName]; - const scG = G.F.n8; - - const singularPoints = []; - - const nPointsChunk = Math.floor((1<<24)/scG); - - for (let i=0; i< nPoints; i += nPointsChunk) { - if (logger) logger.debug(`Importing ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints-i, nPointsChunk); - - const buffC = await fdFrom.read(n * scG); - hasherResponse.update(buffC); - - for (let j=0; j=i) && (sp < i+n)) { - const P = G.fromRprCompressed(buffC, (sp-i)*scG); - singularPoints.push(P); - } - } - } - - return singularPoints; - } - - - async function hashSection(nextChallengeHasher, fdTo, groupName, sectionId, nPoints, sectionName, logger) { - - const G = curve[groupName]; - const sG = G.F.n8*2; - const nPointsChunk = Math.floor((1<<24)/sG); - - const oldPos = fdTo.pos; - fdTo.pos = startSections[sectionId]; - - for (let i=0; i< nPoints; i += nPointsChunk) { - if (logger) logger.debug(`Hashing ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints-i, nPointsChunk); - - const buffLEM = await fdTo.read(n * sG); - - const buffU = await G.batchLEMtoU(buffLEM); - - nextChallengeHasher.update(buffU); - } - - fdTo.pos = oldPos; - } - -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ -const sameRatio$1 = sameRatio$2; - -async function verifyContribution(curve, cur, prev, logger) { - let sr; - if (cur.type == 1) { // Verify the beacon. - const beaconKey = await keyFromBeacon(curve, prev.nextChallenge, cur.beaconHash, cur.numIterationsExp); - - if (!curve.G1.eq(cur.key.tau.g1_s, beaconKey.tau.g1_s)) { - if (logger) logger.error(`BEACON key (tauG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G1.eq(cur.key.tau.g1_sx, beaconKey.tau.g1_sx)) { - if (logger) logger.error(`BEACON key (tauG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G2.eq(cur.key.tau.g2_spx, beaconKey.tau.g2_spx)) { - if (logger) logger.error(`BEACON key (tauG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - - if (!curve.G1.eq(cur.key.alpha.g1_s, beaconKey.alpha.g1_s)) { - if (logger) logger.error(`BEACON key (alphaG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G1.eq(cur.key.alpha.g1_sx, beaconKey.alpha.g1_sx)) { - if (logger) logger.error(`BEACON key (alphaG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G2.eq(cur.key.alpha.g2_spx, beaconKey.alpha.g2_spx)) { - if (logger) logger.error(`BEACON key (alphaG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - - if (!curve.G1.eq(cur.key.beta.g1_s, beaconKey.beta.g1_s)) { - if (logger) logger.error(`BEACON key (betaG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G1.eq(cur.key.beta.g1_sx, beaconKey.beta.g1_sx)) { - if (logger) logger.error(`BEACON key (betaG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G2.eq(cur.key.beta.g2_spx, beaconKey.beta.g2_spx)) { - if (logger) logger.error(`BEACON key (betaG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - } - - cur.key.tau.g2_sp = curve.G2.toAffine(getG2sp(curve, 0, prev.nextChallenge, cur.key.tau.g1_s, cur.key.tau.g1_sx)); - cur.key.alpha.g2_sp = curve.G2.toAffine(getG2sp(curve, 1, prev.nextChallenge, cur.key.alpha.g1_s, cur.key.alpha.g1_sx)); - cur.key.beta.g2_sp = curve.G2.toAffine(getG2sp(curve, 2, prev.nextChallenge, cur.key.beta.g1_s, cur.key.beta.g1_sx)); - - sr = await sameRatio$1(curve, cur.key.tau.g1_s, cur.key.tau.g1_sx, cur.key.tau.g2_sp, cur.key.tau.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID key (tau) in challenge #"+cur.id); - return false; - } - - sr = await sameRatio$1(curve, cur.key.alpha.g1_s, cur.key.alpha.g1_sx, cur.key.alpha.g2_sp, cur.key.alpha.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID key (alpha) in challenge #"+cur.id); - return false; - } - - sr = await sameRatio$1(curve, cur.key.beta.g1_s, cur.key.beta.g1_sx, cur.key.beta.g2_sp, cur.key.beta.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID key (beta) in challenge #"+cur.id); - return false; - } - - sr = await sameRatio$1(curve, prev.tauG1, cur.tauG1, cur.key.tau.g2_sp, cur.key.tau.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID tau*G1. challenge #"+cur.id+" It does not follow the previous contribution"); - return false; - } - - sr = await sameRatio$1(curve, cur.key.tau.g1_s, cur.key.tau.g1_sx, prev.tauG2, cur.tauG2); - if (sr !== true) { - if (logger) logger.error("INVALID tau*G2. challenge #"+cur.id+" It does not follow the previous contribution"); - return false; - } - - sr = await sameRatio$1(curve, prev.alphaG1, cur.alphaG1, cur.key.alpha.g2_sp, cur.key.alpha.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID alpha*G1. challenge #"+cur.id+" It does not follow the previous contribution"); - return false; - } - - sr = await sameRatio$1(curve, prev.betaG1, cur.betaG1, cur.key.beta.g2_sp, cur.key.beta.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID beta*G1. challenge #"+cur.id+" It does not follow the previous contribution"); - return false; - } - - sr = await sameRatio$1(curve, cur.key.beta.g1_s, cur.key.beta.g1_sx, prev.betaG2, cur.betaG2); - if (sr !== true) { - if (logger) logger.error("INVALID beta*G2. challenge #"+cur.id+"It does not follow the previous contribution"); - return false; - } - - if (logger) logger.info("Powers Of tau file OK!"); - return true; -} - -async function verify(tauFilename, logger) { - let sr; - - const {fd, sections} = await readBinFile$1(tauFilename, "ptau", 1); - const {curve, power, ceremonyPower} = await readPTauHeader(fd, sections); - const contrs = await readContributions(fd, curve, sections); - - if (logger) logger.debug("power: 2**" + power); - // Verify Last contribution - - if (logger) logger.debug("Computing initial contribution hash"); - const initialContribution = { - tauG1: curve.G1.g, - tauG2: curve.G2.g, - alphaG1: curve.G1.g, - betaG1: curve.G1.g, - betaG2: curve.G2.g, - nextChallenge: calculateFirstChallengeHash(curve, ceremonyPower, logger), - responseHash: blake2b.create({ dkLen: 64 }).digest() - }; - - if (contrs.length == 0) { - if (logger) logger.error("This file has no contribution! It cannot be used in production"); - return false; - } - - let prevContr; - if (contrs.length>1) { - prevContr = contrs[contrs.length-2]; - } else { - prevContr = initialContribution; - } - const curContr = contrs[contrs.length-1]; - if (logger) logger.debug("Validating contribution #"+contrs[contrs.length-1].id); - const res = await verifyContribution(curve, curContr, prevContr, logger); - if (!res) return false; - - - const nextContributionHasher = blake2b.create({ dkLen: 64 }); - nextContributionHasher.update(curContr.responseHash); - - // Verify powers and compute nextChallengeHash - - // await test(); - - // Verify Section tau*G1 - if (logger) logger.debug("Verifying powers in tau*G1 section"); - const rTau1 = await processSection(2, "G1", "tauG1", (2 ** power)*2-1, [0, 1], logger); - sr = await sameRatio$1(curve, rTau1.R1, rTau1.R2, curve.G2.g, curContr.tauG2); - if (sr !== true) { - if (logger) logger.error("tauG1 section. Powers do not match"); - return false; - } - if (!curve.G1.eq(curve.G1.g, rTau1.singularPoints[0])) { - if (logger) logger.error("First element of tau*G1 section must be the generator"); - return false; - } - if (!curve.G1.eq(curContr.tauG1, rTau1.singularPoints[1])) { - if (logger) logger.error("Second element of tau*G1 section does not match the one in the contribution section"); - return false; - } - - // await test(); - - // Verify Section tau*G2 - if (logger) logger.debug("Verifying powers in tau*G2 section"); - const rTau2 = await processSection(3, "G2", "tauG2", 2 ** power, [0, 1], logger); - sr = await sameRatio$1(curve, curve.G1.g, curContr.tauG1, rTau2.R1, rTau2.R2); - if (sr !== true) { - if (logger) logger.error("tauG2 section. Powers do not match"); - return false; - } - if (!curve.G2.eq(curve.G2.g, rTau2.singularPoints[0])) { - if (logger) logger.error("First element of tau*G2 section must be the generator"); - return false; - } - if (!curve.G2.eq(curContr.tauG2, rTau2.singularPoints[1])) { - if (logger) logger.error("Second element of tau*G2 section does not match the one in the contribution section"); - return false; - } - - // Verify Section alpha*tau*G1 - if (logger) logger.debug("Verifying powers in alpha*tau*G1 section"); - const rAlphaTauG1 = await processSection(4, "G1", "alphatauG1", 2 ** power, [0], logger); - sr = await sameRatio$1(curve, rAlphaTauG1.R1, rAlphaTauG1.R2, curve.G2.g, curContr.tauG2); - if (sr !== true) { - if (logger) logger.error("alphaTauG1 section. Powers do not match"); - return false; - } - if (!curve.G1.eq(curContr.alphaG1, rAlphaTauG1.singularPoints[0])) { - if (logger) logger.error("First element of alpha*tau*G1 section (alpha*G1) does not match the one in the contribution section"); - return false; - } - - // Verify Section beta*tau*G1 - if (logger) logger.debug("Verifying powers in beta*tau*G1 section"); - const rBetaTauG1 = await processSection(5, "G1", "betatauG1", 2 ** power, [0], logger); - sr = await sameRatio$1(curve, rBetaTauG1.R1, rBetaTauG1.R2, curve.G2.g, curContr.tauG2); - if (sr !== true) { - if (logger) logger.error("betaTauG1 section. Powers do not match"); - return false; - } - if (!curve.G1.eq(curContr.betaG1, rBetaTauG1.singularPoints[0])) { - if (logger) logger.error("First element of beta*tau*G1 section (beta*G1) does not match the one in the contribution section"); - return false; - } - - //Verify Beta G2 - const betaG2 = await processSectionBetaG2(logger); - if (!curve.G2.eq(curContr.betaG2, betaG2)) { - if (logger) logger.error("betaG2 element in betaG2 section does not match the one in the contribution section"); - return false; - } - - - const nextContributionHash = nextContributionHasher.digest(); - - // Check the nextChallengeHash - if (power == ceremonyPower) { - if (!hashIsEqual(nextContributionHash,curContr.nextChallenge)) { - if (logger) logger.error("Hash of the values does not match the next challenge of the last contributor in the contributions section"); - return false; - } - } - - if (logger) logger.info(formatHash(nextContributionHash, "Next challenge hash: ")); - - // Verify Previous contributions - - printContribution(curContr, prevContr); - for (let i = contrs.length-2; i>=0; i--) { - const curContr = contrs[i]; - const prevContr = (i>0) ? contrs[i-1] : initialContribution; - const res = await verifyContribution(curve, curContr, prevContr, logger); - if (!res) return false; - printContribution(curContr, prevContr); - } - if (logger) logger.info("-----------------------------------------------------"); - - if ((!sections[12]) || (!sections[13]) || (!sections[14]) || (!sections[15])) { - if (logger) logger.warn( - "this file does not contain phase2 precalculated values. Please run: \n" + - " snarkjs \"powersoftau preparephase2\" to prepare this file to be used in the phase2 ceremony." - ); - } else { - let res; - res = await verifyLagrangeEvaluations("G1", 2, 12, "tauG1", logger); - if (!res) return false; - res = await verifyLagrangeEvaluations("G2", 3, 13, "tauG2", logger); - if (!res) return false; - res = await verifyLagrangeEvaluations("G1", 4, 14, "alphaTauG1", logger); - if (!res) return false; - res = await verifyLagrangeEvaluations("G1", 5, 15, "betaTauG1", logger); - if (!res) return false; - } - - await fd.close(); - - if (logger) logger.info("Powers of Tau Ok!"); - - return true; - - function printContribution(curContr, prevContr) { - if (!logger) return; - logger.info("-----------------------------------------------------"); - logger.info(`Contribution #${curContr.id}: ${curContr.name ||""}`); - - logger.info(formatHash(curContr.nextChallenge, "Next Challenge: ")); - - const buffV = new Uint8Array(curve.G1.F.n8*2*6+curve.G2.F.n8*2*3); - toPtauPubKeyRpr(buffV, 0, curve, curContr.key, false); - - const responseHasher = fromPartialHash(curContr.partialHash); - responseHasher.update(buffV); - const responseHash = responseHasher.digest(); - - logger.info(formatHash(responseHash, "Response Hash:")); - - logger.info(formatHash(prevContr.nextChallenge, "Response Hash:")); - - if (curContr.type == 1) { - logger.info(`Beacon generator: ${byteArray2hex(curContr.beaconHash)}`); - logger.info(`Beacon iterations Exp: ${curContr.numIterationsExp}`); - } - - } - - async function processSectionBetaG2(logger) { - const G = curve.G2; - const sG = G.F.n8*2; - const buffUv = new Uint8Array(sG); - - if (!sections[6]) { - logger.error("File has no BetaG2 section"); - throw new Error("File has no BetaG2 section"); - } - if (sections[6].length>1) { - logger.error("File has no BetaG2 section"); - throw new Error("File has more than one GetaG2 section"); - } - fd.pos = sections[6][0].p; - - const buff = await fd.read(sG); - const P = G.fromRprLEM(buff); - - G.toRprUncompressed(buffUv, 0, P); - nextContributionHasher.update(buffUv); - - return P; - } - - async function processSection(idSection, groupName, sectionName, nPoints, singularPointIndexes, logger) { - const MAX_CHUNK_SIZE = 1<<16; - const G = curve[groupName]; - const sG = G.F.n8*2; - await startReadUniqueSection$1(fd, sections, idSection); - - const singularPoints = []; - - let R1 = G.zero; - let R2 = G.zero; - - let lastBase = G.zero; - - for (let i=0; i0) { - const firstBase = G.fromRprLEM(bases, 0); - const r = readUInt32BE(getRandomBytes(4), 0); - - R1 = G.add(R1, G.timesScalar(lastBase, r)); - R2 = G.add(R2, G.timesScalar(firstBase, r)); - } - - const r1 = await G.multiExpAffine(bases.slice(0, (n-1)*sG), scalars); - const r2 = await G.multiExpAffine(bases.slice(sG), scalars); - - R1 = G.add(R1, r1); - R2 = G.add(R2, r2); - - lastBase = G.fromRprLEM( bases, (n-1)*sG); - - for (let j=0; j=i) && (sp < i+n)) { - const P = G.fromRprLEM(bases, (sp-i)*sG); - singularPoints.push(P); - } - } - - } - await endReadSection$1(fd); - - return { - R1: R1, - R2: R2, - singularPoints: singularPoints - }; - - } - - async function verifyLagrangeEvaluations(gName, tauSection, lagrangeSection, sectionName, logger) { - - if (logger) logger.debug(`Verifying phase2 calculated values ${sectionName}...`); - const G = curve[gName]; - const sG = G.F.n8*2; - - const seed= new Array(8); - for (let i=0; i<8; i++) { - seed[i] = readUInt32BE(getRandomBytes(4), 0); - } - - for (let p=0; p<= power; p ++) { - const res = await verifyPower(p); - if (!res) return false; - } - - if (tauSection == 2) { - const res = await verifyPower(power+1); - if (!res) return false; - } - - return true; - - async function verifyPower(p) { - if (logger) logger.debug(`Power ${p}...`); - const n8r = curve.Fr.n8; - const nPoints = 2 ** p; - let buff_r = new Uint32Array(nPoints); - let buffG; - - let rng = new ChaCha(seed); - - if (logger) logger.debug(`Creating random numbers Powers${p}...`); - for (let i=0; i. -*/ - -/* - This function creates a new section in the fdTo file with id idSection. - It multiplies the points in fdFrom by first, first*inc, first*inc^2, .... - nPoint Times. - It also updates the newChallengeHasher with the new points -*/ - -async function applyKeyToSection(fdOld, sections, fdNew, idSection, curve, groupName, first, inc, sectionName, logger) { - const MAX_CHUNK_SIZE = 1 << 16; - const G = curve[groupName]; - const sG = G.F.n8*2; - const nPoints = sections[idSection][0].size / sG; - - await startReadUniqueSection$1(fdOld, sections,idSection ); - await startWriteSection(fdNew, idSection); - - let t = first; - for (let i=0; i. -*/ - -async function challengeContribute(curve, challengeFilename, responseFileName, entropy, logger) { - const fdFrom = await readExisting$3(challengeFilename); - - - const sG1 = curve.F1.n64*8*2; - const sG2 = curve.F2.n64*8*2; - const domainSize = (fdFrom.totalSize + sG1 - 64 - sG2) / (4*sG1 + sG2); - let e = domainSize; - let power = 0; - while (e>1) { - e = e /2; - power += 1; - } - - if (2 ** power != domainSize) throw new Error("Invalid file size"); - if (logger) logger.debug("Power to tau size: "+power); - - const rng = await getRandomRng(entropy); - - const fdTo = await createOverride(responseFileName); - - // Calculate the hash - const challengeHasher = blake2b.create({ dkLen: 64 }); - for (let i=0; i { - logger.debug(k + ".g1_s: " + curve.G1.toString(key[k].g1_s, 16)); - logger.debug(k + ".g1_sx: " + curve.G1.toString(key[k].g1_sx, 16)); - logger.debug(k + ".g2_sp: " + curve.G2.toString(key[k].g2_sp, 16)); - logger.debug(k + ".g2_spx: " + curve.G2.toString(key[k].g2_spx, 16)); - logger.debug(""); - }); - } - - const responseHasher = blake2b.create({ dkLen: 64 }); - - await fdTo.write(challengeHash); - responseHasher.update(challengeHash); - - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", (2 ** power)*2-1, curve.Fr.one , key.tau.prvKey, "COMPRESSED", "tauG1" , logger ); - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G2", (2 ** power) , curve.Fr.one , key.tau.prvKey, "COMPRESSED", "tauG2" , logger ); - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", (2 ** power) , key.alpha.prvKey, key.tau.prvKey, "COMPRESSED", "alphaTauG1", logger ); - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", (2 ** power) , key.beta.prvKey , key.tau.prvKey, "COMPRESSED", "betaTauG1" , logger ); - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G2", 1 , key.beta.prvKey , key.tau.prvKey, "COMPRESSED", "betaTauG2" , logger ); - - // Write and hash key - const buffKey = new Uint8Array(curve.F1.n8*2*6+curve.F2.n8*2*3); - toPtauPubKeyRpr(buffKey, 0, curve, key, false); - await fdTo.write(buffKey); - responseHasher.update(buffKey); - const responseHash = responseHasher.digest(); - if (logger) logger.info(formatHash(responseHash, "Contribution Response Hash: ")); - - await fdTo.close(); - await fdFrom.close(); -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -async function beacon$1(oldPtauFilename, newPTauFilename, name, beaconHashStr,numIterationsExp, logger) { - const beaconHash = hex2ByteArray(beaconHashStr); - if ( (beaconHash.byteLength == 0) - || (beaconHash.byteLength*2 !=beaconHashStr.length)) - { - if (logger) logger.error("Invalid Beacon Hash. (It must be a valid hexadecimal sequence)"); - return false; - } - if (beaconHash.length>=256) { - if (logger) logger.error("Maximum length of beacon hash is 255 bytes"); - return false; - } - - numIterationsExp = parseInt(numIterationsExp); - if ((numIterationsExp<10)||(numIterationsExp>63)) { - if (logger) logger.error("Invalid numIterationsExp. (Must be between 10 and 63)"); - return false; - } - - - const {fd: fdOld, sections} = await readBinFile$1(oldPtauFilename, "ptau", 1); - const {curve, power, ceremonyPower} = await readPTauHeader(fdOld, sections); - if (power != ceremonyPower) { - if (logger) logger.error("This file has been reduced. You cannot contribute into a reduced file."); - return false; - } - if (sections[12]) { - if (logger) logger.warn("Contributing into a file that has phase2 calculated. You will have to prepare phase2 again."); - } - const contributions = await readContributions(fdOld, curve, sections); - const curContribution = { - name: name, - type: 1, // Beacon - numIterationsExp: numIterationsExp, - beaconHash: beaconHash - }; - - let lastChallengeHash; - - if (contributions.length>0) { - lastChallengeHash = contributions[contributions.length-1].nextChallenge; - } else { - lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); - } - - curContribution.key = await keyFromBeacon(curve, lastChallengeHash, beaconHash, numIterationsExp); - - const responseHasher = blake2b.create({ dkLen: 64 }); - responseHasher.update(lastChallengeHash); - - const fdNew = await createBinFile(newPTauFilename, "ptau", 1, 7); - await writePTauHeader(fdNew, curve, power); - - const startSections = []; - - let firstPoints; - firstPoints = await processSection(2, "G1", (2 ** power) * 2 -1, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG1", logger ); - curContribution.tauG1 = firstPoints[1]; - firstPoints = await processSection(3, "G2", (2 ** power) , curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG2", logger ); - curContribution.tauG2 = firstPoints[1]; - firstPoints = await processSection(4, "G1", (2 ** power) , curContribution.key.alpha.prvKey, curContribution.key.tau.prvKey, "alphaTauG1", logger ); - curContribution.alphaG1 = firstPoints[0]; - firstPoints = await processSection(5, "G1", (2 ** power) , curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG1", logger ); - curContribution.betaG1 = firstPoints[0]; - firstPoints = await processSection(6, "G2", 1, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG2", logger ); - curContribution.betaG2 = firstPoints[0]; - - curContribution.partialHash = toPartialHash(responseHasher); - - const buffKey = new Uint8Array(curve.F1.n8*2*6+curve.F2.n8*2*3); - - toPtauPubKeyRpr(buffKey, 0, curve, curContribution.key, false); - - responseHasher.update(new Uint8Array(buffKey)); - const hashResponse = responseHasher.digest(); - - if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); - - const nextChallengeHasher = blake2b.create({ dkLen: 64 }); - nextChallengeHasher.update(hashResponse); - - await hashSection(fdNew, "G1", 2, (2 ** power) * 2 -1, "tauG1", logger); - await hashSection(fdNew, "G2", 3, (2 ** power) , "tauG2", logger); - await hashSection(fdNew, "G1", 4, (2 ** power) , "alphaTauG1", logger); - await hashSection(fdNew, "G1", 5, (2 ** power) , "betaTauG1", logger); - await hashSection(fdNew, "G2", 6, 1 , "betaG2", logger); - - curContribution.nextChallenge = nextChallengeHasher.digest(); - - if (logger) logger.info(formatHash(curContribution.nextChallenge, "Next Challenge Hash: ")); - - contributions.push(curContribution); - - await writeContributions(fdNew, curve, contributions); - - await fdOld.close(); - await fdNew.close(); - - return hashResponse; - - async function processSection(sectionId, groupName, NPoints, first, inc, sectionName, logger) { - const res = []; - fdOld.pos = sections[sectionId][0].p; - - await startWriteSection(fdNew, sectionId); - - startSections[sectionId] = fdNew.pos; - - const G = curve[groupName]; - const sG = G.F.n8*2; - const chunkSize = Math.floor((1<<20) / sG); // 128Mb chunks - let t = first; - for (let i=0 ; i. -*/ - -async function contribute(oldPtauFilename, newPTauFilename, name, entropy, logger) { - - const {fd: fdOld, sections} = await readBinFile$1(oldPtauFilename, "ptau", 1); - const {curve, power, ceremonyPower} = await readPTauHeader(fdOld, sections); - if (power != ceremonyPower) { - if (logger) logger.error("This file has been reduced. You cannot contribute into a reduced file."); - throw new Error("This file has been reduced. You cannot contribute into a reduced file."); - } - if (sections[12]) { - if (logger) logger.warn("WARNING: Contributing into a file that has phase2 calculated. You will have to prepare phase2 again."); - } - const contributions = await readContributions(fdOld, curve, sections); - const curContribution = { - name: name, - type: 0, // Beacon - }; - - let lastChallengeHash; - - const rng = await getRandomRng(entropy); - - if (contributions.length>0) { - lastChallengeHash = contributions[contributions.length-1].nextChallenge; - } else { - lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); - } - - // Generate a random key - - - curContribution.key = createPTauKey(curve, lastChallengeHash, rng); - - - const responseHasher = blake2b.create({ dkLen: 64 }); - responseHasher.update(lastChallengeHash); - - const fdNew = await createBinFile(newPTauFilename, "ptau", 1, 7); - await writePTauHeader(fdNew, curve, power); - - const startSections = []; - - let firstPoints; - firstPoints = await processSection(2, "G1", (2 ** power) * 2 -1, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG1" ); - curContribution.tauG1 = firstPoints[1]; - firstPoints = await processSection(3, "G2", (2 ** power) , curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG2" ); - curContribution.tauG2 = firstPoints[1]; - firstPoints = await processSection(4, "G1", (2 ** power) , curContribution.key.alpha.prvKey, curContribution.key.tau.prvKey, "alphaTauG1" ); - curContribution.alphaG1 = firstPoints[0]; - firstPoints = await processSection(5, "G1", (2 ** power) , curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG1" ); - curContribution.betaG1 = firstPoints[0]; - firstPoints = await processSection(6, "G2", 1, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG2" ); - curContribution.betaG2 = firstPoints[0]; - - curContribution.partialHash = toPartialHash(responseHasher); - - const buffKey = new Uint8Array(curve.F1.n8*2*6+curve.F2.n8*2*3); - - toPtauPubKeyRpr(buffKey, 0, curve, curContribution.key, false); - - responseHasher.update(new Uint8Array(buffKey)); - const hashResponse = responseHasher.digest(); - - if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); - - const nextChallengeHasher = blake2b.create({ dkLen: 64 }); - nextChallengeHasher.update(hashResponse); - - await hashSection(fdNew, "G1", 2, (2 ** power) * 2 -1, "tauG1"); - await hashSection(fdNew, "G2", 3, (2 ** power) , "tauG2"); - await hashSection(fdNew, "G1", 4, (2 ** power) , "alphaTauG1"); - await hashSection(fdNew, "G1", 5, (2 ** power) , "betaTauG1"); - await hashSection(fdNew, "G2", 6, 1 , "betaG2"); - - curContribution.nextChallenge = nextChallengeHasher.digest(); - - if (logger) logger.info(formatHash(curContribution.nextChallenge, "Next Challenge Hash: ")); - - contributions.push(curContribution); - - await writeContributions(fdNew, curve, contributions); - - await fdOld.close(); - await fdNew.close(); - - return hashResponse; - - async function processSection(sectionId, groupName, NPoints, first, inc, sectionName) { - const res = []; - fdOld.pos = sections[sectionId][0].p; - - await startWriteSection(fdNew, sectionId); - - startSections[sectionId] = fdNew.pos; - - const G = curve[groupName]; - const sG = G.F.n8*2; - const chunkSize = Math.floor((1<<20) / sG); // 128Mb chunks - let t = first; - for (let i=0 ; i. -*/ - -async function preparePhase2(oldPtauFilename, newPTauFilename, logger) { - - const {fd: fdOld, sections} = await readBinFile$1(oldPtauFilename, "ptau", 1); - const {curve, power} = await readPTauHeader(fdOld, sections); - - const fdNew = await createBinFile(newPTauFilename, "ptau", 1, 11); - await writePTauHeader(fdNew, curve, power); - - await copySection(fdOld, sections, fdNew, 2); - await copySection(fdOld, sections, fdNew, 3); - await copySection(fdOld, sections, fdNew, 4); - await copySection(fdOld, sections, fdNew, 5); - await copySection(fdOld, sections, fdNew, 6); - await copySection(fdOld, sections, fdNew, 7); - - await processSection(2, 12, "G1", "tauG1" ); - await processSection(3, 13, "G2", "tauG2" ); - await processSection(4, 14, "G1", "alphaTauG1" ); - await processSection(5, 15, "G1", "betaTauG1" ); - - await fdOld.close(); - await fdNew.close(); - - // await fs.promises.unlink(newPTauFilename+ ".tmp"); - - return; - - async function processSection(oldSectionId, newSectionId, Gstr, sectionName) { - if (logger) logger.debug("Starting section: "+sectionName); - - await startWriteSection(fdNew, newSectionId); - - for (let p=0; p<=power; p++) { - await processSectionPower(p); - } - - if (oldSectionId == 2) { - await processSectionPower(power+1); - } - - await endWriteSection(fdNew); - - - async function processSectionPower(p) { - const nPoints = 2 ** p; - const G = curve[Gstr]; - const sGin = G.F.n8*2; - - let buff; - buff = new BigBuffer(nPoints*sGin); - - await startReadUniqueSection$1(fdOld, sections, oldSectionId); - if ((oldSectionId == 2)&&(p==power+1)) { - await fdOld.readToBuffer(buff, 0,(nPoints-1)*sGin ); - buff.set(curve.G1.zeroAffine, (nPoints-1)*sGin ); - } else { - await fdOld.readToBuffer(buff, 0,nPoints*sGin ); - } - await endReadSection$1(fdOld, true); - - - buff = await G.lagrangeEvaluations(buff, "affine", "affine", logger, sectionName); - await fdNew.write(buff); - -/* - if (p <= curve.Fr.s) { - buff = await G.ifft(buff, "affine", "affine", logger, sectionName); - await fdNew.write(buff); - } else if (p == curve.Fr.s+1) { - const smallM = 1<. -*/ - -async function truncate(ptauFilename, template, logger) { - - const {fd: fdOld, sections} = await readBinFile$1(ptauFilename, "ptau", 1); - const {curve, power, ceremonyPower} = await readPTauHeader(fdOld, sections); - - const sG1 = curve.G1.F.n8*2; - const sG2 = curve.G2.F.n8*2; - - for (let p=1; p. -*/ - -async function convert(oldPtauFilename, newPTauFilename, logger) { - - const {fd: fdOld, sections} = await readBinFile$1(oldPtauFilename, "ptau", 1); - const {curve, power} = await readPTauHeader(fdOld, sections); - - const fdNew = await createBinFile(newPTauFilename, "ptau", 1, 11); - await writePTauHeader(fdNew, curve, power); - - // const fdTmp = await fastFile.createOverride(newPTauFilename+ ".tmp"); - - await copySection(fdOld, sections, fdNew, 2); - await copySection(fdOld, sections, fdNew, 3); - await copySection(fdOld, sections, fdNew, 4); - await copySection(fdOld, sections, fdNew, 5); - await copySection(fdOld, sections, fdNew, 6); - await copySection(fdOld, sections, fdNew, 7); - - await processSection(2, 12, "G1", "tauG1" ); - await copySection(fdOld, sections, fdNew, 13); - await copySection(fdOld, sections, fdNew, 14); - await copySection(fdOld, sections, fdNew, 15); - - await fdOld.close(); - await fdNew.close(); - - // await fs.promises.unlink(newPTauFilename+ ".tmp"); - - return; - - async function processSection(oldSectionId, newSectionId, Gstr, sectionName) { - if (logger) logger.debug("Starting section: "+sectionName); - - await startWriteSection(fdNew, newSectionId); - - const size = sections[newSectionId][0].size; - const chunkSize = fdOld.pageSize; - await startReadUniqueSection$1(fdOld, sections, newSectionId); - for (let p=0; p. -*/ - -async function exportJson(pTauFilename, verbose) { - const {fd, sections} = await readBinFile$1(pTauFilename, "ptau", 1); - - const {curve, power} = await readPTauHeader(fd, sections); - - const pTau = {}; - pTau.q = curve.q; - pTau.power = power; - pTau.contributions = await readContributions(fd, curve, sections); - - pTau.tauG1 = await exportSection(2, "G1", (2 ** power)*2 -1, "tauG1"); - pTau.tauG2 = await exportSection(3, "G2", (2 ** power), "tauG2"); - pTau.alphaTauG1 = await exportSection(4, "G1", (2 ** power), "alphaTauG1"); - pTau.betaTauG1 = await exportSection(5, "G1", (2 ** power), "betaTauG1"); - pTau.betaG2 = await exportSection(6, "G2", 1, "betaG2"); - - pTau.lTauG1 = await exportLagrange(12, "G1", "lTauG1"); - pTau.lTauG2 = await exportLagrange(13, "G2", "lTauG2"); - pTau.lAlphaTauG1 = await exportLagrange(14, "G1", "lAlphaTauG2"); - pTau.lBetaTauG1 = await exportLagrange(15, "G1", "lBetaTauG2"); - - await fd.close(); - - return stringifyBigIntsWithField(curve.Fr, pTau); - - - - async function exportSection(sectionId, groupName, nPoints, sectionName) { - const G = curve[groupName]; - const sG = G.F.n8*2; - - const res = []; - await startReadUniqueSection$1(fd, sections, sectionId); - for (let i=0; i< nPoints; i++) { - if ((verbose)&&i&&(i%10000 == 0)) console.log(`${sectionName}: ` + i); - const buff = await fd.read(sG); - res.push(G.fromRprLEM(buff, 0)); - } - await endReadSection$1(fd); - - return res; - } - - async function exportLagrange(sectionId, groupName, sectionName) { - const G = curve[groupName]; - const sG = G.F.n8*2; - - const res = []; - await startReadUniqueSection$1(fd, sections, sectionId); - for (let p=0; p<=power; p++) { - if (verbose) console.log(`${sectionName}: Power: ${p}`); - res[p] = []; - const nPoints = (2 ** p); - for (let i=0; i. -*/ - -var powersoftau = /*#__PURE__*/Object.freeze({ - __proto__: null, - newAccumulator: newAccumulator, - exportChallenge: exportChallenge, - importResponse: importResponse, - verify: verify, - challengeContribute: challengeContribute, - beacon: beacon$1, - contribute: contribute, - preparePhase2: preparePhase2, - truncate: truncate, - convert: convert, - exportJson: exportJson +//#endregion +//#region src/r1cs_print.js +function jn(e, t, n) { + for (let t = 0; t < e.constraints.length; t++) r(e.constraints[t]); + function r(r) { + let i = (n) => { + let r = ""; + return Object.keys(n).forEach((i) => { + let a = t.varIdx2Name[i]; + a == "one" && (a = "1"); + let o = e.curve.Fr.toString(n[i]); + o == "1" && (o = ""), o == "-1" && (o = "-"), r != "" && o[0] != "-" && (o = "+" + o), r != "" && (o = " " + o), r = r + o + a; + }), r; + }, a = `[ ${i(r[0])} ] * [ ${i(r[1])} ] - [ ${i(r[2])} ] = 0`; + n && n.info(a); + } +} +//#endregion +//#region src/r1cs_info.js +var Mn = u.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16), Nn = u.e("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +async function Pn(e, t) { + let n = await m(e); + return u.eq(n.prime, Nn) ? t && t.info("Curve: bn-128") : u.eq(n.prime, Mn) ? t && t.info("Curve: bls12-381") : t && t.info(`Unknown Curve. Prime: ${u.toString(n.prime)}`), t && t.info(`# of Wires: ${n.nVars}`), t && t.info(`# of Constraints: ${n.nConstraints}`), t && t.info(`# of Private Inputs: ${n.nPrvInputs}`), t && t.info(`# of Public Inputs: ${n.nPubInputs}`), t && t.info(`# of Labels: ${n.nLabels}`), t && t.info(`# of Outputs: ${n.nOutputs}`), n; +} +//#endregion +//#region src/r1cs_export_json.js +async function Fn(e, t) { + let n = await m(e, !0, !0, !0, t), r = n.curve.Fr; + return delete n.curve, delete n.F, Ie(r, n); +} +//#endregion +//#region src/r1cs.js +var In = /* @__PURE__ */ y({ + exportJson: () => Fn, + info: () => Pn, + print: () => jn }); - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -function r1csPrint(r1cs, syms, logger) { - for (let i=0; i { - let S = ""; - const keys = Object.keys(lc); - keys.forEach( (k) => { - let name = syms.varIdx2Name[k]; - if (name == "one") name = "1"; - - let vs = r1cs.curve.Fr.toString(lc[k]); - if (vs == "1") vs = ""; // Do not show ones - if (vs == "-1") vs = "-"; // Do not show ones - if ((S!="")&&(vs[0]!="-")) vs = "+"+vs; - if (S!="") vs = " "+vs; - S= S + vs + name; - }); - return S; - }; - const S = `[ ${lc2str(c[0])} ] * [ ${lc2str(c[1])} ] - [ ${lc2str(c[2])} ] = 0`; - if (logger) logger.info(S); - } - -} - -const SUBARRAY_SIZE$1 = 0x40000; - -const BigArrayHandler$1 = { - get: function(obj, prop) { - if (!isNaN(prop)) { - return obj.getElement(prop); - } else return obj[prop]; - }, - set: function(obj, prop, value) { - if (!isNaN(prop)) { - return obj.setElement(prop, value); - } else { - obj[prop] = value; - return true; - } - } +//#endregion +//#region src/loadsyms.js +async function Ln(e) { + let t = { + labelIdx2Name: ["one"], + varIdx2Name: ["one"], + componentIdx2Name: [] + }, n = await jt(e), r = await n.read(n.totalSize), i = new TextDecoder("utf-8").decode(r).split("\n"); + for (let e = 0; e < i.length; e++) { + let n = i[e].split(","); + n.length == 4 && (t.varIdx2Name[n[1]] ? t.varIdx2Name[n[1]] += "|" + n[3] : t.varIdx2Name[n[1]] = n[3], t.labelIdx2Name[n[0]] = n[3], t.componentIdx2Name[n[2]] || (t.componentIdx2Name[n[2]] = a(n[3]))); + } + return await n.close(), t; + function a(e) { + let t = e.split("."); + return t.pop(), t.join("."); + } +} +//#endregion +//#region src/wtns_debug.js +var { unstringifyBigInts: Rn } = p; +async function zn(t, n, r, i, a, o) { + let s = Rn(t), c = await jt(n), l = await c.read(c.totalSize); + await c.close(); + let u = { + ...a, + sanityCheck: !0 + }, d = await Ln(i); + a.set && (d ||= await Ln(i), u.logSetSignal = function(e, t) { + o && o.info("SET " + d.labelIdx2Name[e] + " <-- " + t.toString()); + }), a.get && (d ||= await Ln(i), u.logGetSignal = function(e, t) { + o && o.info("GET " + d.labelIdx2Name[e] + " --> " + t.toString()); + }), a.trigger && (d ||= await Ln(i), u.logStartComponent = function(e) { + o && o.info("START: " + d.componentIdx2Name[e]); + }, u.logFinishComponent = function(e) { + o && o.info("FINISH: " + d.componentIdx2Name[e]); + }), u.sym = d; + let f = await It(l, u), p = await f.calculateWitness(s, !0), m = await e.createBinFile(r, "wtns", 2, 2); + await $e(m, p, f.prime), await m.close(); +} +//#endregion +//#region src/wtns_export_json.js +async function Bn(e) { + return await nt(e); +} +//#endregion +//#region src/wtns_check.js +async function Vn(t, n, r) { + r && r.info("WITNESS CHECKING STARTED"), r && r.info("> Reading r1cs file"); + let { fd: i, sections: a } = await e.readBinFile(t, "r1cs", 1, 1 << 22, 1 << 24), o = await h(i, a, { + loadConstraints: !1, + loadCustomGates: !1 + }); + r && r.info("> Reading witness file"); + let { fd: s, sections: c } = await e.readBinFile(n, "wtns", 2, 1 << 22, 1 << 24), l = await tt(s, c); + if (!u.eq(o.prime, l.q)) throw Error("Curve of the witness does not match the curve of the proving key"); + let d = await e.readSection(s, c, 2); + await s.close(); + let f = (await T(o.prime)).Fr, p = f.n8, m = await e.readSection(i, a, 2); + r && (r.info("----------------------------"), r.info(" WITNESS CHECK"), r.info(` Curve: ${o.curve.name}`), r.info(` Vars (wires): ${o.nVars}`), r.info(` Outputs: ${o.nOutputs}`), r.info(` Public Inputs: ${o.nPubInputs}`), r.info(` Private Inputs: ${o.nPrvInputs}`), r.info(` Labels: ${o.nLabels}`), r.info(` Constraints: ${o.nConstraints}`), r.info(` Custom Gates: ${o.useCustomGates}`), r.info("----------------------------")), r && r.info("> Checking witness correctness"); + let g = 0, _ = !0; + for (let e = 0; e < o.nConstraints; e++) { + r && e !== 0 && e % 5e5 == 0 && r.info(`··· processing r1cs constraints ${e}/${o.nConstraints}`); + let t = y(), n = y(), i = y(), a = v(t), s = v(n), c = v(i); + if (!f.eq(f.sub(f.mul(a, s), c), f.zero)) { + r.warn("··· aborting checking process at constraint " + e), _ = !1; + break; + } + } + return i.close(), r && (_ ? (r.info("WITNESS IS CORRECT"), r.info("WITNESS CHECKING FINISHED SUCCESSFULLY")) : (r.warn("WITNESS IS NOT CORRECT"), r.warn("WITNESS CHECKING FINISHED UNSUCCESSFULLY"))), _; + function v(e) { + let t = f.zero; + return Object.keys(e).forEach((n) => { + let r = b(n), i = e[n]; + t = f.add(t, f.mul(r, i)); + }), t; + } + function y() { + let e = {}, t = m.slice(g, g + 4); + g += 4; + let n = new DataView(t.buffer).getUint32(0, !0), r = m.slice(g, g + (4 + o.n8) * n); + g += (4 + o.n8) * n; + let i = new DataView(r.buffer); + for (let t = 0; t < n; t++) { + let n = i.getUint32(t * (4 + o.n8), !0); + e[n] = o.F.fromRprLE(r, t * (4 + o.n8) + 4); + } + return e; + } + function b(e) { + return f.fromRprLE(d.slice(e * p, e * p + p)); + } +} +//#endregion +//#region src/wtns.js +var Hn = /* @__PURE__ */ y({ + calculate: () => Bt, + check: () => Vn, + debug: () => zn, + exportJson: () => Bn +}), Un = 262144, Wn = { + get: function(e, t) { + return isNaN(t) ? e[t] : e.getElement(t); + }, + set: function(e, t, n) { + return isNaN(t) ? (e[t] = n, !0) : e.setElement(t, n); + } +}, Gn = class { + constructor(e) { + this.length = e || 0, this.arr = Array(Un); + for (let t = 0; t < e; t += Un) this.arr[t / Un] = Array(Math.min(Un, e - t)); + return this; + } + push() { + for (let e = 0; e < arguments.length; e++) this.setElement(this.length, arguments[e]); + } + slice(e, t) { + let n = Array(t - e); + for (let r = e; r < t; r++) n[r - e] = this.getElement(r); + return n; + } + getElement(e) { + e = parseInt(e); + let t = Math.floor(e / Un), n = e % Un; + return this.arr[t] ? this.arr[t][n] : void 0; + } + setElement(e, t) { + e = parseInt(e); + let n = Math.floor(e / Un); + this.arr[n] || (this.arr[n] = Array(Un)); + let r = e % Un; + return this.arr[n][r] = t, e >= this.length && (this.length = e + 1), !0; + } + getKeys() { + let e = new Kn(); + for (let t = 0; t < this.arr.length; t++) if (this.arr[t]) for (let n = 0; n < this.arr[t].length; n++) this.arr[t][n] !== void 0 && e.push(t * Un + n); + return e; + } +}, Kn = class { + constructor(e) { + let t = new Gn(e); + return new Proxy(t, Wn); + } }; - -class _BigArray$1 { - constructor (initSize) { - this.length = initSize || 0; - this.arr = new Array(SUBARRAY_SIZE$1); - - for (let i=0; i= this.length) this.length = idx+1; - return true; - } - getKeys() { - const newA = new BigArray$2(); - for (let i=0; i { - self.pendingLoads.push({ - page: p, - resolve: resolve, - reject: reject - }); - }); - self.__statusPage("After Load request: ", p); - return P; - } - - __statusPage(s, p) { - const logEntry = []; - const self=this; - if (!self.logHistory) return; - logEntry.push("==" + s+ " " +p); - let S = ""; - for (let i=0; i " + self.history[p][i][j]); - } - } - } - - - - _triggerLoad() { - const self = this; - - if (self.reading) return; - if (self.pendingLoads.length==0) return; - - const pageIdxs = Object.keys(self.pages); - - const deletablePages = []; - for (let i=0; i0) && - ( (typeof self.pages[self.pendingLoads[0].page] != "undefined" ) - ||( (freePages>0) - ||(deletablePages.length>0)))) { - const load = self.pendingLoads.shift(); - if (typeof self.pages[load.page] != "undefined") { - self.pages[load.page].pendingOps ++; - const idx = deletablePages.indexOf(load.page); - if (idx>=0) deletablePages.splice(idx, 1); - if (self.pages[load.page].loading) { - self.pages[load.page].loading.push(load); - } else { - load.resolve(); - } - self.__statusPage("After Load (cached): ", load.page); - - } else { - if (freePages) { - freePages--; - } else { - const fp = deletablePages.shift(); - self.__statusPage("Before Unload: ", fp); - self.avBuffs.unshift(self.pages[fp]); - delete self.pages[fp]; - self.__statusPage("After Unload: ", fp); - } - - if (load.page>=self.totalPages) { - self.pages[load.page] = getNewPage(); - load.resolve(); - self.__statusPage("After Load (new): ", load.page); - } else { - self.reading = true; - self.pages[load.page] = getNewPage(); - self.pages[load.page].loading = [load]; - ops.push(self.fd.read(self.pages[load.page].buff, 0, self.pageSize, load.page*self.pageSize).then((res)=> { - self.pages[load.page].size = res.bytesRead; - const loading = self.pages[load.page].loading; - delete self.pages[load.page].loading; - for (let i=0; i { - load.reject(err); - })); - self.__statusPage("After Load (loading): ", load.page); - } - } - } - // if (ops.length>1) console.log(ops.length); - - Promise.all(ops).then( () => { - self.reading = false; - if (self.pendingLoads.length>0) setImmediate(self._triggerLoad.bind(self)); - self._tryClose(); - }); - - function getNewPage() { - if (self.avBuffs.length>0) { - const p = self.avBuffs.shift(); - p.dirty = false; - p.pendingOps = 1; - p.size =0; - return p; - } else { - return { - dirty: false, - buff: new Uint8Array(self.pageSize), - pendingOps: 1, - size: 0 - }; - } - } - - } - - - _triggerWrite() { - const self = this; - if (self.writing) return; - - const pageIdxs = Object.keys(self.pages); - - const ops = []; - - for (let i=0; i { - page.writing = false; - return; - }, (err) => { - console.log("ERROR Writing: "+err); - self.error = err; - self._tryClose(); - })); - } - } - - if (self.writing) { - Promise.all(ops).then( () => { - self.writing = false; - setImmediate(self._triggerWrite.bind(self)); - self._tryClose(); - if (self.pendingLoads.length>0) setImmediate(self._triggerLoad.bind(self)); - }); - } - } - - _getDirtyPage() { - for (let p in this.pages) { - if (this.pages[p].dirty) return p; - } - return -1; - } - - async write(buff, pos) { - if (buff.byteLength == 0) return; - const self = this; -/* - if (buff.byteLength > self.pageSize*self.maxPagesLoaded*0.8) { - const cacheSize = Math.floor(buff.byteLength * 1.1); - this.maxPagesLoaded = Math.floor( cacheSize / self.pageSize)+1; - } -*/ - if (typeof pos == "undefined") pos = self.pos; - self.pos = pos+buff.byteLength; - if (self.totalSize < pos + buff.byteLength) self.totalSize = pos + buff.byteLength; - if (self.pendingClose) - throw new Error("Writing a closing file"); - const firstPage = Math.floor(pos / self.pageSize); - const lastPage = Math.floor((pos + buff.byteLength -1) / self.pageSize); - - const pagePromises = []; - for (let i=firstPage; i<=lastPage; i++) pagePromises.push(self._loadPage(i)); - self._triggerLoad(); - - let p = firstPage; - let o = pos % self.pageSize; - let r = buff.byteLength; - while (r>0) { - await pagePromises[p-firstPage]; - const l = (o+r > self.pageSize) ? (self.pageSize -o) : r; - const srcView = buff.slice( buff.byteLength - r, buff.byteLength - r + l); - const dstView = new Uint8Array(self.pages[p].buff.buffer, o, l); - dstView.set(srcView); - self.pages[p].dirty = true; - self.pages[p].pendingOps --; - self.pages[p].size = Math.max(o+l, self.pages[p].size); - if (p>=self.totalPages) { - self.totalPages = p+1; - } - r = r-l; - p ++; - o = 0; - if (!self.writing) setImmediate(self._triggerWrite.bind(self)); - } - } - - async read(len, pos) { - const self = this; - let buff = new Uint8Array(len); - await self.readToBuffer(buff, 0, len, pos); - - return buff; - } - - async readToBuffer(buffDst, offset, len, pos) { - if (len == 0) { - return; - } - const self = this; - if (len > self.pageSize*self.maxPagesLoaded*0.8) { - const cacheSize = Math.floor(len * 1.1); - this.maxPagesLoaded = Math.floor( cacheSize / self.pageSize)+1; - } - if (typeof pos == "undefined") pos = self.pos; - self.pos = pos+len; - if (self.pendingClose) - throw new Error("Reading a closing file"); - const firstPage = Math.floor(pos / self.pageSize); - const lastPage = Math.floor((pos + len -1) / self.pageSize); - - const pagePromises = []; - for (let i=firstPage; i<=lastPage; i++) pagePromises.push(self._loadPage(i)); - - self._triggerLoad(); - - let p = firstPage; - let o = pos % self.pageSize; - // Remaining bytes to read - let r = pos + len > self.totalSize ? len - (pos + len - self.totalSize): len; - while (r>0) { - await pagePromises[p - firstPage]; - self.__statusPage("After Await (read): ", p); - - // bytes to copy from this page - const l = (o+r > self.pageSize) ? (self.pageSize -o) : r; - const srcView = new Uint8Array(self.pages[p].buff.buffer, self.pages[p].buff.byteOffset + o, l); - buffDst.set(srcView, offset+len-r); - self.pages[p].pendingOps --; - - self.__statusPage("After Op done: ", p); - - r = r-l; - p ++; - o = 0; - if (self.pendingLoads.length>0) setImmediate(self._triggerLoad.bind(self)); - } - - this.pos = pos + len; - - } - - - _tryClose() { - const self = this; - if (!self.pendingClose) return; - if (self.error) { - self.pendingCloseReject(self.error); - } - const p = self._getDirtyPage(); - if ((p>=0) || (self.writing) || (self.reading) || (self.pendingLoads.length>0)) return; - self.pendingClose(); - } - - close() { - const self = this; - if (self.pendingClose) - throw new Error("Closing the file twice"); - return new Promise((resolve, reject) => { - self.pendingClose = resolve; - self.pendingCloseReject = reject; - self._tryClose(); - }).then(()=> { - self.fd.close(); - }, (err) => { - self.fd.close(); - throw (err); - }); - } - - async discard() { - const self = this; - await self.close(); - await fs.promises.unlink(this.fileName); - } - - async writeULE32(v, pos) { - const self = this; - const tmpBuff32 = new Uint8Array(4); - const tmpBuff32v = new DataView(tmpBuff32.buffer); - - tmpBuff32v.setUint32(0, v, true); - - await self.write(tmpBuff32, pos); - } - - async writeUBE32(v, pos) { - const self = this; - - const tmpBuff32 = new Uint8Array(4); - const tmpBuff32v = new DataView(tmpBuff32.buffer); - - tmpBuff32v.setUint32(0, v, false); - - await self.write(tmpBuff32, pos); - } - - - async writeULE64(v, pos) { - const self = this; - - const tmpBuff64 = new Uint8Array(8); - const tmpBuff64v = new DataView(tmpBuff64.buffer); - - tmpBuff64v.setUint32(0, v & 0xFFFFFFFF, true); - tmpBuff64v.setUint32(4, Math.floor(v / 0x100000000) , true); - - await self.write(tmpBuff64, pos); - } - - async readULE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new Uint32Array(b.buffer); - - return view[0]; - } - - async readUBE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new DataView(b.buffer); - - return view.getUint32(0, false); - } - - async readULE64(pos) { - const self = this; - const b = await self.read(8, pos); - - const view = new Uint32Array(b.buffer); - - return view[1] * 0x100000000 + view[0]; - } - - async readString(pos) { - const self = this; - - if (self.pendingClose) { - throw new Error("Reading a closing file"); - } - - let currentPosition = typeof pos == "undefined" ? self.pos : pos; - let currentPage = Math.floor(currentPosition / self.pageSize); - - let endOfStringFound = false; - let str = ""; - - while (!endOfStringFound) { - //Read page - let pagePromise = self._loadPage(currentPage); - self._triggerLoad(); - await pagePromise; - self.__statusPage("After Await (read): ", currentPage); - - let offsetOnPage = currentPosition % self.pageSize; - - const dataArray = new Uint8Array( - self.pages[currentPage].buff.buffer, - self.pages[currentPage].buff.byteOffset + offsetOnPage, - self.pageSize - offsetOnPage - ); - - let indexEndOfString = dataArray.findIndex(element => element === 0); - endOfStringFound = indexEndOfString !== -1; - - if (endOfStringFound) { - str += new TextDecoder().decode(dataArray.slice(0, indexEndOfString)); - self.pos = currentPage * this.pageSize + offsetOnPage + indexEndOfString + 1; - } else { - str += new TextDecoder().decode(dataArray); - self.pos = currentPage * this.pageSize + offsetOnPage + dataArray.length; - } - - self.pages[currentPage].pendingOps--; - self.__statusPage("After Op done: ", currentPage); - - currentPosition = self.pos; - currentPage++; - - if (self.pendingLoads.length > 0) setImmediate(self._triggerLoad.bind(self)); - } - - return str; - } -} - -function readExisting$2(o) { - const fd = new MemFile(); - fd.o = o; - fd.allocSize = o.data.byteLength; - fd.totalSize = o.data.byteLength; - fd.readOnly = true; - fd.pos = 0; - return fd; -} - -const tmpBuff32$1 = new Uint8Array(4); -const tmpBuff32v$1 = new DataView(tmpBuff32$1.buffer); -const tmpBuff64$1 = new Uint8Array(8); -const tmpBuff64v$1 = new DataView(tmpBuff64$1.buffer); - -class MemFile { - - constructor() { - this.pageSize = 1 << 14; // for compatibility - } - - _resizeIfNeeded(newLen) { - if (newLen > this.allocSize) { - const newAllocSize = Math.max( - this.allocSize + (1 << 20), - Math.floor(this.allocSize * 1.1), - newLen - ); - const newData = new Uint8Array(newAllocSize); - newData.set(this.o.data); - this.o.data = newData; - this.allocSize = newAllocSize; - } - } - - async write(buff, pos) { - const self =this; - if (typeof pos == "undefined") pos = self.pos; - if (this.readOnly) throw new Error("Writing a read only file"); - - this._resizeIfNeeded(pos + buff.byteLength); - - this.o.data.set(buff.slice(), pos); - - if (pos + buff.byteLength > this.totalSize) this.totalSize = pos + buff.byteLength; - - this.pos = pos + buff.byteLength; - } - - async readToBuffer(buffDest, offset, len, pos) { - const self = this; - if (typeof pos == "undefined") pos = self.pos; - if (this.readOnly) { - if (pos + len > this.totalSize) throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos + len); - - const buffSrc = new Uint8Array(this.o.data.buffer, this.o.data.byteOffset + pos, len); - - buffDest.set(buffSrc, offset); - - this.pos = pos + len; - } - - async read(len, pos) { - const self = this; - - const buff = new Uint8Array(len); - await self.readToBuffer(buff, 0, len, pos); - - return buff; - } - - close() { - if (this.o.data.byteLength != this.totalSize) { - this.o.data = this.o.data.slice(0, this.totalSize); - } - } - - async discard() { - } - - - async writeULE32(v, pos) { - const self = this; - - tmpBuff32v$1.setUint32(0, v, true); - - await self.write(tmpBuff32$1, pos); - } - - async writeUBE32(v, pos) { - const self = this; - - tmpBuff32v$1.setUint32(0, v, false); - - await self.write(tmpBuff32$1, pos); - } - - - async writeULE64(v, pos) { - const self = this; - - tmpBuff64v$1.setUint32(0, v & 0xFFFFFFFF, true); - tmpBuff64v$1.setUint32(4, Math.floor(v / 0x100000000) , true); - - await self.write(tmpBuff64$1, pos); - } - - - async readULE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new Uint32Array(b.buffer); - - return view[0]; - } - - async readUBE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new DataView(b.buffer); - - return view.getUint32(0, false); - } - - async readULE64(pos) { - const self = this; - const b = await self.read(8, pos); - - const view = new Uint32Array(b.buffer); - - return view[1] * 0x100000000 + view[0]; - } - - async readString(pos) { - const self = this; - - let currentPosition = typeof pos == "undefined" ? self.pos : pos; - - if (currentPosition > this.totalSize) { - if (this.readOnly) { - throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos); - } - const dataArray = new Uint8Array( - self.o.data.buffer, - currentPosition, - this.totalSize - currentPosition - ); - - let indexEndOfString = dataArray.findIndex(element => element === 0); - let endOfStringFound = indexEndOfString !== -1; - - let str = ""; - if (endOfStringFound) { - str = new TextDecoder().decode(dataArray.slice(0, indexEndOfString)); - self.pos = currentPosition + indexEndOfString + 1; - } else { - self.pos = currentPosition; - } - return str; - } -} - -const PAGE_SIZE = 1<<22; - -function readExisting$1(o) { - const fd = new BigMemFile(); - fd.o = o; - fd.totalSize = (o.data.length-1)* PAGE_SIZE + o.data[o.data.length-1].byteLength; - fd.readOnly = true; - fd.pos = 0; - return fd; -} - -const tmpBuff32 = new Uint8Array(4); -const tmpBuff32v = new DataView(tmpBuff32.buffer); -const tmpBuff64 = new Uint8Array(8); -const tmpBuff64v = new DataView(tmpBuff64.buffer); - -class BigMemFile { - - constructor() { - this.pageSize = 1 << 14; // for compatibility - } - - _resizeIfNeeded(newLen) { - - if (newLen <= this.totalSize) return; - - if (this.readOnly) throw new Error("Reading out of file bounds"); - - const nPages = Math.floor((newLen - 1) / PAGE_SIZE)+1; - for (let i= Math.max(this.o.data.length-1, 0); i0) { - const l = (o+r > PAGE_SIZE) ? (PAGE_SIZE -o) : r; - const srcView = buff.slice(buff.byteLength - r, buff.byteLength - r + l); - const dstView = new Uint8Array(self.o.data[p].buffer, o, l); - dstView.set(srcView); - r = r-l; - p ++; - o = 0; - } - - this.pos = pos + buff.byteLength; - } - - async readToBuffer(buffDst, offset, len, pos) { - const self = this; - if (typeof pos == "undefined") pos = self.pos; - if (this.readOnly) { - if (pos + len > this.totalSize) throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos + len); - - const firstPage = Math.floor(pos / PAGE_SIZE); - - let p = firstPage; - let o = pos % PAGE_SIZE; - // Remaining bytes to read - let r = len; - while (r>0) { - // bytes to copy from this page - const l = (o+r > PAGE_SIZE) ? (PAGE_SIZE -o) : r; - const srcView = new Uint8Array(self.o.data[p].buffer, o, l); - buffDst.set(srcView, offset+len-r); - r = r-l; - p ++; - o = 0; - } - - this.pos = pos + len; - } - - async read(len, pos) { - const self = this; - const buff = new Uint8Array(len); - - await self.readToBuffer(buff, 0, len, pos); - - return buff; - } - - close() { - } - - async discard() { - } - - - async writeULE32(v, pos) { - const self = this; - - tmpBuff32v.setUint32(0, v, true); - - await self.write(tmpBuff32, pos); - } - - async writeUBE32(v, pos) { - const self = this; - - tmpBuff32v.setUint32(0, v, false); - - await self.write(tmpBuff32, pos); - } - - - async writeULE64(v, pos) { - const self = this; - - tmpBuff64v.setUint32(0, v & 0xFFFFFFFF, true); - tmpBuff64v.setUint32(4, Math.floor(v / 0x100000000) , true); - - await self.write(tmpBuff64, pos); - } - - - async readULE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new Uint32Array(b.buffer); - - return view[0]; - } - - async readUBE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new DataView(b.buffer); - - return view.getUint32(0, false); - } - - async readULE64(pos) { - const self = this; - const b = await self.read(8, pos); - - const view = new Uint32Array(b.buffer); - - return view[1] * 0x100000000 + view[0]; - } - - async readString(pos) { - const self = this; - const fixedSize = 2048; - - let currentPosition = typeof pos == "undefined" ? self.pos : pos; - - if (currentPosition > this.totalSize) { - if (this.readOnly) { - throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos); - } - - let endOfStringFound = false; - let str = ""; - - while (!endOfStringFound) { - let currentPage = Math.floor(currentPosition / PAGE_SIZE); - let offsetOnPage = currentPosition % PAGE_SIZE; - - if (self.o.data[currentPage] === undefined) { - throw new Error("ERROR"); - } - - let readLength = Math.min(fixedSize, self.o.data[currentPage].length - offsetOnPage); - const dataArray = new Uint8Array(self.o.data[currentPage].buffer, offsetOnPage, readLength); - - let indexEndOfString = dataArray.findIndex(element => element === 0); - endOfStringFound = indexEndOfString !== -1; - - if (endOfStringFound) { - str += new TextDecoder().decode(dataArray.slice(0, indexEndOfString)); - self.pos = currentPage * PAGE_SIZE + offsetOnPage + indexEndOfString + 1; - } else { - str += new TextDecoder().decode(dataArray); - self.pos = currentPage * PAGE_SIZE + offsetOnPage + dataArray.length; - } - - currentPosition = self.pos; - } - return str; - } -} - -/* global fetch */ - -async function readExisting(o, b, c) { - if (o instanceof Uint8Array) { - o = { - type: "mem", - data: o - }; - } - { - if (typeof o === "string") { - const buff = await fetch(o).then( function(res) { - return res.arrayBuffer(); - }).then(function (ab) { - return new Uint8Array(ab); - }); - o = { - type: "mem", - data: buff - }; - } - } - if (o.type == "file") { - return await open(o.fileName, O_RDONLY, o.cacheSize, o.pageSize); - } else if (o.type == "mem") { - return await readExisting$2(o); - } else if (o.type == "bigMem") { - return await readExisting$1(o); - } else { - throw new Error("Invalid FastFile type: "+o.type); - } -} - -async function readBinFile(fileName, type, maxVersion, cacheSize, pageSize) { - - const fd = await readExisting(fileName); - - const b = await fd.read(4); - let readedType = ""; - for (let i=0; i<4; i++) readedType += String.fromCharCode(b[i]); - - if (readedType != type) throw new Error(fileName + ": Invalid File format"); - - let v = await fd.readULE32(); - - if (v>maxVersion) throw new Error("Version not supported"); - - const nSections = await fd.readULE32(); - - // Scan sections - let sections = []; - for (let i=0; i1) throw new Error(fd.fileName +": Section Duplicated " +idSection); - - fd.pos = sections[idSection][0].p; - - fd.readingSection = sections[idSection][0]; -} - -async function endReadSection(fd, noCheck) { - if (typeof fd.readingSection === "undefined") throw new Error("Not reading a section"); - if (!noCheck) { - if (fd.pos-fd.readingSection.p != fd.readingSection.size) throw new Error("Invalid section size reading"); - } - delete fd.readingSection; -} - -async function readBigInt(fd, n8, pos) { - const buff = await fd.read(n8, pos); - return Scalar.fromRprLE(buff, 0, n8); -} - -async function readSection(fd, sections, idSection, offset, length) { - - offset = (typeof offset === "undefined") ? 0 : offset; - length = (typeof length === "undefined") ? sections[idSection][0].size - offset : length; - - if (offset + length > sections[idSection][0].size) { - throw new Error("Reading out of the range of the section"); - } - - let buff; - if (length < (1 << 30) ) { - buff = new Uint8Array(length); - } else { - buff = new BigBuffer(length); - } - - await fd.readToBuffer(buff, 0, length, sections[idSection][0].p + offset); - return buff; -} - -const R1CS_FILE_CUSTOM_GATES_LIST_SECTION = 4; -const R1CS_FILE_CUSTOM_GATES_USES_SECTION = 5; - -async function readR1csHeader(fd,sections,singleThread) { - let options; - if (typeof singleThread === "object") { - options = singleThread; - } else if (typeof singleThread === "undefined") { - options= { - singleThread: false, - }; - } else { - options = { - singleThread: singleThread, - }; - } - - const res = {}; - await startReadUniqueSection(fd, sections, 1); - // Read Header - res.n8 = await fd.readULE32(); - res.prime = await readBigInt(fd, res.n8); - - if (options.F) { - if (options.F.p != res.prime) throw new Error("Different Prime"); - res.F = options.F; - } else if (options.getFieldFromPrime) { - res.F = await options.getFieldFromPrime(res.prime, options.singleThread); - } else if (options.getCurveFromPrime) { - res.curve = await options.getCurveFromPrime(res.prime, options.singleThread); - res.F = res.curve.Fr; - } else { - try { - res.curve = await getCurveFromR$1(res.prime, options.singleThread); - res.F = res.curve.Fr; - } catch (err) { - res.F = new F1Field(res.prime); - } - } - - res.nVars = await fd.readULE32(); - res.nOutputs = await fd.readULE32(); - res.nPubInputs = await fd.readULE32(); - res.nPrvInputs = await fd.readULE32(); - res.nLabels = await fd.readULE64(); - res.nConstraints = await fd.readULE32(); - res.useCustomGates = typeof sections[R1CS_FILE_CUSTOM_GATES_LIST_SECTION] !== "undefined" && sections[R1CS_FILE_CUSTOM_GATES_LIST_SECTION] !== null - && typeof sections[R1CS_FILE_CUSTOM_GATES_USES_SECTION] !== "undefined" && sections[R1CS_FILE_CUSTOM_GATES_USES_SECTION] !== null; - - await endReadSection(fd); - - return res; -} - -async function readConstraints(fd,sections, r1cs, logger, loggerCtx) { - let options; - if (typeof logger === "object") { - options = logger; - } else if (typeof logger === "undefined") { - options= {}; - } else { - options = { - logger: logger, - loggerCtx: loggerCtx, - }; - } - - const bR1cs = await readSection(fd, sections, 2); - let bR1csPos = 0; - let constraints; - if (r1cs.nConstraints>1<<20) { - constraints = new BigArray$3(); - } else { - constraints = []; - } - for (let i=0; i1<<20) { - map = new BigArray$3(); - } else { - map = []; - } - for (let i=0; i true by default - * loadMap: false by default - * loadCustomGates: true by default - */ - - if(typeof options !== "object") { - throw new Error("readR1csFd: options must be an object"); - } - - options.loadConstraints = "loadConstraints" in options ? options.loadConstraints : true; - options.loadMap = "loadMap" in options ? options.loadMap : false; - options.loadCustomGates = "loadCustomGates" in options ? options.loadCustomGates : true; - - const res = await readR1csHeader(fd, sections, options); - - if (options.loadConstraints) { - res.constraints = await readConstraints(fd, sections, res, options); - } - - // Read Labels - - if (options.loadMap) { - res.map = await readMap(fd, sections, res, options); - } - - if (options.loadCustomGates) { - if (res.useCustomGates) { - res.customGates = await readCustomGatesListSection(fd, sections, res); - res.customGatesUses = await readCustomGatesUsesSection(fd, sections, options); - } else { - res.customGates = []; - res.customGatesUses = []; - } - } - return res; -} - -async function readR1cs(fileName, loadConstraints, loadMap, singleThread, logger, loggerCtx) { - let options; - if (typeof loadConstraints === "object") { - options = loadConstraints; - } else if (typeof loadConstraints === "undefined") { - options= { - loadConstraints: true, - loadMap: false, - loadCustomGates: true - }; - } else { - options = { - loadConstraints: loadConstraints, - loadMap: loadMap, - singleThread: singleThread, - logger: logger, - loggerCtx: loggerCtx - }; - } - - const {fd, sections} = await readBinFile(fileName, "r1cs", 1); - - const res = await readR1csFd(fd, sections, options); - - await fd.close(); - - return res; -} - -async function readCustomGatesListSection(fd, sections, res) { - await startReadUniqueSection(fd, sections, R1CS_FILE_CUSTOM_GATES_LIST_SECTION); - - let num = await fd.readULE32(); - - let customGates = []; - for (let i = 0; i < num; i++) { - let customGate = {}; - customGate.templateName = await fd.readString(); - let numParameters = await fd.readULE32(); - - customGate.parameters = Array(numParameters); - let buff = await fd.read(res.n8 * numParameters); - - for (let j = 0; j < numParameters; j++) { - customGate.parameters[j] = res.F.fromRprLE(buff, j * res.n8, res.n8); } - customGates.push(customGate); - } - await endReadSection(fd); - - return customGates; -} - -async function readCustomGatesUsesSection(fd,sections, options) { - const bR1cs = await readSection(fd, sections, R1CS_FILE_CUSTOM_GATES_USES_SECTION); - const bR1cs32 = new Uint32Array(bR1cs.buffer, bR1cs.byteOffset, bR1cs.byteLength/4); - const nCustomGateUses = bR1cs32[0]; - let bR1csPos = 1; - let customGatesUses; - if (nCustomGateUses>1<<20) { - customGatesUses = new BigArray$3(); - } else { - customGatesUses = []; - } - for (let i=0; i. -*/ - -const bls12381r = Scalar.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16); -const bn128r = Scalar.e("21888242871839275222246405745257275088548364400416034343698204186575808495617"); - -async function r1csInfo(r1csName, logger) { - - const cir = await readR1cs(r1csName); - - if (Scalar.eq(cir.prime, bn128r)) { - if (logger) logger.info("Curve: bn-128"); - } else if (Scalar.eq(cir.prime, bls12381r)) { - if (logger) logger.info("Curve: bls12-381"); - } else { - if (logger) logger.info(`Unknown Curve. Prime: ${Scalar.toString(cir.prime)}`); - } - if (logger) logger.info(`# of Wires: ${cir.nVars}`); - if (logger) logger.info(`# of Constraints: ${cir.nConstraints}`); - if (logger) logger.info(`# of Private Inputs: ${cir.nPrvInputs}`); - if (logger) logger.info(`# of Public Inputs: ${cir.nPubInputs}`); - if (logger) logger.info(`# of Labels: ${cir.nLabels}`); - if (logger) logger.info(`# of Outputs: ${cir.nOutputs}`); - - return cir; -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - - -async function r1csExportJson(r1csFileName, logger) { - - const cir = await readR1cs(r1csFileName, true, true, true, logger); - const Fr=cir.curve.Fr; - delete cir.curve; - delete cir.F; - - return stringifyBigIntsWithField(Fr, cir); -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -var r1cs = /*#__PURE__*/Object.freeze({ - __proto__: null, - print: r1csPrint, - info: r1csInfo, - exportJson: r1csExportJson +//#endregion +//#region src/zkey_new.js +async function qn(e, c, l, d) { + let f = K.create({ dkLen: 64 }), { fd: p, sections: m } = await r(c, "ptau", 1, 1 << 22, 1 << 24), { curve: h, power: _ } = await rn(p, m), { fd: v, sections: y } = await r(e, "r1cs", 1, 1 << 22, 1 << 24), b = await g(v, y, !1), x = await t(l, "zkey", 1, 10, 1 << 22, 1 << 24), S = h.G1.F.n8 * 2, C = h.G2.F.n8 * 2; + if (b.prime != h.r) return d && d.error("r1cs curve does not match powers of tau ceremony curve"), -1; + let w = Se(b.nConstraints + b.nPubInputs + b.nOutputs + 1 - 1) + 1; + if (w > _) return d && d.error(`circuit too big for this power of tau ceremony. ${b.nConstraints}*2 > 2**${_}`), -1; + if (!m[12]) return d && d.error("Powers of tau is not prepared."), -1; + let T = b.nOutputs + b.nPubInputs, E = 2 ** w; + await a(x, 1), await x.writeULE32(1), await n(x), await a(x, 2); + let D = h.q, O = (Math.floor((u.bitLength(D) - 1) / 64) + 1) * 8, k = h.r, A = (Math.floor((u.bitLength(k) - 1) / 64) + 1) * 8, j = u.mod(u.shl(1, A * 8), k), M = h.Fr.e(u.mod(u.mul(j, j), k)); + await x.writeULE32(O), await o(x, D, O), await x.writeULE32(A), await o(x, k, A), await x.writeULE32(b.nVars), await x.writeULE32(T), await x.writeULE32(E); + let N; + N = await p.read(S, m[4][0].p), await x.write(N), N = await h.G1.batchLEMtoU(N), f.update(N); + let P; + P = await p.read(S, m[5][0].p), await x.write(P), P = await h.G1.batchLEMtoU(P), f.update(P); + let F; + F = await p.read(C, m[6][0].p), await x.write(F), F = await h.G2.batchLEMtoU(F), f.update(F); + let I = new Uint8Array(S); + h.G1.toRprLEM(I, 0, h.G1.g); + let L = new Uint8Array(C); + h.G2.toRprLEM(L, 0, h.G2.g); + let ee = new Uint8Array(S); + h.G1.toRprUncompressed(ee, 0, h.G1.g); + let R = new Uint8Array(C); + h.G2.toRprUncompressed(R, 0, h.G2.g), await x.write(L), await x.write(I), await x.write(L), f.update(R), f.update(ee), f.update(R), await n(x), d && d.info(W()), d && d.info("Reading r1cs"); + let z = await i(v, y, 2); + await v.close(); + let B = new Kn(b.nVars), V = new Kn(b.nVars), te = new Kn(b.nVars), H = new Kn(b.nVars - T - 1), U = Array(T + 1); + d && d.info(W()), d && d.info("Reading tauG1"); + let ne = await i(p, m, 12, (E - 1) * S, E * S); + d && d.info("Reading tauG2"); + let re = await i(p, m, 13, (E - 1) * C, E * C); + d && d.info("Reading alphatauG1"); + let ie = await i(p, m, 14, (E - 1) * S, E * S); + d && d.info("Reading betatauG1"); + let ae = await i(p, m, 15, (E - 1) * S, E * S); + d && d.info(W()), d && d.info("processConstraints"), await ce(), d && d.info(W()), d && d.info("composeAndWritePoints"), await le(3, "G1", U, "IC"), U = null, d && d.info(W()), d && d.info("writeHs"), await se(), d && d.info(W()), d && d.info("hashHPoints"), await de(), d && d.info(W()), d && d.info("composeAndWritePoints 8 G1 C"), await le(8, "G1", H, "C"), H = null, d && d.info(W()), d && d.info("composeAndWritePoints 5 G1 A"), await le(5, "G1", B, "A"), B = null, d && d.info(W()), d && d.info("composeAndWritePoints 6 G1 B1"), await le(6, "G1", V, "B1"), V = null, d && d.info(W()), d && d.info("composeAndWritePoints 7 G2 B2"), await le(7, "G2", te, "B2"), te = null, d && d.info(W()), d && d.info("Contributions section"); + let oe = f.digest(); + return await a(x, 10), await x.write(oe), await x.writeULE32(0), await n(x), d && d.info(q(oe, "Circuit hash: ")), await x.close(), await p.close(), oe; + async function se() { + await a(x, 9); + let e = new s(E * S); + if (w < h.Fr.s) { + let t = await i(p, m, 12, (E * 2 - 1) * S, E * 2 * S); + for (let n = 0; n < E; n++) { + d && n % 1e4 == 0 && d.debug(`splitting buffer: ${n}/${E}`); + let r = t.slice((n * 2 + 1) * S, (n * 2 + 1) * S + S); + e.set(r, n * S); + } + } else if (w == h.Fr.s) { + let t = m[12][0].p + (2 ** (w + 1) - 1) * S; + await p.readToBuffer(e, 0, E * S, t + E * S); + } else throw d && d.error("Circuit too big"), Error("Circuit too big for this curve"); + await x.write(e), await n(x); + } + async function ce() { + let e = new Uint8Array(12 + h.Fr.n8), t = new DataView(e.buffer), r = new Uint8Array(h.Fr.n8); + h.Fr.toRprLE(r, 0, h.Fr.e(1)); + let i = 0; + function o() { + let e = z.slice(i, i + 4); + return i += 4, new DataView(e.buffer).getUint32(0, !0); + } + let c = new Kn(); + for (let e = 0; e < b.nConstraints; e++) { + d && e % 1e4 == 0 && d.debug(`processing constraints: ${e}/${b.nConstraints}`); + let t = o(); + for (let n = 0; n < t; n++) { + let t = o(), n = i; + i += h.Fr.n8; + let r = S * e, a = S * e; + B[t] === void 0 && (B[t] = []), B[t].push([ + 0, + r, + n + ]), t <= T ? (U[t] === void 0 && (U[t] = []), U[t].push([ + 3, + a, + n + ])) : (H[t - T - 1] === void 0 && (H[t - T - 1] = []), H[t - T - 1].push([ + 3, + a, + n + ])), c.push([ + 0, + e, + t, + n + ]); + } + let n = o(); + for (let t = 0; t < n; t++) { + let t = o(), n = i; + i += h.Fr.n8; + let r = S * e, a = C * e, s = S * e; + V[t] === void 0 && (V[t] = []), V[t].push([ + 0, + r, + n + ]), te[t] === void 0 && (te[t] = []), te[t].push([ + 1, + a, + n + ]), t <= T ? (U[t] === void 0 && (U[t] = []), U[t].push([ + 2, + s, + n + ])) : (H[t - T - 1] === void 0 && (H[t - T - 1] = []), H[t - T - 1].push([ + 2, + s, + n + ])), c.push([ + 1, + e, + t, + n + ]); + } + let r = o(); + for (let t = 0; t < r; t++) { + let t = o(), n = i; + i += h.Fr.n8; + let r = S * e; + t <= T ? (U[t] === void 0 && (U[t] = []), U[t].push([ + 0, + r, + n + ])) : (H[t - T - 1] === void 0 && (H[t - T - 1] = []), H[t - T - 1].push([ + 0, + r, + n + ])); + } + } + for (let e = 0; e <= T; e++) { + let t = S * (b.nConstraints + e), n = S * (b.nConstraints + e); + B[e] === void 0 && (B[e] = []), B[e].push([ + 0, + t, + -1 + ]), U[e] === void 0 && (U[e] = []), U[e].push([ + 3, + n, + -1 + ]), c.push([ + 0, + b.nConstraints + e, + e, + -1 + ]); + } + await a(x, 4); + let l = new s(c.length * (12 + h.Fr.n8) + 4), u = new Uint8Array(4); + new DataView(u.buffer).setUint32(0, c.length, !0), l.set(u); + let f = 4; + for (let e = 0; e < c.length; e++) d && e % 1e5 == 0 && d.debug(`writing coeffs: ${e}/${c.length}`), p(c[e]); + await x.write(l), await n(x); + function p(n) { + t.setUint32(0, n[0], !0), t.setUint32(4, n[1], !0), t.setUint32(8, n[2], !0); + let i; + i = n[3] >= 0 ? h.Fr.fromRprLE(z.slice(n[3], n[3] + h.Fr.n8), 0) : h.Fr.fromRprLE(r, 0); + let a = h.Fr.mul(i, M); + h.Fr.toRprLE(e, 12, a), l.set(e, f), f += e.length; + } + } + async function le(e, t, r, i) { + let o = 32768, s = h[t]; + me(r.length), await a(x, e); + let c = [], l = 0; + for (; l < r.length;) { + let e = 0; + for (; l < r.length && e < h.tm.concurrency;) { + d && d.debug(`Writing points start ${i}: ${l}/${r.length}`); + let n = 1, a = r[l] ? r[l].length : 0; + for (; l + n < r.length && a + (r[l + n] ? r[l + n].length : 0) < o && n < o;) a += r[l + n] ? r[l + n].length : 0, n++; + d && d.info("before slice:"), d && d.info(W()); + let s = r.slice(l, l + n); + d && d.info("after slice:"), d && d.info(W()); + let u = l; + c.push(ue(t, s, d, i).then((e) => (d && d.debug(`Writing points end ${i}: ${u}/${r.length}`), e))), l += n, e++; + } + let n = await Promise.all(c); + for (let e = 0; e < n.length; e++) { + await x.write(n[e][0]); + let t = await s.batchLEMtoU(n[e][0]); + f.update(t); + } + c = []; + } + await n(x); + } + async function ue(e, t, n, r) { + let i = h[e], a = i.F.n8 * 2, o = i.F.n8 * 3, c = i.F.n8 * 2, l, u, d, f; + if (e == "G1") l = "g1m_timesScalarAffine", u = "g1m_multiexpAffine", d = "g1m_batchToAffine", f = "g1m_zero"; + else if (e == "G2") l = "g2m_timesScalarAffine", u = "g2m_multiexpAffine", d = "g2m_batchToAffine", f = "g2m_zero"; + else throw Error("Invalid group"); + let p = 0; + for (let e = 0; e < t.length; e++) p += t[e] ? t[e].length : 0; + let m, g; + p > 32768 ? (m = new s(p * a), g = new s(p * h.Fr.n8)) : (m = new Uint8Array(p * a), g = new Uint8Array(p * h.Fr.n8)); + let _, v, y = [ + ne, + re, + ie, + ae + ], b = new Uint8Array(h.Fr.n8); + h.Fr.toRprLE(b, 0, h.Fr.e(1)); + let x = 0; + for (let e = 0; e < t.length; e++) if (t[e]) for (let i = 0; i < t[e].length; i++) n && i && i % 1e4 == 0 && n.debug(`Configuring big array ${r}: ${i}/${t[e].length}`), m.set(y[t[e][i][0]].slice(t[e][i][1], t[e][i][1] + a), x * a), t[e][i][2] >= 0 ? g.set(z.slice(t[e][i][2], t[e][i][2] + h.Fr.n8), x * h.Fr.n8) : g.set(b, x * h.Fr.n8), x++; + if (t.length > 1) { + let e = []; + e.push({ + cmd: "ALLOCSET", + var: 0, + buff: m + }), e.push({ + cmd: "ALLOCSET", + var: 1, + buff: g + }), e.push({ + cmd: "ALLOC", + var: 2, + len: t.length * o + }), _ = 0, v = 0; + let n = 0; + for (let r = 0; r < t.length; r++) { + if (!t[r]) { + e.push({ + cmd: "CALL", + fnName: f, + params: [{ + var: 2, + offset: n + }] + }), n += o; + continue; + } + t[r].length == 1 ? e.push({ + cmd: "CALL", + fnName: l, + params: [ + { + var: 0, + offset: _ + }, + { + var: 1, + offset: v + }, + { val: h.Fr.n8 }, + { + var: 2, + offset: n + } + ] + }) : e.push({ + cmd: "CALL", + fnName: u, + params: [ + { + var: 0, + offset: _ + }, + { + var: 1, + offset: v + }, + { val: h.Fr.n8 }, + { val: t[r].length }, + { + var: 2, + offset: n + } + ] + }), _ += a * t[r].length, v += h.Fr.n8 * t[r].length, n += o; + } + return e.push({ + cmd: "CALL", + fnName: d, + params: [ + { var: 2 }, + { val: t.length }, + { var: 2 } + ] + }), e.push({ + cmd: "GET", + out: 0, + var: 2, + len: t.length * c + }), await h.tm.queueAction(e); + } else { + let e = await i.multiExpAffine(m, g, n, r); + return e = [i.toAffine(e)], e; + } + } + async function de() { + let e = 16384; + me(E - 1); + for (let t = 0; t < E - 1; t += e) { + d && d.debug(`HashingHPoints: ${t}/${E}`); + let n = Math.min(E - 1, e); + await fe(t, n); + } + } + async function fe(e, t) { + let n = await p.read(t * S, m[2][0].p + (e + E) * S), r = await p.read(t * S, m[2][0].p + e * S), i = h.tm.concurrency, a = Math.floor(t / i), o = []; + for (let e = 0; e < i; e++) { + let s; + if (s = e < i - 1 ? a : t - e * a, s == 0) continue; + let c = n.slice(e * a * S, (e * a + s) * S), l = r.slice(e * a * S, (e * a + s) * S); + o.push(pe(c, l)); + } + let s = await Promise.all(o); + for (let e = 0; e < s.length; e++) f.update(s[e][0]); + } + async function pe(e, t) { + let n = e.byteLength / S, r = h.G1.F.n8 * 3, i = []; + i.push({ + cmd: "ALLOCSET", + var: 0, + buff: e + }), i.push({ + cmd: "ALLOCSET", + var: 1, + buff: t + }), i.push({ + cmd: "ALLOC", + var: 2, + len: n * r + }); + for (let e = 0; e < n; e++) i.push({ + cmd: "CALL", + fnName: "g1m_subAffine", + params: [ + { + var: 0, + offset: e * S + }, + { + var: 1, + offset: e * S + }, + { + var: 2, + offset: e * r + } + ] + }); + return i.push({ + cmd: "CALL", + fnName: "g1m_batchToAffine", + params: [ + { var: 2 }, + { val: n }, + { var: 2 } + ] + }), i.push({ + cmd: "CALL", + fnName: "g1m_batchLEMtoU", + params: [ + { var: 2 }, + { val: n }, + { var: 2 } + ] + }), i.push({ + cmd: "GET", + out: 0, + var: 2, + len: n * S + }), await h.tm.queueAction(i); + } + function me(e) { + let t = new Uint8Array(4); + new DataView(t.buffer, t.byteOffset, t.byteLength).setUint32(0, e, !1), f.update(t); + } + function W() { + let e = process.memoryUsage(); + for (let t in e) e[t] = Math.round(e[t] / (1024 * 1024)); + return e; + } +} +//#endregion +//#region src/zkey_export_bellman.js +async function Jn(t, n, r) { + let { fd: i, sections: a } = await e.readBinFile(t, "zkey", 2), o = await Ve(i, a); + if (o.protocol != "groth16") throw Error("zkey file is not groth16"); + let s = await E(o.q), c = s.G1.F.n8 * 2, l = s.G2.F.n8 * 2, u = await qe(i, s, a), d = await At(n); + await y(o.vk_alpha_1), await y(o.vk_beta_1), await b(o.vk_beta_2), await b(o.vk_gamma_2), await y(o.vk_delta_1), await b(o.vk_delta_2); + let f; + f = await e.readSection(i, a, 3), f = await s.G1.batchLEMtoU(f), await x("G1", f); + let p = await e.readSection(i, a, 9), m; + m = await s.G1.fft(p, "affine", "jacobian", r), m = await s.G1.batchApplyKey(m, s.Fr.neg(s.Fr.e(2)), s.Fr.w[o.power + 1], "jacobian", "affine", r), m = m.slice(0, m.byteLength - c), m = await s.G1.batchLEMtoU(m), await x("G1", m); + let h; + h = await e.readSection(i, a, 8), h = await s.G1.batchLEMtoU(h), await x("G1", h); + let g; + g = await e.readSection(i, a, 5), g = await s.G1.batchLEMtoU(g), await x("G1", g); + let _; + _ = await e.readSection(i, a, 6), _ = await s.G1.batchLEMtoU(_), await x("G1", _); + let v; + v = await e.readSection(i, a, 7), v = await s.G2.batchLEMtoU(v), await x("G2", v), await d.write(u.csHash), await S(u.contributions.length); + for (let e = 0; e < u.contributions.length; e++) { + let t = u.contributions[e]; + await y(t.deltaAfter), await y(t.delta.g1_s), await y(t.delta.g1_sx), await b(t.delta.g2_spx), await d.write(t.transcript); + } + await i.close(), await d.close(); + async function y(e) { + let t = new Uint8Array(c); + s.G1.toRprUncompressed(t, 0, e), await d.write(t); + } + async function b(e) { + let t = new Uint8Array(l); + s.G2.toRprUncompressed(t, 0, e), await d.write(t); + } + async function x(e, t) { + let n; + n = e == "G1" ? c : l; + let r = new Uint8Array(4); + new DataView(r.buffer, r.byteOffset, r.byteLength).setUint32(0, t.byteLength / n, !1), await d.write(r), await d.write(t); + } + async function S(e) { + let t = new Uint8Array(4); + new DataView(t.buffer, t.byteOffset, t.byteLength).setUint32(0, e, !1), await d.write(t); + } +} +//#endregion +//#region src/zkey_import_bellman.js +async function Yn(t, n, r, i, a) { + let { fd: o, sections: s } = await e.readBinFile(t, "zkey", 2), c = await Ve(o, s, !1); + if (c.protocol != "groth16") throw Error("zkey file is not groth16"); + let l = await E(c.q), u = l.G1.F.n8 * 2, d = l.G2.F.n8 * 2, f = await qe(o, l, s), p = {}, m = await jt(n); + m.pos = u * 3 + d * 3 + 8 + u * c.nVars + 4 + u * (c.domainSize - 1) + 4 + u * c.nVars + 4 + u * c.nVars + 4 + d * c.nVars, p.csHash = await m.read(64); + let h = await m.readUBE32(); + p.contributions = []; + for (let e = 0; e < h; e++) { + let t = { delta: {} }; + t.deltaAfter = await C(m), t.delta.g1_s = await C(m), t.delta.g1_sx = await C(m), t.delta.g2_spx = await w(m), t.transcript = await m.read(64), e < f.contributions.length && (t.type = f.contributions[e].type, t.type == 1 && (t.beaconHash = f.contributions[e].beaconHash, t.numIterationsExp = f.contributions[e].numIterationsExp), f.contributions[e].name && (t.name = f.contributions[e].name)), p.contributions.push(t); + } + if (!Ce(p.csHash, f.csHash)) return a && a.error("Hash of the original circuit does not match with the MPC one"), !1; + if (f.contributions.length > p.contributions.length) return a && a.error("The impoerted file does not include new contributions"), !1; + for (let e = 0; e < f.contributions.length; e++) if (!T(f.contributions[e], p.contributions[e])) return a && a.error(`Previous contribution ${e} does not match`), !1; + if (i) for (let e = f.contributions.length; e < p.contributions.length; e++) p.contributions[e].name = i; + let g = await e.createBinFile(r, "zkey", 1, 10); + if (m.pos = 0, m.pos += u, m.pos += u, m.pos += d, m.pos += d, c.vk_delta_1 = await C(m), c.vk_delta_2 = await w(m), await Le(g, c), await m.readUBE32() != c.nPublic + 1) return a && a.error("Invalid number of points in IC"), await g.discard(), !1; + if (m.pos += u * (c.nPublic + 1), await e.copySection(o, s, g, 3), await e.copySection(o, s, g, 4), await m.readUBE32() != c.domainSize - 1) return a && a.error("Invalid number of points in H"), await g.discard(), !1; + let _, v = await m.read(u * (c.domainSize - 1)), y = await l.G1.batchUtoLEM(v); + _ = new Uint8Array(c.domainSize * u), _.set(y), l.G1.toRprLEM(_, u * (c.domainSize - 1), l.G1.zeroAffine); + let b = l.Fr.neg(l.Fr.inv(l.Fr.e(2))), x = l.Fr.inv(l.Fr.w[c.power + 1]); + if (_ = await l.G1.batchApplyKey(_, b, x, "affine", "jacobian", a), _ = await l.G1.ifft(_, "jacobian", "affine", a), await e.startWriteSection(g, 9), await g.write(_), await e.endWriteSection(g), await m.readUBE32() != c.nVars - c.nPublic - 1) return a && a.error("Invalid number of points in L"), await g.discard(), !1; + let S; + if (S = await m.read(u * (c.nVars - c.nPublic - 1)), S = await l.G1.batchUtoLEM(S), await e.startWriteSection(g, 8), await g.write(S), await e.endWriteSection(g), await m.readUBE32() != c.nVars) return a && a.error("Invalid number of points in A"), await g.discard(), !1; + if (m.pos += u * c.nVars, await e.copySection(o, s, g, 5), await m.readUBE32() != c.nVars) return a && a.error("Invalid number of points in B1"), await g.discard(), !1; + if (m.pos += u * c.nVars, await e.copySection(o, s, g, 6), await m.readUBE32() != c.nVars) return a && a.error("Invalid number of points in B2"), await g.discard(), !1; + return m.pos += d * c.nVars, await e.copySection(o, s, g, 7), await Ye(g, l, p), await m.close(), await g.close(), await o.close(), !0; + async function C(e) { + let t = await e.read(l.G1.F.n8 * 2); + return l.G1.fromRprUncompressed(t, 0); + } + async function w(e) { + let t = await e.read(l.G2.F.n8 * 2); + return l.G2.fromRprUncompressed(t, 0); + } + function T(e, t) { + return !(!l.G1.eq(e.deltaAfter, t.deltaAfter) || !l.G1.eq(e.delta.g1_s, t.delta.g1_s) || !l.G1.eq(e.delta.g1_sx, t.delta.g1_sx) || !l.G2.eq(e.delta.g2_spx, t.delta.g2_spx) || !Ce(e.transcript, t.transcript)); + } +} +//#endregion +//#region src/zkey_verify_frominit.js +var Xn = De; +async function Zn(t, n, r, i) { + let a, { fd: o, sections: l } = await e.readBinFile(r, "zkey", 2), d = await Ve(o, l, !1); + if (d.protocol != "groth16") throw Error("zkey file is not groth16"); + let f = await E(d.q), p = f.G1.F.n8 * 2, m = await qe(o, f, l), h = K.create({ dkLen: 64 }); + h.update(m.csHash); + let g = f.G1.g; + for (let e = 0; e < m.contributions.length; e++) { + let t = m.contributions[e], n = we(h); + if (Xe(n, f, t.delta.g1_s), Xe(n, f, t.delta.g1_sx), !Ce(n.digest(), t.transcript)) return console.log(`INVALID(${e}): Inconsistent transcript `), !1; + let r = Qt(f, t.transcript); + if (a = await Xn(f, t.delta.g1_s, t.delta.g1_sx, r, t.delta.g2_spx), a !== !0) return console.log(`INVALID(${e}): public key G1 and G2 do not have the same ration `), !1; + if (a = await Xn(f, g, t.deltaAfter, r, t.delta.g2_spx), a !== !0) return console.log(`INVALID(${e}): deltaAfter does not fillow the public key `), !1; + if (t.type == 1) { + let n = await Ne(t.beaconHash, t.numIterationsExp), r = f.Fr.fromRng(n), i = f.G1.toAffine(f.G1.fromRng(n)), a = f.G1.toAffine(f.G1.timesFr(i, r)); + if (f.G1.eq(i, t.delta.g1_s) !== !0) return console.log(`INVALID(${e}): Key of the beacon does not match. g1_s `), !1; + if (f.G1.eq(a, t.delta.g1_sx) !== !0) return console.log(`INVALID(${e}): Key of the beacon does not match. g1_sx `), !1; + } + Qe(h, f, t); + let i = K.create({ dkLen: 64 }); + Qe(i, f, t), t.contributionHash = i.digest(), g = t.deltaAfter; + } + let { fd: _, sections: v } = await e.readBinFile(t, "zkey", 2), y = await Ve(_, v, !1); + if (y.protocol != "groth16") throw Error("zkeyinit file is not groth16"); + if (!u.eq(y.q, d.q) || !u.eq(y.r, d.r) || y.n8q != d.n8q || y.n8r != d.n8r) return i && i.error("INVALID: Different curves"), !1; + if (y.nVars != d.nVars || y.nPublic != d.nPublic || y.domainSize != d.domainSize) return i && i.error("INVALID: Different circuit parameters"), !1; + if (!f.G1.eq(d.vk_alpha_1, y.vk_alpha_1)) return i && i.error("INVALID: Invalid alpha1"), !1; + if (!f.G1.eq(d.vk_beta_1, y.vk_beta_1)) return i && i.error("INVALID: Invalid beta1"), !1; + if (!f.G2.eq(d.vk_beta_2, y.vk_beta_2)) return i && i.error("INVALID: Invalid beta2"), !1; + if (!f.G2.eq(d.vk_gamma_2, y.vk_gamma_2)) return i && i.error("INVALID: Invalid gamma2"), !1; + if (!f.G1.eq(d.vk_delta_1, g)) return i && i.error("INVALID: Invalid delta1"), !1; + if (a = await Xn(f, f.G1.g, g, f.G2.g, d.vk_delta_2), a !== !0) return i && i.error("INVALID: Invalid delta2"), !1; + let b = await qe(_, f, v); + if (!Ce(m.csHash, b.csHash)) return i && i.error("INVALID: Circuit does not match"), !1; + if (l[8][0].size != p * (d.nVars - d.nPublic - 1)) return i && i.error("INVALID: Invalid L section size"), !1; + if (l[9][0].size != p * d.domainSize) return i && i.error("INVALID: Invalid H section size"), !1; + let x; + if (x = await e.sectionIsEqual(o, l, _, v, 3), !x) return i && i.error("INVALID: IC section is not identical"), !1; + if (x = await e.sectionIsEqual(o, l, _, v, 4), !x) return i && i.error("Coeffs section is not identical"), !1; + if (x = await e.sectionIsEqual(o, l, _, v, 5), !x) return i && i.error("A section is not identical"), !1; + if (x = await e.sectionIsEqual(o, l, _, v, 6), !x) return i && i.error("B1 section is not identical"), !1; + if (x = await e.sectionIsEqual(o, l, _, v, 7), !x) return i && i.error("B2 section is not identical"), !1; + if (a = await S("G1", _, v, o, l, 8, d.vk_delta_2, y.vk_delta_2, "L section"), a !== !0) return i && i.error("L section does not match"), !1; + if (a = await C(), a !== !0) return i && i.error("H section does not match"), !1; + i && i.info(q(m.csHash, "Circuit Hash: ")), await o.close(), await _.close(); + for (let e = m.contributions.length - 1; e >= 0; e--) { + let t = m.contributions[e]; + i && i.info("-------------------------"), i && i.info(q(t.contributionHash, `contribution #${e + 1} ${t.name ? t.name : ""}:`)), t.type == 1 && (i && i.info(`Beacon generator: ${Fe(t.beaconHash)}`), i && i.info(`Beacon iterations Exp: ${t.numIterationsExp}`)); + } + return i && i.info("-------------------------"), i && i.info("ZKey Ok!"), !0; + async function S(t, n, r, o, s, c, l, u, d) { + let p = 1 << 20, m = f[t], h = m.F.n8 * 2; + await e.startReadUniqueSection(n, r, c), await e.startReadUniqueSection(o, s, c); + let g = m.zero, _ = m.zero, v = r[c][0].size / h; + for (let e = 0; e < v; e += p) { + i && i.debug(`Same ratio check ${d}: ${e}/${v}`); + let t = Math.min(v - e, p), r = await n.read(t * h), a = await o.read(t * h), s = ke(4 * t), c = await m.multiExpAffine(r, s), l = await m.multiExpAffine(a, s); + g = m.add(g, c), _ = m.add(_, l); + } + return await e.endReadSection(n), await e.endReadSection(o), v == 0 ? !0 : (a = await Xn(f, g, _, l, u), a === !0); + } + async function C() { + let t = 1 << 20, r = f.G1, u = f.Fr, p = r.F.n8 * 2, { fd: m, sections: h } = await e.readBinFile(n, "ptau", 1), g = new s(d.domainSize * d.n8r), _ = Array(8); + for (let e = 0; e < 8; e++) _[e] = je(ke(4), 0); + let v = new c(_); + for (let e = 0; e < d.domainSize - 1; e++) { + let t = u.fromRng(v); + u.toRprLE(g, e * d.n8r, t); + } + u.toRprLE(g, (d.domainSize - 1) * d.n8r, u.zero); + let b = r.zero; + for (let e = 0; e < d.domainSize; e += t) { + i && i.debug(`H Verification(tau): ${e}/${d.domainSize}`); + let n = Math.min(d.domainSize - e, t), a = await w(await m.read(p * n, h[2][0].p + d.domainSize * p + e * p), await m.read(p * n, h[2][0].p + e * p)), o = g.slice(e * d.n8r, (e + n) * d.n8r), s = await r.multiExpAffine(a, o); + b = r.add(b, s); + } + g = await u.batchToMontgomery(g); + let x; + if (d.power < u.s) x = u.neg(u.e(2)); + else { + let e = 2 ** u.s, t = u.exp(u.shift, e); + x = u.sub(t, u.one); + } + let S = d.power < u.s ? u.w[d.power + 1] : u.shift; + g = await u.batchApplyKey(g, x, S), g = await u.fft(g), g = await u.batchFromMontgomery(g), await e.startReadUniqueSection(o, l, 9); + let C = r.zero; + for (let e = 0; e < d.domainSize; e += t) { + i && i.debug(`H Verification(lagrange): ${e}/${d.domainSize}`); + let n = Math.min(d.domainSize - e, t), a = await o.read(p * n), s = g.slice(e * d.n8r, (e + n) * d.n8r), c = await r.multiExpAffine(a, s); + C = r.add(C, c); + } + return await e.endReadSection(o), a = await Xn(f, b, C, d.vk_delta_2, y.vk_delta_2), a === !0; + } + async function w(e, t) { + let n = f.G1.F.n8 * 2, r = e.byteLength / n, i = f.tm.concurrency, a = Math.floor(r / i), o = []; + for (let n = 0; n < i; n++) { + let s; + if (s = n < i - 1 ? a : r - n * a, s == 0) continue; + let c = e.slice(n * a * p, (n * a + s) * p), l = t.slice(n * a * p, (n * a + s) * p); + o.push(T(c, l)); + } + let s = await Promise.all(o), c = new Uint8Array(r * n), l = 0; + for (let e = 0; e < s.length; e++) c.set(s[e][0], l), l += s[e][0].byteLength; + return c; + } + async function T(e, t) { + let n = f.G1.F.n8 * 2, r = f.G1.F.n8 * 3, i = e.byteLength / n, a = []; + a.push({ + cmd: "ALLOCSET", + var: 0, + buff: e + }), a.push({ + cmd: "ALLOCSET", + var: 1, + buff: t + }), a.push({ + cmd: "ALLOC", + var: 2, + len: i * r + }); + for (let e = 0; e < i; e++) a.push({ + cmd: "CALL", + fnName: "g1m_subAffine", + params: [ + { + var: 0, + offset: e * n + }, + { + var: 1, + offset: e * n + }, + { + var: 2, + offset: e * r + } + ] + }); + return a.push({ + cmd: "CALL", + fnName: "g1m_batchToAffine", + params: [ + { var: 2 }, + { val: i }, + { var: 2 } + ] + }), a.push({ + cmd: "GET", + out: 0, + var: 2, + len: i * n + }), await f.tm.queueAction(a); + } +} +//#endregion +//#region src/zkey_verify_fromr1cs.js +async function Qn(e, t, n, r) { + let i = { type: "bigMem" }; + return await qn(e, t, i, r), await Zn(i, t, n, r); +} +//#endregion +//#region src/zkey_contribute.js +async function $n(t, n, r, i, a) { + let { fd: o, sections: s } = await e.readBinFile(t, "zkey", 2), c = await Ve(o, s); + if (c.protocol != "groth16") throw Error("zkey file is not groth16"); + let l = await E(c.q), u = await qe(o, l, s), d = await e.createBinFile(n, "zkey", 1, 10), f = await Me(i), p = K.create({ dkLen: 64 }); + p.update(u.csHash); + for (let e = 0; e < u.contributions.length; e++) Qe(p, l, u.contributions[e]); + let m = {}; + m.delta = {}, m.delta.prvKey = l.Fr.fromRng(f), m.delta.g1_s = l.G1.toAffine(l.G1.fromRng(f)), m.delta.g1_sx = l.G1.toAffine(l.G1.timesFr(m.delta.g1_s, m.delta.prvKey)), Xe(p, l, m.delta.g1_s), Xe(p, l, m.delta.g1_sx), m.transcript = p.digest(), m.delta.g2_sp = Qt(l, m.transcript), m.delta.g2_spx = l.G2.toAffine(l.G2.timesFr(m.delta.g2_sp, m.delta.prvKey)), c.vk_delta_1 = l.G1.timesFr(c.vk_delta_1, m.delta.prvKey), c.vk_delta_2 = l.G2.timesFr(c.vk_delta_2, m.delta.prvKey), m.deltaAfter = c.vk_delta_1, m.type = 0, r && (m.name = r), u.contributions.push(m), await Le(d, c), await e.copySection(o, s, d, 3), await e.copySection(o, s, d, 4), await e.copySection(o, s, d, 5), await e.copySection(o, s, d, 6), await e.copySection(o, s, d, 7); + let h = l.Fr.inv(m.delta.prvKey); + await xn(o, s, d, 8, l, "G1", h, l.Fr.e(1), "L Section", a), await xn(o, s, d, 9, l, "G1", h, l.Fr.e(1), "H Section", a), await Ye(d, l, u), await o.close(), await d.close(); + let g = K.create({ dkLen: 64 }); + Qe(g, l, m); + let _ = g.digest(); + return a && a.info(q(u.csHash, "Circuit Hash: ")), a && a.info(q(_, "Contribution Hash: ")), _; +} +//#endregion +//#region src/zkey_beacon.js +async function er(t, n, r, i, a, o) { + let s = Pe(i); + if (s.byteLength == 0 || s.byteLength * 2 != i.length) return o && o.error("Invalid Beacon Hash. (It must be a valid hexadecimal sequence)"), !1; + if (s.length >= 256) return o && o.error("Maximum length of beacon hash is 255 bytes"), !1; + if (a = parseInt(a), a < 10 || a > 63) return o && o.error("Invalid numIterationsExp. (Must be between 10 and 63)"), !1; + let { fd: c, sections: l } = await e.readBinFile(t, "zkey", 2), u = await Ve(c, l); + if (u.protocol != "groth16") throw Error("zkey file is not groth16"); + let d = await E(u.q), f = await qe(c, d, l), p = await e.createBinFile(n, "zkey", 1, 10), m = await Ne(s, a), h = K.create({ dkLen: 64 }); + h.update(f.csHash); + for (let e = 0; e < f.contributions.length; e++) Qe(h, d, f.contributions[e]); + let g = {}; + g.delta = {}, g.delta.prvKey = d.Fr.fromRng(m), g.delta.g1_s = d.G1.toAffine(d.G1.fromRng(m)), g.delta.g1_sx = d.G1.toAffine(d.G1.timesFr(g.delta.g1_s, g.delta.prvKey)), Xe(h, d, g.delta.g1_s), Xe(h, d, g.delta.g1_sx), g.transcript = h.digest(), g.delta.g2_sp = Qt(d, g.transcript), g.delta.g2_spx = d.G2.toAffine(d.G2.timesFr(g.delta.g2_sp, g.delta.prvKey)), u.vk_delta_1 = d.G1.timesFr(u.vk_delta_1, g.delta.prvKey), u.vk_delta_2 = d.G2.timesFr(u.vk_delta_2, g.delta.prvKey), g.deltaAfter = u.vk_delta_1, g.type = 1, g.numIterationsExp = a, g.beaconHash = s, r && (g.name = r), f.contributions.push(g), await Le(p, u), await e.copySection(c, l, p, 3), await e.copySection(c, l, p, 4), await e.copySection(c, l, p, 5), await e.copySection(c, l, p, 6), await e.copySection(c, l, p, 7); + let _ = d.Fr.inv(g.delta.prvKey); + await xn(c, l, p, 8, d, "G1", _, d.Fr.e(1), "L Section", o), await xn(c, l, p, 9, d, "G1", _, d.Fr.e(1), "H Section", o), await Ye(p, d, f), await c.close(), await p.close(); + let v = K.create({ dkLen: 64 }); + Qe(v, d, g); + let y = v.digest(); + return o && o.info(q(y, "Contribution Hash: ")), y; +} +//#endregion +//#region src/zkey_export_json.js +async function tr(e) { + let t = await Ge(e, !0); + return delete t.curve, delete t.F, p.stringifyBigInts(t); +} +//#endregion +//#region src/zkey_bellman_contribute.js +async function nr(e, t, n, r, i) { + let a = await Me(r), o = e.Fr.fromRng(a), s = e.Fr.inv(o), c = e.G1.F.n8 * 2, l = e.G2.F.n8 * 2, u = await jt(t), d = await At(n); + await D(c), await D(c), await D(l), await D(l); + let f = await O(), p = e.G1.timesFr(f, o); + await A(p); + let m = await k(); + await j(e.G2.timesFr(m, o)); + let h = await u.readUBE32(); + await d.writeUBE32(h), await D(h * c); + let g = await u.readUBE32(); + await d.writeUBE32(g), await Sn(u, d, null, e, "G1", g, s, e.Fr.e(1), "UNCOMPRESSED", "H", i); + let _ = await u.readUBE32(); + await d.writeUBE32(_), await Sn(u, d, null, e, "G1", _, s, e.Fr.e(1), "UNCOMPRESSED", "L", i); + let v = await u.readUBE32(); + await d.writeUBE32(v), await D(v * c); + let y = await u.readUBE32(); + await d.writeUBE32(y), await D(y * c); + let b = await u.readUBE32(); + await d.writeUBE32(b), await D(b * l); + let x = K.create({ dkLen: 64 }), S = {}; + S.csHash = await u.read(64), x.update(S.csHash); + let C = await u.readUBE32(); + S.contributions = []; + for (let t = 0; t < C; t++) { + let t = { delta: {} }; + t.deltaAfter = await O(), t.delta.g1_s = await O(), t.delta.g1_sx = await O(), t.delta.g2_spx = await k(), t.transcript = await u.read(64), S.contributions.push(t), Qe(x, e, t); + } + let w = {}; + w.delta = {}, w.delta.prvKey = o, w.delta.g1_s = e.G1.toAffine(e.G1.fromRng(a)), w.delta.g1_sx = e.G1.toAffine(e.G1.timesFr(w.delta.g1_s, o)), Xe(x, e, w.delta.g1_s), Xe(x, e, w.delta.g1_sx), w.transcript = x.digest(), w.delta.g2_sp = Qt(e, w.transcript), w.delta.g2_spx = e.G2.toAffine(e.G2.timesFr(w.delta.g2_sp, o)), w.deltaAfter = p, w.type = 0, S.contributions.push(w), await d.write(S.csHash), await d.writeUBE32(S.contributions.length); + for (let e = 0; e < S.contributions.length; e++) { + let t = S.contributions[e]; + await A(t.deltaAfter), await A(t.delta.g1_s), await A(t.delta.g1_sx), await j(t.delta.g2_spx), await d.write(t.transcript); + } + let T = K.create({ dkLen: 64 }); + Qe(T, e, w); + let E = T.digest(); + return i && i.info(q(E, "Contribution Hash: ")), await d.close(), await u.close(), E; + async function D(e) { + let t = u.pageSize * 2; + for (let n = 0; n < e; n += t) { + let r = Math.min(e - n, t), i = await u.read(r); + await d.write(i); + } + } + async function O() { + let t = await u.read(e.G1.F.n8 * 2); + return e.G1.fromRprUncompressed(t, 0); + } + async function k() { + let t = await u.read(e.G2.F.n8 * 2); + return e.G2.fromRprUncompressed(t, 0); + } + async function A(t) { + let n = new Uint8Array(c); + e.G1.toRprUncompressed(n, 0, t), await d.write(n); + } + async function j(t) { + let n = new Uint8Array(l); + e.G2.toRprUncompressed(n, 0, t), await d.write(n); + } +} +//#endregion +//#region src/zkey_export_verificationkey.js +var { stringifyBigInts: rr } = p; +async function ir(t, n) { + n && n.info("EXPORT VERIFICATION KEY STARTED"); + let { fd: r, sections: i } = await e.readBinFile(t, "zkey", 2), a = await Ve(r, i); + n && n.info("> Detected protocol: " + a.protocol); + let o; + if (a.protocol === "groth16") o = await ar(a, r, i); + else if (a.protocol === "plonk") o = await or(a); + else if (a.protocolId && a.protocolId === 10) o = await sr(a, n); + else throw Error("zkey file protocol unrecognized"); + return await r.close(), n && n.info("EXPORT VERIFICATION KEY FINISHED"), o; +} +async function ar(t, n, r) { + let i = await E(t.q), a = i.G1.F.n8 * 2, o = await i.pairing(t.vk_alpha_1, t.vk_beta_2), s = { + protocol: t.protocol, + curve: i.name, + nPublic: t.nPublic, + vk_alpha_1: i.G1.toObject(t.vk_alpha_1), + vk_beta_2: i.G2.toObject(t.vk_beta_2), + vk_gamma_2: i.G2.toObject(t.vk_gamma_2), + vk_delta_2: i.G2.toObject(t.vk_delta_2), + vk_alphabeta_12: i.Gt.toObject(o) + }; + await e.startReadUniqueSection(n, r, 3), s.IC = []; + for (let e = 0; e <= t.nPublic; e++) { + let e = await n.read(a), t = i.G1.toObject(e); + s.IC.push(t); + } + return await e.endReadSection(n), s = rr(s), s; +} +async function or(e) { + let t = await E(e.q), n = { + protocol: e.protocol, + curve: t.name, + nPublic: e.nPublic, + power: e.power, + k1: t.Fr.toObject(e.k1), + k2: t.Fr.toObject(e.k2), + Qm: t.G1.toObject(e.Qm), + Ql: t.G1.toObject(e.Ql), + Qr: t.G1.toObject(e.Qr), + Qo: t.G1.toObject(e.Qo), + Qc: t.G1.toObject(e.Qc), + S1: t.G1.toObject(e.S1), + S2: t.G1.toObject(e.S2), + S3: t.G1.toObject(e.S3), + X_2: t.G2.toObject(e.X_2), + w: t.Fr.toObject(t.Fr.w[e.power]) + }; + return n = rr(n), n; +} +async function sr(e, t) { + let n = await E(e.q); + return rr({ + protocol: e.protocol, + curve: n.name, + nPublic: e.nPublic, + power: e.power, + k1: n.Fr.toObject(e.k1), + k2: n.Fr.toObject(e.k2), + w: n.Fr.toObject(n.Fr.w[e.power]), + w3: n.Fr.toObject(e.w3), + w4: n.Fr.toObject(e.w4), + w8: n.Fr.toObject(e.w8), + wr: n.Fr.toObject(e.wr), + X_2: n.G2.toObject(e.X_2), + C0: n.G1.toObject(e.C0) + }); +} +//#endregion +//#region src/fflonk_export_solidity_verifier.js +var { unstringifyBigInts: cr, stringifyBigInts: lr } = p; +async function ur(e, t, n) { + n && n.info("FFLONK EXPORT SOLIDITY VERIFIER STARTED"); + let r = await D(e.curve), i = u(e.w3); + e.w3_2 = d(r.Fr.square(i)); + let a = u(e.w4); + e.w4_2 = d(r.Fr.square(a)), e.w4_3 = d(r.Fr.mul(r.Fr.square(a), a)); + let o = u(e.w8), s = r.Fr.one; + for (let t = 1; t < 8; t++) s = r.Fr.mul(s, o), e["w8_" + t] = d(s); + let c = t[e.protocol]; + n && n.info("FFLONK EXPORT SOLIDITY VERIFIER FINISHED"); + let { default: l } = await import("ejs"); + return l.render(c, e); + function u(e) { + let t = cr(e); + return r.Fr.fromObject(t); + } + function d(e) { + return lr(r.Fr.toObject(e)); + } +} +//#endregion +//#region src/zkey_export_solidityverifier.js +async function dr(e, t, n) { + let r = await ir(e, n); + if (r.protocol === "fflonk") return ur(r, t, n); + let i = t[r.protocol], { default: a } = await import("ejs"); + return a.render(i, r); +} +//#endregion +//#region src/zkey.js +var fr = /* @__PURE__ */ y({ + beacon: () => er, + bellmanContribute: () => nr, + contribute: () => $n, + exportBellman: () => Jn, + exportJson: () => tr, + exportSolidityVerifier: () => dr, + exportVerificationKey: () => ir, + importBellman: () => Yn, + newZKey: () => qn, + verifyFromInit: () => Zn, + verifyFromR1cs: () => Qn }); - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -async function loadSymbols(symFileName) { - const sym = { - labelIdx2Name: [ "one" ], - varIdx2Name: [ "one" ], - componentIdx2Name: [] - }; - const fd = await readExisting$3(symFileName); - const buff = await fd.read(fd.totalSize); - const symsStr = new TextDecoder("utf-8").decode(buff); - const lines = symsStr.split("\n"); - for (let i=0; i. -*/ -const {unstringifyBigInts: unstringifyBigInts$7} = utils; - - -async function wtnsDebug(_input, wasmFileName, wtnsFileName, symName, options, logger) { - - const input = unstringifyBigInts$7(_input); - - const fdWasm = await readExisting$3(wasmFileName); - const wasm = await fdWasm.read(fdWasm.totalSize); - await fdWasm.close(); - - const wcOps = {...options, sanityCheck: true}; - let sym = await loadSymbols(symName); - if (options.set) { - if (!sym) sym = await loadSymbols(symName); - wcOps.logSetSignal= function(labelIdx, value) { - // The line below splits the arrow log into 2 strings to avoid some Secure ECMAScript issues - if (logger) logger.info("SET " + sym.labelIdx2Name[labelIdx] + " <" + "-- " + value.toString()); - }; - } - if (options.get) { - if (!sym) sym = await loadSymbols(symName); - wcOps.logGetSignal= function(varIdx, value) { - // The line below splits the arrow log into 2 strings to avoid some Secure ECMAScript issues - if (logger) logger.info("GET " + sym.labelIdx2Name[varIdx] + " --" + "> " + value.toString()); - }; - } - if (options.trigger) { - if (!sym) sym = await loadSymbols(symName); - wcOps.logStartComponent= function(cIdx) { - if (logger) logger.info("START: " + sym.componentIdx2Name[cIdx]); - }; - wcOps.logFinishComponent= function(cIdx) { - if (logger) logger.info("FINISH: " + sym.componentIdx2Name[cIdx]); - }; - } - wcOps.sym = sym; - - const wc = await builder(wasm, wcOps); - const w = await wc.calculateWitness(input, true); - - const fdWtns = await createBinFile(wtnsFileName, "wtns", 2, 2); - - await write(fdWtns, w, wc.prime); - - await fdWtns.close(); -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -async function wtnsExportJson(wtnsFileName) { - - const w = await read(wtnsFileName); - - return w; -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -async function wtnsCheck(r1csFilename, wtnsFilename, logger) { - - if (logger) logger.info("WITNESS CHECKING STARTED"); - - // Read r1cs file - if (logger) logger.info("> Reading r1cs file"); - const { - fd: fdR1cs, - sections: sectionsR1cs - } = await readBinFile$1(r1csFilename, "r1cs", 1); - const r1cs = await readR1csFd(fdR1cs, sectionsR1cs, { loadConstraints: false, loadCustomGates: false }); - - // Read witness file - if (logger) logger.info("> Reading witness file"); - const { - fd: fdWtns, - sections: wtnsSections - } = await readBinFile$1(wtnsFilename, "wtns", 2); - const wtnsHeader = await readHeader(fdWtns, wtnsSections); - - if (!Scalar.eq(r1cs.prime, wtnsHeader.q)) { - throw new Error("Curve of the witness does not match the curve of the proving key"); - } - - const buffWitness = await readSection$1(fdWtns, wtnsSections, 2); - await fdWtns.close(); - - const curve = await getCurveFromR(r1cs.prime); - const Fr = curve.Fr; - const sFr = Fr.n8; - - const bR1cs = await readSection$1(fdR1cs, sectionsR1cs, 2); - - if (logger) { - logger.info("----------------------------"); - logger.info(" WITNESS CHECK"); - logger.info(` Curve: ${r1cs.curve.name}`); - logger.info(` Vars (wires): ${r1cs.nVars}`); - logger.info(` Outputs: ${r1cs.nOutputs}`); - logger.info(` Public Inputs: ${r1cs.nPubInputs}`); - logger.info(` Private Inputs: ${r1cs.nPrvInputs}`); - logger.info(` Labels: ${r1cs.nLabels}`); - logger.info(` Constraints: ${r1cs.nConstraints}`); - logger.info(` Custom Gates: ${r1cs.useCustomGates}`); - logger.info("----------------------------"); - } - - if (logger) logger.info("> Checking witness correctness"); - - let bR1csPos = 0; - let res = true; - for (let i = 0; i < r1cs.nConstraints; i++) { - if ((logger) && (i !== 0) && (i % 500000 === 0)) { - logger.info(`··· processing r1cs constraints ${i}/${r1cs.nConstraints}`); - } - - //Read the three linear combinations of the constraint where A * B - C = 0 - const lcA = readLC(); - const lcB = readLC(); - const lcC = readLC(); - - // Evaluate the linear combinations - const evalA = EvaluateLinearCombination(lcA); - const evalB = EvaluateLinearCombination(lcB); - const evalC = EvaluateLinearCombination(lcC); - - // Check that A * B - C == 0 - if (!Fr.eq(Fr.sub(Fr.mul(evalA, evalB), evalC), Fr.zero)) { - logger.warn("··· aborting checking process at constraint " + i); - res = false; - break; - } - } - - fdR1cs.close(); - - if (logger) { - if (res) { - logger.info("WITNESS IS CORRECT"); - logger.info("WITNESS CHECKING FINISHED SUCCESSFULLY"); - } else { - logger.warn("WITNESS IS NOT CORRECT"); - logger.warn("WITNESS CHECKING FINISHED UNSUCCESSFULLY"); - } - } - - return res; - - function EvaluateLinearCombination(lc) { - let res = Fr.zero; - - const keys = Object.keys(lc); - keys.forEach((signalId) => { - const signalValue = getWitnessValue(signalId); - const signalFactor = lc[signalId]; - - res = Fr.add(res, Fr.mul(signalValue, signalFactor)); - }); - - return res; - } - - function readLC() { - const lc = {}; - - const buffUL32 = bR1cs.slice(bR1csPos, bR1csPos + 4); - bR1csPos += 4; - const buffUL32V = new DataView(buffUL32.buffer); - const nIdx = buffUL32V.getUint32(0, true); - - const buff = bR1cs.slice(bR1csPos, bR1csPos + (4 + r1cs.n8) * nIdx); - bR1csPos += (4 + r1cs.n8) * nIdx; - const buffV = new DataView(buff.buffer); - for (let i = 0; i < nIdx; i++) { - const idx = buffV.getUint32(i * (4 + r1cs.n8), true); - const val = r1cs.F.fromRprLE(buff, i * (4 + r1cs.n8) + 4); - lc[idx] = val; - } - return lc; - } - - function getWitnessValue(signalId) { - return Fr.fromRprLE(buffWitness.slice(signalId * sFr, signalId * sFr + sFr)); - } -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -var wtns = /*#__PURE__*/Object.freeze({ - __proto__: null, - calculate: wtnsCalculate, - debug: wtnsDebug, - exportJson: wtnsExportJson, - check: wtnsCheck +//#endregion +//#region src/plonk_setup.js +async function pr(e, c, l, d) { + globalThis.gc && globalThis.gc(); + let { fd: f, sections: p } = await r(c, "ptau", 1, 1 << 22, 1 << 24), { curve: m, power: g } = await rn(f, p), { fd: _, sections: v } = await r(e, "r1cs", 1, 1 << 22, 1 << 24), y = await h(_, v, { + loadConstraints: !0, + loadCustomGates: !0 + }), b = m.G1.F.n8 * 2, x = m.G1, S = m.G2.F.n8 * 2, C = m.Fr, w = m.Fr.n8; + d && d.info("Reading r1cs"), await i(_, v, 2); + let T = new Kn(), E = new Kn(), D = y.nVars, O = y.nOutputs + y.nPubInputs; + await ee(m.Fr, y, d), globalThis.gc && globalThis.gc(); + let k = await t(l, "zkey", 1, 14, 1 << 22, 1 << 24); + if (y.prime != m.r) return d && d.error("r1cs curve does not match powers of tau ceremony curve"), -1; + let A = Se(T.length - 1) + 1; + A < 3 && (A = 3); + let j = 2 ** A; + if (d && d.info("Plonk constraints: " + T.length), A > g) return d && d.error(`circuit too big for this power of tau ceremony. ${T.length} > 2**${g}`), -1; + if (!p[12]) return d && d.error("Powers of tau is not prepared."), -1; + let M = new s(j * b), N = p[12][0].p + (2 ** A - 1) * b; + await f.readToBuffer(M, 0, j * b, N); + let [P, F] = ne(), I = {}; + await V(3, "Additions"), globalThis.gc && globalThis.gc(), await R(4, 0, "Amap"), globalThis.gc && globalThis.gc(), await R(5, 1, "Bmap"), globalThis.gc && globalThis.gc(), await R(6, 2, "Cmap"), globalThis.gc && globalThis.gc(), await z(7, 3, "Qm"), globalThis.gc && globalThis.gc(), await z(8, 4, "Ql"), globalThis.gc && globalThis.gc(), await z(9, 5, "Qr"), globalThis.gc && globalThis.gc(), await z(10, 6, "Qo"), globalThis.gc && globalThis.gc(), await z(11, 7, "Qc"), globalThis.gc && globalThis.gc(), await te(12, "sigma"), globalThis.gc && globalThis.gc(), await H(13, "lagrange polynomials"), globalThis.gc && globalThis.gc(), await a(k, 14); + let L = new s((j + 6) * b); + await f.readToBuffer(L, 0, (j + 6) * b, p[2][0].p), await k.write(L), await n(k), globalThis.gc && globalThis.gc(), await U(), await k.close(), await _.close(), await f.close(), d && d.info("Setup Finished"); + return; + async function ee(e, t, n) { + function r(e) { + let t = Object.keys(e); + for (let n = 0; n < t.length; n++) e[t[n]] == 0n && delete e[t[n]]; + } + function i(t, n, i) { + let a = {}; + for (let r in t) a[r] === void 0 ? a[r] = e.mul(n, t[r]) : a[r] = e.add(a[r], e.mul(n, t[r])); + for (let t in i) a[t] === void 0 ? a[t] = i[t] : a[t] = e.add(a[t], i[t]); + return r(a), a; + } + function a(t, n) { + let r = { + k: e.zero, + s: [], + coefs: [] + }, i = []; + for (let n in t) n == 0 ? r.k = e.add(r.k, t[n]) : t[n] != 0n && i.push([Number(n), t[n]]); + for (; i.length > n;) { + let t = i.shift(), n = i.shift(), r = t[0], a = n[0], o = D++, s = e.zero, c = e.neg(t[1]), l = e.neg(n[1]), u = e.one, d = e.zero; + T.push([ + r, + a, + o, + s, + c, + l, + u, + d + ]), E.push([ + r, + a, + t[1], + n[1] + ]), i.push([o, e.one]); + } + for (let e = 0; e < i.length; e++) r.s[e] = i[e][0], r.coefs[e] = i[e][1]; + for (; r.coefs.length < n;) r.s.push(0), r.coefs.push(e.zero); + return r; + } + function o(t) { + let n = a(t, 3), r = n.s[0], i = n.s[1], o = n.s[2], s = e.zero, c = n.coefs[0], l = n.coefs[1], u = n.coefs[2], d = n.k; + T.push([ + r, + i, + o, + s, + c, + l, + u, + d + ]); + } + function s(t, n, r) { + let i = a(t, 1), o = a(n, 1), s = a(r, 1), c = i.s[0], l = o.s[0], u = s.s[0], d = e.mul(i.coefs[0], o.coefs[0]), f = e.mul(i.coefs[0], o.k), p = e.mul(i.k, o.coefs[0]), m = e.neg(s.coefs[0]), h = e.sub(e.mul(i.k, o.k), s.k); + T.push([ + c, + l, + u, + d, + f, + p, + m, + h + ]); + } + function c(t) { + let n = e.zero, r = 0, i = Object.keys(t); + for (let a = 0; a < i.length; a++) t[i[a]] == 0n ? delete t[i[a]] : i[a] == 0 ? n = e.add(n, t[i[a]]) : r++; + return r > 0 ? r.toString() : n == e.zero ? "0" : "k"; + } + function l(e, t, n) { + let a = c(e), l = c(t); + a === "0" || l === "0" ? (r(n), o(n)) : a === "k" ? o(i(t, e[0], n)) : l === "k" ? o(i(e, t[0], n)) : s(e, t, n); + } + for (let t = 1; t <= O; t++) { + let n = t, r = e.zero, i = e.one, a = e.zero, o = e.zero, s = e.zero; + T.push([ + n, + 0, + 0, + r, + i, + a, + o, + s + ]); + } + for (let e = 0; e < t.constraints.length; e++) n && e % 1e4 == 0 && n.debug(`processing constraints: ${e}/${t.nConstraints}`), l(...t.constraints[e]); + } + async function R(e, t, r) { + await a(k, e); + for (let e = 0; e < T.length; e++) await k.writeULE32(T[e][t]), d && e % 1e6 == 0 && d.debug(`writing ${r}: ${e}/${T.length}`); + await n(k); + } + async function z(e, t, r) { + let i = new s(j * w); + for (let e = 0; e < T.length; e++) i.set(T[e][t], e * w), d && e % 1e6 == 0 && d.debug(`writing ${r}: ${e}/${T.length}`); + await a(k, e), await B(i), await n(k), i = await C.batchFromMontgomery(i), I[r] = await m.G1.multiExpAffine(M, i, d, "multiexp " + r); + } + async function B(e) { + let t = await C.ifft(e), n = new s(j * w * 4); + n.set(t, 0); + let r = await C.fft(n); + await k.write(t), await k.write(r); + } + async function V(e, t) { + await a(k, e); + let r = new Uint8Array(8 + 2 * w), i = new DataView(r.buffer); + for (let e = 0; e < E.length; e++) { + let n = E[e], a = 0; + i.setUint32(a, n[0], !0), a += 4, i.setUint32(a, n[1], !0), a += 4, r.set(n[2], a), a += w, r.set(n[3], a), await k.write(r), d && e % 1e6 == 0 && d.debug(`writing ${t}: ${e}/${E.length}`); + } + await n(k); + } + async function te(e, t) { + let r = new s(w * j * 3), i = new Kn(D), o = new Kn(D), c = C.one; + for (let e = 0; e < j; e++) e < T.length ? (p(T[e][0], e), p(T[e][1], j + e), p(T[e][2], j * 2 + e)) : (p(0, e), p(0, j + e), p(0, j * 2 + e)), c = C.mul(c, C.w[A]), d && e % 1e6 == 0 && d.debug(`writing ${t} phase1: ${e}/${T.length}`); + for (let e = 0; e < D; e++) o[e] === void 0 ? console.log("Variable not used") : r.set(i[e], o[e] * w), d && e % 1e6 == 0 && d.debug(`writing ${t} phase2: ${e}/${D}`); + globalThis.gc && globalThis.gc(), await a(k, e); + let l = r.slice(0, j * w); + await B(l), globalThis.gc && globalThis.gc(); + let u = r.slice(j * w, j * w * 2); + await B(u), globalThis.gc && globalThis.gc(); + let f = r.slice(j * w * 2, j * w * 3); + await B(f), globalThis.gc && globalThis.gc(), await n(k), l = await C.batchFromMontgomery(l), u = await C.batchFromMontgomery(u), f = await C.batchFromMontgomery(f), I.S1 = await m.G1.multiExpAffine(M, l, d, "multiexp S1"), globalThis.gc && globalThis.gc(), I.S2 = await m.G1.multiExpAffine(M, u, d, "multiexp S2"), globalThis.gc && globalThis.gc(), I.S3 = await m.G1.multiExpAffine(M, f, d, "multiexp S3"), globalThis.gc && globalThis.gc(); + function p(e, t) { + i[e] === void 0 ? o[e] = t : r.set(i[e], t * w); + let n; + n = t < j ? c : t < 2 * j ? C.mul(c, P) : C.mul(c, F), i[e] = n; + } + } + async function H(e, t) { + await a(k, e); + let r = Math.max(O, 1); + for (let e = 0; e < r; e++) { + let n = new s(j * w); + n.set(C.one, e * w), await B(n), d && d.debug(`writing ${t} ${e}/${r}`); + } + await n(k); + } + async function U() { + await a(k, 1), await k.writeULE32(2), await n(k), await a(k, 2); + let e = m.q, t = (Math.floor((u.bitLength(e) - 1) / 64) + 1) * 8, r = m.r, i = (Math.floor((u.bitLength(r) - 1) / 64) + 1) * 8; + await k.writeULE32(t), await o(k, e, t), await k.writeULE32(i), await o(k, r, i), await k.writeULE32(D), await k.writeULE32(O), await k.writeULE32(j), await k.writeULE32(E.length), await k.writeULE32(T.length), await k.write(P), await k.write(F), await k.write(x.toAffine(I.Qm)), await k.write(x.toAffine(I.Ql)), await k.write(x.toAffine(I.Qr)), await k.write(x.toAffine(I.Qo)), await k.write(x.toAffine(I.Qc)), await k.write(x.toAffine(I.S1)), await k.write(x.toAffine(I.S2)), await k.write(x.toAffine(I.S3)); + let s; + s = await f.read(S, p[3][0].p + S), await k.write(s), await n(k); + } + function ne() { + let e = C.two; + for (; n(e, [], A);) C.add(e, C.one); + let t = C.add(e, C.one); + for (; n(t, [e], A);) C.add(t, C.one); + return [e, t]; + function n(e, t, n) { + let r = 2 ** n, i = C.one; + for (let a = 0; a < r; a++) { + if (C.eq(e, i)) return !0; + for (let n = 0; n < t.length; n++) if (C.eq(e, C.mul(t[n], i))) return !0; + i = C.mul(i, C.w[n]); + } + return !1; + } + } +} +//#endregion +//#region src/proof.js +var mr = class { + constructor(e, t) { + this.curve = e, this.logger = t, this.resetProof(); + } + resetProof() { + this.polynomials = {}, this.evaluations = {}; + } + addPolynomial(e, t) { + e in this.polynomials && this.logger.warn(`proof: polynomial.${e} already exist in proof`), this.polynomials[e] = t; + } + getPolynomial(e) { + return e in this.polynomials || this.logger.warn(`proof: polynomial ${e} does not exist in proof`), this.polynomials[e]; + } + addEvaluation(e, t) { + e in this.evaluations && this.logger.warn(`proof: evaluations.${e} already exist in proof`), this.evaluations[e] = t; + } + getEvaluation(e) { + return e in this.evaluations || this.logger.warn(`proof: evaluation ${e} does not exist in proof`), this.evaluations[e]; + } + toObjectProof(e = !0) { + let t = e ? { + polynomials: {}, + evaluations: {} + } : {}; + return Object.keys(this.polynomials).forEach((n) => { + let r = this.curve.G1.toObject(this.polynomials[n]); + e ? t.polynomials[n] = r : t[n] = r; + }), Object.keys(this.evaluations).forEach((n) => { + let r = this.curve.Fr.toObject(this.evaluations[n]); + e ? t.evaluations[n] = r : t[n] = r; + }), t; + } + fromObjectProof(e) { + this.resetProof(), Object.keys(e.polynomials).forEach((t) => { + this.polynomials[t] = this.curve.G1.fromObject(e.polynomials[t]); + }), Object.keys(e.evaluations).forEach((t) => { + this.evaluations[t] = this.curve.Fr.fromObject(e.evaluations[t]); + }); + } +}, hr = BigInt(0), gr = BigInt(1), _r = BigInt(2), vr = BigInt(7), yr = BigInt(256), br = BigInt(113), xr = [], Sr = [], Cr = []; +for (let e = 0, t = gr, n = 1, r = 0; e < 24; e++) { + [n, r] = [r, (2 * n + 3 * r) % 5], xr.push(2 * (5 * r + n)), Sr.push((e + 1) * (e + 2) / 2 % 64); + let i = hr; + for (let e = 0; e < 7; e++) t = (t << gr ^ (t >> vr) * br) % yr, t & _r && (i ^= gr << (gr << BigInt(e)) - gr); + Cr.push(i); +} +var wr = U(Cr, !0), Tr = wr[0], Er = wr[1], Dr = (e, t, n) => n > 32 ? ue(e, t, n) : ce(e, t, n), Or = (e, t, n) => n > 32 ? de(e, t, n) : le(e, t, n); +function kr(e, t = 24) { + let n = new Uint32Array(10); + for (let r = 24 - t; r < 24; r++) { + for (let t = 0; t < 10; t++) n[t] = e[t] ^ e[t + 10] ^ e[t + 20] ^ e[t + 30] ^ e[t + 40]; + for (let t = 0; t < 10; t += 2) { + let r = (t + 8) % 10, i = (t + 2) % 10, a = n[i], o = n[i + 1], s = Dr(a, o, 1) ^ n[r], c = Or(a, o, 1) ^ n[r + 1]; + for (let n = 0; n < 50; n += 10) e[t + n] ^= s, e[t + n + 1] ^= c; + } + let t = e[2], i = e[3]; + for (let n = 0; n < 24; n++) { + let r = Sr[n], a = Dr(t, i, r), o = Or(t, i, r), s = xr[n]; + t = e[s], i = e[s + 1], e[s] = a, e[s + 1] = o; + } + for (let t = 0; t < 50; t += 10) { + for (let r = 0; r < 10; r++) n[r] = e[t + r]; + for (let r = 0; r < 10; r++) e[t + r] ^= ~n[(r + 2) % 10] & n[(r + 4) % 10]; + } + e[0] ^= Tr[r], e[1] ^= Er[r]; + } + P(n); +} +var Ar = class e { + state; + pos = 0; + posOut = 0; + finished = !1; + state32; + destroyed = !1; + blockLen; + suffix; + outputLen; + enableXOF = !1; + rounds; + constructor(e, t, n, r = !1, i = 24) { + if (this.blockLen = e, this.suffix = t, this.outputLen = n, this.enableXOF = r, this.rounds = i, k(n, "outputLen"), !(0 < e && e < 200)) throw Error("only keccak-f1600 function is supported"); + this.state = new Uint8Array(200), this.state32 = N(this.state); + } + clone() { + return this._cloneInto(); + } + keccak() { + R(this.state32), kr(this.state32, this.rounds), R(this.state32), this.posOut = 0, this.pos = 0; + } + update(e) { + j(this), A(e); + let { blockLen: t, state: n } = this, r = e.length; + for (let i = 0; i < r;) { + let a = Math.min(t - this.pos, r - i); + for (let t = 0; t < a; t++) n[this.pos++] ^= e[i++]; + this.pos === t && this.keccak(); + } + return this; + } + finish() { + if (this.finished) return; + this.finished = !0; + let { state: e, suffix: t, pos: n, blockLen: r } = this; + e[n] ^= t, t & 128 && n === r - 1 && this.keccak(), e[r - 1] ^= 128, this.keccak(); + } + writeInto(e) { + j(this, !1), A(e), this.finish(); + let t = this.state, { blockLen: n } = this; + for (let r = 0, i = e.length; r < i;) { + this.posOut >= n && this.keccak(); + let a = Math.min(n - this.posOut, i - r); + e.set(t.subarray(this.posOut, this.posOut + a), r), this.posOut += a, r += a; + } + return e; + } + xofInto(e) { + if (!this.enableXOF) throw Error("XOF is not possible for this instance"); + return this.writeInto(e); + } + xof(e) { + return k(e), this.xofInto(new Uint8Array(e)); + } + digestInto(e) { + if (M(e, this), this.finished) throw Error("digest() was already called"); + return this.writeInto(e), this.destroy(), e; + } + digest() { + return this.digestInto(new Uint8Array(this.outputLen)); + } + destroy() { + this.destroyed = !0, P(this.state); + } + _cloneInto(t) { + let { blockLen: n, suffix: r, outputLen: i, rounds: a, enableXOF: o } = this; + return t ||= new e(n, r, i, o, a), t.state32.set(this.state32), t.pos = this.pos, t.posOut = this.posOut, t.finished = this.finished, t.rounds = a, t.suffix = r, t.outputLen = i, t.enableXOF = o, t.destroyed = this.destroyed, t; + } +}, jr = /* @__PURE__ */ ((e, t, n, r = {}) => z(() => new Ar(t, e, n), r))(1, 136, 32), Mr = 0, Nr = 1, Pr = class { + constructor(e) { + this.G1 = e.G1, this.Fr = e.Fr, this.reset(); + } + reset() { + this.data = []; + } + addPolCommitment(e) { + this.data.push({ + type: Mr, + data: e + }); + } + addScalar(e) { + this.data.push({ + type: Nr, + data: e + }); + } + getChallenge() { + if (this.data.length === 0) throw Error("Keccak256Transcript: No data to generate a transcript"); + let e = 0, t = 0; + this.data.forEach((n) => Mr === n.type ? e++ : t++); + let n = new Uint8Array(t * this.Fr.n8 + e * this.G1.F.n8 * 2), r = 0; + for (let e = 0; e < this.data.length; e++) Mr === this.data[e].type ? (this.G1.toRprUncompressed(n, r, this.data[e].data), r += this.G1.F.n8 * 2) : (this.Fr.toRprBE(n, r, this.data[e].data), r += this.Fr.n8); + let i = u.fromRprBE(jr(n)); + return this.Fr.e(i); + } +}, Fr = class { + static getZ1(e) { + return [ + e.zero, + e.add(e.e(-1), e.w[2]), + e.e(-2), + e.sub(e.e(-1), e.w[2]) + ]; + } + static getZ2(e) { + return [ + e.zero, + e.add(e.zero, e.mul(e.e(-2), e.w[2])), + e.e(4), + e.sub(e.zero, e.mul(e.e(-2), e.w[2])) + ]; + } + static getZ3(e) { + return [ + e.zero, + e.add(e.e(2), e.mul(e.e(2), e.w[2])), + e.e(-8), + e.sub(e.e(2), e.mul(e.e(2), e.w[2])) + ]; + } + static mul2(e, t, n, r, i, a) { + let o = this.getZ1(a), s, c, l = a.mul(e, t), u = a.mul(e, r), d = a.mul(n, t), f = a.mul(n, r); + s = l; + let p = a.add(u, d), m = f; + return c = p, i && (c = a.add(c, a.mul(o[i], m))), [s, c]; + } + static mul3(e, t, n, r, i, a, o, s) { + let c = this.getZ1(s), l = this.getZ2(s), u, d, f = s.mul(e, t), p = s.mul(e, i), m = s.mul(r, t), h = s.mul(r, i); + u = s.mul(f, n); + let g = s.mul(m, n); + g = s.add(g, s.mul(p, n)), g = s.add(g, s.mul(f, a)); + let _ = s.mul(h, n); + if (_ = s.add(_, s.mul(p, a)), _ = s.add(_, s.mul(m, a)), d = g, o) { + let e = s.mul(h, a); + d = s.add(d, s.mul(c[o], _)), d = s.add(d, s.mul(l[o], e)); + } + return [u, d]; + } + static mul4(e, t, n, r, i, a, o, s, c, l) { + let u = this.getZ1(l), d = this.getZ2(l), f = this.getZ3(l), p, m, h = l.mul(e, t), g = l.mul(e, a), _ = l.mul(i, t), v = l.mul(i, a), y = l.mul(n, r), b = l.mul(n, s), x = l.mul(o, r), S = l.mul(o, s); + p = l.mul(h, y); + let C = l.mul(_, y); + C = l.add(C, l.mul(g, y)), C = l.add(C, l.mul(h, x)), C = l.add(C, l.mul(h, b)); + let w = l.mul(v, y); + w = l.add(w, l.mul(_, x)), w = l.add(w, l.mul(_, b)), w = l.add(w, l.mul(g, x)), w = l.add(w, l.mul(g, b)), w = l.add(w, l.mul(h, S)); + let T = l.mul(g, S); + T = l.add(T, l.mul(_, S)), T = l.add(T, l.mul(v, b)), T = l.add(T, l.mul(v, x)); + let E = l.mul(v, S); + return m = C, c && (m = l.add(m, l.mul(u[c], w)), m = l.add(m, l.mul(d[c], T)), m = l.add(m, l.mul(f[c], E))), [p, m]; + } +}, X = class e { + constructor(e, t, n) { + this.coef = e, this.curve = t, this.Fr = t.Fr, this.G1 = t.G1, this.logger = n; + } + static async fromEvaluations(t, n, r) { + return new e(await n.Fr.ifft(t), n, r); + } + static fromCoefficientsArray(t, n, r) { + let i = n.Fr, a = t.length > 32768 ? new s(t.length * i.n8) : new Uint8Array(t.length * i.n8); + for (let e = 0; e < t.length; e++) a.set(t[e], e * i.n8); + return new e(a, n, r); + } + static fromPolynomial(t, n, r) { + let i = t.length(), a = n.Fr, o = i > 32768 ? new s(i * a.n8) : new Uint8Array(i * a.n8); + return o.set(t.coef.slice(), 0), new e(o, n, r); + } + isEqual(e) { + let t = this.degree(); + if (t !== e.degree()) return !1; + for (let n = 0; n < t + 1; n++) if (!this.Fr.eq(this.getCoef(n), e.getCoef(n))) return !1; + return !0; + } + blindCoefficients(e) { + e ||= []; + let t = this.length() + e.length > 32768 ? new s((this.length() + e.length) * this.Fr.n8) : new Uint8Array((this.length() + e.length) * this.Fr.n8); + t.set(this.coef, 0); + for (let n = 0; n < e.length; n++) t.set(this.Fr.add(t.slice((this.length() + n) * this.Fr.n8, (this.length() + n + 1) * this.Fr.n8), e[n]), (this.length() + n) * this.Fr.n8), t.set(this.Fr.sub(t.slice(n * this.Fr.n8, (n + 1) * this.Fr.n8), e[n]), n * this.Fr.n8); + this.coef = t; + } + getCoef(e) { + let t = e * this.Fr.n8; + return t + this.Fr.n8 > this.coef.byteLength ? this.Fr.zero : this.coef.slice(t, t + this.Fr.n8); + } + setCoef(e, t) { + if (e > this.length() - 1) throw Error("Coef index is not available"); + this.coef.set(t, e * this.Fr.n8); + } + static async to4T(e, t, n, r) { + n ||= []; + let i = await r.ifft(e), a = t * 4 > 32768 ? new s(t * 4 * r.n8) : new Uint8Array(t * 4 * r.n8); + a.set(i, 0); + let o = await r.fft(a); + if (n.length === 0) return [i, o]; + let c = t + n.length > 32768 ? new s((t + n.length) * r.n8) : new Uint8Array((t + n.length) * r.n8); + c.set(i, 0); + for (let e = 0; e < n.length; e++) c.set(r.add(c.slice((t + e) * r.n8, (t + e + 1) * r.n8), n[e]), (t + e) * r.n8), c.set(r.sub(c.slice(e * r.n8, (e + 1) * r.n8), n[e]), e * r.n8); + return [c, o]; + } + length() { + let e = this.coef.byteLength / this.Fr.n8; + if (e !== Math.floor(this.coef.byteLength / this.Fr.n8)) throw Error("Polynomial coefficients buffer has incorrect size"); + return e === 0 && this.logger && this.logger.warn("Polynomial has length zero"), e; + } + degree() { + for (let e = this.length() - 1; e > 0; e--) { + let t = e * this.Fr.n8; + if (!this.Fr.eq(this.Fr.zero, this.coef.slice(t, t + this.Fr.n8))) return e; + } + return 0; + } + evaluate(e) { + let t = this.Fr.zero; + for (let n = this.degree() + 1; n > 0; n--) { + let r = n * this.Fr.n8, i = this.coef.slice(r - this.Fr.n8, r); + t = this.Fr.add(i, this.Fr.mul(t, e)); + } + return t; + } + fastEvaluate(e) { + let t = this.Fr, n = this.degree() + 1, r = parseInt(n / 3), i = n - r * 3, a = [], o = []; + o[0] = t.one; + for (let n = 0; n < 3; n++) { + a[n] = t.zero; + let s = n === 2 ? r + i : r; + for (let i = s; i > 0; i--) a[n] = t.add(this.getCoef(n * r + i - 1), t.mul(a[n], e)), n === 0 && (o[0] = t.mul(o[0], e)); + } + for (let e = 1; e < 3; e++) a[0] = t.add(a[0], t.mul(o[e - 1], a[e])), o[e] = t.mul(o[e - 1], o[0]); + return a[0]; + } + add(e, t) { + let n = !1; + e.length() > this.length() && (n = !0); + let r = this.length(), i = e.length(); + for (let a = 0; a < Math.max(r, i); a++) { + let o = a * this.Fr.n8, s = a < r ? this.coef.slice(o, o + this.Fr.n8) : this.Fr.zero, c = a < i ? e.coef.slice(o, o + this.Fr.n8) : this.Fr.zero; + t !== void 0 && (c = this.Fr.mul(c, t)), n ? e.coef.set(this.Fr.add(s, c), o) : this.coef.set(this.Fr.add(s, c), o); + } + n && (delete this.coef, this.coef = e.coef); + } + sub(e, t) { + let n = !1; + e.length() > this.length() && (n = !0); + let r = this.length(), i = e.length(); + for (let a = 0; a < Math.max(r, i); a++) { + let o = a * this.Fr.n8, s = a < r ? this.coef.slice(o, o + this.Fr.n8) : this.Fr.zero, c = a < i ? e.coef.slice(o, o + this.Fr.n8) : this.Fr.zero; + t !== void 0 && (c = this.Fr.mul(c, t)), n ? e.coef.set(this.Fr.sub(s, c), o) : this.coef.set(this.Fr.sub(s, c), o); + } + n && (delete this.coef, this.coef = e.coef); + } + mulScalar(e) { + for (let t = 0; t < this.length(); t++) { + let n = t * this.Fr.n8; + this.coef.set(this.Fr.mul(this.coef.slice(n, n + this.Fr.n8), e), n); + } + } + addScalar(e) { + let t = this.length() === 0 ? this.Fr.zero : this.coef.slice(0, this.Fr.n8); + this.coef.set(this.Fr.add(t, e), 0); + } + subScalar(e) { + let t = this.length() === 0 ? this.Fr.zero : this.coef.slice(0, this.Fr.n8); + this.coef.set(this.Fr.sub(t, e), 0); + } + byXSubValue(t) { + let n = this.Fr, r = n.eq(n.zero, this.getCoef(this.length() - 1)) ? this.length() : this.length() + 1, i = new e(r > 32768 ? new s(r * n.n8) : new Uint8Array(r * n.n8), this.curve, this.logger); + i.coef.set(this.coef.slice(0, (r - 1) * n.n8), 32), this.mulScalar(n.neg(t)), i.add(this), this.coef = i.coef; + } + byXNSubValue(t, n) { + let r = this.Fr, i = this.length() - t - 1 >= this.degree() ? this.length() : this.length() + t, a = new e(i > 32768 ? new s(i * r.n8) : new Uint8Array(i * r.n8), this.curve, this.logger); + a.coef.set(this.coef.slice(0, (this.degree() + 1) * 32), t * 32), this.mulScalar(n), a.add(this), this.coef = a.coef; + } + divBy(t) { + let n = this.Fr, r = this.degree(), i = t.degree(), a = new e(this.coef, this.curve, this.logger); + this.coef = this.length() > 32768 ? new s(this.length() * n.n8) : new Uint8Array(this.length() * n.n8); + for (let e = r - i; e >= 0; e--) { + this.setCoef(e, n.div(a.getCoef(e + i), t.getCoef(i))); + for (let r = 0; r <= i; r++) a.setCoef(e + r, n.sub(a.getCoef(e + r), n.mul(this.getCoef(e), t.getCoef(r)))); + } + return a; + } + divByMonic(t, n) { + let r = this.Fr, i = this.degree(), a = new e(this.length() > 32768 ? new s(this.length() * r.n8) : new Uint8Array(this.length() * r.n8), this.curve, this.logger), o = []; + for (let e = 0; e < t; e++) a.setCoef(i - e - t, this.getCoef(i - e)), o[e] = this.getCoef(i - e); + let c = t, l = 0; + for (let e = 0; e < c; e++) for (let s = i - 2 * t - e; s >= 0 && !(s < 0); s -= c) { + let i = e; + o[i] = r.add(this.getCoef(s + t), r.mul(o[i], n)), a.setCoef(s, o[i]), l = (l + 1) % t; + } + this.coef = a.coef; + } + divByVanishing(t, n) { + if (this.degree() < t) throw Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); + let r = this.Fr, i = new e(this.coef, this.curve, this.logger); + this.coef = this.length() > 32768 ? new s(this.length() * r.n8) : new Uint8Array(this.length() * r.n8); + for (let e = this.length() - 1; e >= t; e--) { + let a = i.getCoef(e); + r.eq(r.zero, a) || (i.setCoef(e, r.zero), i.setCoef(e - t, r.add(i.getCoef(e - t), r.mul(n, a))), this.setCoef(e - t, r.add(this.getCoef(e - t), a))); + } + return i; + } + divByVanishing2(t, n) { + if (this.degree() < t) throw Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); + let r = this.Fr, i = new e(this.coef, this.curve, this.logger); + this.coef = this.length() > 32768 ? new s(this.length() * r.n8) : new Uint8Array(this.length() * r.n8); + let a = this.length() - t, o = Math.floor(a / 3), c = a - 2 * o; + console.log(a), console.log(o + " " + c); + for (let e = 0; e < 3; e++) { + console.log("> Thread " + e); + for (let a = e === 0 ? c : o; a > 0; a--) { + let s = a - 1; + e !== 0 && (s += (e - 1) * o + c); + let l = s + t, u = i.getCoef(l); + r.eq(r.zero, u) || (i.setCoef(l, r.zero), i.setCoef(s, r.add(i.getCoef(s), r.mul(n, u))), this.setCoef(s, r.add(this.getCoef(s), u)), console.log(s + " <-- " + l)); + } + } + return this.print(), i; + } + fastDivByVanishing(t) { + let n = this.Fr; + for (let r = 0; r < t.length; r++) { + let i = t[r][0], a = t[r][1]; + if (this.degree() < i) throw Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); + let o = this.length() - i, c = Math.floor(o / 5 / i), l = c * i, u = o - 5 * l, d = new e(this.length() > 32768 ? new s(this.length() * n.n8) : new Uint8Array(this.length() * n.n8), this.curve, this.logger), f = this.coef; + this.coef = d.coef, d.coef = f; + for (let e = 0; e < 5; e++) { + let t = (e + 1) * l + u; + for (let e = 0; e < i; e++) this.setCoef(t + e - i, d.getCoef(t + e)); + for (let e = 0; e < l - i; e++) { + let r = t - e - 1, o = n.add(d.getCoef(r), n.mul(a, this.getCoef(r))); + this.setCoef(r - i, o); + } + } + let p = u, m = u; + for (let e = 0; e < i && m; e++) this.setCoef(p - e - 1, d.getCoef(p + i - e - 1)), m--; + for (let e = 0; e < m; e++) { + let t = p - e - 1, r = n.add(d.getCoef(t), n.mul(a, this.getCoef(t))); + this.setCoef(t - i, r); + } + let h = [], g = n.one; + for (let e = 0; e < c; e++) g = n.mul(g, a); + let _ = n.one; + for (let e = 5; e > 0; e--) { + let t = e - 1, r = t * l + u; + h[t] = []; + for (let a = 0; a < i; a++) h[t][a] = this.getCoef(r + a), e !== 5 && (h[t][a] = n.add(h[t][a], n.mul(g, h[t + 1][a]))); + _ = n.mul(_, g); + } + for (let e = 0; e < 5; e++) { + let t = e * l + u, r = a, o = i - 1, s = e === 0 ? u : l; + for (let c = 0; c < s; c++) { + let s = t - c - 1, l = n.add(this.getCoef(s), n.mul(r, h[e][o])); + this.setCoef(s, l), o === 0 ? (o = i - 1, r = n.mul(r, a)) : o--; + } + } + } + } + divByXSubValue(e) { + let t = this.length() > 32768 ? new s(this.length() * this.Fr.n8) : new Uint8Array(this.length() * this.Fr.n8); + t.set(this.Fr.zero, (this.length() - 1) * this.Fr.n8), t.set(this.coef.slice((this.length() - 1) * this.Fr.n8, this.length() * this.Fr.n8), (this.length() - 2) * this.Fr.n8); + for (let n = this.length() - 3; n >= 0; n--) { + let r = n * this.Fr.n8; + t.set(this.Fr.add(this.coef.slice(r + this.Fr.n8, r + 2 * this.Fr.n8), this.Fr.mul(e, t.slice(r + this.Fr.n8, r + 2 * this.Fr.n8))), n * this.Fr.n8); + } + if (!this.Fr.eq(this.coef.slice(0, this.Fr.n8), this.Fr.mul(this.Fr.neg(e), t.slice(0, this.Fr.n8)))) throw Error("Polynomial does not divide"); + this.coef = t; + } + divZh(e, t = 4) { + for (let t = 0; t < e; t++) { + let e = t * this.Fr.n8; + this.coef.set(this.Fr.neg(this.coef.slice(e, e + this.Fr.n8)), e); + } + let n = this.coef.byteLength / this.Fr.n8; + for (let r = e; r < n; r++) { + let n = r * this.Fr.n8, i = this.Fr.sub(this.coef.slice((r - e) * this.Fr.n8, (r - e) * this.Fr.n8 + this.Fr.n8), this.coef.slice(n, n + this.Fr.n8)); + if (this.coef.set(i, n), r > e * (t - 1) - t && !this.Fr.isZero(i)) throw Error("Polynomial is not divisible"); + } + return this; + } + divByZerofier(e, t) { + let n = this.Fr, r = n.inv(t), i = n.neg(r), a = n.eq(n.one, i), o = n.eq(n.negone, i); + if (!a) for (let t = 0; t < e; t++) { + let e = t * this.Fr.n8, r; + r = o ? n.neg(this.coef.slice(e, e + this.Fr.n8)) : n.mul(i, this.coef.slice(e, e + this.Fr.n8)), this.coef.set(r, e); + } + a = n.eq(n.one, r), o = n.eq(n.negone, r); + for (let t = e; t < this.length(); t++) { + let i = t * this.Fr.n8, s = (t - e) * this.Fr.n8, c = this.Fr.sub(this.coef.slice(s, s + this.Fr.n8), this.coef.slice(i, i + this.Fr.n8)); + if (a || (c = o ? n.neg(c) : n.mul(r, c)), this.coef.set(c, i), t > this.length() - e - 1 && !this.Fr.isZero(c)) throw Error("Polynomial is not divisible"); + } + return this; + } + byX() { + let e = this.length() + 1 > 32768 ? new s(this.coef.byteLength + this.Fr.n8) : new Uint8Array(this.coef.byteLength + this.Fr.n8); + e.set(this.Fr.zero, 0), e.set(this.coef, this.Fr.n8), this.coef = e; + } + static async expX(t, n, r = !1) { + let i = t.Fr; + if (n < 1) throw Error("Compute a new polynomial to a zero or negative number is not allowed"); + if (n === 1) return await e.fromEvaluations(t.coef, t.curve, t.logger); + let a = r ? t.degree() : t.length() - 1, o = a * n + 1 > 32768 ? new s((a * n + 1) * i.n8) : new Uint8Array((a * n + 1) * i.n8); + o.set(t.getCoef(0), 0); + for (let e = 1; e <= a; e++) { + let r = e * i.n8, a = t.getCoef(e); + o.set(a, r * n); + } + return new e(o, t.curve, t.logger); + } + split(t, n, r) { + if (t < 1) throw Error(`Polynomials can't be split in ${t} parts`); + if (t === 1) return [this]; + if (r.length !== 0 && r.length < t - 1) throw Error(`Blinding factors length must be ${t - 1}`); + let i = (n + 1) * this.Fr.n8, a = [], o = Math.ceil((this.degree() + 1) * this.Fr.n8 / i); + if (o < t) for (let n = o; n < t; n++) a[n] = new e(new Uint8Array(this.Fr.n8), this.curve, this.logger); + t = Math.min(t, o); + for (let n = 0; n < t; n++) { + let o = t - 1 === n, c = o ? this.coef.byteLength - (t - 1) * i : i + this.Fr.n8; + a[n] = new e(c / this.Fr.n8 > 32768 ? new s(c) : new Uint8Array(c), this.curve, this.logger); + let l = n * i, u = o ? this.coef.byteLength : (n + 1) * i; + if (a[n].coef.set(this.coef.slice(l, u), 0), o || a[n].coef.set(r[n], i), n !== 0) { + let e = this.Fr.sub(a[n].coef.slice(0, this.Fr.n8), r[n - 1]); + a[n].coef.set(e, 0); + } + o && a[n].truncate(); + } + return a; + } + truncate() { + let e = this.degree(); + if (e + 1 < this.coef.byteLength / this.Fr.n8) { + let t = e + 1 > 32768 ? new s((e + 1) * this.Fr.n8) : new Uint8Array((e + 1) * this.Fr.n8); + t.set(this.coef.slice(0, (e + 1) * this.Fr.n8), 0), this.coef = t; + } + } + static lagrangePolynomialInterpolation(t, n, r) { + let i = r.Fr, a = o(0); + for (let e = 1; e < t.length; e++) a.add(o(e)); + return a; + function o(a) { + let o; + for (let n = 0; n < t.length; n++) n !== a && (o === void 0 ? (o = new e(t.length > 32768 ? new s(t.length * i.n8) : new Uint8Array(t.length * i.n8), r), o.setCoef(0, i.neg(t[n])), o.setCoef(1, i.one)) : o.byXSubValue(t[n])); + let c = o.evaluate(t[a]); + c = i.inv(c); + let l = i.mul(n[a], c); + return o.mulScalar(l), o; + } + } + static zerofierPolynomial(t, n) { + let r = n.Fr, i = new e(t.length + 1 > 32768 ? new s((t.length + 1) * r.n8) : new Uint8Array((t.length + 1) * r.n8), n); + i.setCoef(0, r.neg(t[0])), i.setCoef(1, r.one); + for (let e = 1; e < t.length; e++) i.byXSubValue(t[e]); + return i; + } + print() { + let e = this.Fr, t = ""; + for (let n = this.degree(); n >= 0; n--) { + let r = this.getCoef(n); + e.eq(e.zero, r) || (e.isNegative(r) ? t += " - " : n !== this.degree() && (t += " + "), t += e.toString(r), n > 0 && (t += n > 1 ? "x^" + n : "x")); + } + console.log(t); + } + async multiExponentiation(e, t) { + let n = this.coef.byteLength / this.Fr.n8, r = e.slice(0, n * this.G1.F.n8 * 2), i = await this.Fr.batchFromMontgomery(this.coef), a = await this.G1.multiExpAffine(r, i, this.logger, t); + return a = this.G1.toAffine(a), a; + } +}, Z = class e { + constructor(e, t, n) { + this.eval = e, this.curve = t, this.Fr = t.Fr, this.logger = n; + } + static async fromPolynomial(t, n, r, i) { + let a = new s(t.length() * n * r.Fr.n8); + return a.set(t.coef, 0), new e(await r.Fr.fft(a), r, i); + } + getEvaluation(e) { + let t = e * this.Fr.n8; + if (t + this.Fr.n8 > this.eval.byteLength) throw Error("Evaluations.getEvaluation() out of bounds"); + return this.eval.slice(t, t + this.Fr.n8); + } + length() { + let e = this.eval.byteLength / this.Fr.n8; + if (e !== Math.floor(this.eval.byteLength / this.Fr.n8)) throw Error("Polynomial evaluations buffer has incorrect size"); + return e === 0 && this.logger.warn("Polynomial has length zero"), e; + } +}, { stringifyBigInts: Ir } = p; +async function Lr(t, n, r, i) { + let { fd: a, sections: o } = await e.readBinFile(n, "wtns", 2, 1 << 25, 1 << 23); + r && r.debug("> Reading witness file"); + let c = await tt(a, o); + r && r.debug("> Reading zkey file"); + let { fd: l, sections: d } = await e.readBinFile(t, "zkey", 2, 1 << 25, 1 << 23), f = await Ve(l, d, void 0, i); + if (f.protocol != "plonk") throw Error("zkey file is not plonk"); + if (!u.eq(f.r, c.q)) throw Error("Curve of the witness does not match the curve of the proving key"); + if (c.nWitness != f.nVars - f.nAdditions) throw Error(`Invalid witness length. Circuit: ${f.nVars}, witness: ${c.nWitness}, ${f.nAdditions}`); + let p = f.curve, m = p.Fr, h = p.Fr.n8, g = f.domainSize * h; + r && (r.debug("----------------------------"), r.debug(" PLONK PROVE SETTINGS"), r.debug(` Curve: ${p.name}`), r.debug(` Circuit power: ${f.power}`), r.debug(` Domain size: ${f.domainSize}`), r.debug(` Vars: ${f.nVars}`), r.debug(` Public vars: ${f.nPublic}`), r.debug(` Constraints: ${f.nConstraints}`), r.debug(` Additions: ${f.nAdditions}`), r.debug("----------------------------")), r && r.debug("> Reading witness file data"); + let _ = await e.readSection(a, o, 2); + _.set(m.zero, 0); + let v = new s(h * f.nAdditions), y = {}, b = {}, x = {}, S = {}, C = new mr(p, r), w = new Pr(p); + r && r.debug("> Reading Section 3. Additions"), await O(), r && r.debug("> Reading Section 12. Sigma1, Sigma2 & Sigma 3"), r && r.debug("··· Reading Sigma polynomials "), b.Sigma1 = new X(new s(g), p, r), b.Sigma2 = new X(new s(g), p, r), b.Sigma3 = new X(new s(g), p, r), await l.readToBuffer(b.Sigma1.coef, 0, g, d[12][0].p), await l.readToBuffer(b.Sigma2.coef, 0, g, d[12][0].p + 5 * g), await l.readToBuffer(b.Sigma3.coef, 0, g, d[12][0].p + 10 * g), r && r.debug("··· Reading Sigma evaluations"), x.Sigma1 = new Z(new s(g * 4), p, r), x.Sigma2 = new Z(new s(g * 4), p, r), x.Sigma3 = new Z(new s(g * 4), p, r), await l.readToBuffer(x.Sigma1.eval, 0, g * 4, d[12][0].p + g), await l.readToBuffer(x.Sigma2.eval, 0, g * 4, d[12][0].p + 6 * g), await l.readToBuffer(x.Sigma3.eval, 0, g * 4, d[12][0].p + 11 * g), r && r.debug("> Reading Section 14. Powers of Tau"); + let T = await e.readSection(l, d, 14), E = []; + for (let e = 1; e <= f.nPublic; e++) { + let t = _.slice(e * m.n8, e * m.n8 + m.n8); + E.push(u.fromRprLE(t)); + } + r && r.debug(""), r && r.debug("> ROUND 1"), await j(), r && r.debug("> ROUND 2"), await N(), r && r.debug("> ROUND 3"), await F(), r && r.debug("> ROUND 4"), await L(), r && r.debug("> ROUND 5"), await ee(), await l.close(), await a.close(); + let D = C.toObjectProof(!1); + return D.protocol = "plonk", D.curve = p.name, r && r.debug("PLONK PROVER FINISHED"), { + proof: Ir(D), + publicSignals: Ir(E) + }; + async function O() { + r && r.debug("··· Computing additions"); + let t = await e.readSection(l, d, 3), n = 8 + h * 2; + for (let e = 0; e < f.nAdditions; e++) { + r && e !== 0 && e % 1e5 == 0 && r.debug(` addition ${e}/${f.nAdditions}`); + let i = e * n, a = k(t, i); + i += 4; + let o = k(t, i); + i += 4; + let s = t.slice(i, i + h); + i += h; + let c = t.slice(i, i + h), l = A(a), u = A(o), d = m.add(m.mul(s, l), m.mul(c, u)); + v.set(d, h * e); + } + } + function k(e, t) { + let n = e.slice(t, t + 4); + return new DataView(n.buffer, n.byteOffset, n.byteLength).getUint32(0, !0); + } + function A(e) { + return e < f.nVars - f.nAdditions ? _.slice(e * h, e * h + h) : e < f.nVars ? v.slice((e - (f.nVars - f.nAdditions)) * h, (e - (f.nVars - f.nAdditions)) * h + h) : p.Fr.zero; + } + async function j() { + S.b = []; + for (let e = 1; e <= 11; e++) S.b[e] = p.Fr.random(); + r && r.debug("> Computing A, B, C wire polynomials"), await M(), r && r.debug("> Computing A, B, C MSM"); + let e = await b.A.multiExponentiation(T, "A"), t = await b.B.multiExponentiation(T, "B"), n = await b.C.multiExponentiation(T, "C"); + return C.addPolynomial("A", e), C.addPolynomial("B", t), C.addPolynomial("C", n), 0; + } + async function M() { + r && r.debug("··· Reading data from zkey file"), y.A = new s(g), y.B = new s(g), y.C = new s(g); + let t = await e.readSection(l, d, 4), n = await e.readSection(l, d, 5), i = await e.readSection(l, d, 6); + for (let e = 0; e < f.nConstraints; e++) { + let r = e * h, a = e * 4, o = k(t, a); + y.A.set(A(o), r); + let s = k(n, a); + y.B.set(A(s), r); + let c = k(i, a); + y.C.set(A(c), r); + } + if (y.A = await m.batchToMontgomery(y.A), y.B = await m.batchToMontgomery(y.B), y.C = await m.batchToMontgomery(y.C), r && r.debug("··· Computing A ifft"), b.A = await X.fromEvaluations(y.A, p, r), r && r.debug("··· Computing B ifft"), b.B = await X.fromEvaluations(y.B, p, r), r && r.debug("··· Computing C ifft"), b.C = await X.fromEvaluations(y.C, p, r), r && r.debug("··· Computing A fft"), x.A = await Z.fromPolynomial(b.A, 4, p, r), r && r.debug("··· Computing B fft"), x.B = await Z.fromPolynomial(b.B, 4, p, r), r && r.debug("··· Computing C fft"), x.C = await Z.fromPolynomial(b.C, 4, p, r), b.A.blindCoefficients([S.b[2], S.b[1]]), b.B.blindCoefficients([S.b[4], S.b[3]]), b.C.blindCoefficients([S.b[6], S.b[5]]), b.A.degree() >= f.domainSize + 2) throw Error("A Polynomial is not well calculated"); + if (b.B.degree() >= f.domainSize + 2) throw Error("B Polynomial is not well calculated"); + if (b.C.degree() >= f.domainSize + 2) throw Error("C Polynomial is not well calculated"); + } + async function N() { + r && r.debug("> Computing challenges beta and gamma"), w.reset(), w.addPolCommitment(f.Qm), w.addPolCommitment(f.Ql), w.addPolCommitment(f.Qr), w.addPolCommitment(f.Qo), w.addPolCommitment(f.Qc), w.addPolCommitment(f.S1), w.addPolCommitment(f.S2), w.addPolCommitment(f.S3); + for (let e = 0; e < f.nPublic; e++) w.addScalar(y.A.slice(e * h, e * h + h)); + w.addPolCommitment(C.getPolynomial("A")), w.addPolCommitment(C.getPolynomial("B")), w.addPolCommitment(C.getPolynomial("C")), S.beta = w.getChallenge(), r && r.debug("··· challenges.beta: " + m.toString(S.beta, 16)), w.reset(), w.addScalar(S.beta), S.gamma = w.getChallenge(), r && r.debug("··· challenges.gamma: " + m.toString(S.gamma, 16)), r && r.debug("> Computing Z polynomial"), await P(), r && r.debug("> Computing Z MSM"); + let e = await b.Z.multiExponentiation(T, "Z"); + C.addPolynomial("Z", e); + } + async function P() { + r && r.debug("··· Computing Z evaluations"); + let e = new s(g), t = new s(g); + e.set(m.one, 0), t.set(m.one, 0); + let n = m.one; + for (let r = 0; r < f.domainSize; r++) { + let i = r * h, a = y.A.slice(i, i + h), o = y.B.slice(i, i + h), s = y.C.slice(i, i + h), c = m.mul(S.beta, n), l = m.add(a, c); + l = m.add(l, S.gamma); + let u = m.add(o, m.mul(f.k1, c)); + u = m.add(u, S.gamma); + let d = m.add(s, m.mul(f.k2, c)); + d = m.add(d, S.gamma); + let p = m.mul(l, m.mul(u, d)), g = m.add(a, m.mul(x.Sigma1.getEvaluation(r * 4), S.beta)); + g = m.add(g, S.gamma); + let _ = m.add(o, m.mul(x.Sigma2.getEvaluation(r * 4), S.beta)); + _ = m.add(_, S.gamma); + let v = m.add(s, m.mul(x.Sigma3.getEvaluation(r * 4), S.beta)); + v = m.add(v, S.gamma); + let b = m.mul(g, m.mul(_, v)); + p = m.mul(e.slice(i, i + h), p), e.set(p, (r + 1) % f.domainSize * h), b = m.mul(t.slice(i, i + h), b), t.set(b, (r + 1) % f.domainSize * h), n = m.mul(n, m.w[f.power]); + } + t = await m.batchInverse(t); + for (let n = 0; n < f.domainSize; n++) { + let r = n * h, i = m.mul(e.slice(r, r + h), t.slice(r, r + h)); + e.set(i, r); + } + if (y.Z = e, !m.eq(e.slice(0, h), m.one)) throw Error("Copy constraints does not match"); + if (r && r.debug("··· Computing Z ifft"), b.Z = await X.fromEvaluations(y.Z, p, r), r && r.debug("··· Computing Z fft"), x.Z = await Z.fromPolynomial(b.Z, 4, p, r), b.Z.blindCoefficients([ + S.b[9], + S.b[8], + S.b[7] + ]), b.Z.degree() >= f.domainSize + 3) throw Error("Z Polynomial is not well calculated"); + delete y.Z; + } + async function F() { + r && r.debug("> Computing challenge alpha"), w.reset(), w.addScalar(S.beta), w.addScalar(S.gamma), w.addPolCommitment(C.getPolynomial("Z")), S.alpha = w.getChallenge(), S.alpha2 = m.square(S.alpha), r && r.debug("··· challenges.alpha: " + m.toString(S.alpha, 16)), r && r.debug("> Computing T polynomial"), await I(), r && r.debug("> Computing T MSM"); + let e = await b.T1.multiExponentiation(T, "T1"), t = await b.T2.multiExponentiation(T, "T2"), n = await b.T3.multiExponentiation(T, "T3"); + C.addPolynomial("T1", e), C.addPolynomial("T2", t), C.addPolynomial("T3", n); + } + async function I() { + r && r.debug("··· Reading sections 8, 9, 7, 10, 11. Q selectors"), x.QL = new Z(new s(g * 4), p, r), x.QR = new Z(new s(g * 4), p, r), x.QM = new Z(new s(g * 4), p, r), x.QO = new Z(new s(g * 4), p, r), x.QC = new Z(new s(g * 4), p, r), await l.readToBuffer(x.QL.eval, 0, g * 4, d[8][0].p + g), await l.readToBuffer(x.QR.eval, 0, g * 4, d[9][0].p + g), await l.readToBuffer(x.QM.eval, 0, g * 4, d[7][0].p + g), await l.readToBuffer(x.QO.eval, 0, g * 4, d[10][0].p + g), await l.readToBuffer(x.QC.eval, 0, g * 4, d[11][0].p + g), x.Lagrange = new Z(new s(g * 4 * f.nPublic), p, r); + for (let e = 0; e < f.nPublic; e++) await l.readToBuffer(x.Lagrange.eval, e * g * 4, g * 4, d[13][0].p + e * 5 * g + g); + y.T = new s(g * 4), y.Tz = new s(g * 4), r && r.debug("··· Computing T evaluations"); + let e = m.one; + for (let t = 0; t < f.domainSize * 4; t++) { + r && t !== 0 && t % 1e5 == 0 && r.debug(` T evaluation ${t}/${f.domainSize * 4}`); + let n = x.A.getEvaluation(t), i = x.B.getEvaluation(t), a = x.C.getEvaluation(t), o = x.Z.getEvaluation(t), s = x.Z.getEvaluation((f.domainSize * 4 + 4 + t) % (f.domainSize * 4)), c = x.QM.getEvaluation(t), l = x.QL.getEvaluation(t), u = x.QR.getEvaluation(t), d = x.QO.getEvaluation(t), p = x.QC.getEvaluation(t), g = x.Sigma1.getEvaluation(t), _ = x.Sigma2.getEvaluation(t), v = x.Sigma3.getEvaluation(t), b = m.add(S.b[2], m.mul(S.b[1], e)), C = m.add(S.b[4], m.mul(S.b[3], e)), w = m.add(S.b[6], m.mul(S.b[5], e)), T = m.square(e), E = m.add(m.add(m.mul(S.b[7], T), m.mul(S.b[8], e)), S.b[9]), D = m.mul(e, m.w[f.power]), O = m.square(D), k = m.add(m.add(m.mul(S.b[7], O), m.mul(S.b[8], D)), S.b[9]), A = m.zero; + for (let e = 0; e < f.nPublic; e++) { + let n = e * 4 * f.domainSize + t, r = x.Lagrange.getEvaluation(n), i = y.A.slice(e * h, (e + 1) * h); + A = m.sub(A, m.mul(r, i)); + } + let [j, M] = Fr.mul2(n, i, b, C, t % 4, m); + j = m.mul(j, c), M = m.mul(M, c), j = m.add(j, m.mul(n, l)), M = m.add(M, m.mul(b, l)), j = m.add(j, m.mul(i, u)), M = m.add(M, m.mul(C, u)), j = m.add(j, m.mul(a, d)), M = m.add(M, m.mul(w, d)), j = m.add(j, A), j = m.add(j, p); + let N = m.mul(S.beta, e), P = n; + P = m.add(P, N), P = m.add(P, S.gamma); + let F = i; + F = m.add(F, m.mul(N, f.k1)), F = m.add(F, S.gamma); + let I = a; + I = m.add(I, m.mul(N, f.k2)), I = m.add(I, S.gamma); + let L = o, [ee, R] = Fr.mul4(P, F, I, L, b, C, w, E, t % 4, m); + ee = m.mul(ee, S.alpha), R = m.mul(R, S.alpha); + let z = n; + z = m.add(z, m.mul(S.beta, g)), z = m.add(z, S.gamma); + let B = i; + B = m.add(B, m.mul(S.beta, _)), B = m.add(B, S.gamma); + let V = a; + V = m.add(V, m.mul(S.beta, v)), V = m.add(V, S.gamma); + let te = s, [H, U] = Fr.mul4(z, B, V, te, b, C, w, k, t % 4, m); + H = m.mul(H, S.alpha), U = m.mul(U, S.alpha); + let ne = m.sub(o, m.one); + ne = m.mul(ne, x.Lagrange.getEvaluation(t)), ne = m.mul(ne, S.alpha2); + let re = m.mul(E, x.Lagrange.getEvaluation(t)); + re = m.mul(re, S.alpha2); + let ie = m.add(m.sub(m.add(j, ee), H), ne), ae = m.add(m.sub(m.add(M, R), U), re); + y.T.set(ie, t * h), y.Tz.set(ae, t * h), e = m.mul(e, m.w[f.power + 2]); + } + if (r && r.debug("··· Computing T ifft"), b.T = await X.fromEvaluations(y.T, p, r), r && r.debug("··· Computing T / ZH"), b.T.divZh(f.domainSize, 4), r && r.debug("··· Computing Tz ifft"), b.Tz = await X.fromEvaluations(y.Tz, p, r), b.T.add(b.Tz), b.T.degree() >= f.domainSize * 3 + 6) throw Error("T Polynomial is not well calculated"); + r && r.debug("··· Computing T1, T2, T3 polynomials"), b.T1 = new X(new s((f.domainSize + 1) * h), p, r), b.T2 = new X(new s((f.domainSize + 1) * h), p, r), b.T3 = new X(new s((f.domainSize + 6) * h), p, r), b.T1.coef.set(b.T.coef.slice(0, g), 0), b.T2.coef.set(b.T.coef.slice(g, g * 2), 0), b.T3.coef.set(b.T.coef.slice(g * 2, g * 3 + 6 * h), 0), b.T1.setCoef(f.domainSize, S.b[10]); + let t = m.sub(b.T2.getCoef(0), S.b[10]); + b.T2.setCoef(0, t), b.T2.setCoef(f.domainSize, S.b[11]); + let n = m.sub(b.T3.getCoef(0), S.b[11]); + b.T3.setCoef(0, n); + } + async function L() { + r && r.debug("> Computing challenge xi"), w.reset(), w.addScalar(S.alpha), w.addPolCommitment(C.getPolynomial("T1")), w.addPolCommitment(C.getPolynomial("T2")), w.addPolCommitment(C.getPolynomial("T3")), S.xi = w.getChallenge(), S.xiw = m.mul(S.xi, m.w[f.power]), r && r.debug("··· challenges.xi: " + m.toString(S.xi, 16)), C.addEvaluation("eval_a", b.A.evaluate(S.xi)), C.addEvaluation("eval_b", b.B.evaluate(S.xi)), C.addEvaluation("eval_c", b.C.evaluate(S.xi)), C.addEvaluation("eval_s1", b.Sigma1.evaluate(S.xi)), C.addEvaluation("eval_s2", b.Sigma2.evaluate(S.xi)), C.addEvaluation("eval_zw", b.Z.evaluate(S.xiw)); + } + async function ee() { + r && r.debug("> Computing challenge v"), w.reset(), w.addScalar(S.xi), w.addScalar(C.getEvaluation("eval_a")), w.addScalar(C.getEvaluation("eval_b")), w.addScalar(C.getEvaluation("eval_c")), w.addScalar(C.getEvaluation("eval_s1")), w.addScalar(C.getEvaluation("eval_s2")), w.addScalar(C.getEvaluation("eval_zw")), S.v = [], S.v[1] = w.getChallenge(), r && r.debug("··· challenges.v: " + m.toString(S.v[1], 16)); + for (let e = 2; e < 6; e++) S.v[e] = m.mul(S.v[e - 1], S.v[1]); + r && r.debug("> Computing linearisation polynomial R(X)"), await R(), r && r.debug("> Computing opening proof polynomial Wxi(X) polynomial"), z(), r && r.debug("> Computing opening proof polynomial Wxiw(X) polynomial"), B(), r && r.debug("> Computing Wxi, Wxiw MSM"); + let e = await b.Wxi.multiExponentiation(T, "Wxi"), t = await b.Wxiw.multiExponentiation(T, "Wxiw"); + C.addPolynomial("Wxi", e), C.addPolynomial("Wxiw", t); + } + async function R() { + let e = p.Fr; + b.QL = new X(new s(g), p, r), b.QR = new X(new s(g), p, r), b.QM = new X(new s(g), p, r), b.QO = new X(new s(g), p, r), b.QC = new X(new s(g), p, r), await l.readToBuffer(b.QL.coef, 0, g, d[8][0].p), await l.readToBuffer(b.QR.coef, 0, g, d[9][0].p), await l.readToBuffer(b.QM.coef, 0, g, d[7][0].p), await l.readToBuffer(b.QO.coef, 0, g, d[10][0].p), await l.readToBuffer(b.QC.coef, 0, g, d[11][0].p), S.xin = S.xi; + for (let t = 0; t < f.power; t++) S.xin = e.square(S.xin); + S.zh = e.sub(S.xin, e.one); + let t = [], n = e.e(f.domainSize), i = e.one; + for (let r = 1; r <= Math.max(1, f.nPublic); r++) t[r] = e.div(e.mul(i, S.zh), e.mul(n, e.sub(S.xi, i))), i = e.mul(i, e.w[f.power]); + let a = e.div(e.sub(S.xin, e.one), e.mul(n, e.sub(S.xi, e.one))); + if (r) { + r.debug("Lagrange Evaluations: "); + for (let n = 1; n < t.length; n++) r.debug(`L${n}(xi)=` + e.toString(t[n], 16)); + } + let o = e.zero; + for (let n = 0; n < E.length; n++) { + let r = e.e(E[n]); + o = e.sub(o, e.mul(r, t[n + 1])); + } + r && r.debug("PI: " + e.toString(o, 16)); + let c = e.mul(C.evaluations.eval_a, C.evaluations.eval_b), u = C.evaluations.eval_a, m = e.mul(S.beta, S.xi); + u = e.add(u, m), u = e.add(u, S.gamma); + let _ = C.evaluations.eval_b; + _ = e.add(_, e.mul(m, f.k1)), _ = e.add(_, S.gamma); + let v = C.evaluations.eval_c; + v = e.add(v, e.mul(m, f.k2)), v = e.add(v, S.gamma); + let y = e.mul(e.mul(e.mul(u, _), v), S.alpha), x = C.evaluations.eval_a; + x = e.add(x, e.mul(S.beta, C.evaluations.eval_s1)), x = e.add(x, S.gamma); + let w = C.evaluations.eval_b; + w = e.add(w, e.mul(S.beta, C.evaluations.eval_s2)), w = e.add(w, S.gamma); + let T = e.mul(x, w); + T = e.mul(T, C.evaluations.eval_zw), T = e.mul(T, S.alpha); + let D = e.mul(a, S.alpha2); + b.R = new X(new s((f.domainSize + 6) * h), p, r), b.R.add(b.QM, c), b.R.add(b.QL, C.evaluations.eval_a), b.R.add(b.QR, C.evaluations.eval_b), b.R.add(b.QO, C.evaluations.eval_c), b.R.add(b.QC), b.R.add(b.Z, y), b.R.sub(b.Sigma3, e.mul(T, S.beta)), b.R.add(b.Z, D); + let O = X.fromPolynomial(b.T3, p, r); + O.mulScalar(e.square(S.xin)), O.add(b.T2, S.xin), O.add(b.T1), O.mulScalar(S.zh), b.R.sub(O); + let k = e.sub(o, e.mul(T, e.add(C.evaluations.eval_c, S.gamma))); + k = e.sub(k, D), r && r.debug("r0: " + e.toString(k, 16)), b.R.addScalar(k); + } + function z() { + b.Wxi = new X(new s(g + 6 * h), p, r), b.Wxi.add(b.R), b.Wxi.add(b.A, S.v[1]), b.Wxi.add(b.B, S.v[2]), b.Wxi.add(b.C, S.v[3]), b.Wxi.add(b.Sigma1, S.v[4]), b.Wxi.add(b.Sigma2, S.v[5]), b.Wxi.subScalar(m.mul(S.v[1], C.evaluations.eval_a)), b.Wxi.subScalar(m.mul(S.v[2], C.evaluations.eval_b)), b.Wxi.subScalar(m.mul(S.v[3], C.evaluations.eval_c)), b.Wxi.subScalar(m.mul(S.v[4], C.evaluations.eval_s1)), b.Wxi.subScalar(m.mul(S.v[5], C.evaluations.eval_s2)), b.Wxi.divByZerofier(1, S.xi); + } + async function B() { + b.Wxiw = X.fromPolynomial(b.Z, p, r), b.Wxiw.subScalar(C.evaluations.eval_zw), b.Wxiw.divByZerofier(1, S.xiw); + } +} +//#endregion +//#region src/plonk_fullprove.js +var { unstringifyBigInts: Rr } = p; +async function zr(e, t, n, r, i, a) { + let o = Rr(e), s = { type: "mem" }; + return await Bt(o, t, s, i), await Lr(n, s, r, a); +} +//#endregion +//#region src/plonk_verify.js +var { unstringifyBigInts: Br } = p; +async function Vr(e, t, n, r) { + let i = Br(e); + n = Br(n); + let a = Br(t), o = await D(i.curve), s = o.Fr, c = o.G1; + r && r.info("PLONK VERIFIER STARTED"); + let l = Hr(o, n); + if (i = Ur(o, i), !Wr(o, l)) return r.error("Proof commitments are not valid."), !1; + if (a.length != i.nPublic) return r && r.error("Invalid number of public inputs"), !1; + if (!qr(o, l)) return r && r.error("Proof evaluations are not valid"), !1; + if (!Jr(o, a)) return r && r.error("Public inputs are not valid."), !1; + let u = Yr(o, l, a, i); + if (r) { + r.debug("beta: " + s.toString(u.beta, 16)), r.debug("gamma: " + s.toString(u.gamma, 16)), r.debug("alpha: " + s.toString(u.alpha, 16)), r.debug("xi: " + s.toString(u.xi, 16)); + for (let e = 1; e < 6; e++) r && r.debug("v: " + s.toString(u.v[e], 16)); + r.debug("u: " + s.toString(u.u, 16)); + } + let d = Xr(o, u, i); + if (r) for (let e = 1; e < d.length; e++) r.debug(`L${e}(xi)=` + s.toString(d[e], 16)); + if (a.length != i.nPublic) return r.error("Number of public signals does not match with vk"), !1; + let f = Zr(o, a, d); + r && r.debug("PI(xi): " + s.toString(f, 16)); + let p = Qr(o, l, u, f, d[1]); + r && r.debug("r0: " + s.toString(p, 16)); + let m = $r(o, l, u, i, d[1]); + r && r.debug("D: " + c.toString(c.toAffine(m), 16)); + let h = ei(o, l, u, i, m); + r && r.debug("F: " + c.toString(c.toAffine(h), 16)); + let g = ti(o, l, u, p); + r && r.debug("E: " + c.toString(c.toAffine(g), 16)); + let _ = await ni(o, l, u, i, g, h); + return r && (_ ? r.info("OK!") : r.warn("Invalid Proof")), _; +} +function Hr(e, t) { + let n = e.G1, r = e.Fr, i = {}; + return i.A = n.fromObject(t.A), i.B = n.fromObject(t.B), i.C = n.fromObject(t.C), i.Z = n.fromObject(t.Z), i.T1 = n.fromObject(t.T1), i.T2 = n.fromObject(t.T2), i.T3 = n.fromObject(t.T3), i.eval_a = r.fromObject(t.eval_a), i.eval_b = r.fromObject(t.eval_b), i.eval_c = r.fromObject(t.eval_c), i.eval_zw = r.fromObject(t.eval_zw), i.eval_s1 = r.fromObject(t.eval_s1), i.eval_s2 = r.fromObject(t.eval_s2), i.Wxi = n.fromObject(t.Wxi), i.Wxiw = n.fromObject(t.Wxiw), i; +} +function Ur(e, t) { + let n = e.G1, r = e.G2, i = e.Fr, a = t; + return a.Qm = n.fromObject(t.Qm), a.Ql = n.fromObject(t.Ql), a.Qr = n.fromObject(t.Qr), a.Qo = n.fromObject(t.Qo), a.Qc = n.fromObject(t.Qc), a.S1 = n.fromObject(t.S1), a.S2 = n.fromObject(t.S2), a.S3 = n.fromObject(t.S3), a.k1 = i.fromObject(t.k1), a.k2 = i.fromObject(t.k2), a.X_2 = r.fromObject(t.X_2), a; +} +function Wr(e, t) { + let n = e.G1; + return !(!n.isValid(t.A) || !n.isValid(t.B) || !n.isValid(t.C) || !n.isValid(t.Z) || !n.isValid(t.T1) || !n.isValid(t.T2) || !n.isValid(t.T3) || !n.isValid(t.Wxi) || !n.isValid(t.Wxiw)); +} +function Gr(e, t) { + return u.geq(t, 0) && u.lt(t, e.r); +} +function Kr(e, t) { + return Gr(e, u.fromRprLE(t)); +} +function qr(e, t) { + return Kr(e, t.eval_a) && Kr(e, t.eval_b) && Kr(e, t.eval_c) && Kr(e, t.eval_s1) && Kr(e, t.eval_s2) && Kr(e, t.eval_zw); +} +function Jr(e, t) { + for (let n = 0; n < t.length; n++) if (!Gr(e, t[n])) return !1; + return !0; +} +function Yr(e, t, n, r) { + let i = e.Fr, a = {}, o = new Pr(e); + o.addPolCommitment(r.Qm), o.addPolCommitment(r.Ql), o.addPolCommitment(r.Qr), o.addPolCommitment(r.Qo), o.addPolCommitment(r.Qc), o.addPolCommitment(r.S1), o.addPolCommitment(r.S2), o.addPolCommitment(r.S3); + for (let e = 0; e < n.length; e++) o.addScalar(i.e(n[e])); + o.addPolCommitment(t.A), o.addPolCommitment(t.B), o.addPolCommitment(t.C), a.beta = o.getChallenge(), o.reset(), o.addScalar(a.beta), a.gamma = o.getChallenge(), o.reset(), o.addScalar(a.beta), o.addScalar(a.gamma), o.addPolCommitment(t.Z), a.alpha = o.getChallenge(), o.reset(), o.addScalar(a.alpha), o.addPolCommitment(t.T1), o.addPolCommitment(t.T2), o.addPolCommitment(t.T3), a.xi = o.getChallenge(), o.reset(), o.addScalar(a.xi), o.addScalar(t.eval_a), o.addScalar(t.eval_b), o.addScalar(t.eval_c), o.addScalar(t.eval_s1), o.addScalar(t.eval_s2), o.addScalar(t.eval_zw), a.v = [], a.v[1] = o.getChallenge(); + for (let e = 2; e < 6; e++) a.v[e] = i.mul(a.v[e - 1], a.v[1]); + return o.reset(), o.addPolCommitment(t.Wxi), o.addPolCommitment(t.Wxiw), a.u = o.getChallenge(), a; +} +function Xr(e, t, n) { + let r = e.Fr, i = t.xi, a = 1; + for (let e = 0; e < n.power; e++) i = r.square(i), a *= 2; + t.xin = i, t.zh = r.sub(i, r.one); + let o = [], s = r.e(a), c = r.one; + for (let e = 1; e <= Math.max(1, n.nPublic); e++) o[e] = r.div(r.mul(c, t.zh), r.mul(s, r.sub(t.xi, c))), c = r.mul(c, r.w[n.power]); + return o; +} +function Zr(e, t, n) { + let r = e.Fr, i = r.zero; + for (let e = 0; e < t.length; e++) { + let a = r.e(t[e]); + i = r.sub(i, r.mul(a, n[e + 1])); + } + return i; +} +function Qr(e, t, n, r, i) { + let a = e.Fr, o = r, s = a.mul(i, a.square(n.alpha)), c = a.add(t.eval_a, a.mul(n.beta, t.eval_s1)); + c = a.add(c, n.gamma); + let l = a.add(t.eval_b, a.mul(n.beta, t.eval_s2)); + l = a.add(l, n.gamma); + let u = a.add(t.eval_c, n.gamma), d = a.mul(a.mul(c, l), u); + return d = a.mul(d, t.eval_zw), d = a.mul(d, n.alpha), a.sub(a.sub(o, s), d); +} +function $r(e, t, n, r, i) { + let a = e.G1, o = e.Fr, s = a.timesFr(r.Qm, o.mul(t.eval_a, t.eval_b)); + s = a.add(s, a.timesFr(r.Ql, t.eval_a)), s = a.add(s, a.timesFr(r.Qr, t.eval_b)), s = a.add(s, a.timesFr(r.Qo, t.eval_c)), s = a.add(s, r.Qc); + let c = o.mul(n.beta, n.xi), l = o.add(o.add(t.eval_a, c), n.gamma), u = o.add(o.add(t.eval_b, o.mul(c, r.k1)), n.gamma), d = o.add(o.add(t.eval_c, o.mul(c, r.k2)), n.gamma), f = o.mul(o.mul(o.mul(l, u), d), n.alpha), p = o.mul(i, o.square(n.alpha)), m = a.timesFr(t.Z, o.add(o.add(f, p), n.u)), h = o.add(o.add(t.eval_a, o.mul(n.beta, t.eval_s1)), n.gamma), g = o.add(o.add(t.eval_b, o.mul(n.beta, t.eval_s2)), n.gamma), _ = o.mul(o.mul(n.alpha, n.beta), t.eval_zw), v = a.timesFr(r.S3, o.mul(o.mul(h, g), _)), y = t.T1, b = a.timesFr(t.T2, n.xin), x = a.timesFr(t.T3, o.square(n.xin)), S = a.add(y, a.add(b, x)); + return S = a.timesFr(S, n.zh), a.sub(a.sub(a.add(s, m), v), S); +} +function ei(e, t, n, r, i) { + let a = e.G1, o = a.add(i, a.timesFr(t.A, n.v[1])); + return o = a.add(o, a.timesFr(t.B, n.v[2])), o = a.add(o, a.timesFr(t.C, n.v[3])), o = a.add(o, a.timesFr(r.S1, n.v[4])), o = a.add(o, a.timesFr(r.S2, n.v[5])), o; +} +function ti(e, t, n, r) { + let i = e.G1, a = e.Fr, o = a.add(a.neg(r), a.mul(n.v[1], t.eval_a)); + return o = a.add(o, a.mul(n.v[2], t.eval_b)), o = a.add(o, a.mul(n.v[3], t.eval_c)), o = a.add(o, a.mul(n.v[4], t.eval_s1)), o = a.add(o, a.mul(n.v[5], t.eval_s2)), o = a.add(o, a.mul(n.u, t.eval_zw)), i.timesFr(i.one, o); +} +async function ni(e, t, n, r, i, a) { + let o = e.G1, s = e.Fr, c = t.Wxi; + c = o.add(c, o.timesFr(t.Wxiw, n.u)); + let l = o.timesFr(t.Wxi, n.xi), u = s.mul(s.mul(n.u, n.xi), s.w[r.power]); + return l = o.add(l, o.timesFr(t.Wxiw, u)), l = o.add(l, a), l = o.sub(l, i), await e.pairingEq(o.neg(c), r.X_2, l, e.G2.one); +} +//#endregion +//#region src/plonk_exportsoliditycalldata.js +var { unstringifyBigInts: ri } = p; +function Q(e) { + let t = e.toString(16); + for (; t.length < 64;) t = "0" + t; + return t = `"0x${t}"`, t; +} +async function ii(e, t) { + let n = ri(e), r = ri(t); + await D(n.curve); + let i = ""; + for (let e = 0; e < r.length; e++) i != "" && (i += ","), i += Q(r[e]); + return `[${Q(n.A[0])}, ${Q(n.A[1])},${Q(n.B[0])},${Q(n.B[1])},${Q(n.C[0])},${Q(n.C[1])},${Q(n.Z[0])},${Q(n.Z[1])},${Q(n.T1[0])},${Q(n.T1[1])},${Q(n.T2[0])},${Q(n.T2[1])},${Q(n.T3[0])},${Q(n.T3[1])},${Q(n.Wxi[0])},${Q(n.Wxi[1])},${Q(n.Wxiw[0])},${Q(n.Wxiw[1])},${Q(n.eval_a)},${Q(n.eval_b)},${Q(n.eval_c)},${Q(n.eval_s1)},${Q(n.eval_s2)},${Q(n.eval_zw)}][${i}]`; +} +//#endregion +//#region src/plonk.js +var ai = /* @__PURE__ */ y({ + exportSolidityCallData: () => ii, + fullProve: () => zr, + prove: () => Lr, + setup: () => pr, + verify: () => Vr }); - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -const SUBARRAY_SIZE = 0x40000; - -const BigArrayHandler = { - get: function(obj, prop) { - if (!isNaN(prop)) { - return obj.getElement(prop); - } else return obj[prop]; - }, - set: function(obj, prop, value) { - if (!isNaN(prop)) { - return obj.setElement(prop, value); - } else { - obj[prop] = value; - return true; - } - } +//#endregion +//#region src/plonk_equation.js +function oi(e, t) { + return [ + e, + 0, + 0, + t.one, + t.zero, + t.zero, + t.zero, + t.zero + ]; +} +function si(e, t, n, r, i, a, o, s) { + return [ + e, + t, + n, + r, + i, + a, + o, + s + ]; +} +function ci(e, t, n, r, i, a, o, s, c) { + return [ + e, + t, + n, + r, + i, + a, + o, + s + ]; +} +//#endregion +//#region src/r1cs_constraint_processor.js +var li = 0, ui = 1, di = 2, fi = class { + constructor(e, t, n, r, i) { + this.Fr = e, this.logger = i, this.fnGetAdditionConstraint = n, this.fnGetMultiplicationConstraint = r; + } + processR1csConstraint(e, t, n, r) { + this.normalizeLinearCombination(t), this.normalizeLinearCombination(n), this.normalizeLinearCombination(r); + let i = this.getLinearCombinationType(t), a = this.getLinearCombinationType(n); + if (i === li || a === li) return this.processR1csAdditionConstraint(e, r); + if (i === ui) { + let i = this.joinLinearCombinations(n, r, t[0]); + return this.processR1csAdditionConstraint(e, i); + } else if (a === ui) { + let i = this.joinLinearCombinations(t, r, n[0]); + return this.processR1csAdditionConstraint(e, i); + } else return this.processR1csMultiplicationConstraint(e, t, n, r); + } + getLinearCombinationType(e) { + let t = this.Fr.zero, n = 0, r = Object.keys(e); + for (let i = 0; i < r.length; i++) e[r[i]] == 0n ? delete e[r[i]] : r[i] == 0 ? t = this.Fr.add(t, e[r[i]]) : n++; + return n > 0 ? di : this.Fr.isZero(t) ? li : ui; + } + normalizeLinearCombination(e) { + let t = Object.keys(e); + for (let n = 0; n < t.length; n++) this.Fr.isZero(e[t[n]]) && delete e[t[n]]; + return e; + } + joinLinearCombinations(e, t, n) { + let r = {}; + for (let t in e) r[t] === void 0 ? r[t] = this.Fr.mul(n, e[t]) : r[t] = this.Fr.add(r[t], this.Fr.mul(n, e[t])); + for (let e in t) r[e] === void 0 ? r[e] = t[e] : r[e] = this.Fr.add(r[e], t[e]); + return this.normalizeLinearCombination(r); + } + reduceCoefs(e, t, n, r, i) { + let a = { + k: this.Fr.zero, + signals: [], + coefs: [] + }, o = []; + for (let e in r) e == 0 ? a.k = this.Fr.add(a.k, r[e]) : r[e] != 0n && o.push([Number(e), r[e]]); + for (; o.length > i;) { + let r = o.shift(), i = o.shift(), a = e.nVars++, s = this.fnGetAdditionConstraint(r[0], i[0], a, this.Fr.neg(r[1]), this.Fr.neg(i[1]), this.Fr.zero, this.Fr.one, this.Fr.zero); + t.push(s), n.push([ + r[0], + i[0], + r[1], + i[1] + ]), o.push([a, this.Fr.one]); + } + for (let e = 0; e < o.length; e++) a.signals[e] = o[e][0], a.coefs[e] = o[e][1]; + for (; a.coefs.length < i;) a.signals.push(0), a.coefs.push(this.Fr.zero); + return a; + } + processR1csAdditionConstraint(e, t) { + let n = [], r = [], i = this.reduceCoefs(e, n, r, t, 3), a = this.fnGetAdditionConstraint(i.signals[0], i.signals[1], i.signals[2], i.coefs[0], i.coefs[1], this.Fr.zero, i.coefs[2], i.k); + return n.push(a), [n, r]; + } + processR1csMultiplicationConstraint(e, t, n, r) { + let i = [], a = [], o = this.reduceCoefs(e, i, a, t, 1), s = this.reduceCoefs(e, i, a, n, 1), c = this.reduceCoefs(e, i, a, r, 1), l = this.fnGetMultiplicationConstraint(o.signals[0], s.signals[0], c.signals[0], this.Fr.mul(o.coefs[0], s.k), this.Fr.mul(o.k, s.coefs[0]), this.Fr.mul(o.coefs[0], s.coefs[0]), this.Fr.neg(c.coefs[0]), this.Fr.sub(this.Fr.mul(o.k, s.k), c.k)); + return i.push(l), [i, a]; + } +}, pi = class { + constructor(e, t, n) { + this.n = e, this.polynomials = Array(e).fill(void 0), this.curve = t, this.Fr = t.Fr, this.G1 = t.G1, this.logger = n; + } + addPolynomial(e, t) { + if (e > this.n - 1) throw Error("CPolynomial:addPolynomial, cannot add a polynomial to a position greater than n-1"); + this.polynomials[e] = t; + } + degree() { + let e = this.polynomials.map((e, t) => e === void 0 ? 0 : e.degree() * this.n + t); + return Math.max(...e); + } + getPolynomial() { + let e = this.polynomials.map((e) => e === void 0 ? 0 : e.degree()), t = this.degree(), n = 2 ** (Se(t - 1) + 1), r = this.Fr.n8, i = new X(new s(n * r), this.curve, this.logger); + for (let n = 0; n < t; n++) { + let t = n * r, a = t * this.n; + for (let o = 0; o < this.n; o++) this.polynomials[o] !== void 0 && n <= e[o] && i.coef.set(this.polynomials[o].coef.slice(t, t + r), a + o * r); + } + return i; + } + async multiExponentiation(e, t) { + let n = this.getPolynomial(), r = n.coef.byteLength / this.Fr.n8, i = e.slice(0, r * this.G1.F.n8 * 2), a = await this.Fr.batchFromMontgomery(n.coef), o = await this.G1.multiExpAffine(i, a, this.logger, t); + return o = this.G1.toAffine(o), o; + } }; - -class _BigArray { - constructor (initSize) { - this.length = initSize || 0; - this.arr = new Array(SUBARRAY_SIZE); - - for (let i=0; i= this.length) this.length = idx+1; - return true; - } - getKeys() { - const newA = new BigArray(); - for (let i=0; i. -*/ - -async function newZKey(r1csName, ptauName, zkeyName, logger) { - - const TAU_G1 = 0; - const TAU_G2 = 1; - const ALPHATAU_G1 = 2; - const BETATAU_G1 = 3; - const csHasher = blake2b.create({ dkLen: 64 }); - - const {fd: fdPTau, sections: sectionsPTau} = await readBinFile$1(ptauName, "ptau", 1); - const {curve, power} = await readPTauHeader(fdPTau, sectionsPTau); - const {fd: fdR1cs, sections: sectionsR1cs} = await readBinFile$1(r1csName, "r1cs", 1); - const r1cs = await readR1csHeader(fdR1cs, sectionsR1cs, false); - - const fdZKey = await createBinFile(zkeyName, "zkey", 1, 10, 1<<22, 1<<24); - - const sG1 = curve.G1.F.n8*2; - const sG2 = curve.G2.F.n8*2; - - if (r1cs.prime != curve.r) { - if (logger) logger.error("r1cs curve does not match powers of tau ceremony curve"); - return -1; - } - - const cirPower = log2(r1cs.nConstraints + r1cs.nPubInputs + r1cs.nOutputs +1 -1) +1; - - if (cirPower > power) { - if (logger) logger.error(`circuit too big for this power of tau ceremony. ${r1cs.nConstraints}*2 > 2**${power}`); - return -1; - } - - if (!sectionsPTau[12]) { - if (logger) logger.error("Powers of tau is not prepared."); - return -1; - } - - const nPublic = r1cs.nOutputs + r1cs.nPubInputs; - const domainSize = 2 ** cirPower; - - // Write the header - /////////// - await startWriteSection(fdZKey, 1); - await fdZKey.writeULE32(1); // Groth - await endWriteSection(fdZKey); - - // Write the Groth header section - /////////// - - await startWriteSection(fdZKey, 2); - const primeQ = curve.q; - const n8q = (Math.floor( (Scalar.bitLength(primeQ) - 1) / 64) +1)*8; - - const primeR = curve.r; - const n8r = (Math.floor( (Scalar.bitLength(primeR) - 1) / 64) +1)*8; - const Rr = Scalar.mod(Scalar.shl(1, n8r*8), primeR); - const R2r = curve.Fr.e(Scalar.mod(Scalar.mul(Rr,Rr), primeR)); - - await fdZKey.writeULE32(n8q); - await writeBigInt(fdZKey, primeQ, n8q); - await fdZKey.writeULE32(n8r); - await writeBigInt(fdZKey, primeR, n8r); - await fdZKey.writeULE32(r1cs.nVars); // Total number of bars - await fdZKey.writeULE32(nPublic); // Total number of public vars (not including ONE) - await fdZKey.writeULE32(domainSize); // domainSize - - let bAlpha1; - bAlpha1 = await fdPTau.read(sG1, sectionsPTau[4][0].p); - await fdZKey.write(bAlpha1); - bAlpha1 = await curve.G1.batchLEMtoU(bAlpha1); - csHasher.update(bAlpha1); - - let bBeta1; - bBeta1 = await fdPTau.read(sG1, sectionsPTau[5][0].p); - await fdZKey.write(bBeta1); - bBeta1 = await curve.G1.batchLEMtoU(bBeta1); - csHasher.update(bBeta1); - - let bBeta2; - bBeta2 = await fdPTau.read(sG2, sectionsPTau[6][0].p); - await fdZKey.write(bBeta2); - bBeta2 = await curve.G2.batchLEMtoU(bBeta2); - csHasher.update(bBeta2); - - const bg1 = new Uint8Array(sG1); - curve.G1.toRprLEM(bg1, 0, curve.G1.g); - const bg2 = new Uint8Array(sG2); - curve.G2.toRprLEM(bg2, 0, curve.G2.g); - const bg1U = new Uint8Array(sG1); - curve.G1.toRprUncompressed(bg1U, 0, curve.G1.g); - const bg2U = new Uint8Array(sG2); - curve.G2.toRprUncompressed(bg2U, 0, curve.G2.g); - - await fdZKey.write(bg2); // gamma2 - await fdZKey.write(bg1); // delta1 - await fdZKey.write(bg2); // delta2 - csHasher.update(bg2U); // gamma2 - csHasher.update(bg1U); // delta1 - csHasher.update(bg2U); // delta2 - await endWriteSection(fdZKey); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("Reading r1cs"); - let sR1cs = await readSection$1(fdR1cs, sectionsR1cs, 2); - await fdR1cs.close(); - - let A = new BigArray$1(r1cs.nVars); - let B1 = new BigArray$1(r1cs.nVars); - let B2 = new BigArray$1(r1cs.nVars); - let C = new BigArray$1(r1cs.nVars- nPublic -1); - let IC = new Array(nPublic+1); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("Reading tauG1"); - let sTauG1 = await readSection$1(fdPTau, sectionsPTau, 12, (domainSize -1)*sG1, domainSize*sG1); - if (logger) logger.info("Reading tauG2"); - let sTauG2 = await readSection$1(fdPTau, sectionsPTau, 13, (domainSize -1)*sG2, domainSize*sG2); - if (logger) logger.info("Reading alphatauG1"); - let sAlphaTauG1 = await readSection$1(fdPTau, sectionsPTau, 14, (domainSize -1)*sG1, domainSize*sG1); - if (logger) logger.info("Reading betatauG1"); - let sBetaTauG1 = await readSection$1(fdPTau, sectionsPTau, 15, (domainSize -1)*sG1, domainSize*sG1); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("processConstraints"); - await processConstraints(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints"); - await composeAndWritePoints(3, "G1", IC, "IC"); - - IC = null; - // const gc = runInNewContext("gc"); // nocommit - // gc(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("writeHs"); - await writeHs(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("hashHPoints"); - await hashHPoints(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints 8 G1 C"); - await composeAndWritePoints(8, "G1", C, "C"); - - C = null; - // gc(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints 5 G1 A"); - await composeAndWritePoints(5, "G1", A, "A"); - - A = null; - // gc(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints 6 G1 B1"); - await composeAndWritePoints(6, "G1", B1, "B1"); - - B1 = null; - // gc(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints 7 G2 B2"); - await composeAndWritePoints(7, "G2", B2, "B2"); - - B2 = null; - // gc(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("Contributions section"); - const csHash = csHasher.digest(); - // Contributions section - await startWriteSection(fdZKey, 10); - await fdZKey.write(csHash); - await fdZKey.writeULE32(0); - await endWriteSection(fdZKey); - - if (logger) logger.info(formatHash(csHash, "Circuit hash: ")); - - - await fdZKey.close(); - await fdPTau.close(); - - return csHash; - - async function writeHs() { - await startWriteSection(fdZKey, 9); - const buffOut = new BigBuffer(domainSize*sG1); - if (cirPower < curve.Fr.s) { - let sTauG1 = await readSection$1(fdPTau, sectionsPTau, 12, (domainSize*2-1)*sG1, domainSize*2*sG1); - for (let i=0; i< domainSize; i++) { - if ((logger)&&(i%10000 == 0)) logger.debug(`splitting buffer: ${i}/${domainSize}`); - const buff = sTauG1.slice( (i*2+1)*sG1, (i*2+1)*sG1 + sG1 ); - buffOut.set(buff, i*sG1); - } - } else if (cirPower == curve.Fr.s) { - const o = sectionsPTau[12][0].p + ((2 ** (cirPower+1)) -1)*sG1; - await fdPTau.readToBuffer(buffOut, 0, domainSize*sG1, o + domainSize*sG1); - } else { - if (logger) logger.error("Circuit too big"); - throw new Error("Circuit too big for this curve"); - } - await fdZKey.write(buffOut); - await endWriteSection(fdZKey); - } - - async function processConstraints() { - const buffCoeff = new Uint8Array(12 + curve.Fr.n8); - const buffCoeffV = new DataView(buffCoeff.buffer); - const bOne = new Uint8Array(curve.Fr.n8); - curve.Fr.toRprLE(bOne, 0, curve.Fr.e(1)); - - let r1csPos = 0; - - function r1cs_readULE32() { - const buff = sR1cs.slice(r1csPos, r1csPos+4); - r1csPos += 4; - const buffV = new DataView(buff.buffer); - return buffV.getUint32(0, true); - } - - const coefs = new BigArray$1(); - for (let c=0; c=0) { - n = curve.Fr.fromRprLE(sR1cs.slice(c[3], c[3] + curve.Fr.n8), 0); - } else { - n = curve.Fr.fromRprLE(bOne, 0); - } - const nR2 = curve.Fr.mul(n, R2r); - curve.Fr.toRprLE(buffCoeff, 12, nR2); - buffSection.set(buffCoeff, coefsPos); - coefsPos += buffCoeff.length; - } - - } - - async function composeAndWritePoints(idSection, groupName, arr, sectionName) { - const CHUNK_SIZE= 1<<15; - const G = curve[groupName]; - - hashU32(arr.length); - await startWriteSection(fdZKey, idSection); - - let opPromises = []; - - let i=0; - while (i { - if (logger) logger.debug(`Writing points end ${sectionName}: ${_i}/${arr.length}`); - return r; - })); - i += n; - t++; - } - - const result = await Promise.all(opPromises); - - for (let k=0; k 2<<14) { - bBases = new BigBuffer(acc*sGin); - bScalars = new BigBuffer(acc*curve.Fr.n8); - } else { - bBases = new Uint8Array(acc*sGin); - bScalars = new Uint8Array(acc*curve.Fr.n8); - } - let pB =0; - let pS =0; - - const sBuffs = [ - sTauG1, - sTauG2, - sAlphaTauG1, - sBetaTauG1 - ]; - - const bOne = new Uint8Array(curve.Fr.n8); - curve.Fr.toRprLE(bOne, 0, curve.Fr.e(1)); - - let offset = 0; - for (let i=0; i=0) { - bScalars.set( - sR1cs.slice( - arr[i][j][2], - arr[i][j][2] + curve.Fr.n8 - ), - offset*curve.Fr.n8 - ); - } else { - bScalars.set(bOne, offset*curve.Fr.n8); - } - offset ++; - } - } - - if (arr.length>1) { - const task = []; - task.push({cmd: "ALLOCSET", var: 0, buff: bBases}); - task.push({cmd: "ALLOCSET", var: 1, buff: bScalars}); - task.push({cmd: "ALLOC", var: 2, len: arr.length*sGmid}); - pB = 0; - pS = 0; - let pD =0; - for (let i=0; i. -*/ - -async function phase2importMPCParams(zkeyNameOld, mpcparamsName, zkeyNameNew, name, logger) { - - const {fd: fdZKeyOld, sections: sectionsZKeyOld} = await readBinFile$1(zkeyNameOld, "zkey", 2); - const zkeyHeader = await readHeader$1(fdZKeyOld, sectionsZKeyOld, false); - if (zkeyHeader.protocol != "groth16") { - throw new Error("zkey file is not groth16"); - } - - const curve = await getCurveFromQ(zkeyHeader.q); - const sG1 = curve.G1.F.n8*2; - const sG2 = curve.G2.F.n8*2; - - const oldMPCParams = await readMPCParams(fdZKeyOld, curve, sectionsZKeyOld); - const newMPCParams = {}; - - const fdMPCParams = await readExisting$3(mpcparamsName); - - fdMPCParams.pos = - sG1*3 + sG2*3 + // vKey - 8 + sG1*zkeyHeader.nVars + // IC + C - 4 + sG1*(zkeyHeader.domainSize-1) + // H - 4 + sG1*zkeyHeader.nVars + // A - 4 + sG1*zkeyHeader.nVars + // B1 - 4 + sG2*zkeyHeader.nVars; // B2 - - // csHash - newMPCParams.csHash = await fdMPCParams.read(64); - - const nContributions = await fdMPCParams.readUBE32(); - newMPCParams.contributions = []; - for (let i=0; i newMPCParams.contributions.length) { - if (logger) logger.error("The impoerted file does not include new contributions"); - return false; - } - - for (let i=0; i. -*/ -const sameRatio = sameRatio$2; - - - -async function phase2verifyFromInit(initFileName, pTauFileName, zkeyFileName, logger) { - - let sr; - const {fd, sections} = await readBinFile$1(zkeyFileName, "zkey", 2); - const zkey = await readHeader$1(fd, sections, false); - if (zkey.protocol != "groth16") { - throw new Error("zkey file is not groth16"); - } - - const curve = await getCurveFromQ(zkey.q); - const sG1 = curve.G1.F.n8*2; - - const mpcParams = await readMPCParams(fd, curve, sections); - - const accumulatedHasher = blake2b.create({ dkLen: 64 }); - accumulatedHasher.update(mpcParams.csHash); - let curDelta = curve.G1.g; - for (let i=0; i=0; i--) { - const c = mpcParams.contributions[i]; - if (logger) logger.info("-------------------------"); - if (logger) logger.info(formatHash(c.contributionHash, `contribution #${i+1} ${c.name ? c.name : ""}:`)); - if (c.type == 1) { - if (logger) logger.info(`Beacon generator: ${byteArray2hex(c.beaconHash)}`); - if (logger) logger.info(`Beacon iterations Exp: ${c.numIterationsExp}`); - } - } - if (logger) logger.info("-------------------------"); - - if (logger) logger.info("ZKey Ok!"); - - return true; - - - async function sectionHasSameRatio(groupName, fd1, sections1, fd2, sections2, idSection, g2sp, g2spx, sectionName) { - const MAX_CHUNK_SIZE = 1<<20; - const G = curve[groupName]; - const sG = G.F.n8*2; - await startReadUniqueSection$1(fd1, sections1, idSection); - await startReadUniqueSection$1(fd2, sections2, idSection); - - let R1 = G.zero; - let R2 = G.zero; - - const nPoints = sections1[idSection][0].size / sG; - - for (let i=0; i. -*/ - -async function phase2verifyFromR1cs(r1csFileName, pTauFileName, zkeyFileName, logger) { - - // const initFileName = "~" + zkeyFileName + ".init"; - const initFileName = {type: "bigMem"}; - await newZKey(r1csFileName, pTauFileName, initFileName, logger); - - return await phase2verifyFromInit(initFileName, pTauFileName, zkeyFileName, logger); -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -async function phase2contribute(zkeyNameOld, zkeyNameNew, name, entropy, logger) { - - const {fd: fdOld, sections: sections} = await readBinFile$1(zkeyNameOld, "zkey", 2); - const zkey = await readHeader$1(fdOld, sections); - if (zkey.protocol != "groth16") { - throw new Error("zkey file is not groth16"); - } - - const curve = await getCurveFromQ(zkey.q); - - const mpcParams = await readMPCParams(fdOld, curve, sections); - - const fdNew = await createBinFile(zkeyNameNew, "zkey", 1, 10); - - - const rng = await getRandomRng(entropy); - - const transcriptHasher = blake2b.create({ dkLen: 64 }); - transcriptHasher.update(mpcParams.csHash); - for (let i=0; i. -*/ - - -async function beacon(zkeyNameOld, zkeyNameNew, name, beaconHashStr, numIterationsExp, logger) { - const beaconHash = hex2ByteArray(beaconHashStr); - if ( (beaconHash.byteLength == 0) - || (beaconHash.byteLength*2 !=beaconHashStr.length)) - { - if (logger) logger.error("Invalid Beacon Hash. (It must be a valid hexadecimal sequence)"); - return false; - } - if (beaconHash.length>=256) { - if (logger) logger.error("Maximum length of beacon hash is 255 bytes"); - return false; - } - - numIterationsExp = parseInt(numIterationsExp); - if ((numIterationsExp<10)||(numIterationsExp>63)) { - if (logger) logger.error("Invalid numIterationsExp. (Must be between 10 and 63)"); - return false; - } - - - const {fd: fdOld, sections: sections} = await readBinFile$1(zkeyNameOld, "zkey", 2); - const zkey = await readHeader$1(fdOld, sections); - - if (zkey.protocol != "groth16") { - throw new Error("zkey file is not groth16"); - } - - - const curve = await getCurveFromQ(zkey.q); - - const mpcParams = await readMPCParams(fdOld, curve, sections); - - const fdNew = await createBinFile(zkeyNameNew, "zkey", 1, 10); - - const rng = await rngFromBeaconParams(beaconHash, numIterationsExp); - - const transcriptHasher = blake2b.create({ dkLen: 64 }); transcriptHasher.update(mpcParams.csHash); - for (let i=0; i. -*/ - -async function bellmanContribute(curve, challengeFilename, responseFileName, entropy, logger) { - const rng = await getRandomRng(entropy); - - const delta = curve.Fr.fromRng(rng); - const invDelta = curve.Fr.inv(delta); - - const sG1 = curve.G1.F.n8*2; - const sG2 = curve.G2.F.n8*2; - - const fdFrom = await readExisting$3(challengeFilename); - const fdTo = await createOverride(responseFileName); - - - await copy(sG1); // alpha1 - await copy(sG1); // beta1 - await copy(sG2); // beta2 - await copy(sG2); // gamma2 - const oldDelta1 = await readG1(); - const delta1 = curve.G1.timesFr(oldDelta1, delta); - await writeG1(delta1); - const oldDelta2 = await readG2(); - const delta2 = curve.G2.timesFr(oldDelta2, delta); - await writeG2(delta2); - - // IC - const nIC = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nIC); - await copy(nIC*sG1); - - // H - const nH = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nH); - await applyKeyToChallengeSection(fdFrom, fdTo, null, curve, "G1", nH, invDelta, curve.Fr.e(1), "UNCOMPRESSED", "H", logger); - - // L - const nL = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nL); - await applyKeyToChallengeSection(fdFrom, fdTo, null, curve, "G1", nL, invDelta, curve.Fr.e(1), "UNCOMPRESSED", "L", logger); - - // A - const nA = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nA); - await copy(nA*sG1); - - // B1 - const nB1 = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nB1); - await copy(nB1*sG1); - - // B2 - const nB2 = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nB2); - await copy(nB2*sG2); - - - ////////// - /// Read contributions - ////////// - const transcriptHasher = blake2b.create({ dkLen: 64 }); - const mpcParams = {}; - // csHash - mpcParams.csHash = await fdFrom.read(64); - transcriptHasher.update(mpcParams.csHash); - - const nContributions = await fdFrom.readUBE32(); - mpcParams.contributions = []; - for (let i=0; i. -*/ - -const {stringifyBigInts: stringifyBigInts$3} = utils; - -async function zkeyExportVerificationKey(zkeyName, logger) { - if (logger) logger.info("EXPORT VERIFICATION KEY STARTED"); - - const {fd, sections} = await readBinFile$1(zkeyName, "zkey", 2); - const zkey = await readHeader$1(fd, sections); - - if (logger) logger.info("> Detected protocol: " + zkey.protocol); - - let res; - if (zkey.protocol === "groth16") { - res = await groth16Vk(zkey, fd, sections); - } else if (zkey.protocol === "plonk") { - res = await plonkVk(zkey); - } else if (zkey.protocolId && zkey.protocolId === FFLONK_PROTOCOL_ID) { - res = await exportFFlonkVk(zkey); - } else { - throw new Error("zkey file protocol unrecognized"); - } - - await fd.close(); - - if (logger) logger.info("EXPORT VERIFICATION KEY FINISHED"); - - return res; -} - - -async function groth16Vk(zkey, fd, sections) { - const curve = await getCurveFromQ(zkey.q); - const sG1 = curve.G1.F.n8 * 2; - - const alphaBeta = await curve.pairing(zkey.vk_alpha_1, zkey.vk_beta_2); - - let vKey = { - protocol: zkey.protocol, - curve: curve.name, - nPublic: zkey.nPublic, - - vk_alpha_1: curve.G1.toObject(zkey.vk_alpha_1), - - vk_beta_2: curve.G2.toObject(zkey.vk_beta_2), - vk_gamma_2: curve.G2.toObject(zkey.vk_gamma_2), - vk_delta_2: curve.G2.toObject(zkey.vk_delta_2), - - vk_alphabeta_12: curve.Gt.toObject(alphaBeta) - }; - - // Read IC Section - /////////// - await startReadUniqueSection$1(fd, sections, 3); - vKey.IC = []; - for (let i = 0; i <= zkey.nPublic; i++) { - const buff = await fd.read(sG1); - const P = curve.G1.toObject(buff); - vKey.IC.push(P); - } - await endReadSection$1(fd); - - vKey = stringifyBigInts$3(vKey); - - return vKey; -} - - -async function plonkVk(zkey) { - const curve = await getCurveFromQ(zkey.q); - - let vKey = { - protocol: zkey.protocol, - curve: curve.name, - nPublic: zkey.nPublic, - power: zkey.power, - - k1: curve.Fr.toObject(zkey.k1), - k2: curve.Fr.toObject(zkey.k2), - - Qm: curve.G1.toObject(zkey.Qm), - Ql: curve.G1.toObject(zkey.Ql), - Qr: curve.G1.toObject(zkey.Qr), - Qo: curve.G1.toObject(zkey.Qo), - Qc: curve.G1.toObject(zkey.Qc), - S1: curve.G1.toObject(zkey.S1), - S2: curve.G1.toObject(zkey.S2), - S3: curve.G1.toObject(zkey.S3), - - X_2: curve.G2.toObject(zkey.X_2), - - w: curve.Fr.toObject(curve.Fr.w[zkey.power]) - }; - - vKey = stringifyBigInts$3(vKey); - - return vKey; -} - -async function exportFFlonkVk(zkey, logger) { - const curve = await getCurveFromQ(zkey.q); - - let vKey = { - protocol: zkey.protocol, - curve: curve.name, - nPublic: zkey.nPublic, - power: zkey.power, - - k1: curve.Fr.toObject(zkey.k1), - k2: curve.Fr.toObject(zkey.k2), - - w: curve.Fr.toObject(curve.Fr.w[zkey.power]), - //wW: curve.Fr.toObject(curve.Fr.w[zkey.power + 1]), - w3: curve.Fr.toObject(zkey.w3), - w4: curve.Fr.toObject(zkey.w4), - w8: curve.Fr.toObject(zkey.w8), - wr: curve.Fr.toObject(zkey.wr), - - X_2: curve.G2.toObject(zkey.X_2), - - C0: curve.G1.toObject(zkey.C0), - }; - - return stringifyBigInts$3(vKey); -} - -/* - Copyright 2021 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -const {unstringifyBigInts: unstringifyBigInts$6, stringifyBigInts: stringifyBigInts$2} = utils; - -async function fflonkExportSolidityVerifier(vk, templates, logger) { - if (logger) logger.info("FFLONK EXPORT SOLIDITY VERIFIER STARTED"); - - const curve = await getCurveFromName(vk.curve); - - // Precompute w3_2, w4_2 and w4_3 - let w3 = fromVkey(vk.w3); - vk.w3_2 = toVkey(curve.Fr.square(w3)); - - let w4 = fromVkey(vk.w4); - vk.w4_2 = toVkey(curve.Fr.square(w4)); - vk.w4_3 = toVkey(curve.Fr.mul(curve.Fr.square(w4), w4)); - - let w8 = fromVkey(vk.w8); - let acc = curve.Fr.one; - - for (let i = 1; i < 8; i++) { - acc = curve.Fr.mul(acc, w8); - vk["w8_" + i] = toVkey(acc); - } - - let template = templates[vk.protocol]; - - if (logger) logger.info("FFLONK EXPORT SOLIDITY VERIFIER FINISHED"); - - const {default: ejs} = await Promise.resolve().then(function () { return _virtual_ejs$1; }); - return ejs.render(template, vk); - - function fromVkey(str) { - const val = unstringifyBigInts$6(str); - return curve.Fr.fromObject(val); - } - - function toVkey(val) { - const str = curve.Fr.toObject(val); - return stringifyBigInts$2(str); - } -} - -// Not ready yet -// module.exports.generateVerifier_kimleeoh = generateVerifier_kimleeoh; - -async function exportSolidityVerifier(zKeyName, templates, logger) { - - const verificationKey = await zkeyExportVerificationKey(zKeyName, logger); - - if ("fflonk" === verificationKey.protocol) { - return fflonkExportSolidityVerifier(verificationKey, templates, logger); - } - - let template = templates[verificationKey.protocol]; - - const {default: ejs} = await Promise.resolve().then(function () { return _virtual_ejs$1; }); - - return ejs.render(template, verificationKey); -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -var zkey = /*#__PURE__*/Object.freeze({ - __proto__: null, - newZKey: newZKey, - exportBellman: phase2exportMPCParams, - importBellman: phase2importMPCParams, - verifyFromR1cs: phase2verifyFromR1cs, - verifyFromInit: phase2verifyFromInit, - contribute: phase2contribute, - beacon: beacon, - exportJson: zkeyExportJson, - bellmanContribute: bellmanContribute, - exportVerificationKey: zkeyExportVerificationKey, - exportSolidityVerifier: exportSolidityVerifier -}); - -/* - Copyright 2021 0kims association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - - -async function plonkSetup(r1csName, ptauName, zkeyName, logger) { - - if (globalThis.gc) {globalThis.gc();} - - const {fd: fdPTau, sections: sectionsPTau} = await readBinFile$1(ptauName, "ptau", 1); - const {curve, power} = await readPTauHeader(fdPTau, sectionsPTau); - const {fd: fdR1cs, sections: sectionsR1cs} = await readBinFile$1(r1csName, "r1cs", 1); - - const r1cs = await readR1csFd(fdR1cs, sectionsR1cs, {loadConstraints: true, loadCustomGates: true}); - - const sG1 = curve.G1.F.n8*2; - const G1 = curve.G1; - const sG2 = curve.G2.F.n8*2; - const Fr = curve.Fr; - const n8r = curve.Fr.n8; - - if (logger) logger.info("Reading r1cs"); - await readSection$1(fdR1cs, sectionsR1cs, 2); - - const plonkConstraints = new BigArray$1(); - const plonkAdditions = new BigArray$1(); - let plonkNVars = r1cs.nVars; - - const nPublic = r1cs.nOutputs + r1cs.nPubInputs; - - await processConstraints(curve.Fr, r1cs, logger); - - if (globalThis.gc) {globalThis.gc();} - - const fdZKey = await createBinFile(zkeyName, "zkey", 1, 14, 1<<22, 1<<24); - - - if (r1cs.prime != curve.r) { - if (logger) logger.error("r1cs curve does not match powers of tau ceremony curve"); - return -1; - } - - let cirPower = log2(plonkConstraints.length -1) +1; - if (cirPower < 3) cirPower = 3; // As the t polynomial is n+5 we need at least a power of 4 - const domainSize = 2 ** cirPower; - - if (logger) logger.info("Plonk constraints: " + plonkConstraints.length); - if (cirPower > power) { - if (logger) logger.error(`circuit too big for this power of tau ceremony. ${plonkConstraints.length} > 2**${power}`); - return -1; - } - - if (!sectionsPTau[12]) { - if (logger) logger.error("Powers of tau is not prepared."); - return -1; - } - - - const LPoints = new BigBuffer(domainSize*sG1); - const o = sectionsPTau[12][0].p + ((2 ** (cirPower)) -1)*sG1; - await fdPTau.readToBuffer(LPoints, 0, domainSize*sG1, o); - - const [k1, k2] = getK1K2(); - - const vk = {}; - - - await writeAdditions(3, "Additions"); - if (globalThis.gc) {globalThis.gc();} - await writeWitnessMap(4, 0, "Amap"); - if (globalThis.gc) {globalThis.gc();} - await writeWitnessMap(5, 1, "Bmap"); - if (globalThis.gc) {globalThis.gc();} - await writeWitnessMap(6, 2, "Cmap"); - if (globalThis.gc) {globalThis.gc();} - await writeQMap(7, 3, "Qm"); - if (globalThis.gc) {globalThis.gc();} - await writeQMap(8, 4, "Ql"); - if (globalThis.gc) {globalThis.gc();} - await writeQMap(9, 5, "Qr"); - if (globalThis.gc) {globalThis.gc();} - await writeQMap(10, 6, "Qo"); - if (globalThis.gc) {globalThis.gc();} - await writeQMap(11, 7, "Qc"); - if (globalThis.gc) {globalThis.gc();} - await writeSigma(12, "sigma"); - if (globalThis.gc) {globalThis.gc();} - await writeLs(13, "lagrange polynomials"); - if (globalThis.gc) {globalThis.gc();} - - // Write PTau points - //////////// - - await startWriteSection(fdZKey, 14); - const buffOut = new BigBuffer((domainSize+6)*sG1); - await fdPTau.readToBuffer(buffOut, 0, (domainSize+6)*sG1, sectionsPTau[2][0].p); - await fdZKey.write(buffOut); - await endWriteSection(fdZKey); - if (globalThis.gc) {globalThis.gc();} - - - await writeHeaders(); - - await fdZKey.close(); - await fdR1cs.close(); - await fdPTau.close(); - - if (logger) logger.info("Setup Finished"); - - return ; - - async function processConstraints(Fr, r1cs, logger) { - - function normalize(linearComb) { - const ss = Object.keys(linearComb); - for (let i = 0; i < ss.length; i++) { - if (linearComb[ss[i]] == 0n) delete linearComb[ss[i]]; - } - } - - function join(linearComb1, k, linearComb2) { - const res = {}; - - for (let s in linearComb1) { - if (typeof res[s] == "undefined") { - res[s] = Fr.mul(k, linearComb1[s]); - } else { - res[s] = Fr.add(res[s], Fr.mul(k, linearComb1[s])); - } - } - - for (let s in linearComb2) { - if (typeof res[s] == "undefined") { - res[s] = linearComb2[s]; - } else { - res[s] = Fr.add(res[s], linearComb2[s]); - } - } - normalize(res); - return res; - } - - function reduceCoefs(linearComb, maxC) { - const res = { - k: Fr.zero, - s: [], - coefs: [] - }; - const cs = []; - - for (let s in linearComb) { - if (s == 0) { - res.k = Fr.add(res.k, linearComb[s]); - } else if (linearComb[s] != 0n) { - cs.push([Number(s), linearComb[s]]); - } - } - while (cs.length > maxC) { - const c1 = cs.shift(); - const c2 = cs.shift(); - - const sl = c1[0]; - const sr = c2[0]; - const so = plonkNVars++; - const qm = Fr.zero; - const ql = Fr.neg(c1[1]); - const qr = Fr.neg(c2[1]); - const qo = Fr.one; - const qc = Fr.zero; - - plonkConstraints.push([sl, sr, so, qm, ql, qr, qo, qc]); - - plonkAdditions.push([sl, sr, c1[1], c2[1]]); - - cs.push([so, Fr.one]); - } - for (let i = 0; i < cs.length; i++) { - res.s[i] = cs[i][0]; - res.coefs[i] = cs[i][1]; - } - while (res.coefs.length < maxC) { - res.s.push(0); - res.coefs.push(Fr.zero); - } - return res; - } - - function addConstraintSum(lc) { - const C = reduceCoefs(lc, 3); - const sl = C.s[0]; - const sr = C.s[1]; - const so = C.s[2]; - const qm = Fr.zero; - const ql = C.coefs[0]; - const qr = C.coefs[1]; - const qo = C.coefs[2]; - const qc = C.k; - plonkConstraints.push([sl, sr, so, qm, ql, qr, qo, qc]); - } - - function addConstraintMul(lcA, lcB, lcC) { - const A = reduceCoefs(lcA, 1); - const B = reduceCoefs(lcB, 1); - const C = reduceCoefs(lcC, 1); - - - const sl = A.s[0]; - const sr = B.s[0]; - const so = C.s[0]; - const qm = Fr.mul(A.coefs[0], B.coefs[0]); - const ql = Fr.mul(A.coefs[0], B.k); - const qr = Fr.mul(A.k, B.coefs[0]); - const qo = Fr.neg(C.coefs[0]); - const qc = Fr.sub(Fr.mul(A.k, B.k), C.k); - plonkConstraints.push([sl, sr, so, qm, ql, qr, qo, qc]); - } - - function getLinearCombinationType(lc) { - let k = Fr.zero; - let n = 0; - const ss = Object.keys(lc); - for (let i = 0; i < ss.length; i++) { - if (lc[ss[i]] == 0n) { - delete lc[ss[i]]; - } else if (ss[i] == 0) { - k = Fr.add(k, lc[ss[i]]); - } else { - n++; - } - } - if (n > 0) return n.toString(); - if (k != Fr.zero) return "k"; - return "0"; - } - - function process(lcA, lcB, lcC) { - const lctA = getLinearCombinationType(lcA); - const lctB = getLinearCombinationType(lcB); - if ((lctA === "0") || (lctB === "0")) { - normalize(lcC); - addConstraintSum(lcC); - } else if (lctA === "k") { - const lcCC = join(lcB, lcA[0], lcC); - addConstraintSum(lcCC); - } else if (lctB === "k") { - const lcCC = join(lcA, lcB[0], lcC); - addConstraintSum(lcCC); - } else { - addConstraintMul(lcA, lcB, lcC); - } - } - - for (let s = 1; s <= nPublic; s++) { - const sl = s; - const sr = 0; - const so = 0; - const qm = Fr.zero; - const ql = Fr.one; - const qr = Fr.zero; - const qo = Fr.zero; - const qc = Fr.zero; - - plonkConstraints.push([sl, sr, so, qm, ql, qr, qo, qc]); - } - - for (let c = 0; c < r1cs.constraints.length; c++) { - if ((logger) && (c % 10000 === 0)) logger.debug(`processing constraints: ${c}/${r1cs.nConstraints}`); - process(...r1cs.constraints[c]); - } - } - - async function writeWitnessMap(sectionNum, posConstraint, name) { - await startWriteSection(fdZKey, sectionNum); - for (let i=0; i. -*/ - -class Proof { - constructor(curve, logger) { - this.curve = curve; - this.logger = logger; - - this.resetProof(); - } - - resetProof() { - this.polynomials = {}; - this.evaluations = {}; - } - - addPolynomial(key, polynomial) { - if (key in this.polynomials) { - this.logger.warn(`proof: polynomial.${key} already exist in proof`); - } - this.polynomials[key] = polynomial; - } - - getPolynomial(key) { - if (!(key in this.polynomials)) { - this.logger.warn(`proof: polynomial ${key} does not exist in proof`); - } - return this.polynomials[key]; - } - - addEvaluation(key, evaluation) { - if (key in this.evaluations) { - this.logger.warn(`proof: evaluations.${key} already exist in proof`); - } - this.evaluations[key] = evaluation; - } - - getEvaluation(key) { - if (!(key in this.evaluations)) { - this.logger.warn(`proof: evaluation ${key} does not exist in proof`); - } - return this.evaluations[key]; - } - - toObjectProof(splitFields = true) { - let res = splitFields ? {polynomials: {}, evaluations: {}} : {}; - - Object.keys(this.polynomials).forEach(key => { - const value = this.curve.G1.toObject(this.polynomials[key]); - if(splitFields) { - res.polynomials[key] = value; - } else { - res[key] = value; - } - }); - - Object.keys(this.evaluations).forEach(key => { - const value = this.curve.Fr.toObject(this.evaluations[key]); - if(splitFields) { - res.evaluations[key] = value; - } else { - res[key] = value; - } - }); - - return res; - } - - fromObjectProof(objectProof) { - this.resetProof(); - - Object.keys(objectProof.polynomials).forEach(key => { - this.polynomials[key] = this.curve.G1.fromObject(objectProof.polynomials[key]); - }); - - Object.keys(objectProof.evaluations).forEach(key => { - this.evaluations[key] = this.curve.Fr.fromObject(objectProof.evaluations[key]); - }); - } -} - -/** - * SHA3 (keccak) hash function, based on a new "Sponge function" design. - * Different from older hashes, the internal state is bigger than output size. - * - * Check out [FIPS-202](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf), - * [Website](https://keccak.team/keccak.html), - * [the differences between SHA-3 and Keccak](https://crypto.stackexchange.com/questions/15727/what-are-the-key-differences-between-the-draft-sha-3-standard-and-the-keccak-sub). - * - * Check out `sha3-addons` module for cSHAKE, k12, and others. - * @module - */ -// Various per round constants calculations -const SHA3_PI = []; -const SHA3_ROTL = []; -const _SHA3_IOTA = []; -const _0n = /* @__PURE__ */ BigInt(0); -const _1n = /* @__PURE__ */ BigInt(1); -const _2n = /* @__PURE__ */ BigInt(2); -const _7n = /* @__PURE__ */ BigInt(7); -const _256n = /* @__PURE__ */ BigInt(256); -const _0x71n = /* @__PURE__ */ BigInt(0x71); -for (let round = 0, R = _1n, x = 1, y = 0; round < 24; round++) { - // Pi - [x, y] = [y, (2 * x + 3 * y) % 5]; - SHA3_PI.push(2 * (5 * y + x)); - // Rotational - SHA3_ROTL.push((((round + 1) * (round + 2)) / 2) % 64); - // Iota - let t = _0n; - for (let j = 0; j < 7; j++) { - R = ((R << _1n) ^ ((R >> _7n) * _0x71n)) % _256n; - if (R & _2n) - t ^= _1n << ((_1n << /* @__PURE__ */ BigInt(j)) - _1n); - } - _SHA3_IOTA.push(t); -} -const [SHA3_IOTA_H, SHA3_IOTA_L] = /* @__PURE__ */ split(_SHA3_IOTA, true); -// Left rotation (without 0, 32, 64) -const rotlH = (h, l, s) => (s > 32 ? rotlBH(h, l, s) : rotlSH(h, l, s)); -const rotlL = (h, l, s) => (s > 32 ? rotlBL(h, l, s) : rotlSL(h, l, s)); -/** `keccakf1600` internal function, additionally allows to adjust round count. */ -function keccakP(s, rounds = 24) { - const B = new Uint32Array(5 * 2); - // NOTE: all indices are x2 since we store state as u32 instead of u64 (bigints to slow in js) - for (let round = 24 - rounds; round < 24; round++) { - // Theta θ - for (let x = 0; x < 10; x++) - B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40]; - for (let x = 0; x < 10; x += 2) { - const idx1 = (x + 8) % 10; - const idx0 = (x + 2) % 10; - const B0 = B[idx0]; - const B1 = B[idx0 + 1]; - const Th = rotlH(B0, B1, 1) ^ B[idx1]; - const Tl = rotlL(B0, B1, 1) ^ B[idx1 + 1]; - for (let y = 0; y < 50; y += 10) { - s[x + y] ^= Th; - s[x + y + 1] ^= Tl; - } - } - // Rho (ρ) and Pi (π) - let curH = s[2]; - let curL = s[3]; - for (let t = 0; t < 24; t++) { - const shift = SHA3_ROTL[t]; - const Th = rotlH(curH, curL, shift); - const Tl = rotlL(curH, curL, shift); - const PI = SHA3_PI[t]; - curH = s[PI]; - curL = s[PI + 1]; - s[PI] = Th; - s[PI + 1] = Tl; - } - // Chi (χ) - for (let y = 0; y < 50; y += 10) { - for (let x = 0; x < 10; x++) - B[x] = s[y + x]; - for (let x = 0; x < 10; x++) - s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10]; - } - // Iota (ι) - s[0] ^= SHA3_IOTA_H[round]; - s[1] ^= SHA3_IOTA_L[round]; - } - B.fill(0); -} -/** Keccak sponge function. */ -class Keccak extends Hash { - // NOTE: we accept arguments in bytes instead of bits here. - constructor(blockLen, suffix, outputLen, enableXOF = false, rounds = 24) { - super(); - this.blockLen = blockLen; - this.suffix = suffix; - this.outputLen = outputLen; - this.enableXOF = enableXOF; - this.rounds = rounds; - this.pos = 0; - this.posOut = 0; - this.finished = false; - this.destroyed = false; - // Can be passed from user as dkLen - anumber(outputLen); - // 1600 = 5x5 matrix of 64bit. 1600 bits === 200 bytes - // 0 < blockLen < 200 - if (0 >= this.blockLen || this.blockLen >= 200) - throw new Error('Sha3 supports only keccak-f1600 function'); - this.state = new Uint8Array(200); - this.state32 = u32(this.state); - } - keccak() { - if (!isLE) - byteSwap32(this.state32); - keccakP(this.state32, this.rounds); - if (!isLE) - byteSwap32(this.state32); - this.posOut = 0; - this.pos = 0; - } - update(data) { - aexists(this); - const { blockLen, state } = this; - data = toBytes(data); - const len = data.length; - for (let pos = 0; pos < len;) { - const take = Math.min(blockLen - this.pos, len - pos); - for (let i = 0; i < take; i++) - state[this.pos++] ^= data[pos++]; - if (this.pos === blockLen) - this.keccak(); - } - return this; - } - finish() { - if (this.finished) - return; - this.finished = true; - const { state, suffix, pos, blockLen } = this; - // Do the padding - state[pos] ^= suffix; - if ((suffix & 0x80) !== 0 && pos === blockLen - 1) - this.keccak(); - state[blockLen - 1] ^= 0x80; - this.keccak(); - } - writeInto(out) { - aexists(this, false); - abytes(out); - this.finish(); - const bufferOut = this.state; - const { blockLen } = this; - for (let pos = 0, len = out.length; pos < len;) { - if (this.posOut >= blockLen) - this.keccak(); - const take = Math.min(blockLen - this.posOut, len - pos); - out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos); - this.posOut += take; - pos += take; - } - return out; - } - xofInto(out) { - // Sha3/Keccak usage with XOF is probably mistake, only SHAKE instances can do XOF - if (!this.enableXOF) - throw new Error('XOF is not possible for this instance'); - return this.writeInto(out); - } - xof(bytes) { - anumber(bytes); - return this.xofInto(new Uint8Array(bytes)); - } - digestInto(out) { - aoutput(out, this); - if (this.finished) - throw new Error('digest() was already called'); - this.writeInto(out); - this.destroy(); - return out; - } - digest() { - return this.digestInto(new Uint8Array(this.outputLen)); - } - destroy() { - this.destroyed = true; - this.state.fill(0); - } - _cloneInto(to) { - const { blockLen, suffix, outputLen, rounds, enableXOF } = this; - to || (to = new Keccak(blockLen, suffix, outputLen, enableXOF, rounds)); - to.state32.set(this.state32); - to.pos = this.pos; - to.posOut = this.posOut; - to.finished = this.finished; - to.rounds = rounds; - // Suffix can change in cSHAKE - to.suffix = suffix; - to.outputLen = outputLen; - to.enableXOF = enableXOF; - to.destroyed = this.destroyed; - return to; - } -} -const gen = (suffix, blockLen, outputLen) => wrapConstructor(() => new Keccak(blockLen, suffix, outputLen)); -/** keccak-256 hash function. Different from SHA3-256. */ -const keccak_256 = /* @__PURE__ */ gen(0x01, 136, 256 / 8); - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -const POLYNOMIAL = 0; -const SCALAR = 1; - -class Keccak256Transcript { - constructor(curve) { - this.G1 = curve.G1; - this.Fr = curve.Fr; - - this.reset(); - } - - reset() { - this.data = []; - } - - addPolCommitment(polynomialCommitment) { - this.data.push({type: POLYNOMIAL, data: polynomialCommitment}); - } - - addScalar(scalar) { - this.data.push({type: SCALAR, data: scalar}); - } - - getChallenge() { - if(0 === this.data.length) { - throw new Error("Keccak256Transcript: No data to generate a transcript"); - } - - let nPolynomials = 0; - let nScalars = 0; - - this.data.forEach(element => POLYNOMIAL === element.type ? nPolynomials++ : nScalars++); - - let buffer = new Uint8Array(nScalars * this.Fr.n8 + nPolynomials * this.G1.F.n8 * 2); - let offset = 0; - - for (let i = 0; i < this.data.length; i++) { - if (POLYNOMIAL === this.data[i].type) { - this.G1.toRprUncompressed(buffer, offset, this.data[i].data); - offset += this.G1.F.n8 * 2; - } else { - this.Fr.toRprBE(buffer, offset, this.data[i].data); - offset += this.Fr.n8; - } - } - - const value = Scalar.fromRprBE(keccak_256(buffer)); - return this.Fr.e(value); - } -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -class MulZ { - static getZ1(Fr) { - return [ - Fr.zero, - Fr.add(Fr.e(-1), Fr.w[2]), - Fr.e(-2), - Fr.sub(Fr.e(-1), Fr.w[2]), - ]; - } - - static getZ2(Fr) { - return [ - Fr.zero, - Fr.add(Fr.zero, Fr.mul(Fr.e(-2), Fr.w[2])), - Fr.e(4), - Fr.sub(Fr.zero, Fr.mul(Fr.e(-2), Fr.w[2])), - ]; - } - - static getZ3(Fr) { - return [ - Fr.zero, - Fr.add(Fr.e(2), Fr.mul(Fr.e(2), Fr.w[2])), - Fr.e(-8), - Fr.sub(Fr.e(2), Fr.mul(Fr.e(2), Fr.w[2])), - ]; - - } - - static mul2(a, b, ap, bp, p, Fr) { - const Z1 = this.getZ1(Fr); - let r, rz; - - const a_b = Fr.mul(a, b); - const a_bp = Fr.mul(a, bp); - const ap_b = Fr.mul(ap, b); - const ap_bp = Fr.mul(ap, bp); - - r = a_b; - - let a0 = Fr.add(a_bp, ap_b); - - let a1 = ap_bp; - - rz = a0; - if (p) { - rz = Fr.add(rz, Fr.mul(Z1[p], a1)); - } - - return [r, rz]; - } - - static mul3(a, b, c, ap, bp, cp, p, Fr) { - const Z1 = this.getZ1(Fr); - const Z2 = this.getZ2(Fr); - let r, rz; - - const a_b = Fr.mul(a, b); - const a_bp = Fr.mul(a, bp); - const ap_b = Fr.mul(ap, b); - const ap_bp = Fr.mul(ap, bp); - - r = Fr.mul(a_b, c); - - let a0 = Fr.mul(ap_b, c); - a0 = Fr.add(a0, Fr.mul(a_bp, c)); - a0 = Fr.add(a0, Fr.mul(a_b, cp)); - - let a1 = Fr.mul(ap_bp, c); - a1 = Fr.add(a1, Fr.mul(a_bp, cp)); - a1 = Fr.add(a1, Fr.mul(ap_b, cp)); - - rz = a0; - if (p) { - const a2 = Fr.mul(ap_bp, cp); - rz = Fr.add(rz, Fr.mul(Z1[p], a1)); - rz = Fr.add(rz, Fr.mul(Z2[p], a2)); - } - - return [r, rz]; - } - - static mul4(a, b, c, d, ap, bp, cp, dp, p, Fr) { - const Z1 = this.getZ1(Fr); - const Z2 = this.getZ2(Fr); - const Z3 = this.getZ3(Fr); - - let r, rz; - - const a_b = Fr.mul(a, b); - const a_bp = Fr.mul(a, bp); - const ap_b = Fr.mul(ap, b); - const ap_bp = Fr.mul(ap, bp); - - const c_d = Fr.mul(c, d); - const c_dp = Fr.mul(c, dp); - const cp_d = Fr.mul(cp, d); - const cp_dp = Fr.mul(cp, dp); - - r = Fr.mul(a_b, c_d); - - let a0 = Fr.mul(ap_b, c_d); - a0 = Fr.add(a0, Fr.mul(a_bp, c_d)); - a0 = Fr.add(a0, Fr.mul(a_b, cp_d)); - a0 = Fr.add(a0, Fr.mul(a_b, c_dp)); - - let a1 = Fr.mul(ap_bp, c_d); - a1 = Fr.add(a1, Fr.mul(ap_b, cp_d)); - a1 = Fr.add(a1, Fr.mul(ap_b, c_dp)); - a1 = Fr.add(a1, Fr.mul(a_bp, cp_d)); - a1 = Fr.add(a1, Fr.mul(a_bp, c_dp)); - a1 = Fr.add(a1, Fr.mul(a_b, cp_dp)); - - let a2 = Fr.mul(a_bp, cp_dp); - a2 = Fr.add(a2, Fr.mul(ap_b, cp_dp)); - a2 = Fr.add(a2, Fr.mul(ap_bp, c_dp)); - a2 = Fr.add(a2, Fr.mul(ap_bp, cp_d)); - - let a3 = Fr.mul(ap_bp, cp_dp); - - rz = a0; - if (p) { - rz = Fr.add(rz, Fr.mul(Z1[p], a1)); - rz = Fr.add(rz, Fr.mul(Z2[p], a2)); - rz = Fr.add(rz, Fr.mul(Z3[p], a3)); - } - - return [r, rz]; - } -} - -const ZKEY_PL_ADDITIONS_SECTION = 3; -const ZKEY_PL_A_MAP_SECTION = 4; -const ZKEY_PL_B_MAP_SECTION = 5; -const ZKEY_PL_C_MAP_SECTION = 6; -const ZKEY_PL_QM_SECTION = 7; -const ZKEY_PL_QL_SECTION = 8; -const ZKEY_PL_QR_SECTION = 9; -const ZKEY_PL_QO_SECTION = 10; -const ZKEY_PL_QC_SECTION = 11; -const ZKEY_PL_SIGMA_SECTION = 12; -const ZKEY_PL_LAGRANGE_SECTION = 13; -const ZKEY_PL_PTAU_SECTION = 14; - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -class Polynomial { - constructor(coefficients, curve, logger) { - this.coef = coefficients; - this.curve = curve; - this.Fr = curve.Fr; - this.G1 = curve.G1; - this.logger = logger; - } - - static async fromEvaluations(buffer, curve, logger) { - let coefficients = await curve.Fr.ifft(buffer); - - return new Polynomial(coefficients, curve, logger); - } - - static fromCoefficientsArray(array, curve, logger) { - const Fr = curve.Fr; - let buff = array.length > 2 << 14 ? - new BigBuffer(array.length * Fr.n8) : new Uint8Array(array.length * Fr.n8); - for (let i = 0; i < array.length; i++) buff.set(array[i], i * Fr.n8); - - return new Polynomial(buff, curve, logger); - } - - static fromPolynomial(polynomial, curve, logger) { - let length = polynomial.length(); - let Fr = curve.Fr; - - let buff = length > 2 << 14 ? - new BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8); - buff.set(polynomial.coef.slice(), 0); - - return new Polynomial(buff, curve, logger); - } - - isEqual(polynomial) { - const degree = this.degree(); - if (degree !== polynomial.degree()) return false; - - for (let i = 0; i < degree + 1; i++) { - if (!this.Fr.eq(this.getCoef(i), polynomial.getCoef(i))) return false; - } - - return true; - } - - blindCoefficients(blindingFactors) { - blindingFactors = blindingFactors || []; - - const blindedCoefficients = (this.length() + blindingFactors.length) > 2 << 14 ? - new BigBuffer((this.length() + blindingFactors.length) * this.Fr.n8) : - new Uint8Array((this.length() + blindingFactors.length) * this.Fr.n8); - - blindedCoefficients.set(this.coef, 0); - for (let i = 0; i < blindingFactors.length; i++) { - blindedCoefficients.set( - this.Fr.add( - blindedCoefficients.slice((this.length() + i) * this.Fr.n8, (this.length() + i + 1) * this.Fr.n8), - blindingFactors[i] - ), - (this.length() + i) * this.Fr.n8 - ); - blindedCoefficients.set( - this.Fr.sub( - blindedCoefficients.slice(i * this.Fr.n8, (i + 1) * this.Fr.n8), - blindingFactors[i] - ), - i * this.Fr.n8 - ); - } - this.coef = blindedCoefficients; - } - - getCoef(index) { - const i_n8 = index * this.Fr.n8; - - if (i_n8 + this.Fr.n8 > this.coef.byteLength) return this.Fr.zero; - - return this.coef.slice(i_n8, i_n8 + this.Fr.n8); - } - - setCoef(index, value) { - if (index > (this.length() - 1)) { - throw new Error("Coef index is not available"); - } - - this.coef.set(value, index * this.Fr.n8); - } - - static async to4T(buffer, domainSize, blindingFactors, Fr) { - blindingFactors = blindingFactors || []; - let a = await Fr.ifft(buffer); - - const a4 = (domainSize * 4) > 2 << 14 ? - new BigBuffer(domainSize * 4 * Fr.n8) : new Uint8Array(domainSize * 4 * Fr.n8); - a4.set(a, 0); - - const A4 = await Fr.fft(a4); - - if (blindingFactors.length === 0) { - return [a, A4]; - } - - const a1 = domainSize + blindingFactors.length > 2 << 14 ? - new BigBuffer((domainSize + blindingFactors.length) * Fr.n8) : - new Uint8Array((domainSize + blindingFactors.length) * Fr.n8); - - a1.set(a, 0); - for (let i = 0; i < blindingFactors.length; i++) { - a1.set( - Fr.add( - a1.slice((domainSize + i) * Fr.n8, (domainSize + i + 1) * Fr.n8), - blindingFactors[i] - ), - (domainSize + i) * Fr.n8 - ); - a1.set( - Fr.sub( - a1.slice(i * Fr.n8, (i + 1) * Fr.n8), - blindingFactors[i] - ), - i * Fr.n8 - ); - } - - return [a1, A4]; - } - - length() { - let length = this.coef.byteLength / this.Fr.n8; - if (length !== Math.floor(this.coef.byteLength / this.Fr.n8)) { - throw new Error("Polynomial coefficients buffer has incorrect size"); - } - if (0 === length) { - if (this.logger) { - this.logger.warn("Polynomial has length zero"); - } - } - return length; - } - - degree() { - for (let i = this.length() - 1; i > 0; i--) { - const i_n8 = i * this.Fr.n8; - if (!this.Fr.eq(this.Fr.zero, this.coef.slice(i_n8, i_n8 + this.Fr.n8))) { - return i; - } - } - - return 0; - } - - evaluate(point) { - let res = this.Fr.zero; - - for (let i = this.degree() + 1; i > 0; i--) { - let i_n8 = i * this.Fr.n8; - const currentCoefficient = this.coef.slice(i_n8 - this.Fr.n8, i_n8); - res = this.Fr.add(currentCoefficient, this.Fr.mul(res, point)); - } - - return res; - } - - fastEvaluate(point) { - const Fr = this.Fr; - let nThreads = 3; - - let nCoefs = this.degree() + 1; - let coefsThread = parseInt(nCoefs / nThreads); - let residualCoefs = nCoefs - coefsThread * nThreads; - - let res = []; - let xN = []; - - xN[0] = Fr.one; - - for (let i = 0; i < nThreads; i++) { - res[i] = Fr.zero; - - let nCoefs = i === (nThreads - 1) ? coefsThread + residualCoefs : coefsThread; - for (let j = nCoefs; j > 0; j--) { - res[i] = Fr.add(this.getCoef((i * coefsThread) + j - 1), Fr.mul(res[i], point)); - - if (i === 0) xN[0] = Fr.mul(xN[0], point); - } - } - - for (let i = 1; i < nThreads; i++) { - res[0] = Fr.add(res[0], Fr.mul(xN[i - 1], res[i])); - xN[i] = Fr.mul(xN[i - 1], xN[0]); - } - - return res[0]; - } - - add(polynomial, blindingValue) { - let other = false; - - if (polynomial.length() > this.length()) { - other = true; - } - - const thisLength = this.length(); - const polyLength = polynomial.length(); - for (let i = 0; i < Math.max(thisLength, polyLength); i++) { - const i_n8 = i * this.Fr.n8; - - const a = i < thisLength ? this.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; - let b = i < polyLength ? polynomial.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; - - if (blindingValue !== undefined) { - b = this.Fr.mul(b, blindingValue); - } - if (other) { - polynomial.coef.set(this.Fr.add(a, b), i_n8); - } else { - this.coef.set(this.Fr.add(a, b), i_n8); - } - } - if (other) { - delete this.coef; - this.coef = polynomial.coef; - } - } - - sub(polynomial, blindingValue) { - let other = false; - - if (polynomial.length() > this.length()) { - other = true; - } - - const thisLength = this.length(); - const polyLength = polynomial.length(); - for (let i = 0; i < Math.max(thisLength, polyLength); i++) { - const i_n8 = i * this.Fr.n8; - - const a = i < thisLength ? this.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; - let b = i < polyLength ? polynomial.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; - - if (blindingValue !== undefined) { - b = this.Fr.mul(b, blindingValue); - } - if (other) { - polynomial.coef.set(this.Fr.sub(a, b), i_n8); - } else { - this.coef.set(this.Fr.sub(a, b), i_n8); - } - } - if (other) { - delete this.coef; - this.coef = polynomial.coef; - } - } - - mulScalar(value) { - for (let i = 0; i < this.length(); i++) { - const i_n8 = i * this.Fr.n8; - - this.coef.set(this.Fr.mul(this.coef.slice(i_n8, i_n8 + this.Fr.n8), value), i_n8); - } - } - - addScalar(value) { - const currentValue = 0 === this.length() ? this.Fr.zero : this.coef.slice(0, this.Fr.n8); - this.coef.set(this.Fr.add(currentValue, value), 0); - } - - subScalar(value) { - const currentValue = 0 === this.length() ? this.Fr.zero : this.coef.slice(0, this.Fr.n8); - this.coef.set(this.Fr.sub(currentValue, value), 0); - } - - // Multiply current polynomial by the polynomial (X - value) - byXSubValue(value) { - const Fr = this.Fr; - const resize = !Fr.eq(Fr.zero, this.getCoef(this.length() - 1)); - - const length = resize ? this.length() + 1 : this.length(); - const buff = length > 2 << 14 ? new BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8); - let pol = new Polynomial(buff, this.curve, this.logger); - - // Step 0: Set current coefficients to the new buffer shifted one position - pol.coef.set(this.coef.slice(0, (length - 1) * Fr.n8), 32); - - // Step 1: multiply each coefficient by (-value) - this.mulScalar(Fr.neg(value)); - - // Step 2: Add current polynomial to destination polynomial - pol.add(this); - - // Swap buffers - this.coef = pol.coef; - } - - // Multiply current polynomial by the polynomial (X^n + value) - byXNSubValue(n, value) { - const Fr = this.Fr; - const resize = !(this.length() - n - 1 >= this.degree()); - - const length = resize ? this.length() + n : this.length(); - const buff = length > 2 << 14 ? new BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8); - let pol = new Polynomial(buff, this.curve, this.logger); - - // Step 0: Set current coefficients to the new buffer shifted one position - pol.coef.set(this.coef.slice(0, (this.degree() + 1) * 32, ), n * 32); - - // Step 1: multiply each coefficient by (- value) - this.mulScalar(value); - - // Step 2: Add current polynomial to destination polynomial - pol.add(this); - - // Swap buffers - this.coef = pol.coef; - } - - // Euclidean division - divBy(polynomial) { - const Fr = this.Fr; - const degreeA = this.degree(); - const degreeB = polynomial.degree(); - - let polR = new Polynomial(this.coef, this.curve, this.logger); - - this.coef = this.length() > 2 << 14 ? - new BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); - - for (let i = degreeA - degreeB; i >= 0; i--) { - this.setCoef(i, Fr.div(polR.getCoef(i + degreeB), polynomial.getCoef(degreeB))); - for (let j = 0; j <= degreeB; j++) { - polR.setCoef(i + j, Fr.sub(polR.getCoef(i + j), Fr.mul(this.getCoef(i), polynomial.getCoef(j)))); - } - } - - return polR; - } - - // Division by a Polynomial of the form (x^m - beta) - divByMonic(m, beta) { - const Fr = this.Fr; - - let d = this.degree(); - - let buffer = this.length() > 2 << 14 ? - new BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); - let quotient = new Polynomial(buffer, this.curve, this.logger); - - let bArr = []; - - // Add the m leading coefficients of this to quotient - for (let i = 0; i < m; i++) { - quotient.setCoef((d - i) - m, this.getCoef(d - i)); - bArr[i] = this.getCoef(d - i); - } - - let nThreads = m; - for (let k = 0; k < nThreads; k++) { - for (let i = d - 2 * m - k; i >= 0; i = i - nThreads) { - if (i < 0) break; - let idx = k; - bArr[idx] = Fr.add(this.getCoef(i + m), Fr.mul(bArr[idx], beta)); - - quotient.setCoef(i, bArr[idx]); - } - } - - this.coef = quotient.coef; - } - - divByVanishing(n, beta) { - if (this.degree() < n) { - throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); - } - - const Fr = this.Fr; - - let polR = new Polynomial(this.coef, this.curve, this.logger); - - this.coef = this.length() > 2 << 14 ? - new BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); - - for (let i = this.length() - 1; i >= n; i--) { - let leadingCoef = polR.getCoef(i); - if (Fr.eq(Fr.zero, leadingCoef)) continue; - - polR.setCoef(i, Fr.zero); - polR.setCoef(i - n, Fr.add(polR.getCoef(i - n), Fr.mul(beta, leadingCoef))); - this.setCoef(i - n, Fr.add(this.getCoef(i - n), leadingCoef)); - } - - return polR; - } - - divByVanishing2(m, beta) { - if (this.degree() < m) { - throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); - } - - const Fr = this.Fr; - - let polR = new Polynomial(this.coef, this.curve, this.logger); - - this.coef = this.length() > 2 << 14 ? - new BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); - - let nThreads = 3; - let nTotal = this.length() - m; - let nElementsChunk = Math.floor(nTotal / nThreads); - let nElementsLast = nTotal - (nThreads - 1) * nElementsChunk; - - console.log(nTotal); - console.log(nElementsChunk + " " + nElementsLast); - for (let k = 0; k < nThreads; k++) { - console.log("> Thread " + k); - for (let i = (k === 0 ? nElementsLast : nElementsChunk); i > 0; i--) { - let idxDst = i - 1; - if (k !== 0) idxDst += (k - 1) * nElementsChunk + nElementsLast; - let idxSrc = idxDst + m; - - let leadingCoef = polR.getCoef(idxSrc); - if (Fr.eq(Fr.zero, leadingCoef)) continue; - - polR.setCoef(idxSrc, Fr.zero); - polR.setCoef(idxDst, Fr.add(polR.getCoef(idxDst), Fr.mul(beta, leadingCoef))); - this.setCoef(idxDst, Fr.add(this.getCoef(idxDst), leadingCoef)); - console.log(idxDst + " <-- " + idxSrc); - } - } - - this.print(); - return polR; - } - - fastDivByVanishing(data) { - const Fr = this.Fr; - - for (let i = 0; i < data.length; i++) { - - let m = data[i][0]; - let beta = data[i][1]; - - if (this.degree() < m) { - throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); - } - - let nThreads = 5; - let nElements = this.length() - m; - let nElementsBucket = Math.floor(nElements / nThreads / m); - let nElementsChunk = nElementsBucket * m; - let nElementsLast = nElements - nThreads * nElementsChunk; - - //In C++ implementation this buffer will be allocated only once outside the loop - let polTmp = new Polynomial(this.length() > 2 << 14 ? - new BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8), this.curve, this.logger); - - let ptr = this.coef; - this.coef = polTmp.coef; - polTmp.coef = ptr; - - // STEP 1: Setejar els m valors del següent bucket al chunk actual, PARALEL·LITZAR - for (let k = 0; k < nThreads; k++) { - let idx0 = (k + 1) * nElementsChunk + nElementsLast; - for (let i = 0; i < m; i++) { - this.setCoef(idx0 + i - m, polTmp.getCoef(idx0 + i)); - } - - for (let i = 0; i < nElementsChunk - m; i++) { - let offset = idx0 - i - 1; - let val = Fr.add(polTmp.getCoef(offset), Fr.mul(beta, this.getCoef(offset))); - this.setCoef(offset - m, val); - } - } - - //STEP 2: Setejar els valors del elements last NO PARAL·LELITZAR - let idx0 = nElementsLast; - let pending = nElementsLast; - for (let i = 0; i < m && pending; i++) { - this.setCoef(idx0 - i - 1, polTmp.getCoef(idx0 + m - i - 1)); - pending--; - } - - for (let i = 0; i < pending; i++) { - let offset = idx0 - i - 1; - let val = Fr.add(polTmp.getCoef(offset), Fr.mul(beta, this.getCoef(offset))); - this.setCoef(offset - m, val); - } - - //Step 3: calcular acumulats NO PARALEL·LITZAR - - let acc = []; - let betaPow = Fr.one; - for (let i = 0; i < nElementsBucket; i++) { - betaPow = Fr.mul(betaPow, beta); - } - let currentBeta = Fr.one; - - for (let k = nThreads; k > 0; k--) { - let idThread = k - 1; - let idx0 = idThread * nElementsChunk + nElementsLast; - acc[idThread] = []; - - for (let i = 0; i < m; i++) { - acc[idThread][i] = this.getCoef(idx0 + i); - - if (k !== nThreads) { - acc[idThread][i] = Fr.add(acc[idThread][i], Fr.mul(betaPow, acc[idThread + 1][i])); - } - } - currentBeta = Fr.mul(currentBeta, betaPow); - } - - //STEP 4 recalcular PARALEL·LITZAR - for (let k = 0; k < nThreads; k++) { - - let idx0 = k * nElementsChunk + nElementsLast; - let currentBeta = beta; //Quan hopassem a C++ i ho paralelitzem aquesta variable ha de ser privada - let currentM = m - 1; - - let limit = k === 0 ? nElementsLast : nElementsChunk; - for (let i = 0; i < limit; i++) { - let offset = idx0 - i - 1; - let val = Fr.add(this.getCoef(offset), Fr.mul(currentBeta, acc[k][currentM])); - - this.setCoef(offset, val); - - // To avoid modular operations in each loop... - if (currentM === 0) { - currentM = m - 1; - currentBeta = Fr.mul(currentBeta, beta); - } else { - currentM--; - } - } - } - } - } - - - // Divide polynomial by X - value - divByXSubValue(value) { - const coefs = this.length() > 2 << 14 ? - new BigBuffer(this.length() * this.Fr.n8) : new Uint8Array(this.length() * this.Fr.n8); - - coefs.set(this.Fr.zero, (this.length() - 1) * this.Fr.n8); - coefs.set(this.coef.slice((this.length() - 1) * this.Fr.n8, this.length() * this.Fr.n8), (this.length() - 2) * this.Fr.n8); - for (let i = this.length() - 3; i >= 0; i--) { - let i_n8 = i * this.Fr.n8; - coefs.set( - this.Fr.add( - this.coef.slice(i_n8 + this.Fr.n8, i_n8 + 2 * this.Fr.n8), - this.Fr.mul(value, coefs.slice(i_n8 + this.Fr.n8, i_n8 + 2 * this.Fr.n8)) - ), - i * this.Fr.n8 - ); - } - if (!this.Fr.eq( - this.coef.slice(0, this.Fr.n8), - this.Fr.mul(this.Fr.neg(value), coefs.slice(0, this.Fr.n8)) - )) { - throw new Error("Polynomial does not divide"); - } - - this.coef = coefs; - } - - divZh(domainSize, extensions = 4) { - for (let i = 0; i < domainSize; i++) { - const i_n8 = i * this.Fr.n8; - this.coef.set(this.Fr.neg(this.coef.slice(i_n8, i_n8 + this.Fr.n8)), i_n8); - } - - const upperBound = this.coef.byteLength / this.Fr.n8; - for (let i = domainSize; i < upperBound; i++) { - const i_n8 = i * this.Fr.n8; - - const a = this.Fr.sub( - this.coef.slice((i - domainSize) * this.Fr.n8, (i - domainSize) * this.Fr.n8 + this.Fr.n8), - this.coef.slice(i_n8, i_n8 + this.Fr.n8) - ); - this.coef.set(a, i_n8); - if (i > (domainSize * (extensions-1) - extensions)) { - if (!this.Fr.isZero(a)) { - throw new Error("Polynomial is not divisible"); - } - } - } - - return this; - } - - divByZerofier(n, beta) { - let Fr = this.Fr; - const invBeta = Fr.inv(beta); - const invBetaNeg = Fr.neg(invBeta); - - let isOne = Fr.eq(Fr.one, invBetaNeg); - let isNegOne = Fr.eq(Fr.negone, invBetaNeg); - - if (!isOne) { - for (let i = 0; i < n; i++) { - const i_n8 = i * this.Fr.n8; - let element; - - // If invBetaNeg === -1 we'll save a multiplication changing it by a neg function call - if (isNegOne) { - element = Fr.neg(this.coef.slice(i_n8, i_n8 + this.Fr.n8)); - } else { - element = Fr.mul(invBetaNeg, this.coef.slice(i_n8, i_n8 + this.Fr.n8)); - } - - this.coef.set(element, i_n8); - } - } - - isOne = Fr.eq(Fr.one, invBeta); - isNegOne = Fr.eq(Fr.negone, invBeta); - - for (let i = n; i < this.length(); i++) { - const i_n8 = i * this.Fr.n8; - const i_prev_n8 = (i - n) * this.Fr.n8; - - let element = this.Fr.sub( - this.coef.slice(i_prev_n8, i_prev_n8 + this.Fr.n8), - this.coef.slice(i_n8, i_n8 + this.Fr.n8) - ); - - // If invBeta === 1 we'll not do anything - if(!isOne) { - // If invBeta === -1 we'll save a multiplication changing it by a neg function call - if(isNegOne) { - element = Fr.neg(element); - } else { - element = Fr.mul(invBeta, element); - } - } - - this.coef.set(element, i_n8); - - // Check if polynomial is divisible by checking if n high coefficients are zero - if (i > this.length() - n - 1) { - if (!this.Fr.isZero(element)) { - throw new Error("Polynomial is not divisible"); - } - } - } - - return this; - } - -// function divideByVanishing(f, n, p) { -// // polynomial division f(X) / (X^n - 1) with remainder -// // very cheap, 0 multiplications -// // strategy: -// // start with q(X) = 0, r(X) = f(X) -// // then start changing q, r while preserving the identity: -// // f(X) = q(X) * (X^n - 1) + r(X) -// // in every step, move highest-degree term of r into the product -// // => r eventually has degree < n and we're done -// let q = Array(f.length).fill(0n); -// let r = [...f]; -// for (let i = f.length - 1; i >= n; i--) { -// let leadingCoeff = r[i]; -// if (leadingCoeff === 0n) continue; -// r[i] = 0n; -// r[i - n] = mod(r[i - n] + leadingCoeff, p); -// q[i - n] = mod(q[i - n] + leadingCoeff, p); -// } -// return [q, r]; -// } - - byX() { - const coefs = (this.length() + 1) > 2 << 14 ? - new BigBuffer(this.coef.byteLength + this.Fr.n8) : new Uint8Array(this.coef.byteLength + this.Fr.n8); - coefs.set(this.Fr.zero, 0); - coefs.set(this.coef, this.Fr.n8); - - this.coef = coefs; - } - -// Compute a new polynomial f(x^n) from f(x) -// f(x) = a_0 + a_1·x + a_2·x^2 + ... + a_j·x^j -// f(x^n) = a_0 + a_1·x^n + a_2·x^2n + ... + a_j·x^jn - static - async expX(polynomial, n, truncate = false) { - const Fr = polynomial.Fr; - - if (n < 1) { - // n == 0 not allowed because it has no sense, but if it's necessary we have to return - // a zero degree polynomial with a constant coefficient equals to the sum of all the original coefficients - throw new Error("Compute a new polynomial to a zero or negative number is not allowed"); - } else if (1 === n) { - return await Polynomial.fromEvaluations(polynomial.coef, curve, polynomial.logger); - } - - // length is the length of non-constant coefficients - // if truncate === true, the highest zero coefficients (if exist) will be removed - const length = truncate ? polynomial.degree() : (polynomial.length() - 1); - const bufferDst = (length * n + 1) > 2 << 14 ? - new BigBuffer((length * n + 1) * Fr.n8) : new Uint8Array((length * n + 1) * Fr.n8); - - // Copy constant coefficient as is because is not related to x - bufferDst.set(polynomial.getCoef(0), 0); - - for (let i = 1; i <= length; i++) { - const i_sFr = i * Fr.n8; - - const coef = polynomial.getCoef(i); - bufferDst.set(coef, i_sFr * n); - } - - return new Polynomial(bufferDst, polynomial.curve, polynomial.logger); - } - - split(numPols, degPols, blindingFactors) { - if (numPols < 1) { - throw new Error(`Polynomials can't be split in ${numPols} parts`); - } else if (1 === numPols) { - return [this]; - } - - //blinding factors can be void or must have a length of numPols - 1 - if (0 !== blindingFactors.length && blindingFactors.length < numPols - 1) { - throw new Error(`Blinding factors length must be ${numPols - 1}`); - } - - const chunkByteLength = (degPols + 1) * this.Fr.n8; - let res = []; - - // Check polynomial can be split in numChunks parts of chunkSize bytes... - const numRealPols = Math.ceil((this.degree() + 1) * this.Fr.n8 / chunkByteLength); - if (numRealPols < numPols) { - //throw new Error(`Polynomial is short to be split in ${numPols} parts of ${degPols} coefficients each.`); - for (let i = numRealPols; i < numPols; i++) { - res[i] = new Polynomial(new Uint8Array(this.Fr.n8), this.curve, this.logger); - } - } - - numPols = Math.min(numPols, numRealPols); - for (let i = 0; i < numPols; i++) { - const isLast = (numPols - 1) === i; - const byteLength = isLast ? this.coef.byteLength - ((numPols - 1) * chunkByteLength) : chunkByteLength + this.Fr.n8; - - let buff = (byteLength / this.Fr.n8) > 2 << 14 ? new BigBuffer(byteLength) : new Uint8Array(byteLength); - res[i] = new Polynomial(buff, this.curve, this.logger); - - const fr = i * chunkByteLength; - const to = isLast ? this.coef.byteLength : (i + 1) * chunkByteLength; - res[i].coef.set(this.coef.slice(fr, to), 0); - - // Add a blinding factor as higher degree - if (!isLast) { - res[i].coef.set(blindingFactors[i], chunkByteLength); - } - - // Sub blinding factor to the lowest degree - if (0 !== i) { - const lowestDegree = this.Fr.sub(res[i].coef.slice(0, this.Fr.n8), blindingFactors[i - 1]); - res[i].coef.set(lowestDegree, 0); - } - - if (isLast) { - res[i].truncate(); - } - } - - return res; - - // // compute t_low(X) - // let polTLow = new BigBuffer((chunkSize + 1) * n8r); - // polTLow.set(t.slice(0, zkey.domainSize * n8r), 0); - // // Add blinding scalar b_10 as a new coefficient n - // polTLow.set(ch.b[10], zkey.domainSize * n8r); - // - // // compute t_mid(X) - // let polTMid = new BigBuffer((zkey.domainSize + 1) * n8r); - // polTMid.set(t.slice(zkey.domainSize * n8r, zkey.domainSize * 2 * n8r), 0); - // // Subtract blinding scalar b_10 to the lowest coefficient of t_mid - // const lowestMid = Fr.sub(polTMid.slice(0, n8r), ch.b[10]); - // polTMid.set(lowestMid, 0); - // // Add blinding scalar b_11 as a new coefficient n - // polTMid.set(ch.b[11], zkey.domainSize * n8r); - // - // // compute t_high(X) - // let polTHigh = new BigBuffer((zkey.domainSize + 6) * n8r); - // polTHigh.set(t.slice(zkey.domainSize * 2 * n8r, (zkey.domainSize * 3 + 6) * n8r), 0); - // //Subtract blinding scalar b_11 to the lowest coefficient of t_high - // const lowestHigh = Fr.sub(polTHigh.slice(0, n8r), ch.b[11]); - // polTHigh.set(lowestHigh, 0); - // - // proof.T1 = await expTau(polTLow, "multiexp T1"); - // proof.T2 = await expTau(polTMid, "multiexp T2"); - // proof.T3 = await expTau(polTHigh, "multiexp T3"); - } - -// split2(degPols, blindingFactors) { -// let currentDegree = this.degree(); -// const numFilledPols = Math.ceil((currentDegree + 1) / (degPols + 1)); -// -// //blinding factors can be void or must have a length of numPols - 1 -// if (0 !== blindingFactors.length && blindingFactors.length < numFilledPols - 1) { -// throw new Error(`Blinding factors length must be ${numFilledPols - 1}`); -// } -// -// const chunkByteLength = (degPols + 1) * this.Fr.n8; -// -// // Check polynomial can be split in numChunks parts of chunkSize bytes... -// if (this.coef.byteLength / chunkByteLength <= numFilledPols - 1) { -// throw new Error(`Polynomial is short to be split in ${numFilledPols} parts of ${degPols} coefficients each.`); -// } -// -// let res = []; -// for (let i = 0; i < numFilledPols; i++) { -// const isLast = (numFilledPols - 1) === i; -// const byteLength = isLast ? (currentDegree + 1) * this.Fr.n8 - ((numFilledPols - 1) * chunkByteLength) : chunkByteLength + this.Fr.n8; -// -// res[i] = new Polynomial(new BigBuffer(byteLength), this.Fr, this.logger); -// const fr = i * chunkByteLength; -// const to = isLast ? (currentDegree + 1) * this.Fr.n8 : (i + 1) * chunkByteLength; -// res[i].coef.set(this.coef.slice(fr, to), 0); -// -// // Add a blinding factor as higher degree -// if (!isLast) { -// res[i].coef.set(blindingFactors[i], chunkByteLength); -// } -// -// // Sub blinding factor to the lowest degree -// if (0 !== i) { -// const lowestDegree = this.Fr.sub(res[i].coef.slice(0, this.Fr.n8), blindingFactors[i - 1]); -// res[i].coef.set(lowestDegree, 0); -// } -// } -// -// return res; -// } - -// merge(pols, overlap = true) { -// let length = 0; -// for (let i = 0; i < pols.length; i++) { -// length += pols[i].length(); -// } -// -// if (overlap) { -// length -= pols.length - 1; -// } -// -// let res = new Polynomial(new BigBuffer(length * this.Fr.n8)); -// for (let i = 0; i < pols.length; i++) { -// const byteLength = pols[i].coef.byteLength; -// if (0 === i) { -// res.coef.set(pols[i].coef, 0); -// } else { -// -// } -// } -// -// return res; -// } - - truncate() { - const deg = this.degree(); - if (deg + 1 < this.coef.byteLength / this.Fr.n8) { - const newCoefs = (deg + 1) > 2 << 14 ? - new BigBuffer((deg + 1) * this.Fr.n8) : new Uint8Array((deg + 1) * this.Fr.n8); - - newCoefs.set(this.coef.slice(0, (deg + 1) * this.Fr.n8), 0); - this.coef = newCoefs; - } - } - - static lagrangePolynomialInterpolation(xArr, yArr, curve) { - const Fr = curve.Fr; - let polynomial = computeLagrangePolynomial(0); - for (let i = 1; i < xArr.length; i++) { - polynomial.add(computeLagrangePolynomial(i)); - } - - return polynomial; - - function computeLagrangePolynomial(i) { - let polynomial; - - for (let j = 0; j < xArr.length; j++) { - if (j === i) continue; - - if (polynomial === undefined) { - let buff = (xArr.length) > 2 << 14 ? - new BigBuffer((xArr.length) * Fr.n8) : new Uint8Array((xArr.length) * Fr.n8); - polynomial = new Polynomial(buff, curve); - polynomial.setCoef(0, Fr.neg(xArr[j])); - polynomial.setCoef(1, Fr.one); - } else { - polynomial.byXSubValue(xArr[j]); - } - } - - let denominator = polynomial.evaluate(xArr[i]); - denominator = Fr.inv(denominator); - const mulFactor = Fr.mul(yArr[i], denominator); - - polynomial.mulScalar(mulFactor); - - return polynomial; - } - } - - static zerofierPolynomial(xArr, curve) { - const Fr = curve.Fr; - let buff = (xArr.length + 1) > 2 << 14 ? - new BigBuffer((xArr.length + 1) * Fr.n8) : new Uint8Array((xArr.length + 1) * Fr.n8); - let polynomial = new Polynomial(buff, curve); - - // Build a zerofier polynomial with the following form: - // zerofier(X) = (X-xArr[0])(X-xArr[1])...(X-xArr[n]) - polynomial.setCoef(0, Fr.neg(xArr[0])); - polynomial.setCoef(1, Fr.one); - - for (let i = 1; i < xArr.length; i++) { - polynomial.byXSubValue(xArr[i]); - } - - return polynomial; - } - - print() { - const Fr = this.Fr; - let res = ""; - for (let i = this.degree(); i >= 0; i--) { - const coef = this.getCoef(i); - if (!Fr.eq(Fr.zero, coef)) { - if (Fr.isNegative(coef)) { - res += " - "; - } else if (i !== this.degree()) { - res += " + "; - } - res += Fr.toString(coef); - if (i > 0) { - res += i > 1 ? "x^" + i : "x"; - } - } - } - console.log(res); - } - - async multiExponentiation(PTau, name) { - const n = this.coef.byteLength / this.Fr.n8; - const PTauN = PTau.slice(0, n * this.G1.F.n8 * 2); - const bm = await this.Fr.batchFromMontgomery(this.coef); - let res = await this.G1.multiExpAffine(PTauN, bm, this.logger, name); - res = this.G1.toAffine(res); - return res; - } -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -class Evaluations { - constructor(evaluations, curve, logger) { - this.eval = evaluations; - this.curve = curve; - this.Fr = curve.Fr; - this.logger = logger; - } - - static async fromPolynomial(polynomial, extension, curve, logger) { - const coefficientsN = new BigBuffer(polynomial.length() * extension * curve.Fr.n8); - coefficientsN.set(polynomial.coef, 0); - - const evaluations = await curve.Fr.fft(coefficientsN); - - return new Evaluations(evaluations, curve, logger); - } - - getEvaluation(index) { - const i_n8 = index * this.Fr.n8; - - if (i_n8 + this.Fr.n8 > this.eval.byteLength) { - throw new Error("Evaluations.getEvaluation() out of bounds"); - } - - return this.eval.slice(i_n8, i_n8 + this.Fr.n8); - } - - length() { - let length = this.eval.byteLength / this.Fr.n8; - if (length !== Math.floor(this.eval.byteLength / this.Fr.n8)) { - throw new Error("Polynomial evaluations buffer has incorrect size"); - } - if (0 === length) { - this.logger.warn("Polynomial has length zero"); - } - return length; - } -} - -/* - Copyright 2021 0kims association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ -const {stringifyBigInts: stringifyBigInts$1} = utils; - -async function plonk16Prove(zkeyFileName, witnessFileName, logger, options) { - const {fd: fdWtns, sections: sectionsWtns} = await readBinFile$1(witnessFileName, "wtns", 2); - - // Read witness file - if (logger) logger.debug("> Reading witness file"); - const wtns = await readHeader(fdWtns, sectionsWtns); - - // Read zkey file - if (logger) logger.debug("> Reading zkey file"); - const {fd: fdZKey, sections: zkeySections} = await readBinFile$1(zkeyFileName, "zkey", 2); - - const zkey = await readHeader$1(fdZKey, zkeySections, undefined, options); - if (zkey.protocol != "plonk") { - throw new Error("zkey file is not plonk"); - } - - if (!Scalar.eq(zkey.r, wtns.q)) { - throw new Error("Curve of the witness does not match the curve of the proving key"); - } - - if (wtns.nWitness != zkey.nVars -zkey.nAdditions) { - throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}, ${zkey.nAdditions}`); - } - - const curve = zkey.curve; - - const Fr = curve.Fr; - const n8r = curve.Fr.n8; - const sDomain = zkey.domainSize * n8r; - - if (logger) { - logger.debug("----------------------------"); - logger.debug(" PLONK PROVE SETTINGS"); - logger.debug(` Curve: ${curve.name}`); - logger.debug(` Circuit power: ${zkey.power}`); - logger.debug(` Domain size: ${zkey.domainSize}`); - logger.debug(` Vars: ${zkey.nVars}`); - logger.debug(` Public vars: ${zkey.nPublic}`); - logger.debug(` Constraints: ${zkey.nConstraints}`); - logger.debug(` Additions: ${zkey.nAdditions}`); - logger.debug("----------------------------"); - } - - //Read witness data - if (logger) logger.debug("> Reading witness file data"); - const buffWitness = await readSection$1(fdWtns, sectionsWtns, 2); - - // First element in plonk is not used and can be any value. (But always the same). - // We set it to zero to go faster in the exponentiations. - buffWitness.set(Fr.zero, 0); - const buffInternalWitness = new BigBuffer(n8r*zkey.nAdditions); - - let buffers = {}; - let polynomials = {}; - let evaluations = {}; - - let challenges = {}; - let proof = new Proof(curve, logger); - const transcript = new Keccak256Transcript(curve); - - if (logger) logger.debug(`> Reading Section ${ZKEY_PL_ADDITIONS_SECTION}. Additions`); - await calculateAdditions(); - - if (logger) logger.debug(`> Reading Section ${ZKEY_PL_SIGMA_SECTION}. Sigma1, Sigma2 & Sigma 3`); - if (logger) logger.debug("··· Reading Sigma polynomials "); - polynomials.Sigma1 = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.Sigma2 = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.Sigma3 = new Polynomial(new BigBuffer(sDomain), curve, logger); - - await fdZKey.readToBuffer(polynomials.Sigma1.coef, 0, sDomain, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.Sigma2.coef, 0, sDomain, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p + 5 * sDomain); - await fdZKey.readToBuffer(polynomials.Sigma3.coef, 0, sDomain, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p + 10 * sDomain); - - if (logger) logger.debug("··· Reading Sigma evaluations"); - evaluations.Sigma1 = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.Sigma2 = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.Sigma3 = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - - await fdZKey.readToBuffer(evaluations.Sigma1.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.Sigma2.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p + 6 * sDomain); - await fdZKey.readToBuffer(evaluations.Sigma3.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p + 11 * sDomain); - - if (logger) logger.debug(`> Reading Section ${ZKEY_PL_PTAU_SECTION}. Powers of Tau`); - const PTau = await readSection$1(fdZKey, zkeySections, ZKEY_PL_PTAU_SECTION); - - let publicSignals = []; - - for (let i=1; i<= zkey.nPublic; i++) { - const pub = buffWitness.slice(i*Fr.n8, i*Fr.n8+Fr.n8); - publicSignals.push(Scalar.fromRprLE(pub)); - } - - if (logger) logger.debug(""); - if (logger) logger.debug("> ROUND 1"); - await round1(); - - if (logger) logger.debug("> ROUND 2"); - await round2(); - - if (logger) logger.debug("> ROUND 3"); - await round3(); - - if (logger) logger.debug("> ROUND 4"); - await round4(); - - if (logger) logger.debug("> ROUND 5"); - await round5(); - - /////////////////////// - // Final adjustments // - /////////////////////// - - await fdZKey.close(); - await fdWtns.close(); - - // Prepare proof - let _proof = proof.toObjectProof(false); - _proof.protocol = "plonk"; - _proof.curve = curve.name; - - if (logger) logger.debug("PLONK PROVER FINISHED"); - - return { - proof: stringifyBigInts$1(_proof), - publicSignals: stringifyBigInts$1(publicSignals) - }; - - async function calculateAdditions() { - if (logger) logger.debug("··· Computing additions"); - const additionsBuff = await readSection$1(fdZKey, zkeySections, ZKEY_PL_ADDITIONS_SECTION); - - // sizes: wireId_x = 4 bytes (32 bits), factor_x = field size bits - // Addition form: wireId_a wireId_b factor_a factor_b (size is 4 + 4 + sFr + sFr) - const sSum = 8 + n8r * 2; - - for (let i = 0; i < zkey.nAdditions; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.debug(` addition ${i}/${zkey.nAdditions}`); - - // Read addition values - let offset = i * sSum; - const signalId1 = readUInt32(additionsBuff, offset); - offset += 4; - const signalId2 = readUInt32(additionsBuff, offset); - offset += 4; - const factor1 = additionsBuff.slice(offset, offset + n8r); - offset += n8r; - const factor2 = additionsBuff.slice(offset, offset + n8r); - - // Get witness value - const witness1 = getWitness(signalId1); - const witness2 = getWitness(signalId2); - - //Calculate final result - const result = Fr.add(Fr.mul(factor1, witness1), Fr.mul(factor2, witness2)); - - buffInternalWitness.set(result, n8r * i); - } - } - - function readUInt32(b, o) { - const buff = b.slice(o, o+4); - const buffV = new DataView(buff.buffer, buff.byteOffset, buff.byteLength); - return buffV.getUint32(0, true); - } - - function getWitness(idx) { - if (idx < zkey.nVars-zkey.nAdditions) { - return buffWitness.slice(idx*n8r, idx*n8r+n8r); - } else if (idx < zkey.nVars) { - return buffInternalWitness.slice((idx - (zkey.nVars-zkey.nAdditions))*n8r, (idx-(zkey.nVars-zkey.nAdditions))*n8r + n8r); - } else { - return curve.Fr.zero; - } - } - - async function round1() { - // STEP 1.1 - Generate random blinding scalars (b1, ..., b11) ∈ F - challenges.b = []; - for (let i=1; i<=11; i++) { - challenges.b[i] = curve.Fr.random(); - } - - // STEP 1.2 - Compute wire polynomials a(X), b(X) and c(X) - if (logger) logger.debug("> Computing A, B, C wire polynomials"); - await computeWirePolynomials(); - - // STEP 1.3 - Compute [a]_1, [b]_1, [c]_1 - if (logger) logger.debug("> Computing A, B, C MSM"); - let commitA = await polynomials.A.multiExponentiation(PTau, "A"); - let commitB = await polynomials.B.multiExponentiation(PTau, "B"); - let commitC = await polynomials.C.multiExponentiation(PTau, "C"); - - // First output of the prover is ([A]_1, [B]_1, [C]_1) - proof.addPolynomial("A", commitA); - proof.addPolynomial("B", commitB); - proof.addPolynomial("C", commitC); - - return 0; - } - - async function computeWirePolynomials() { - if (logger) logger.debug("··· Reading data from zkey file"); - - // Build A, B and C evaluations buffer from zkey and witness files - buffers.A = new BigBuffer(sDomain); - buffers.B = new BigBuffer(sDomain); - buffers.C = new BigBuffer(sDomain); - - // Read zkey file to the buffers - const aMapBuff = await readSection$1(fdZKey, zkeySections, ZKEY_PL_A_MAP_SECTION); - const bMapBuff = await readSection$1(fdZKey, zkeySections, ZKEY_PL_B_MAP_SECTION); - const cMapBuff = await readSection$1(fdZKey, zkeySections, ZKEY_PL_C_MAP_SECTION); - - // Compute all witness from signal ids and set them to A,B & C buffers - for (let i = 0; i < zkey.nConstraints; i++) { - const i_sFr = i * n8r; - const offset = i * 4; - - // Compute A value from a signal id - const signalIdA = readUInt32(aMapBuff, offset); - buffers.A.set(getWitness(signalIdA), i_sFr); - - // Compute B value from a signal id - const signalIdB = readUInt32(bMapBuff, offset); - buffers.B.set(getWitness(signalIdB), i_sFr); - - // Compute C value from a signal id - const signalIdC = readUInt32(cMapBuff, offset); - buffers.C.set(getWitness(signalIdC), i_sFr); - } - - buffers.A = await Fr.batchToMontgomery(buffers.A); - buffers.B = await Fr.batchToMontgomery(buffers.B); - buffers.C = await Fr.batchToMontgomery(buffers.C); - - // Compute the coefficients of the wire polynomials a(X), b(X) and c(X) from A,B & C buffers - if (logger) logger.debug("··· Computing A ifft"); - polynomials.A = await Polynomial.fromEvaluations(buffers.A, curve, logger); - if (logger) logger.debug("··· Computing B ifft"); - polynomials.B = await Polynomial.fromEvaluations(buffers.B, curve, logger); - if (logger) logger.debug("··· Computing C ifft"); - polynomials.C = await Polynomial.fromEvaluations(buffers.C, curve, logger); - - // Compute extended evaluations of a(X), b(X) and c(X) polynomials - if (logger) logger.debug("··· Computing A fft"); - evaluations.A = await Evaluations.fromPolynomial(polynomials.A, 4, curve, logger); - if (logger) logger.debug("··· Computing B fft"); - evaluations.B = await Evaluations.fromPolynomial(polynomials.B, 4, curve, logger); - if (logger) logger.debug("··· Computing C fft"); - evaluations.C = await Evaluations.fromPolynomial(polynomials.C, 4, curve, logger); - - // Blind a(X), b(X) and c(X) polynomials coefficients with blinding scalars b - polynomials.A.blindCoefficients([challenges.b[2], challenges.b[1]]); - polynomials.B.blindCoefficients([challenges.b[4], challenges.b[3]]); - polynomials.C.blindCoefficients([challenges.b[6], challenges.b[5]]); - - // Check degrees - if (polynomials.A.degree() >= zkey.domainSize + 2) { - throw new Error("A Polynomial is not well calculated"); - } - if (polynomials.B.degree() >= zkey.domainSize + 2) { - throw new Error("B Polynomial is not well calculated"); - } - if (polynomials.C.degree() >= zkey.domainSize + 2) { - throw new Error("C Polynomial is not well calculated"); - } - } - - async function round2() { - // STEP 2.1 - Compute permutation challenge beta and gamma ∈ F - // Compute permutation challenge beta - if (logger) logger.debug("> Computing challenges beta and gamma"); - transcript.reset(); - - transcript.addPolCommitment(zkey.Qm); - transcript.addPolCommitment(zkey.Ql); - transcript.addPolCommitment(zkey.Qr); - transcript.addPolCommitment(zkey.Qo); - transcript.addPolCommitment(zkey.Qc); - transcript.addPolCommitment(zkey.S1); - transcript.addPolCommitment(zkey.S2); - transcript.addPolCommitment(zkey.S3); - - // Add A to the transcript - for (let i = 0; i < zkey.nPublic; i++) { - transcript.addScalar(buffers.A.slice(i * n8r, i * n8r + n8r)); - } - - // Add A, B, C to the transcript - transcript.addPolCommitment(proof.getPolynomial("A")); - transcript.addPolCommitment(proof.getPolynomial("B")); - transcript.addPolCommitment(proof.getPolynomial("C")); - - challenges.beta = transcript.getChallenge(); - if (logger) logger.debug("··· challenges.beta: " + Fr.toString(challenges.beta, 16)); - - // Compute permutation challenge gamma - transcript.reset(); - transcript.addScalar(challenges.beta); - challenges.gamma = transcript.getChallenge(); - if (logger) logger.debug("··· challenges.gamma: " + Fr.toString(challenges.gamma, 16)); - - // STEP 2.2 - Compute permutation polynomial z(X) - if (logger) logger.debug("> Computing Z polynomial"); - await computeZ(); - - // STEP 2.3 - Compute permutation [z]_1 - if (logger) logger.debug("> Computing Z MSM"); - let commitZ = await polynomials.Z.multiExponentiation(PTau, "Z"); - - // Second output of the prover is ([Z]_1) - proof.addPolynomial("Z", commitZ); - } - - async function computeZ() { - if (logger) logger.debug("··· Computing Z evaluations"); - - let numArr = new BigBuffer(sDomain); - let denArr = new BigBuffer(sDomain); - - // Set the first values to 1 - numArr.set(Fr.one, 0); - denArr.set(Fr.one, 0); - - // Set initial omega - let w = Fr.one; - for (let i = 0; i < zkey.domainSize; i++) { - const i_n8r = i * n8r; - - const a = buffers.A.slice(i_n8r, i_n8r + n8r); - const b = buffers.B.slice(i_n8r, i_n8r + n8r); - const c = buffers.C.slice(i_n8r, i_n8r + n8r); - - // Z(X) := numArr / denArr - // numArr := (a + beta·ω + gamma)(b + beta·ω·k1 + gamma)(c + beta·ω·k2 + gamma) - const betaw = Fr.mul(challenges.beta, w); - - let n1 = Fr.add(a, betaw); - n1 = Fr.add(n1, challenges.gamma); - - let n2 = Fr.add(b, Fr.mul(zkey.k1, betaw)); - n2 = Fr.add(n2, challenges.gamma); - - let n3 = Fr.add(c, Fr.mul(zkey.k2, betaw)); - n3 = Fr.add(n3, challenges.gamma); - - let num = Fr.mul(n1, Fr.mul(n2, n3)); - - // denArr := (a + beta·sigma1 + gamma)(b + beta·sigma2 + gamma)(c + beta·sigma3 + gamma) - let d1 = Fr.add(a, Fr.mul(evaluations.Sigma1.getEvaluation(i * 4), challenges.beta)); - d1 = Fr.add(d1, challenges.gamma); - - let d2 = Fr.add(b, Fr.mul(evaluations.Sigma2.getEvaluation(i * 4), challenges.beta)); - d2 = Fr.add(d2, challenges.gamma); - - let d3 = Fr.add(c, Fr.mul(evaluations.Sigma3.getEvaluation(i * 4), challenges.beta)); - d3 = Fr.add(d3, challenges.gamma); - - let den = Fr.mul(d1, Fr.mul(d2, d3)); - - // Multiply current num value with the previous one saved in numArr - num = Fr.mul(numArr.slice(i_n8r, i_n8r + n8r), num); - numArr.set(num, ((i + 1) % zkey.domainSize) * n8r); - - // Multiply current den value with the previous one saved in denArr - den = Fr.mul(denArr.slice(i_n8r, i_n8r + n8r), den); - denArr.set(den, ((i + 1) % zkey.domainSize) * n8r); - - w = Fr.mul(w, Fr.w[zkey.power]); - } - - // Compute the inverse of denArr to compute in the next command the - // division numArr/denArr by multiplying num · 1/denArr - denArr = await Fr.batchInverse(denArr); - - // TODO: Do it in assembly and in parallel - // Multiply numArr · denArr where denArr was inverted in the previous command - for (let i = 0; i < zkey.domainSize; i++) { - const i_sFr = i * n8r; - - const z = Fr.mul(numArr.slice(i_sFr, i_sFr + n8r), denArr.slice(i_sFr, i_sFr + n8r)); - numArr.set(z, i_sFr); - } - - // From now on the values saved on numArr will be Z(X) buffer - buffers.Z = numArr; - - if (!Fr.eq(numArr.slice(0, n8r), Fr.one)) { - throw new Error("Copy constraints does not match"); - } - - // Compute polynomial coefficients z(X) from buffers.Z - if (logger) logger.debug("··· Computing Z ifft"); - polynomials.Z = await Polynomial.fromEvaluations(buffers.Z, curve, logger); - - // Compute extended evaluations of z(X) polynomial - if (logger) logger.debug("··· Computing Z fft"); - evaluations.Z = await Evaluations.fromPolynomial(polynomials.Z, 4, curve, logger); - - // Blind z(X) polynomial coefficients with blinding scalars b - polynomials.Z.blindCoefficients([challenges.b[9], challenges.b[8], challenges.b[7]]); - - // Check degree - if (polynomials.Z.degree() >= zkey.domainSize + 3) { - throw new Error("Z Polynomial is not well calculated"); - } - - delete buffers.Z; - } - - async function round3() { - if (logger) logger.debug("> Computing challenge alpha"); - - // STEP 3.1 - Compute evaluation challenge alpha ∈ F - transcript.reset(); - transcript.addScalar(challenges.beta); - transcript.addScalar(challenges.gamma); - transcript.addPolCommitment(proof.getPolynomial("Z")); - - challenges.alpha = transcript.getChallenge(); - challenges.alpha2 = Fr.square(challenges.alpha); - if (logger) logger.debug("··· challenges.alpha: " + Fr.toString(challenges.alpha, 16)); - - // Compute quotient polynomial T(X) - if (logger) logger.debug("> Computing T polynomial"); - await computeT(); - - // Compute [T1]_1, [T2]_1, [T3]_1 - if (logger) logger.debug("> Computing T MSM"); - let commitT1 = await polynomials.T1.multiExponentiation(PTau, "T1"); - let commitT2 = await polynomials.T2.multiExponentiation(PTau, "T2"); - let commitT3 = await polynomials.T3.multiExponentiation(PTau, "T3"); - - // Third output of the prover is ([T1]_1, [T2]_1, [T3]_1) - proof.addPolynomial("T1", commitT1); - proof.addPolynomial("T2", commitT2); - proof.addPolynomial("T3", commitT3); - } - - async function computeT() { - if (logger) - logger.debug(`··· Reading sections ${ZKEY_PL_QL_SECTION}, ${ZKEY_PL_QR_SECTION}` + - `, ${ZKEY_PL_QM_SECTION}, ${ZKEY_PL_QO_SECTION}, ${ZKEY_PL_QC_SECTION}. Q selectors`); - // Reserve memory for Q's evaluations - evaluations.QL = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.QR = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.QM = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.QO = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.QC = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - - // Read Q's evaluations from zkey file - await fdZKey.readToBuffer(evaluations.QL.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_QL_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QR.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_QR_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QM.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_QM_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QO.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_QO_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QC.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_QC_SECTION][0].p + sDomain); - - // Read Lagrange polynomials & evaluations from zkey file - evaluations.Lagrange = new Evaluations(new BigBuffer(sDomain * 4 * zkey.nPublic), curve, logger); - - for (let i = 0; i < zkey.nPublic; i++) { - await fdZKey.readToBuffer(evaluations.Lagrange.eval, i * sDomain * 4, sDomain * 4, zkeySections[ZKEY_PL_LAGRANGE_SECTION][0].p + i * 5 * sDomain + sDomain); - } - - buffers.T = new BigBuffer(sDomain * 4); - buffers.Tz = new BigBuffer(sDomain * 4); - - if (logger) logger.debug("··· Computing T evaluations"); - - let w = Fr.one; - for (let i = 0; i < zkey.domainSize * 4; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) - logger.debug(` T evaluation ${i}/${zkey.domainSize * 4}`); - - const a = evaluations.A.getEvaluation(i); - const b = evaluations.B.getEvaluation(i); - const c = evaluations.C.getEvaluation(i); - const z = evaluations.Z.getEvaluation(i); - const zw = evaluations.Z.getEvaluation((zkey.domainSize * 4 + 4 + i) % (zkey.domainSize * 4)); - - const qm = evaluations.QM.getEvaluation(i); - const ql = evaluations.QL.getEvaluation(i); - const qr = evaluations.QR.getEvaluation(i); - const qo = evaluations.QO.getEvaluation(i); - const qc = evaluations.QC.getEvaluation(i); - const s1 = evaluations.Sigma1.getEvaluation(i); - const s2 = evaluations.Sigma2.getEvaluation(i); - const s3 = evaluations.Sigma3.getEvaluation(i); - - const ap = Fr.add(challenges.b[2], Fr.mul(challenges.b[1], w)); - const bp = Fr.add(challenges.b[4], Fr.mul(challenges.b[3], w)); - const cp = Fr.add(challenges.b[6], Fr.mul(challenges.b[5], w)); - - const w2 = Fr.square(w); - const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], w2), Fr.mul(challenges.b[8], w)), challenges.b[9]); - const wW = Fr.mul(w, Fr.w[zkey.power]); - const wW2 = Fr.square(wW); - const zWp = Fr.add(Fr.add(Fr.mul(challenges.b[7], wW2), Fr.mul(challenges.b[8], wW)), challenges.b[9]); - - let pi = Fr.zero; - for (let j = 0; j < zkey.nPublic; j++) { - const offset = (j * 4 * zkey.domainSize) + i; - - const lPol = evaluations.Lagrange.getEvaluation(offset); - const aVal = buffers.A.slice(j * n8r, (j + 1) * n8r); - - pi = Fr.sub(pi, Fr.mul(lPol, aVal)); - } - - // e1 := a(X)b(X)qM(X) + a(X)qL(X) + b(X)qR(X) + c(X)qO(X) + PI(X) + qC(X) - let [e1, e1z] = MulZ.mul2(a, b, ap, bp, i % 4, Fr); - e1 = Fr.mul(e1, qm); - e1z = Fr.mul(e1z, qm); - - e1 = Fr.add(e1, Fr.mul(a, ql)); - e1z = Fr.add(e1z, Fr.mul(ap, ql)); - - e1 = Fr.add(e1, Fr.mul(b, qr)); - e1z = Fr.add(e1z, Fr.mul(bp, qr)); - - e1 = Fr.add(e1, Fr.mul(c, qo)); - e1z = Fr.add(e1z, Fr.mul(cp, qo)); - - e1 = Fr.add(e1, pi); - e1 = Fr.add(e1, qc); - - // e2 := α[(a(X) + βX + γ)(b(X) + βk1X + γ)(c(X) + βk2X + γ)z(X)] - const betaw = Fr.mul(challenges.beta, w); - let e2a = a; - e2a = Fr.add(e2a, betaw); - e2a = Fr.add(e2a, challenges.gamma); - - let e2b = b; - e2b = Fr.add(e2b, Fr.mul(betaw, zkey.k1)); - e2b = Fr.add(e2b, challenges.gamma); - - let e2c = c; - e2c = Fr.add(e2c, Fr.mul(betaw, zkey.k2)); - e2c = Fr.add(e2c, challenges.gamma); - - let e2d = z; - - let [e2, e2z] = MulZ.mul4(e2a, e2b, e2c, e2d, ap, bp, cp, zp, i % 4, Fr); - e2 = Fr.mul(e2, challenges.alpha); - e2z = Fr.mul(e2z, challenges.alpha); - - // e3 := α[(a(X) + βSσ1(X) + γ)(b(X) + βSσ2(X) + γ)(c(X) + βSσ3(X) + γ)z(Xω)] - let e3a = a; - e3a = Fr.add(e3a, Fr.mul(challenges.beta, s1)); - e3a = Fr.add(e3a, challenges.gamma); - - let e3b = b; - e3b = Fr.add(e3b, Fr.mul(challenges.beta, s2)); - e3b = Fr.add(e3b, challenges.gamma); - - let e3c = c; - e3c = Fr.add(e3c, Fr.mul(challenges.beta, s3)); - e3c = Fr.add(e3c, challenges.gamma); - - let e3d = zw; - let [e3, e3z] = MulZ.mul4(e3a, e3b, e3c, e3d, ap, bp, cp, zWp, i % 4, Fr); - - e3 = Fr.mul(e3, challenges.alpha); - e3z = Fr.mul(e3z, challenges.alpha); - - // e4 := α^2(z(X)−1)L1(X) - let e4 = Fr.sub(z, Fr.one); - e4 = Fr.mul(e4, evaluations.Lagrange.getEvaluation(i)); - e4 = Fr.mul(e4, challenges.alpha2); - - let e4z = Fr.mul(zp, evaluations.Lagrange.getEvaluation(i)); - e4z = Fr.mul(e4z, challenges.alpha2); - - - let t = Fr.add(Fr.sub(Fr.add(e1, e2), e3), e4); - let tz = Fr.add(Fr.sub(Fr.add(e1z, e2z), e3z), e4z); - - buffers.T.set(t, i * n8r); - buffers.Tz.set(tz, i * n8r); - - w = Fr.mul(w, Fr.w[zkey.power + 2]); - } - - // Compute the coefficients of the polynomial T0(X) from buffers.T0 - if (logger) - logger.debug("··· Computing T ifft"); - polynomials.T = await Polynomial.fromEvaluations(buffers.T, curve, logger); - - // Divide the polynomial T0 by Z_H(X) - if (logger) - logger.debug("··· Computing T / ZH"); - polynomials.T.divZh(zkey.domainSize, 4); - - // Compute the coefficients of the polynomial Tz(X) from buffers.Tz - if (logger) - logger.debug("··· Computing Tz ifft"); - polynomials.Tz = await Polynomial.fromEvaluations(buffers.Tz, curve, logger); - - // Add the polynomial T1z to T1 to get the final polynomial T1 - polynomials.T.add(polynomials.Tz); - - // Check degree - if (polynomials.T.degree() >= zkey.domainSize * 3 + 6) { - throw new Error("T Polynomial is not well calculated"); - } - - // t(x) has degree 3n + 5, we are going to split t(x) into three smaller polynomials: - // T1' and T2' with a degree < n and T3' with a degree n+5 - // such that t(x) = T1'(X) + X^n T2'(X) + X^{2n} T3'(X) - // To randomize the parts we use blinding scalars b_10 and b_11 in a way that doesn't change t(X): - // T1(X) = T1'(X) + b_10 X^n - // T2(X) = T2'(X) - b_10 + b_11 X^n - // T3(X) = T3'(X) - b_11 - // such that - // t(X) = T1(X) + X^n T2(X) + X^2n T3(X) - if (logger) logger.debug("··· Computing T1, T2, T3 polynomials"); - polynomials.T1 = new Polynomial(new BigBuffer((zkey.domainSize + 1) * n8r), curve, logger); - polynomials.T2 = new Polynomial(new BigBuffer((zkey.domainSize + 1) * n8r), curve, logger); - polynomials.T3 = new Polynomial(new BigBuffer((zkey.domainSize + 6) * n8r), curve, logger); - - polynomials.T1.coef.set(polynomials.T.coef.slice(0, sDomain), 0); - polynomials.T2.coef.set(polynomials.T.coef.slice(sDomain, sDomain * 2), 0); - polynomials.T3.coef.set(polynomials.T.coef.slice(sDomain * 2, sDomain * 3 + 6 * n8r), 0); - - // Add blinding scalar b_10 as a new coefficient n - polynomials.T1.setCoef(zkey.domainSize, challenges.b[10]); - - // compute t_mid(X) - // Subtract blinding scalar b_10 to the lowest coefficient of t_mid - const lowestMid = Fr.sub(polynomials.T2.getCoef(0), challenges.b[10]); - polynomials.T2.setCoef(0, lowestMid); - polynomials.T2.setCoef(zkey.domainSize, challenges.b[11]); - - // compute t_high(X) - //Subtract blinding scalar b_11 to the lowest coefficient of t_high - const lowestHigh = Fr.sub(polynomials.T3.getCoef(0), challenges.b[11]); - polynomials.T3.setCoef(0, lowestHigh); - } - - async function round4() { - if (logger) logger.debug("> Computing challenge xi"); - - // STEP 4.1 - Compute evaluation challenge xi ∈ F - transcript.reset(); - transcript.addScalar(challenges.alpha); - transcript.addPolCommitment(proof.getPolynomial("T1")); - transcript.addPolCommitment(proof.getPolynomial("T2")); - transcript.addPolCommitment(proof.getPolynomial("T3")); - - challenges.xi = transcript.getChallenge(); - challenges.xiw = Fr.mul(challenges.xi, Fr.w[zkey.power]); - - if (logger) logger.debug("··· challenges.xi: " + Fr.toString(challenges.xi, 16)); - - // Fourth output of the prover is ( a(xi), b(xi), c(xi), s1(xi), s2(xi), z(xiw) ) - proof.addEvaluation("eval_a", polynomials.A.evaluate(challenges.xi)); - proof.addEvaluation("eval_b", polynomials.B.evaluate(challenges.xi)); - proof.addEvaluation("eval_c", polynomials.C.evaluate(challenges.xi)); - proof.addEvaluation("eval_s1", polynomials.Sigma1.evaluate(challenges.xi)); - proof.addEvaluation("eval_s2", polynomials.Sigma2.evaluate(challenges.xi)); - proof.addEvaluation("eval_zw", polynomials.Z.evaluate(challenges.xiw)); - } - - async function round5() { - if (logger) logger.debug("> Computing challenge v"); - - // STEP 5.1 - Compute evaluation challenge v ∈ F - transcript.reset(); - transcript.addScalar(challenges.xi); - transcript.addScalar(proof.getEvaluation("eval_a")); - transcript.addScalar(proof.getEvaluation("eval_b")); - transcript.addScalar(proof.getEvaluation("eval_c")); - transcript.addScalar(proof.getEvaluation("eval_s1")); - transcript.addScalar(proof.getEvaluation("eval_s2")); - transcript.addScalar(proof.getEvaluation("eval_zw")); - - challenges.v = []; - challenges.v[1] = transcript.getChallenge(); - if (logger) logger.debug("··· challenges.v: " + Fr.toString(challenges.v[1], 16)); - - for (let i = 2; i < 6; i++) { - challenges.v[i] = Fr.mul(challenges.v[i - 1], challenges.v[1]); - } - - // STEP 5.2 Compute linearisation polynomial r(X) - if (logger) logger.debug("> Computing linearisation polynomial R(X)"); - await computeR(); - - //STEP 5.3 Compute opening proof polynomial Wxi(X) - if (logger) logger.debug("> Computing opening proof polynomial Wxi(X) polynomial"); - computeWxi(); - - //STEP 5.4 Compute opening proof polynomial Wxiw(X) - if (logger) logger.debug("> Computing opening proof polynomial Wxiw(X) polynomial"); - computeWxiw(); - - if (logger) logger.debug("> Computing Wxi, Wxiw MSM"); - let commitWxi = await polynomials.Wxi.multiExponentiation(PTau, "Wxi"); - let commitWxiw = await polynomials.Wxiw.multiExponentiation(PTau, "Wxiw"); - - // Fifth output of the prover is ([Wxi]_1, [Wxiw]_1) - proof.addPolynomial("Wxi", commitWxi); - proof.addPolynomial("Wxiw", commitWxiw); - } - - async function computeR() { - const Fr = curve.Fr; - - // Reserve memory for Q's polynomials - polynomials.QL = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.QR = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.QM = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.QO = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.QC = new Polynomial(new BigBuffer(sDomain), curve, logger); - - // Read Q's evaluations from zkey file - await fdZKey.readToBuffer(polynomials.QL.coef, 0, sDomain, zkeySections[ZKEY_PL_QL_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QR.coef, 0, sDomain, zkeySections[ZKEY_PL_QR_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QM.coef, 0, sDomain, zkeySections[ZKEY_PL_QM_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QO.coef, 0, sDomain, zkeySections[ZKEY_PL_QO_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QC.coef, 0, sDomain, zkeySections[ZKEY_PL_QC_SECTION][0].p); - - challenges.xin = challenges.xi; - for (let i = 0; i < zkey.power; i++) { - challenges.xin = Fr.square(challenges.xin); - } - - challenges.zh = Fr.sub(challenges.xin, Fr.one); - - const L = []; - - const n = Fr.e(zkey.domainSize); - let w = Fr.one; - for (let i = 1; i <= Math.max(1, zkey.nPublic); i++) { - L[i] = Fr.div(Fr.mul(w, challenges.zh), Fr.mul(n, Fr.sub(challenges.xi, w))); - w = Fr.mul(w, Fr.w[zkey.power]); - } - - const eval_l1 = Fr.div( - Fr.sub(challenges.xin, Fr.one), - Fr.mul(n, Fr.sub(challenges.xi, Fr.one)) - ); - - if (logger) { - logger.debug("Lagrange Evaluations: "); - for (let i=1; i. -*/ -const {unstringifyBigInts: unstringifyBigInts$5} = utils; - -async function plonkFullProve(_input, wasmFile, zkeyFileName, logger, wtnsCalcOptions, proverOptions) { - const input = unstringifyBigInts$5(_input); - - const wtns= { - type: "mem" - }; - await wtnsCalculate(input, wasmFile, wtns, wtnsCalcOptions); - return await plonk16Prove(zkeyFileName, wtns, logger, proverOptions); -} - -/* - Copyright 2021 0kims association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -const { unstringifyBigInts: unstringifyBigInts$4 } = utils; - -async function plonkVerify(_vk_verifier, _publicSignals, _proof, logger) { - let vk_verifier = unstringifyBigInts$4(_vk_verifier); - _proof = unstringifyBigInts$4(_proof); - let publicSignals = unstringifyBigInts$4(_publicSignals); - - const curve = await getCurveFromName(vk_verifier.curve); - - const Fr = curve.Fr; - const G1 = curve.G1; - - if (logger) logger.info("PLONK VERIFIER STARTED"); - - let proof = fromObjectProof(curve,_proof); - vk_verifier = fromObjectVk$1(curve, vk_verifier); - - if (!isWellConstructed(curve, proof)) { - logger.error("Proof commitments are not valid."); - return false; - } - - if (publicSignals.length != vk_verifier.nPublic) { - if (logger) logger.error("Invalid number of public inputs"); - return false; - } - - if (!evaluationsAreValid$1(curve, proof)) { - if (logger) logger.error("Proof evaluations are not valid"); - return false; - } - - if (!publicInputsAreValid$1(curve, publicSignals)) { - if (logger) logger.error("Public inputs are not valid."); - return false; - } - - const challenges = calculatechallenges(curve, proof, publicSignals, vk_verifier); - if (logger) { - logger.debug("beta: " + Fr.toString(challenges.beta, 16)); - logger.debug("gamma: " + Fr.toString(challenges.gamma, 16)); - logger.debug("alpha: " + Fr.toString(challenges.alpha, 16)); - logger.debug("xi: " + Fr.toString(challenges.xi, 16)); - for(let i=1;i<6;i++) { - if (logger) logger.debug("v: " + Fr.toString(challenges.v[i], 16)); - } - logger.debug("u: " + Fr.toString(challenges.u, 16)); - } - const L = calculateLagrangeEvaluations(curve, challenges, vk_verifier); - if (logger) { - for (let i=1; i. -*/ -const { unstringifyBigInts: unstringifyBigInts$3} = utils; - -function p256$1(n) { - let nstr = n.toString(16); - while (nstr.length < 64) nstr = "0"+nstr; - nstr = `"0x${nstr}"`; - return nstr; -} - -async function plonkExportSolidityCallData(_proof, _pub) { - const proof = unstringifyBigInts$3(_proof); - const pub = unstringifyBigInts$3(_pub); - - await getCurveFromName(proof.curve); - - let inputs = ""; - for (let i=0; i. -*/ - -var plonk = /*#__PURE__*/Object.freeze({ - __proto__: null, - setup: plonkSetup, - fullProve: plonkFullProve, - prove: plonk16Prove, - verify: plonkVerify, - exportSolidityCallData: plonkExportSolidityCallData -}); - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -// We export to zkey the signals and values of the a, b, c, ql, qr, qm, qo and qc - -// a, b and c are signals id (32-bit integers) -// ql, qr, qm, qo and qc are field values - -function getFFlonkConstantConstraint(signal1, Fr) { - return [signal1, 0, 0, Fr.one, Fr.zero, Fr.zero, Fr.zero, Fr.zero]; -} - -function getFFlonkAdditionConstraint(signal1, signal2, signalOut, ql, qr, qm, qo, qc) { - return [signal1, signal2, signalOut, ql, qr, qm, qo, qc]; -} - -function getFFlonkMultiplicationConstraint(signal1, signal2, signalOut, ql, qr, qm, qo, qc, Fr) { - return [signal1, signal2, signalOut, ql, qr, qm, qo, qc]; -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -const LINEAR_COMBINATION_NULLABLE = 0; -const LINEAR_COMBINATION_CONSTANT = 1; -const LINEAR_COMBINATION_VARIABLE = 2; - -class r1csConstraintProcessor { - constructor(Fr, fnGetConstantConstraint, fnGetAdditionConstraint, fnGetMultiplicationConstraint, logger) { - this.Fr = Fr; - this.logger = logger; - this.fnGetAdditionConstraint = fnGetAdditionConstraint; - this.fnGetMultiplicationConstraint = fnGetMultiplicationConstraint; - } - - processR1csConstraint(settings, lcA, lcB, lcC) { - this.normalizeLinearCombination(lcA); - this.normalizeLinearCombination(lcB); - this.normalizeLinearCombination(lcC); - - const lctA = this.getLinearCombinationType(lcA); - const lctB = this.getLinearCombinationType(lcB); - - if ((lctA === LINEAR_COMBINATION_NULLABLE) || (lctB === LINEAR_COMBINATION_NULLABLE)) { - return this.processR1csAdditionConstraint(settings, lcC); - } else if (lctA === LINEAR_COMBINATION_CONSTANT) { - const lcCC = this.joinLinearCombinations(lcB, lcC, lcA[0]); - return this.processR1csAdditionConstraint(settings, lcCC); - } else if (lctB === LINEAR_COMBINATION_CONSTANT) { - const lcCC = this.joinLinearCombinations(lcA, lcC, lcB[0]); - return this.processR1csAdditionConstraint(settings, lcCC); - } else { - return this.processR1csMultiplicationConstraint(settings, lcA, lcB, lcC); - } - } - - getLinearCombinationType(linCom) { - // let k = this.Fr.zero; - // - // const signalIds = Object.keys(linCom); - // for (let i = 0; i < signalIds.length; i++) { - // if (signalIds[i] === "0") { - // k = this.Fr.add(k, linCom[signalIds[i]]); - // } else { - // return LINEAR_COMBINATION_VARIABLE; - // } - // } - // - // if (!this.Fr.eq(k, this.Fr.zero)) return LINEAR_COMBINATION_CONSTANT; - // - // return LINEAR_COMBINATION_NULLABLE; - - let k = this.Fr.zero; - let n = 0; - const ss = Object.keys(linCom); - for (let i = 0; i < ss.length; i++) { - if (linCom[ss[i]] == 0n) { - delete linCom[ss[i]]; - } else if (ss[i] == 0) { - k = this.Fr.add(k, linCom[ss[i]]); - } else { - n++; - } - } - if (n > 0) return LINEAR_COMBINATION_VARIABLE; - if (!this.Fr.isZero(k)) return LINEAR_COMBINATION_CONSTANT; - return LINEAR_COMBINATION_NULLABLE; - } - - normalizeLinearCombination(linCom) { - const signalIds = Object.keys(linCom); - for (let i = 0; i < signalIds.length; i++) { - if (this.Fr.isZero(linCom[signalIds[i]])) delete linCom[signalIds[i]]; - } - - return linCom; - } - - joinLinearCombinations(linCom1, linCom2, k) { - const res = {}; - - // for (let s in linCom1) { - // const val = this.Fr.mul(k, linCom1[s]); - // res[s] = !(s in res) ? val : this.Fr.add(val, res[s]); - // } - // - // for (let s in linCom2) { - // const val = this.Fr.mul(k, linCom2[s]); - // res[s] = !(s in res) ? val : this.Fr.add(val, res[s]); - // } - - for (let s in linCom1) { - if (typeof res[s] == "undefined") { - res[s] = this.Fr.mul(k, linCom1[s]); - } else { - res[s] = this.Fr.add(res[s], this.Fr.mul(k, linCom1[s])); - } - } - - for (let s in linCom2) { - if (typeof res[s] == "undefined") { - res[s] = linCom2[s]; - } else { - res[s] = this.Fr.add(res[s], linCom2[s]); - } - } - - return this.normalizeLinearCombination(res); - } - - reduceCoefs(settings, constraintsArr, additionsArr, linCom, maxC) { - const res = { - k: this.Fr.zero, - signals: [], - coefs: [] - }; - const cs = []; - - for (let signalId in linCom) { - if (signalId == 0) { - res.k = this.Fr.add(res.k, linCom[signalId]); - } else if (linCom[signalId] != 0n) { - cs.push([Number(signalId), linCom[signalId]]); - } - } - - while (cs.length > maxC) { - const c1 = cs.shift(); - const c2 = cs.shift(); - const so = settings.nVars++; - - const constraints = this.fnGetAdditionConstraint( - c1[0], c2[0], so, - this.Fr.neg(c1[1]), this.Fr.neg(c2[1]), this.Fr.zero, this.Fr.one, this.Fr.zero); - - constraintsArr.push(constraints); - additionsArr.push([c1[0], c2[0], c1[1], c2[1]]); - - cs.push([so, this.Fr.one]); - } - - for (let i = 0; i < cs.length; i++) { - res.signals[i] = cs[i][0]; - res.coefs[i] = cs[i][1]; - } - - while (res.coefs.length < maxC) { - res.signals.push(0); - res.coefs.push(this.Fr.zero); - } - - return res; - } - - processR1csAdditionConstraint(settings, linCom) { - const constraintsArr = []; - const additionsArr = []; - - const C = this.reduceCoefs(settings, constraintsArr, additionsArr, linCom, 3); - - const constraints = this.fnGetAdditionConstraint( - C.signals[0], C.signals[1], C.signals[2], - C.coefs[0], C.coefs[1], this.Fr.zero, C.coefs[2], C.k); - - constraintsArr.push(constraints); - - return [constraintsArr, additionsArr]; - } - - processR1csMultiplicationConstraint(settings, lcA, lcB, lcC) { - const constraintsArr = []; - const additionsArr = []; - - const A = this.reduceCoefs(settings, constraintsArr, additionsArr, lcA, 1); - const B = this.reduceCoefs(settings, constraintsArr, additionsArr, lcB, 1); - const C = this.reduceCoefs(settings, constraintsArr, additionsArr, lcC, 1); - - const constraints = this.fnGetMultiplicationConstraint( - A.signals[0], B.signals[0], C.signals[0], - this.Fr.mul(A.coefs[0], B.k), - this.Fr.mul(A.k, B.coefs[0]), - this.Fr.mul(A.coefs[0], B.coefs[0]), - this.Fr.neg(C.coefs[0]), - this.Fr.sub(this.Fr.mul(A.k, B.k), C.k)); - - constraintsArr.push(constraints); - - return [constraintsArr, additionsArr]; - } -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -class CPolynomial { - constructor(n, curve, logger) { - this.n = n; - this.polynomials = Array(n).fill(undefined); - this.curve = curve; - this.Fr = curve.Fr; - this.G1 = curve.G1; - this.logger = logger; - } - - addPolynomial(position, polynomial) { - if (position > this.n - 1) { - throw new Error("CPolynomial:addPolynomial, cannot add a polynomial to a position greater than n-1"); - } - - this.polynomials[position] = polynomial; - } - - degree() { - let degrees = this.polynomials.map( - (polynomial, index) => polynomial === undefined ? 0 : polynomial.degree() * this.n + index); - return Math.max(...degrees); - } - - getPolynomial() { - let degrees = this.polynomials.map(polynomial => polynomial === undefined ? 0 : polynomial.degree()); - const maxDegree = this.degree(); - const lengthBuffer = 2 ** (log2(maxDegree - 1) + 1); - const sFr = this.Fr.n8; - - let polynomial = new Polynomial(new BigBuffer(lengthBuffer * sFr), this.curve, this.logger); - - for (let i = 0; i < maxDegree; i++) { - const i_n8 = i * sFr; - const i_sFr = i_n8 * this.n; - - for (let j = 0; j < this.n; j++) { - if (this.polynomials[j] !== undefined) { - if (i <= degrees[j]) polynomial.coef.set(this.polynomials[j].coef.slice(i_n8, i_n8 + sFr), i_sFr + j * sFr); - } - } - } - - return polynomial; - } - - async multiExponentiation(PTau, name) { - let polynomial = this.getPolynomial(); - const n = polynomial.coef.byteLength / this.Fr.n8; - const PTauN = PTau.slice(0, n * this.G1.F.n8 * 2); - const bm = await this.Fr.batchFromMontgomery(polynomial.coef); - let res = await this.G1.multiExpAffine(PTauN, bm, this.logger, name); - res = this.G1.toAffine(res); - return res; - } -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - - -async function fflonkSetup(r1csFilename, ptauFilename, zkeyFilename, logger) { - if (logger) logger.info("FFLONK SETUP STARTED"); - - if (globalThis.gc) globalThis.gc(); - - // Read PTau file - if (logger) logger.info("> Reading PTau file"); - const {fd: fdPTau, sections: pTauSections} = await readBinFile$1(ptauFilename, "ptau", 1); - if (!pTauSections[12]) { - throw new Error("Powers of Tau is not well prepared. Section 12 missing."); - } - - // Get curve defined in PTau - if (logger) logger.info("> Getting curve from PTau settings"); - const {curve} = await readPTauHeader(fdPTau, pTauSections); - - // Read r1cs file - if (logger) logger.info("> Reading r1cs file"); - const {fd: fdR1cs, sections: sectionsR1cs} = await readBinFile$1(r1csFilename, "r1cs", 1); - const r1cs = await readR1csFd(fdR1cs, sectionsR1cs, {loadConstraints: false, loadCustomGates: true}); - - // Potential error checks - if (r1cs.prime !== curve.r) { - throw new Error("r1cs curve does not match powers of tau ceremony curve"); - } - - // Initializations - const Fr = curve.Fr; - - const sFr = curve.Fr.n8; - const sG1 = curve.G1.F.n8 * 2; - const sG2 = curve.G2.F.n8 * 2; - - let polynomials = {}; - let evaluations = {}; - let PTau; - - let settings = { - nVars: r1cs.nVars, - nPublic: r1cs.nOutputs + r1cs.nPubInputs - }; - - const plonkConstraints = new BigArray$1(); - let plonkAdditions = new BigArray$1(); - - // Process constraints inside r1cs - if (logger) logger.info("> Processing FFlonk constraints"); - await computeFFConstraints(curve.Fr, r1cs, logger); - if (globalThis.gc) globalThis.gc(); - - // As the t polynomial is n+5 we need at least a power of 4 - //TODO check!!!! - // NOTE : plonkConstraints + 2 = #constraints + blinding coefficients for each wire polynomial - settings.cirPower = Math.max(FF_T_POL_DEG_MIN, log2((plonkConstraints.length + 2) - 1) + 1); - settings.domainSize = 2 ** settings.cirPower; - - if (pTauSections[2][0].size < (settings.domainSize * 9 + 18) * sG1) { - throw new Error("Powers of Tau is not big enough for this circuit size. Section 2 too small."); - } - if (pTauSections[3][0].size < sG2) { - throw new Error("Powers of Tau is not well prepared. Section 3 too small."); - } - - if (logger) { - logger.info("----------------------------"); - logger.info(" FFLONK SETUP SETTINGS"); - logger.info(` Curve: ${curve.name}`); - logger.info(` Circuit power: ${settings.cirPower}`); - logger.info(` Domain size: ${settings.domainSize}`); - logger.info(` Vars: ${settings.nVars}`); - logger.info(` Public vars: ${settings.nPublic}`); - logger.info(` Constraints: ${plonkConstraints.length}`); - logger.info(` Additions: ${plonkAdditions.length}`); - logger.info("----------------------------"); - } - - // Compute k1 and k2 to be used in the permutation checks - if (logger) logger.info("> computing k1 and k2"); - const [k1, k2] = computeK1K2(); - - // Compute omega 3 (w3) and omega 4 (w4) to be used in the prover and the verifier - // w3^3 = 1 and w4^4 = 1 - if (logger) logger.info("> computing w3"); - const w3 = computeW3(); - if (logger) logger.info("> computing w4"); - const w4 = computeW4(); - if (logger) logger.info("> computing w8"); - const w8 = computeW8(); - if (logger) logger.info("> computing wr"); - const wr = getOmegaCubicRoot(settings.cirPower, curve.Fr); - - // Write output zkey file - await writeZkeyFile(); - - await fdR1cs.close(); - await fdPTau.close(); - - if (logger) logger.info("FFLONK SETUP FINISHED"); - - return 0; - - async function computeFFConstraints(Fr, r1cs, logger) { - // Add public inputs and outputs - for (let i = 0; i < settings.nPublic; i++) { - plonkConstraints.push(getFFlonkConstantConstraint(i + 1, Fr)); - } - - // Add all constraints from r1cs file - const r1csProcessor = new r1csConstraintProcessor(Fr, getFFlonkConstantConstraint, getFFlonkAdditionConstraint, getFFlonkMultiplicationConstraint, logger); - - const bR1cs = await readSection$1(fdR1cs, sectionsR1cs, 2); - let bR1csPos = 0; - for (let i = 0; i < r1cs.nConstraints; i++) { - if ((logger) && (i !== 0) && (i % 500000 === 0)) { - logger.info(` processing r1cs constraints ${i}/${r1cs.nConstraints}`); - } - const [constraints, additions] = r1csProcessor.processR1csConstraint(settings, ...readConstraint()); - - plonkConstraints.push(...constraints); - plonkAdditions.push(...additions); - } - - function readConstraint() { - const c = []; - c[0] = readLC(); - c[1] = readLC(); - c[2] = readLC(); - return c; - } - - function readLC() { - const lc = {}; - - const buffUL32 = bR1cs.slice(bR1csPos, bR1csPos + 4); - bR1csPos += 4; - const buffUL32V = new DataView(buffUL32.buffer); - const nIdx = buffUL32V.getUint32(0, true); - - const buff = bR1cs.slice(bR1csPos, bR1csPos + (4 + r1cs.n8) * nIdx); - bR1csPos += (4 + r1cs.n8) * nIdx; - const buffV = new DataView(buff.buffer); - for (let i = 0; i < nIdx; i++) { - const idx = buffV.getUint32(i * (4 + r1cs.n8), true); - const val = r1cs.F.fromRprLE(buff, i * (4 + r1cs.n8) + 4); - lc[idx] = val; - } - return lc; - } - - return 0; - } - - async function writeZkeyFile() { - if (logger) logger.info("> Writing the zkey file"); - const fdZKey = await createBinFile(zkeyFilename, "zkey", 1, ZKEY_FF_NSECTIONS, 1 << 22, 1 << 24); - - if (logger) logger.info(`··· Writing Section ${HEADER_ZKEY_SECTION}. Zkey Header`); - await writeZkeyHeader(fdZKey); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_ADDITIONS_SECTION}. Additions`); - await writeAdditions(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_A_MAP_SECTION}. A Map`); - await writeWitnessMap(fdZKey, ZKEY_FF_A_MAP_SECTION, 0, "A map"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_B_MAP_SECTION}. B Map`); - await writeWitnessMap(fdZKey, ZKEY_FF_B_MAP_SECTION, 1, "B map"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_C_MAP_SECTION}. C Map`); - await writeWitnessMap(fdZKey, ZKEY_FF_C_MAP_SECTION, 2, "C map"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_QL_SECTION}. QL`); - await writeQMap(fdZKey, ZKEY_FF_QL_SECTION, 3, "QL"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_QR_SECTION}. QR`); - await writeQMap(fdZKey, ZKEY_FF_QR_SECTION, 4, "QR"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_QM_SECTION}. QM`); - await writeQMap(fdZKey, ZKEY_FF_QM_SECTION, 5, "QM"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_QO_SECTION}. QO`); - await writeQMap(fdZKey, ZKEY_FF_QO_SECTION, 6, "QO"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_QC_SECTION}. QC`); - await writeQMap(fdZKey, ZKEY_FF_QC_SECTION, 7, "QC"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Sections ${ZKEY_FF_SIGMA1_SECTION},${ZKEY_FF_SIGMA2_SECTION},${ZKEY_FF_SIGMA3_SECTION}. Sigma1, Sigma2 & Sigma 3`); - await writeSigma(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_LAGRANGE_SECTION}. Lagrange Polynomials`); - await writeLagrangePolynomials(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_PTAU_SECTION}. Powers of Tau`); - await writePtau(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_C0_SECTION}. C0`); - await writeC0(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_HEADER_SECTION}. FFlonk Header`); - await writeFFlonkHeader(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info("> Writing the zkey file finished"); - - await fdZKey.close(); - } - - async function writeZkeyHeader(fdZKey) { - await startWriteSection(fdZKey, HEADER_ZKEY_SECTION); - await fdZKey.writeULE32(FFLONK_PROTOCOL_ID); - await endWriteSection(fdZKey); - } - - async function writeAdditions(fdZKey) { - await startWriteSection(fdZKey, ZKEY_FF_ADDITIONS_SECTION); - - // Written values are 2 * 32 bit integers (2 * 4 bytes) + 2 field size values ( 2 * sFr bytes) - const buffOut = new Uint8Array(8 + 2 * sFr); - const buffOutV = new DataView(buffOut.buffer); - - for (let i = 0; i < plonkAdditions.length; i++) { - if ((logger) && (i !== 0) && (i % 500000 === 0)) logger.info(` writing Additions: ${i}/${plonkAdditions.length}`); - - const addition = plonkAdditions[i]; - - buffOutV.setUint32(0, addition[0], true); - buffOutV.setUint32(4, addition[1], true); - buffOut.set(addition[2], 8); - buffOut.set(addition[3], 8 + sFr); - - await fdZKey.write(buffOut); - } - await endWriteSection(fdZKey); - } - - async function writeWitnessMap(fdZKey, sectionNum, posConstraint, name) { - await startWriteSection(fdZKey, sectionNum); - for (let i = 0; i < plonkConstraints.length; i++) { - if (logger && (i !== 0) && (i % 500000 === 0)) { - logger.info(` writing witness ${name}: ${i}/${plonkConstraints.length}`); - } - - await fdZKey.writeULE32(plonkConstraints[i][posConstraint]); - } - await endWriteSection(fdZKey); - } - - async function writeQMap(fdZKey, sectionNum, posConstraint, name) { - // Compute Q from q evaluations - let Q = new BigBuffer(settings.domainSize * sFr); - - for (let i = 0; i < plonkConstraints.length; i++) { - Q.set(plonkConstraints[i][posConstraint], i * sFr); - if ((logger) && (i !== 0) && (i % 500000 === 0)) { - logger.info(` writing ${name}: ${i}/${plonkConstraints.length}`); - } - } - - polynomials[name] = await Polynomial.fromEvaluations(Q, curve, logger); - evaluations[name] = await Evaluations.fromPolynomial(polynomials[name], 4, curve, logger); - - // Write Q coefficients and evaluations - await startWriteSection(fdZKey, sectionNum); - await fdZKey.write(polynomials[name].coef); - await fdZKey.write(evaluations[name].eval); - await endWriteSection(fdZKey); - } - - async function writeSigma(fdZKey) { - // Compute sigma - const sigma = new BigBuffer(sFr * settings.domainSize * 3); - const lastSeen = new BigArray$1(settings.nVars); - const firstPos = new BigArray$1(settings.nVars); - - let w = Fr.one; - for (let i = 0; i < settings.domainSize; i++) { - if (i < plonkConstraints.length) { - buildSigma(plonkConstraints[i][0], i); - buildSigma(plonkConstraints[i][1], settings.domainSize + i); - buildSigma(plonkConstraints[i][2], settings.domainSize * 2 + i); - } else if (i < settings.domainSize - 2) { - buildSigma(0, i); - buildSigma(0, settings.domainSize + i); - buildSigma(0, settings.domainSize * 2 + i); - } else { - sigma.set(w, i * sFr); - sigma.set(Fr.mul(w, k1), (settings.domainSize + i) * sFr); - sigma.set(Fr.mul(w, k2), (settings.domainSize * 2 + i) * sFr); - } - - w = Fr.mul(w, Fr.w[settings.cirPower]); - - if ((logger) && (i !== 0) && (i % 500000 === 0)) { - logger.info(` writing sigma phase1: ${i}/${plonkConstraints.length}`); - } - } - - for (let i = 0; i < settings.nVars; i++) { - if (typeof firstPos[i] !== "undefined") { - sigma.set(lastSeen[i], firstPos[i] * sFr); - } else { - // throw new Error("Variable not used"); - console.log("Variable not used"); - } - if ((logger) && (i !== 0) && (i % 500000 === 0)) logger.info(` writing sigma phase2: ${i}/${settings.nVars}`); - } - - if (globalThis.gc) globalThis.gc(); - - // Write sigma coefficients and evaluations - for (let i = 0; i < 3; i++) { - const sectionId = 0 === i ? ZKEY_FF_SIGMA1_SECTION : 1 === i ? ZKEY_FF_SIGMA2_SECTION : ZKEY_FF_SIGMA3_SECTION; - - let name = "S" + (i + 1); - polynomials[name] = await Polynomial.fromEvaluations(sigma.slice(settings.domainSize * sFr * i, settings.domainSize * sFr * (i + 1)), curve, logger); - evaluations[name] = await Evaluations.fromPolynomial(polynomials[name], 4, curve, logger); - await startWriteSection(fdZKey, sectionId); - await fdZKey.write(polynomials[name].coef); - await fdZKey.write(evaluations[name].eval); - await endWriteSection(fdZKey); - - if (globalThis.gc) globalThis.gc(); - } - - return 0; - - function buildSigma(signalId, idx) { - if (typeof lastSeen[signalId] === "undefined") { - firstPos[signalId] = idx; - } else { - sigma.set(lastSeen[signalId], idx * sFr); - } - let v; - if (idx < settings.domainSize) { - v = w; - } else if (idx < 2 * settings.domainSize) { - v = Fr.mul(w, k1); - } else { - v = Fr.mul(w, k2); - } - - lastSeen[signalId] = v; - } - } - - async function writeLagrangePolynomials(fdZKey) { - await startWriteSection(fdZKey, ZKEY_FF_LAGRANGE_SECTION); - - const l = Math.max(settings.nPublic, 1); - for (let i = 0; i < l; i++) { - let buff = new BigBuffer(settings.domainSize * sFr); - buff.set(Fr.one, i * sFr); - - await writeP4(fdZKey, buff); - } - await endWriteSection(fdZKey); - } - - async function writePtau(fdZKey) { - await startWriteSection(fdZKey, ZKEY_FF_PTAU_SECTION); - - // domainSize * 9 + 18 = maximum SRS length needed, specifically to commit C2 - PTau = new BigBuffer((settings.domainSize * 9 + 18) * sG1); - await fdPTau.readToBuffer(PTau, 0, (settings.domainSize * 9 + 18) * sG1, pTauSections[2][0].p); - - await fdZKey.write(PTau); - await endWriteSection(fdZKey); - } - - async function writeC0(fdZKey) { - // C0(X) := QL(X^8) + X · QR(X^8) + X^2 · QO(X^8) + X^3 · QM(X^8) + X^4 · QC(X^8) - // + X^5 · SIGMA1(X^8) + X^6 · SIGMA2(X^8) + X^7 · SIGMA3(X^8) - let C0 = new CPolynomial(8, curve, logger); - C0.addPolynomial(0, polynomials.QL); - C0.addPolynomial(1, polynomials.QR); - C0.addPolynomial(2, polynomials.QO); - C0.addPolynomial(3, polynomials.QM); - C0.addPolynomial(4, polynomials.QC); - C0.addPolynomial(5, polynomials.S1); - C0.addPolynomial(6, polynomials.S2); - C0.addPolynomial(7, polynomials.S3); - - polynomials.C0 = C0.getPolynomial(); - - // Check degree - if (polynomials.C0.degree() >= 8 * settings.domainSize) { - throw new Error("C0 Polynomial is not well calculated"); - } - - await startWriteSection(fdZKey, ZKEY_FF_C0_SECTION); - await fdZKey.write(polynomials.C0.coef); - await endWriteSection(fdZKey); - } - - async function writeFFlonkHeader(fdZKey) { - await startWriteSection(fdZKey, ZKEY_FF_HEADER_SECTION); - - const primeQ = curve.q; - const n8q = (Math.floor((Scalar.bitLength(primeQ) - 1) / 64) + 1) * 8; - await fdZKey.writeULE32(n8q); - await writeBigInt(fdZKey, primeQ, n8q); - - const primeR = curve.r; - const n8r = (Math.floor((Scalar.bitLength(primeR) - 1) / 64) + 1) * 8; - await fdZKey.writeULE32(n8r); - await writeBigInt(fdZKey, primeR, n8r); - - // Total number of r1cs vars - await fdZKey.writeULE32(settings.nVars); - // Total number of r1cs public vars = outputs + public inputs - await fdZKey.writeULE32(settings.nPublic); - await fdZKey.writeULE32(settings.domainSize); - await fdZKey.writeULE32(plonkAdditions.length); - await fdZKey.writeULE32(plonkConstraints.length); - - await fdZKey.write(k1); - await fdZKey.write(k2); - - await fdZKey.write(w3); - await fdZKey.write(w4); - await fdZKey.write(w8); - await fdZKey.write(wr); - - let bX_2; - bX_2 = await fdPTau.read(sG2, pTauSections[3][0].p + sG2); - await fdZKey.write(bX_2); - - let commitC0 = await polynomials.C0.multiExponentiation(PTau, "C0"); - await fdZKey.write(commitC0); - - await endWriteSection(fdZKey); - } - - async function writeP4(fdZKey, buff) { - const [coefficients, evaluations4] = await Polynomial.to4T(buff, settings.domainSize, [], Fr); - await fdZKey.write(coefficients); - await fdZKey.write(evaluations4); - - return [coefficients, evaluations4]; - } - - function computeK1K2() { - let k1 = Fr.two; - while (isIncluded(k1, [], settings.cirPower)) Fr.add(k1, Fr.one); - let k2 = Fr.add(k1, Fr.one); - while (isIncluded(k2, [k1], settings.cirPower)) Fr.add(k2, Fr.one); - return [k1, k2]; - - function isIncluded(k, kArr, pow) { - const domainSize = 2 ** pow; - let w = Fr.one; - for (let i = 0; i < domainSize; i++) { - if (Fr.eq(k, w)) return true; - for (let j = 0; j < kArr.length; j++) { - if (Fr.eq(k, Fr.mul(kArr[j], w))) return true; - } - w = Fr.mul(w, Fr.w[pow]); - } - return false; - } - } - - function computeW3() { - let generator = Fr.e(31624); - - // Exponent is order(r - 1) / 3 - let orderRsub1 = 3648040478639879203707734290876212514758060733402672390616367364429301415936n; - let exponent = Scalar.div(orderRsub1, Scalar.e(3)); - - return Fr.exp(generator, exponent); - } - - function computeW4() { - return Fr.w[2]; - } - - function computeW8() { - return Fr.w[3]; - } - - function getOmegaCubicRoot(power, Fr) { - // Hardcorded 3th-root of Fr.w[28] - const firstRoot = Fr.e(467799165886069610036046866799264026481344299079011762026774533774345988080n); - - return Fr.exp(firstRoot, 2 ** (28 - power)); - } -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -const { stringifyBigInts } = utils; - - -async function fflonkProve(zkeyFileName, witnessFileName, logger, options) { - if (logger) logger.info("FFLONK PROVER STARTED"); - - // Read witness file - if (logger) logger.info("> Reading witness file"); - const { - fd: fdWtns, - sections: wtnsSections - } = await readBinFile$1(witnessFileName, "wtns", 2); - const wtns = await readHeader(fdWtns, wtnsSections); - - //Read zkey file - if (logger) logger.info("> Reading zkey file"); - const { - fd: fdZKey, - sections: zkeySections - } = await readBinFile$1(zkeyFileName, "zkey", 2); - - const zkey = await readHeader$1(fdZKey, zkeySections, undefined, options); - - if (zkey.protocolId !== FFLONK_PROTOCOL_ID) { - throw new Error("zkey file is not fflonk"); - } - - if (!Scalar.eq(zkey.r, wtns.q)) { - throw new Error("Curve of the witness does not match the curve of the proving key"); - } - - if (wtns.nWitness !== zkey.nVars - zkey.nAdditions) { - throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}, ${zkey.nAdditions}`); - } - - const curve = zkey.curve; - - const Fr = curve.Fr; - - const sFr = curve.Fr.n8; - const sG1 = curve.G1.F.n8 * 2; - const sDomain = zkey.domainSize * sFr; - - if (logger) { - logger.info("----------------------------"); - logger.info(" FFLONK PROVE SETTINGS"); - logger.info(` Curve: ${curve.name}`); - logger.info(` Circuit power: ${zkey.power}`); - logger.info(` Domain size: ${zkey.domainSize}`); - logger.info(` Vars: ${zkey.nVars}`); - logger.info(` Public vars: ${zkey.nPublic}`); - logger.info(` Constraints: ${zkey.nConstraints}`); - logger.info(` Additions: ${zkey.nAdditions}`); - logger.info("----------------------------"); - } - - //Read witness data - if (logger) logger.info("> Reading witness file data"); - const buffWitness = await readSection$1(fdWtns, wtnsSections, 2); - await fdWtns.close(); - - // First element in plonk is not used and can be any value. (But always the same). - // We set it to zero to go faster in the exponentiations. - buffWitness.set(Fr.zero, 0); - const buffInternalWitness = new BigBuffer(zkey.nAdditions * sFr); - - let buffers = {}; - let polynomials = {}; - let evaluations = {}; - - // To divide prime fields the Extended Euclidean Algorithm for computing modular inverses is needed. - // NOTE: This is the equivalent of compute 1/denominator and then multiply it by the numerator. - // The Extended Euclidean Algorithm is expensive in terms of computation. - // For the special case where we need to do many modular inverses, there's a simple mathematical trick - // that allows us to compute many inverses, called Montgomery batch inversion. - // More info: https://vitalik.ca/general/2018/07/21/starks_part_3.html - // Montgomery batch inversion reduces the n inverse computations to a single one - // To save this (single) inverse computation on-chain, will compute it in proving time and send it to the verifier. - // The verifier will have to check: - // 1) the denominator is correct multiplying by himself non-inverted -> a * 1/a == 1 - // 2) compute the rest of the denominators using the Montgomery batch inversion - // The inversions are: - // · denominator needed in step 8 and 9 of the verifier to multiply by 1/Z_H(xi) - // · denominator needed in step 10 and 11 of the verifier - // · denominator needed in the verifier when computing L_i^{S1}(X) and L_i^{S2}(X) - // · L_i i=1 to num public inputs, needed in step 6 and 7 of the verifier to compute L_1(xi) and PI(xi) - let toInverse = {}; - - let challenges = {}; - let roots = {}; - - let proof = new Proof(curve, logger); - - if (logger) logger.info(`> Reading Section ${ZKEY_FF_ADDITIONS_SECTION}. Additions`); - await calculateAdditions(); - - if (logger) logger.info(`> Reading Sections ${ZKEY_FF_SIGMA1_SECTION},${ZKEY_FF_SIGMA2_SECTION},${ZKEY_FF_SIGMA3_SECTION}. Sigma1, Sigma2 & Sigma 3`); - if (logger) logger.info("··· Reading Sigma polynomials "); - polynomials.Sigma1 = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.Sigma2 = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.Sigma3 = new Polynomial(new BigBuffer(sDomain), curve, logger); - - await fdZKey.readToBuffer(polynomials.Sigma1.coef, 0, sDomain, zkeySections[ZKEY_FF_SIGMA1_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.Sigma2.coef, 0, sDomain, zkeySections[ZKEY_FF_SIGMA2_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.Sigma3.coef, 0, sDomain, zkeySections[ZKEY_FF_SIGMA3_SECTION][0].p); - - if (logger) logger.info("··· Reading Sigma evaluations"); - evaluations.Sigma1 = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.Sigma2 = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.Sigma3 = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - - await fdZKey.readToBuffer(evaluations.Sigma1.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_SIGMA1_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.Sigma2.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_SIGMA2_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.Sigma3.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_SIGMA3_SECTION][0].p + sDomain); - - if (logger) logger.info(`> Reading Section ${ZKEY_FF_PTAU_SECTION}. Powers of Tau`); - const PTau = new BigBuffer(zkey.domainSize * 16 * sG1); - // domainSize * 9 + 18 = SRS length in the zkey saved in setup process. - // it corresponds to the maximum SRS length needed, specifically to commit C2 - // notice that the reserved buffers size is zkey.domainSize * 16 * sG1 because a power of two buffer size is needed - // the remaining buffer not filled from SRS are set to 0 - await fdZKey.readToBuffer(PTau, 0, (zkey.domainSize * 9 + 18) * sG1, zkeySections[ZKEY_FF_PTAU_SECTION][0].p); - - // START FFLONK PROVER PROTOCOL - if (globalThis.gc) globalThis.gc(); - - // ROUND 1. Compute C1(X) polynomial - if (logger) logger.info(""); - if (logger) logger.info("> ROUND 1"); - await round1(); - - delete polynomials.T0; - delete evaluations.QL; - delete evaluations.QR; - delete evaluations.QM; - delete evaluations.QO; - delete evaluations.QC; - if (globalThis.gc) globalThis.gc(); - - // ROUND 2. Compute C2(X) polynomial - if (logger) logger.info("> ROUND 2"); - await round2(); - - delete buffers.A; - delete buffers.B; - delete buffers.C; - delete evaluations.A; - delete evaluations.B; - delete evaluations.C; - delete evaluations.Sigma1; - delete evaluations.Sigma2; - delete evaluations.Sigma3; - delete evaluations.lagrange1; - delete evaluations.Z; - if (globalThis.gc) globalThis.gc(); - - // ROUND 3. Compute opening evaluations - if (logger) logger.info("> ROUND 3"); - await round3(); - - delete polynomials.A; - delete polynomials.B; - delete polynomials.C; - delete polynomials.Z; - delete polynomials.T1; - delete polynomials.T2; - delete polynomials.Sigma1; - delete polynomials.Sigma2; - delete polynomials.Sigma3; - delete polynomials.QL; - delete polynomials.QR; - delete polynomials.QM; - delete polynomials.QC; - delete polynomials.QO; - if (globalThis.gc) globalThis.gc(); - - // ROUND 4. Compute W(X) polynomial - if (logger) logger.info("> ROUND 4"); - await round4(); - if (globalThis.gc) globalThis.gc(); - - // ROUND 5. Compute W'(X) polynomial - if (logger) logger.info("> ROUND 5"); - await round5(); - - delete polynomials.C0; - delete polynomials.C1; - delete polynomials.C2; - delete polynomials.R1; - delete polynomials.R2; - delete polynomials.F; - delete polynomials.L; - delete polynomials.ZT; - delete polynomials.ZTS2; - await fdZKey.close(); - if (globalThis.gc) globalThis.gc(); - - proof.addEvaluation("inv", getMontgomeryBatchedInverse()); - - // Prepare proof - let _proof = proof.toObjectProof(); - _proof.protocol = "fflonk"; - _proof.curve = curve.name; - - // Prepare public inputs - let publicSignals = []; - - for (let i = 1; i <= zkey.nPublic; i++) { - const i_sFr = i * sFr; - - const pub = buffWitness.slice(i_sFr, i_sFr + sFr); - publicSignals.push(Scalar.fromRprLE(pub)); - } - - if (logger) logger.info("FFLONK PROVER FINISHED"); - - return { - proof: stringifyBigInts(_proof), - publicSignals: stringifyBigInts(publicSignals) - }; - - async function calculateAdditions() { - if (logger) logger.info("··· Computing additions"); - const additionsBuff = await readSection$1(fdZKey, zkeySections, ZKEY_FF_ADDITIONS_SECTION); - - // sizes: wireId_x = 4 bytes (32 bits), factor_x = field size bits - // Addition form: wireId_a wireId_b factor_a factor_b (size is 4 + 4 + sFr + sFr) - const sSum = 8 + sFr * 2; - - for (let i = 0; i < zkey.nAdditions; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.info(` addition ${i}/${zkey.nAdditions}`); - - // Read addition values - let offset = i * sSum; - const signalId1 = readUInt32(additionsBuff, offset); - offset += 4; - const signalId2 = readUInt32(additionsBuff, offset); - offset += 4; - const factor1 = additionsBuff.slice(offset, offset + sFr); - offset += sFr; - const factor2 = additionsBuff.slice(offset, offset + sFr); - - // Get witness value - const witness1 = getWitness(signalId1); - const witness2 = getWitness(signalId2); - - //Calculate final result - const result = Fr.add(Fr.mul(factor1, witness1), Fr.mul(factor2, witness2)); - - buffInternalWitness.set(result, sFr * i); - } - } - - function readUInt32(b, o) { - const buff = b.slice(o, o + 4); - const buffV = new DataView(buff.buffer, buff.byteOffset, buff.byteLength); - return buffV.getUint32(0, true); - } - - function getWitness(idx) { - let diff = zkey.nVars - zkey.nAdditions; - if (idx < diff) { - return buffWitness.slice(idx * sFr, idx * sFr + sFr); - } else if (idx < zkey.nVars) { - const offset = (idx - diff) * sFr; - return buffInternalWitness.slice(offset, offset + sFr); - } - - return Fr.zero; - } - - async function round1() { - // STEP 1.1 - Generate random blinding scalars (b_1, ..., b9) ∈ F - challenges.b = []; - for (let i = 1; i <= 9; i++) { - challenges.b[i] = Fr.random(); - } - - // STEP 1.2 - Compute wire polynomials a(X), b(X) and c(X) - if (logger) logger.info("> Computing A, B, C wire polynomials"); - await computeWirePolynomials(); - - // STEP 1.3 - Compute the quotient polynomial T0(X) - if (logger) logger.info("> Computing T0 polynomial"); - await computeT0(); - - // STEP 1.4 - Compute the FFT-style combination polynomial C1(X) - if (logger) logger.info("> Computing C1 polynomial"); - await computeC1(); - - // The first output of the prover is ([C1]_1) - if (logger) logger.info("> Computing C1 multi exponentiation"); - let commitC1 = await polynomials.C1.multiExponentiation(PTau, "C1"); - proof.addPolynomial("C1", commitC1); - - return 0; - - async function computeWirePolynomials() { - if (logger) logger.info("··· Reading data from zkey file"); - // Build A, B and C evaluations buffer from zkey and witness files - buffers.A = new BigBuffer(sDomain); - buffers.B = new BigBuffer(sDomain); - buffers.C = new BigBuffer(sDomain); - - // Read zkey sections and fill the buffers - const aMapBuff = await readSection$1(fdZKey, zkeySections, ZKEY_FF_A_MAP_SECTION); - const bMapBuff = await readSection$1(fdZKey, zkeySections, ZKEY_FF_B_MAP_SECTION); - const cMapBuff = await readSection$1(fdZKey, zkeySections, ZKEY_FF_C_MAP_SECTION); - - // Compute all witness from signal ids and set them to A,B & C buffers - for (let i = 0; i < zkey.nConstraints; i++) { - const i_sFr = i * sFr; - const offset = i * 4; - - // Compute A value from a signal id - const signalIdA = readUInt32(aMapBuff, offset); - buffers.A.set(getWitness(signalIdA), i_sFr); - - // Compute B value from a signal id - const signalIdB = readUInt32(bMapBuff, offset); - buffers.B.set(getWitness(signalIdB), i_sFr); - - // Compute C value from a signal id - const signalIdC = readUInt32(cMapBuff, offset); - buffers.C.set(getWitness(signalIdC), i_sFr); - } - - // Blind a(X), b(X) and c(X) polynomials coefficients with blinding scalars b - buffers.A.set(challenges.b[1], sDomain - 64); - buffers.A.set(challenges.b[2], sDomain - 32); - buffers.B.set(challenges.b[3], sDomain - 64); - buffers.B.set(challenges.b[4], sDomain - 32); - buffers.C.set(challenges.b[5], sDomain - 64); - buffers.C.set(challenges.b[6], sDomain - 32); - - buffers.A = await Fr.batchToMontgomery(buffers.A); - buffers.B = await Fr.batchToMontgomery(buffers.B); - buffers.C = await Fr.batchToMontgomery(buffers.C); - - // Compute the coefficients of the wire polynomials a(X), b(X) and c(X) from A,B & C buffers - if (logger) logger.info("··· Computing A ifft"); - polynomials.A = await Polynomial.fromEvaluations(buffers.A, curve, logger); - if (logger) logger.info("··· Computing B ifft"); - polynomials.B = await Polynomial.fromEvaluations(buffers.B, curve, logger); - if (logger) logger.info("··· Computing C ifft"); - polynomials.C = await Polynomial.fromEvaluations(buffers.C, curve, logger); - - // Compute extended evaluations of a(X), b(X) and c(X) polynomials - if (logger) logger.info("··· Computing A fft"); - evaluations.A = await Evaluations.fromPolynomial(polynomials.A, 4, curve, logger); - if (logger) logger.info("··· Computing B fft"); - evaluations.B = await Evaluations.fromPolynomial(polynomials.B, 4, curve, logger); - if (logger) logger.info("··· Computing C fft"); - evaluations.C = await Evaluations.fromPolynomial(polynomials.C, 4, curve, logger); - - // Check degrees - if (polynomials.A.degree() >= zkey.domainSize) { - throw new Error("A Polynomial is not well calculated"); - } - if (polynomials.B.degree() >= zkey.domainSize) { - throw new Error("B Polynomial is not well calculated"); - } - if (polynomials.C.degree() >= zkey.domainSize) { - throw new Error("C Polynomial is not well calculated"); - } - } - - async function computeT0() { - if (logger) logger.info(`··· Reading sections ${ZKEY_FF_QL_SECTION}, ${ZKEY_FF_QR_SECTION}` + - `, ${ZKEY_FF_QM_SECTION}, ${ZKEY_FF_QO_SECTION}, ${ZKEY_FF_QC_SECTION}. Q selectors`); - // Reserve memory for Q's evaluations - evaluations.QL = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.QR = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.QM = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.QO = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.QC = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - - // Read Q's evaluations from zkey file - await fdZKey.readToBuffer(evaluations.QL.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_QL_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QR.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_QR_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QM.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_QM_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QO.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_QO_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QC.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_QC_SECTION][0].p + sDomain); - - // Read Lagrange polynomials & evaluations from zkey file - const lagrangePolynomials = await readSection$1(fdZKey, zkeySections, ZKEY_FF_LAGRANGE_SECTION); - evaluations.lagrange1 = new Evaluations(lagrangePolynomials, curve, logger); - - // Reserve memory for buffers T0 - buffers.T0 = new BigBuffer(sDomain * 4); - - if (logger) logger.info("··· Computing T0 evaluations"); - for (let i = 0; i < zkey.domainSize * 4; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.info(` T0 evaluation ${i}/${zkey.domainSize * 4}`); - - // Get related evaluations to compute current T0 evaluation - const a = evaluations.A.getEvaluation(i); - const b = evaluations.B.getEvaluation(i); - const c = evaluations.C.getEvaluation(i); - - const ql = evaluations.QL.getEvaluation(i); - const qr = evaluations.QR.getEvaluation(i); - const qm = evaluations.QM.getEvaluation(i); - const qo = evaluations.QO.getEvaluation(i); - const qc = evaluations.QC.getEvaluation(i); - - // Compute current public input - let pi = Fr.zero; - for (let j = 0; j < zkey.nPublic; j++) { - const offset = (j * 5 * zkey.domainSize) + zkey.domainSize + i; - - const lPol = evaluations.lagrange1.getEvaluation(offset); - const aVal = buffers.A.slice(j * sFr, (j + 1) * sFr); - - pi = Fr.sub(pi, Fr.mul(lPol, aVal)); - } - - //T0(X) = [q_L(X)·a(X) + q_R(X)·b(X) + q_M(X)·a(X)·b(X) + q_O(X)·c(X) + q_C(X) + PI(X)] · 1/Z_H(X) - // Compute first T0(X)·Z_H(X), so divide later the resulting polynomial by Z_H(X) - // expression 1 -> q_L(X)·a(X) - const e1 = Fr.mul(a, ql); - - // expression 2 -> q_R(X)·b(X) - const e2 = Fr.mul(b, qr); - - // expression 3 -> q_M(X)·a(X)·b(X) - const e3 = Fr.mul(Fr.mul(a, b), qm); - - // expression 4 -> q_O(X)·c(X) - const e4 = Fr.mul(c, qo); - - // t0 = expressions 1 + expression 2 + expression 3 + expression 4 + qc + pi - const t0 = Fr.add(e1, Fr.add(e2, Fr.add(e3, Fr.add(e4, Fr.add(qc, pi))))); - - buffers.T0.set(t0, i * sFr); - } - - if (logger) logger.info("buffer T0: " + buffers.T0.byteLength / sFr); - - // Compute the coefficients of the polynomial T0(X) from buffers.T0 - if (logger) logger.info("··· Computing T0 ifft"); - polynomials.T0 = await Polynomial.fromEvaluations(buffers.T0, curve, logger); - - if (logger) logger.info("T0 length: " + polynomials.T0.length()); - if (logger) logger.info("T0 degree: " + polynomials.T0.degree()); - - // Divide the polynomial T0 by Z_H(X) - if (logger) logger.info("··· Computing T0 / ZH"); - polynomials.T0.divByZerofier(zkey.domainSize, Fr.one); - - // Check degree - if (polynomials.T0.degree() >= 2 * zkey.domainSize - 2) { - throw new Error(`T0 Polynomial is not well calculated (degree is ${polynomials.T0.degree()} and must be less than ${2 * zkey.domainSize + 2}`); - } - - delete buffers.T0; - } - - async function computeC1() { - let C1 = new CPolynomial(4, curve, logger); - C1.addPolynomial(0, polynomials.A); - C1.addPolynomial(1, polynomials.B); - C1.addPolynomial(2, polynomials.C); - C1.addPolynomial(3, polynomials.T0); - - polynomials.C1 = C1.getPolynomial(); - - // Check degree - if (polynomials.C1.degree() >= 8 * zkey.domainSize - 8) { - throw new Error("C1 Polynomial is not well calculated"); - } - } - } - - async function round2() { - // STEP 2.1 - Compute permutation challenge beta and gamma ∈ F - // Compute permutation challenge beta - if (logger) logger.info("> Computing challenges beta and gamma"); - const transcript = new Keccak256Transcript(curve); - - // Add C0 to the transcript - transcript.addPolCommitment(zkey.C0); - - // Add A to the transcript - for (let i = 0; i < zkey.nPublic; i++) { - transcript.addScalar(buffers.A.slice(i * sFr, i * sFr + sFr)); - } - - // Add C1 to the transcript - transcript.addPolCommitment(proof.getPolynomial("C1")); - - challenges.beta = transcript.getChallenge(); - if (logger) logger.info("··· challenges.beta: " + Fr.toString(challenges.beta)); - - // Compute permutation challenge gamma - transcript.reset(); - transcript.addScalar(challenges.beta); - challenges.gamma = transcript.getChallenge(); - if (logger) logger.info("··· challenges.gamma: " + Fr.toString(challenges.gamma)); - - // STEP 2.2 - Compute permutation polynomial z(X) - if (logger) logger.info("> Computing Z polynomial"); - await computeZ(); - - // STEP 2.3 - Compute quotient polynomial T1(X) and T2(X) - if (logger) logger.info("> Computing T1 polynomial"); - await computeT1(); - if (logger) logger.info("> Computing T2 polynomial"); - await computeT2(); - - // STEP 2.4 - Compute the FFT-style combination polynomial C2(X) - if (logger) logger.info("> Computing C2 polynomial"); - await computeC2(); - - // The second output of the prover is ([C2]_1) - if (logger) logger.info("> Computing C2 multi exponentiation"); - let commitC2 = await polynomials.C2.multiExponentiation(PTau, "C2"); - proof.addPolynomial("C2", commitC2); - - return 0; - - async function computeZ() { - if (logger) logger.info("··· Computing Z evaluations"); - - let numArr = new BigBuffer(sDomain); - let denArr = new BigBuffer(sDomain); - - // Set the first values to 1 - numArr.set(Fr.one, 0); - denArr.set(Fr.one, 0); - - // Set initial omega - let w = Fr.one; - for (let i = 0; i < zkey.domainSize; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.info(` Z evaluation ${i}/${zkey.domainSize}`); - const i_sFr = i * sFr; - - // Z(X) := numArr / denArr - // numArr := (a + beta·ω + gamma)(b + beta·ω·k1 + gamma)(c + beta·ω·k2 + gamma) - const betaw = Fr.mul(challenges.beta, w); - - let num1 = buffers.A.slice(i_sFr, i_sFr + sFr); - num1 = Fr.add(num1, betaw); - num1 = Fr.add(num1, challenges.gamma); - - let num2 = buffers.B.slice(i_sFr, i_sFr + sFr); - num2 = Fr.add(num2, Fr.mul(zkey.k1, betaw)); - num2 = Fr.add(num2, challenges.gamma); - - let num3 = buffers.C.slice(i_sFr, i_sFr + sFr); - num3 = Fr.add(num3, Fr.mul(zkey.k2, betaw)); - num3 = Fr.add(num3, challenges.gamma); - - let num = Fr.mul(num1, Fr.mul(num2, num3)); - - // denArr := (a + beta·sigma1 + gamma)(b + beta·sigma2 + gamma)(c + beta·sigma3 + gamma) - let den1 = buffers.A.slice(i_sFr, i_sFr + sFr); - den1 = Fr.add(den1, Fr.mul(challenges.beta, evaluations.Sigma1.getEvaluation(i * 4))); - den1 = Fr.add(den1, challenges.gamma); - - let den2 = buffers.B.slice(i_sFr, i_sFr + sFr); - den2 = Fr.add(den2, Fr.mul(challenges.beta, evaluations.Sigma2.getEvaluation(i * 4))); - den2 = Fr.add(den2, challenges.gamma); - - let den3 = buffers.C.slice(i_sFr, i_sFr + sFr); - den3 = Fr.add(den3, Fr.mul(challenges.beta, evaluations.Sigma3.getEvaluation(i * 4))); - den3 = Fr.add(den3, challenges.gamma); - - let den = Fr.mul(den1, Fr.mul(den2, den3)); - - // Multiply current num value with the previous one saved in numArr - num = Fr.mul(numArr.slice(i_sFr, i_sFr + sFr), num); - numArr.set(num, ((i + 1) % zkey.domainSize) * sFr); - - // Multiply current den value with the previous one saved in denArr - den = Fr.mul(denArr.slice(i_sFr, i_sFr + sFr), den); - denArr.set(den, ((i + 1) % zkey.domainSize) * sFr); - - // Next omega - w = Fr.mul(w, Fr.w[zkey.power]); - } - // Compute the inverse of denArr to compute in the next command the - // division numArr/denArr by multiplying num · 1/denArr - denArr = await Fr.batchInverse(denArr); - - // TODO: Do it in assembly and in parallel - // Multiply numArr · denArr where denArr was inverted in the previous command - for (let i = 0; i < zkey.domainSize; i++) { - const i_sFr = i * sFr; - - const z = Fr.mul(numArr.slice(i_sFr, i_sFr + sFr), denArr.slice(i_sFr, i_sFr + sFr)); - numArr.set(z, i_sFr); - } - // From now on the values saved on numArr will be Z(X) buffer - buffers.Z = numArr; - - if (!Fr.eq(numArr.slice(0, sFr), Fr.one)) { - throw new Error("Copy constraints does not match"); - } - - // Compute polynomial coefficients z(X) from buffers.Z - if (logger) logger.info("··· Computing Z ifft"); - polynomials.Z = await Polynomial.fromEvaluations(buffers.Z, curve, logger); - - // Compute extended evaluations of z(X) polynomial - if (logger) logger.info("··· Computing Z fft"); - evaluations.Z = await Evaluations.fromPolynomial(polynomials.Z, 4, curve, logger); - - // Blind z(X) polynomial coefficients with blinding scalars b - polynomials.Z.blindCoefficients([challenges.b[9], challenges.b[8], challenges.b[7]]); - - // Check degree - if (polynomials.Z.degree() >= zkey.domainSize + 3) { - throw new Error("Z Polynomial is not well calculated"); - } - - delete buffers.Z; - } - - async function computeT1() { - if (logger) logger.info("··· Computing T1 evaluations"); - - buffers.T1 = new BigBuffer(sDomain * 2); - buffers.T1z = new BigBuffer(sDomain * 2); - - // Set initial omega - let omega = Fr.one; - for (let i = 0; i < zkey.domainSize * 2; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.info(` T1 evaluation ${i}/${zkey.domainSize * 4}`); - - const omega2 = Fr.square(omega); - - const z = evaluations.Z.getEvaluation(i * 2); - const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omega2), Fr.mul(challenges.b[8], omega)), challenges.b[9]); - - // T1(X) := (z(X) - 1) · L_1(X) - // Compute first T1(X)·Z_H(X), so divide later the resulting polynomial by Z_H(X) - const lagrange1 = evaluations.lagrange1.getEvaluation(zkey.domainSize + i * 2); - let t1 = Fr.mul(Fr.sub(z, Fr.one), lagrange1); - let t1z = Fr.mul(zp, lagrange1); - - buffers.T1.set(t1, i * sFr); - buffers.T1z.set(t1z, i * sFr); - - // Compute next omega - omega = Fr.mul(omega, Fr.w[zkey.power + 1]); - } - - // Compute the coefficients of the polynomial T1(X) from buffers.T1 - if (logger) logger.info("··· Computing T1 ifft"); - polynomials.T1 = await Polynomial.fromEvaluations(buffers.T1, curve, logger); - - // Divide the polynomial T1 by Z_H(X) - polynomials.T1.divByZerofier(zkey.domainSize, Fr.one); - - // Compute the coefficients of the polynomial T1z(X) from buffers.T1z - if (logger) logger.info("··· Computing T1z ifft"); - polynomials.T1z = await Polynomial.fromEvaluations(buffers.T1z, curve, logger); - - // Add the polynomial T1z to T1 to get the final polynomial T1 - polynomials.T1.add(polynomials.T1z); - - // Check degree - if (polynomials.T1.degree() >= zkey.domainSize + 2) { - throw new Error("T1 Polynomial is not well calculated"); - } - - delete buffers.T1; - delete buffers.T1z; - delete polynomials.T1z; - } - - async function computeT2() { - if (logger) logger.info("··· Computing T2 evaluations"); - - buffers.T2 = new BigBuffer(sDomain * 4); - buffers.T2z = new BigBuffer(sDomain * 4); - - // Set initial omega - let omega = Fr.one; - for (let i = 0; i < zkey.domainSize * 4; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.info(` T2 evaluation ${i}/${zkey.domainSize * 4}`); - - const omega2 = Fr.square(omega); - const omegaW = Fr.mul(omega, Fr.w[zkey.power]); - const omegaW2 = Fr.square(omegaW); - - const a = evaluations.A.getEvaluation(i); - const b = evaluations.B.getEvaluation(i); - const c = evaluations.C.getEvaluation(i); - const z = evaluations.Z.getEvaluation(i); - const zW = evaluations.Z.getEvaluation((zkey.domainSize * 4 + 4 + i) % (zkey.domainSize * 4)); - - const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omega2), Fr.mul(challenges.b[8], omega)), challenges.b[9]); - const zWp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omegaW2), Fr.mul(challenges.b[8], omegaW)), challenges.b[9]); - - const sigma1 = evaluations.Sigma1.getEvaluation(i); - const sigma2 = evaluations.Sigma2.getEvaluation(i); - const sigma3 = evaluations.Sigma3.getEvaluation(i); - - // T2(X) := [ (a(X) + beta·X + gamma)(b(X) + beta·k1·X + gamma)(c(X) + beta·k2·X + gamma)z(X) - // -(a(X) + beta·sigma1(X) + gamma)(b(X) + beta·sigma2(X) + gamma)(c(X) + beta·sigma3(X) + gamma)z(Xω)] · 1/Z_H(X) - // Compute first T2(X)·Z_H(X), so divide later the resulting polynomial by Z_H(X) - - // expression 1 -> (a(X) + beta·X + gamma)(b(X) + beta·k1·X + gamma)(c(X) + beta·k2·X + gamma)z(X) - const betaX = Fr.mul(challenges.beta, omega); - - let e11 = Fr.add(a, betaX); - e11 = Fr.add(e11, challenges.gamma); - - let e12 = Fr.add(b, Fr.mul(betaX, zkey.k1)); - e12 = Fr.add(e12, challenges.gamma); - - let e13 = Fr.add(c, Fr.mul(betaX, zkey.k2)); - e13 = Fr.add(e13, challenges.gamma); - - let e1 = Fr.mul(Fr.mul(Fr.mul(e11, e12), e13), z); - let e1z = Fr.mul(Fr.mul(Fr.mul(e11, e12), e13), zp); - // const [e1, e1z] = MulZ.mul4(e11, e12, e13, z, ap, bp, cp, zp, i % 4, Fr); - - // expression 2 -> (a(X) + beta·sigma1(X) + gamma)(b(X) + beta·sigma2(X) + gamma)(c(X) + beta·sigma3(X) + gamma)z(Xω) - let e21 = Fr.add(a, Fr.mul(challenges.beta, sigma1)); - e21 = Fr.add(e21, challenges.gamma); - - let e22 = Fr.add(b, Fr.mul(challenges.beta, sigma2)); - e22 = Fr.add(e22, challenges.gamma); - - let e23 = Fr.add(c, Fr.mul(challenges.beta, sigma3)); - e23 = Fr.add(e23, challenges.gamma); - - let e2 = Fr.mul(Fr.mul(Fr.mul(e21, e22), e23), zW); - let e2z = Fr.mul(Fr.mul(Fr.mul(e21, e22), e23), zWp); - // const [e2, e2z] = MulZ.mul4(e21, e22, e23, zW, ap, bp, cp, zWp, i % 4, Fr); - - let t2 = Fr.sub(e1, e2); - let t2z = Fr.sub(e1z, e2z); - - buffers.T2.set(t2, i * sFr); - buffers.T2z.set(t2z, i * sFr); - - // Compute next omega - omega = Fr.mul(omega, Fr.w[zkey.power + 2]); - } - - // Compute the coefficients of the polynomial T2(X) from buffers.T2 - if (logger) logger.info("··· Computing T2 ifft"); - polynomials.T2 = await Polynomial.fromEvaluations(buffers.T2, curve, logger); - - // Divide the polynomial T2 by Z_H(X) - if (logger) logger.info("··· Computing T2 / ZH"); - polynomials.T2.divByZerofier(zkey.domainSize, Fr.one); - - // Compute the coefficients of the polynomial T2z(X) from buffers.T2z - if (logger) logger.info("··· Computing T2z ifft"); - polynomials.T2z = await Polynomial.fromEvaluations(buffers.T2z, curve, logger); - - // Add the polynomial T2z to T2 to get the final polynomial T2 - polynomials.T2.add(polynomials.T2z); - - // Check degree - if (polynomials.T2.degree() >= 3 * zkey.domainSize) { - throw new Error("T2 Polynomial is not well calculated"); - } - - delete buffers.T2; - delete buffers.T2z; - delete polynomials.T2z; - } - - async function computeC2() { - let C2 = new CPolynomial(3, curve, logger); - C2.addPolynomial(0, polynomials.Z); - C2.addPolynomial(1, polynomials.T1); - C2.addPolynomial(2, polynomials.T2); - - polynomials.C2 = C2.getPolynomial(); - - // Check degree - if (polynomials.C2.degree() >= 9 * zkey.domainSize) { - throw new Error("C2 Polynomial is not well calculated"); - } - } - } - - async function round3() { - if (logger) logger.info("> Computing challenge xi"); - // STEP 3.1 - Compute evaluation challenge xi ∈ S - const transcript = new Keccak256Transcript(curve); - transcript.addScalar(challenges.gamma); - transcript.addPolCommitment(proof.getPolynomial("C2")); - - // Obtain a xi_seeder from the transcript - // To force h1^4 = xi, h2^3 = xi and h_3^2 = xiω - // we compute xi = xi_seeder^12, h1 = xi_seeder^3, h2 = xi_seeder^4 and h3 = xi_seeder^6 - challenges.xiSeed = transcript.getChallenge(); - const xiSeed2 = Fr.square(challenges.xiSeed); - - // Compute omega8, omega4 and omega3 - roots.w8 = []; - roots.w8[0] = Fr.one; - for (let i = 1; i < 8; i++) { - roots.w8[i] = Fr.mul(roots.w8[i - 1], zkey.w8); - } - - roots.w4 = []; - roots.w4[0] = Fr.one; - for (let i = 1; i < 4; i++) { - roots.w4[i] = Fr.mul(roots.w4[i - 1], zkey.w4); - } - - roots.w3 = []; - roots.w3[0] = Fr.one; - roots.w3[1] = zkey.w3; - roots.w3[2] = Fr.square(zkey.w3); - - // Compute h0 = xiSeeder^3 - roots.S0 = {}; - roots.S0.h0w8 = []; - roots.S0.h0w8[0] = Fr.mul(xiSeed2, challenges.xiSeed); - for (let i = 1; i < 8; i++) { - roots.S0.h0w8[i] = Fr.mul(roots.S0.h0w8[0], roots.w8[i]); - } - - // Compute h1 = xi_seeder^6 - roots.S1 = {}; - roots.S1.h1w4 = []; - roots.S1.h1w4[0] = Fr.square(roots.S0.h0w8[0]); - for (let i = 1; i < 4; i++) { - roots.S1.h1w4[i] = Fr.mul(roots.S1.h1w4[0], roots.w4[i]); - } - - // Compute h2 = xi_seeder^8 - roots.S2 = {}; - roots.S2.h2w3 = []; - roots.S2.h2w3[0] = Fr.mul(roots.S1.h1w4[0], xiSeed2); - roots.S2.h2w3[1] = Fr.mul(roots.S2.h2w3[0], roots.w3[1]); - roots.S2.h2w3[2] = Fr.mul(roots.S2.h2w3[0], roots.w3[2]); - - roots.S2.h3w3 = []; - // Multiply h3 by third-root-omega to obtain h_3^3 = xiω - // So, h3 = xi_seeder^8 ω^{1/3} - roots.S2.h3w3[0] = Fr.mul(roots.S2.h2w3[0], zkey.wr); - roots.S2.h3w3[1] = Fr.mul(roots.S2.h3w3[0], roots.w3[1]); - roots.S2.h3w3[2] = Fr.mul(roots.S2.h3w3[0], roots.w3[2]); - - // Compute xi = xi_seeder^24 - challenges.xi = Fr.mul(Fr.square(roots.S2.h2w3[0]), roots.S2.h2w3[0]); - - if (logger) logger.info("··· challenges.xi: " + Fr.toString(challenges.xi)); - - // Reserve memory for Q's polynomials - polynomials.QL = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.QR = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.QM = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.QO = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.QC = new Polynomial(new BigBuffer(sDomain), curve, logger); - - // Read Q's evaluations from zkey file - await fdZKey.readToBuffer(polynomials.QL.coef, 0, sDomain, zkeySections[ZKEY_FF_QL_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QR.coef, 0, sDomain, zkeySections[ZKEY_FF_QR_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QM.coef, 0, sDomain, zkeySections[ZKEY_FF_QM_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QO.coef, 0, sDomain, zkeySections[ZKEY_FF_QO_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QC.coef, 0, sDomain, zkeySections[ZKEY_FF_QC_SECTION][0].p); - - // STEP 3.2 - Compute opening evaluations and add them to the proof (third output of the prover) - if (logger) logger.info("··· Computing evaluations"); - proof.addEvaluation("ql", polynomials.QL.evaluate(challenges.xi)); - proof.addEvaluation("qr", polynomials.QR.evaluate(challenges.xi)); - proof.addEvaluation("qm", polynomials.QM.evaluate(challenges.xi)); - proof.addEvaluation("qo", polynomials.QO.evaluate(challenges.xi)); - proof.addEvaluation("qc", polynomials.QC.evaluate(challenges.xi)); - proof.addEvaluation("s1", polynomials.Sigma1.evaluate(challenges.xi)); - proof.addEvaluation("s2", polynomials.Sigma2.evaluate(challenges.xi)); - proof.addEvaluation("s3", polynomials.Sigma3.evaluate(challenges.xi)); - proof.addEvaluation("a", polynomials.A.evaluate(challenges.xi)); - proof.addEvaluation("b", polynomials.B.evaluate(challenges.xi)); - proof.addEvaluation("c", polynomials.C.evaluate(challenges.xi)); - proof.addEvaluation("z", polynomials.Z.evaluate(challenges.xi)); - - challenges.xiw = Fr.mul(challenges.xi, Fr.w[zkey.power]); - proof.addEvaluation("zw", polynomials.Z.evaluate(challenges.xiw)); - proof.addEvaluation("t1w", polynomials.T1.evaluate(challenges.xiw)); - proof.addEvaluation("t2w", polynomials.T2.evaluate(challenges.xiw)); - } - - async function round4() { - if (logger) logger.info("> Computing challenge alpha"); - // STEP 4.1 - Compute challenge alpha ∈ F - const transcript = new Keccak256Transcript(curve); - transcript.addScalar(challenges.xiSeed); - transcript.addScalar(proof.getEvaluation("ql")); - transcript.addScalar(proof.getEvaluation("qr")); - transcript.addScalar(proof.getEvaluation("qm")); - transcript.addScalar(proof.getEvaluation("qo")); - transcript.addScalar(proof.getEvaluation("qc")); - transcript.addScalar(proof.getEvaluation("s1")); - transcript.addScalar(proof.getEvaluation("s2")); - transcript.addScalar(proof.getEvaluation("s3")); - transcript.addScalar(proof.getEvaluation("a")); - transcript.addScalar(proof.getEvaluation("b")); - transcript.addScalar(proof.getEvaluation("c")); - transcript.addScalar(proof.getEvaluation("z")); - transcript.addScalar(proof.getEvaluation("zw")); - transcript.addScalar(proof.getEvaluation("t1w")); - transcript.addScalar(proof.getEvaluation("t2w")); - challenges.alpha = transcript.getChallenge(); - if (logger) logger.info("··· challenges.alpha: " + Fr.toString(challenges.alpha)); - - // STEP 4.2 - Compute F(X) - if (logger) logger.info("> Reading C0 polynomial"); - polynomials.C0 = new Polynomial(new BigBuffer(sDomain * 8), curve, logger); - await fdZKey.readToBuffer(polynomials.C0.coef, 0, sDomain * 8, zkeySections[ZKEY_FF_C0_SECTION][0].p); - - if (logger) logger.info("> Computing R0 polynomial"); - computeR0(); - if (logger) logger.info("> Computing R1 polynomial"); - computeR1(); - if (logger) logger.info("> Computing R2 polynomial"); - computeR2(); - - if (logger) logger.info("> Computing F polynomial"); - await computeF(); - - // The fourth output of the prover is ([W1]_1), where W1:=(f/Z_t)(x) - if (logger) logger.info("> Computing W1 multi exponentiation"); - let commitW1 = await polynomials.F.multiExponentiation(PTau, "W1"); - proof.addPolynomial("W1", commitW1); - - return 0; - - function computeR0() { - // COMPUTE R0 - // Compute the coefficients of R0(X) from 8 evaluations using lagrange interpolation. R0(X) ∈ F_{<8}[X] - // We decide to use Lagrange interpolations because the R0 degree is very small (deg(R0)===7), - // and we were not able to compute it using current ifft implementation because the omega are different - polynomials.R0 = Polynomial.lagrangePolynomialInterpolation( - [roots.S0.h0w8[0], roots.S0.h0w8[1], roots.S0.h0w8[2], roots.S0.h0w8[3], - roots.S0.h0w8[4], roots.S0.h0w8[5], roots.S0.h0w8[6], roots.S0.h0w8[7]], - [polynomials.C0.evaluate(roots.S0.h0w8[0]), polynomials.C0.evaluate(roots.S0.h0w8[1]), - polynomials.C0.evaluate(roots.S0.h0w8[2]), polynomials.C0.evaluate(roots.S0.h0w8[3]), - polynomials.C0.evaluate(roots.S0.h0w8[4]), polynomials.C0.evaluate(roots.S0.h0w8[5]), - polynomials.C0.evaluate(roots.S0.h0w8[6]), polynomials.C0.evaluate(roots.S0.h0w8[7])], curve); - - // Check the degree of r0(X) < 8 - if (polynomials.R0.degree() > 7) { - throw new Error("R0 Polynomial is not well calculated"); - } - } - - function computeR1() { - // COMPUTE R1 - // Compute the coefficients of R1(X) from 4 evaluations using lagrange interpolation. R1(X) ∈ F_{<4}[X] - // We decide to use Lagrange interpolations because the R1 degree is very small (deg(R1)===3), - // and we were not able to compute it using current ifft implementation because the omega are different - polynomials.R1 = Polynomial.lagrangePolynomialInterpolation( - [roots.S1.h1w4[0], roots.S1.h1w4[1], roots.S1.h1w4[2], roots.S1.h1w4[3]], - [polynomials.C1.evaluate(roots.S1.h1w4[0]), polynomials.C1.evaluate(roots.S1.h1w4[1]), - polynomials.C1.evaluate(roots.S1.h1w4[2]), polynomials.C1.evaluate(roots.S1.h1w4[3])], curve); - - // Check the degree of r1(X) < 4 - if (polynomials.R1.degree() > 3) { - throw new Error("R1 Polynomial is not well calculated"); - } - } - - function computeR2() { - // COMPUTE R2 - // Compute the coefficients of r2(X) from 6 evaluations using lagrange interpolation. r2(X) ∈ F_{<6}[X] - // We decide to use Lagrange interpolations because the R2.degree is very small (deg(R2)===5), - // and we were not able to compute it using current ifft implementation because the omega are different - polynomials.R2 = Polynomial.lagrangePolynomialInterpolation( - [roots.S2.h2w3[0], roots.S2.h2w3[1], roots.S2.h2w3[2], - roots.S2.h3w3[0], roots.S2.h3w3[1], roots.S2.h3w3[2]], - [polynomials.C2.evaluate(roots.S2.h2w3[0]), polynomials.C2.evaluate(roots.S2.h2w3[1]), - polynomials.C2.evaluate(roots.S2.h2w3[2]), polynomials.C2.evaluate(roots.S2.h3w3[0]), - polynomials.C2.evaluate(roots.S2.h3w3[1]), polynomials.C2.evaluate(roots.S2.h3w3[2])], curve); - - // Check the degree of r2(X) < 6 - if (polynomials.R2.degree() > 5) { - throw new Error("R2 Polynomial is not well calculated"); - } - } - - async function computeF() { - if (logger) logger.info("··· Computing F polynomial"); - - // COMPUTE F(X) - polynomials.F = Polynomial.fromPolynomial(polynomials.C0, curve, logger); - polynomials.F.sub(polynomials.R0); - polynomials.F.divByZerofier(8, challenges.xi); - - let f2 = Polynomial.fromPolynomial(polynomials.C1, curve, logger); - f2.sub(polynomials.R1); - f2.mulScalar(challenges.alpha); - f2.divByZerofier(4, challenges.xi); - - let f3 = Polynomial.fromPolynomial(polynomials.C2, curve, logger); - f3.sub(polynomials.R2); - f3.mulScalar(Fr.square(challenges.alpha)); - f3.divByZerofier(3, challenges.xi); - f3.divByZerofier(3, challenges.xiw); - - polynomials.F.add(f2); - polynomials.F.add(f3); - - if (polynomials.F.degree() >= 9 * zkey.domainSize - 6) { - throw new Error("F Polynomial is not well calculated"); - } - } - } - - async function round5() { - if (logger) logger.info("> Computing challenge y"); - - // STEP 5.1 - Compute random evaluation point y ∈ F - const transcript = new Keccak256Transcript(curve); - transcript.addScalar(challenges.alpha); - transcript.addPolCommitment(proof.getPolynomial("W1")); - - challenges.y = transcript.getChallenge(); - if (logger) logger.info("··· challenges.y: " + Fr.toString(challenges.y)); - - // STEP 5.2 - Compute L(X) - if (logger) logger.info("> Computing L polynomial"); - await computeL(); - - if (logger) logger.info("> Computing ZTS2 polynomial"); - await computeZTS2(); - - let ZTS2Y = polynomials.ZTS2.evaluate(challenges.y); - ZTS2Y = Fr.inv(ZTS2Y); - polynomials.L.mulScalar(ZTS2Y); - - const polDividend = Polynomial.fromCoefficientsArray([Fr.neg(challenges.y), Fr.one], curve); - if (logger) logger.info("> Computing W' = L / ZTS2 polynomial"); - const polRemainder = polynomials.L.divBy(polDividend); - - //Check polReminder degree is equal to zero - if (polRemainder.degree() > 0) { - throw new Error(`Degree of L(X)/(ZTS2(y)(X-y)) remainder is ${polRemainder.degree()} and should be 0`); - } - - if (polynomials.L.degree() >= 9 * zkey.domainSize - 1) { - throw new Error("Degree of L(X)/(ZTS2(y)(X-y)) is not correct"); - } - - // The fifth output of the prover is ([W2]_1), where W2:=(f/Z_t)(x) - if (logger) logger.info("> Computing W' multi exponentiation"); - let commitW2 = await polynomials.L.multiExponentiation(PTau, "W2"); - proof.addPolynomial("W2", commitW2); - - return 0; - - async function computeL() { - if (logger) logger.info("··· Computing L polynomial"); - - const evalR0Y = polynomials.R0.evaluate(challenges.y); - const evalR1Y = polynomials.R1.evaluate(challenges.y); - const evalR2Y = polynomials.R2.evaluate(challenges.y); - - let mulL0 = Fr.sub(challenges.y, roots.S0.h0w8[0]); - for (let i = 1; i < 8; i++) { - mulL0 = Fr.mul(mulL0, Fr.sub(challenges.y, roots.S0.h0w8[i])); - } - - let mulL1 = Fr.sub(challenges.y, roots.S1.h1w4[0]); - for (let i = 1; i < 4; i++) { - mulL1 = Fr.mul(mulL1, Fr.sub(challenges.y, roots.S1.h1w4[i])); - } - - let mulL2 = Fr.sub(challenges.y, roots.S2.h2w3[0]); - for (let i = 1; i < 3; i++) { - mulL2 = Fr.mul(mulL2, Fr.sub(challenges.y, roots.S2.h2w3[i])); - } - for (let i = 0; i < 3; i++) { - mulL2 = Fr.mul(mulL2, Fr.sub(challenges.y, roots.S2.h3w3[i])); - } - - let preL0 = Fr.mul(mulL1, mulL2); - let preL1 = Fr.mul(challenges.alpha, Fr.mul(mulL0, mulL2)); - let preL2 = Fr.mul(Fr.square(challenges.alpha), Fr.mul(mulL0, mulL1)); - - toInverse["denH1"] = mulL1; - toInverse["denH2"] = mulL2; - - // COMPUTE L(X) - polynomials.L = Polynomial.fromPolynomial(polynomials.C0, curve, logger); - polynomials.L.subScalar(evalR0Y); - polynomials.L.mulScalar(preL0); - - let l2 = Polynomial.fromPolynomial(polynomials.C1, curve, logger); - l2.subScalar(evalR1Y); - l2.mulScalar(preL1); - - let l3 = Polynomial.fromPolynomial(polynomials.C2, curve, logger); - l3.subScalar(evalR2Y); - l3.mulScalar(preL2); - - polynomials.L.add(l2); - polynomials.L.add(l3); - - if (logger) logger.info("> Computing ZT polynomial"); - await computeZT(); - - const evalZTY = polynomials.ZT.evaluate(challenges.y); - polynomials.F.mulScalar(evalZTY); - polynomials.L.sub(polynomials.F); - - // Check degree - if (polynomials.L.degree() >= 9 * zkey.domainSize) { - throw new Error("L Polynomial is not well calculated"); - } - - delete buffers.L; - } - - async function computeZT() { - polynomials.ZT = Polynomial.zerofierPolynomial( - [ - roots.S0.h0w8[0], roots.S0.h0w8[1], roots.S0.h0w8[2], roots.S0.h0w8[3], - roots.S0.h0w8[4], roots.S0.h0w8[5], roots.S0.h0w8[6], roots.S0.h0w8[7], - roots.S1.h1w4[0], roots.S1.h1w4[1], roots.S1.h1w4[2], roots.S1.h1w4[3], - roots.S2.h2w3[0], roots.S2.h2w3[1], roots.S2.h2w3[2], - roots.S2.h3w3[0], roots.S2.h3w3[1], roots.S2.h3w3[2]], curve); - } - - async function computeZTS2() { - polynomials.ZTS2 = Polynomial.zerofierPolynomial( - [roots.S1.h1w4[0], roots.S1.h1w4[1], roots.S1.h1w4[2], roots.S1.h1w4[3], - roots.S2.h2w3[0], roots.S2.h2w3[1], roots.S2.h2w3[2], - roots.S2.h3w3[0], roots.S2.h3w3[1], roots.S2.h3w3[2]], curve); - } - } - - function getMontgomeryBatchedInverse() { - // · denominator needed in step 8 and 9 of the verifier to multiply by 1/Z_H(xi) - let xiN = challenges.xi; - for (let i = 0; i < zkey.power; i++) { - xiN = Fr.square(xiN); - } - toInverse["zh"] = Fr.sub(xiN, Fr.one); - - // · denominator needed in step 10 and 11 of the verifier - // toInverse.denH1 & toInverse.denH2 -> Computed in round5, computeL() - - // · denominator needed in the verifier when computing L_i^{S0}(X), L_i^{S1}(X) and L_i^{S2}(X) - computeLiS0(toInverse, roots.S0.h0w8, challenges.y, curve); - - computeLiS1(toInverse, roots.S1.h1w4, challenges.y, curve); - - computeLiS2(toInverse, roots.S2.h2w3, roots.S2.h3w3, challenges.y, challenges.xi, challenges.xiw, curve); - - // · L_i i=1 to num public inputs, needed in step 6 and 7 of the verifier to compute L_1(xi) and PI(xi) - const size = Math.max(1, zkey.nPublic); - - let w = Fr.one; - for (let i = 0; i < size; i++) { - toInverse["Li_" + (i + 1)] = Fr.mul(Fr.e(zkey.domainSize), Fr.sub(challenges.xi, w)); - w = Fr.mul(w, Fr.w[zkey.power]); - } - - let mulAccumulator = Fr.one; - for (const element of Object.values(toInverse)) { - if(Array.isArray(element)) { - for (const subElement of element) { - mulAccumulator = Fr.mul(mulAccumulator, subElement); - } - } else { - mulAccumulator = Fr.mul(mulAccumulator, element); - } - } - return Fr.inv(mulAccumulator); - - - function computeLiS0(toInverse, roots, x, curve) { - const Fr = curve.Fr; - const len = roots.length; - - const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); - - const Li = []; - for (let i = 0; i < len; i++) { - const den2 = roots[((len - 1) * i) % len]; - const den3 = Fr.sub(x, roots[i]); - - toInverse[["LiS0_" + (i + 1)]] = Fr.mul(Fr.mul(den1, den2), den3); - } - - return Li; - } - - function computeLiS1(toInverse, roots, x, curve) { - const Fr = curve.Fr; - const len = roots.length; - - const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); - - const Li = []; - for (let i = 0; i < len; i++) { - const den2 = roots[((len - 1) * i) % len]; - const den3 = Fr.sub(x, roots[i]); - - toInverse[["LiS1_" + (i + 1)]] = Fr.mul(Fr.mul(den1, den2), den3); - - } - - return Li; - } - - function computeLiS2(toInverse, S2, S2p, value, xi, xiw, curve) { - const Fr = curve.Fr; - - const Li = []; - - const _3h2 = Fr.mul(Fr.e(3), S2[0]); - const xisubxiw = Fr.sub(xi, xiw); - let den1 = Fr.mul(_3h2, xisubxiw); - for (let i = 0; i < 3; i++) { - const den2 = S2[2 * i % 3]; - const den3 = Fr.sub(value, S2[i]); - - toInverse[["LiS2_" + (i + 1)]] = Fr.mul(den1,Fr.mul(den2, den3)); - - } - - const _3h3 = Fr.mul(Fr.e(3), S2p[0]); - const xiwsubxi = Fr.sub(xiw, xi); - den1 = Fr.mul(_3h3, xiwsubxi); - for (let i = 0; i < 3; i++) { - const den2 = S2p[2 * i % 3]; - const den3 = Fr.sub(value, S2p[i]); - - toInverse[["LiS2_" + (i + 1 + 3)]] = Fr.mul(den1,Fr.mul(den2, den3)); - } - - return Li; - } - } -} - -/* - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ -const {unstringifyBigInts: unstringifyBigInts$2} = utils; - -async function fflonkFullProve(_input, wasmFilename, zkeyFilename, logger, wtnsCalcOptions, proverOptions) { - const input = unstringifyBigInts$2(_input); - - const wtns= {type: "mem"}; - - // Compute the witness - await wtnsCalculate(input, wasmFilename, wtns, wtnsCalcOptions); - - // Compute the proof - return await fflonkProve(zkeyFilename, wtns, logger, proverOptions); -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -const { unstringifyBigInts: unstringifyBigInts$1 } = utils; - -async function fflonkVerify(_vk_verifier, _publicSignals, _proof, logger) { - if (logger) logger.info("FFLONK VERIFIER STARTED"); - - _vk_verifier = unstringifyBigInts$1(_vk_verifier); - _proof = unstringifyBigInts$1(_proof); - - const curve = await getCurveFromName(_vk_verifier.curve); - - const vk = fromObjectVk(curve, _vk_verifier); - - // TODO ??? Compute wr^3 and check if it matches with w - - const proof = new Proof(curve, logger); - proof.fromObjectProof(_proof); - - const publicSignals = unstringifyBigInts$1(_publicSignals); - - if (publicSignals.length !== vk.nPublic) { - logger.error("Number of public signals does not match with vk"); - return false; - } - - const Fr = curve.Fr; - - if (logger) { - logger.info("----------------------------"); - logger.info(" FFLONK VERIFY SETTINGS"); - logger.info(` Curve: ${curve.name}`); - logger.info(` Circuit power: ${vk.power}`); - logger.info(` Domain size: ${2 ** vk.power}`); - logger.info(` Public vars: ${vk.nPublic}`); - logger.info("----------------------------"); - } - - // STEP 1 - Validate that all polynomial commitments ∈ G_1 - if (logger) logger.info("> Checking commitments belong to G1"); - if (!commitmentsBelongToG1(curve, proof, vk)) { - if (logger) logger.error("Proof commitments are not valid"); - return false; - } - - // STEP 2 - Validate that all evaluations ∈ F - if (logger) logger.info("> Checking evaluations belong to F"); - if (!evaluationsAreValid(curve, proof)) { - if (logger) logger.error("Proof evaluations are not valid."); - return false; - } - - // STEP 3 - Validate that w_i ∈ F for i ∈ [l] - if (logger) logger.info("> Checking public inputs belong to F"); - if (!publicInputsAreValid(curve, publicSignals)) { - if (logger) logger.error("Public inputs are not valid."); - return false; - } - - // STEP 4 - Compute the challenges: beta, gamma, xi, alpha and y ∈ F - // as in prover description, from the common preprocessed inputs, public inputs and elements of π_SNARK - if (logger) logger.info("> Computing challenges"); - const { challenges, roots } = computeChallenges(curve, proof, vk, publicSignals, logger); - - // STEP 5 - Compute the zero polynomial evaluation Z_H(xi) = xi^n - 1 - if (logger) logger.info("> Computing Zero polynomial evaluation Z_H(xi)"); - challenges.zh = Fr.sub(challenges.xiN, Fr.one); - challenges.invzh = Fr.inv(challenges.zh); - - // STEP 6 - Compute the lagrange polynomial evaluation L_1(xi) - if (logger) logger.info("> Computing Lagrange evaluations"); - const lagrangeEvals = await computeLagrangeEvaluations(curve, challenges, vk); - - // STEP 7 - Compute public input evaluation PI(xi) - if (logger) logger.info("> Computing polynomial identities PI(X)"); - const pi = calculatePI(curve, publicSignals, lagrangeEvals); - - // STEP 8 - Compute polynomial r0 ∈ F_{<4}[X] - if (logger) logger.info("> Computing r0(y)"); - const r0 = computeR0(proof, challenges, roots, curve, logger); - - // STEP 9 - Compute polynomial r1 ∈ F_{<4}[X] - if (logger) logger.info("> Computing r1(y)"); - const r1 = computeR1(proof, challenges, roots, pi, curve, logger); - - // STEP 9 - Compute polynomial r2 ∈ F_{<6}[X] - if (logger) logger.info("> Computing r2(y)"); - const r2 = computeR2(proof, challenges, roots, lagrangeEvals[1], vk, curve, logger); - - if (logger) logger.info("> Computing F"); - const F = computeF(curve, proof, vk, challenges, roots); - - if (logger) logger.info("> Computing E"); - const E = computeE(curve, proof, challenges, vk, r0, r1, r2); - - if (logger) logger.info("> Computing J"); - const J = computeJ(curve, proof, challenges); - - if (logger) logger.info("> Validate all evaluations with a pairing"); - const res = await isValidPairing(curve, proof, challenges, vk, F, E, J); - - if (logger) { - if (res) { - logger.info("PROOF VERIFIED SUCCESSFULLY"); - } else { - logger.warn("Invalid Proof"); - } - } - - if (logger) logger.info("FFLONK VERIFIER FINISHED"); - - return res; - -} - -function fromObjectVk(curve, vk) { - const res = vk; - res.k1 = curve.Fr.fromObject(vk.k1); - res.k2 = curve.Fr.fromObject(vk.k2); - res.w = curve.Fr.fromObject(vk.w); - // res.wW = curve.Fr.fromObject(vk.wW); - res.w3 = curve.Fr.fromObject(vk.w3); - res.w4 = curve.Fr.fromObject(vk.w4); - res.w8 = curve.Fr.fromObject(vk.w8); - res.wr = curve.Fr.fromObject(vk.wr); - res.X_2 = curve.G2.fromObject(vk.X_2); - res.C0 = curve.G1.fromObject(vk.C0); - return res; -} - -function commitmentsBelongToG1(curve, proof, vk) { - const G1 = curve.G1; - return G1.isValid(proof.polynomials.C1) - && G1.isValid(proof.polynomials.C2) - && G1.isValid(proof.polynomials.W1) - && G1.isValid(proof.polynomials.W2) - && G1.isValid(vk.C0); -} - -function checkValueBelongToField(curve, value) { - return Scalar.geq(value, 0) && Scalar.lt(value, curve.r); -} - -function checkEvaluationIsValid(curve, evaluation) { - return checkValueBelongToField(curve, Scalar.fromRprLE(evaluation)); -} - -function evaluationsAreValid(curve, proof) { - return checkEvaluationIsValid(curve, proof.evaluations.ql) - && checkEvaluationIsValid(curve, proof.evaluations.qr) - && checkEvaluationIsValid(curve, proof.evaluations.qm) - && checkEvaluationIsValid(curve, proof.evaluations.qo) - && checkEvaluationIsValid(curve, proof.evaluations.qc) - && checkEvaluationIsValid(curve, proof.evaluations.s1) - && checkEvaluationIsValid(curve, proof.evaluations.s2) - && checkEvaluationIsValid(curve, proof.evaluations.s3) - && checkEvaluationIsValid(curve, proof.evaluations.a) - && checkEvaluationIsValid(curve, proof.evaluations.b) - && checkEvaluationIsValid(curve, proof.evaluations.c) - && checkEvaluationIsValid(curve, proof.evaluations.z) - && checkEvaluationIsValid(curve, proof.evaluations.zw) - && checkEvaluationIsValid(curve, proof.evaluations.t1w) - && checkEvaluationIsValid(curve, proof.evaluations.t2w); -} - -function publicInputsAreValid(curve, publicInputs) { - for(let i = 0; i < publicInputs.length; i++) { - if(!checkValueBelongToField(curve, publicInputs[i])) { - return false; - } - } - return true; -} - -function computeChallenges(curve, proof, vk, publicSignals, logger) { - const Fr = curve.Fr; - - const challenges = {}; - const roots = {}; - const transcript = new Keccak256Transcript(curve); - - // Add C0 to the transcript - transcript.addPolCommitment(vk.C0); - - for (let i = 0; i < publicSignals.length; i++) { - transcript.addScalar(Fr.e(publicSignals[i])); - } - - transcript.addPolCommitment(proof.polynomials.C1); - challenges.beta = transcript.getChallenge(); - transcript.reset(); - - transcript.addScalar(challenges.beta); - challenges.gamma = transcript.getChallenge(); - - transcript.reset(); - transcript.addScalar(challenges.gamma); - transcript.addPolCommitment(proof.polynomials.C2); - const xiSeed = transcript.getChallenge(); - const xiSeed2 = Fr.square(xiSeed); - - let w8 = []; - w8[1] = vk.w8; - w8[2] = Fr.square(vk.w8); - w8[3] = Fr.mul(w8[2], vk.w8); - w8[4] = Fr.mul(w8[3], vk.w8); - w8[5] = Fr.mul(w8[4], vk.w8); - w8[6] = Fr.mul(w8[5], vk.w8); - w8[7] = Fr.mul(w8[6], vk.w8); - let w4 = []; - w4[1] = vk.w4; - w4[2] = Fr.square(vk.w4); - w4[3] = Fr.mul(w4[2], vk.w4); - let w3 = []; - w3[1] = vk.w3; - w3[2] = Fr.square(vk.w3); - - // const w4_2 = Fr.square(vk.w4); - // const w4_3 = Fr.mul(w4_2, vk.w4); - // const w3_2 = Fr.square(vk.w3); - - // Compute h0 = xiSeeder^3 - roots.S0 = {}; - roots.S0.h0w8 = []; - roots.S0.h0w8[0] = Fr.mul(xiSeed2, xiSeed); - for (let i = 1; i < 8; i++) { - roots.S0.h0w8[i] = Fr.mul(roots.S0.h0w8[0], w8[i]); - } - - // Compute h1 = xi_seeder^6 - roots.S1 = {}; - roots.S1.h1w4 = []; - roots.S1.h1w4[0] = Fr.square(roots.S0.h0w8[0]); - for (let i = 1; i < 4; i++) { - roots.S1.h1w4[i] = Fr.mul(roots.S1.h1w4[0], w4[i]); - } - - // Compute h2 = xi_seeder^8 - roots.S2 = {}; - roots.S2.h2w3 = []; - roots.S2.h2w3[0] = Fr.mul(roots.S1.h1w4[0], xiSeed2); - roots.S2.h2w3[1] = Fr.mul(roots.S2.h2w3[0], w3[1]); - roots.S2.h2w3[2] = Fr.mul(roots.S2.h2w3[0], w3[2]); - - roots.S2.h3w3 = []; - // Multiply h3 by third-root-omega to obtain h_3^3 = xiω - // So, h3 = xi_seeder^8 ω^{1/3} - roots.S2.h3w3[0] = Fr.mul(roots.S2.h2w3[0], vk.wr); - roots.S2.h3w3[1] = Fr.mul(roots.S2.h3w3[0], w3[1]); - roots.S2.h3w3[2] = Fr.mul(roots.S2.h3w3[0], w3[2]); - - // Compute xi = xi_seeder^12 - challenges.xi = Fr.mul(Fr.square(roots.S2.h2w3[0]), roots.S2.h2w3[0]); - challenges.xiw = Fr.mul(challenges.xi, Fr.w[vk.power]); - - challenges.xiN = challenges.xi; - vk.domainSize = 1; - for (let i = 0; i < vk.power; i++) { - challenges.xiN = Fr.square(challenges.xiN); - vk.domainSize *= 2; - } - - transcript.reset(); - transcript.addScalar(xiSeed); - transcript.addScalar(proof.evaluations.ql); - transcript.addScalar(proof.evaluations.qr); - transcript.addScalar(proof.evaluations.qm); - transcript.addScalar(proof.evaluations.qo); - transcript.addScalar(proof.evaluations.qc); - transcript.addScalar(proof.evaluations.s1); - transcript.addScalar(proof.evaluations.s2); - transcript.addScalar(proof.evaluations.s3); - transcript.addScalar(proof.evaluations.a); - transcript.addScalar(proof.evaluations.b); - transcript.addScalar(proof.evaluations.c); - transcript.addScalar(proof.evaluations.z); - transcript.addScalar(proof.evaluations.zw); - transcript.addScalar(proof.evaluations.t1w); - transcript.addScalar(proof.evaluations.t2w); - challenges.alpha = transcript.getChallenge(); - - transcript.reset(); - transcript.addScalar(challenges.alpha); - transcript.addPolCommitment(proof.polynomials.W1); - challenges.y = transcript.getChallenge(); - - if (logger) { - logger.info("··· challenges.beta: " + Fr.toString(challenges.beta)); - logger.info("··· challenges.gamma: " + Fr.toString(challenges.gamma)); - logger.info("··· challenges.xi: " + Fr.toString(challenges.xi)); - logger.info("··· challenges.alpha: " + Fr.toString(challenges.alpha)); - logger.info("··· challenges.y: " + Fr.toString(challenges.y)); - } - - return { challenges: challenges, roots: roots }; -} - -async function computeLagrangeEvaluations(curve, challenges, vk) { - const Fr = curve.Fr; - - const size = Math.max(1, vk.nPublic); - const numArr = new BigBuffer(size * Fr.n8); - let denArr = new BigBuffer(size * Fr.n8); - - let w = Fr.one; - for (let i = 0; i < size; i++) { - const i_sFr = i * Fr.n8; - numArr.set(Fr.mul(w, challenges.zh), i_sFr); - denArr.set(Fr.mul(Fr.e(vk.domainSize), Fr.sub(challenges.xi, w)), i_sFr); - w = Fr.mul(w, vk.w); - } - - denArr = await Fr.batchInverse(denArr); - - let L = []; - for (let i = 0; i < size; i++) { - const i_sFr = i * Fr.n8; - L[i + 1] = Fr.mul(numArr.slice(i_sFr, i_sFr + Fr.n8), denArr.slice(i_sFr, i_sFr + Fr.n8)); - } - return L; -} - -function calculatePI(curve, publicSignals, lagrangeEvals) { - const Fr = curve.Fr; - - let pi = Fr.zero; - for (let i = 0; i < publicSignals.length; i++) { - const w = Fr.e(publicSignals[i]); - pi = Fr.sub(pi, Fr.mul(w, lagrangeEvals[i + 1])); - } - return pi; -} - -function computeR0(proof, challenges, roots, curve, logger) { - const Fr = curve.Fr; - - const Li = computeLagrangeLiSi(roots.S0.h0w8, challenges.y, challenges.xi, curve); - - // r0(y) = ∑_1^8 C_0(h_0 ω_8^{i-1}) L_i(y). To this end we need to compute - - // Compute the 8 C0 values - if (logger) logger.info("··· Computing r0(y)"); - - let res = Fr.zero; - for (let i = 0; i < 8; i++) { - let coefValues = []; - coefValues[1] = roots.S0.h0w8[i]; - for (let j = 2; j < 8; j++) { - coefValues[j] = Fr.mul(coefValues[j - 1], roots.S0.h0w8[i]); - } - - let c0 = Fr.add(proof.evaluations.ql, Fr.mul(proof.evaluations.qr, coefValues[1])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.qo, coefValues[2])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.qm, coefValues[3])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.qc, coefValues[4])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.s1, coefValues[5])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.s2, coefValues[6])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.s3, coefValues[7])); - - res = Fr.add(res, Fr.mul(c0, Li[i])); - } - - return res; -} - -function computeR1(proof, challenges, roots, pi, curve, logger) { - const Fr = curve.Fr; - - const Li = computeLagrangeLiSi(roots.S1.h1w4, challenges.y, challenges.xi, curve); - - // r1(y) = ∑_1^4 C_1(h_1 ω_4^{i-1}) L_i(y). To this end we need to compute - // Z1 = {C1(h_1}, C1(h_1 ω_4), C1(h_1 ω_4^2), C1(h_1 ω_4^3)} - // where C_1(h_1 ω_4^{i-1}) = eval.a + h_1 ω_4^i eval.b + (h_1 ω_4^i)^2 eval.c + (h_1 ω_4^i)^3 T0(xi), - // where T0(xi) = [ qL·a + qR·b + qM·a·b + qO·c + qC + PI(xi) ] / Z_H(xi) - - // Compute T0(xi) - if (logger) logger.info("··· Computing T0(xi)"); - let t0 = Fr.mul(proof.evaluations.ql, proof.evaluations.a); - t0 = Fr.add(t0, Fr.mul(proof.evaluations.qr, proof.evaluations.b)); - t0 = Fr.add(t0, Fr.mul(proof.evaluations.qm, Fr.mul(proof.evaluations.a, proof.evaluations.b))); - t0 = Fr.add(t0, Fr.mul(proof.evaluations.qo, proof.evaluations.c)); - t0 = Fr.add(t0, proof.evaluations.qc); - t0 = Fr.add(t0, pi); - t0 = Fr.mul(t0, challenges.invzh); - - // Compute the 4 C1 values - if (logger) logger.info("··· Computing C1(h_1ω_4^i) values"); - - let res = Fr.zero; - for (let i = 0; i < 4; i++) { - let c1 = proof.evaluations.a; - c1 = Fr.add(c1, Fr.mul(roots.S1.h1w4[i], proof.evaluations.b)); - const h1w4Squared = Fr.square(roots.S1.h1w4[i]); - c1 = Fr.add(c1, Fr.mul(h1w4Squared, proof.evaluations.c)); - c1 = Fr.add(c1, Fr.mul(Fr.mul(h1w4Squared, roots.S1.h1w4[i]), t0)); - - res = Fr.add(res, Fr.mul(c1, Li[i])); - } - - return res; -} - -function computeR2(proof, challenges, roots, lagrange1, vk, curve, logger) { - const Fr = curve.Fr; - - const LiS2 = computeLagrangeLiS2([roots.S2.h2w3, roots.S2.h3w3], challenges.y, challenges.xi, challenges.xiw, curve); - - // r2(y) = ∑_1^3 C_2(h_2 ω_3^{i-1}) L_i(y) + ∑_1^3 C_2(h_3 ω_3^{i-1}) L_{i+3}(y). To this end we need to compute - // Z2 = {[C2(h_2}, C2(h_2 ω_3), C2(h_2 ω_3^2)], [C2(h_3}, C2(h_3 ω_3), C2(h_3 ω_3^2)]} - // where C_2(h_2 ω_3^{i-1}) = eval.z + h_2 ω_2^i T1(xi) + (h_2 ω_3^i)^2 T2(xi), - // where C_2(h_3 ω_3^{i-1}) = eval.z + h_3 ω_2^i T1(xi) + (h_3 ω_3^i)^2 T2(xi), - // where T1(xi) = [ L_1(xi)(z-1)] / Z_H(xi) - // and T2(xi) = [ (a + beta·xi + gamma)(b + beta·xi·k1 + gamma)(c + beta·xi·k2 + gamma)z - // - (a + beta·sigma1 + gamma)(b + beta·sigma2 + gamma)(c + beta·sigma3 + gamma)zω ] / Z_H(xi) - - // Compute T1(xi) - if (logger) logger.info("··· Computing T1(xi)"); - let t1 = Fr.sub(proof.evaluations.z, Fr.one); - t1 = Fr.mul(t1, lagrange1); - t1 = Fr.mul(t1, challenges.invzh); - - // Compute T2(xi) - if (logger) logger.info("··· Computing T2(xi)"); - const betaxi = Fr.mul(challenges.beta, challenges.xi); - const t211 = Fr.add(proof.evaluations.a, Fr.add(betaxi, challenges.gamma)); - const t212 = Fr.add(proof.evaluations.b, Fr.add(Fr.mul(betaxi, vk.k1), challenges.gamma)); - const t213 = Fr.add(proof.evaluations.c, Fr.add(Fr.mul(betaxi, vk.k2), challenges.gamma)); - const t21 = Fr.mul(t211, Fr.mul(t212, Fr.mul(t213, proof.evaluations.z))); - - const t221 = Fr.add(proof.evaluations.a, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s1), challenges.gamma)); - const t222 = Fr.add(proof.evaluations.b, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s2), challenges.gamma)); - const t223 = Fr.add(proof.evaluations.c, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s3), challenges.gamma)); - const t22 = Fr.mul(t221, Fr.mul(t222, Fr.mul(t223, proof.evaluations.zw))); - - let t2 = Fr.sub(t21, t22); - t2 = Fr.mul(t2, challenges.invzh); - - // Compute the 6 C2 values - if (logger) logger.info("··· Computing C2(h_2ω_3^i) values"); - let res = Fr.zero; - for (let i = 0; i < 3; i++) { - let c2 = Fr.add(proof.evaluations.z, Fr.mul(roots.S2.h2w3[i], t1)); - c2 = Fr.add(c2, Fr.mul(Fr.square(roots.S2.h2w3[i]), t2)); - - res = Fr.add(res, Fr.mul(c2, LiS2[i])); - } - - if (logger) logger.info("··· Computing C2(h_3ω_3^i) values"); - for (let i = 0; i < 3; i++) { - let c2 = Fr.add(proof.evaluations.zw, Fr.mul(roots.S2.h3w3[i], proof.evaluations.t1w)); - c2 = Fr.add(c2, Fr.mul(Fr.square(roots.S2.h3w3[i]), proof.evaluations.t2w)); - - res = Fr.add(res, Fr.mul(c2, LiS2[i + 3])); - } - - return res; -} - -function computeF(curve, proof, vk, challenges, roots) { - const G1 = curve.G1; - const Fr = curve.Fr; - - let mulH0 = Fr.sub(challenges.y, roots.S0.h0w8[0]); - for (let i = 1; i < 8; i++) { - mulH0 = Fr.mul(mulH0, Fr.sub(challenges.y, roots.S0.h0w8[i])); - } - - challenges.temp = mulH0; - - let mulH1 = Fr.sub(challenges.y, roots.S1.h1w4[0]); - for (let i = 1; i < 4; i++) { - mulH1 = Fr.mul(mulH1, Fr.sub(challenges.y, roots.S1.h1w4[i])); - } - - let mulH2 = Fr.sub(challenges.y, roots.S2.h2w3[0]); - for (let i = 1; i < 3; i++) { - mulH2 = Fr.mul(mulH2, Fr.sub(challenges.y, roots.S2.h2w3[i])); - } - for (let i = 0; i < 3; i++) { - mulH2 = Fr.mul(mulH2, Fr.sub(challenges.y, roots.S2.h3w3[i])); - } - - challenges.quotient1 = Fr.mul(challenges.alpha, Fr.div(mulH0, mulH1)); - challenges.quotient2 = Fr.mul(Fr.square(challenges.alpha), Fr.div(mulH0, mulH2)); - - let F2 = G1.timesFr(proof.polynomials.C1, challenges.quotient1); - let F3 = G1.timesFr(proof.polynomials.C2, challenges.quotient2); - - return G1.add(vk.C0, G1.add(F2, F3)); -} - -function computeE(curve, proof, challenges, vk, r0, r1, r2) { - const G1 = curve.G1; - const Fr = curve.Fr; - - let E2 = Fr.mul(r1, challenges.quotient1); - let E3 = Fr.mul(r2, challenges.quotient2); - - return G1.timesFr(G1.one, Fr.add(r0, Fr.add(E2, E3))); -} - -function computeJ(curve, proof, challenges) { - const G1 = curve.G1; - - return G1.timesFr(proof.polynomials.W1, challenges.temp); -} - -async function isValidPairing(curve, proof, challenges, vk, F, E, J) { - const G1 = curve.G1; - - let A1 = G1.timesFr(proof.polynomials.W2, challenges.y); - A1 = G1.add(G1.sub(G1.sub(F, E), J), A1); - const A2 = curve.G2.one; - - const B1 = proof.polynomials.W2; - const B2 = vk.X_2; - - return await curve.pairingEq(G1.neg(A1), A2, B1, B2); -} - - -function computeLagrangeLiSi(roots, x, xi, curve) { - const Fr = curve.Fr; - const len = roots.length; - - const num = Fr.sub(Fr.exp(x, len), xi); - const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); - - const Li = []; - for (let i = 0; i < len; i++) { - const den2 = roots[((len - 1) * i) % len]; - const den3 = Fr.sub(x, roots[i]); - - Li[i] = Fr.div(num, Fr.mul(Fr.mul(den1, den2), den3)); - } - - return Li; -} - -function computeLagrangeLiS2(roots, value, xi0, xi1, curve) { - const Fr = curve.Fr; - - const Li = []; - - const len = roots[0].length; - const n = len * roots.length; - - const num1 = Fr.exp(value, n); - const num2 = Fr.mul(Fr.add(xi0, xi1), Fr.exp(value, len)); - const num3 = Fr.mul(xi0, xi1); - const num = Fr.add(Fr.sub(num1, num2), num3); - - let den1 = Fr.mul(Fr.mul(Fr.e(len), roots[0][0]), Fr.sub(xi0, xi1)); - for (let i = 0; i < len; i++) { - const den2 = roots[0][(len - 1) * i % len]; - const den3 = Fr.sub(value, roots[0][i]); - - const den = Fr.mul(den1,Fr.mul(den2, den3)); - - Li[i] = Fr.div(num, den); - } - - den1 = Fr.mul(Fr.mul(Fr.e(len), roots[1][0]), Fr.sub(xi1, xi0)); - for (let i = 0; i < len; i++) { - const den2 = roots[1][(len - 1) * i % len]; - const den3 = Fr.sub(value, roots[1][i]); - - const den = Fr.mul(den1,Fr.mul(den2, den3)); - - Li[i + len] = Fr.div(num, den); - } - - return Li; -} - -/* - Copyright 2021 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -const {unstringifyBigInts} = utils; - -function p256(n) { - let nstr = n.toString(16); - while (nstr.length < 64) nstr = "0" + nstr; - nstr = `0x${nstr}`; - return nstr; -} - -async function fflonkExportCallData(_pub, _proof) { - const proof = unstringifyBigInts(_proof); - const pub = unstringifyBigInts(_pub); - - await getCurveFromName(proof.curve); - - let inputs = ""; - for (let i = 0; i < pub.length; i++) { - if (inputs !== "") inputs = inputs + ","; - inputs = inputs + p256(pub[i]); - } - - return `[${p256(proof.polynomials.C1[0])}, ${p256(proof.polynomials.C1[1])},` + - `${p256(proof.polynomials.C2[0])},${p256(proof.polynomials.C2[1])},` + - `${p256(proof.polynomials.W1[0])},${p256(proof.polynomials.W1[1])},` + - `${p256(proof.polynomials.W2[0])},${p256(proof.polynomials.W2[1])},` + - `${p256(proof.evaluations.ql)},${p256(proof.evaluations.qr)},${p256(proof.evaluations.qm)},` + - `${p256(proof.evaluations.qo)},${p256(proof.evaluations.qc)},${p256(proof.evaluations.s1)},` + - `${p256(proof.evaluations.s2)},${p256(proof.evaluations.s3)},${p256(proof.evaluations.a)},` + - `${p256(proof.evaluations.b)},${p256(proof.evaluations.c)},${p256(proof.evaluations.z)},` + - `${p256(proof.evaluations.zw)},${p256(proof.evaluations.t1w)},${p256(proof.evaluations.t2w)},` + - `${p256(proof.evaluations.inv)}],` + - `[${inputs}]`; -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -var fflonk = /*#__PURE__*/Object.freeze({ - __proto__: null, - setup: fflonkSetup, - prove: fflonkProve, - fullProve: fflonkFullProve, - verify: fflonkVerify, - exportSolidityVerifier: fflonkExportSolidityVerifier, - exportSolidityCallData: fflonkExportCallData -}); - -var _virtual_ejs = {}; - -var _virtual_ejs$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - 'default': _virtual_ejs +//#endregion +//#region src/fflonk_setup.js +async function mi(i, c, l, d) { + d && d.info("FFLONK SETUP STARTED"), globalThis.gc && globalThis.gc(), d && d.info("> Reading PTau file"); + let { fd: f, sections: p } = await r(c, "ptau", 1, 1 << 22, 1 << 24); + if (!p[12]) throw Error("Powers of Tau is not well prepared. Section 12 missing."); + d && d.info("> Getting curve from PTau settings"); + let { curve: m } = await rn(f, p); + d && d.info("> Reading r1cs file"); + let { fd: g, sections: _ } = await r(i, "r1cs", 1, 1 << 22, 1 << 24), v = await h(g, _, { + loadConstraints: !1, + loadCustomGates: !0 + }); + if (v.prime !== m.r) throw Error("r1cs curve does not match powers of tau ceremony curve"); + let y = m.Fr, b = m.Fr.n8, x = m.G1.F.n8 * 2, S = m.G2.F.n8 * 2, C = {}, w = {}, T, E = { + nVars: v.nVars, + nPublic: v.nOutputs + v.nPubInputs + }, D = new Kn(), O = new Kn(); + if (d && d.info("> Processing FFlonk constraints"), await F(m.Fr, v, d), globalThis.gc && globalThis.gc(), E.cirPower = Math.max(3, Se(D.length + 2 - 1) + 1), E.domainSize = 2 ** E.cirPower, p[2][0].size < (E.domainSize * 9 + 18) * x) throw Error("Powers of Tau is not big enough for this circuit size. Section 2 too small."); + if (p[3][0].size < S) throw Error("Powers of Tau is not well prepared. Section 3 too small."); + d && (d.info("----------------------------"), d.info(" FFLONK SETUP SETTINGS"), d.info(` Curve: ${m.name}`), d.info(` Circuit power: ${E.cirPower}`), d.info(` Domain size: ${E.domainSize}`), d.info(` Vars: ${E.nVars}`), d.info(` Public vars: ${E.nPublic}`), d.info(` Constraints: ${D.length}`), d.info(` Additions: ${O.length}`), d.info("----------------------------")), d && d.info("> computing k1 and k2"); + let [k, A] = re(); + d && d.info("> computing w3"); + let j = ie(); + d && d.info("> computing w4"); + let M = ae(); + d && d.info("> computing w8"); + let N = oe(); + d && d.info("> computing wr"); + let P = se(E.cirPower, m.Fr); + return await I(), await g.close(), await f.close(), d && d.info("FFLONK SETUP FINISHED"), 0; + async function F(t, n, r) { + for (let e = 0; e < E.nPublic; e++) D.push(oi(e + 1, t)); + let i = new fi(t, oi, si, ci, r), a = await e.readSection(g, _, 2), o = 0; + for (let e = 0; e < n.nConstraints; e++) { + r && e !== 0 && e % 5e5 == 0 && r.info(` processing r1cs constraints ${e}/${n.nConstraints}`); + let [t, a] = i.processR1csConstraint(E, ...s()); + D.push(...t), O.push(...a); + } + function s() { + let e = []; + return e[0] = c(), e[1] = c(), e[2] = c(), e; + } + function c() { + let e = {}, t = a.slice(o, o + 4); + o += 4; + let r = new DataView(t.buffer).getUint32(0, !0), i = a.slice(o, o + (4 + n.n8) * r); + o += (4 + n.n8) * r; + let s = new DataView(i.buffer); + for (let t = 0; t < r; t++) { + let r = s.getUint32(t * (4 + n.n8), !0); + e[r] = n.F.fromRprLE(i, t * (4 + n.n8) + 4); + } + return e; + } + return 0; + } + async function I() { + d && d.info("> Writing the zkey file"); + let e = await t(l, "zkey", 1, 17, 1 << 22, 1 << 24); + d && d.info("··· Writing Section 1. Zkey Header"), await L(e), d && d.info("··· Writing Section 3. Additions"), await ee(e), globalThis.gc && globalThis.gc(), d && d.info("··· Writing Section 4. A Map"), await R(e, 4, 0, "A map"), globalThis.gc && globalThis.gc(), d && d.info("··· Writing Section 5. B Map"), await R(e, 5, 1, "B map"), globalThis.gc && globalThis.gc(), d && d.info("··· Writing Section 6. C Map"), await R(e, 6, 2, "C map"), globalThis.gc && globalThis.gc(), d && d.info("··· Writing Section 7. QL"), await z(e, 7, 3, "QL"), globalThis.gc && globalThis.gc(), d && d.info("··· Writing Section 8. QR"), await z(e, 8, 4, "QR"), globalThis.gc && globalThis.gc(), d && d.info("··· Writing Section 9. QM"), await z(e, 9, 5, "QM"), globalThis.gc && globalThis.gc(), d && d.info("··· Writing Section 10. QO"), await z(e, 10, 6, "QO"), globalThis.gc && globalThis.gc(), d && d.info("··· Writing Section 11. QC"), await z(e, 11, 7, "QC"), globalThis.gc && globalThis.gc(), d && d.info("··· Writing Sections 12,13,14. Sigma1, Sigma2 & Sigma 3"), await B(e), globalThis.gc && globalThis.gc(), d && d.info("··· Writing Section 15. Lagrange Polynomials"), await V(e), globalThis.gc && globalThis.gc(), d && d.info("··· Writing Section 16. Powers of Tau"), await te(e), globalThis.gc && globalThis.gc(), d && d.info("··· Writing Section 17. C0"), await H(e), globalThis.gc && globalThis.gc(), d && d.info("··· Writing Section 2. FFlonk Header"), await U(e), globalThis.gc && globalThis.gc(), d && d.info("> Writing the zkey file finished"), await e.close(); + } + async function L(e) { + await a(e, 1), await e.writeULE32(10), await n(e); + } + async function ee(e) { + await a(e, 3); + let t = new Uint8Array(8 + 2 * b), r = new DataView(t.buffer); + for (let n = 0; n < O.length; n++) { + d && n !== 0 && n % 5e5 == 0 && d.info(` writing Additions: ${n}/${O.length}`); + let i = O[n]; + r.setUint32(0, i[0], !0), r.setUint32(4, i[1], !0), t.set(i[2], 8), t.set(i[3], 8 + b), await e.write(t); + } + await n(e); + } + async function R(e, t, r, i) { + await a(e, t); + for (let t = 0; t < D.length; t++) d && t !== 0 && t % 5e5 == 0 && d.info(` writing witness ${i}: ${t}/${D.length}`), await e.writeULE32(D[t][r]); + await n(e); + } + async function z(e, t, r, i) { + let o = new s(E.domainSize * b); + for (let e = 0; e < D.length; e++) o.set(D[e][r], e * b), d && e !== 0 && e % 5e5 == 0 && d.info(` writing ${i}: ${e}/${D.length}`); + C[i] = await X.fromEvaluations(o, m, d), w[i] = await Z.fromPolynomial(C[i], 4, m, d), await a(e, t), await e.write(C[i].coef), await e.write(w[i].eval), await n(e); + } + async function B(e) { + let t = new s(b * E.domainSize * 3), r = new Kn(E.nVars), i = new Kn(E.nVars), o = y.one; + for (let e = 0; e < E.domainSize; e++) e < D.length ? (c(D[e][0], e), c(D[e][1], E.domainSize + e), c(D[e][2], E.domainSize * 2 + e)) : e < E.domainSize - 2 ? (c(0, e), c(0, E.domainSize + e), c(0, E.domainSize * 2 + e)) : (t.set(o, e * b), t.set(y.mul(o, k), (E.domainSize + e) * b), t.set(y.mul(o, A), (E.domainSize * 2 + e) * b)), o = y.mul(o, y.w[E.cirPower]), d && e !== 0 && e % 5e5 == 0 && d.info(` writing sigma phase1: ${e}/${D.length}`); + for (let e = 0; e < E.nVars; e++) i[e] === void 0 ? console.log("Variable not used") : t.set(r[e], i[e] * b), d && e !== 0 && e % 5e5 == 0 && d.info(` writing sigma phase2: ${e}/${E.nVars}`); + globalThis.gc && globalThis.gc(); + for (let r = 0; r < 3; r++) { + let i = r === 0 ? 12 : r === 1 ? 13 : 14, o = "S" + (r + 1); + C[o] = await X.fromEvaluations(t.slice(E.domainSize * b * r, E.domainSize * b * (r + 1)), m, d), w[o] = await Z.fromPolynomial(C[o], 4, m, d), await a(e, i), await e.write(C[o].coef), await e.write(w[o].eval), await n(e), globalThis.gc && globalThis.gc(); + } + return 0; + function c(e, n) { + r[e] === void 0 ? i[e] = n : t.set(r[e], n * b); + let a; + a = n < E.domainSize ? o : n < 2 * E.domainSize ? y.mul(o, k) : y.mul(o, A), r[e] = a; + } + } + async function V(e) { + await a(e, 15); + let t = Math.max(E.nPublic, 1); + for (let n = 0; n < t; n++) { + let t = new s(E.domainSize * b); + t.set(y.one, n * b), await ne(e, t); + } + await n(e); + } + async function te(e) { + await a(e, 16), T = new s((E.domainSize * 9 + 18) * x), await f.readToBuffer(T, 0, (E.domainSize * 9 + 18) * x, p[2][0].p), await e.write(T), await n(e); + } + async function H(e) { + let t = new pi(8, m, d); + if (t.addPolynomial(0, C.QL), t.addPolynomial(1, C.QR), t.addPolynomial(2, C.QO), t.addPolynomial(3, C.QM), t.addPolynomial(4, C.QC), t.addPolynomial(5, C.S1), t.addPolynomial(6, C.S2), t.addPolynomial(7, C.S3), C.C0 = t.getPolynomial(), C.C0.degree() >= 8 * E.domainSize) throw Error("C0 Polynomial is not well calculated"); + await a(e, 17), await e.write(C.C0.coef), await n(e); + } + async function U(e) { + await a(e, 2); + let t = m.q, r = (Math.floor((u.bitLength(t) - 1) / 64) + 1) * 8; + await e.writeULE32(r), await o(e, t, r); + let i = m.r, s = (Math.floor((u.bitLength(i) - 1) / 64) + 1) * 8; + await e.writeULE32(s), await o(e, i, s), await e.writeULE32(E.nVars), await e.writeULE32(E.nPublic), await e.writeULE32(E.domainSize), await e.writeULE32(O.length), await e.writeULE32(D.length), await e.write(k), await e.write(A), await e.write(j), await e.write(M), await e.write(N), await e.write(P); + let c; + c = await f.read(S, p[3][0].p + S), await e.write(c); + let l = await C.C0.multiExponentiation(T, "C0"); + await e.write(l), await n(e); + } + async function ne(e, t) { + let [n, r] = await X.to4T(t, E.domainSize, [], y); + return await e.write(n), await e.write(r), [n, r]; + } + function re() { + let e = y.two; + for (; n(e, [], E.cirPower);) y.add(e, y.one); + let t = y.add(e, y.one); + for (; n(t, [e], E.cirPower);) y.add(t, y.one); + return [e, t]; + function n(e, t, n) { + let r = 2 ** n, i = y.one; + for (let a = 0; a < r; a++) { + if (y.eq(e, i)) return !0; + for (let n = 0; n < t.length; n++) if (y.eq(e, y.mul(t[n], i))) return !0; + i = y.mul(i, y.w[n]); + } + return !1; + } + } + function ie() { + let e = y.e(31624), t = u.div(3648040478639879203707734290876212514758060733402672390616367364429301415936n, u.e(3)); + return y.exp(e, t); + } + function ae() { + return y.w[2]; + } + function oe() { + return y.w[3]; + } + function se(e, t) { + let n = t.e(467799165886069610036046866799264026481344299079011762026774533774345988080n); + return t.exp(n, 2 ** (28 - e)); + } +} +//#endregion +//#region src/fflonk_prove.js +var { stringifyBigInts: hi } = p; +async function gi(t, n, r, i) { + r && r.info("FFLONK PROVER STARTED"), r && r.info("> Reading witness file"); + let { fd: a, sections: o } = await e.readBinFile(n, "wtns", 2, 1 << 25, 1 << 23), c = await tt(a, o); + r && r.info("> Reading zkey file"); + let { fd: l, sections: d } = await e.readBinFile(t, "zkey", 2, 1 << 25, 1 << 23), f = await Ve(l, d, void 0, i); + if (f.protocolId !== 10) throw Error("zkey file is not fflonk"); + if (!u.eq(f.r, c.q)) throw Error("Curve of the witness does not match the curve of the proving key"); + if (c.nWitness !== f.nVars - f.nAdditions) throw Error(`Invalid witness length. Circuit: ${f.nVars}, witness: ${c.nWitness}, ${f.nAdditions}`); + let p = f.curve, m = p.Fr, h = p.Fr.n8, g = p.G1.F.n8 * 2, _ = f.domainSize * h; + r && (r.info("----------------------------"), r.info(" FFLONK PROVE SETTINGS"), r.info(` Curve: ${p.name}`), r.info(` Circuit power: ${f.power}`), r.info(` Domain size: ${f.domainSize}`), r.info(` Vars: ${f.nVars}`), r.info(` Public vars: ${f.nPublic}`), r.info(` Constraints: ${f.nConstraints}`), r.info(` Additions: ${f.nAdditions}`), r.info("----------------------------")), r && r.info("> Reading witness file data"); + let v = await e.readSection(a, o, 2); + await a.close(), v.set(m.zero, 0); + let y = new s(f.nAdditions * h), b = {}, x = {}, S = {}, C = {}, w = {}, T = {}, E = new mr(p, r); + r && r.info("> Reading Section 3. Additions"), await A(), r && r.info("> Reading Sections 12,13,14. Sigma1, Sigma2 & Sigma 3"), r && r.info("··· Reading Sigma polynomials "), x.Sigma1 = new X(new s(_), p, r), x.Sigma2 = new X(new s(_), p, r), x.Sigma3 = new X(new s(_), p, r), await l.readToBuffer(x.Sigma1.coef, 0, _, d[12][0].p), await l.readToBuffer(x.Sigma2.coef, 0, _, d[13][0].p), await l.readToBuffer(x.Sigma3.coef, 0, _, d[14][0].p), r && r.info("··· Reading Sigma evaluations"), S.Sigma1 = new Z(new s(_ * 4), p, r), S.Sigma2 = new Z(new s(_ * 4), p, r), S.Sigma3 = new Z(new s(_ * 4), p, r), await l.readToBuffer(S.Sigma1.eval, 0, _ * 4, d[12][0].p + _), await l.readToBuffer(S.Sigma2.eval, 0, _ * 4, d[13][0].p + _), await l.readToBuffer(S.Sigma3.eval, 0, _ * 4, d[14][0].p + _), r && r.info("> Reading Section 16. Powers of Tau"); + let D = new s(f.domainSize * 16 * g); + await l.readToBuffer(D, 0, (f.domainSize * 9 + 18) * g, d[16][0].p), globalThis.gc && globalThis.gc(), r && r.info(""), r && r.info("> ROUND 1"), await N(), delete x.T0, delete S.QL, delete S.QR, delete S.QM, delete S.QO, delete S.QC, globalThis.gc && globalThis.gc(), r && r.info("> ROUND 2"), await P(), delete b.A, delete b.B, delete b.C, delete S.A, delete S.B, delete S.C, delete S.Sigma1, delete S.Sigma2, delete S.Sigma3, delete S.lagrange1, delete S.Z, globalThis.gc && globalThis.gc(), r && r.info("> ROUND 3"), await F(), delete x.A, delete x.B, delete x.C, delete x.Z, delete x.T1, delete x.T2, delete x.Sigma1, delete x.Sigma2, delete x.Sigma3, delete x.QL, delete x.QR, delete x.QM, delete x.QC, delete x.QO, globalThis.gc && globalThis.gc(), r && r.info("> ROUND 4"), await I(), globalThis.gc && globalThis.gc(), r && r.info("> ROUND 5"), await L(), delete x.C0, delete x.C1, delete x.C2, delete x.R1, delete x.R2, delete x.F, delete x.L, delete x.ZT, delete x.ZTS2, await l.close(), globalThis.gc && globalThis.gc(), E.addEvaluation("inv", ee()); + let O = E.toObjectProof(); + O.protocol = "fflonk", O.curve = p.name; + let k = []; + for (let e = 1; e <= f.nPublic; e++) { + let t = e * h, n = v.slice(t, t + h); + k.push(u.fromRprLE(n)); + } + return r && r.info("FFLONK PROVER FINISHED"), { + proof: hi(O), + publicSignals: hi(k) + }; + async function A() { + r && r.info("··· Computing additions"); + let t = await e.readSection(l, d, 3), n = 8 + h * 2; + for (let e = 0; e < f.nAdditions; e++) { + r && e !== 0 && e % 1e5 == 0 && r.info(` addition ${e}/${f.nAdditions}`); + let i = e * n, a = j(t, i); + i += 4; + let o = j(t, i); + i += 4; + let s = t.slice(i, i + h); + i += h; + let c = t.slice(i, i + h), l = M(a), u = M(o), d = m.add(m.mul(s, l), m.mul(c, u)); + y.set(d, h * e); + } + } + function j(e, t) { + let n = e.slice(t, t + 4); + return new DataView(n.buffer, n.byteOffset, n.byteLength).getUint32(0, !0); + } + function M(e) { + let t = f.nVars - f.nAdditions; + if (e < t) return v.slice(e * h, e * h + h); + if (e < f.nVars) { + let n = (e - t) * h; + return y.slice(n, n + h); + } + return m.zero; + } + async function N() { + w.b = []; + for (let e = 1; e <= 9; e++) w.b[e] = m.random(); + r && r.info("> Computing A, B, C wire polynomials"), await n(), r && r.info("> Computing T0 polynomial"), await i(), r && r.info("> Computing C1 polynomial"), await a(), r && r.info("> Computing C1 multi exponentiation"); + let t = await x.C1.multiExponentiation(D, "C1"); + return E.addPolynomial("C1", t), 0; + async function n() { + r && r.info("··· Reading data from zkey file"), b.A = new s(_), b.B = new s(_), b.C = new s(_); + let t = await e.readSection(l, d, 4), n = await e.readSection(l, d, 5), i = await e.readSection(l, d, 6); + for (let e = 0; e < f.nConstraints; e++) { + let r = e * h, a = e * 4, o = j(t, a); + b.A.set(M(o), r); + let s = j(n, a); + b.B.set(M(s), r); + let c = j(i, a); + b.C.set(M(c), r); + } + if (b.A.set(w.b[1], _ - 64), b.A.set(w.b[2], _ - 32), b.B.set(w.b[3], _ - 64), b.B.set(w.b[4], _ - 32), b.C.set(w.b[5], _ - 64), b.C.set(w.b[6], _ - 32), b.A = await m.batchToMontgomery(b.A), b.B = await m.batchToMontgomery(b.B), b.C = await m.batchToMontgomery(b.C), r && r.info("··· Computing A ifft"), x.A = await X.fromEvaluations(b.A, p, r), r && r.info("··· Computing B ifft"), x.B = await X.fromEvaluations(b.B, p, r), r && r.info("··· Computing C ifft"), x.C = await X.fromEvaluations(b.C, p, r), r && r.info("··· Computing A fft"), S.A = await Z.fromPolynomial(x.A, 4, p, r), r && r.info("··· Computing B fft"), S.B = await Z.fromPolynomial(x.B, 4, p, r), r && r.info("··· Computing C fft"), S.C = await Z.fromPolynomial(x.C, 4, p, r), x.A.degree() >= f.domainSize) throw Error("A Polynomial is not well calculated"); + if (x.B.degree() >= f.domainSize) throw Error("B Polynomial is not well calculated"); + if (x.C.degree() >= f.domainSize) throw Error("C Polynomial is not well calculated"); + } + async function i() { + r && r.info("··· Reading sections 7, 8, 9, 10, 11. Q selectors"), S.QL = new Z(new s(_ * 4), p, r), S.QR = new Z(new s(_ * 4), p, r), S.QM = new Z(new s(_ * 4), p, r), S.QO = new Z(new s(_ * 4), p, r), S.QC = new Z(new s(_ * 4), p, r), await l.readToBuffer(S.QL.eval, 0, _ * 4, d[7][0].p + _), await l.readToBuffer(S.QR.eval, 0, _ * 4, d[8][0].p + _), await l.readToBuffer(S.QM.eval, 0, _ * 4, d[9][0].p + _), await l.readToBuffer(S.QO.eval, 0, _ * 4, d[10][0].p + _), await l.readToBuffer(S.QC.eval, 0, _ * 4, d[11][0].p + _), S.lagrange1 = new Z(await e.readSection(l, d, 15), p, r), b.T0 = new s(_ * 4), r && r.info("··· Computing T0 evaluations"); + for (let e = 0; e < f.domainSize * 4; e++) { + r && e !== 0 && e % 1e5 == 0 && r.info(` T0 evaluation ${e}/${f.domainSize * 4}`); + let t = S.A.getEvaluation(e), n = S.B.getEvaluation(e), i = S.C.getEvaluation(e), a = S.QL.getEvaluation(e), o = S.QR.getEvaluation(e), s = S.QM.getEvaluation(e), c = S.QO.getEvaluation(e), l = S.QC.getEvaluation(e), u = m.zero; + for (let t = 0; t < f.nPublic; t++) { + let n = t * 5 * f.domainSize + f.domainSize + e, r = S.lagrange1.getEvaluation(n), i = b.A.slice(t * h, (t + 1) * h); + u = m.sub(u, m.mul(r, i)); + } + let d = m.mul(t, a), p = m.mul(n, o), g = m.mul(m.mul(t, n), s), _ = m.mul(i, c), v = m.add(d, m.add(p, m.add(g, m.add(_, m.add(l, u))))); + b.T0.set(v, e * h); + } + if (r && r.info("buffer T0: " + b.T0.byteLength / h), r && r.info("··· Computing T0 ifft"), x.T0 = await X.fromEvaluations(b.T0, p, r), r && r.info("T0 length: " + x.T0.length()), r && r.info("T0 degree: " + x.T0.degree()), r && r.info("··· Computing T0 / ZH"), x.T0.divByZerofier(f.domainSize, m.one), x.T0.degree() >= 2 * f.domainSize - 2) throw Error(`T0 Polynomial is not well calculated (degree is ${x.T0.degree()} and must be less than ${2 * f.domainSize + 2}`); + delete b.T0; + } + async function a() { + let e = new pi(4, p, r); + if (e.addPolynomial(0, x.A), e.addPolynomial(1, x.B), e.addPolynomial(2, x.C), e.addPolynomial(3, x.T0), x.C1 = e.getPolynomial(), x.C1.degree() >= 8 * f.domainSize - 8) throw Error("C1 Polynomial is not well calculated"); + } + } + async function P() { + r && r.info("> Computing challenges beta and gamma"); + let e = new Pr(p); + e.addPolCommitment(f.C0); + for (let t = 0; t < f.nPublic; t++) e.addScalar(b.A.slice(t * h, t * h + h)); + e.addPolCommitment(E.getPolynomial("C1")), w.beta = e.getChallenge(), r && r.info("··· challenges.beta: " + m.toString(w.beta)), e.reset(), e.addScalar(w.beta), w.gamma = e.getChallenge(), r && r.info("··· challenges.gamma: " + m.toString(w.gamma)), r && r.info("> Computing Z polynomial"), await n(), r && r.info("> Computing T1 polynomial"), await i(), r && r.info("> Computing T2 polynomial"), await a(), r && r.info("> Computing C2 polynomial"), await o(), r && r.info("> Computing C2 multi exponentiation"); + let t = await x.C2.multiExponentiation(D, "C2"); + return E.addPolynomial("C2", t), 0; + async function n() { + r && r.info("··· Computing Z evaluations"); + let e = new s(_), t = new s(_); + e.set(m.one, 0), t.set(m.one, 0); + let n = m.one; + for (let i = 0; i < f.domainSize; i++) { + r && i !== 0 && i % 1e5 == 0 && r.info(` Z evaluation ${i}/${f.domainSize}`); + let a = i * h, o = m.mul(w.beta, n), s = b.A.slice(a, a + h); + s = m.add(s, o), s = m.add(s, w.gamma); + let c = b.B.slice(a, a + h); + c = m.add(c, m.mul(f.k1, o)), c = m.add(c, w.gamma); + let l = b.C.slice(a, a + h); + l = m.add(l, m.mul(f.k2, o)), l = m.add(l, w.gamma); + let u = m.mul(s, m.mul(c, l)), d = b.A.slice(a, a + h); + d = m.add(d, m.mul(w.beta, S.Sigma1.getEvaluation(i * 4))), d = m.add(d, w.gamma); + let p = b.B.slice(a, a + h); + p = m.add(p, m.mul(w.beta, S.Sigma2.getEvaluation(i * 4))), p = m.add(p, w.gamma); + let g = b.C.slice(a, a + h); + g = m.add(g, m.mul(w.beta, S.Sigma3.getEvaluation(i * 4))), g = m.add(g, w.gamma); + let _ = m.mul(d, m.mul(p, g)); + u = m.mul(e.slice(a, a + h), u), e.set(u, (i + 1) % f.domainSize * h), _ = m.mul(t.slice(a, a + h), _), t.set(_, (i + 1) % f.domainSize * h), n = m.mul(n, m.w[f.power]); + } + t = await m.batchInverse(t); + for (let n = 0; n < f.domainSize; n++) { + let r = n * h, i = m.mul(e.slice(r, r + h), t.slice(r, r + h)); + e.set(i, r); + } + if (b.Z = e, !m.eq(e.slice(0, h), m.one)) throw Error("Copy constraints does not match"); + if (r && r.info("··· Computing Z ifft"), x.Z = await X.fromEvaluations(b.Z, p, r), r && r.info("··· Computing Z fft"), S.Z = await Z.fromPolynomial(x.Z, 4, p, r), x.Z.blindCoefficients([ + w.b[9], + w.b[8], + w.b[7] + ]), x.Z.degree() >= f.domainSize + 3) throw Error("Z Polynomial is not well calculated"); + delete b.Z; + } + async function i() { + r && r.info("··· Computing T1 evaluations"), b.T1 = new s(_ * 2), b.T1z = new s(_ * 2); + let e = m.one; + for (let t = 0; t < f.domainSize * 2; t++) { + r && t !== 0 && t % 1e5 == 0 && r.info(` T1 evaluation ${t}/${f.domainSize * 4}`); + let n = m.square(e), i = S.Z.getEvaluation(t * 2), a = m.add(m.add(m.mul(w.b[7], n), m.mul(w.b[8], e)), w.b[9]), o = S.lagrange1.getEvaluation(f.domainSize + t * 2), s = m.mul(m.sub(i, m.one), o), c = m.mul(a, o); + b.T1.set(s, t * h), b.T1z.set(c, t * h), e = m.mul(e, m.w[f.power + 1]); + } + if (r && r.info("··· Computing T1 ifft"), x.T1 = await X.fromEvaluations(b.T1, p, r), x.T1.divByZerofier(f.domainSize, m.one), r && r.info("··· Computing T1z ifft"), x.T1z = await X.fromEvaluations(b.T1z, p, r), x.T1.add(x.T1z), x.T1.degree() >= f.domainSize + 2) throw Error("T1 Polynomial is not well calculated"); + delete b.T1, delete b.T1z, delete x.T1z; + } + async function a() { + r && r.info("··· Computing T2 evaluations"), b.T2 = new s(_ * 4), b.T2z = new s(_ * 4); + let e = m.one; + for (let t = 0; t < f.domainSize * 4; t++) { + r && t !== 0 && t % 1e5 == 0 && r.info(` T2 evaluation ${t}/${f.domainSize * 4}`); + let n = m.square(e), i = m.mul(e, m.w[f.power]), a = m.square(i), o = S.A.getEvaluation(t), s = S.B.getEvaluation(t), c = S.C.getEvaluation(t), l = S.Z.getEvaluation(t), u = S.Z.getEvaluation((f.domainSize * 4 + 4 + t) % (f.domainSize * 4)), d = m.add(m.add(m.mul(w.b[7], n), m.mul(w.b[8], e)), w.b[9]), p = m.add(m.add(m.mul(w.b[7], a), m.mul(w.b[8], i)), w.b[9]), g = S.Sigma1.getEvaluation(t), _ = S.Sigma2.getEvaluation(t), v = S.Sigma3.getEvaluation(t), y = m.mul(w.beta, e), x = m.add(o, y); + x = m.add(x, w.gamma); + let C = m.add(s, m.mul(y, f.k1)); + C = m.add(C, w.gamma); + let T = m.add(c, m.mul(y, f.k2)); + T = m.add(T, w.gamma); + let E = m.mul(m.mul(m.mul(x, C), T), l), D = m.mul(m.mul(m.mul(x, C), T), d), O = m.add(o, m.mul(w.beta, g)); + O = m.add(O, w.gamma); + let k = m.add(s, m.mul(w.beta, _)); + k = m.add(k, w.gamma); + let A = m.add(c, m.mul(w.beta, v)); + A = m.add(A, w.gamma); + let j = m.mul(m.mul(m.mul(O, k), A), u), M = m.mul(m.mul(m.mul(O, k), A), p), N = m.sub(E, j), P = m.sub(D, M); + b.T2.set(N, t * h), b.T2z.set(P, t * h), e = m.mul(e, m.w[f.power + 2]); + } + if (r && r.info("··· Computing T2 ifft"), x.T2 = await X.fromEvaluations(b.T2, p, r), r && r.info("··· Computing T2 / ZH"), x.T2.divByZerofier(f.domainSize, m.one), r && r.info("··· Computing T2z ifft"), x.T2z = await X.fromEvaluations(b.T2z, p, r), x.T2.add(x.T2z), x.T2.degree() >= 3 * f.domainSize) throw Error("T2 Polynomial is not well calculated"); + delete b.T2, delete b.T2z, delete x.T2z; + } + async function o() { + let e = new pi(3, p, r); + if (e.addPolynomial(0, x.Z), e.addPolynomial(1, x.T1), e.addPolynomial(2, x.T2), x.C2 = e.getPolynomial(), x.C2.degree() >= 9 * f.domainSize) throw Error("C2 Polynomial is not well calculated"); + } + } + async function F() { + r && r.info("> Computing challenge xi"); + let e = new Pr(p); + e.addScalar(w.gamma), e.addPolCommitment(E.getPolynomial("C2")), w.xiSeed = e.getChallenge(); + let t = m.square(w.xiSeed); + T.w8 = [], T.w8[0] = m.one; + for (let e = 1; e < 8; e++) T.w8[e] = m.mul(T.w8[e - 1], f.w8); + T.w4 = [], T.w4[0] = m.one; + for (let e = 1; e < 4; e++) T.w4[e] = m.mul(T.w4[e - 1], f.w4); + T.w3 = [], T.w3[0] = m.one, T.w3[1] = f.w3, T.w3[2] = m.square(f.w3), T.S0 = {}, T.S0.h0w8 = [], T.S0.h0w8[0] = m.mul(t, w.xiSeed); + for (let e = 1; e < 8; e++) T.S0.h0w8[e] = m.mul(T.S0.h0w8[0], T.w8[e]); + T.S1 = {}, T.S1.h1w4 = [], T.S1.h1w4[0] = m.square(T.S0.h0w8[0]); + for (let e = 1; e < 4; e++) T.S1.h1w4[e] = m.mul(T.S1.h1w4[0], T.w4[e]); + T.S2 = {}, T.S2.h2w3 = [], T.S2.h2w3[0] = m.mul(T.S1.h1w4[0], t), T.S2.h2w3[1] = m.mul(T.S2.h2w3[0], T.w3[1]), T.S2.h2w3[2] = m.mul(T.S2.h2w3[0], T.w3[2]), T.S2.h3w3 = [], T.S2.h3w3[0] = m.mul(T.S2.h2w3[0], f.wr), T.S2.h3w3[1] = m.mul(T.S2.h3w3[0], T.w3[1]), T.S2.h3w3[2] = m.mul(T.S2.h3w3[0], T.w3[2]), w.xi = m.mul(m.square(T.S2.h2w3[0]), T.S2.h2w3[0]), r && r.info("··· challenges.xi: " + m.toString(w.xi)), x.QL = new X(new s(_), p, r), x.QR = new X(new s(_), p, r), x.QM = new X(new s(_), p, r), x.QO = new X(new s(_), p, r), x.QC = new X(new s(_), p, r), await l.readToBuffer(x.QL.coef, 0, _, d[7][0].p), await l.readToBuffer(x.QR.coef, 0, _, d[8][0].p), await l.readToBuffer(x.QM.coef, 0, _, d[9][0].p), await l.readToBuffer(x.QO.coef, 0, _, d[10][0].p), await l.readToBuffer(x.QC.coef, 0, _, d[11][0].p), r && r.info("··· Computing evaluations"), E.addEvaluation("ql", x.QL.evaluate(w.xi)), E.addEvaluation("qr", x.QR.evaluate(w.xi)), E.addEvaluation("qm", x.QM.evaluate(w.xi)), E.addEvaluation("qo", x.QO.evaluate(w.xi)), E.addEvaluation("qc", x.QC.evaluate(w.xi)), E.addEvaluation("s1", x.Sigma1.evaluate(w.xi)), E.addEvaluation("s2", x.Sigma2.evaluate(w.xi)), E.addEvaluation("s3", x.Sigma3.evaluate(w.xi)), E.addEvaluation("a", x.A.evaluate(w.xi)), E.addEvaluation("b", x.B.evaluate(w.xi)), E.addEvaluation("c", x.C.evaluate(w.xi)), E.addEvaluation("z", x.Z.evaluate(w.xi)), w.xiw = m.mul(w.xi, m.w[f.power]), E.addEvaluation("zw", x.Z.evaluate(w.xiw)), E.addEvaluation("t1w", x.T1.evaluate(w.xiw)), E.addEvaluation("t2w", x.T2.evaluate(w.xiw)); + } + async function I() { + r && r.info("> Computing challenge alpha"); + let e = new Pr(p); + e.addScalar(w.xiSeed), e.addScalar(E.getEvaluation("ql")), e.addScalar(E.getEvaluation("qr")), e.addScalar(E.getEvaluation("qm")), e.addScalar(E.getEvaluation("qo")), e.addScalar(E.getEvaluation("qc")), e.addScalar(E.getEvaluation("s1")), e.addScalar(E.getEvaluation("s2")), e.addScalar(E.getEvaluation("s3")), e.addScalar(E.getEvaluation("a")), e.addScalar(E.getEvaluation("b")), e.addScalar(E.getEvaluation("c")), e.addScalar(E.getEvaluation("z")), e.addScalar(E.getEvaluation("zw")), e.addScalar(E.getEvaluation("t1w")), e.addScalar(E.getEvaluation("t2w")), w.alpha = e.getChallenge(), r && r.info("··· challenges.alpha: " + m.toString(w.alpha)), r && r.info("> Reading C0 polynomial"), x.C0 = new X(new s(_ * 8), p, r), await l.readToBuffer(x.C0.coef, 0, _ * 8, d[17][0].p), r && r.info("> Computing R0 polynomial"), n(), r && r.info("> Computing R1 polynomial"), i(), r && r.info("> Computing R2 polynomial"), a(), r && r.info("> Computing F polynomial"), await o(), r && r.info("> Computing W1 multi exponentiation"); + let t = await x.F.multiExponentiation(D, "W1"); + return E.addPolynomial("W1", t), 0; + function n() { + if (x.R0 = X.lagrangePolynomialInterpolation([ + T.S0.h0w8[0], + T.S0.h0w8[1], + T.S0.h0w8[2], + T.S0.h0w8[3], + T.S0.h0w8[4], + T.S0.h0w8[5], + T.S0.h0w8[6], + T.S0.h0w8[7] + ], [ + x.C0.evaluate(T.S0.h0w8[0]), + x.C0.evaluate(T.S0.h0w8[1]), + x.C0.evaluate(T.S0.h0w8[2]), + x.C0.evaluate(T.S0.h0w8[3]), + x.C0.evaluate(T.S0.h0w8[4]), + x.C0.evaluate(T.S0.h0w8[5]), + x.C0.evaluate(T.S0.h0w8[6]), + x.C0.evaluate(T.S0.h0w8[7]) + ], p), x.R0.degree() > 7) throw Error("R0 Polynomial is not well calculated"); + } + function i() { + if (x.R1 = X.lagrangePolynomialInterpolation([ + T.S1.h1w4[0], + T.S1.h1w4[1], + T.S1.h1w4[2], + T.S1.h1w4[3] + ], [ + x.C1.evaluate(T.S1.h1w4[0]), + x.C1.evaluate(T.S1.h1w4[1]), + x.C1.evaluate(T.S1.h1w4[2]), + x.C1.evaluate(T.S1.h1w4[3]) + ], p), x.R1.degree() > 3) throw Error("R1 Polynomial is not well calculated"); + } + function a() { + if (x.R2 = X.lagrangePolynomialInterpolation([ + T.S2.h2w3[0], + T.S2.h2w3[1], + T.S2.h2w3[2], + T.S2.h3w3[0], + T.S2.h3w3[1], + T.S2.h3w3[2] + ], [ + x.C2.evaluate(T.S2.h2w3[0]), + x.C2.evaluate(T.S2.h2w3[1]), + x.C2.evaluate(T.S2.h2w3[2]), + x.C2.evaluate(T.S2.h3w3[0]), + x.C2.evaluate(T.S2.h3w3[1]), + x.C2.evaluate(T.S2.h3w3[2]) + ], p), x.R2.degree() > 5) throw Error("R2 Polynomial is not well calculated"); + } + async function o() { + r && r.info("··· Computing F polynomial"), x.F = X.fromPolynomial(x.C0, p, r), x.F.sub(x.R0), x.F.divByZerofier(8, w.xi); + let e = X.fromPolynomial(x.C1, p, r); + e.sub(x.R1), e.mulScalar(w.alpha), e.divByZerofier(4, w.xi); + let t = X.fromPolynomial(x.C2, p, r); + if (t.sub(x.R2), t.mulScalar(m.square(w.alpha)), t.divByZerofier(3, w.xi), t.divByZerofier(3, w.xiw), x.F.add(e), x.F.add(t), x.F.degree() >= 9 * f.domainSize - 6) throw Error("F Polynomial is not well calculated"); + } + } + async function L() { + r && r.info("> Computing challenge y"); + let e = new Pr(p); + e.addScalar(w.alpha), e.addPolCommitment(E.getPolynomial("W1")), w.y = e.getChallenge(), r && r.info("··· challenges.y: " + m.toString(w.y)), r && r.info("> Computing L polynomial"), await o(), r && r.info("> Computing ZTS2 polynomial"), await c(); + let t = x.ZTS2.evaluate(w.y); + t = m.inv(t), x.L.mulScalar(t); + let n = X.fromCoefficientsArray([m.neg(w.y), m.one], p); + r && r.info("> Computing W' = L / ZTS2 polynomial"); + let i = x.L.divBy(n); + if (i.degree() > 0) throw Error(`Degree of L(X)/(ZTS2(y)(X-y)) remainder is ${i.degree()} and should be 0`); + if (x.L.degree() >= 9 * f.domainSize - 1) throw Error("Degree of L(X)/(ZTS2(y)(X-y)) is not correct"); + r && r.info("> Computing W' multi exponentiation"); + let a = await x.L.multiExponentiation(D, "W2"); + return E.addPolynomial("W2", a), 0; + async function o() { + r && r.info("··· Computing L polynomial"); + let e = x.R0.evaluate(w.y), t = x.R1.evaluate(w.y), n = x.R2.evaluate(w.y), i = m.sub(w.y, T.S0.h0w8[0]); + for (let e = 1; e < 8; e++) i = m.mul(i, m.sub(w.y, T.S0.h0w8[e])); + let a = m.sub(w.y, T.S1.h1w4[0]); + for (let e = 1; e < 4; e++) a = m.mul(a, m.sub(w.y, T.S1.h1w4[e])); + let o = m.sub(w.y, T.S2.h2w3[0]); + for (let e = 1; e < 3; e++) o = m.mul(o, m.sub(w.y, T.S2.h2w3[e])); + for (let e = 0; e < 3; e++) o = m.mul(o, m.sub(w.y, T.S2.h3w3[e])); + let c = m.mul(a, o), l = m.mul(w.alpha, m.mul(i, o)), u = m.mul(m.square(w.alpha), m.mul(i, a)); + C.denH1 = a, C.denH2 = o, x.L = X.fromPolynomial(x.C0, p, r), x.L.subScalar(e), x.L.mulScalar(c); + let d = X.fromPolynomial(x.C1, p, r); + d.subScalar(t), d.mulScalar(l); + let h = X.fromPolynomial(x.C2, p, r); + h.subScalar(n), h.mulScalar(u), x.L.add(d), x.L.add(h), r && r.info("> Computing ZT polynomial"), await s(); + let g = x.ZT.evaluate(w.y); + if (x.F.mulScalar(g), x.L.sub(x.F), x.L.degree() >= 9 * f.domainSize) throw Error("L Polynomial is not well calculated"); + delete b.L; + } + async function s() { + x.ZT = X.zerofierPolynomial([ + T.S0.h0w8[0], + T.S0.h0w8[1], + T.S0.h0w8[2], + T.S0.h0w8[3], + T.S0.h0w8[4], + T.S0.h0w8[5], + T.S0.h0w8[6], + T.S0.h0w8[7], + T.S1.h1w4[0], + T.S1.h1w4[1], + T.S1.h1w4[2], + T.S1.h1w4[3], + T.S2.h2w3[0], + T.S2.h2w3[1], + T.S2.h2w3[2], + T.S2.h3w3[0], + T.S2.h3w3[1], + T.S2.h3w3[2] + ], p); + } + async function c() { + x.ZTS2 = X.zerofierPolynomial([ + T.S1.h1w4[0], + T.S1.h1w4[1], + T.S1.h1w4[2], + T.S1.h1w4[3], + T.S2.h2w3[0], + T.S2.h2w3[1], + T.S2.h2w3[2], + T.S2.h3w3[0], + T.S2.h3w3[1], + T.S2.h3w3[2] + ], p); + } + } + function ee() { + let e = w.xi; + for (let t = 0; t < f.power; t++) e = m.square(e); + C.zh = m.sub(e, m.one), i(C, T.S0.h0w8, w.y, p), a(C, T.S1.h1w4, w.y, p), o(C, T.S2.h2w3, T.S2.h3w3, w.y, w.xi, w.xiw, p); + let t = Math.max(1, f.nPublic), n = m.one; + for (let e = 0; e < t; e++) C["Li_" + (e + 1)] = m.mul(m.e(f.domainSize), m.sub(w.xi, n)), n = m.mul(n, m.w[f.power]); + let r = m.one; + for (let e of Object.values(C)) if (Array.isArray(e)) for (let t of e) r = m.mul(r, t); + else r = m.mul(r, e); + return m.inv(r); + function i(e, t, n, r) { + let i = r.Fr, a = t.length, o = i.mul(i.e(a), i.exp(t[0], a - 2)), s = []; + for (let r = 0; r < a; r++) { + let s = t[(a - 1) * r % a], c = i.sub(n, t[r]); + e[["LiS0_" + (r + 1)]] = i.mul(i.mul(o, s), c); + } + return s; + } + function a(e, t, n, r) { + let i = r.Fr, a = t.length, o = i.mul(i.e(a), i.exp(t[0], a - 2)), s = []; + for (let r = 0; r < a; r++) { + let s = t[(a - 1) * r % a], c = i.sub(n, t[r]); + e[["LiS1_" + (r + 1)]] = i.mul(i.mul(o, s), c); + } + return s; + } + function o(e, t, n, r, i, a, o) { + let s = o.Fr, c = [], l = s.mul(s.e(3), t[0]), u = s.sub(i, a), d = s.mul(l, u); + for (let n = 0; n < 3; n++) { + let i = t[2 * n % 3], a = s.sub(r, t[n]); + e[["LiS2_" + (n + 1)]] = s.mul(d, s.mul(i, a)); + } + let f = s.mul(s.e(3), n[0]), p = s.sub(a, i); + d = s.mul(f, p); + for (let t = 0; t < 3; t++) { + let i = n[2 * t % 3], a = s.sub(r, n[t]); + e[["LiS2_" + (t + 1 + 3)]] = s.mul(d, s.mul(i, a)); + } + return c; + } + } +} +//#endregion +//#region src/fflonk_full_prove.js +var { unstringifyBigInts: _i } = p; +async function vi(e, t, n, r, i, a) { + let o = _i(e), s = { type: "mem" }; + return await Bt(o, t, s, i), await gi(n, s, r, a); +} +//#endregion +//#region src/fflonk_verify.js +var { unstringifyBigInts: yi } = p; +async function bi(e, t, n, r) { + r && r.info("FFLONK VERIFIER STARTED"), e = yi(e), n = yi(n); + let i = await D(e.curve), a = xi(i, e), o = new mr(i, r); + o.fromObjectProof(n); + let s = yi(t); + if (s.length !== a.nPublic) return r.error("Number of public signals does not match with vk"), !1; + let c = i.Fr; + if (r && (r.info("----------------------------"), r.info(" FFLONK VERIFY SETTINGS"), r.info(` Curve: ${i.name}`), r.info(` Circuit power: ${a.power}`), r.info(` Domain size: ${2 ** a.power}`), r.info(` Public vars: ${a.nPublic}`), r.info("----------------------------")), r && r.info("> Checking commitments belong to G1"), !Si(i, o, a)) return r && r.error("Proof commitments are not valid"), !1; + if (r && r.info("> Checking evaluations belong to F"), !Ti(i, o)) return r && r.error("Proof evaluations are not valid."), !1; + if (r && r.info("> Checking public inputs belong to F"), !Ei(i, s)) return r && r.error("Public inputs are not valid."), !1; + r && r.info("> Computing challenges"); + let { challenges: l, roots: u } = Di(i, o, a, s, r); + r && r.info("> Computing Zero polynomial evaluation Z_H(xi)"), l.zh = c.sub(l.xiN, c.one), l.invzh = c.inv(l.zh), r && r.info("> Computing Lagrange evaluations"); + let d = await Oi(i, l, a); + r && r.info("> Computing polynomial identities PI(X)"); + let f = ki(i, s, d); + r && r.info("> Computing r0(y)"); + let p = Ai(o, l, u, i, r); + r && r.info("> Computing r1(y)"); + let m = ji(o, l, u, f, i, r); + r && r.info("> Computing r2(y)"); + let h = Mi(o, l, u, d[1], a, i, r); + r && r.info("> Computing F"); + let g = Ni(i, o, a, l, u); + r && r.info("> Computing E"); + let _ = Pi(i, o, l, a, p, m, h); + r && r.info("> Computing J"); + let v = Fi(i, o, l); + r && r.info("> Validate all evaluations with a pairing"); + let y = await Ii(i, o, l, a, g, _, v); + return r && (y ? r.info("PROOF VERIFIED SUCCESSFULLY") : r.warn("Invalid Proof")), r && r.info("FFLONK VERIFIER FINISHED"), y; +} +function xi(e, t) { + let n = t; + return n.k1 = e.Fr.fromObject(t.k1), n.k2 = e.Fr.fromObject(t.k2), n.w = e.Fr.fromObject(t.w), n.w3 = e.Fr.fromObject(t.w3), n.w4 = e.Fr.fromObject(t.w4), n.w8 = e.Fr.fromObject(t.w8), n.wr = e.Fr.fromObject(t.wr), n.X_2 = e.G2.fromObject(t.X_2), n.C0 = e.G1.fromObject(t.C0), n; +} +function Si(e, t, n) { + let r = e.G1; + return r.isValid(t.polynomials.C1) && r.isValid(t.polynomials.C2) && r.isValid(t.polynomials.W1) && r.isValid(t.polynomials.W2) && r.isValid(n.C0); +} +function Ci(e, t) { + return u.geq(t, 0) && u.lt(t, e.r); +} +function wi(e, t) { + return Ci(e, u.fromRprLE(t)); +} +function Ti(e, t) { + return wi(e, t.evaluations.ql) && wi(e, t.evaluations.qr) && wi(e, t.evaluations.qm) && wi(e, t.evaluations.qo) && wi(e, t.evaluations.qc) && wi(e, t.evaluations.s1) && wi(e, t.evaluations.s2) && wi(e, t.evaluations.s3) && wi(e, t.evaluations.a) && wi(e, t.evaluations.b) && wi(e, t.evaluations.c) && wi(e, t.evaluations.z) && wi(e, t.evaluations.zw) && wi(e, t.evaluations.t1w) && wi(e, t.evaluations.t2w); +} +function Ei(e, t) { + for (let n = 0; n < t.length; n++) if (!Ci(e, t[n])) return !1; + return !0; +} +function Di(e, t, n, r, i) { + let a = e.Fr, o = {}, s = {}, c = new Pr(e); + c.addPolCommitment(n.C0); + for (let e = 0; e < r.length; e++) c.addScalar(a.e(r[e])); + c.addPolCommitment(t.polynomials.C1), o.beta = c.getChallenge(), c.reset(), c.addScalar(o.beta), o.gamma = c.getChallenge(), c.reset(), c.addScalar(o.gamma), c.addPolCommitment(t.polynomials.C2); + let l = c.getChallenge(), u = a.square(l), d = []; + d[1] = n.w8, d[2] = a.square(n.w8), d[3] = a.mul(d[2], n.w8), d[4] = a.mul(d[3], n.w8), d[5] = a.mul(d[4], n.w8), d[6] = a.mul(d[5], n.w8), d[7] = a.mul(d[6], n.w8); + let f = []; + f[1] = n.w4, f[2] = a.square(n.w4), f[3] = a.mul(f[2], n.w4); + let p = []; + p[1] = n.w3, p[2] = a.square(n.w3), s.S0 = {}, s.S0.h0w8 = [], s.S0.h0w8[0] = a.mul(u, l); + for (let e = 1; e < 8; e++) s.S0.h0w8[e] = a.mul(s.S0.h0w8[0], d[e]); + s.S1 = {}, s.S1.h1w4 = [], s.S1.h1w4[0] = a.square(s.S0.h0w8[0]); + for (let e = 1; e < 4; e++) s.S1.h1w4[e] = a.mul(s.S1.h1w4[0], f[e]); + s.S2 = {}, s.S2.h2w3 = [], s.S2.h2w3[0] = a.mul(s.S1.h1w4[0], u), s.S2.h2w3[1] = a.mul(s.S2.h2w3[0], p[1]), s.S2.h2w3[2] = a.mul(s.S2.h2w3[0], p[2]), s.S2.h3w3 = [], s.S2.h3w3[0] = a.mul(s.S2.h2w3[0], n.wr), s.S2.h3w3[1] = a.mul(s.S2.h3w3[0], p[1]), s.S2.h3w3[2] = a.mul(s.S2.h3w3[0], p[2]), o.xi = a.mul(a.square(s.S2.h2w3[0]), s.S2.h2w3[0]), o.xiw = a.mul(o.xi, a.w[n.power]), o.xiN = o.xi, n.domainSize = 1; + for (let e = 0; e < n.power; e++) o.xiN = a.square(o.xiN), n.domainSize *= 2; + return c.reset(), c.addScalar(l), c.addScalar(t.evaluations.ql), c.addScalar(t.evaluations.qr), c.addScalar(t.evaluations.qm), c.addScalar(t.evaluations.qo), c.addScalar(t.evaluations.qc), c.addScalar(t.evaluations.s1), c.addScalar(t.evaluations.s2), c.addScalar(t.evaluations.s3), c.addScalar(t.evaluations.a), c.addScalar(t.evaluations.b), c.addScalar(t.evaluations.c), c.addScalar(t.evaluations.z), c.addScalar(t.evaluations.zw), c.addScalar(t.evaluations.t1w), c.addScalar(t.evaluations.t2w), o.alpha = c.getChallenge(), c.reset(), c.addScalar(o.alpha), c.addPolCommitment(t.polynomials.W1), o.y = c.getChallenge(), i && (i.info("··· challenges.beta: " + a.toString(o.beta)), i.info("··· challenges.gamma: " + a.toString(o.gamma)), i.info("··· challenges.xi: " + a.toString(o.xi)), i.info("··· challenges.alpha: " + a.toString(o.alpha)), i.info("··· challenges.y: " + a.toString(o.y))), { + challenges: o, + roots: s + }; +} +async function Oi(e, t, n) { + let r = e.Fr, i = Math.max(1, n.nPublic), a = new s(i * r.n8), o = new s(i * r.n8), c = r.one; + for (let e = 0; e < i; e++) { + let i = e * r.n8; + a.set(r.mul(c, t.zh), i), o.set(r.mul(r.e(n.domainSize), r.sub(t.xi, c)), i), c = r.mul(c, n.w); + } + o = await r.batchInverse(o); + let l = []; + for (let e = 0; e < i; e++) { + let t = e * r.n8; + l[e + 1] = r.mul(a.slice(t, t + r.n8), o.slice(t, t + r.n8)); + } + return l; +} +function ki(e, t, n) { + let r = e.Fr, i = r.zero; + for (let e = 0; e < t.length; e++) { + let a = r.e(t[e]); + i = r.sub(i, r.mul(a, n[e + 1])); + } + return i; +} +function Ai(e, t, n, r, i) { + let a = r.Fr, o = Li(n.S0.h0w8, t.y, t.xi, r); + i && i.info("··· Computing r0(y)"); + let s = a.zero; + for (let t = 0; t < 8; t++) { + let r = []; + r[1] = n.S0.h0w8[t]; + for (let e = 2; e < 8; e++) r[e] = a.mul(r[e - 1], n.S0.h0w8[t]); + let i = a.add(e.evaluations.ql, a.mul(e.evaluations.qr, r[1])); + i = a.add(i, a.mul(e.evaluations.qo, r[2])), i = a.add(i, a.mul(e.evaluations.qm, r[3])), i = a.add(i, a.mul(e.evaluations.qc, r[4])), i = a.add(i, a.mul(e.evaluations.s1, r[5])), i = a.add(i, a.mul(e.evaluations.s2, r[6])), i = a.add(i, a.mul(e.evaluations.s3, r[7])), s = a.add(s, a.mul(i, o[t])); + } + return s; +} +function ji(e, t, n, r, i, a) { + let o = i.Fr, s = Li(n.S1.h1w4, t.y, t.xi, i); + a && a.info("··· Computing T0(xi)"); + let c = o.mul(e.evaluations.ql, e.evaluations.a); + c = o.add(c, o.mul(e.evaluations.qr, e.evaluations.b)), c = o.add(c, o.mul(e.evaluations.qm, o.mul(e.evaluations.a, e.evaluations.b))), c = o.add(c, o.mul(e.evaluations.qo, e.evaluations.c)), c = o.add(c, e.evaluations.qc), c = o.add(c, r), c = o.mul(c, t.invzh), a && a.info("··· Computing C1(h_1ω_4^i) values"); + let l = o.zero; + for (let t = 0; t < 4; t++) { + let r = e.evaluations.a; + r = o.add(r, o.mul(n.S1.h1w4[t], e.evaluations.b)); + let i = o.square(n.S1.h1w4[t]); + r = o.add(r, o.mul(i, e.evaluations.c)), r = o.add(r, o.mul(o.mul(i, n.S1.h1w4[t]), c)), l = o.add(l, o.mul(r, s[t])); + } + return l; +} +function Mi(e, t, n, r, i, a, o) { + let s = a.Fr, c = Ri([n.S2.h2w3, n.S2.h3w3], t.y, t.xi, t.xiw, a); + o && o.info("··· Computing T1(xi)"); + let l = s.sub(e.evaluations.z, s.one); + l = s.mul(l, r), l = s.mul(l, t.invzh), o && o.info("··· Computing T2(xi)"); + let u = s.mul(t.beta, t.xi), d = s.add(e.evaluations.a, s.add(u, t.gamma)), f = s.add(e.evaluations.b, s.add(s.mul(u, i.k1), t.gamma)), p = s.add(e.evaluations.c, s.add(s.mul(u, i.k2), t.gamma)), m = s.mul(d, s.mul(f, s.mul(p, e.evaluations.z))), h = s.add(e.evaluations.a, s.add(s.mul(t.beta, e.evaluations.s1), t.gamma)), g = s.add(e.evaluations.b, s.add(s.mul(t.beta, e.evaluations.s2), t.gamma)), _ = s.add(e.evaluations.c, s.add(s.mul(t.beta, e.evaluations.s3), t.gamma)), v = s.mul(h, s.mul(g, s.mul(_, e.evaluations.zw))), y = s.sub(m, v); + y = s.mul(y, t.invzh), o && o.info("··· Computing C2(h_2ω_3^i) values"); + let b = s.zero; + for (let t = 0; t < 3; t++) { + let r = s.add(e.evaluations.z, s.mul(n.S2.h2w3[t], l)); + r = s.add(r, s.mul(s.square(n.S2.h2w3[t]), y)), b = s.add(b, s.mul(r, c[t])); + } + o && o.info("··· Computing C2(h_3ω_3^i) values"); + for (let t = 0; t < 3; t++) { + let r = s.add(e.evaluations.zw, s.mul(n.S2.h3w3[t], e.evaluations.t1w)); + r = s.add(r, s.mul(s.square(n.S2.h3w3[t]), e.evaluations.t2w)), b = s.add(b, s.mul(r, c[t + 3])); + } + return b; +} +function Ni(e, t, n, r, i) { + let a = e.G1, o = e.Fr, s = o.sub(r.y, i.S0.h0w8[0]); + for (let e = 1; e < 8; e++) s = o.mul(s, o.sub(r.y, i.S0.h0w8[e])); + r.temp = s; + let c = o.sub(r.y, i.S1.h1w4[0]); + for (let e = 1; e < 4; e++) c = o.mul(c, o.sub(r.y, i.S1.h1w4[e])); + let l = o.sub(r.y, i.S2.h2w3[0]); + for (let e = 1; e < 3; e++) l = o.mul(l, o.sub(r.y, i.S2.h2w3[e])); + for (let e = 0; e < 3; e++) l = o.mul(l, o.sub(r.y, i.S2.h3w3[e])); + r.quotient1 = o.mul(r.alpha, o.div(s, c)), r.quotient2 = o.mul(o.square(r.alpha), o.div(s, l)); + let u = a.timesFr(t.polynomials.C1, r.quotient1), d = a.timesFr(t.polynomials.C2, r.quotient2); + return a.add(n.C0, a.add(u, d)); +} +function Pi(e, t, n, r, i, a, o) { + let s = e.G1, c = e.Fr, l = c.mul(a, n.quotient1), u = c.mul(o, n.quotient2); + return s.timesFr(s.one, c.add(i, c.add(l, u))); +} +function Fi(e, t, n) { + return e.G1.timesFr(t.polynomials.W1, n.temp); +} +async function Ii(e, t, n, r, i, a, o) { + let s = e.G1, c = s.timesFr(t.polynomials.W2, n.y); + c = s.add(s.sub(s.sub(i, a), o), c); + let l = e.G2.one, u = t.polynomials.W2, d = r.X_2; + return await e.pairingEq(s.neg(c), l, u, d); +} +function Li(e, t, n, r) { + let i = r.Fr, a = e.length, o = i.sub(i.exp(t, a), n), s = i.mul(i.e(a), i.exp(e[0], a - 2)), c = []; + for (let n = 0; n < a; n++) { + let r = e[(a - 1) * n % a], l = i.sub(t, e[n]); + c[n] = i.div(o, i.mul(i.mul(s, r), l)); + } + return c; +} +function Ri(e, t, n, r, i) { + let a = i.Fr, o = [], s = e[0].length, c = s * e.length, l = a.exp(t, c), u = a.mul(a.add(n, r), a.exp(t, s)), d = a.mul(n, r), f = a.add(a.sub(l, u), d), p = a.mul(a.mul(a.e(s), e[0][0]), a.sub(n, r)); + for (let n = 0; n < s; n++) { + let r = e[0][(s - 1) * n % s], i = a.sub(t, e[0][n]), c = a.mul(p, a.mul(r, i)); + o[n] = a.div(f, c); + } + p = a.mul(a.mul(a.e(s), e[1][0]), a.sub(r, n)); + for (let n = 0; n < s; n++) { + let r = e[1][(s - 1) * n % s], i = a.sub(t, e[1][n]), c = a.mul(p, a.mul(r, i)); + o[n + s] = a.div(f, c); + } + return o; +} +//#endregion +//#region src/fflonk_export_calldata.js +var { unstringifyBigInts: zi } = p; +function $(e) { + let t = e.toString(16); + for (; t.length < 64;) t = "0" + t; + return t = `0x${t}`, t; +} +async function Bi(e, t) { + let n = zi(t), r = zi(e); + await D(n.curve); + let i = ""; + for (let e = 0; e < r.length; e++) i !== "" && (i += ","), i += $(r[e]); + return `[${$(n.polynomials.C1[0])}, ${$(n.polynomials.C1[1])},${$(n.polynomials.C2[0])},${$(n.polynomials.C2[1])},${$(n.polynomials.W1[0])},${$(n.polynomials.W1[1])},${$(n.polynomials.W2[0])},${$(n.polynomials.W2[1])},${$(n.evaluations.ql)},${$(n.evaluations.qr)},${$(n.evaluations.qm)},${$(n.evaluations.qo)},${$(n.evaluations.qc)},${$(n.evaluations.s1)},${$(n.evaluations.s2)},${$(n.evaluations.s3)},${$(n.evaluations.a)},${$(n.evaluations.b)},${$(n.evaluations.c)},${$(n.evaluations.z)},${$(n.evaluations.zw)},${$(n.evaluations.t1w)},${$(n.evaluations.t2w)},${$(n.evaluations.inv)}],[${i}]`; +} +//#endregion +//#region src/fflonk.js +var Vi = /* @__PURE__ */ y({ + exportSolidityCallData: () => Bi, + exportSolidityVerifier: () => ur, + fullProve: () => vi, + prove: () => gi, + setup: () => mi, + verify: () => bi }); - -export { curves, fflonk, groth16, plonk, powersoftau as powersOfTau, r1cs, wtns, zkey as zKey }; +//#endregion +export { b as curves, Vi as fflonk, Zt as groth16, ai as plonk, An as powersOfTau, In as r1cs, Hn as wtns, fr as zKey }; diff --git a/build/cli.cjs b/build/cli.cjs old mode 100755 new mode 100644 index 27592232..b060d041 --- a/build/cli.cjs +++ b/build/cli.cjs @@ -1,14188 +1,11816 @@ -#!/usr/bin/node --expose-gc - -'use strict'; - -var fs = require('fs'); -var url = require('url'); -var r1csfile = require('r1csfile'); -var fastFile = require('fastfile'); -var ffjavascript = require('ffjavascript'); -var blake2b = require('@noble/hashes/blake2b'); -var utils = require('@noble/hashes/utils'); -var readline = require('readline'); -var crypto = require('crypto'); -var path = require('path'); -var binFileUtils = require('@iden3/binfileutils'); -var circom_runtime = require('circom_runtime'); -var sha3 = require('@noble/hashes/sha3'); -var Logger = require('logplease'); -var v8 = require('v8'); - -function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } - -function _interopNamespace(e) { - if (e && e.__esModule) return e; - var n = Object.create(null); - if (e) { - Object.keys(e).forEach(function (k) { - if (k !== 'default') { - var d = Object.getOwnPropertyDescriptor(e, k); - Object.defineProperty(n, k, d.get ? d : { - enumerable: true, - get: function () { return e[k]; } - }); - } - }); - } - n["default"] = e; - return Object.freeze(n); -} - -var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs); -var url__default = /*#__PURE__*/_interopDefaultLegacy(url); -var fastFile__namespace = /*#__PURE__*/_interopNamespace(fastFile); -var readline__default = /*#__PURE__*/_interopDefaultLegacy(readline); -var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto); -var path__default = /*#__PURE__*/_interopDefaultLegacy(path); -var binFileUtils__namespace = /*#__PURE__*/_interopNamespace(binFileUtils); -var Logger__default = /*#__PURE__*/_interopDefaultLegacy(Logger); - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - +#!/usr/bin/env node +//#region \0rolldown/runtime.js +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports); +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { + key = keys[i]; + if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { + get: ((k) => from[k]).bind(null, key), + enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable + }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { + value: mod, + enumerable: true +}) : target, mod)); +//#endregion +let fs = require("fs"); +fs = __toESM(fs); +let url = require("url"); +url = __toESM(url); +let r1csfile = require("r1csfile"); +let fastfile = require("fastfile"); +fastfile = __toESM(fastfile); +let ffjavascript = require("ffjavascript"); +let _noble_hashes_blake2_js = require("@noble/hashes/blake2.js"); +let _noble_hashes_utils_js = require("@noble/hashes/utils.js"); +let readline = require("readline"); +readline = __toESM(readline); +let crypto = require("crypto"); +crypto = __toESM(crypto); +let path = require("path"); +path = __toESM(path); +let _iden3_binfileutils = require("@iden3/binfileutils"); +_iden3_binfileutils = __toESM(_iden3_binfileutils); +let circom_runtime = require("circom_runtime"); +let _noble_hashes_sha3_js = require("@noble/hashes/sha3.js"); +let logplease = require("logplease"); +logplease = __toESM(logplease); +let v8 = require("v8"); +//#region src/loadsyms.js async function loadSymbols(symFileName) { - const sym = { - labelIdx2Name: [ "one" ], - varIdx2Name: [ "one" ], - componentIdx2Name: [] - }; - const fd = await fastFile__namespace.readExisting(symFileName); - const buff = await fd.read(fd.totalSize); - const symsStr = new TextDecoder("utf-8").decode(buff); - const lines = symsStr.split("\n"); - for (let i=0; i. -*/ - + const sym = { + labelIdx2Name: ["one"], + varIdx2Name: ["one"], + componentIdx2Name: [] + }; + const fd = await fastfile.readExisting(symFileName); + const buff = await fd.read(fd.totalSize); + const lines = new TextDecoder("utf-8").decode(buff).split("\n"); + for (let i = 0; i < lines.length; i++) { + const arr = lines[i].split(","); + if (arr.length != 4) continue; + if (sym.varIdx2Name[arr[1]]) sym.varIdx2Name[arr[1]] += "|" + arr[3]; + else sym.varIdx2Name[arr[1]] = arr[3]; + sym.labelIdx2Name[arr[0]] = arr[3]; + if (!sym.componentIdx2Name[arr[2]]) sym.componentIdx2Name[arr[2]] = extractComponent(arr[3]); + } + await fd.close(); + return sym; + function extractComponent(name) { + const arr = name.split("."); + arr.pop(); + return arr.join("."); + } +} +//#endregion +//#region src/r1cs_print.js function r1csPrint$1(r1cs, syms, logger) { - for (let i=0; i { - let S = ""; - const keys = Object.keys(lc); - keys.forEach( (k) => { - let name = syms.varIdx2Name[k]; - if (name == "one") name = "1"; - - let vs = r1cs.curve.Fr.toString(lc[k]); - if (vs == "1") vs = ""; // Do not show ones - if (vs == "-1") vs = "-"; // Do not show ones - if ((S!="")&&(vs[0]!="-")) vs = "+"+vs; - if (S!="") vs = " "+vs; - S= S + vs + name; - }); - return S; - }; - const S = `[ ${lc2str(c[0])} ] * [ ${lc2str(c[1])} ] - [ ${lc2str(c[2])} ] = 0`; - if (logger) logger.info(S); - } - -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -const bls12381r$1 = ffjavascript.Scalar.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16); -const bn128r$1 = ffjavascript.Scalar.e("21888242871839275222246405745257275088548364400416034343698204186575808495617"); - + for (let i = 0; i < r1cs.constraints.length; i++) printCostraint(r1cs.constraints[i]); + function printCostraint(c) { + const lc2str = (lc) => { + let S = ""; + Object.keys(lc).forEach((k) => { + let name = syms.varIdx2Name[k]; + if (name == "one") name = "1"; + let vs = r1cs.curve.Fr.toString(lc[k]); + if (vs == "1") vs = ""; + if (vs == "-1") vs = "-"; + if (S != "" && vs[0] != "-") vs = "+" + vs; + if (S != "") vs = " " + vs; + S = S + vs + name; + }); + return S; + }; + const S = `[ ${lc2str(c[0])} ] * [ ${lc2str(c[1])} ] - [ ${lc2str(c[2])} ] = 0`; + if (logger) logger.info(S); + } +} +//#endregion +//#region src/r1cs_info.js +var bls12381r$1 = ffjavascript.Scalar.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16); +var bn128r$1 = ffjavascript.Scalar.e("21888242871839275222246405745257275088548364400416034343698204186575808495617"); async function r1csInfo$1(r1csName, logger) { - - const cir = await r1csfile.readR1cs(r1csName); - - if (ffjavascript.Scalar.eq(cir.prime, bn128r$1)) { - if (logger) logger.info("Curve: bn-128"); - } else if (ffjavascript.Scalar.eq(cir.prime, bls12381r$1)) { - if (logger) logger.info("Curve: bls12-381"); - } else { - if (logger) logger.info(`Unknown Curve. Prime: ${ffjavascript.Scalar.toString(cir.prime)}`); - } - if (logger) logger.info(`# of Wires: ${cir.nVars}`); - if (logger) logger.info(`# of Constraints: ${cir.nConstraints}`); - if (logger) logger.info(`# of Private Inputs: ${cir.nPrvInputs}`); - if (logger) logger.info(`# of Public Inputs: ${cir.nPubInputs}`); - if (logger) logger.info(`# of Labels: ${cir.nLabels}`); - if (logger) logger.info(`# of Outputs: ${cir.nOutputs}`); - - return cir; -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - - -function log2( V ) -{ - return( ( ( V & 0xFFFF0000 ) !== 0 ? ( V &= 0xFFFF0000, 16 ) : 0 ) | ( ( V & 0xFF00FF00 ) !== 0 ? ( V &= 0xFF00FF00, 8 ) : 0 ) | ( ( V & 0xF0F0F0F0 ) !== 0 ? ( V &= 0xF0F0F0F0, 4 ) : 0 ) | ( ( V & 0xCCCCCCCC ) !== 0 ? ( V &= 0xCCCCCCCC, 2 ) : 0 ) | ( ( V & 0xAAAAAAAA ) !== 0 ) ); -} - - + const cir = await (0, r1csfile.readR1cs)(r1csName); + if (ffjavascript.Scalar.eq(cir.prime, bn128r$1)) { + if (logger) logger.info("Curve: bn-128"); + } else if (ffjavascript.Scalar.eq(cir.prime, bls12381r$1)) { + if (logger) logger.info("Curve: bls12-381"); + } else if (logger) logger.info(`Unknown Curve. Prime: ${ffjavascript.Scalar.toString(cir.prime)}`); + if (logger) logger.info(`# of Wires: ${cir.nVars}`); + if (logger) logger.info(`# of Constraints: ${cir.nConstraints}`); + if (logger) logger.info(`# of Private Inputs: ${cir.nPrvInputs}`); + if (logger) logger.info(`# of Public Inputs: ${cir.nPubInputs}`); + if (logger) logger.info(`# of Labels: ${cir.nLabels}`); + if (logger) logger.info(`# of Outputs: ${cir.nOutputs}`); + return cir; +} +//#endregion +//#region src/misc.js +var _revTable = []; +for (let i = 0; i < 256; i++) _revTable[i] = _revSlow(i, 8); +function _revSlow(idx, bits) { + let res = 0; + let a = idx; + for (let i = 0; i < bits; i++) { + res <<= 1; + res = res | a & 1; + a >>= 1; + } + return res; +} +function log2(V) { + return ((V & 4294901760) !== 0 ? (V &= 4294901760, 16) : 0) | ((V & 4278255360) !== 0 ? (V &= 4278255360, 8) : 0) | ((V & 4042322160) !== 0 ? (V &= 4042322160, 4) : 0) | ((V & 3435973836) !== 0 ? (V &= 3435973836, 2) : 0) | (V & 2863311530) !== 0; +} function formatHash(b, title) { - const a = new DataView(b.buffer, b.byteOffset, b.byteLength); - let S = ""; - for (let i=0; i<4; i++) { - if (i>0) S += "\n"; - S += "\t\t"; - for (let j=0; j<4; j++) { - if (j>0) S += " "; - S += a.getUint32(i*16+j*4).toString(16).padStart(8, "0"); - } - } - if (title) S = title + "\n" + S; - return S; -} - + const a = new DataView(b.buffer, b.byteOffset, b.byteLength); + let S = ""; + for (let i = 0; i < 4; i++) { + if (i > 0) S += "\n"; + S += " "; + for (let j = 0; j < 4; j++) { + if (j > 0) S += " "; + S += a.getUint32(i * 16 + j * 4).toString(16).padStart(8, "0"); + } + } + if (title) S = title + "\n" + S; + return S; +} function hashIsEqual(h1, h2) { - if (h1.byteLength != h2.byteLength) return false; - var dv1 = new Int8Array(h1); - var dv2 = new Int8Array(h2); - for (var i = 0 ; i != h1.byteLength ; i++) - { - if (dv1[i] != dv2[i]) return false; - } - return true; -} - + if (h1.byteLength != h2.byteLength) return false; + var dv1 = new Int8Array(h1); + var dv2 = new Int8Array(h2); + for (var i = 0; i != h1.byteLength; i++) if (dv1[i] != dv2[i]) return false; + return true; +} function cloneHasher(h) { - return h.clone(); + return h.clone(); } - function fromPartialHash(partial) { - // NOTE: this is unsafe and uses internal API - const buf = partial.subarray(0, 128); - const rest = utils.u32(partial.subarray(128)); - const res = blake2b.blake2b.create({ dkLen: 64 }); - res.buffer.set(buf); - (res.v0l = rest[0] | 0), (res.v0h = rest[1] | 0); - (res.v1l = rest[2] | 0), (res.v1h = rest[3] | 0); - (res.v2l = rest[4] | 0), (res.v2h = rest[5] | 0); - (res.v3l = rest[6] | 0), (res.v3h = rest[7] | 0); - (res.v4l = rest[8] | 0), (res.v4h = rest[9] | 0); - (res.v5l = rest[10] | 0), (res.v5h = rest[11] | 0); - (res.v6l = rest[12] | 0), (res.v6h = rest[13] | 0); - (res.v7l = rest[14] | 0), (res.v7h = rest[15] | 0); - const shift = 2 ** 32; - const len = rest[16] + rest[17] * shift; - const pos = rest[18] + rest[19] * shift; - res.length = len + pos; - res.pos = pos; - return res; -} - -function toPartialHash(hash){ - // NOTE: this is unsafe and uses internal API - const res = new Uint8Array(216); - const res32 = utils.u32(res.subarray(128)); - res.set(hash.buffer); - (res32[0] = hash.v0l), (res32[1] = hash.v0h); - (res32[2] = hash.v1l), (res32[3] = hash.v1h); - (res32[4] = hash.v2l), (res32[5] = hash.v2h); - (res32[6] = hash.v3l), (res32[7] = hash.v3h); - (res32[8] = hash.v4l), (res32[9] = hash.v4h); - (res32[10] = hash.v5l), (res32[11] = hash.v5h); - (res32[12] = hash.v6l), (res32[13] = hash.v6h); - (res32[14] = hash.v7l), (res32[15] = hash.v7h); - res32[18] = hash.pos; - res32[16] = hash.length-hash.pos; - return res; -} - + const buf = partial.subarray(0, 128); + const rest = (0, _noble_hashes_utils_js.u32)(partial.subarray(128)); + const res = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + res.buffer.set(buf); + res.v0l = rest[0] | 0, res.v0h = rest[1] | 0; + res.v1l = rest[2] | 0, res.v1h = rest[3] | 0; + res.v2l = rest[4] | 0, res.v2h = rest[5] | 0; + res.v3l = rest[6] | 0, res.v3h = rest[7] | 0; + res.v4l = rest[8] | 0, res.v4h = rest[9] | 0; + res.v5l = rest[10] | 0, res.v5h = rest[11] | 0; + res.v6l = rest[12] | 0, res.v6h = rest[13] | 0; + res.v7l = rest[14] | 0, res.v7h = rest[15] | 0; + const shift = 2 ** 32; + const len = rest[16] + rest[17] * shift; + const pos = rest[18] + rest[19] * shift; + res.length = len + pos; + res.pos = pos; + return res; +} +function toPartialHash(hash) { + const res = new Uint8Array(216); + const res32 = (0, _noble_hashes_utils_js.u32)(res.subarray(128)); + res.set(hash.buffer); + res32[0] = hash.v0l, res32[1] = hash.v0h; + res32[2] = hash.v1l, res32[3] = hash.v1h; + res32[4] = hash.v2l, res32[5] = hash.v2h; + res32[6] = hash.v3l, res32[7] = hash.v3h; + res32[8] = hash.v4l, res32[9] = hash.v4h; + res32[10] = hash.v5l, res32[11] = hash.v5h; + res32[12] = hash.v6l, res32[13] = hash.v6h; + res32[14] = hash.v7l, res32[15] = hash.v7h; + res32[18] = hash.pos; + res32[16] = hash.length - hash.pos; + return res; +} async function sameRatio$2(curve, g1s, g1sx, g2s, g2sx) { - if (curve.G1.isZero(g1s)) return false; - if (curve.G1.isZero(g1sx)) return false; - if (curve.G2.isZero(g2s)) return false; - if (curve.G2.isZero(g2sx)) return false; - // return curve.F12.eq(curve.pairing(g1s, g2sx), curve.pairing(g1sx, g2s)); - const res = await curve.pairingEq(g1s, g2sx, curve.G1.neg(g1sx), g2s); - return res; -} - - + if (curve.G1.isZero(g1s)) return false; + if (curve.G1.isZero(g1sx)) return false; + if (curve.G2.isZero(g2s)) return false; + if (curve.G2.isZero(g2sx)) return false; + return await curve.pairingEq(g1s, g2sx, curve.G1.neg(g1sx), g2s); +} function askEntropy() { - if (process.browser) { - return window.prompt("Enter a random text. (Entropy): ", ""); - } else { - const rl = readline__default["default"].createInterface({ - input: process.stdin, - output: process.stdout - }); - - return new Promise((resolve) => { - rl.question("Enter a random text. (Entropy): ", (input) => resolve(input) ); - }); - } -} - + if (process.browser) return window.prompt("Enter a random text. (Entropy): ", ""); + else { + const rl = readline.default.createInterface({ + input: process.stdin, + output: process.stdout + }); + return new Promise((resolve) => { + rl.question("Enter a random text. (Entropy): ", (input) => resolve(input)); + }); + } +} function getRandomBytes(n) { - let array = new Uint8Array(n); - if (process.browser) { // Supported - globalThis.crypto.getRandomValues(array); - } else { // NodeJS - crypto__default["default"].randomFillSync(array); - } - return array; -} - + let array = new Uint8Array(n); + if (process.browser) globalThis.crypto.getRandomValues(array); + else crypto.default.randomFillSync(array); + return array; +} async function sha256digest(data) { - if (process.browser) { // Supported - const buffer = await globalThis.crypto.subtle.digest("SHA-256", data.buffer); - return new Uint8Array(buffer); - } else { // NodeJS - return crypto__default["default"].createHash("sha256").update(data).digest(); - } -} - + if (process.browser) { + const buffer = await globalThis.crypto.subtle.digest("SHA-256", data.buffer); + return new Uint8Array(buffer); + } else return crypto.default.createHash("sha256").update(data).digest(); +} /** - * @param {Uint8Array} data - * @param {number} offset - */ +* @param {Uint8Array} data +* @param {number} offset +*/ function readUInt32BE(data, offset) { - return new DataView(data.buffer).getUint32(offset, false); + return new DataView(data.buffer).getUint32(offset, false); } - async function getRandomRng(entropy) { - // Generate a random Rng - while (!entropy) { - entropy = await askEntropy(); - } - const hasher = blake2b.blake2b.create(64); - hasher.update(getRandomBytes(64)); - const enc = new TextEncoder(); // always utf-8 - hasher.update(enc.encode(entropy)); - const hash = hasher.digest(); - - const seed = []; - for (let i=0;i<8;i++) { - seed[i] = readUInt32BE(hash, i*4); - } - const rng = new ffjavascript.ChaCha(seed); - return rng; -} - + while (!entropy) entropy = await askEntropy(); + const hasher = _noble_hashes_blake2_js.blake2b.create(64); + hasher.update(getRandomBytes(64)); + const enc = new TextEncoder(); + hasher.update(enc.encode(entropy)); + const hash = hasher.digest(); + const seed = []; + for (let i = 0; i < 8; i++) seed[i] = readUInt32BE(hash, i * 4); + return new ffjavascript.ChaCha(seed); +} async function rngFromBeaconParams(beaconHash, numIterationsExp) { - let nIterationsInner; - let nIterationsOuter; - if (numIterationsExp<32) { - nIterationsInner = (1 << numIterationsExp) >>> 0; - nIterationsOuter = 1; - } else { - nIterationsInner = 0x100000000; - nIterationsOuter = (1 << (numIterationsExp-32)) >>> 0; - } - - let curHash = beaconHash; - for (let i=0; i>> 0; + nIterationsOuter = 1; + } else { + nIterationsInner = 4294967296; + nIterationsOuter = 1 << numIterationsExp - 32 >>> 0; + } + let curHash = beaconHash; + for (let i = 0; i < nIterationsOuter; i++) for (let j = 0; j < nIterationsInner; j++) curHash = await sha256digest(curHash); + const curHashV = new DataView(curHash.buffer, curHash.byteOffset, curHash.byteLength); + const seed = []; + for (let i = 0; i < 8; i++) seed[i] = curHashV.getUint32(i * 4, false); + return new ffjavascript.ChaCha(seed); +} function hex2ByteArray(s) { - if (s instanceof Uint8Array) return s; - if (s.slice(0,2) == "0x") s= s.slice(2); - return new Uint8Array(s.match(/[\da-f]{2}/gi).map(function (h) { - return parseInt(h, 16); - })); + if (s instanceof Uint8Array) return s; + if (s.slice(0, 2) == "0x") s = s.slice(2); + return new Uint8Array(s.match(/[\da-f]{2}/gi).map(function(h) { + return parseInt(h, 16); + })); } - function byteArray2hex(byteArray) { - return Array.prototype.map.call(byteArray, function(byte) { - return ("0" + (byte & 0xFF).toString(16)).slice(-2); - }).join(""); + return Array.prototype.map.call(byteArray, function(byte) { + return ("0" + (byte & 255).toString(16)).slice(-2); + }).join(""); } - function stringifyBigIntsWithField(Fr, o) { - if (o instanceof Uint8Array) { - return Fr.toString(o); - } else if (Array.isArray(o)) { - return o.map(stringifyBigIntsWithField.bind(null, Fr)); - } else if (typeof o == "object") { - const res = {}; - const keys = Object.keys(o); - keys.forEach( (k) => { - res[k] = stringifyBigIntsWithField(Fr, o[k]); - }); - return res; - } else if ((typeof(o) == "bigint") || o.eq !== undefined) { - return o.toString(10); - } else { - return o; - } -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - - + if (o instanceof Uint8Array) return Fr.toString(o); + else if (Array.isArray(o)) return o.map(stringifyBigIntsWithField.bind(null, Fr)); + else if (typeof o == "object") { + const res = {}; + Object.keys(o).forEach((k) => { + res[k] = stringifyBigIntsWithField(Fr, o[k]); + }); + return res; + } else if (typeof o == "bigint" || o.eq !== void 0) return o.toString(10); + else return o; +} +//#endregion +//#region src/r1cs_export_json.js async function r1csExportJson(r1csFileName, logger) { - - const cir = await r1csfile.readR1cs(r1csFileName, true, true, true, logger); - const Fr=cir.curve.Fr; - delete cir.curve; - delete cir.F; - - return stringifyBigIntsWithField(Fr, cir); -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -const __dirname$2 = path__default["default"].dirname(url__default["default"].fileURLToPath((typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT' && document.currentScript.src || new URL('cli.cjs', document.baseURI).href)))); - -let pkgS; + const cir = await (0, r1csfile.readR1cs)(r1csFileName, true, true, true, logger); + const Fr = cir.curve.Fr; + delete cir.curve; + delete cir.F; + return stringifyBigIntsWithField(Fr, cir); +} +//#endregion +//#region src/clprocessor.js +var __dirname$2 = path.default.dirname(url.default.fileURLToPath(require("url").pathToFileURL(__filename).href)); +var pkgS; try { - pkgS = fs__default["default"].readFileSync(path__default["default"].join(__dirname$2, "package.json")); -} catch (err) { - pkgS = fs__default["default"].readFileSync(path__default["default"].join(__dirname$2, "..","package.json")); -} - -const pkg = JSON.parse(pkgS); -const version = pkg.version; -let selectedCommand = null; - + pkgS = fs.default.readFileSync(path.default.join(__dirname$2, "package.json")); +} catch { + pkgS = fs.default.readFileSync(path.default.join(__dirname$2, "..", "package.json")); +} +var version = JSON.parse(pkgS).version; +var selectedCommand = null; async function clProcessor(commands) { - const cl = []; - const argv = {}; - for (let i=2; i 1) { - argv[arr[0]] = arr.slice(1).join("="); - } else { - argv[arr[0]] = true; - } - } else { - cl.push(process.argv[i]); - } - } - for (let i=0; i0) console.log("Invalid number of parameters"); - helpCmd(cmd); - return 99; - } - return res; - } - } - if (cl.length>0) console.log("Invalid command"); - helpAll(); - return 99; - - function calculateMatch(cmd, cl) { - const alias = []; - const m = parseLine(cmd.cmd); - alias.push(m); - if (cmd.alias) { - if (Array.isArray(cmd.alias)) { - for (let i=0; i1) ? arr1[1] : null - }; - } - - - function areParamsValid(cmd, params) { - while ((params.length)&&(!params[params.length-1])) params.pop(); - const pl = parseLine(cmd); - if (params.length > pl.params.length) return false; - let minParams = pl.params.length; - while ((minParams>0)&&(pl.params[minParams-1][0] == "[")) minParams --; - if (params.length < minParams) return false; - - for (let i=0; (i< pl.params.length)&&(pl.params[i][0]=="<"); i++) { - if (typeof params[i] == "undefined") return false; - } - return true; - } - - function getOptions(options) { - const res = {}; - const opts = options.match(/(\S+)/g); - for (let i=0; i 1) argv[arr[0]] = arr.slice(1).join("="); + else argv[arr[0]] = true; + } else cl.push(process.argv[i]); + for (let i = 0; i < commands.length; i++) { + const cmd = commands[i]; + const m = calculateMatch(commands[i], cl); + let res; + if (m) { + if (argv.h || argv.help) { + helpCmd(cmd); + return; + } + if (areParamsValid(cmd.cmd, m)) if (cmd.options) { + const options = getOptions(cmd.options); + res = await cmd.action(m, options); + } else res = await cmd.action(m, {}); + else { + if (m.length > 0) console.log("Invalid number of parameters"); + helpCmd(cmd); + return 99; + } + return res; + } + } + if (cl.length > 0) console.log("Invalid command"); + helpAll(); + return 99; + function calculateMatch(cmd, cl) { + const alias = []; + const m = parseLine(cmd.cmd); + alias.push(m); + if (cmd.alias) if (Array.isArray(cmd.alias)) for (let i = 0; i < cmd.alias.length; i++) { + const a = parseLine(cmd.alias[i]); + alias.push({ + cmd: a.cmd, + params: m.params + }); + } + else { + const a = parseLine(cmd.alias); + alias.push({ + cmd: a.cmd, + params: m.params + }); + } + for (let i = 0; i < cl.length; i++) for (let j = 0; j < alias.length; j++) { + const w = alias[j].cmd.shift(); + if (cl[i].toUpperCase() == w.toUpperCase()) { + if (alias[j].cmd.length == 0) return buildRemaining(alias[j].params, cl.slice(i + 1)); + } else { + alias.splice(j, 1); + j--; + } + } + return null; + function buildRemaining(defParams, cl) { + const res = []; + let p = 0; + for (let i = 0; i < defParams.length; i++) if (defParams[i][0] == "-") res.push(getOption(defParams[i]).val); + else if (p < cl.length) res.push(cl[p++]); + else res.push(null); + while (p < cl.length) res.push(cl[p++]); + return res; + } + } + function parseLine(l) { + const words = l.match(/(\S+)/g); + for (let i = 0; i < words.length; i++) if (words[i][0] == "<" || words[i][0] == "[" || words[i][0] == "-") return { + cmd: words.slice(0, i), + params: words.slice(i) + }; + return { + cmd: words, + params: [] + }; + } + function getOption(o) { + const arr1 = o.slice(1).split(":"); + const arr2 = arr1[0].split("|"); + for (let i = 0; i < arr2.length; i++) if (argv[arr2[i]]) return { + key: arr2[0], + val: argv[arr2[i]] + }; + return { + key: arr2[0], + val: arr1.length > 1 ? arr1[1] : null + }; + } + function areParamsValid(cmd, params) { + while (params.length && !params[params.length - 1]) params.pop(); + const pl = parseLine(cmd); + if (params.length > pl.params.length) return false; + let minParams = pl.params.length; + while (minParams > 0 && pl.params[minParams - 1][0] == "[") minParams--; + if (params.length < minParams) return false; + for (let i = 0; i < pl.params.length && pl.params[i][0] == "<"; i++) if (typeof params[i] == "undefined") return false; + return true; + } + function getOptions(options) { + const res = {}; + const opts = options.match(/(\S+)/g); + for (let i = 0; i < opts.length; i++) { + const o = getOption(opts[i]); + res[o.key] = o.val; + } + return res; + } + function printVersion() { + console.log("snarkjs@" + version); + } + function epilog() { + console.log(` Copyright (C) 2018 0kims association This program comes with ABSOLUTELY NO WARRANTY; This is free software, and you are welcome to redistribute it under certain conditions; see the COPYING file in the official repo directory at https://github.com/iden3/snarkjs `); - } - - function helpAll() { - printVersion(); - epilog(); - console.log(""); - console.log("Usage:"); - console.log(" snarkjs ... "); - console.log(" or snarkjs ... "); - console.log(""); - console.log("Type snarkjs --help to get more information for that command"); - console.log(""); - console.log("Full Command Description"); - console.log("============ ================="); - for (let i=0; i. -*/ - + } + function helpAll() { + printVersion(); + epilog(); + console.log(""); + console.log("Usage:"); + console.log(" snarkjs ... "); + console.log(" or snarkjs ... "); + console.log(""); + console.log("Type snarkjs --help to get more information for that command"); + console.log(""); + console.log("Full Command Description"); + console.log("============ ================="); + for (let i = 0; i < commands.length; i++) { + const cmd = commands[i]; + let S = ""; + const pl = parseLine(cmd.cmd); + S += pl.cmd.join(" "); + while (S.length < 30) S = S + " "; + S += cmd.description; + console.log(S); + S = " Usage: snarkjs "; + if (cmd.alias) if (Array.isArray(cmd.alias)) S += cmd.alias[0]; + else S += cmd.alias; + else S += pl.cmd.join(" "); + S += " " + pl.params.join(" "); + console.log(S); + } + } + function helpCmd(cmd) { + if (typeof cmd == "undefined") cmd = selectedCommand; + if (typeof cmd == "undefined") return helpAll(); + printVersion(); + epilog(); + console.log(""); + if (cmd.longDescription) console.log(cmd.longDescription); + else console.log(cmd.description); + console.log("Usage: "); + console.log(" snarkjs " + cmd.cmd); + const pl = parseLine(cmd.cmd); + let S = " or snarkjs "; + if (cmd.alias) if (Array.isArray(cmd.alias)) S += cmd.alias[0]; + else S += cmd.alias; + else S += pl.cmd.join(" "); + S += " " + pl.params.join(" "); + console.log(S); + console.log(""); + } +} +//#endregion +//#region src/keypair.js function hashToG2(curve, hash) { - const hashV = new DataView(hash.buffer, hash.byteOffset, hash.byteLength); - const seed = []; - for (let i=0; i<8; i++) { - seed[i] = hashV.getUint32(i*4); - } - - const rng = new ffjavascript.ChaCha(seed); - - const g2_sp = curve.G2.fromRng(rng); - - return g2_sp; -} - + const hashV = new DataView(hash.buffer, hash.byteOffset, hash.byteLength); + const seed = []; + for (let i = 0; i < 8; i++) seed[i] = hashV.getUint32(i * 4); + const rng = new ffjavascript.ChaCha(seed); + return curve.G2.fromRng(rng); +} function getG2sp(curve, persinalization, challenge, g1s, g1sx) { - - const h = blake2b.blake2b.create({ dkLen: 64 }); - const b1 = new Uint8Array([persinalization]); - h.update(b1); - h.update(challenge); - const b3 = curve.G1.toUncompressed(g1s); - h.update( b3); - const b4 = curve.G1.toUncompressed(g1sx); - h.update( b4); - const hash =h.digest(); - - return hashToG2(curve, hash); -} - -function calculatePubKey(k, curve, personalization, challengeHash, rng ) { - k.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); - k.g1_sx = curve.G1.toAffine(curve.G1.timesFr(k.g1_s, k.prvKey)); - k.g2_sp = curve.G2.toAffine(getG2sp(curve, personalization, challengeHash, k.g1_s, k.g1_sx)); - k.g2_spx = curve.G2.toAffine(curve.G2.timesFr(k.g2_sp, k.prvKey)); - return k; -} - + const h = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + const b1 = new Uint8Array([persinalization]); + h.update(b1); + h.update(challenge); + const b3 = curve.G1.toUncompressed(g1s); + h.update(b3); + const b4 = curve.G1.toUncompressed(g1sx); + h.update(b4); + return hashToG2(curve, h.digest()); +} +function calculatePubKey(k, curve, personalization, challengeHash, rng) { + k.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); + k.g1_sx = curve.G1.toAffine(curve.G1.timesFr(k.g1_s, k.prvKey)); + k.g2_sp = curve.G2.toAffine(getG2sp(curve, personalization, challengeHash, k.g1_s, k.g1_sx)); + k.g2_spx = curve.G2.toAffine(curve.G2.timesFr(k.g2_sp, k.prvKey)); + return k; +} function createPTauKey(curve, challengeHash, rng) { - const key = { - tau: {}, - alpha: {}, - beta: {} - }; - key.tau.prvKey = curve.Fr.fromRng(rng); - key.alpha.prvKey = curve.Fr.fromRng(rng); - key.beta.prvKey = curve.Fr.fromRng(rng); - calculatePubKey(key.tau, curve, 0, challengeHash, rng); - calculatePubKey(key.alpha, curve, 1, challengeHash, rng); - calculatePubKey(key.beta, curve, 2, challengeHash, rng); - return key; -} - -const bls12381r = ffjavascript.Scalar.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16); -const bn128r = ffjavascript.Scalar.e("21888242871839275222246405745257275088548364400416034343698204186575808495617"); - -const bls12381q = ffjavascript.Scalar.e("1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", 16); -const bn128q = ffjavascript.Scalar.e("21888242871839275222246405745257275088696311157297823662689037894645226208583"); - + const key = { + tau: {}, + alpha: {}, + beta: {} + }; + key.tau.prvKey = curve.Fr.fromRng(rng); + key.alpha.prvKey = curve.Fr.fromRng(rng); + key.beta.prvKey = curve.Fr.fromRng(rng); + calculatePubKey(key.tau, curve, 0, challengeHash, rng); + calculatePubKey(key.alpha, curve, 1, challengeHash, rng); + calculatePubKey(key.beta, curve, 2, challengeHash, rng); + return key; +} +//#endregion +//#region src/curves.js +var bls12381r = ffjavascript.Scalar.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16); +var bn128r = ffjavascript.Scalar.e("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +var bls12381q = ffjavascript.Scalar.e("1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", 16); +var bn128q = ffjavascript.Scalar.e("21888242871839275222246405745257275088696311157297823662689037894645226208583"); async function getCurveFromR(r, options) { - let curve; - // check that options param is defined and that options.singleThread is defined - let singleThread = options && options.singleThread; - if (ffjavascript.Scalar.eq(r, bn128r)) { - curve = await ffjavascript.buildBn128(singleThread); - } else if (ffjavascript.Scalar.eq(r, bls12381r)) { - curve = await ffjavascript.buildBls12381(singleThread); - } else { - throw new Error(`Curve not supported: ${ffjavascript.Scalar.toString(r)}`); - } - return curve; -} - + let curve; + let singleThread = options && options.singleThread; + if (ffjavascript.Scalar.eq(r, bn128r)) curve = await (0, ffjavascript.buildBn128)(singleThread); + else if (ffjavascript.Scalar.eq(r, bls12381r)) curve = await (0, ffjavascript.buildBls12381)(singleThread); + else throw new Error(`Curve not supported: ${ffjavascript.Scalar.toString(r)}`); + return curve; +} async function getCurveFromQ(q, options) { - let curve; - let singleThread = options && options.singleThread; - if (ffjavascript.Scalar.eq(q, bn128q)) { - curve = await ffjavascript.buildBn128(singleThread); - } else if (ffjavascript.Scalar.eq(q, bls12381q)) { - curve = await ffjavascript.buildBls12381(singleThread); - } else { - throw new Error(`Curve not supported: ${ffjavascript.Scalar.toString(q)}`); - } - return curve; -} - + let curve; + let singleThread = options && options.singleThread; + if (ffjavascript.Scalar.eq(q, bn128q)) curve = await (0, ffjavascript.buildBn128)(singleThread); + else if (ffjavascript.Scalar.eq(q, bls12381q)) curve = await (0, ffjavascript.buildBls12381)(singleThread); + else throw new Error(`Curve not supported: ${ffjavascript.Scalar.toString(q)}`); + return curve; +} async function getCurveFromName(name, options) { - let curve; - let singleThread = options && options.singleThread; - const normName = normalizeName(name); - if (["BN128", "BN254", "ALTBN128"].indexOf(normName) >= 0) { - curve = await ffjavascript.buildBn128(singleThread); - } else if (["BLS12381"].indexOf(normName) >= 0) { - curve = await ffjavascript.buildBls12381(singleThread); - } else { - throw new Error(`Curve not supported: ${name}`); - } - return curve; - - function normalizeName(n) { - return n.toUpperCase().match(/[A-Za-z0-9]+/g).join(""); - } - -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - + let curve; + let singleThread = options && options.singleThread; + const normName = normalizeName(name); + if ([ + "BN128", + "BN254", + "ALTBN128" + ].indexOf(normName) >= 0) curve = await (0, ffjavascript.buildBn128)(singleThread); + else if (["BLS12381"].indexOf(normName) >= 0) curve = await (0, ffjavascript.buildBls12381)(singleThread); + else throw new Error(`Curve not supported: ${name}`); + return curve; + function normalizeName(n) { + return n.toUpperCase().match(/[A-Za-z0-9]+/g).join(""); + } +} +//#endregion +//#region src/powersoftau_utils.js async function writePTauHeader(fd, curve, power, ceremonyPower) { - // Write the header - /////////// - - if (! ceremonyPower) ceremonyPower = power; - await fd.writeULE32(1); // Header type - const pHeaderSize = fd.pos; - await fd.writeULE64(0); // Temporally set to 0 length - - await fd.writeULE32(curve.F1.n64*8); - - const buff = new Uint8Array(curve.F1.n8); - ffjavascript.Scalar.toRprLE(buff, 0, curve.q, curve.F1.n8); - await fd.write(buff); - await fd.writeULE32(power); // power - await fd.writeULE32(ceremonyPower); // power - - const headerSize = fd.pos - pHeaderSize - 8; - - const oldPos = fd.pos; - - await fd.writeULE64(headerSize, pHeaderSize); - - fd.pos = oldPos; -} - + if (!ceremonyPower) ceremonyPower = power; + await fd.writeULE32(1); + const pHeaderSize = fd.pos; + await fd.writeULE64(0); + await fd.writeULE32(curve.F1.n64 * 8); + const buff = new Uint8Array(curve.F1.n8); + ffjavascript.Scalar.toRprLE(buff, 0, curve.q, curve.F1.n8); + await fd.write(buff); + await fd.writeULE32(power); + await fd.writeULE32(ceremonyPower); + const headerSize = fd.pos - pHeaderSize - 8; + const oldPos = fd.pos; + await fd.writeULE64(headerSize, pHeaderSize); + fd.pos = oldPos; +} async function readPTauHeader(fd, sections) { - if (!sections[1]) throw new Error(fd.fileName + ": File has no header"); - if (sections[1].length>1) throw new Error(fd.fileName +": File has more than one header"); - - fd.pos = sections[1][0].p; - const n8 = await fd.readULE32(); - const buff = await fd.read(n8); - const q = ffjavascript.Scalar.fromRprLE(buff); - - const curve = await getCurveFromQ(q); - - if (curve.F1.n64*8 != n8) throw new Error(fd.fileName +": Invalid size"); - - const power = await fd.readULE32(); - const ceremonyPower = await fd.readULE32(); - - if (fd.pos-sections[1][0].p != sections[1][0].size) throw new Error("Invalid PTau header size"); - - return {curve, power, ceremonyPower}; -} - - + if (!sections[1]) throw new Error(fd.fileName + ": File has no header"); + if (sections[1].length > 1) throw new Error(fd.fileName + ": File has more than one header"); + fd.pos = sections[1][0].p; + const n8 = await fd.readULE32(); + const buff = await fd.read(n8); + const curve = await getCurveFromQ(ffjavascript.Scalar.fromRprLE(buff)); + if (curve.F1.n64 * 8 != n8) throw new Error(fd.fileName + ": Invalid size"); + const power = await fd.readULE32(); + const ceremonyPower = await fd.readULE32(); + if (fd.pos - sections[1][0].p != sections[1][0].size) throw new Error("Invalid PTau header size"); + return { + curve, + power, + ceremonyPower + }; +} async function readPtauPubKey(fd, curve, montgomery) { - - const buff = await fd.read(curve.F1.n8*2*6 + curve.F2.n8*2*3); - - return fromPtauPubKeyRpr(buff, 0, curve, montgomery); + return fromPtauPubKeyRpr(await fd.read(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3), 0, curve, montgomery); } - function fromPtauPubKeyRpr(buff, pos, curve, montgomery) { - - const key = { - tau: {}, - alpha: {}, - beta: {} - }; - - key.tau.g1_s = readG1(); - key.tau.g1_sx = readG1(); - key.alpha.g1_s = readG1(); - key.alpha.g1_sx = readG1(); - key.beta.g1_s = readG1(); - key.beta.g1_sx = readG1(); - key.tau.g2_spx = readG2(); - key.alpha.g2_spx = readG2(); - key.beta.g2_spx = readG2(); - - return key; - - function readG1() { - let p; - if (montgomery) { - p = curve.G1.fromRprLEM( buff, pos ); - } else { - p = curve.G1.fromRprUncompressed( buff, pos ); - } - pos += curve.G1.F.n8*2; - return p; - } - - function readG2() { - let p; - if (montgomery) { - p = curve.G2.fromRprLEM( buff, pos ); - } else { - p = curve.G2.fromRprUncompressed( buff, pos ); - } - pos += curve.G2.F.n8*2; - return p; - } -} - + const key = { + tau: {}, + alpha: {}, + beta: {} + }; + key.tau.g1_s = readG1(); + key.tau.g1_sx = readG1(); + key.alpha.g1_s = readG1(); + key.alpha.g1_sx = readG1(); + key.beta.g1_s = readG1(); + key.beta.g1_sx = readG1(); + key.tau.g2_spx = readG2(); + key.alpha.g2_spx = readG2(); + key.beta.g2_spx = readG2(); + return key; + function readG1() { + let p; + if (montgomery) p = curve.G1.fromRprLEM(buff, pos); + else p = curve.G1.fromRprUncompressed(buff, pos); + pos += curve.G1.F.n8 * 2; + return p; + } + function readG2() { + let p; + if (montgomery) p = curve.G2.fromRprLEM(buff, pos); + else p = curve.G2.fromRprUncompressed(buff, pos); + pos += curve.G2.F.n8 * 2; + return p; + } +} function toPtauPubKeyRpr(buff, pos, curve, key, montgomery) { - - writeG1(key.tau.g1_s); - writeG1(key.tau.g1_sx); - writeG1(key.alpha.g1_s); - writeG1(key.alpha.g1_sx); - writeG1(key.beta.g1_s); - writeG1(key.beta.g1_sx); - writeG2(key.tau.g2_spx); - writeG2(key.alpha.g2_spx); - writeG2(key.beta.g2_spx); - - async function writeG1(p) { - if (montgomery) { - curve.G1.toRprLEM(buff, pos, p); - } else { - curve.G1.toRprUncompressed(buff, pos, p); - } - pos += curve.F1.n8*2; - } - - async function writeG2(p) { - if (montgomery) { - curve.G2.toRprLEM(buff, pos, p); - } else { - curve.G2.toRprUncompressed(buff, pos, p); - } - pos += curve.F2.n8*2; - } - - return buff; -} - + writeG1(key.tau.g1_s); + writeG1(key.tau.g1_sx); + writeG1(key.alpha.g1_s); + writeG1(key.alpha.g1_sx); + writeG1(key.beta.g1_s); + writeG1(key.beta.g1_sx); + writeG2(key.tau.g2_spx); + writeG2(key.alpha.g2_spx); + writeG2(key.beta.g2_spx); + async function writeG1(p) { + if (montgomery) curve.G1.toRprLEM(buff, pos, p); + else curve.G1.toRprUncompressed(buff, pos, p); + pos += curve.F1.n8 * 2; + } + async function writeG2(p) { + if (montgomery) curve.G2.toRprLEM(buff, pos, p); + else curve.G2.toRprUncompressed(buff, pos, p); + pos += curve.F2.n8 * 2; + } + return buff; +} async function writePtauPubKey(fd, curve, key, montgomery) { - const buff = new Uint8Array(curve.F1.n8*2*6 + curve.F2.n8*2*3); - toPtauPubKeyRpr(buff, 0, curve, key, montgomery); - await fd.write(buff); + const buff = new Uint8Array(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3); + toPtauPubKeyRpr(buff, 0, curve, key, montgomery); + await fd.write(buff); } - async function readContribution$1(fd, curve) { - const c = {}; - - c.tauG1 = await readG1(); - c.tauG2 = await readG2(); - c.alphaG1 = await readG1(); - c.betaG1 = await readG1(); - c.betaG2 = await readG2(); - c.key = await readPtauPubKey(fd, curve, true); - c.partialHash = await fd.read(216); - c.nextChallenge = await fd.read(64); - c.type = await fd.readULE32(); - - const buffV = new Uint8Array(curve.G1.F.n8*2*6+curve.G2.F.n8*2*3); - toPtauPubKeyRpr(buffV, 0, curve, c.key, false); - - const responseHasher = fromPartialHash(c.partialHash); - responseHasher.update(buffV); - c.responseHash = responseHasher.digest(); - - const paramLength = await fd.readULE32(); - const curPos = fd.pos; - let lastType =0; - while (fd.pos-curPos < paramLength) { - const buffType = await readDV(1); - if (buffType[0]<= lastType) throw new Error("Parameters in the contribution must be sorted"); - lastType = buffType[0]; - if (buffType[0]==1) { // Name - const buffLen = await readDV(1); - const buffStr = await readDV(buffLen[0]); - c.name = new TextDecoder().decode(buffStr); - } else if (buffType[0]==2) { - const buffExp = await readDV(1); - c.numIterationsExp = buffExp[0]; - } else if (buffType[0]==3) { - const buffLen = await readDV(1); - c.beaconHash = await readDV(buffLen[0]); - } else { - throw new Error("Parameter not recognized"); - } - } - if (fd.pos != curPos + paramLength) { - throw new Error("Parameters do not match"); - } - - return c; - - async function readG1() { - const pBuff = await fd.read(curve.G1.F.n8*2); - return curve.G1.fromRprLEM( pBuff ); - } - - async function readG2() { - const pBuff = await fd.read(curve.G2.F.n8*2); - return curve.G2.fromRprLEM( pBuff ); - } - - async function readDV(n) { - const b = await fd.read(n); - return new Uint8Array(b); - } -} - + const c = {}; + c.tauG1 = await readG1(); + c.tauG2 = await readG2(); + c.alphaG1 = await readG1(); + c.betaG1 = await readG1(); + c.betaG2 = await readG2(); + c.key = await readPtauPubKey(fd, curve, true); + c.partialHash = await fd.read(216); + c.nextChallenge = await fd.read(64); + c.type = await fd.readULE32(); + const buffV = new Uint8Array(curve.G1.F.n8 * 2 * 6 + curve.G2.F.n8 * 2 * 3); + toPtauPubKeyRpr(buffV, 0, curve, c.key, false); + const responseHasher = fromPartialHash(c.partialHash); + responseHasher.update(buffV); + c.responseHash = responseHasher.digest(); + const paramLength = await fd.readULE32(); + const curPos = fd.pos; + let lastType = 0; + while (fd.pos - curPos < paramLength) { + const buffType = await readDV(1); + if (buffType[0] <= lastType) throw new Error("Parameters in the contribution must be sorted"); + lastType = buffType[0]; + if (buffType[0] == 1) { + const buffStr = await readDV((await readDV(1))[0]); + c.name = new TextDecoder().decode(buffStr); + } else if (buffType[0] == 2) c.numIterationsExp = (await readDV(1))[0]; + else if (buffType[0] == 3) c.beaconHash = await readDV((await readDV(1))[0]); + else throw new Error("Parameter not recognized"); + } + if (fd.pos != curPos + paramLength) throw new Error("Parameters do not match"); + return c; + async function readG1() { + const pBuff = await fd.read(curve.G1.F.n8 * 2); + return curve.G1.fromRprLEM(pBuff); + } + async function readG2() { + const pBuff = await fd.read(curve.G2.F.n8 * 2); + return curve.G2.fromRprLEM(pBuff); + } + async function readDV(n) { + const b = await fd.read(n); + return new Uint8Array(b); + } +} async function readContributions(fd, curve, sections) { - if (!sections[7]) throw new Error(fd.fileName + ": File has no contributions"); - if (sections[7][0].length>1) throw new Error(fd.fileName +": File has more than one contributions section"); - - fd.pos = sections[7][0].p; - const nContributions = await fd.readULE32(); - const contributions = []; - for (let i=0; i 1) throw new Error(fd.fileName + ": File has more than one contributions section"); + fd.pos = sections[7][0].p; + const nContributions = await fd.readULE32(); + const contributions = []; + for (let i = 0; i < nContributions; i++) { + const c = await readContribution$1(fd, curve); + c.id = i + 1; + contributions.push(c); + } + if (fd.pos - sections[7][0].p != sections[7][0].size) throw new Error("Invalid contribution section size"); + return contributions; +} async function writeContribution$1(fd, curve, contribution) { - - const buffG1 = new Uint8Array(curve.F1.n8*2); - const buffG2 = new Uint8Array(curve.F2.n8*2); - await writeG1(contribution.tauG1); - await writeG2(contribution.tauG2); - await writeG1(contribution.alphaG1); - await writeG1(contribution.betaG1); - await writeG2(contribution.betaG2); - await writePtauPubKey(fd, curve, contribution.key, true); - await fd.write(contribution.partialHash); - await fd.write(contribution.nextChallenge); - await fd.writeULE32(contribution.type || 0); - - const params = []; - if (contribution.name) { - params.push(1); // Param Name - const nameData = new TextEncoder("utf-8").encode(contribution.name.substring(0,64)); - params.push(nameData.byteLength); - for (let i=0; i0) { - const paramsBuff = new Uint8Array(params); - await fd.writeULE32(paramsBuff.byteLength); - await fd.write(paramsBuff); - } else { - await fd.writeULE32(0); - } - - - async function writeG1(p) { - curve.G1.toRprLEM(buffG1, 0, p); - await fd.write(buffG1); - } - - async function writeG2(p) { - curve.G2.toRprLEM(buffG2, 0, p); - await fd.write(buffG2); - } - -} - + const buffG1 = new Uint8Array(curve.F1.n8 * 2); + const buffG2 = new Uint8Array(curve.F2.n8 * 2); + await writeG1(contribution.tauG1); + await writeG2(contribution.tauG2); + await writeG1(contribution.alphaG1); + await writeG1(contribution.betaG1); + await writeG2(contribution.betaG2); + await writePtauPubKey(fd, curve, contribution.key, true); + await fd.write(contribution.partialHash); + await fd.write(contribution.nextChallenge); + await fd.writeULE32(contribution.type || 0); + const params = []; + if (contribution.name) { + params.push(1); + const nameData = new TextEncoder("utf-8").encode(contribution.name.substring(0, 64)); + params.push(nameData.byteLength); + for (let i = 0; i < nameData.byteLength; i++) params.push(nameData[i]); + } + if (contribution.type == 1) { + params.push(2); + params.push(contribution.numIterationsExp); + params.push(3); + params.push(contribution.beaconHash.byteLength); + for (let i = 0; i < contribution.beaconHash.byteLength; i++) params.push(contribution.beaconHash[i]); + } + if (params.length > 0) { + const paramsBuff = new Uint8Array(params); + await fd.writeULE32(paramsBuff.byteLength); + await fd.write(paramsBuff); + } else await fd.writeULE32(0); + async function writeG1(p) { + curve.G1.toRprLEM(buffG1, 0, p); + await fd.write(buffG1); + } + async function writeG2(p) { + curve.G2.toRprLEM(buffG2, 0, p); + await fd.write(buffG2); + } +} async function writeContributions(fd, curve, contributions) { - - await fd.writeULE32(7); // Header type - const pContributionsSize = fd.pos; - await fd.writeULE64(0); // Temporally set to 0 length - - await fd.writeULE32(contributions.length); - for (let i=0; i< contributions.length; i++) { - await writeContribution$1(fd, curve, contributions[i]); - } - const contributionsSize = fd.pos - pContributionsSize - 8; - - const oldPos = fd.pos; - - await fd.writeULE64(contributionsSize, pContributionsSize); - fd.pos = oldPos; -} - + await fd.writeULE32(7); + const pContributionsSize = fd.pos; + await fd.writeULE64(0); + await fd.writeULE32(contributions.length); + for (let i = 0; i < contributions.length; i++) await writeContribution$1(fd, curve, contributions[i]); + const contributionsSize = fd.pos - pContributionsSize - 8; + const oldPos = fd.pos; + await fd.writeULE64(contributionsSize, pContributionsSize); + fd.pos = oldPos; +} function calculateFirstChallengeHash(curve, power, logger) { - if (logger) logger.debug("Calculating First Challenge Hash"); - - const hasher = blake2b.blake2b.create({ dkLen: 64 }); - - const vG1 = new Uint8Array(curve.G1.F.n8*2); - const vG2 = new Uint8Array(curve.G2.F.n8*2); - curve.G1.toRprUncompressed(vG1, 0, curve.G1.g); - curve.G2.toRprUncompressed(vG2, 0, curve.G2.g); - - hasher.update(blake2b.blake2b.create({ dkLen: 64 }).digest()); - - let n; - - n=(2 ** power)*2 -1; - if (logger) logger.debug("Calculate Initial Hash: tauG1"); - hashBlock(vG1, n); - n= 2 ** power; - if (logger) logger.debug("Calculate Initial Hash: tauG2"); - hashBlock(vG2, n); - if (logger) logger.debug("Calculate Initial Hash: alphaTauG1"); - hashBlock(vG1, n); - if (logger) logger.debug("Calculate Initial Hash: betaTauG1"); - hashBlock(vG1, n); - hasher.update(vG2); - - return hasher.digest(); - - function hashBlock(buff, n) { - // this block size is a good compromise between speed and the maximum - // input size of the Blake2b update method (65,535,720 bytes). - const blockSize = 341000; - const nBlocks = Math.floor(n / blockSize); - const rem = n % blockSize; - const bigBuff = new Uint8Array(blockSize * buff.byteLength); - for (let i=0; i. -*/ - + return createPTauKey(curve, challengeHash, await rngFromBeaconParams(beaconHash, numIterationsExp)); +} +//#endregion +//#region src/powersoftau_new.js async function newAccumulator(curve, power, fileName, logger) { - - const fd = await binFileUtils__namespace.createBinFile(fileName, "ptau", 1, 7); - - await writePTauHeader(fd, curve, power, 0); - - const buffG1 = curve.G1.oneAffine; - const buffG2 = curve.G2.oneAffine; - - // Write tauG1 - /////////// - await binFileUtils__namespace.startWriteSection(fd, 2); - const nTauG1 = (2 ** power) * 2 -1; - for (let i=0; i< nTauG1; i++) { - await fd.write(buffG1); - if ((logger)&&((i%100000) == 0)&&i) logger.log("tauG1: " + i); - } - await binFileUtils__namespace.endWriteSection(fd); - - // Write tauG2 - /////////// - await binFileUtils__namespace.startWriteSection(fd, 3); - const nTauG2 = (2 ** power); - for (let i=0; i< nTauG2; i++) { - await fd.write(buffG2); - if ((logger)&&((i%100000) == 0)&&i) logger.log("tauG2: " + i); - } - await binFileUtils__namespace.endWriteSection(fd); - - // Write alphaTauG1 - /////////// - await binFileUtils__namespace.startWriteSection(fd, 4); - const nAlfaTauG1 = (2 ** power); - for (let i=0; i< nAlfaTauG1; i++) { - await fd.write(buffG1); - if ((logger)&&((i%100000) == 0)&&i) logger.log("alphaTauG1: " + i); - } - await binFileUtils__namespace.endWriteSection(fd); - - // Write betaTauG1 - /////////// - await binFileUtils__namespace.startWriteSection(fd, 5); - const nBetaTauG1 = (2 ** power); - for (let i=0; i< nBetaTauG1; i++) { - await fd.write(buffG1); - if ((logger)&&((i%100000) == 0)&&i) logger.log("betaTauG1: " + i); - } - await binFileUtils__namespace.endWriteSection(fd); - - // Write betaG2 - /////////// - await binFileUtils__namespace.startWriteSection(fd, 6); - await fd.write(buffG2); - await binFileUtils__namespace.endWriteSection(fd); - - // Contributions - /////////// - await binFileUtils__namespace.startWriteSection(fd, 7); - await fd.writeULE32(0); // 0 Contributions - await binFileUtils__namespace.endWriteSection(fd); - - await fd.close(); - - const firstChallengeHash = calculateFirstChallengeHash(curve, power, logger); - - if (logger) logger.debug(formatHash(blake2b.blake2b.create({ dkLen: 64 }).digest(), "Blank Contribution Hash:")); - - if (logger) logger.info(formatHash(firstChallengeHash, "First Contribution Hash:")); - - return firstChallengeHash; - -} - -// Format of the outpu - + const fd = await _iden3_binfileutils.createBinFile(fileName, "ptau", 1, 7); + await writePTauHeader(fd, curve, power, 0); + const buffG1 = curve.G1.oneAffine; + const buffG2 = curve.G2.oneAffine; + await _iden3_binfileutils.startWriteSection(fd, 2); + const nTauG1 = 2 ** power * 2 - 1; + for (let i = 0; i < nTauG1; i++) { + await fd.write(buffG1); + if (logger && i % 1e5 == 0 && i) logger.log("tauG1: " + i); + } + await _iden3_binfileutils.endWriteSection(fd); + await _iden3_binfileutils.startWriteSection(fd, 3); + const nTauG2 = 2 ** power; + for (let i = 0; i < nTauG2; i++) { + await fd.write(buffG2); + if (logger && i % 1e5 == 0 && i) logger.log("tauG2: " + i); + } + await _iden3_binfileutils.endWriteSection(fd); + await _iden3_binfileutils.startWriteSection(fd, 4); + const nAlfaTauG1 = 2 ** power; + for (let i = 0; i < nAlfaTauG1; i++) { + await fd.write(buffG1); + if (logger && i % 1e5 == 0 && i) logger.log("alphaTauG1: " + i); + } + await _iden3_binfileutils.endWriteSection(fd); + await _iden3_binfileutils.startWriteSection(fd, 5); + const nBetaTauG1 = 2 ** power; + for (let i = 0; i < nBetaTauG1; i++) { + await fd.write(buffG1); + if (logger && i % 1e5 == 0 && i) logger.log("betaTauG1: " + i); + } + await _iden3_binfileutils.endWriteSection(fd); + await _iden3_binfileutils.startWriteSection(fd, 6); + await fd.write(buffG2); + await _iden3_binfileutils.endWriteSection(fd); + await _iden3_binfileutils.startWriteSection(fd, 7); + await fd.writeULE32(0); + await _iden3_binfileutils.endWriteSection(fd); + await fd.close(); + const firstChallengeHash = calculateFirstChallengeHash(curve, power, logger); + if (logger) logger.debug(formatHash(_noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }).digest(), "Blank Contribution Hash:")); + if (logger) logger.info(formatHash(firstChallengeHash, "First Contribution Hash:")); + return firstChallengeHash; +} +//#endregion +//#region src/powersoftau_export_challenge.js async function exportChallenge(pTauFilename, challengeFilename, logger) { - const {fd: fdFrom, sections} = await binFileUtils__namespace.readBinFile(pTauFilename, "ptau", 1); - - const {curve, power} = await readPTauHeader(fdFrom, sections); - - const contributions = await readContributions(fdFrom, curve, sections); - let lastResponseHash, curChallengeHash; - if (contributions.length == 0) { - lastResponseHash = blake2b.blake2b.create({ dkLen: 64 }).digest(); - curChallengeHash = calculateFirstChallengeHash(curve, power); - } else { - lastResponseHash = contributions[contributions.length-1].responseHash; - curChallengeHash = contributions[contributions.length-1].nextChallenge; - } - - if (logger) logger.info(formatHash(lastResponseHash, "Last Response Hash: ")); - - if (logger) logger.info(formatHash(curChallengeHash, "New Challenge Hash: ")); - - - const fdTo = await fastFile__namespace.createOverride(challengeFilename); - - const toHash = blake2b.blake2b.create({ dkLen: 64 }); - await fdTo.write(lastResponseHash); - toHash.update(lastResponseHash); - - await exportSection(2, "G1", (2 ** power) * 2 -1, "tauG1"); - await exportSection(3, "G2", (2 ** power) , "tauG2"); - await exportSection(4, "G1", (2 ** power) , "alphaTauG1"); - await exportSection(5, "G1", (2 ** power) , "betaTauG1"); - await exportSection(6, "G2", 1 , "betaG2"); - - await fdFrom.close(); - await fdTo.close(); - - const calcCurChallengeHash = toHash.digest(); - - if (!hashIsEqual (curChallengeHash, calcCurChallengeHash)) { - if (logger) logger.info(formatHash(calcCurChallengeHash, "Calc Curret Challenge Hash: ")); - - if (logger) logger.error("PTau file is corrupted. Calculated new challenge hash does not match with the eclared one"); - throw new Error("PTau file is corrupted. Calculated new challenge hash does not match with the eclared one"); - } - - return curChallengeHash; - - async function exportSection(sectionId, groupName, nPoints, sectionName) { - const G = curve[groupName]; - const sG = G.F.n8*2; - const nPointsChunk = Math.floor((1<<24)/sG); - - await binFileUtils__namespace.startReadUniqueSection(fdFrom, sections, sectionId); - for (let i=0; i< nPoints; i+= nPointsChunk) { - if (logger) logger.debug(`Exporting ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints-i, nPointsChunk); - let buff; - buff = await fdFrom.read(n*sG); - buff = await G.batchLEMtoU(buff); - await fdTo.write(buff); - toHash.update(buff); - } - await binFileUtils__namespace.endReadSection(fdFrom); - } - - -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - + const { fd: fdFrom, sections } = await _iden3_binfileutils.readBinFile(pTauFilename, "ptau", 1); + const { curve, power } = await readPTauHeader(fdFrom, sections); + const contributions = await readContributions(fdFrom, curve, sections); + let lastResponseHash, curChallengeHash; + if (contributions.length == 0) { + lastResponseHash = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }).digest(); + curChallengeHash = calculateFirstChallengeHash(curve, power); + } else { + lastResponseHash = contributions[contributions.length - 1].responseHash; + curChallengeHash = contributions[contributions.length - 1].nextChallenge; + } + if (logger) logger.info(formatHash(lastResponseHash, "Last Response Hash: ")); + if (logger) logger.info(formatHash(curChallengeHash, "New Challenge Hash: ")); + const fdTo = await fastfile.createOverride(challengeFilename); + const toHash = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + await fdTo.write(lastResponseHash); + toHash.update(lastResponseHash); + await exportSection(2, "G1", 2 ** power * 2 - 1, "tauG1"); + await exportSection(3, "G2", 2 ** power, "tauG2"); + await exportSection(4, "G1", 2 ** power, "alphaTauG1"); + await exportSection(5, "G1", 2 ** power, "betaTauG1"); + await exportSection(6, "G2", 1, "betaG2"); + await fdFrom.close(); + await fdTo.close(); + const calcCurChallengeHash = toHash.digest(); + if (!hashIsEqual(curChallengeHash, calcCurChallengeHash)) { + if (logger) logger.info(formatHash(calcCurChallengeHash, "Calc Curret Challenge Hash: ")); + if (logger) logger.error("PTau file is corrupted. Calculated new challenge hash does not match with the eclared one"); + throw new Error("PTau file is corrupted. Calculated new challenge hash does not match with the eclared one"); + } + return curChallengeHash; + async function exportSection(sectionId, groupName, nPoints, sectionName) { + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const nPointsChunk = Math.floor((1 << 24) / sG); + await _iden3_binfileutils.startReadUniqueSection(fdFrom, sections, sectionId); + for (let i = 0; i < nPoints; i += nPointsChunk) { + if (logger) logger.debug(`Exporting ${sectionName}: ${i}/${nPoints}`); + const n = Math.min(nPoints - i, nPointsChunk); + let buff; + buff = await fdFrom.read(n * sG); + buff = await G.batchLEMtoU(buff); + await fdTo.write(buff); + toHash.update(buff); + } + await _iden3_binfileutils.endReadSection(fdFrom); + } +} +//#endregion +//#region src/powersoftau_import.js async function importResponse(oldPtauFilename, contributionFilename, newPTauFilename, name, importPoints, logger) { - - const noHash = new Uint8Array(64); - for (let i=0; i<64; i++) noHash[i] = 0xFF; - - const {fd: fdOld, sections} = await binFileUtils__namespace.readBinFile(oldPtauFilename, "ptau", 1); - const {curve, power} = await readPTauHeader(fdOld, sections); - const contributions = await readContributions(fdOld, curve, sections); - const currentContribution = {}; - - if (name) currentContribution.name = name; - - const sG1 = curve.F1.n8*2; - const scG1 = curve.F1.n8; // Compressed size - const sG2 = curve.F2.n8*2; - const scG2 = curve.F2.n8; // Compressed size - - const fdResponse = await fastFile__namespace.readExisting(contributionFilename); - - if (fdResponse.totalSize != - 64 + // Old Hash - ((2 ** power)*2-1)*scG1 + - (2 ** power)*scG2 + - (2 ** power)*scG1 + - (2 ** power)*scG1 + - scG2 + - sG1*6 + sG2*3) - throw new Error("Size of the contribution is invalid"); - - let lastChallengeHash; - - if (contributions.length>0) { - lastChallengeHash = contributions[contributions.length-1].nextChallenge; - } else { - lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); - } - - const fdNew = await binFileUtils__namespace.createBinFile(newPTauFilename, "ptau", 1, importPoints ? 7: 2); - await writePTauHeader(fdNew, curve, power); - - const contributionPreviousHash = await fdResponse.read(64); - - if (hashIsEqual(noHash,lastChallengeHash)) { - lastChallengeHash = contributionPreviousHash; - contributions[contributions.length-1].nextChallenge = lastChallengeHash; - } - - if(!hashIsEqual(contributionPreviousHash,lastChallengeHash)) - throw new Error("Wrong contribution. This contribution is not based on the previous hash"); - - const hasherResponse = blake2b.blake2b.create({ dkLen: 64 }); - hasherResponse.update(contributionPreviousHash); - - const startSections = []; - let res; - res = await processSection(fdResponse, fdNew, "G1", 2, (2 ** power) * 2 -1, [1], "tauG1"); - currentContribution.tauG1 = res[0]; - res = await processSection(fdResponse, fdNew, "G2", 3, (2 ** power) , [1], "tauG2"); - currentContribution.tauG2 = res[0]; - res = await processSection(fdResponse, fdNew, "G1", 4, (2 ** power) , [0], "alphaG1"); - currentContribution.alphaG1 = res[0]; - res = await processSection(fdResponse, fdNew, "G1", 5, (2 ** power) , [0], "betaG1"); - currentContribution.betaG1 = res[0]; - res = await processSection(fdResponse, fdNew, "G2", 6, 1 , [0], "betaG2"); - currentContribution.betaG2 = res[0]; - - currentContribution.partialHash = toPartialHash(hasherResponse); - - - const buffKey = await fdResponse.read(curve.F1.n8*2*6+curve.F2.n8*2*3); - - currentContribution.key = fromPtauPubKeyRpr(buffKey, 0, curve, false); - - hasherResponse.update(new Uint8Array(buffKey)); - const hashResponse = hasherResponse.digest(); - - if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); - - if (importPoints) { - const nextChallengeHasher = blake2b.blake2b.create({ dkLen: 64 }); - nextChallengeHasher.update(hashResponse); - - await hashSection(nextChallengeHasher, fdNew, "G1", 2, (2 ** power) * 2 -1, "tauG1", logger); - await hashSection(nextChallengeHasher, fdNew, "G2", 3, (2 ** power) , "tauG2", logger); - await hashSection(nextChallengeHasher, fdNew, "G1", 4, (2 ** power) , "alphaTauG1", logger); - await hashSection(nextChallengeHasher, fdNew, "G1", 5, (2 ** power) , "betaTauG1", logger); - await hashSection(nextChallengeHasher, fdNew, "G2", 6, 1 , "betaG2", logger); - - currentContribution.nextChallenge = nextChallengeHasher.digest(); - - if (logger) logger.info(formatHash(currentContribution.nextChallenge, "Next Challenge Hash: ")); - } else { - currentContribution.nextChallenge = noHash; - } - - contributions.push(currentContribution); - - await writeContributions(fdNew, curve, contributions); - - await fdResponse.close(); - await fdNew.close(); - await fdOld.close(); - - return currentContribution.nextChallenge; - - async function processSection(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { - if (importPoints) { - return await processSectionImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName); - } else { - return await processSectionNoImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName); - } - } - - async function processSectionImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { - - const G = curve[groupName]; - const scG = G.F.n8; - const sG = G.F.n8*2; - - const singularPoints = []; - - await binFileUtils__namespace.startWriteSection(fdTo, sectionId); - const nPointsChunk = Math.floor((1<<24)/sG); - - startSections[sectionId] = fdTo.pos; - - for (let i=0; i< nPoints; i += nPointsChunk) { - if (logger) logger.debug(`Importing ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints-i, nPointsChunk); - - const buffC = await fdFrom.read(n * scG); - hasherResponse.update(buffC); - - const buffLEM = await G.batchCtoLEM(buffC); - - await fdTo.write(buffLEM); - for (let j=0; j=i) && (sp < i+n)) { - const P = G.fromRprLEM(buffLEM, (sp-i)*sG); - singularPoints.push(P); - } - } - } - - await binFileUtils__namespace.endWriteSection(fdTo); - - return singularPoints; - } - - - async function processSectionNoImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { - - const G = curve[groupName]; - const scG = G.F.n8; - - const singularPoints = []; - - const nPointsChunk = Math.floor((1<<24)/scG); - - for (let i=0; i< nPoints; i += nPointsChunk) { - if (logger) logger.debug(`Importing ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints-i, nPointsChunk); - - const buffC = await fdFrom.read(n * scG); - hasherResponse.update(buffC); - - for (let j=0; j=i) && (sp < i+n)) { - const P = G.fromRprCompressed(buffC, (sp-i)*scG); - singularPoints.push(P); - } - } - } - - return singularPoints; - } - - - async function hashSection(nextChallengeHasher, fdTo, groupName, sectionId, nPoints, sectionName, logger) { - - const G = curve[groupName]; - const sG = G.F.n8*2; - const nPointsChunk = Math.floor((1<<24)/sG); - - const oldPos = fdTo.pos; - fdTo.pos = startSections[sectionId]; - - for (let i=0; i< nPoints; i += nPointsChunk) { - if (logger) logger.debug(`Hashing ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints-i, nPointsChunk); - - const buffLEM = await fdTo.read(n * sG); - - const buffU = await G.batchLEMtoU(buffLEM); - - nextChallengeHasher.update(buffU); - } - - fdTo.pos = oldPos; - } - -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ -const sameRatio$1 = sameRatio$2; - + const noHash = new Uint8Array(64); + for (let i = 0; i < 64; i++) noHash[i] = 255; + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(oldPtauFilename, "ptau", 1); + const { curve, power } = await readPTauHeader(fdOld, sections); + const contributions = await readContributions(fdOld, curve, sections); + const currentContribution = {}; + if (name) currentContribution.name = name; + const sG1 = curve.F1.n8 * 2; + const scG1 = curve.F1.n8; + const sG2 = curve.F2.n8 * 2; + const scG2 = curve.F2.n8; + const fdResponse = await fastfile.readExisting(contributionFilename); + if (fdResponse.totalSize != 64 + (2 ** power * 2 - 1) * scG1 + 2 ** power * scG2 + 2 ** power * scG1 + 2 ** power * scG1 + scG2 + sG1 * 6 + sG2 * 3) throw new Error("Size of the contribution is invalid"); + let lastChallengeHash; + if (contributions.length > 0) lastChallengeHash = contributions[contributions.length - 1].nextChallenge; + else lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); + const fdNew = await _iden3_binfileutils.createBinFile(newPTauFilename, "ptau", 1, importPoints ? 7 : 2); + await writePTauHeader(fdNew, curve, power); + const contributionPreviousHash = await fdResponse.read(64); + if (hashIsEqual(noHash, lastChallengeHash)) { + lastChallengeHash = contributionPreviousHash; + contributions[contributions.length - 1].nextChallenge = lastChallengeHash; + } + if (!hashIsEqual(contributionPreviousHash, lastChallengeHash)) throw new Error("Wrong contribution. This contribution is not based on the previous hash"); + const hasherResponse = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + hasherResponse.update(contributionPreviousHash); + const startSections = []; + let res; + res = await processSection(fdResponse, fdNew, "G1", 2, 2 ** power * 2 - 1, [1], "tauG1"); + currentContribution.tauG1 = res[0]; + res = await processSection(fdResponse, fdNew, "G2", 3, 2 ** power, [1], "tauG2"); + currentContribution.tauG2 = res[0]; + res = await processSection(fdResponse, fdNew, "G1", 4, 2 ** power, [0], "alphaG1"); + currentContribution.alphaG1 = res[0]; + res = await processSection(fdResponse, fdNew, "G1", 5, 2 ** power, [0], "betaG1"); + currentContribution.betaG1 = res[0]; + res = await processSection(fdResponse, fdNew, "G2", 6, 1, [0], "betaG2"); + currentContribution.betaG2 = res[0]; + currentContribution.partialHash = toPartialHash(hasherResponse); + const buffKey = await fdResponse.read(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3); + currentContribution.key = fromPtauPubKeyRpr(buffKey, 0, curve, false); + hasherResponse.update(new Uint8Array(buffKey)); + const hashResponse = hasherResponse.digest(); + if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); + if (importPoints) { + const nextChallengeHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + nextChallengeHasher.update(hashResponse); + await hashSection(nextChallengeHasher, fdNew, "G1", 2, 2 ** power * 2 - 1, "tauG1", logger); + await hashSection(nextChallengeHasher, fdNew, "G2", 3, 2 ** power, "tauG2", logger); + await hashSection(nextChallengeHasher, fdNew, "G1", 4, 2 ** power, "alphaTauG1", logger); + await hashSection(nextChallengeHasher, fdNew, "G1", 5, 2 ** power, "betaTauG1", logger); + await hashSection(nextChallengeHasher, fdNew, "G2", 6, 1, "betaG2", logger); + currentContribution.nextChallenge = nextChallengeHasher.digest(); + if (logger) logger.info(formatHash(currentContribution.nextChallenge, "Next Challenge Hash: ")); + } else currentContribution.nextChallenge = noHash; + contributions.push(currentContribution); + await writeContributions(fdNew, curve, contributions); + await fdResponse.close(); + await fdNew.close(); + await fdOld.close(); + return currentContribution.nextChallenge; + async function processSection(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { + if (importPoints) return await processSectionImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName); + else return await processSectionNoImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName); + } + async function processSectionImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { + const G = curve[groupName]; + const scG = G.F.n8; + const sG = G.F.n8 * 2; + const singularPoints = []; + await _iden3_binfileutils.startWriteSection(fdTo, sectionId); + const nPointsChunk = Math.floor((1 << 24) / sG); + startSections[sectionId] = fdTo.pos; + for (let i = 0; i < nPoints; i += nPointsChunk) { + if (logger) logger.debug(`Importing ${sectionName}: ${i}/${nPoints}`); + const n = Math.min(nPoints - i, nPointsChunk); + const buffC = await fdFrom.read(n * scG); + hasherResponse.update(buffC); + const buffLEM = await G.batchCtoLEM(buffC); + await fdTo.write(buffLEM); + for (let j = 0; j < singularPointIndexes.length; j++) { + const sp = singularPointIndexes[j]; + if (sp >= i && sp < i + n) { + const P = G.fromRprLEM(buffLEM, (sp - i) * sG); + singularPoints.push(P); + } + } + } + await _iden3_binfileutils.endWriteSection(fdTo); + return singularPoints; + } + async function processSectionNoImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { + const G = curve[groupName]; + const scG = G.F.n8; + const singularPoints = []; + const nPointsChunk = Math.floor((1 << 24) / scG); + for (let i = 0; i < nPoints; i += nPointsChunk) { + if (logger) logger.debug(`Importing ${sectionName}: ${i}/${nPoints}`); + const n = Math.min(nPoints - i, nPointsChunk); + const buffC = await fdFrom.read(n * scG); + hasherResponse.update(buffC); + for (let j = 0; j < singularPointIndexes.length; j++) { + const sp = singularPointIndexes[j]; + if (sp >= i && sp < i + n) { + const P = G.fromRprCompressed(buffC, (sp - i) * scG); + singularPoints.push(P); + } + } + } + return singularPoints; + } + async function hashSection(nextChallengeHasher, fdTo, groupName, sectionId, nPoints, sectionName, logger) { + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const nPointsChunk = Math.floor((1 << 24) / sG); + const oldPos = fdTo.pos; + fdTo.pos = startSections[sectionId]; + for (let i = 0; i < nPoints; i += nPointsChunk) { + if (logger) logger.debug(`Hashing ${sectionName}: ${i}/${nPoints}`); + const n = Math.min(nPoints - i, nPointsChunk); + const buffLEM = await fdTo.read(n * sG); + const buffU = await G.batchLEMtoU(buffLEM); + nextChallengeHasher.update(buffU); + } + fdTo.pos = oldPos; + } +} +//#endregion +//#region src/powersoftau_verify.js +var sameRatio$1 = sameRatio$2; async function verifyContribution(curve, cur, prev, logger) { - let sr; - if (cur.type == 1) { // Verify the beacon. - const beaconKey = await keyFromBeacon(curve, prev.nextChallenge, cur.beaconHash, cur.numIterationsExp); - - if (!curve.G1.eq(cur.key.tau.g1_s, beaconKey.tau.g1_s)) { - if (logger) logger.error(`BEACON key (tauG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G1.eq(cur.key.tau.g1_sx, beaconKey.tau.g1_sx)) { - if (logger) logger.error(`BEACON key (tauG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G2.eq(cur.key.tau.g2_spx, beaconKey.tau.g2_spx)) { - if (logger) logger.error(`BEACON key (tauG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - - if (!curve.G1.eq(cur.key.alpha.g1_s, beaconKey.alpha.g1_s)) { - if (logger) logger.error(`BEACON key (alphaG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G1.eq(cur.key.alpha.g1_sx, beaconKey.alpha.g1_sx)) { - if (logger) logger.error(`BEACON key (alphaG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G2.eq(cur.key.alpha.g2_spx, beaconKey.alpha.g2_spx)) { - if (logger) logger.error(`BEACON key (alphaG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - - if (!curve.G1.eq(cur.key.beta.g1_s, beaconKey.beta.g1_s)) { - if (logger) logger.error(`BEACON key (betaG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G1.eq(cur.key.beta.g1_sx, beaconKey.beta.g1_sx)) { - if (logger) logger.error(`BEACON key (betaG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G2.eq(cur.key.beta.g2_spx, beaconKey.beta.g2_spx)) { - if (logger) logger.error(`BEACON key (betaG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - } - - cur.key.tau.g2_sp = curve.G2.toAffine(getG2sp(curve, 0, prev.nextChallenge, cur.key.tau.g1_s, cur.key.tau.g1_sx)); - cur.key.alpha.g2_sp = curve.G2.toAffine(getG2sp(curve, 1, prev.nextChallenge, cur.key.alpha.g1_s, cur.key.alpha.g1_sx)); - cur.key.beta.g2_sp = curve.G2.toAffine(getG2sp(curve, 2, prev.nextChallenge, cur.key.beta.g1_s, cur.key.beta.g1_sx)); - - sr = await sameRatio$1(curve, cur.key.tau.g1_s, cur.key.tau.g1_sx, cur.key.tau.g2_sp, cur.key.tau.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID key (tau) in challenge #"+cur.id); - return false; - } - - sr = await sameRatio$1(curve, cur.key.alpha.g1_s, cur.key.alpha.g1_sx, cur.key.alpha.g2_sp, cur.key.alpha.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID key (alpha) in challenge #"+cur.id); - return false; - } - - sr = await sameRatio$1(curve, cur.key.beta.g1_s, cur.key.beta.g1_sx, cur.key.beta.g2_sp, cur.key.beta.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID key (beta) in challenge #"+cur.id); - return false; - } - - sr = await sameRatio$1(curve, prev.tauG1, cur.tauG1, cur.key.tau.g2_sp, cur.key.tau.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID tau*G1. challenge #"+cur.id+" It does not follow the previous contribution"); - return false; - } - - sr = await sameRatio$1(curve, cur.key.tau.g1_s, cur.key.tau.g1_sx, prev.tauG2, cur.tauG2); - if (sr !== true) { - if (logger) logger.error("INVALID tau*G2. challenge #"+cur.id+" It does not follow the previous contribution"); - return false; - } - - sr = await sameRatio$1(curve, prev.alphaG1, cur.alphaG1, cur.key.alpha.g2_sp, cur.key.alpha.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID alpha*G1. challenge #"+cur.id+" It does not follow the previous contribution"); - return false; - } - - sr = await sameRatio$1(curve, prev.betaG1, cur.betaG1, cur.key.beta.g2_sp, cur.key.beta.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID beta*G1. challenge #"+cur.id+" It does not follow the previous contribution"); - return false; - } - - sr = await sameRatio$1(curve, cur.key.beta.g1_s, cur.key.beta.g1_sx, prev.betaG2, cur.betaG2); - if (sr !== true) { - if (logger) logger.error("INVALID beta*G2. challenge #"+cur.id+"It does not follow the previous contribution"); - return false; - } - - if (logger) logger.info("Powers Of tau file OK!"); - return true; -} - + let sr; + if (cur.type == 1) { + const beaconKey = await keyFromBeacon(curve, prev.nextChallenge, cur.beaconHash, cur.numIterationsExp); + if (!curve.G1.eq(cur.key.tau.g1_s, beaconKey.tau.g1_s)) { + if (logger) logger.error(`BEACON key (tauG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G1.eq(cur.key.tau.g1_sx, beaconKey.tau.g1_sx)) { + if (logger) logger.error(`BEACON key (tauG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G2.eq(cur.key.tau.g2_spx, beaconKey.tau.g2_spx)) { + if (logger) logger.error(`BEACON key (tauG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G1.eq(cur.key.alpha.g1_s, beaconKey.alpha.g1_s)) { + if (logger) logger.error(`BEACON key (alphaG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G1.eq(cur.key.alpha.g1_sx, beaconKey.alpha.g1_sx)) { + if (logger) logger.error(`BEACON key (alphaG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G2.eq(cur.key.alpha.g2_spx, beaconKey.alpha.g2_spx)) { + if (logger) logger.error(`BEACON key (alphaG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G1.eq(cur.key.beta.g1_s, beaconKey.beta.g1_s)) { + if (logger) logger.error(`BEACON key (betaG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G1.eq(cur.key.beta.g1_sx, beaconKey.beta.g1_sx)) { + if (logger) logger.error(`BEACON key (betaG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G2.eq(cur.key.beta.g2_spx, beaconKey.beta.g2_spx)) { + if (logger) logger.error(`BEACON key (betaG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + } + cur.key.tau.g2_sp = curve.G2.toAffine(getG2sp(curve, 0, prev.nextChallenge, cur.key.tau.g1_s, cur.key.tau.g1_sx)); + cur.key.alpha.g2_sp = curve.G2.toAffine(getG2sp(curve, 1, prev.nextChallenge, cur.key.alpha.g1_s, cur.key.alpha.g1_sx)); + cur.key.beta.g2_sp = curve.G2.toAffine(getG2sp(curve, 2, prev.nextChallenge, cur.key.beta.g1_s, cur.key.beta.g1_sx)); + sr = await sameRatio$1(curve, cur.key.tau.g1_s, cur.key.tau.g1_sx, cur.key.tau.g2_sp, cur.key.tau.g2_spx); + if (sr !== true) { + if (logger) logger.error("INVALID key (tau) in challenge #" + cur.id); + return false; + } + sr = await sameRatio$1(curve, cur.key.alpha.g1_s, cur.key.alpha.g1_sx, cur.key.alpha.g2_sp, cur.key.alpha.g2_spx); + if (sr !== true) { + if (logger) logger.error("INVALID key (alpha) in challenge #" + cur.id); + return false; + } + sr = await sameRatio$1(curve, cur.key.beta.g1_s, cur.key.beta.g1_sx, cur.key.beta.g2_sp, cur.key.beta.g2_spx); + if (sr !== true) { + if (logger) logger.error("INVALID key (beta) in challenge #" + cur.id); + return false; + } + sr = await sameRatio$1(curve, prev.tauG1, cur.tauG1, cur.key.tau.g2_sp, cur.key.tau.g2_spx); + if (sr !== true) { + if (logger) logger.error("INVALID tau*G1. challenge #" + cur.id + " It does not follow the previous contribution"); + return false; + } + sr = await sameRatio$1(curve, cur.key.tau.g1_s, cur.key.tau.g1_sx, prev.tauG2, cur.tauG2); + if (sr !== true) { + if (logger) logger.error("INVALID tau*G2. challenge #" + cur.id + " It does not follow the previous contribution"); + return false; + } + sr = await sameRatio$1(curve, prev.alphaG1, cur.alphaG1, cur.key.alpha.g2_sp, cur.key.alpha.g2_spx); + if (sr !== true) { + if (logger) logger.error("INVALID alpha*G1. challenge #" + cur.id + " It does not follow the previous contribution"); + return false; + } + sr = await sameRatio$1(curve, prev.betaG1, cur.betaG1, cur.key.beta.g2_sp, cur.key.beta.g2_spx); + if (sr !== true) { + if (logger) logger.error("INVALID beta*G1. challenge #" + cur.id + " It does not follow the previous contribution"); + return false; + } + sr = await sameRatio$1(curve, cur.key.beta.g1_s, cur.key.beta.g1_sx, prev.betaG2, cur.betaG2); + if (sr !== true) { + if (logger) logger.error("INVALID beta*G2. challenge #" + cur.id + "It does not follow the previous contribution"); + return false; + } + if (logger) logger.info("Powers Of tau file OK!"); + return true; +} async function verify(tauFilename, logger) { - let sr; - - const {fd, sections} = await binFileUtils__namespace.readBinFile(tauFilename, "ptau", 1); - const {curve, power, ceremonyPower} = await readPTauHeader(fd, sections); - const contrs = await readContributions(fd, curve, sections); - - if (logger) logger.debug("power: 2**" + power); - // Verify Last contribution - - if (logger) logger.debug("Computing initial contribution hash"); - const initialContribution = { - tauG1: curve.G1.g, - tauG2: curve.G2.g, - alphaG1: curve.G1.g, - betaG1: curve.G1.g, - betaG2: curve.G2.g, - nextChallenge: calculateFirstChallengeHash(curve, ceremonyPower, logger), - responseHash: blake2b.blake2b.create({ dkLen: 64 }).digest() - }; - - if (contrs.length == 0) { - if (logger) logger.error("This file has no contribution! It cannot be used in production"); - return false; - } - - let prevContr; - if (contrs.length>1) { - prevContr = contrs[contrs.length-2]; - } else { - prevContr = initialContribution; - } - const curContr = contrs[contrs.length-1]; - if (logger) logger.debug("Validating contribution #"+contrs[contrs.length-1].id); - const res = await verifyContribution(curve, curContr, prevContr, logger); - if (!res) return false; - - - const nextContributionHasher = blake2b.blake2b.create({ dkLen: 64 }); - nextContributionHasher.update(curContr.responseHash); - - // Verify powers and compute nextChallengeHash - - // await test(); - - // Verify Section tau*G1 - if (logger) logger.debug("Verifying powers in tau*G1 section"); - const rTau1 = await processSection(2, "G1", "tauG1", (2 ** power)*2-1, [0, 1], logger); - sr = await sameRatio$1(curve, rTau1.R1, rTau1.R2, curve.G2.g, curContr.tauG2); - if (sr !== true) { - if (logger) logger.error("tauG1 section. Powers do not match"); - return false; - } - if (!curve.G1.eq(curve.G1.g, rTau1.singularPoints[0])) { - if (logger) logger.error("First element of tau*G1 section must be the generator"); - return false; - } - if (!curve.G1.eq(curContr.tauG1, rTau1.singularPoints[1])) { - if (logger) logger.error("Second element of tau*G1 section does not match the one in the contribution section"); - return false; - } - - // await test(); - - // Verify Section tau*G2 - if (logger) logger.debug("Verifying powers in tau*G2 section"); - const rTau2 = await processSection(3, "G2", "tauG2", 2 ** power, [0, 1], logger); - sr = await sameRatio$1(curve, curve.G1.g, curContr.tauG1, rTau2.R1, rTau2.R2); - if (sr !== true) { - if (logger) logger.error("tauG2 section. Powers do not match"); - return false; - } - if (!curve.G2.eq(curve.G2.g, rTau2.singularPoints[0])) { - if (logger) logger.error("First element of tau*G2 section must be the generator"); - return false; - } - if (!curve.G2.eq(curContr.tauG2, rTau2.singularPoints[1])) { - if (logger) logger.error("Second element of tau*G2 section does not match the one in the contribution section"); - return false; - } - - // Verify Section alpha*tau*G1 - if (logger) logger.debug("Verifying powers in alpha*tau*G1 section"); - const rAlphaTauG1 = await processSection(4, "G1", "alphatauG1", 2 ** power, [0], logger); - sr = await sameRatio$1(curve, rAlphaTauG1.R1, rAlphaTauG1.R2, curve.G2.g, curContr.tauG2); - if (sr !== true) { - if (logger) logger.error("alphaTauG1 section. Powers do not match"); - return false; - } - if (!curve.G1.eq(curContr.alphaG1, rAlphaTauG1.singularPoints[0])) { - if (logger) logger.error("First element of alpha*tau*G1 section (alpha*G1) does not match the one in the contribution section"); - return false; - } - - // Verify Section beta*tau*G1 - if (logger) logger.debug("Verifying powers in beta*tau*G1 section"); - const rBetaTauG1 = await processSection(5, "G1", "betatauG1", 2 ** power, [0], logger); - sr = await sameRatio$1(curve, rBetaTauG1.R1, rBetaTauG1.R2, curve.G2.g, curContr.tauG2); - if (sr !== true) { - if (logger) logger.error("betaTauG1 section. Powers do not match"); - return false; - } - if (!curve.G1.eq(curContr.betaG1, rBetaTauG1.singularPoints[0])) { - if (logger) logger.error("First element of beta*tau*G1 section (beta*G1) does not match the one in the contribution section"); - return false; - } - - //Verify Beta G2 - const betaG2 = await processSectionBetaG2(logger); - if (!curve.G2.eq(curContr.betaG2, betaG2)) { - if (logger) logger.error("betaG2 element in betaG2 section does not match the one in the contribution section"); - return false; - } - - - const nextContributionHash = nextContributionHasher.digest(); - - // Check the nextChallengeHash - if (power == ceremonyPower) { - if (!hashIsEqual(nextContributionHash,curContr.nextChallenge)) { - if (logger) logger.error("Hash of the values does not match the next challenge of the last contributor in the contributions section"); - return false; - } - } - - if (logger) logger.info(formatHash(nextContributionHash, "Next challenge hash: ")); - - // Verify Previous contributions - - printContribution(curContr, prevContr); - for (let i = contrs.length-2; i>=0; i--) { - const curContr = contrs[i]; - const prevContr = (i>0) ? contrs[i-1] : initialContribution; - const res = await verifyContribution(curve, curContr, prevContr, logger); - if (!res) return false; - printContribution(curContr, prevContr); - } - if (logger) logger.info("-----------------------------------------------------"); - - if ((!sections[12]) || (!sections[13]) || (!sections[14]) || (!sections[15])) { - if (logger) logger.warn( - "this file does not contain phase2 precalculated values. Please run: \n" + - " snarkjs \"powersoftau preparephase2\" to prepare this file to be used in the phase2 ceremony." - ); - } else { - let res; - res = await verifyLagrangeEvaluations("G1", 2, 12, "tauG1", logger); - if (!res) return false; - res = await verifyLagrangeEvaluations("G2", 3, 13, "tauG2", logger); - if (!res) return false; - res = await verifyLagrangeEvaluations("G1", 4, 14, "alphaTauG1", logger); - if (!res) return false; - res = await verifyLagrangeEvaluations("G1", 5, 15, "betaTauG1", logger); - if (!res) return false; - } - - await fd.close(); - - if (logger) logger.info("Powers of Tau Ok!"); - - return true; - - function printContribution(curContr, prevContr) { - if (!logger) return; - logger.info("-----------------------------------------------------"); - logger.info(`Contribution #${curContr.id}: ${curContr.name ||""}`); - - logger.info(formatHash(curContr.nextChallenge, "Next Challenge: ")); - - const buffV = new Uint8Array(curve.G1.F.n8*2*6+curve.G2.F.n8*2*3); - toPtauPubKeyRpr(buffV, 0, curve, curContr.key, false); - - const responseHasher = fromPartialHash(curContr.partialHash); - responseHasher.update(buffV); - const responseHash = responseHasher.digest(); - - logger.info(formatHash(responseHash, "Response Hash:")); - - logger.info(formatHash(prevContr.nextChallenge, "Response Hash:")); - - if (curContr.type == 1) { - logger.info(`Beacon generator: ${byteArray2hex(curContr.beaconHash)}`); - logger.info(`Beacon iterations Exp: ${curContr.numIterationsExp}`); - } - - } - - async function processSectionBetaG2(logger) { - const G = curve.G2; - const sG = G.F.n8*2; - const buffUv = new Uint8Array(sG); - - if (!sections[6]) { - logger.error("File has no BetaG2 section"); - throw new Error("File has no BetaG2 section"); - } - if (sections[6].length>1) { - logger.error("File has no BetaG2 section"); - throw new Error("File has more than one GetaG2 section"); - } - fd.pos = sections[6][0].p; - - const buff = await fd.read(sG); - const P = G.fromRprLEM(buff); - - G.toRprUncompressed(buffUv, 0, P); - nextContributionHasher.update(buffUv); - - return P; - } - - async function processSection(idSection, groupName, sectionName, nPoints, singularPointIndexes, logger) { - const MAX_CHUNK_SIZE = 1<<16; - const G = curve[groupName]; - const sG = G.F.n8*2; - await binFileUtils__namespace.startReadUniqueSection(fd, sections, idSection); - - const singularPoints = []; - - let R1 = G.zero; - let R2 = G.zero; - - let lastBase = G.zero; - - for (let i=0; i0) { - const firstBase = G.fromRprLEM(bases, 0); - const r = readUInt32BE(getRandomBytes(4), 0); - - R1 = G.add(R1, G.timesScalar(lastBase, r)); - R2 = G.add(R2, G.timesScalar(firstBase, r)); - } - - const r1 = await G.multiExpAffine(bases.slice(0, (n-1)*sG), scalars); - const r2 = await G.multiExpAffine(bases.slice(sG), scalars); - - R1 = G.add(R1, r1); - R2 = G.add(R2, r2); - - lastBase = G.fromRprLEM( bases, (n-1)*sG); - - for (let j=0; j=i) && (sp < i+n)) { - const P = G.fromRprLEM(bases, (sp-i)*sG); - singularPoints.push(P); - } - } - - } - await binFileUtils__namespace.endReadSection(fd); - - return { - R1: R1, - R2: R2, - singularPoints: singularPoints - }; - - } - - async function verifyLagrangeEvaluations(gName, tauSection, lagrangeSection, sectionName, logger) { - - if (logger) logger.debug(`Verifying phase2 calculated values ${sectionName}...`); - const G = curve[gName]; - const sG = G.F.n8*2; - - const seed= new Array(8); - for (let i=0; i<8; i++) { - seed[i] = readUInt32BE(getRandomBytes(4), 0); - } - - for (let p=0; p<= power; p ++) { - const res = await verifyPower(p); - if (!res) return false; - } - - if (tauSection == 2) { - const res = await verifyPower(power+1); - if (!res) return false; - } - - return true; - - async function verifyPower(p) { - if (logger) logger.debug(`Power ${p}...`); - const n8r = curve.Fr.n8; - const nPoints = 2 ** p; - let buff_r = new Uint32Array(nPoints); - let buffG; - - let rng = new ffjavascript.ChaCha(seed); - - if (logger) logger.debug(`Creating random numbers Powers${p}...`); - for (let i=0; i. -*/ - -/* - This function creates a new section in the fdTo file with id idSection. - It multiplies the points in fdFrom by first, first*inc, first*inc^2, .... - nPoint Times. - It also updates the newChallengeHasher with the new points -*/ - + let sr; + const { fd, sections } = await _iden3_binfileutils.readBinFile(tauFilename, "ptau", 1); + const { curve, power, ceremonyPower } = await readPTauHeader(fd, sections); + const contrs = await readContributions(fd, curve, sections); + if (logger) logger.debug("power: 2**" + power); + if (logger) logger.debug("Computing initial contribution hash"); + const initialContribution = { + tauG1: curve.G1.g, + tauG2: curve.G2.g, + alphaG1: curve.G1.g, + betaG1: curve.G1.g, + betaG2: curve.G2.g, + nextChallenge: calculateFirstChallengeHash(curve, ceremonyPower, logger), + responseHash: _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }).digest() + }; + if (contrs.length == 0) { + if (logger) logger.error("This file has no contribution! It cannot be used in production"); + return false; + } + let prevContr; + if (contrs.length > 1) prevContr = contrs[contrs.length - 2]; + else prevContr = initialContribution; + const curContr = contrs[contrs.length - 1]; + if (logger) logger.debug("Validating contribution #" + contrs[contrs.length - 1].id); + if (!await verifyContribution(curve, curContr, prevContr, logger)) return false; + const nextContributionHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + nextContributionHasher.update(curContr.responseHash); + if (logger) logger.debug("Verifying powers in tau*G1 section"); + const rTau1 = await processSection(2, "G1", "tauG1", 2 ** power * 2 - 1, [0, 1], logger); + sr = await sameRatio$1(curve, rTau1.R1, rTau1.R2, curve.G2.g, curContr.tauG2); + if (sr !== true) { + if (logger) logger.error("tauG1 section. Powers do not match"); + return false; + } + if (!curve.G1.eq(curve.G1.g, rTau1.singularPoints[0])) { + if (logger) logger.error("First element of tau*G1 section must be the generator"); + return false; + } + if (!curve.G1.eq(curContr.tauG1, rTau1.singularPoints[1])) { + if (logger) logger.error("Second element of tau*G1 section does not match the one in the contribution section"); + return false; + } + if (logger) logger.debug("Verifying powers in tau*G2 section"); + const rTau2 = await processSection(3, "G2", "tauG2", 2 ** power, [0, 1], logger); + sr = await sameRatio$1(curve, curve.G1.g, curContr.tauG1, rTau2.R1, rTau2.R2); + if (sr !== true) { + if (logger) logger.error("tauG2 section. Powers do not match"); + return false; + } + if (!curve.G2.eq(curve.G2.g, rTau2.singularPoints[0])) { + if (logger) logger.error("First element of tau*G2 section must be the generator"); + return false; + } + if (!curve.G2.eq(curContr.tauG2, rTau2.singularPoints[1])) { + if (logger) logger.error("Second element of tau*G2 section does not match the one in the contribution section"); + return false; + } + if (logger) logger.debug("Verifying powers in alpha*tau*G1 section"); + const rAlphaTauG1 = await processSection(4, "G1", "alphatauG1", 2 ** power, [0], logger); + sr = await sameRatio$1(curve, rAlphaTauG1.R1, rAlphaTauG1.R2, curve.G2.g, curContr.tauG2); + if (sr !== true) { + if (logger) logger.error("alphaTauG1 section. Powers do not match"); + return false; + } + if (!curve.G1.eq(curContr.alphaG1, rAlphaTauG1.singularPoints[0])) { + if (logger) logger.error("First element of alpha*tau*G1 section (alpha*G1) does not match the one in the contribution section"); + return false; + } + if (logger) logger.debug("Verifying powers in beta*tau*G1 section"); + const rBetaTauG1 = await processSection(5, "G1", "betatauG1", 2 ** power, [0], logger); + sr = await sameRatio$1(curve, rBetaTauG1.R1, rBetaTauG1.R2, curve.G2.g, curContr.tauG2); + if (sr !== true) { + if (logger) logger.error("betaTauG1 section. Powers do not match"); + return false; + } + if (!curve.G1.eq(curContr.betaG1, rBetaTauG1.singularPoints[0])) { + if (logger) logger.error("First element of beta*tau*G1 section (beta*G1) does not match the one in the contribution section"); + return false; + } + const betaG2 = await processSectionBetaG2(logger); + if (!curve.G2.eq(curContr.betaG2, betaG2)) { + if (logger) logger.error("betaG2 element in betaG2 section does not match the one in the contribution section"); + return false; + } + const nextContributionHash = nextContributionHasher.digest(); + if (power == ceremonyPower) { + if (!hashIsEqual(nextContributionHash, curContr.nextChallenge)) { + if (logger) logger.error("Hash of the values does not match the next challenge of the last contributor in the contributions section"); + return false; + } + } + if (logger) logger.info(formatHash(nextContributionHash, "Next challenge hash: ")); + printContribution(curContr, prevContr); + for (let i = contrs.length - 2; i >= 0; i--) { + const curContr = contrs[i]; + const prevContr = i > 0 ? contrs[i - 1] : initialContribution; + if (!await verifyContribution(curve, curContr, prevContr, logger)) return false; + printContribution(curContr, prevContr, logger); + } + if (logger) logger.info("-----------------------------------------------------"); + if (!sections[12] || !sections[13] || !sections[14] || !sections[15]) { + if (logger) logger.warn("this file does not contain phase2 precalculated values. Please run: \n snarkjs \"powersoftau preparephase2\" to prepare this file to be used in the phase2 ceremony."); + } else { + let res; + res = await verifyLagrangeEvaluations("G1", 2, 12, "tauG1", logger); + if (!res) return false; + res = await verifyLagrangeEvaluations("G2", 3, 13, "tauG2", logger); + if (!res) return false; + res = await verifyLagrangeEvaluations("G1", 4, 14, "alphaTauG1", logger); + if (!res) return false; + res = await verifyLagrangeEvaluations("G1", 5, 15, "betaTauG1", logger); + if (!res) return false; + } + await fd.close(); + if (logger) logger.info("Powers of Tau Ok!"); + return true; + function printContribution(curContr, prevContr) { + if (!logger) return; + logger.info("-----------------------------------------------------"); + logger.info(`Contribution #${curContr.id}: ${curContr.name || ""}`); + logger.info(formatHash(curContr.nextChallenge, "Next Challenge: ")); + const buffV = new Uint8Array(curve.G1.F.n8 * 2 * 6 + curve.G2.F.n8 * 2 * 3); + toPtauPubKeyRpr(buffV, 0, curve, curContr.key, false); + const responseHasher = fromPartialHash(curContr.partialHash); + responseHasher.update(buffV); + const responseHash = responseHasher.digest(); + logger.info(formatHash(responseHash, "Response Hash:")); + logger.info(formatHash(prevContr.nextChallenge, "Response Hash:")); + if (curContr.type == 1) { + logger.info(`Beacon generator: ${byteArray2hex(curContr.beaconHash)}`); + logger.info(`Beacon iterations Exp: ${curContr.numIterationsExp}`); + } + } + async function processSectionBetaG2(logger) { + const G = curve.G2; + const sG = G.F.n8 * 2; + const buffUv = new Uint8Array(sG); + if (!sections[6]) { + logger.error("File has no BetaG2 section"); + throw new Error("File has no BetaG2 section"); + } + if (sections[6].length > 1) { + logger.error("File has no BetaG2 section"); + throw new Error("File has more than one GetaG2 section"); + } + fd.pos = sections[6][0].p; + const buff = await fd.read(sG); + const P = G.fromRprLEM(buff); + G.toRprUncompressed(buffUv, 0, P); + nextContributionHasher.update(buffUv); + return P; + } + async function processSection(idSection, groupName, sectionName, nPoints, singularPointIndexes, logger) { + const MAX_CHUNK_SIZE = 65536; + const G = curve[groupName]; + const sG = G.F.n8 * 2; + await _iden3_binfileutils.startReadUniqueSection(fd, sections, idSection); + const singularPoints = []; + let R1 = G.zero; + let R2 = G.zero; + let lastBase = G.zero; + for (let i = 0; i < nPoints; i += MAX_CHUNK_SIZE) { + if (logger) logger.debug(`points relations: ${sectionName}: ${i}/${nPoints} `); + const n = Math.min(nPoints - i, MAX_CHUNK_SIZE); + const bases = await fd.read(n * sG); + const basesU = await G.batchLEMtoU(bases); + nextContributionHasher.update(basesU); + const scalars = getRandomBytes(4 * (n - 1)); + if (i > 0) { + const firstBase = G.fromRprLEM(bases, 0); + const r = readUInt32BE(getRandomBytes(4), 0); + R1 = G.add(R1, G.timesScalar(lastBase, r)); + R2 = G.add(R2, G.timesScalar(firstBase, r)); + } + const r1 = await G.multiExpAffine(bases.slice(0, (n - 1) * sG), scalars); + const r2 = await G.multiExpAffine(bases.slice(sG), scalars); + R1 = G.add(R1, r1); + R2 = G.add(R2, r2); + lastBase = G.fromRprLEM(bases, (n - 1) * sG); + for (let j = 0; j < singularPointIndexes.length; j++) { + const sp = singularPointIndexes[j]; + if (sp >= i && sp < i + n) { + const P = G.fromRprLEM(bases, (sp - i) * sG); + singularPoints.push(P); + } + } + } + await _iden3_binfileutils.endReadSection(fd); + return { + R1, + R2, + singularPoints + }; + } + async function verifyLagrangeEvaluations(gName, tauSection, lagrangeSection, sectionName, logger) { + if (logger) logger.debug(`Verifying phase2 calculated values ${sectionName}...`); + const G = curve[gName]; + const sG = G.F.n8 * 2; + const seed = new Array(8); + for (let i = 0; i < 8; i++) seed[i] = readUInt32BE(getRandomBytes(4), 0); + for (let p = 0; p <= power; p++) if (!await verifyPower(p)) return false; + if (tauSection == 2) { + if (!await verifyPower(power + 1)) return false; + } + return true; + async function verifyPower(p) { + if (logger) logger.debug(`Power ${p}...`); + const n8r = curve.Fr.n8; + const nPoints = 2 ** p; + let buff_r = new Uint32Array(nPoints); + let buffG; + let rng = new ffjavascript.ChaCha(seed); + if (logger) logger.debug(`Creating random numbers Powers${p}...`); + for (let i = 0; i < nPoints; i++) if (p == power + 1 && i == nPoints - 1) buff_r[i] = 0; + else buff_r[i] = rng.nextU32(); + buff_r = new Uint8Array(buff_r.buffer, buff_r.byteOffset, buff_r.byteLength); + if (logger) logger.debug(`reading points Powers${p}...`); + await _iden3_binfileutils.startReadUniqueSection(fd, sections, tauSection); + buffG = new ffjavascript.BigBuffer(nPoints * sG); + if (p == power + 1) { + await fd.readToBuffer(buffG, 0, (nPoints - 1) * sG); + buffG.set(curve.G1.zeroAffine, (nPoints - 1) * sG); + } else await fd.readToBuffer(buffG, 0, nPoints * sG); + await _iden3_binfileutils.endReadSection(fd, true); + const resTau = await G.multiExpAffine(buffG, buff_r, logger, sectionName + "_" + p); + buff_r = new ffjavascript.BigBuffer(nPoints * n8r); + rng = new ffjavascript.ChaCha(seed); + const buff4 = new Uint8Array(4); + const buff4V = new DataView(buff4.buffer); + if (logger) logger.debug(`Creating random numbers Powers${p}...`); + for (let i = 0; i < nPoints; i++) if (i != nPoints - 1 || p != power + 1) { + buff4V.setUint32(0, rng.nextU32(), true); + buff_r.set(buff4, i * n8r); + } + if (logger) logger.debug(`batchToMontgomery ${p}...`); + buff_r = await curve.Fr.batchToMontgomery(buff_r); + if (logger) logger.debug(`fft ${p}...`); + buff_r = await curve.Fr.fft(buff_r); + if (logger) logger.debug(`batchFromMontgomery ${p}...`); + buff_r = await curve.Fr.batchFromMontgomery(buff_r); + if (logger) logger.debug(`reading points Lagrange${p}...`); + await _iden3_binfileutils.startReadUniqueSection(fd, sections, lagrangeSection); + fd.pos += sG * (2 ** p - 1); + await fd.readToBuffer(buffG, 0, nPoints * sG); + await _iden3_binfileutils.endReadSection(fd, true); + const resLagrange = await G.multiExpAffine(buffG, buff_r, logger, sectionName + "_" + p + "_transformed"); + if (!G.eq(resTau, resLagrange)) { + if (logger) logger.error("Phase2 caclutation does not match with powers of tau"); + return false; + } + return true; + } + } +} +//#endregion +//#region src/mpc_applykey.js async function applyKeyToSection(fdOld, sections, fdNew, idSection, curve, groupName, first, inc, sectionName, logger) { - const MAX_CHUNK_SIZE = 1 << 16; - const G = curve[groupName]; - const sG = G.F.n8*2; - const nPoints = sections[idSection][0].size / sG; - - await binFileUtils__namespace.startReadUniqueSection(fdOld, sections,idSection ); - await binFileUtils__namespace.startWriteSection(fdNew, idSection); - - let t = first; - for (let i=0; i. -*/ - + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const chunkSize = Math.floor((1 << 20) / sG); + let t = first; + for (let i = 0; i < nPoints; i += chunkSize) { + if (logger) logger.debug(`Applying key ${sectionName}: ${i}/${nPoints}`); + const n = Math.min(nPoints - i, chunkSize); + const buffInU = await fdOld.read(n * sG); + const buffInLEM = await G.batchUtoLEM(buffInU); + const buffOutLEM = await G.batchApplyKey(buffInLEM, t, inc); + let buffOut; + if (formatOut == "COMPRESSED") buffOut = await G.batchLEMtoC(buffOutLEM); + else buffOut = await G.batchLEMtoU(buffOutLEM); + if (responseHasher) responseHasher.update(buffOut); + await fdNew.write(buffOut); + t = curve.Fr.mul(t, curve.Fr.exp(inc, n)); + } +} +//#endregion +//#region src/powersoftau_challenge_contribute.js async function challengeContribute(curve, challengeFilename, responseFileName, entropy, logger) { - const fdFrom = await fastFile__namespace.readExisting(challengeFilename); - - - const sG1 = curve.F1.n64*8*2; - const sG2 = curve.F2.n64*8*2; - const domainSize = (fdFrom.totalSize + sG1 - 64 - sG2) / (4*sG1 + sG2); - let e = domainSize; - let power = 0; - while (e>1) { - e = e /2; - power += 1; - } - - if (2 ** power != domainSize) throw new Error("Invalid file size"); - if (logger) logger.debug("Power to tau size: "+power); - - const rng = await getRandomRng(entropy); - - const fdTo = await fastFile__namespace.createOverride(responseFileName); - - // Calculate the hash - const challengeHasher = blake2b.blake2b.create({ dkLen: 64 }); - for (let i=0; i { - logger.debug(k + ".g1_s: " + curve.G1.toString(key[k].g1_s, 16)); - logger.debug(k + ".g1_sx: " + curve.G1.toString(key[k].g1_sx, 16)); - logger.debug(k + ".g2_sp: " + curve.G2.toString(key[k].g2_sp, 16)); - logger.debug(k + ".g2_spx: " + curve.G2.toString(key[k].g2_spx, 16)); - logger.debug(""); - }); - } - - const responseHasher = blake2b.blake2b.create({ dkLen: 64 }); - - await fdTo.write(challengeHash); - responseHasher.update(challengeHash); - - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", (2 ** power)*2-1, curve.Fr.one , key.tau.prvKey, "COMPRESSED", "tauG1" , logger ); - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G2", (2 ** power) , curve.Fr.one , key.tau.prvKey, "COMPRESSED", "tauG2" , logger ); - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", (2 ** power) , key.alpha.prvKey, key.tau.prvKey, "COMPRESSED", "alphaTauG1", logger ); - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", (2 ** power) , key.beta.prvKey , key.tau.prvKey, "COMPRESSED", "betaTauG1" , logger ); - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G2", 1 , key.beta.prvKey , key.tau.prvKey, "COMPRESSED", "betaTauG2" , logger ); - - // Write and hash key - const buffKey = new Uint8Array(curve.F1.n8*2*6+curve.F2.n8*2*3); - toPtauPubKeyRpr(buffKey, 0, curve, key, false); - await fdTo.write(buffKey); - responseHasher.update(buffKey); - const responseHash = responseHasher.digest(); - if (logger) logger.info(formatHash(responseHash, "Contribution Response Hash: ")); - - await fdTo.close(); - await fdFrom.close(); -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -async function beacon$1(oldPtauFilename, newPTauFilename, name, beaconHashStr,numIterationsExp, logger) { - const beaconHash = hex2ByteArray(beaconHashStr); - if ( (beaconHash.byteLength == 0) - || (beaconHash.byteLength*2 !=beaconHashStr.length)) - { - if (logger) logger.error("Invalid Beacon Hash. (It must be a valid hexadecimal sequence)"); - return false; - } - if (beaconHash.length>=256) { - if (logger) logger.error("Maximum length of beacon hash is 255 bytes"); - return false; - } - - numIterationsExp = parseInt(numIterationsExp); - if ((numIterationsExp<10)||(numIterationsExp>63)) { - if (logger) logger.error("Invalid numIterationsExp. (Must be between 10 and 63)"); - return false; - } - - - const {fd: fdOld, sections} = await binFileUtils__namespace.readBinFile(oldPtauFilename, "ptau", 1); - const {curve, power, ceremonyPower} = await readPTauHeader(fdOld, sections); - if (power != ceremonyPower) { - if (logger) logger.error("This file has been reduced. You cannot contribute into a reduced file."); - return false; - } - if (sections[12]) { - if (logger) logger.warn("Contributing into a file that has phase2 calculated. You will have to prepare phase2 again."); - } - const contributions = await readContributions(fdOld, curve, sections); - const curContribution = { - name: name, - type: 1, // Beacon - numIterationsExp: numIterationsExp, - beaconHash: beaconHash - }; - - let lastChallengeHash; - - if (contributions.length>0) { - lastChallengeHash = contributions[contributions.length-1].nextChallenge; - } else { - lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); - } - - curContribution.key = await keyFromBeacon(curve, lastChallengeHash, beaconHash, numIterationsExp); - - const responseHasher = blake2b.blake2b.create({ dkLen: 64 }); - responseHasher.update(lastChallengeHash); - - const fdNew = await binFileUtils__namespace.createBinFile(newPTauFilename, "ptau", 1, 7); - await writePTauHeader(fdNew, curve, power); - - const startSections = []; - - let firstPoints; - firstPoints = await processSection(2, "G1", (2 ** power) * 2 -1, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG1", logger ); - curContribution.tauG1 = firstPoints[1]; - firstPoints = await processSection(3, "G2", (2 ** power) , curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG2", logger ); - curContribution.tauG2 = firstPoints[1]; - firstPoints = await processSection(4, "G1", (2 ** power) , curContribution.key.alpha.prvKey, curContribution.key.tau.prvKey, "alphaTauG1", logger ); - curContribution.alphaG1 = firstPoints[0]; - firstPoints = await processSection(5, "G1", (2 ** power) , curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG1", logger ); - curContribution.betaG1 = firstPoints[0]; - firstPoints = await processSection(6, "G2", 1, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG2", logger ); - curContribution.betaG2 = firstPoints[0]; - - curContribution.partialHash = toPartialHash(responseHasher); - - const buffKey = new Uint8Array(curve.F1.n8*2*6+curve.F2.n8*2*3); - - toPtauPubKeyRpr(buffKey, 0, curve, curContribution.key, false); - - responseHasher.update(new Uint8Array(buffKey)); - const hashResponse = responseHasher.digest(); - - if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); - - const nextChallengeHasher = blake2b.blake2b.create({ dkLen: 64 }); - nextChallengeHasher.update(hashResponse); - - await hashSection(fdNew, "G1", 2, (2 ** power) * 2 -1, "tauG1", logger); - await hashSection(fdNew, "G2", 3, (2 ** power) , "tauG2", logger); - await hashSection(fdNew, "G1", 4, (2 ** power) , "alphaTauG1", logger); - await hashSection(fdNew, "G1", 5, (2 ** power) , "betaTauG1", logger); - await hashSection(fdNew, "G2", 6, 1 , "betaG2", logger); - - curContribution.nextChallenge = nextChallengeHasher.digest(); - - if (logger) logger.info(formatHash(curContribution.nextChallenge, "Next Challenge Hash: ")); - - contributions.push(curContribution); - - await writeContributions(fdNew, curve, contributions); - - await fdOld.close(); - await fdNew.close(); - - return hashResponse; - - async function processSection(sectionId, groupName, NPoints, first, inc, sectionName, logger) { - const res = []; - fdOld.pos = sections[sectionId][0].p; - - await binFileUtils__namespace.startWriteSection(fdNew, sectionId); - - startSections[sectionId] = fdNew.pos; - - const G = curve[groupName]; - const sG = G.F.n8*2; - const chunkSize = Math.floor((1<<20) / sG); // 128Mb chunks - let t = first; - for (let i=0 ; i. -*/ - + const fdFrom = await fastfile.readExisting(challengeFilename); + const sG1 = curve.F1.n64 * 8 * 2; + const sG2 = curve.F2.n64 * 8 * 2; + const domainSize = (fdFrom.totalSize + sG1 - 64 - sG2) / (4 * sG1 + sG2); + let e = domainSize; + let power = 0; + while (e > 1) { + e = e / 2; + power += 1; + } + if (2 ** power != domainSize) throw new Error("Invalid file size"); + if (logger) logger.debug("Power to tau size: " + power); + const rng = await getRandomRng(entropy); + const fdTo = await fastfile.createOverride(responseFileName); + const challengeHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + for (let i = 0; i < fdFrom.totalSize; i += fdFrom.pageSize) { + if (logger) logger.debug(`Hashing challenge ${i}/${fdFrom.totalSize}`); + const s = Math.min(fdFrom.totalSize - i, fdFrom.pageSize); + const buff = await fdFrom.read(s); + challengeHasher.update(buff); + } + const claimedHash = await fdFrom.read(64, 0); + if (logger) logger.info(formatHash(claimedHash, "Claimed Previous Response Hash: ")); + const challengeHash = challengeHasher.digest(); + if (logger) logger.info(formatHash(challengeHash, "Current Challenge Hash: ")); + const key = createPTauKey(curve, challengeHash, rng); + if (logger) [ + "tau", + "alpha", + "beta" + ].forEach((k) => { + logger.debug(k + ".g1_s: " + curve.G1.toString(key[k].g1_s, 16)); + logger.debug(k + ".g1_sx: " + curve.G1.toString(key[k].g1_sx, 16)); + logger.debug(k + ".g2_sp: " + curve.G2.toString(key[k].g2_sp, 16)); + logger.debug(k + ".g2_spx: " + curve.G2.toString(key[k].g2_spx, 16)); + logger.debug(""); + }); + const responseHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + await fdTo.write(challengeHash); + responseHasher.update(challengeHash); + await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", 2 ** power * 2 - 1, curve.Fr.one, key.tau.prvKey, "COMPRESSED", "tauG1", logger); + await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G2", 2 ** power, curve.Fr.one, key.tau.prvKey, "COMPRESSED", "tauG2", logger); + await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", 2 ** power, key.alpha.prvKey, key.tau.prvKey, "COMPRESSED", "alphaTauG1", logger); + await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", 2 ** power, key.beta.prvKey, key.tau.prvKey, "COMPRESSED", "betaTauG1", logger); + await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G2", 1, key.beta.prvKey, key.tau.prvKey, "COMPRESSED", "betaTauG2", logger); + const buffKey = new Uint8Array(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3); + toPtauPubKeyRpr(buffKey, 0, curve, key, false); + await fdTo.write(buffKey); + responseHasher.update(buffKey); + const responseHash = responseHasher.digest(); + if (logger) logger.info(formatHash(responseHash, "Contribution Response Hash: ")); + await fdTo.close(); + await fdFrom.close(); +} +//#endregion +//#region src/powersoftau_beacon.js +async function beacon$1(oldPtauFilename, newPTauFilename, name, beaconHashStr, numIterationsExp, logger) { + const beaconHash = hex2ByteArray(beaconHashStr); + if (beaconHash.byteLength == 0 || beaconHash.byteLength * 2 != beaconHashStr.length) { + if (logger) logger.error("Invalid Beacon Hash. (It must be a valid hexadecimal sequence)"); + return false; + } + if (beaconHash.length >= 256) { + if (logger) logger.error("Maximum length of beacon hash is 255 bytes"); + return false; + } + numIterationsExp = parseInt(numIterationsExp); + if (numIterationsExp < 10 || numIterationsExp > 63) { + if (logger) logger.error("Invalid numIterationsExp. (Must be between 10 and 63)"); + return false; + } + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(oldPtauFilename, "ptau", 1); + const { curve, power, ceremonyPower } = await readPTauHeader(fdOld, sections); + if (power != ceremonyPower) { + if (logger) logger.error("This file has been reduced. You cannot contribute into a reduced file."); + return false; + } + if (sections[12]) { + if (logger) logger.warn("Contributing into a file that has phase2 calculated. You will have to prepare phase2 again."); + } + const contributions = await readContributions(fdOld, curve, sections); + const curContribution = { + name, + type: 1, + numIterationsExp, + beaconHash + }; + let lastChallengeHash; + if (contributions.length > 0) lastChallengeHash = contributions[contributions.length - 1].nextChallenge; + else lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); + curContribution.key = await keyFromBeacon(curve, lastChallengeHash, beaconHash, numIterationsExp); + const responseHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + responseHasher.update(lastChallengeHash); + const fdNew = await _iden3_binfileutils.createBinFile(newPTauFilename, "ptau", 1, 7); + await writePTauHeader(fdNew, curve, power); + const startSections = []; + let firstPoints; + firstPoints = await processSection(2, "G1", 2 ** power * 2 - 1, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG1", logger); + curContribution.tauG1 = firstPoints[1]; + firstPoints = await processSection(3, "G2", 2 ** power, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG2", logger); + curContribution.tauG2 = firstPoints[1]; + firstPoints = await processSection(4, "G1", 2 ** power, curContribution.key.alpha.prvKey, curContribution.key.tau.prvKey, "alphaTauG1", logger); + curContribution.alphaG1 = firstPoints[0]; + firstPoints = await processSection(5, "G1", 2 ** power, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG1", logger); + curContribution.betaG1 = firstPoints[0]; + firstPoints = await processSection(6, "G2", 1, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG2", logger); + curContribution.betaG2 = firstPoints[0]; + curContribution.partialHash = toPartialHash(responseHasher); + const buffKey = new Uint8Array(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3); + toPtauPubKeyRpr(buffKey, 0, curve, curContribution.key, false); + responseHasher.update(new Uint8Array(buffKey)); + const hashResponse = responseHasher.digest(); + if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); + const nextChallengeHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + nextChallengeHasher.update(hashResponse); + await hashSection(fdNew, "G1", 2, 2 ** power * 2 - 1, "tauG1", logger); + await hashSection(fdNew, "G2", 3, 2 ** power, "tauG2", logger); + await hashSection(fdNew, "G1", 4, 2 ** power, "alphaTauG1", logger); + await hashSection(fdNew, "G1", 5, 2 ** power, "betaTauG1", logger); + await hashSection(fdNew, "G2", 6, 1, "betaG2", logger); + curContribution.nextChallenge = nextChallengeHasher.digest(); + if (logger) logger.info(formatHash(curContribution.nextChallenge, "Next Challenge Hash: ")); + contributions.push(curContribution); + await writeContributions(fdNew, curve, contributions); + await fdOld.close(); + await fdNew.close(); + return hashResponse; + async function processSection(sectionId, groupName, NPoints, first, inc, sectionName, logger) { + const res = []; + fdOld.pos = sections[sectionId][0].p; + await _iden3_binfileutils.startWriteSection(fdNew, sectionId); + startSections[sectionId] = fdNew.pos; + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const chunkSize = Math.floor((1 << 20) / sG); + let t = first; + for (let i = 0; i < NPoints; i += chunkSize) { + if (logger) logger.debug(`applying key${sectionName}: ${i}/${NPoints}`); + const n = Math.min(NPoints - i, chunkSize); + const buffIn = await fdOld.read(n * sG); + const buffOutLEM = await G.batchApplyKey(buffIn, t, inc); + const promiseWrite = fdNew.write(buffOutLEM); + const buffOutC = await G.batchLEMtoC(buffOutLEM); + responseHasher.update(buffOutC); + await promiseWrite; + if (i == 0) for (let j = 0; j < Math.min(2, NPoints); j++) res.push(G.fromRprLEM(buffOutLEM, j * sG)); + t = curve.Fr.mul(t, curve.Fr.exp(inc, n)); + } + await _iden3_binfileutils.endWriteSection(fdNew); + return res; + } + async function hashSection(fdTo, groupName, sectionId, nPoints, sectionName, logger) { + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const nPointsChunk = Math.floor((1 << 24) / sG); + const oldPos = fdTo.pos; + fdTo.pos = startSections[sectionId]; + for (let i = 0; i < nPoints; i += nPointsChunk) { + if (logger) logger.debug(`Hashing ${sectionName}: ${i}/${nPoints}`); + const n = Math.min(nPoints - i, nPointsChunk); + const buffLEM = await fdTo.read(n * sG); + const buffU = await G.batchLEMtoU(buffLEM); + nextChallengeHasher.update(buffU); + } + fdTo.pos = oldPos; + } +} +//#endregion +//#region src/powersoftau_contribute.js async function contribute(oldPtauFilename, newPTauFilename, name, entropy, logger) { - - const {fd: fdOld, sections} = await binFileUtils__namespace.readBinFile(oldPtauFilename, "ptau", 1); - const {curve, power, ceremonyPower} = await readPTauHeader(fdOld, sections); - if (power != ceremonyPower) { - if (logger) logger.error("This file has been reduced. You cannot contribute into a reduced file."); - throw new Error("This file has been reduced. You cannot contribute into a reduced file."); - } - if (sections[12]) { - if (logger) logger.warn("WARNING: Contributing into a file that has phase2 calculated. You will have to prepare phase2 again."); - } - const contributions = await readContributions(fdOld, curve, sections); - const curContribution = { - name: name, - type: 0, // Beacon - }; - - let lastChallengeHash; - - const rng = await getRandomRng(entropy); - - if (contributions.length>0) { - lastChallengeHash = contributions[contributions.length-1].nextChallenge; - } else { - lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); - } - - // Generate a random key - - - curContribution.key = createPTauKey(curve, lastChallengeHash, rng); - - - const responseHasher = blake2b.blake2b.create({ dkLen: 64 }); - responseHasher.update(lastChallengeHash); - - const fdNew = await binFileUtils__namespace.createBinFile(newPTauFilename, "ptau", 1, 7); - await writePTauHeader(fdNew, curve, power); - - const startSections = []; - - let firstPoints; - firstPoints = await processSection(2, "G1", (2 ** power) * 2 -1, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG1" ); - curContribution.tauG1 = firstPoints[1]; - firstPoints = await processSection(3, "G2", (2 ** power) , curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG2" ); - curContribution.tauG2 = firstPoints[1]; - firstPoints = await processSection(4, "G1", (2 ** power) , curContribution.key.alpha.prvKey, curContribution.key.tau.prvKey, "alphaTauG1" ); - curContribution.alphaG1 = firstPoints[0]; - firstPoints = await processSection(5, "G1", (2 ** power) , curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG1" ); - curContribution.betaG1 = firstPoints[0]; - firstPoints = await processSection(6, "G2", 1, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG2" ); - curContribution.betaG2 = firstPoints[0]; - - curContribution.partialHash = toPartialHash(responseHasher); - - const buffKey = new Uint8Array(curve.F1.n8*2*6+curve.F2.n8*2*3); - - toPtauPubKeyRpr(buffKey, 0, curve, curContribution.key, false); - - responseHasher.update(new Uint8Array(buffKey)); - const hashResponse = responseHasher.digest(); - - if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); - - const nextChallengeHasher = blake2b.blake2b.create({ dkLen: 64 }); - nextChallengeHasher.update(hashResponse); - - await hashSection(fdNew, "G1", 2, (2 ** power) * 2 -1, "tauG1"); - await hashSection(fdNew, "G2", 3, (2 ** power) , "tauG2"); - await hashSection(fdNew, "G1", 4, (2 ** power) , "alphaTauG1"); - await hashSection(fdNew, "G1", 5, (2 ** power) , "betaTauG1"); - await hashSection(fdNew, "G2", 6, 1 , "betaG2"); - - curContribution.nextChallenge = nextChallengeHasher.digest(); - - if (logger) logger.info(formatHash(curContribution.nextChallenge, "Next Challenge Hash: ")); - - contributions.push(curContribution); - - await writeContributions(fdNew, curve, contributions); - - await fdOld.close(); - await fdNew.close(); - - return hashResponse; - - async function processSection(sectionId, groupName, NPoints, first, inc, sectionName) { - const res = []; - fdOld.pos = sections[sectionId][0].p; - - await binFileUtils__namespace.startWriteSection(fdNew, sectionId); - - startSections[sectionId] = fdNew.pos; - - const G = curve[groupName]; - const sG = G.F.n8*2; - const chunkSize = Math.floor((1<<20) / sG); // 128Mb chunks - let t = first; - for (let i=0 ; i. -*/ - + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(oldPtauFilename, "ptau", 1); + const { curve, power, ceremonyPower } = await readPTauHeader(fdOld, sections); + if (power != ceremonyPower) { + if (logger) logger.error("This file has been reduced. You cannot contribute into a reduced file."); + throw new Error("This file has been reduced. You cannot contribute into a reduced file."); + } + if (sections[12]) { + if (logger) logger.warn("WARNING: Contributing into a file that has phase2 calculated. You will have to prepare phase2 again."); + } + const contributions = await readContributions(fdOld, curve, sections); + const curContribution = { + name, + type: 0 + }; + let lastChallengeHash; + const rng = await getRandomRng(entropy); + if (contributions.length > 0) lastChallengeHash = contributions[contributions.length - 1].nextChallenge; + else lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); + curContribution.key = createPTauKey(curve, lastChallengeHash, rng); + const responseHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + responseHasher.update(lastChallengeHash); + const fdNew = await _iden3_binfileutils.createBinFile(newPTauFilename, "ptau", 1, 7); + await writePTauHeader(fdNew, curve, power); + const startSections = []; + let firstPoints; + firstPoints = await processSection(2, "G1", 2 ** power * 2 - 1, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG1"); + curContribution.tauG1 = firstPoints[1]; + firstPoints = await processSection(3, "G2", 2 ** power, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG2"); + curContribution.tauG2 = firstPoints[1]; + firstPoints = await processSection(4, "G1", 2 ** power, curContribution.key.alpha.prvKey, curContribution.key.tau.prvKey, "alphaTauG1"); + curContribution.alphaG1 = firstPoints[0]; + firstPoints = await processSection(5, "G1", 2 ** power, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG1"); + curContribution.betaG1 = firstPoints[0]; + firstPoints = await processSection(6, "G2", 1, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG2"); + curContribution.betaG2 = firstPoints[0]; + curContribution.partialHash = toPartialHash(responseHasher); + const buffKey = new Uint8Array(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3); + toPtauPubKeyRpr(buffKey, 0, curve, curContribution.key, false); + responseHasher.update(new Uint8Array(buffKey)); + const hashResponse = responseHasher.digest(); + if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); + const nextChallengeHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + nextChallengeHasher.update(hashResponse); + await hashSection(fdNew, "G1", 2, 2 ** power * 2 - 1, "tauG1"); + await hashSection(fdNew, "G2", 3, 2 ** power, "tauG2"); + await hashSection(fdNew, "G1", 4, 2 ** power, "alphaTauG1"); + await hashSection(fdNew, "G1", 5, 2 ** power, "betaTauG1"); + await hashSection(fdNew, "G2", 6, 1, "betaG2"); + curContribution.nextChallenge = nextChallengeHasher.digest(); + if (logger) logger.info(formatHash(curContribution.nextChallenge, "Next Challenge Hash: ")); + contributions.push(curContribution); + await writeContributions(fdNew, curve, contributions); + await fdOld.close(); + await fdNew.close(); + return hashResponse; + async function processSection(sectionId, groupName, NPoints, first, inc, sectionName) { + const res = []; + fdOld.pos = sections[sectionId][0].p; + await _iden3_binfileutils.startWriteSection(fdNew, sectionId); + startSections[sectionId] = fdNew.pos; + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const chunkSize = Math.floor((1 << 20) / sG); + let t = first; + for (let i = 0; i < NPoints; i += chunkSize) { + if (logger) logger.debug(`processing: ${sectionName}: ${i}/${NPoints}`); + const n = Math.min(NPoints - i, chunkSize); + const buffIn = await fdOld.read(n * sG); + const buffOutLEM = await G.batchApplyKey(buffIn, t, inc); + const promiseWrite = fdNew.write(buffOutLEM); + const buffOutC = await G.batchLEMtoC(buffOutLEM); + responseHasher.update(buffOutC); + await promiseWrite; + if (i == 0) for (let j = 0; j < Math.min(2, NPoints); j++) res.push(G.fromRprLEM(buffOutLEM, j * sG)); + t = curve.Fr.mul(t, curve.Fr.exp(inc, n)); + } + await _iden3_binfileutils.endWriteSection(fdNew); + return res; + } + async function hashSection(fdTo, groupName, sectionId, nPoints, sectionName) { + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const nPointsChunk = Math.floor((1 << 24) / sG); + const oldPos = fdTo.pos; + fdTo.pos = startSections[sectionId]; + for (let i = 0; i < nPoints; i += nPointsChunk) { + if (logger && i) logger.debug(`Hashing ${sectionName}: ` + i); + const n = Math.min(nPoints - i, nPointsChunk); + const buffLEM = await fdTo.read(n * sG); + const buffU = await G.batchLEMtoU(buffLEM); + nextChallengeHasher.update(buffU); + } + fdTo.pos = oldPos; + } +} +//#endregion +//#region src/powersoftau_preparephase2.js async function preparePhase2(oldPtauFilename, newPTauFilename, logger) { - - const {fd: fdOld, sections} = await binFileUtils__namespace.readBinFile(oldPtauFilename, "ptau", 1); - const {curve, power} = await readPTauHeader(fdOld, sections); - - const fdNew = await binFileUtils__namespace.createBinFile(newPTauFilename, "ptau", 1, 11); - await writePTauHeader(fdNew, curve, power); - - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 2); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 3); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 4); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 5); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 6); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 7); - - await processSection(2, 12, "G1", "tauG1" ); - await processSection(3, 13, "G2", "tauG2" ); - await processSection(4, 14, "G1", "alphaTauG1" ); - await processSection(5, 15, "G1", "betaTauG1" ); - - await fdOld.close(); - await fdNew.close(); - - // await fs.promises.unlink(newPTauFilename+ ".tmp"); - - return; - - async function processSection(oldSectionId, newSectionId, Gstr, sectionName) { - if (logger) logger.debug("Starting section: "+sectionName); - - await binFileUtils__namespace.startWriteSection(fdNew, newSectionId); - - for (let p=0; p<=power; p++) { - await processSectionPower(p); - } - - if (oldSectionId == 2) { - await processSectionPower(power+1); - } - - await binFileUtils__namespace.endWriteSection(fdNew); - - - async function processSectionPower(p) { - const nPoints = 2 ** p; - const G = curve[Gstr]; - curve.Fr; - const sGin = G.F.n8*2; - G.F.n8*3; - - let buff; - buff = new ffjavascript.BigBuffer(nPoints*sGin); - - await binFileUtils__namespace.startReadUniqueSection(fdOld, sections, oldSectionId); - if ((oldSectionId == 2)&&(p==power+1)) { - await fdOld.readToBuffer(buff, 0,(nPoints-1)*sGin ); - buff.set(curve.G1.zeroAffine, (nPoints-1)*sGin ); - } else { - await fdOld.readToBuffer(buff, 0,nPoints*sGin ); - } - await binFileUtils__namespace.endReadSection(fdOld, true); - - - buff = await G.lagrangeEvaluations(buff, "affine", "affine", logger, sectionName); - await fdNew.write(buff); - -/* - if (p <= curve.Fr.s) { - buff = await G.ifft(buff, "affine", "affine", logger, sectionName); - await fdNew.write(buff); - } else if (p == curve.Fr.s+1) { - const smallM = 1<. -*/ - + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(oldPtauFilename, "ptau", 1); + const { curve, power } = await readPTauHeader(fdOld, sections); + const fdNew = await _iden3_binfileutils.createBinFile(newPTauFilename, "ptau", 1, 11); + await writePTauHeader(fdNew, curve, power); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 2); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 3); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 4); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 5); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 6); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 7); + await processSection(2, 12, "G1", "tauG1"); + await processSection(3, 13, "G2", "tauG2"); + await processSection(4, 14, "G1", "alphaTauG1"); + await processSection(5, 15, "G1", "betaTauG1"); + await fdOld.close(); + await fdNew.close(); + return; + async function processSection(oldSectionId, newSectionId, Gstr, sectionName) { + if (logger) logger.debug("Starting section: " + sectionName); + await _iden3_binfileutils.startWriteSection(fdNew, newSectionId); + for (let p = 0; p <= power; p++) await processSectionPower(p); + if (oldSectionId == 2) await processSectionPower(power + 1); + await _iden3_binfileutils.endWriteSection(fdNew); + async function processSectionPower(p) { + const nPoints = 2 ** p; + const G = curve[Gstr]; + const sGin = G.F.n8 * 2; + let buff; + buff = new ffjavascript.BigBuffer(nPoints * sGin); + await _iden3_binfileutils.startReadUniqueSection(fdOld, sections, oldSectionId); + if (oldSectionId == 2 && p == power + 1) { + await fdOld.readToBuffer(buff, 0, (nPoints - 1) * sGin); + buff.set(curve.G1.zeroAffine, (nPoints - 1) * sGin); + } else await fdOld.readToBuffer(buff, 0, nPoints * sGin); + await _iden3_binfileutils.endReadSection(fdOld, true); + buff = await G.lagrangeEvaluations(buff, "affine", "affine", logger, sectionName); + await fdNew.write(buff); + } + } +} +//#endregion +//#region src/powersoftau_truncate.js async function truncate(ptauFilename, template, logger) { - - const {fd: fdOld, sections} = await binFileUtils__namespace.readBinFile(ptauFilename, "ptau", 1); - const {curve, power, ceremonyPower} = await readPTauHeader(fdOld, sections); - - const sG1 = curve.G1.F.n8*2; - const sG2 = curve.G2.F.n8*2; - - for (let p=1; p. -*/ - + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(ptauFilename, "ptau", 1); + const { curve, power, ceremonyPower } = await readPTauHeader(fdOld, sections); + const sG1 = curve.G1.F.n8 * 2; + const sG2 = curve.G2.F.n8 * 2; + for (let p = 1; p < power; p++) await generateTruncate(p); + await fdOld.close(); + return true; + async function generateTruncate(p) { + let sP = p.toString(); + while (sP.length < 2) sP = "0" + sP; + if (logger) logger.debug("Writing Power: " + sP); + const fdNew = await _iden3_binfileutils.createBinFile(template + sP + ".ptau", "ptau", 1, 11); + await writePTauHeader(fdNew, curve, p, ceremonyPower); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 2, (2 ** p * 2 - 1) * sG1); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 3, 2 ** p * sG2); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 4, 2 ** p * sG1); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 5, 2 ** p * sG1); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 6, sG2); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 7); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 12, (2 ** (p + 1) * 2 - 1) * sG1); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 13, (2 ** p * 2 - 1) * sG2); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 14, (2 ** p * 2 - 1) * sG1); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 15, (2 ** p * 2 - 1) * sG1); + await fdNew.close(); + } +} +//#endregion +//#region src/powersoftau_convert.js async function convert(oldPtauFilename, newPTauFilename, logger) { - - const {fd: fdOld, sections} = await binFileUtils__namespace.readBinFile(oldPtauFilename, "ptau", 1); - const {curve, power} = await readPTauHeader(fdOld, sections); - - const fdNew = await binFileUtils__namespace.createBinFile(newPTauFilename, "ptau", 1, 11); - await writePTauHeader(fdNew, curve, power); - - // const fdTmp = await fastFile.createOverride(newPTauFilename+ ".tmp"); - - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 2); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 3); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 4); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 5); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 6); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 7); - - await processSection(2, 12, "G1", "tauG1" ); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 13); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 14); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 15); - - await fdOld.close(); - await fdNew.close(); - - // await fs.promises.unlink(newPTauFilename+ ".tmp"); - - return; - - async function processSection(oldSectionId, newSectionId, Gstr, sectionName) { - if (logger) logger.debug("Starting section: "+sectionName); - - await binFileUtils__namespace.startWriteSection(fdNew, newSectionId); - - const size = sections[newSectionId][0].size; - const chunkSize = fdOld.pageSize; - await binFileUtils__namespace.startReadUniqueSection(fdOld, sections, newSectionId); - for (let p=0; p. -*/ - + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(oldPtauFilename, "ptau", 1); + const { curve, power } = await readPTauHeader(fdOld, sections); + const fdNew = await _iden3_binfileutils.createBinFile(newPTauFilename, "ptau", 1, 11); + await writePTauHeader(fdNew, curve, power); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 2); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 3); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 4); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 5); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 6); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 7); + await processSection(2, 12, "G1", "tauG1"); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 13); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 14); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 15); + await fdOld.close(); + await fdNew.close(); + return; + async function processSection(oldSectionId, newSectionId, Gstr, sectionName) { + if (logger) logger.debug("Starting section: " + sectionName); + await _iden3_binfileutils.startWriteSection(fdNew, newSectionId); + const size = sections[newSectionId][0].size; + const chunkSize = fdOld.pageSize; + await _iden3_binfileutils.startReadUniqueSection(fdOld, sections, newSectionId); + for (let p = 0; p < size; p += chunkSize) { + const l = Math.min(size - p, chunkSize); + const buff = await fdOld.read(l); + await fdNew.write(buff); + } + await _iden3_binfileutils.endReadSection(fdOld); + if (oldSectionId == 2) await processSectionPower(power + 1); + await _iden3_binfileutils.endWriteSection(fdNew); + async function processSectionPower(p) { + const nPoints = 2 ** p; + const G = curve[Gstr]; + const sGin = G.F.n8 * 2; + let buff; + buff = new ffjavascript.BigBuffer(nPoints * sGin); + await _iden3_binfileutils.startReadUniqueSection(fdOld, sections, oldSectionId); + if (oldSectionId == 2 && p == power + 1) { + await fdOld.readToBuffer(buff, 0, (nPoints - 1) * sGin); + buff.set(curve.G1.zeroAffine, (nPoints - 1) * sGin); + } else await fdOld.readToBuffer(buff, 0, nPoints * sGin); + await _iden3_binfileutils.endReadSection(fdOld, true); + buff = await G.lagrangeEvaluations(buff, "affine", "affine", logger, sectionName); + await fdNew.write(buff); + } + } +} +//#endregion +//#region src/powersoftau_export_json.js async function exportJson(pTauFilename, verbose) { - const {fd, sections} = await binFileUtils__namespace.readBinFile(pTauFilename, "ptau", 1); - - const {curve, power} = await readPTauHeader(fd, sections); - - const pTau = {}; - pTau.q = curve.q; - pTau.power = power; - pTau.contributions = await readContributions(fd, curve, sections); - - pTau.tauG1 = await exportSection(2, "G1", (2 ** power)*2 -1, "tauG1"); - pTau.tauG2 = await exportSection(3, "G2", (2 ** power), "tauG2"); - pTau.alphaTauG1 = await exportSection(4, "G1", (2 ** power), "alphaTauG1"); - pTau.betaTauG1 = await exportSection(5, "G1", (2 ** power), "betaTauG1"); - pTau.betaG2 = await exportSection(6, "G2", 1, "betaG2"); - - pTau.lTauG1 = await exportLagrange(12, "G1", "lTauG1"); - pTau.lTauG2 = await exportLagrange(13, "G2", "lTauG2"); - pTau.lAlphaTauG1 = await exportLagrange(14, "G1", "lAlphaTauG2"); - pTau.lBetaTauG1 = await exportLagrange(15, "G1", "lBetaTauG2"); - - await fd.close(); - - return stringifyBigIntsWithField(curve.Fr, pTau); - - - - async function exportSection(sectionId, groupName, nPoints, sectionName) { - const G = curve[groupName]; - const sG = G.F.n8*2; - - const res = []; - await binFileUtils__namespace.startReadUniqueSection(fd, sections, sectionId); - for (let i=0; i< nPoints; i++) { - if ((verbose)&&i&&(i%10000 == 0)) console.log(`${sectionName}: ` + i); - const buff = await fd.read(sG); - res.push(G.fromRprLEM(buff, 0)); - } - await binFileUtils__namespace.endReadSection(fd); - - return res; - } - - async function exportLagrange(sectionId, groupName, sectionName) { - const G = curve[groupName]; - const sG = G.F.n8*2; - - const res = []; - await binFileUtils__namespace.startReadUniqueSection(fd, sections, sectionId); - for (let p=0; p<=power; p++) { - if (verbose) console.log(`${sectionName}: Power: ${p}`); - res[p] = []; - const nPoints = (2 ** p); - for (let i=0; i. -*/ - -const SUBARRAY_SIZE = 0x40000; - -const BigArrayHandler = { - get: function(obj, prop) { - if (!isNaN(prop)) { - return obj.getElement(prop); - } else return obj[prop]; - }, - set: function(obj, prop, value) { - if (!isNaN(prop)) { - return obj.setElement(prop, value); - } else { - obj[prop] = value; - return true; - } - } + const { fd, sections } = await _iden3_binfileutils.readBinFile(pTauFilename, "ptau", 1); + const { curve, power } = await readPTauHeader(fd, sections); + const pTau = {}; + pTau.q = curve.q; + pTau.power = power; + pTau.contributions = await readContributions(fd, curve, sections); + pTau.tauG1 = await exportSection(2, "G1", 2 ** power * 2 - 1, "tauG1"); + pTau.tauG2 = await exportSection(3, "G2", 2 ** power, "tauG2"); + pTau.alphaTauG1 = await exportSection(4, "G1", 2 ** power, "alphaTauG1"); + pTau.betaTauG1 = await exportSection(5, "G1", 2 ** power, "betaTauG1"); + pTau.betaG2 = await exportSection(6, "G2", 1, "betaG2"); + pTau.lTauG1 = await exportLagrange(12, "G1", "lTauG1"); + pTau.lTauG2 = await exportLagrange(13, "G2", "lTauG2"); + pTau.lAlphaTauG1 = await exportLagrange(14, "G1", "lAlphaTauG2"); + pTau.lBetaTauG1 = await exportLagrange(15, "G1", "lBetaTauG2"); + await fd.close(); + return stringifyBigIntsWithField(curve.Fr, pTau); + async function exportSection(sectionId, groupName, nPoints, sectionName) { + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const res = []; + await _iden3_binfileutils.startReadUniqueSection(fd, sections, sectionId); + for (let i = 0; i < nPoints; i++) { + if (verbose && i && i % 1e4 == 0) console.log(`${sectionName}: ` + i); + const buff = await fd.read(sG); + res.push(G.fromRprLEM(buff, 0)); + } + await _iden3_binfileutils.endReadSection(fd); + return res; + } + async function exportLagrange(sectionId, groupName, sectionName) { + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const res = []; + await _iden3_binfileutils.startReadUniqueSection(fd, sections, sectionId); + for (let p = 0; p <= power; p++) { + if (verbose) console.log(`${sectionName}: Power: ${p}`); + res[p] = []; + const nPoints = 2 ** p; + for (let i = 0; i < nPoints; i++) { + if (verbose && i && i % 1e4 == 0) console.log(`${sectionName}: ${i}/${nPoints}`); + const buff = await fd.read(sG); + res[p].push(G.fromRprLEM(buff, 0)); + } + } + await _iden3_binfileutils.endReadSection(fd, true); + return res; + } +} +//#endregion +//#region src/bigarray.js +var SUBARRAY_SIZE = 262144; +var BigArrayHandler = { + get: function(obj, prop) { + if (!isNaN(prop)) return obj.getElement(prop); + else return obj[prop]; + }, + set: function(obj, prop, value) { + if (!isNaN(prop)) return obj.setElement(prop, value); + else { + obj[prop] = value; + return true; + } + } }; - -class _BigArray { - constructor (initSize) { - this.length = initSize || 0; - this.arr = new Array(SUBARRAY_SIZE); - - for (let i=0; i= this.length) this.length = idx+1; - return true; - } - getKeys() { - const newA = new BigArray(); - for (let i=0; i. -*/ - +var _BigArray = class { + constructor(initSize) { + this.length = initSize || 0; + this.arr = new Array(SUBARRAY_SIZE); + for (let i = 0; i < initSize; i += SUBARRAY_SIZE) this.arr[i / SUBARRAY_SIZE] = new Array(Math.min(SUBARRAY_SIZE, initSize - i)); + return this; + } + push() { + for (let i = 0; i < arguments.length; i++) this.setElement(this.length, arguments[i]); + } + slice(f, t) { + const arr = new Array(t - f); + for (let i = f; i < t; i++) arr[i - f] = this.getElement(i); + return arr; + } + getElement(idx) { + idx = parseInt(idx); + const idx1 = Math.floor(idx / SUBARRAY_SIZE); + const idx2 = idx % SUBARRAY_SIZE; + return this.arr[idx1] ? this.arr[idx1][idx2] : void 0; + } + setElement(idx, value) { + idx = parseInt(idx); + const idx1 = Math.floor(idx / SUBARRAY_SIZE); + if (!this.arr[idx1]) this.arr[idx1] = new Array(SUBARRAY_SIZE); + const idx2 = idx % SUBARRAY_SIZE; + this.arr[idx1][idx2] = value; + if (idx >= this.length) this.length = idx + 1; + return true; + } + getKeys() { + const newA = new BigArray(); + for (let i = 0; i < this.arr.length; i++) if (this.arr[i]) { + for (let j = 0; j < this.arr[i].length; j++) if (typeof this.arr[i][j] !== "undefined") newA.push(i * SUBARRAY_SIZE + j); + } + return newA; + } +}; +var BigArray = class { + constructor(initSize) { + const obj = new _BigArray(initSize); + return new Proxy(obj, BigArrayHandler); + } +}; +//#endregion +//#region src/zkey_new.js async function newZKey(r1csName, ptauName, zkeyName, logger) { - - const TAU_G1 = 0; - const TAU_G2 = 1; - const ALPHATAU_G1 = 2; - const BETATAU_G1 = 3; - const csHasher = blake2b.blake2b.create({ dkLen: 64 }); - - const {fd: fdPTau, sections: sectionsPTau} = await binFileUtils.readBinFile(ptauName, "ptau", 1, 1<<22, 1<<24); - const {curve, power} = await readPTauHeader(fdPTau, sectionsPTau); - const {fd: fdR1cs, sections: sectionsR1cs} = await binFileUtils.readBinFile(r1csName, "r1cs", 1, 1<<22, 1<<24); - const r1cs = await r1csfile.readR1csHeader(fdR1cs, sectionsR1cs, false); - - const fdZKey = await binFileUtils.createBinFile(zkeyName, "zkey", 1, 10, 1<<22, 1<<24); - - const sG1 = curve.G1.F.n8*2; - const sG2 = curve.G2.F.n8*2; - - if (r1cs.prime != curve.r) { - if (logger) logger.error("r1cs curve does not match powers of tau ceremony curve"); - return -1; - } - - const cirPower = log2(r1cs.nConstraints + r1cs.nPubInputs + r1cs.nOutputs +1 -1) +1; - - if (cirPower > power) { - if (logger) logger.error(`circuit too big for this power of tau ceremony. ${r1cs.nConstraints}*2 > 2**${power}`); - return -1; - } - - if (!sectionsPTau[12]) { - if (logger) logger.error("Powers of tau is not prepared."); - return -1; - } - - const nPublic = r1cs.nOutputs + r1cs.nPubInputs; - const domainSize = 2 ** cirPower; - - // Write the header - /////////// - await binFileUtils.startWriteSection(fdZKey, 1); - await fdZKey.writeULE32(1); // Groth - await binFileUtils.endWriteSection(fdZKey); - - // Write the Groth header section - /////////// - - await binFileUtils.startWriteSection(fdZKey, 2); - const primeQ = curve.q; - const n8q = (Math.floor( (ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) +1)*8; - - const primeR = curve.r; - const n8r = (Math.floor( (ffjavascript.Scalar.bitLength(primeR) - 1) / 64) +1)*8; - const Rr = ffjavascript.Scalar.mod(ffjavascript.Scalar.shl(1, n8r*8), primeR); - const R2r = curve.Fr.e(ffjavascript.Scalar.mod(ffjavascript.Scalar.mul(Rr,Rr), primeR)); - - await fdZKey.writeULE32(n8q); - await binFileUtils.writeBigInt(fdZKey, primeQ, n8q); - await fdZKey.writeULE32(n8r); - await binFileUtils.writeBigInt(fdZKey, primeR, n8r); - await fdZKey.writeULE32(r1cs.nVars); // Total number of bars - await fdZKey.writeULE32(nPublic); // Total number of public vars (not including ONE) - await fdZKey.writeULE32(domainSize); // domainSize - - let bAlpha1; - bAlpha1 = await fdPTau.read(sG1, sectionsPTau[4][0].p); - await fdZKey.write(bAlpha1); - bAlpha1 = await curve.G1.batchLEMtoU(bAlpha1); - csHasher.update(bAlpha1); - - let bBeta1; - bBeta1 = await fdPTau.read(sG1, sectionsPTau[5][0].p); - await fdZKey.write(bBeta1); - bBeta1 = await curve.G1.batchLEMtoU(bBeta1); - csHasher.update(bBeta1); - - let bBeta2; - bBeta2 = await fdPTau.read(sG2, sectionsPTau[6][0].p); - await fdZKey.write(bBeta2); - bBeta2 = await curve.G2.batchLEMtoU(bBeta2); - csHasher.update(bBeta2); - - const bg1 = new Uint8Array(sG1); - curve.G1.toRprLEM(bg1, 0, curve.G1.g); - const bg2 = new Uint8Array(sG2); - curve.G2.toRprLEM(bg2, 0, curve.G2.g); - const bg1U = new Uint8Array(sG1); - curve.G1.toRprUncompressed(bg1U, 0, curve.G1.g); - const bg2U = new Uint8Array(sG2); - curve.G2.toRprUncompressed(bg2U, 0, curve.G2.g); - - await fdZKey.write(bg2); // gamma2 - await fdZKey.write(bg1); // delta1 - await fdZKey.write(bg2); // delta2 - csHasher.update(bg2U); // gamma2 - csHasher.update(bg1U); // delta1 - csHasher.update(bg2U); // delta2 - await binFileUtils.endWriteSection(fdZKey); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("Reading r1cs"); - let sR1cs = await binFileUtils.readSection(fdR1cs, sectionsR1cs, 2); - await fdR1cs.close(); - - let A = new BigArray(r1cs.nVars); - let B1 = new BigArray(r1cs.nVars); - let B2 = new BigArray(r1cs.nVars); - let C = new BigArray(r1cs.nVars- nPublic -1); - let IC = new Array(nPublic+1); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("Reading tauG1"); - let sTauG1 = await binFileUtils.readSection(fdPTau, sectionsPTau, 12, (domainSize -1)*sG1, domainSize*sG1); - if (logger) logger.info("Reading tauG2"); - let sTauG2 = await binFileUtils.readSection(fdPTau, sectionsPTau, 13, (domainSize -1)*sG2, domainSize*sG2); - if (logger) logger.info("Reading alphatauG1"); - let sAlphaTauG1 = await binFileUtils.readSection(fdPTau, sectionsPTau, 14, (domainSize -1)*sG1, domainSize*sG1); - if (logger) logger.info("Reading betatauG1"); - let sBetaTauG1 = await binFileUtils.readSection(fdPTau, sectionsPTau, 15, (domainSize -1)*sG1, domainSize*sG1); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("processConstraints"); - await processConstraints(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints"); - await composeAndWritePoints(3, "G1", IC, "IC"); - - IC = null; - // const gc = runInNewContext("gc"); // nocommit - // gc(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("writeHs"); - await writeHs(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("hashHPoints"); - await hashHPoints(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints 8 G1 C"); - await composeAndWritePoints(8, "G1", C, "C"); - - C = null; - // gc(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints 5 G1 A"); - await composeAndWritePoints(5, "G1", A, "A"); - - A = null; - // gc(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints 6 G1 B1"); - await composeAndWritePoints(6, "G1", B1, "B1"); - - B1 = null; - // gc(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints 7 G2 B2"); - await composeAndWritePoints(7, "G2", B2, "B2"); - - B2 = null; - // gc(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("Contributions section"); - const csHash = csHasher.digest(); - // Contributions section - await binFileUtils.startWriteSection(fdZKey, 10); - await fdZKey.write(csHash); - await fdZKey.writeULE32(0); - await binFileUtils.endWriteSection(fdZKey); - - if (logger) logger.info(formatHash(csHash, "Circuit hash: ")); - - - await fdZKey.close(); - await fdPTau.close(); - - return csHash; - - async function writeHs() { - await binFileUtils.startWriteSection(fdZKey, 9); - const buffOut = new ffjavascript.BigBuffer(domainSize*sG1); - if (cirPower < curve.Fr.s) { - let sTauG1 = await binFileUtils.readSection(fdPTau, sectionsPTau, 12, (domainSize*2-1)*sG1, domainSize*2*sG1); - for (let i=0; i< domainSize; i++) { - if ((logger)&&(i%10000 == 0)) logger.debug(`splitting buffer: ${i}/${domainSize}`); - const buff = sTauG1.slice( (i*2+1)*sG1, (i*2+1)*sG1 + sG1 ); - buffOut.set(buff, i*sG1); - } - } else if (cirPower == curve.Fr.s) { - const o = sectionsPTau[12][0].p + ((2 ** (cirPower+1)) -1)*sG1; - await fdPTau.readToBuffer(buffOut, 0, domainSize*sG1, o + domainSize*sG1); - } else { - if (logger) logger.error("Circuit too big"); - throw new Error("Circuit too big for this curve"); - } - await fdZKey.write(buffOut); - await binFileUtils.endWriteSection(fdZKey); - } - - async function processConstraints() { - const buffCoeff = new Uint8Array(12 + curve.Fr.n8); - const buffCoeffV = new DataView(buffCoeff.buffer); - const bOne = new Uint8Array(curve.Fr.n8); - curve.Fr.toRprLE(bOne, 0, curve.Fr.e(1)); - - let r1csPos = 0; - - function r1cs_readULE32() { - const buff = sR1cs.slice(r1csPos, r1csPos+4); - r1csPos += 4; - const buffV = new DataView(buff.buffer); - return buffV.getUint32(0, true); - } - - const coefs = new BigArray(); - for (let c=0; c=0) { - n = curve.Fr.fromRprLE(sR1cs.slice(c[3], c[3] + curve.Fr.n8), 0); - } else { - n = curve.Fr.fromRprLE(bOne, 0); - } - const nR2 = curve.Fr.mul(n, R2r); - curve.Fr.toRprLE(buffCoeff, 12, nR2); - buffSection.set(buffCoeff, coefsPos); - coefsPos += buffCoeff.length; - } - - } - - async function composeAndWritePoints(idSection, groupName, arr, sectionName) { - const CHUNK_SIZE= 1<<15; - const G = curve[groupName]; - - hashU32(arr.length); - await binFileUtils.startWriteSection(fdZKey, idSection); - - let opPromises = []; - - let i=0; - while (i { - if (logger) logger.debug(`Writing points end ${sectionName}: ${_i}/${arr.length}`); - return r; - })); - i += n; - t++; - } - - const result = await Promise.all(opPromises); - - for (let k=0; k 2<<14) { - bBases = new ffjavascript.BigBuffer(acc*sGin); - bScalars = new ffjavascript.BigBuffer(acc*curve.Fr.n8); - } else { - bBases = new Uint8Array(acc*sGin); - bScalars = new Uint8Array(acc*curve.Fr.n8); - } - let pB =0; - let pS =0; - - const sBuffs = [ - sTauG1, - sTauG2, - sAlphaTauG1, - sBetaTauG1 - ]; - - const bOne = new Uint8Array(curve.Fr.n8); - curve.Fr.toRprLE(bOne, 0, curve.Fr.e(1)); - - let offset = 0; - for (let i=0; i=0) { - bScalars.set( - sR1cs.slice( - arr[i][j][2], - arr[i][j][2] + curve.Fr.n8 - ), - offset*curve.Fr.n8 - ); - } else { - bScalars.set(bOne, offset*curve.Fr.n8); - } - offset ++; - } - } - - if (arr.length>1) { - const task = []; - task.push({cmd: "ALLOCSET", var: 0, buff: bBases}); - task.push({cmd: "ALLOCSET", var: 1, buff: bScalars}); - task.push({cmd: "ALLOC", var: 2, len: arr.length*sGmid}); - pB = 0; - pS = 0; - let pD =0; - for (let i=0; i. -*/ - -// FFlonk constants -const FF_T_POL_DEG_MIN = 3; - -// ZKEY constants -const ZKEY_FF_NSECTIONS = 17; - -const ZKEY_FF_HEADER_SECTION = 2; -const ZKEY_FF_ADDITIONS_SECTION = 3; -const ZKEY_FF_A_MAP_SECTION = 4; -const ZKEY_FF_B_MAP_SECTION = 5; -const ZKEY_FF_C_MAP_SECTION = 6; -const ZKEY_FF_QL_SECTION = 7; -const ZKEY_FF_QR_SECTION = 8; -const ZKEY_FF_QM_SECTION = 9; -const ZKEY_FF_QO_SECTION = 10; -const ZKEY_FF_QC_SECTION = 11; -const ZKEY_FF_SIGMA1_SECTION = 12; -const ZKEY_FF_SIGMA2_SECTION = 13; -const ZKEY_FF_SIGMA3_SECTION = 14; -const ZKEY_FF_LAGRANGE_SECTION = 15; -const ZKEY_FF_PTAU_SECTION = 16; -const ZKEY_FF_C0_SECTION = 17; - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - + const TAU_G1 = 0; + const TAU_G2 = 1; + const ALPHATAU_G1 = 2; + const BETATAU_G1 = 3; + const csHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + const { fd: fdPTau, sections: sectionsPTau } = await (0, _iden3_binfileutils.readBinFile)(ptauName, "ptau", 1, 1 << 22, 1 << 24); + const { curve, power } = await readPTauHeader(fdPTau, sectionsPTau); + const { fd: fdR1cs, sections: sectionsR1cs } = await (0, _iden3_binfileutils.readBinFile)(r1csName, "r1cs", 1, 1 << 22, 1 << 24); + const r1cs = await (0, r1csfile.readR1csHeader)(fdR1cs, sectionsR1cs, false); + const fdZKey = await (0, _iden3_binfileutils.createBinFile)(zkeyName, "zkey", 1, 10, 1 << 22, 1 << 24); + const sG1 = curve.G1.F.n8 * 2; + const sG2 = curve.G2.F.n8 * 2; + if (r1cs.prime != curve.r) { + if (logger) logger.error("r1cs curve does not match powers of tau ceremony curve"); + return -1; + } + const cirPower = log2(r1cs.nConstraints + r1cs.nPubInputs + r1cs.nOutputs + 1 - 1) + 1; + if (cirPower > power) { + if (logger) logger.error(`circuit too big for this power of tau ceremony. ${r1cs.nConstraints}*2 > 2**${power}`); + return -1; + } + if (!sectionsPTau[12]) { + if (logger) logger.error("Powers of tau is not prepared."); + return -1; + } + const nPublic = r1cs.nOutputs + r1cs.nPubInputs; + const domainSize = 2 ** cirPower; + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 1); + await fdZKey.writeULE32(1); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 2); + const primeQ = curve.q; + const n8q = (Math.floor((ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) + 1) * 8; + const primeR = curve.r; + const n8r = (Math.floor((ffjavascript.Scalar.bitLength(primeR) - 1) / 64) + 1) * 8; + const Rr = ffjavascript.Scalar.mod(ffjavascript.Scalar.shl(1, n8r * 8), primeR); + const R2r = curve.Fr.e(ffjavascript.Scalar.mod(ffjavascript.Scalar.mul(Rr, Rr), primeR)); + await fdZKey.writeULE32(n8q); + await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeQ, n8q); + await fdZKey.writeULE32(n8r); + await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeR, n8r); + await fdZKey.writeULE32(r1cs.nVars); + await fdZKey.writeULE32(nPublic); + await fdZKey.writeULE32(domainSize); + let bAlpha1; + bAlpha1 = await fdPTau.read(sG1, sectionsPTau[4][0].p); + await fdZKey.write(bAlpha1); + bAlpha1 = await curve.G1.batchLEMtoU(bAlpha1); + csHasher.update(bAlpha1); + let bBeta1; + bBeta1 = await fdPTau.read(sG1, sectionsPTau[5][0].p); + await fdZKey.write(bBeta1); + bBeta1 = await curve.G1.batchLEMtoU(bBeta1); + csHasher.update(bBeta1); + let bBeta2; + bBeta2 = await fdPTau.read(sG2, sectionsPTau[6][0].p); + await fdZKey.write(bBeta2); + bBeta2 = await curve.G2.batchLEMtoU(bBeta2); + csHasher.update(bBeta2); + const bg1 = new Uint8Array(sG1); + curve.G1.toRprLEM(bg1, 0, curve.G1.g); + const bg2 = new Uint8Array(sG2); + curve.G2.toRprLEM(bg2, 0, curve.G2.g); + const bg1U = new Uint8Array(sG1); + curve.G1.toRprUncompressed(bg1U, 0, curve.G1.g); + const bg2U = new Uint8Array(sG2); + curve.G2.toRprUncompressed(bg2U, 0, curve.G2.g); + await fdZKey.write(bg2); + await fdZKey.write(bg1); + await fdZKey.write(bg2); + csHasher.update(bg2U); + csHasher.update(bg1U); + csHasher.update(bg2U); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + if (logger) logger.info(memUsage()); + if (logger) logger.info("Reading r1cs"); + let sR1cs = await (0, _iden3_binfileutils.readSection)(fdR1cs, sectionsR1cs, 2); + await fdR1cs.close(); + let A = new BigArray(r1cs.nVars); + let B1 = new BigArray(r1cs.nVars); + let B2 = new BigArray(r1cs.nVars); + let C = new BigArray(r1cs.nVars - nPublic - 1); + let IC = new Array(nPublic + 1); + if (logger) logger.info(memUsage()); + if (logger) logger.info("Reading tauG1"); + let sTauG1 = await (0, _iden3_binfileutils.readSection)(fdPTau, sectionsPTau, 12, (domainSize - 1) * sG1, domainSize * sG1); + if (logger) logger.info("Reading tauG2"); + let sTauG2 = await (0, _iden3_binfileutils.readSection)(fdPTau, sectionsPTau, 13, (domainSize - 1) * sG2, domainSize * sG2); + if (logger) logger.info("Reading alphatauG1"); + let sAlphaTauG1 = await (0, _iden3_binfileutils.readSection)(fdPTau, sectionsPTau, 14, (domainSize - 1) * sG1, domainSize * sG1); + if (logger) logger.info("Reading betatauG1"); + let sBetaTauG1 = await (0, _iden3_binfileutils.readSection)(fdPTau, sectionsPTau, 15, (domainSize - 1) * sG1, domainSize * sG1); + if (logger) logger.info(memUsage()); + if (logger) logger.info("processConstraints"); + await processConstraints(); + if (logger) logger.info(memUsage()); + if (logger) logger.info("composeAndWritePoints"); + await composeAndWritePoints(3, "G1", IC, "IC"); + IC = null; + if (logger) logger.info(memUsage()); + if (logger) logger.info("writeHs"); + await writeHs(); + if (logger) logger.info(memUsage()); + if (logger) logger.info("hashHPoints"); + await hashHPoints(); + if (logger) logger.info(memUsage()); + if (logger) logger.info("composeAndWritePoints 8 G1 C"); + await composeAndWritePoints(8, "G1", C, "C"); + C = null; + if (logger) logger.info(memUsage()); + if (logger) logger.info("composeAndWritePoints 5 G1 A"); + await composeAndWritePoints(5, "G1", A, "A"); + A = null; + if (logger) logger.info(memUsage()); + if (logger) logger.info("composeAndWritePoints 6 G1 B1"); + await composeAndWritePoints(6, "G1", B1, "B1"); + B1 = null; + if (logger) logger.info(memUsage()); + if (logger) logger.info("composeAndWritePoints 7 G2 B2"); + await composeAndWritePoints(7, "G2", B2, "B2"); + B2 = null; + if (logger) logger.info(memUsage()); + if (logger) logger.info("Contributions section"); + const csHash = csHasher.digest(); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 10); + await fdZKey.write(csHash); + await fdZKey.writeULE32(0); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + if (logger) logger.info(formatHash(csHash, "Circuit hash: ")); + await fdZKey.close(); + await fdPTau.close(); + return csHash; + async function writeHs() { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 9); + const buffOut = new ffjavascript.BigBuffer(domainSize * sG1); + if (cirPower < curve.Fr.s) { + let sTauG1 = await (0, _iden3_binfileutils.readSection)(fdPTau, sectionsPTau, 12, (domainSize * 2 - 1) * sG1, domainSize * 2 * sG1); + for (let i = 0; i < domainSize; i++) { + if (logger && i % 1e4 == 0) logger.debug(`splitting buffer: ${i}/${domainSize}`); + const buff = sTauG1.slice((i * 2 + 1) * sG1, (i * 2 + 1) * sG1 + sG1); + buffOut.set(buff, i * sG1); + } + } else if (cirPower == curve.Fr.s) { + const o = sectionsPTau[12][0].p + (2 ** (cirPower + 1) - 1) * sG1; + await fdPTau.readToBuffer(buffOut, 0, domainSize * sG1, o + domainSize * sG1); + } else { + if (logger) logger.error("Circuit too big"); + throw new Error("Circuit too big for this curve"); + } + await fdZKey.write(buffOut); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function processConstraints() { + const buffCoeff = new Uint8Array(12 + curve.Fr.n8); + const buffCoeffV = new DataView(buffCoeff.buffer); + const bOne = new Uint8Array(curve.Fr.n8); + curve.Fr.toRprLE(bOne, 0, curve.Fr.e(1)); + let r1csPos = 0; + function r1cs_readULE32() { + const buff = sR1cs.slice(r1csPos, r1csPos + 4); + r1csPos += 4; + return new DataView(buff.buffer).getUint32(0, true); + } + const coefs = new BigArray(); + for (let c = 0; c < r1cs.nConstraints; c++) { + if (logger && c % 1e4 == 0) logger.debug(`processing constraints: ${c}/${r1cs.nConstraints}`); + const nA = r1cs_readULE32(); + for (let i = 0; i < nA; i++) { + const s = r1cs_readULE32(); + const coefp = r1csPos; + r1csPos += curve.Fr.n8; + const l1t = TAU_G1; + const l1 = sG1 * c; + const l2t = BETATAU_G1; + const l2 = sG1 * c; + if (typeof A[s] === "undefined") A[s] = []; + A[s].push([ + l1t, + l1, + coefp + ]); + if (s <= nPublic) { + if (typeof IC[s] === "undefined") IC[s] = []; + IC[s].push([ + l2t, + l2, + coefp + ]); + } else { + if (typeof C[s - nPublic - 1] === "undefined") C[s - nPublic - 1] = []; + C[s - nPublic - 1].push([ + l2t, + l2, + coefp + ]); + } + coefs.push([ + 0, + c, + s, + coefp + ]); + } + const nB = r1cs_readULE32(); + for (let i = 0; i < nB; i++) { + const s = r1cs_readULE32(); + const coefp = r1csPos; + r1csPos += curve.Fr.n8; + const l1t = TAU_G1; + const l1 = sG1 * c; + const l2t = TAU_G2; + const l2 = sG2 * c; + const l3t = ALPHATAU_G1; + const l3 = sG1 * c; + if (typeof B1[s] === "undefined") B1[s] = []; + B1[s].push([ + l1t, + l1, + coefp + ]); + if (typeof B2[s] === "undefined") B2[s] = []; + B2[s].push([ + l2t, + l2, + coefp + ]); + if (s <= nPublic) { + if (typeof IC[s] === "undefined") IC[s] = []; + IC[s].push([ + l3t, + l3, + coefp + ]); + } else { + if (typeof C[s - nPublic - 1] === "undefined") C[s - nPublic - 1] = []; + C[s - nPublic - 1].push([ + l3t, + l3, + coefp + ]); + } + coefs.push([ + 1, + c, + s, + coefp + ]); + } + const nC = r1cs_readULE32(); + for (let i = 0; i < nC; i++) { + const s = r1cs_readULE32(); + const coefp = r1csPos; + r1csPos += curve.Fr.n8; + const l1t = TAU_G1; + const l1 = sG1 * c; + if (s <= nPublic) { + if (typeof IC[s] === "undefined") IC[s] = []; + IC[s].push([ + l1t, + l1, + coefp + ]); + } else { + if (typeof C[s - nPublic - 1] === "undefined") C[s - nPublic - 1] = []; + C[s - nPublic - 1].push([ + l1t, + l1, + coefp + ]); + } + } + } + for (let s = 0; s <= nPublic; s++) { + const l1t = TAU_G1; + const l1 = sG1 * (r1cs.nConstraints + s); + const l2t = BETATAU_G1; + const l2 = sG1 * (r1cs.nConstraints + s); + if (typeof A[s] === "undefined") A[s] = []; + A[s].push([ + l1t, + l1, + -1 + ]); + if (typeof IC[s] === "undefined") IC[s] = []; + IC[s].push([ + l2t, + l2, + -1 + ]); + coefs.push([ + 0, + r1cs.nConstraints + s, + s, + -1 + ]); + } + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 4); + const buffSection = new ffjavascript.BigBuffer(coefs.length * (12 + curve.Fr.n8) + 4); + const buff4 = new Uint8Array(4); + new DataView(buff4.buffer).setUint32(0, coefs.length, true); + buffSection.set(buff4); + let coefsPos = 4; + for (let i = 0; i < coefs.length; i++) { + if (logger && i % 1e5 == 0) logger.debug(`writing coeffs: ${i}/${coefs.length}`); + writeCoef(coefs[i]); + } + await fdZKey.write(buffSection); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + function writeCoef(c) { + buffCoeffV.setUint32(0, c[0], true); + buffCoeffV.setUint32(4, c[1], true); + buffCoeffV.setUint32(8, c[2], true); + let n; + if (c[3] >= 0) n = curve.Fr.fromRprLE(sR1cs.slice(c[3], c[3] + curve.Fr.n8), 0); + else n = curve.Fr.fromRprLE(bOne, 0); + const nR2 = curve.Fr.mul(n, R2r); + curve.Fr.toRprLE(buffCoeff, 12, nR2); + buffSection.set(buffCoeff, coefsPos); + coefsPos += buffCoeff.length; + } + } + async function composeAndWritePoints(idSection, groupName, arr, sectionName) { + const CHUNK_SIZE = 32768; + const G = curve[groupName]; + hashU32(arr.length); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, idSection); + let opPromises = []; + let i = 0; + while (i < arr.length) { + let t = 0; + while (i < arr.length && t < curve.tm.concurrency) { + if (logger) logger.debug(`Writing points start ${sectionName}: ${i}/${arr.length}`); + let n = 1; + let nP = arr[i] ? arr[i].length : 0; + while (i + n < arr.length && nP + (arr[i + n] ? arr[i + n].length : 0) < CHUNK_SIZE && n < CHUNK_SIZE) { + nP += arr[i + n] ? arr[i + n].length : 0; + n++; + } + if (logger) logger.info("before slice:"); + if (logger) logger.info(memUsage()); + const subArr = arr.slice(i, i + n); + if (logger) logger.info("after slice:"); + if (logger) logger.info(memUsage()); + const _i = i; + opPromises.push(composeAndWritePointsThread(groupName, subArr, logger, sectionName).then((r) => { + if (logger) logger.debug(`Writing points end ${sectionName}: ${_i}/${arr.length}`); + return r; + })); + i += n; + t++; + } + const result = await Promise.all(opPromises); + for (let k = 0; k < result.length; k++) { + await fdZKey.write(result[k][0]); + const buff = await G.batchLEMtoU(result[k][0]); + csHasher.update(buff); + } + opPromises = []; + } + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function composeAndWritePointsThread(groupName, arr, logger, sectionName) { + const G = curve[groupName]; + const sGin = G.F.n8 * 2; + const sGmid = G.F.n8 * 3; + const sGout = G.F.n8 * 2; + let fnExp, fnMultiExp, fnBatchToAffine, fnZero; + if (groupName == "G1") { + fnExp = "g1m_timesScalarAffine"; + fnMultiExp = "g1m_multiexpAffine"; + fnBatchToAffine = "g1m_batchToAffine"; + fnZero = "g1m_zero"; + } else if (groupName == "G2") { + fnExp = "g2m_timesScalarAffine"; + fnMultiExp = "g2m_multiexpAffine"; + fnBatchToAffine = "g2m_batchToAffine"; + fnZero = "g2m_zero"; + } else throw new Error("Invalid group"); + let acc = 0; + for (let i = 0; i < arr.length; i++) acc += arr[i] ? arr[i].length : 0; + let bBases, bScalars; + if (acc > 32768) { + bBases = new ffjavascript.BigBuffer(acc * sGin); + bScalars = new ffjavascript.BigBuffer(acc * curve.Fr.n8); + } else { + bBases = new Uint8Array(acc * sGin); + bScalars = new Uint8Array(acc * curve.Fr.n8); + } + let pB; + let pS; + const sBuffs = [ + sTauG1, + sTauG2, + sAlphaTauG1, + sBetaTauG1 + ]; + const bOne = new Uint8Array(curve.Fr.n8); + curve.Fr.toRprLE(bOne, 0, curve.Fr.e(1)); + let offset = 0; + for (let i = 0; i < arr.length; i++) { + if (!arr[i]) continue; + for (let j = 0; j < arr[i].length; j++) { + if (logger && j && j % 1e4 == 0) logger.debug(`Configuring big array ${sectionName}: ${j}/${arr[i].length}`); + bBases.set(sBuffs[arr[i][j][0]].slice(arr[i][j][1], arr[i][j][1] + sGin), offset * sGin); + if (arr[i][j][2] >= 0) bScalars.set(sR1cs.slice(arr[i][j][2], arr[i][j][2] + curve.Fr.n8), offset * curve.Fr.n8); + else bScalars.set(bOne, offset * curve.Fr.n8); + offset++; + } + } + if (arr.length > 1) { + const task = []; + task.push({ + cmd: "ALLOCSET", + var: 0, + buff: bBases + }); + task.push({ + cmd: "ALLOCSET", + var: 1, + buff: bScalars + }); + task.push({ + cmd: "ALLOC", + var: 2, + len: arr.length * sGmid + }); + pB = 0; + pS = 0; + let pD = 0; + for (let i = 0; i < arr.length; i++) { + if (!arr[i]) { + task.push({ + cmd: "CALL", + fnName: fnZero, + params: [{ + var: 2, + offset: pD + }] + }); + pD += sGmid; + continue; + } + if (arr[i].length == 1) task.push({ + cmd: "CALL", + fnName: fnExp, + params: [ + { + var: 0, + offset: pB + }, + { + var: 1, + offset: pS + }, + { val: curve.Fr.n8 }, + { + var: 2, + offset: pD + } + ] + }); + else task.push({ + cmd: "CALL", + fnName: fnMultiExp, + params: [ + { + var: 0, + offset: pB + }, + { + var: 1, + offset: pS + }, + { val: curve.Fr.n8 }, + { val: arr[i].length }, + { + var: 2, + offset: pD + } + ] + }); + pB += sGin * arr[i].length; + pS += curve.Fr.n8 * arr[i].length; + pD += sGmid; + } + task.push({ + cmd: "CALL", + fnName: fnBatchToAffine, + params: [ + { var: 2 }, + { val: arr.length }, + { var: 2 } + ] + }); + task.push({ + cmd: "GET", + out: 0, + var: 2, + len: arr.length * sGout + }); + return await curve.tm.queueAction(task); + } else { + let res = await G.multiExpAffine(bBases, bScalars, logger, sectionName); + res = [G.toAffine(res)]; + return res; + } + } + async function hashHPoints() { + const CHUNK_SIZE = 16384; + hashU32(domainSize - 1); + for (let i = 0; i < domainSize - 1; i += CHUNK_SIZE) { + if (logger) logger.debug(`HashingHPoints: ${i}/${domainSize}`); + const n = Math.min(domainSize - 1, CHUNK_SIZE); + await hashHPointsChunk(i, n); + } + } + async function hashHPointsChunk(offset, nPoints) { + const buff1 = await fdPTau.read(nPoints * sG1, sectionsPTau[2][0].p + (offset + domainSize) * sG1); + const buff2 = await fdPTau.read(nPoints * sG1, sectionsPTau[2][0].p + offset * sG1); + const concurrency = curve.tm.concurrency; + const nPointsPerThread = Math.floor(nPoints / concurrency); + const opPromises = []; + for (let i = 0; i < concurrency; i++) { + let n; + if (i < concurrency - 1) n = nPointsPerThread; + else n = nPoints - i * nPointsPerThread; + if (n == 0) continue; + const subBuff1 = buff1.slice(i * nPointsPerThread * sG1, (i * nPointsPerThread + n) * sG1); + const subBuff2 = buff2.slice(i * nPointsPerThread * sG1, (i * nPointsPerThread + n) * sG1); + opPromises.push(hashHPointsThread(subBuff1, subBuff2)); + } + const result = await Promise.all(opPromises); + for (let i = 0; i < result.length; i++) csHasher.update(result[i][0]); + } + async function hashHPointsThread(buff1, buff2) { + const nPoints = buff1.byteLength / sG1; + const sGmid = curve.G1.F.n8 * 3; + const task = []; + task.push({ + cmd: "ALLOCSET", + var: 0, + buff: buff1 + }); + task.push({ + cmd: "ALLOCSET", + var: 1, + buff: buff2 + }); + task.push({ + cmd: "ALLOC", + var: 2, + len: nPoints * sGmid + }); + for (let i = 0; i < nPoints; i++) task.push({ + cmd: "CALL", + fnName: "g1m_subAffine", + params: [ + { + var: 0, + offset: i * sG1 + }, + { + var: 1, + offset: i * sG1 + }, + { + var: 2, + offset: i * sGmid + } + ] + }); + task.push({ + cmd: "CALL", + fnName: "g1m_batchToAffine", + params: [ + { var: 2 }, + { val: nPoints }, + { var: 2 } + ] + }); + task.push({ + cmd: "CALL", + fnName: "g1m_batchLEMtoU", + params: [ + { var: 2 }, + { val: nPoints }, + { var: 2 } + ] + }); + task.push({ + cmd: "GET", + out: 0, + var: 2, + len: nPoints * sG1 + }); + return await curve.tm.queueAction(task); + } + function hashU32(n) { + const buff = new Uint8Array(4); + new DataView(buff.buffer, buff.byteOffset, buff.byteLength).setUint32(0, n, false); + csHasher.update(buff); + } + function memUsage() { + let m = process.memoryUsage(); + for (const i in m) m[i] = Math.round(m[i] / (1024 * 1024)); + return m; + } +} +//#endregion +//#region src/zkey_utils.js async function writeHeader(fd, zkey) { - - // Write the header - /////////// - await binFileUtils__namespace.startWriteSection(fd, 1); - await fd.writeULE32(1); // Groth - await binFileUtils__namespace.endWriteSection(fd); - - // Write the Groth header section - /////////// - - const curve = await getCurveFromQ(zkey.q); - - await binFileUtils__namespace.startWriteSection(fd, 2); - const primeQ = curve.q; - const n8q = (Math.floor( (ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) +1)*8; - - const primeR = curve.r; - const n8r = (Math.floor( (ffjavascript.Scalar.bitLength(primeR) - 1) / 64) +1)*8; - - await fd.writeULE32(n8q); - await binFileUtils__namespace.writeBigInt(fd, primeQ, n8q); - await fd.writeULE32(n8r); - await binFileUtils__namespace.writeBigInt(fd, primeR, n8r); - await fd.writeULE32(zkey.nVars); // Total number of bars - await fd.writeULE32(zkey.nPublic); // Total number of public vars (not including ONE) - await fd.writeULE32(zkey.domainSize); // domainSize - await writeG1(fd, curve, zkey.vk_alpha_1); - await writeG1(fd, curve, zkey.vk_beta_1); - await writeG2(fd, curve, zkey.vk_beta_2); - await writeG2(fd, curve, zkey.vk_gamma_2); - await writeG1(fd, curve, zkey.vk_delta_1); - await writeG2(fd, curve, zkey.vk_delta_2); - - await binFileUtils__namespace.endWriteSection(fd); - - -} - + await _iden3_binfileutils.startWriteSection(fd, 1); + await fd.writeULE32(1); + await _iden3_binfileutils.endWriteSection(fd); + const curve = await getCurveFromQ(zkey.q); + await _iden3_binfileutils.startWriteSection(fd, 2); + const primeQ = curve.q; + const n8q = (Math.floor((ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) + 1) * 8; + const primeR = curve.r; + const n8r = (Math.floor((ffjavascript.Scalar.bitLength(primeR) - 1) / 64) + 1) * 8; + await fd.writeULE32(n8q); + await _iden3_binfileutils.writeBigInt(fd, primeQ, n8q); + await fd.writeULE32(n8r); + await _iden3_binfileutils.writeBigInt(fd, primeR, n8r); + await fd.writeULE32(zkey.nVars); + await fd.writeULE32(zkey.nPublic); + await fd.writeULE32(zkey.domainSize); + await writeG1(fd, curve, zkey.vk_alpha_1); + await writeG1(fd, curve, zkey.vk_beta_1); + await writeG2(fd, curve, zkey.vk_beta_2); + await writeG2(fd, curve, zkey.vk_gamma_2); + await writeG1(fd, curve, zkey.vk_delta_1); + await writeG2(fd, curve, zkey.vk_delta_2); + await _iden3_binfileutils.endWriteSection(fd); +} async function writeG1(fd, curve, p) { - const buff = new Uint8Array(curve.G1.F.n8*2); - curve.G1.toRprLEM(buff, 0, p); - await fd.write(buff); + const buff = new Uint8Array(curve.G1.F.n8 * 2); + curve.G1.toRprLEM(buff, 0, p); + await fd.write(buff); } - async function writeG2(fd, curve, p) { - const buff = new Uint8Array(curve.G2.F.n8*2); - curve.G2.toRprLEM(buff, 0, p); - await fd.write(buff); + const buff = new Uint8Array(curve.G2.F.n8 * 2); + curve.G2.toRprLEM(buff, 0, p); + await fd.write(buff); } - async function readG1(fd, curve, toObject) { - const buff = await fd.read(curve.G1.F.n8*2); - const res = curve.G1.fromRprLEM(buff, 0); - return toObject ? curve.G1.toObject(res) : res; + const buff = await fd.read(curve.G1.F.n8 * 2); + const res = curve.G1.fromRprLEM(buff, 0); + return toObject ? curve.G1.toObject(res) : res; } - async function readG2(fd, curve, toObject) { - const buff = await fd.read(curve.G2.F.n8*2); - const res = curve.G2.fromRprLEM(buff, 0); - return toObject ? curve.G2.toObject(res) : res; + const buff = await fd.read(curve.G2.F.n8 * 2); + const res = curve.G2.fromRprLEM(buff, 0); + return toObject ? curve.G2.toObject(res) : res; } - - async function readHeader$1(fd, sections, toObject, options) { - // Read Header - ///////////////////// - await binFileUtils__namespace.startReadUniqueSection(fd, sections, 1); - const protocolId = await fd.readULE32(); - await binFileUtils__namespace.endReadSection(fd); - - if (protocolId === GROTH16_PROTOCOL_ID) { - return await readHeaderGroth16(fd, sections, toObject, options); - } else if (protocolId === PLONK_PROTOCOL_ID) { - return await readHeaderPlonk(fd, sections, toObject, options); - } else if (protocolId === FFLONK_PROTOCOL_ID) { - return await readHeaderFFlonk(fd, sections, toObject, options); - } else { - throw new Error("Protocol not supported: "); - } -} - - - - + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 1); + const protocolId = await fd.readULE32(); + await _iden3_binfileutils.endReadSection(fd); + if (protocolId === 1) return await readHeaderGroth16(fd, sections, toObject, options); + else if (protocolId === 2) return await readHeaderPlonk(fd, sections, toObject, options); + else if (protocolId === 10) return await readHeaderFFlonk(fd, sections, toObject, options); + else throw new Error("Protocol not supported: "); +} async function readHeaderGroth16(fd, sections, toObject, options) { - const zkey = {}; - - zkey.protocol = "groth16"; - - // Read Groth Header - ///////////////////// - await binFileUtils__namespace.startReadUniqueSection(fd, sections, 2); - const n8q = await fd.readULE32(); - zkey.n8q = n8q; - zkey.q = await binFileUtils__namespace.readBigInt(fd, n8q); - - const n8r = await fd.readULE32(); - zkey.n8r = n8r; - zkey.r = await binFileUtils__namespace.readBigInt(fd, n8r); - zkey.curve = await getCurveFromQ(zkey.q, options); - zkey.nVars = await fd.readULE32(); - zkey.nPublic = await fd.readULE32(); - zkey.domainSize = await fd.readULE32(); - zkey.power = log2(zkey.domainSize); - zkey.vk_alpha_1 = await readG1(fd, zkey.curve, toObject); - zkey.vk_beta_1 = await readG1(fd, zkey.curve, toObject); - zkey.vk_beta_2 = await readG2(fd, zkey.curve, toObject); - zkey.vk_gamma_2 = await readG2(fd, zkey.curve, toObject); - zkey.vk_delta_1 = await readG1(fd, zkey.curve, toObject); - zkey.vk_delta_2 = await readG2(fd, zkey.curve, toObject); - await binFileUtils__namespace.endReadSection(fd); - - return zkey; - -} - + const zkey = {}; + zkey.protocol = "groth16"; + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 2); + const n8q = await fd.readULE32(); + zkey.n8q = n8q; + zkey.q = await _iden3_binfileutils.readBigInt(fd, n8q); + const n8r = await fd.readULE32(); + zkey.n8r = n8r; + zkey.r = await _iden3_binfileutils.readBigInt(fd, n8r); + zkey.curve = await getCurveFromQ(zkey.q, options); + zkey.nVars = await fd.readULE32(); + zkey.nPublic = await fd.readULE32(); + zkey.domainSize = await fd.readULE32(); + zkey.power = log2(zkey.domainSize); + zkey.vk_alpha_1 = await readG1(fd, zkey.curve, toObject); + zkey.vk_beta_1 = await readG1(fd, zkey.curve, toObject); + zkey.vk_beta_2 = await readG2(fd, zkey.curve, toObject); + zkey.vk_gamma_2 = await readG2(fd, zkey.curve, toObject); + zkey.vk_delta_1 = await readG1(fd, zkey.curve, toObject); + zkey.vk_delta_2 = await readG2(fd, zkey.curve, toObject); + await _iden3_binfileutils.endReadSection(fd); + return zkey; +} async function readHeaderPlonk(fd, sections, toObject, options) { - const zkey = {}; - - zkey.protocol = "plonk"; - - // Read Plonk Header - ///////////////////// - await binFileUtils__namespace.startReadUniqueSection(fd, sections, 2); - const n8q = await fd.readULE32(); - zkey.n8q = n8q; - zkey.q = await binFileUtils__namespace.readBigInt(fd, n8q); - - const n8r = await fd.readULE32(); - zkey.n8r = n8r; - zkey.r = await binFileUtils__namespace.readBigInt(fd, n8r); - zkey.curve = await getCurveFromQ(zkey.q, options); - zkey.nVars = await fd.readULE32(); - zkey.nPublic = await fd.readULE32(); - zkey.domainSize = await fd.readULE32(); - zkey.power = log2(zkey.domainSize); - zkey.nAdditions = await fd.readULE32(); - zkey.nConstraints = await fd.readULE32(); - zkey.k1 = await fd.read(n8r); - zkey.k2 = await fd.read(n8r); - - zkey.Qm = await readG1(fd, zkey.curve, toObject); - zkey.Ql = await readG1(fd, zkey.curve, toObject); - zkey.Qr = await readG1(fd, zkey.curve, toObject); - zkey.Qo = await readG1(fd, zkey.curve, toObject); - zkey.Qc = await readG1(fd, zkey.curve, toObject); - zkey.S1 = await readG1(fd, zkey.curve, toObject); - zkey.S2 = await readG1(fd, zkey.curve, toObject); - zkey.S3 = await readG1(fd, zkey.curve, toObject); - zkey.X_2 = await readG2(fd, zkey.curve, toObject); - - await binFileUtils__namespace.endReadSection(fd); - - return zkey; -} - + const zkey = {}; + zkey.protocol = "plonk"; + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 2); + const n8q = await fd.readULE32(); + zkey.n8q = n8q; + zkey.q = await _iden3_binfileutils.readBigInt(fd, n8q); + const n8r = await fd.readULE32(); + zkey.n8r = n8r; + zkey.r = await _iden3_binfileutils.readBigInt(fd, n8r); + zkey.curve = await getCurveFromQ(zkey.q, options); + zkey.nVars = await fd.readULE32(); + zkey.nPublic = await fd.readULE32(); + zkey.domainSize = await fd.readULE32(); + zkey.power = log2(zkey.domainSize); + zkey.nAdditions = await fd.readULE32(); + zkey.nConstraints = await fd.readULE32(); + zkey.k1 = await fd.read(n8r); + zkey.k2 = await fd.read(n8r); + zkey.Qm = await readG1(fd, zkey.curve, toObject); + zkey.Ql = await readG1(fd, zkey.curve, toObject); + zkey.Qr = await readG1(fd, zkey.curve, toObject); + zkey.Qo = await readG1(fd, zkey.curve, toObject); + zkey.Qc = await readG1(fd, zkey.curve, toObject); + zkey.S1 = await readG1(fd, zkey.curve, toObject); + zkey.S2 = await readG1(fd, zkey.curve, toObject); + zkey.S3 = await readG1(fd, zkey.curve, toObject); + zkey.X_2 = await readG2(fd, zkey.curve, toObject); + await _iden3_binfileutils.endReadSection(fd); + return zkey; +} async function readHeaderFFlonk(fd, sections, toObject, options) { - const zkey = {}; - - zkey.protocol = "fflonk"; - zkey.protocolId = FFLONK_PROTOCOL_ID; - - await binFileUtils__namespace.startReadUniqueSection(fd, sections, ZKEY_FF_HEADER_SECTION); - const n8q = await fd.readULE32(); - zkey.n8q = n8q; - zkey.q = await binFileUtils__namespace.readBigInt(fd, n8q); - zkey.curve = await getCurveFromQ(zkey.q, options); - - const n8r = await fd.readULE32(); - zkey.n8r = n8r; - zkey.r = await binFileUtils__namespace.readBigInt(fd, n8r); - - zkey.nVars = await fd.readULE32(); - zkey.nPublic = await fd.readULE32(); - zkey.domainSize = await fd.readULE32(); - zkey.power = log2(zkey.domainSize); - zkey.nAdditions = await fd.readULE32(); - zkey.nConstraints = await fd.readULE32(); - - zkey.k1 = await fd.read(n8r); - zkey.k2 = await fd.read(n8r); - - zkey.w3 = await fd.read(n8r); - zkey.w4 = await fd.read(n8r); - zkey.w8 = await fd.read(n8r); - zkey.wr = await fd.read(n8r); - - zkey.X_2 = await readG2(fd, zkey.curve, toObject); - - zkey.C0 = await readG1(fd, zkey.curve, toObject); - - await binFileUtils__namespace.endReadSection(fd); - - return zkey; -} - + const zkey = {}; + zkey.protocol = "fflonk"; + zkey.protocolId = 10; + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 2); + const n8q = await fd.readULE32(); + zkey.n8q = n8q; + zkey.q = await _iden3_binfileutils.readBigInt(fd, n8q); + zkey.curve = await getCurveFromQ(zkey.q, options); + const n8r = await fd.readULE32(); + zkey.n8r = n8r; + zkey.r = await _iden3_binfileutils.readBigInt(fd, n8r); + zkey.nVars = await fd.readULE32(); + zkey.nPublic = await fd.readULE32(); + zkey.domainSize = await fd.readULE32(); + zkey.power = log2(zkey.domainSize); + zkey.nAdditions = await fd.readULE32(); + zkey.nConstraints = await fd.readULE32(); + zkey.k1 = await fd.read(n8r); + zkey.k2 = await fd.read(n8r); + zkey.w3 = await fd.read(n8r); + zkey.w4 = await fd.read(n8r); + zkey.w8 = await fd.read(n8r); + zkey.wr = await fd.read(n8r); + zkey.X_2 = await readG2(fd, zkey.curve, toObject); + zkey.C0 = await readG1(fd, zkey.curve, toObject); + await _iden3_binfileutils.endReadSection(fd); + return zkey; +} async function readZKey(fileName, toObject) { - const {fd, sections} = await binFileUtils__namespace.readBinFile(fileName, "zkey", 1); - - const zkey = await readHeader$1(fd, sections, toObject); - - const Fr = new ffjavascript.F1Field(zkey.r); - const Rr = ffjavascript.Scalar.mod(ffjavascript.Scalar.shl(1, zkey.n8r*8), zkey.r); - const Rri = Fr.inv(Rr); - const Rri2 = Fr.mul(Rri, Rri); - - let curve = await getCurveFromQ(zkey.q); - - // Read IC Section - /////////// - await binFileUtils__namespace.startReadUniqueSection(fd, sections, 3); - zkey.IC = []; - for (let i=0; i<= zkey.nPublic; i++) { - const P = await readG1(fd, curve, toObject); - zkey.IC.push(P); - } - await binFileUtils__namespace.endReadSection(fd); - - - // Read Coefs - /////////// - await binFileUtils__namespace.startReadUniqueSection(fd, sections, 4); - const nCCoefs = await fd.readULE32(); - zkey.ccoefs = []; - for (let i=0; i0) { - const paramsBuff = new Uint8Array(params); - await fd.writeULE32(paramsBuff.byteLength); - await fd.write(paramsBuff); - } else { - await fd.writeULE32(0); - } - -} - + await writeG1(fd, curve, c.deltaAfter); + await writeG1(fd, curve, c.delta.g1_s); + await writeG1(fd, curve, c.delta.g1_sx); + await writeG2(fd, curve, c.delta.g2_spx); + await fd.write(c.transcript); + await fd.writeULE32(c.type || 0); + const params = []; + if (c.name) { + params.push(1); + const nameData = new TextEncoder("utf-8").encode(c.name.substring(0, 64)); + params.push(nameData.byteLength); + for (let i = 0; i < nameData.byteLength; i++) params.push(nameData[i]); + } + if (c.type == 1) { + params.push(2); + params.push(c.numIterationsExp); + params.push(3); + params.push(c.beaconHash.byteLength); + for (let i = 0; i < c.beaconHash.byteLength; i++) params.push(c.beaconHash[i]); + } + if (params.length > 0) { + const paramsBuff = new Uint8Array(params); + await fd.writeULE32(paramsBuff.byteLength); + await fd.write(paramsBuff); + } else await fd.writeULE32(0); +} async function writeMPCParams(fd, curve, mpcParams) { - await binFileUtils__namespace.startWriteSection(fd, 10); - await fd.write(mpcParams.csHash); - await fd.writeULE32(mpcParams.contributions.length); - for (let i=0; i. -*/ - + const { fd: fdZKey, sections: sectionsZKey } = await _iden3_binfileutils.readBinFile(zkeyName, "zkey", 2); + const zkey = await readHeader$1(fdZKey, sectionsZKey); + if (zkey.protocol != "groth16") throw new Error("zkey file is not groth16"); + const curve = await getCurveFromQ(zkey.q); + const sG1 = curve.G1.F.n8 * 2; + const sG2 = curve.G2.F.n8 * 2; + const mpcParams = await readMPCParams(fdZKey, curve, sectionsZKey); + const fdMPCParams = await fastfile.createOverride(mpcparamsName); + await writeG1(zkey.vk_alpha_1); + await writeG1(zkey.vk_beta_1); + await writeG2(zkey.vk_beta_2); + await writeG2(zkey.vk_gamma_2); + await writeG1(zkey.vk_delta_1); + await writeG2(zkey.vk_delta_2); + let buffBasesIC; + buffBasesIC = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 3); + buffBasesIC = await curve.G1.batchLEMtoU(buffBasesIC); + await writePointArray("G1", buffBasesIC); + const buffBasesH_Lodd = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 9); + let buffBasesH_Tau; + buffBasesH_Tau = await curve.G1.fft(buffBasesH_Lodd, "affine", "jacobian", logger); + buffBasesH_Tau = await curve.G1.batchApplyKey(buffBasesH_Tau, curve.Fr.neg(curve.Fr.e(2)), curve.Fr.w[zkey.power + 1], "jacobian", "affine", logger); + buffBasesH_Tau = buffBasesH_Tau.slice(0, buffBasesH_Tau.byteLength - sG1); + buffBasesH_Tau = await curve.G1.batchLEMtoU(buffBasesH_Tau); + await writePointArray("G1", buffBasesH_Tau); + let buffBasesC; + buffBasesC = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 8); + buffBasesC = await curve.G1.batchLEMtoU(buffBasesC); + await writePointArray("G1", buffBasesC); + let buffBasesA; + buffBasesA = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 5); + buffBasesA = await curve.G1.batchLEMtoU(buffBasesA); + await writePointArray("G1", buffBasesA); + let buffBasesB1; + buffBasesB1 = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 6); + buffBasesB1 = await curve.G1.batchLEMtoU(buffBasesB1); + await writePointArray("G1", buffBasesB1); + let buffBasesB2; + buffBasesB2 = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 7); + buffBasesB2 = await curve.G2.batchLEMtoU(buffBasesB2); + await writePointArray("G2", buffBasesB2); + await fdMPCParams.write(mpcParams.csHash); + await writeU32(mpcParams.contributions.length); + for (let i = 0; i < mpcParams.contributions.length; i++) { + const c = mpcParams.contributions[i]; + await writeG1(c.deltaAfter); + await writeG1(c.delta.g1_s); + await writeG1(c.delta.g1_sx); + await writeG2(c.delta.g2_spx); + await fdMPCParams.write(c.transcript); + } + await fdZKey.close(); + await fdMPCParams.close(); + async function writeG1(P) { + const buff = new Uint8Array(sG1); + curve.G1.toRprUncompressed(buff, 0, P); + await fdMPCParams.write(buff); + } + async function writeG2(P) { + const buff = new Uint8Array(sG2); + curve.G2.toRprUncompressed(buff, 0, P); + await fdMPCParams.write(buff); + } + async function writePointArray(groupName, buff) { + let sG; + if (groupName == "G1") sG = sG1; + else sG = sG2; + const buffSize = new Uint8Array(4); + new DataView(buffSize.buffer, buffSize.byteOffset, buffSize.byteLength).setUint32(0, buff.byteLength / sG, false); + await fdMPCParams.write(buffSize); + await fdMPCParams.write(buff); + } + async function writeU32(n) { + const buffSize = new Uint8Array(4); + new DataView(buffSize.buffer, buffSize.byteOffset, buffSize.byteLength).setUint32(0, n, false); + await fdMPCParams.write(buffSize); + } +} +//#endregion +//#region src/zkey_import_bellman.js async function phase2importMPCParams(zkeyNameOld, mpcparamsName, zkeyNameNew, name, logger) { - - const {fd: fdZKeyOld, sections: sectionsZKeyOld} = await binFileUtils__namespace.readBinFile(zkeyNameOld, "zkey", 2); - const zkeyHeader = await readHeader$1(fdZKeyOld, sectionsZKeyOld, false); - if (zkeyHeader.protocol != "groth16") { - throw new Error("zkey file is not groth16"); - } - - const curve = await getCurveFromQ(zkeyHeader.q); - const sG1 = curve.G1.F.n8*2; - const sG2 = curve.G2.F.n8*2; - - const oldMPCParams = await readMPCParams(fdZKeyOld, curve, sectionsZKeyOld); - const newMPCParams = {}; - - const fdMPCParams = await fastFile__namespace.readExisting(mpcparamsName); - - fdMPCParams.pos = - sG1*3 + sG2*3 + // vKey - 8 + sG1*zkeyHeader.nVars + // IC + C - 4 + sG1*(zkeyHeader.domainSize-1) + // H - 4 + sG1*zkeyHeader.nVars + // A - 4 + sG1*zkeyHeader.nVars + // B1 - 4 + sG2*zkeyHeader.nVars; // B2 - - // csHash - newMPCParams.csHash = await fdMPCParams.read(64); - - const nContributions = await fdMPCParams.readUBE32(); - newMPCParams.contributions = []; - for (let i=0; i newMPCParams.contributions.length) { - if (logger) logger.error("The impoerted file does not include new contributions"); - return false; - } - - for (let i=0; i. -*/ -const sameRatio = sameRatio$2; - - - + const { fd: fdZKeyOld, sections: sectionsZKeyOld } = await _iden3_binfileutils.readBinFile(zkeyNameOld, "zkey", 2); + const zkeyHeader = await readHeader$1(fdZKeyOld, sectionsZKeyOld, false); + if (zkeyHeader.protocol != "groth16") throw new Error("zkey file is not groth16"); + const curve = await getCurveFromQ(zkeyHeader.q); + const sG1 = curve.G1.F.n8 * 2; + const sG2 = curve.G2.F.n8 * 2; + const oldMPCParams = await readMPCParams(fdZKeyOld, curve, sectionsZKeyOld); + const newMPCParams = {}; + const fdMPCParams = await fastfile.readExisting(mpcparamsName); + fdMPCParams.pos = sG1 * 3 + sG2 * 3 + 8 + sG1 * zkeyHeader.nVars + 4 + sG1 * (zkeyHeader.domainSize - 1) + 4 + sG1 * zkeyHeader.nVars + 4 + sG1 * zkeyHeader.nVars + 4 + sG2 * zkeyHeader.nVars; + newMPCParams.csHash = await fdMPCParams.read(64); + const nContributions = await fdMPCParams.readUBE32(); + newMPCParams.contributions = []; + for (let i = 0; i < nContributions; i++) { + const c = { delta: {} }; + c.deltaAfter = await readG1(fdMPCParams); + c.delta.g1_s = await readG1(fdMPCParams); + c.delta.g1_sx = await readG1(fdMPCParams); + c.delta.g2_spx = await readG2(fdMPCParams); + c.transcript = await fdMPCParams.read(64); + if (i < oldMPCParams.contributions.length) { + c.type = oldMPCParams.contributions[i].type; + if (c.type == 1) { + c.beaconHash = oldMPCParams.contributions[i].beaconHash; + c.numIterationsExp = oldMPCParams.contributions[i].numIterationsExp; + } + if (oldMPCParams.contributions[i].name) c.name = oldMPCParams.contributions[i].name; + } + newMPCParams.contributions.push(c); + } + if (!hashIsEqual(newMPCParams.csHash, oldMPCParams.csHash)) { + if (logger) logger.error("Hash of the original circuit does not match with the MPC one"); + return false; + } + if (oldMPCParams.contributions.length > newMPCParams.contributions.length) { + if (logger) logger.error("The impoerted file does not include new contributions"); + return false; + } + for (let i = 0; i < oldMPCParams.contributions.length; i++) if (!contributionIsEqual(oldMPCParams.contributions[i], newMPCParams.contributions[i])) { + if (logger) logger.error(`Previous contribution ${i} does not match`); + return false; + } + if (name) for (let i = oldMPCParams.contributions.length; i < newMPCParams.contributions.length; i++) newMPCParams.contributions[i].name = name; + const fdZKeyNew = await _iden3_binfileutils.createBinFile(zkeyNameNew, "zkey", 1, 10); + fdMPCParams.pos = 0; + fdMPCParams.pos += sG1; + fdMPCParams.pos += sG1; + fdMPCParams.pos += sG2; + fdMPCParams.pos += sG2; + zkeyHeader.vk_delta_1 = await readG1(fdMPCParams); + zkeyHeader.vk_delta_2 = await readG2(fdMPCParams); + await writeHeader(fdZKeyNew, zkeyHeader); + if (await fdMPCParams.readUBE32() != zkeyHeader.nPublic + 1) { + if (logger) logger.error("Invalid number of points in IC"); + await fdZKeyNew.discard(); + return false; + } + fdMPCParams.pos += sG1 * (zkeyHeader.nPublic + 1); + await _iden3_binfileutils.copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 3); + await _iden3_binfileutils.copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 4); + if (await fdMPCParams.readUBE32() != zkeyHeader.domainSize - 1) { + if (logger) logger.error("Invalid number of points in H"); + await fdZKeyNew.discard(); + return false; + } + let buffH; + const buffTauU = await fdMPCParams.read(sG1 * (zkeyHeader.domainSize - 1)); + const buffTauLEM = await curve.G1.batchUtoLEM(buffTauU); + buffH = new Uint8Array(zkeyHeader.domainSize * sG1); + buffH.set(buffTauLEM); + curve.G1.toRprLEM(buffH, sG1 * (zkeyHeader.domainSize - 1), curve.G1.zeroAffine); + const n2Inv = curve.Fr.neg(curve.Fr.inv(curve.Fr.e(2))); + const wInv = curve.Fr.inv(curve.Fr.w[zkeyHeader.power + 1]); + buffH = await curve.G1.batchApplyKey(buffH, n2Inv, wInv, "affine", "jacobian", logger); + buffH = await curve.G1.ifft(buffH, "jacobian", "affine", logger); + await _iden3_binfileutils.startWriteSection(fdZKeyNew, 9); + await fdZKeyNew.write(buffH); + await _iden3_binfileutils.endWriteSection(fdZKeyNew); + if (await fdMPCParams.readUBE32() != zkeyHeader.nVars - zkeyHeader.nPublic - 1) { + if (logger) logger.error("Invalid number of points in L"); + await fdZKeyNew.discard(); + return false; + } + let buffL; + buffL = await fdMPCParams.read(sG1 * (zkeyHeader.nVars - zkeyHeader.nPublic - 1)); + buffL = await curve.G1.batchUtoLEM(buffL); + await _iden3_binfileutils.startWriteSection(fdZKeyNew, 8); + await fdZKeyNew.write(buffL); + await _iden3_binfileutils.endWriteSection(fdZKeyNew); + if (await fdMPCParams.readUBE32() != zkeyHeader.nVars) { + if (logger) logger.error("Invalid number of points in A"); + await fdZKeyNew.discard(); + return false; + } + fdMPCParams.pos += sG1 * zkeyHeader.nVars; + await _iden3_binfileutils.copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 5); + if (await fdMPCParams.readUBE32() != zkeyHeader.nVars) { + if (logger) logger.error("Invalid number of points in B1"); + await fdZKeyNew.discard(); + return false; + } + fdMPCParams.pos += sG1 * zkeyHeader.nVars; + await _iden3_binfileutils.copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 6); + if (await fdMPCParams.readUBE32() != zkeyHeader.nVars) { + if (logger) logger.error("Invalid number of points in B2"); + await fdZKeyNew.discard(); + return false; + } + fdMPCParams.pos += sG2 * zkeyHeader.nVars; + await _iden3_binfileutils.copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 7); + await writeMPCParams(fdZKeyNew, curve, newMPCParams); + await fdMPCParams.close(); + await fdZKeyNew.close(); + await fdZKeyOld.close(); + return true; + async function readG1(fd) { + const buff = await fd.read(curve.G1.F.n8 * 2); + return curve.G1.fromRprUncompressed(buff, 0); + } + async function readG2(fd) { + const buff = await fd.read(curve.G2.F.n8 * 2); + return curve.G2.fromRprUncompressed(buff, 0); + } + function contributionIsEqual(c1, c2) { + if (!curve.G1.eq(c1.deltaAfter, c2.deltaAfter)) return false; + if (!curve.G1.eq(c1.delta.g1_s, c2.delta.g1_s)) return false; + if (!curve.G1.eq(c1.delta.g1_sx, c2.delta.g1_sx)) return false; + if (!curve.G2.eq(c1.delta.g2_spx, c2.delta.g2_spx)) return false; + if (!hashIsEqual(c1.transcript, c2.transcript)) return false; + return true; + } +} +//#endregion +//#region src/zkey_verify_frominit.js +var sameRatio = sameRatio$2; async function phase2verifyFromInit(initFileName, pTauFileName, zkeyFileName, logger) { - - let sr; - const {fd, sections} = await binFileUtils__namespace.readBinFile(zkeyFileName, "zkey", 2); - const zkey = await readHeader$1(fd, sections, false); - if (zkey.protocol != "groth16") { - throw new Error("zkey file is not groth16"); - } - - const curve = await getCurveFromQ(zkey.q); - const sG1 = curve.G1.F.n8*2; - - const mpcParams = await readMPCParams(fd, curve, sections); - - const accumulatedHasher = blake2b.blake2b.create({ dkLen: 64 }); - accumulatedHasher.update(mpcParams.csHash); - let curDelta = curve.G1.g; - for (let i=0; i=0; i--) { - const c = mpcParams.contributions[i]; - if (logger) logger.info("-------------------------"); - if (logger) logger.info(formatHash(c.contributionHash, `contribution #${i+1} ${c.name ? c.name : ""}:`)); - if (c.type == 1) { - if (logger) logger.info(`Beacon generator: ${byteArray2hex(c.beaconHash)}`); - if (logger) logger.info(`Beacon iterations Exp: ${c.numIterationsExp}`); - } - } - if (logger) logger.info("-------------------------"); - - if (logger) logger.info("ZKey Ok!"); - - return true; - - - async function sectionHasSameRatio(groupName, fd1, sections1, fd2, sections2, idSection, g2sp, g2spx, sectionName) { - const MAX_CHUNK_SIZE = 1<<20; - const G = curve[groupName]; - const sG = G.F.n8*2; - await binFileUtils__namespace.startReadUniqueSection(fd1, sections1, idSection); - await binFileUtils__namespace.startReadUniqueSection(fd2, sections2, idSection); - - let R1 = G.zero; - let R2 = G.zero; - - const nPoints = sections1[idSection][0].size / sG; - - for (let i=0; i. -*/ - + let sr; + const { fd, sections } = await _iden3_binfileutils.readBinFile(zkeyFileName, "zkey", 2); + const zkey = await readHeader$1(fd, sections, false); + if (zkey.protocol != "groth16") throw new Error("zkey file is not groth16"); + const curve = await getCurveFromQ(zkey.q); + const sG1 = curve.G1.F.n8 * 2; + const mpcParams = await readMPCParams(fd, curve, sections); + const accumulatedHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + accumulatedHasher.update(mpcParams.csHash); + let curDelta = curve.G1.g; + for (let i = 0; i < mpcParams.contributions.length; i++) { + const c = mpcParams.contributions[i]; + const ourHasher = cloneHasher(accumulatedHasher); + hashG1(ourHasher, curve, c.delta.g1_s); + hashG1(ourHasher, curve, c.delta.g1_sx); + if (!hashIsEqual(ourHasher.digest(), c.transcript)) { + console.log(`INVALID(${i}): Inconsistent transcript `); + return false; + } + const delta_g2_sp = hashToG2(curve, c.transcript); + sr = await sameRatio(curve, c.delta.g1_s, c.delta.g1_sx, delta_g2_sp, c.delta.g2_spx); + if (sr !== true) { + console.log(`INVALID(${i}): public key G1 and G2 do not have the same ration `); + return false; + } + sr = await sameRatio(curve, curDelta, c.deltaAfter, delta_g2_sp, c.delta.g2_spx); + if (sr !== true) { + console.log(`INVALID(${i}): deltaAfter does not fillow the public key `); + return false; + } + if (c.type == 1) { + const rng = await rngFromBeaconParams(c.beaconHash, c.numIterationsExp); + const expected_prvKey = curve.Fr.fromRng(rng); + const expected_g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); + const expected_g1_sx = curve.G1.toAffine(curve.G1.timesFr(expected_g1_s, expected_prvKey)); + if (curve.G1.eq(expected_g1_s, c.delta.g1_s) !== true) { + console.log(`INVALID(${i}): Key of the beacon does not match. g1_s `); + return false; + } + if (curve.G1.eq(expected_g1_sx, c.delta.g1_sx) !== true) { + console.log(`INVALID(${i}): Key of the beacon does not match. g1_sx `); + return false; + } + } + hashPubKey(accumulatedHasher, curve, c); + const contributionHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + hashPubKey(contributionHasher, curve, c); + c.contributionHash = contributionHasher.digest(); + curDelta = c.deltaAfter; + } + const { fd: fdInit, sections: sectionsInit } = await _iden3_binfileutils.readBinFile(initFileName, "zkey", 2); + const zkeyInit = await readHeader$1(fdInit, sectionsInit, false); + if (zkeyInit.protocol != "groth16") throw new Error("zkeyinit file is not groth16"); + if (!ffjavascript.Scalar.eq(zkeyInit.q, zkey.q) || !ffjavascript.Scalar.eq(zkeyInit.r, zkey.r) || zkeyInit.n8q != zkey.n8q || zkeyInit.n8r != zkey.n8r) { + if (logger) logger.error("INVALID: Different curves"); + return false; + } + if (zkeyInit.nVars != zkey.nVars || zkeyInit.nPublic != zkey.nPublic || zkeyInit.domainSize != zkey.domainSize) { + if (logger) logger.error("INVALID: Different circuit parameters"); + return false; + } + if (!curve.G1.eq(zkey.vk_alpha_1, zkeyInit.vk_alpha_1)) { + if (logger) logger.error("INVALID: Invalid alpha1"); + return false; + } + if (!curve.G1.eq(zkey.vk_beta_1, zkeyInit.vk_beta_1)) { + if (logger) logger.error("INVALID: Invalid beta1"); + return false; + } + if (!curve.G2.eq(zkey.vk_beta_2, zkeyInit.vk_beta_2)) { + if (logger) logger.error("INVALID: Invalid beta2"); + return false; + } + if (!curve.G2.eq(zkey.vk_gamma_2, zkeyInit.vk_gamma_2)) { + if (logger) logger.error("INVALID: Invalid gamma2"); + return false; + } + if (!curve.G1.eq(zkey.vk_delta_1, curDelta)) { + if (logger) logger.error("INVALID: Invalid delta1"); + return false; + } + sr = await sameRatio(curve, curve.G1.g, curDelta, curve.G2.g, zkey.vk_delta_2); + if (sr !== true) { + if (logger) logger.error("INVALID: Invalid delta2"); + return false; + } + const mpcParamsInit = await readMPCParams(fdInit, curve, sectionsInit); + if (!hashIsEqual(mpcParams.csHash, mpcParamsInit.csHash)) { + if (logger) logger.error("INVALID: Circuit does not match"); + return false; + } + if (sections[8][0].size != sG1 * (zkey.nVars - zkey.nPublic - 1)) { + if (logger) logger.error("INVALID: Invalid L section size"); + return false; + } + if (sections[9][0].size != sG1 * zkey.domainSize) { + if (logger) logger.error("INVALID: Invalid H section size"); + return false; + } + let ss; + ss = await _iden3_binfileutils.sectionIsEqual(fd, sections, fdInit, sectionsInit, 3); + if (!ss) { + if (logger) logger.error("INVALID: IC section is not identical"); + return false; + } + ss = await _iden3_binfileutils.sectionIsEqual(fd, sections, fdInit, sectionsInit, 4); + if (!ss) { + if (logger) logger.error("Coeffs section is not identical"); + return false; + } + ss = await _iden3_binfileutils.sectionIsEqual(fd, sections, fdInit, sectionsInit, 5); + if (!ss) { + if (logger) logger.error("A section is not identical"); + return false; + } + ss = await _iden3_binfileutils.sectionIsEqual(fd, sections, fdInit, sectionsInit, 6); + if (!ss) { + if (logger) logger.error("B1 section is not identical"); + return false; + } + ss = await _iden3_binfileutils.sectionIsEqual(fd, sections, fdInit, sectionsInit, 7); + if (!ss) { + if (logger) logger.error("B2 section is not identical"); + return false; + } + sr = await sectionHasSameRatio("G1", fdInit, sectionsInit, fd, sections, 8, zkey.vk_delta_2, zkeyInit.vk_delta_2, "L section"); + if (sr !== true) { + if (logger) logger.error("L section does not match"); + return false; + } + sr = await sameRatioH(); + if (sr !== true) { + if (logger) logger.error("H section does not match"); + return false; + } + if (logger) logger.info(formatHash(mpcParams.csHash, "Circuit Hash: ")); + await fd.close(); + await fdInit.close(); + for (let i = mpcParams.contributions.length - 1; i >= 0; i--) { + const c = mpcParams.contributions[i]; + if (logger) logger.info("-------------------------"); + if (logger) logger.info(formatHash(c.contributionHash, `contribution #${i + 1} ${c.name ? c.name : ""}:`)); + if (c.type == 1) { + if (logger) logger.info(`Beacon generator: ${byteArray2hex(c.beaconHash)}`); + if (logger) logger.info(`Beacon iterations Exp: ${c.numIterationsExp}`); + } + } + if (logger) logger.info("-------------------------"); + if (logger) logger.info("ZKey Ok!"); + return true; + async function sectionHasSameRatio(groupName, fd1, sections1, fd2, sections2, idSection, g2sp, g2spx, sectionName) { + const MAX_CHUNK_SIZE = 1 << 20; + const G = curve[groupName]; + const sG = G.F.n8 * 2; + await _iden3_binfileutils.startReadUniqueSection(fd1, sections1, idSection); + await _iden3_binfileutils.startReadUniqueSection(fd2, sections2, idSection); + let R1 = G.zero; + let R2 = G.zero; + const nPoints = sections1[idSection][0].size / sG; + for (let i = 0; i < nPoints; i += MAX_CHUNK_SIZE) { + if (logger) logger.debug(`Same ratio check ${sectionName}: ${i}/${nPoints}`); + const n = Math.min(nPoints - i, MAX_CHUNK_SIZE); + const bases1 = await fd1.read(n * sG); + const bases2 = await fd2.read(n * sG); + const scalars = getRandomBytes(4 * n); + const r1 = await G.multiExpAffine(bases1, scalars); + const r2 = await G.multiExpAffine(bases2, scalars); + R1 = G.add(R1, r1); + R2 = G.add(R2, r2); + } + await _iden3_binfileutils.endReadSection(fd1); + await _iden3_binfileutils.endReadSection(fd2); + if (nPoints == 0) return true; + sr = await sameRatio(curve, R1, R2, g2sp, g2spx); + if (sr !== true) return false; + return true; + } + async function sameRatioH() { + const MAX_CHUNK_SIZE = 1 << 20; + const G = curve.G1; + const Fr = curve.Fr; + const sG = G.F.n8 * 2; + const { fd: fdPTau, sections: sectionsPTau } = await _iden3_binfileutils.readBinFile(pTauFileName, "ptau", 1); + let buff_r = new ffjavascript.BigBuffer(zkey.domainSize * zkey.n8r); + const seed = new Array(8); + for (let i = 0; i < 8; i++) seed[i] = readUInt32BE(getRandomBytes(4), 0); + const rng = new ffjavascript.ChaCha(seed); + for (let i = 0; i < zkey.domainSize - 1; i++) { + const e = Fr.fromRng(rng); + Fr.toRprLE(buff_r, i * zkey.n8r, e); + } + Fr.toRprLE(buff_r, (zkey.domainSize - 1) * zkey.n8r, Fr.zero); + let R1 = G.zero; + for (let i = 0; i < zkey.domainSize; i += MAX_CHUNK_SIZE) { + if (logger) logger.debug(`H Verification(tau): ${i}/${zkey.domainSize}`); + const n = Math.min(zkey.domainSize - i, MAX_CHUNK_SIZE); + const buffB = await batchSubtract(await fdPTau.read(sG * n, sectionsPTau[2][0].p + zkey.domainSize * sG + i * sG), await fdPTau.read(sG * n, sectionsPTau[2][0].p + i * sG)); + const buffS = buff_r.slice(i * zkey.n8r, (i + n) * zkey.n8r); + const r = await G.multiExpAffine(buffB, buffS); + R1 = G.add(R1, r); + } + buff_r = await Fr.batchToMontgomery(buff_r); + let first; + if (zkey.power < Fr.s) first = Fr.neg(Fr.e(2)); + else { + const small_m = 2 ** Fr.s; + const shift_to_small_m = Fr.exp(Fr.shift, small_m); + first = Fr.sub(shift_to_small_m, Fr.one); + } + const inc = zkey.power < Fr.s ? Fr.w[zkey.power + 1] : Fr.shift; + buff_r = await Fr.batchApplyKey(buff_r, first, inc); + buff_r = await Fr.fft(buff_r); + buff_r = await Fr.batchFromMontgomery(buff_r); + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 9); + let R2 = G.zero; + for (let i = 0; i < zkey.domainSize; i += MAX_CHUNK_SIZE) { + if (logger) logger.debug(`H Verification(lagrange): ${i}/${zkey.domainSize}`); + const n = Math.min(zkey.domainSize - i, MAX_CHUNK_SIZE); + const buff = await fd.read(sG * n); + const buffS = buff_r.slice(i * zkey.n8r, (i + n) * zkey.n8r); + const r = await G.multiExpAffine(buff, buffS); + R2 = G.add(R2, r); + } + await _iden3_binfileutils.endReadSection(fd); + sr = await sameRatio(curve, R1, R2, zkey.vk_delta_2, zkeyInit.vk_delta_2); + if (sr !== true) return false; + return true; + } + async function batchSubtract(buff1, buff2) { + const sG = curve.G1.F.n8 * 2; + const nPoints = buff1.byteLength / sG; + const concurrency = curve.tm.concurrency; + const nPointsPerThread = Math.floor(nPoints / concurrency); + const opPromises = []; + for (let i = 0; i < concurrency; i++) { + let n; + if (i < concurrency - 1) n = nPointsPerThread; + else n = nPoints - i * nPointsPerThread; + if (n == 0) continue; + const subBuff1 = buff1.slice(i * nPointsPerThread * sG1, (i * nPointsPerThread + n) * sG1); + const subBuff2 = buff2.slice(i * nPointsPerThread * sG1, (i * nPointsPerThread + n) * sG1); + opPromises.push(batchSubtractThread(subBuff1, subBuff2)); + } + const result = await Promise.all(opPromises); + const fullBuffOut = new Uint8Array(nPoints * sG); + let p = 0; + for (let i = 0; i < result.length; i++) { + fullBuffOut.set(result[i][0], p); + p += result[i][0].byteLength; + } + return fullBuffOut; + } + async function batchSubtractThread(buff1, buff2) { + const sG1 = curve.G1.F.n8 * 2; + const sGmid = curve.G1.F.n8 * 3; + const nPoints = buff1.byteLength / sG1; + const task = []; + task.push({ + cmd: "ALLOCSET", + var: 0, + buff: buff1 + }); + task.push({ + cmd: "ALLOCSET", + var: 1, + buff: buff2 + }); + task.push({ + cmd: "ALLOC", + var: 2, + len: nPoints * sGmid + }); + for (let i = 0; i < nPoints; i++) task.push({ + cmd: "CALL", + fnName: "g1m_subAffine", + params: [ + { + var: 0, + offset: i * sG1 + }, + { + var: 1, + offset: i * sG1 + }, + { + var: 2, + offset: i * sGmid + } + ] + }); + task.push({ + cmd: "CALL", + fnName: "g1m_batchToAffine", + params: [ + { var: 2 }, + { val: nPoints }, + { var: 2 } + ] + }); + task.push({ + cmd: "GET", + out: 0, + var: 2, + len: nPoints * sG1 + }); + return await curve.tm.queueAction(task); + } +} +//#endregion +//#region src/zkey_verify_fromr1cs.js async function phase2verifyFromR1cs(r1csFileName, pTauFileName, zkeyFileName, logger) { - - // const initFileName = "~" + zkeyFileName + ".init"; - const initFileName = {type: "bigMem"}; - await newZKey(r1csFileName, pTauFileName, initFileName, logger); - - return await phase2verifyFromInit(initFileName, pTauFileName, zkeyFileName, logger); -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - + const initFileName = { type: "bigMem" }; + await newZKey(r1csFileName, pTauFileName, initFileName, logger); + return await phase2verifyFromInit(initFileName, pTauFileName, zkeyFileName, logger); +} +//#endregion +//#region src/zkey_contribute.js async function phase2contribute(zkeyNameOld, zkeyNameNew, name, entropy, logger) { - - const {fd: fdOld, sections: sections} = await binFileUtils__namespace.readBinFile(zkeyNameOld, "zkey", 2); - const zkey = await readHeader$1(fdOld, sections); - if (zkey.protocol != "groth16") { - throw new Error("zkey file is not groth16"); - } - - const curve = await getCurveFromQ(zkey.q); - - const mpcParams = await readMPCParams(fdOld, curve, sections); - - const fdNew = await binFileUtils__namespace.createBinFile(zkeyNameNew, "zkey", 1, 10); - - - const rng = await getRandomRng(entropy); - - const transcriptHasher = blake2b.blake2b.create({ dkLen: 64 }); - transcriptHasher.update(mpcParams.csHash); - for (let i=0; i. -*/ - - + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(zkeyNameOld, "zkey", 2); + const zkey = await readHeader$1(fdOld, sections); + if (zkey.protocol != "groth16") throw new Error("zkey file is not groth16"); + const curve = await getCurveFromQ(zkey.q); + const mpcParams = await readMPCParams(fdOld, curve, sections); + const fdNew = await _iden3_binfileutils.createBinFile(zkeyNameNew, "zkey", 1, 10); + const rng = await getRandomRng(entropy); + const transcriptHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + transcriptHasher.update(mpcParams.csHash); + for (let i = 0; i < mpcParams.contributions.length; i++) hashPubKey(transcriptHasher, curve, mpcParams.contributions[i]); + const curContribution = {}; + curContribution.delta = {}; + curContribution.delta.prvKey = curve.Fr.fromRng(rng); + curContribution.delta.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); + curContribution.delta.g1_sx = curve.G1.toAffine(curve.G1.timesFr(curContribution.delta.g1_s, curContribution.delta.prvKey)); + hashG1(transcriptHasher, curve, curContribution.delta.g1_s); + hashG1(transcriptHasher, curve, curContribution.delta.g1_sx); + curContribution.transcript = transcriptHasher.digest(); + curContribution.delta.g2_sp = hashToG2(curve, curContribution.transcript); + curContribution.delta.g2_spx = curve.G2.toAffine(curve.G2.timesFr(curContribution.delta.g2_sp, curContribution.delta.prvKey)); + zkey.vk_delta_1 = curve.G1.timesFr(zkey.vk_delta_1, curContribution.delta.prvKey); + zkey.vk_delta_2 = curve.G2.timesFr(zkey.vk_delta_2, curContribution.delta.prvKey); + curContribution.deltaAfter = zkey.vk_delta_1; + curContribution.type = 0; + if (name) curContribution.name = name; + mpcParams.contributions.push(curContribution); + await writeHeader(fdNew, zkey); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 3); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 4); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 5); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 6); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 7); + const invDelta = curve.Fr.inv(curContribution.delta.prvKey); + await applyKeyToSection(fdOld, sections, fdNew, 8, curve, "G1", invDelta, curve.Fr.e(1), "L Section", logger); + await applyKeyToSection(fdOld, sections, fdNew, 9, curve, "G1", invDelta, curve.Fr.e(1), "H Section", logger); + await writeMPCParams(fdNew, curve, mpcParams); + await fdOld.close(); + await fdNew.close(); + const contributionHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + hashPubKey(contributionHasher, curve, curContribution); + const contributionHash = contributionHasher.digest(); + if (logger) logger.info(formatHash(mpcParams.csHash, "Circuit Hash: ")); + if (logger) logger.info(formatHash(contributionHash, "Contribution Hash: ")); + return contributionHash; +} +//#endregion +//#region src/zkey_beacon.js async function beacon(zkeyNameOld, zkeyNameNew, name, beaconHashStr, numIterationsExp, logger) { - const beaconHash = hex2ByteArray(beaconHashStr); - if ( (beaconHash.byteLength == 0) - || (beaconHash.byteLength*2 !=beaconHashStr.length)) - { - if (logger) logger.error("Invalid Beacon Hash. (It must be a valid hexadecimal sequence)"); - return false; - } - if (beaconHash.length>=256) { - if (logger) logger.error("Maximum length of beacon hash is 255 bytes"); - return false; - } - - numIterationsExp = parseInt(numIterationsExp); - if ((numIterationsExp<10)||(numIterationsExp>63)) { - if (logger) logger.error("Invalid numIterationsExp. (Must be between 10 and 63)"); - return false; - } - - - const {fd: fdOld, sections: sections} = await binFileUtils__namespace.readBinFile(zkeyNameOld, "zkey", 2); - const zkey = await readHeader$1(fdOld, sections); - - if (zkey.protocol != "groth16") { - throw new Error("zkey file is not groth16"); - } - - - const curve = await getCurveFromQ(zkey.q); - - const mpcParams = await readMPCParams(fdOld, curve, sections); - - const fdNew = await binFileUtils__namespace.createBinFile(zkeyNameNew, "zkey", 1, 10); - - const rng = await rngFromBeaconParams(beaconHash, numIterationsExp); - - const transcriptHasher = blake2b.blake2b.create({ dkLen: 64 }); transcriptHasher.update(mpcParams.csHash); - for (let i=0; i= 256) { + if (logger) logger.error("Maximum length of beacon hash is 255 bytes"); + return false; + } + numIterationsExp = parseInt(numIterationsExp); + if (numIterationsExp < 10 || numIterationsExp > 63) { + if (logger) logger.error("Invalid numIterationsExp. (Must be between 10 and 63)"); + return false; + } + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(zkeyNameOld, "zkey", 2); + const zkey = await readHeader$1(fdOld, sections); + if (zkey.protocol != "groth16") throw new Error("zkey file is not groth16"); + const curve = await getCurveFromQ(zkey.q); + const mpcParams = await readMPCParams(fdOld, curve, sections); + const fdNew = await _iden3_binfileutils.createBinFile(zkeyNameNew, "zkey", 1, 10); + const rng = await rngFromBeaconParams(beaconHash, numIterationsExp); + const transcriptHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + transcriptHasher.update(mpcParams.csHash); + for (let i = 0; i < mpcParams.contributions.length; i++) hashPubKey(transcriptHasher, curve, mpcParams.contributions[i]); + const curContribution = {}; + curContribution.delta = {}; + curContribution.delta.prvKey = curve.Fr.fromRng(rng); + curContribution.delta.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); + curContribution.delta.g1_sx = curve.G1.toAffine(curve.G1.timesFr(curContribution.delta.g1_s, curContribution.delta.prvKey)); + hashG1(transcriptHasher, curve, curContribution.delta.g1_s); + hashG1(transcriptHasher, curve, curContribution.delta.g1_sx); + curContribution.transcript = transcriptHasher.digest(); + curContribution.delta.g2_sp = hashToG2(curve, curContribution.transcript); + curContribution.delta.g2_spx = curve.G2.toAffine(curve.G2.timesFr(curContribution.delta.g2_sp, curContribution.delta.prvKey)); + zkey.vk_delta_1 = curve.G1.timesFr(zkey.vk_delta_1, curContribution.delta.prvKey); + zkey.vk_delta_2 = curve.G2.timesFr(zkey.vk_delta_2, curContribution.delta.prvKey); + curContribution.deltaAfter = zkey.vk_delta_1; + curContribution.type = 1; + curContribution.numIterationsExp = numIterationsExp; + curContribution.beaconHash = beaconHash; + if (name) curContribution.name = name; + mpcParams.contributions.push(curContribution); + await writeHeader(fdNew, zkey); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 3); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 4); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 5); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 6); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 7); + const invDelta = curve.Fr.inv(curContribution.delta.prvKey); + await applyKeyToSection(fdOld, sections, fdNew, 8, curve, "G1", invDelta, curve.Fr.e(1), "L Section", logger); + await applyKeyToSection(fdOld, sections, fdNew, 9, curve, "G1", invDelta, curve.Fr.e(1), "H Section", logger); + await writeMPCParams(fdNew, curve, mpcParams); + await fdOld.close(); + await fdNew.close(); + const contributionHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + hashPubKey(contributionHasher, curve, curContribution); + const contributionHash = contributionHasher.digest(); + if (logger) logger.info(formatHash(contributionHash, "Contribution Hash: ")); + return contributionHash; +} +//#endregion +//#region src/zkey_export_json.js async function zkeyExportJson$1(zkeyFileName) { - - const zKey = await readZKey(zkeyFileName, true); - delete zKey.curve; - delete zKey.F; - - return ffjavascript.utils.stringifyBigInts(zKey); -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - + const zKey = await readZKey(zkeyFileName, true); + delete zKey.curve; + delete zKey.F; + return ffjavascript.utils.stringifyBigInts(zKey); +} +//#endregion +//#region src/zkey_bellman_contribute.js async function bellmanContribute(curve, challengeFilename, responseFileName, entropy, logger) { - const rng = await getRandomRng(entropy); - - const delta = curve.Fr.fromRng(rng); - const invDelta = curve.Fr.inv(delta); - - const sG1 = curve.G1.F.n8*2; - const sG2 = curve.G2.F.n8*2; - - const fdFrom = await fastFile__namespace.readExisting(challengeFilename); - const fdTo = await fastFile__namespace.createOverride(responseFileName); - - - await copy(sG1); // alpha1 - await copy(sG1); // beta1 - await copy(sG2); // beta2 - await copy(sG2); // gamma2 - const oldDelta1 = await readG1(); - const delta1 = curve.G1.timesFr(oldDelta1, delta); - await writeG1(delta1); - const oldDelta2 = await readG2(); - const delta2 = curve.G2.timesFr(oldDelta2, delta); - await writeG2(delta2); - - // IC - const nIC = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nIC); - await copy(nIC*sG1); - - // H - const nH = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nH); - await applyKeyToChallengeSection(fdFrom, fdTo, null, curve, "G1", nH, invDelta, curve.Fr.e(1), "UNCOMPRESSED", "H", logger); - - // L - const nL = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nL); - await applyKeyToChallengeSection(fdFrom, fdTo, null, curve, "G1", nL, invDelta, curve.Fr.e(1), "UNCOMPRESSED", "L", logger); - - // A - const nA = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nA); - await copy(nA*sG1); - - // B1 - const nB1 = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nB1); - await copy(nB1*sG1); - - // B2 - const nB2 = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nB2); - await copy(nB2*sG2); - - - ////////// - /// Read contributions - ////////// - const transcriptHasher = blake2b.blake2b.create({ dkLen: 64 }); - const mpcParams = {}; - // csHash - mpcParams.csHash = await fdFrom.read(64); - transcriptHasher.update(mpcParams.csHash); - - const nContributions = await fdFrom.readUBE32(); - mpcParams.contributions = []; - for (let i=0; i. -*/ - -const {stringifyBigInts: stringifyBigInts$5} = ffjavascript.utils; - + const rng = await getRandomRng(entropy); + const delta = curve.Fr.fromRng(rng); + const invDelta = curve.Fr.inv(delta); + const sG1 = curve.G1.F.n8 * 2; + const sG2 = curve.G2.F.n8 * 2; + const fdFrom = await fastfile.readExisting(challengeFilename); + const fdTo = await fastfile.createOverride(responseFileName); + await copy(sG1); + await copy(sG1); + await copy(sG2); + await copy(sG2); + const oldDelta1 = await readG1(); + const delta1 = curve.G1.timesFr(oldDelta1, delta); + await writeG1(delta1); + const oldDelta2 = await readG2(); + await writeG2(curve.G2.timesFr(oldDelta2, delta)); + const nIC = await fdFrom.readUBE32(); + await fdTo.writeUBE32(nIC); + await copy(nIC * sG1); + const nH = await fdFrom.readUBE32(); + await fdTo.writeUBE32(nH); + await applyKeyToChallengeSection(fdFrom, fdTo, null, curve, "G1", nH, invDelta, curve.Fr.e(1), "UNCOMPRESSED", "H", logger); + const nL = await fdFrom.readUBE32(); + await fdTo.writeUBE32(nL); + await applyKeyToChallengeSection(fdFrom, fdTo, null, curve, "G1", nL, invDelta, curve.Fr.e(1), "UNCOMPRESSED", "L", logger); + const nA = await fdFrom.readUBE32(); + await fdTo.writeUBE32(nA); + await copy(nA * sG1); + const nB1 = await fdFrom.readUBE32(); + await fdTo.writeUBE32(nB1); + await copy(nB1 * sG1); + const nB2 = await fdFrom.readUBE32(); + await fdTo.writeUBE32(nB2); + await copy(nB2 * sG2); + const transcriptHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + const mpcParams = {}; + mpcParams.csHash = await fdFrom.read(64); + transcriptHasher.update(mpcParams.csHash); + const nContributions = await fdFrom.readUBE32(); + mpcParams.contributions = []; + for (let i = 0; i < nContributions; i++) { + const c = { delta: {} }; + c.deltaAfter = await readG1(); + c.delta.g1_s = await readG1(); + c.delta.g1_sx = await readG1(); + c.delta.g2_spx = await readG2(); + c.transcript = await fdFrom.read(64); + mpcParams.contributions.push(c); + hashPubKey(transcriptHasher, curve, c); + } + const curContribution = {}; + curContribution.delta = {}; + curContribution.delta.prvKey = delta; + curContribution.delta.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); + curContribution.delta.g1_sx = curve.G1.toAffine(curve.G1.timesFr(curContribution.delta.g1_s, delta)); + hashG1(transcriptHasher, curve, curContribution.delta.g1_s); + hashG1(transcriptHasher, curve, curContribution.delta.g1_sx); + curContribution.transcript = transcriptHasher.digest(); + curContribution.delta.g2_sp = hashToG2(curve, curContribution.transcript); + curContribution.delta.g2_spx = curve.G2.toAffine(curve.G2.timesFr(curContribution.delta.g2_sp, delta)); + curContribution.deltaAfter = delta1; + curContribution.type = 0; + mpcParams.contributions.push(curContribution); + await fdTo.write(mpcParams.csHash); + await fdTo.writeUBE32(mpcParams.contributions.length); + for (let i = 0; i < mpcParams.contributions.length; i++) { + const c = mpcParams.contributions[i]; + await writeG1(c.deltaAfter); + await writeG1(c.delta.g1_s); + await writeG1(c.delta.g1_sx); + await writeG2(c.delta.g2_spx); + await fdTo.write(c.transcript); + } + const contributionHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + hashPubKey(contributionHasher, curve, curContribution); + const contributionHash = contributionHasher.digest(); + if (logger) logger.info(formatHash(contributionHash, "Contribution Hash: ")); + await fdTo.close(); + await fdFrom.close(); + return contributionHash; + async function copy(nBytes) { + const CHUNK_SIZE = fdFrom.pageSize * 2; + for (let i = 0; i < nBytes; i += CHUNK_SIZE) { + const n = Math.min(nBytes - i, CHUNK_SIZE); + const buff = await fdFrom.read(n); + await fdTo.write(buff); + } + } + async function readG1() { + const buff = await fdFrom.read(curve.G1.F.n8 * 2); + return curve.G1.fromRprUncompressed(buff, 0); + } + async function readG2() { + const buff = await fdFrom.read(curve.G2.F.n8 * 2); + return curve.G2.fromRprUncompressed(buff, 0); + } + async function writeG1(P) { + const buff = new Uint8Array(sG1); + curve.G1.toRprUncompressed(buff, 0, P); + await fdTo.write(buff); + } + async function writeG2(P) { + const buff = new Uint8Array(sG2); + curve.G2.toRprUncompressed(buff, 0, P); + await fdTo.write(buff); + } +} +//#endregion +//#region src/zkey_export_verificationkey.js +var { stringifyBigInts: stringifyBigInts$5 } = ffjavascript.utils; async function zkeyExportVerificationKey(zkeyName, logger) { - if (logger) logger.info("EXPORT VERIFICATION KEY STARTED"); - - const {fd, sections} = await binFileUtils__namespace.readBinFile(zkeyName, "zkey", 2); - const zkey = await readHeader$1(fd, sections); - - if (logger) logger.info("> Detected protocol: " + zkey.protocol); - - let res; - if (zkey.protocol === "groth16") { - res = await groth16Vk(zkey, fd, sections); - } else if (zkey.protocol === "plonk") { - res = await plonkVk(zkey); - } else if (zkey.protocolId && zkey.protocolId === FFLONK_PROTOCOL_ID) { - res = await exportFFlonkVk(zkey); - } else { - throw new Error("zkey file protocol unrecognized"); - } - - await fd.close(); - - if (logger) logger.info("EXPORT VERIFICATION KEY FINISHED"); - - return res; -} - - + if (logger) logger.info("EXPORT VERIFICATION KEY STARTED"); + const { fd, sections } = await _iden3_binfileutils.readBinFile(zkeyName, "zkey", 2); + const zkey = await readHeader$1(fd, sections); + if (logger) logger.info("> Detected protocol: " + zkey.protocol); + let res; + if (zkey.protocol === "groth16") res = await groth16Vk(zkey, fd, sections); + else if (zkey.protocol === "plonk") res = await plonkVk(zkey); + else if (zkey.protocolId && zkey.protocolId === 10) res = await exportFFlonkVk(zkey, logger); + else throw new Error("zkey file protocol unrecognized"); + await fd.close(); + if (logger) logger.info("EXPORT VERIFICATION KEY FINISHED"); + return res; +} async function groth16Vk(zkey, fd, sections) { - const curve = await getCurveFromQ(zkey.q); - const sG1 = curve.G1.F.n8 * 2; - - const alphaBeta = await curve.pairing(zkey.vk_alpha_1, zkey.vk_beta_2); - - let vKey = { - protocol: zkey.protocol, - curve: curve.name, - nPublic: zkey.nPublic, - - vk_alpha_1: curve.G1.toObject(zkey.vk_alpha_1), - - vk_beta_2: curve.G2.toObject(zkey.vk_beta_2), - vk_gamma_2: curve.G2.toObject(zkey.vk_gamma_2), - vk_delta_2: curve.G2.toObject(zkey.vk_delta_2), - - vk_alphabeta_12: curve.Gt.toObject(alphaBeta) - }; - - // Read IC Section - /////////// - await binFileUtils__namespace.startReadUniqueSection(fd, sections, 3); - vKey.IC = []; - for (let i = 0; i <= zkey.nPublic; i++) { - const buff = await fd.read(sG1); - const P = curve.G1.toObject(buff); - vKey.IC.push(P); - } - await binFileUtils__namespace.endReadSection(fd); - - vKey = stringifyBigInts$5(vKey); - - return vKey; -} - - + const curve = await getCurveFromQ(zkey.q); + const sG1 = curve.G1.F.n8 * 2; + const alphaBeta = await curve.pairing(zkey.vk_alpha_1, zkey.vk_beta_2); + let vKey = { + protocol: zkey.protocol, + curve: curve.name, + nPublic: zkey.nPublic, + vk_alpha_1: curve.G1.toObject(zkey.vk_alpha_1), + vk_beta_2: curve.G2.toObject(zkey.vk_beta_2), + vk_gamma_2: curve.G2.toObject(zkey.vk_gamma_2), + vk_delta_2: curve.G2.toObject(zkey.vk_delta_2), + vk_alphabeta_12: curve.Gt.toObject(alphaBeta) + }; + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 3); + vKey.IC = []; + for (let i = 0; i <= zkey.nPublic; i++) { + const buff = await fd.read(sG1); + const P = curve.G1.toObject(buff); + vKey.IC.push(P); + } + await _iden3_binfileutils.endReadSection(fd); + vKey = stringifyBigInts$5(vKey); + return vKey; +} async function plonkVk(zkey) { - const curve = await getCurveFromQ(zkey.q); - - let vKey = { - protocol: zkey.protocol, - curve: curve.name, - nPublic: zkey.nPublic, - power: zkey.power, - - k1: curve.Fr.toObject(zkey.k1), - k2: curve.Fr.toObject(zkey.k2), - - Qm: curve.G1.toObject(zkey.Qm), - Ql: curve.G1.toObject(zkey.Ql), - Qr: curve.G1.toObject(zkey.Qr), - Qo: curve.G1.toObject(zkey.Qo), - Qc: curve.G1.toObject(zkey.Qc), - S1: curve.G1.toObject(zkey.S1), - S2: curve.G1.toObject(zkey.S2), - S3: curve.G1.toObject(zkey.S3), - - X_2: curve.G2.toObject(zkey.X_2), - - w: curve.Fr.toObject(curve.Fr.w[zkey.power]) - }; - - vKey = stringifyBigInts$5(vKey); - - return vKey; -} - -async function exportFFlonkVk(zkey, logger) { - const curve = await getCurveFromQ(zkey.q); - - let vKey = { - protocol: zkey.protocol, - curve: curve.name, - nPublic: zkey.nPublic, - power: zkey.power, - - k1: curve.Fr.toObject(zkey.k1), - k2: curve.Fr.toObject(zkey.k2), - - w: curve.Fr.toObject(curve.Fr.w[zkey.power]), - //wW: curve.Fr.toObject(curve.Fr.w[zkey.power + 1]), - w3: curve.Fr.toObject(zkey.w3), - w4: curve.Fr.toObject(zkey.w4), - w8: curve.Fr.toObject(zkey.w8), - wr: curve.Fr.toObject(zkey.wr), - - X_2: curve.G2.toObject(zkey.X_2), - - C0: curve.G1.toObject(zkey.C0), - }; - - return stringifyBigInts$5(vKey); -} - -/* - Copyright 2021 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -const {unstringifyBigInts: unstringifyBigInts$b, stringifyBigInts: stringifyBigInts$4} = ffjavascript.utils; - + const curve = await getCurveFromQ(zkey.q); + let vKey = { + protocol: zkey.protocol, + curve: curve.name, + nPublic: zkey.nPublic, + power: zkey.power, + k1: curve.Fr.toObject(zkey.k1), + k2: curve.Fr.toObject(zkey.k2), + Qm: curve.G1.toObject(zkey.Qm), + Ql: curve.G1.toObject(zkey.Ql), + Qr: curve.G1.toObject(zkey.Qr), + Qo: curve.G1.toObject(zkey.Qo), + Qc: curve.G1.toObject(zkey.Qc), + S1: curve.G1.toObject(zkey.S1), + S2: curve.G1.toObject(zkey.S2), + S3: curve.G1.toObject(zkey.S3), + X_2: curve.G2.toObject(zkey.X_2), + w: curve.Fr.toObject(curve.Fr.w[zkey.power]) + }; + vKey = stringifyBigInts$5(vKey); + return vKey; +} +async function exportFFlonkVk(zkey, _logger) { + const curve = await getCurveFromQ(zkey.q); + return stringifyBigInts$5({ + protocol: zkey.protocol, + curve: curve.name, + nPublic: zkey.nPublic, + power: zkey.power, + k1: curve.Fr.toObject(zkey.k1), + k2: curve.Fr.toObject(zkey.k2), + w: curve.Fr.toObject(curve.Fr.w[zkey.power]), + w3: curve.Fr.toObject(zkey.w3), + w4: curve.Fr.toObject(zkey.w4), + w8: curve.Fr.toObject(zkey.w8), + wr: curve.Fr.toObject(zkey.wr), + X_2: curve.G2.toObject(zkey.X_2), + C0: curve.G1.toObject(zkey.C0) + }); +} +//#endregion +//#region src/fflonk_export_solidity_verifier.js +var { unstringifyBigInts: unstringifyBigInts$11, stringifyBigInts: stringifyBigInts$4 } = ffjavascript.utils; async function fflonkExportSolidityVerifier(vk, templates, logger) { - if (logger) logger.info("FFLONK EXPORT SOLIDITY VERIFIER STARTED"); - - const curve = await getCurveFromName(vk.curve); - - // Precompute w3_2, w4_2 and w4_3 - let w3 = fromVkey(vk.w3); - vk.w3_2 = toVkey(curve.Fr.square(w3)); - - let w4 = fromVkey(vk.w4); - vk.w4_2 = toVkey(curve.Fr.square(w4)); - vk.w4_3 = toVkey(curve.Fr.mul(curve.Fr.square(w4), w4)); - - let w8 = fromVkey(vk.w8); - let acc = curve.Fr.one; - - for (let i = 1; i < 8; i++) { - acc = curve.Fr.mul(acc, w8); - vk["w8_" + i] = toVkey(acc); - } - - let template = templates[vk.protocol]; - - if (logger) logger.info("FFLONK EXPORT SOLIDITY VERIFIER FINISHED"); - - const {default: ejs} = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('ejs')); }); - return ejs.render(template, vk); - - function fromVkey(str) { - const val = unstringifyBigInts$b(str); - return curve.Fr.fromObject(val); - } - - function toVkey(val) { - const str = curve.Fr.toObject(val); - return stringifyBigInts$4(str); - } -} - -// Not ready yet -// module.exports.generateVerifier_kimleeoh = generateVerifier_kimleeoh; - + if (logger) logger.info("FFLONK EXPORT SOLIDITY VERIFIER STARTED"); + const curve = await getCurveFromName(vk.curve); + let w3 = fromVkey(vk.w3); + vk.w3_2 = toVkey(curve.Fr.square(w3)); + let w4 = fromVkey(vk.w4); + vk.w4_2 = toVkey(curve.Fr.square(w4)); + vk.w4_3 = toVkey(curve.Fr.mul(curve.Fr.square(w4), w4)); + let w8 = fromVkey(vk.w8); + let acc = curve.Fr.one; + for (let i = 1; i < 8; i++) { + acc = curve.Fr.mul(acc, w8); + vk["w8_" + i] = toVkey(acc); + } + let template = templates[vk.protocol]; + if (logger) logger.info("FFLONK EXPORT SOLIDITY VERIFIER FINISHED"); + const { default: ejs } = await import("ejs"); + return ejs.render(template, vk); + function fromVkey(str) { + const val = unstringifyBigInts$11(str); + return curve.Fr.fromObject(val); + } + function toVkey(val) { + return stringifyBigInts$4(curve.Fr.toObject(val)); + } +} +//#endregion +//#region src/zkey_export_solidityverifier.js async function exportSolidityVerifier(zKeyName, templates, logger) { - - const verificationKey = await zkeyExportVerificationKey(zKeyName, logger); - - if ("fflonk" === verificationKey.protocol) { - return fflonkExportSolidityVerifier(verificationKey, templates, logger); - } - - let template = templates[verificationKey.protocol]; - - const {default: ejs} = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('ejs')); }); - - return ejs.render(template, verificationKey); -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - - + const verificationKey = await zkeyExportVerificationKey(zKeyName, logger); + if ("fflonk" === verificationKey.protocol) return fflonkExportSolidityVerifier(verificationKey, templates, logger); + let template = templates[verificationKey.protocol]; + const { default: ejs } = await import("ejs"); + return ejs.render(template, verificationKey); +} +//#endregion +//#region src/wtns_utils.js async function write(fd, witness, prime) { - - await binFileUtils__namespace.startWriteSection(fd, 1); - const n8 = (Math.floor( (ffjavascript.Scalar.bitLength(prime) - 1) / 64) +1)*8; - await fd.writeULE32(n8); - await binFileUtils__namespace.writeBigInt(fd, prime, n8); - await fd.writeULE32(witness.length); - await binFileUtils__namespace.endWriteSection(fd); - - await binFileUtils__namespace.startWriteSection(fd, 2); - for (let i=0; i. -*/ -const {stringifyBigInts: stringifyBigInts$3} = ffjavascript.utils; - + const { fd, sections } = await _iden3_binfileutils.readBinFile(fileName, "wtns", 2); + const { n8, nWitness } = await readHeader(fd, sections); + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 2); + const res = []; + for (let i = 0; i < nWitness; i++) { + const v = await _iden3_binfileutils.readBigInt(fd, n8); + res.push(v); + } + await _iden3_binfileutils.endReadSection(fd); + await fd.close(); + return res; +} +//#endregion +//#region src/groth16_prove.js +var { stringifyBigInts: stringifyBigInts$3 } = ffjavascript.utils; async function groth16Prove$1(zkeyFileName, witnessFileName, logger, options) { - - if (logger) monitorMemoryUsage(logger, 50); - const {fd: fdWtns, sections: sectionsWtns} = await binFileUtils__namespace.readBinFile(witnessFileName, "wtns", 2, 1<<25, 1<<23); - - const wtns = await readHeader(fdWtns, sectionsWtns); - - const {fd: fdZKey, sections: sectionsZKey} = await binFileUtils__namespace.readBinFile(zkeyFileName, "zkey", 2, 1<<25, 1<<23); - - const zkey = await readHeader$1(fdZKey, sectionsZKey, undefined, options); - - if (zkey.protocol != "groth16") { - throw new Error("zkey file is not groth16"); - } - - if (!ffjavascript.Scalar.eq(zkey.r, wtns.q)) { - throw new Error("Curve of the witness does not match the curve of the proving key"); - } - - if (wtns.nWitness != zkey.nVars) { - throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}`); - } - - const curve = zkey.curve; - const Fr = curve.Fr; - const G1 = curve.G1; - const G2 = curve.G2; - - const power = log2(zkey.domainSize); - - if (logger) logger.debug("Reading Wtns"); - const buffWitness = await binFileUtils__namespace.readSection(fdWtns, sectionsWtns, 2); - - let resH; - let resHPromise; - let buffPodd_T; - - let abcPromise = (async function (){ - let buffA_T, buffB_T, buffC_T; - - await (async function (){ - if (logger) logger.debug("Reading Coeffs"); - console.time("buildABC_outer"); - const buffCoeffs = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 4); - - if (logger) logger.debug("Building ABC"); - - options = options || {}; - //options.buildABC="wasm1"; // for testing - - if (options && options.buildABC==="wasm") { - // build ABC in WASM - [buffA_T, buffB_T, buffC_T] = await buildABC(curve, zkey, buffWitness, buffCoeffs, logger); - } else if (options && options.buildABC==="wasm1") { - // build ABC in WASM - [buffA_T, buffB_T, buffC_T] = await buildABCWASM1(curve, zkey, buffWitness, buffCoeffs, logger); - } else { - // default, build ABC in JS - [buffA_T, buffB_T, buffC_T] = await buildABC1(curve, zkey, buffWitness, buffCoeffs, logger); - } - console.timeEnd("buildABC_outer"); - })(); - - console.time("abcPromise"); - - if (globalThis.gc) {globalThis.gc();} - - const inc = power === Fr.s ? curve.Fr.shift : curve.Fr.w[power+1]; - - let buffAodd_T; - await (async function () { - let buffA = await Fr.ifft(buffA_T, "", "", logger, "IFFT_A"); - buffA_T = null; - const buffAodd = await Fr.batchApplyKey(buffA, Fr.e(1), inc); - buffAodd_T = await Fr.fft(buffAodd, "", "", logger, "FFT_A"); - })(); - - let buffBodd_T; - await (async function () { - const buffB = await Fr.ifft(buffB_T, "", "", logger, "IFFT_B"); - buffB_T = null; - const buffBodd = await Fr.batchApplyKey(buffB, Fr.e(1), inc); - buffBodd_T = await Fr.fft(buffBodd, "", "", logger, "FFT_B"); - })(); - - let buffCodd_T; - await (async function () { - const buffC = await Fr.ifft(buffC_T, "", "", logger, "IFFT_C"); - buffC_T = null; - const buffCodd = await Fr.batchApplyKey(buffC, Fr.e(1), inc); - buffCodd_T = await Fr.fft(buffCodd, "", "", logger, "FFT_C"); - })(); - - if (logger) logger.debug("Join ABC"); - buffPodd_T = await joinABC(curve, zkey, buffAodd_T, buffBodd_T, buffCodd_T, logger); - if (logger) logger.debug("Join ABC finished"); - buffAodd_T = null; - buffBodd_T = null; - buffCodd_T = null; - - if (globalThis.gc) {globalThis.gc();} - console.timeEnd("abcPromise"); - })(); - //await abcPromise; - - let proof = {}; - - async function calcPiA(){ - if (logger) logger.debug("Reading A Points"); - const buffBasesA = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 5); - console.time("Calculate PiA"); - proof.pi_a = await curve.G1.multiExpAffine(buffBasesA, buffWitness, logger, "multiexp A"); - console.timeEnd("Calculate PiA"); - } - - let piaPromise = calcPiA(); - //await piaPromise; - - let pib1; - - async function calcPiB1() { - if (logger) logger.debug("Reading B1 Points"); - const buffBasesB1 = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 6); - console.time("Calculate PiB1"); - pib1 = await curve.G1.multiExpAffine(buffBasesB1, buffWitness, logger, "multiexp B1"); - console.timeEnd("Calculate PiB1"); - } - - let pib1Promise = calcPiB1(); - //await pib1Promise; - - async function calcPiB() { - if (logger) logger.debug("Reading B2 Points"); - const buffBasesB2 = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 7); - console.time("Calculate PiB"); - proof.pi_b = await curve.G2.multiExpAffine(buffBasesB2, buffWitness, logger, "multiexp B2"); - console.timeEnd("Calculate PiB"); - } - - let pibPromise = calcPiB(); - //await pibPromise; - - let picPromise = (async function (){ - if (logger) logger.debug("Reading C Points"); - const buffBasesC = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 8); - console.time("Calculate PiC"); - proof.pi_c = await curve.G1.multiExpAffine(buffBasesC, buffWitness.slice((zkey.nPublic+1)*curve.Fr.n8), logger, "multiexp C"); - console.timeEnd("Calculate PiC"); - })(); - //await picPromise; - - - resHPromise = (async function (){ - if (logger) logger.debug("Reading H Points"); - await abcPromise; - console.time("resHPromise"); - const buffBasesH = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 9); - //await Promise.all([abcPromise, piaPromise, pib1Promise, pibPromise, picPromise]); - resH = await curve.G1.multiExpAffine(buffBasesH, buffPodd_T, logger, "multiexp H"); - //buffPodd_T = null; - console.timeEnd("resHPromise"); - })(); - //await resHPromise; - - - const r = curve.Fr.random(); - const s = curve.Fr.random(); - - await piaPromise; - proof.pi_a = G1.add( proof.pi_a, zkey.vk_alpha_1 ); - proof.pi_a = G1.add( proof.pi_a, G1.timesFr( zkey.vk_delta_1, r )); - - await pibPromise; - proof.pi_b = G2.add( proof.pi_b, zkey.vk_beta_2 ); - proof.pi_b = G2.add( proof.pi_b, G2.timesFr( zkey.vk_delta_2, s )); - - await pib1Promise; - pib1 = G1.add( pib1, zkey.vk_beta_1 ); - pib1 = G1.add( pib1, G1.timesFr( zkey.vk_delta_1, s )); - - await Promise.all([picPromise, resHPromise]); - proof.pi_c = G1.add(proof.pi_c, resH); - - - proof.pi_c = G1.add( proof.pi_c, G1.timesFr( proof.pi_a, s )); - proof.pi_c = G1.add( proof.pi_c, G1.timesFr( pib1, r )); - proof.pi_c = G1.add( proof.pi_c, G1.timesFr( zkey.vk_delta_1, Fr.neg(Fr.mul(r,s) ))); - - - let publicSignals = []; - - for (let i=1; i<= zkey.nPublic; i++) { - const b = buffWitness.slice(i*Fr.n8, i*Fr.n8+Fr.n8); - publicSignals.push(ffjavascript.Scalar.fromRprLE(b)); - } - - proof.pi_a = G1.toObject(G1.toAffine(proof.pi_a)); - proof.pi_b = G2.toObject(G2.toAffine(proof.pi_b)); - proof.pi_c = G1.toObject(G1.toAffine(proof.pi_c)); - - proof.protocol = "groth16"; - proof.curve = curve.name; - - await fdZKey.close(); - await fdWtns.close(); - - proof = stringifyBigInts$3(proof); - publicSignals = stringifyBigInts$3(publicSignals); - - return {proof, publicSignals}; -} - - + if (logger) monitorMemoryUsage(logger, 50); + const { fd: fdWtns, sections: sectionsWtns } = await _iden3_binfileutils.readBinFile(witnessFileName, "wtns", 2, 1 << 25, 1 << 23); + const wtns = await readHeader(fdWtns, sectionsWtns); + const { fd: fdZKey, sections: sectionsZKey } = await _iden3_binfileutils.readBinFile(zkeyFileName, "zkey", 2, 1 << 25, 1 << 23); + const zkey = await readHeader$1(fdZKey, sectionsZKey, void 0, options); + if (zkey.protocol != "groth16") throw new Error("zkey file is not groth16"); + if (!ffjavascript.Scalar.eq(zkey.r, wtns.q)) throw new Error("Curve of the witness does not match the curve of the proving key"); + if (wtns.nWitness != zkey.nVars) throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}`); + const curve = zkey.curve; + const Fr = curve.Fr; + const G1 = curve.G1; + const G2 = curve.G2; + const power = log2(zkey.domainSize); + if (logger) logger.debug("Reading Wtns"); + const buffWitness = await _iden3_binfileutils.readSection(fdWtns, sectionsWtns, 2); + let resH; + let resHPromise; + let buffPodd_T; + let abcPromise = (async function() { + let buffA_T, buffB_T, buffC_T; + await (async function() { + if (logger) logger.debug("Reading Coeffs"); + console.time("buildABC_outer"); + const buffCoeffs = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 4); + if (logger) logger.debug("Building ABC"); + options = options || {}; + if (options && options.buildABC === "wasm") [buffA_T, buffB_T, buffC_T] = await buildABC(curve, zkey, buffWitness, buffCoeffs, logger); + else if (options && options.buildABC === "wasm1") [buffA_T, buffB_T, buffC_T] = await buildABCWASM1(curve, zkey, buffWitness, buffCoeffs, logger); + else [buffA_T, buffB_T, buffC_T] = await buildABC1(curve, zkey, buffWitness, buffCoeffs, logger); + console.timeEnd("buildABC_outer"); + })(); + console.time("abcPromise"); + if (globalThis.gc) globalThis.gc(); + const inc = power === Fr.s ? curve.Fr.shift : curve.Fr.w[power + 1]; + let buffAodd_T; + await (async function() { + let buffA = await Fr.ifft(buffA_T, "", "", logger, "IFFT_A"); + buffA_T = null; + const buffAodd = await Fr.batchApplyKey(buffA, Fr.e(1), inc); + buffAodd_T = await Fr.fft(buffAodd, "", "", logger, "FFT_A"); + })(); + let buffBodd_T; + await (async function() { + const buffB = await Fr.ifft(buffB_T, "", "", logger, "IFFT_B"); + buffB_T = null; + const buffBodd = await Fr.batchApplyKey(buffB, Fr.e(1), inc); + buffBodd_T = await Fr.fft(buffBodd, "", "", logger, "FFT_B"); + })(); + let buffCodd_T; + await (async function() { + const buffC = await Fr.ifft(buffC_T, "", "", logger, "IFFT_C"); + buffC_T = null; + const buffCodd = await Fr.batchApplyKey(buffC, Fr.e(1), inc); + buffCodd_T = await Fr.fft(buffCodd, "", "", logger, "FFT_C"); + })(); + if (logger) logger.debug("Join ABC"); + buffPodd_T = await joinABC(curve, zkey, buffAodd_T, buffBodd_T, buffCodd_T, logger); + if (logger) logger.debug("Join ABC finished"); + buffAodd_T = null; + buffBodd_T = null; + buffCodd_T = null; + if (globalThis.gc) globalThis.gc(); + console.timeEnd("abcPromise"); + })(); + let proof = {}; + async function calcPiA() { + if (logger) logger.debug("Reading A Points"); + const buffBasesA = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 5); + console.time("Calculate PiA"); + proof.pi_a = await curve.G1.multiExpAffine(buffBasesA, buffWitness, logger, "multiexp A"); + console.timeEnd("Calculate PiA"); + } + let piaPromise = calcPiA(); + let pib1; + async function calcPiB1() { + if (logger) logger.debug("Reading B1 Points"); + const buffBasesB1 = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 6); + console.time("Calculate PiB1"); + pib1 = await curve.G1.multiExpAffine(buffBasesB1, buffWitness, logger, "multiexp B1"); + console.timeEnd("Calculate PiB1"); + } + let pib1Promise = calcPiB1(); + async function calcPiB() { + if (logger) logger.debug("Reading B2 Points"); + const buffBasesB2 = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 7); + console.time("Calculate PiB"); + proof.pi_b = await curve.G2.multiExpAffine(buffBasesB2, buffWitness, logger, "multiexp B2"); + console.timeEnd("Calculate PiB"); + } + let pibPromise = calcPiB(); + let picPromise = (async function() { + if (logger) logger.debug("Reading C Points"); + const buffBasesC = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 8); + console.time("Calculate PiC"); + proof.pi_c = await curve.G1.multiExpAffine(buffBasesC, buffWitness.slice((zkey.nPublic + 1) * curve.Fr.n8), logger, "multiexp C"); + console.timeEnd("Calculate PiC"); + })(); + resHPromise = (async function() { + if (logger) logger.debug("Reading H Points"); + await abcPromise; + console.time("resHPromise"); + const buffBasesH = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 9); + resH = await curve.G1.multiExpAffine(buffBasesH, buffPodd_T, logger, "multiexp H"); + console.timeEnd("resHPromise"); + })(); + const r = curve.Fr.random(); + const s = curve.Fr.random(); + await piaPromise; + proof.pi_a = G1.add(proof.pi_a, zkey.vk_alpha_1); + proof.pi_a = G1.add(proof.pi_a, G1.timesFr(zkey.vk_delta_1, r)); + await pibPromise; + proof.pi_b = G2.add(proof.pi_b, zkey.vk_beta_2); + proof.pi_b = G2.add(proof.pi_b, G2.timesFr(zkey.vk_delta_2, s)); + await pib1Promise; + pib1 = G1.add(pib1, zkey.vk_beta_1); + pib1 = G1.add(pib1, G1.timesFr(zkey.vk_delta_1, s)); + await Promise.all([picPromise, resHPromise]); + proof.pi_c = G1.add(proof.pi_c, resH); + proof.pi_c = G1.add(proof.pi_c, G1.timesFr(proof.pi_a, s)); + proof.pi_c = G1.add(proof.pi_c, G1.timesFr(pib1, r)); + proof.pi_c = G1.add(proof.pi_c, G1.timesFr(zkey.vk_delta_1, Fr.neg(Fr.mul(r, s)))); + let publicSignals = []; + for (let i = 1; i <= zkey.nPublic; i++) { + const b = buffWitness.slice(i * Fr.n8, i * Fr.n8 + Fr.n8); + publicSignals.push(ffjavascript.Scalar.fromRprLE(b)); + } + proof.pi_a = G1.toObject(G1.toAffine(proof.pi_a)); + proof.pi_b = G2.toObject(G2.toAffine(proof.pi_b)); + proof.pi_c = G1.toObject(G1.toAffine(proof.pi_c)); + proof.protocol = "groth16"; + proof.curve = curve.name; + await fdZKey.close(); + await fdWtns.close(); + proof = stringifyBigInts$3(proof); + publicSignals = stringifyBigInts$3(publicSignals); + return { + proof, + publicSignals + }; +} async function buildABC1(curve, zkey, witness, coeffs, logger) { - const n8 = curve.Fr.n8; - const sCoef = 4*3 + zkey.n8r; - const nCoef = (coeffs.byteLength-4) / sCoef; - - const outBuffA = new ffjavascript.BigBuffer(zkey.domainSize * n8); - const outBuffB = new ffjavascript.BigBuffer(zkey.domainSize * n8); - const outBuffC = new ffjavascript.BigBuffer(zkey.domainSize * n8); - - const outBuf = [ outBuffA, outBuffB ]; - for (let i=0; i 2**16) { - concurrency*=2; - elementsPerChunk = Math.floor(zkey.domainSize/concurrency); - } - console.log("@@@ new elementsPerChunk", elementsPerChunk); - - - const promises = []; - - const cutPoints = []; - for (let i=0; i1) { - const promises2 = []; - for (let i=0; i v) { - n = k - 1; - } else if (va < v) { - m = k + 1; - } else { - n = k; - } - } - return 4 + m*sCoef; - } -} - - -// buildABCWASM1 is single-threaded implementation of buildABS using wasm -// It has much better memory usage than multithreaded wasm implementation. -// It's much faster than pure js one, but uses much more memory. + let concurrency = curve.tm.concurrency; + const sCoef = 12 + zkey.n8r; + let getUint32; + if (coeffs instanceof ffjavascript.BigBuffer) { + const coeffsDV = []; + const PAGE_LEN = coeffs.buffers[0].length; + for (let i = 0; i < coeffs.buffers.length; i++) coeffsDV.push(new DataView(coeffs.buffers[i].buffer)); + getUint32 = function(pos) { + return coeffsDV[Math.floor(pos / PAGE_LEN)].getUint32(pos % PAGE_LEN, true); + }; + } else { + const coeffsDV = new DataView(coeffs.buffer, coeffs.byteOffset, coeffs.byteLength); + getUint32 = function(pos) { + return coeffsDV.getUint32(pos, true); + }; + } + let elementsPerChunk = Math.floor(zkey.domainSize / concurrency); + console.log("@@@ elementsPerChunk", elementsPerChunk); + while (elementsPerChunk > 2 ** 16) { + concurrency *= 2; + elementsPerChunk = Math.floor(zkey.domainSize / concurrency); + } + console.log("@@@ new elementsPerChunk", elementsPerChunk); + const promises = []; + const cutPoints = []; + for (let i = 0; i < concurrency; i++) cutPoints.push(getCutPoint(Math.floor(i * elementsPerChunk))); + cutPoints.push(coeffs.byteLength); + const chunkSize = 2 ** 26; + for (let s = 0; s < zkey.nVars; s += chunkSize) { + if (logger) logger.debug(`QAP ${s}: ${s}/${zkey.nVars}`); + const ns = Math.min(zkey.nVars - s, chunkSize); + for (let i = 0; i < concurrency; i++) { + let n; + if (i < concurrency - 1) n = elementsPerChunk; + else n = zkey.domainSize - i * elementsPerChunk; + if (n == 0) continue; + const task = []; + task.push({ + cmd: "ALLOCSET", + var: 0, + buff: coeffs.slice(cutPoints[i], cutPoints[i + 1]) + }); + task.push({ + cmd: "ALLOCSET", + var: 1, + buff: witness.slice(s * curve.Fr.n8, (s + ns) * curve.Fr.n8) + }); + task.push({ + cmd: "ALLOC", + var: 2, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "ALLOC", + var: 3, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "ALLOC", + var: 4, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "CALL", + fnName: "qap_buildABC", + params: [ + { var: 0 }, + { val: (cutPoints[i + 1] - cutPoints[i]) / sCoef }, + { var: 1 }, + { var: 2 }, + { var: 3 }, + { var: 4 }, + { val: i * elementsPerChunk }, + { val: n }, + { val: s }, + { val: ns } + ] + }); + task.push({ + cmd: "GET", + out: 0, + var: 2, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "GET", + out: 1, + var: 3, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "GET", + out: 2, + var: 4, + len: n * curve.Fr.n8 + }); + promises.push(curve.tm.queueAction(task)); + } + } + let result = await Promise.all(promises); + const nGroups = result.length / concurrency; + if (nGroups > 1) { + const promises2 = []; + for (let i = 0; i < concurrency; i++) { + const task = []; + task.push({ + cmd: "ALLOC", + var: 0, + len: result[i][0].byteLength + }); + task.push({ + cmd: "ALLOC", + var: 1, + len: result[i][0].byteLength + }); + for (let m = 0; m < 3; m++) { + task.push({ + cmd: "SET", + var: 0, + buff: result[i][m] + }); + for (let s = 1; s < nGroups; s++) { + task.push({ + cmd: "SET", + var: 1, + buff: result[s * concurrency + i][m] + }); + task.push({ + cmd: "CALL", + fnName: "qap_batchAdd", + params: [ + { var: 0 }, + { var: 1 }, + { val: result[i][m].length / curve.Fr.n8 }, + { var: 0 } + ] + }); + } + task.push({ + cmd: "GET", + out: m, + var: 0, + len: result[i][m].length + }); + } + promises2.push(curve.tm.queueAction(task)); + } + result = await Promise.all(promises2); + } + const outBuffA = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); + const outBuffB = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); + const outBuffC = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); + let p = 0; + for (let i = 0; i < result.length; i++) { + outBuffA.set(result[i][0], p); + outBuffB.set(result[i][1], p); + outBuffC.set(result[i][2], p); + p += result[i][0].byteLength; + } + return [ + outBuffA, + outBuffB, + outBuffC + ]; + function getCutPoint(v) { + let m = 0; + let n = getUint32(0); + while (m < n) { + var k = Math.floor((n + m) / 2); + const va = getUint32(4 + k * sCoef + 4); + if (va > v) n = k - 1; + else if (va < v) m = k + 1; + else n = k; + } + return 4 + m * sCoef; + } +} async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { - console.time("buildABC"); - const concurrency = 1;//curve.tm.concurrency; - const sCoef = 4 * 3 + zkey.n8r; - - let getUint32; - - if (coeffs instanceof ffjavascript.BigBuffer) { - const coeffsDV = []; - const PAGE_LEN = coeffs.buffers[0].length; - for (let i = 0; i < coeffs.buffers.length; i++) { - coeffsDV.push(new DataView(coeffs.buffers[i].buffer)); - } - getUint32 = function (pos) { - return coeffsDV[Math.floor(pos / PAGE_LEN)].getUint32(pos % PAGE_LEN, true); - }; - } else { - const coeffsDV = new DataView(coeffs.buffer, coeffs.byteOffset, coeffs.byteLength); - getUint32 = function (pos) { - return coeffsDV.getUint32(pos, true); - }; - } - - const elementsPerChunk = Math.floor((zkey.domainSize - 1) / concurrency) + 1; - const promises = []; - - const cutPoints = []; - for (let i = 0; i < concurrency; i++) { - cutPoints.push(getCutPoint(Math.floor(i * elementsPerChunk))); - } - cutPoints.push(coeffs.byteLength); - - //const chunkSize = 2**18; - const chunkSize = elementsPerChunk; - - console.log("zkey.domainSize", zkey.domainSize); - console.log("concurrency", concurrency); - console.log("elementsPerChunk", elementsPerChunk); - console.log("chunkSize", chunkSize); - - for (let s = 0; s < zkey.nVars; s += chunkSize) { - if (logger) logger.debug(`QAP: ${s}/${zkey.nVars}`); - const ns = Math.min(zkey.nVars - s, chunkSize); - - console.log("ns", ns); - - //let i=0; - for (let i = 0; i < concurrency; i++) { - let n; - if (i < concurrency - 1) { - n = elementsPerChunk; - } else { - n = zkey.domainSize - i * elementsPerChunk; - } - if (n === 0) continue; - - const task = []; - - const coeffsBuff = coeffs.slice(cutPoints[i], cutPoints[i + 1]); - const witnessBuff = witness.slice(s * curve.Fr.n8, (s + ns) * curve.Fr.n8); - - task.push({cmd: "ALLOCSET", var: 0, buff: coeffsBuff}); - task.push({cmd: "ALLOCSET", var: 1, buff: witnessBuff}); - task.push({cmd: "ALLOC", var: 2, len: n * curve.Fr.n8}); - task.push({cmd: "ALLOC", var: 3, len: n * curve.Fr.n8}); - task.push({cmd: "ALLOC", var: 4, len: n * curve.Fr.n8}); - task.push({ - cmd: "CALL", fnName: "qap_buildABC", params: [ - {var: 0}, - {val: (cutPoints[i + 1] - cutPoints[i]) / sCoef}, - {var: 1}, - {var: 2}, - {var: 3}, - {var: 4}, - {val: i * elementsPerChunk}, - {val: n}, - {val: s}, - {val: ns} - ] - }); - task.push({cmd: "GET", out: 0, var: 2, len: n * curve.Fr.n8}); - task.push({cmd: "GET", out: 1, var: 3, len: n * curve.Fr.n8}); - task.push({cmd: "GET", out: 2, var: 4, len: n * curve.Fr.n8}); - //task.push({cmd: "TERMINATE"}); // to free memory immediately - //promises.push(curve.tm.queueAction(task)); - promises.push(curve.tm.queueAction(task, [coeffsBuff.buffer, witnessBuff.buffer])); - } - } - - let result = await Promise.all(promises); - - - console.log("result.length", result.length); - console.log("result", result); - - const nGroups = result.length / concurrency; - - console.log("nGroups", nGroups); - let result2; - if (nGroups > 1) { - const promises2 = []; - for (let i = 0; i < concurrency; i++) { - const task = []; - task.push({cmd: "ALLOC", var: 0, len: result[i][0].byteLength}); - task.push({cmd: "ALLOC", var: 1, len: result[i][0].byteLength}); - for (let m = 0; m < 3; m++) { - task.push({cmd: "SET", var: 0, buff: result[i][m]}); - //transfers.push(result[i][m].buffer); - for (let s = 1; s < nGroups; s++) { - task.push({cmd: "SET", var: 1, buff: result[s * concurrency + i][m]}); - //transfers.push(result[s*concurrency + i][m].buffer); - task.push({ - cmd: "CALL", fnName: "qap_batchAdd", params: [ - {var: 0}, - {var: 1}, - {val: result[i][m].length / curve.Fr.n8}, - {var: 0} - ] - }); - } - task.push({cmd: "GET", out: m, var: 0, len: result[i][m].length}); - //task.push({cmd: "TERMINATE"}); // to free memory immediately - } - console.log("task.length", task.length); - //promises2.push(curve.tm.queueAction(task)); - promises2.push(curve.tm.queueAction(task, result.buffer)); - } - console.log("promises2.length", promises2.length); - result2 = await Promise.all(promises2); - result = result2; - } - - //console.log("result", result); - //console.log("result2", result2); - //result = result2 || result; - - const outBuffA = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); - const outBuffB = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); - const outBuffC = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); - let p = 0; - for (let i = 0; i < result.length; i++) { - outBuffA.set(result[i][0], p); - outBuffB.set(result[i][1], p); - outBuffC.set(result[i][2], p); - p += result[i][0].byteLength; - } - - console.timeEnd("buildABC"); - - return [outBuffA, outBuffB, outBuffC]; - - function getCutPoint(v) { - let m = 0; - let n = getUint32(0); - while (m < n) { - let k = Math.floor((n + m) / 2); - const va = getUint32(4 + k * sCoef + 4); - if (va > v) { - n = k - 1; - } else if (va < v) { - m = k + 1; - } else { - n = k; - } - } - return 4 + m * sCoef; - } -} - - + console.time("buildABC"); + const concurrency = 1; + const sCoef = 12 + zkey.n8r; + let getUint32; + if (coeffs instanceof ffjavascript.BigBuffer) { + const coeffsDV = []; + const PAGE_LEN = coeffs.buffers[0].length; + for (let i = 0; i < coeffs.buffers.length; i++) coeffsDV.push(new DataView(coeffs.buffers[i].buffer)); + getUint32 = function(pos) { + return coeffsDV[Math.floor(pos / PAGE_LEN)].getUint32(pos % PAGE_LEN, true); + }; + } else { + const coeffsDV = new DataView(coeffs.buffer, coeffs.byteOffset, coeffs.byteLength); + getUint32 = function(pos) { + return coeffsDV.getUint32(pos, true); + }; + } + const elementsPerChunk = Math.floor((zkey.domainSize - 1) / concurrency) + 1; + const promises = []; + const cutPoints = []; + for (let i = 0; i < concurrency; i++) cutPoints.push(getCutPoint(Math.floor(i * elementsPerChunk))); + cutPoints.push(coeffs.byteLength); + const chunkSize = elementsPerChunk; + console.log("zkey.domainSize", zkey.domainSize); + console.log("concurrency", concurrency); + console.log("elementsPerChunk", elementsPerChunk); + console.log("chunkSize", chunkSize); + for (let s = 0; s < zkey.nVars; s += chunkSize) { + if (logger) logger.debug(`QAP: ${s}/${zkey.nVars}`); + const ns = Math.min(zkey.nVars - s, chunkSize); + console.log("ns", ns); + for (let i = 0; i < concurrency; i++) { + let n; + if (i < concurrency - 1) n = elementsPerChunk; + else n = zkey.domainSize - i * elementsPerChunk; + if (n === 0) continue; + const task = []; + const coeffsBuff = coeffs.slice(cutPoints[i], cutPoints[i + 1]); + const witnessBuff = witness.slice(s * curve.Fr.n8, (s + ns) * curve.Fr.n8); + task.push({ + cmd: "ALLOCSET", + var: 0, + buff: coeffsBuff + }); + task.push({ + cmd: "ALLOCSET", + var: 1, + buff: witnessBuff + }); + task.push({ + cmd: "ALLOC", + var: 2, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "ALLOC", + var: 3, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "ALLOC", + var: 4, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "CALL", + fnName: "qap_buildABC", + params: [ + { var: 0 }, + { val: (cutPoints[i + 1] - cutPoints[i]) / sCoef }, + { var: 1 }, + { var: 2 }, + { var: 3 }, + { var: 4 }, + { val: i * elementsPerChunk }, + { val: n }, + { val: s }, + { val: ns } + ] + }); + task.push({ + cmd: "GET", + out: 0, + var: 2, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "GET", + out: 1, + var: 3, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "GET", + out: 2, + var: 4, + len: n * curve.Fr.n8 + }); + promises.push(curve.tm.queueAction(task, [coeffsBuff.buffer, witnessBuff.buffer])); + } + } + let result = await Promise.all(promises); + console.log("result.length", result.length); + console.log("result", result); + const nGroups = result.length / concurrency; + console.log("nGroups", nGroups); + let result2; + if (nGroups > 1) { + const promises2 = []; + for (let i = 0; i < concurrency; i++) { + const task = []; + task.push({ + cmd: "ALLOC", + var: 0, + len: result[i][0].byteLength + }); + task.push({ + cmd: "ALLOC", + var: 1, + len: result[i][0].byteLength + }); + for (let m = 0; m < 3; m++) { + task.push({ + cmd: "SET", + var: 0, + buff: result[i][m] + }); + for (let s = 1; s < nGroups; s++) { + task.push({ + cmd: "SET", + var: 1, + buff: result[s * concurrency + i][m] + }); + task.push({ + cmd: "CALL", + fnName: "qap_batchAdd", + params: [ + { var: 0 }, + { var: 1 }, + { val: result[i][m].length / curve.Fr.n8 }, + { var: 0 } + ] + }); + } + task.push({ + cmd: "GET", + out: m, + var: 0, + len: result[i][m].length + }); + } + console.log("task.length", task.length); + promises2.push(curve.tm.queueAction(task, result.buffer)); + } + console.log("promises2.length", promises2.length); + result2 = await Promise.all(promises2); + result = result2; + } + const outBuffA = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); + const outBuffB = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); + const outBuffC = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); + let p = 0; + for (let i = 0; i < result.length; i++) { + outBuffA.set(result[i][0], p); + outBuffB.set(result[i][1], p); + outBuffC.set(result[i][2], p); + p += result[i][0].byteLength; + } + console.timeEnd("buildABC"); + return [ + outBuffA, + outBuffB, + outBuffC + ]; + function getCutPoint(v) { + let m = 0; + let n = getUint32(0); + while (m < n) { + let k = Math.floor((n + m) / 2); + const va = getUint32(4 + k * sCoef + 4); + if (va > v) n = k - 1; + else if (va < v) m = k + 1; + else n = k; + } + return 4 + m * sCoef; + } +} async function joinABC(curve, zkey, a, b, c, logger) { - console.time("joinABC"); - const MAX_CHUNK_SIZE = 1 << 16; - - const n8 = curve.Fr.n8; - const nElements = Math.floor(a.byteLength / curve.Fr.n8); - - const promises = []; - - for (let i=0; i { - memUsage(logger); - }, interval); -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ -const { unstringifyBigInts: unstringifyBigInts$a} = ffjavascript.utils; - + if (!logger) return; + const used = process.memoryUsage(); + logger.debug(" ", "\x1B[0m Heap:\x1B[32m", `${Math.round(used.heapUsed / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m / \x1B[32m", `${Math.round(used.heapTotal / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m RSS:\x1B[32m", `${Math.round(used.rss / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m External:\x1B[32m", `${Math.round(used.external / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m ArrBuffers:\x1B[32m", `${Math.round(used.arrayBuffers / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m"); +} +function monitorMemoryUsage(logger, interval = 5e3) { + return setInterval(() => { + memUsage(logger); + }, interval); +} +//#endregion +//#region src/wtns_calculate.js +var { unstringifyBigInts: unstringifyBigInts$10 } = ffjavascript.utils; async function wtnsCalculate$1(_input, wasmFileName, wtnsFileName, options) { - const input = unstringifyBigInts$a(_input); - - const fdWasm = await fastFile__namespace.readExisting(wasmFileName); - const wasm = await fdWasm.read(fdWasm.totalSize); - await fdWasm.close(); - - const wc = await circom_runtime.WitnessCalculatorBuilder(wasm, options); - if (wc.circom_version() === 1) { - const w = await wc.calculateBinWitness(input); - - const fdWtns = await binFileUtils__namespace.createBinFile(wtnsFileName, "wtns", 2, 2); - - await writeBin(fdWtns, w, wc.prime); - await fdWtns.close(); - } else { - const fdWtns = await fastFile__namespace.createOverride(wtnsFileName); - - const w = await wc.calculateWTNSBin(input); - - await fdWtns.write(w); - await fdWtns.close(); - } -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ -const {unstringifyBigInts: unstringifyBigInts$9} = ffjavascript.utils; - + const input = unstringifyBigInts$10(_input); + const fdWasm = await fastfile.readExisting(wasmFileName); + const wasm = await fdWasm.read(fdWasm.totalSize); + await fdWasm.close(); + const wc = await (0, circom_runtime.WitnessCalculatorBuilder)(wasm, options); + if (wc.circom_version() === 1) { + const w = await wc.calculateBinWitness(input); + const fdWtns = await _iden3_binfileutils.createBinFile(wtnsFileName, "wtns", 2, 2); + await writeBin(fdWtns, w, wc.prime); + await fdWtns.close(); + } else { + const fdWtns = await fastfile.createOverride(wtnsFileName); + const w = await wc.calculateWTNSBin(input); + await fdWtns.write(w); + await fdWtns.close(); + } +} +//#endregion +//#region src/groth16_fullprove.js +var { unstringifyBigInts: unstringifyBigInts$9 } = ffjavascript.utils; async function groth16FullProve$1(_input, wasmFile, zkeyFileName, logger, wtnsCalcOptions, proverOptions) { - const input = unstringifyBigInts$9(_input); - - const wtns= { - type: "mem" - }; - await wtnsCalculate$1(input, wasmFile, wtns, wtnsCalcOptions); - return await groth16Prove$1(zkeyFileName, wtns, logger, proverOptions); -} - -/* - Copyright 2018 0kims association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ -const {unstringifyBigInts: unstringifyBigInts$8} = ffjavascript.utils; - + const input = unstringifyBigInts$9(_input); + const wtns = { type: "mem" }; + await wtnsCalculate$1(input, wasmFile, wtns, wtnsCalcOptions); + return await groth16Prove$1(zkeyFileName, wtns, logger, proverOptions); +} +//#endregion +//#region src/groth16_verify.js +var { unstringifyBigInts: unstringifyBigInts$8 } = ffjavascript.utils; async function groth16Verify$1(_vk_verifier, _publicSignals, _proof, logger) { -/* - let cpub = vk_verifier.IC[0]; - for (let s= 0; s< vk_verifier.nPublic; s++) { - cpub = G1.add( cpub, G1.timesScalar( vk_verifier.IC[s+1], publicSignals[s])); - } -*/ - - const vk_verifier = unstringifyBigInts$8(_vk_verifier); - const proof = unstringifyBigInts$8(_proof); - const publicSignals = unstringifyBigInts$8(_publicSignals); - - const curve = await getCurveFromName(vk_verifier.curve); - - const IC0 = curve.G1.fromObject(vk_verifier.IC[0]); - const IC = new Uint8Array(curve.G1.F.n8*2 * publicSignals.length); - const w = new Uint8Array(curve.Fr.n8 * publicSignals.length); - - if (!publicInputsAreValid$2(curve, publicSignals)) { - if (logger) logger.error("Public inputs are not valid."); - return false; - } - - for (let i=0; i. -*/ -const { unstringifyBigInts: unstringifyBigInts$7} = ffjavascript.utils; - + for (let i = 0; i < publicInputs.length; i++) if (!checkValueBelongToField$2(curve, publicInputs[i])) return false; + return true; +} +//#endregion +//#region src/groth16_exportsoliditycalldata.js +var { unstringifyBigInts: unstringifyBigInts$7 } = ffjavascript.utils; function p256$2(n) { - let nstr = n.toString(16); - while (nstr.length < 64) nstr = "0"+nstr; - nstr = `"0x${nstr}"`; - return nstr; + let nstr = n.toString(16); + while (nstr.length < 64) nstr = "0" + nstr; + nstr = `"0x${nstr}"`; + return nstr; } - async function groth16ExportSolidityCallData(_proof, _pub) { - const proof = unstringifyBigInts$7(_proof); - const pub = unstringifyBigInts$7(_pub); - - let inputs = ""; - for (let i=0; i. -*/ - - + const proof = unstringifyBigInts$7(_proof); + const pub = unstringifyBigInts$7(_pub); + let inputs = ""; + for (let i = 0; i < pub.length; i++) { + if (inputs != "") inputs = inputs + ","; + inputs = inputs + p256$2(pub[i]); + } + let S; + S = `[${p256$2(proof.pi_a[0])}, ${p256$2(proof.pi_a[1])}],[[${p256$2(proof.pi_b[0][1])}, ${p256$2(proof.pi_b[0][0])}],[${p256$2(proof.pi_b[1][1])}, ${p256$2(proof.pi_b[1][0])}]],[${p256$2(proof.pi_c[0])}, ${p256$2(proof.pi_c[1])}],[${inputs}]`; + return S; +} +//#endregion +//#region src/plonk_setup.js async function plonkSetup$1(r1csName, ptauName, zkeyName, logger) { - - if (globalThis.gc) {globalThis.gc();} - - const {fd: fdPTau, sections: sectionsPTau} = await binFileUtils.readBinFile(ptauName, "ptau", 1, 1<<22, 1<<24); - const {curve, power} = await readPTauHeader(fdPTau, sectionsPTau); - const {fd: fdR1cs, sections: sectionsR1cs} = await binFileUtils.readBinFile(r1csName, "r1cs", 1, 1<<22, 1<<24); - - const r1cs = await r1csfile.readR1csFd(fdR1cs, sectionsR1cs, {loadConstraints: true, loadCustomGates: true}); - - const sG1 = curve.G1.F.n8*2; - const G1 = curve.G1; - const sG2 = curve.G2.F.n8*2; - const Fr = curve.Fr; - const n8r = curve.Fr.n8; - - if (logger) logger.info("Reading r1cs"); - await binFileUtils.readSection(fdR1cs, sectionsR1cs, 2); - - const plonkConstraints = new BigArray(); - const plonkAdditions = new BigArray(); - let plonkNVars = r1cs.nVars; - - const nPublic = r1cs.nOutputs + r1cs.nPubInputs; - - await processConstraints(curve.Fr, r1cs, logger); - - if (globalThis.gc) {globalThis.gc();} - - const fdZKey = await binFileUtils.createBinFile(zkeyName, "zkey", 1, 14, 1<<22, 1<<24); - - - if (r1cs.prime != curve.r) { - if (logger) logger.error("r1cs curve does not match powers of tau ceremony curve"); - return -1; - } - - let cirPower = log2(plonkConstraints.length -1) +1; - if (cirPower < 3) cirPower = 3; // As the t polynomial is n+5 we need at least a power of 4 - const domainSize = 2 ** cirPower; - - if (logger) logger.info("Plonk constraints: " + plonkConstraints.length); - if (cirPower > power) { - if (logger) logger.error(`circuit too big for this power of tau ceremony. ${plonkConstraints.length} > 2**${power}`); - return -1; - } - - if (!sectionsPTau[12]) { - if (logger) logger.error("Powers of tau is not prepared."); - return -1; - } - - - const LPoints = new ffjavascript.BigBuffer(domainSize*sG1); - const o = sectionsPTau[12][0].p + ((2 ** (cirPower)) -1)*sG1; - await fdPTau.readToBuffer(LPoints, 0, domainSize*sG1, o); - - const [k1, k2] = getK1K2(); - - const vk = {}; - - - await writeAdditions(3, "Additions"); - if (globalThis.gc) {globalThis.gc();} - await writeWitnessMap(4, 0, "Amap"); - if (globalThis.gc) {globalThis.gc();} - await writeWitnessMap(5, 1, "Bmap"); - if (globalThis.gc) {globalThis.gc();} - await writeWitnessMap(6, 2, "Cmap"); - if (globalThis.gc) {globalThis.gc();} - await writeQMap(7, 3, "Qm"); - if (globalThis.gc) {globalThis.gc();} - await writeQMap(8, 4, "Ql"); - if (globalThis.gc) {globalThis.gc();} - await writeQMap(9, 5, "Qr"); - if (globalThis.gc) {globalThis.gc();} - await writeQMap(10, 6, "Qo"); - if (globalThis.gc) {globalThis.gc();} - await writeQMap(11, 7, "Qc"); - if (globalThis.gc) {globalThis.gc();} - await writeSigma(12, "sigma"); - if (globalThis.gc) {globalThis.gc();} - await writeLs(13, "lagrange polynomials"); - if (globalThis.gc) {globalThis.gc();} - - // Write PTau points - //////////// - - await binFileUtils.startWriteSection(fdZKey, 14); - const buffOut = new ffjavascript.BigBuffer((domainSize+6)*sG1); - await fdPTau.readToBuffer(buffOut, 0, (domainSize+6)*sG1, sectionsPTau[2][0].p); - await fdZKey.write(buffOut); - await binFileUtils.endWriteSection(fdZKey); - if (globalThis.gc) {globalThis.gc();} - - - await writeHeaders(); - - await fdZKey.close(); - await fdR1cs.close(); - await fdPTau.close(); - - if (logger) logger.info("Setup Finished"); - - return ; - - async function processConstraints(Fr, r1cs, logger) { - - function normalize(linearComb) { - const ss = Object.keys(linearComb); - for (let i = 0; i < ss.length; i++) { - if (linearComb[ss[i]] == 0n) delete linearComb[ss[i]]; - } - } - - function join(linearComb1, k, linearComb2) { - const res = {}; - - for (let s in linearComb1) { - if (typeof res[s] == "undefined") { - res[s] = Fr.mul(k, linearComb1[s]); - } else { - res[s] = Fr.add(res[s], Fr.mul(k, linearComb1[s])); - } - } - - for (let s in linearComb2) { - if (typeof res[s] == "undefined") { - res[s] = linearComb2[s]; - } else { - res[s] = Fr.add(res[s], linearComb2[s]); - } - } - normalize(res); - return res; - } - - function reduceCoefs(linearComb, maxC) { - const res = { - k: Fr.zero, - s: [], - coefs: [] - }; - const cs = []; - - for (let s in linearComb) { - if (s == 0) { - res.k = Fr.add(res.k, linearComb[s]); - } else if (linearComb[s] != 0n) { - cs.push([Number(s), linearComb[s]]); - } - } - while (cs.length > maxC) { - const c1 = cs.shift(); - const c2 = cs.shift(); - - const sl = c1[0]; - const sr = c2[0]; - const so = plonkNVars++; - const qm = Fr.zero; - const ql = Fr.neg(c1[1]); - const qr = Fr.neg(c2[1]); - const qo = Fr.one; - const qc = Fr.zero; - - plonkConstraints.push([sl, sr, so, qm, ql, qr, qo, qc]); - - plonkAdditions.push([sl, sr, c1[1], c2[1]]); - - cs.push([so, Fr.one]); - } - for (let i = 0; i < cs.length; i++) { - res.s[i] = cs[i][0]; - res.coefs[i] = cs[i][1]; - } - while (res.coefs.length < maxC) { - res.s.push(0); - res.coefs.push(Fr.zero); - } - return res; - } - - function addConstraintSum(lc) { - const C = reduceCoefs(lc, 3); - const sl = C.s[0]; - const sr = C.s[1]; - const so = C.s[2]; - const qm = Fr.zero; - const ql = C.coefs[0]; - const qr = C.coefs[1]; - const qo = C.coefs[2]; - const qc = C.k; - plonkConstraints.push([sl, sr, so, qm, ql, qr, qo, qc]); - } - - function addConstraintMul(lcA, lcB, lcC) { - const A = reduceCoefs(lcA, 1); - const B = reduceCoefs(lcB, 1); - const C = reduceCoefs(lcC, 1); - - - const sl = A.s[0]; - const sr = B.s[0]; - const so = C.s[0]; - const qm = Fr.mul(A.coefs[0], B.coefs[0]); - const ql = Fr.mul(A.coefs[0], B.k); - const qr = Fr.mul(A.k, B.coefs[0]); - const qo = Fr.neg(C.coefs[0]); - const qc = Fr.sub(Fr.mul(A.k, B.k), C.k); - plonkConstraints.push([sl, sr, so, qm, ql, qr, qo, qc]); - } - - function getLinearCombinationType(lc) { - let k = Fr.zero; - let n = 0; - const ss = Object.keys(lc); - for (let i = 0; i < ss.length; i++) { - if (lc[ss[i]] == 0n) { - delete lc[ss[i]]; - } else if (ss[i] == 0) { - k = Fr.add(k, lc[ss[i]]); - } else { - n++; - } - } - if (n > 0) return n.toString(); - if (k != Fr.zero) return "k"; - return "0"; - } - - function process(lcA, lcB, lcC) { - const lctA = getLinearCombinationType(lcA); - const lctB = getLinearCombinationType(lcB); - if ((lctA === "0") || (lctB === "0")) { - normalize(lcC); - addConstraintSum(lcC); - } else if (lctA === "k") { - const lcCC = join(lcB, lcA[0], lcC); - addConstraintSum(lcCC); - } else if (lctB === "k") { - const lcCC = join(lcA, lcB[0], lcC); - addConstraintSum(lcCC); - } else { - addConstraintMul(lcA, lcB, lcC); - } - } - - for (let s = 1; s <= nPublic; s++) { - const sl = s; - const sr = 0; - const so = 0; - const qm = Fr.zero; - const ql = Fr.one; - const qr = Fr.zero; - const qo = Fr.zero; - const qc = Fr.zero; - - plonkConstraints.push([sl, sr, so, qm, ql, qr, qo, qc]); - } - - for (let c = 0; c < r1cs.constraints.length; c++) { - if ((logger) && (c % 10000 === 0)) logger.debug(`processing constraints: ${c}/${r1cs.nConstraints}`); - process(...r1cs.constraints[c]); - } - } - - async function writeWitnessMap(sectionNum, posConstraint, name) { - await binFileUtils.startWriteSection(fdZKey, sectionNum); - for (let i=0; i. -*/ - -class Proof { - constructor(curve, logger) { - this.curve = curve; - this.logger = logger; - - this.resetProof(); - } - - resetProof() { - this.polynomials = {}; - this.evaluations = {}; - } - - addPolynomial(key, polynomial) { - if (key in this.polynomials) { - this.logger.warn(`proof: polynomial.${key} already exist in proof`); - } - this.polynomials[key] = polynomial; - } - - getPolynomial(key) { - if (!(key in this.polynomials)) { - this.logger.warn(`proof: polynomial ${key} does not exist in proof`); - } - return this.polynomials[key]; - } - - addEvaluation(key, evaluation) { - if (key in this.evaluations) { - this.logger.warn(`proof: evaluations.${key} already exist in proof`); - } - this.evaluations[key] = evaluation; - } - - getEvaluation(key) { - if (!(key in this.evaluations)) { - this.logger.warn(`proof: evaluation ${key} does not exist in proof`); - } - return this.evaluations[key]; - } - - toObjectProof(splitFields = true) { - let res = splitFields ? {polynomials: {}, evaluations: {}} : {}; - - Object.keys(this.polynomials).forEach(key => { - const value = this.curve.G1.toObject(this.polynomials[key]); - if(splitFields) { - res.polynomials[key] = value; - } else { - res[key] = value; - } - }); - - Object.keys(this.evaluations).forEach(key => { - const value = this.curve.Fr.toObject(this.evaluations[key]); - if(splitFields) { - res.evaluations[key] = value; - } else { - res[key] = value; - } - }); - - return res; - } - - fromObjectProof(objectProof) { - this.resetProof(); - - Object.keys(objectProof.polynomials).forEach(key => { - this.polynomials[key] = this.curve.G1.fromObject(objectProof.polynomials[key]); - }); - - Object.keys(objectProof.evaluations).forEach(key => { - this.evaluations[key] = this.curve.Fr.fromObject(objectProof.evaluations[key]); - }); - } -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -const POLYNOMIAL = 0; -const SCALAR = 1; - -class Keccak256Transcript { - constructor(curve) { - this.G1 = curve.G1; - this.Fr = curve.Fr; - - this.reset(); - } - - reset() { - this.data = []; - } - - addPolCommitment(polynomialCommitment) { - this.data.push({type: POLYNOMIAL, data: polynomialCommitment}); - } - - addScalar(scalar) { - this.data.push({type: SCALAR, data: scalar}); - } - - getChallenge() { - if(0 === this.data.length) { - throw new Error("Keccak256Transcript: No data to generate a transcript"); - } - - let nPolynomials = 0; - let nScalars = 0; - - this.data.forEach(element => POLYNOMIAL === element.type ? nPolynomials++ : nScalars++); - - let buffer = new Uint8Array(nScalars * this.Fr.n8 + nPolynomials * this.G1.F.n8 * 2); - let offset = 0; - - for (let i = 0; i < this.data.length; i++) { - if (POLYNOMIAL === this.data[i].type) { - this.G1.toRprUncompressed(buffer, offset, this.data[i].data); - offset += this.G1.F.n8 * 2; - } else { - this.Fr.toRprBE(buffer, offset, this.data[i].data); - offset += this.Fr.n8; - } - } - - const value = ffjavascript.Scalar.fromRprBE(sha3.keccak_256(buffer)); - return this.Fr.e(value); - } -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -class MulZ { - static getZ1(Fr) { - return [ - Fr.zero, - Fr.add(Fr.e(-1), Fr.w[2]), - Fr.e(-2), - Fr.sub(Fr.e(-1), Fr.w[2]), - ]; - } - - static getZ2(Fr) { - return [ - Fr.zero, - Fr.add(Fr.zero, Fr.mul(Fr.e(-2), Fr.w[2])), - Fr.e(4), - Fr.sub(Fr.zero, Fr.mul(Fr.e(-2), Fr.w[2])), - ]; - } - - static getZ3(Fr) { - return [ - Fr.zero, - Fr.add(Fr.e(2), Fr.mul(Fr.e(2), Fr.w[2])), - Fr.e(-8), - Fr.sub(Fr.e(2), Fr.mul(Fr.e(2), Fr.w[2])), - ]; - - } - - static mul2(a, b, ap, bp, p, Fr) { - const Z1 = this.getZ1(Fr); - let r, rz; - - const a_b = Fr.mul(a, b); - const a_bp = Fr.mul(a, bp); - const ap_b = Fr.mul(ap, b); - const ap_bp = Fr.mul(ap, bp); - - r = a_b; - - let a0 = Fr.add(a_bp, ap_b); - - let a1 = ap_bp; - - rz = a0; - if (p) { - rz = Fr.add(rz, Fr.mul(Z1[p], a1)); - } - - return [r, rz]; - } - - static mul3(a, b, c, ap, bp, cp, p, Fr) { - const Z1 = this.getZ1(Fr); - const Z2 = this.getZ2(Fr); - let r, rz; - - const a_b = Fr.mul(a, b); - const a_bp = Fr.mul(a, bp); - const ap_b = Fr.mul(ap, b); - const ap_bp = Fr.mul(ap, bp); - - r = Fr.mul(a_b, c); - - let a0 = Fr.mul(ap_b, c); - a0 = Fr.add(a0, Fr.mul(a_bp, c)); - a0 = Fr.add(a0, Fr.mul(a_b, cp)); - - let a1 = Fr.mul(ap_bp, c); - a1 = Fr.add(a1, Fr.mul(a_bp, cp)); - a1 = Fr.add(a1, Fr.mul(ap_b, cp)); - - rz = a0; - if (p) { - const a2 = Fr.mul(ap_bp, cp); - rz = Fr.add(rz, Fr.mul(Z1[p], a1)); - rz = Fr.add(rz, Fr.mul(Z2[p], a2)); - } - - return [r, rz]; - } - - static mul4(a, b, c, d, ap, bp, cp, dp, p, Fr) { - const Z1 = this.getZ1(Fr); - const Z2 = this.getZ2(Fr); - const Z3 = this.getZ3(Fr); - - let r, rz; - - const a_b = Fr.mul(a, b); - const a_bp = Fr.mul(a, bp); - const ap_b = Fr.mul(ap, b); - const ap_bp = Fr.mul(ap, bp); - - const c_d = Fr.mul(c, d); - const c_dp = Fr.mul(c, dp); - const cp_d = Fr.mul(cp, d); - const cp_dp = Fr.mul(cp, dp); - - r = Fr.mul(a_b, c_d); - - let a0 = Fr.mul(ap_b, c_d); - a0 = Fr.add(a0, Fr.mul(a_bp, c_d)); - a0 = Fr.add(a0, Fr.mul(a_b, cp_d)); - a0 = Fr.add(a0, Fr.mul(a_b, c_dp)); - - let a1 = Fr.mul(ap_bp, c_d); - a1 = Fr.add(a1, Fr.mul(ap_b, cp_d)); - a1 = Fr.add(a1, Fr.mul(ap_b, c_dp)); - a1 = Fr.add(a1, Fr.mul(a_bp, cp_d)); - a1 = Fr.add(a1, Fr.mul(a_bp, c_dp)); - a1 = Fr.add(a1, Fr.mul(a_b, cp_dp)); - - let a2 = Fr.mul(a_bp, cp_dp); - a2 = Fr.add(a2, Fr.mul(ap_b, cp_dp)); - a2 = Fr.add(a2, Fr.mul(ap_bp, c_dp)); - a2 = Fr.add(a2, Fr.mul(ap_bp, cp_d)); - - let a3 = Fr.mul(ap_bp, cp_dp); - - rz = a0; - if (p) { - rz = Fr.add(rz, Fr.mul(Z1[p], a1)); - rz = Fr.add(rz, Fr.mul(Z2[p], a2)); - rz = Fr.add(rz, Fr.mul(Z3[p], a3)); - } - - return [r, rz]; - } -} - -const ZKEY_PL_ADDITIONS_SECTION = 3; -const ZKEY_PL_A_MAP_SECTION = 4; -const ZKEY_PL_B_MAP_SECTION = 5; -const ZKEY_PL_C_MAP_SECTION = 6; -const ZKEY_PL_QM_SECTION = 7; -const ZKEY_PL_QL_SECTION = 8; -const ZKEY_PL_QR_SECTION = 9; -const ZKEY_PL_QO_SECTION = 10; -const ZKEY_PL_QC_SECTION = 11; -const ZKEY_PL_SIGMA_SECTION = 12; -const ZKEY_PL_LAGRANGE_SECTION = 13; -const ZKEY_PL_PTAU_SECTION = 14; - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -class Polynomial { - constructor(coefficients, curve, logger) { - this.coef = coefficients; - this.curve = curve; - this.Fr = curve.Fr; - this.G1 = curve.G1; - this.logger = logger; - } - - static async fromEvaluations(buffer, curve, logger) { - let coefficients = await curve.Fr.ifft(buffer); - - return new Polynomial(coefficients, curve, logger); - } - - static fromCoefficientsArray(array, curve, logger) { - const Fr = curve.Fr; - let buff = array.length > 2 << 14 ? - new ffjavascript.BigBuffer(array.length * Fr.n8) : new Uint8Array(array.length * Fr.n8); - for (let i = 0; i < array.length; i++) buff.set(array[i], i * Fr.n8); - - return new Polynomial(buff, curve, logger); - } - - static fromPolynomial(polynomial, curve, logger) { - let length = polynomial.length(); - let Fr = curve.Fr; - - let buff = length > 2 << 14 ? - new ffjavascript.BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8); - buff.set(polynomial.coef.slice(), 0); - - return new Polynomial(buff, curve, logger); - } - - isEqual(polynomial) { - const degree = this.degree(); - if (degree !== polynomial.degree()) return false; - - for (let i = 0; i < degree + 1; i++) { - if (!this.Fr.eq(this.getCoef(i), polynomial.getCoef(i))) return false; - } - - return true; - } - - blindCoefficients(blindingFactors) { - blindingFactors = blindingFactors || []; - - const blindedCoefficients = (this.length() + blindingFactors.length) > 2 << 14 ? - new ffjavascript.BigBuffer((this.length() + blindingFactors.length) * this.Fr.n8) : - new Uint8Array((this.length() + blindingFactors.length) * this.Fr.n8); - - blindedCoefficients.set(this.coef, 0); - for (let i = 0; i < blindingFactors.length; i++) { - blindedCoefficients.set( - this.Fr.add( - blindedCoefficients.slice((this.length() + i) * this.Fr.n8, (this.length() + i + 1) * this.Fr.n8), - blindingFactors[i] - ), - (this.length() + i) * this.Fr.n8 - ); - blindedCoefficients.set( - this.Fr.sub( - blindedCoefficients.slice(i * this.Fr.n8, (i + 1) * this.Fr.n8), - blindingFactors[i] - ), - i * this.Fr.n8 - ); - } - this.coef = blindedCoefficients; - } - - getCoef(index) { - const i_n8 = index * this.Fr.n8; - - if (i_n8 + this.Fr.n8 > this.coef.byteLength) return this.Fr.zero; - - return this.coef.slice(i_n8, i_n8 + this.Fr.n8); - } - - setCoef(index, value) { - if (index > (this.length() - 1)) { - throw new Error("Coef index is not available"); - } - - this.coef.set(value, index * this.Fr.n8); - } - - static async to4T(buffer, domainSize, blindingFactors, Fr) { - blindingFactors = blindingFactors || []; - let a = await Fr.ifft(buffer); - - const a4 = (domainSize * 4) > 2 << 14 ? - new ffjavascript.BigBuffer(domainSize * 4 * Fr.n8) : new Uint8Array(domainSize * 4 * Fr.n8); - a4.set(a, 0); - - const A4 = await Fr.fft(a4); - - if (blindingFactors.length === 0) { - return [a, A4]; - } - - const a1 = domainSize + blindingFactors.length > 2 << 14 ? - new ffjavascript.BigBuffer((domainSize + blindingFactors.length) * Fr.n8) : - new Uint8Array((domainSize + blindingFactors.length) * Fr.n8); - - a1.set(a, 0); - for (let i = 0; i < blindingFactors.length; i++) { - a1.set( - Fr.add( - a1.slice((domainSize + i) * Fr.n8, (domainSize + i + 1) * Fr.n8), - blindingFactors[i] - ), - (domainSize + i) * Fr.n8 - ); - a1.set( - Fr.sub( - a1.slice(i * Fr.n8, (i + 1) * Fr.n8), - blindingFactors[i] - ), - i * Fr.n8 - ); - } - - return [a1, A4]; - } - - length() { - let length = this.coef.byteLength / this.Fr.n8; - if (length !== Math.floor(this.coef.byteLength / this.Fr.n8)) { - throw new Error("Polynomial coefficients buffer has incorrect size"); - } - if (0 === length) { - if (this.logger) { - this.logger.warn("Polynomial has length zero"); - } - } - return length; - } - - degree() { - for (let i = this.length() - 1; i > 0; i--) { - const i_n8 = i * this.Fr.n8; - if (!this.Fr.eq(this.Fr.zero, this.coef.slice(i_n8, i_n8 + this.Fr.n8))) { - return i; - } - } - - return 0; - } - - evaluate(point) { - let res = this.Fr.zero; - - for (let i = this.degree() + 1; i > 0; i--) { - let i_n8 = i * this.Fr.n8; - const currentCoefficient = this.coef.slice(i_n8 - this.Fr.n8, i_n8); - res = this.Fr.add(currentCoefficient, this.Fr.mul(res, point)); - } - - return res; - } - - fastEvaluate(point) { - const Fr = this.Fr; - let nThreads = 3; - - let nCoefs = this.degree() + 1; - let coefsThread = parseInt(nCoefs / nThreads); - let residualCoefs = nCoefs - coefsThread * nThreads; - - let res = []; - let xN = []; - - xN[0] = Fr.one; - - for (let i = 0; i < nThreads; i++) { - res[i] = Fr.zero; - - let nCoefs = i === (nThreads - 1) ? coefsThread + residualCoefs : coefsThread; - for (let j = nCoefs; j > 0; j--) { - res[i] = Fr.add(this.getCoef((i * coefsThread) + j - 1), Fr.mul(res[i], point)); - - if (i === 0) xN[0] = Fr.mul(xN[0], point); - } - } - - for (let i = 1; i < nThreads; i++) { - res[0] = Fr.add(res[0], Fr.mul(xN[i - 1], res[i])); - xN[i] = Fr.mul(xN[i - 1], xN[0]); - } - - return res[0]; - } - - add(polynomial, blindingValue) { - let other = false; - - if (polynomial.length() > this.length()) { - other = true; - } - - const thisLength = this.length(); - const polyLength = polynomial.length(); - for (let i = 0; i < Math.max(thisLength, polyLength); i++) { - const i_n8 = i * this.Fr.n8; - - const a = i < thisLength ? this.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; - let b = i < polyLength ? polynomial.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; - - if (blindingValue !== undefined) { - b = this.Fr.mul(b, blindingValue); - } - if (other) { - polynomial.coef.set(this.Fr.add(a, b), i_n8); - } else { - this.coef.set(this.Fr.add(a, b), i_n8); - } - } - if (other) { - delete this.coef; - this.coef = polynomial.coef; - } - } - - sub(polynomial, blindingValue) { - let other = false; - - if (polynomial.length() > this.length()) { - other = true; - } - - const thisLength = this.length(); - const polyLength = polynomial.length(); - for (let i = 0; i < Math.max(thisLength, polyLength); i++) { - const i_n8 = i * this.Fr.n8; - - const a = i < thisLength ? this.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; - let b = i < polyLength ? polynomial.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; - - if (blindingValue !== undefined) { - b = this.Fr.mul(b, blindingValue); - } - if (other) { - polynomial.coef.set(this.Fr.sub(a, b), i_n8); - } else { - this.coef.set(this.Fr.sub(a, b), i_n8); - } - } - if (other) { - delete this.coef; - this.coef = polynomial.coef; - } - } - - mulScalar(value) { - for (let i = 0; i < this.length(); i++) { - const i_n8 = i * this.Fr.n8; - - this.coef.set(this.Fr.mul(this.coef.slice(i_n8, i_n8 + this.Fr.n8), value), i_n8); - } - } - - addScalar(value) { - const currentValue = 0 === this.length() ? this.Fr.zero : this.coef.slice(0, this.Fr.n8); - this.coef.set(this.Fr.add(currentValue, value), 0); - } - - subScalar(value) { - const currentValue = 0 === this.length() ? this.Fr.zero : this.coef.slice(0, this.Fr.n8); - this.coef.set(this.Fr.sub(currentValue, value), 0); - } - - // Multiply current polynomial by the polynomial (X - value) - byXSubValue(value) { - const Fr = this.Fr; - const resize = !Fr.eq(Fr.zero, this.getCoef(this.length() - 1)); - - const length = resize ? this.length() + 1 : this.length(); - const buff = length > 2 << 14 ? new ffjavascript.BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8); - let pol = new Polynomial(buff, this.curve, this.logger); - - // Step 0: Set current coefficients to the new buffer shifted one position - pol.coef.set(this.coef.slice(0, (length - 1) * Fr.n8), 32); - - // Step 1: multiply each coefficient by (-value) - this.mulScalar(Fr.neg(value)); - - // Step 2: Add current polynomial to destination polynomial - pol.add(this); - - // Swap buffers - this.coef = pol.coef; - } - - // Multiply current polynomial by the polynomial (X^n + value) - byXNSubValue(n, value) { - const Fr = this.Fr; - const resize = !(this.length() - n - 1 >= this.degree()); - - const length = resize ? this.length() + n : this.length(); - const buff = length > 2 << 14 ? new ffjavascript.BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8); - let pol = new Polynomial(buff, this.curve, this.logger); - - // Step 0: Set current coefficients to the new buffer shifted one position - pol.coef.set(this.coef.slice(0, (this.degree() + 1) * 32, ), n * 32); - - // Step 1: multiply each coefficient by (- value) - this.mulScalar(value); - - // Step 2: Add current polynomial to destination polynomial - pol.add(this); - - // Swap buffers - this.coef = pol.coef; - } - - // Euclidean division - divBy(polynomial) { - const Fr = this.Fr; - const degreeA = this.degree(); - const degreeB = polynomial.degree(); - - let polR = new Polynomial(this.coef, this.curve, this.logger); - - this.coef = this.length() > 2 << 14 ? - new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); - - for (let i = degreeA - degreeB; i >= 0; i--) { - this.setCoef(i, Fr.div(polR.getCoef(i + degreeB), polynomial.getCoef(degreeB))); - for (let j = 0; j <= degreeB; j++) { - polR.setCoef(i + j, Fr.sub(polR.getCoef(i + j), Fr.mul(this.getCoef(i), polynomial.getCoef(j)))); - } - } - - return polR; - } - - // Division by a Polynomial of the form (x^m - beta) - divByMonic(m, beta) { - const Fr = this.Fr; - - let d = this.degree(); - - let buffer = this.length() > 2 << 14 ? - new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); - let quotient = new Polynomial(buffer, this.curve, this.logger); - - let bArr = []; - - // Add the m leading coefficients of this to quotient - for (let i = 0; i < m; i++) { - quotient.setCoef((d - i) - m, this.getCoef(d - i)); - bArr[i] = this.getCoef(d - i); - } - - let nThreads = m; - for (let k = 0; k < nThreads; k++) { - for (let i = d - 2 * m - k; i >= 0; i = i - nThreads) { - if (i < 0) break; - let idx = k; - bArr[idx] = Fr.add(this.getCoef(i + m), Fr.mul(bArr[idx], beta)); - - quotient.setCoef(i, bArr[idx]); - } - } - - this.coef = quotient.coef; - } - - divByVanishing(n, beta) { - if (this.degree() < n) { - throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); - } - - const Fr = this.Fr; - - let polR = new Polynomial(this.coef, this.curve, this.logger); - - this.coef = this.length() > 2 << 14 ? - new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); - - for (let i = this.length() - 1; i >= n; i--) { - let leadingCoef = polR.getCoef(i); - if (Fr.eq(Fr.zero, leadingCoef)) continue; - - polR.setCoef(i, Fr.zero); - polR.setCoef(i - n, Fr.add(polR.getCoef(i - n), Fr.mul(beta, leadingCoef))); - this.setCoef(i - n, Fr.add(this.getCoef(i - n), leadingCoef)); - } - - return polR; - } - - divByVanishing2(m, beta) { - if (this.degree() < m) { - throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); - } - - const Fr = this.Fr; - - let polR = new Polynomial(this.coef, this.curve, this.logger); - - this.coef = this.length() > 2 << 14 ? - new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); - - let nThreads = 3; - let nTotal = this.length() - m; - let nElementsChunk = Math.floor(nTotal / nThreads); - let nElementsLast = nTotal - (nThreads - 1) * nElementsChunk; - - console.log(nTotal); - console.log(nElementsChunk + " " + nElementsLast); - for (let k = 0; k < nThreads; k++) { - console.log("> Thread " + k); - for (let i = (k === 0 ? nElementsLast : nElementsChunk); i > 0; i--) { - let idxDst = i - 1; - if (k !== 0) idxDst += (k - 1) * nElementsChunk + nElementsLast; - let idxSrc = idxDst + m; - - let leadingCoef = polR.getCoef(idxSrc); - if (Fr.eq(Fr.zero, leadingCoef)) continue; - - polR.setCoef(idxSrc, Fr.zero); - polR.setCoef(idxDst, Fr.add(polR.getCoef(idxDst), Fr.mul(beta, leadingCoef))); - this.setCoef(idxDst, Fr.add(this.getCoef(idxDst), leadingCoef)); - console.log(idxDst + " <-- " + idxSrc); - } - } - - this.print(); - return polR; - } - - fastDivByVanishing(data) { - const Fr = this.Fr; - - for (let i = 0; i < data.length; i++) { - - let m = data[i][0]; - let beta = data[i][1]; - - if (this.degree() < m) { - throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); - } - - let nThreads = 5; - let nElements = this.length() - m; - let nElementsBucket = Math.floor(nElements / nThreads / m); - let nElementsChunk = nElementsBucket * m; - let nElementsLast = nElements - nThreads * nElementsChunk; - - //In C++ implementation this buffer will be allocated only once outside the loop - let polTmp = new Polynomial(this.length() > 2 << 14 ? - new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8), this.curve, this.logger); - - let ptr = this.coef; - this.coef = polTmp.coef; - polTmp.coef = ptr; - - // STEP 1: Setejar els m valors del següent bucket al chunk actual, PARALEL·LITZAR - for (let k = 0; k < nThreads; k++) { - let idx0 = (k + 1) * nElementsChunk + nElementsLast; - for (let i = 0; i < m; i++) { - this.setCoef(idx0 + i - m, polTmp.getCoef(idx0 + i)); - } - - for (let i = 0; i < nElementsChunk - m; i++) { - let offset = idx0 - i - 1; - let val = Fr.add(polTmp.getCoef(offset), Fr.mul(beta, this.getCoef(offset))); - this.setCoef(offset - m, val); - } - } - - //STEP 2: Setejar els valors del elements last NO PARAL·LELITZAR - let idx0 = nElementsLast; - let pending = nElementsLast; - for (let i = 0; i < m && pending; i++) { - this.setCoef(idx0 - i - 1, polTmp.getCoef(idx0 + m - i - 1)); - pending--; - } - - for (let i = 0; i < pending; i++) { - let offset = idx0 - i - 1; - let val = Fr.add(polTmp.getCoef(offset), Fr.mul(beta, this.getCoef(offset))); - this.setCoef(offset - m, val); - } - - //Step 3: calcular acumulats NO PARALEL·LITZAR - - let acc = []; - let betaPow = Fr.one; - for (let i = 0; i < nElementsBucket; i++) { - betaPow = Fr.mul(betaPow, beta); - } - let currentBeta = Fr.one; - - for (let k = nThreads; k > 0; k--) { - let idThread = k - 1; - let idx0 = idThread * nElementsChunk + nElementsLast; - acc[idThread] = []; - - for (let i = 0; i < m; i++) { - acc[idThread][i] = this.getCoef(idx0 + i); - - if (k !== nThreads) { - acc[idThread][i] = Fr.add(acc[idThread][i], Fr.mul(betaPow, acc[idThread + 1][i])); - } - } - currentBeta = Fr.mul(currentBeta, betaPow); - } - - //STEP 4 recalcular PARALEL·LITZAR - for (let k = 0; k < nThreads; k++) { - - let idx0 = k * nElementsChunk + nElementsLast; - let currentBeta = beta; //Quan hopassem a C++ i ho paralelitzem aquesta variable ha de ser privada - let currentM = m - 1; - - let limit = k === 0 ? nElementsLast : nElementsChunk; - for (let i = 0; i < limit; i++) { - let offset = idx0 - i - 1; - let val = Fr.add(this.getCoef(offset), Fr.mul(currentBeta, acc[k][currentM])); - - this.setCoef(offset, val); - - // To avoid modular operations in each loop... - if (currentM === 0) { - currentM = m - 1; - currentBeta = Fr.mul(currentBeta, beta); - } else { - currentM--; - } - } - } - } - } - - - // Divide polynomial by X - value - divByXSubValue(value) { - const coefs = this.length() > 2 << 14 ? - new ffjavascript.BigBuffer(this.length() * this.Fr.n8) : new Uint8Array(this.length() * this.Fr.n8); - - coefs.set(this.Fr.zero, (this.length() - 1) * this.Fr.n8); - coefs.set(this.coef.slice((this.length() - 1) * this.Fr.n8, this.length() * this.Fr.n8), (this.length() - 2) * this.Fr.n8); - for (let i = this.length() - 3; i >= 0; i--) { - let i_n8 = i * this.Fr.n8; - coefs.set( - this.Fr.add( - this.coef.slice(i_n8 + this.Fr.n8, i_n8 + 2 * this.Fr.n8), - this.Fr.mul(value, coefs.slice(i_n8 + this.Fr.n8, i_n8 + 2 * this.Fr.n8)) - ), - i * this.Fr.n8 - ); - } - if (!this.Fr.eq( - this.coef.slice(0, this.Fr.n8), - this.Fr.mul(this.Fr.neg(value), coefs.slice(0, this.Fr.n8)) - )) { - throw new Error("Polynomial does not divide"); - } - - this.coef = coefs; - } - - divZh(domainSize, extensions = 4) { - for (let i = 0; i < domainSize; i++) { - const i_n8 = i * this.Fr.n8; - this.coef.set(this.Fr.neg(this.coef.slice(i_n8, i_n8 + this.Fr.n8)), i_n8); - } - - const upperBound = this.coef.byteLength / this.Fr.n8; - for (let i = domainSize; i < upperBound; i++) { - const i_n8 = i * this.Fr.n8; - - const a = this.Fr.sub( - this.coef.slice((i - domainSize) * this.Fr.n8, (i - domainSize) * this.Fr.n8 + this.Fr.n8), - this.coef.slice(i_n8, i_n8 + this.Fr.n8) - ); - this.coef.set(a, i_n8); - if (i > (domainSize * (extensions-1) - extensions)) { - if (!this.Fr.isZero(a)) { - throw new Error("Polynomial is not divisible"); - } - } - } - - return this; - } - - divByZerofier(n, beta) { - let Fr = this.Fr; - const invBeta = Fr.inv(beta); - const invBetaNeg = Fr.neg(invBeta); - - let isOne = Fr.eq(Fr.one, invBetaNeg); - let isNegOne = Fr.eq(Fr.negone, invBetaNeg); - - if (!isOne) { - for (let i = 0; i < n; i++) { - const i_n8 = i * this.Fr.n8; - let element; - - // If invBetaNeg === -1 we'll save a multiplication changing it by a neg function call - if (isNegOne) { - element = Fr.neg(this.coef.slice(i_n8, i_n8 + this.Fr.n8)); - } else { - element = Fr.mul(invBetaNeg, this.coef.slice(i_n8, i_n8 + this.Fr.n8)); - } - - this.coef.set(element, i_n8); - } - } - - isOne = Fr.eq(Fr.one, invBeta); - isNegOne = Fr.eq(Fr.negone, invBeta); - - for (let i = n; i < this.length(); i++) { - const i_n8 = i * this.Fr.n8; - const i_prev_n8 = (i - n) * this.Fr.n8; - - let element = this.Fr.sub( - this.coef.slice(i_prev_n8, i_prev_n8 + this.Fr.n8), - this.coef.slice(i_n8, i_n8 + this.Fr.n8) - ); - - // If invBeta === 1 we'll not do anything - if(!isOne) { - // If invBeta === -1 we'll save a multiplication changing it by a neg function call - if(isNegOne) { - element = Fr.neg(element); - } else { - element = Fr.mul(invBeta, element); - } - } - - this.coef.set(element, i_n8); - - // Check if polynomial is divisible by checking if n high coefficients are zero - if (i > this.length() - n - 1) { - if (!this.Fr.isZero(element)) { - throw new Error("Polynomial is not divisible"); - } - } - } - - return this; - } - -// function divideByVanishing(f, n, p) { -// // polynomial division f(X) / (X^n - 1) with remainder -// // very cheap, 0 multiplications -// // strategy: -// // start with q(X) = 0, r(X) = f(X) -// // then start changing q, r while preserving the identity: -// // f(X) = q(X) * (X^n - 1) + r(X) -// // in every step, move highest-degree term of r into the product -// // => r eventually has degree < n and we're done -// let q = Array(f.length).fill(0n); -// let r = [...f]; -// for (let i = f.length - 1; i >= n; i--) { -// let leadingCoeff = r[i]; -// if (leadingCoeff === 0n) continue; -// r[i] = 0n; -// r[i - n] = mod(r[i - n] + leadingCoeff, p); -// q[i - n] = mod(q[i - n] + leadingCoeff, p); -// } -// return [q, r]; -// } - - byX() { - const coefs = (this.length() + 1) > 2 << 14 ? - new ffjavascript.BigBuffer(this.coef.byteLength + this.Fr.n8) : new Uint8Array(this.coef.byteLength + this.Fr.n8); - coefs.set(this.Fr.zero, 0); - coefs.set(this.coef, this.Fr.n8); - - this.coef = coefs; - } - -// Compute a new polynomial f(x^n) from f(x) -// f(x) = a_0 + a_1·x + a_2·x^2 + ... + a_j·x^j -// f(x^n) = a_0 + a_1·x^n + a_2·x^2n + ... + a_j·x^jn - static - async expX(polynomial, n, truncate = false) { - const Fr = polynomial.Fr; - - if (n < 1) { - // n == 0 not allowed because it has no sense, but if it's necessary we have to return - // a zero degree polynomial with a constant coefficient equals to the sum of all the original coefficients - throw new Error("Compute a new polynomial to a zero or negative number is not allowed"); - } else if (1 === n) { - return await Polynomial.fromEvaluations(polynomial.coef, curve, polynomial.logger); - } - - // length is the length of non-constant coefficients - // if truncate === true, the highest zero coefficients (if exist) will be removed - const length = truncate ? polynomial.degree() : (polynomial.length() - 1); - const bufferDst = (length * n + 1) > 2 << 14 ? - new ffjavascript.BigBuffer((length * n + 1) * Fr.n8) : new Uint8Array((length * n + 1) * Fr.n8); - - // Copy constant coefficient as is because is not related to x - bufferDst.set(polynomial.getCoef(0), 0); - - for (let i = 1; i <= length; i++) { - const i_sFr = i * Fr.n8; - - const coef = polynomial.getCoef(i); - bufferDst.set(coef, i_sFr * n); - } - - return new Polynomial(bufferDst, polynomial.curve, polynomial.logger); - } - - split(numPols, degPols, blindingFactors) { - if (numPols < 1) { - throw new Error(`Polynomials can't be split in ${numPols} parts`); - } else if (1 === numPols) { - return [this]; - } - - //blinding factors can be void or must have a length of numPols - 1 - if (0 !== blindingFactors.length && blindingFactors.length < numPols - 1) { - throw new Error(`Blinding factors length must be ${numPols - 1}`); - } - - const chunkByteLength = (degPols + 1) * this.Fr.n8; - let res = []; - - // Check polynomial can be split in numChunks parts of chunkSize bytes... - const numRealPols = Math.ceil((this.degree() + 1) * this.Fr.n8 / chunkByteLength); - if (numRealPols < numPols) { - //throw new Error(`Polynomial is short to be split in ${numPols} parts of ${degPols} coefficients each.`); - for (let i = numRealPols; i < numPols; i++) { - res[i] = new Polynomial(new Uint8Array(this.Fr.n8), this.curve, this.logger); - } - } - - numPols = Math.min(numPols, numRealPols); - for (let i = 0; i < numPols; i++) { - const isLast = (numPols - 1) === i; - const byteLength = isLast ? this.coef.byteLength - ((numPols - 1) * chunkByteLength) : chunkByteLength + this.Fr.n8; - - let buff = (byteLength / this.Fr.n8) > 2 << 14 ? new ffjavascript.BigBuffer(byteLength) : new Uint8Array(byteLength); - res[i] = new Polynomial(buff, this.curve, this.logger); - - const fr = i * chunkByteLength; - const to = isLast ? this.coef.byteLength : (i + 1) * chunkByteLength; - res[i].coef.set(this.coef.slice(fr, to), 0); - - // Add a blinding factor as higher degree - if (!isLast) { - res[i].coef.set(blindingFactors[i], chunkByteLength); - } - - // Sub blinding factor to the lowest degree - if (0 !== i) { - const lowestDegree = this.Fr.sub(res[i].coef.slice(0, this.Fr.n8), blindingFactors[i - 1]); - res[i].coef.set(lowestDegree, 0); - } - - if (isLast) { - res[i].truncate(); - } - } - - return res; - - // // compute t_low(X) - // let polTLow = new BigBuffer((chunkSize + 1) * n8r); - // polTLow.set(t.slice(0, zkey.domainSize * n8r), 0); - // // Add blinding scalar b_10 as a new coefficient n - // polTLow.set(ch.b[10], zkey.domainSize * n8r); - // - // // compute t_mid(X) - // let polTMid = new BigBuffer((zkey.domainSize + 1) * n8r); - // polTMid.set(t.slice(zkey.domainSize * n8r, zkey.domainSize * 2 * n8r), 0); - // // Subtract blinding scalar b_10 to the lowest coefficient of t_mid - // const lowestMid = Fr.sub(polTMid.slice(0, n8r), ch.b[10]); - // polTMid.set(lowestMid, 0); - // // Add blinding scalar b_11 as a new coefficient n - // polTMid.set(ch.b[11], zkey.domainSize * n8r); - // - // // compute t_high(X) - // let polTHigh = new BigBuffer((zkey.domainSize + 6) * n8r); - // polTHigh.set(t.slice(zkey.domainSize * 2 * n8r, (zkey.domainSize * 3 + 6) * n8r), 0); - // //Subtract blinding scalar b_11 to the lowest coefficient of t_high - // const lowestHigh = Fr.sub(polTHigh.slice(0, n8r), ch.b[11]); - // polTHigh.set(lowestHigh, 0); - // - // proof.T1 = await expTau(polTLow, "multiexp T1"); - // proof.T2 = await expTau(polTMid, "multiexp T2"); - // proof.T3 = await expTau(polTHigh, "multiexp T3"); - } - -// split2(degPols, blindingFactors) { -// let currentDegree = this.degree(); -// const numFilledPols = Math.ceil((currentDegree + 1) / (degPols + 1)); -// -// //blinding factors can be void or must have a length of numPols - 1 -// if (0 !== blindingFactors.length && blindingFactors.length < numFilledPols - 1) { -// throw new Error(`Blinding factors length must be ${numFilledPols - 1}`); -// } -// -// const chunkByteLength = (degPols + 1) * this.Fr.n8; -// -// // Check polynomial can be split in numChunks parts of chunkSize bytes... -// if (this.coef.byteLength / chunkByteLength <= numFilledPols - 1) { -// throw new Error(`Polynomial is short to be split in ${numFilledPols} parts of ${degPols} coefficients each.`); -// } -// -// let res = []; -// for (let i = 0; i < numFilledPols; i++) { -// const isLast = (numFilledPols - 1) === i; -// const byteLength = isLast ? (currentDegree + 1) * this.Fr.n8 - ((numFilledPols - 1) * chunkByteLength) : chunkByteLength + this.Fr.n8; -// -// res[i] = new Polynomial(new BigBuffer(byteLength), this.Fr, this.logger); -// const fr = i * chunkByteLength; -// const to = isLast ? (currentDegree + 1) * this.Fr.n8 : (i + 1) * chunkByteLength; -// res[i].coef.set(this.coef.slice(fr, to), 0); -// -// // Add a blinding factor as higher degree -// if (!isLast) { -// res[i].coef.set(blindingFactors[i], chunkByteLength); -// } -// -// // Sub blinding factor to the lowest degree -// if (0 !== i) { -// const lowestDegree = this.Fr.sub(res[i].coef.slice(0, this.Fr.n8), blindingFactors[i - 1]); -// res[i].coef.set(lowestDegree, 0); -// } -// } -// -// return res; -// } - -// merge(pols, overlap = true) { -// let length = 0; -// for (let i = 0; i < pols.length; i++) { -// length += pols[i].length(); -// } -// -// if (overlap) { -// length -= pols.length - 1; -// } -// -// let res = new Polynomial(new BigBuffer(length * this.Fr.n8)); -// for (let i = 0; i < pols.length; i++) { -// const byteLength = pols[i].coef.byteLength; -// if (0 === i) { -// res.coef.set(pols[i].coef, 0); -// } else { -// -// } -// } -// -// return res; -// } - - truncate() { - const deg = this.degree(); - if (deg + 1 < this.coef.byteLength / this.Fr.n8) { - const newCoefs = (deg + 1) > 2 << 14 ? - new ffjavascript.BigBuffer((deg + 1) * this.Fr.n8) : new Uint8Array((deg + 1) * this.Fr.n8); - - newCoefs.set(this.coef.slice(0, (deg + 1) * this.Fr.n8), 0); - this.coef = newCoefs; - } - } - - static lagrangePolynomialInterpolation(xArr, yArr, curve) { - const Fr = curve.Fr; - let polynomial = computeLagrangePolynomial(0); - for (let i = 1; i < xArr.length; i++) { - polynomial.add(computeLagrangePolynomial(i)); - } - - return polynomial; - - function computeLagrangePolynomial(i) { - let polynomial; - - for (let j = 0; j < xArr.length; j++) { - if (j === i) continue; - - if (polynomial === undefined) { - let buff = (xArr.length) > 2 << 14 ? - new ffjavascript.BigBuffer((xArr.length) * Fr.n8) : new Uint8Array((xArr.length) * Fr.n8); - polynomial = new Polynomial(buff, curve); - polynomial.setCoef(0, Fr.neg(xArr[j])); - polynomial.setCoef(1, Fr.one); - } else { - polynomial.byXSubValue(xArr[j]); - } - } - - let denominator = polynomial.evaluate(xArr[i]); - denominator = Fr.inv(denominator); - const mulFactor = Fr.mul(yArr[i], denominator); - - polynomial.mulScalar(mulFactor); - - return polynomial; - } - } - - static zerofierPolynomial(xArr, curve) { - const Fr = curve.Fr; - let buff = (xArr.length + 1) > 2 << 14 ? - new ffjavascript.BigBuffer((xArr.length + 1) * Fr.n8) : new Uint8Array((xArr.length + 1) * Fr.n8); - let polynomial = new Polynomial(buff, curve); - - // Build a zerofier polynomial with the following form: - // zerofier(X) = (X-xArr[0])(X-xArr[1])...(X-xArr[n]) - polynomial.setCoef(0, Fr.neg(xArr[0])); - polynomial.setCoef(1, Fr.one); - - for (let i = 1; i < xArr.length; i++) { - polynomial.byXSubValue(xArr[i]); - } - - return polynomial; - } - - print() { - const Fr = this.Fr; - let res = ""; - for (let i = this.degree(); i >= 0; i--) { - const coef = this.getCoef(i); - if (!Fr.eq(Fr.zero, coef)) { - if (Fr.isNegative(coef)) { - res += " - "; - } else if (i !== this.degree()) { - res += " + "; - } - res += Fr.toString(coef); - if (i > 0) { - res += i > 1 ? "x^" + i : "x"; - } - } - } - console.log(res); - } - - async multiExponentiation(PTau, name) { - const n = this.coef.byteLength / this.Fr.n8; - const PTauN = PTau.slice(0, n * this.G1.F.n8 * 2); - const bm = await this.Fr.batchFromMontgomery(this.coef); - let res = await this.G1.multiExpAffine(PTauN, bm, this.logger, name); - res = this.G1.toAffine(res); - return res; - } -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -class Evaluations { - constructor(evaluations, curve, logger) { - this.eval = evaluations; - this.curve = curve; - this.Fr = curve.Fr; - this.logger = logger; - } - - static async fromPolynomial(polynomial, extension, curve, logger) { - const coefficientsN = new ffjavascript.BigBuffer(polynomial.length() * extension * curve.Fr.n8); - coefficientsN.set(polynomial.coef, 0); - - const evaluations = await curve.Fr.fft(coefficientsN); - - return new Evaluations(evaluations, curve, logger); - } - - getEvaluation(index) { - const i_n8 = index * this.Fr.n8; - - if (i_n8 + this.Fr.n8 > this.eval.byteLength) { - throw new Error("Evaluations.getEvaluation() out of bounds"); - } - - return this.eval.slice(i_n8, i_n8 + this.Fr.n8); - } - - length() { - let length = this.eval.byteLength / this.Fr.n8; - if (length !== Math.floor(this.eval.byteLength / this.Fr.n8)) { - throw new Error("Polynomial evaluations buffer has incorrect size"); - } - if (0 === length) { - this.logger.warn("Polynomial has length zero"); - } - return length; - } -} - -/* - Copyright 2021 0kims association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ -const {stringifyBigInts: stringifyBigInts$2} = ffjavascript.utils; - + if (globalThis.gc) globalThis.gc(); + const { fd: fdPTau, sections: sectionsPTau } = await (0, _iden3_binfileutils.readBinFile)(ptauName, "ptau", 1, 1 << 22, 1 << 24); + const { curve, power } = await readPTauHeader(fdPTau, sectionsPTau); + const { fd: fdR1cs, sections: sectionsR1cs } = await (0, _iden3_binfileutils.readBinFile)(r1csName, "r1cs", 1, 1 << 22, 1 << 24); + const r1cs = await (0, r1csfile.readR1csFd)(fdR1cs, sectionsR1cs, { + loadConstraints: true, + loadCustomGates: true + }); + const sG1 = curve.G1.F.n8 * 2; + const G1 = curve.G1; + const sG2 = curve.G2.F.n8 * 2; + const Fr = curve.Fr; + const n8r = curve.Fr.n8; + if (logger) logger.info("Reading r1cs"); + await (0, _iden3_binfileutils.readSection)(fdR1cs, sectionsR1cs, 2); + const plonkConstraints = new BigArray(); + const plonkAdditions = new BigArray(); + let plonkNVars = r1cs.nVars; + const nPublic = r1cs.nOutputs + r1cs.nPubInputs; + await processConstraints(curve.Fr, r1cs, logger); + if (globalThis.gc) globalThis.gc(); + const fdZKey = await (0, _iden3_binfileutils.createBinFile)(zkeyName, "zkey", 1, 14, 1 << 22, 1 << 24); + if (r1cs.prime != curve.r) { + if (logger) logger.error("r1cs curve does not match powers of tau ceremony curve"); + return -1; + } + let cirPower = log2(plonkConstraints.length - 1) + 1; + if (cirPower < 3) cirPower = 3; + const domainSize = 2 ** cirPower; + if (logger) logger.info("Plonk constraints: " + plonkConstraints.length); + if (cirPower > power) { + if (logger) logger.error(`circuit too big for this power of tau ceremony. ${plonkConstraints.length} > 2**${power}`); + return -1; + } + if (!sectionsPTau[12]) { + if (logger) logger.error("Powers of tau is not prepared."); + return -1; + } + const LPoints = new ffjavascript.BigBuffer(domainSize * sG1); + const o = sectionsPTau[12][0].p + (2 ** cirPower - 1) * sG1; + await fdPTau.readToBuffer(LPoints, 0, domainSize * sG1, o); + const [k1, k2] = getK1K2(); + const vk = {}; + await writeAdditions(3, "Additions"); + if (globalThis.gc) globalThis.gc(); + await writeWitnessMap(4, 0, "Amap"); + if (globalThis.gc) globalThis.gc(); + await writeWitnessMap(5, 1, "Bmap"); + if (globalThis.gc) globalThis.gc(); + await writeWitnessMap(6, 2, "Cmap"); + if (globalThis.gc) globalThis.gc(); + await writeQMap(7, 3, "Qm"); + if (globalThis.gc) globalThis.gc(); + await writeQMap(8, 4, "Ql"); + if (globalThis.gc) globalThis.gc(); + await writeQMap(9, 5, "Qr"); + if (globalThis.gc) globalThis.gc(); + await writeQMap(10, 6, "Qo"); + if (globalThis.gc) globalThis.gc(); + await writeQMap(11, 7, "Qc"); + if (globalThis.gc) globalThis.gc(); + await writeSigma(12, "sigma"); + if (globalThis.gc) globalThis.gc(); + await writeLs(13, "lagrange polynomials"); + if (globalThis.gc) globalThis.gc(); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 14); + const buffOut = new ffjavascript.BigBuffer((domainSize + 6) * sG1); + await fdPTau.readToBuffer(buffOut, 0, (domainSize + 6) * sG1, sectionsPTau[2][0].p); + await fdZKey.write(buffOut); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + if (globalThis.gc) globalThis.gc(); + await writeHeaders(); + await fdZKey.close(); + await fdR1cs.close(); + await fdPTau.close(); + if (logger) logger.info("Setup Finished"); + return; + async function processConstraints(Fr, r1cs, logger) { + function normalize(linearComb) { + const ss = Object.keys(linearComb); + for (let i = 0; i < ss.length; i++) if (linearComb[ss[i]] == 0n) delete linearComb[ss[i]]; + } + function join(linearComb1, k, linearComb2) { + const res = {}; + for (let s in linearComb1) if (typeof res[s] == "undefined") res[s] = Fr.mul(k, linearComb1[s]); + else res[s] = Fr.add(res[s], Fr.mul(k, linearComb1[s])); + for (let s in linearComb2) if (typeof res[s] == "undefined") res[s] = linearComb2[s]; + else res[s] = Fr.add(res[s], linearComb2[s]); + normalize(res); + return res; + } + function reduceCoefs(linearComb, maxC) { + const res = { + k: Fr.zero, + s: [], + coefs: [] + }; + const cs = []; + for (let s in linearComb) if (s == 0) res.k = Fr.add(res.k, linearComb[s]); + else if (linearComb[s] != 0n) cs.push([Number(s), linearComb[s]]); + while (cs.length > maxC) { + const c1 = cs.shift(); + const c2 = cs.shift(); + const sl = c1[0]; + const sr = c2[0]; + const so = plonkNVars++; + const qm = Fr.zero; + const ql = Fr.neg(c1[1]); + const qr = Fr.neg(c2[1]); + const qo = Fr.one; + const qc = Fr.zero; + plonkConstraints.push([ + sl, + sr, + so, + qm, + ql, + qr, + qo, + qc + ]); + plonkAdditions.push([ + sl, + sr, + c1[1], + c2[1] + ]); + cs.push([so, Fr.one]); + } + for (let i = 0; i < cs.length; i++) { + res.s[i] = cs[i][0]; + res.coefs[i] = cs[i][1]; + } + while (res.coefs.length < maxC) { + res.s.push(0); + res.coefs.push(Fr.zero); + } + return res; + } + function addConstraintSum(lc) { + const C = reduceCoefs(lc, 3); + const sl = C.s[0]; + const sr = C.s[1]; + const so = C.s[2]; + const qm = Fr.zero; + const ql = C.coefs[0]; + const qr = C.coefs[1]; + const qo = C.coefs[2]; + const qc = C.k; + plonkConstraints.push([ + sl, + sr, + so, + qm, + ql, + qr, + qo, + qc + ]); + } + function addConstraintMul(lcA, lcB, lcC) { + const A = reduceCoefs(lcA, 1); + const B = reduceCoefs(lcB, 1); + const C = reduceCoefs(lcC, 1); + const sl = A.s[0]; + const sr = B.s[0]; + const so = C.s[0]; + const qm = Fr.mul(A.coefs[0], B.coefs[0]); + const ql = Fr.mul(A.coefs[0], B.k); + const qr = Fr.mul(A.k, B.coefs[0]); + const qo = Fr.neg(C.coefs[0]); + const qc = Fr.sub(Fr.mul(A.k, B.k), C.k); + plonkConstraints.push([ + sl, + sr, + so, + qm, + ql, + qr, + qo, + qc + ]); + } + function getLinearCombinationType(lc) { + let k = Fr.zero; + let n = 0; + const ss = Object.keys(lc); + for (let i = 0; i < ss.length; i++) if (lc[ss[i]] == 0n) delete lc[ss[i]]; + else if (ss[i] == 0) k = Fr.add(k, lc[ss[i]]); + else n++; + if (n > 0) return n.toString(); + if (k != Fr.zero) return "k"; + return "0"; + } + function process(lcA, lcB, lcC) { + const lctA = getLinearCombinationType(lcA); + const lctB = getLinearCombinationType(lcB); + if (lctA === "0" || lctB === "0") { + normalize(lcC); + addConstraintSum(lcC); + } else if (lctA === "k") addConstraintSum(join(lcB, lcA[0], lcC)); + else if (lctB === "k") addConstraintSum(join(lcA, lcB[0], lcC)); + else addConstraintMul(lcA, lcB, lcC); + } + for (let s = 1; s <= nPublic; s++) { + const sl = s; + const sr = 0; + const so = 0; + const qm = Fr.zero; + const ql = Fr.one; + const qr = Fr.zero; + const qo = Fr.zero; + const qc = Fr.zero; + plonkConstraints.push([ + sl, + sr, + so, + qm, + ql, + qr, + qo, + qc + ]); + } + for (let c = 0; c < r1cs.constraints.length; c++) { + if (logger && c % 1e4 === 0) logger.debug(`processing constraints: ${c}/${r1cs.nConstraints}`); + process(...r1cs.constraints[c]); + } + } + async function writeWitnessMap(sectionNum, posConstraint, name) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); + for (let i = 0; i < plonkConstraints.length; i++) { + await fdZKey.writeULE32(plonkConstraints[i][posConstraint]); + if (logger && i % 1e6 == 0) logger.debug(`writing ${name}: ${i}/${plonkConstraints.length}`); + } + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeQMap(sectionNum, posConstraint, name) { + let Q = new ffjavascript.BigBuffer(domainSize * n8r); + for (let i = 0; i < plonkConstraints.length; i++) { + Q.set(plonkConstraints[i][posConstraint], i * n8r); + if (logger && i % 1e6 == 0) logger.debug(`writing ${name}: ${i}/${plonkConstraints.length}`); + } + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); + await writeP4(Q); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + Q = await Fr.batchFromMontgomery(Q); + vk[name] = await curve.G1.multiExpAffine(LPoints, Q, logger, "multiexp " + name); + } + async function writeP4(buff) { + const q = await Fr.ifft(buff); + const q4 = new ffjavascript.BigBuffer(domainSize * n8r * 4); + q4.set(q, 0); + const Q4 = await Fr.fft(q4); + await fdZKey.write(q); + await fdZKey.write(Q4); + } + async function writeAdditions(sectionNum, name) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); + const buffOut = new Uint8Array(8 + 2 * n8r); + const buffOutV = new DataView(buffOut.buffer); + for (let i = 0; i < plonkAdditions.length; i++) { + const addition = plonkAdditions[i]; + let o = 0; + buffOutV.setUint32(o, addition[0], true); + o += 4; + buffOutV.setUint32(o, addition[1], true); + o += 4; + buffOut.set(addition[2], o); + o += n8r; + buffOut.set(addition[3], o); + await fdZKey.write(buffOut); + if (logger && i % 1e6 == 0) logger.debug(`writing ${name}: ${i}/${plonkAdditions.length}`); + } + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeSigma(sectionNum, name) { + const sigma = new ffjavascript.BigBuffer(n8r * domainSize * 3); + const lastAparence = new BigArray(plonkNVars); + const firstPos = new BigArray(plonkNVars); + let w = Fr.one; + for (let i = 0; i < domainSize; i++) { + if (i < plonkConstraints.length) { + buildSigma(plonkConstraints[i][0], i); + buildSigma(plonkConstraints[i][1], domainSize + i); + buildSigma(plonkConstraints[i][2], domainSize * 2 + i); + } else { + buildSigma(0, i); + buildSigma(0, domainSize + i); + buildSigma(0, domainSize * 2 + i); + } + w = Fr.mul(w, Fr.w[cirPower]); + if (logger && i % 1e6 == 0) logger.debug(`writing ${name} phase1: ${i}/${plonkConstraints.length}`); + } + for (let s = 0; s < plonkNVars; s++) { + if (typeof firstPos[s] !== "undefined") sigma.set(lastAparence[s], firstPos[s] * n8r); + else console.log("Variable not used"); + if (logger && s % 1e6 == 0) logger.debug(`writing ${name} phase2: ${s}/${plonkNVars}`); + } + if (globalThis.gc) globalThis.gc(); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); + let S1 = sigma.slice(0, domainSize * n8r); + await writeP4(S1); + if (globalThis.gc) globalThis.gc(); + let S2 = sigma.slice(domainSize * n8r, domainSize * n8r * 2); + await writeP4(S2); + if (globalThis.gc) globalThis.gc(); + let S3 = sigma.slice(domainSize * n8r * 2, domainSize * n8r * 3); + await writeP4(S3); + if (globalThis.gc) globalThis.gc(); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + S1 = await Fr.batchFromMontgomery(S1); + S2 = await Fr.batchFromMontgomery(S2); + S3 = await Fr.batchFromMontgomery(S3); + vk.S1 = await curve.G1.multiExpAffine(LPoints, S1, logger, "multiexp S1"); + if (globalThis.gc) globalThis.gc(); + vk.S2 = await curve.G1.multiExpAffine(LPoints, S2, logger, "multiexp S2"); + if (globalThis.gc) globalThis.gc(); + vk.S3 = await curve.G1.multiExpAffine(LPoints, S3, logger, "multiexp S3"); + if (globalThis.gc) globalThis.gc(); + function buildSigma(s, p) { + if (typeof lastAparence[s] === "undefined") firstPos[s] = p; + else sigma.set(lastAparence[s], p * n8r); + let v; + if (p < domainSize) v = w; + else if (p < 2 * domainSize) v = Fr.mul(w, k1); + else v = Fr.mul(w, k2); + lastAparence[s] = v; + } + } + async function writeLs(sectionNum, name) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); + const l = Math.max(nPublic, 1); + for (let i = 0; i < l; i++) { + let buff = new ffjavascript.BigBuffer(domainSize * n8r); + buff.set(Fr.one, i * n8r); + await writeP4(buff); + if (logger) logger.debug(`writing ${name} ${i}/${l}`); + } + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeHeaders() { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 1); + await fdZKey.writeULE32(2); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 2); + const primeQ = curve.q; + const n8q = (Math.floor((ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) + 1) * 8; + const primeR = curve.r; + const n8r = (Math.floor((ffjavascript.Scalar.bitLength(primeR) - 1) / 64) + 1) * 8; + await fdZKey.writeULE32(n8q); + await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeQ, n8q); + await fdZKey.writeULE32(n8r); + await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeR, n8r); + await fdZKey.writeULE32(plonkNVars); + await fdZKey.writeULE32(nPublic); + await fdZKey.writeULE32(domainSize); + await fdZKey.writeULE32(plonkAdditions.length); + await fdZKey.writeULE32(plonkConstraints.length); + await fdZKey.write(k1); + await fdZKey.write(k2); + await fdZKey.write(G1.toAffine(vk.Qm)); + await fdZKey.write(G1.toAffine(vk.Ql)); + await fdZKey.write(G1.toAffine(vk.Qr)); + await fdZKey.write(G1.toAffine(vk.Qo)); + await fdZKey.write(G1.toAffine(vk.Qc)); + await fdZKey.write(G1.toAffine(vk.S1)); + await fdZKey.write(G1.toAffine(vk.S2)); + await fdZKey.write(G1.toAffine(vk.S3)); + let bX_2; + bX_2 = await fdPTau.read(sG2, sectionsPTau[3][0].p + sG2); + await fdZKey.write(bX_2); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + function getK1K2() { + let k1 = Fr.two; + while (isIncluded(k1, [], cirPower)) Fr.add(k1, Fr.one); + let k2 = Fr.add(k1, Fr.one); + while (isIncluded(k2, [k1], cirPower)) Fr.add(k2, Fr.one); + return [k1, k2]; + function isIncluded(k, kArr, pow) { + const domainSize = 2 ** pow; + let w = Fr.one; + for (let i = 0; i < domainSize; i++) { + if (Fr.eq(k, w)) return true; + for (let j = 0; j < kArr.length; j++) if (Fr.eq(k, Fr.mul(kArr[j], w))) return true; + w = Fr.mul(w, Fr.w[pow]); + } + return false; + } + } +} +//#endregion +//#region src/proof.js +var Proof = class { + constructor(curve, logger) { + this.curve = curve; + this.logger = logger; + this.resetProof(); + } + resetProof() { + this.polynomials = {}; + this.evaluations = {}; + } + addPolynomial(key, polynomial) { + if (key in this.polynomials) this.logger.warn(`proof: polynomial.${key} already exist in proof`); + this.polynomials[key] = polynomial; + } + getPolynomial(key) { + if (!(key in this.polynomials)) this.logger.warn(`proof: polynomial ${key} does not exist in proof`); + return this.polynomials[key]; + } + addEvaluation(key, evaluation) { + if (key in this.evaluations) this.logger.warn(`proof: evaluations.${key} already exist in proof`); + this.evaluations[key] = evaluation; + } + getEvaluation(key) { + if (!(key in this.evaluations)) this.logger.warn(`proof: evaluation ${key} does not exist in proof`); + return this.evaluations[key]; + } + toObjectProof(splitFields = true) { + let res = splitFields ? { + polynomials: {}, + evaluations: {} + } : {}; + Object.keys(this.polynomials).forEach((key) => { + const value = this.curve.G1.toObject(this.polynomials[key]); + if (splitFields) res.polynomials[key] = value; + else res[key] = value; + }); + Object.keys(this.evaluations).forEach((key) => { + const value = this.curve.Fr.toObject(this.evaluations[key]); + if (splitFields) res.evaluations[key] = value; + else res[key] = value; + }); + return res; + } + fromObjectProof(objectProof) { + this.resetProof(); + Object.keys(objectProof.polynomials).forEach((key) => { + this.polynomials[key] = this.curve.G1.fromObject(objectProof.polynomials[key]); + }); + Object.keys(objectProof.evaluations).forEach((key) => { + this.evaluations[key] = this.curve.Fr.fromObject(objectProof.evaluations[key]); + }); + } +}; +//#endregion +//#region src/Keccak256Transcript.js +var POLYNOMIAL = 0; +var SCALAR = 1; +var Keccak256Transcript = class { + constructor(curve) { + this.G1 = curve.G1; + this.Fr = curve.Fr; + this.reset(); + } + reset() { + this.data = []; + } + addPolCommitment(polynomialCommitment) { + this.data.push({ + type: POLYNOMIAL, + data: polynomialCommitment + }); + } + addScalar(scalar) { + this.data.push({ + type: SCALAR, + data: scalar + }); + } + getChallenge() { + if (0 === this.data.length) throw new Error("Keccak256Transcript: No data to generate a transcript"); + let nPolynomials = 0; + let nScalars = 0; + this.data.forEach((element) => POLYNOMIAL === element.type ? nPolynomials++ : nScalars++); + let buffer = new Uint8Array(nScalars * this.Fr.n8 + nPolynomials * this.G1.F.n8 * 2); + let offset = 0; + for (let i = 0; i < this.data.length; i++) if (POLYNOMIAL === this.data[i].type) { + this.G1.toRprUncompressed(buffer, offset, this.data[i].data); + offset += this.G1.F.n8 * 2; + } else { + this.Fr.toRprBE(buffer, offset, this.data[i].data); + offset += this.Fr.n8; + } + const value = ffjavascript.Scalar.fromRprBE((0, _noble_hashes_sha3_js.keccak_256)(buffer)); + return this.Fr.e(value); + } +}; +//#endregion +//#region src/mul_z.js +var MulZ = class { + static getZ1(Fr) { + return [ + Fr.zero, + Fr.add(Fr.e(-1), Fr.w[2]), + Fr.e(-2), + Fr.sub(Fr.e(-1), Fr.w[2]) + ]; + } + static getZ2(Fr) { + return [ + Fr.zero, + Fr.add(Fr.zero, Fr.mul(Fr.e(-2), Fr.w[2])), + Fr.e(4), + Fr.sub(Fr.zero, Fr.mul(Fr.e(-2), Fr.w[2])) + ]; + } + static getZ3(Fr) { + return [ + Fr.zero, + Fr.add(Fr.e(2), Fr.mul(Fr.e(2), Fr.w[2])), + Fr.e(-8), + Fr.sub(Fr.e(2), Fr.mul(Fr.e(2), Fr.w[2])) + ]; + } + static mul2(a, b, ap, bp, p, Fr) { + const Z1 = this.getZ1(Fr); + let r, rz; + const a_b = Fr.mul(a, b); + const a_bp = Fr.mul(a, bp); + const ap_b = Fr.mul(ap, b); + const ap_bp = Fr.mul(ap, bp); + r = a_b; + let a0 = Fr.add(a_bp, ap_b); + let a1 = ap_bp; + rz = a0; + if (p) rz = Fr.add(rz, Fr.mul(Z1[p], a1)); + return [r, rz]; + } + static mul3(a, b, c, ap, bp, cp, p, Fr) { + const Z1 = this.getZ1(Fr); + const Z2 = this.getZ2(Fr); + let r, rz; + const a_b = Fr.mul(a, b); + const a_bp = Fr.mul(a, bp); + const ap_b = Fr.mul(ap, b); + const ap_bp = Fr.mul(ap, bp); + r = Fr.mul(a_b, c); + let a0 = Fr.mul(ap_b, c); + a0 = Fr.add(a0, Fr.mul(a_bp, c)); + a0 = Fr.add(a0, Fr.mul(a_b, cp)); + let a1 = Fr.mul(ap_bp, c); + a1 = Fr.add(a1, Fr.mul(a_bp, cp)); + a1 = Fr.add(a1, Fr.mul(ap_b, cp)); + rz = a0; + if (p) { + const a2 = Fr.mul(ap_bp, cp); + rz = Fr.add(rz, Fr.mul(Z1[p], a1)); + rz = Fr.add(rz, Fr.mul(Z2[p], a2)); + } + return [r, rz]; + } + static mul4(a, b, c, d, ap, bp, cp, dp, p, Fr) { + const Z1 = this.getZ1(Fr); + const Z2 = this.getZ2(Fr); + const Z3 = this.getZ3(Fr); + let r, rz; + const a_b = Fr.mul(a, b); + const a_bp = Fr.mul(a, bp); + const ap_b = Fr.mul(ap, b); + const ap_bp = Fr.mul(ap, bp); + const c_d = Fr.mul(c, d); + const c_dp = Fr.mul(c, dp); + const cp_d = Fr.mul(cp, d); + const cp_dp = Fr.mul(cp, dp); + r = Fr.mul(a_b, c_d); + let a0 = Fr.mul(ap_b, c_d); + a0 = Fr.add(a0, Fr.mul(a_bp, c_d)); + a0 = Fr.add(a0, Fr.mul(a_b, cp_d)); + a0 = Fr.add(a0, Fr.mul(a_b, c_dp)); + let a1 = Fr.mul(ap_bp, c_d); + a1 = Fr.add(a1, Fr.mul(ap_b, cp_d)); + a1 = Fr.add(a1, Fr.mul(ap_b, c_dp)); + a1 = Fr.add(a1, Fr.mul(a_bp, cp_d)); + a1 = Fr.add(a1, Fr.mul(a_bp, c_dp)); + a1 = Fr.add(a1, Fr.mul(a_b, cp_dp)); + let a2 = Fr.mul(a_bp, cp_dp); + a2 = Fr.add(a2, Fr.mul(ap_b, cp_dp)); + a2 = Fr.add(a2, Fr.mul(ap_bp, c_dp)); + a2 = Fr.add(a2, Fr.mul(ap_bp, cp_d)); + let a3 = Fr.mul(ap_bp, cp_dp); + rz = a0; + if (p) { + rz = Fr.add(rz, Fr.mul(Z1[p], a1)); + rz = Fr.add(rz, Fr.mul(Z2[p], a2)); + rz = Fr.add(rz, Fr.mul(Z3[p], a3)); + } + return [r, rz]; + } +}; +//#endregion +//#region src/polynomial/polynomial.js +var Polynomial = class Polynomial { + constructor(coefficients, curve, logger) { + this.coef = coefficients; + this.curve = curve; + this.Fr = curve.Fr; + this.G1 = curve.G1; + this.logger = logger; + } + static async fromEvaluations(buffer, curve, logger) { + return new Polynomial(await curve.Fr.ifft(buffer), curve, logger); + } + static fromCoefficientsArray(array, curve, logger) { + const Fr = curve.Fr; + let buff = array.length > 32768 ? new ffjavascript.BigBuffer(array.length * Fr.n8) : new Uint8Array(array.length * Fr.n8); + for (let i = 0; i < array.length; i++) buff.set(array[i], i * Fr.n8); + return new Polynomial(buff, curve, logger); + } + static fromPolynomial(polynomial, curve, logger) { + let length = polynomial.length(); + let Fr = curve.Fr; + let buff = length > 32768 ? new ffjavascript.BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8); + buff.set(polynomial.coef.slice(), 0); + return new Polynomial(buff, curve, logger); + } + isEqual(polynomial) { + const degree = this.degree(); + if (degree !== polynomial.degree()) return false; + for (let i = 0; i < degree + 1; i++) if (!this.Fr.eq(this.getCoef(i), polynomial.getCoef(i))) return false; + return true; + } + blindCoefficients(blindingFactors) { + blindingFactors = blindingFactors || []; + const blindedCoefficients = this.length() + blindingFactors.length > 32768 ? new ffjavascript.BigBuffer((this.length() + blindingFactors.length) * this.Fr.n8) : new Uint8Array((this.length() + blindingFactors.length) * this.Fr.n8); + blindedCoefficients.set(this.coef, 0); + for (let i = 0; i < blindingFactors.length; i++) { + blindedCoefficients.set(this.Fr.add(blindedCoefficients.slice((this.length() + i) * this.Fr.n8, (this.length() + i + 1) * this.Fr.n8), blindingFactors[i]), (this.length() + i) * this.Fr.n8); + blindedCoefficients.set(this.Fr.sub(blindedCoefficients.slice(i * this.Fr.n8, (i + 1) * this.Fr.n8), blindingFactors[i]), i * this.Fr.n8); + } + this.coef = blindedCoefficients; + } + getCoef(index) { + const i_n8 = index * this.Fr.n8; + if (i_n8 + this.Fr.n8 > this.coef.byteLength) return this.Fr.zero; + return this.coef.slice(i_n8, i_n8 + this.Fr.n8); + } + setCoef(index, value) { + if (index > this.length() - 1) throw new Error("Coef index is not available"); + this.coef.set(value, index * this.Fr.n8); + } + static async to4T(buffer, domainSize, blindingFactors, Fr) { + blindingFactors = blindingFactors || []; + let a = await Fr.ifft(buffer); + const a4 = domainSize * 4 > 32768 ? new ffjavascript.BigBuffer(domainSize * 4 * Fr.n8) : new Uint8Array(domainSize * 4 * Fr.n8); + a4.set(a, 0); + const A4 = await Fr.fft(a4); + if (blindingFactors.length === 0) return [a, A4]; + const a1 = domainSize + blindingFactors.length > 32768 ? new ffjavascript.BigBuffer((domainSize + blindingFactors.length) * Fr.n8) : new Uint8Array((domainSize + blindingFactors.length) * Fr.n8); + a1.set(a, 0); + for (let i = 0; i < blindingFactors.length; i++) { + a1.set(Fr.add(a1.slice((domainSize + i) * Fr.n8, (domainSize + i + 1) * Fr.n8), blindingFactors[i]), (domainSize + i) * Fr.n8); + a1.set(Fr.sub(a1.slice(i * Fr.n8, (i + 1) * Fr.n8), blindingFactors[i]), i * Fr.n8); + } + return [a1, A4]; + } + length() { + let length = this.coef.byteLength / this.Fr.n8; + if (length !== Math.floor(this.coef.byteLength / this.Fr.n8)) throw new Error("Polynomial coefficients buffer has incorrect size"); + if (0 === length) { + if (this.logger) this.logger.warn("Polynomial has length zero"); + } + return length; + } + degree() { + for (let i = this.length() - 1; i > 0; i--) { + const i_n8 = i * this.Fr.n8; + if (!this.Fr.eq(this.Fr.zero, this.coef.slice(i_n8, i_n8 + this.Fr.n8))) return i; + } + return 0; + } + evaluate(point) { + let res = this.Fr.zero; + for (let i = this.degree() + 1; i > 0; i--) { + let i_n8 = i * this.Fr.n8; + const currentCoefficient = this.coef.slice(i_n8 - this.Fr.n8, i_n8); + res = this.Fr.add(currentCoefficient, this.Fr.mul(res, point)); + } + return res; + } + fastEvaluate(point) { + const Fr = this.Fr; + let nThreads = 3; + let nCoefs = this.degree() + 1; + let coefsThread = parseInt(nCoefs / nThreads); + let residualCoefs = nCoefs - coefsThread * nThreads; + let res = []; + let xN = []; + xN[0] = Fr.one; + for (let i = 0; i < nThreads; i++) { + res[i] = Fr.zero; + let nCoefs = i === nThreads - 1 ? coefsThread + residualCoefs : coefsThread; + for (let j = nCoefs; j > 0; j--) { + res[i] = Fr.add(this.getCoef(i * coefsThread + j - 1), Fr.mul(res[i], point)); + if (i === 0) xN[0] = Fr.mul(xN[0], point); + } + } + for (let i = 1; i < nThreads; i++) { + res[0] = Fr.add(res[0], Fr.mul(xN[i - 1], res[i])); + xN[i] = Fr.mul(xN[i - 1], xN[0]); + } + return res[0]; + } + add(polynomial, blindingValue) { + let other = false; + if (polynomial.length() > this.length()) other = true; + const thisLength = this.length(); + const polyLength = polynomial.length(); + for (let i = 0; i < Math.max(thisLength, polyLength); i++) { + const i_n8 = i * this.Fr.n8; + const a = i < thisLength ? this.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; + let b = i < polyLength ? polynomial.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; + if (blindingValue !== void 0) b = this.Fr.mul(b, blindingValue); + if (other) polynomial.coef.set(this.Fr.add(a, b), i_n8); + else this.coef.set(this.Fr.add(a, b), i_n8); + } + if (other) { + delete this.coef; + this.coef = polynomial.coef; + } + } + sub(polynomial, blindingValue) { + let other = false; + if (polynomial.length() > this.length()) other = true; + const thisLength = this.length(); + const polyLength = polynomial.length(); + for (let i = 0; i < Math.max(thisLength, polyLength); i++) { + const i_n8 = i * this.Fr.n8; + const a = i < thisLength ? this.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; + let b = i < polyLength ? polynomial.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; + if (blindingValue !== void 0) b = this.Fr.mul(b, blindingValue); + if (other) polynomial.coef.set(this.Fr.sub(a, b), i_n8); + else this.coef.set(this.Fr.sub(a, b), i_n8); + } + if (other) { + delete this.coef; + this.coef = polynomial.coef; + } + } + mulScalar(value) { + for (let i = 0; i < this.length(); i++) { + const i_n8 = i * this.Fr.n8; + this.coef.set(this.Fr.mul(this.coef.slice(i_n8, i_n8 + this.Fr.n8), value), i_n8); + } + } + addScalar(value) { + const currentValue = 0 === this.length() ? this.Fr.zero : this.coef.slice(0, this.Fr.n8); + this.coef.set(this.Fr.add(currentValue, value), 0); + } + subScalar(value) { + const currentValue = 0 === this.length() ? this.Fr.zero : this.coef.slice(0, this.Fr.n8); + this.coef.set(this.Fr.sub(currentValue, value), 0); + } + byXSubValue(value) { + const Fr = this.Fr; + const length = !Fr.eq(Fr.zero, this.getCoef(this.length() - 1)) ? this.length() + 1 : this.length(); + let pol = new Polynomial(length > 32768 ? new ffjavascript.BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8), this.curve, this.logger); + pol.coef.set(this.coef.slice(0, (length - 1) * Fr.n8), 32); + this.mulScalar(Fr.neg(value)); + pol.add(this); + this.coef = pol.coef; + } + byXNSubValue(n, value) { + const Fr = this.Fr; + const length = !(this.length() - n - 1 >= this.degree()) ? this.length() + n : this.length(); + let pol = new Polynomial(length > 32768 ? new ffjavascript.BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8), this.curve, this.logger); + pol.coef.set(this.coef.slice(0, (this.degree() + 1) * 32), n * 32); + this.mulScalar(value); + pol.add(this); + this.coef = pol.coef; + } + divBy(polynomial) { + const Fr = this.Fr; + const degreeA = this.degree(); + const degreeB = polynomial.degree(); + let polR = new Polynomial(this.coef, this.curve, this.logger); + this.coef = this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); + for (let i = degreeA - degreeB; i >= 0; i--) { + this.setCoef(i, Fr.div(polR.getCoef(i + degreeB), polynomial.getCoef(degreeB))); + for (let j = 0; j <= degreeB; j++) polR.setCoef(i + j, Fr.sub(polR.getCoef(i + j), Fr.mul(this.getCoef(i), polynomial.getCoef(j)))); + } + return polR; + } + divByMonic(m, beta) { + const Fr = this.Fr; + let d = this.degree(); + let quotient = new Polynomial(this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8), this.curve, this.logger); + let bArr = []; + for (let i = 0; i < m; i++) { + quotient.setCoef(d - i - m, this.getCoef(d - i)); + bArr[i] = this.getCoef(d - i); + } + let nThreads = m; + let j = 0; + for (let k = 0; k < nThreads; k++) for (let i = d - 2 * m - k; i >= 0; i = i - nThreads) { + if (i < 0) break; + let idx = k; + bArr[idx] = Fr.add(this.getCoef(i + m), Fr.mul(bArr[idx], beta)); + quotient.setCoef(i, bArr[idx]); + j = (j + 1) % m; + } + this.coef = quotient.coef; + } + divByVanishing(n, beta) { + if (this.degree() < n) throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); + const Fr = this.Fr; + let polR = new Polynomial(this.coef, this.curve, this.logger); + this.coef = this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); + for (let i = this.length() - 1; i >= n; i--) { + let leadingCoef = polR.getCoef(i); + if (Fr.eq(Fr.zero, leadingCoef)) continue; + polR.setCoef(i, Fr.zero); + polR.setCoef(i - n, Fr.add(polR.getCoef(i - n), Fr.mul(beta, leadingCoef))); + this.setCoef(i - n, Fr.add(this.getCoef(i - n), leadingCoef)); + } + return polR; + } + divByVanishing2(m, beta) { + if (this.degree() < m) throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); + const Fr = this.Fr; + let polR = new Polynomial(this.coef, this.curve, this.logger); + this.coef = this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); + let nThreads = 3; + let nTotal = this.length() - m; + let nElementsChunk = Math.floor(nTotal / nThreads); + let nElementsLast = nTotal - (nThreads - 1) * nElementsChunk; + console.log(nTotal); + console.log(nElementsChunk + " " + nElementsLast); + for (let k = 0; k < nThreads; k++) { + console.log("> Thread " + k); + for (let i = k === 0 ? nElementsLast : nElementsChunk; i > 0; i--) { + let idxDst = i - 1; + if (k !== 0) idxDst += (k - 1) * nElementsChunk + nElementsLast; + let idxSrc = idxDst + m; + let leadingCoef = polR.getCoef(idxSrc); + if (Fr.eq(Fr.zero, leadingCoef)) continue; + polR.setCoef(idxSrc, Fr.zero); + polR.setCoef(idxDst, Fr.add(polR.getCoef(idxDst), Fr.mul(beta, leadingCoef))); + this.setCoef(idxDst, Fr.add(this.getCoef(idxDst), leadingCoef)); + console.log(idxDst + " <-- " + idxSrc); + } + } + this.print(); + return polR; + } + fastDivByVanishing(data) { + const Fr = this.Fr; + for (let i = 0; i < data.length; i++) { + let m = data[i][0]; + let beta = data[i][1]; + if (this.degree() < m) throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); + let nThreads = 5; + let nElements = this.length() - m; + let nElementsBucket = Math.floor(nElements / nThreads / m); + let nElementsChunk = nElementsBucket * m; + let nElementsLast = nElements - nThreads * nElementsChunk; + let polTmp = new Polynomial(this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8), this.curve, this.logger); + let ptr = this.coef; + this.coef = polTmp.coef; + polTmp.coef = ptr; + for (let k = 0; k < nThreads; k++) { + let idx0 = (k + 1) * nElementsChunk + nElementsLast; + for (let i = 0; i < m; i++) this.setCoef(idx0 + i - m, polTmp.getCoef(idx0 + i)); + for (let i = 0; i < nElementsChunk - m; i++) { + let offset = idx0 - i - 1; + let val = Fr.add(polTmp.getCoef(offset), Fr.mul(beta, this.getCoef(offset))); + this.setCoef(offset - m, val); + } + } + let idx0 = nElementsLast; + let pending = nElementsLast; + for (let i = 0; i < m && pending; i++) { + this.setCoef(idx0 - i - 1, polTmp.getCoef(idx0 + m - i - 1)); + pending--; + } + for (let i = 0; i < pending; i++) { + let offset = idx0 - i - 1; + let val = Fr.add(polTmp.getCoef(offset), Fr.mul(beta, this.getCoef(offset))); + this.setCoef(offset - m, val); + } + let acc = []; + let betaPow = Fr.one; + for (let i = 0; i < nElementsBucket; i++) betaPow = Fr.mul(betaPow, beta); + let currentBeta = Fr.one; + for (let k = nThreads; k > 0; k--) { + let idThread = k - 1; + let idx0 = idThread * nElementsChunk + nElementsLast; + acc[idThread] = []; + for (let i = 0; i < m; i++) { + acc[idThread][i] = this.getCoef(idx0 + i); + if (k !== nThreads) acc[idThread][i] = Fr.add(acc[idThread][i], Fr.mul(betaPow, acc[idThread + 1][i])); + } + currentBeta = Fr.mul(currentBeta, betaPow); + } + for (let k = 0; k < nThreads; k++) { + let idx0 = k * nElementsChunk + nElementsLast; + let currentBeta = beta; + let currentM = m - 1; + let limit = k === 0 ? nElementsLast : nElementsChunk; + for (let i = 0; i < limit; i++) { + let offset = idx0 - i - 1; + let val = Fr.add(this.getCoef(offset), Fr.mul(currentBeta, acc[k][currentM])); + this.setCoef(offset, val); + if (currentM === 0) { + currentM = m - 1; + currentBeta = Fr.mul(currentBeta, beta); + } else currentM--; + } + } + } + } + divByXSubValue(value) { + const coefs = this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * this.Fr.n8) : new Uint8Array(this.length() * this.Fr.n8); + coefs.set(this.Fr.zero, (this.length() - 1) * this.Fr.n8); + coefs.set(this.coef.slice((this.length() - 1) * this.Fr.n8, this.length() * this.Fr.n8), (this.length() - 2) * this.Fr.n8); + for (let i = this.length() - 3; i >= 0; i--) { + let i_n8 = i * this.Fr.n8; + coefs.set(this.Fr.add(this.coef.slice(i_n8 + this.Fr.n8, i_n8 + 2 * this.Fr.n8), this.Fr.mul(value, coefs.slice(i_n8 + this.Fr.n8, i_n8 + 2 * this.Fr.n8))), i * this.Fr.n8); + } + if (!this.Fr.eq(this.coef.slice(0, this.Fr.n8), this.Fr.mul(this.Fr.neg(value), coefs.slice(0, this.Fr.n8)))) throw new Error("Polynomial does not divide"); + this.coef = coefs; + } + divZh(domainSize, extensions = 4) { + for (let i = 0; i < domainSize; i++) { + const i_n8 = i * this.Fr.n8; + this.coef.set(this.Fr.neg(this.coef.slice(i_n8, i_n8 + this.Fr.n8)), i_n8); + } + const upperBound = this.coef.byteLength / this.Fr.n8; + for (let i = domainSize; i < upperBound; i++) { + const i_n8 = i * this.Fr.n8; + const a = this.Fr.sub(this.coef.slice((i - domainSize) * this.Fr.n8, (i - domainSize) * this.Fr.n8 + this.Fr.n8), this.coef.slice(i_n8, i_n8 + this.Fr.n8)); + this.coef.set(a, i_n8); + if (i > domainSize * (extensions - 1) - extensions) { + if (!this.Fr.isZero(a)) throw new Error("Polynomial is not divisible"); + } + } + return this; + } + divByZerofier(n, beta) { + let Fr = this.Fr; + const invBeta = Fr.inv(beta); + const invBetaNeg = Fr.neg(invBeta); + let isOne = Fr.eq(Fr.one, invBetaNeg); + let isNegOne = Fr.eq(Fr.negone, invBetaNeg); + if (!isOne) for (let i = 0; i < n; i++) { + const i_n8 = i * this.Fr.n8; + let element; + if (isNegOne) element = Fr.neg(this.coef.slice(i_n8, i_n8 + this.Fr.n8)); + else element = Fr.mul(invBetaNeg, this.coef.slice(i_n8, i_n8 + this.Fr.n8)); + this.coef.set(element, i_n8); + } + isOne = Fr.eq(Fr.one, invBeta); + isNegOne = Fr.eq(Fr.negone, invBeta); + for (let i = n; i < this.length(); i++) { + const i_n8 = i * this.Fr.n8; + const i_prev_n8 = (i - n) * this.Fr.n8; + let element = this.Fr.sub(this.coef.slice(i_prev_n8, i_prev_n8 + this.Fr.n8), this.coef.slice(i_n8, i_n8 + this.Fr.n8)); + if (!isOne) if (isNegOne) element = Fr.neg(element); + else element = Fr.mul(invBeta, element); + this.coef.set(element, i_n8); + if (i > this.length() - n - 1) { + if (!this.Fr.isZero(element)) throw new Error("Polynomial is not divisible"); + } + } + return this; + } + byX() { + const coefs = this.length() + 1 > 32768 ? new ffjavascript.BigBuffer(this.coef.byteLength + this.Fr.n8) : new Uint8Array(this.coef.byteLength + this.Fr.n8); + coefs.set(this.Fr.zero, 0); + coefs.set(this.coef, this.Fr.n8); + this.coef = coefs; + } + static async expX(polynomial, n, truncate = false) { + const Fr = polynomial.Fr; + if (n < 1) throw new Error("Compute a new polynomial to a zero or negative number is not allowed"); + else if (1 === n) return await Polynomial.fromEvaluations(polynomial.coef, polynomial.curve, polynomial.logger); + const length = truncate ? polynomial.degree() : polynomial.length() - 1; + const bufferDst = length * n + 1 > 32768 ? new ffjavascript.BigBuffer((length * n + 1) * Fr.n8) : new Uint8Array((length * n + 1) * Fr.n8); + bufferDst.set(polynomial.getCoef(0), 0); + for (let i = 1; i <= length; i++) { + const i_sFr = i * Fr.n8; + const coef = polynomial.getCoef(i); + bufferDst.set(coef, i_sFr * n); + } + return new Polynomial(bufferDst, polynomial.curve, polynomial.logger); + } + split(numPols, degPols, blindingFactors) { + if (numPols < 1) throw new Error(`Polynomials can't be split in ${numPols} parts`); + else if (1 === numPols) return [this]; + if (0 !== blindingFactors.length && blindingFactors.length < numPols - 1) throw new Error(`Blinding factors length must be ${numPols - 1}`); + const chunkByteLength = (degPols + 1) * this.Fr.n8; + let res = []; + const numRealPols = Math.ceil((this.degree() + 1) * this.Fr.n8 / chunkByteLength); + if (numRealPols < numPols) for (let i = numRealPols; i < numPols; i++) res[i] = new Polynomial(new Uint8Array(this.Fr.n8), this.curve, this.logger); + numPols = Math.min(numPols, numRealPols); + for (let i = 0; i < numPols; i++) { + const isLast = numPols - 1 === i; + const byteLength = isLast ? this.coef.byteLength - (numPols - 1) * chunkByteLength : chunkByteLength + this.Fr.n8; + res[i] = new Polynomial(byteLength / this.Fr.n8 > 32768 ? new ffjavascript.BigBuffer(byteLength) : new Uint8Array(byteLength), this.curve, this.logger); + const fr = i * chunkByteLength; + const to = isLast ? this.coef.byteLength : (i + 1) * chunkByteLength; + res[i].coef.set(this.coef.slice(fr, to), 0); + if (!isLast) res[i].coef.set(blindingFactors[i], chunkByteLength); + if (0 !== i) { + const lowestDegree = this.Fr.sub(res[i].coef.slice(0, this.Fr.n8), blindingFactors[i - 1]); + res[i].coef.set(lowestDegree, 0); + } + if (isLast) res[i].truncate(); + } + return res; + } + truncate() { + const deg = this.degree(); + if (deg + 1 < this.coef.byteLength / this.Fr.n8) { + const newCoefs = deg + 1 > 32768 ? new ffjavascript.BigBuffer((deg + 1) * this.Fr.n8) : new Uint8Array((deg + 1) * this.Fr.n8); + newCoefs.set(this.coef.slice(0, (deg + 1) * this.Fr.n8), 0); + this.coef = newCoefs; + } + } + static lagrangePolynomialInterpolation(xArr, yArr, curve) { + const Fr = curve.Fr; + let polynomial = computeLagrangePolynomial(0); + for (let i = 1; i < xArr.length; i++) polynomial.add(computeLagrangePolynomial(i)); + return polynomial; + function computeLagrangePolynomial(i) { + let polynomial; + for (let j = 0; j < xArr.length; j++) { + if (j === i) continue; + if (polynomial === void 0) { + polynomial = new Polynomial(xArr.length > 32768 ? new ffjavascript.BigBuffer(xArr.length * Fr.n8) : new Uint8Array(xArr.length * Fr.n8), curve); + polynomial.setCoef(0, Fr.neg(xArr[j])); + polynomial.setCoef(1, Fr.one); + } else polynomial.byXSubValue(xArr[j]); + } + let denominator = polynomial.evaluate(xArr[i]); + denominator = Fr.inv(denominator); + const mulFactor = Fr.mul(yArr[i], denominator); + polynomial.mulScalar(mulFactor); + return polynomial; + } + } + static zerofierPolynomial(xArr, curve) { + const Fr = curve.Fr; + let polynomial = new Polynomial(xArr.length + 1 > 32768 ? new ffjavascript.BigBuffer((xArr.length + 1) * Fr.n8) : new Uint8Array((xArr.length + 1) * Fr.n8), curve); + polynomial.setCoef(0, Fr.neg(xArr[0])); + polynomial.setCoef(1, Fr.one); + for (let i = 1; i < xArr.length; i++) polynomial.byXSubValue(xArr[i]); + return polynomial; + } + print() { + const Fr = this.Fr; + let res = ""; + for (let i = this.degree(); i >= 0; i--) { + const coef = this.getCoef(i); + if (!Fr.eq(Fr.zero, coef)) { + if (Fr.isNegative(coef)) res += " - "; + else if (i !== this.degree()) res += " + "; + res += Fr.toString(coef); + if (i > 0) res += i > 1 ? "x^" + i : "x"; + } + } + console.log(res); + } + async multiExponentiation(PTau, name) { + const n = this.coef.byteLength / this.Fr.n8; + const PTauN = PTau.slice(0, n * this.G1.F.n8 * 2); + const bm = await this.Fr.batchFromMontgomery(this.coef); + let res = await this.G1.multiExpAffine(PTauN, bm, this.logger, name); + res = this.G1.toAffine(res); + return res; + } +}; +//#endregion +//#region src/polynomial/evaluations.js +var Evaluations = class Evaluations { + constructor(evaluations, curve, logger) { + this.eval = evaluations; + this.curve = curve; + this.Fr = curve.Fr; + this.logger = logger; + } + static async fromPolynomial(polynomial, extension, curve, logger) { + const coefficientsN = new ffjavascript.BigBuffer(polynomial.length() * extension * curve.Fr.n8); + coefficientsN.set(polynomial.coef, 0); + return new Evaluations(await curve.Fr.fft(coefficientsN), curve, logger); + } + getEvaluation(index) { + const i_n8 = index * this.Fr.n8; + if (i_n8 + this.Fr.n8 > this.eval.byteLength) throw new Error("Evaluations.getEvaluation() out of bounds"); + return this.eval.slice(i_n8, i_n8 + this.Fr.n8); + } + length() { + let length = this.eval.byteLength / this.Fr.n8; + if (length !== Math.floor(this.eval.byteLength / this.Fr.n8)) throw new Error("Polynomial evaluations buffer has incorrect size"); + if (0 === length) this.logger.warn("Polynomial has length zero"); + return length; + } +}; +//#endregion +//#region src/plonk_prove.js +var { stringifyBigInts: stringifyBigInts$2 } = ffjavascript.utils; async function plonk16Prove(zkeyFileName, witnessFileName, logger, options) { - const {fd: fdWtns, sections: sectionsWtns} = await binFileUtils__namespace.readBinFile(witnessFileName, "wtns", 2, 1<<25, 1<<23); - - // Read witness file - if (logger) logger.debug("> Reading witness file"); - const wtns = await readHeader(fdWtns, sectionsWtns); - - // Read zkey file - if (logger) logger.debug("> Reading zkey file"); - const {fd: fdZKey, sections: zkeySections} = await binFileUtils__namespace.readBinFile(zkeyFileName, "zkey", 2, 1<<25, 1<<23); - - const zkey = await readHeader$1(fdZKey, zkeySections, undefined, options); - if (zkey.protocol != "plonk") { - throw new Error("zkey file is not plonk"); - } - - if (!ffjavascript.Scalar.eq(zkey.r, wtns.q)) { - throw new Error("Curve of the witness does not match the curve of the proving key"); - } - - if (wtns.nWitness != zkey.nVars -zkey.nAdditions) { - throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}, ${zkey.nAdditions}`); - } - - const curve = zkey.curve; - - const Fr = curve.Fr; - const n8r = curve.Fr.n8; - const sDomain = zkey.domainSize * n8r; - - if (logger) { - logger.debug("----------------------------"); - logger.debug(" PLONK PROVE SETTINGS"); - logger.debug(` Curve: ${curve.name}`); - logger.debug(` Circuit power: ${zkey.power}`); - logger.debug(` Domain size: ${zkey.domainSize}`); - logger.debug(` Vars: ${zkey.nVars}`); - logger.debug(` Public vars: ${zkey.nPublic}`); - logger.debug(` Constraints: ${zkey.nConstraints}`); - logger.debug(` Additions: ${zkey.nAdditions}`); - logger.debug("----------------------------"); - } - - //Read witness data - if (logger) logger.debug("> Reading witness file data"); - const buffWitness = await binFileUtils__namespace.readSection(fdWtns, sectionsWtns, 2); - - // First element in plonk is not used and can be any value. (But always the same). - // We set it to zero to go faster in the exponentiations. - buffWitness.set(Fr.zero, 0); - const buffInternalWitness = new ffjavascript.BigBuffer(n8r*zkey.nAdditions); - - let buffers = {}; - let polynomials = {}; - let evaluations = {}; - - let challenges = {}; - let proof = new Proof(curve, logger); - const transcript = new Keccak256Transcript(curve); - - if (logger) logger.debug(`> Reading Section ${ZKEY_PL_ADDITIONS_SECTION}. Additions`); - await calculateAdditions(); - - if (logger) logger.debug(`> Reading Section ${ZKEY_PL_SIGMA_SECTION}. Sigma1, Sigma2 & Sigma 3`); - if (logger) logger.debug("··· Reading Sigma polynomials "); - polynomials.Sigma1 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.Sigma2 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.Sigma3 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - - await fdZKey.readToBuffer(polynomials.Sigma1.coef, 0, sDomain, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.Sigma2.coef, 0, sDomain, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p + 5 * sDomain); - await fdZKey.readToBuffer(polynomials.Sigma3.coef, 0, sDomain, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p + 10 * sDomain); - - if (logger) logger.debug("··· Reading Sigma evaluations"); - evaluations.Sigma1 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.Sigma2 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.Sigma3 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - - await fdZKey.readToBuffer(evaluations.Sigma1.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.Sigma2.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p + 6 * sDomain); - await fdZKey.readToBuffer(evaluations.Sigma3.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p + 11 * sDomain); - - if (logger) logger.debug(`> Reading Section ${ZKEY_PL_PTAU_SECTION}. Powers of Tau`); - const PTau = await binFileUtils__namespace.readSection(fdZKey, zkeySections, ZKEY_PL_PTAU_SECTION); - - let publicSignals = []; - - for (let i=1; i<= zkey.nPublic; i++) { - const pub = buffWitness.slice(i*Fr.n8, i*Fr.n8+Fr.n8); - publicSignals.push(ffjavascript.Scalar.fromRprLE(pub)); - } - - if (logger) logger.debug(""); - if (logger) logger.debug("> ROUND 1"); - await round1(); - - if (logger) logger.debug("> ROUND 2"); - await round2(); - - if (logger) logger.debug("> ROUND 3"); - await round3(); - - if (logger) logger.debug("> ROUND 4"); - await round4(); - - if (logger) logger.debug("> ROUND 5"); - await round5(); - - /////////////////////// - // Final adjustments // - /////////////////////// - - await fdZKey.close(); - await fdWtns.close(); - - // Prepare proof - let _proof = proof.toObjectProof(false); - _proof.protocol = "plonk"; - _proof.curve = curve.name; - - if (logger) logger.debug("PLONK PROVER FINISHED"); - - return { - proof: stringifyBigInts$2(_proof), - publicSignals: stringifyBigInts$2(publicSignals) - }; - - async function calculateAdditions() { - if (logger) logger.debug("··· Computing additions"); - const additionsBuff = await binFileUtils__namespace.readSection(fdZKey, zkeySections, ZKEY_PL_ADDITIONS_SECTION); - - // sizes: wireId_x = 4 bytes (32 bits), factor_x = field size bits - // Addition form: wireId_a wireId_b factor_a factor_b (size is 4 + 4 + sFr + sFr) - const sSum = 8 + n8r * 2; - - for (let i = 0; i < zkey.nAdditions; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.debug(` addition ${i}/${zkey.nAdditions}`); - - // Read addition values - let offset = i * sSum; - const signalId1 = readUInt32(additionsBuff, offset); - offset += 4; - const signalId2 = readUInt32(additionsBuff, offset); - offset += 4; - const factor1 = additionsBuff.slice(offset, offset + n8r); - offset += n8r; - const factor2 = additionsBuff.slice(offset, offset + n8r); - - // Get witness value - const witness1 = getWitness(signalId1); - const witness2 = getWitness(signalId2); - - //Calculate final result - const result = Fr.add(Fr.mul(factor1, witness1), Fr.mul(factor2, witness2)); - - buffInternalWitness.set(result, n8r * i); - } - } - - function readUInt32(b, o) { - const buff = b.slice(o, o+4); - const buffV = new DataView(buff.buffer, buff.byteOffset, buff.byteLength); - return buffV.getUint32(0, true); - } - - function getWitness(idx) { - if (idx < zkey.nVars-zkey.nAdditions) { - return buffWitness.slice(idx*n8r, idx*n8r+n8r); - } else if (idx < zkey.nVars) { - return buffInternalWitness.slice((idx - (zkey.nVars-zkey.nAdditions))*n8r, (idx-(zkey.nVars-zkey.nAdditions))*n8r + n8r); - } else { - return curve.Fr.zero; - } - } - - async function round1() { - // STEP 1.1 - Generate random blinding scalars (b1, ..., b11) ∈ F - challenges.b = []; - for (let i=1; i<=11; i++) { - challenges.b[i] = curve.Fr.random(); - } - - // STEP 1.2 - Compute wire polynomials a(X), b(X) and c(X) - if (logger) logger.debug("> Computing A, B, C wire polynomials"); - await computeWirePolynomials(); - - // STEP 1.3 - Compute [a]_1, [b]_1, [c]_1 - if (logger) logger.debug("> Computing A, B, C MSM"); - let commitA = await polynomials.A.multiExponentiation(PTau, "A"); - let commitB = await polynomials.B.multiExponentiation(PTau, "B"); - let commitC = await polynomials.C.multiExponentiation(PTau, "C"); - - // First output of the prover is ([A]_1, [B]_1, [C]_1) - proof.addPolynomial("A", commitA); - proof.addPolynomial("B", commitB); - proof.addPolynomial("C", commitC); - - return 0; - } - - async function computeWirePolynomials() { - if (logger) logger.debug("··· Reading data from zkey file"); - - // Build A, B and C evaluations buffer from zkey and witness files - buffers.A = new ffjavascript.BigBuffer(sDomain); - buffers.B = new ffjavascript.BigBuffer(sDomain); - buffers.C = new ffjavascript.BigBuffer(sDomain); - - // Read zkey file to the buffers - const aMapBuff = await binFileUtils__namespace.readSection(fdZKey, zkeySections, ZKEY_PL_A_MAP_SECTION); - const bMapBuff = await binFileUtils__namespace.readSection(fdZKey, zkeySections, ZKEY_PL_B_MAP_SECTION); - const cMapBuff = await binFileUtils__namespace.readSection(fdZKey, zkeySections, ZKEY_PL_C_MAP_SECTION); - - // Compute all witness from signal ids and set them to A,B & C buffers - for (let i = 0; i < zkey.nConstraints; i++) { - const i_sFr = i * n8r; - const offset = i * 4; - - // Compute A value from a signal id - const signalIdA = readUInt32(aMapBuff, offset); - buffers.A.set(getWitness(signalIdA), i_sFr); - - // Compute B value from a signal id - const signalIdB = readUInt32(bMapBuff, offset); - buffers.B.set(getWitness(signalIdB), i_sFr); - - // Compute C value from a signal id - const signalIdC = readUInt32(cMapBuff, offset); - buffers.C.set(getWitness(signalIdC), i_sFr); - } - - buffers.A = await Fr.batchToMontgomery(buffers.A); - buffers.B = await Fr.batchToMontgomery(buffers.B); - buffers.C = await Fr.batchToMontgomery(buffers.C); - - // Compute the coefficients of the wire polynomials a(X), b(X) and c(X) from A,B & C buffers - if (logger) logger.debug("··· Computing A ifft"); - polynomials.A = await Polynomial.fromEvaluations(buffers.A, curve, logger); - if (logger) logger.debug("··· Computing B ifft"); - polynomials.B = await Polynomial.fromEvaluations(buffers.B, curve, logger); - if (logger) logger.debug("··· Computing C ifft"); - polynomials.C = await Polynomial.fromEvaluations(buffers.C, curve, logger); - - // Compute extended evaluations of a(X), b(X) and c(X) polynomials - if (logger) logger.debug("··· Computing A fft"); - evaluations.A = await Evaluations.fromPolynomial(polynomials.A, 4, curve, logger); - if (logger) logger.debug("··· Computing B fft"); - evaluations.B = await Evaluations.fromPolynomial(polynomials.B, 4, curve, logger); - if (logger) logger.debug("··· Computing C fft"); - evaluations.C = await Evaluations.fromPolynomial(polynomials.C, 4, curve, logger); - - // Blind a(X), b(X) and c(X) polynomials coefficients with blinding scalars b - polynomials.A.blindCoefficients([challenges.b[2], challenges.b[1]]); - polynomials.B.blindCoefficients([challenges.b[4], challenges.b[3]]); - polynomials.C.blindCoefficients([challenges.b[6], challenges.b[5]]); - - // Check degrees - if (polynomials.A.degree() >= zkey.domainSize + 2) { - throw new Error("A Polynomial is not well calculated"); - } - if (polynomials.B.degree() >= zkey.domainSize + 2) { - throw new Error("B Polynomial is not well calculated"); - } - if (polynomials.C.degree() >= zkey.domainSize + 2) { - throw new Error("C Polynomial is not well calculated"); - } - } - - async function round2() { - // STEP 2.1 - Compute permutation challenge beta and gamma ∈ F - // Compute permutation challenge beta - if (logger) logger.debug("> Computing challenges beta and gamma"); - transcript.reset(); - - transcript.addPolCommitment(zkey.Qm); - transcript.addPolCommitment(zkey.Ql); - transcript.addPolCommitment(zkey.Qr); - transcript.addPolCommitment(zkey.Qo); - transcript.addPolCommitment(zkey.Qc); - transcript.addPolCommitment(zkey.S1); - transcript.addPolCommitment(zkey.S2); - transcript.addPolCommitment(zkey.S3); - - // Add A to the transcript - for (let i = 0; i < zkey.nPublic; i++) { - transcript.addScalar(buffers.A.slice(i * n8r, i * n8r + n8r)); - } - - // Add A, B, C to the transcript - transcript.addPolCommitment(proof.getPolynomial("A")); - transcript.addPolCommitment(proof.getPolynomial("B")); - transcript.addPolCommitment(proof.getPolynomial("C")); - - challenges.beta = transcript.getChallenge(); - if (logger) logger.debug("··· challenges.beta: " + Fr.toString(challenges.beta, 16)); - - // Compute permutation challenge gamma - transcript.reset(); - transcript.addScalar(challenges.beta); - challenges.gamma = transcript.getChallenge(); - if (logger) logger.debug("··· challenges.gamma: " + Fr.toString(challenges.gamma, 16)); - - // STEP 2.2 - Compute permutation polynomial z(X) - if (logger) logger.debug("> Computing Z polynomial"); - await computeZ(); - - // STEP 2.3 - Compute permutation [z]_1 - if (logger) logger.debug("> Computing Z MSM"); - let commitZ = await polynomials.Z.multiExponentiation(PTau, "Z"); - - // Second output of the prover is ([Z]_1) - proof.addPolynomial("Z", commitZ); - } - - async function computeZ() { - if (logger) logger.debug("··· Computing Z evaluations"); - - let numArr = new ffjavascript.BigBuffer(sDomain); - let denArr = new ffjavascript.BigBuffer(sDomain); - - // Set the first values to 1 - numArr.set(Fr.one, 0); - denArr.set(Fr.one, 0); - - // Set initial omega - let w = Fr.one; - for (let i = 0; i < zkey.domainSize; i++) { - const i_n8r = i * n8r; - - const a = buffers.A.slice(i_n8r, i_n8r + n8r); - const b = buffers.B.slice(i_n8r, i_n8r + n8r); - const c = buffers.C.slice(i_n8r, i_n8r + n8r); - - // Z(X) := numArr / denArr - // numArr := (a + beta·ω + gamma)(b + beta·ω·k1 + gamma)(c + beta·ω·k2 + gamma) - const betaw = Fr.mul(challenges.beta, w); - - let n1 = Fr.add(a, betaw); - n1 = Fr.add(n1, challenges.gamma); - - let n2 = Fr.add(b, Fr.mul(zkey.k1, betaw)); - n2 = Fr.add(n2, challenges.gamma); - - let n3 = Fr.add(c, Fr.mul(zkey.k2, betaw)); - n3 = Fr.add(n3, challenges.gamma); - - let num = Fr.mul(n1, Fr.mul(n2, n3)); - - // denArr := (a + beta·sigma1 + gamma)(b + beta·sigma2 + gamma)(c + beta·sigma3 + gamma) - let d1 = Fr.add(a, Fr.mul(evaluations.Sigma1.getEvaluation(i * 4), challenges.beta)); - d1 = Fr.add(d1, challenges.gamma); - - let d2 = Fr.add(b, Fr.mul(evaluations.Sigma2.getEvaluation(i * 4), challenges.beta)); - d2 = Fr.add(d2, challenges.gamma); - - let d3 = Fr.add(c, Fr.mul(evaluations.Sigma3.getEvaluation(i * 4), challenges.beta)); - d3 = Fr.add(d3, challenges.gamma); - - let den = Fr.mul(d1, Fr.mul(d2, d3)); - - // Multiply current num value with the previous one saved in numArr - num = Fr.mul(numArr.slice(i_n8r, i_n8r + n8r), num); - numArr.set(num, ((i + 1) % zkey.domainSize) * n8r); - - // Multiply current den value with the previous one saved in denArr - den = Fr.mul(denArr.slice(i_n8r, i_n8r + n8r), den); - denArr.set(den, ((i + 1) % zkey.domainSize) * n8r); - - w = Fr.mul(w, Fr.w[zkey.power]); - } - - // Compute the inverse of denArr to compute in the next command the - // division numArr/denArr by multiplying num · 1/denArr - denArr = await Fr.batchInverse(denArr); - - // TODO: Do it in assembly and in parallel - // Multiply numArr · denArr where denArr was inverted in the previous command - for (let i = 0; i < zkey.domainSize; i++) { - const i_sFr = i * n8r; - - const z = Fr.mul(numArr.slice(i_sFr, i_sFr + n8r), denArr.slice(i_sFr, i_sFr + n8r)); - numArr.set(z, i_sFr); - } - - // From now on the values saved on numArr will be Z(X) buffer - buffers.Z = numArr; - - if (!Fr.eq(numArr.slice(0, n8r), Fr.one)) { - throw new Error("Copy constraints does not match"); - } - - // Compute polynomial coefficients z(X) from buffers.Z - if (logger) logger.debug("··· Computing Z ifft"); - polynomials.Z = await Polynomial.fromEvaluations(buffers.Z, curve, logger); - - // Compute extended evaluations of z(X) polynomial - if (logger) logger.debug("··· Computing Z fft"); - evaluations.Z = await Evaluations.fromPolynomial(polynomials.Z, 4, curve, logger); - - // Blind z(X) polynomial coefficients with blinding scalars b - polynomials.Z.blindCoefficients([challenges.b[9], challenges.b[8], challenges.b[7]]); - - // Check degree - if (polynomials.Z.degree() >= zkey.domainSize + 3) { - throw new Error("Z Polynomial is not well calculated"); - } - - delete buffers.Z; - } - - async function round3() { - if (logger) logger.debug("> Computing challenge alpha"); - - // STEP 3.1 - Compute evaluation challenge alpha ∈ F - transcript.reset(); - transcript.addScalar(challenges.beta); - transcript.addScalar(challenges.gamma); - transcript.addPolCommitment(proof.getPolynomial("Z")); - - challenges.alpha = transcript.getChallenge(); - challenges.alpha2 = Fr.square(challenges.alpha); - if (logger) logger.debug("··· challenges.alpha: " + Fr.toString(challenges.alpha, 16)); - - // Compute quotient polynomial T(X) - if (logger) logger.debug("> Computing T polynomial"); - await computeT(); - - // Compute [T1]_1, [T2]_1, [T3]_1 - if (logger) logger.debug("> Computing T MSM"); - let commitT1 = await polynomials.T1.multiExponentiation(PTau, "T1"); - let commitT2 = await polynomials.T2.multiExponentiation(PTau, "T2"); - let commitT3 = await polynomials.T3.multiExponentiation(PTau, "T3"); - - // Third output of the prover is ([T1]_1, [T2]_1, [T3]_1) - proof.addPolynomial("T1", commitT1); - proof.addPolynomial("T2", commitT2); - proof.addPolynomial("T3", commitT3); - } - - async function computeT() { - if (logger) - logger.debug(`··· Reading sections ${ZKEY_PL_QL_SECTION}, ${ZKEY_PL_QR_SECTION}` + - `, ${ZKEY_PL_QM_SECTION}, ${ZKEY_PL_QO_SECTION}, ${ZKEY_PL_QC_SECTION}. Q selectors`); - // Reserve memory for Q's evaluations - evaluations.QL = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QR = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QM = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QO = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QC = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - - // Read Q's evaluations from zkey file - await fdZKey.readToBuffer(evaluations.QL.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_QL_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QR.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_QR_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QM.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_QM_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QO.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_QO_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QC.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_QC_SECTION][0].p + sDomain); - - // Read Lagrange polynomials & evaluations from zkey file - evaluations.Lagrange = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4 * zkey.nPublic), curve, logger); - - for (let i = 0; i < zkey.nPublic; i++) { - await fdZKey.readToBuffer(evaluations.Lagrange.eval, i * sDomain * 4, sDomain * 4, zkeySections[ZKEY_PL_LAGRANGE_SECTION][0].p + i * 5 * sDomain + sDomain); - } - - buffers.T = new ffjavascript.BigBuffer(sDomain * 4); - buffers.Tz = new ffjavascript.BigBuffer(sDomain * 4); - - if (logger) logger.debug("··· Computing T evaluations"); - - let w = Fr.one; - for (let i = 0; i < zkey.domainSize * 4; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) - logger.debug(` T evaluation ${i}/${zkey.domainSize * 4}`); - - const a = evaluations.A.getEvaluation(i); - const b = evaluations.B.getEvaluation(i); - const c = evaluations.C.getEvaluation(i); - const z = evaluations.Z.getEvaluation(i); - const zw = evaluations.Z.getEvaluation((zkey.domainSize * 4 + 4 + i) % (zkey.domainSize * 4)); - - const qm = evaluations.QM.getEvaluation(i); - const ql = evaluations.QL.getEvaluation(i); - const qr = evaluations.QR.getEvaluation(i); - const qo = evaluations.QO.getEvaluation(i); - const qc = evaluations.QC.getEvaluation(i); - const s1 = evaluations.Sigma1.getEvaluation(i); - const s2 = evaluations.Sigma2.getEvaluation(i); - const s3 = evaluations.Sigma3.getEvaluation(i); - - const ap = Fr.add(challenges.b[2], Fr.mul(challenges.b[1], w)); - const bp = Fr.add(challenges.b[4], Fr.mul(challenges.b[3], w)); - const cp = Fr.add(challenges.b[6], Fr.mul(challenges.b[5], w)); - - const w2 = Fr.square(w); - const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], w2), Fr.mul(challenges.b[8], w)), challenges.b[9]); - const wW = Fr.mul(w, Fr.w[zkey.power]); - const wW2 = Fr.square(wW); - const zWp = Fr.add(Fr.add(Fr.mul(challenges.b[7], wW2), Fr.mul(challenges.b[8], wW)), challenges.b[9]); - - let pi = Fr.zero; - for (let j = 0; j < zkey.nPublic; j++) { - const offset = (j * 4 * zkey.domainSize) + i; - - const lPol = evaluations.Lagrange.getEvaluation(offset); - const aVal = buffers.A.slice(j * n8r, (j + 1) * n8r); - - pi = Fr.sub(pi, Fr.mul(lPol, aVal)); - } - - // e1 := a(X)b(X)qM(X) + a(X)qL(X) + b(X)qR(X) + c(X)qO(X) + PI(X) + qC(X) - let [e1, e1z] = MulZ.mul2(a, b, ap, bp, i % 4, Fr); - e1 = Fr.mul(e1, qm); - e1z = Fr.mul(e1z, qm); - - e1 = Fr.add(e1, Fr.mul(a, ql)); - e1z = Fr.add(e1z, Fr.mul(ap, ql)); - - e1 = Fr.add(e1, Fr.mul(b, qr)); - e1z = Fr.add(e1z, Fr.mul(bp, qr)); - - e1 = Fr.add(e1, Fr.mul(c, qo)); - e1z = Fr.add(e1z, Fr.mul(cp, qo)); - - e1 = Fr.add(e1, pi); - e1 = Fr.add(e1, qc); - - // e2 := α[(a(X) + βX + γ)(b(X) + βk1X + γ)(c(X) + βk2X + γ)z(X)] - const betaw = Fr.mul(challenges.beta, w); - let e2a = a; - e2a = Fr.add(e2a, betaw); - e2a = Fr.add(e2a, challenges.gamma); - - let e2b = b; - e2b = Fr.add(e2b, Fr.mul(betaw, zkey.k1)); - e2b = Fr.add(e2b, challenges.gamma); - - let e2c = c; - e2c = Fr.add(e2c, Fr.mul(betaw, zkey.k2)); - e2c = Fr.add(e2c, challenges.gamma); - - let e2d = z; - - let [e2, e2z] = MulZ.mul4(e2a, e2b, e2c, e2d, ap, bp, cp, zp, i % 4, Fr); - e2 = Fr.mul(e2, challenges.alpha); - e2z = Fr.mul(e2z, challenges.alpha); - - // e3 := α[(a(X) + βSσ1(X) + γ)(b(X) + βSσ2(X) + γ)(c(X) + βSσ3(X) + γ)z(Xω)] - let e3a = a; - e3a = Fr.add(e3a, Fr.mul(challenges.beta, s1)); - e3a = Fr.add(e3a, challenges.gamma); - - let e3b = b; - e3b = Fr.add(e3b, Fr.mul(challenges.beta, s2)); - e3b = Fr.add(e3b, challenges.gamma); - - let e3c = c; - e3c = Fr.add(e3c, Fr.mul(challenges.beta, s3)); - e3c = Fr.add(e3c, challenges.gamma); - - let e3d = zw; - let [e3, e3z] = MulZ.mul4(e3a, e3b, e3c, e3d, ap, bp, cp, zWp, i % 4, Fr); - - e3 = Fr.mul(e3, challenges.alpha); - e3z = Fr.mul(e3z, challenges.alpha); - - // e4 := α^2(z(X)−1)L1(X) - let e4 = Fr.sub(z, Fr.one); - e4 = Fr.mul(e4, evaluations.Lagrange.getEvaluation(i)); - e4 = Fr.mul(e4, challenges.alpha2); - - let e4z = Fr.mul(zp, evaluations.Lagrange.getEvaluation(i)); - e4z = Fr.mul(e4z, challenges.alpha2); - - - let t = Fr.add(Fr.sub(Fr.add(e1, e2), e3), e4); - let tz = Fr.add(Fr.sub(Fr.add(e1z, e2z), e3z), e4z); - - buffers.T.set(t, i * n8r); - buffers.Tz.set(tz, i * n8r); - - w = Fr.mul(w, Fr.w[zkey.power + 2]); - } - - // Compute the coefficients of the polynomial T0(X) from buffers.T0 - if (logger) - logger.debug("··· Computing T ifft"); - polynomials.T = await Polynomial.fromEvaluations(buffers.T, curve, logger); - - // Divide the polynomial T0 by Z_H(X) - if (logger) - logger.debug("··· Computing T / ZH"); - polynomials.T.divZh(zkey.domainSize, 4); - - // Compute the coefficients of the polynomial Tz(X) from buffers.Tz - if (logger) - logger.debug("··· Computing Tz ifft"); - polynomials.Tz = await Polynomial.fromEvaluations(buffers.Tz, curve, logger); - - // Add the polynomial T1z to T1 to get the final polynomial T1 - polynomials.T.add(polynomials.Tz); - - // Check degree - if (polynomials.T.degree() >= zkey.domainSize * 3 + 6) { - throw new Error("T Polynomial is not well calculated"); - } - - // t(x) has degree 3n + 5, we are going to split t(x) into three smaller polynomials: - // T1' and T2' with a degree < n and T3' with a degree n+5 - // such that t(x) = T1'(X) + X^n T2'(X) + X^{2n} T3'(X) - // To randomize the parts we use blinding scalars b_10 and b_11 in a way that doesn't change t(X): - // T1(X) = T1'(X) + b_10 X^n - // T2(X) = T2'(X) - b_10 + b_11 X^n - // T3(X) = T3'(X) - b_11 - // such that - // t(X) = T1(X) + X^n T2(X) + X^2n T3(X) - if (logger) logger.debug("··· Computing T1, T2, T3 polynomials"); - polynomials.T1 = new Polynomial(new ffjavascript.BigBuffer((zkey.domainSize + 1) * n8r), curve, logger); - polynomials.T2 = new Polynomial(new ffjavascript.BigBuffer((zkey.domainSize + 1) * n8r), curve, logger); - polynomials.T3 = new Polynomial(new ffjavascript.BigBuffer((zkey.domainSize + 6) * n8r), curve, logger); - - polynomials.T1.coef.set(polynomials.T.coef.slice(0, sDomain), 0); - polynomials.T2.coef.set(polynomials.T.coef.slice(sDomain, sDomain * 2), 0); - polynomials.T3.coef.set(polynomials.T.coef.slice(sDomain * 2, sDomain * 3 + 6 * n8r), 0); - - // Add blinding scalar b_10 as a new coefficient n - polynomials.T1.setCoef(zkey.domainSize, challenges.b[10]); - - // compute t_mid(X) - // Subtract blinding scalar b_10 to the lowest coefficient of t_mid - const lowestMid = Fr.sub(polynomials.T2.getCoef(0), challenges.b[10]); - polynomials.T2.setCoef(0, lowestMid); - polynomials.T2.setCoef(zkey.domainSize, challenges.b[11]); - - // compute t_high(X) - //Subtract blinding scalar b_11 to the lowest coefficient of t_high - const lowestHigh = Fr.sub(polynomials.T3.getCoef(0), challenges.b[11]); - polynomials.T3.setCoef(0, lowestHigh); - } - - async function round4() { - if (logger) logger.debug("> Computing challenge xi"); - - // STEP 4.1 - Compute evaluation challenge xi ∈ F - transcript.reset(); - transcript.addScalar(challenges.alpha); - transcript.addPolCommitment(proof.getPolynomial("T1")); - transcript.addPolCommitment(proof.getPolynomial("T2")); - transcript.addPolCommitment(proof.getPolynomial("T3")); - - challenges.xi = transcript.getChallenge(); - challenges.xiw = Fr.mul(challenges.xi, Fr.w[zkey.power]); - - if (logger) logger.debug("··· challenges.xi: " + Fr.toString(challenges.xi, 16)); - - // Fourth output of the prover is ( a(xi), b(xi), c(xi), s1(xi), s2(xi), z(xiw) ) - proof.addEvaluation("eval_a", polynomials.A.evaluate(challenges.xi)); - proof.addEvaluation("eval_b", polynomials.B.evaluate(challenges.xi)); - proof.addEvaluation("eval_c", polynomials.C.evaluate(challenges.xi)); - proof.addEvaluation("eval_s1", polynomials.Sigma1.evaluate(challenges.xi)); - proof.addEvaluation("eval_s2", polynomials.Sigma2.evaluate(challenges.xi)); - proof.addEvaluation("eval_zw", polynomials.Z.evaluate(challenges.xiw)); - } - - async function round5() { - if (logger) logger.debug("> Computing challenge v"); - - // STEP 5.1 - Compute evaluation challenge v ∈ F - transcript.reset(); - transcript.addScalar(challenges.xi); - transcript.addScalar(proof.getEvaluation("eval_a")); - transcript.addScalar(proof.getEvaluation("eval_b")); - transcript.addScalar(proof.getEvaluation("eval_c")); - transcript.addScalar(proof.getEvaluation("eval_s1")); - transcript.addScalar(proof.getEvaluation("eval_s2")); - transcript.addScalar(proof.getEvaluation("eval_zw")); - - challenges.v = []; - challenges.v[1] = transcript.getChallenge(); - if (logger) logger.debug("··· challenges.v: " + Fr.toString(challenges.v[1], 16)); - - for (let i = 2; i < 6; i++) { - challenges.v[i] = Fr.mul(challenges.v[i - 1], challenges.v[1]); - } - - // STEP 5.2 Compute linearisation polynomial r(X) - if (logger) logger.debug("> Computing linearisation polynomial R(X)"); - await computeR(); - - //STEP 5.3 Compute opening proof polynomial Wxi(X) - if (logger) logger.debug("> Computing opening proof polynomial Wxi(X) polynomial"); - computeWxi(); - - //STEP 5.4 Compute opening proof polynomial Wxiw(X) - if (logger) logger.debug("> Computing opening proof polynomial Wxiw(X) polynomial"); - computeWxiw(); - - if (logger) logger.debug("> Computing Wxi, Wxiw MSM"); - let commitWxi = await polynomials.Wxi.multiExponentiation(PTau, "Wxi"); - let commitWxiw = await polynomials.Wxiw.multiExponentiation(PTau, "Wxiw"); - - // Fifth output of the prover is ([Wxi]_1, [Wxiw]_1) - proof.addPolynomial("Wxi", commitWxi); - proof.addPolynomial("Wxiw", commitWxiw); - } - - async function computeR() { - const Fr = curve.Fr; - - // Reserve memory for Q's polynomials - polynomials.QL = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QR = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QM = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QO = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QC = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - - // Read Q's evaluations from zkey file - await fdZKey.readToBuffer(polynomials.QL.coef, 0, sDomain, zkeySections[ZKEY_PL_QL_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QR.coef, 0, sDomain, zkeySections[ZKEY_PL_QR_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QM.coef, 0, sDomain, zkeySections[ZKEY_PL_QM_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QO.coef, 0, sDomain, zkeySections[ZKEY_PL_QO_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QC.coef, 0, sDomain, zkeySections[ZKEY_PL_QC_SECTION][0].p); - - challenges.xin = challenges.xi; - for (let i = 0; i < zkey.power; i++) { - challenges.xin = Fr.square(challenges.xin); - } - - challenges.zh = Fr.sub(challenges.xin, Fr.one); - - const L = []; - - const n = Fr.e(zkey.domainSize); - let w = Fr.one; - for (let i = 1; i <= Math.max(1, zkey.nPublic); i++) { - L[i] = Fr.div(Fr.mul(w, challenges.zh), Fr.mul(n, Fr.sub(challenges.xi, w))); - w = Fr.mul(w, Fr.w[zkey.power]); - } - - const eval_l1 = Fr.div( - Fr.sub(challenges.xin, Fr.one), - Fr.mul(n, Fr.sub(challenges.xi, Fr.one)) - ); - - if (logger) { - logger.debug("Lagrange Evaluations: "); - for (let i=1; i. -*/ -const {unstringifyBigInts: unstringifyBigInts$6} = ffjavascript.utils; - + const { fd: fdWtns, sections: sectionsWtns } = await _iden3_binfileutils.readBinFile(witnessFileName, "wtns", 2, 1 << 25, 1 << 23); + if (logger) logger.debug("> Reading witness file"); + const wtns = await readHeader(fdWtns, sectionsWtns); + if (logger) logger.debug("> Reading zkey file"); + const { fd: fdZKey, sections: zkeySections } = await _iden3_binfileutils.readBinFile(zkeyFileName, "zkey", 2, 1 << 25, 1 << 23); + const zkey = await readHeader$1(fdZKey, zkeySections, void 0, options); + if (zkey.protocol != "plonk") throw new Error("zkey file is not plonk"); + if (!ffjavascript.Scalar.eq(zkey.r, wtns.q)) throw new Error("Curve of the witness does not match the curve of the proving key"); + if (wtns.nWitness != zkey.nVars - zkey.nAdditions) throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}, ${zkey.nAdditions}`); + const curve = zkey.curve; + const Fr = curve.Fr; + const n8r = curve.Fr.n8; + const sDomain = zkey.domainSize * n8r; + if (logger) { + logger.debug("----------------------------"); + logger.debug(" PLONK PROVE SETTINGS"); + logger.debug(` Curve: ${curve.name}`); + logger.debug(` Circuit power: ${zkey.power}`); + logger.debug(` Domain size: ${zkey.domainSize}`); + logger.debug(` Vars: ${zkey.nVars}`); + logger.debug(` Public vars: ${zkey.nPublic}`); + logger.debug(` Constraints: ${zkey.nConstraints}`); + logger.debug(` Additions: ${zkey.nAdditions}`); + logger.debug("----------------------------"); + } + if (logger) logger.debug("> Reading witness file data"); + const buffWitness = await _iden3_binfileutils.readSection(fdWtns, sectionsWtns, 2); + buffWitness.set(Fr.zero, 0); + const buffInternalWitness = new ffjavascript.BigBuffer(n8r * zkey.nAdditions); + let buffers = {}; + let polynomials = {}; + let evaluations = {}; + let challenges = {}; + let proof = new Proof(curve, logger); + const transcript = new Keccak256Transcript(curve); + if (logger) logger.debug(`> Reading Section 3. Additions`); + await calculateAdditions(); + if (logger) logger.debug(`> Reading Section 12. Sigma1, Sigma2 & Sigma 3`); + if (logger) logger.debug("··· Reading Sigma polynomials "); + polynomials.Sigma1 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.Sigma2 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.Sigma3 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + await fdZKey.readToBuffer(polynomials.Sigma1.coef, 0, sDomain, zkeySections[12][0].p); + await fdZKey.readToBuffer(polynomials.Sigma2.coef, 0, sDomain, zkeySections[12][0].p + 5 * sDomain); + await fdZKey.readToBuffer(polynomials.Sigma3.coef, 0, sDomain, zkeySections[12][0].p + 10 * sDomain); + if (logger) logger.debug("··· Reading Sigma evaluations"); + evaluations.Sigma1 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.Sigma2 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.Sigma3 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + await fdZKey.readToBuffer(evaluations.Sigma1.eval, 0, sDomain * 4, zkeySections[12][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.Sigma2.eval, 0, sDomain * 4, zkeySections[12][0].p + 6 * sDomain); + await fdZKey.readToBuffer(evaluations.Sigma3.eval, 0, sDomain * 4, zkeySections[12][0].p + 11 * sDomain); + if (logger) logger.debug(`> Reading Section 14. Powers of Tau`); + const PTau = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 14); + let publicSignals = []; + for (let i = 1; i <= zkey.nPublic; i++) { + const pub = buffWitness.slice(i * Fr.n8, i * Fr.n8 + Fr.n8); + publicSignals.push(ffjavascript.Scalar.fromRprLE(pub)); + } + if (logger) logger.debug(""); + if (logger) logger.debug("> ROUND 1"); + await round1(); + if (logger) logger.debug("> ROUND 2"); + await round2(); + if (logger) logger.debug("> ROUND 3"); + await round3(); + if (logger) logger.debug("> ROUND 4"); + await round4(); + if (logger) logger.debug("> ROUND 5"); + await round5(); + await fdZKey.close(); + await fdWtns.close(); + let _proof = proof.toObjectProof(false); + _proof.protocol = "plonk"; + _proof.curve = curve.name; + if (logger) logger.debug("PLONK PROVER FINISHED"); + return { + proof: stringifyBigInts$2(_proof), + publicSignals: stringifyBigInts$2(publicSignals) + }; + async function calculateAdditions() { + if (logger) logger.debug("··· Computing additions"); + const additionsBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 3); + const sSum = 8 + n8r * 2; + for (let i = 0; i < zkey.nAdditions; i++) { + if (logger && 0 !== i && i % 1e5 === 0) logger.debug(` addition ${i}/${zkey.nAdditions}`); + let offset = i * sSum; + const signalId1 = readUInt32(additionsBuff, offset); + offset += 4; + const signalId2 = readUInt32(additionsBuff, offset); + offset += 4; + const factor1 = additionsBuff.slice(offset, offset + n8r); + offset += n8r; + const factor2 = additionsBuff.slice(offset, offset + n8r); + const witness1 = getWitness(signalId1); + const witness2 = getWitness(signalId2); + const result = Fr.add(Fr.mul(factor1, witness1), Fr.mul(factor2, witness2)); + buffInternalWitness.set(result, n8r * i); + } + } + function readUInt32(b, o) { + const buff = b.slice(o, o + 4); + return new DataView(buff.buffer, buff.byteOffset, buff.byteLength).getUint32(0, true); + } + function getWitness(idx) { + if (idx < zkey.nVars - zkey.nAdditions) return buffWitness.slice(idx * n8r, idx * n8r + n8r); + else if (idx < zkey.nVars) return buffInternalWitness.slice((idx - (zkey.nVars - zkey.nAdditions)) * n8r, (idx - (zkey.nVars - zkey.nAdditions)) * n8r + n8r); + else return curve.Fr.zero; + } + async function round1() { + challenges.b = []; + for (let i = 1; i <= 11; i++) challenges.b[i] = curve.Fr.random(); + if (logger) logger.debug("> Computing A, B, C wire polynomials"); + await computeWirePolynomials(); + if (logger) logger.debug("> Computing A, B, C MSM"); + let commitA = await polynomials.A.multiExponentiation(PTau, "A"); + let commitB = await polynomials.B.multiExponentiation(PTau, "B"); + let commitC = await polynomials.C.multiExponentiation(PTau, "C"); + proof.addPolynomial("A", commitA); + proof.addPolynomial("B", commitB); + proof.addPolynomial("C", commitC); + return 0; + } + async function computeWirePolynomials() { + if (logger) logger.debug("··· Reading data from zkey file"); + buffers.A = new ffjavascript.BigBuffer(sDomain); + buffers.B = new ffjavascript.BigBuffer(sDomain); + buffers.C = new ffjavascript.BigBuffer(sDomain); + const aMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 4); + const bMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 5); + const cMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 6); + for (let i = 0; i < zkey.nConstraints; i++) { + const i_sFr = i * n8r; + const offset = i * 4; + const signalIdA = readUInt32(aMapBuff, offset); + buffers.A.set(getWitness(signalIdA), i_sFr); + const signalIdB = readUInt32(bMapBuff, offset); + buffers.B.set(getWitness(signalIdB), i_sFr); + const signalIdC = readUInt32(cMapBuff, offset); + buffers.C.set(getWitness(signalIdC), i_sFr); + } + buffers.A = await Fr.batchToMontgomery(buffers.A); + buffers.B = await Fr.batchToMontgomery(buffers.B); + buffers.C = await Fr.batchToMontgomery(buffers.C); + if (logger) logger.debug("··· Computing A ifft"); + polynomials.A = await Polynomial.fromEvaluations(buffers.A, curve, logger); + if (logger) logger.debug("··· Computing B ifft"); + polynomials.B = await Polynomial.fromEvaluations(buffers.B, curve, logger); + if (logger) logger.debug("··· Computing C ifft"); + polynomials.C = await Polynomial.fromEvaluations(buffers.C, curve, logger); + if (logger) logger.debug("··· Computing A fft"); + evaluations.A = await Evaluations.fromPolynomial(polynomials.A, 4, curve, logger); + if (logger) logger.debug("··· Computing B fft"); + evaluations.B = await Evaluations.fromPolynomial(polynomials.B, 4, curve, logger); + if (logger) logger.debug("··· Computing C fft"); + evaluations.C = await Evaluations.fromPolynomial(polynomials.C, 4, curve, logger); + polynomials.A.blindCoefficients([challenges.b[2], challenges.b[1]]); + polynomials.B.blindCoefficients([challenges.b[4], challenges.b[3]]); + polynomials.C.blindCoefficients([challenges.b[6], challenges.b[5]]); + if (polynomials.A.degree() >= zkey.domainSize + 2) throw new Error("A Polynomial is not well calculated"); + if (polynomials.B.degree() >= zkey.domainSize + 2) throw new Error("B Polynomial is not well calculated"); + if (polynomials.C.degree() >= zkey.domainSize + 2) throw new Error("C Polynomial is not well calculated"); + } + async function round2() { + if (logger) logger.debug("> Computing challenges beta and gamma"); + transcript.reset(); + transcript.addPolCommitment(zkey.Qm); + transcript.addPolCommitment(zkey.Ql); + transcript.addPolCommitment(zkey.Qr); + transcript.addPolCommitment(zkey.Qo); + transcript.addPolCommitment(zkey.Qc); + transcript.addPolCommitment(zkey.S1); + transcript.addPolCommitment(zkey.S2); + transcript.addPolCommitment(zkey.S3); + for (let i = 0; i < zkey.nPublic; i++) transcript.addScalar(buffers.A.slice(i * n8r, i * n8r + n8r)); + transcript.addPolCommitment(proof.getPolynomial("A")); + transcript.addPolCommitment(proof.getPolynomial("B")); + transcript.addPolCommitment(proof.getPolynomial("C")); + challenges.beta = transcript.getChallenge(); + if (logger) logger.debug("··· challenges.beta: " + Fr.toString(challenges.beta, 16)); + transcript.reset(); + transcript.addScalar(challenges.beta); + challenges.gamma = transcript.getChallenge(); + if (logger) logger.debug("··· challenges.gamma: " + Fr.toString(challenges.gamma, 16)); + if (logger) logger.debug("> Computing Z polynomial"); + await computeZ(); + if (logger) logger.debug("> Computing Z MSM"); + let commitZ = await polynomials.Z.multiExponentiation(PTau, "Z"); + proof.addPolynomial("Z", commitZ); + } + async function computeZ() { + if (logger) logger.debug("··· Computing Z evaluations"); + let numArr = new ffjavascript.BigBuffer(sDomain); + let denArr = new ffjavascript.BigBuffer(sDomain); + numArr.set(Fr.one, 0); + denArr.set(Fr.one, 0); + let w = Fr.one; + for (let i = 0; i < zkey.domainSize; i++) { + const i_n8r = i * n8r; + const a = buffers.A.slice(i_n8r, i_n8r + n8r); + const b = buffers.B.slice(i_n8r, i_n8r + n8r); + const c = buffers.C.slice(i_n8r, i_n8r + n8r); + const betaw = Fr.mul(challenges.beta, w); + let n1 = Fr.add(a, betaw); + n1 = Fr.add(n1, challenges.gamma); + let n2 = Fr.add(b, Fr.mul(zkey.k1, betaw)); + n2 = Fr.add(n2, challenges.gamma); + let n3 = Fr.add(c, Fr.mul(zkey.k2, betaw)); + n3 = Fr.add(n3, challenges.gamma); + let num = Fr.mul(n1, Fr.mul(n2, n3)); + let d1 = Fr.add(a, Fr.mul(evaluations.Sigma1.getEvaluation(i * 4), challenges.beta)); + d1 = Fr.add(d1, challenges.gamma); + let d2 = Fr.add(b, Fr.mul(evaluations.Sigma2.getEvaluation(i * 4), challenges.beta)); + d2 = Fr.add(d2, challenges.gamma); + let d3 = Fr.add(c, Fr.mul(evaluations.Sigma3.getEvaluation(i * 4), challenges.beta)); + d3 = Fr.add(d3, challenges.gamma); + let den = Fr.mul(d1, Fr.mul(d2, d3)); + num = Fr.mul(numArr.slice(i_n8r, i_n8r + n8r), num); + numArr.set(num, (i + 1) % zkey.domainSize * n8r); + den = Fr.mul(denArr.slice(i_n8r, i_n8r + n8r), den); + denArr.set(den, (i + 1) % zkey.domainSize * n8r); + w = Fr.mul(w, Fr.w[zkey.power]); + } + denArr = await Fr.batchInverse(denArr); + for (let i = 0; i < zkey.domainSize; i++) { + const i_sFr = i * n8r; + const z = Fr.mul(numArr.slice(i_sFr, i_sFr + n8r), denArr.slice(i_sFr, i_sFr + n8r)); + numArr.set(z, i_sFr); + } + buffers.Z = numArr; + if (!Fr.eq(numArr.slice(0, n8r), Fr.one)) throw new Error("Copy constraints does not match"); + if (logger) logger.debug("··· Computing Z ifft"); + polynomials.Z = await Polynomial.fromEvaluations(buffers.Z, curve, logger); + if (logger) logger.debug("··· Computing Z fft"); + evaluations.Z = await Evaluations.fromPolynomial(polynomials.Z, 4, curve, logger); + polynomials.Z.blindCoefficients([ + challenges.b[9], + challenges.b[8], + challenges.b[7] + ]); + if (polynomials.Z.degree() >= zkey.domainSize + 3) throw new Error("Z Polynomial is not well calculated"); + delete buffers.Z; + } + async function round3() { + if (logger) logger.debug("> Computing challenge alpha"); + transcript.reset(); + transcript.addScalar(challenges.beta); + transcript.addScalar(challenges.gamma); + transcript.addPolCommitment(proof.getPolynomial("Z")); + challenges.alpha = transcript.getChallenge(); + challenges.alpha2 = Fr.square(challenges.alpha); + if (logger) logger.debug("··· challenges.alpha: " + Fr.toString(challenges.alpha, 16)); + if (logger) logger.debug("> Computing T polynomial"); + await computeT(); + if (logger) logger.debug("> Computing T MSM"); + let commitT1 = await polynomials.T1.multiExponentiation(PTau, "T1"); + let commitT2 = await polynomials.T2.multiExponentiation(PTau, "T2"); + let commitT3 = await polynomials.T3.multiExponentiation(PTau, "T3"); + proof.addPolynomial("T1", commitT1); + proof.addPolynomial("T2", commitT2); + proof.addPolynomial("T3", commitT3); + } + async function computeT() { + if (logger) logger.debug(`··· Reading sections 8, 9, 7, 10, 11. Q selectors`); + evaluations.QL = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QR = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QM = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QO = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QC = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + await fdZKey.readToBuffer(evaluations.QL.eval, 0, sDomain * 4, zkeySections[8][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QR.eval, 0, sDomain * 4, zkeySections[9][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QM.eval, 0, sDomain * 4, zkeySections[7][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QO.eval, 0, sDomain * 4, zkeySections[10][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QC.eval, 0, sDomain * 4, zkeySections[11][0].p + sDomain); + evaluations.Lagrange = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4 * zkey.nPublic), curve, logger); + for (let i = 0; i < zkey.nPublic; i++) await fdZKey.readToBuffer(evaluations.Lagrange.eval, i * sDomain * 4, sDomain * 4, zkeySections[13][0].p + i * 5 * sDomain + sDomain); + buffers.T = new ffjavascript.BigBuffer(sDomain * 4); + buffers.Tz = new ffjavascript.BigBuffer(sDomain * 4); + if (logger) logger.debug("··· Computing T evaluations"); + let w = Fr.one; + for (let i = 0; i < zkey.domainSize * 4; i++) { + if (logger && 0 !== i && i % 1e5 === 0) logger.debug(` T evaluation ${i}/${zkey.domainSize * 4}`); + const a = evaluations.A.getEvaluation(i); + const b = evaluations.B.getEvaluation(i); + const c = evaluations.C.getEvaluation(i); + const z = evaluations.Z.getEvaluation(i); + const zw = evaluations.Z.getEvaluation((zkey.domainSize * 4 + 4 + i) % (zkey.domainSize * 4)); + const qm = evaluations.QM.getEvaluation(i); + const ql = evaluations.QL.getEvaluation(i); + const qr = evaluations.QR.getEvaluation(i); + const qo = evaluations.QO.getEvaluation(i); + const qc = evaluations.QC.getEvaluation(i); + const s1 = evaluations.Sigma1.getEvaluation(i); + const s2 = evaluations.Sigma2.getEvaluation(i); + const s3 = evaluations.Sigma3.getEvaluation(i); + const ap = Fr.add(challenges.b[2], Fr.mul(challenges.b[1], w)); + const bp = Fr.add(challenges.b[4], Fr.mul(challenges.b[3], w)); + const cp = Fr.add(challenges.b[6], Fr.mul(challenges.b[5], w)); + const w2 = Fr.square(w); + const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], w2), Fr.mul(challenges.b[8], w)), challenges.b[9]); + const wW = Fr.mul(w, Fr.w[zkey.power]); + const wW2 = Fr.square(wW); + const zWp = Fr.add(Fr.add(Fr.mul(challenges.b[7], wW2), Fr.mul(challenges.b[8], wW)), challenges.b[9]); + let pi = Fr.zero; + for (let j = 0; j < zkey.nPublic; j++) { + const offset = j * 4 * zkey.domainSize + i; + const lPol = evaluations.Lagrange.getEvaluation(offset); + const aVal = buffers.A.slice(j * n8r, (j + 1) * n8r); + pi = Fr.sub(pi, Fr.mul(lPol, aVal)); + } + let [e1, e1z] = MulZ.mul2(a, b, ap, bp, i % 4, Fr); + e1 = Fr.mul(e1, qm); + e1z = Fr.mul(e1z, qm); + e1 = Fr.add(e1, Fr.mul(a, ql)); + e1z = Fr.add(e1z, Fr.mul(ap, ql)); + e1 = Fr.add(e1, Fr.mul(b, qr)); + e1z = Fr.add(e1z, Fr.mul(bp, qr)); + e1 = Fr.add(e1, Fr.mul(c, qo)); + e1z = Fr.add(e1z, Fr.mul(cp, qo)); + e1 = Fr.add(e1, pi); + e1 = Fr.add(e1, qc); + const betaw = Fr.mul(challenges.beta, w); + let e2a = a; + e2a = Fr.add(e2a, betaw); + e2a = Fr.add(e2a, challenges.gamma); + let e2b = b; + e2b = Fr.add(e2b, Fr.mul(betaw, zkey.k1)); + e2b = Fr.add(e2b, challenges.gamma); + let e2c = c; + e2c = Fr.add(e2c, Fr.mul(betaw, zkey.k2)); + e2c = Fr.add(e2c, challenges.gamma); + let e2d = z; + let [e2, e2z] = MulZ.mul4(e2a, e2b, e2c, e2d, ap, bp, cp, zp, i % 4, Fr); + e2 = Fr.mul(e2, challenges.alpha); + e2z = Fr.mul(e2z, challenges.alpha); + let e3a = a; + e3a = Fr.add(e3a, Fr.mul(challenges.beta, s1)); + e3a = Fr.add(e3a, challenges.gamma); + let e3b = b; + e3b = Fr.add(e3b, Fr.mul(challenges.beta, s2)); + e3b = Fr.add(e3b, challenges.gamma); + let e3c = c; + e3c = Fr.add(e3c, Fr.mul(challenges.beta, s3)); + e3c = Fr.add(e3c, challenges.gamma); + let e3d = zw; + let [e3, e3z] = MulZ.mul4(e3a, e3b, e3c, e3d, ap, bp, cp, zWp, i % 4, Fr); + e3 = Fr.mul(e3, challenges.alpha); + e3z = Fr.mul(e3z, challenges.alpha); + let e4 = Fr.sub(z, Fr.one); + e4 = Fr.mul(e4, evaluations.Lagrange.getEvaluation(i)); + e4 = Fr.mul(e4, challenges.alpha2); + let e4z = Fr.mul(zp, evaluations.Lagrange.getEvaluation(i)); + e4z = Fr.mul(e4z, challenges.alpha2); + let t = Fr.add(Fr.sub(Fr.add(e1, e2), e3), e4); + let tz = Fr.add(Fr.sub(Fr.add(e1z, e2z), e3z), e4z); + buffers.T.set(t, i * n8r); + buffers.Tz.set(tz, i * n8r); + w = Fr.mul(w, Fr.w[zkey.power + 2]); + } + if (logger) logger.debug("··· Computing T ifft"); + polynomials.T = await Polynomial.fromEvaluations(buffers.T, curve, logger); + if (logger) logger.debug("··· Computing T / ZH"); + polynomials.T.divZh(zkey.domainSize, 4); + if (logger) logger.debug("··· Computing Tz ifft"); + polynomials.Tz = await Polynomial.fromEvaluations(buffers.Tz, curve, logger); + polynomials.T.add(polynomials.Tz); + if (polynomials.T.degree() >= zkey.domainSize * 3 + 6) throw new Error("T Polynomial is not well calculated"); + if (logger) logger.debug("··· Computing T1, T2, T3 polynomials"); + polynomials.T1 = new Polynomial(new ffjavascript.BigBuffer((zkey.domainSize + 1) * n8r), curve, logger); + polynomials.T2 = new Polynomial(new ffjavascript.BigBuffer((zkey.domainSize + 1) * n8r), curve, logger); + polynomials.T3 = new Polynomial(new ffjavascript.BigBuffer((zkey.domainSize + 6) * n8r), curve, logger); + polynomials.T1.coef.set(polynomials.T.coef.slice(0, sDomain), 0); + polynomials.T2.coef.set(polynomials.T.coef.slice(sDomain, sDomain * 2), 0); + polynomials.T3.coef.set(polynomials.T.coef.slice(sDomain * 2, sDomain * 3 + 6 * n8r), 0); + polynomials.T1.setCoef(zkey.domainSize, challenges.b[10]); + const lowestMid = Fr.sub(polynomials.T2.getCoef(0), challenges.b[10]); + polynomials.T2.setCoef(0, lowestMid); + polynomials.T2.setCoef(zkey.domainSize, challenges.b[11]); + const lowestHigh = Fr.sub(polynomials.T3.getCoef(0), challenges.b[11]); + polynomials.T3.setCoef(0, lowestHigh); + } + async function round4() { + if (logger) logger.debug("> Computing challenge xi"); + transcript.reset(); + transcript.addScalar(challenges.alpha); + transcript.addPolCommitment(proof.getPolynomial("T1")); + transcript.addPolCommitment(proof.getPolynomial("T2")); + transcript.addPolCommitment(proof.getPolynomial("T3")); + challenges.xi = transcript.getChallenge(); + challenges.xiw = Fr.mul(challenges.xi, Fr.w[zkey.power]); + if (logger) logger.debug("··· challenges.xi: " + Fr.toString(challenges.xi, 16)); + proof.addEvaluation("eval_a", polynomials.A.evaluate(challenges.xi)); + proof.addEvaluation("eval_b", polynomials.B.evaluate(challenges.xi)); + proof.addEvaluation("eval_c", polynomials.C.evaluate(challenges.xi)); + proof.addEvaluation("eval_s1", polynomials.Sigma1.evaluate(challenges.xi)); + proof.addEvaluation("eval_s2", polynomials.Sigma2.evaluate(challenges.xi)); + proof.addEvaluation("eval_zw", polynomials.Z.evaluate(challenges.xiw)); + } + async function round5() { + if (logger) logger.debug("> Computing challenge v"); + transcript.reset(); + transcript.addScalar(challenges.xi); + transcript.addScalar(proof.getEvaluation("eval_a")); + transcript.addScalar(proof.getEvaluation("eval_b")); + transcript.addScalar(proof.getEvaluation("eval_c")); + transcript.addScalar(proof.getEvaluation("eval_s1")); + transcript.addScalar(proof.getEvaluation("eval_s2")); + transcript.addScalar(proof.getEvaluation("eval_zw")); + challenges.v = []; + challenges.v[1] = transcript.getChallenge(); + if (logger) logger.debug("··· challenges.v: " + Fr.toString(challenges.v[1], 16)); + for (let i = 2; i < 6; i++) challenges.v[i] = Fr.mul(challenges.v[i - 1], challenges.v[1]); + if (logger) logger.debug("> Computing linearisation polynomial R(X)"); + await computeR(); + if (logger) logger.debug("> Computing opening proof polynomial Wxi(X) polynomial"); + computeWxi(); + if (logger) logger.debug("> Computing opening proof polynomial Wxiw(X) polynomial"); + computeWxiw(); + if (logger) logger.debug("> Computing Wxi, Wxiw MSM"); + let commitWxi = await polynomials.Wxi.multiExponentiation(PTau, "Wxi"); + let commitWxiw = await polynomials.Wxiw.multiExponentiation(PTau, "Wxiw"); + proof.addPolynomial("Wxi", commitWxi); + proof.addPolynomial("Wxiw", commitWxiw); + } + async function computeR() { + const Fr = curve.Fr; + polynomials.QL = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QR = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QM = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QO = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QC = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + await fdZKey.readToBuffer(polynomials.QL.coef, 0, sDomain, zkeySections[8][0].p); + await fdZKey.readToBuffer(polynomials.QR.coef, 0, sDomain, zkeySections[9][0].p); + await fdZKey.readToBuffer(polynomials.QM.coef, 0, sDomain, zkeySections[7][0].p); + await fdZKey.readToBuffer(polynomials.QO.coef, 0, sDomain, zkeySections[10][0].p); + await fdZKey.readToBuffer(polynomials.QC.coef, 0, sDomain, zkeySections[11][0].p); + challenges.xin = challenges.xi; + for (let i = 0; i < zkey.power; i++) challenges.xin = Fr.square(challenges.xin); + challenges.zh = Fr.sub(challenges.xin, Fr.one); + const L = []; + const n = Fr.e(zkey.domainSize); + let w = Fr.one; + for (let i = 1; i <= Math.max(1, zkey.nPublic); i++) { + L[i] = Fr.div(Fr.mul(w, challenges.zh), Fr.mul(n, Fr.sub(challenges.xi, w))); + w = Fr.mul(w, Fr.w[zkey.power]); + } + const eval_l1 = Fr.div(Fr.sub(challenges.xin, Fr.one), Fr.mul(n, Fr.sub(challenges.xi, Fr.one))); + if (logger) { + logger.debug("Lagrange Evaluations: "); + for (let i = 1; i < L.length; i++) logger.debug(`L${i}(xi)=` + Fr.toString(L[i], 16)); + } + let eval_pi = Fr.zero; + for (let i = 0; i < publicSignals.length; i++) { + const w = Fr.e(publicSignals[i]); + eval_pi = Fr.sub(eval_pi, Fr.mul(w, L[i + 1])); + } + if (logger) logger.debug("PI: " + Fr.toString(eval_pi, 16)); + const coef_ab = Fr.mul(proof.evaluations.eval_a, proof.evaluations.eval_b); + let e2a = proof.evaluations.eval_a; + const betaxi = Fr.mul(challenges.beta, challenges.xi); + e2a = Fr.add(e2a, betaxi); + e2a = Fr.add(e2a, challenges.gamma); + let e2b = proof.evaluations.eval_b; + e2b = Fr.add(e2b, Fr.mul(betaxi, zkey.k1)); + e2b = Fr.add(e2b, challenges.gamma); + let e2c = proof.evaluations.eval_c; + e2c = Fr.add(e2c, Fr.mul(betaxi, zkey.k2)); + e2c = Fr.add(e2c, challenges.gamma); + const e2 = Fr.mul(Fr.mul(Fr.mul(e2a, e2b), e2c), challenges.alpha); + let e3a = proof.evaluations.eval_a; + e3a = Fr.add(e3a, Fr.mul(challenges.beta, proof.evaluations.eval_s1)); + e3a = Fr.add(e3a, challenges.gamma); + let e3b = proof.evaluations.eval_b; + e3b = Fr.add(e3b, Fr.mul(challenges.beta, proof.evaluations.eval_s2)); + e3b = Fr.add(e3b, challenges.gamma); + let e3 = Fr.mul(e3a, e3b); + e3 = Fr.mul(e3, proof.evaluations.eval_zw); + e3 = Fr.mul(e3, challenges.alpha); + const e4 = Fr.mul(eval_l1, challenges.alpha2); + polynomials.R = new Polynomial(new ffjavascript.BigBuffer((zkey.domainSize + 6) * n8r), curve, logger); + polynomials.R.add(polynomials.QM, coef_ab); + polynomials.R.add(polynomials.QL, proof.evaluations.eval_a); + polynomials.R.add(polynomials.QR, proof.evaluations.eval_b); + polynomials.R.add(polynomials.QO, proof.evaluations.eval_c); + polynomials.R.add(polynomials.QC); + polynomials.R.add(polynomials.Z, e2); + polynomials.R.sub(polynomials.Sigma3, Fr.mul(e3, challenges.beta)); + polynomials.R.add(polynomials.Z, e4); + let tmp = Polynomial.fromPolynomial(polynomials.T3, curve, logger); + tmp.mulScalar(Fr.square(challenges.xin)); + tmp.add(polynomials.T2, challenges.xin); + tmp.add(polynomials.T1); + tmp.mulScalar(challenges.zh); + polynomials.R.sub(tmp); + let r0 = Fr.sub(eval_pi, Fr.mul(e3, Fr.add(proof.evaluations.eval_c, challenges.gamma))); + r0 = Fr.sub(r0, e4); + if (logger) logger.debug("r0: " + Fr.toString(r0, 16)); + polynomials.R.addScalar(r0); + } + function computeWxi() { + polynomials.Wxi = new Polynomial(new ffjavascript.BigBuffer(sDomain + 6 * n8r), curve, logger); + polynomials.Wxi.add(polynomials.R); + polynomials.Wxi.add(polynomials.A, challenges.v[1]); + polynomials.Wxi.add(polynomials.B, challenges.v[2]); + polynomials.Wxi.add(polynomials.C, challenges.v[3]); + polynomials.Wxi.add(polynomials.Sigma1, challenges.v[4]); + polynomials.Wxi.add(polynomials.Sigma2, challenges.v[5]); + polynomials.Wxi.subScalar(Fr.mul(challenges.v[1], proof.evaluations.eval_a)); + polynomials.Wxi.subScalar(Fr.mul(challenges.v[2], proof.evaluations.eval_b)); + polynomials.Wxi.subScalar(Fr.mul(challenges.v[3], proof.evaluations.eval_c)); + polynomials.Wxi.subScalar(Fr.mul(challenges.v[4], proof.evaluations.eval_s1)); + polynomials.Wxi.subScalar(Fr.mul(challenges.v[5], proof.evaluations.eval_s2)); + polynomials.Wxi.divByZerofier(1, challenges.xi); + } + async function computeWxiw() { + polynomials.Wxiw = Polynomial.fromPolynomial(polynomials.Z, curve, logger); + polynomials.Wxiw.subScalar(proof.evaluations.eval_zw); + polynomials.Wxiw.divByZerofier(1, challenges.xiw); + } +} +//#endregion +//#region src/plonk_fullprove.js +var { unstringifyBigInts: unstringifyBigInts$6 } = ffjavascript.utils; async function plonkFullProve$1(_input, wasmFile, zkeyFileName, logger, wtnsCalcOptions, proverOptions) { - const input = unstringifyBigInts$6(_input); - - const wtns= { - type: "mem" - }; - await wtnsCalculate$1(input, wasmFile, wtns, wtnsCalcOptions); - return await plonk16Prove(zkeyFileName, wtns, logger, proverOptions); -} - -/* - Copyright 2021 0kims association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -const { unstringifyBigInts: unstringifyBigInts$5 } = ffjavascript.utils; - + const input = unstringifyBigInts$6(_input); + const wtns = { type: "mem" }; + await wtnsCalculate$1(input, wasmFile, wtns, wtnsCalcOptions); + return await plonk16Prove(zkeyFileName, wtns, logger, proverOptions); +} +//#endregion +//#region src/plonk_verify.js +var { unstringifyBigInts: unstringifyBigInts$5 } = ffjavascript.utils; async function plonkVerify$1(_vk_verifier, _publicSignals, _proof, logger) { - let vk_verifier = unstringifyBigInts$5(_vk_verifier); - _proof = unstringifyBigInts$5(_proof); - let publicSignals = unstringifyBigInts$5(_publicSignals); - - const curve = await getCurveFromName(vk_verifier.curve); - - const Fr = curve.Fr; - const G1 = curve.G1; - - if (logger) logger.info("PLONK VERIFIER STARTED"); - - let proof = fromObjectProof(curve,_proof); - vk_verifier = fromObjectVk$1(curve, vk_verifier); - - if (!isWellConstructed(curve, proof)) { - logger.error("Proof commitments are not valid."); - return false; - } - - if (publicSignals.length != vk_verifier.nPublic) { - if (logger) logger.error("Invalid number of public inputs"); - return false; - } - - if (!evaluationsAreValid$1(curve, proof)) { - if (logger) logger.error("Proof evaluations are not valid"); - return false; - } - - if (!publicInputsAreValid$1(curve, publicSignals)) { - if (logger) logger.error("Public inputs are not valid."); - return false; - } - - const challenges = calculatechallenges(curve, proof, publicSignals, vk_verifier); - if (logger) { - logger.debug("beta: " + Fr.toString(challenges.beta, 16)); - logger.debug("gamma: " + Fr.toString(challenges.gamma, 16)); - logger.debug("alpha: " + Fr.toString(challenges.alpha, 16)); - logger.debug("xi: " + Fr.toString(challenges.xi, 16)); - for(let i=1;i<6;i++) { - if (logger) logger.debug("v: " + Fr.toString(challenges.v[i], 16)); - } - logger.debug("u: " + Fr.toString(challenges.u, 16)); - } - const L = calculateLagrangeEvaluations(curve, challenges, vk_verifier); - if (logger) { - for (let i=1; i. -*/ -const { unstringifyBigInts: unstringifyBigInts$4} = ffjavascript.utils; - + const G1 = curve.G1; + const Fr = curve.Fr; + let A1 = proof.Wxi; + A1 = G1.add(A1, G1.timesFr(proof.Wxiw, challenges.u)); + let B1 = G1.timesFr(proof.Wxi, challenges.xi); + const s = Fr.mul(Fr.mul(challenges.u, challenges.xi), Fr.w[vk.power]); + B1 = G1.add(B1, G1.timesFr(proof.Wxiw, s)); + B1 = G1.add(B1, F); + B1 = G1.sub(B1, E); + return await curve.pairingEq(G1.neg(A1), vk.X_2, B1, curve.G2.one); +} +//#endregion +//#region src/plonk_exportsoliditycalldata.js +var { unstringifyBigInts: unstringifyBigInts$4 } = ffjavascript.utils; function p256$1(n) { - let nstr = n.toString(16); - while (nstr.length < 64) nstr = "0"+nstr; - nstr = `"0x${nstr}"`; - return nstr; + let nstr = n.toString(16); + while (nstr.length < 64) nstr = "0" + nstr; + nstr = `"0x${nstr}"`; + return nstr; } - async function plonkExportSolidityCallData(_proof, _pub) { - const proof = unstringifyBigInts$4(_proof); - const pub = unstringifyBigInts$4(_pub); - - const curve = await getCurveFromName(proof.curve); - curve.G1; - curve.Fr; - - let inputs = ""; - for (let i=0; i. -*/ - -// We export to zkey the signals and values of the a, b, c, ql, qr, qm, qo and qc - -// a, b and c are signals id (32-bit integers) -// ql, qr, qm, qo and qc are field values - + const proof = unstringifyBigInts$4(_proof); + const pub = unstringifyBigInts$4(_pub); + await getCurveFromName(proof.curve); + let inputs = ""; + for (let i = 0; i < pub.length; i++) { + if (inputs != "") inputs = inputs + ","; + inputs = inputs + p256$1(pub[i]); + } + return `[${p256$1(proof.A[0])}, ${p256$1(proof.A[1])},${p256$1(proof.B[0])},${p256$1(proof.B[1])},${p256$1(proof.C[0])},${p256$1(proof.C[1])},${p256$1(proof.Z[0])},${p256$1(proof.Z[1])},${p256$1(proof.T1[0])},${p256$1(proof.T1[1])},${p256$1(proof.T2[0])},${p256$1(proof.T2[1])},${p256$1(proof.T3[0])},${p256$1(proof.T3[1])},${p256$1(proof.Wxi[0])},${p256$1(proof.Wxi[1])},${p256$1(proof.Wxiw[0])},${p256$1(proof.Wxiw[1])},${p256$1(proof.eval_a)},${p256$1(proof.eval_b)},${p256$1(proof.eval_c)},${p256$1(proof.eval_s1)},${p256$1(proof.eval_s2)},${p256$1(proof.eval_zw)}][${inputs}]`; +} +//#endregion +//#region src/plonk_equation.js function getFFlonkConstantConstraint(signal1, Fr) { - return [signal1, 0, 0, Fr.one, Fr.zero, Fr.zero, Fr.zero, Fr.zero]; + return [ + signal1, + 0, + 0, + Fr.one, + Fr.zero, + Fr.zero, + Fr.zero, + Fr.zero + ]; } - function getFFlonkAdditionConstraint(signal1, signal2, signalOut, ql, qr, qm, qo, qc) { - return [signal1, signal2, signalOut, ql, qr, qm, qo, qc]; -} - -function getFFlonkMultiplicationConstraint(signal1, signal2, signalOut, ql, qr, qm, qo, qc, Fr) { - return [signal1, signal2, signalOut, ql, qr, qm, qo, qc]; -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -const LINEAR_COMBINATION_NULLABLE = 0; -const LINEAR_COMBINATION_CONSTANT = 1; -const LINEAR_COMBINATION_VARIABLE = 2; - -class r1csConstraintProcessor { - constructor(Fr, fnGetConstantConstraint, fnGetAdditionConstraint, fnGetMultiplicationConstraint, logger) { - this.Fr = Fr; - this.logger = logger; - this.fnGetAdditionConstraint = fnGetAdditionConstraint; - this.fnGetMultiplicationConstraint = fnGetMultiplicationConstraint; - } - - processR1csConstraint(settings, lcA, lcB, lcC) { - this.normalizeLinearCombination(lcA); - this.normalizeLinearCombination(lcB); - this.normalizeLinearCombination(lcC); - - const lctA = this.getLinearCombinationType(lcA); - const lctB = this.getLinearCombinationType(lcB); - - if ((lctA === LINEAR_COMBINATION_NULLABLE) || (lctB === LINEAR_COMBINATION_NULLABLE)) { - return this.processR1csAdditionConstraint(settings, lcC); - } else if (lctA === LINEAR_COMBINATION_CONSTANT) { - const lcCC = this.joinLinearCombinations(lcB, lcC, lcA[0]); - return this.processR1csAdditionConstraint(settings, lcCC); - } else if (lctB === LINEAR_COMBINATION_CONSTANT) { - const lcCC = this.joinLinearCombinations(lcA, lcC, lcB[0]); - return this.processR1csAdditionConstraint(settings, lcCC); - } else { - return this.processR1csMultiplicationConstraint(settings, lcA, lcB, lcC); - } - } - - getLinearCombinationType(linCom) { - // let k = this.Fr.zero; - // - // const signalIds = Object.keys(linCom); - // for (let i = 0; i < signalIds.length; i++) { - // if (signalIds[i] === "0") { - // k = this.Fr.add(k, linCom[signalIds[i]]); - // } else { - // return LINEAR_COMBINATION_VARIABLE; - // } - // } - // - // if (!this.Fr.eq(k, this.Fr.zero)) return LINEAR_COMBINATION_CONSTANT; - // - // return LINEAR_COMBINATION_NULLABLE; - - let k = this.Fr.zero; - let n = 0; - const ss = Object.keys(linCom); - for (let i = 0; i < ss.length; i++) { - if (linCom[ss[i]] == 0n) { - delete linCom[ss[i]]; - } else if (ss[i] == 0) { - k = this.Fr.add(k, linCom[ss[i]]); - } else { - n++; - } - } - if (n > 0) return LINEAR_COMBINATION_VARIABLE; - if (!this.Fr.isZero(k)) return LINEAR_COMBINATION_CONSTANT; - return LINEAR_COMBINATION_NULLABLE; - } - - normalizeLinearCombination(linCom) { - const signalIds = Object.keys(linCom); - for (let i = 0; i < signalIds.length; i++) { - if (this.Fr.isZero(linCom[signalIds[i]])) delete linCom[signalIds[i]]; - } - - return linCom; - } - - joinLinearCombinations(linCom1, linCom2, k) { - const res = {}; - - // for (let s in linCom1) { - // const val = this.Fr.mul(k, linCom1[s]); - // res[s] = !(s in res) ? val : this.Fr.add(val, res[s]); - // } - // - // for (let s in linCom2) { - // const val = this.Fr.mul(k, linCom2[s]); - // res[s] = !(s in res) ? val : this.Fr.add(val, res[s]); - // } - - for (let s in linCom1) { - if (typeof res[s] == "undefined") { - res[s] = this.Fr.mul(k, linCom1[s]); - } else { - res[s] = this.Fr.add(res[s], this.Fr.mul(k, linCom1[s])); - } - } - - for (let s in linCom2) { - if (typeof res[s] == "undefined") { - res[s] = linCom2[s]; - } else { - res[s] = this.Fr.add(res[s], linCom2[s]); - } - } - - return this.normalizeLinearCombination(res); - } - - reduceCoefs(settings, constraintsArr, additionsArr, linCom, maxC) { - const res = { - k: this.Fr.zero, - signals: [], - coefs: [] - }; - const cs = []; - - for (let signalId in linCom) { - if (signalId == 0) { - res.k = this.Fr.add(res.k, linCom[signalId]); - } else if (linCom[signalId] != 0n) { - cs.push([Number(signalId), linCom[signalId]]); - } - } - - while (cs.length > maxC) { - const c1 = cs.shift(); - const c2 = cs.shift(); - const so = settings.nVars++; - - const constraints = this.fnGetAdditionConstraint( - c1[0], c2[0], so, - this.Fr.neg(c1[1]), this.Fr.neg(c2[1]), this.Fr.zero, this.Fr.one, this.Fr.zero); - - constraintsArr.push(constraints); - additionsArr.push([c1[0], c2[0], c1[1], c2[1]]); - - cs.push([so, this.Fr.one]); - } - - for (let i = 0; i < cs.length; i++) { - res.signals[i] = cs[i][0]; - res.coefs[i] = cs[i][1]; - } - - while (res.coefs.length < maxC) { - res.signals.push(0); - res.coefs.push(this.Fr.zero); - } - - return res; - } - - processR1csAdditionConstraint(settings, linCom) { - const constraintsArr = []; - const additionsArr = []; - - const C = this.reduceCoefs(settings, constraintsArr, additionsArr, linCom, 3); - - const constraints = this.fnGetAdditionConstraint( - C.signals[0], C.signals[1], C.signals[2], - C.coefs[0], C.coefs[1], this.Fr.zero, C.coefs[2], C.k); - - constraintsArr.push(constraints); - - return [constraintsArr, additionsArr]; - } - - processR1csMultiplicationConstraint(settings, lcA, lcB, lcC) { - const constraintsArr = []; - const additionsArr = []; - - const A = this.reduceCoefs(settings, constraintsArr, additionsArr, lcA, 1); - const B = this.reduceCoefs(settings, constraintsArr, additionsArr, lcB, 1); - const C = this.reduceCoefs(settings, constraintsArr, additionsArr, lcC, 1); - - const constraints = this.fnGetMultiplicationConstraint( - A.signals[0], B.signals[0], C.signals[0], - this.Fr.mul(A.coefs[0], B.k), - this.Fr.mul(A.k, B.coefs[0]), - this.Fr.mul(A.coefs[0], B.coefs[0]), - this.Fr.neg(C.coefs[0]), - this.Fr.sub(this.Fr.mul(A.k, B.k), C.k)); - - constraintsArr.push(constraints); - - return [constraintsArr, additionsArr]; - } -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -class CPolynomial { - constructor(n, curve, logger) { - this.n = n; - this.polynomials = Array(n).fill(undefined); - this.curve = curve; - this.Fr = curve.Fr; - this.G1 = curve.G1; - this.logger = logger; - } - - addPolynomial(position, polynomial) { - if (position > this.n - 1) { - throw new Error("CPolynomial:addPolynomial, cannot add a polynomial to a position greater than n-1"); - } - - this.polynomials[position] = polynomial; - } - - degree() { - let degrees = this.polynomials.map( - (polynomial, index) => polynomial === undefined ? 0 : polynomial.degree() * this.n + index); - return Math.max(...degrees); - } - - getPolynomial() { - let degrees = this.polynomials.map(polynomial => polynomial === undefined ? 0 : polynomial.degree()); - const maxDegree = this.degree(); - const lengthBuffer = 2 ** (log2(maxDegree - 1) + 1); - const sFr = this.Fr.n8; - - let polynomial = new Polynomial(new ffjavascript.BigBuffer(lengthBuffer * sFr), this.curve, this.logger); - - for (let i = 0; i < maxDegree; i++) { - const i_n8 = i * sFr; - const i_sFr = i_n8 * this.n; - - for (let j = 0; j < this.n; j++) { - if (this.polynomials[j] !== undefined) { - if (i <= degrees[j]) polynomial.coef.set(this.polynomials[j].coef.slice(i_n8, i_n8 + sFr), i_sFr + j * sFr); - } - } - } - - return polynomial; - } - - async multiExponentiation(PTau, name) { - let polynomial = this.getPolynomial(); - const n = polynomial.coef.byteLength / this.Fr.n8; - const PTauN = PTau.slice(0, n * this.G1.F.n8 * 2); - const bm = await this.Fr.batchFromMontgomery(polynomial.coef); - let res = await this.G1.multiExpAffine(PTauN, bm, this.logger, name); - res = this.G1.toAffine(res); - return res; - } -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - - + return [ + signal1, + signal2, + signalOut, + ql, + qr, + qm, + qo, + qc + ]; +} +function getFFlonkMultiplicationConstraint(signal1, signal2, signalOut, ql, qr, qm, qo, qc, _Fr) { + return [ + signal1, + signal2, + signalOut, + ql, + qr, + qm, + qo, + qc + ]; +} +//#endregion +//#region src/r1cs_constraint_processor.js +var LINEAR_COMBINATION_NULLABLE = 0; +var LINEAR_COMBINATION_CONSTANT = 1; +var LINEAR_COMBINATION_VARIABLE = 2; +var r1csConstraintProcessor = class { + constructor(Fr, fnGetConstantConstraint, fnGetAdditionConstraint, fnGetMultiplicationConstraint, logger) { + this.Fr = Fr; + this.logger = logger; + this.fnGetAdditionConstraint = fnGetAdditionConstraint; + this.fnGetMultiplicationConstraint = fnGetMultiplicationConstraint; + } + processR1csConstraint(settings, lcA, lcB, lcC) { + this.normalizeLinearCombination(lcA); + this.normalizeLinearCombination(lcB); + this.normalizeLinearCombination(lcC); + const lctA = this.getLinearCombinationType(lcA); + const lctB = this.getLinearCombinationType(lcB); + if (lctA === LINEAR_COMBINATION_NULLABLE || lctB === LINEAR_COMBINATION_NULLABLE) return this.processR1csAdditionConstraint(settings, lcC); + else if (lctA === LINEAR_COMBINATION_CONSTANT) { + const lcCC = this.joinLinearCombinations(lcB, lcC, lcA[0]); + return this.processR1csAdditionConstraint(settings, lcCC); + } else if (lctB === LINEAR_COMBINATION_CONSTANT) { + const lcCC = this.joinLinearCombinations(lcA, lcC, lcB[0]); + return this.processR1csAdditionConstraint(settings, lcCC); + } else return this.processR1csMultiplicationConstraint(settings, lcA, lcB, lcC); + } + getLinearCombinationType(linCom) { + let k = this.Fr.zero; + let n = 0; + const ss = Object.keys(linCom); + for (let i = 0; i < ss.length; i++) if (linCom[ss[i]] == 0n) delete linCom[ss[i]]; + else if (ss[i] == 0) k = this.Fr.add(k, linCom[ss[i]]); + else n++; + if (n > 0) return LINEAR_COMBINATION_VARIABLE; + if (!this.Fr.isZero(k)) return LINEAR_COMBINATION_CONSTANT; + return LINEAR_COMBINATION_NULLABLE; + } + normalizeLinearCombination(linCom) { + const signalIds = Object.keys(linCom); + for (let i = 0; i < signalIds.length; i++) if (this.Fr.isZero(linCom[signalIds[i]])) delete linCom[signalIds[i]]; + return linCom; + } + joinLinearCombinations(linCom1, linCom2, k) { + const res = {}; + for (let s in linCom1) if (typeof res[s] == "undefined") res[s] = this.Fr.mul(k, linCom1[s]); + else res[s] = this.Fr.add(res[s], this.Fr.mul(k, linCom1[s])); + for (let s in linCom2) if (typeof res[s] == "undefined") res[s] = linCom2[s]; + else res[s] = this.Fr.add(res[s], linCom2[s]); + return this.normalizeLinearCombination(res); + } + reduceCoefs(settings, constraintsArr, additionsArr, linCom, maxC) { + const res = { + k: this.Fr.zero, + signals: [], + coefs: [] + }; + const cs = []; + for (let signalId in linCom) if (signalId == 0) res.k = this.Fr.add(res.k, linCom[signalId]); + else if (linCom[signalId] != 0n) cs.push([Number(signalId), linCom[signalId]]); + while (cs.length > maxC) { + const c1 = cs.shift(); + const c2 = cs.shift(); + const so = settings.nVars++; + const constraints = this.fnGetAdditionConstraint(c1[0], c2[0], so, this.Fr.neg(c1[1]), this.Fr.neg(c2[1]), this.Fr.zero, this.Fr.one, this.Fr.zero); + constraintsArr.push(constraints); + additionsArr.push([ + c1[0], + c2[0], + c1[1], + c2[1] + ]); + cs.push([so, this.Fr.one]); + } + for (let i = 0; i < cs.length; i++) { + res.signals[i] = cs[i][0]; + res.coefs[i] = cs[i][1]; + } + while (res.coefs.length < maxC) { + res.signals.push(0); + res.coefs.push(this.Fr.zero); + } + return res; + } + processR1csAdditionConstraint(settings, linCom) { + const constraintsArr = []; + const additionsArr = []; + const C = this.reduceCoefs(settings, constraintsArr, additionsArr, linCom, 3); + const constraints = this.fnGetAdditionConstraint(C.signals[0], C.signals[1], C.signals[2], C.coefs[0], C.coefs[1], this.Fr.zero, C.coefs[2], C.k); + constraintsArr.push(constraints); + return [constraintsArr, additionsArr]; + } + processR1csMultiplicationConstraint(settings, lcA, lcB, lcC) { + const constraintsArr = []; + const additionsArr = []; + const A = this.reduceCoefs(settings, constraintsArr, additionsArr, lcA, 1); + const B = this.reduceCoefs(settings, constraintsArr, additionsArr, lcB, 1); + const C = this.reduceCoefs(settings, constraintsArr, additionsArr, lcC, 1); + const constraints = this.fnGetMultiplicationConstraint(A.signals[0], B.signals[0], C.signals[0], this.Fr.mul(A.coefs[0], B.k), this.Fr.mul(A.k, B.coefs[0]), this.Fr.mul(A.coefs[0], B.coefs[0]), this.Fr.neg(C.coefs[0]), this.Fr.sub(this.Fr.mul(A.k, B.k), C.k)); + constraintsArr.push(constraints); + return [constraintsArr, additionsArr]; + } +}; +//#endregion +//#region src/polynomial/cpolynomial.js +var CPolynomial = class { + constructor(n, curve, logger) { + this.n = n; + this.polynomials = Array(n).fill(void 0); + this.curve = curve; + this.Fr = curve.Fr; + this.G1 = curve.G1; + this.logger = logger; + } + addPolynomial(position, polynomial) { + if (position > this.n - 1) throw new Error("CPolynomial:addPolynomial, cannot add a polynomial to a position greater than n-1"); + this.polynomials[position] = polynomial; + } + degree() { + let degrees = this.polynomials.map((polynomial, index) => polynomial === void 0 ? 0 : polynomial.degree() * this.n + index); + return Math.max(...degrees); + } + getPolynomial() { + let degrees = this.polynomials.map((polynomial) => polynomial === void 0 ? 0 : polynomial.degree()); + const maxDegree = this.degree(); + const lengthBuffer = 2 ** (log2(maxDegree - 1) + 1); + const sFr = this.Fr.n8; + let polynomial = new Polynomial(new ffjavascript.BigBuffer(lengthBuffer * sFr), this.curve, this.logger); + for (let i = 0; i < maxDegree; i++) { + const i_n8 = i * sFr; + const i_sFr = i_n8 * this.n; + for (let j = 0; j < this.n; j++) if (this.polynomials[j] !== void 0) { + if (i <= degrees[j]) polynomial.coef.set(this.polynomials[j].coef.slice(i_n8, i_n8 + sFr), i_sFr + j * sFr); + } + } + return polynomial; + } + async multiExponentiation(PTau, name) { + let polynomial = this.getPolynomial(); + const n = polynomial.coef.byteLength / this.Fr.n8; + const PTauN = PTau.slice(0, n * this.G1.F.n8 * 2); + const bm = await this.Fr.batchFromMontgomery(polynomial.coef); + let res = await this.G1.multiExpAffine(PTauN, bm, this.logger, name); + res = this.G1.toAffine(res); + return res; + } +}; +//#endregion +//#region src/fflonk_setup.js async function fflonkSetup$1(r1csFilename, ptauFilename, zkeyFilename, logger) { - if (logger) logger.info("FFLONK SETUP STARTED"); - - if (globalThis.gc) globalThis.gc(); - - // Read PTau file - if (logger) logger.info("> Reading PTau file"); - const {fd: fdPTau, sections: pTauSections} = await binFileUtils.readBinFile(ptauFilename, "ptau", 1, 1 << 22, 1 << 24); - if (!pTauSections[12]) { - throw new Error("Powers of Tau is not well prepared. Section 12 missing."); - } - - // Get curve defined in PTau - if (logger) logger.info("> Getting curve from PTau settings"); - const {curve} = await readPTauHeader(fdPTau, pTauSections); - - // Read r1cs file - if (logger) logger.info("> Reading r1cs file"); - const {fd: fdR1cs, sections: sectionsR1cs} = await binFileUtils.readBinFile(r1csFilename, "r1cs", 1, 1 << 22, 1 << 24); - const r1cs = await r1csfile.readR1csFd(fdR1cs, sectionsR1cs, {loadConstraints: false, loadCustomGates: true}); - - // Potential error checks - if (r1cs.prime !== curve.r) { - throw new Error("r1cs curve does not match powers of tau ceremony curve"); - } - - // Initializations - const Fr = curve.Fr; - - const sFr = curve.Fr.n8; - const sG1 = curve.G1.F.n8 * 2; - const sG2 = curve.G2.F.n8 * 2; - - let polynomials = {}; - let evaluations = {}; - let PTau; - - let settings = { - nVars: r1cs.nVars, - nPublic: r1cs.nOutputs + r1cs.nPubInputs - }; - - const plonkConstraints = new BigArray(); - let plonkAdditions = new BigArray(); - - // Process constraints inside r1cs - if (logger) logger.info("> Processing FFlonk constraints"); - await computeFFConstraints(curve.Fr, r1cs, logger); - if (globalThis.gc) globalThis.gc(); - - // As the t polynomial is n+5 we need at least a power of 4 - //TODO check!!!! - // NOTE : plonkConstraints + 2 = #constraints + blinding coefficients for each wire polynomial - settings.cirPower = Math.max(FF_T_POL_DEG_MIN, log2((plonkConstraints.length + 2) - 1) + 1); - settings.domainSize = 2 ** settings.cirPower; - - if (pTauSections[2][0].size < (settings.domainSize * 9 + 18) * sG1) { - throw new Error("Powers of Tau is not big enough for this circuit size. Section 2 too small."); - } - if (pTauSections[3][0].size < sG2) { - throw new Error("Powers of Tau is not well prepared. Section 3 too small."); - } - - if (logger) { - logger.info("----------------------------"); - logger.info(" FFLONK SETUP SETTINGS"); - logger.info(` Curve: ${curve.name}`); - logger.info(` Circuit power: ${settings.cirPower}`); - logger.info(` Domain size: ${settings.domainSize}`); - logger.info(` Vars: ${settings.nVars}`); - logger.info(` Public vars: ${settings.nPublic}`); - logger.info(` Constraints: ${plonkConstraints.length}`); - logger.info(` Additions: ${plonkAdditions.length}`); - logger.info("----------------------------"); - } - - // Compute k1 and k2 to be used in the permutation checks - if (logger) logger.info("> computing k1 and k2"); - const [k1, k2] = computeK1K2(); - - // Compute omega 3 (w3) and omega 4 (w4) to be used in the prover and the verifier - // w3^3 = 1 and w4^4 = 1 - if (logger) logger.info("> computing w3"); - const w3 = computeW3(); - if (logger) logger.info("> computing w4"); - const w4 = computeW4(); - if (logger) logger.info("> computing w8"); - const w8 = computeW8(); - if (logger) logger.info("> computing wr"); - const wr = getOmegaCubicRoot(settings.cirPower, curve.Fr); - - // Write output zkey file - await writeZkeyFile(); - - await fdR1cs.close(); - await fdPTau.close(); - - if (logger) logger.info("FFLONK SETUP FINISHED"); - - return 0; - - async function computeFFConstraints(Fr, r1cs, logger) { - // Add public inputs and outputs - for (let i = 0; i < settings.nPublic; i++) { - plonkConstraints.push(getFFlonkConstantConstraint(i + 1, Fr)); - } - - // Add all constraints from r1cs file - const r1csProcessor = new r1csConstraintProcessor(Fr, getFFlonkConstantConstraint, getFFlonkAdditionConstraint, getFFlonkMultiplicationConstraint, logger); - - const bR1cs = await binFileUtils__namespace.readSection(fdR1cs, sectionsR1cs, 2); - let bR1csPos = 0; - for (let i = 0; i < r1cs.nConstraints; i++) { - if ((logger) && (i !== 0) && (i % 500000 === 0)) { - logger.info(` processing r1cs constraints ${i}/${r1cs.nConstraints}`); - } - const [constraints, additions] = r1csProcessor.processR1csConstraint(settings, ...readConstraint()); - - plonkConstraints.push(...constraints); - plonkAdditions.push(...additions); - } - - function readConstraint() { - const c = []; - c[0] = readLC(); - c[1] = readLC(); - c[2] = readLC(); - return c; - } - - function readLC() { - const lc = {}; - - const buffUL32 = bR1cs.slice(bR1csPos, bR1csPos + 4); - bR1csPos += 4; - const buffUL32V = new DataView(buffUL32.buffer); - const nIdx = buffUL32V.getUint32(0, true); - - const buff = bR1cs.slice(bR1csPos, bR1csPos + (4 + r1cs.n8) * nIdx); - bR1csPos += (4 + r1cs.n8) * nIdx; - const buffV = new DataView(buff.buffer); - for (let i = 0; i < nIdx; i++) { - const idx = buffV.getUint32(i * (4 + r1cs.n8), true); - const val = r1cs.F.fromRprLE(buff, i * (4 + r1cs.n8) + 4); - lc[idx] = val; - } - return lc; - } - - return 0; - } - - async function writeZkeyFile() { - if (logger) logger.info("> Writing the zkey file"); - const fdZKey = await binFileUtils.createBinFile(zkeyFilename, "zkey", 1, ZKEY_FF_NSECTIONS, 1 << 22, 1 << 24); - - if (logger) logger.info(`··· Writing Section ${HEADER_ZKEY_SECTION}. Zkey Header`); - await writeZkeyHeader(fdZKey); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_ADDITIONS_SECTION}. Additions`); - await writeAdditions(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_A_MAP_SECTION}. A Map`); - await writeWitnessMap(fdZKey, ZKEY_FF_A_MAP_SECTION, 0, "A map"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_B_MAP_SECTION}. B Map`); - await writeWitnessMap(fdZKey, ZKEY_FF_B_MAP_SECTION, 1, "B map"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_C_MAP_SECTION}. C Map`); - await writeWitnessMap(fdZKey, ZKEY_FF_C_MAP_SECTION, 2, "C map"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_QL_SECTION}. QL`); - await writeQMap(fdZKey, ZKEY_FF_QL_SECTION, 3, "QL"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_QR_SECTION}. QR`); - await writeQMap(fdZKey, ZKEY_FF_QR_SECTION, 4, "QR"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_QM_SECTION}. QM`); - await writeQMap(fdZKey, ZKEY_FF_QM_SECTION, 5, "QM"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_QO_SECTION}. QO`); - await writeQMap(fdZKey, ZKEY_FF_QO_SECTION, 6, "QO"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_QC_SECTION}. QC`); - await writeQMap(fdZKey, ZKEY_FF_QC_SECTION, 7, "QC"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Sections ${ZKEY_FF_SIGMA1_SECTION},${ZKEY_FF_SIGMA2_SECTION},${ZKEY_FF_SIGMA3_SECTION}. Sigma1, Sigma2 & Sigma 3`); - await writeSigma(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_LAGRANGE_SECTION}. Lagrange Polynomials`); - await writeLagrangePolynomials(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_PTAU_SECTION}. Powers of Tau`); - await writePtau(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_C0_SECTION}. C0`); - await writeC0(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_HEADER_SECTION}. FFlonk Header`); - await writeFFlonkHeader(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info("> Writing the zkey file finished"); - - await fdZKey.close(); - } - - async function writeZkeyHeader(fdZKey) { - await binFileUtils.startWriteSection(fdZKey, HEADER_ZKEY_SECTION); - await fdZKey.writeULE32(FFLONK_PROTOCOL_ID); - await binFileUtils.endWriteSection(fdZKey); - } - - async function writeAdditions(fdZKey) { - await binFileUtils.startWriteSection(fdZKey, ZKEY_FF_ADDITIONS_SECTION); - - // Written values are 2 * 32 bit integers (2 * 4 bytes) + 2 field size values ( 2 * sFr bytes) - const buffOut = new Uint8Array(8 + 2 * sFr); - const buffOutV = new DataView(buffOut.buffer); - - for (let i = 0; i < plonkAdditions.length; i++) { - if ((logger) && (i !== 0) && (i % 500000 === 0)) logger.info(` writing Additions: ${i}/${plonkAdditions.length}`); - - const addition = plonkAdditions[i]; - - buffOutV.setUint32(0, addition[0], true); - buffOutV.setUint32(4, addition[1], true); - buffOut.set(addition[2], 8); - buffOut.set(addition[3], 8 + sFr); - - await fdZKey.write(buffOut); - } - await binFileUtils.endWriteSection(fdZKey); - } - - async function writeWitnessMap(fdZKey, sectionNum, posConstraint, name) { - await binFileUtils.startWriteSection(fdZKey, sectionNum); - for (let i = 0; i < plonkConstraints.length; i++) { - if (logger && (i !== 0) && (i % 500000 === 0)) { - logger.info(` writing witness ${name}: ${i}/${plonkConstraints.length}`); - } - - await fdZKey.writeULE32(plonkConstraints[i][posConstraint]); - } - await binFileUtils.endWriteSection(fdZKey); - } - - async function writeQMap(fdZKey, sectionNum, posConstraint, name) { - // Compute Q from q evaluations - let Q = new ffjavascript.BigBuffer(settings.domainSize * sFr); - - for (let i = 0; i < plonkConstraints.length; i++) { - Q.set(plonkConstraints[i][posConstraint], i * sFr); - if ((logger) && (i !== 0) && (i % 500000 === 0)) { - logger.info(` writing ${name}: ${i}/${plonkConstraints.length}`); - } - } - - polynomials[name] = await Polynomial.fromEvaluations(Q, curve, logger); - evaluations[name] = await Evaluations.fromPolynomial(polynomials[name], 4, curve, logger); - - // Write Q coefficients and evaluations - await binFileUtils.startWriteSection(fdZKey, sectionNum); - await fdZKey.write(polynomials[name].coef); - await fdZKey.write(evaluations[name].eval); - await binFileUtils.endWriteSection(fdZKey); - } - - async function writeSigma(fdZKey) { - // Compute sigma - const sigma = new ffjavascript.BigBuffer(sFr * settings.domainSize * 3); - const lastSeen = new BigArray(settings.nVars); - const firstPos = new BigArray(settings.nVars); - - let w = Fr.one; - for (let i = 0; i < settings.domainSize; i++) { - if (i < plonkConstraints.length) { - buildSigma(plonkConstraints[i][0], i); - buildSigma(plonkConstraints[i][1], settings.domainSize + i); - buildSigma(plonkConstraints[i][2], settings.domainSize * 2 + i); - } else if (i < settings.domainSize - 2) { - buildSigma(0, i); - buildSigma(0, settings.domainSize + i); - buildSigma(0, settings.domainSize * 2 + i); - } else { - sigma.set(w, i * sFr); - sigma.set(Fr.mul(w, k1), (settings.domainSize + i) * sFr); - sigma.set(Fr.mul(w, k2), (settings.domainSize * 2 + i) * sFr); - } - - w = Fr.mul(w, Fr.w[settings.cirPower]); - - if ((logger) && (i !== 0) && (i % 500000 === 0)) { - logger.info(` writing sigma phase1: ${i}/${plonkConstraints.length}`); - } - } - - for (let i = 0; i < settings.nVars; i++) { - if (typeof firstPos[i] !== "undefined") { - sigma.set(lastSeen[i], firstPos[i] * sFr); - } else { - // throw new Error("Variable not used"); - console.log("Variable not used"); - } - if ((logger) && (i !== 0) && (i % 500000 === 0)) logger.info(` writing sigma phase2: ${i}/${settings.nVars}`); - } - - if (globalThis.gc) globalThis.gc(); - - // Write sigma coefficients and evaluations - for (let i = 0; i < 3; i++) { - const sectionId = 0 === i ? ZKEY_FF_SIGMA1_SECTION : 1 === i ? ZKEY_FF_SIGMA2_SECTION : ZKEY_FF_SIGMA3_SECTION; - - let name = "S" + (i + 1); - polynomials[name] = await Polynomial.fromEvaluations(sigma.slice(settings.domainSize * sFr * i, settings.domainSize * sFr * (i + 1)), curve, logger); - evaluations[name] = await Evaluations.fromPolynomial(polynomials[name], 4, curve, logger); - await binFileUtils.startWriteSection(fdZKey, sectionId); - await fdZKey.write(polynomials[name].coef); - await fdZKey.write(evaluations[name].eval); - await binFileUtils.endWriteSection(fdZKey); - - if (globalThis.gc) globalThis.gc(); - } - - return 0; - - function buildSigma(signalId, idx) { - if (typeof lastSeen[signalId] === "undefined") { - firstPos[signalId] = idx; - } else { - sigma.set(lastSeen[signalId], idx * sFr); - } - let v; - if (idx < settings.domainSize) { - v = w; - } else if (idx < 2 * settings.domainSize) { - v = Fr.mul(w, k1); - } else { - v = Fr.mul(w, k2); - } - - lastSeen[signalId] = v; - } - } - - async function writeLagrangePolynomials(fdZKey) { - await binFileUtils.startWriteSection(fdZKey, ZKEY_FF_LAGRANGE_SECTION); - - const l = Math.max(settings.nPublic, 1); - for (let i = 0; i < l; i++) { - let buff = new ffjavascript.BigBuffer(settings.domainSize * sFr); - buff.set(Fr.one, i * sFr); - - await writeP4(fdZKey, buff); - } - await binFileUtils.endWriteSection(fdZKey); - } - - async function writePtau(fdZKey) { - await binFileUtils.startWriteSection(fdZKey, ZKEY_FF_PTAU_SECTION); - - // domainSize * 9 + 18 = maximum SRS length needed, specifically to commit C2 - PTau = new ffjavascript.BigBuffer((settings.domainSize * 9 + 18) * sG1); - await fdPTau.readToBuffer(PTau, 0, (settings.domainSize * 9 + 18) * sG1, pTauSections[2][0].p); - - await fdZKey.write(PTau); - await binFileUtils.endWriteSection(fdZKey); - } - - async function writeC0(fdZKey) { - // C0(X) := QL(X^8) + X · QR(X^8) + X^2 · QO(X^8) + X^3 · QM(X^8) + X^4 · QC(X^8) - // + X^5 · SIGMA1(X^8) + X^6 · SIGMA2(X^8) + X^7 · SIGMA3(X^8) - let C0 = new CPolynomial(8, curve, logger); - C0.addPolynomial(0, polynomials.QL); - C0.addPolynomial(1, polynomials.QR); - C0.addPolynomial(2, polynomials.QO); - C0.addPolynomial(3, polynomials.QM); - C0.addPolynomial(4, polynomials.QC); - C0.addPolynomial(5, polynomials.S1); - C0.addPolynomial(6, polynomials.S2); - C0.addPolynomial(7, polynomials.S3); - - polynomials.C0 = C0.getPolynomial(); - - // Check degree - if (polynomials.C0.degree() >= 8 * settings.domainSize) { - throw new Error("C0 Polynomial is not well calculated"); - } - - await binFileUtils.startWriteSection(fdZKey, ZKEY_FF_C0_SECTION); - await fdZKey.write(polynomials.C0.coef); - await binFileUtils.endWriteSection(fdZKey); - } - - async function writeFFlonkHeader(fdZKey) { - await binFileUtils.startWriteSection(fdZKey, ZKEY_FF_HEADER_SECTION); - - const primeQ = curve.q; - const n8q = (Math.floor((ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) + 1) * 8; - await fdZKey.writeULE32(n8q); - await binFileUtils.writeBigInt(fdZKey, primeQ, n8q); - - const primeR = curve.r; - const n8r = (Math.floor((ffjavascript.Scalar.bitLength(primeR) - 1) / 64) + 1) * 8; - await fdZKey.writeULE32(n8r); - await binFileUtils.writeBigInt(fdZKey, primeR, n8r); - - // Total number of r1cs vars - await fdZKey.writeULE32(settings.nVars); - // Total number of r1cs public vars = outputs + public inputs - await fdZKey.writeULE32(settings.nPublic); - await fdZKey.writeULE32(settings.domainSize); - await fdZKey.writeULE32(plonkAdditions.length); - await fdZKey.writeULE32(plonkConstraints.length); - - await fdZKey.write(k1); - await fdZKey.write(k2); - - await fdZKey.write(w3); - await fdZKey.write(w4); - await fdZKey.write(w8); - await fdZKey.write(wr); - - let bX_2; - bX_2 = await fdPTau.read(sG2, pTauSections[3][0].p + sG2); - await fdZKey.write(bX_2); - - let commitC0 = await polynomials.C0.multiExponentiation(PTau, "C0"); - await fdZKey.write(commitC0); - - await binFileUtils.endWriteSection(fdZKey); - } - - async function writeP4(fdZKey, buff) { - const [coefficients, evaluations4] = await Polynomial.to4T(buff, settings.domainSize, [], Fr); - await fdZKey.write(coefficients); - await fdZKey.write(evaluations4); - - return [coefficients, evaluations4]; - } - - function computeK1K2() { - let k1 = Fr.two; - while (isIncluded(k1, [], settings.cirPower)) Fr.add(k1, Fr.one); - let k2 = Fr.add(k1, Fr.one); - while (isIncluded(k2, [k1], settings.cirPower)) Fr.add(k2, Fr.one); - return [k1, k2]; - - function isIncluded(k, kArr, pow) { - const domainSize = 2 ** pow; - let w = Fr.one; - for (let i = 0; i < domainSize; i++) { - if (Fr.eq(k, w)) return true; - for (let j = 0; j < kArr.length; j++) { - if (Fr.eq(k, Fr.mul(kArr[j], w))) return true; - } - w = Fr.mul(w, Fr.w[pow]); - } - return false; - } - } - - function computeW3() { - let generator = Fr.e(31624); - - // Exponent is order(r - 1) / 3 - let orderRsub1 = 3648040478639879203707734290876212514758060733402672390616367364429301415936n; - let exponent = ffjavascript.Scalar.div(orderRsub1, ffjavascript.Scalar.e(3)); - - return Fr.exp(generator, exponent); - } - - function computeW4() { - return Fr.w[2]; - } - - function computeW8() { - return Fr.w[3]; - } - - function getOmegaCubicRoot(power, Fr) { - // Hardcorded 3th-root of Fr.w[28] - const firstRoot = Fr.e(467799165886069610036046866799264026481344299079011762026774533774345988080n); - - return Fr.exp(firstRoot, 2 ** (28 - power)); - } -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -const { stringifyBigInts: stringifyBigInts$1 } = ffjavascript.utils; - - + if (logger) logger.info("FFLONK SETUP STARTED"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info("> Reading PTau file"); + const { fd: fdPTau, sections: pTauSections } = await (0, _iden3_binfileutils.readBinFile)(ptauFilename, "ptau", 1, 1 << 22, 1 << 24); + if (!pTauSections[12]) throw new Error("Powers of Tau is not well prepared. Section 12 missing."); + if (logger) logger.info("> Getting curve from PTau settings"); + const { curve } = await readPTauHeader(fdPTau, pTauSections); + if (logger) logger.info("> Reading r1cs file"); + const { fd: fdR1cs, sections: sectionsR1cs } = await (0, _iden3_binfileutils.readBinFile)(r1csFilename, "r1cs", 1, 1 << 22, 1 << 24); + const r1cs = await (0, r1csfile.readR1csFd)(fdR1cs, sectionsR1cs, { + loadConstraints: false, + loadCustomGates: true + }); + if (r1cs.prime !== curve.r) throw new Error("r1cs curve does not match powers of tau ceremony curve"); + const Fr = curve.Fr; + const sFr = curve.Fr.n8; + const sG1 = curve.G1.F.n8 * 2; + const sG2 = curve.G2.F.n8 * 2; + let polynomials = {}; + let evaluations = {}; + let PTau; + let settings = { + nVars: r1cs.nVars, + nPublic: r1cs.nOutputs + r1cs.nPubInputs + }; + const plonkConstraints = new BigArray(); + let plonkAdditions = new BigArray(); + if (logger) logger.info("> Processing FFlonk constraints"); + await computeFFConstraints(curve.Fr, r1cs, logger); + if (globalThis.gc) globalThis.gc(); + settings.cirPower = Math.max(3, log2(plonkConstraints.length + 2 - 1) + 1); + settings.domainSize = 2 ** settings.cirPower; + if (pTauSections[2][0].size < (settings.domainSize * 9 + 18) * sG1) throw new Error("Powers of Tau is not big enough for this circuit size. Section 2 too small."); + if (pTauSections[3][0].size < sG2) throw new Error("Powers of Tau is not well prepared. Section 3 too small."); + if (logger) { + logger.info("----------------------------"); + logger.info(" FFLONK SETUP SETTINGS"); + logger.info(` Curve: ${curve.name}`); + logger.info(` Circuit power: ${settings.cirPower}`); + logger.info(` Domain size: ${settings.domainSize}`); + logger.info(` Vars: ${settings.nVars}`); + logger.info(` Public vars: ${settings.nPublic}`); + logger.info(` Constraints: ${plonkConstraints.length}`); + logger.info(` Additions: ${plonkAdditions.length}`); + logger.info("----------------------------"); + } + if (logger) logger.info("> computing k1 and k2"); + const [k1, k2] = computeK1K2(); + if (logger) logger.info("> computing w3"); + const w3 = computeW3(); + if (logger) logger.info("> computing w4"); + const w4 = computeW4(); + if (logger) logger.info("> computing w8"); + const w8 = computeW8(); + if (logger) logger.info("> computing wr"); + const wr = getOmegaCubicRoot(settings.cirPower, curve.Fr); + await writeZkeyFile(); + await fdR1cs.close(); + await fdPTau.close(); + if (logger) logger.info("FFLONK SETUP FINISHED"); + return 0; + async function computeFFConstraints(Fr, r1cs, logger) { + for (let i = 0; i < settings.nPublic; i++) plonkConstraints.push(getFFlonkConstantConstraint(i + 1, Fr)); + const r1csProcessor = new r1csConstraintProcessor(Fr, getFFlonkConstantConstraint, getFFlonkAdditionConstraint, getFFlonkMultiplicationConstraint, logger); + const bR1cs = await _iden3_binfileutils.readSection(fdR1cs, sectionsR1cs, 2); + let bR1csPos = 0; + for (let i = 0; i < r1cs.nConstraints; i++) { + if (logger && i !== 0 && i % 5e5 === 0) logger.info(` processing r1cs constraints ${i}/${r1cs.nConstraints}`); + const [constraints, additions] = r1csProcessor.processR1csConstraint(settings, ...readConstraint()); + plonkConstraints.push(...constraints); + plonkAdditions.push(...additions); + } + function readConstraint() { + const c = []; + c[0] = readLC(); + c[1] = readLC(); + c[2] = readLC(); + return c; + } + function readLC() { + const lc = {}; + const buffUL32 = bR1cs.slice(bR1csPos, bR1csPos + 4); + bR1csPos += 4; + const nIdx = new DataView(buffUL32.buffer).getUint32(0, true); + const buff = bR1cs.slice(bR1csPos, bR1csPos + (4 + r1cs.n8) * nIdx); + bR1csPos += (4 + r1cs.n8) * nIdx; + const buffV = new DataView(buff.buffer); + for (let i = 0; i < nIdx; i++) { + const idx = buffV.getUint32(i * (4 + r1cs.n8), true); + lc[idx] = r1cs.F.fromRprLE(buff, i * (4 + r1cs.n8) + 4); + } + return lc; + } + return 0; + } + async function writeZkeyFile() { + if (logger) logger.info("> Writing the zkey file"); + const fdZKey = await (0, _iden3_binfileutils.createBinFile)(zkeyFilename, "zkey", 1, 17, 1 << 22, 1 << 24); + if (logger) logger.info(`··· Writing Section 1. Zkey Header`); + await writeZkeyHeader(fdZKey); + if (logger) logger.info(`··· Writing Section 3. Additions`); + await writeAdditions(fdZKey); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 4. A Map`); + await writeWitnessMap(fdZKey, 4, 0, "A map"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 5. B Map`); + await writeWitnessMap(fdZKey, 5, 1, "B map"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 6. C Map`); + await writeWitnessMap(fdZKey, 6, 2, "C map"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 7. QL`); + await writeQMap(fdZKey, 7, 3, "QL"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 8. QR`); + await writeQMap(fdZKey, 8, 4, "QR"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 9. QM`); + await writeQMap(fdZKey, 9, 5, "QM"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 10. QO`); + await writeQMap(fdZKey, 10, 6, "QO"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 11. QC`); + await writeQMap(fdZKey, 11, 7, "QC"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Sections 12,13,14. Sigma1, Sigma2 & Sigma 3`); + await writeSigma(fdZKey); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 15. Lagrange Polynomials`); + await writeLagrangePolynomials(fdZKey); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 16. Powers of Tau`); + await writePtau(fdZKey); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 17. C0`); + await writeC0(fdZKey); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 2. FFlonk Header`); + await writeFFlonkHeader(fdZKey); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info("> Writing the zkey file finished"); + await fdZKey.close(); + } + async function writeZkeyHeader(fdZKey) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 1); + await fdZKey.writeULE32(10); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeAdditions(fdZKey) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 3); + const buffOut = new Uint8Array(8 + 2 * sFr); + const buffOutV = new DataView(buffOut.buffer); + for (let i = 0; i < plonkAdditions.length; i++) { + if (logger && i !== 0 && i % 5e5 === 0) logger.info(` writing Additions: ${i}/${plonkAdditions.length}`); + const addition = plonkAdditions[i]; + buffOutV.setUint32(0, addition[0], true); + buffOutV.setUint32(4, addition[1], true); + buffOut.set(addition[2], 8); + buffOut.set(addition[3], 8 + sFr); + await fdZKey.write(buffOut); + } + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeWitnessMap(fdZKey, sectionNum, posConstraint, name) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); + for (let i = 0; i < plonkConstraints.length; i++) { + if (logger && i !== 0 && i % 5e5 === 0) logger.info(` writing witness ${name}: ${i}/${plonkConstraints.length}`); + await fdZKey.writeULE32(plonkConstraints[i][posConstraint]); + } + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeQMap(fdZKey, sectionNum, posConstraint, name) { + let Q = new ffjavascript.BigBuffer(settings.domainSize * sFr); + for (let i = 0; i < plonkConstraints.length; i++) { + Q.set(plonkConstraints[i][posConstraint], i * sFr); + if (logger && i !== 0 && i % 5e5 === 0) logger.info(` writing ${name}: ${i}/${plonkConstraints.length}`); + } + polynomials[name] = await Polynomial.fromEvaluations(Q, curve, logger); + evaluations[name] = await Evaluations.fromPolynomial(polynomials[name], 4, curve, logger); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); + await fdZKey.write(polynomials[name].coef); + await fdZKey.write(evaluations[name].eval); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeSigma(fdZKey) { + const sigma = new ffjavascript.BigBuffer(sFr * settings.domainSize * 3); + const lastSeen = new BigArray(settings.nVars); + const firstPos = new BigArray(settings.nVars); + let w = Fr.one; + for (let i = 0; i < settings.domainSize; i++) { + if (i < plonkConstraints.length) { + buildSigma(plonkConstraints[i][0], i); + buildSigma(plonkConstraints[i][1], settings.domainSize + i); + buildSigma(plonkConstraints[i][2], settings.domainSize * 2 + i); + } else if (i < settings.domainSize - 2) { + buildSigma(0, i); + buildSigma(0, settings.domainSize + i); + buildSigma(0, settings.domainSize * 2 + i); + } else { + sigma.set(w, i * sFr); + sigma.set(Fr.mul(w, k1), (settings.domainSize + i) * sFr); + sigma.set(Fr.mul(w, k2), (settings.domainSize * 2 + i) * sFr); + } + w = Fr.mul(w, Fr.w[settings.cirPower]); + if (logger && i !== 0 && i % 5e5 === 0) logger.info(` writing sigma phase1: ${i}/${plonkConstraints.length}`); + } + for (let i = 0; i < settings.nVars; i++) { + if (typeof firstPos[i] !== "undefined") sigma.set(lastSeen[i], firstPos[i] * sFr); + else console.log("Variable not used"); + if (logger && i !== 0 && i % 5e5 === 0) logger.info(` writing sigma phase2: ${i}/${settings.nVars}`); + } + if (globalThis.gc) globalThis.gc(); + for (let i = 0; i < 3; i++) { + const sectionId = 0 === i ? 12 : 1 === i ? 13 : 14; + let name = "S" + (i + 1); + polynomials[name] = await Polynomial.fromEvaluations(sigma.slice(settings.domainSize * sFr * i, settings.domainSize * sFr * (i + 1)), curve, logger); + evaluations[name] = await Evaluations.fromPolynomial(polynomials[name], 4, curve, logger); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionId); + await fdZKey.write(polynomials[name].coef); + await fdZKey.write(evaluations[name].eval); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + if (globalThis.gc) globalThis.gc(); + } + return 0; + function buildSigma(signalId, idx) { + if (typeof lastSeen[signalId] === "undefined") firstPos[signalId] = idx; + else sigma.set(lastSeen[signalId], idx * sFr); + let v; + if (idx < settings.domainSize) v = w; + else if (idx < 2 * settings.domainSize) v = Fr.mul(w, k1); + else v = Fr.mul(w, k2); + lastSeen[signalId] = v; + } + } + async function writeLagrangePolynomials(fdZKey) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 15); + const l = Math.max(settings.nPublic, 1); + for (let i = 0; i < l; i++) { + let buff = new ffjavascript.BigBuffer(settings.domainSize * sFr); + buff.set(Fr.one, i * sFr); + await writeP4(fdZKey, buff); + } + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writePtau(fdZKey) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 16); + PTau = new ffjavascript.BigBuffer((settings.domainSize * 9 + 18) * sG1); + await fdPTau.readToBuffer(PTau, 0, (settings.domainSize * 9 + 18) * sG1, pTauSections[2][0].p); + await fdZKey.write(PTau); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeC0(fdZKey) { + let C0 = new CPolynomial(8, curve, logger); + C0.addPolynomial(0, polynomials.QL); + C0.addPolynomial(1, polynomials.QR); + C0.addPolynomial(2, polynomials.QO); + C0.addPolynomial(3, polynomials.QM); + C0.addPolynomial(4, polynomials.QC); + C0.addPolynomial(5, polynomials.S1); + C0.addPolynomial(6, polynomials.S2); + C0.addPolynomial(7, polynomials.S3); + polynomials.C0 = C0.getPolynomial(); + if (polynomials.C0.degree() >= 8 * settings.domainSize) throw new Error("C0 Polynomial is not well calculated"); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 17); + await fdZKey.write(polynomials.C0.coef); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeFFlonkHeader(fdZKey) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 2); + const primeQ = curve.q; + const n8q = (Math.floor((ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) + 1) * 8; + await fdZKey.writeULE32(n8q); + await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeQ, n8q); + const primeR = curve.r; + const n8r = (Math.floor((ffjavascript.Scalar.bitLength(primeR) - 1) / 64) + 1) * 8; + await fdZKey.writeULE32(n8r); + await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeR, n8r); + await fdZKey.writeULE32(settings.nVars); + await fdZKey.writeULE32(settings.nPublic); + await fdZKey.writeULE32(settings.domainSize); + await fdZKey.writeULE32(plonkAdditions.length); + await fdZKey.writeULE32(plonkConstraints.length); + await fdZKey.write(k1); + await fdZKey.write(k2); + await fdZKey.write(w3); + await fdZKey.write(w4); + await fdZKey.write(w8); + await fdZKey.write(wr); + let bX_2; + bX_2 = await fdPTau.read(sG2, pTauSections[3][0].p + sG2); + await fdZKey.write(bX_2); + let commitC0 = await polynomials.C0.multiExponentiation(PTau, "C0"); + await fdZKey.write(commitC0); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeP4(fdZKey, buff) { + const [coefficients, evaluations4] = await Polynomial.to4T(buff, settings.domainSize, [], Fr); + await fdZKey.write(coefficients); + await fdZKey.write(evaluations4); + return [coefficients, evaluations4]; + } + function computeK1K2() { + let k1 = Fr.two; + while (isIncluded(k1, [], settings.cirPower)) Fr.add(k1, Fr.one); + let k2 = Fr.add(k1, Fr.one); + while (isIncluded(k2, [k1], settings.cirPower)) Fr.add(k2, Fr.one); + return [k1, k2]; + function isIncluded(k, kArr, pow) { + const domainSize = 2 ** pow; + let w = Fr.one; + for (let i = 0; i < domainSize; i++) { + if (Fr.eq(k, w)) return true; + for (let j = 0; j < kArr.length; j++) if (Fr.eq(k, Fr.mul(kArr[j], w))) return true; + w = Fr.mul(w, Fr.w[pow]); + } + return false; + } + } + function computeW3() { + let generator = Fr.e(31624); + let exponent = ffjavascript.Scalar.div(3648040478639879203707734290876212514758060733402672390616367364429301415936n, ffjavascript.Scalar.e(3)); + return Fr.exp(generator, exponent); + } + function computeW4() { + return Fr.w[2]; + } + function computeW8() { + return Fr.w[3]; + } + function getOmegaCubicRoot(power, Fr) { + const firstRoot = Fr.e(467799165886069610036046866799264026481344299079011762026774533774345988080n); + return Fr.exp(firstRoot, 2 ** (28 - power)); + } +} +//#endregion +//#region src/fflonk_prove.js +var { stringifyBigInts: stringifyBigInts$1 } = ffjavascript.utils; async function fflonkProve$1(zkeyFileName, witnessFileName, logger, options) { - if (logger) logger.info("FFLONK PROVER STARTED"); - - // Read witness file - if (logger) logger.info("> Reading witness file"); - const { - fd: fdWtns, - sections: wtnsSections - } = await binFileUtils__namespace.readBinFile(witnessFileName, "wtns", 2, 1 << 25, 1 << 23); - const wtns = await readHeader(fdWtns, wtnsSections); - - //Read zkey file - if (logger) logger.info("> Reading zkey file"); - const { - fd: fdZKey, - sections: zkeySections - } = await binFileUtils__namespace.readBinFile(zkeyFileName, "zkey", 2, 1 << 25, 1 << 23); - - const zkey = await readHeader$1(fdZKey, zkeySections, undefined, options); - - if (zkey.protocolId !== FFLONK_PROTOCOL_ID) { - throw new Error("zkey file is not fflonk"); - } - - if (!ffjavascript.Scalar.eq(zkey.r, wtns.q)) { - throw new Error("Curve of the witness does not match the curve of the proving key"); - } - - if (wtns.nWitness !== zkey.nVars - zkey.nAdditions) { - throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}, ${zkey.nAdditions}`); - } - - const curve = zkey.curve; - - const Fr = curve.Fr; - - const sFr = curve.Fr.n8; - const sG1 = curve.G1.F.n8 * 2; - const sDomain = zkey.domainSize * sFr; - - if (logger) { - logger.info("----------------------------"); - logger.info(" FFLONK PROVE SETTINGS"); - logger.info(` Curve: ${curve.name}`); - logger.info(` Circuit power: ${zkey.power}`); - logger.info(` Domain size: ${zkey.domainSize}`); - logger.info(` Vars: ${zkey.nVars}`); - logger.info(` Public vars: ${zkey.nPublic}`); - logger.info(` Constraints: ${zkey.nConstraints}`); - logger.info(` Additions: ${zkey.nAdditions}`); - logger.info("----------------------------"); - } - - //Read witness data - if (logger) logger.info("> Reading witness file data"); - const buffWitness = await binFileUtils__namespace.readSection(fdWtns, wtnsSections, 2); - await fdWtns.close(); - - // First element in plonk is not used and can be any value. (But always the same). - // We set it to zero to go faster in the exponentiations. - buffWitness.set(Fr.zero, 0); - const buffInternalWitness = new ffjavascript.BigBuffer(zkey.nAdditions * sFr); - - let buffers = {}; - let polynomials = {}; - let evaluations = {}; - - // To divide prime fields the Extended Euclidean Algorithm for computing modular inverses is needed. - // NOTE: This is the equivalent of compute 1/denominator and then multiply it by the numerator. - // The Extended Euclidean Algorithm is expensive in terms of computation. - // For the special case where we need to do many modular inverses, there's a simple mathematical trick - // that allows us to compute many inverses, called Montgomery batch inversion. - // More info: https://vitalik.ca/general/2018/07/21/starks_part_3.html - // Montgomery batch inversion reduces the n inverse computations to a single one - // To save this (single) inverse computation on-chain, will compute it in proving time and send it to the verifier. - // The verifier will have to check: - // 1) the denominator is correct multiplying by himself non-inverted -> a * 1/a == 1 - // 2) compute the rest of the denominators using the Montgomery batch inversion - // The inversions are: - // · denominator needed in step 8 and 9 of the verifier to multiply by 1/Z_H(xi) - // · denominator needed in step 10 and 11 of the verifier - // · denominator needed in the verifier when computing L_i^{S1}(X) and L_i^{S2}(X) - // · L_i i=1 to num public inputs, needed in step 6 and 7 of the verifier to compute L_1(xi) and PI(xi) - let toInverse = {}; - - let challenges = {}; - let roots = {}; - - let proof = new Proof(curve, logger); - - if (logger) logger.info(`> Reading Section ${ZKEY_FF_ADDITIONS_SECTION}. Additions`); - await calculateAdditions(); - - if (logger) logger.info(`> Reading Sections ${ZKEY_FF_SIGMA1_SECTION},${ZKEY_FF_SIGMA2_SECTION},${ZKEY_FF_SIGMA3_SECTION}. Sigma1, Sigma2 & Sigma 3`); - if (logger) logger.info("··· Reading Sigma polynomials "); - polynomials.Sigma1 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.Sigma2 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.Sigma3 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - - await fdZKey.readToBuffer(polynomials.Sigma1.coef, 0, sDomain, zkeySections[ZKEY_FF_SIGMA1_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.Sigma2.coef, 0, sDomain, zkeySections[ZKEY_FF_SIGMA2_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.Sigma3.coef, 0, sDomain, zkeySections[ZKEY_FF_SIGMA3_SECTION][0].p); - - if (logger) logger.info("··· Reading Sigma evaluations"); - evaluations.Sigma1 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.Sigma2 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.Sigma3 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - - await fdZKey.readToBuffer(evaluations.Sigma1.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_SIGMA1_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.Sigma2.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_SIGMA2_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.Sigma3.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_SIGMA3_SECTION][0].p + sDomain); - - if (logger) logger.info(`> Reading Section ${ZKEY_FF_PTAU_SECTION}. Powers of Tau`); - const PTau = new ffjavascript.BigBuffer(zkey.domainSize * 16 * sG1); - // domainSize * 9 + 18 = SRS length in the zkey saved in setup process. - // it corresponds to the maximum SRS length needed, specifically to commit C2 - // notice that the reserved buffers size is zkey.domainSize * 16 * sG1 because a power of two buffer size is needed - // the remaining buffer not filled from SRS are set to 0 - await fdZKey.readToBuffer(PTau, 0, (zkey.domainSize * 9 + 18) * sG1, zkeySections[ZKEY_FF_PTAU_SECTION][0].p); - - // START FFLONK PROVER PROTOCOL - if (globalThis.gc) globalThis.gc(); - - // ROUND 1. Compute C1(X) polynomial - if (logger) logger.info(""); - if (logger) logger.info("> ROUND 1"); - await round1(); - - delete polynomials.T0; - delete evaluations.QL; - delete evaluations.QR; - delete evaluations.QM; - delete evaluations.QO; - delete evaluations.QC; - if (globalThis.gc) globalThis.gc(); - - // ROUND 2. Compute C2(X) polynomial - if (logger) logger.info("> ROUND 2"); - await round2(); - - delete buffers.A; - delete buffers.B; - delete buffers.C; - delete evaluations.A; - delete evaluations.B; - delete evaluations.C; - delete evaluations.Sigma1; - delete evaluations.Sigma2; - delete evaluations.Sigma3; - delete evaluations.lagrange1; - delete evaluations.Z; - if (globalThis.gc) globalThis.gc(); - - // ROUND 3. Compute opening evaluations - if (logger) logger.info("> ROUND 3"); - await round3(); - - delete polynomials.A; - delete polynomials.B; - delete polynomials.C; - delete polynomials.Z; - delete polynomials.T1; - delete polynomials.T2; - delete polynomials.Sigma1; - delete polynomials.Sigma2; - delete polynomials.Sigma3; - delete polynomials.QL; - delete polynomials.QR; - delete polynomials.QM; - delete polynomials.QC; - delete polynomials.QO; - if (globalThis.gc) globalThis.gc(); - - // ROUND 4. Compute W(X) polynomial - if (logger) logger.info("> ROUND 4"); - await round4(); - if (globalThis.gc) globalThis.gc(); - - // ROUND 5. Compute W'(X) polynomial - if (logger) logger.info("> ROUND 5"); - await round5(); - - delete polynomials.C0; - delete polynomials.C1; - delete polynomials.C2; - delete polynomials.R1; - delete polynomials.R2; - delete polynomials.F; - delete polynomials.L; - delete polynomials.ZT; - delete polynomials.ZTS2; - await fdZKey.close(); - if (globalThis.gc) globalThis.gc(); - - proof.addEvaluation("inv", getMontgomeryBatchedInverse()); - - // Prepare proof - let _proof = proof.toObjectProof(); - _proof.protocol = "fflonk"; - _proof.curve = curve.name; - - // Prepare public inputs - let publicSignals = []; - - for (let i = 1; i <= zkey.nPublic; i++) { - const i_sFr = i * sFr; - - const pub = buffWitness.slice(i_sFr, i_sFr + sFr); - publicSignals.push(ffjavascript.Scalar.fromRprLE(pub)); - } - - if (logger) logger.info("FFLONK PROVER FINISHED"); - - return { - proof: stringifyBigInts$1(_proof), - publicSignals: stringifyBigInts$1(publicSignals) - }; - - async function calculateAdditions() { - if (logger) logger.info("··· Computing additions"); - const additionsBuff = await binFileUtils__namespace.readSection(fdZKey, zkeySections, ZKEY_FF_ADDITIONS_SECTION); - - // sizes: wireId_x = 4 bytes (32 bits), factor_x = field size bits - // Addition form: wireId_a wireId_b factor_a factor_b (size is 4 + 4 + sFr + sFr) - const sSum = 8 + sFr * 2; - - for (let i = 0; i < zkey.nAdditions; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.info(` addition ${i}/${zkey.nAdditions}`); - - // Read addition values - let offset = i * sSum; - const signalId1 = readUInt32(additionsBuff, offset); - offset += 4; - const signalId2 = readUInt32(additionsBuff, offset); - offset += 4; - const factor1 = additionsBuff.slice(offset, offset + sFr); - offset += sFr; - const factor2 = additionsBuff.slice(offset, offset + sFr); - - // Get witness value - const witness1 = getWitness(signalId1); - const witness2 = getWitness(signalId2); - - //Calculate final result - const result = Fr.add(Fr.mul(factor1, witness1), Fr.mul(factor2, witness2)); - - buffInternalWitness.set(result, sFr * i); - } - } - - function readUInt32(b, o) { - const buff = b.slice(o, o + 4); - const buffV = new DataView(buff.buffer, buff.byteOffset, buff.byteLength); - return buffV.getUint32(0, true); - } - - function getWitness(idx) { - let diff = zkey.nVars - zkey.nAdditions; - if (idx < diff) { - return buffWitness.slice(idx * sFr, idx * sFr + sFr); - } else if (idx < zkey.nVars) { - const offset = (idx - diff) * sFr; - return buffInternalWitness.slice(offset, offset + sFr); - } - - return Fr.zero; - } - - async function round1() { - // STEP 1.1 - Generate random blinding scalars (b_1, ..., b9) ∈ F - challenges.b = []; - for (let i = 1; i <= 9; i++) { - challenges.b[i] = Fr.random(); - } - - // STEP 1.2 - Compute wire polynomials a(X), b(X) and c(X) - if (logger) logger.info("> Computing A, B, C wire polynomials"); - await computeWirePolynomials(); - - // STEP 1.3 - Compute the quotient polynomial T0(X) - if (logger) logger.info("> Computing T0 polynomial"); - await computeT0(); - - // STEP 1.4 - Compute the FFT-style combination polynomial C1(X) - if (logger) logger.info("> Computing C1 polynomial"); - await computeC1(); - - // The first output of the prover is ([C1]_1) - if (logger) logger.info("> Computing C1 multi exponentiation"); - let commitC1 = await polynomials.C1.multiExponentiation(PTau, "C1"); - proof.addPolynomial("C1", commitC1); - - return 0; - - async function computeWirePolynomials() { - if (logger) logger.info("··· Reading data from zkey file"); - // Build A, B and C evaluations buffer from zkey and witness files - buffers.A = new ffjavascript.BigBuffer(sDomain); - buffers.B = new ffjavascript.BigBuffer(sDomain); - buffers.C = new ffjavascript.BigBuffer(sDomain); - - // Read zkey sections and fill the buffers - const aMapBuff = await binFileUtils__namespace.readSection(fdZKey, zkeySections, ZKEY_FF_A_MAP_SECTION); - const bMapBuff = await binFileUtils__namespace.readSection(fdZKey, zkeySections, ZKEY_FF_B_MAP_SECTION); - const cMapBuff = await binFileUtils__namespace.readSection(fdZKey, zkeySections, ZKEY_FF_C_MAP_SECTION); - - // Compute all witness from signal ids and set them to A,B & C buffers - for (let i = 0; i < zkey.nConstraints; i++) { - const i_sFr = i * sFr; - const offset = i * 4; - - // Compute A value from a signal id - const signalIdA = readUInt32(aMapBuff, offset); - buffers.A.set(getWitness(signalIdA), i_sFr); - - // Compute B value from a signal id - const signalIdB = readUInt32(bMapBuff, offset); - buffers.B.set(getWitness(signalIdB), i_sFr); - - // Compute C value from a signal id - const signalIdC = readUInt32(cMapBuff, offset); - buffers.C.set(getWitness(signalIdC), i_sFr); - } - - // Blind a(X), b(X) and c(X) polynomials coefficients with blinding scalars b - buffers.A.set(challenges.b[1], sDomain - 64); - buffers.A.set(challenges.b[2], sDomain - 32); - buffers.B.set(challenges.b[3], sDomain - 64); - buffers.B.set(challenges.b[4], sDomain - 32); - buffers.C.set(challenges.b[5], sDomain - 64); - buffers.C.set(challenges.b[6], sDomain - 32); - - buffers.A = await Fr.batchToMontgomery(buffers.A); - buffers.B = await Fr.batchToMontgomery(buffers.B); - buffers.C = await Fr.batchToMontgomery(buffers.C); - - // Compute the coefficients of the wire polynomials a(X), b(X) and c(X) from A,B & C buffers - if (logger) logger.info("··· Computing A ifft"); - polynomials.A = await Polynomial.fromEvaluations(buffers.A, curve, logger); - if (logger) logger.info("··· Computing B ifft"); - polynomials.B = await Polynomial.fromEvaluations(buffers.B, curve, logger); - if (logger) logger.info("··· Computing C ifft"); - polynomials.C = await Polynomial.fromEvaluations(buffers.C, curve, logger); - - // Compute extended evaluations of a(X), b(X) and c(X) polynomials - if (logger) logger.info("··· Computing A fft"); - evaluations.A = await Evaluations.fromPolynomial(polynomials.A, 4, curve, logger); - if (logger) logger.info("··· Computing B fft"); - evaluations.B = await Evaluations.fromPolynomial(polynomials.B, 4, curve, logger); - if (logger) logger.info("··· Computing C fft"); - evaluations.C = await Evaluations.fromPolynomial(polynomials.C, 4, curve, logger); - - // Check degrees - if (polynomials.A.degree() >= zkey.domainSize) { - throw new Error("A Polynomial is not well calculated"); - } - if (polynomials.B.degree() >= zkey.domainSize) { - throw new Error("B Polynomial is not well calculated"); - } - if (polynomials.C.degree() >= zkey.domainSize) { - throw new Error("C Polynomial is not well calculated"); - } - } - - async function computeT0() { - if (logger) logger.info(`··· Reading sections ${ZKEY_FF_QL_SECTION}, ${ZKEY_FF_QR_SECTION}` + - `, ${ZKEY_FF_QM_SECTION}, ${ZKEY_FF_QO_SECTION}, ${ZKEY_FF_QC_SECTION}. Q selectors`); - // Reserve memory for Q's evaluations - evaluations.QL = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QR = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QM = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QO = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QC = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - - // Read Q's evaluations from zkey file - await fdZKey.readToBuffer(evaluations.QL.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_QL_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QR.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_QR_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QM.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_QM_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QO.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_QO_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QC.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_QC_SECTION][0].p + sDomain); - - // Read Lagrange polynomials & evaluations from zkey file - const lagrangePolynomials = await binFileUtils__namespace.readSection(fdZKey, zkeySections, ZKEY_FF_LAGRANGE_SECTION); - evaluations.lagrange1 = new Evaluations(lagrangePolynomials, curve, logger); - - // Reserve memory for buffers T0 - buffers.T0 = new ffjavascript.BigBuffer(sDomain * 4); - - if (logger) logger.info("··· Computing T0 evaluations"); - for (let i = 0; i < zkey.domainSize * 4; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.info(` T0 evaluation ${i}/${zkey.domainSize * 4}`); - - // Get related evaluations to compute current T0 evaluation - const a = evaluations.A.getEvaluation(i); - const b = evaluations.B.getEvaluation(i); - const c = evaluations.C.getEvaluation(i); - - const ql = evaluations.QL.getEvaluation(i); - const qr = evaluations.QR.getEvaluation(i); - const qm = evaluations.QM.getEvaluation(i); - const qo = evaluations.QO.getEvaluation(i); - const qc = evaluations.QC.getEvaluation(i); - - // Compute current public input - let pi = Fr.zero; - for (let j = 0; j < zkey.nPublic; j++) { - const offset = (j * 5 * zkey.domainSize) + zkey.domainSize + i; - - const lPol = evaluations.lagrange1.getEvaluation(offset); - const aVal = buffers.A.slice(j * sFr, (j + 1) * sFr); - - pi = Fr.sub(pi, Fr.mul(lPol, aVal)); - } - - //T0(X) = [q_L(X)·a(X) + q_R(X)·b(X) + q_M(X)·a(X)·b(X) + q_O(X)·c(X) + q_C(X) + PI(X)] · 1/Z_H(X) - // Compute first T0(X)·Z_H(X), so divide later the resulting polynomial by Z_H(X) - // expression 1 -> q_L(X)·a(X) - const e1 = Fr.mul(a, ql); - - // expression 2 -> q_R(X)·b(X) - const e2 = Fr.mul(b, qr); - - // expression 3 -> q_M(X)·a(X)·b(X) - const e3 = Fr.mul(Fr.mul(a, b), qm); - - // expression 4 -> q_O(X)·c(X) - const e4 = Fr.mul(c, qo); - - // t0 = expressions 1 + expression 2 + expression 3 + expression 4 + qc + pi - const t0 = Fr.add(e1, Fr.add(e2, Fr.add(e3, Fr.add(e4, Fr.add(qc, pi))))); - - buffers.T0.set(t0, i * sFr); - } - - if (logger) logger.info("buffer T0: " + buffers.T0.byteLength / sFr); - - // Compute the coefficients of the polynomial T0(X) from buffers.T0 - if (logger) logger.info("··· Computing T0 ifft"); - polynomials.T0 = await Polynomial.fromEvaluations(buffers.T0, curve, logger); - - if (logger) logger.info("T0 length: " + polynomials.T0.length()); - if (logger) logger.info("T0 degree: " + polynomials.T0.degree()); - - // Divide the polynomial T0 by Z_H(X) - if (logger) logger.info("··· Computing T0 / ZH"); - polynomials.T0.divByZerofier(zkey.domainSize, Fr.one); - - // Check degree - if (polynomials.T0.degree() >= 2 * zkey.domainSize - 2) { - throw new Error(`T0 Polynomial is not well calculated (degree is ${polynomials.T0.degree()} and must be less than ${2 * zkey.domainSize + 2}`); - } - - delete buffers.T0; - } - - async function computeC1() { - let C1 = new CPolynomial(4, curve, logger); - C1.addPolynomial(0, polynomials.A); - C1.addPolynomial(1, polynomials.B); - C1.addPolynomial(2, polynomials.C); - C1.addPolynomial(3, polynomials.T0); - - polynomials.C1 = C1.getPolynomial(); - - // Check degree - if (polynomials.C1.degree() >= 8 * zkey.domainSize - 8) { - throw new Error("C1 Polynomial is not well calculated"); - } - } - } - - async function round2() { - // STEP 2.1 - Compute permutation challenge beta and gamma ∈ F - // Compute permutation challenge beta - if (logger) logger.info("> Computing challenges beta and gamma"); - const transcript = new Keccak256Transcript(curve); - - // Add C0 to the transcript - transcript.addPolCommitment(zkey.C0); - - // Add A to the transcript - for (let i = 0; i < zkey.nPublic; i++) { - transcript.addScalar(buffers.A.slice(i * sFr, i * sFr + sFr)); - } - - // Add C1 to the transcript - transcript.addPolCommitment(proof.getPolynomial("C1")); - - challenges.beta = transcript.getChallenge(); - if (logger) logger.info("··· challenges.beta: " + Fr.toString(challenges.beta)); - - // Compute permutation challenge gamma - transcript.reset(); - transcript.addScalar(challenges.beta); - challenges.gamma = transcript.getChallenge(); - if (logger) logger.info("··· challenges.gamma: " + Fr.toString(challenges.gamma)); - - // STEP 2.2 - Compute permutation polynomial z(X) - if (logger) logger.info("> Computing Z polynomial"); - await computeZ(); - - // STEP 2.3 - Compute quotient polynomial T1(X) and T2(X) - if (logger) logger.info("> Computing T1 polynomial"); - await computeT1(); - if (logger) logger.info("> Computing T2 polynomial"); - await computeT2(); - - // STEP 2.4 - Compute the FFT-style combination polynomial C2(X) - if (logger) logger.info("> Computing C2 polynomial"); - await computeC2(); - - // The second output of the prover is ([C2]_1) - if (logger) logger.info("> Computing C2 multi exponentiation"); - let commitC2 = await polynomials.C2.multiExponentiation(PTau, "C2"); - proof.addPolynomial("C2", commitC2); - - return 0; - - async function computeZ() { - if (logger) logger.info("··· Computing Z evaluations"); - - let numArr = new ffjavascript.BigBuffer(sDomain); - let denArr = new ffjavascript.BigBuffer(sDomain); - - // Set the first values to 1 - numArr.set(Fr.one, 0); - denArr.set(Fr.one, 0); - - // Set initial omega - let w = Fr.one; - for (let i = 0; i < zkey.domainSize; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.info(` Z evaluation ${i}/${zkey.domainSize}`); - const i_sFr = i * sFr; - - // Z(X) := numArr / denArr - // numArr := (a + beta·ω + gamma)(b + beta·ω·k1 + gamma)(c + beta·ω·k2 + gamma) - const betaw = Fr.mul(challenges.beta, w); - - let num1 = buffers.A.slice(i_sFr, i_sFr + sFr); - num1 = Fr.add(num1, betaw); - num1 = Fr.add(num1, challenges.gamma); - - let num2 = buffers.B.slice(i_sFr, i_sFr + sFr); - num2 = Fr.add(num2, Fr.mul(zkey.k1, betaw)); - num2 = Fr.add(num2, challenges.gamma); - - let num3 = buffers.C.slice(i_sFr, i_sFr + sFr); - num3 = Fr.add(num3, Fr.mul(zkey.k2, betaw)); - num3 = Fr.add(num3, challenges.gamma); - - let num = Fr.mul(num1, Fr.mul(num2, num3)); - - // denArr := (a + beta·sigma1 + gamma)(b + beta·sigma2 + gamma)(c + beta·sigma3 + gamma) - let den1 = buffers.A.slice(i_sFr, i_sFr + sFr); - den1 = Fr.add(den1, Fr.mul(challenges.beta, evaluations.Sigma1.getEvaluation(i * 4))); - den1 = Fr.add(den1, challenges.gamma); - - let den2 = buffers.B.slice(i_sFr, i_sFr + sFr); - den2 = Fr.add(den2, Fr.mul(challenges.beta, evaluations.Sigma2.getEvaluation(i * 4))); - den2 = Fr.add(den2, challenges.gamma); - - let den3 = buffers.C.slice(i_sFr, i_sFr + sFr); - den3 = Fr.add(den3, Fr.mul(challenges.beta, evaluations.Sigma3.getEvaluation(i * 4))); - den3 = Fr.add(den3, challenges.gamma); - - let den = Fr.mul(den1, Fr.mul(den2, den3)); - - // Multiply current num value with the previous one saved in numArr - num = Fr.mul(numArr.slice(i_sFr, i_sFr + sFr), num); - numArr.set(num, ((i + 1) % zkey.domainSize) * sFr); - - // Multiply current den value with the previous one saved in denArr - den = Fr.mul(denArr.slice(i_sFr, i_sFr + sFr), den); - denArr.set(den, ((i + 1) % zkey.domainSize) * sFr); - - // Next omega - w = Fr.mul(w, Fr.w[zkey.power]); - } - // Compute the inverse of denArr to compute in the next command the - // division numArr/denArr by multiplying num · 1/denArr - denArr = await Fr.batchInverse(denArr); - - // TODO: Do it in assembly and in parallel - // Multiply numArr · denArr where denArr was inverted in the previous command - for (let i = 0; i < zkey.domainSize; i++) { - const i_sFr = i * sFr; - - const z = Fr.mul(numArr.slice(i_sFr, i_sFr + sFr), denArr.slice(i_sFr, i_sFr + sFr)); - numArr.set(z, i_sFr); - } - // From now on the values saved on numArr will be Z(X) buffer - buffers.Z = numArr; - - if (!Fr.eq(numArr.slice(0, sFr), Fr.one)) { - throw new Error("Copy constraints does not match"); - } - - // Compute polynomial coefficients z(X) from buffers.Z - if (logger) logger.info("··· Computing Z ifft"); - polynomials.Z = await Polynomial.fromEvaluations(buffers.Z, curve, logger); - - // Compute extended evaluations of z(X) polynomial - if (logger) logger.info("··· Computing Z fft"); - evaluations.Z = await Evaluations.fromPolynomial(polynomials.Z, 4, curve, logger); - - // Blind z(X) polynomial coefficients with blinding scalars b - polynomials.Z.blindCoefficients([challenges.b[9], challenges.b[8], challenges.b[7]]); - - // Check degree - if (polynomials.Z.degree() >= zkey.domainSize + 3) { - throw new Error("Z Polynomial is not well calculated"); - } - - delete buffers.Z; - } - - async function computeT1() { - if (logger) logger.info("··· Computing T1 evaluations"); - - buffers.T1 = new ffjavascript.BigBuffer(sDomain * 2); - buffers.T1z = new ffjavascript.BigBuffer(sDomain * 2); - - // Set initial omega - let omega = Fr.one; - for (let i = 0; i < zkey.domainSize * 2; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.info(` T1 evaluation ${i}/${zkey.domainSize * 4}`); - - const omega2 = Fr.square(omega); - - const z = evaluations.Z.getEvaluation(i * 2); - const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omega2), Fr.mul(challenges.b[8], omega)), challenges.b[9]); - - // T1(X) := (z(X) - 1) · L_1(X) - // Compute first T1(X)·Z_H(X), so divide later the resulting polynomial by Z_H(X) - const lagrange1 = evaluations.lagrange1.getEvaluation(zkey.domainSize + i * 2); - let t1 = Fr.mul(Fr.sub(z, Fr.one), lagrange1); - let t1z = Fr.mul(zp, lagrange1); - - buffers.T1.set(t1, i * sFr); - buffers.T1z.set(t1z, i * sFr); - - // Compute next omega - omega = Fr.mul(omega, Fr.w[zkey.power + 1]); - } - - // Compute the coefficients of the polynomial T1(X) from buffers.T1 - if (logger) logger.info("··· Computing T1 ifft"); - polynomials.T1 = await Polynomial.fromEvaluations(buffers.T1, curve, logger); - - // Divide the polynomial T1 by Z_H(X) - polynomials.T1.divByZerofier(zkey.domainSize, Fr.one); - - // Compute the coefficients of the polynomial T1z(X) from buffers.T1z - if (logger) logger.info("··· Computing T1z ifft"); - polynomials.T1z = await Polynomial.fromEvaluations(buffers.T1z, curve, logger); - - // Add the polynomial T1z to T1 to get the final polynomial T1 - polynomials.T1.add(polynomials.T1z); - - // Check degree - if (polynomials.T1.degree() >= zkey.domainSize + 2) { - throw new Error("T1 Polynomial is not well calculated"); - } - - delete buffers.T1; - delete buffers.T1z; - delete polynomials.T1z; - } - - async function computeT2() { - if (logger) logger.info("··· Computing T2 evaluations"); - - buffers.T2 = new ffjavascript.BigBuffer(sDomain * 4); - buffers.T2z = new ffjavascript.BigBuffer(sDomain * 4); - - // Set initial omega - let omega = Fr.one; - for (let i = 0; i < zkey.domainSize * 4; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.info(` T2 evaluation ${i}/${zkey.domainSize * 4}`); - - const omega2 = Fr.square(omega); - const omegaW = Fr.mul(omega, Fr.w[zkey.power]); - const omegaW2 = Fr.square(omegaW); - - const a = evaluations.A.getEvaluation(i); - const b = evaluations.B.getEvaluation(i); - const c = evaluations.C.getEvaluation(i); - const z = evaluations.Z.getEvaluation(i); - const zW = evaluations.Z.getEvaluation((zkey.domainSize * 4 + 4 + i) % (zkey.domainSize * 4)); - - const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omega2), Fr.mul(challenges.b[8], omega)), challenges.b[9]); - const zWp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omegaW2), Fr.mul(challenges.b[8], omegaW)), challenges.b[9]); - - const sigma1 = evaluations.Sigma1.getEvaluation(i); - const sigma2 = evaluations.Sigma2.getEvaluation(i); - const sigma3 = evaluations.Sigma3.getEvaluation(i); - - // T2(X) := [ (a(X) + beta·X + gamma)(b(X) + beta·k1·X + gamma)(c(X) + beta·k2·X + gamma)z(X) - // -(a(X) + beta·sigma1(X) + gamma)(b(X) + beta·sigma2(X) + gamma)(c(X) + beta·sigma3(X) + gamma)z(Xω)] · 1/Z_H(X) - // Compute first T2(X)·Z_H(X), so divide later the resulting polynomial by Z_H(X) - - // expression 1 -> (a(X) + beta·X + gamma)(b(X) + beta·k1·X + gamma)(c(X) + beta·k2·X + gamma)z(X) - const betaX = Fr.mul(challenges.beta, omega); - - let e11 = Fr.add(a, betaX); - e11 = Fr.add(e11, challenges.gamma); - - let e12 = Fr.add(b, Fr.mul(betaX, zkey.k1)); - e12 = Fr.add(e12, challenges.gamma); - - let e13 = Fr.add(c, Fr.mul(betaX, zkey.k2)); - e13 = Fr.add(e13, challenges.gamma); - - let e1 = Fr.mul(Fr.mul(Fr.mul(e11, e12), e13), z); - let e1z = Fr.mul(Fr.mul(Fr.mul(e11, e12), e13), zp); - // const [e1, e1z] = MulZ.mul4(e11, e12, e13, z, ap, bp, cp, zp, i % 4, Fr); - - // expression 2 -> (a(X) + beta·sigma1(X) + gamma)(b(X) + beta·sigma2(X) + gamma)(c(X) + beta·sigma3(X) + gamma)z(Xω) - let e21 = Fr.add(a, Fr.mul(challenges.beta, sigma1)); - e21 = Fr.add(e21, challenges.gamma); - - let e22 = Fr.add(b, Fr.mul(challenges.beta, sigma2)); - e22 = Fr.add(e22, challenges.gamma); - - let e23 = Fr.add(c, Fr.mul(challenges.beta, sigma3)); - e23 = Fr.add(e23, challenges.gamma); - - let e2 = Fr.mul(Fr.mul(Fr.mul(e21, e22), e23), zW); - let e2z = Fr.mul(Fr.mul(Fr.mul(e21, e22), e23), zWp); - // const [e2, e2z] = MulZ.mul4(e21, e22, e23, zW, ap, bp, cp, zWp, i % 4, Fr); - - let t2 = Fr.sub(e1, e2); - let t2z = Fr.sub(e1z, e2z); - - buffers.T2.set(t2, i * sFr); - buffers.T2z.set(t2z, i * sFr); - - // Compute next omega - omega = Fr.mul(omega, Fr.w[zkey.power + 2]); - } - - // Compute the coefficients of the polynomial T2(X) from buffers.T2 - if (logger) logger.info("··· Computing T2 ifft"); - polynomials.T2 = await Polynomial.fromEvaluations(buffers.T2, curve, logger); - - // Divide the polynomial T2 by Z_H(X) - if (logger) logger.info("··· Computing T2 / ZH"); - polynomials.T2.divByZerofier(zkey.domainSize, Fr.one); - - // Compute the coefficients of the polynomial T2z(X) from buffers.T2z - if (logger) logger.info("··· Computing T2z ifft"); - polynomials.T2z = await Polynomial.fromEvaluations(buffers.T2z, curve, logger); - - // Add the polynomial T2z to T2 to get the final polynomial T2 - polynomials.T2.add(polynomials.T2z); - - // Check degree - if (polynomials.T2.degree() >= 3 * zkey.domainSize) { - throw new Error("T2 Polynomial is not well calculated"); - } - - delete buffers.T2; - delete buffers.T2z; - delete polynomials.T2z; - } - - async function computeC2() { - let C2 = new CPolynomial(3, curve, logger); - C2.addPolynomial(0, polynomials.Z); - C2.addPolynomial(1, polynomials.T1); - C2.addPolynomial(2, polynomials.T2); - - polynomials.C2 = C2.getPolynomial(); - - // Check degree - if (polynomials.C2.degree() >= 9 * zkey.domainSize) { - throw new Error("C2 Polynomial is not well calculated"); - } - } - } - - async function round3() { - if (logger) logger.info("> Computing challenge xi"); - // STEP 3.1 - Compute evaluation challenge xi ∈ S - const transcript = new Keccak256Transcript(curve); - transcript.addScalar(challenges.gamma); - transcript.addPolCommitment(proof.getPolynomial("C2")); - - // Obtain a xi_seeder from the transcript - // To force h1^4 = xi, h2^3 = xi and h_3^2 = xiω - // we compute xi = xi_seeder^12, h1 = xi_seeder^3, h2 = xi_seeder^4 and h3 = xi_seeder^6 - challenges.xiSeed = transcript.getChallenge(); - const xiSeed2 = Fr.square(challenges.xiSeed); - - // Compute omega8, omega4 and omega3 - roots.w8 = []; - roots.w8[0] = Fr.one; - for (let i = 1; i < 8; i++) { - roots.w8[i] = Fr.mul(roots.w8[i - 1], zkey.w8); - } - - roots.w4 = []; - roots.w4[0] = Fr.one; - for (let i = 1; i < 4; i++) { - roots.w4[i] = Fr.mul(roots.w4[i - 1], zkey.w4); - } - - roots.w3 = []; - roots.w3[0] = Fr.one; - roots.w3[1] = zkey.w3; - roots.w3[2] = Fr.square(zkey.w3); - - // Compute h0 = xiSeeder^3 - roots.S0 = {}; - roots.S0.h0w8 = []; - roots.S0.h0w8[0] = Fr.mul(xiSeed2, challenges.xiSeed); - for (let i = 1; i < 8; i++) { - roots.S0.h0w8[i] = Fr.mul(roots.S0.h0w8[0], roots.w8[i]); - } - - // Compute h1 = xi_seeder^6 - roots.S1 = {}; - roots.S1.h1w4 = []; - roots.S1.h1w4[0] = Fr.square(roots.S0.h0w8[0]); - for (let i = 1; i < 4; i++) { - roots.S1.h1w4[i] = Fr.mul(roots.S1.h1w4[0], roots.w4[i]); - } - - // Compute h2 = xi_seeder^8 - roots.S2 = {}; - roots.S2.h2w3 = []; - roots.S2.h2w3[0] = Fr.mul(roots.S1.h1w4[0], xiSeed2); - roots.S2.h2w3[1] = Fr.mul(roots.S2.h2w3[0], roots.w3[1]); - roots.S2.h2w3[2] = Fr.mul(roots.S2.h2w3[0], roots.w3[2]); - - roots.S2.h3w3 = []; - // Multiply h3 by third-root-omega to obtain h_3^3 = xiω - // So, h3 = xi_seeder^8 ω^{1/3} - roots.S2.h3w3[0] = Fr.mul(roots.S2.h2w3[0], zkey.wr); - roots.S2.h3w3[1] = Fr.mul(roots.S2.h3w3[0], roots.w3[1]); - roots.S2.h3w3[2] = Fr.mul(roots.S2.h3w3[0], roots.w3[2]); - - // Compute xi = xi_seeder^24 - challenges.xi = Fr.mul(Fr.square(roots.S2.h2w3[0]), roots.S2.h2w3[0]); - - if (logger) logger.info("··· challenges.xi: " + Fr.toString(challenges.xi)); - - // Reserve memory for Q's polynomials - polynomials.QL = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QR = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QM = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QO = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QC = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - - // Read Q's evaluations from zkey file - await fdZKey.readToBuffer(polynomials.QL.coef, 0, sDomain, zkeySections[ZKEY_FF_QL_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QR.coef, 0, sDomain, zkeySections[ZKEY_FF_QR_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QM.coef, 0, sDomain, zkeySections[ZKEY_FF_QM_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QO.coef, 0, sDomain, zkeySections[ZKEY_FF_QO_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QC.coef, 0, sDomain, zkeySections[ZKEY_FF_QC_SECTION][0].p); - - // STEP 3.2 - Compute opening evaluations and add them to the proof (third output of the prover) - if (logger) logger.info("··· Computing evaluations"); - proof.addEvaluation("ql", polynomials.QL.evaluate(challenges.xi)); - proof.addEvaluation("qr", polynomials.QR.evaluate(challenges.xi)); - proof.addEvaluation("qm", polynomials.QM.evaluate(challenges.xi)); - proof.addEvaluation("qo", polynomials.QO.evaluate(challenges.xi)); - proof.addEvaluation("qc", polynomials.QC.evaluate(challenges.xi)); - proof.addEvaluation("s1", polynomials.Sigma1.evaluate(challenges.xi)); - proof.addEvaluation("s2", polynomials.Sigma2.evaluate(challenges.xi)); - proof.addEvaluation("s3", polynomials.Sigma3.evaluate(challenges.xi)); - proof.addEvaluation("a", polynomials.A.evaluate(challenges.xi)); - proof.addEvaluation("b", polynomials.B.evaluate(challenges.xi)); - proof.addEvaluation("c", polynomials.C.evaluate(challenges.xi)); - proof.addEvaluation("z", polynomials.Z.evaluate(challenges.xi)); - - challenges.xiw = Fr.mul(challenges.xi, Fr.w[zkey.power]); - proof.addEvaluation("zw", polynomials.Z.evaluate(challenges.xiw)); - proof.addEvaluation("t1w", polynomials.T1.evaluate(challenges.xiw)); - proof.addEvaluation("t2w", polynomials.T2.evaluate(challenges.xiw)); - } - - async function round4() { - if (logger) logger.info("> Computing challenge alpha"); - // STEP 4.1 - Compute challenge alpha ∈ F - const transcript = new Keccak256Transcript(curve); - transcript.addScalar(challenges.xiSeed); - transcript.addScalar(proof.getEvaluation("ql")); - transcript.addScalar(proof.getEvaluation("qr")); - transcript.addScalar(proof.getEvaluation("qm")); - transcript.addScalar(proof.getEvaluation("qo")); - transcript.addScalar(proof.getEvaluation("qc")); - transcript.addScalar(proof.getEvaluation("s1")); - transcript.addScalar(proof.getEvaluation("s2")); - transcript.addScalar(proof.getEvaluation("s3")); - transcript.addScalar(proof.getEvaluation("a")); - transcript.addScalar(proof.getEvaluation("b")); - transcript.addScalar(proof.getEvaluation("c")); - transcript.addScalar(proof.getEvaluation("z")); - transcript.addScalar(proof.getEvaluation("zw")); - transcript.addScalar(proof.getEvaluation("t1w")); - transcript.addScalar(proof.getEvaluation("t2w")); - challenges.alpha = transcript.getChallenge(); - if (logger) logger.info("··· challenges.alpha: " + Fr.toString(challenges.alpha)); - - // STEP 4.2 - Compute F(X) - if (logger) logger.info("> Reading C0 polynomial"); - polynomials.C0 = new Polynomial(new ffjavascript.BigBuffer(sDomain * 8), curve, logger); - await fdZKey.readToBuffer(polynomials.C0.coef, 0, sDomain * 8, zkeySections[ZKEY_FF_C0_SECTION][0].p); - - if (logger) logger.info("> Computing R0 polynomial"); - computeR0(); - if (logger) logger.info("> Computing R1 polynomial"); - computeR1(); - if (logger) logger.info("> Computing R2 polynomial"); - computeR2(); - - if (logger) logger.info("> Computing F polynomial"); - await computeF(); - - // The fourth output of the prover is ([W1]_1), where W1:=(f/Z_t)(x) - if (logger) logger.info("> Computing W1 multi exponentiation"); - let commitW1 = await polynomials.F.multiExponentiation(PTau, "W1"); - proof.addPolynomial("W1", commitW1); - - return 0; - - function computeR0() { - // COMPUTE R0 - // Compute the coefficients of R0(X) from 8 evaluations using lagrange interpolation. R0(X) ∈ F_{<8}[X] - // We decide to use Lagrange interpolations because the R0 degree is very small (deg(R0)===7), - // and we were not able to compute it using current ifft implementation because the omega are different - polynomials.R0 = Polynomial.lagrangePolynomialInterpolation( - [roots.S0.h0w8[0], roots.S0.h0w8[1], roots.S0.h0w8[2], roots.S0.h0w8[3], - roots.S0.h0w8[4], roots.S0.h0w8[5], roots.S0.h0w8[6], roots.S0.h0w8[7]], - [polynomials.C0.evaluate(roots.S0.h0w8[0]), polynomials.C0.evaluate(roots.S0.h0w8[1]), - polynomials.C0.evaluate(roots.S0.h0w8[2]), polynomials.C0.evaluate(roots.S0.h0w8[3]), - polynomials.C0.evaluate(roots.S0.h0w8[4]), polynomials.C0.evaluate(roots.S0.h0w8[5]), - polynomials.C0.evaluate(roots.S0.h0w8[6]), polynomials.C0.evaluate(roots.S0.h0w8[7])], curve); - - // Check the degree of r0(X) < 8 - if (polynomials.R0.degree() > 7) { - throw new Error("R0 Polynomial is not well calculated"); - } - } - - function computeR1() { - // COMPUTE R1 - // Compute the coefficients of R1(X) from 4 evaluations using lagrange interpolation. R1(X) ∈ F_{<4}[X] - // We decide to use Lagrange interpolations because the R1 degree is very small (deg(R1)===3), - // and we were not able to compute it using current ifft implementation because the omega are different - polynomials.R1 = Polynomial.lagrangePolynomialInterpolation( - [roots.S1.h1w4[0], roots.S1.h1w4[1], roots.S1.h1w4[2], roots.S1.h1w4[3]], - [polynomials.C1.evaluate(roots.S1.h1w4[0]), polynomials.C1.evaluate(roots.S1.h1w4[1]), - polynomials.C1.evaluate(roots.S1.h1w4[2]), polynomials.C1.evaluate(roots.S1.h1w4[3])], curve); - - // Check the degree of r1(X) < 4 - if (polynomials.R1.degree() > 3) { - throw new Error("R1 Polynomial is not well calculated"); - } - } - - function computeR2() { - // COMPUTE R2 - // Compute the coefficients of r2(X) from 6 evaluations using lagrange interpolation. r2(X) ∈ F_{<6}[X] - // We decide to use Lagrange interpolations because the R2.degree is very small (deg(R2)===5), - // and we were not able to compute it using current ifft implementation because the omega are different - polynomials.R2 = Polynomial.lagrangePolynomialInterpolation( - [roots.S2.h2w3[0], roots.S2.h2w3[1], roots.S2.h2w3[2], - roots.S2.h3w3[0], roots.S2.h3w3[1], roots.S2.h3w3[2]], - [polynomials.C2.evaluate(roots.S2.h2w3[0]), polynomials.C2.evaluate(roots.S2.h2w3[1]), - polynomials.C2.evaluate(roots.S2.h2w3[2]), polynomials.C2.evaluate(roots.S2.h3w3[0]), - polynomials.C2.evaluate(roots.S2.h3w3[1]), polynomials.C2.evaluate(roots.S2.h3w3[2])], curve); - - // Check the degree of r2(X) < 6 - if (polynomials.R2.degree() > 5) { - throw new Error("R2 Polynomial is not well calculated"); - } - } - - async function computeF() { - if (logger) logger.info("··· Computing F polynomial"); - - // COMPUTE F(X) - polynomials.F = Polynomial.fromPolynomial(polynomials.C0, curve, logger); - polynomials.F.sub(polynomials.R0); - polynomials.F.divByZerofier(8, challenges.xi); - - let f2 = Polynomial.fromPolynomial(polynomials.C1, curve, logger); - f2.sub(polynomials.R1); - f2.mulScalar(challenges.alpha); - f2.divByZerofier(4, challenges.xi); - - let f3 = Polynomial.fromPolynomial(polynomials.C2, curve, logger); - f3.sub(polynomials.R2); - f3.mulScalar(Fr.square(challenges.alpha)); - f3.divByZerofier(3, challenges.xi); - f3.divByZerofier(3, challenges.xiw); - - polynomials.F.add(f2); - polynomials.F.add(f3); - - if (polynomials.F.degree() >= 9 * zkey.domainSize - 6) { - throw new Error("F Polynomial is not well calculated"); - } - } - } - - async function round5() { - if (logger) logger.info("> Computing challenge y"); - - // STEP 5.1 - Compute random evaluation point y ∈ F - const transcript = new Keccak256Transcript(curve); - transcript.addScalar(challenges.alpha); - transcript.addPolCommitment(proof.getPolynomial("W1")); - - challenges.y = transcript.getChallenge(); - if (logger) logger.info("··· challenges.y: " + Fr.toString(challenges.y)); - - // STEP 5.2 - Compute L(X) - if (logger) logger.info("> Computing L polynomial"); - await computeL(); - - if (logger) logger.info("> Computing ZTS2 polynomial"); - await computeZTS2(); - - let ZTS2Y = polynomials.ZTS2.evaluate(challenges.y); - ZTS2Y = Fr.inv(ZTS2Y); - polynomials.L.mulScalar(ZTS2Y); - - const polDividend = Polynomial.fromCoefficientsArray([Fr.neg(challenges.y), Fr.one], curve); - if (logger) logger.info("> Computing W' = L / ZTS2 polynomial"); - const polRemainder = polynomials.L.divBy(polDividend); - - //Check polReminder degree is equal to zero - if (polRemainder.degree() > 0) { - throw new Error(`Degree of L(X)/(ZTS2(y)(X-y)) remainder is ${polRemainder.degree()} and should be 0`); - } - - if (polynomials.L.degree() >= 9 * zkey.domainSize - 1) { - throw new Error("Degree of L(X)/(ZTS2(y)(X-y)) is not correct"); - } - - // The fifth output of the prover is ([W2]_1), where W2:=(f/Z_t)(x) - if (logger) logger.info("> Computing W' multi exponentiation"); - let commitW2 = await polynomials.L.multiExponentiation(PTau, "W2"); - proof.addPolynomial("W2", commitW2); - - return 0; - - async function computeL() { - if (logger) logger.info("··· Computing L polynomial"); - - const evalR0Y = polynomials.R0.evaluate(challenges.y); - const evalR1Y = polynomials.R1.evaluate(challenges.y); - const evalR2Y = polynomials.R2.evaluate(challenges.y); - - let mulL0 = Fr.sub(challenges.y, roots.S0.h0w8[0]); - for (let i = 1; i < 8; i++) { - mulL0 = Fr.mul(mulL0, Fr.sub(challenges.y, roots.S0.h0w8[i])); - } - - let mulL1 = Fr.sub(challenges.y, roots.S1.h1w4[0]); - for (let i = 1; i < 4; i++) { - mulL1 = Fr.mul(mulL1, Fr.sub(challenges.y, roots.S1.h1w4[i])); - } - - let mulL2 = Fr.sub(challenges.y, roots.S2.h2w3[0]); - for (let i = 1; i < 3; i++) { - mulL2 = Fr.mul(mulL2, Fr.sub(challenges.y, roots.S2.h2w3[i])); - } - for (let i = 0; i < 3; i++) { - mulL2 = Fr.mul(mulL2, Fr.sub(challenges.y, roots.S2.h3w3[i])); - } - - let preL0 = Fr.mul(mulL1, mulL2); - let preL1 = Fr.mul(challenges.alpha, Fr.mul(mulL0, mulL2)); - let preL2 = Fr.mul(Fr.square(challenges.alpha), Fr.mul(mulL0, mulL1)); - - toInverse["denH1"] = mulL1; - toInverse["denH2"] = mulL2; - - // COMPUTE L(X) - polynomials.L = Polynomial.fromPolynomial(polynomials.C0, curve, logger); - polynomials.L.subScalar(evalR0Y); - polynomials.L.mulScalar(preL0); - - let l2 = Polynomial.fromPolynomial(polynomials.C1, curve, logger); - l2.subScalar(evalR1Y); - l2.mulScalar(preL1); - - let l3 = Polynomial.fromPolynomial(polynomials.C2, curve, logger); - l3.subScalar(evalR2Y); - l3.mulScalar(preL2); - - polynomials.L.add(l2); - polynomials.L.add(l3); - - if (logger) logger.info("> Computing ZT polynomial"); - await computeZT(); - - const evalZTY = polynomials.ZT.evaluate(challenges.y); - polynomials.F.mulScalar(evalZTY); - polynomials.L.sub(polynomials.F); - - // Check degree - if (polynomials.L.degree() >= 9 * zkey.domainSize) { - throw new Error("L Polynomial is not well calculated"); - } - - delete buffers.L; - } - - async function computeZT() { - polynomials.ZT = Polynomial.zerofierPolynomial( - [ - roots.S0.h0w8[0], roots.S0.h0w8[1], roots.S0.h0w8[2], roots.S0.h0w8[3], - roots.S0.h0w8[4], roots.S0.h0w8[5], roots.S0.h0w8[6], roots.S0.h0w8[7], - roots.S1.h1w4[0], roots.S1.h1w4[1], roots.S1.h1w4[2], roots.S1.h1w4[3], - roots.S2.h2w3[0], roots.S2.h2w3[1], roots.S2.h2w3[2], - roots.S2.h3w3[0], roots.S2.h3w3[1], roots.S2.h3w3[2]], curve); - } - - async function computeZTS2() { - polynomials.ZTS2 = Polynomial.zerofierPolynomial( - [roots.S1.h1w4[0], roots.S1.h1w4[1], roots.S1.h1w4[2], roots.S1.h1w4[3], - roots.S2.h2w3[0], roots.S2.h2w3[1], roots.S2.h2w3[2], - roots.S2.h3w3[0], roots.S2.h3w3[1], roots.S2.h3w3[2]], curve); - } - } - - function getMontgomeryBatchedInverse() { - // · denominator needed in step 8 and 9 of the verifier to multiply by 1/Z_H(xi) - let xiN = challenges.xi; - for (let i = 0; i < zkey.power; i++) { - xiN = Fr.square(xiN); - } - toInverse["zh"] = Fr.sub(xiN, Fr.one); - - // · denominator needed in step 10 and 11 of the verifier - // toInverse.denH1 & toInverse.denH2 -> Computed in round5, computeL() - - // · denominator needed in the verifier when computing L_i^{S0}(X), L_i^{S1}(X) and L_i^{S2}(X) - computeLiS0(toInverse, roots.S0.h0w8, challenges.y, curve); - - computeLiS1(toInverse, roots.S1.h1w4, challenges.y, curve); - - computeLiS2(toInverse, roots.S2.h2w3, roots.S2.h3w3, challenges.y, challenges.xi, challenges.xiw, curve); - - // · L_i i=1 to num public inputs, needed in step 6 and 7 of the verifier to compute L_1(xi) and PI(xi) - const size = Math.max(1, zkey.nPublic); - - let w = Fr.one; - for (let i = 0; i < size; i++) { - toInverse["Li_" + (i + 1)] = Fr.mul(Fr.e(zkey.domainSize), Fr.sub(challenges.xi, w)); - w = Fr.mul(w, Fr.w[zkey.power]); - } - - let mulAccumulator = Fr.one; - for (const element of Object.values(toInverse)) { - if(Array.isArray(element)) { - for (const subElement of element) { - mulAccumulator = Fr.mul(mulAccumulator, subElement); - } - } else { - mulAccumulator = Fr.mul(mulAccumulator, element); - } - } - return Fr.inv(mulAccumulator); - - - function computeLiS0(toInverse, roots, x, curve) { - const Fr = curve.Fr; - const len = roots.length; - - const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); - - const Li = []; - for (let i = 0; i < len; i++) { - const den2 = roots[((len - 1) * i) % len]; - const den3 = Fr.sub(x, roots[i]); - - toInverse[["LiS0_" + (i + 1)]] = Fr.mul(Fr.mul(den1, den2), den3); - } - - return Li; - } - - function computeLiS1(toInverse, roots, x, curve) { - const Fr = curve.Fr; - const len = roots.length; - - const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); - - const Li = []; - for (let i = 0; i < len; i++) { - const den2 = roots[((len - 1) * i) % len]; - const den3 = Fr.sub(x, roots[i]); - - toInverse[["LiS1_" + (i + 1)]] = Fr.mul(Fr.mul(den1, den2), den3); - - } - - return Li; - } - - function computeLiS2(toInverse, S2, S2p, value, xi, xiw, curve) { - const Fr = curve.Fr; - - const Li = []; - - const _3h2 = Fr.mul(Fr.e(3), S2[0]); - const xisubxiw = Fr.sub(xi, xiw); - let den1 = Fr.mul(_3h2, xisubxiw); - for (let i = 0; i < 3; i++) { - const den2 = S2[2 * i % 3]; - const den3 = Fr.sub(value, S2[i]); - - toInverse[["LiS2_" + (i + 1)]] = Fr.mul(den1,Fr.mul(den2, den3)); - - } - - const _3h3 = Fr.mul(Fr.e(3), S2p[0]); - const xiwsubxi = Fr.sub(xiw, xi); - den1 = Fr.mul(_3h3, xiwsubxi); - for (let i = 0; i < 3; i++) { - const den2 = S2p[2 * i % 3]; - const den3 = Fr.sub(value, S2p[i]); - - toInverse[["LiS2_" + (i + 1 + 3)]] = Fr.mul(den1,Fr.mul(den2, den3)); - } - - return Li; - } - } -} - -/* - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ -const {unstringifyBigInts: unstringifyBigInts$3} = ffjavascript.utils; - + if (logger) logger.info("FFLONK PROVER STARTED"); + if (logger) logger.info("> Reading witness file"); + const { fd: fdWtns, sections: wtnsSections } = await _iden3_binfileutils.readBinFile(witnessFileName, "wtns", 2, 1 << 25, 1 << 23); + const wtns = await readHeader(fdWtns, wtnsSections); + if (logger) logger.info("> Reading zkey file"); + const { fd: fdZKey, sections: zkeySections } = await _iden3_binfileutils.readBinFile(zkeyFileName, "zkey", 2, 1 << 25, 1 << 23); + const zkey = await readHeader$1(fdZKey, zkeySections, void 0, options); + if (zkey.protocolId !== 10) throw new Error("zkey file is not fflonk"); + if (!ffjavascript.Scalar.eq(zkey.r, wtns.q)) throw new Error("Curve of the witness does not match the curve of the proving key"); + if (wtns.nWitness !== zkey.nVars - zkey.nAdditions) throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}, ${zkey.nAdditions}`); + const curve = zkey.curve; + const Fr = curve.Fr; + const sFr = curve.Fr.n8; + const sG1 = curve.G1.F.n8 * 2; + const sDomain = zkey.domainSize * sFr; + if (logger) { + logger.info("----------------------------"); + logger.info(" FFLONK PROVE SETTINGS"); + logger.info(` Curve: ${curve.name}`); + logger.info(` Circuit power: ${zkey.power}`); + logger.info(` Domain size: ${zkey.domainSize}`); + logger.info(` Vars: ${zkey.nVars}`); + logger.info(` Public vars: ${zkey.nPublic}`); + logger.info(` Constraints: ${zkey.nConstraints}`); + logger.info(` Additions: ${zkey.nAdditions}`); + logger.info("----------------------------"); + } + if (logger) logger.info("> Reading witness file data"); + const buffWitness = await _iden3_binfileutils.readSection(fdWtns, wtnsSections, 2); + await fdWtns.close(); + buffWitness.set(Fr.zero, 0); + const buffInternalWitness = new ffjavascript.BigBuffer(zkey.nAdditions * sFr); + let buffers = {}; + let polynomials = {}; + let evaluations = {}; + let toInverse = {}; + let challenges = {}; + let roots = {}; + let proof = new Proof(curve, logger); + if (logger) logger.info(`> Reading Section 3. Additions`); + await calculateAdditions(); + if (logger) logger.info(`> Reading Sections 12,13,14. Sigma1, Sigma2 & Sigma 3`); + if (logger) logger.info("··· Reading Sigma polynomials "); + polynomials.Sigma1 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.Sigma2 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.Sigma3 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + await fdZKey.readToBuffer(polynomials.Sigma1.coef, 0, sDomain, zkeySections[12][0].p); + await fdZKey.readToBuffer(polynomials.Sigma2.coef, 0, sDomain, zkeySections[13][0].p); + await fdZKey.readToBuffer(polynomials.Sigma3.coef, 0, sDomain, zkeySections[14][0].p); + if (logger) logger.info("··· Reading Sigma evaluations"); + evaluations.Sigma1 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.Sigma2 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.Sigma3 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + await fdZKey.readToBuffer(evaluations.Sigma1.eval, 0, sDomain * 4, zkeySections[12][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.Sigma2.eval, 0, sDomain * 4, zkeySections[13][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.Sigma3.eval, 0, sDomain * 4, zkeySections[14][0].p + sDomain); + if (logger) logger.info(`> Reading Section 16. Powers of Tau`); + const PTau = new ffjavascript.BigBuffer(zkey.domainSize * 16 * sG1); + await fdZKey.readToBuffer(PTau, 0, (zkey.domainSize * 9 + 18) * sG1, zkeySections[16][0].p); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(""); + if (logger) logger.info("> ROUND 1"); + await round1(); + delete polynomials.T0; + delete evaluations.QL; + delete evaluations.QR; + delete evaluations.QM; + delete evaluations.QO; + delete evaluations.QC; + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info("> ROUND 2"); + await round2(); + delete buffers.A; + delete buffers.B; + delete buffers.C; + delete evaluations.A; + delete evaluations.B; + delete evaluations.C; + delete evaluations.Sigma1; + delete evaluations.Sigma2; + delete evaluations.Sigma3; + delete evaluations.lagrange1; + delete evaluations.Z; + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info("> ROUND 3"); + await round3(); + delete polynomials.A; + delete polynomials.B; + delete polynomials.C; + delete polynomials.Z; + delete polynomials.T1; + delete polynomials.T2; + delete polynomials.Sigma1; + delete polynomials.Sigma2; + delete polynomials.Sigma3; + delete polynomials.QL; + delete polynomials.QR; + delete polynomials.QM; + delete polynomials.QC; + delete polynomials.QO; + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info("> ROUND 4"); + await round4(); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info("> ROUND 5"); + await round5(); + delete polynomials.C0; + delete polynomials.C1; + delete polynomials.C2; + delete polynomials.R1; + delete polynomials.R2; + delete polynomials.F; + delete polynomials.L; + delete polynomials.ZT; + delete polynomials.ZTS2; + await fdZKey.close(); + if (globalThis.gc) globalThis.gc(); + proof.addEvaluation("inv", getMontgomeryBatchedInverse()); + let _proof = proof.toObjectProof(); + _proof.protocol = "fflonk"; + _proof.curve = curve.name; + let publicSignals = []; + for (let i = 1; i <= zkey.nPublic; i++) { + const i_sFr = i * sFr; + const pub = buffWitness.slice(i_sFr, i_sFr + sFr); + publicSignals.push(ffjavascript.Scalar.fromRprLE(pub)); + } + if (logger) logger.info("FFLONK PROVER FINISHED"); + return { + proof: stringifyBigInts$1(_proof), + publicSignals: stringifyBigInts$1(publicSignals) + }; + async function calculateAdditions() { + if (logger) logger.info("··· Computing additions"); + const additionsBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 3); + const sSum = 8 + sFr * 2; + for (let i = 0; i < zkey.nAdditions; i++) { + if (logger && 0 !== i && i % 1e5 === 0) logger.info(` addition ${i}/${zkey.nAdditions}`); + let offset = i * sSum; + const signalId1 = readUInt32(additionsBuff, offset); + offset += 4; + const signalId2 = readUInt32(additionsBuff, offset); + offset += 4; + const factor1 = additionsBuff.slice(offset, offset + sFr); + offset += sFr; + const factor2 = additionsBuff.slice(offset, offset + sFr); + const witness1 = getWitness(signalId1); + const witness2 = getWitness(signalId2); + const result = Fr.add(Fr.mul(factor1, witness1), Fr.mul(factor2, witness2)); + buffInternalWitness.set(result, sFr * i); + } + } + function readUInt32(b, o) { + const buff = b.slice(o, o + 4); + return new DataView(buff.buffer, buff.byteOffset, buff.byteLength).getUint32(0, true); + } + function getWitness(idx) { + let diff = zkey.nVars - zkey.nAdditions; + if (idx < diff) return buffWitness.slice(idx * sFr, idx * sFr + sFr); + else if (idx < zkey.nVars) { + const offset = (idx - diff) * sFr; + return buffInternalWitness.slice(offset, offset + sFr); + } + return Fr.zero; + } + async function round1() { + challenges.b = []; + for (let i = 1; i <= 9; i++) challenges.b[i] = Fr.random(); + if (logger) logger.info("> Computing A, B, C wire polynomials"); + await computeWirePolynomials(); + if (logger) logger.info("> Computing T0 polynomial"); + await computeT0(); + if (logger) logger.info("> Computing C1 polynomial"); + await computeC1(); + if (logger) logger.info("> Computing C1 multi exponentiation"); + let commitC1 = await polynomials.C1.multiExponentiation(PTau, "C1"); + proof.addPolynomial("C1", commitC1); + return 0; + async function computeWirePolynomials() { + if (logger) logger.info("··· Reading data from zkey file"); + buffers.A = new ffjavascript.BigBuffer(sDomain); + buffers.B = new ffjavascript.BigBuffer(sDomain); + buffers.C = new ffjavascript.BigBuffer(sDomain); + const aMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 4); + const bMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 5); + const cMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 6); + for (let i = 0; i < zkey.nConstraints; i++) { + const i_sFr = i * sFr; + const offset = i * 4; + const signalIdA = readUInt32(aMapBuff, offset); + buffers.A.set(getWitness(signalIdA), i_sFr); + const signalIdB = readUInt32(bMapBuff, offset); + buffers.B.set(getWitness(signalIdB), i_sFr); + const signalIdC = readUInt32(cMapBuff, offset); + buffers.C.set(getWitness(signalIdC), i_sFr); + } + buffers.A.set(challenges.b[1], sDomain - 64); + buffers.A.set(challenges.b[2], sDomain - 32); + buffers.B.set(challenges.b[3], sDomain - 64); + buffers.B.set(challenges.b[4], sDomain - 32); + buffers.C.set(challenges.b[5], sDomain - 64); + buffers.C.set(challenges.b[6], sDomain - 32); + buffers.A = await Fr.batchToMontgomery(buffers.A); + buffers.B = await Fr.batchToMontgomery(buffers.B); + buffers.C = await Fr.batchToMontgomery(buffers.C); + if (logger) logger.info("··· Computing A ifft"); + polynomials.A = await Polynomial.fromEvaluations(buffers.A, curve, logger); + if (logger) logger.info("··· Computing B ifft"); + polynomials.B = await Polynomial.fromEvaluations(buffers.B, curve, logger); + if (logger) logger.info("··· Computing C ifft"); + polynomials.C = await Polynomial.fromEvaluations(buffers.C, curve, logger); + if (logger) logger.info("··· Computing A fft"); + evaluations.A = await Evaluations.fromPolynomial(polynomials.A, 4, curve, logger); + if (logger) logger.info("··· Computing B fft"); + evaluations.B = await Evaluations.fromPolynomial(polynomials.B, 4, curve, logger); + if (logger) logger.info("··· Computing C fft"); + evaluations.C = await Evaluations.fromPolynomial(polynomials.C, 4, curve, logger); + if (polynomials.A.degree() >= zkey.domainSize) throw new Error("A Polynomial is not well calculated"); + if (polynomials.B.degree() >= zkey.domainSize) throw new Error("B Polynomial is not well calculated"); + if (polynomials.C.degree() >= zkey.domainSize) throw new Error("C Polynomial is not well calculated"); + } + async function computeT0() { + if (logger) logger.info(`··· Reading sections 7, 8, 9, 10, 11. Q selectors`); + evaluations.QL = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QR = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QM = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QO = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QC = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + await fdZKey.readToBuffer(evaluations.QL.eval, 0, sDomain * 4, zkeySections[7][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QR.eval, 0, sDomain * 4, zkeySections[8][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QM.eval, 0, sDomain * 4, zkeySections[9][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QO.eval, 0, sDomain * 4, zkeySections[10][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QC.eval, 0, sDomain * 4, zkeySections[11][0].p + sDomain); + evaluations.lagrange1 = new Evaluations(await _iden3_binfileutils.readSection(fdZKey, zkeySections, 15), curve, logger); + buffers.T0 = new ffjavascript.BigBuffer(sDomain * 4); + if (logger) logger.info("··· Computing T0 evaluations"); + for (let i = 0; i < zkey.domainSize * 4; i++) { + if (logger && 0 !== i && i % 1e5 === 0) logger.info(` T0 evaluation ${i}/${zkey.domainSize * 4}`); + const a = evaluations.A.getEvaluation(i); + const b = evaluations.B.getEvaluation(i); + const c = evaluations.C.getEvaluation(i); + const ql = evaluations.QL.getEvaluation(i); + const qr = evaluations.QR.getEvaluation(i); + const qm = evaluations.QM.getEvaluation(i); + const qo = evaluations.QO.getEvaluation(i); + const qc = evaluations.QC.getEvaluation(i); + let pi = Fr.zero; + for (let j = 0; j < zkey.nPublic; j++) { + const offset = j * 5 * zkey.domainSize + zkey.domainSize + i; + const lPol = evaluations.lagrange1.getEvaluation(offset); + const aVal = buffers.A.slice(j * sFr, (j + 1) * sFr); + pi = Fr.sub(pi, Fr.mul(lPol, aVal)); + } + const e1 = Fr.mul(a, ql); + const e2 = Fr.mul(b, qr); + const e3 = Fr.mul(Fr.mul(a, b), qm); + const e4 = Fr.mul(c, qo); + const t0 = Fr.add(e1, Fr.add(e2, Fr.add(e3, Fr.add(e4, Fr.add(qc, pi))))); + buffers.T0.set(t0, i * sFr); + } + if (logger) logger.info("buffer T0: " + buffers.T0.byteLength / sFr); + if (logger) logger.info("··· Computing T0 ifft"); + polynomials.T0 = await Polynomial.fromEvaluations(buffers.T0, curve, logger); + if (logger) logger.info("T0 length: " + polynomials.T0.length()); + if (logger) logger.info("T0 degree: " + polynomials.T0.degree()); + if (logger) logger.info("··· Computing T0 / ZH"); + polynomials.T0.divByZerofier(zkey.domainSize, Fr.one); + if (polynomials.T0.degree() >= 2 * zkey.domainSize - 2) throw new Error(`T0 Polynomial is not well calculated (degree is ${polynomials.T0.degree()} and must be less than ${2 * zkey.domainSize + 2}`); + delete buffers.T0; + } + async function computeC1() { + let C1 = new CPolynomial(4, curve, logger); + C1.addPolynomial(0, polynomials.A); + C1.addPolynomial(1, polynomials.B); + C1.addPolynomial(2, polynomials.C); + C1.addPolynomial(3, polynomials.T0); + polynomials.C1 = C1.getPolynomial(); + if (polynomials.C1.degree() >= 8 * zkey.domainSize - 8) throw new Error("C1 Polynomial is not well calculated"); + } + } + async function round2() { + if (logger) logger.info("> Computing challenges beta and gamma"); + const transcript = new Keccak256Transcript(curve); + transcript.addPolCommitment(zkey.C0); + for (let i = 0; i < zkey.nPublic; i++) transcript.addScalar(buffers.A.slice(i * sFr, i * sFr + sFr)); + transcript.addPolCommitment(proof.getPolynomial("C1")); + challenges.beta = transcript.getChallenge(); + if (logger) logger.info("··· challenges.beta: " + Fr.toString(challenges.beta)); + transcript.reset(); + transcript.addScalar(challenges.beta); + challenges.gamma = transcript.getChallenge(); + if (logger) logger.info("··· challenges.gamma: " + Fr.toString(challenges.gamma)); + if (logger) logger.info("> Computing Z polynomial"); + await computeZ(); + if (logger) logger.info("> Computing T1 polynomial"); + await computeT1(); + if (logger) logger.info("> Computing T2 polynomial"); + await computeT2(); + if (logger) logger.info("> Computing C2 polynomial"); + await computeC2(); + if (logger) logger.info("> Computing C2 multi exponentiation"); + let commitC2 = await polynomials.C2.multiExponentiation(PTau, "C2"); + proof.addPolynomial("C2", commitC2); + return 0; + async function computeZ() { + if (logger) logger.info("··· Computing Z evaluations"); + let numArr = new ffjavascript.BigBuffer(sDomain); + let denArr = new ffjavascript.BigBuffer(sDomain); + numArr.set(Fr.one, 0); + denArr.set(Fr.one, 0); + let w = Fr.one; + for (let i = 0; i < zkey.domainSize; i++) { + if (logger && 0 !== i && i % 1e5 === 0) logger.info(` Z evaluation ${i}/${zkey.domainSize}`); + const i_sFr = i * sFr; + const betaw = Fr.mul(challenges.beta, w); + let num1 = buffers.A.slice(i_sFr, i_sFr + sFr); + num1 = Fr.add(num1, betaw); + num1 = Fr.add(num1, challenges.gamma); + let num2 = buffers.B.slice(i_sFr, i_sFr + sFr); + num2 = Fr.add(num2, Fr.mul(zkey.k1, betaw)); + num2 = Fr.add(num2, challenges.gamma); + let num3 = buffers.C.slice(i_sFr, i_sFr + sFr); + num3 = Fr.add(num3, Fr.mul(zkey.k2, betaw)); + num3 = Fr.add(num3, challenges.gamma); + let num = Fr.mul(num1, Fr.mul(num2, num3)); + let den1 = buffers.A.slice(i_sFr, i_sFr + sFr); + den1 = Fr.add(den1, Fr.mul(challenges.beta, evaluations.Sigma1.getEvaluation(i * 4))); + den1 = Fr.add(den1, challenges.gamma); + let den2 = buffers.B.slice(i_sFr, i_sFr + sFr); + den2 = Fr.add(den2, Fr.mul(challenges.beta, evaluations.Sigma2.getEvaluation(i * 4))); + den2 = Fr.add(den2, challenges.gamma); + let den3 = buffers.C.slice(i_sFr, i_sFr + sFr); + den3 = Fr.add(den3, Fr.mul(challenges.beta, evaluations.Sigma3.getEvaluation(i * 4))); + den3 = Fr.add(den3, challenges.gamma); + let den = Fr.mul(den1, Fr.mul(den2, den3)); + num = Fr.mul(numArr.slice(i_sFr, i_sFr + sFr), num); + numArr.set(num, (i + 1) % zkey.domainSize * sFr); + den = Fr.mul(denArr.slice(i_sFr, i_sFr + sFr), den); + denArr.set(den, (i + 1) % zkey.domainSize * sFr); + w = Fr.mul(w, Fr.w[zkey.power]); + } + denArr = await Fr.batchInverse(denArr); + for (let i = 0; i < zkey.domainSize; i++) { + const i_sFr = i * sFr; + const z = Fr.mul(numArr.slice(i_sFr, i_sFr + sFr), denArr.slice(i_sFr, i_sFr + sFr)); + numArr.set(z, i_sFr); + } + buffers.Z = numArr; + if (!Fr.eq(numArr.slice(0, sFr), Fr.one)) throw new Error("Copy constraints does not match"); + if (logger) logger.info("··· Computing Z ifft"); + polynomials.Z = await Polynomial.fromEvaluations(buffers.Z, curve, logger); + if (logger) logger.info("··· Computing Z fft"); + evaluations.Z = await Evaluations.fromPolynomial(polynomials.Z, 4, curve, logger); + polynomials.Z.blindCoefficients([ + challenges.b[9], + challenges.b[8], + challenges.b[7] + ]); + if (polynomials.Z.degree() >= zkey.domainSize + 3) throw new Error("Z Polynomial is not well calculated"); + delete buffers.Z; + } + async function computeT1() { + if (logger) logger.info("··· Computing T1 evaluations"); + buffers.T1 = new ffjavascript.BigBuffer(sDomain * 2); + buffers.T1z = new ffjavascript.BigBuffer(sDomain * 2); + let omega = Fr.one; + for (let i = 0; i < zkey.domainSize * 2; i++) { + if (logger && 0 !== i && i % 1e5 === 0) logger.info(` T1 evaluation ${i}/${zkey.domainSize * 4}`); + const omega2 = Fr.square(omega); + const z = evaluations.Z.getEvaluation(i * 2); + const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omega2), Fr.mul(challenges.b[8], omega)), challenges.b[9]); + const lagrange1 = evaluations.lagrange1.getEvaluation(zkey.domainSize + i * 2); + let t1 = Fr.mul(Fr.sub(z, Fr.one), lagrange1); + let t1z = Fr.mul(zp, lagrange1); + buffers.T1.set(t1, i * sFr); + buffers.T1z.set(t1z, i * sFr); + omega = Fr.mul(omega, Fr.w[zkey.power + 1]); + } + if (logger) logger.info("··· Computing T1 ifft"); + polynomials.T1 = await Polynomial.fromEvaluations(buffers.T1, curve, logger); + polynomials.T1.divByZerofier(zkey.domainSize, Fr.one); + if (logger) logger.info("··· Computing T1z ifft"); + polynomials.T1z = await Polynomial.fromEvaluations(buffers.T1z, curve, logger); + polynomials.T1.add(polynomials.T1z); + if (polynomials.T1.degree() >= zkey.domainSize + 2) throw new Error("T1 Polynomial is not well calculated"); + delete buffers.T1; + delete buffers.T1z; + delete polynomials.T1z; + } + async function computeT2() { + if (logger) logger.info("··· Computing T2 evaluations"); + buffers.T2 = new ffjavascript.BigBuffer(sDomain * 4); + buffers.T2z = new ffjavascript.BigBuffer(sDomain * 4); + let omega = Fr.one; + for (let i = 0; i < zkey.domainSize * 4; i++) { + if (logger && 0 !== i && i % 1e5 === 0) logger.info(` T2 evaluation ${i}/${zkey.domainSize * 4}`); + const omega2 = Fr.square(omega); + const omegaW = Fr.mul(omega, Fr.w[zkey.power]); + const omegaW2 = Fr.square(omegaW); + const a = evaluations.A.getEvaluation(i); + const b = evaluations.B.getEvaluation(i); + const c = evaluations.C.getEvaluation(i); + const z = evaluations.Z.getEvaluation(i); + const zW = evaluations.Z.getEvaluation((zkey.domainSize * 4 + 4 + i) % (zkey.domainSize * 4)); + const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omega2), Fr.mul(challenges.b[8], omega)), challenges.b[9]); + const zWp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omegaW2), Fr.mul(challenges.b[8], omegaW)), challenges.b[9]); + const sigma1 = evaluations.Sigma1.getEvaluation(i); + const sigma2 = evaluations.Sigma2.getEvaluation(i); + const sigma3 = evaluations.Sigma3.getEvaluation(i); + const betaX = Fr.mul(challenges.beta, omega); + let e11 = Fr.add(a, betaX); + e11 = Fr.add(e11, challenges.gamma); + let e12 = Fr.add(b, Fr.mul(betaX, zkey.k1)); + e12 = Fr.add(e12, challenges.gamma); + let e13 = Fr.add(c, Fr.mul(betaX, zkey.k2)); + e13 = Fr.add(e13, challenges.gamma); + let e1 = Fr.mul(Fr.mul(Fr.mul(e11, e12), e13), z); + let e1z = Fr.mul(Fr.mul(Fr.mul(e11, e12), e13), zp); + let e21 = Fr.add(a, Fr.mul(challenges.beta, sigma1)); + e21 = Fr.add(e21, challenges.gamma); + let e22 = Fr.add(b, Fr.mul(challenges.beta, sigma2)); + e22 = Fr.add(e22, challenges.gamma); + let e23 = Fr.add(c, Fr.mul(challenges.beta, sigma3)); + e23 = Fr.add(e23, challenges.gamma); + let e2 = Fr.mul(Fr.mul(Fr.mul(e21, e22), e23), zW); + let e2z = Fr.mul(Fr.mul(Fr.mul(e21, e22), e23), zWp); + let t2 = Fr.sub(e1, e2); + let t2z = Fr.sub(e1z, e2z); + buffers.T2.set(t2, i * sFr); + buffers.T2z.set(t2z, i * sFr); + omega = Fr.mul(omega, Fr.w[zkey.power + 2]); + } + if (logger) logger.info("··· Computing T2 ifft"); + polynomials.T2 = await Polynomial.fromEvaluations(buffers.T2, curve, logger); + if (logger) logger.info("··· Computing T2 / ZH"); + polynomials.T2.divByZerofier(zkey.domainSize, Fr.one); + if (logger) logger.info("··· Computing T2z ifft"); + polynomials.T2z = await Polynomial.fromEvaluations(buffers.T2z, curve, logger); + polynomials.T2.add(polynomials.T2z); + if (polynomials.T2.degree() >= 3 * zkey.domainSize) throw new Error("T2 Polynomial is not well calculated"); + delete buffers.T2; + delete buffers.T2z; + delete polynomials.T2z; + } + async function computeC2() { + let C2 = new CPolynomial(3, curve, logger); + C2.addPolynomial(0, polynomials.Z); + C2.addPolynomial(1, polynomials.T1); + C2.addPolynomial(2, polynomials.T2); + polynomials.C2 = C2.getPolynomial(); + if (polynomials.C2.degree() >= 9 * zkey.domainSize) throw new Error("C2 Polynomial is not well calculated"); + } + } + async function round3() { + if (logger) logger.info("> Computing challenge xi"); + const transcript = new Keccak256Transcript(curve); + transcript.addScalar(challenges.gamma); + transcript.addPolCommitment(proof.getPolynomial("C2")); + challenges.xiSeed = transcript.getChallenge(); + const xiSeed2 = Fr.square(challenges.xiSeed); + roots.w8 = []; + roots.w8[0] = Fr.one; + for (let i = 1; i < 8; i++) roots.w8[i] = Fr.mul(roots.w8[i - 1], zkey.w8); + roots.w4 = []; + roots.w4[0] = Fr.one; + for (let i = 1; i < 4; i++) roots.w4[i] = Fr.mul(roots.w4[i - 1], zkey.w4); + roots.w3 = []; + roots.w3[0] = Fr.one; + roots.w3[1] = zkey.w3; + roots.w3[2] = Fr.square(zkey.w3); + roots.S0 = {}; + roots.S0.h0w8 = []; + roots.S0.h0w8[0] = Fr.mul(xiSeed2, challenges.xiSeed); + for (let i = 1; i < 8; i++) roots.S0.h0w8[i] = Fr.mul(roots.S0.h0w8[0], roots.w8[i]); + roots.S1 = {}; + roots.S1.h1w4 = []; + roots.S1.h1w4[0] = Fr.square(roots.S0.h0w8[0]); + for (let i = 1; i < 4; i++) roots.S1.h1w4[i] = Fr.mul(roots.S1.h1w4[0], roots.w4[i]); + roots.S2 = {}; + roots.S2.h2w3 = []; + roots.S2.h2w3[0] = Fr.mul(roots.S1.h1w4[0], xiSeed2); + roots.S2.h2w3[1] = Fr.mul(roots.S2.h2w3[0], roots.w3[1]); + roots.S2.h2w3[2] = Fr.mul(roots.S2.h2w3[0], roots.w3[2]); + roots.S2.h3w3 = []; + roots.S2.h3w3[0] = Fr.mul(roots.S2.h2w3[0], zkey.wr); + roots.S2.h3w3[1] = Fr.mul(roots.S2.h3w3[0], roots.w3[1]); + roots.S2.h3w3[2] = Fr.mul(roots.S2.h3w3[0], roots.w3[2]); + challenges.xi = Fr.mul(Fr.square(roots.S2.h2w3[0]), roots.S2.h2w3[0]); + if (logger) logger.info("··· challenges.xi: " + Fr.toString(challenges.xi)); + polynomials.QL = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QR = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QM = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QO = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QC = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + await fdZKey.readToBuffer(polynomials.QL.coef, 0, sDomain, zkeySections[7][0].p); + await fdZKey.readToBuffer(polynomials.QR.coef, 0, sDomain, zkeySections[8][0].p); + await fdZKey.readToBuffer(polynomials.QM.coef, 0, sDomain, zkeySections[9][0].p); + await fdZKey.readToBuffer(polynomials.QO.coef, 0, sDomain, zkeySections[10][0].p); + await fdZKey.readToBuffer(polynomials.QC.coef, 0, sDomain, zkeySections[11][0].p); + if (logger) logger.info("··· Computing evaluations"); + proof.addEvaluation("ql", polynomials.QL.evaluate(challenges.xi)); + proof.addEvaluation("qr", polynomials.QR.evaluate(challenges.xi)); + proof.addEvaluation("qm", polynomials.QM.evaluate(challenges.xi)); + proof.addEvaluation("qo", polynomials.QO.evaluate(challenges.xi)); + proof.addEvaluation("qc", polynomials.QC.evaluate(challenges.xi)); + proof.addEvaluation("s1", polynomials.Sigma1.evaluate(challenges.xi)); + proof.addEvaluation("s2", polynomials.Sigma2.evaluate(challenges.xi)); + proof.addEvaluation("s3", polynomials.Sigma3.evaluate(challenges.xi)); + proof.addEvaluation("a", polynomials.A.evaluate(challenges.xi)); + proof.addEvaluation("b", polynomials.B.evaluate(challenges.xi)); + proof.addEvaluation("c", polynomials.C.evaluate(challenges.xi)); + proof.addEvaluation("z", polynomials.Z.evaluate(challenges.xi)); + challenges.xiw = Fr.mul(challenges.xi, Fr.w[zkey.power]); + proof.addEvaluation("zw", polynomials.Z.evaluate(challenges.xiw)); + proof.addEvaluation("t1w", polynomials.T1.evaluate(challenges.xiw)); + proof.addEvaluation("t2w", polynomials.T2.evaluate(challenges.xiw)); + } + async function round4() { + if (logger) logger.info("> Computing challenge alpha"); + const transcript = new Keccak256Transcript(curve); + transcript.addScalar(challenges.xiSeed); + transcript.addScalar(proof.getEvaluation("ql")); + transcript.addScalar(proof.getEvaluation("qr")); + transcript.addScalar(proof.getEvaluation("qm")); + transcript.addScalar(proof.getEvaluation("qo")); + transcript.addScalar(proof.getEvaluation("qc")); + transcript.addScalar(proof.getEvaluation("s1")); + transcript.addScalar(proof.getEvaluation("s2")); + transcript.addScalar(proof.getEvaluation("s3")); + transcript.addScalar(proof.getEvaluation("a")); + transcript.addScalar(proof.getEvaluation("b")); + transcript.addScalar(proof.getEvaluation("c")); + transcript.addScalar(proof.getEvaluation("z")); + transcript.addScalar(proof.getEvaluation("zw")); + transcript.addScalar(proof.getEvaluation("t1w")); + transcript.addScalar(proof.getEvaluation("t2w")); + challenges.alpha = transcript.getChallenge(); + if (logger) logger.info("··· challenges.alpha: " + Fr.toString(challenges.alpha)); + if (logger) logger.info("> Reading C0 polynomial"); + polynomials.C0 = new Polynomial(new ffjavascript.BigBuffer(sDomain * 8), curve, logger); + await fdZKey.readToBuffer(polynomials.C0.coef, 0, sDomain * 8, zkeySections[17][0].p); + if (logger) logger.info("> Computing R0 polynomial"); + computeR0(); + if (logger) logger.info("> Computing R1 polynomial"); + computeR1(); + if (logger) logger.info("> Computing R2 polynomial"); + computeR2(); + if (logger) logger.info("> Computing F polynomial"); + await computeF(); + if (logger) logger.info("> Computing W1 multi exponentiation"); + let commitW1 = await polynomials.F.multiExponentiation(PTau, "W1"); + proof.addPolynomial("W1", commitW1); + return 0; + function computeR0() { + polynomials.R0 = Polynomial.lagrangePolynomialInterpolation([ + roots.S0.h0w8[0], + roots.S0.h0w8[1], + roots.S0.h0w8[2], + roots.S0.h0w8[3], + roots.S0.h0w8[4], + roots.S0.h0w8[5], + roots.S0.h0w8[6], + roots.S0.h0w8[7] + ], [ + polynomials.C0.evaluate(roots.S0.h0w8[0]), + polynomials.C0.evaluate(roots.S0.h0w8[1]), + polynomials.C0.evaluate(roots.S0.h0w8[2]), + polynomials.C0.evaluate(roots.S0.h0w8[3]), + polynomials.C0.evaluate(roots.S0.h0w8[4]), + polynomials.C0.evaluate(roots.S0.h0w8[5]), + polynomials.C0.evaluate(roots.S0.h0w8[6]), + polynomials.C0.evaluate(roots.S0.h0w8[7]) + ], curve); + if (polynomials.R0.degree() > 7) throw new Error("R0 Polynomial is not well calculated"); + } + function computeR1() { + polynomials.R1 = Polynomial.lagrangePolynomialInterpolation([ + roots.S1.h1w4[0], + roots.S1.h1w4[1], + roots.S1.h1w4[2], + roots.S1.h1w4[3] + ], [ + polynomials.C1.evaluate(roots.S1.h1w4[0]), + polynomials.C1.evaluate(roots.S1.h1w4[1]), + polynomials.C1.evaluate(roots.S1.h1w4[2]), + polynomials.C1.evaluate(roots.S1.h1w4[3]) + ], curve); + if (polynomials.R1.degree() > 3) throw new Error("R1 Polynomial is not well calculated"); + } + function computeR2() { + polynomials.R2 = Polynomial.lagrangePolynomialInterpolation([ + roots.S2.h2w3[0], + roots.S2.h2w3[1], + roots.S2.h2w3[2], + roots.S2.h3w3[0], + roots.S2.h3w3[1], + roots.S2.h3w3[2] + ], [ + polynomials.C2.evaluate(roots.S2.h2w3[0]), + polynomials.C2.evaluate(roots.S2.h2w3[1]), + polynomials.C2.evaluate(roots.S2.h2w3[2]), + polynomials.C2.evaluate(roots.S2.h3w3[0]), + polynomials.C2.evaluate(roots.S2.h3w3[1]), + polynomials.C2.evaluate(roots.S2.h3w3[2]) + ], curve); + if (polynomials.R2.degree() > 5) throw new Error("R2 Polynomial is not well calculated"); + } + async function computeF() { + if (logger) logger.info("··· Computing F polynomial"); + polynomials.F = Polynomial.fromPolynomial(polynomials.C0, curve, logger); + polynomials.F.sub(polynomials.R0); + polynomials.F.divByZerofier(8, challenges.xi); + let f2 = Polynomial.fromPolynomial(polynomials.C1, curve, logger); + f2.sub(polynomials.R1); + f2.mulScalar(challenges.alpha); + f2.divByZerofier(4, challenges.xi); + let f3 = Polynomial.fromPolynomial(polynomials.C2, curve, logger); + f3.sub(polynomials.R2); + f3.mulScalar(Fr.square(challenges.alpha)); + f3.divByZerofier(3, challenges.xi); + f3.divByZerofier(3, challenges.xiw); + polynomials.F.add(f2); + polynomials.F.add(f3); + if (polynomials.F.degree() >= 9 * zkey.domainSize - 6) throw new Error("F Polynomial is not well calculated"); + } + } + async function round5() { + if (logger) logger.info("> Computing challenge y"); + const transcript = new Keccak256Transcript(curve); + transcript.addScalar(challenges.alpha); + transcript.addPolCommitment(proof.getPolynomial("W1")); + challenges.y = transcript.getChallenge(); + if (logger) logger.info("··· challenges.y: " + Fr.toString(challenges.y)); + if (logger) logger.info("> Computing L polynomial"); + await computeL(); + if (logger) logger.info("> Computing ZTS2 polynomial"); + await computeZTS2(); + let ZTS2Y = polynomials.ZTS2.evaluate(challenges.y); + ZTS2Y = Fr.inv(ZTS2Y); + polynomials.L.mulScalar(ZTS2Y); + const polDividend = Polynomial.fromCoefficientsArray([Fr.neg(challenges.y), Fr.one], curve); + if (logger) logger.info("> Computing W' = L / ZTS2 polynomial"); + const polRemainder = polynomials.L.divBy(polDividend); + if (polRemainder.degree() > 0) throw new Error(`Degree of L(X)/(ZTS2(y)(X-y)) remainder is ${polRemainder.degree()} and should be 0`); + if (polynomials.L.degree() >= 9 * zkey.domainSize - 1) throw new Error("Degree of L(X)/(ZTS2(y)(X-y)) is not correct"); + if (logger) logger.info("> Computing W' multi exponentiation"); + let commitW2 = await polynomials.L.multiExponentiation(PTau, "W2"); + proof.addPolynomial("W2", commitW2); + return 0; + async function computeL() { + if (logger) logger.info("··· Computing L polynomial"); + const evalR0Y = polynomials.R0.evaluate(challenges.y); + const evalR1Y = polynomials.R1.evaluate(challenges.y); + const evalR2Y = polynomials.R2.evaluate(challenges.y); + let mulL0 = Fr.sub(challenges.y, roots.S0.h0w8[0]); + for (let i = 1; i < 8; i++) mulL0 = Fr.mul(mulL0, Fr.sub(challenges.y, roots.S0.h0w8[i])); + let mulL1 = Fr.sub(challenges.y, roots.S1.h1w4[0]); + for (let i = 1; i < 4; i++) mulL1 = Fr.mul(mulL1, Fr.sub(challenges.y, roots.S1.h1w4[i])); + let mulL2 = Fr.sub(challenges.y, roots.S2.h2w3[0]); + for (let i = 1; i < 3; i++) mulL2 = Fr.mul(mulL2, Fr.sub(challenges.y, roots.S2.h2w3[i])); + for (let i = 0; i < 3; i++) mulL2 = Fr.mul(mulL2, Fr.sub(challenges.y, roots.S2.h3w3[i])); + let preL0 = Fr.mul(mulL1, mulL2); + let preL1 = Fr.mul(challenges.alpha, Fr.mul(mulL0, mulL2)); + let preL2 = Fr.mul(Fr.square(challenges.alpha), Fr.mul(mulL0, mulL1)); + toInverse["denH1"] = mulL1; + toInverse["denH2"] = mulL2; + polynomials.L = Polynomial.fromPolynomial(polynomials.C0, curve, logger); + polynomials.L.subScalar(evalR0Y); + polynomials.L.mulScalar(preL0); + let l2 = Polynomial.fromPolynomial(polynomials.C1, curve, logger); + l2.subScalar(evalR1Y); + l2.mulScalar(preL1); + let l3 = Polynomial.fromPolynomial(polynomials.C2, curve, logger); + l3.subScalar(evalR2Y); + l3.mulScalar(preL2); + polynomials.L.add(l2); + polynomials.L.add(l3); + if (logger) logger.info("> Computing ZT polynomial"); + await computeZT(); + const evalZTY = polynomials.ZT.evaluate(challenges.y); + polynomials.F.mulScalar(evalZTY); + polynomials.L.sub(polynomials.F); + if (polynomials.L.degree() >= 9 * zkey.domainSize) throw new Error("L Polynomial is not well calculated"); + delete buffers.L; + } + async function computeZT() { + polynomials.ZT = Polynomial.zerofierPolynomial([ + roots.S0.h0w8[0], + roots.S0.h0w8[1], + roots.S0.h0w8[2], + roots.S0.h0w8[3], + roots.S0.h0w8[4], + roots.S0.h0w8[5], + roots.S0.h0w8[6], + roots.S0.h0w8[7], + roots.S1.h1w4[0], + roots.S1.h1w4[1], + roots.S1.h1w4[2], + roots.S1.h1w4[3], + roots.S2.h2w3[0], + roots.S2.h2w3[1], + roots.S2.h2w3[2], + roots.S2.h3w3[0], + roots.S2.h3w3[1], + roots.S2.h3w3[2] + ], curve); + } + async function computeZTS2() { + polynomials.ZTS2 = Polynomial.zerofierPolynomial([ + roots.S1.h1w4[0], + roots.S1.h1w4[1], + roots.S1.h1w4[2], + roots.S1.h1w4[3], + roots.S2.h2w3[0], + roots.S2.h2w3[1], + roots.S2.h2w3[2], + roots.S2.h3w3[0], + roots.S2.h3w3[1], + roots.S2.h3w3[2] + ], curve); + } + } + function getMontgomeryBatchedInverse() { + let xiN = challenges.xi; + for (let i = 0; i < zkey.power; i++) xiN = Fr.square(xiN); + toInverse["zh"] = Fr.sub(xiN, Fr.one); + computeLiS0(toInverse, roots.S0.h0w8, challenges.y, curve); + computeLiS1(toInverse, roots.S1.h1w4, challenges.y, curve); + computeLiS2(toInverse, roots.S2.h2w3, roots.S2.h3w3, challenges.y, challenges.xi, challenges.xiw, curve); + const size = Math.max(1, zkey.nPublic); + let w = Fr.one; + for (let i = 0; i < size; i++) { + toInverse["Li_" + (i + 1)] = Fr.mul(Fr.e(zkey.domainSize), Fr.sub(challenges.xi, w)); + w = Fr.mul(w, Fr.w[zkey.power]); + } + let mulAccumulator = Fr.one; + for (const element of Object.values(toInverse)) if (Array.isArray(element)) for (const subElement of element) mulAccumulator = Fr.mul(mulAccumulator, subElement); + else mulAccumulator = Fr.mul(mulAccumulator, element); + return Fr.inv(mulAccumulator); + function computeLiS0(toInverse, roots, x, curve) { + const Fr = curve.Fr; + const len = roots.length; + const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); + const Li = []; + for (let i = 0; i < len; i++) { + const den2 = roots[(len - 1) * i % len]; + const den3 = Fr.sub(x, roots[i]); + toInverse[["LiS0_" + (i + 1)]] = Fr.mul(Fr.mul(den1, den2), den3); + } + return Li; + } + function computeLiS1(toInverse, roots, x, curve) { + const Fr = curve.Fr; + const len = roots.length; + const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); + const Li = []; + for (let i = 0; i < len; i++) { + const den2 = roots[(len - 1) * i % len]; + const den3 = Fr.sub(x, roots[i]); + toInverse[["LiS1_" + (i + 1)]] = Fr.mul(Fr.mul(den1, den2), den3); + } + return Li; + } + function computeLiS2(toInverse, S2, S2p, value, xi, xiw, curve) { + const Fr = curve.Fr; + const Li = []; + const _3h2 = Fr.mul(Fr.e(3), S2[0]); + const xisubxiw = Fr.sub(xi, xiw); + let den1 = Fr.mul(_3h2, xisubxiw); + for (let i = 0; i < 3; i++) { + const den2 = S2[2 * i % 3]; + const den3 = Fr.sub(value, S2[i]); + toInverse[["LiS2_" + (i + 1)]] = Fr.mul(den1, Fr.mul(den2, den3)); + } + const _3h3 = Fr.mul(Fr.e(3), S2p[0]); + const xiwsubxi = Fr.sub(xiw, xi); + den1 = Fr.mul(_3h3, xiwsubxi); + for (let i = 0; i < 3; i++) { + const den2 = S2p[2 * i % 3]; + const den3 = Fr.sub(value, S2p[i]); + toInverse[["LiS2_" + (i + 1 + 3)]] = Fr.mul(den1, Fr.mul(den2, den3)); + } + return Li; + } + } +} +//#endregion +//#region src/fflonk_full_prove.js +var { unstringifyBigInts: unstringifyBigInts$3 } = ffjavascript.utils; async function fflonkFullProve$1(_input, wasmFilename, zkeyFilename, logger, wtnsCalcOptions, proverOptions) { - const input = unstringifyBigInts$3(_input); - - const wtns= {type: "mem"}; - - // Compute the witness - await wtnsCalculate$1(input, wasmFilename, wtns, wtnsCalcOptions); - - // Compute the proof - return await fflonkProve$1(zkeyFilename, wtns, logger, proverOptions); -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -const { unstringifyBigInts: unstringifyBigInts$2 } = ffjavascript.utils; - + const input = unstringifyBigInts$3(_input); + const wtns = { type: "mem" }; + await wtnsCalculate$1(input, wasmFilename, wtns, wtnsCalcOptions); + return await fflonkProve$1(zkeyFilename, wtns, logger, proverOptions); +} +//#endregion +//#region src/fflonk_verify.js +var { unstringifyBigInts: unstringifyBigInts$2 } = ffjavascript.utils; async function fflonkVerify$1(_vk_verifier, _publicSignals, _proof, logger) { - if (logger) logger.info("FFLONK VERIFIER STARTED"); - - _vk_verifier = unstringifyBigInts$2(_vk_verifier); - _proof = unstringifyBigInts$2(_proof); - - const curve = await getCurveFromName(_vk_verifier.curve); - - const vk = fromObjectVk(curve, _vk_verifier); - - // TODO ??? Compute wr^3 and check if it matches with w - - const proof = new Proof(curve, logger); - proof.fromObjectProof(_proof); - - const publicSignals = unstringifyBigInts$2(_publicSignals); - - if (publicSignals.length !== vk.nPublic) { - logger.error("Number of public signals does not match with vk"); - return false; - } - - const Fr = curve.Fr; - - if (logger) { - logger.info("----------------------------"); - logger.info(" FFLONK VERIFY SETTINGS"); - logger.info(` Curve: ${curve.name}`); - logger.info(` Circuit power: ${vk.power}`); - logger.info(` Domain size: ${2 ** vk.power}`); - logger.info(` Public vars: ${vk.nPublic}`); - logger.info("----------------------------"); - } - - // STEP 1 - Validate that all polynomial commitments ∈ G_1 - if (logger) logger.info("> Checking commitments belong to G1"); - if (!commitmentsBelongToG1(curve, proof, vk)) { - if (logger) logger.error("Proof commitments are not valid"); - return false; - } - - // STEP 2 - Validate that all evaluations ∈ F - if (logger) logger.info("> Checking evaluations belong to F"); - if (!evaluationsAreValid(curve, proof)) { - if (logger) logger.error("Proof evaluations are not valid."); - return false; - } - - // STEP 3 - Validate that w_i ∈ F for i ∈ [l] - if (logger) logger.info("> Checking public inputs belong to F"); - if (!publicInputsAreValid(curve, publicSignals)) { - if (logger) logger.error("Public inputs are not valid."); - return false; - } - - // STEP 4 - Compute the challenges: beta, gamma, xi, alpha and y ∈ F - // as in prover description, from the common preprocessed inputs, public inputs and elements of π_SNARK - if (logger) logger.info("> Computing challenges"); - const { challenges, roots } = computeChallenges(curve, proof, vk, publicSignals, logger); - - // STEP 5 - Compute the zero polynomial evaluation Z_H(xi) = xi^n - 1 - if (logger) logger.info("> Computing Zero polynomial evaluation Z_H(xi)"); - challenges.zh = Fr.sub(challenges.xiN, Fr.one); - challenges.invzh = Fr.inv(challenges.zh); - - // STEP 6 - Compute the lagrange polynomial evaluation L_1(xi) - if (logger) logger.info("> Computing Lagrange evaluations"); - const lagrangeEvals = await computeLagrangeEvaluations(curve, challenges, vk); - - // STEP 7 - Compute public input evaluation PI(xi) - if (logger) logger.info("> Computing polynomial identities PI(X)"); - const pi = calculatePI(curve, publicSignals, lagrangeEvals); - - // STEP 8 - Compute polynomial r0 ∈ F_{<4}[X] - if (logger) logger.info("> Computing r0(y)"); - const r0 = computeR0(proof, challenges, roots, curve, logger); - - // STEP 9 - Compute polynomial r1 ∈ F_{<4}[X] - if (logger) logger.info("> Computing r1(y)"); - const r1 = computeR1(proof, challenges, roots, pi, curve, logger); - - // STEP 9 - Compute polynomial r2 ∈ F_{<6}[X] - if (logger) logger.info("> Computing r2(y)"); - const r2 = computeR2(proof, challenges, roots, lagrangeEvals[1], vk, curve, logger); - - if (logger) logger.info("> Computing F"); - const F = computeF(curve, proof, vk, challenges, roots); - - if (logger) logger.info("> Computing E"); - const E = computeE(curve, proof, challenges, vk, r0, r1, r2); - - if (logger) logger.info("> Computing J"); - const J = computeJ(curve, proof, challenges); - - if (logger) logger.info("> Validate all evaluations with a pairing"); - const res = await isValidPairing(curve, proof, challenges, vk, F, E, J); - - if (logger) { - if (res) { - logger.info("PROOF VERIFIED SUCCESSFULLY"); - } else { - logger.warn("Invalid Proof"); - } - } - - if (logger) logger.info("FFLONK VERIFIER FINISHED"); - - return res; - -} - + if (logger) logger.info("FFLONK VERIFIER STARTED"); + _vk_verifier = unstringifyBigInts$2(_vk_verifier); + _proof = unstringifyBigInts$2(_proof); + const curve = await getCurveFromName(_vk_verifier.curve); + const vk = fromObjectVk(curve, _vk_verifier); + const proof = new Proof(curve, logger); + proof.fromObjectProof(_proof); + const publicSignals = unstringifyBigInts$2(_publicSignals); + if (publicSignals.length !== vk.nPublic) { + logger.error("Number of public signals does not match with vk"); + return false; + } + const Fr = curve.Fr; + if (logger) { + logger.info("----------------------------"); + logger.info(" FFLONK VERIFY SETTINGS"); + logger.info(` Curve: ${curve.name}`); + logger.info(` Circuit power: ${vk.power}`); + logger.info(` Domain size: ${2 ** vk.power}`); + logger.info(` Public vars: ${vk.nPublic}`); + logger.info("----------------------------"); + } + if (logger) logger.info("> Checking commitments belong to G1"); + if (!commitmentsBelongToG1(curve, proof, vk)) { + if (logger) logger.error("Proof commitments are not valid"); + return false; + } + if (logger) logger.info("> Checking evaluations belong to F"); + if (!evaluationsAreValid(curve, proof)) { + if (logger) logger.error("Proof evaluations are not valid."); + return false; + } + if (logger) logger.info("> Checking public inputs belong to F"); + if (!publicInputsAreValid(curve, publicSignals)) { + if (logger) logger.error("Public inputs are not valid."); + return false; + } + if (logger) logger.info("> Computing challenges"); + const { challenges, roots } = computeChallenges(curve, proof, vk, publicSignals, logger); + if (logger) logger.info("> Computing Zero polynomial evaluation Z_H(xi)"); + challenges.zh = Fr.sub(challenges.xiN, Fr.one); + challenges.invzh = Fr.inv(challenges.zh); + if (logger) logger.info("> Computing Lagrange evaluations"); + const lagrangeEvals = await computeLagrangeEvaluations(curve, challenges, vk); + if (logger) logger.info("> Computing polynomial identities PI(X)"); + const pi = calculatePI(curve, publicSignals, lagrangeEvals); + if (logger) logger.info("> Computing r0(y)"); + const r0 = computeR0(proof, challenges, roots, curve, logger); + if (logger) logger.info("> Computing r1(y)"); + const r1 = computeR1(proof, challenges, roots, pi, curve, logger); + if (logger) logger.info("> Computing r2(y)"); + const r2 = computeR2(proof, challenges, roots, lagrangeEvals[1], vk, curve, logger); + if (logger) logger.info("> Computing F"); + const F = computeF(curve, proof, vk, challenges, roots); + if (logger) logger.info("> Computing E"); + const E = computeE(curve, proof, challenges, vk, r0, r1, r2); + if (logger) logger.info("> Computing J"); + const J = computeJ(curve, proof, challenges); + if (logger) logger.info("> Validate all evaluations with a pairing"); + const res = await isValidPairing(curve, proof, challenges, vk, F, E, J); + if (logger) if (res) logger.info("PROOF VERIFIED SUCCESSFULLY"); + else logger.warn("Invalid Proof"); + if (logger) logger.info("FFLONK VERIFIER FINISHED"); + return res; +} function fromObjectVk(curve, vk) { - const res = vk; - res.k1 = curve.Fr.fromObject(vk.k1); - res.k2 = curve.Fr.fromObject(vk.k2); - res.w = curve.Fr.fromObject(vk.w); - // res.wW = curve.Fr.fromObject(vk.wW); - res.w3 = curve.Fr.fromObject(vk.w3); - res.w4 = curve.Fr.fromObject(vk.w4); - res.w8 = curve.Fr.fromObject(vk.w8); - res.wr = curve.Fr.fromObject(vk.wr); - res.X_2 = curve.G2.fromObject(vk.X_2); - res.C0 = curve.G1.fromObject(vk.C0); - return res; -} - + const res = vk; + res.k1 = curve.Fr.fromObject(vk.k1); + res.k2 = curve.Fr.fromObject(vk.k2); + res.w = curve.Fr.fromObject(vk.w); + res.w3 = curve.Fr.fromObject(vk.w3); + res.w4 = curve.Fr.fromObject(vk.w4); + res.w8 = curve.Fr.fromObject(vk.w8); + res.wr = curve.Fr.fromObject(vk.wr); + res.X_2 = curve.G2.fromObject(vk.X_2); + res.C0 = curve.G1.fromObject(vk.C0); + return res; +} function commitmentsBelongToG1(curve, proof, vk) { - const G1 = curve.G1; - return G1.isValid(proof.polynomials.C1) - && G1.isValid(proof.polynomials.C2) - && G1.isValid(proof.polynomials.W1) - && G1.isValid(proof.polynomials.W2) - && G1.isValid(vk.C0); -} - + const G1 = curve.G1; + return G1.isValid(proof.polynomials.C1) && G1.isValid(proof.polynomials.C2) && G1.isValid(proof.polynomials.W1) && G1.isValid(proof.polynomials.W2) && G1.isValid(vk.C0); +} function checkValueBelongToField(curve, value) { - return ffjavascript.Scalar.geq(value, 0) && ffjavascript.Scalar.lt(value, curve.r); + return ffjavascript.Scalar.geq(value, 0) && ffjavascript.Scalar.lt(value, curve.r); } - function checkEvaluationIsValid(curve, evaluation) { - return checkValueBelongToField(curve, ffjavascript.Scalar.fromRprLE(evaluation)); + return checkValueBelongToField(curve, ffjavascript.Scalar.fromRprLE(evaluation)); } - function evaluationsAreValid(curve, proof) { - return checkEvaluationIsValid(curve, proof.evaluations.ql) - && checkEvaluationIsValid(curve, proof.evaluations.qr) - && checkEvaluationIsValid(curve, proof.evaluations.qm) - && checkEvaluationIsValid(curve, proof.evaluations.qo) - && checkEvaluationIsValid(curve, proof.evaluations.qc) - && checkEvaluationIsValid(curve, proof.evaluations.s1) - && checkEvaluationIsValid(curve, proof.evaluations.s2) - && checkEvaluationIsValid(curve, proof.evaluations.s3) - && checkEvaluationIsValid(curve, proof.evaluations.a) - && checkEvaluationIsValid(curve, proof.evaluations.b) - && checkEvaluationIsValid(curve, proof.evaluations.c) - && checkEvaluationIsValid(curve, proof.evaluations.z) - && checkEvaluationIsValid(curve, proof.evaluations.zw) - && checkEvaluationIsValid(curve, proof.evaluations.t1w) - && checkEvaluationIsValid(curve, proof.evaluations.t2w); -} - + return checkEvaluationIsValid(curve, proof.evaluations.ql) && checkEvaluationIsValid(curve, proof.evaluations.qr) && checkEvaluationIsValid(curve, proof.evaluations.qm) && checkEvaluationIsValid(curve, proof.evaluations.qo) && checkEvaluationIsValid(curve, proof.evaluations.qc) && checkEvaluationIsValid(curve, proof.evaluations.s1) && checkEvaluationIsValid(curve, proof.evaluations.s2) && checkEvaluationIsValid(curve, proof.evaluations.s3) && checkEvaluationIsValid(curve, proof.evaluations.a) && checkEvaluationIsValid(curve, proof.evaluations.b) && checkEvaluationIsValid(curve, proof.evaluations.c) && checkEvaluationIsValid(curve, proof.evaluations.z) && checkEvaluationIsValid(curve, proof.evaluations.zw) && checkEvaluationIsValid(curve, proof.evaluations.t1w) && checkEvaluationIsValid(curve, proof.evaluations.t2w); +} function publicInputsAreValid(curve, publicInputs) { - for(let i = 0; i < publicInputs.length; i++) { - if(!checkValueBelongToField(curve, publicInputs[i])) { - return false; - } - } - return true; -} - + for (let i = 0; i < publicInputs.length; i++) if (!checkValueBelongToField(curve, publicInputs[i])) return false; + return true; +} function computeChallenges(curve, proof, vk, publicSignals, logger) { - const Fr = curve.Fr; - - const challenges = {}; - const roots = {}; - const transcript = new Keccak256Transcript(curve); - - // Add C0 to the transcript - transcript.addPolCommitment(vk.C0); - - for (let i = 0; i < publicSignals.length; i++) { - transcript.addScalar(Fr.e(publicSignals[i])); - } - - transcript.addPolCommitment(proof.polynomials.C1); - challenges.beta = transcript.getChallenge(); - transcript.reset(); - - transcript.addScalar(challenges.beta); - challenges.gamma = transcript.getChallenge(); - - transcript.reset(); - transcript.addScalar(challenges.gamma); - transcript.addPolCommitment(proof.polynomials.C2); - const xiSeed = transcript.getChallenge(); - const xiSeed2 = Fr.square(xiSeed); - - let w8 = []; - w8[1] = vk.w8; - w8[2] = Fr.square(vk.w8); - w8[3] = Fr.mul(w8[2], vk.w8); - w8[4] = Fr.mul(w8[3], vk.w8); - w8[5] = Fr.mul(w8[4], vk.w8); - w8[6] = Fr.mul(w8[5], vk.w8); - w8[7] = Fr.mul(w8[6], vk.w8); - let w4 = []; - w4[1] = vk.w4; - w4[2] = Fr.square(vk.w4); - w4[3] = Fr.mul(w4[2], vk.w4); - let w3 = []; - w3[1] = vk.w3; - w3[2] = Fr.square(vk.w3); - - // const w4_2 = Fr.square(vk.w4); - // const w4_3 = Fr.mul(w4_2, vk.w4); - // const w3_2 = Fr.square(vk.w3); - - // Compute h0 = xiSeeder^3 - roots.S0 = {}; - roots.S0.h0w8 = []; - roots.S0.h0w8[0] = Fr.mul(xiSeed2, xiSeed); - for (let i = 1; i < 8; i++) { - roots.S0.h0w8[i] = Fr.mul(roots.S0.h0w8[0], w8[i]); - } - - // Compute h1 = xi_seeder^6 - roots.S1 = {}; - roots.S1.h1w4 = []; - roots.S1.h1w4[0] = Fr.square(roots.S0.h0w8[0]); - for (let i = 1; i < 4; i++) { - roots.S1.h1w4[i] = Fr.mul(roots.S1.h1w4[0], w4[i]); - } - - // Compute h2 = xi_seeder^8 - roots.S2 = {}; - roots.S2.h2w3 = []; - roots.S2.h2w3[0] = Fr.mul(roots.S1.h1w4[0], xiSeed2); - roots.S2.h2w3[1] = Fr.mul(roots.S2.h2w3[0], w3[1]); - roots.S2.h2w3[2] = Fr.mul(roots.S2.h2w3[0], w3[2]); - - roots.S2.h3w3 = []; - // Multiply h3 by third-root-omega to obtain h_3^3 = xiω - // So, h3 = xi_seeder^8 ω^{1/3} - roots.S2.h3w3[0] = Fr.mul(roots.S2.h2w3[0], vk.wr); - roots.S2.h3w3[1] = Fr.mul(roots.S2.h3w3[0], w3[1]); - roots.S2.h3w3[2] = Fr.mul(roots.S2.h3w3[0], w3[2]); - - // Compute xi = xi_seeder^12 - challenges.xi = Fr.mul(Fr.square(roots.S2.h2w3[0]), roots.S2.h2w3[0]); - challenges.xiw = Fr.mul(challenges.xi, Fr.w[vk.power]); - - challenges.xiN = challenges.xi; - vk.domainSize = 1; - for (let i = 0; i < vk.power; i++) { - challenges.xiN = Fr.square(challenges.xiN); - vk.domainSize *= 2; - } - - transcript.reset(); - transcript.addScalar(xiSeed); - transcript.addScalar(proof.evaluations.ql); - transcript.addScalar(proof.evaluations.qr); - transcript.addScalar(proof.evaluations.qm); - transcript.addScalar(proof.evaluations.qo); - transcript.addScalar(proof.evaluations.qc); - transcript.addScalar(proof.evaluations.s1); - transcript.addScalar(proof.evaluations.s2); - transcript.addScalar(proof.evaluations.s3); - transcript.addScalar(proof.evaluations.a); - transcript.addScalar(proof.evaluations.b); - transcript.addScalar(proof.evaluations.c); - transcript.addScalar(proof.evaluations.z); - transcript.addScalar(proof.evaluations.zw); - transcript.addScalar(proof.evaluations.t1w); - transcript.addScalar(proof.evaluations.t2w); - challenges.alpha = transcript.getChallenge(); - - transcript.reset(); - transcript.addScalar(challenges.alpha); - transcript.addPolCommitment(proof.polynomials.W1); - challenges.y = transcript.getChallenge(); - - if (logger) { - logger.info("··· challenges.beta: " + Fr.toString(challenges.beta)); - logger.info("··· challenges.gamma: " + Fr.toString(challenges.gamma)); - logger.info("··· challenges.xi: " + Fr.toString(challenges.xi)); - logger.info("··· challenges.alpha: " + Fr.toString(challenges.alpha)); - logger.info("··· challenges.y: " + Fr.toString(challenges.y)); - } - - return { challenges: challenges, roots: roots }; -} - + const Fr = curve.Fr; + const challenges = {}; + const roots = {}; + const transcript = new Keccak256Transcript(curve); + transcript.addPolCommitment(vk.C0); + for (let i = 0; i < publicSignals.length; i++) transcript.addScalar(Fr.e(publicSignals[i])); + transcript.addPolCommitment(proof.polynomials.C1); + challenges.beta = transcript.getChallenge(); + transcript.reset(); + transcript.addScalar(challenges.beta); + challenges.gamma = transcript.getChallenge(); + transcript.reset(); + transcript.addScalar(challenges.gamma); + transcript.addPolCommitment(proof.polynomials.C2); + const xiSeed = transcript.getChallenge(); + const xiSeed2 = Fr.square(xiSeed); + let w8 = []; + w8[1] = vk.w8; + w8[2] = Fr.square(vk.w8); + w8[3] = Fr.mul(w8[2], vk.w8); + w8[4] = Fr.mul(w8[3], vk.w8); + w8[5] = Fr.mul(w8[4], vk.w8); + w8[6] = Fr.mul(w8[5], vk.w8); + w8[7] = Fr.mul(w8[6], vk.w8); + let w4 = []; + w4[1] = vk.w4; + w4[2] = Fr.square(vk.w4); + w4[3] = Fr.mul(w4[2], vk.w4); + let w3 = []; + w3[1] = vk.w3; + w3[2] = Fr.square(vk.w3); + roots.S0 = {}; + roots.S0.h0w8 = []; + roots.S0.h0w8[0] = Fr.mul(xiSeed2, xiSeed); + for (let i = 1; i < 8; i++) roots.S0.h0w8[i] = Fr.mul(roots.S0.h0w8[0], w8[i]); + roots.S1 = {}; + roots.S1.h1w4 = []; + roots.S1.h1w4[0] = Fr.square(roots.S0.h0w8[0]); + for (let i = 1; i < 4; i++) roots.S1.h1w4[i] = Fr.mul(roots.S1.h1w4[0], w4[i]); + roots.S2 = {}; + roots.S2.h2w3 = []; + roots.S2.h2w3[0] = Fr.mul(roots.S1.h1w4[0], xiSeed2); + roots.S2.h2w3[1] = Fr.mul(roots.S2.h2w3[0], w3[1]); + roots.S2.h2w3[2] = Fr.mul(roots.S2.h2w3[0], w3[2]); + roots.S2.h3w3 = []; + roots.S2.h3w3[0] = Fr.mul(roots.S2.h2w3[0], vk.wr); + roots.S2.h3w3[1] = Fr.mul(roots.S2.h3w3[0], w3[1]); + roots.S2.h3w3[2] = Fr.mul(roots.S2.h3w3[0], w3[2]); + challenges.xi = Fr.mul(Fr.square(roots.S2.h2w3[0]), roots.S2.h2w3[0]); + challenges.xiw = Fr.mul(challenges.xi, Fr.w[vk.power]); + challenges.xiN = challenges.xi; + vk.domainSize = 1; + for (let i = 0; i < vk.power; i++) { + challenges.xiN = Fr.square(challenges.xiN); + vk.domainSize *= 2; + } + transcript.reset(); + transcript.addScalar(xiSeed); + transcript.addScalar(proof.evaluations.ql); + transcript.addScalar(proof.evaluations.qr); + transcript.addScalar(proof.evaluations.qm); + transcript.addScalar(proof.evaluations.qo); + transcript.addScalar(proof.evaluations.qc); + transcript.addScalar(proof.evaluations.s1); + transcript.addScalar(proof.evaluations.s2); + transcript.addScalar(proof.evaluations.s3); + transcript.addScalar(proof.evaluations.a); + transcript.addScalar(proof.evaluations.b); + transcript.addScalar(proof.evaluations.c); + transcript.addScalar(proof.evaluations.z); + transcript.addScalar(proof.evaluations.zw); + transcript.addScalar(proof.evaluations.t1w); + transcript.addScalar(proof.evaluations.t2w); + challenges.alpha = transcript.getChallenge(); + transcript.reset(); + transcript.addScalar(challenges.alpha); + transcript.addPolCommitment(proof.polynomials.W1); + challenges.y = transcript.getChallenge(); + if (logger) { + logger.info("··· challenges.beta: " + Fr.toString(challenges.beta)); + logger.info("··· challenges.gamma: " + Fr.toString(challenges.gamma)); + logger.info("··· challenges.xi: " + Fr.toString(challenges.xi)); + logger.info("··· challenges.alpha: " + Fr.toString(challenges.alpha)); + logger.info("··· challenges.y: " + Fr.toString(challenges.y)); + } + return { + challenges, + roots + }; +} async function computeLagrangeEvaluations(curve, challenges, vk) { - const Fr = curve.Fr; - - const size = Math.max(1, vk.nPublic); - const numArr = new ffjavascript.BigBuffer(size * Fr.n8); - let denArr = new ffjavascript.BigBuffer(size * Fr.n8); - - let w = Fr.one; - for (let i = 0; i < size; i++) { - const i_sFr = i * Fr.n8; - numArr.set(Fr.mul(w, challenges.zh), i_sFr); - denArr.set(Fr.mul(Fr.e(vk.domainSize), Fr.sub(challenges.xi, w)), i_sFr); - w = Fr.mul(w, vk.w); - } - - denArr = await Fr.batchInverse(denArr); - - let L = []; - for (let i = 0; i < size; i++) { - const i_sFr = i * Fr.n8; - L[i + 1] = Fr.mul(numArr.slice(i_sFr, i_sFr + Fr.n8), denArr.slice(i_sFr, i_sFr + Fr.n8)); - } - return L; -} - + const Fr = curve.Fr; + const size = Math.max(1, vk.nPublic); + const numArr = new ffjavascript.BigBuffer(size * Fr.n8); + let denArr = new ffjavascript.BigBuffer(size * Fr.n8); + let w = Fr.one; + for (let i = 0; i < size; i++) { + const i_sFr = i * Fr.n8; + numArr.set(Fr.mul(w, challenges.zh), i_sFr); + denArr.set(Fr.mul(Fr.e(vk.domainSize), Fr.sub(challenges.xi, w)), i_sFr); + w = Fr.mul(w, vk.w); + } + denArr = await Fr.batchInverse(denArr); + let L = []; + for (let i = 0; i < size; i++) { + const i_sFr = i * Fr.n8; + L[i + 1] = Fr.mul(numArr.slice(i_sFr, i_sFr + Fr.n8), denArr.slice(i_sFr, i_sFr + Fr.n8)); + } + return L; +} function calculatePI(curve, publicSignals, lagrangeEvals) { - const Fr = curve.Fr; - - let pi = Fr.zero; - for (let i = 0; i < publicSignals.length; i++) { - const w = Fr.e(publicSignals[i]); - pi = Fr.sub(pi, Fr.mul(w, lagrangeEvals[i + 1])); - } - return pi; -} - + const Fr = curve.Fr; + let pi = Fr.zero; + for (let i = 0; i < publicSignals.length; i++) { + const w = Fr.e(publicSignals[i]); + pi = Fr.sub(pi, Fr.mul(w, lagrangeEvals[i + 1])); + } + return pi; +} function computeR0(proof, challenges, roots, curve, logger) { - const Fr = curve.Fr; - - const Li = computeLagrangeLiSi(roots.S0.h0w8, challenges.y, challenges.xi, curve); - - // r0(y) = ∑_1^8 C_0(h_0 ω_8^{i-1}) L_i(y). To this end we need to compute - - // Compute the 8 C0 values - if (logger) logger.info("··· Computing r0(y)"); - - let res = Fr.zero; - for (let i = 0; i < 8; i++) { - let coefValues = []; - coefValues[1] = roots.S0.h0w8[i]; - for (let j = 2; j < 8; j++) { - coefValues[j] = Fr.mul(coefValues[j - 1], roots.S0.h0w8[i]); - } - - let c0 = Fr.add(proof.evaluations.ql, Fr.mul(proof.evaluations.qr, coefValues[1])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.qo, coefValues[2])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.qm, coefValues[3])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.qc, coefValues[4])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.s1, coefValues[5])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.s2, coefValues[6])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.s3, coefValues[7])); - - res = Fr.add(res, Fr.mul(c0, Li[i])); - } - - return res; -} - + const Fr = curve.Fr; + const Li = computeLagrangeLiSi(roots.S0.h0w8, challenges.y, challenges.xi, curve); + if (logger) logger.info("··· Computing r0(y)"); + let res = Fr.zero; + for (let i = 0; i < 8; i++) { + let coefValues = []; + coefValues[1] = roots.S0.h0w8[i]; + for (let j = 2; j < 8; j++) coefValues[j] = Fr.mul(coefValues[j - 1], roots.S0.h0w8[i]); + let c0 = Fr.add(proof.evaluations.ql, Fr.mul(proof.evaluations.qr, coefValues[1])); + c0 = Fr.add(c0, Fr.mul(proof.evaluations.qo, coefValues[2])); + c0 = Fr.add(c0, Fr.mul(proof.evaluations.qm, coefValues[3])); + c0 = Fr.add(c0, Fr.mul(proof.evaluations.qc, coefValues[4])); + c0 = Fr.add(c0, Fr.mul(proof.evaluations.s1, coefValues[5])); + c0 = Fr.add(c0, Fr.mul(proof.evaluations.s2, coefValues[6])); + c0 = Fr.add(c0, Fr.mul(proof.evaluations.s3, coefValues[7])); + res = Fr.add(res, Fr.mul(c0, Li[i])); + } + return res; +} function computeR1(proof, challenges, roots, pi, curve, logger) { - const Fr = curve.Fr; - - const Li = computeLagrangeLiSi(roots.S1.h1w4, challenges.y, challenges.xi, curve); - - // r1(y) = ∑_1^4 C_1(h_1 ω_4^{i-1}) L_i(y). To this end we need to compute - // Z1 = {C1(h_1}, C1(h_1 ω_4), C1(h_1 ω_4^2), C1(h_1 ω_4^3)} - // where C_1(h_1 ω_4^{i-1}) = eval.a + h_1 ω_4^i eval.b + (h_1 ω_4^i)^2 eval.c + (h_1 ω_4^i)^3 T0(xi), - // where T0(xi) = [ qL·a + qR·b + qM·a·b + qO·c + qC + PI(xi) ] / Z_H(xi) - - // Compute T0(xi) - if (logger) logger.info("··· Computing T0(xi)"); - let t0 = Fr.mul(proof.evaluations.ql, proof.evaluations.a); - t0 = Fr.add(t0, Fr.mul(proof.evaluations.qr, proof.evaluations.b)); - t0 = Fr.add(t0, Fr.mul(proof.evaluations.qm, Fr.mul(proof.evaluations.a, proof.evaluations.b))); - t0 = Fr.add(t0, Fr.mul(proof.evaluations.qo, proof.evaluations.c)); - t0 = Fr.add(t0, proof.evaluations.qc); - t0 = Fr.add(t0, pi); - t0 = Fr.mul(t0, challenges.invzh); - - // Compute the 4 C1 values - if (logger) logger.info("··· Computing C1(h_1ω_4^i) values"); - - let res = Fr.zero; - for (let i = 0; i < 4; i++) { - let c1 = proof.evaluations.a; - c1 = Fr.add(c1, Fr.mul(roots.S1.h1w4[i], proof.evaluations.b)); - const h1w4Squared = Fr.square(roots.S1.h1w4[i]); - c1 = Fr.add(c1, Fr.mul(h1w4Squared, proof.evaluations.c)); - c1 = Fr.add(c1, Fr.mul(Fr.mul(h1w4Squared, roots.S1.h1w4[i]), t0)); - - res = Fr.add(res, Fr.mul(c1, Li[i])); - } - - return res; -} - + const Fr = curve.Fr; + const Li = computeLagrangeLiSi(roots.S1.h1w4, challenges.y, challenges.xi, curve); + if (logger) logger.info("··· Computing T0(xi)"); + let t0 = Fr.mul(proof.evaluations.ql, proof.evaluations.a); + t0 = Fr.add(t0, Fr.mul(proof.evaluations.qr, proof.evaluations.b)); + t0 = Fr.add(t0, Fr.mul(proof.evaluations.qm, Fr.mul(proof.evaluations.a, proof.evaluations.b))); + t0 = Fr.add(t0, Fr.mul(proof.evaluations.qo, proof.evaluations.c)); + t0 = Fr.add(t0, proof.evaluations.qc); + t0 = Fr.add(t0, pi); + t0 = Fr.mul(t0, challenges.invzh); + if (logger) logger.info("··· Computing C1(h_1ω_4^i) values"); + let res = Fr.zero; + for (let i = 0; i < 4; i++) { + let c1 = proof.evaluations.a; + c1 = Fr.add(c1, Fr.mul(roots.S1.h1w4[i], proof.evaluations.b)); + const h1w4Squared = Fr.square(roots.S1.h1w4[i]); + c1 = Fr.add(c1, Fr.mul(h1w4Squared, proof.evaluations.c)); + c1 = Fr.add(c1, Fr.mul(Fr.mul(h1w4Squared, roots.S1.h1w4[i]), t0)); + res = Fr.add(res, Fr.mul(c1, Li[i])); + } + return res; +} function computeR2(proof, challenges, roots, lagrange1, vk, curve, logger) { - const Fr = curve.Fr; - - const LiS2 = computeLagrangeLiS2([roots.S2.h2w3, roots.S2.h3w3], challenges.y, challenges.xi, challenges.xiw, curve); - - // r2(y) = ∑_1^3 C_2(h_2 ω_3^{i-1}) L_i(y) + ∑_1^3 C_2(h_3 ω_3^{i-1}) L_{i+3}(y). To this end we need to compute - // Z2 = {[C2(h_2}, C2(h_2 ω_3), C2(h_2 ω_3^2)], [C2(h_3}, C2(h_3 ω_3), C2(h_3 ω_3^2)]} - // where C_2(h_2 ω_3^{i-1}) = eval.z + h_2 ω_2^i T1(xi) + (h_2 ω_3^i)^2 T2(xi), - // where C_2(h_3 ω_3^{i-1}) = eval.z + h_3 ω_2^i T1(xi) + (h_3 ω_3^i)^2 T2(xi), - // where T1(xi) = [ L_1(xi)(z-1)] / Z_H(xi) - // and T2(xi) = [ (a + beta·xi + gamma)(b + beta·xi·k1 + gamma)(c + beta·xi·k2 + gamma)z - // - (a + beta·sigma1 + gamma)(b + beta·sigma2 + gamma)(c + beta·sigma3 + gamma)zω ] / Z_H(xi) - - // Compute T1(xi) - if (logger) logger.info("··· Computing T1(xi)"); - let t1 = Fr.sub(proof.evaluations.z, Fr.one); - t1 = Fr.mul(t1, lagrange1); - t1 = Fr.mul(t1, challenges.invzh); - - // Compute T2(xi) - if (logger) logger.info("··· Computing T2(xi)"); - const betaxi = Fr.mul(challenges.beta, challenges.xi); - const t211 = Fr.add(proof.evaluations.a, Fr.add(betaxi, challenges.gamma)); - const t212 = Fr.add(proof.evaluations.b, Fr.add(Fr.mul(betaxi, vk.k1), challenges.gamma)); - const t213 = Fr.add(proof.evaluations.c, Fr.add(Fr.mul(betaxi, vk.k2), challenges.gamma)); - const t21 = Fr.mul(t211, Fr.mul(t212, Fr.mul(t213, proof.evaluations.z))); - - const t221 = Fr.add(proof.evaluations.a, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s1), challenges.gamma)); - const t222 = Fr.add(proof.evaluations.b, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s2), challenges.gamma)); - const t223 = Fr.add(proof.evaluations.c, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s3), challenges.gamma)); - const t22 = Fr.mul(t221, Fr.mul(t222, Fr.mul(t223, proof.evaluations.zw))); - - let t2 = Fr.sub(t21, t22); - t2 = Fr.mul(t2, challenges.invzh); - - // Compute the 6 C2 values - if (logger) logger.info("··· Computing C2(h_2ω_3^i) values"); - let res = Fr.zero; - for (let i = 0; i < 3; i++) { - let c2 = Fr.add(proof.evaluations.z, Fr.mul(roots.S2.h2w3[i], t1)); - c2 = Fr.add(c2, Fr.mul(Fr.square(roots.S2.h2w3[i]), t2)); - - res = Fr.add(res, Fr.mul(c2, LiS2[i])); - } - - if (logger) logger.info("··· Computing C2(h_3ω_3^i) values"); - for (let i = 0; i < 3; i++) { - let c2 = Fr.add(proof.evaluations.zw, Fr.mul(roots.S2.h3w3[i], proof.evaluations.t1w)); - c2 = Fr.add(c2, Fr.mul(Fr.square(roots.S2.h3w3[i]), proof.evaluations.t2w)); - - res = Fr.add(res, Fr.mul(c2, LiS2[i + 3])); - } - - return res; -} - + const Fr = curve.Fr; + const LiS2 = computeLagrangeLiS2([roots.S2.h2w3, roots.S2.h3w3], challenges.y, challenges.xi, challenges.xiw, curve); + if (logger) logger.info("··· Computing T1(xi)"); + let t1 = Fr.sub(proof.evaluations.z, Fr.one); + t1 = Fr.mul(t1, lagrange1); + t1 = Fr.mul(t1, challenges.invzh); + if (logger) logger.info("··· Computing T2(xi)"); + const betaxi = Fr.mul(challenges.beta, challenges.xi); + const t211 = Fr.add(proof.evaluations.a, Fr.add(betaxi, challenges.gamma)); + const t212 = Fr.add(proof.evaluations.b, Fr.add(Fr.mul(betaxi, vk.k1), challenges.gamma)); + const t213 = Fr.add(proof.evaluations.c, Fr.add(Fr.mul(betaxi, vk.k2), challenges.gamma)); + const t21 = Fr.mul(t211, Fr.mul(t212, Fr.mul(t213, proof.evaluations.z))); + const t221 = Fr.add(proof.evaluations.a, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s1), challenges.gamma)); + const t222 = Fr.add(proof.evaluations.b, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s2), challenges.gamma)); + const t223 = Fr.add(proof.evaluations.c, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s3), challenges.gamma)); + const t22 = Fr.mul(t221, Fr.mul(t222, Fr.mul(t223, proof.evaluations.zw))); + let t2 = Fr.sub(t21, t22); + t2 = Fr.mul(t2, challenges.invzh); + if (logger) logger.info("··· Computing C2(h_2ω_3^i) values"); + let res = Fr.zero; + for (let i = 0; i < 3; i++) { + let c2 = Fr.add(proof.evaluations.z, Fr.mul(roots.S2.h2w3[i], t1)); + c2 = Fr.add(c2, Fr.mul(Fr.square(roots.S2.h2w3[i]), t2)); + res = Fr.add(res, Fr.mul(c2, LiS2[i])); + } + if (logger) logger.info("··· Computing C2(h_3ω_3^i) values"); + for (let i = 0; i < 3; i++) { + let c2 = Fr.add(proof.evaluations.zw, Fr.mul(roots.S2.h3w3[i], proof.evaluations.t1w)); + c2 = Fr.add(c2, Fr.mul(Fr.square(roots.S2.h3w3[i]), proof.evaluations.t2w)); + res = Fr.add(res, Fr.mul(c2, LiS2[i + 3])); + } + return res; +} function computeF(curve, proof, vk, challenges, roots) { - const G1 = curve.G1; - const Fr = curve.Fr; - - let mulH0 = Fr.sub(challenges.y, roots.S0.h0w8[0]); - for (let i = 1; i < 8; i++) { - mulH0 = Fr.mul(mulH0, Fr.sub(challenges.y, roots.S0.h0w8[i])); - } - - challenges.temp = mulH0; - - let mulH1 = Fr.sub(challenges.y, roots.S1.h1w4[0]); - for (let i = 1; i < 4; i++) { - mulH1 = Fr.mul(mulH1, Fr.sub(challenges.y, roots.S1.h1w4[i])); - } - - let mulH2 = Fr.sub(challenges.y, roots.S2.h2w3[0]); - for (let i = 1; i < 3; i++) { - mulH2 = Fr.mul(mulH2, Fr.sub(challenges.y, roots.S2.h2w3[i])); - } - for (let i = 0; i < 3; i++) { - mulH2 = Fr.mul(mulH2, Fr.sub(challenges.y, roots.S2.h3w3[i])); - } - - challenges.quotient1 = Fr.mul(challenges.alpha, Fr.div(mulH0, mulH1)); - challenges.quotient2 = Fr.mul(Fr.square(challenges.alpha), Fr.div(mulH0, mulH2)); - - let F2 = G1.timesFr(proof.polynomials.C1, challenges.quotient1); - let F3 = G1.timesFr(proof.polynomials.C2, challenges.quotient2); - - return G1.add(vk.C0, G1.add(F2, F3)); -} - + const G1 = curve.G1; + const Fr = curve.Fr; + let mulH0 = Fr.sub(challenges.y, roots.S0.h0w8[0]); + for (let i = 1; i < 8; i++) mulH0 = Fr.mul(mulH0, Fr.sub(challenges.y, roots.S0.h0w8[i])); + challenges.temp = mulH0; + let mulH1 = Fr.sub(challenges.y, roots.S1.h1w4[0]); + for (let i = 1; i < 4; i++) mulH1 = Fr.mul(mulH1, Fr.sub(challenges.y, roots.S1.h1w4[i])); + let mulH2 = Fr.sub(challenges.y, roots.S2.h2w3[0]); + for (let i = 1; i < 3; i++) mulH2 = Fr.mul(mulH2, Fr.sub(challenges.y, roots.S2.h2w3[i])); + for (let i = 0; i < 3; i++) mulH2 = Fr.mul(mulH2, Fr.sub(challenges.y, roots.S2.h3w3[i])); + challenges.quotient1 = Fr.mul(challenges.alpha, Fr.div(mulH0, mulH1)); + challenges.quotient2 = Fr.mul(Fr.square(challenges.alpha), Fr.div(mulH0, mulH2)); + let F2 = G1.timesFr(proof.polynomials.C1, challenges.quotient1); + let F3 = G1.timesFr(proof.polynomials.C2, challenges.quotient2); + return G1.add(vk.C0, G1.add(F2, F3)); +} function computeE(curve, proof, challenges, vk, r0, r1, r2) { - const G1 = curve.G1; - const Fr = curve.Fr; - - let E2 = Fr.mul(r1, challenges.quotient1); - let E3 = Fr.mul(r2, challenges.quotient2); - - return G1.timesFr(G1.one, Fr.add(r0, Fr.add(E2, E3))); -} - + const G1 = curve.G1; + const Fr = curve.Fr; + let E2 = Fr.mul(r1, challenges.quotient1); + let E3 = Fr.mul(r2, challenges.quotient2); + return G1.timesFr(G1.one, Fr.add(r0, Fr.add(E2, E3))); +} function computeJ(curve, proof, challenges) { - const G1 = curve.G1; - - return G1.timesFr(proof.polynomials.W1, challenges.temp); + return curve.G1.timesFr(proof.polynomials.W1, challenges.temp); } - async function isValidPairing(curve, proof, challenges, vk, F, E, J) { - const G1 = curve.G1; - - let A1 = G1.timesFr(proof.polynomials.W2, challenges.y); - A1 = G1.add(G1.sub(G1.sub(F, E), J), A1); - const A2 = curve.G2.one; - - const B1 = proof.polynomials.W2; - const B2 = vk.X_2; - - return await curve.pairingEq(G1.neg(A1), A2, B1, B2); -} - - + const G1 = curve.G1; + let A1 = G1.timesFr(proof.polynomials.W2, challenges.y); + A1 = G1.add(G1.sub(G1.sub(F, E), J), A1); + const A2 = curve.G2.one; + const B1 = proof.polynomials.W2; + const B2 = vk.X_2; + return await curve.pairingEq(G1.neg(A1), A2, B1, B2); +} function computeLagrangeLiSi(roots, x, xi, curve) { - const Fr = curve.Fr; - const len = roots.length; - - const num = Fr.sub(Fr.exp(x, len), xi); - const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); - - const Li = []; - for (let i = 0; i < len; i++) { - const den2 = roots[((len - 1) * i) % len]; - const den3 = Fr.sub(x, roots[i]); - - Li[i] = Fr.div(num, Fr.mul(Fr.mul(den1, den2), den3)); - } - - return Li; -} - + const Fr = curve.Fr; + const len = roots.length; + const num = Fr.sub(Fr.exp(x, len), xi); + const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); + const Li = []; + for (let i = 0; i < len; i++) { + const den2 = roots[(len - 1) * i % len]; + const den3 = Fr.sub(x, roots[i]); + Li[i] = Fr.div(num, Fr.mul(Fr.mul(den1, den2), den3)); + } + return Li; +} function computeLagrangeLiS2(roots, value, xi0, xi1, curve) { - const Fr = curve.Fr; - - const Li = []; - - const len = roots[0].length; - const n = len * roots.length; - - const num1 = Fr.exp(value, n); - const num2 = Fr.mul(Fr.add(xi0, xi1), Fr.exp(value, len)); - const num3 = Fr.mul(xi0, xi1); - const num = Fr.add(Fr.sub(num1, num2), num3); - - let den1 = Fr.mul(Fr.mul(Fr.e(len), roots[0][0]), Fr.sub(xi0, xi1)); - for (let i = 0; i < len; i++) { - const den2 = roots[0][(len - 1) * i % len]; - const den3 = Fr.sub(value, roots[0][i]); - - const den = Fr.mul(den1,Fr.mul(den2, den3)); - - Li[i] = Fr.div(num, den); - } - - den1 = Fr.mul(Fr.mul(Fr.e(len), roots[1][0]), Fr.sub(xi1, xi0)); - for (let i = 0; i < len; i++) { - const den2 = roots[1][(len - 1) * i % len]; - const den3 = Fr.sub(value, roots[1][i]); - - const den = Fr.mul(den1,Fr.mul(den2, den3)); - - Li[i + len] = Fr.div(num, den); - } - - return Li; -} - -/* - Copyright 2021 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -const {unstringifyBigInts: unstringifyBigInts$1} = ffjavascript.utils; - + const Fr = curve.Fr; + const Li = []; + const len = roots[0].length; + const n = len * roots.length; + const num1 = Fr.exp(value, n); + const num2 = Fr.mul(Fr.add(xi0, xi1), Fr.exp(value, len)); + const num3 = Fr.mul(xi0, xi1); + const num = Fr.add(Fr.sub(num1, num2), num3); + let den1 = Fr.mul(Fr.mul(Fr.e(len), roots[0][0]), Fr.sub(xi0, xi1)); + for (let i = 0; i < len; i++) { + const den2 = roots[0][(len - 1) * i % len]; + const den3 = Fr.sub(value, roots[0][i]); + const den = Fr.mul(den1, Fr.mul(den2, den3)); + Li[i] = Fr.div(num, den); + } + den1 = Fr.mul(Fr.mul(Fr.e(len), roots[1][0]), Fr.sub(xi1, xi0)); + for (let i = 0; i < len; i++) { + const den2 = roots[1][(len - 1) * i % len]; + const den3 = Fr.sub(value, roots[1][i]); + const den = Fr.mul(den1, Fr.mul(den2, den3)); + Li[i + len] = Fr.div(num, den); + } + return Li; +} +//#endregion +//#region src/fflonk_export_calldata.js +var { unstringifyBigInts: unstringifyBigInts$1 } = ffjavascript.utils; function p256(n) { - let nstr = n.toString(16); - while (nstr.length < 64) nstr = "0" + nstr; - nstr = `0x${nstr}`; - return nstr; + let nstr = n.toString(16); + while (nstr.length < 64) nstr = "0" + nstr; + nstr = `0x${nstr}`; + return nstr; } - async function fflonkExportCallData(_pub, _proof) { - const proof = unstringifyBigInts$1(_proof); - const pub = unstringifyBigInts$1(_pub); - - const curve = await getCurveFromName(proof.curve); - curve.G1; - curve.Fr; - - let inputs = ""; - for (let i = 0; i < pub.length; i++) { - if (inputs !== "") inputs = inputs + ","; - inputs = inputs + p256(pub[i]); - } - - return `[${p256(proof.polynomials.C1[0])}, ${p256(proof.polynomials.C1[1])},` + - `${p256(proof.polynomials.C2[0])},${p256(proof.polynomials.C2[1])},` + - `${p256(proof.polynomials.W1[0])},${p256(proof.polynomials.W1[1])},` + - `${p256(proof.polynomials.W2[0])},${p256(proof.polynomials.W2[1])},` + - `${p256(proof.evaluations.ql)},${p256(proof.evaluations.qr)},${p256(proof.evaluations.qm)},` + - `${p256(proof.evaluations.qo)},${p256(proof.evaluations.qc)},${p256(proof.evaluations.s1)},` + - `${p256(proof.evaluations.s2)},${p256(proof.evaluations.s3)},${p256(proof.evaluations.a)},` + - `${p256(proof.evaluations.b)},${p256(proof.evaluations.c)},${p256(proof.evaluations.z)},` + - `${p256(proof.evaluations.zw)},${p256(proof.evaluations.t1w)},${p256(proof.evaluations.t2w)},` + - `${p256(proof.evaluations.inv)}],` + - `[${inputs}]`; -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ -const {unstringifyBigInts} = ffjavascript.utils; - - + const proof = unstringifyBigInts$1(_proof); + const pub = unstringifyBigInts$1(_pub); + await getCurveFromName(proof.curve); + let inputs = ""; + for (let i = 0; i < pub.length; i++) { + if (inputs !== "") inputs = inputs + ","; + inputs = inputs + p256(pub[i]); + } + return `[${p256(proof.polynomials.C1[0])}, ${p256(proof.polynomials.C1[1])},${p256(proof.polynomials.C2[0])},${p256(proof.polynomials.C2[1])},${p256(proof.polynomials.W1[0])},${p256(proof.polynomials.W1[1])},${p256(proof.polynomials.W2[0])},${p256(proof.polynomials.W2[1])},${p256(proof.evaluations.ql)},${p256(proof.evaluations.qr)},${p256(proof.evaluations.qm)},${p256(proof.evaluations.qo)},${p256(proof.evaluations.qc)},${p256(proof.evaluations.s1)},${p256(proof.evaluations.s2)},${p256(proof.evaluations.s3)},${p256(proof.evaluations.a)},${p256(proof.evaluations.b)},${p256(proof.evaluations.c)},${p256(proof.evaluations.z)},${p256(proof.evaluations.zw)},${p256(proof.evaluations.t1w)},${p256(proof.evaluations.t2w)},${p256(proof.evaluations.inv)}],[${inputs}]`; +} +//#endregion +//#region src/wtns_debug.js +var { unstringifyBigInts } = ffjavascript.utils; async function wtnsDebug$1(_input, wasmFileName, wtnsFileName, symName, options, logger) { - - const input = unstringifyBigInts(_input); - - const fdWasm = await fastFile__namespace.readExisting(wasmFileName); - const wasm = await fdWasm.read(fdWasm.totalSize); - await fdWasm.close(); - - const wcOps = {...options, sanityCheck: true}; - let sym = await loadSymbols(symName); - if (options.set) { - if (!sym) sym = await loadSymbols(symName); - wcOps.logSetSignal= function(labelIdx, value) { - // The line below splits the arrow log into 2 strings to avoid some Secure ECMAScript issues - if (logger) logger.info("SET " + sym.labelIdx2Name[labelIdx] + " <" + "-- " + value.toString()); - }; - } - if (options.get) { - if (!sym) sym = await loadSymbols(symName); - wcOps.logGetSignal= function(varIdx, value) { - // The line below splits the arrow log into 2 strings to avoid some Secure ECMAScript issues - if (logger) logger.info("GET " + sym.labelIdx2Name[varIdx] + " --" + "> " + value.toString()); - }; - } - if (options.trigger) { - if (!sym) sym = await loadSymbols(symName); - wcOps.logStartComponent= function(cIdx) { - if (logger) logger.info("START: " + sym.componentIdx2Name[cIdx]); - }; - wcOps.logFinishComponent= function(cIdx) { - if (logger) logger.info("FINISH: " + sym.componentIdx2Name[cIdx]); - }; - } - wcOps.sym = sym; - - const wc = await circom_runtime.WitnessCalculatorBuilder(wasm, wcOps); - const w = await wc.calculateWitness(input, true); - - const fdWtns = await binFileUtils__namespace.createBinFile(wtnsFileName, "wtns", 2, 2); - - await write(fdWtns, w, wc.prime); - - await fdWtns.close(); -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - + const input = unstringifyBigInts(_input); + const fdWasm = await fastfile.readExisting(wasmFileName); + const wasm = await fdWasm.read(fdWasm.totalSize); + await fdWasm.close(); + const wcOps = { + ...options, + sanityCheck: true + }; + let sym = await loadSymbols(symName); + if (options.set) { + if (!sym) sym = await loadSymbols(symName); + wcOps.logSetSignal = function(labelIdx, value) { + if (logger) logger.info("SET " + sym.labelIdx2Name[labelIdx] + " <-- " + value.toString()); + }; + } + if (options.get) { + if (!sym) sym = await loadSymbols(symName); + wcOps.logGetSignal = function(varIdx, value) { + if (logger) logger.info("GET " + sym.labelIdx2Name[varIdx] + " --> " + value.toString()); + }; + } + if (options.trigger) { + if (!sym) sym = await loadSymbols(symName); + wcOps.logStartComponent = function(cIdx) { + if (logger) logger.info("START: " + sym.componentIdx2Name[cIdx]); + }; + wcOps.logFinishComponent = function(cIdx) { + if (logger) logger.info("FINISH: " + sym.componentIdx2Name[cIdx]); + }; + } + wcOps.sym = sym; + const wc = await (0, circom_runtime.WitnessCalculatorBuilder)(wasm, wcOps); + const w = await wc.calculateWitness(input, true); + const fdWtns = await _iden3_binfileutils.createBinFile(wtnsFileName, "wtns", 2, 2); + await write(fdWtns, w, wc.prime); + await fdWtns.close(); +} +//#endregion +//#region src/wtns_export_json.js async function wtnsExportJson$1(wtnsFileName) { - - const w = await read(wtnsFileName); - - return w; -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - + return await read(wtnsFileName); +} +//#endregion +//#region src/wtns_check.js async function wtnsCheck$1(r1csFilename, wtnsFilename, logger) { - - if (logger) logger.info("WITNESS CHECKING STARTED"); - - // Read r1cs file - if (logger) logger.info("> Reading r1cs file"); - const { - fd: fdR1cs, - sections: sectionsR1cs - } = await binFileUtils__namespace.readBinFile(r1csFilename, "r1cs", 1, 1 << 22, 1 << 24); - const r1cs = await r1csfile.readR1csFd(fdR1cs, sectionsR1cs, { loadConstraints: false, loadCustomGates: false }); - - // Read witness file - if (logger) logger.info("> Reading witness file"); - const { - fd: fdWtns, - sections: wtnsSections - } = await binFileUtils__namespace.readBinFile(wtnsFilename, "wtns", 2, 1 << 22, 1 << 24); - const wtnsHeader = await readHeader(fdWtns, wtnsSections); - - if (!ffjavascript.Scalar.eq(r1cs.prime, wtnsHeader.q)) { - throw new Error("Curve of the witness does not match the curve of the proving key"); - } - - const buffWitness = await binFileUtils__namespace.readSection(fdWtns, wtnsSections, 2); - await fdWtns.close(); - - const curve = await getCurveFromR(r1cs.prime); - const Fr = curve.Fr; - const sFr = Fr.n8; - - const bR1cs = await binFileUtils__namespace.readSection(fdR1cs, sectionsR1cs, 2); - - if (logger) { - logger.info("----------------------------"); - logger.info(" WITNESS CHECK"); - logger.info(` Curve: ${r1cs.curve.name}`); - logger.info(` Vars (wires): ${r1cs.nVars}`); - logger.info(` Outputs: ${r1cs.nOutputs}`); - logger.info(` Public Inputs: ${r1cs.nPubInputs}`); - logger.info(` Private Inputs: ${r1cs.nPrvInputs}`); - logger.info(` Labels: ${r1cs.nLabels}`); - logger.info(` Constraints: ${r1cs.nConstraints}`); - logger.info(` Custom Gates: ${r1cs.useCustomGates}`); - logger.info("----------------------------"); - } - - if (logger) logger.info("> Checking witness correctness"); - - let bR1csPos = 0; - let res = true; - for (let i = 0; i < r1cs.nConstraints; i++) { - if ((logger) && (i !== 0) && (i % 500000 === 0)) { - logger.info(`··· processing r1cs constraints ${i}/${r1cs.nConstraints}`); - } - - //Read the three linear combinations of the constraint where A * B - C = 0 - const lcA = readLC(); - const lcB = readLC(); - const lcC = readLC(); - - // Evaluate the linear combinations - const evalA = EvaluateLinearCombination(lcA); - const evalB = EvaluateLinearCombination(lcB); - const evalC = EvaluateLinearCombination(lcC); - - // Check that A * B - C == 0 - if (!Fr.eq(Fr.sub(Fr.mul(evalA, evalB), evalC), Fr.zero)) { - logger.warn("··· aborting checking process at constraint " + i); - res = false; - break; - } - } - - fdR1cs.close(); - - if (logger) { - if (res) { - logger.info("WITNESS IS CORRECT"); - logger.info("WITNESS CHECKING FINISHED SUCCESSFULLY"); - } else { - logger.warn("WITNESS IS NOT CORRECT"); - logger.warn("WITNESS CHECKING FINISHED UNSUCCESSFULLY"); - } - } - - return res; - - function EvaluateLinearCombination(lc) { - let res = Fr.zero; - - const keys = Object.keys(lc); - keys.forEach((signalId) => { - const signalValue = getWitnessValue(signalId); - const signalFactor = lc[signalId]; - - res = Fr.add(res, Fr.mul(signalValue, signalFactor)); - }); - - return res; - } - - function readLC() { - const lc = {}; - - const buffUL32 = bR1cs.slice(bR1csPos, bR1csPos + 4); - bR1csPos += 4; - const buffUL32V = new DataView(buffUL32.buffer); - const nIdx = buffUL32V.getUint32(0, true); - - const buff = bR1cs.slice(bR1csPos, bR1csPos + (4 + r1cs.n8) * nIdx); - bR1csPos += (4 + r1cs.n8) * nIdx; - const buffV = new DataView(buff.buffer); - for (let i = 0; i < nIdx; i++) { - const idx = buffV.getUint32(i * (4 + r1cs.n8), true); - const val = r1cs.F.fromRprLE(buff, i * (4 + r1cs.n8) + 4); - lc[idx] = val; - } - return lc; - } - - function getWitnessValue(signalId) { - return Fr.fromRprLE(buffWitness.slice(signalId * sFr, signalId * sFr + sFr)); - } -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -const {stringifyBigInts} = ffjavascript.utils; - -v8.setFlagsFromString("--expose_gc"); - - -const logger = Logger__default["default"].create("snarkJS", {showTimestamp: false}); -Logger__default["default"].setLogLevel("INFO"); -// const logger = console; -// const Logger = { -// setLogLevel: function (x) {} -// }; - -const __dirname$1 = path__default["default"].dirname(url__default["default"].fileURLToPath((typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT' && document.currentScript.src || new URL('cli.cjs', document.baseURI).href)))); - -const commands = [ - { - cmd: "powersoftau new [powersoftau_0000.ptau]", - description: "Starts a powers of tau ceremony", - alias: ["ptn"], - options: "-verbose|v", - action: powersOfTauNew - }, - { - cmd: "powersoftau contribute ", - description: "creates a ptau file with a new contribution", - alias: ["ptc"], - options: "-verbose|v -name|n -entropy|e", - action: powersOfTauContribute - }, - { - cmd: "powersoftau export challenge [challenge]", - description: "Creates a challenge", - alias: ["ptec"], - options: "-verbose|v", - action: powersOfTauExportChallenge - }, - { - cmd: "powersoftau challenge contribute [response]", - description: "Contribute to a challenge", - alias: ["ptcc"], - options: "-verbose|v -entropy|e", - action: powersOfTauChallengeContribute - }, - { - cmd: "powersoftau import response <", - description: "import a response to a ptau file", - alias: ["ptir"], - options: "-verbose|v -nopoints -nocheck -name|n", - action: powersOfTauImport - }, - { - cmd: "powersoftau beacon ", - description: "adds a beacon", - alias: ["ptb"], - options: "-verbose|v -name|n", - action: powersOfTauBeacon - }, - { - cmd: "powersoftau prepare phase2 ", - description: "Prepares phase 2. ", - longDescription: " This process calculates the evaluation of the Lagrange polinomials at tau for alpha*tau and beta tau", - alias: ["pt2"], - options: "-verbose|v", - action: powersOfTauPreparePhase2 - }, - { - cmd: "powersoftau convert ", - description: "Convert ptau", - longDescription: " This process calculates the evaluation of the Lagrange polinomials at tau for alpha*tau and beta tau", - alias: ["ptcv"], - options: "-verbose|v", - action: powersOfTauConvert - }, - { - cmd: "powersoftau truncate ", - description: "Generate different powers of tau with smaller sizes ", - longDescription: " This process generates smaller ptau files from a bigger power ptau", - alias: ["ptt"], - options: "-verbose|v", - action: powersOfTauTruncate - }, - { - cmd: "powersoftau verify ", - description: "verifies a powers of tau file", - alias: ["ptv"], - options: "-verbose|v", - action: powersOfTauVerify - }, - { - cmd: "powersoftau export json ", - description: "Exports a power of tau file to a JSON", - alias: ["ptej"], - options: "-verbose|v", - action: powersOfTauExportJson - }, - { - cmd: "r1cs info [circuit.r1cs]", - description: "Print statistiscs of a circuit", - alias: ["ri", "info -r|r1cs:circuit.r1cs"], - action: r1csInfo - }, - { - cmd: "r1cs print [circuit.r1cs] [circuit.sym]", - description: "Print the constraints of a circuit", - alias: ["rp", "print -r|r1cs:circuit.r1cs -s|sym"], - action: r1csPrint - }, - { - cmd: "r1cs export json [circuit.r1cs] [circuit.json]", - description: "Export r1cs to JSON file", - alias: ["rej"], - action: r1csExportJSON - }, - { - cmd: "wtns calculate [circuit.wasm] [input.json] [witness.wtns]", - description: "Caclculate specific witness of a circuit given an input", - alias: ["wc", "calculatewitness -ws|wasm:circuit.wasm -i|input:input.json -wt|witness:witness.wtns"], - action: wtnsCalculate - }, - { - cmd: "wtns debug [circuit.wasm] [input.json] [witness.wtns] [circuit.sym]", - description: "Calculate the witness with debug info.", - longDescription: "Calculate the witness with debug info. \nOptions:\n-g or --g : Log signal gets\n-s or --s : Log signal sets\n-t or --trigger : Log triggers ", - options: "-get|g -set|s -trigger|t", - alias: ["wd"], - action: wtnsDebug - }, - { - cmd: "wtns export json [witness.wtns] [witnes.json]", - description: "Calculate the witness with debug info.", - longDescription: "Calculate the witness with debug info. \nOptions:\n-g or --g : Log signal gets\n-s or --s : Log signal sets\n-t or --trigger : Log triggers ", - options: "-verbose|v", - alias: ["wej"], - action: wtnsExportJson - }, - { - cmd: "wtns check [circuit.r1cs] [[witness.wtns]", - description: "Check if a specific witness of a circuit fulfills the r1cs constraints", - alias: ["wchk"], - action: wtnsCheck - }, - { - cmd: "zkey contribute ", - description: "creates a zkey file with a new contribution", - alias: ["zkc"], - options: "-verbose|v -entropy|e -name|n", - action: zkeyContribute - }, - { - cmd: "zkey export bellman [circuit.mpcparams]", - description: "Export a zKey to a MPCParameters file compatible with kobi/phase2 (Bellman)", - alias: ["zkeb"], - options: "-verbose|v", - action: zkeyExportBellman - }, - { - cmd: "zkey bellman contribute ", - description: "contributes to a challenge file in bellman format", - alias: ["zkbc"], - options: "-verbose|v -entropy|e", - action: zkeyBellmanContribute - }, - { - cmd: "zkey import bellman ", - description: "Export a zKey to a MPCParameters file compatible with kobi/phase2 (Bellman) ", - alias: ["zkib"], - options: "-verbose|v -name|n", - action: zkeyImportBellman - }, - { - cmd: "zkey beacon ", - description: "adds a beacon", - alias: ["zkb"], - options: "-verbose|v -name|n", - action: zkeyBeacon - }, - { - cmd: "zkey verify r1cs [circuit.r1cs] [powersoftau.ptau] [circuit_final.zkey]", - description: "Verify zkey file contributions and verify that matches with the original circuit.r1cs and ptau", - alias: ["zkv", "zkvr", "zkey verify"], - options: "-verbose|v", - action: zkeyVerifyFromR1cs - }, - { - cmd: "zkey verify init [circuit_0000.zkey] [powersoftau.ptau] [circuit_final.zkey]", - description: "Verify zkey file contributions and verify that matches with the original circuit.r1cs and ptau", - alias: ["zkvi"], - options: "-verbose|v", - action: zkeyVerifyFromInit - }, - { - cmd: "zkey export verificationkey [circuit_final.zkey] [verification_key.json]", - description: "Exports a verification key", - alias: ["zkev"], - action: zkeyExportVKey - }, - { - cmd: "zkey export json [circuit_final.zkey] [circuit_final.zkey.json]", - description: "Exports a circuit key to a JSON file", - alias: ["zkej"], - options: "-verbose|v", - action: zkeyExportJson - }, - { - cmd: "zkey export solidityverifier [circuit_final.zkey] [verifier.sol]", - description: "Creates a verifier in solidity", - alias: ["zkesv", "generateverifier -vk|verificationkey -v|verifier"], - action: zkeyExportSolidityVerifier - }, - { - cmd: "zkey export soliditycalldata [public.json] [proof.json]", - description: "Generates call parameters ready to be called.", - alias: ["zkesc", "generatecall -pub|public -p|proof"], - action: zkeyExportSolidityCalldata - }, - { - cmd: "groth16 setup [circuit.r1cs] [powersoftau.ptau] [circuit_0000.zkey]", - description: "Creates an initial groth16 pkey file with zero contributions", - alias: ["g16s", "zkn", "zkey new"], - options: "-verbose|v", - action: zkeyNew - }, - { - cmd: "groth16 prove [circuit_final.zkey] [witness.wtns] [proof.json] [public.json]", - description: "Generates a zk Proof from witness", - alias: ["g16p", "zpw", "zksnark proof", "proof -pk|provingkey -wt|witness -p|proof -pub|public"], - options: "-verbose|v -protocol", - action: groth16Prove - }, - { - cmd: "groth16 fullprove [input.json] [circuit_final.wasm] [circuit_final.zkey] [proof.json] [public.json]", - description: "Generates a zk Proof from input", - alias: ["g16f", "g16i"], - options: "-verbose|v -protocol", - action: groth16FullProve - }, - { - cmd: "groth16 verify [verification_key.json] [public.json] [proof.json]", - description: "Verify a zk Proof", - alias: ["g16v", "verify -vk|verificationkey -pub|public -p|proof"], - action: groth16Verify - }, - { - cmd: "plonk setup [circuit.r1cs] [powersoftau.ptau] [circuit.zkey]", - description: "Creates an initial PLONK pkey ", - alias: ["pks"], - options: "-verbose|v", - action: plonkSetup - }, - { - cmd: "plonk prove [circuit.zkey] [witness.wtns] [proof.json] [public.json]", - description: "Generates a PLONK Proof from witness", - alias: ["pkp"], - options: "-verbose|v -protocol", - action: plonkProve - }, - { - cmd: "plonk fullprove [input.json] [circuit.wasm] [circuit.zkey] [proof.json] [public.json]", - description: "Generates a PLONK Proof from input", - alias: ["pkf"], - options: "-verbose|v -protocol", - action: plonkFullProve - }, - { - cmd: "plonk verify [verification_key.json] [public.json] [proof.json]", - description: "Verify a PLONK Proof", - alias: ["pkv"], - options: "-verbose|v", - action: plonkVerify - }, - { - cmd: "fflonk setup [circuit.r1cs] [powersoftau.ptau] [circuit.zkey]", - description: "BETA version. Creates a FFLONK zkey from a circuit", - alias: ["ffs"], - options: "-verbose|v", - action: fflonkSetup - }, - { - cmd: "fflonk prove [circuit.zkey] [witness.wtns] [proof.json] [public.json]", - description: "BETA version. Generates a FFLONK Proof from witness", - alias: ["ffp"], - options: "-verbose|v -protocol", - action: fflonkProve - }, - { - cmd: "fflonk fullprove [witness.json] [circuit.wasm] [circuit.zkey] [proof.json] [public.json]", - description: "BETA version. Generates a witness and the FFLONK Proof in the same command", - alias: ["fff"], - options: "-verbose|v -protocol", - action: fflonkFullProve - }, - { - cmd: "fflonk verify [verification_key.json] [public.json] [proof.json]", - description: "BETA version. Verify a FFLONK Proof", - alias: ["ffv"], - options: "-verbose|v", - action: fflonkVerify - }, - { - cmd: "file info [binary.file]", - description: "Check info of a binary file", - alias: ["fi"], - action: fileInfo - } -]; - - -clProcessor(commands).then((res) => { - process.exit(res); + if (logger) logger.info("WITNESS CHECKING STARTED"); + if (logger) logger.info("> Reading r1cs file"); + const { fd: fdR1cs, sections: sectionsR1cs } = await _iden3_binfileutils.readBinFile(r1csFilename, "r1cs", 1, 1 << 22, 1 << 24); + const r1cs = await (0, r1csfile.readR1csFd)(fdR1cs, sectionsR1cs, { + loadConstraints: false, + loadCustomGates: false + }); + if (logger) logger.info("> Reading witness file"); + const { fd: fdWtns, sections: wtnsSections } = await _iden3_binfileutils.readBinFile(wtnsFilename, "wtns", 2, 1 << 22, 1 << 24); + const wtnsHeader = await readHeader(fdWtns, wtnsSections); + if (!ffjavascript.Scalar.eq(r1cs.prime, wtnsHeader.q)) throw new Error("Curve of the witness does not match the curve of the proving key"); + const buffWitness = await _iden3_binfileutils.readSection(fdWtns, wtnsSections, 2); + await fdWtns.close(); + const Fr = (await getCurveFromR(r1cs.prime)).Fr; + const sFr = Fr.n8; + const bR1cs = await _iden3_binfileutils.readSection(fdR1cs, sectionsR1cs, 2); + if (logger) { + logger.info("----------------------------"); + logger.info(" WITNESS CHECK"); + logger.info(` Curve: ${r1cs.curve.name}`); + logger.info(` Vars (wires): ${r1cs.nVars}`); + logger.info(` Outputs: ${r1cs.nOutputs}`); + logger.info(` Public Inputs: ${r1cs.nPubInputs}`); + logger.info(` Private Inputs: ${r1cs.nPrvInputs}`); + logger.info(` Labels: ${r1cs.nLabels}`); + logger.info(` Constraints: ${r1cs.nConstraints}`); + logger.info(` Custom Gates: ${r1cs.useCustomGates}`); + logger.info("----------------------------"); + } + if (logger) logger.info("> Checking witness correctness"); + let bR1csPos = 0; + let res = true; + for (let i = 0; i < r1cs.nConstraints; i++) { + if (logger && i !== 0 && i % 5e5 === 0) logger.info(`··· processing r1cs constraints ${i}/${r1cs.nConstraints}`); + const lcA = readLC(); + const lcB = readLC(); + const lcC = readLC(); + const evalA = EvaluateLinearCombination(lcA); + const evalB = EvaluateLinearCombination(lcB); + const evalC = EvaluateLinearCombination(lcC); + if (!Fr.eq(Fr.sub(Fr.mul(evalA, evalB), evalC), Fr.zero)) { + logger.warn("··· aborting checking process at constraint " + i); + res = false; + break; + } + } + fdR1cs.close(); + if (logger) if (res) { + logger.info("WITNESS IS CORRECT"); + logger.info("WITNESS CHECKING FINISHED SUCCESSFULLY"); + } else { + logger.warn("WITNESS IS NOT CORRECT"); + logger.warn("WITNESS CHECKING FINISHED UNSUCCESSFULLY"); + } + return res; + function EvaluateLinearCombination(lc) { + let res = Fr.zero; + Object.keys(lc).forEach((signalId) => { + const signalValue = getWitnessValue(signalId); + const signalFactor = lc[signalId]; + res = Fr.add(res, Fr.mul(signalValue, signalFactor)); + }); + return res; + } + function readLC() { + const lc = {}; + const buffUL32 = bR1cs.slice(bR1csPos, bR1csPos + 4); + bR1csPos += 4; + const nIdx = new DataView(buffUL32.buffer).getUint32(0, true); + const buff = bR1cs.slice(bR1csPos, bR1csPos + (4 + r1cs.n8) * nIdx); + bR1csPos += (4 + r1cs.n8) * nIdx; + const buffV = new DataView(buff.buffer); + for (let i = 0; i < nIdx; i++) { + const idx = buffV.getUint32(i * (4 + r1cs.n8), true); + lc[idx] = r1cs.F.fromRprLE(buff, i * (4 + r1cs.n8) + 4); + } + return lc; + } + function getWitnessValue(signalId) { + return Fr.fromRprLE(buffWitness.slice(signalId * sFr, signalId * sFr + sFr)); + } +} +//#endregion +//#region node_modules/check-types/src/check-types.js +var require_check_types = /* @__PURE__ */ __commonJSMin(((exports, module) => { + (function(globals) { + "use strict"; + var messages = {}, predicates = {}, functions, assert, not, maybe, collections, hasOwnProperty, toString, keys, slice, isArray, neginf, posinf, haveSymbols, haveMaps, haveSets; + [ + { + n: "equal", + f: equal, + s: "equal {e}" + }, + { + n: "undefined", + f: isUndefined, + s: "be undefined" + }, + { + n: "null", + f: isNull, + s: "be null" + }, + { + n: "assigned", + f: assigned, + s: "be assigned" + }, + { + n: "primitive", + f: primitive, + s: "be primitive type" + }, + { + n: "contains", + f: contains, + s: "contain {e}" + }, + { + n: "in", + f: isIn, + s: "be in {e}" + }, + { + n: "containsKey", + f: containsKey, + s: "contain key {e}" + }, + { + n: "keyIn", + f: keyIn, + s: "be key in {e}" + }, + { + n: "zero", + f: zero, + s: "be 0" + }, + { + n: "one", + f: one, + s: "be 1" + }, + { + n: "infinity", + f: infinity, + s: "be infinity" + }, + { + n: "number", + f: number, + s: "be Number" + }, + { + n: "integer", + f: integer, + s: "be integer" + }, + { + n: "float", + f: float, + s: "be non-integer number" + }, + { + n: "even", + f: even, + s: "be even number" + }, + { + n: "odd", + f: odd, + s: "be odd number" + }, + { + n: "greater", + f: greater, + s: "be greater than {e}" + }, + { + n: "less", + f: less, + s: "be less than {e}" + }, + { + n: "between", + f: between, + s: "be between {e} and {e2}" + }, + { + n: "greaterOrEqual", + f: greaterOrEqual, + s: "be greater than or equal to {e}" + }, + { + n: "lessOrEqual", + f: lessOrEqual, + s: "be less than or equal to {e}" + }, + { + n: "inRange", + f: inRange, + s: "be in the range {e} to {e2}" + }, + { + n: "positive", + f: positive, + s: "be positive number" + }, + { + n: "negative", + f: negative, + s: "be negative number" + }, + { + n: "string", + f: string, + s: "be String" + }, + { + n: "emptyString", + f: emptyString, + s: "be empty string" + }, + { + n: "nonEmptyString", + f: nonEmptyString, + s: "be non-empty string" + }, + { + n: "match", + f: match, + s: "match {e}" + }, + { + n: "boolean", + f: boolean, + s: "be Boolean" + }, + { + n: "object", + f: object, + s: "be Object" + }, + { + n: "emptyObject", + f: emptyObject, + s: "be empty object" + }, + { + n: "nonEmptyObject", + f: nonEmptyObject, + s: "be non-empty object" + }, + { + n: "instanceStrict", + f: instanceStrict, + s: "be instanceof {t}" + }, + { + n: "thenable", + f: thenable, + s: "be promise-like" + }, + { + n: "instance", + f: instance, + s: "be {t}" + }, + { + n: "like", + f: like, + s: "be like {e}" + }, + { + n: "identical", + f: identical, + s: "be identical to {e}" + }, + { + n: "array", + f: array, + s: "be Array" + }, + { + n: "emptyArray", + f: emptyArray, + s: "be empty array" + }, + { + n: "nonEmptyArray", + f: nonEmptyArray, + s: "be non-empty array" + }, + { + n: "arrayLike", + f: arrayLike, + s: "be array-like" + }, + { + n: "iterable", + f: iterable, + s: "be iterable" + }, + { + n: "date", + f: date, + s: "be valid Date" + }, + { + n: "function", + f: isFunction, + s: "be Function" + }, + { + n: "hasLength", + f: hasLength, + s: "have length {e}" + }, + { + n: "throws", + f: throws, + s: "throw" + } + ].map(function(data) { + var n = data.n; + messages[n] = "assert failed: expected {a} to " + data.s; + predicates[n] = data.f; + }); + functions = { + map, + all, + any + }; + collections = [ + "array", + "arrayLike", + "iterable", + "object" + ]; + hasOwnProperty = Object.prototype.hasOwnProperty; + toString = Object.prototype.toString; + keys = Object.keys; + slice = Array.prototype.slice; + isArray = Array.isArray; + neginf = Number.NEGATIVE_INFINITY; + posinf = Number.POSITIVE_INFINITY; + haveSymbols = typeof Symbol === "function"; + haveMaps = typeof Map === "function"; + haveSets = typeof Set === "function"; + functions = mixin(functions, predicates); + assert = createModifiedPredicates(assertModifier, assertImpl); + not = createModifiedPredicates(notModifier, notImpl); + maybe = createModifiedPredicates(maybeModifier, maybeImpl); + assert.not = createModifiedModifier(assertModifier, not, "not "); + assert.maybe = createModifiedModifier(assertModifier, maybe, "maybe "); + collections.forEach(createOfPredicates); + createOfModifiers(assert, assertModifier); + createOfModifiers(not, notModifier); + collections.forEach(createMaybeOfModifiers); + exportFunctions(mixin(functions, { + assert, + not, + maybe + })); + /** + * Public function `equal`. + * + * Returns true if `lhs` and `rhs` are strictly equal, without coercion. + * Returns false otherwise. + */ + function equal(lhs, rhs) { + return lhs === rhs; + } + /** + * Public function `undefined`. + * + * Returns true if `data` is undefined, false otherwise. + */ + function isUndefined(data) { + return data === void 0; + } + /** + * Public function `null`. + * + * Returns true if `data` is null, false otherwise. + */ + function isNull(data) { + return data === null; + } + /** + * Public function `assigned`. + * + * Returns true if `data` is not null or undefined, false otherwise. + */ + function assigned(data) { + return data !== void 0 && data !== null; + } + /** + * Public function `primitive`. + * + * Returns true if `data` is a primitive type, false otherwise. + */ + function primitive(data) { + var type; + switch (data) { + case null: + case void 0: + case false: + case true: return true; + } + type = typeof data; + return type === "string" || type === "number" || haveSymbols && type === "symbol"; + } + /** + * Public function `zero`. + * + * Returns true if `data` is zero, false otherwise. + */ + function zero(data) { + return data === 0; + } + /** + * Public function `one`. + * + * Returns true if `data` is one, false otherwise. + */ + function one(data) { + return data === 1; + } + /** + * Public function `infinity`. + * + * Returns true if `data` is positive or negative infinity, false otherwise. + */ + function infinity(data) { + return data === neginf || data === posinf; + } + /** + * Public function `number`. + * + * Returns true if `data` is a number, false otherwise. + */ + function number(data) { + return typeof data === "number" && data > neginf && data < posinf; + } + /** + * Public function `integer`. + * + * Returns true if `data` is an integer, false otherwise. + */ + function integer(data) { + return typeof data === "number" && data % 1 === 0; + } + /** + * Public function `float`. + * + * Returns true if `data` is a non-integer number, false otherwise. + */ + function float(data) { + return number(data) && data % 1 !== 0; + } + /** + * Public function `even`. + * + * Returns true if `data` is an even number, false otherwise. + */ + function even(data) { + return typeof data === "number" && data % 2 === 0; + } + /** + * Public function `odd`. + * + * Returns true if `data` is an odd number, false otherwise. + */ + function odd(data) { + return integer(data) && data % 2 !== 0; + } + /** + * Public function `greater`. + * + * Returns true if `lhs` is a number greater than `rhs`, false otherwise. + */ + function greater(lhs, rhs) { + return number(lhs) && lhs > rhs; + } + /** + * Public function `less`. + * + * Returns true if `lhs` is a number less than `rhs`, false otherwise. + */ + function less(lhs, rhs) { + return number(lhs) && lhs < rhs; + } + /** + * Public function `between`. + * + * Returns true if `data` is a number between `x` and `y`, false otherwise. + */ + function between(data, x, y) { + if (x < y) return greater(data, x) && data < y; + return less(data, x) && data > y; + } + /** + * Public function `greaterOrEqual`. + * + * Returns true if `lhs` is a number greater than or equal to `rhs`, false + * otherwise. + */ + function greaterOrEqual(lhs, rhs) { + return number(lhs) && lhs >= rhs; + } + /** + * Public function `lessOrEqual`. + * + * Returns true if `lhs` is a number less than or equal to `rhs`, false + * otherwise. + */ + function lessOrEqual(lhs, rhs) { + return number(lhs) && lhs <= rhs; + } + /** + * Public function `inRange`. + * + * Returns true if `data` is a number in the range `x..y`, false otherwise. + */ + function inRange(data, x, y) { + if (x < y) return greaterOrEqual(data, x) && data <= y; + return lessOrEqual(data, x) && data >= y; + } + /** + * Public function `positive`. + * + * Returns true if `data` is a positive number, false otherwise. + */ + function positive(data) { + return greater(data, 0); + } + /** + * Public function `negative`. + * + * Returns true if `data` is a negative number, false otherwise. + */ + function negative(data) { + return less(data, 0); + } + /** + * Public function `string`. + * + * Returns true if `data` is a string, false otherwise. + */ + function string(data) { + return typeof data === "string"; + } + /** + * Public function `emptyString`. + * + * Returns true if `data` is the empty string, false otherwise. + */ + function emptyString(data) { + return data === ""; + } + /** + * Public function `nonEmptyString`. + * + * Returns true if `data` is a non-empty string, false otherwise. + */ + function nonEmptyString(data) { + return string(data) && data !== ""; + } + /** + * Public function `match`. + * + * Returns true if `data` is a string that matches `regex`, false otherwise. + */ + function match(data, regex) { + return string(data) && !!data.match(regex); + } + /** + * Public function `boolean`. + * + * Returns true if `data` is a boolean value, false otherwise. + */ + function boolean(data) { + return data === false || data === true; + } + /** + * Public function `object`. + * + * Returns true if `data` is a plain-old JS object, false otherwise. + */ + function object(data) { + return toString.call(data) === "[object Object]"; + } + /** + * Public function `emptyObject`. + * + * Returns true if `data` is an empty object, false otherwise. + */ + function emptyObject(data) { + return object(data) && !some(data, function() { + return true; + }); + } + function some(data, predicate) { + for (var key in data) if (hasOwnProperty.call(data, key)) { + if (predicate(key, data[key])) return true; + } + return false; + } + /** + * Public function `nonEmptyObject`. + * + * Returns true if `data` is a non-empty object, false otherwise. + */ + function nonEmptyObject(data) { + return object(data) && some(data, function() { + return true; + }); + } + /** + * Public function `thenable`. + * + * Returns true if `data` has a `then` method. + */ + function thenable(data) { + return assigned(data) && isFunction(data.then); + } + /** + * Public function `instanceStrict`. + * + * Returns true if `data` is an instance of `prototype`, false otherwise. + */ + function instanceStrict(data, prototype) { + try { + return data instanceof prototype; + } catch (error) { + return false; + } + } + /** + * Public function `instance`. + * + * Returns true if `data` is an instance of `prototype`, false otherwise. + * Falls back to testing constructor.name and Object.prototype.toString + * if the initial instanceof test fails. + */ + function instance(data, prototype) { + try { + return instanceStrict(data, prototype) || data.constructor.name === prototype.name || toString.call(data) === "[object " + prototype.name + "]"; + } catch (error) { + return false; + } + } + /** + * Public function `like`. + * + * Tests whether `data` 'quacks like a duck'. Returns true if `data` has all + * of the properties of `archetype` (the 'duck'), false otherwise. Interrogates + * objects recursively, to arbitrary depth. + */ + function like(data, archetype) { + var name; + if (!assigned(data) || !assigned(archetype)) return data === archetype; + for (name in archetype) if (hasOwnProperty.call(archetype, name)) { + if (!hasOwnProperty.call(data, name) || typeof data[name] !== typeof archetype[name]) return false; + if (object(data[name]) && !like(data[name], archetype[name])) return false; + } + return true; + } + /** + * Public function `identical`. + * + * Tests whether `data` has all of the same properties and values as `archetype`. + * Interrogates objects recursively, to arbitrary depth. + */ + function identical(data, archetype) { + var name; + if (!assigned(data) || !assigned(archetype)) return data === archetype; + for (name in archetype) if (hasOwnProperty.call(archetype, name)) { + if (!hasOwnProperty.call(data, name)) return false; + if (object(data[name])) { + if (!identical(data[name], archetype[name])) return false; + } else if (data[name] !== archetype[name]) return false; + } + for (name in data) if (hasOwnProperty.call(data, name)) { + if (!hasOwnProperty.call(archetype, name)) return false; + if (object(archetype[name])) { + if (!identical(archetype[name], data[name])) return false; + } else if (archetype[name] !== data[name]) return false; + } + return true; + } + /** + * Public function `array`. + * + * Returns true if `data` is an array, false otherwise. + */ + function array(data) { + return isArray(data); + } + /** + * Public function `emptyArray`. + * + * Returns true if `data` is an empty array, false otherwise. + */ + function emptyArray(data) { + return isArray(data) && data.length === 0; + } + /** + * Public function `nonEmptyArray`. + * + * Returns true if `data` is a non-empty array, false otherwise. + */ + function nonEmptyArray(data) { + return isArray(data) && data.length > 0; + } + /** + * Public function `arrayLike`. + * + * Returns true if `data` is an array-like object, false otherwise. + */ + function arrayLike(data) { + return assigned(data) && data.length >= 0; + } + /** + * Public function `iterable`. + * + * Returns true if `data` is an iterable, false otherwise. + */ + function iterable(data) { + if (!haveSymbols) return arrayLike(data); + return assigned(data) && isFunction(data[Symbol.iterator]); + } + /** + * Public function `contains`. + * + * Returns true if `data` contains `value`, false otherwise. + * Works with objects, arrays and array-likes (including strings). + */ + function contains(data, value) { + var iterator, iteration; + if (!assigned(data)) return false; + if (haveSets && instanceStrict(data, Set)) return data.has(value); + if (string(data)) return data.indexOf(value) !== -1; + if (haveSymbols && data[Symbol.iterator] && isFunction(data.values)) { + iterator = data.values(); + do { + iteration = iterator.next(); + if (iteration.value === value) return true; + } while (!iteration.done); + return false; + } + return some(data, function(key, dataValue) { + return dataValue === value; + }); + } + /** + * Public function `in`. + * + * Returns true if `value` is in `data`, false otherwise. + * Like `contains`, but with arguments flipped. + */ + function isIn(value, data) { + return contains(data, value); + } + /** + * Public function `containsKey`. + * + * Returns true if `data` contains key `key`, false otherwise. + * Works with objects, arrays and array-likes (including strings). + */ + function containsKey(data, key) { + if (!assigned(data)) return false; + if (haveMaps && instanceStrict(data, Map)) return data.has(key); + if (iterable(data) && !number(+key)) return false; + return !!data[key]; + } + /** + * Public function `keyIn`. + * + * Returns true if key `key` is in `data`, false otherwise. + * Like `contains`, but with arguments flipped. + */ + function keyIn(key, data) { + return containsKey(data, key); + } + /** + * Public function `hasLength`. + * + * Returns true if `data` has a length property that equals `length`, false + * otherwise. + */ + function hasLength(data, length) { + return assigned(data) && data.length === length; + } + /** + * Public function `date`. + * + * Returns true if `data` is a valid date, false otherwise. + */ + function date(data) { + return instanceStrict(data, Date) && integer(data.getTime()); + } + /** + * Public function `function`. + * + * Returns true if `data` is a function, false otherwise. + */ + function isFunction(data) { + return typeof data === "function"; + } + /** + * Public function `throws`. + * + * Returns true if `data` is a function that throws, false otherwise. + */ + function throws(data) { + if (!isFunction(data)) return false; + try { + data(); + } catch (error) { + return true; + } + return false; + } + /** + * Public function `map`. + * + * Maps each value from `data` to the corresponding predicate and returns + * the results. If the same function is to be applied across all of the data, + * a single predicate function may be passed in. + */ + function map(data, predicates) { + var result; + if (isArray(data)) result = []; + else result = {}; + if (isFunction(predicates)) forEach(data, function(key, value) { + result[key] = predicates(value); + }); + else { + if (!isArray(predicates)) assert.object(predicates); + var dataKeys = keys(data || {}); + forEach(predicates, function(key, predicate) { + dataKeys.some(function(dataKey, index) { + if (dataKey === key) { + dataKeys.splice(index, 1); + return true; + } + return false; + }); + if (isFunction(predicate)) if (not.assigned(data)) result[key] = !!predicate.m; + else result[key] = predicate(data[key]); + else result[key] = map(data[key], predicate); + }); + } + return result; + } + function forEach(object, action) { + for (var key in object) if (hasOwnProperty.call(object, key)) action(key, object[key]); + } + /** + * Public function `all` + * + * Check that all boolean values are true + * in an array or object returned from `map`. + */ + function all(data) { + if (isArray(data)) return testArray(data, false); + assert.object(data); + return testObject(data, false); + } + function testArray(data, result) { + var i; + for (i = 0; i < data.length; i += 1) if (data[i] === result) return result; + return !result; + } + function testObject(data, result) { + var key, value; + for (key in data) if (hasOwnProperty.call(data, key)) { + value = data[key]; + if (object(value) && testObject(value, result) === result) return result; + if (value === result) return result; + } + return !result; + } + /** + * Public function `any` + * + * Check that at least one boolean value is true + * in an array or object returned from `map`. + */ + function any(data) { + if (isArray(data)) return testArray(data, true); + assert.object(data); + return testObject(data, true); + } + function mixin(target, source) { + forEach(source, function(key, value) { + target[key] = value; + }); + return target; + } + /** + * Public modifier `assert`. + * + * Throws if `predicate` returns false. + */ + function assertModifier(predicate, defaultMessage) { + return function() { + var args = arguments; + var argCount = predicate.l || predicate.length; + var message = args[argCount]; + var ErrorType = args[argCount + 1]; + assertImpl(predicate.apply(null, args), nonEmptyString(message) ? message : defaultMessage.replace("{a}", messageFormatter(args[0])).replace("{e}", messageFormatter(args[1])).replace("{e2}", messageFormatter(args[2])).replace("{t}", function() { + var arg = args[1]; + if (arg && arg.name) return arg.name; + return arg; + }), isFunction(ErrorType) ? ErrorType : TypeError); + return args[0]; + }; + } + function messageFormatter(arg) { + return function() { + if (string(arg)) return "\"" + arg.replace(/\\/g, "\\\\").replace(/"/g, "\\\"") + "\""; + if (arg && arg !== true && arg.constructor && !instanceStrict(arg, RegExp) && typeof arg !== "number") return arg.constructor.name; + return arg; + }; + } + function assertImpl(value, message, ErrorType) { + if (value) return value; + throw new (ErrorType || Error)(message || "assert failed"); + } + /** + * Public modifier `not`. + * + * Negates `predicate`. + */ + function notModifier(predicate) { + var modifiedPredicate = function() { + return notImpl(predicate.apply(null, arguments)); + }; + modifiedPredicate.l = predicate.length; + return modifiedPredicate; + } + function notImpl(value) { + return !value; + } + /** + * Public modifier `maybe`. + * + * Returns true if predicate argument is null or undefined, + * otherwise propagates the return value from `predicate`. + */ + function maybeModifier(predicate) { + var modifiedPredicate = function() { + if (not.assigned(arguments[0])) return true; + return predicate.apply(null, arguments); + }; + modifiedPredicate.l = predicate.length; + modifiedPredicate.m = true; + return modifiedPredicate; + } + function maybeImpl(value) { + if (!assigned(value)) return true; + return value; + } + /** + * Public modifier `of`. + * + * Applies the chained predicate to members of the collection. + */ + function ofModifier(target, type, predicate) { + var modifiedPredicate = function() { + var collection = arguments[0], args; + if (target === "maybe" && not.assigned(collection)) return true; + if (!type(collection)) return false; + collection = coerceCollection(type, collection); + args = slice.call(arguments, 1); + try { + collection.forEach(function(item) { + if ((target !== "maybe" || assigned(item)) && !predicate.apply(null, [item].concat(args))) throw 0; + }); + } catch (ignore) { + return false; + } + return true; + }; + modifiedPredicate.l = predicate.length; + return modifiedPredicate; + } + function coerceCollection(type, collection) { + switch (type) { + case arrayLike: return slice.call(collection); + case object: return keys(collection).map(function(key) { + return collection[key]; + }); + default: return collection; + } + } + function createModifiedPredicates(modifier, object) { + return createModifiedFunctions([ + modifier, + predicates, + object, + "" + ]); + } + function createModifiedFunctions(args) { + var modifier = args.shift(), messageModifier = args.pop(), object = args.pop(); + forEach(args.pop(), function(key, fn) { + var message = messages[key]; + if (message && messageModifier) message = message.replace("to", messageModifier + "to"); + Object.defineProperty(object, key, { + configurable: false, + enumerable: true, + writable: false, + value: modifier.apply(null, args.concat(fn, message)) + }); + }); + return object; + } + function createModifiedModifier(modifier, modified, messageModifier) { + return createModifiedFunctions([ + modifier, + modified, + {}, + messageModifier + ]); + } + function createOfPredicates(key) { + predicates[key].of = createModifiedFunctions([ + ofModifier.bind(null, null), + predicates[key], + predicates, + {}, + "" + ]); + } + function createOfModifiers(base, modifier) { + collections.forEach(function(key) { + base[key].of = createModifiedModifier(modifier, predicates[key].of); + }); + } + function createMaybeOfModifiers(key) { + maybe[key].of = createModifiedFunctions([ + ofModifier.bind(null, "maybe"), + predicates[key], + predicates, + {}, + "" + ]); + assert.maybe[key].of = createModifiedModifier(assertModifier, maybe[key].of); + assert.not[key].of = createModifiedModifier(assertModifier, not[key].of); + } + function exportFunctions(functions) { + if (typeof define === "function" && define.amd) define(function() { + return functions; + }); + else if (typeof module !== "undefined" && module !== null && module.exports) module.exports = functions; + else globals.check = functions; + } + })(exports); +})); +//#endregion +//#region node_modules/bfj/src/error.js +var require_error = /* @__PURE__ */ __commonJSMin(((exports, module) => { + module.exports = { create }; + function create(actual, expected, line, column) { + const error = /* @__PURE__ */ new Error("JSON error: encountered `" + actual + "` at line " + line + ", column " + column + " where `" + expected + "` was expected."); + error.actual = actual; + error.expected = expected; + error.lineNumber = line; + error.columnNumber = column; + return error; + } +})); +//#endregion +//#region node_modules/bfj/src/events.js +var require_events = /* @__PURE__ */ __commonJSMin(((exports, module) => { + module.exports = { + array: "arr", + object: "obj", + property: "pro", + string: "str", + stringChunk: "str-chunk", + number: "num", + literal: "lit", + endPrefix: "end-", + end: "end", + error: "err" + }; + module.exports.endArray = module.exports.endPrefix + module.exports.array; + module.exports.endObject = module.exports.endPrefix + module.exports.object; + module.exports.endLine = `${module.exports.endPrefix}line`; + module.exports.dataError = `${module.exports.error}-data`; +})); +//#endregion +//#region node_modules/bfj/src/walk.js +var require_walk = /* @__PURE__ */ __commonJSMin(((exports, module) => { + var check = require_check_types(); + var error = require_error(); + var EventEmitter$1 = require("events").EventEmitter; + var events = require_events(); + var terminators = { + obj: "}", + arr: "]" + }; + var escapes = { + "\"": "\"", + "\\": "\\", + "/": "/", + "b": "\b", + "f": "\f", + "n": "\n", + "r": "\r", + "t": " " + }; + var DEFAULT_BUFFER_LENGTH = 256; + module.exports = initialise; + /** + * Public function `walk`. + * + * Returns an event emitter and asynchronously walks a stream of JSON data, + * emitting events as it encounters tokens. The event emitter is decorated + * with a `pause` method that can be called to pause processing. + * + * @param stream: Readable instance representing the incoming JSON. + * + * @option bufferLength: The length of the walk buffer, default is 256. + * + * @option ndjson: Set this to true to parse newline-delimited JSON. + * + * @option stringChunkSize: The size at which to chunk long strings, emitting + * `string-chunk` events for each chunk followed by a + * regular `string` event when the complete string has + * been walked. Default is disabled. + * + * @option yieldRate: The number of data items to process per timeslice, + * default is 1024. + **/ + function initialise(stream, options = {}) { + check.assert.instanceStrict(stream, require("stream").Readable, "Invalid stream argument"); + check.assert.maybe.greater(options.stringChunkSize, 0, "Invalid stringChunkSize option"); + const currentPosition = { + line: 1, + column: 1 + }; + const emitter = new EventEmitter$1(); + const json = []; + const lengths = []; + const previousPosition = {}; + const scopes = []; + const shouldHandleNdjson = !!options.ndjson; + const yieldRate = options.yieldRate || 1024; + const bufferLength = options.bufferLength || DEFAULT_BUFFER_LENGTH; + const stringChunkSize = options.stringChunkSize || Number.POSITIVE_INFINITY; + let index = 0; + let isStreamEnded = false; + let isStreamPaused = false; + let isWalkBegun = false; + let isWalkEnded = false; + let isWalkingString = false; + let hasEndedLine = true; + let count = 0; + let stringChunkCount = 0; + let stringChunkStart = 0; + let resumeFn; + let pause; + let cachedCharacter; + stream.setEncoding("utf8"); + stream.on("data", readStream); + stream.on("end", endStream); + stream.on("error", (err) => { + emitter.emit(events.error, err); + endStream(); + }); + emitter.pause = () => { + let resolve; + pause = new Promise((res) => resolve = res); + return () => { + pause = null; + count = 0; + if (shouldHandleNdjson && isStreamEnded && isWalkEnded) emit(events.end); + else resolve(); + }; + }; + return emitter; + function readStream(chunk) { + addChunk(chunk); + if (isWalkBegun) resume(); + else { + isWalkBegun = true; + topLevelLoop(); + } + } + function addChunk(chunk) { + json.push(chunk); + if (json.length >= bufferLength) { + stream.pause(); + isStreamPaused = true; + } + const chunkLength = chunk.length; + lengths.push({ + item: chunkLength, + aggregate: length() + chunkLength + }); + } + function length() { + const chunkCount = lengths.length; + if (chunkCount === 0) return 0; + return lengths[chunkCount - 1].aggregate; + } + async function topLevelLoop() { + try { + if (shouldHandleNdjson) while (true) { + await awaitNonWhitespace(); + if (character() === "\n") { + hasEndedLine = true; + await next(); + await emit(events.endLine); + continue; + } + if (!hasEndedLine) { + await fail(character(), "\n", currentPosition); + await next(); + continue; + } + hasEndedLine = false; + await value(); + } + else { + await value(); + while (true) { + await awaitNonWhitespace(); + await fail(character(), "EOF", currentPosition); + await value(); + } + } + } catch (_) { + setImmediate(endWalk); + } + } + async function value() { + if (++count % yieldRate === 0) await new Promise((resolve) => { + setImmediate(resolve); + }); + await parseOneValue(); + } + async function parseOneValue() { + await awaitNonWhitespace(); + const char = await next(); + switch (char) { + case "[": return array(); + case "{": return object(); + case "\"": return string(); + case "0": + case "1": + case "2": + case "3": + case "4": + case "5": + case "6": + case "7": + case "8": + case "9": + case "-": + case ".": return number(char); + case "f": return literalFalse(); + case "n": return literalNull(); + case "t": return literalTrue(); + default: + await fail(char, "value", previousPosition); + return value(); + } + } + async function awaitNonWhitespace() { + while (true) { + await awaitCharacter(); + if (!isWhitespace(character())) return; + await next(); + } + } + function awaitCharacter() { + if (index < length()) return Promise.resolve(); + if (isStreamEnded) { + setImmediate(endWalk); + return Promise.reject(); + } + return new Promise((resolve, reject) => { + resumeFn = afterCharacter.bind(null, resolve, reject); + }); + } + function afterCharacter(resolve, reject) { + if (index < length()) return resolve(); + reject(); + if (isStreamEnded) setImmediate(endWalk); + } + function character() { + if (cachedCharacter) return cachedCharacter; + if (lengths[0].item > index) return cachedCharacter = json[0].charAt(index); + const len = lengths.length; + for (let i = 1; i < len; ++i) { + const { aggregate, item } = lengths[i]; + if (aggregate > index) return cachedCharacter = json[i].charAt(index + item - aggregate); + } + } + function isWhitespace(char) { + switch (char) { + case "\n": if (shouldHandleNdjson && scopes.length === 0) return false; + case " ": + case " ": + case "\r": return true; + } + return false; + } + async function next() { + await awaitCharacter(); + const result = character(); + cachedCharacter = null; + index += 1; + previousPosition.line = currentPosition.line; + previousPosition.column = currentPosition.column; + if (result === "\n") { + currentPosition.line += 1; + currentPosition.column = 1; + } else currentPosition.column += 1; + while (index > lengths[0].aggregate) { + json.shift(); + const difference = lengths.shift().item; + index -= difference; + lengths.forEach((len) => len.aggregate -= difference); + } + if (isStreamPaused && json.length <= Math.floor(bufferLength / 2)) { + isStreamPaused = false; + setImmediate(() => stream.resume()); + } + return result; + } + function array() { + return scope(events.array, value); + } + async function scope(event, contentHandler) { + await emit(event); + scopes.push(event); + try { + await awaitNonWhitespace(); + if (character() === terminators[event]) { + await emit(events.endPrefix + event); + scopes.pop(); + await next(); + return; + } + while (true) { + await contentHandler(); + await awaitNonWhitespace(); + if (character() === terminators[event]) { + await emit(events.endPrefix + event); + scopes.pop(); + await next(); + return; + } + if (await checkCharacter(character(), ",", currentPosition)) await next(); + } + } catch (_) { + setImmediate(endWalk); + } + } + async function emit(...args) { + if (pause) await pause; + try { + emitter.emit(...args); + } catch (err) { + try { + emitter.emit(events.error, err); + } catch (_) {} + } + } + function fail(actual, expected, position) { + return emit(events.dataError, error.create(actual, expected, position.line, position.column)); + } + async function checkCharacter(char, expected, position) { + if (char === expected) return true; + await fail(char, expected, position); + return false; + } + function object() { + return scope(events.object, property); + } + async function property() { + await awaitNonWhitespace(); + await checkCharacter(await next(), "\"", previousPosition); + await walkString(events.property); + await awaitNonWhitespace(); + await checkCharacter(await next(), ":", previousPosition); + await value(); + } + async function walkString(event) { + isWalkingString = true; + const str = []; + let escaping = false; + while (true) { + const char = await next(); + if (escaping) { + str.push(await escape(char)); + if (++stringChunkCount >= stringChunkSize) await walkStringChunk(event, str); + escaping = false; + continue; + } + if (char === "\\") { + escaping = true; + continue; + } + if (char === "\"") break; + str.push(char); + if (++stringChunkCount >= stringChunkSize) await walkStringChunk(event, str); + } + isWalkingString = false; + await walkStringChunk(event, str); + stringChunkStart = 0; + await emit(event, str.join("")); + } + function walkStringChunk(event, str) { + if (event === events.string) { + const chunk = str.slice(stringChunkStart).join(""); + stringChunkStart = str.length; + stringChunkCount = 0; + return emit(events.stringChunk, chunk); + } + } + async function escape(char) { + if (escapes[char]) return escapes[char]; + if (char === "u") return escapeHex(); + await fail(char, "escape character", previousPosition); + return `\\${char}`; + } + async function escapeHex() { + const hexits = []; + for (let i = 0; i < 4; i++) { + const char = await next(); + if (!isHexit(char)) { + await fail(char, "hex digit", previousPosition); + return `\\u${hexits.join("")}${char}`; + } + hexits.push(char); + } + return String.fromCharCode(parseInt(hexits.join(""), 16)); + } + async function string() { + await walkString(events.string); + } + async function number(firstCharacter) { + const digits = [firstCharacter]; + let atEnd = await walkDigits(digits); + if (atEnd) return endNumber(digits); + if (character() === ".") { + digits.push(await next()); + atEnd = await walkDigits(digits); + if (atEnd) return endNumber(digits); + } + if (character() === "e" || character() === "E") try { + digits.push(await next()); + await awaitCharacter(); + if (character() === "+" || character() === "-") digits.push(await next()); + await walkDigits(digits); + } catch (_) { + return fail("EOF", "exponent", currentPosition); + } + return endNumber(digits); + } + async function walkDigits(digits) { + try { + while (true) { + await awaitCharacter(); + if (!isDigit(character())) return false; + digits.push(await next()); + } + } catch (_) { + return true; + } + } + async function endNumber(digits) { + await emit(events.number, parseFloat(digits.join(""))); + } + function literalFalse() { + return literal([ + "a", + "l", + "s", + "e" + ], false); + } + async function literal(expectedCharacters, val) { + let consumed = 0; + try { + for (; consumed < expectedCharacters.length; consumed++) { + await awaitCharacter(); + const actual = await next(); + const expected = expectedCharacters[consumed]; + if (actual !== expected) { + if (consumed < expectedCharacters.length - 1) await fail("EOF", expectedCharacters[consumed + 1], currentPosition); + else await fail(actual, expected, previousPosition); + return; + } + } + await emit(events.literal, val); + } catch (_) { + if (consumed < expectedCharacters.length) await fail("EOF", expectedCharacters[consumed], currentPosition); + } + } + function literalNull() { + return literal([ + "u", + "l", + "l" + ], null); + } + function literalTrue() { + return literal([ + "r", + "u", + "e" + ], true); + } + function endStream() { + isStreamEnded = true; + if (isWalkBegun) return resume(); + endWalk(); + } + function resume() { + if (resumeFn) { + resumeFn(); + resumeFn = null; + } + } + async function endWalk() { + if (isWalkEnded) return; + isWalkEnded = true; + if (isWalkingString) await fail("EOF", "\"", currentPosition); + await popScopes(); + await emit(events.end); + } + async function popScopes() { + while (scopes.length > 0) await fail("EOF", terminators[scopes.pop()], currentPosition); + } + } + function isHexit(character) { + return isDigit(character) || isInRange(character, "A", "F") || isInRange(character, "a", "f"); + } + function isDigit(character) { + return isInRange(character, "0", "9"); + } + function isInRange(character, lower, upper) { + const code = character.charCodeAt(0); + return code >= lower.charCodeAt(0) && code <= upper.charCodeAt(0); + } +})); +//#endregion +//#region node_modules/bfj/src/stream.js +var require_stream = /* @__PURE__ */ __commonJSMin(((exports, module) => { + var util = require("util"); + var Readable = require("stream").Readable; + var check = require_check_types(); + util.inherits(BfjStream, Readable); + module.exports = BfjStream; + function BfjStream(read, options) { + if (check.not.instanceStrict(this, BfjStream)) return new BfjStream(read); + check.assert.function(read, "Invalid read implementation"); + this._read = function() { + read(); + }; + return Readable.call(this, options); + } +})); +//#endregion +//#region node_modules/bfj/src/datastream.js +var require_datastream = /* @__PURE__ */ __commonJSMin(((exports, module) => { + var check = require_check_types(); + var BfjStream = require_stream(); + require("util").inherits(DataStream, BfjStream); + module.exports = DataStream; + function DataStream(read, options) { + if (check.not.instanceStrict(this, DataStream)) return new DataStream(read, options); + return BfjStream.call(this, read, { + ...options, + objectMode: true + }); + } +})); +//#endregion +//#region node_modules/hoopy/index.js +var require_hoopy = /* @__PURE__ */ __commonJSMin(((exports, module) => { + var Hoopy = class extends Array { + constructor(size) { + let index, isIndexOverflowed; + if (!isPositiveInteger(size)) throw new TypeError("Argument `size` must be a positive integer."); + super(size); + this.grow = (by) => { + if (!isPositiveInteger(by)) throw new TypeError("Argument `by` must be a positive integer."); + let i; + const newSize = size + by; + for (i = size; i < newSize; ++i) this[i] = void 0; + if (isIndexOverflowed) for (i = 0; i <= index; ++i) { + let j = size + i; + if (j >= newSize) j %= newSize; + this[j] = this[i]; + this[i] = void 0; + } + size = newSize; + }; + return new Proxy(this, { + get(target, key) { + if (isInteger(key)) return target[getIndex(key, size)]; + return target[key]; + }, + set(target, key, value) { + if (isInteger(key)) { + index = getIndex(key, size); + target[index] = value; + if (Math.abs(key) >= size) isIndexOverflowed = true; + else isIndexOverflowed = false; + } else target[key] = value; + return true; + } + }); + } + }; + function isPositiveInteger(thing) { + return isInteger(thing) && thing > 0; + } + function isInteger(thing) { + try { + return +thing % 1 === 0; + } catch (error) {} + return false; + } + function getIndex(key, size) { + if (key === 0) return 0; + if (key < 0) return (size - Math.abs(key)) % size; + return key % size; + } + function nop() { + throw new Error("Not implemented"); + } + Hoopy.prototype.push = nop; + Hoopy.prototype.pop = nop; + Hoopy.prototype.shift = nop; + Hoopy.prototype.unshift = nop; + module.exports = Hoopy; +})); +//#endregion +//#region node_modules/bfj/src/jsonpath.js +var require_jsonpath = /* @__PURE__ */ __commonJSMin(((exports, module) => { + module.exports = parseJsonPath; + function parseJsonPath(selector) { + if (typeof selector !== "string" || selector.length === 0 || selector[0] !== "$") throw new SyntaxError("Invalid jsonpath: must start with $"); + const result = [{ expression: { + type: "root", + value: "$" + } }]; + let position = 1; + if (position >= selector.length) throw new SyntaxError("Invalid jsonpath: must have at least one segment after $"); + while (position < selector.length) { + const character = selector[position]; + if (character === ".") { + position += 1; + if (position >= selector.length || selector[position] === ".") throw new SyntaxError("Invalid jsonpath: unexpected character after dot"); + const id = parseIdentifier(selector, position); + result.push({ + expression: { + type: "identifier", + value: id.value + }, + operation: "member", + scope: "child" + }); + position = id.position; + } else if (character === "[") { + position += 1; + const content = parseBracketContent(selector, position); + result.push({ + expression: content.expression, + operation: "subscript", + scope: "child" + }); + position = content.position; + if (position >= selector.length || selector[position] !== "]") throw new SyntaxError("Invalid jsonpath: unterminated bracket"); + position += 1; + } else throw new SyntaxError(`Invalid jsonpath: unexpected character "${character}"`); + } + return result; + } + function parseBracketContent(selector, position) { + if (position >= selector.length) throw new SyntaxError("Invalid jsonpath: unterminated bracket"); + const character = selector[position]; + if (character === "*") return { + expression: { + type: "wildcard", + value: "*" + }, + position: position + 1 + }; + if (character === "\"" || character === "'") { + const str = parseStringLiteral(selector, position); + return { + expression: { + type: "string_literal", + value: str.value + }, + position: str.position + }; + } + if (isDigit(character)) { + const num = parseNumericLiteral(selector, position); + return { + expression: { + type: "numeric_literal", + value: num.value + }, + position: num.position + }; + } + throw new SyntaxError(`Invalid jsonpath: unexpected bracket content "${character}"`); + } + function parseIdentifier(selector, position) { + const start = position; + if (position >= selector.length || !isIdentifierStart(selector[position])) throw new SyntaxError("Invalid jsonpath: expected identifier"); + position += 1; + while (position < selector.length && isIdentifier(selector[position])) position += 1; + return { + value: selector.slice(start, position), + position + }; + } + function parseNumericLiteral(selector, position) { + const start = position; + while (position < selector.length && isDigit(selector[position])) position += 1; + return { + value: parseInt(selector.slice(start, position), 10), + position + }; + } + function parseStringLiteral(selector, position) { + const quote = selector[position]; + position += 1; + const start = position; + while (position < selector.length && selector[position] !== quote) { + if (selector[position] === "\\") throw new SyntaxError("Invalid jsonpath: escape sequences in strings are not supported"); + position += 1; + } + if (position >= selector.length) throw new SyntaxError("Invalid jsonpath: unterminated string"); + const value = selector.slice(start, position); + position += 1; + return { + value, + position + }; + } + function isDigit(character) { + return character >= "0" && character <= "9"; + } + function isIdentifier(character) { + return character >= "a" && character <= "z" || character >= "A" && character <= "Z" || character >= "0" && character <= "9" || character === "_" || character === "$"; + } + function isIdentifierStart(character) { + return character >= "a" && character <= "z" || character >= "A" && character <= "Z" || character === "_" || character === "$"; + } +})); +//#endregion +//#region __vite-browser-external +var require___vite_browser_external = /* @__PURE__ */ __commonJSMin(((exports, module) => { + module.exports = {}; +})); +//#endregion +//#region node_modules/bfj/src/match.js +var require_match = /* @__PURE__ */ __commonJSMin(((exports, module) => { + var check = require_check_types(); + var DataStream = require_datastream(); + var events = require_events(); + var Hoopy = require_hoopy(); + var parseJsonPath = require_jsonpath(); + var { PassThrough } = require___vite_browser_external(); + var walk = require_walk(); + var DEFAULT_BUFFER_LENGTH = 256; + module.exports = match; + /** + * Public function `match`. + * + * Asynchronously parses a stream of JSON data, returning a stream of items + * that match the argument. Note that if a value is `null`, it won't be matched + * because `null` is used to signify end-of-stream in node. + * + * @param stream: Readable instance representing the incoming JSON. + * + * @param selector: Regular expression, string or predicate function used to + * identify matches. If a regular expression or string is + * passed, only property keys are tested. If a predicate is + * passed, both the key and the value are passed to it as + * arguments. + * + * @option minDepth: Number indicating the minimum depth to apply the selector + * to. The default is `0`, but setting it to a higher value + * can improve performance and reduce memory usage by + * eliminating the need to actualise top-level items. + * + * @option numbers: Boolean, indicating whether numerical keys (e.g. array + * indices) should be coerced to strings before testing the + * match. Only applies if the `selector` argument is a string + * or regular expression. + * + * @option ndjson: Set this to true to parse newline-delimited JSON, + * default is `false`. + * + * @option recursive: Set this to true to recursively parse + * matched string values, + * default is `false`. + * + * @option yieldRate: The number of data items to process per timeslice, + * default is 1024. + * + * @option bufferLength: The length of the match buffer, default is 256. + * + * @option highWaterMark: If set, will be passed to the readable stream constructor + * as the value for the highWaterMark option. + **/ + function match(stream, selector, options = {}) { + const keys = []; + const scopes = []; + const properties = []; + const matches = new Hoopy(options.bufferLength || DEFAULT_BUFFER_LENGTH); + let streamOptions; + const { highWaterMark } = options; + if (highWaterMark) streamOptions = { highWaterMark }; + const results = options.results || new DataStream(read, streamOptions); + let chunkStream, selectorFunction, selectorPath, selectorString, resume; + let coerceNumbers = false; + let awaitPush = !options.results; + let isEnded = false; + let length = 0; + let index = 0; + const minDepth = options.minDepth || 0; + check.assert.greaterOrEqual(minDepth, 0); + const recursive = options.recursive || false; + check.assert.boolean(recursive); + if (check.function(selector)) { + selectorFunction = selector; + selector = null; + } else if (check.string(selector)) { + check.assert.nonEmptyString(selector); + if (selector.startsWith("$.")) { + selectorPath = parseJsonPath(selector); + check.assert.identical(selectorPath.shift(), { expression: { + type: "root", + value: "$" + } }); + selectorPath.forEach((part) => { + check.assert.equal(part.scope, "child"); + }); + } else { + selectorString = selector; + coerceNumbers = !!options.numbers; + } + selector = null; + } else { + check.assert.instanceStrict(selector, RegExp); + coerceNumbers = !!options.numbers; + } + const emitter = walk(stream, { + ...options, + streamChunkSize: recursive ? matches.length : null + }); + emitter.on(events.array, array); + emitter.on(events.object, object); + emitter.on(events.property, property); + emitter.on(events.endArray, endScope); + emitter.on(events.endObject, endScope); + emitter.on(events.string, value); + emitter.on(events.number, value); + emitter.on(events.literal, value); + emitter.on(events.end, end); + emitter.on(events.error, error); + emitter.on(events.dataError, dataError); + if (recursive) emitter.on(events.stringChunk, stringChunk); + return results; + function read() { + if (awaitPush) { + awaitPush = false; + if (isEnded) { + if (length > 0) after(); + return endResults(); + } + } + if (resume) { + const resumeCopy = resume; + resume = null; + resumeCopy(); + after(); + } + } + function after() { + if (awaitPush || resume) return; + let i; + for (i = 0; i < length && !resume; ++i) if (!results.push(matches[i + index])) pause(); + if (i === length) index = length = 0; + else { + length -= i; + index += i; + } + } + function pause() { + resume = emitter.pause(); + } + function endResults() { + if (!awaitPush) results.push(null); + } + function array() { + scopes.push([]); + } + function object() { + scopes.push({}); + } + function property(name) { + keys.push(name); + if (scopes.length < minDepth) return; + properties.push(name); + } + function endScope() { + if (selectorPath) keys.pop(); + value(scopes.pop()); + } + function value(v) { + if (chunkStream) chunkStream = null; + if (scopes.length < minDepth) return; + let key; + if (scopes.length > 0) { + const scope = scopes[scopes.length - 1]; + if (Array.isArray(scope)) key = scope.length; + else key = properties.pop(); + scope[key] = v; + } + if (v === null) return; + if (selectorFunction) { + if (selectorFunction(key, v, scopes.length)) push(v); + } else if (selectorPath) { + if (isSelectorPathSatisfied([...keys, key])) push(v); + } else { + if (coerceNumbers && typeof key === "number") key = key.toString(); + if (selectorString && selectorString === key || selector && selector.test(key)) push(v); + } + } + function isSelectorPathSatisfied(path) { + if (selectorPath.length !== path.length) return false; + return selectorPath.every(({ expression, operation }, i) => { + if (operation === "member" && expression.type === "identifier" || operation === "subscript" && (expression.type === "string_literal" || expression.type === "numeric_literal")) return path[i] === expression.value; + if (operation === "subscript" && expression.type === "wildcard" && expression.value === "*") return true; + return false; + }); + } + function push(v) { + if (length + 1 === matches.length) pause(); + matches[index + length++] = v; + after(); + } + function stringChunk(chunk) { + if (!chunkStream) { + chunkStream = new PassThrough(streamOptions); + match(chunkStream, selectorFunction || selectorPath || selectorString || selector, { + ...options, + results + }); + } + chunkStream.write(chunk); + } + function end() { + isEnded = true; + endResults(); + } + function error(e) { + results.emit("error", e); + } + function dataError(e) { + results.emit("dataError", e); + } + } +})); +//#endregion +//#region node_modules/bfj/src/parse.js +var require_parse = /* @__PURE__ */ __commonJSMin(((exports, module) => { + var check = require_check_types(); + var events = require_events(); + var walk = require_walk(); + module.exports = parse; + var NDJSON_STATE = /* @__PURE__ */ new Map(); + /** + * Public function `parse`. + * + * Returns a promise and asynchronously parses a stream of JSON data. If + * there are no errors, the promise is resolved with the parsed data. If + * errors occur, the promise is rejected with the first error. + * + * @param stream: Readable instance representing the incoming JSON. + * + * @option reviver: Transformation function, invoked depth-first. + * + * @option yieldRate: The number of data items to process per timeslice, + * default is 1024. + * + * @option ndjson: Set this to true to parse newline-delimited JSON. In + * this case, each call will be resolved with one value + * from the stream. To parse the entire stream, calls + * should be made sequentially one-at-a-time until the + * returned promise resolves to `undefined`. + **/ + async function parse(stream, options = {}) { + check.assert.maybe.function(options.reviver, "Invalid reviver option"); + const errors = []; + const scopes = []; + const reviver = options.reviver; + const shouldHandleNdjson = !!options.ndjson; + let emitter, resolve, reject, scopeKey; + if (shouldHandleNdjson && NDJSON_STATE.has(stream)) { + const state = NDJSON_STATE.get(stream); + NDJSON_STATE.delete(stream); + emitter = state.emitter; + setImmediate(state.resume); + } else emitter = walk(stream, options); + emitter.on(events.array, array); + emitter.on(events.object, object); + emitter.on(events.property, property); + emitter.on(events.string, value); + emitter.on(events.number, value); + emitter.on(events.literal, value); + emitter.on(events.endArray, endScope); + emitter.on(events.endObject, endScope); + emitter.on(events.end, end); + emitter.on(events.error, error); + emitter.on(events.dataError, error); + if (shouldHandleNdjson) emitter.on(events.endLine, endLine); + return new Promise((res, rej) => { + resolve = res; + reject = rej; + }); + function array() { + if (errors.length > 0) return; + beginScope([]); + } + function beginScope(parsed) { + if (errors.length > 0) return; + if (scopes.length > 0) value(parsed); + scopes.push(parsed); + } + function value(v) { + if (errors.length > 0) return; + if (scopes.length === 0) return scopes.push(v); + const scope = scopes[scopes.length - 1]; + if (scopeKey) { + scope[scopeKey] = v; + scopeKey = null; + } else scope.push(v); + } + function object() { + if (errors.length > 0) return; + beginScope({}); + } + function property(name) { + if (errors.length > 0) return; + scopeKey = name; + } + function endScope() { + if (errors.length > 0) return; + if (scopes.length > 1) scopes.pop(); + } + function end() { + if (shouldHandleNdjson) { + const resume = emitter.pause(); + emitter.removeAllListeners(); + NDJSON_STATE.set(stream, { + emitter, + resume + }); + } + if (errors.length > 0) return reject(errors[0]); + if (reviver) scopes[0] = transform(scopes[0], ""); + resolve(scopes[0]); + } + function transform(obj, key) { + if (obj && typeof obj === "object") Object.entries(obj).forEach(([k, v]) => { + obj[k] = transform(v, k); + }); + return reviver(key, obj); + } + function error(e) { + errors.push(e); + } + function endLine() { + if (scopes.length > 0) end(); + } + } +})); +//#endregion +//#region node_modules/bfj/src/unpipe.js +var require_unpipe = /* @__PURE__ */ __commonJSMin(((exports, module) => { + var stream = require("stream"); + var check = require_check_types(); + var parse = require_parse(); + module.exports = unpipe; + /** + * Public function `unpipe`. + * + * Returns a writeable stream that can be passed to stream.pipe, then parses JSON + * data read from the stream. If there are no errors, the callback is invoked with + * the result as the second argument. If errors occur, the first error is passed to + * the callback as the first argument. + * + * @param callback: Function that will be called after parsing is complete. + * + * @option reviver: Transformation function, invoked depth-first. + * + * @option discard: The number of characters to process before discarding them + * to save memory. The default value is `1048576`. + * + * @option yieldRate: The number of data items to process per timeslice, + * default is 1024. + **/ + function unpipe(callback, options) { + check.assert.function(callback, "Invalid callback argument"); + const jsonstream = new stream.PassThrough(); + initStream(jsonstream, callback, options); + return jsonstream; + } + async function initStream(jsonstream, callback, options) { + try { + await callback(null, await parse(jsonstream, { + ...options, + ndjson: false + })); + } catch (error) { + await callback(error); + } + } +})); +//#endregion +//#region node_modules/bfj/src/read.js +var require_read = /* @__PURE__ */ __commonJSMin(((exports, module) => { + var fs$3 = require("fs"); + var parse = require_parse(); + module.exports = read; + /** + * Public function `read`. + * + * Returns a promise and asynchronously parses a JSON file read from disk. If + * there are no errors, the promise is resolved with the parsed data. If errors + * occur, the promise is rejected with the first error. + * + * @param path: Path to the JSON file. + * + * @option reviver: Transformation function, invoked depth-first. + * + * @option yieldRate: The number of data items to process per timeslice, + * default is 1024. + **/ + function read(path, options) { + return parse(fs$3.createReadStream(path, options), { + ...options, + ndjson: false + }); + } +})); +//#endregion +//#region node_modules/bfj/src/eventify.js +var require_eventify = /* @__PURE__ */ __commonJSMin(((exports, module) => { + var check = require_check_types(); + var EventEmitter = require("events").EventEmitter; + var events = require_events(); + var invalidTypes = { + undefined: true, + function: true, + symbol: true + }; + module.exports = eventify; + /** + * Public function `eventify`. + * + * Returns an event emitter and asynchronously traverses a data structure + * (depth-first), emitting events as it encounters items. Sanely handles + * promises, buffers, maps and other iterables. The event emitter is + * decorated with a `pause` method that can be called to pause processing. + * + * @param data: The data structure to traverse. + * + * @option promises: 'resolve' or 'ignore', default is 'resolve'. + * + * @option buffers: 'toString' or 'ignore', default is 'toString'. + * + * @option maps: 'object' or 'ignore', default is 'object'. + * + * @option iterables: 'array' or 'ignore', default is 'array'. + * + * @option circular: 'error' or 'ignore', default is 'error'. + * + * @option yieldRate: The number of data items to process per timeslice, + * default is 1024. + **/ + function eventify(data, options = {}) { + const coercions = {}; + const emitter = new EventEmitter(); + const references = /* @__PURE__ */ new Map(); + let count = 0; + let disableCoercions = false; + let ignoreCircularReferences; + let ignoreItems; + let pause; + let yieldRate; + emitter.pause = () => { + let resolve; + pause = new Promise((res) => resolve = res); + return () => { + pause = null; + count = 0; + resolve(); + }; + }; + parseOptions(); + setImmediate(begin); + return emitter; + function parseOptions() { + parseCoercionOption("promises"); + parseCoercionOption("buffers"); + parseCoercionOption("maps"); + parseCoercionOption("iterables"); + if (Object.keys(coercions).length === 0) disableCoercions = true; + if (options.circular === "ignore") ignoreCircularReferences = true; + check.assert.maybe.positive(options.yieldRate); + yieldRate = options.yieldRate || 1024; + } + function parseCoercionOption(key) { + if (options[key] !== "ignore") coercions[key] = true; + } + async function begin() { + try { + await proceed(data); + } catch (error) { + await emit(events.error, error); + } finally { + await emit(events.end); + } + } + async function proceed(datum) { + if (++count % yieldRate !== 0) return afterCoercion(await coerce(datum)); + return new Promise(yieldThenProceed.bind(null, datum)); + } + async function coerce(datum) { + if (disableCoercions || check.primitive(datum)) return datum; + if (check.thenable(datum)) return coerce(await coerceThing(datum, "promises", coercePromise)); + if (check.instanceStrict(datum, Buffer)) return coerceThing(datum, "buffers", coerceBuffer); + if (check.instanceStrict(datum, Map)) return coerceThing(datum, "maps", coerceMap); + if (check.iterable(datum) && check.not.string(datum) && check.not.array(datum)) return coerceThing(datum, "iterables", coerceIterable); + if (check.function(datum.toJSON)) return datum.toJSON(); + return datum; + } + function coerceThing(datum, thing, fn) { + if (coercions[thing]) return fn(datum); + return Promise.resolve(); + } + function coercePromise(p) { + return p; + } + function coerceBuffer(buffer) { + return Promise.resolve(buffer.toString()); + } + function coerceMap(map) { + const result = {}; + return coerceCollection(map, result, (val, key) => { + result[key] = val; + }); + } + function coerceCollection(coll, target, push) { + coll.forEach(push); + return Promise.resolve(target); + } + function coerceIterable(iterable) { + const result = []; + return coerceCollection(iterable, result, (val) => { + result.push(val); + }); + } + function afterCoercion(coerced) { + if (isInvalid(coerced)) return; + if (coerced === false || coerced === true || coerced === null) return literal(coerced); + if (Array.isArray(coerced)) return array(coerced); + const type = typeof coerced; + switch (type) { + case "number": return value(coerced, type); + case "string": return value(escapeString(coerced), type); + default: return object(coerced); + } + } + function isInvalid(datum) { + const type = typeof datum; + return !!invalidTypes[type] || type === "number" && !isValidNumber(datum); + } + function isValidNumber(datum) { + return datum > Number.NEGATIVE_INFINITY && datum < Number.POSITIVE_INFINITY; + } + function yieldThenProceed(datum, resolve, reject) { + setImmediate(async () => { + try { + resolve(await afterCoercion(await coerce(datum))); + } catch (error) { + reject(error); + } + }); + } + function literal(datum) { + return value(datum, "literal"); + } + function array(datum) { + return collection(datum, datum, "array", async (val) => { + if (isInvalid(val)) await proceed(null); + else await proceed(val); + }); + } + async function collection(obj, arr, type, action) { + let ignoreThisItem; + if (references.has(obj)) { + ignoreThisItem = ignoreItems = true; + if (!ignoreCircularReferences) return emit(events.dataError, /* @__PURE__ */ new Error("Circular reference.")); + } else references.set(obj, true); + await emit(events[type]); + await item(obj, arr, type, action, ignoreThisItem); + } + async function emit(event, eventData) { + try { + await pause; + emitter.emit(event, eventData); + } catch (error) { + try { + emitter.emit(events.error, error); + } catch (_) {} + } + } + async function item(obj, arr, type, action, ignoreThisItem) { + for (let index = 0; index < arr.length; index++) { + if (ignoreItems) break; + await action(arr[index]); + } + if (ignoreThisItem) ignoreItems = false; + if (ignoreItems) return; + await emit(events.endPrefix + events[type]); + references.delete(obj); + } + function value(datum, type) { + return emit(events[type], datum); + } + function object(datum) { + return collection(datum, Object.keys(datum), "object", async (key) => { + const val = datum[key]; + if (isInvalid(val)) return; + await emit(events.property, escapeString(key)); + await proceed(val); + }); + } + function escapeString(string) { + string = JSON.stringify(string); + return string.substring(1, string.length - 1); + } + } +})); +//#endregion +//#region node_modules/bfj/src/jsonstream.js +var require_jsonstream = /* @__PURE__ */ __commonJSMin(((exports, module) => { + var check = require_check_types(); + var BfjStream = require_stream(); + require("util").inherits(JsonStream, BfjStream); + module.exports = JsonStream; + function JsonStream(read, options) { + if (check.not.instanceStrict(this, JsonStream)) return new JsonStream(read, options); + return BfjStream.call(this, read, { + ...options, + encoding: "utf8" + }); + } +})); +//#endregion +//#region node_modules/tryer/src/tryer.js +var require_tryer = /* @__PURE__ */ __commonJSMin(((exports, module) => { + (function(globals) { + "use strict"; + if (typeof define === "function" && define.amd) define(function() { + return tryer; + }); + else if (typeof module !== "undefined" && module !== null) module.exports = tryer; + else globals.tryer = tryer; + function tryer(options) { + options = normaliseOptions(options); + iterateWhen(); + function iterateWhen() { + if (preRecur()) iterateUntil(); + } + function preRecur() { + return conditionallyRecur("when", iterateWhen); + } + function conditionallyRecur(predicateKey, iterate) { + if (!options[predicateKey]()) { + incrementCount(options); + if (shouldFail(options)) options.fail(); + else recur(iterate, postIncrementInterval(options)); + return false; + } + return true; + } + function iterateUntil() { + var result; + if (isActionSynchronous(options)) { + result = options.action(); + if (result && isFunction(result.then)) return result.then(postRecur, postRecur); + return postRecur(); + } + options.action(postRecur); + } + function postRecur() { + if (conditionallyRecur("until", iterateUntil)) options.pass(); + } + } + function normaliseOptions(options) { + options = options || {}; + return { + count: 0, + when: normalisePredicate(options.when), + until: normalisePredicate(options.until), + action: normaliseFunction(options.action), + fail: normaliseFunction(options.fail), + pass: normaliseFunction(options.pass), + interval: normaliseNumber(options.interval, -1e3), + limit: normaliseNumber(options.limit, -1) + }; + } + function normalisePredicate(fn) { + return normalise(fn, isFunction, yes); + } + function isFunction(fn) { + return typeof fn === "function"; + } + function yes() { + return true; + } + function normaliseFunction(fn) { + return normalise(fn, isFunction, nop); + } + function nop() {} + function normalise(thing, predicate, defaultValue) { + if (predicate(thing)) return thing; + return defaultValue; + } + function normaliseNumber(number, defaultNumber) { + return normalise(number, isNumber, defaultNumber); + } + function isNumber(number) { + return typeof number === "number" && number === number; + } + function isActionSynchronous(options) { + return options.action.length === 0; + } + function incrementCount(options) { + options.count += 1; + } + function shouldFail(options) { + return options.limit >= 0 && options.count >= options.limit; + } + function postIncrementInterval(options) { + var currentInterval = options.interval; + if (options.interval < 0) options.interval *= 2; + return currentInterval; + } + function recur(fn, interval) { + setTimeout(fn, Math.abs(interval)); + } + })(exports); +})); +//#endregion +//#region node_modules/bfj/src/streamify.js +var require_streamify = /* @__PURE__ */ __commonJSMin(((exports, module) => { + var check = require_check_types(); + var eventify = require_eventify(); + var events = require_events(); + var JsonStream = require_jsonstream(); + var Hoopy = require_hoopy(); + var tryer = require_tryer(); + var DEFAULT_BUFFER_LENGTH = 256; + module.exports = streamify; + /** + * Public function `streamify`. + * + * Asynchronously serialises a data structure to a stream of JSON + * data. Sanely handles promises, buffers, maps and other iterables. + * + * @param data: The data to transform. + * + * @option space: Indentation string, or the number of spaces + * to indent each nested level by. + * + * @option promises: 'resolve' or 'ignore', default is 'resolve'. + * + * @option buffers: 'toString' or 'ignore', default is 'toString'. + * + * @option maps: 'object' or 'ignore', default is 'object'. + * + * @option iterables: 'array' or 'ignore', default is 'array'. + * + * @option circular: 'error' or 'ignore', default is 'error'. + * + * @option yieldRate: The number of data items to process per timeslice, + * default is 1024. + * + * @option bufferLength: The length of the buffer, default is 256. + * + * @option highWaterMark: If set, will be passed to the readable stream constructor + * as the value for the highWaterMark option. + **/ + function streamify(data, options = {}) { + const emitter = eventify(data, options); + const json = new Hoopy(options.bufferLength || DEFAULT_BUFFER_LENGTH); + const space = normaliseSpace(options); + let streamOptions; + const { highWaterMark } = options; + if (highWaterMark) streamOptions = { highWaterMark }; + const stream = new JsonStream(read, streamOptions); + const eventQueue = []; + let awaitPush = true; + let index = 0; + let indentation = ""; + let isEnded; + let isPaused = false; + let isProperty; + let length = 0; + let needsComma; + emitter.on(events.array, noRacing(array)); + emitter.on(events.object, noRacing(object)); + emitter.on(events.property, noRacing(property)); + emitter.on(events.string, noRacing(string)); + emitter.on(events.number, noRacing(value)); + emitter.on(events.literal, noRacing(value)); + emitter.on(events.endArray, noRacing(endArray)); + emitter.on(events.endObject, noRacing(endObject)); + emitter.on(events.end, noRacing(end)); + emitter.on(events.error, noRacing(error)); + emitter.on(events.dataError, noRacing(dataError)); + return stream; + function read() { + if (awaitPush) { + awaitPush = false; + if (isEnded) { + if (length > 0) after(); + return endStream(); + } + } + if (isPaused) after(); + } + function after() { + if (awaitPush) return; + let i; + for (i = 0; i < length && !awaitPush; ++i) if (!stream.push(json[i + index], "utf8")) awaitPush = true; + if (i === length) index = length = 0; + else { + length -= i; + index += i; + } + } + function endStream() { + if (!awaitPush) stream.push(null); + } + function noRacing(handler) { + return async (eventData) => { + let resolve; + eventQueue.push(new Promise((res) => resolve = res)); + if (eventQueue.length > 1) { + await eventQueue[eventQueue.length - 2]; + eventQueue.shift(); + } + await handler(eventData); + resolve(); + }; + } + async function array() { + await beforeScope(); + await addJson("["); + afterScope(); + } + function beforeScope() { + return before(true); + } + async function before(isScope) { + if (isProperty) { + isProperty = false; + if (space) return addJson(" "); + return; + } + if (needsComma) { + if (isScope) needsComma = false; + await addJson(","); + } else if (!isScope) needsComma = true; + if (space && indentation) return indent(); + } + function addJson(chunk) { + if (length + 1 <= json.length) { + json[index + length++] = chunk; + after(); + return Promise.resolve(); + } + isPaused = true; + return new Promise((resolve) => { + const unpause = emitter.pause(); + tryer({ + interval: -10, + until() { + return length + 1 <= json.length; + }, + pass() { + isPaused = false; + json[index + length++] = chunk; + resolve(); + setImmediate(unpause); + } + }); + }); + } + function indent() { + return addJson(`\n${indentation}`); + } + function afterScope() { + needsComma = false; + if (space) indentation += space; + } + async function object() { + await beforeScope(); + await addJson("{"); + afterScope(); + } + async function property(name) { + await before(); + await addJson(`"${name}":`); + isProperty = true; + } + function string(s) { + return value(`"${s}"`); + } + async function value(v) { + await before(); + await addJson(`${v}`); + needsComma = true; + } + async function endArray() { + await beforeScopeEnd(); + await addJson("]"); + afterScopeEnd(); + } + async function beforeScopeEnd() { + if (space) { + indentation = indentation.substr(space.length); + await indent(); + } + } + function afterScopeEnd() { + needsComma = true; + } + async function endObject() { + await beforeScopeEnd(); + await addJson("}"); + afterScopeEnd(); + } + function end() { + after(); + isEnded = true; + endStream(); + } + function error(err) { + stream.emit("error", err); + } + function dataError(err) { + stream.emit("dataError", err); + } + } + function normaliseSpace(options) { + if (check.positive(options.space)) return new Array(options.space + 1).join(" "); + if (check.nonEmptyString(options.space)) return options.space; + } +})); +//#endregion +//#region node_modules/bfj/src/stringify.js +var require_stringify = /* @__PURE__ */ __commonJSMin(((exports, module) => { + var streamify = require_streamify(); + module.exports = stringify; + /** + * Public function `stringify`. + * + * Returns a promise and asynchronously serialises a data structure to a + * JSON string. Sanely handles promises, buffers, maps and other iterables. + * + * @param data: The data to transform + * + * @option space: Indentation string, or the number of spaces + * to indent each nested level by. + * + * @option promises: 'resolve' or 'ignore', default is 'resolve'. + * + * @option buffers: 'toString' or 'ignore', default is 'toString'. + * + * @option maps: 'object' or 'ignore', default is 'object'. + * + * @option iterables: 'array' or 'ignore', default is 'array'. + * + * @option circular: 'error' or 'ignore', default is 'error'. + * + * @option yieldRate: The number of data items to process per timeslice, + * default is 1024. + * + * @option bufferLength: The length of the buffer, default is 256. + * + * @option highWaterMark: If set, will be passed to the readable stream constructor + * as the value for the highWaterMark option. + **/ + function stringify(data, options) { + const json = []; + const stream = streamify(data, options); + let resolve, reject; + stream.on("data", read); + stream.on("end", end); + stream.on("error", error); + stream.on("dataError", error); + return new Promise((res, rej) => { + resolve = res; + reject = rej; + }); + function read(chunk) { + json.push(chunk); + } + function end() { + resolve(json.join("")); + } + function error(e) { + reject(e); + } + } +})); +//#endregion +//#region node_modules/bfj/src/write.js +var require_write = /* @__PURE__ */ __commonJSMin(((exports, module) => { + var fs$2 = require("fs"); + var streamify = require_streamify(); + module.exports = write; + /** + * Public function `write`. + * + * Returns a promise and asynchronously serialises a data structure to a + * JSON file on disk. Sanely handles promises, buffers, maps and other + * iterables. + * + * @param path: Path to the JSON file. + * + * @param data: The data to transform. + * + * @option space: Indentation string, or the number of spaces + * to indent each nested level by. + * + * @option promises: 'resolve' or 'ignore', default is 'resolve'. + * + * @option buffers: 'toString' or 'ignore', default is 'toString'. + * + * @option maps: 'object' or 'ignore', default is 'object'. + * + * @option iterables: 'array' or 'ignore', default is 'array'. + * + * @option circular: 'error' or 'ignore', default is 'error'. + * + * @option yieldRate: The number of data items to process per timeslice, + * default is 1024. + * + * @option bufferLength: The length of the buffer, default is 256. + * + * @option highWaterMark: If set, will be passed to the readable stream constructor + * as the value for the highWaterMark option. + **/ + function write(path, data, options) { + return new Promise((resolve, reject) => { + streamify(data, options).pipe(fs$2.createWriteStream(path, options)).on("finish", () => { + resolve(); + }).on("error", reject).on("dataError", reject); + }); + } +})); +//#endregion +//#region node_modules/bfj/src/index.js +var require_src = /* @__PURE__ */ __commonJSMin(((exports, module) => { + module.exports = { + walk: require_walk(), + match: require_match(), + parse: require_parse(), + unpipe: require_unpipe(), + read: require_read(), + eventify: require_eventify(), + streamify: require_streamify(), + stringify: require_stringify(), + write: require_write(), + events: require_events() + }; +})); +//#endregion +//#region cli.js +var { stringifyBigInts } = ffjavascript.utils; +(0, v8.setFlagsFromString)("--expose_gc"); +var logger = logplease.default.create("snarkJS", { showTimestamp: false }); +logplease.default.setLogLevel("INFO"); +var __dirname$1 = path.default.dirname(url.default.fileURLToPath(require("url").pathToFileURL(__filename).href)); +clProcessor([ + { + cmd: "powersoftau new [powersoftau_0000.ptau]", + description: "Starts a powers of tau ceremony", + alias: ["ptn"], + options: "-verbose|v", + action: powersOfTauNew + }, + { + cmd: "powersoftau contribute ", + description: "creates a ptau file with a new contribution", + alias: ["ptc"], + options: "-verbose|v -name|n -entropy|e", + action: powersOfTauContribute + }, + { + cmd: "powersoftau export challenge [challenge]", + description: "Creates a challenge", + alias: ["ptec"], + options: "-verbose|v", + action: powersOfTauExportChallenge + }, + { + cmd: "powersoftau challenge contribute [response]", + description: "Contribute to a challenge", + alias: ["ptcc"], + options: "-verbose|v -entropy|e", + action: powersOfTauChallengeContribute + }, + { + cmd: "powersoftau import response <", + description: "import a response to a ptau file", + alias: ["ptir"], + options: "-verbose|v -nopoints -nocheck -name|n", + action: powersOfTauImport + }, + { + cmd: "powersoftau beacon ", + description: "adds a beacon", + alias: ["ptb"], + options: "-verbose|v -name|n", + action: powersOfTauBeacon + }, + { + cmd: "powersoftau prepare phase2 ", + description: "Prepares phase 2. ", + longDescription: " This process calculates the evaluation of the Lagrange polinomials at tau for alpha*tau and beta tau", + alias: ["pt2"], + options: "-verbose|v", + action: powersOfTauPreparePhase2 + }, + { + cmd: "powersoftau convert ", + description: "Convert ptau", + longDescription: " This process calculates the evaluation of the Lagrange polinomials at tau for alpha*tau and beta tau", + alias: ["ptcv"], + options: "-verbose|v", + action: powersOfTauConvert + }, + { + cmd: "powersoftau truncate ", + description: "Generate different powers of tau with smaller sizes ", + longDescription: " This process generates smaller ptau files from a bigger power ptau", + alias: ["ptt"], + options: "-verbose|v", + action: powersOfTauTruncate + }, + { + cmd: "powersoftau verify ", + description: "verifies a powers of tau file", + alias: ["ptv"], + options: "-verbose|v", + action: powersOfTauVerify + }, + { + cmd: "powersoftau export json ", + description: "Exports a power of tau file to a JSON", + alias: ["ptej"], + options: "-verbose|v", + action: powersOfTauExportJson + }, + { + cmd: "r1cs info [circuit.r1cs]", + description: "Print statistiscs of a circuit", + alias: ["ri", "info -r|r1cs:circuit.r1cs"], + action: r1csInfo + }, + { + cmd: "r1cs print [circuit.r1cs] [circuit.sym]", + description: "Print the constraints of a circuit", + alias: ["rp", "print -r|r1cs:circuit.r1cs -s|sym"], + action: r1csPrint + }, + { + cmd: "r1cs export json [circuit.r1cs] [circuit.json]", + description: "Export r1cs to JSON file", + alias: ["rej"], + action: r1csExportJSON + }, + { + cmd: "wtns calculate [circuit.wasm] [input.json] [witness.wtns]", + description: "Caclculate specific witness of a circuit given an input", + alias: ["wc", "calculatewitness -ws|wasm:circuit.wasm -i|input:input.json -wt|witness:witness.wtns"], + action: wtnsCalculate + }, + { + cmd: "wtns debug [circuit.wasm] [input.json] [witness.wtns] [circuit.sym]", + description: "Calculate the witness with debug info.", + longDescription: "Calculate the witness with debug info. \nOptions:\n-g or --g : Log signal gets\n-s or --s : Log signal sets\n-t or --trigger : Log triggers ", + options: "-get|g -set|s -trigger|t", + alias: ["wd"], + action: wtnsDebug + }, + { + cmd: "wtns export json [witness.wtns] [witnes.json]", + description: "Calculate the witness with debug info.", + longDescription: "Calculate the witness with debug info. \nOptions:\n-g or --g : Log signal gets\n-s or --s : Log signal sets\n-t or --trigger : Log triggers ", + options: "-verbose|v", + alias: ["wej"], + action: wtnsExportJson + }, + { + cmd: "wtns check [circuit.r1cs] [[witness.wtns]", + description: "Check if a specific witness of a circuit fulfills the r1cs constraints", + alias: ["wchk"], + action: wtnsCheck + }, + { + cmd: "zkey contribute ", + description: "creates a zkey file with a new contribution", + alias: ["zkc"], + options: "-verbose|v -entropy|e -name|n", + action: zkeyContribute + }, + { + cmd: "zkey export bellman [circuit.mpcparams]", + description: "Export a zKey to a MPCParameters file compatible with kobi/phase2 (Bellman)", + alias: ["zkeb"], + options: "-verbose|v", + action: zkeyExportBellman + }, + { + cmd: "zkey bellman contribute ", + description: "contributes to a challenge file in bellman format", + alias: ["zkbc"], + options: "-verbose|v -entropy|e", + action: zkeyBellmanContribute + }, + { + cmd: "zkey import bellman ", + description: "Export a zKey to a MPCParameters file compatible with kobi/phase2 (Bellman) ", + alias: ["zkib"], + options: "-verbose|v -name|n", + action: zkeyImportBellman + }, + { + cmd: "zkey beacon ", + description: "adds a beacon", + alias: ["zkb"], + options: "-verbose|v -name|n", + action: zkeyBeacon + }, + { + cmd: "zkey verify r1cs [circuit.r1cs] [powersoftau.ptau] [circuit_final.zkey]", + description: "Verify zkey file contributions and verify that matches with the original circuit.r1cs and ptau", + alias: [ + "zkv", + "zkvr", + "zkey verify" + ], + options: "-verbose|v", + action: zkeyVerifyFromR1cs + }, + { + cmd: "zkey verify init [circuit_0000.zkey] [powersoftau.ptau] [circuit_final.zkey]", + description: "Verify zkey file contributions and verify that matches with the original circuit.r1cs and ptau", + alias: ["zkvi"], + options: "-verbose|v", + action: zkeyVerifyFromInit + }, + { + cmd: "zkey export verificationkey [circuit_final.zkey] [verification_key.json]", + description: "Exports a verification key", + alias: ["zkev"], + action: zkeyExportVKey + }, + { + cmd: "zkey export json [circuit_final.zkey] [circuit_final.zkey.json]", + description: "Exports a circuit key to a JSON file", + alias: ["zkej"], + options: "-verbose|v", + action: zkeyExportJson + }, + { + cmd: "zkey export solidityverifier [circuit_final.zkey] [verifier.sol]", + description: "Creates a verifier in solidity", + alias: ["zkesv", "generateverifier -vk|verificationkey -v|verifier"], + action: zkeyExportSolidityVerifier + }, + { + cmd: "zkey export soliditycalldata [public.json] [proof.json]", + description: "Generates call parameters ready to be called.", + alias: ["zkesc", "generatecall -pub|public -p|proof"], + action: zkeyExportSolidityCalldata + }, + { + cmd: "groth16 setup [circuit.r1cs] [powersoftau.ptau] [circuit_0000.zkey]", + description: "Creates an initial groth16 pkey file with zero contributions", + alias: [ + "g16s", + "zkn", + "zkey new" + ], + options: "-verbose|v", + action: zkeyNew + }, + { + cmd: "groth16 prove [circuit_final.zkey] [witness.wtns] [proof.json] [public.json]", + description: "Generates a zk Proof from witness", + alias: [ + "g16p", + "zpw", + "zksnark proof", + "proof -pk|provingkey -wt|witness -p|proof -pub|public" + ], + options: "-verbose|v -protocol", + action: groth16Prove + }, + { + cmd: "groth16 fullprove [input.json] [circuit_final.wasm] [circuit_final.zkey] [proof.json] [public.json]", + description: "Generates a zk Proof from input", + alias: ["g16f", "g16i"], + options: "-verbose|v -protocol", + action: groth16FullProve + }, + { + cmd: "groth16 verify [verification_key.json] [public.json] [proof.json]", + description: "Verify a zk Proof", + alias: ["g16v", "verify -vk|verificationkey -pub|public -p|proof"], + action: groth16Verify + }, + { + cmd: "plonk setup [circuit.r1cs] [powersoftau.ptau] [circuit.zkey]", + description: "Creates an initial PLONK pkey ", + alias: ["pks"], + options: "-verbose|v", + action: plonkSetup + }, + { + cmd: "plonk prove [circuit.zkey] [witness.wtns] [proof.json] [public.json]", + description: "Generates a PLONK Proof from witness", + alias: ["pkp"], + options: "-verbose|v -protocol", + action: plonkProve + }, + { + cmd: "plonk fullprove [input.json] [circuit.wasm] [circuit.zkey] [proof.json] [public.json]", + description: "Generates a PLONK Proof from input", + alias: ["pkf"], + options: "-verbose|v -protocol", + action: plonkFullProve + }, + { + cmd: "plonk verify [verification_key.json] [public.json] [proof.json]", + description: "Verify a PLONK Proof", + alias: ["pkv"], + options: "-verbose|v", + action: plonkVerify + }, + { + cmd: "fflonk setup [circuit.r1cs] [powersoftau.ptau] [circuit.zkey]", + description: "BETA version. Creates a FFLONK zkey from a circuit", + alias: ["ffs"], + options: "-verbose|v", + action: fflonkSetup + }, + { + cmd: "fflonk prove [circuit.zkey] [witness.wtns] [proof.json] [public.json]", + description: "BETA version. Generates a FFLONK Proof from witness", + alias: ["ffp"], + options: "-verbose|v -protocol", + action: fflonkProve + }, + { + cmd: "fflonk fullprove [witness.json] [circuit.wasm] [circuit.zkey] [proof.json] [public.json]", + description: "BETA version. Generates a witness and the FFLONK Proof in the same command", + alias: ["fff"], + options: "-verbose|v -protocol", + action: fflonkFullProve + }, + { + cmd: "fflonk verify [verification_key.json] [public.json] [proof.json]", + description: "BETA version. Verify a FFLONK Proof", + alias: ["ffv"], + options: "-verbose|v", + action: fflonkVerify + }, + { + cmd: "file info [binary.file]", + description: "Check info of a binary file", + alias: ["fi"], + action: fileInfo + } +]).then((res) => { + process.exit(res); }, (err) => { - logger.error(err); - process.exit(1); + logger.error(err); + process.exit(1); }); - -/* - -TODO COMMANDS -============= - - { - cmd: "zksnark setup [circuit.r1cs] [circuit.zkey] [verification_key.json]", - description: "Run a simple setup for a circuit generating the proving key.", - alias: ["zs", "setup -r1cs|r -provingkey|pk -verificationkey|vk"], - options: "-verbose|v -protocol", - action: zksnarkSetup - }, - { - cmd: "witness verify ", - description: "Verify a witness against a r1cs", - alias: ["wv"], - action: witnessVerify - }, - { - cmd: "powersOfTau export response" - } -*/ - -// BFJ(Big-Friendly JSON) is pretty heavy module, so we are doing lazy loading for faster startup -let _bfj; +var _bfj; async function getBFJ() { - if (_bfj) return _bfj; - const {default: bfj} = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('bfj')); }); - _bfj = bfj; - return _bfj; + if (_bfj) return _bfj; + const { default: bfj } = await Promise.resolve().then(() => /* @__PURE__ */ __toESM(require_src(), 1)); + _bfj = bfj; + return _bfj; } - function changeExt(fileName, newExt) { - let S = fileName; - while ((S.length > 0) && (S[S.length - 1] != ".")) S = S.slice(0, S.length - 1); - if (S.length > 0) { - return S + newExt; - } else { - return fileName + "." + newExt; - } -} - -// r1cs export circomJSON [circuit.r1cs] [circuit.json] + let S = fileName; + while (S.length > 0 && S[S.length - 1] != ".") S = S.slice(0, S.length - 1); + if (S.length > 0) return S + newExt; + else return fileName + "." + newExt; +} async function r1csInfo(params, options) { - const r1csName = params[0] || "circuit.r1cs"; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - await r1csInfo$1(r1csName, logger); - - - return 0; -} - -// r1cs print [circuit.r1cs] [circuit.sym] + const r1csName = params[0] || "circuit.r1cs"; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + await r1csInfo$1(r1csName, logger); + return 0; +} async function r1csPrint(params, options) { - const r1csName = params[0] || "circuit.r1cs"; - const symName = params[1] || changeExt(r1csName, "sym"); - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const cir = await r1csfile.readR1cs(r1csName, true, true, false); - - const sym = await loadSymbols(symName); - - await r1csPrint$1(cir, sym, logger); - - return 0; -} - - -// r1cs export json [circuit.r1cs] [circuit.json] + const r1csName = params[0] || "circuit.r1cs"; + const symName = params[1] || changeExt(r1csName, "sym"); + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + await r1csPrint$1(await (0, r1csfile.readR1cs)(r1csName, true, true, false), await loadSymbols(symName), logger); + return 0; +} async function r1csExportJSON(params, options) { - const r1csName = params[0] || "circuit.r1cs"; - const jsonName = params[1] || changeExt(r1csName, "json"); - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const r1csObj = await r1csExportJson(r1csName, logger); - - const bfj = await getBFJ(); - await bfj.write(jsonName, r1csObj, {space: 1}); - - return 0; -} - -// wtns calculate + const r1csName = params[0] || "circuit.r1cs"; + const jsonName = params[1] || changeExt(r1csName, "json"); + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + const r1csObj = await r1csExportJson(r1csName, logger); + await (await getBFJ()).write(jsonName, r1csObj, { space: 1 }); + return 0; +} async function wtnsCalculate(params, options) { - const wasmName = params[0] || "circuit.wasm"; - const inputName = params[1] || "input.json"; - const witnessName = params[2] || "witness.wtns"; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const input = JSON.parse(await fs__default["default"].promises.readFile(inputName, "utf8")); - - await wtnsCalculate$1(input, wasmName, witnessName, {}); - - return 0; -} - - -// wtns debug -// -get|g -set|s -trigger|t + const wasmName = params[0] || "circuit.wasm"; + const inputName = params[1] || "input.json"; + const witnessName = params[2] || "witness.wtns"; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + await wtnsCalculate$1(JSON.parse(await fs.default.promises.readFile(inputName, "utf8")), wasmName, witnessName, {}); + return 0; +} async function wtnsDebug(params, options) { - const wasmName = params[0] || "circuit.wasm"; - const inputName = params[1] || "input.json"; - const witnessName = params[2] || "witness.wtns"; - const symName = params[3] || changeExt(wasmName, "sym"); - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const input = JSON.parse(await fs__default["default"].promises.readFile(inputName, "utf8")); - - await wtnsDebug$1(input, wasmName, witnessName, symName, options, logger); - - return 0; -} - - -// wtns export json [witness.wtns] [witness.json] -// -get|g -set|s -trigger|t + const wasmName = params[0] || "circuit.wasm"; + const inputName = params[1] || "input.json"; + const witnessName = params[2] || "witness.wtns"; + const symName = params[3] || changeExt(wasmName, "sym"); + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + await wtnsDebug$1(JSON.parse(await fs.default.promises.readFile(inputName, "utf8")), wasmName, witnessName, symName, options, logger); + return 0; +} async function wtnsExportJson(params, options) { - const wtnsName = params[0] || "witness.wtns"; - const jsonName = params[1] || "witness.json"; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const w = await wtnsExportJson$1(wtnsName); - - const bfj = await getBFJ(); - await bfj.write(jsonName, stringifyBigInts(w), {space: 1}); - - return 0; -} - -// wtns export json [witness.wtns] [witness.json] -// -get|g -set|s -trigger|t + const wtnsName = params[0] || "witness.wtns"; + const jsonName = params[1] || "witness.json"; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + const w = await wtnsExportJson$1(wtnsName); + await (await getBFJ()).write(jsonName, stringifyBigInts(w), { space: 1 }); + return 0; +} async function wtnsCheck(params, options) { - const r1csFilename = params[0] || "circuit.r1cs"; - const wtnsFilename = params[1] || "witness.wtns"; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const isValid = await wtnsCheck$1(r1csFilename, wtnsFilename, logger); - - if (isValid) { - return 0; - } else { - return 1; - } -} - - -/* -// zksnark setup [circuit.r1cs] [circuit.zkey] [verification_key.json] -async function zksnarkSetup(params, options) { - - const r1csName = params[0] || "circuit.r1cs"; - const zkeyName = params[1] || changeExt(r1csName, "zkey"); - const verificationKeyName = params[2] || "verification_key.json"; - - const protocol = options.protocol || "groth16"; - - const cir = await readR1cs(r1csName, true); - - if (!zkSnark[protocol]) throw new Error("Invalid protocol"); - const setup = zkSnark[protocol].setup(cir, options.verbose); - - await zkey.utils.write(zkeyName, setup.vk_proof); - await bfj.write(provingKeyName, stringifyBigInts(setup.vk_proof), { space: 1 }); - - await bfj.write(verificationKeyName, stringifyBigInts(setup.vk_verifier), { space: 1 }); - - return 0; + const r1csFilename = params[0] || "circuit.r1cs"; + const wtnsFilename = params[1] || "witness.wtns"; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + if (await wtnsCheck$1(r1csFilename, wtnsFilename, logger)) return 0; + else return 1; } -*/ - -// groth16 prove [circuit.zkey] [witness.wtns] [proof.json] [public.json] async function groth16Prove(params, options) { - - const zkeyName = params[0] || "circuit_final.zkey"; - const witnessName = params[1] || "witness.wtns"; - const proofName = params[2] || "proof.json"; - const publicName = params[3] || "public.json"; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const {proof, publicSignals} = await groth16Prove$1(zkeyName, witnessName, logger); - - fs__default["default"].writeFileSync(proofName, JSON.stringify(stringifyBigInts(proof), null, 1)); - fs__default["default"].writeFileSync(publicName, JSON.stringify(stringifyBigInts(publicSignals), null, 1)); - - return 0; -} - -// groth16 fullprove [input.json] [circuit.wasm] [circuit.zkey] [proof.json] [public.json] + const zkeyName = params[0] || "circuit_final.zkey"; + const witnessName = params[1] || "witness.wtns"; + const proofName = params[2] || "proof.json"; + const publicName = params[3] || "public.json"; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + const { proof, publicSignals } = await groth16Prove$1(zkeyName, witnessName, logger); + fs.default.writeFileSync(proofName, JSON.stringify(stringifyBigInts(proof), null, 1)); + fs.default.writeFileSync(publicName, JSON.stringify(stringifyBigInts(publicSignals), null, 1)); + return 0; +} async function groth16FullProve(params, options) { - - const inputName = params[0] || "input.json"; - const wasmName = params[1] || "circuit.wasm"; - const zkeyName = params[2] || "circuit_final.zkey"; - const proofName = params[3] || "proof.json"; - const publicName = params[4] || "public.json"; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const input = JSON.parse(await fs__default["default"].promises.readFile(inputName, "utf8")); - - const {proof, publicSignals} = await groth16FullProve$1(input, wasmName, zkeyName, logger); - - fs__default["default"].writeFileSync(proofName, JSON.stringify(stringifyBigInts(proof), null, 1)); - fs__default["default"].writeFileSync(publicName, JSON.stringify(stringifyBigInts(publicSignals), null, 1)); - - return 0; -} - -// groth16 verify [verification_key.json] [public.json] [proof.json] + const inputName = params[0] || "input.json"; + const wasmName = params[1] || "circuit.wasm"; + const zkeyName = params[2] || "circuit_final.zkey"; + const proofName = params[3] || "proof.json"; + const publicName = params[4] || "public.json"; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + const { proof, publicSignals } = await groth16FullProve$1(JSON.parse(await fs.default.promises.readFile(inputName, "utf8")), wasmName, zkeyName, logger); + fs.default.writeFileSync(proofName, JSON.stringify(stringifyBigInts(proof), null, 1)); + fs.default.writeFileSync(publicName, JSON.stringify(stringifyBigInts(publicSignals), null, 1)); + return 0; +} async function groth16Verify(params, options) { - - const verificationKeyName = params[0] || "verification_key.json"; - const publicName = params[1] || "public.json"; - const proofName = params[2] || "proof.json"; - - const verificationKey = JSON.parse(fs__default["default"].readFileSync(verificationKeyName, "utf8")); - const pub = JSON.parse(fs__default["default"].readFileSync(publicName, "utf8")); - const proof = JSON.parse(fs__default["default"].readFileSync(proofName, "utf8")); - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const isValid = await groth16Verify$1(verificationKey, pub, proof, logger); - - if (isValid) { - return 0; - } else { - return 1; - } -} - -// zkey export vkey [circuit_final.zkey] [verification_key.json]", + const verificationKeyName = params[0] || "verification_key.json"; + const publicName = params[1] || "public.json"; + const proofName = params[2] || "proof.json"; + const verificationKey = JSON.parse(fs.default.readFileSync(verificationKeyName, "utf8")); + const pub = JSON.parse(fs.default.readFileSync(publicName, "utf8")); + const proof = JSON.parse(fs.default.readFileSync(proofName, "utf8")); + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + if (await groth16Verify$1(verificationKey, pub, proof, logger)) return 0; + else return 1; +} async function zkeyExportVKey(params, options) { - const zKeyFileName = params[0] || "circuit_final.zkey"; - const vKeyFilename = params[1] || "circuit_vk.json"; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const vKey = await zkeyExportVerificationKey(zKeyFileName, logger); - - const bfj = await getBFJ(); - await bfj.write(vKeyFilename, stringifyBigInts(vKey), {space: 1}); - - return 0; -} - -// zkey export json [circuit_final.zkey] [circuit.zkey.json]", + const zKeyFileName = params[0] || "circuit_final.zkey"; + const vKeyFilename = params[1] || "circuit_vk.json"; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + const vKey = await zkeyExportVerificationKey(zKeyFileName, logger); + await (await getBFJ()).write(vKeyFilename, stringifyBigInts(vKey), { space: 1 }); + return 0; +} async function zkeyExportJson(params, options) { - const zkeyName = params[0] || "circuit_final.zkey"; - const zkeyJsonName = params[1] || "circuit_final.zkey.json"; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const zKeyJson = await zkeyExportJson$1(zkeyName); - - const bfj = await getBFJ(); - await bfj.write(zkeyJsonName, zKeyJson, {space: 1}); -} - + const zkeyName = params[0] || "circuit_final.zkey"; + const zkeyJsonName = params[1] || "circuit_final.zkey.json"; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + const zKeyJson = await zkeyExportJson$1(zkeyName, logger); + await (await getBFJ()).write(zkeyJsonName, zKeyJson, { space: 1 }); +} async function fileExists(file) { - return fs__default["default"].promises.access(file, fs__default["default"].constants.F_OK) - .then(() => true) - .catch(() => false); + return fs.default.promises.access(file, fs.default.constants.F_OK).then(() => true).catch(() => false); } - -// solidity genverifier [circuit_final.zkey] [verifier.sol] async function zkeyExportSolidityVerifier(params, options) { - let zkeyName; - let verifierName; - - if (params.length < 1) { - zkeyName = "circuit_final.zkey"; - } else { - zkeyName = params[0]; - } - - if (params.length < 2) { - verifierName = "verifier.sol"; - } else { - verifierName = params[1]; - } - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const templates = {}; - - if (await fileExists(path__default["default"].join(__dirname$1, "templates"))) { - templates.groth16 = await fs__default["default"].promises.readFile(path__default["default"].join(__dirname$1, "templates", "verifier_groth16.sol.ejs"), "utf8"); - templates.plonk = await fs__default["default"].promises.readFile(path__default["default"].join(__dirname$1, "templates", "verifier_plonk.sol.ejs"), "utf8"); - templates.fflonk = await fs__default["default"].promises.readFile(path__default["default"].join(__dirname$1, "templates", "verifier_fflonk.sol.ejs"), "utf8"); - } else { - templates.groth16 = await fs__default["default"].promises.readFile(path__default["default"].join(__dirname$1, "..", "templates", "verifier_groth16.sol.ejs"), "utf8"); - templates.plonk = await fs__default["default"].promises.readFile(path__default["default"].join(__dirname$1, "..", "templates", "verifier_plonk.sol.ejs"), "utf8"); - templates.fflonk = await fs__default["default"].promises.readFile(path__default["default"].join(__dirname$1, "..", "templates", "verifier_fflonk.sol.ejs"), "utf8"); - } - - const verifierCode = await exportSolidityVerifier(zkeyName, templates, logger); - - fs__default["default"].writeFileSync(verifierName, verifierCode, "utf-8"); - - return 0; -} - - -// solidity gencall + let zkeyName; + let verifierName; + if (params.length < 1) zkeyName = "circuit_final.zkey"; + else zkeyName = params[0]; + if (params.length < 2) verifierName = "verifier.sol"; + else verifierName = params[1]; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + const templates = {}; + if (await fileExists(path.default.join(__dirname$1, "templates"))) { + templates.groth16 = await fs.default.promises.readFile(path.default.join(__dirname$1, "templates", "verifier_groth16.sol.ejs"), "utf8"); + templates.plonk = await fs.default.promises.readFile(path.default.join(__dirname$1, "templates", "verifier_plonk.sol.ejs"), "utf8"); + templates.fflonk = await fs.default.promises.readFile(path.default.join(__dirname$1, "templates", "verifier_fflonk.sol.ejs"), "utf8"); + } else { + templates.groth16 = await fs.default.promises.readFile(path.default.join(__dirname$1, "..", "templates", "verifier_groth16.sol.ejs"), "utf8"); + templates.plonk = await fs.default.promises.readFile(path.default.join(__dirname$1, "..", "templates", "verifier_plonk.sol.ejs"), "utf8"); + templates.fflonk = await fs.default.promises.readFile(path.default.join(__dirname$1, "..", "templates", "verifier_fflonk.sol.ejs"), "utf8"); + } + const verifierCode = await exportSolidityVerifier(zkeyName, templates, logger); + fs.default.writeFileSync(verifierName, verifierCode, "utf-8"); + return 0; +} async function zkeyExportSolidityCalldata(params, options) { - let publicName; - let proofName; - - if (params.length < 1) { - publicName = "public.json"; - } else { - publicName = params[0]; - } - - if (params.length < 2) { - proofName = "proof.json"; - } else { - proofName = params[1]; - } - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const pub = JSON.parse(fs__default["default"].readFileSync(publicName, "utf8")); - const proof = JSON.parse(fs__default["default"].readFileSync(proofName, "utf8")); - - let res; - if (proof.protocol == "groth16") { - res = await groth16ExportSolidityCallData(proof, pub); - } else if (proof.protocol == "plonk") { - res = await plonkExportSolidityCallData(proof, pub); - } else if (proof.protocol === "fflonk") { - res = await fflonkExportCallData(pub, proof); - } else { - throw new Error("Invalid Protocol"); - } - console.log(res); - - return 0; -} - -// powersoftau new [powersoftau_0000.ptau]", + let publicName; + let proofName; + if (params.length < 1) publicName = "public.json"; + else publicName = params[0]; + if (params.length < 2) proofName = "proof.json"; + else proofName = params[1]; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + const pub = JSON.parse(fs.default.readFileSync(publicName, "utf8")); + const proof = JSON.parse(fs.default.readFileSync(proofName, "utf8")); + let res; + if (proof.protocol == "groth16") res = await groth16ExportSolidityCallData(proof, pub); + else if (proof.protocol == "plonk") res = await plonkExportSolidityCallData(proof, pub); + else if (proof.protocol === "fflonk") res = await fflonkExportCallData(pub, proof); + else throw new Error("Invalid Protocol"); + console.log(res); + return 0; +} async function powersOfTauNew(params, options) { - let curveName; - let power; - let ptauName; - - curveName = params[0]; - - power = parseInt(params[1]); - if ((power<1) || (power>28) || isNaN(power)) { - throw new Error("Power must be between 1 and 28"); - } - - if (params.length < 3) { - ptauName = "powersOfTau" + power + "_0000.ptau"; - } else { - ptauName = params[2]; - } - - const curve = await getCurveFromName(curveName); - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - // Discard firstChallengeHash - await newAccumulator(curve, power, ptauName, logger); - - return 0; -} - + let curveName; + let power; + let ptauName; + curveName = params[0]; + power = parseInt(params[1]); + if (power < 1 || power > 28 || isNaN(power)) throw new Error("Power must be between 1 and 28"); + if (params.length < 3) ptauName = "powersOfTau" + power + "_0000.ptau"; + else ptauName = params[2]; + const curve = await getCurveFromName(curveName); + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + await newAccumulator(curve, power, ptauName, logger); + return 0; +} async function powersOfTauExportChallenge(params, options) { - let ptauName; - let challengeName; - - ptauName = params[0]; - - if (params.length < 2) { - challengeName = "challenge"; - } else { - challengeName = params[1]; - } - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - // Discard curChallengeHash - await exportChallenge(ptauName, challengeName, logger); - - return 0; -} - -// powersoftau challenge contribute [response] + let ptauName; + let challengeName; + ptauName = params[0]; + if (params.length < 2) challengeName = "challenge"; + else challengeName = params[1]; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + await exportChallenge(ptauName, challengeName, logger); + return 0; +} async function powersOfTauChallengeContribute(params, options) { - let challengeName; - let responseName; - - const curve = await getCurveFromName(params[0]); - - challengeName = params[1]; - - if (params.length < 3) { - responseName = changeExt(challengeName, "response"); - } else { - responseName = params[2]; - } - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - await challengeContribute(curve, challengeName, responseName, options.entropy, logger); - - return 0; -} - - + let challengeName; + let responseName; + const curve = await getCurveFromName(params[0]); + challengeName = params[1]; + if (params.length < 3) responseName = changeExt(challengeName, "response"); + else responseName = params[2]; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + await challengeContribute(curve, challengeName, responseName, options.entropy, logger); + return 0; +} async function powersOfTauImport(params, options) { - let oldPtauName; - let response; - let newPtauName; - let importPoints = true; - let doCheck = true; - - oldPtauName = params[0]; - response = params[1]; - newPtauName = params[2]; - - if (options.nopoints) importPoints = false; - if (options.nocheck) doCheck = false; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const nextChallenge = await importResponse(oldPtauName, response, newPtauName, options.name, importPoints, logger); - - if (nextChallenge) return 0; - if (!doCheck) return 0; - - // TODO Verify -} - + let oldPtauName; + let response; + let newPtauName; + let importPoints = true; + let doCheck = true; + oldPtauName = params[0]; + response = params[1]; + newPtauName = params[2]; + if (options.nopoints) importPoints = false; + if (options.nocheck) doCheck = false; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + if (await importResponse(oldPtauName, response, newPtauName, options.name, importPoints, logger)) return 0; + if (!doCheck) return 0; +} async function powersOfTauVerify(params, options) { - let ptauName; - - ptauName = params[0]; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const res = await verify(ptauName, logger); - if (res === true) { - return 0; - } else { - return 1; - } -} - + let ptauName; + ptauName = params[0]; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + if (await verify(ptauName, logger) === true) return 0; + else return 1; +} async function powersOfTauBeacon(params, options) { - let oldPtauName; - let newPtauName; - let beaconHashStr; - let numIterationsExp; - - oldPtauName = params[0]; - newPtauName = params[1]; - beaconHashStr = params[2]; - numIterationsExp = params[3]; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - // Discard hashResponse - await beacon$1(oldPtauName, newPtauName, options.name, beaconHashStr, numIterationsExp, logger); - - return 0; -} - + let oldPtauName; + let newPtauName; + let beaconHashStr; + let numIterationsExp; + oldPtauName = params[0]; + newPtauName = params[1]; + beaconHashStr = params[2]; + numIterationsExp = params[3]; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + await beacon$1(oldPtauName, newPtauName, options.name, beaconHashStr, numIterationsExp, logger); + return 0; +} async function powersOfTauContribute(params, options) { - let oldPtauName; - let newPtauName; - - oldPtauName = params[0]; - newPtauName = params[1]; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - // Discard hashResponse - await contribute(oldPtauName, newPtauName, options.name, options.entropy, logger); - - return 0; -} - + let oldPtauName; + let newPtauName; + oldPtauName = params[0]; + newPtauName = params[1]; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + await contribute(oldPtauName, newPtauName, options.name, options.entropy, logger); + return 0; +} async function powersOfTauPreparePhase2(params, options) { - let oldPtauName; - let newPtauName; - - oldPtauName = params[0]; - newPtauName = params[1]; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - await preparePhase2(oldPtauName, newPtauName, logger); - - return 0; -} - + let oldPtauName; + let newPtauName; + oldPtauName = params[0]; + newPtauName = params[1]; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + await preparePhase2(oldPtauName, newPtauName, logger); + return 0; +} async function powersOfTauConvert(params, options) { - let oldPtauName; - let newPtauName; - - oldPtauName = params[0]; - newPtauName = params[1]; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - await convert(oldPtauName, newPtauName, logger); - - return 0; -} - - + let oldPtauName; + let newPtauName; + oldPtauName = params[0]; + newPtauName = params[1]; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + await convert(oldPtauName, newPtauName, logger); + return 0; +} async function powersOfTauTruncate(params, options) { - let ptauName; - - ptauName = params[0]; - - let template = ptauName; - while ((template.length > 0) && (template[template.length - 1] != ".")) template = template.slice(0, template.length - 1); - template = template.slice(0, template.length - 1); - template = template + "_"; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - // Discard `true` - await truncate(ptauName, template, logger); - - return 0; -} - -// powersoftau export json ", + let ptauName; + ptauName = params[0]; + let template = ptauName; + while (template.length > 0 && template[template.length - 1] != ".") template = template.slice(0, template.length - 1); + template = template.slice(0, template.length - 1); + template = template + "_"; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + await truncate(ptauName, template, logger); + return 0; +} async function powersOfTauExportJson(params, options) { - let ptauName; - let jsonName; - - ptauName = params[0]; - jsonName = params[1]; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const pTauJson = await exportJson(ptauName, logger); - - const bfj = await getBFJ(); - await bfj.write(jsonName, pTauJson, {space: 1}); -} - - -// phase2 new + let ptauName; + let jsonName; + ptauName = params[0]; + jsonName = params[1]; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + const pTauJson = await exportJson(ptauName, logger); + await (await getBFJ()).write(jsonName, pTauJson, { space: 1 }); +} async function zkeyNew(params, options) { - let r1csName; - let ptauName; - let zkeyName; - - if (params.length < 1) { - r1csName = "circuit.r1cs"; - } else { - r1csName = params[0]; - } - - if (params.length < 2) { - ptauName = "powersoftau.ptau"; - } else { - ptauName = params[1]; - } - - if (params.length < 3) { - zkeyName = "circuit_0000.zkey"; - } else { - zkeyName = params[2]; - } - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - // Discard csHash - await newZKey(r1csName, ptauName, zkeyName, logger); - - return 0; -} - -// zkey export bellman [circuit_0000.zkey] [circuit.mpcparams] + let r1csName; + let ptauName; + let zkeyName; + if (params.length < 1) r1csName = "circuit.r1cs"; + else r1csName = params[0]; + if (params.length < 2) ptauName = "powersoftau.ptau"; + else ptauName = params[1]; + if (params.length < 3) zkeyName = "circuit_0000.zkey"; + else zkeyName = params[2]; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + await newZKey(r1csName, ptauName, zkeyName, logger); + return 0; +} async function zkeyExportBellman(params, options) { - let zkeyName; - let mpcparamsName; - - zkeyName = params[0]; - - if (params.length < 2) { - mpcparamsName = "circuit.mpcparams"; - } else { - mpcparamsName = params[1]; - } - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - await phase2exportMPCParams(zkeyName, mpcparamsName, logger); - - return 0; -} - - -// zkey import bellman + let zkeyName; + let mpcparamsName; + zkeyName = params[0]; + if (params.length < 2) mpcparamsName = "circuit.mpcparams"; + else mpcparamsName = params[1]; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + await phase2exportMPCParams(zkeyName, mpcparamsName, logger); + return 0; +} async function zkeyImportBellman(params, options) { - let zkeyNameOld; - let mpcParamsName; - let zkeyNameNew; - - zkeyNameOld = params[0]; - mpcParamsName = params[1]; - zkeyNameNew = params[2]; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const isValid = await phase2importMPCParams(zkeyNameOld, mpcParamsName, zkeyNameNew, options.name, logger); - if (isValid) { - return 0; - } else { - return 1; - } -} - -// phase2 verify r1cs [circuit.r1cs] [powersoftau.ptau] [circuit_final.zkey] + let zkeyNameOld; + let mpcParamsName; + let zkeyNameNew; + zkeyNameOld = params[0]; + mpcParamsName = params[1]; + zkeyNameNew = params[2]; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + if (await phase2importMPCParams(zkeyNameOld, mpcParamsName, zkeyNameNew, options.name, logger)) return 0; + else return 1; +} async function zkeyVerifyFromR1cs(params, options) { - let r1csName; - let ptauName; - let zkeyName; - - if (params.length < 1) { - r1csName = "circuit.r1cs"; - } else { - r1csName = params[0]; - } - - if (params.length < 2) { - ptauName = "powersoftau.ptau"; - } else { - ptauName = params[1]; - } - - if (params.length < 3) { - zkeyName = "circuit_final.zkey"; - } else { - zkeyName = params[2]; - } - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const res = await phase2verifyFromR1cs(r1csName, ptauName, zkeyName, logger); - if (res === true) { - return 0; - } else { - return 1; - } - -} - -// phase2 verify [circuit_0000] [powersoftau.ptau] [circuit_final.zkey] + let r1csName; + let ptauName; + let zkeyName; + if (params.length < 1) r1csName = "circuit.r1cs"; + else r1csName = params[0]; + if (params.length < 2) ptauName = "powersoftau.ptau"; + else ptauName = params[1]; + if (params.length < 3) zkeyName = "circuit_final.zkey"; + else zkeyName = params[2]; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + if (await phase2verifyFromR1cs(r1csName, ptauName, zkeyName, logger) === true) return 0; + else return 1; +} async function zkeyVerifyFromInit(params, options) { - let initZKeyName; - let ptauName; - let zkeyName; - - if (params.length < 1) { - initZKeyName = "circuit_0000.zkey"; - } else { - initZKeyName = params[0]; - } - - if (params.length < 2) { - ptauName = "powersoftau.ptau"; - } else { - ptauName = params[1]; - } - - if (params.length < 3) { - zkeyName = "circuit_final.zkey"; - } else { - zkeyName = params[2]; - } - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const res = await phase2verifyFromInit(initZKeyName, ptauName, zkeyName, logger); - if (res === true) { - return 0; - } else { - return 1; - } -} - -// zkey contribute + let initZKeyName; + let ptauName; + let zkeyName; + if (params.length < 1) initZKeyName = "circuit_0000.zkey"; + else initZKeyName = params[0]; + if (params.length < 2) ptauName = "powersoftau.ptau"; + else ptauName = params[1]; + if (params.length < 3) zkeyName = "circuit_final.zkey"; + else zkeyName = params[2]; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + if (await phase2verifyFromInit(initZKeyName, ptauName, zkeyName, logger) === true) return 0; + else return 1; +} async function zkeyContribute(params, options) { - let zkeyOldName; - let zkeyNewName; - - zkeyOldName = params[0]; - zkeyNewName = params[1]; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - // Discard contribuionHash - await phase2contribute(zkeyOldName, zkeyNewName, options.name, options.entropy, logger); - - return 0; -} - -// zkey beacon + let zkeyOldName; + let zkeyNewName; + zkeyOldName = params[0]; + zkeyNewName = params[1]; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + await phase2contribute(zkeyOldName, zkeyNewName, options.name, options.entropy, logger); + return 0; +} async function zkeyBeacon(params, options) { - let zkeyOldName; - let zkeyNewName; - let beaconHashStr; - let numIterationsExp; - - zkeyOldName = params[0]; - zkeyNewName = params[1]; - beaconHashStr = params[2]; - numIterationsExp = params[3]; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - // Discard contribuionHash - await beacon(zkeyOldName, zkeyNewName, options.name, beaconHashStr, numIterationsExp, logger); - - return 0; -} - - -// zkey challenge contribute [response]", + let zkeyOldName; + let zkeyNewName; + let beaconHashStr; + let numIterationsExp; + zkeyOldName = params[0]; + zkeyNewName = params[1]; + beaconHashStr = params[2]; + numIterationsExp = params[3]; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + await beacon(zkeyOldName, zkeyNewName, options.name, beaconHashStr, numIterationsExp, logger); + return 0; +} async function zkeyBellmanContribute(params, options) { - let challengeName; - let responseName; - - const curve = await getCurveFromName(params[0]); - - challengeName = params[1]; - - if (params.length < 3) { - responseName = changeExt(challengeName, "response"); - } else { - responseName = params[2]; - } - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - // Discard contributionHash - await bellmanContribute(curve, challengeName, responseName, options.entropy, logger); - - return 0; -} - - -// plonk setup + let challengeName; + let responseName; + const curve = await getCurveFromName(params[0]); + challengeName = params[1]; + if (params.length < 3) responseName = changeExt(challengeName, "response"); + else responseName = params[2]; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + await bellmanContribute(curve, challengeName, responseName, options.entropy, logger); + return 0; +} async function plonkSetup(params, options) { - let r1csName; - let ptauName; - let zkeyName; - - if (params.length < 1) { - r1csName = "circuit.r1cs"; - } else { - r1csName = params[0]; - } - - if (params.length < 2) { - ptauName = "powersoftau.ptau"; - } else { - ptauName = params[1]; - } - - if (params.length < 3) { - zkeyName = "circuit.zkey"; - } else { - zkeyName = params[2]; - } - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - // TODO: Make plonk.setup reject instead of returning -1 or null - return plonkSetup$1(r1csName, ptauName, zkeyName, logger); -} - - -// plonk prove [circuit.zkey] [witness.wtns] [proof.json] [public.json] + let r1csName; + let ptauName; + let zkeyName; + if (params.length < 1) r1csName = "circuit.r1cs"; + else r1csName = params[0]; + if (params.length < 2) ptauName = "powersoftau.ptau"; + else ptauName = params[1]; + if (params.length < 3) zkeyName = "circuit.zkey"; + else zkeyName = params[2]; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + return plonkSetup$1(r1csName, ptauName, zkeyName, logger); +} async function plonkProve(params, options) { - - const zkeyName = params[0] || "circuit.zkey"; - const witnessName = params[1] || "witness.wtns"; - const proofName = params[2] || "proof.json"; - const publicName = params[3] || "public.json"; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const {proof, publicSignals} = await plonk16Prove(zkeyName, witnessName, logger); - - const bfj = await getBFJ(); - await bfj.write(proofName, stringifyBigInts(proof), {space: 1}); - await bfj.write(publicName, stringifyBigInts(publicSignals), {space: 1}); - - return 0; -} - - -// plonk fullprove [input.json] [circuit.wasm] [circuit.zkey] [proof.json] [public.json] + const zkeyName = params[0] || "circuit.zkey"; + const witnessName = params[1] || "witness.wtns"; + const proofName = params[2] || "proof.json"; + const publicName = params[3] || "public.json"; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + const { proof, publicSignals } = await plonk16Prove(zkeyName, witnessName, logger); + const bfj = await getBFJ(); + await bfj.write(proofName, stringifyBigInts(proof), { space: 1 }); + await bfj.write(publicName, stringifyBigInts(publicSignals), { space: 1 }); + return 0; +} async function plonkFullProve(params, options) { - - const inputName = params[0] || "input.json"; - const wasmName = params[1] || "circuit.wasm"; - const zkeyName = params[2] || "circuit.zkey"; - const proofName = params[3] || "proof.json"; - const publicName = params[4] || "public.json"; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const input = JSON.parse(await fs__default["default"].promises.readFile(inputName, "utf8")); - - const {proof, publicSignals} = await plonkFullProve$1(input, wasmName, zkeyName, logger); - - const bfj = await getBFJ(); - await bfj.write(proofName, stringifyBigInts(proof), {space: 1}); - await bfj.write(publicName, stringifyBigInts(publicSignals), {space: 1}); - - return 0; -} - - -// plonk verify [verification_key.json] [public.json] [proof.json] + const inputName = params[0] || "input.json"; + const wasmName = params[1] || "circuit.wasm"; + const zkeyName = params[2] || "circuit.zkey"; + const proofName = params[3] || "proof.json"; + const publicName = params[4] || "public.json"; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + const { proof, publicSignals } = await plonkFullProve$1(JSON.parse(await fs.default.promises.readFile(inputName, "utf8")), wasmName, zkeyName, logger); + const bfj = await getBFJ(); + await bfj.write(proofName, stringifyBigInts(proof), { space: 1 }); + await bfj.write(publicName, stringifyBigInts(publicSignals), { space: 1 }); + return 0; +} async function plonkVerify(params, options) { - - const verificationKeyName = params[0] || "verification_key.json"; - const publicName = params[1] || "public.json"; - const proofName = params[2] || "proof.json"; - - const verificationKey = JSON.parse(fs__default["default"].readFileSync(verificationKeyName, "utf8")); - const pub = JSON.parse(fs__default["default"].readFileSync(publicName, "utf8")); - const proof = JSON.parse(fs__default["default"].readFileSync(proofName, "utf8")); - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const isValid = await plonkVerify$1(verificationKey, pub, proof, logger); - - if (isValid) { - return 0; - } else { - return 1; - } -} - + const verificationKeyName = params[0] || "verification_key.json"; + const publicName = params[1] || "public.json"; + const proofName = params[2] || "proof.json"; + const verificationKey = JSON.parse(fs.default.readFileSync(verificationKeyName, "utf8")); + const pub = JSON.parse(fs.default.readFileSync(publicName, "utf8")); + const proof = JSON.parse(fs.default.readFileSync(proofName, "utf8")); + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + if (await plonkVerify$1(verificationKey, pub, proof, logger)) return 0; + else return 1; +} async function fflonkSetup(params, options) { - const r1csFilename = params[0] || "circuit.r1cs"; - const ptauFilename = params[1] || "powersoftau.ptau"; - const zkeyFilename = params[2] || "circuit.zkey"; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - // TODO: Make fflonk.setup return valuable information or nothing at all - return await fflonkSetup$1(r1csFilename, ptauFilename, zkeyFilename, logger); -} - - + const r1csFilename = params[0] || "circuit.r1cs"; + const ptauFilename = params[1] || "powersoftau.ptau"; + const zkeyFilename = params[2] || "circuit.zkey"; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + return await fflonkSetup$1(r1csFilename, ptauFilename, zkeyFilename, logger); +} async function fflonkProve(params, options) { - const zkeyFilename = params[0] || "circuit.zkey"; - const witnessFilename = params[1] || "witness.wtns"; - const proofFilename = params[2] || "proof.json"; - const publicInputsFilename = params[3] || "public.json"; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const {proof, publicSignals} = await fflonkProve$1(zkeyFilename, witnessFilename, logger); - - if(undefined !== proofFilename && undefined !== publicInputsFilename) { - const bfj = await getBFJ(); - // Write the proof and the public signals in each file - await bfj.write(proofFilename, stringifyBigInts(proof), {space: 1}); - await bfj.write(publicInputsFilename, stringifyBigInts(publicSignals), {space: 1}); - } - - return 0; -} - + const zkeyFilename = params[0] || "circuit.zkey"; + const witnessFilename = params[1] || "witness.wtns"; + const proofFilename = params[2] || "proof.json"; + const publicInputsFilename = params[3] || "public.json"; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + const { proof, publicSignals } = await fflonkProve$1(zkeyFilename, witnessFilename, logger); + if (void 0 !== proofFilename && void 0 !== publicInputsFilename) { + const bfj = await getBFJ(); + await bfj.write(proofFilename, stringifyBigInts(proof), { space: 1 }); + await bfj.write(publicInputsFilename, stringifyBigInts(publicSignals), { space: 1 }); + } + return 0; +} async function fflonkFullProve(params, options) { - - const witnessInputsFilename = params[0] || "witness.json"; - const wasmFilename = params[1] || "circuit.wasm"; - const zkeyFilename = params[2] || "circuit.zkey"; - const proofFilename = params[3] || "proof.json"; - const publicInputsFilename = params[4] || "public.json"; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const input = JSON.parse(await fs__default["default"].promises.readFile(witnessInputsFilename, "utf8")); - - const {proof, publicSignals} = await fflonkFullProve$1(input, wasmFilename, zkeyFilename, logger); - - const bfj = await getBFJ(); - // Write the proof and the public signals in each file - await bfj.write(proofFilename, stringifyBigInts(proof), {space: 1}); - await bfj.write(publicInputsFilename, stringifyBigInts(publicSignals), {space: 1}); - - return 0; -} - + const witnessInputsFilename = params[0] || "witness.json"; + const wasmFilename = params[1] || "circuit.wasm"; + const zkeyFilename = params[2] || "circuit.zkey"; + const proofFilename = params[3] || "proof.json"; + const publicInputsFilename = params[4] || "public.json"; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + const { proof, publicSignals } = await fflonkFullProve$1(JSON.parse(await fs.default.promises.readFile(witnessInputsFilename, "utf8")), wasmFilename, zkeyFilename, logger); + const bfj = await getBFJ(); + await bfj.write(proofFilename, stringifyBigInts(proof), { space: 1 }); + await bfj.write(publicInputsFilename, stringifyBigInts(publicSignals), { space: 1 }); + return 0; +} async function fflonkVerify(params, options) { - const vkeyFilename = params[0] || "circuit.vkey"; - const publicInputsFilename = params[1] || "public.json"; - const proofFilename = params[2] || "proof.json"; - - if (options.verbose) Logger__default["default"].setLogLevel("DEBUG"); - - const vkey = JSON.parse(fs__default["default"].readFileSync(vkeyFilename, "utf8")); - const publicInputs = JSON.parse(fs__default["default"].readFileSync(publicInputsFilename, "utf8")); - const proof = JSON.parse(fs__default["default"].readFileSync(proofFilename, "utf8")); - - const isValid = await fflonkVerify$1(vkey, publicInputs, proof, logger); - - return isValid ? 0 : 1; -} - -async function fileInfo(params) { - const filename = params[0]; - const extension = filename.split(".").pop(); - - if (!["zkey", "r1cs", "ptau", "wtns"].includes(extension)) { - console.error(`Extension ${extension} is not allowed.`); - return; - } - - try { - const { - fd: fd, - sections: sections - } = await binFileUtils__namespace.readBinFile(filename, extension, 2, 1 << 25, 1 << 23); - - console.log(`File info for ${filename}`); - console.log(); - console.log(`File size: ${fd.totalSize} bytes`); - console.log(`File type: ${extension}`); - console.log(`Version: ${fd.version}`); - console.log(`Bin version: ${fd.binVersion}`); - console.log(""); - - sections.forEach((section, index) => { - let errors = []; - if (section.length > 1) errors.push(`Section ${index} has more than one section definition`); - else { - if (section[0].size === 0) { - errors.push(`Section ${index} size is zero. This could cause false errors in other sections.`); - } - } - if (section[0].p + section[0].size > fd.totalSize) { - errors.push(`Section ${index} is out of bounds of the file.`); - } - - const color = errors.length === 0 ? "%s%s%s" : "%s\x1b[31m%s\x1b[0m%s"; - const text0 = "section " + ("#" + index).padStart(5, " "); - const text1 = errors.length === 0 ? " " : " !!"; - const text2 = ` size: ${section[0].size}\toffset: 0x${(section[0].p - 12).toString(16)}`; - console.log(color, text0, text1, text2); - errors.forEach((error) => { - console.error("\x1b[31m%s\x1b[0m", " > " + error); - }); - }); - } catch (error) { - console.error(error.message); - } + const vkeyFilename = params[0] || "circuit.vkey"; + const publicInputsFilename = params[1] || "public.json"; + const proofFilename = params[2] || "proof.json"; + if (options.verbose) logplease.default.setLogLevel("DEBUG"); + return await fflonkVerify$1(JSON.parse(fs.default.readFileSync(vkeyFilename, "utf8")), JSON.parse(fs.default.readFileSync(publicInputsFilename, "utf8")), JSON.parse(fs.default.readFileSync(proofFilename, "utf8")), logger) ? 0 : 1; } +async function fileInfo(params) { + const filename = params[0]; + const extension = filename.split(".").pop(); + if (![ + "zkey", + "r1cs", + "ptau", + "wtns" + ].includes(extension)) { + console.error(`Extension ${extension} is not allowed.`); + return; + } + try { + const { fd, sections } = await _iden3_binfileutils.readBinFile(filename, extension, 2, 1 << 25, 1 << 23); + console.log(`File info for ${filename}`); + console.log(); + console.log(`File size: ${fd.totalSize} bytes`); + console.log(`File type: ${extension}`); + console.log(`Version: ${fd.version}`); + console.log(`Bin version: ${fd.binVersion}`); + console.log(""); + sections.forEach((section, index) => { + let errors = []; + if (section.length > 1) errors.push(`Section ${index} has more than one section definition`); + else if (section[0].size === 0) errors.push(`Section ${index} size is zero. This could cause false errors in other sections.`); + if (section[0].p + section[0].size > fd.totalSize) errors.push(`Section ${index} is out of bounds of the file.`); + const color = errors.length === 0 ? "%s%s%s" : "%s\x1B[31m%s\x1B[0m%s"; + const text0 = "section " + ("#" + index).padStart(5, " "); + const text1 = errors.length === 0 ? " " : " !!"; + const text2 = ` size: ${section[0].size}\toffset: 0x${(section[0].p - 12).toString(16)}`; + console.log(color, text0, text1, text2); + errors.forEach((error) => { + console.error("\x1B[31m%s\x1B[0m", " > " + error); + }); + }); + } catch (error) { + console.error(error.message); + } +} +//#endregion diff --git a/build/main.cjs b/build/main.cjs index 1987b5a1..98df8cae 100644 --- a/build/main.cjs +++ b/build/main.cjs @@ -1,12816 +1,8217 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { value: true }); - -var binFileUtils = require('@iden3/binfileutils'); -var ffjavascript = require('ffjavascript'); -var blake2b = require('@noble/hashes/blake2b'); -var utils = require('@noble/hashes/utils'); -var readline = require('readline'); -var crypto = require('crypto'); -var fastFile = require('fastfile'); -var circom_runtime = require('circom_runtime'); -var r1csfile = require('r1csfile'); -var sha3 = require('@noble/hashes/sha3'); - -function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } - -function _interopNamespace(e) { - if (e && e.__esModule) return e; - var n = Object.create(null); - if (e) { - Object.keys(e).forEach(function (k) { - if (k !== 'default') { - var d = Object.getOwnPropertyDescriptor(e, k); - Object.defineProperty(n, k, d.get ? d : { - enumerable: true, - get: function () { return e[k]; } - }); - } - }); - } - n["default"] = e; - return Object.freeze(n); -} - -var binFileUtils__namespace = /*#__PURE__*/_interopNamespace(binFileUtils); -var readline__default = /*#__PURE__*/_interopDefaultLegacy(readline); -var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto); -var fastFile__namespace = /*#__PURE__*/_interopNamespace(fastFile); - -const bls12381r$1 = ffjavascript.Scalar.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16); -const bn128r$1 = ffjavascript.Scalar.e("21888242871839275222246405745257275088548364400416034343698204186575808495617"); - -const bls12381q = ffjavascript.Scalar.e("1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", 16); -const bn128q = ffjavascript.Scalar.e("21888242871839275222246405745257275088696311157297823662689037894645226208583"); - +Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); +//#region \0rolldown/runtime.js +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __exportAll = (all, no_symbols) => { + let target = {}; + for (var name in all) __defProp(target, name, { + get: all[name], + enumerable: true + }); + if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" }); + return target; +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { + key = keys[i]; + if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { + get: ((k) => from[k]).bind(null, key), + enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable + }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { + value: mod, + enumerable: true +}) : target, mod)); +//#endregion +let _iden3_binfileutils = require("@iden3/binfileutils"); +_iden3_binfileutils = __toESM(_iden3_binfileutils); +let ffjavascript = require("ffjavascript"); +let _noble_hashes_blake2_js = require("@noble/hashes/blake2.js"); +let _noble_hashes_utils_js = require("@noble/hashes/utils.js"); +let readline = require("readline"); +readline = __toESM(readline); +let crypto = require("crypto"); +crypto = __toESM(crypto); +let fastfile = require("fastfile"); +fastfile = __toESM(fastfile); +let circom_runtime = require("circom_runtime"); +let r1csfile = require("r1csfile"); +let _noble_hashes_sha3_js = require("@noble/hashes/sha3.js"); +//#region src/curves.js +var curves_exports = /* @__PURE__ */ __exportAll({ + getCurveFromName: () => getCurveFromName, + getCurveFromQ: () => getCurveFromQ, + getCurveFromR: () => getCurveFromR +}); +var bls12381r$1 = ffjavascript.Scalar.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16); +var bn128r$1 = ffjavascript.Scalar.e("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +var bls12381q = ffjavascript.Scalar.e("1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", 16); +var bn128q = ffjavascript.Scalar.e("21888242871839275222246405745257275088696311157297823662689037894645226208583"); async function getCurveFromR(r, options) { - let curve; - // check that options param is defined and that options.singleThread is defined - let singleThread = options && options.singleThread; - if (ffjavascript.Scalar.eq(r, bn128r$1)) { - curve = await ffjavascript.buildBn128(singleThread); - } else if (ffjavascript.Scalar.eq(r, bls12381r$1)) { - curve = await ffjavascript.buildBls12381(singleThread); - } else { - throw new Error(`Curve not supported: ${ffjavascript.Scalar.toString(r)}`); - } - return curve; -} - + let curve; + let singleThread = options && options.singleThread; + if (ffjavascript.Scalar.eq(r, bn128r$1)) curve = await (0, ffjavascript.buildBn128)(singleThread); + else if (ffjavascript.Scalar.eq(r, bls12381r$1)) curve = await (0, ffjavascript.buildBls12381)(singleThread); + else throw new Error(`Curve not supported: ${ffjavascript.Scalar.toString(r)}`); + return curve; +} async function getCurveFromQ(q, options) { - let curve; - let singleThread = options && options.singleThread; - if (ffjavascript.Scalar.eq(q, bn128q)) { - curve = await ffjavascript.buildBn128(singleThread); - } else if (ffjavascript.Scalar.eq(q, bls12381q)) { - curve = await ffjavascript.buildBls12381(singleThread); - } else { - throw new Error(`Curve not supported: ${ffjavascript.Scalar.toString(q)}`); - } - return curve; -} - + let curve; + let singleThread = options && options.singleThread; + if (ffjavascript.Scalar.eq(q, bn128q)) curve = await (0, ffjavascript.buildBn128)(singleThread); + else if (ffjavascript.Scalar.eq(q, bls12381q)) curve = await (0, ffjavascript.buildBls12381)(singleThread); + else throw new Error(`Curve not supported: ${ffjavascript.Scalar.toString(q)}`); + return curve; +} async function getCurveFromName(name, options) { - let curve; - let singleThread = options && options.singleThread; - const normName = normalizeName(name); - if (["BN128", "BN254", "ALTBN128"].indexOf(normName) >= 0) { - curve = await ffjavascript.buildBn128(singleThread); - } else if (["BLS12381"].indexOf(normName) >= 0) { - curve = await ffjavascript.buildBls12381(singleThread); - } else { - throw new Error(`Curve not supported: ${name}`); - } - return curve; - - function normalizeName(n) { - return n.toUpperCase().match(/[A-Za-z0-9]+/g).join(""); - } - -} - -var curves = /*#__PURE__*/Object.freeze({ - __proto__: null, - getCurveFromR: getCurveFromR, - getCurveFromQ: getCurveFromQ, - getCurveFromName: getCurveFromName -}); - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - - -function log2( V ) -{ - return( ( ( V & 0xFFFF0000 ) !== 0 ? ( V &= 0xFFFF0000, 16 ) : 0 ) | ( ( V & 0xFF00FF00 ) !== 0 ? ( V &= 0xFF00FF00, 8 ) : 0 ) | ( ( V & 0xF0F0F0F0 ) !== 0 ? ( V &= 0xF0F0F0F0, 4 ) : 0 ) | ( ( V & 0xCCCCCCCC ) !== 0 ? ( V &= 0xCCCCCCCC, 2 ) : 0 ) | ( ( V & 0xAAAAAAAA ) !== 0 ) ); -} - - + let curve; + let singleThread = options && options.singleThread; + const normName = normalizeName(name); + if ([ + "BN128", + "BN254", + "ALTBN128" + ].indexOf(normName) >= 0) curve = await (0, ffjavascript.buildBn128)(singleThread); + else if (["BLS12381"].indexOf(normName) >= 0) curve = await (0, ffjavascript.buildBls12381)(singleThread); + else throw new Error(`Curve not supported: ${name}`); + return curve; + function normalizeName(n) { + return n.toUpperCase().match(/[A-Za-z0-9]+/g).join(""); + } +} +//#endregion +//#region src/misc.js +var _revTable = []; +for (let i = 0; i < 256; i++) _revTable[i] = _revSlow(i, 8); +function _revSlow(idx, bits) { + let res = 0; + let a = idx; + for (let i = 0; i < bits; i++) { + res <<= 1; + res = res | a & 1; + a >>= 1; + } + return res; +} +function log2(V) { + return ((V & 4294901760) !== 0 ? (V &= 4294901760, 16) : 0) | ((V & 4278255360) !== 0 ? (V &= 4278255360, 8) : 0) | ((V & 4042322160) !== 0 ? (V &= 4042322160, 4) : 0) | ((V & 3435973836) !== 0 ? (V &= 3435973836, 2) : 0) | (V & 2863311530) !== 0; +} function formatHash(b, title) { - const a = new DataView(b.buffer, b.byteOffset, b.byteLength); - let S = ""; - for (let i=0; i<4; i++) { - if (i>0) S += "\n"; - S += "\t\t"; - for (let j=0; j<4; j++) { - if (j>0) S += " "; - S += a.getUint32(i*16+j*4).toString(16).padStart(8, "0"); - } - } - if (title) S = title + "\n" + S; - return S; -} - + const a = new DataView(b.buffer, b.byteOffset, b.byteLength); + let S = ""; + for (let i = 0; i < 4; i++) { + if (i > 0) S += "\n"; + S += " "; + for (let j = 0; j < 4; j++) { + if (j > 0) S += " "; + S += a.getUint32(i * 16 + j * 4).toString(16).padStart(8, "0"); + } + } + if (title) S = title + "\n" + S; + return S; +} function hashIsEqual(h1, h2) { - if (h1.byteLength != h2.byteLength) return false; - var dv1 = new Int8Array(h1); - var dv2 = new Int8Array(h2); - for (var i = 0 ; i != h1.byteLength ; i++) - { - if (dv1[i] != dv2[i]) return false; - } - return true; -} - + if (h1.byteLength != h2.byteLength) return false; + var dv1 = new Int8Array(h1); + var dv2 = new Int8Array(h2); + for (var i = 0; i != h1.byteLength; i++) if (dv1[i] != dv2[i]) return false; + return true; +} function cloneHasher(h) { - return h.clone(); + return h.clone(); } - function fromPartialHash(partial) { - // NOTE: this is unsafe and uses internal API - const buf = partial.subarray(0, 128); - const rest = utils.u32(partial.subarray(128)); - const res = blake2b.blake2b.create({ dkLen: 64 }); - res.buffer.set(buf); - (res.v0l = rest[0] | 0), (res.v0h = rest[1] | 0); - (res.v1l = rest[2] | 0), (res.v1h = rest[3] | 0); - (res.v2l = rest[4] | 0), (res.v2h = rest[5] | 0); - (res.v3l = rest[6] | 0), (res.v3h = rest[7] | 0); - (res.v4l = rest[8] | 0), (res.v4h = rest[9] | 0); - (res.v5l = rest[10] | 0), (res.v5h = rest[11] | 0); - (res.v6l = rest[12] | 0), (res.v6h = rest[13] | 0); - (res.v7l = rest[14] | 0), (res.v7h = rest[15] | 0); - const shift = 2 ** 32; - const len = rest[16] + rest[17] * shift; - const pos = rest[18] + rest[19] * shift; - res.length = len + pos; - res.pos = pos; - return res; -} - -function toPartialHash(hash){ - // NOTE: this is unsafe and uses internal API - const res = new Uint8Array(216); - const res32 = utils.u32(res.subarray(128)); - res.set(hash.buffer); - (res32[0] = hash.v0l), (res32[1] = hash.v0h); - (res32[2] = hash.v1l), (res32[3] = hash.v1h); - (res32[4] = hash.v2l), (res32[5] = hash.v2h); - (res32[6] = hash.v3l), (res32[7] = hash.v3h); - (res32[8] = hash.v4l), (res32[9] = hash.v4h); - (res32[10] = hash.v5l), (res32[11] = hash.v5h); - (res32[12] = hash.v6l), (res32[13] = hash.v6h); - (res32[14] = hash.v7l), (res32[15] = hash.v7h); - res32[18] = hash.pos; - res32[16] = hash.length-hash.pos; - return res; -} - + const buf = partial.subarray(0, 128); + const rest = (0, _noble_hashes_utils_js.u32)(partial.subarray(128)); + const res = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + res.buffer.set(buf); + res.v0l = rest[0] | 0, res.v0h = rest[1] | 0; + res.v1l = rest[2] | 0, res.v1h = rest[3] | 0; + res.v2l = rest[4] | 0, res.v2h = rest[5] | 0; + res.v3l = rest[6] | 0, res.v3h = rest[7] | 0; + res.v4l = rest[8] | 0, res.v4h = rest[9] | 0; + res.v5l = rest[10] | 0, res.v5h = rest[11] | 0; + res.v6l = rest[12] | 0, res.v6h = rest[13] | 0; + res.v7l = rest[14] | 0, res.v7h = rest[15] | 0; + const shift = 2 ** 32; + const len = rest[16] + rest[17] * shift; + const pos = rest[18] + rest[19] * shift; + res.length = len + pos; + res.pos = pos; + return res; +} +function toPartialHash(hash) { + const res = new Uint8Array(216); + const res32 = (0, _noble_hashes_utils_js.u32)(res.subarray(128)); + res.set(hash.buffer); + res32[0] = hash.v0l, res32[1] = hash.v0h; + res32[2] = hash.v1l, res32[3] = hash.v1h; + res32[4] = hash.v2l, res32[5] = hash.v2h; + res32[6] = hash.v3l, res32[7] = hash.v3h; + res32[8] = hash.v4l, res32[9] = hash.v4h; + res32[10] = hash.v5l, res32[11] = hash.v5h; + res32[12] = hash.v6l, res32[13] = hash.v6h; + res32[14] = hash.v7l, res32[15] = hash.v7h; + res32[18] = hash.pos; + res32[16] = hash.length - hash.pos; + return res; +} async function sameRatio$2(curve, g1s, g1sx, g2s, g2sx) { - if (curve.G1.isZero(g1s)) return false; - if (curve.G1.isZero(g1sx)) return false; - if (curve.G2.isZero(g2s)) return false; - if (curve.G2.isZero(g2sx)) return false; - // return curve.F12.eq(curve.pairing(g1s, g2sx), curve.pairing(g1sx, g2s)); - const res = await curve.pairingEq(g1s, g2sx, curve.G1.neg(g1sx), g2s); - return res; -} - - + if (curve.G1.isZero(g1s)) return false; + if (curve.G1.isZero(g1sx)) return false; + if (curve.G2.isZero(g2s)) return false; + if (curve.G2.isZero(g2sx)) return false; + return await curve.pairingEq(g1s, g2sx, curve.G1.neg(g1sx), g2s); +} function askEntropy() { - if (process.browser) { - return window.prompt("Enter a random text. (Entropy): ", ""); - } else { - const rl = readline__default["default"].createInterface({ - input: process.stdin, - output: process.stdout - }); - - return new Promise((resolve) => { - rl.question("Enter a random text. (Entropy): ", (input) => resolve(input) ); - }); - } -} - + if (process.browser) return window.prompt("Enter a random text. (Entropy): ", ""); + else { + const rl = readline.default.createInterface({ + input: process.stdin, + output: process.stdout + }); + return new Promise((resolve) => { + rl.question("Enter a random text. (Entropy): ", (input) => resolve(input)); + }); + } +} function getRandomBytes(n) { - let array = new Uint8Array(n); - if (process.browser) { // Supported - globalThis.crypto.getRandomValues(array); - } else { // NodeJS - crypto__default["default"].randomFillSync(array); - } - return array; -} - + let array = new Uint8Array(n); + if (process.browser) globalThis.crypto.getRandomValues(array); + else crypto.default.randomFillSync(array); + return array; +} async function sha256digest(data) { - if (process.browser) { // Supported - const buffer = await globalThis.crypto.subtle.digest("SHA-256", data.buffer); - return new Uint8Array(buffer); - } else { // NodeJS - return crypto__default["default"].createHash("sha256").update(data).digest(); - } -} - + if (process.browser) { + const buffer = await globalThis.crypto.subtle.digest("SHA-256", data.buffer); + return new Uint8Array(buffer); + } else return crypto.default.createHash("sha256").update(data).digest(); +} /** - * @param {Uint8Array} data - * @param {number} offset - */ +* @param {Uint8Array} data +* @param {number} offset +*/ function readUInt32BE(data, offset) { - return new DataView(data.buffer).getUint32(offset, false); + return new DataView(data.buffer).getUint32(offset, false); } - async function getRandomRng(entropy) { - // Generate a random Rng - while (!entropy) { - entropy = await askEntropy(); - } - const hasher = blake2b.blake2b.create(64); - hasher.update(getRandomBytes(64)); - const enc = new TextEncoder(); // always utf-8 - hasher.update(enc.encode(entropy)); - const hash = hasher.digest(); - - const seed = []; - for (let i=0;i<8;i++) { - seed[i] = readUInt32BE(hash, i*4); - } - const rng = new ffjavascript.ChaCha(seed); - return rng; -} - + while (!entropy) entropy = await askEntropy(); + const hasher = _noble_hashes_blake2_js.blake2b.create(64); + hasher.update(getRandomBytes(64)); + const enc = new TextEncoder(); + hasher.update(enc.encode(entropy)); + const hash = hasher.digest(); + const seed = []; + for (let i = 0; i < 8; i++) seed[i] = readUInt32BE(hash, i * 4); + return new ffjavascript.ChaCha(seed); +} async function rngFromBeaconParams(beaconHash, numIterationsExp) { - let nIterationsInner; - let nIterationsOuter; - if (numIterationsExp<32) { - nIterationsInner = (1 << numIterationsExp) >>> 0; - nIterationsOuter = 1; - } else { - nIterationsInner = 0x100000000; - nIterationsOuter = (1 << (numIterationsExp-32)) >>> 0; - } - - let curHash = beaconHash; - for (let i=0; i>> 0; + nIterationsOuter = 1; + } else { + nIterationsInner = 4294967296; + nIterationsOuter = 1 << numIterationsExp - 32 >>> 0; + } + let curHash = beaconHash; + for (let i = 0; i < nIterationsOuter; i++) for (let j = 0; j < nIterationsInner; j++) curHash = await sha256digest(curHash); + const curHashV = new DataView(curHash.buffer, curHash.byteOffset, curHash.byteLength); + const seed = []; + for (let i = 0; i < 8; i++) seed[i] = curHashV.getUint32(i * 4, false); + return new ffjavascript.ChaCha(seed); +} function hex2ByteArray(s) { - if (s instanceof Uint8Array) return s; - if (s.slice(0,2) == "0x") s= s.slice(2); - return new Uint8Array(s.match(/[\da-f]{2}/gi).map(function (h) { - return parseInt(h, 16); - })); + if (s instanceof Uint8Array) return s; + if (s.slice(0, 2) == "0x") s = s.slice(2); + return new Uint8Array(s.match(/[\da-f]{2}/gi).map(function(h) { + return parseInt(h, 16); + })); } - function byteArray2hex(byteArray) { - return Array.prototype.map.call(byteArray, function(byte) { - return ("0" + (byte & 0xFF).toString(16)).slice(-2); - }).join(""); + return Array.prototype.map.call(byteArray, function(byte) { + return ("0" + (byte & 255).toString(16)).slice(-2); + }).join(""); } - function stringifyBigIntsWithField(Fr, o) { - if (o instanceof Uint8Array) { - return Fr.toString(o); - } else if (Array.isArray(o)) { - return o.map(stringifyBigIntsWithField.bind(null, Fr)); - } else if (typeof o == "object") { - const res = {}; - const keys = Object.keys(o); - keys.forEach( (k) => { - res[k] = stringifyBigIntsWithField(Fr, o[k]); - }); - return res; - } else if ((typeof(o) == "bigint") || o.eq !== undefined) { - return o.toString(10); - } else { - return o; - } -} - -const HEADER_ZKEY_SECTION = 1; - -const GROTH16_PROTOCOL_ID = 1; -const PLONK_PROTOCOL_ID = 2; -const FFLONK_PROTOCOL_ID = 10; - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -// FFlonk constants -const FF_T_POL_DEG_MIN = 3; - -// ZKEY constants -const ZKEY_FF_NSECTIONS = 17; - -const ZKEY_FF_HEADER_SECTION = 2; -const ZKEY_FF_ADDITIONS_SECTION = 3; -const ZKEY_FF_A_MAP_SECTION = 4; -const ZKEY_FF_B_MAP_SECTION = 5; -const ZKEY_FF_C_MAP_SECTION = 6; -const ZKEY_FF_QL_SECTION = 7; -const ZKEY_FF_QR_SECTION = 8; -const ZKEY_FF_QM_SECTION = 9; -const ZKEY_FF_QO_SECTION = 10; -const ZKEY_FF_QC_SECTION = 11; -const ZKEY_FF_SIGMA1_SECTION = 12; -const ZKEY_FF_SIGMA2_SECTION = 13; -const ZKEY_FF_SIGMA3_SECTION = 14; -const ZKEY_FF_LAGRANGE_SECTION = 15; -const ZKEY_FF_PTAU_SECTION = 16; -const ZKEY_FF_C0_SECTION = 17; - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - + if (o instanceof Uint8Array) return Fr.toString(o); + else if (Array.isArray(o)) return o.map(stringifyBigIntsWithField.bind(null, Fr)); + else if (typeof o == "object") { + const res = {}; + Object.keys(o).forEach((k) => { + res[k] = stringifyBigIntsWithField(Fr, o[k]); + }); + return res; + } else if (typeof o == "bigint" || o.eq !== void 0) return o.toString(10); + else return o; +} +//#endregion +//#region src/zkey_utils.js async function writeHeader(fd, zkey) { - - // Write the header - /////////// - await binFileUtils__namespace.startWriteSection(fd, 1); - await fd.writeULE32(1); // Groth - await binFileUtils__namespace.endWriteSection(fd); - - // Write the Groth header section - /////////// - - const curve = await getCurveFromQ(zkey.q); - - await binFileUtils__namespace.startWriteSection(fd, 2); - const primeQ = curve.q; - const n8q = (Math.floor( (ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) +1)*8; - - const primeR = curve.r; - const n8r = (Math.floor( (ffjavascript.Scalar.bitLength(primeR) - 1) / 64) +1)*8; - - await fd.writeULE32(n8q); - await binFileUtils__namespace.writeBigInt(fd, primeQ, n8q); - await fd.writeULE32(n8r); - await binFileUtils__namespace.writeBigInt(fd, primeR, n8r); - await fd.writeULE32(zkey.nVars); // Total number of bars - await fd.writeULE32(zkey.nPublic); // Total number of public vars (not including ONE) - await fd.writeULE32(zkey.domainSize); // domainSize - await writeG1(fd, curve, zkey.vk_alpha_1); - await writeG1(fd, curve, zkey.vk_beta_1); - await writeG2(fd, curve, zkey.vk_beta_2); - await writeG2(fd, curve, zkey.vk_gamma_2); - await writeG1(fd, curve, zkey.vk_delta_1); - await writeG2(fd, curve, zkey.vk_delta_2); - - await binFileUtils__namespace.endWriteSection(fd); - - -} - + await _iden3_binfileutils.startWriteSection(fd, 1); + await fd.writeULE32(1); + await _iden3_binfileutils.endWriteSection(fd); + const curve = await getCurveFromQ(zkey.q); + await _iden3_binfileutils.startWriteSection(fd, 2); + const primeQ = curve.q; + const n8q = (Math.floor((ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) + 1) * 8; + const primeR = curve.r; + const n8r = (Math.floor((ffjavascript.Scalar.bitLength(primeR) - 1) / 64) + 1) * 8; + await fd.writeULE32(n8q); + await _iden3_binfileutils.writeBigInt(fd, primeQ, n8q); + await fd.writeULE32(n8r); + await _iden3_binfileutils.writeBigInt(fd, primeR, n8r); + await fd.writeULE32(zkey.nVars); + await fd.writeULE32(zkey.nPublic); + await fd.writeULE32(zkey.domainSize); + await writeG1(fd, curve, zkey.vk_alpha_1); + await writeG1(fd, curve, zkey.vk_beta_1); + await writeG2(fd, curve, zkey.vk_beta_2); + await writeG2(fd, curve, zkey.vk_gamma_2); + await writeG1(fd, curve, zkey.vk_delta_1); + await writeG2(fd, curve, zkey.vk_delta_2); + await _iden3_binfileutils.endWriteSection(fd); +} async function writeG1(fd, curve, p) { - const buff = new Uint8Array(curve.G1.F.n8*2); - curve.G1.toRprLEM(buff, 0, p); - await fd.write(buff); + const buff = new Uint8Array(curve.G1.F.n8 * 2); + curve.G1.toRprLEM(buff, 0, p); + await fd.write(buff); } - async function writeG2(fd, curve, p) { - const buff = new Uint8Array(curve.G2.F.n8*2); - curve.G2.toRprLEM(buff, 0, p); - await fd.write(buff); + const buff = new Uint8Array(curve.G2.F.n8 * 2); + curve.G2.toRprLEM(buff, 0, p); + await fd.write(buff); } - async function readG1(fd, curve, toObject) { - const buff = await fd.read(curve.G1.F.n8*2); - const res = curve.G1.fromRprLEM(buff, 0); - return toObject ? curve.G1.toObject(res) : res; + const buff = await fd.read(curve.G1.F.n8 * 2); + const res = curve.G1.fromRprLEM(buff, 0); + return toObject ? curve.G1.toObject(res) : res; } - async function readG2(fd, curve, toObject) { - const buff = await fd.read(curve.G2.F.n8*2); - const res = curve.G2.fromRprLEM(buff, 0); - return toObject ? curve.G2.toObject(res) : res; + const buff = await fd.read(curve.G2.F.n8 * 2); + const res = curve.G2.fromRprLEM(buff, 0); + return toObject ? curve.G2.toObject(res) : res; } - - async function readHeader$1(fd, sections, toObject, options) { - // Read Header - ///////////////////// - await binFileUtils__namespace.startReadUniqueSection(fd, sections, 1); - const protocolId = await fd.readULE32(); - await binFileUtils__namespace.endReadSection(fd); - - if (protocolId === GROTH16_PROTOCOL_ID) { - return await readHeaderGroth16(fd, sections, toObject, options); - } else if (protocolId === PLONK_PROTOCOL_ID) { - return await readHeaderPlonk(fd, sections, toObject, options); - } else if (protocolId === FFLONK_PROTOCOL_ID) { - return await readHeaderFFlonk(fd, sections, toObject, options); - } else { - throw new Error("Protocol not supported: "); - } -} - - - - + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 1); + const protocolId = await fd.readULE32(); + await _iden3_binfileutils.endReadSection(fd); + if (protocolId === 1) return await readHeaderGroth16(fd, sections, toObject, options); + else if (protocolId === 2) return await readHeaderPlonk(fd, sections, toObject, options); + else if (protocolId === 10) return await readHeaderFFlonk(fd, sections, toObject, options); + else throw new Error("Protocol not supported: "); +} async function readHeaderGroth16(fd, sections, toObject, options) { - const zkey = {}; - - zkey.protocol = "groth16"; - - // Read Groth Header - ///////////////////// - await binFileUtils__namespace.startReadUniqueSection(fd, sections, 2); - const n8q = await fd.readULE32(); - zkey.n8q = n8q; - zkey.q = await binFileUtils__namespace.readBigInt(fd, n8q); - - const n8r = await fd.readULE32(); - zkey.n8r = n8r; - zkey.r = await binFileUtils__namespace.readBigInt(fd, n8r); - zkey.curve = await getCurveFromQ(zkey.q, options); - zkey.nVars = await fd.readULE32(); - zkey.nPublic = await fd.readULE32(); - zkey.domainSize = await fd.readULE32(); - zkey.power = log2(zkey.domainSize); - zkey.vk_alpha_1 = await readG1(fd, zkey.curve, toObject); - zkey.vk_beta_1 = await readG1(fd, zkey.curve, toObject); - zkey.vk_beta_2 = await readG2(fd, zkey.curve, toObject); - zkey.vk_gamma_2 = await readG2(fd, zkey.curve, toObject); - zkey.vk_delta_1 = await readG1(fd, zkey.curve, toObject); - zkey.vk_delta_2 = await readG2(fd, zkey.curve, toObject); - await binFileUtils__namespace.endReadSection(fd); - - return zkey; - -} - + const zkey = {}; + zkey.protocol = "groth16"; + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 2); + const n8q = await fd.readULE32(); + zkey.n8q = n8q; + zkey.q = await _iden3_binfileutils.readBigInt(fd, n8q); + const n8r = await fd.readULE32(); + zkey.n8r = n8r; + zkey.r = await _iden3_binfileutils.readBigInt(fd, n8r); + zkey.curve = await getCurveFromQ(zkey.q, options); + zkey.nVars = await fd.readULE32(); + zkey.nPublic = await fd.readULE32(); + zkey.domainSize = await fd.readULE32(); + zkey.power = log2(zkey.domainSize); + zkey.vk_alpha_1 = await readG1(fd, zkey.curve, toObject); + zkey.vk_beta_1 = await readG1(fd, zkey.curve, toObject); + zkey.vk_beta_2 = await readG2(fd, zkey.curve, toObject); + zkey.vk_gamma_2 = await readG2(fd, zkey.curve, toObject); + zkey.vk_delta_1 = await readG1(fd, zkey.curve, toObject); + zkey.vk_delta_2 = await readG2(fd, zkey.curve, toObject); + await _iden3_binfileutils.endReadSection(fd); + return zkey; +} async function readHeaderPlonk(fd, sections, toObject, options) { - const zkey = {}; - - zkey.protocol = "plonk"; - - // Read Plonk Header - ///////////////////// - await binFileUtils__namespace.startReadUniqueSection(fd, sections, 2); - const n8q = await fd.readULE32(); - zkey.n8q = n8q; - zkey.q = await binFileUtils__namespace.readBigInt(fd, n8q); - - const n8r = await fd.readULE32(); - zkey.n8r = n8r; - zkey.r = await binFileUtils__namespace.readBigInt(fd, n8r); - zkey.curve = await getCurveFromQ(zkey.q, options); - zkey.nVars = await fd.readULE32(); - zkey.nPublic = await fd.readULE32(); - zkey.domainSize = await fd.readULE32(); - zkey.power = log2(zkey.domainSize); - zkey.nAdditions = await fd.readULE32(); - zkey.nConstraints = await fd.readULE32(); - zkey.k1 = await fd.read(n8r); - zkey.k2 = await fd.read(n8r); - - zkey.Qm = await readG1(fd, zkey.curve, toObject); - zkey.Ql = await readG1(fd, zkey.curve, toObject); - zkey.Qr = await readG1(fd, zkey.curve, toObject); - zkey.Qo = await readG1(fd, zkey.curve, toObject); - zkey.Qc = await readG1(fd, zkey.curve, toObject); - zkey.S1 = await readG1(fd, zkey.curve, toObject); - zkey.S2 = await readG1(fd, zkey.curve, toObject); - zkey.S3 = await readG1(fd, zkey.curve, toObject); - zkey.X_2 = await readG2(fd, zkey.curve, toObject); - - await binFileUtils__namespace.endReadSection(fd); - - return zkey; -} - + const zkey = {}; + zkey.protocol = "plonk"; + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 2); + const n8q = await fd.readULE32(); + zkey.n8q = n8q; + zkey.q = await _iden3_binfileutils.readBigInt(fd, n8q); + const n8r = await fd.readULE32(); + zkey.n8r = n8r; + zkey.r = await _iden3_binfileutils.readBigInt(fd, n8r); + zkey.curve = await getCurveFromQ(zkey.q, options); + zkey.nVars = await fd.readULE32(); + zkey.nPublic = await fd.readULE32(); + zkey.domainSize = await fd.readULE32(); + zkey.power = log2(zkey.domainSize); + zkey.nAdditions = await fd.readULE32(); + zkey.nConstraints = await fd.readULE32(); + zkey.k1 = await fd.read(n8r); + zkey.k2 = await fd.read(n8r); + zkey.Qm = await readG1(fd, zkey.curve, toObject); + zkey.Ql = await readG1(fd, zkey.curve, toObject); + zkey.Qr = await readG1(fd, zkey.curve, toObject); + zkey.Qo = await readG1(fd, zkey.curve, toObject); + zkey.Qc = await readG1(fd, zkey.curve, toObject); + zkey.S1 = await readG1(fd, zkey.curve, toObject); + zkey.S2 = await readG1(fd, zkey.curve, toObject); + zkey.S3 = await readG1(fd, zkey.curve, toObject); + zkey.X_2 = await readG2(fd, zkey.curve, toObject); + await _iden3_binfileutils.endReadSection(fd); + return zkey; +} async function readHeaderFFlonk(fd, sections, toObject, options) { - const zkey = {}; - - zkey.protocol = "fflonk"; - zkey.protocolId = FFLONK_PROTOCOL_ID; - - await binFileUtils__namespace.startReadUniqueSection(fd, sections, ZKEY_FF_HEADER_SECTION); - const n8q = await fd.readULE32(); - zkey.n8q = n8q; - zkey.q = await binFileUtils__namespace.readBigInt(fd, n8q); - zkey.curve = await getCurveFromQ(zkey.q, options); - - const n8r = await fd.readULE32(); - zkey.n8r = n8r; - zkey.r = await binFileUtils__namespace.readBigInt(fd, n8r); - - zkey.nVars = await fd.readULE32(); - zkey.nPublic = await fd.readULE32(); - zkey.domainSize = await fd.readULE32(); - zkey.power = log2(zkey.domainSize); - zkey.nAdditions = await fd.readULE32(); - zkey.nConstraints = await fd.readULE32(); - - zkey.k1 = await fd.read(n8r); - zkey.k2 = await fd.read(n8r); - - zkey.w3 = await fd.read(n8r); - zkey.w4 = await fd.read(n8r); - zkey.w8 = await fd.read(n8r); - zkey.wr = await fd.read(n8r); - - zkey.X_2 = await readG2(fd, zkey.curve, toObject); - - zkey.C0 = await readG1(fd, zkey.curve, toObject); - - await binFileUtils__namespace.endReadSection(fd); - - return zkey; -} - + const zkey = {}; + zkey.protocol = "fflonk"; + zkey.protocolId = 10; + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 2); + const n8q = await fd.readULE32(); + zkey.n8q = n8q; + zkey.q = await _iden3_binfileutils.readBigInt(fd, n8q); + zkey.curve = await getCurveFromQ(zkey.q, options); + const n8r = await fd.readULE32(); + zkey.n8r = n8r; + zkey.r = await _iden3_binfileutils.readBigInt(fd, n8r); + zkey.nVars = await fd.readULE32(); + zkey.nPublic = await fd.readULE32(); + zkey.domainSize = await fd.readULE32(); + zkey.power = log2(zkey.domainSize); + zkey.nAdditions = await fd.readULE32(); + zkey.nConstraints = await fd.readULE32(); + zkey.k1 = await fd.read(n8r); + zkey.k2 = await fd.read(n8r); + zkey.w3 = await fd.read(n8r); + zkey.w4 = await fd.read(n8r); + zkey.w8 = await fd.read(n8r); + zkey.wr = await fd.read(n8r); + zkey.X_2 = await readG2(fd, zkey.curve, toObject); + zkey.C0 = await readG1(fd, zkey.curve, toObject); + await _iden3_binfileutils.endReadSection(fd); + return zkey; +} async function readZKey(fileName, toObject) { - const {fd, sections} = await binFileUtils__namespace.readBinFile(fileName, "zkey", 1); - - const zkey = await readHeader$1(fd, sections, toObject); - - const Fr = new ffjavascript.F1Field(zkey.r); - const Rr = ffjavascript.Scalar.mod(ffjavascript.Scalar.shl(1, zkey.n8r*8), zkey.r); - const Rri = Fr.inv(Rr); - const Rri2 = Fr.mul(Rri, Rri); - - let curve = await getCurveFromQ(zkey.q); - - // Read IC Section - /////////// - await binFileUtils__namespace.startReadUniqueSection(fd, sections, 3); - zkey.IC = []; - for (let i=0; i<= zkey.nPublic; i++) { - const P = await readG1(fd, curve, toObject); - zkey.IC.push(P); - } - await binFileUtils__namespace.endReadSection(fd); - - - // Read Coefs - /////////// - await binFileUtils__namespace.startReadUniqueSection(fd, sections, 4); - const nCCoefs = await fd.readULE32(); - zkey.ccoefs = []; - for (let i=0; i0) { - const paramsBuff = new Uint8Array(params); - await fd.writeULE32(paramsBuff.byteLength); - await fd.write(paramsBuff); - } else { - await fd.writeULE32(0); - } - -} - + await writeG1(fd, curve, c.deltaAfter); + await writeG1(fd, curve, c.delta.g1_s); + await writeG1(fd, curve, c.delta.g1_sx); + await writeG2(fd, curve, c.delta.g2_spx); + await fd.write(c.transcript); + await fd.writeULE32(c.type || 0); + const params = []; + if (c.name) { + params.push(1); + const nameData = new TextEncoder("utf-8").encode(c.name.substring(0, 64)); + params.push(nameData.byteLength); + for (let i = 0; i < nameData.byteLength; i++) params.push(nameData[i]); + } + if (c.type == 1) { + params.push(2); + params.push(c.numIterationsExp); + params.push(3); + params.push(c.beaconHash.byteLength); + for (let i = 0; i < c.beaconHash.byteLength; i++) params.push(c.beaconHash[i]); + } + if (params.length > 0) { + const paramsBuff = new Uint8Array(params); + await fd.writeULE32(paramsBuff.byteLength); + await fd.write(paramsBuff); + } else await fd.writeULE32(0); +} async function writeMPCParams(fd, curve, mpcParams) { - await binFileUtils__namespace.startWriteSection(fd, 10); - await fd.write(mpcParams.csHash); - await fd.writeULE32(mpcParams.contributions.length); - for (let i=0; i. -*/ - - + hashG1(hasher, curve, c.deltaAfter); + hashG1(hasher, curve, c.delta.g1_s); + hashG1(hasher, curve, c.delta.g1_sx); + hashG2(hasher, curve, c.delta.g2_spx); + hasher.update(c.transcript); +} +//#endregion +//#region src/wtns_utils.js async function write(fd, witness, prime) { - - await binFileUtils__namespace.startWriteSection(fd, 1); - const n8 = (Math.floor( (ffjavascript.Scalar.bitLength(prime) - 1) / 64) +1)*8; - await fd.writeULE32(n8); - await binFileUtils__namespace.writeBigInt(fd, prime, n8); - await fd.writeULE32(witness.length); - await binFileUtils__namespace.endWriteSection(fd); - - await binFileUtils__namespace.startWriteSection(fd, 2); - for (let i=0; i. -*/ -const {stringifyBigInts: stringifyBigInts$4} = ffjavascript.utils; - + const { fd, sections } = await _iden3_binfileutils.readBinFile(fileName, "wtns", 2); + const { n8, nWitness } = await readHeader(fd, sections); + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 2); + const res = []; + for (let i = 0; i < nWitness; i++) { + const v = await _iden3_binfileutils.readBigInt(fd, n8); + res.push(v); + } + await _iden3_binfileutils.endReadSection(fd); + await fd.close(); + return res; +} +//#endregion +//#region src/groth16_prove.js +var { stringifyBigInts: stringifyBigInts$4 } = ffjavascript.utils; async function groth16Prove(zkeyFileName, witnessFileName, logger, options) { - - if (logger) monitorMemoryUsage(logger, 50); - const {fd: fdWtns, sections: sectionsWtns} = await binFileUtils__namespace.readBinFile(witnessFileName, "wtns", 2, 1<<25, 1<<23); - - const wtns = await readHeader(fdWtns, sectionsWtns); - - const {fd: fdZKey, sections: sectionsZKey} = await binFileUtils__namespace.readBinFile(zkeyFileName, "zkey", 2, 1<<25, 1<<23); - - const zkey = await readHeader$1(fdZKey, sectionsZKey, undefined, options); - - if (zkey.protocol != "groth16") { - throw new Error("zkey file is not groth16"); - } - - if (!ffjavascript.Scalar.eq(zkey.r, wtns.q)) { - throw new Error("Curve of the witness does not match the curve of the proving key"); - } - - if (wtns.nWitness != zkey.nVars) { - throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}`); - } - - const curve = zkey.curve; - const Fr = curve.Fr; - const G1 = curve.G1; - const G2 = curve.G2; - - const power = log2(zkey.domainSize); - - if (logger) logger.debug("Reading Wtns"); - const buffWitness = await binFileUtils__namespace.readSection(fdWtns, sectionsWtns, 2); - - let resH; - let resHPromise; - let buffPodd_T; - - let abcPromise = (async function (){ - let buffA_T, buffB_T, buffC_T; - - await (async function (){ - if (logger) logger.debug("Reading Coeffs"); - console.time("buildABC_outer"); - const buffCoeffs = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 4); - - if (logger) logger.debug("Building ABC"); - - options = options || {}; - //options.buildABC="wasm1"; // for testing - - if (options && options.buildABC==="wasm") { - // build ABC in WASM - [buffA_T, buffB_T, buffC_T] = await buildABC(curve, zkey, buffWitness, buffCoeffs, logger); - } else if (options && options.buildABC==="wasm1") { - // build ABC in WASM - [buffA_T, buffB_T, buffC_T] = await buildABCWASM1(curve, zkey, buffWitness, buffCoeffs, logger); - } else { - // default, build ABC in JS - [buffA_T, buffB_T, buffC_T] = await buildABC1(curve, zkey, buffWitness, buffCoeffs, logger); - } - console.timeEnd("buildABC_outer"); - })(); - - console.time("abcPromise"); - - if (globalThis.gc) {globalThis.gc();} - - const inc = power === Fr.s ? curve.Fr.shift : curve.Fr.w[power+1]; - - let buffAodd_T; - await (async function () { - let buffA = await Fr.ifft(buffA_T, "", "", logger, "IFFT_A"); - buffA_T = null; - const buffAodd = await Fr.batchApplyKey(buffA, Fr.e(1), inc); - buffAodd_T = await Fr.fft(buffAodd, "", "", logger, "FFT_A"); - })(); - - let buffBodd_T; - await (async function () { - const buffB = await Fr.ifft(buffB_T, "", "", logger, "IFFT_B"); - buffB_T = null; - const buffBodd = await Fr.batchApplyKey(buffB, Fr.e(1), inc); - buffBodd_T = await Fr.fft(buffBodd, "", "", logger, "FFT_B"); - })(); - - let buffCodd_T; - await (async function () { - const buffC = await Fr.ifft(buffC_T, "", "", logger, "IFFT_C"); - buffC_T = null; - const buffCodd = await Fr.batchApplyKey(buffC, Fr.e(1), inc); - buffCodd_T = await Fr.fft(buffCodd, "", "", logger, "FFT_C"); - })(); - - if (logger) logger.debug("Join ABC"); - buffPodd_T = await joinABC(curve, zkey, buffAodd_T, buffBodd_T, buffCodd_T, logger); - if (logger) logger.debug("Join ABC finished"); - buffAodd_T = null; - buffBodd_T = null; - buffCodd_T = null; - - if (globalThis.gc) {globalThis.gc();} - console.timeEnd("abcPromise"); - })(); - //await abcPromise; - - let proof = {}; - - async function calcPiA(){ - if (logger) logger.debug("Reading A Points"); - const buffBasesA = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 5); - console.time("Calculate PiA"); - proof.pi_a = await curve.G1.multiExpAffine(buffBasesA, buffWitness, logger, "multiexp A"); - console.timeEnd("Calculate PiA"); - } - - let piaPromise = calcPiA(); - //await piaPromise; - - let pib1; - - async function calcPiB1() { - if (logger) logger.debug("Reading B1 Points"); - const buffBasesB1 = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 6); - console.time("Calculate PiB1"); - pib1 = await curve.G1.multiExpAffine(buffBasesB1, buffWitness, logger, "multiexp B1"); - console.timeEnd("Calculate PiB1"); - } - - let pib1Promise = calcPiB1(); - //await pib1Promise; - - async function calcPiB() { - if (logger) logger.debug("Reading B2 Points"); - const buffBasesB2 = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 7); - console.time("Calculate PiB"); - proof.pi_b = await curve.G2.multiExpAffine(buffBasesB2, buffWitness, logger, "multiexp B2"); - console.timeEnd("Calculate PiB"); - } - - let pibPromise = calcPiB(); - //await pibPromise; - - let picPromise = (async function (){ - if (logger) logger.debug("Reading C Points"); - const buffBasesC = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 8); - console.time("Calculate PiC"); - proof.pi_c = await curve.G1.multiExpAffine(buffBasesC, buffWitness.slice((zkey.nPublic+1)*curve.Fr.n8), logger, "multiexp C"); - console.timeEnd("Calculate PiC"); - })(); - //await picPromise; - - - resHPromise = (async function (){ - if (logger) logger.debug("Reading H Points"); - await abcPromise; - console.time("resHPromise"); - const buffBasesH = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 9); - //await Promise.all([abcPromise, piaPromise, pib1Promise, pibPromise, picPromise]); - resH = await curve.G1.multiExpAffine(buffBasesH, buffPodd_T, logger, "multiexp H"); - //buffPodd_T = null; - console.timeEnd("resHPromise"); - })(); - //await resHPromise; - - - const r = curve.Fr.random(); - const s = curve.Fr.random(); - - await piaPromise; - proof.pi_a = G1.add( proof.pi_a, zkey.vk_alpha_1 ); - proof.pi_a = G1.add( proof.pi_a, G1.timesFr( zkey.vk_delta_1, r )); - - await pibPromise; - proof.pi_b = G2.add( proof.pi_b, zkey.vk_beta_2 ); - proof.pi_b = G2.add( proof.pi_b, G2.timesFr( zkey.vk_delta_2, s )); - - await pib1Promise; - pib1 = G1.add( pib1, zkey.vk_beta_1 ); - pib1 = G1.add( pib1, G1.timesFr( zkey.vk_delta_1, s )); - - await Promise.all([picPromise, resHPromise]); - proof.pi_c = G1.add(proof.pi_c, resH); - - - proof.pi_c = G1.add( proof.pi_c, G1.timesFr( proof.pi_a, s )); - proof.pi_c = G1.add( proof.pi_c, G1.timesFr( pib1, r )); - proof.pi_c = G1.add( proof.pi_c, G1.timesFr( zkey.vk_delta_1, Fr.neg(Fr.mul(r,s) ))); - - - let publicSignals = []; - - for (let i=1; i<= zkey.nPublic; i++) { - const b = buffWitness.slice(i*Fr.n8, i*Fr.n8+Fr.n8); - publicSignals.push(ffjavascript.Scalar.fromRprLE(b)); - } - - proof.pi_a = G1.toObject(G1.toAffine(proof.pi_a)); - proof.pi_b = G2.toObject(G2.toAffine(proof.pi_b)); - proof.pi_c = G1.toObject(G1.toAffine(proof.pi_c)); - - proof.protocol = "groth16"; - proof.curve = curve.name; - - await fdZKey.close(); - await fdWtns.close(); - - proof = stringifyBigInts$4(proof); - publicSignals = stringifyBigInts$4(publicSignals); - - return {proof, publicSignals}; -} - - + if (logger) monitorMemoryUsage(logger, 50); + const { fd: fdWtns, sections: sectionsWtns } = await _iden3_binfileutils.readBinFile(witnessFileName, "wtns", 2, 1 << 25, 1 << 23); + const wtns = await readHeader(fdWtns, sectionsWtns); + const { fd: fdZKey, sections: sectionsZKey } = await _iden3_binfileutils.readBinFile(zkeyFileName, "zkey", 2, 1 << 25, 1 << 23); + const zkey = await readHeader$1(fdZKey, sectionsZKey, void 0, options); + if (zkey.protocol != "groth16") throw new Error("zkey file is not groth16"); + if (!ffjavascript.Scalar.eq(zkey.r, wtns.q)) throw new Error("Curve of the witness does not match the curve of the proving key"); + if (wtns.nWitness != zkey.nVars) throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}`); + const curve = zkey.curve; + const Fr = curve.Fr; + const G1 = curve.G1; + const G2 = curve.G2; + const power = log2(zkey.domainSize); + if (logger) logger.debug("Reading Wtns"); + const buffWitness = await _iden3_binfileutils.readSection(fdWtns, sectionsWtns, 2); + let resH; + let resHPromise; + let buffPodd_T; + let abcPromise = (async function() { + let buffA_T, buffB_T, buffC_T; + await (async function() { + if (logger) logger.debug("Reading Coeffs"); + console.time("buildABC_outer"); + const buffCoeffs = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 4); + if (logger) logger.debug("Building ABC"); + options = options || {}; + if (options && options.buildABC === "wasm") [buffA_T, buffB_T, buffC_T] = await buildABC(curve, zkey, buffWitness, buffCoeffs, logger); + else if (options && options.buildABC === "wasm1") [buffA_T, buffB_T, buffC_T] = await buildABCWASM1(curve, zkey, buffWitness, buffCoeffs, logger); + else [buffA_T, buffB_T, buffC_T] = await buildABC1(curve, zkey, buffWitness, buffCoeffs, logger); + console.timeEnd("buildABC_outer"); + })(); + console.time("abcPromise"); + if (globalThis.gc) globalThis.gc(); + const inc = power === Fr.s ? curve.Fr.shift : curve.Fr.w[power + 1]; + let buffAodd_T; + await (async function() { + let buffA = await Fr.ifft(buffA_T, "", "", logger, "IFFT_A"); + buffA_T = null; + const buffAodd = await Fr.batchApplyKey(buffA, Fr.e(1), inc); + buffAodd_T = await Fr.fft(buffAodd, "", "", logger, "FFT_A"); + })(); + let buffBodd_T; + await (async function() { + const buffB = await Fr.ifft(buffB_T, "", "", logger, "IFFT_B"); + buffB_T = null; + const buffBodd = await Fr.batchApplyKey(buffB, Fr.e(1), inc); + buffBodd_T = await Fr.fft(buffBodd, "", "", logger, "FFT_B"); + })(); + let buffCodd_T; + await (async function() { + const buffC = await Fr.ifft(buffC_T, "", "", logger, "IFFT_C"); + buffC_T = null; + const buffCodd = await Fr.batchApplyKey(buffC, Fr.e(1), inc); + buffCodd_T = await Fr.fft(buffCodd, "", "", logger, "FFT_C"); + })(); + if (logger) logger.debug("Join ABC"); + buffPodd_T = await joinABC(curve, zkey, buffAodd_T, buffBodd_T, buffCodd_T, logger); + if (logger) logger.debug("Join ABC finished"); + buffAodd_T = null; + buffBodd_T = null; + buffCodd_T = null; + if (globalThis.gc) globalThis.gc(); + console.timeEnd("abcPromise"); + })(); + let proof = {}; + async function calcPiA() { + if (logger) logger.debug("Reading A Points"); + const buffBasesA = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 5); + console.time("Calculate PiA"); + proof.pi_a = await curve.G1.multiExpAffine(buffBasesA, buffWitness, logger, "multiexp A"); + console.timeEnd("Calculate PiA"); + } + let piaPromise = calcPiA(); + let pib1; + async function calcPiB1() { + if (logger) logger.debug("Reading B1 Points"); + const buffBasesB1 = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 6); + console.time("Calculate PiB1"); + pib1 = await curve.G1.multiExpAffine(buffBasesB1, buffWitness, logger, "multiexp B1"); + console.timeEnd("Calculate PiB1"); + } + let pib1Promise = calcPiB1(); + async function calcPiB() { + if (logger) logger.debug("Reading B2 Points"); + const buffBasesB2 = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 7); + console.time("Calculate PiB"); + proof.pi_b = await curve.G2.multiExpAffine(buffBasesB2, buffWitness, logger, "multiexp B2"); + console.timeEnd("Calculate PiB"); + } + let pibPromise = calcPiB(); + let picPromise = (async function() { + if (logger) logger.debug("Reading C Points"); + const buffBasesC = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 8); + console.time("Calculate PiC"); + proof.pi_c = await curve.G1.multiExpAffine(buffBasesC, buffWitness.slice((zkey.nPublic + 1) * curve.Fr.n8), logger, "multiexp C"); + console.timeEnd("Calculate PiC"); + })(); + resHPromise = (async function() { + if (logger) logger.debug("Reading H Points"); + await abcPromise; + console.time("resHPromise"); + const buffBasesH = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 9); + resH = await curve.G1.multiExpAffine(buffBasesH, buffPodd_T, logger, "multiexp H"); + console.timeEnd("resHPromise"); + })(); + const r = curve.Fr.random(); + const s = curve.Fr.random(); + await piaPromise; + proof.pi_a = G1.add(proof.pi_a, zkey.vk_alpha_1); + proof.pi_a = G1.add(proof.pi_a, G1.timesFr(zkey.vk_delta_1, r)); + await pibPromise; + proof.pi_b = G2.add(proof.pi_b, zkey.vk_beta_2); + proof.pi_b = G2.add(proof.pi_b, G2.timesFr(zkey.vk_delta_2, s)); + await pib1Promise; + pib1 = G1.add(pib1, zkey.vk_beta_1); + pib1 = G1.add(pib1, G1.timesFr(zkey.vk_delta_1, s)); + await Promise.all([picPromise, resHPromise]); + proof.pi_c = G1.add(proof.pi_c, resH); + proof.pi_c = G1.add(proof.pi_c, G1.timesFr(proof.pi_a, s)); + proof.pi_c = G1.add(proof.pi_c, G1.timesFr(pib1, r)); + proof.pi_c = G1.add(proof.pi_c, G1.timesFr(zkey.vk_delta_1, Fr.neg(Fr.mul(r, s)))); + let publicSignals = []; + for (let i = 1; i <= zkey.nPublic; i++) { + const b = buffWitness.slice(i * Fr.n8, i * Fr.n8 + Fr.n8); + publicSignals.push(ffjavascript.Scalar.fromRprLE(b)); + } + proof.pi_a = G1.toObject(G1.toAffine(proof.pi_a)); + proof.pi_b = G2.toObject(G2.toAffine(proof.pi_b)); + proof.pi_c = G1.toObject(G1.toAffine(proof.pi_c)); + proof.protocol = "groth16"; + proof.curve = curve.name; + await fdZKey.close(); + await fdWtns.close(); + proof = stringifyBigInts$4(proof); + publicSignals = stringifyBigInts$4(publicSignals); + return { + proof, + publicSignals + }; +} async function buildABC1(curve, zkey, witness, coeffs, logger) { - const n8 = curve.Fr.n8; - const sCoef = 4*3 + zkey.n8r; - const nCoef = (coeffs.byteLength-4) / sCoef; - - const outBuffA = new ffjavascript.BigBuffer(zkey.domainSize * n8); - const outBuffB = new ffjavascript.BigBuffer(zkey.domainSize * n8); - const outBuffC = new ffjavascript.BigBuffer(zkey.domainSize * n8); - - const outBuf = [ outBuffA, outBuffB ]; - for (let i=0; i 2**16) { - concurrency*=2; - elementsPerChunk = Math.floor(zkey.domainSize/concurrency); - } - console.log("@@@ new elementsPerChunk", elementsPerChunk); - - - const promises = []; - - const cutPoints = []; - for (let i=0; i1) { - const promises2 = []; - for (let i=0; i v) { - n = k - 1; - } else if (va < v) { - m = k + 1; - } else { - n = k; - } - } - return 4 + m*sCoef; - } -} - - -// buildABCWASM1 is single-threaded implementation of buildABS using wasm -// It has much better memory usage than multithreaded wasm implementation. -// It's much faster than pure js one, but uses much more memory. + let concurrency = curve.tm.concurrency; + const sCoef = 12 + zkey.n8r; + let getUint32; + if (coeffs instanceof ffjavascript.BigBuffer) { + const coeffsDV = []; + const PAGE_LEN = coeffs.buffers[0].length; + for (let i = 0; i < coeffs.buffers.length; i++) coeffsDV.push(new DataView(coeffs.buffers[i].buffer)); + getUint32 = function(pos) { + return coeffsDV[Math.floor(pos / PAGE_LEN)].getUint32(pos % PAGE_LEN, true); + }; + } else { + const coeffsDV = new DataView(coeffs.buffer, coeffs.byteOffset, coeffs.byteLength); + getUint32 = function(pos) { + return coeffsDV.getUint32(pos, true); + }; + } + let elementsPerChunk = Math.floor(zkey.domainSize / concurrency); + console.log("@@@ elementsPerChunk", elementsPerChunk); + while (elementsPerChunk > 2 ** 16) { + concurrency *= 2; + elementsPerChunk = Math.floor(zkey.domainSize / concurrency); + } + console.log("@@@ new elementsPerChunk", elementsPerChunk); + const promises = []; + const cutPoints = []; + for (let i = 0; i < concurrency; i++) cutPoints.push(getCutPoint(Math.floor(i * elementsPerChunk))); + cutPoints.push(coeffs.byteLength); + const chunkSize = 2 ** 26; + for (let s = 0; s < zkey.nVars; s += chunkSize) { + if (logger) logger.debug(`QAP ${s}: ${s}/${zkey.nVars}`); + const ns = Math.min(zkey.nVars - s, chunkSize); + for (let i = 0; i < concurrency; i++) { + let n; + if (i < concurrency - 1) n = elementsPerChunk; + else n = zkey.domainSize - i * elementsPerChunk; + if (n == 0) continue; + const task = []; + task.push({ + cmd: "ALLOCSET", + var: 0, + buff: coeffs.slice(cutPoints[i], cutPoints[i + 1]) + }); + task.push({ + cmd: "ALLOCSET", + var: 1, + buff: witness.slice(s * curve.Fr.n8, (s + ns) * curve.Fr.n8) + }); + task.push({ + cmd: "ALLOC", + var: 2, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "ALLOC", + var: 3, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "ALLOC", + var: 4, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "CALL", + fnName: "qap_buildABC", + params: [ + { var: 0 }, + { val: (cutPoints[i + 1] - cutPoints[i]) / sCoef }, + { var: 1 }, + { var: 2 }, + { var: 3 }, + { var: 4 }, + { val: i * elementsPerChunk }, + { val: n }, + { val: s }, + { val: ns } + ] + }); + task.push({ + cmd: "GET", + out: 0, + var: 2, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "GET", + out: 1, + var: 3, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "GET", + out: 2, + var: 4, + len: n * curve.Fr.n8 + }); + promises.push(curve.tm.queueAction(task)); + } + } + let result = await Promise.all(promises); + const nGroups = result.length / concurrency; + if (nGroups > 1) { + const promises2 = []; + for (let i = 0; i < concurrency; i++) { + const task = []; + task.push({ + cmd: "ALLOC", + var: 0, + len: result[i][0].byteLength + }); + task.push({ + cmd: "ALLOC", + var: 1, + len: result[i][0].byteLength + }); + for (let m = 0; m < 3; m++) { + task.push({ + cmd: "SET", + var: 0, + buff: result[i][m] + }); + for (let s = 1; s < nGroups; s++) { + task.push({ + cmd: "SET", + var: 1, + buff: result[s * concurrency + i][m] + }); + task.push({ + cmd: "CALL", + fnName: "qap_batchAdd", + params: [ + { var: 0 }, + { var: 1 }, + { val: result[i][m].length / curve.Fr.n8 }, + { var: 0 } + ] + }); + } + task.push({ + cmd: "GET", + out: m, + var: 0, + len: result[i][m].length + }); + } + promises2.push(curve.tm.queueAction(task)); + } + result = await Promise.all(promises2); + } + const outBuffA = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); + const outBuffB = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); + const outBuffC = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); + let p = 0; + for (let i = 0; i < result.length; i++) { + outBuffA.set(result[i][0], p); + outBuffB.set(result[i][1], p); + outBuffC.set(result[i][2], p); + p += result[i][0].byteLength; + } + return [ + outBuffA, + outBuffB, + outBuffC + ]; + function getCutPoint(v) { + let m = 0; + let n = getUint32(0); + while (m < n) { + var k = Math.floor((n + m) / 2); + const va = getUint32(4 + k * sCoef + 4); + if (va > v) n = k - 1; + else if (va < v) m = k + 1; + else n = k; + } + return 4 + m * sCoef; + } +} async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { - console.time("buildABC"); - const concurrency = 1;//curve.tm.concurrency; - const sCoef = 4 * 3 + zkey.n8r; - - let getUint32; - - if (coeffs instanceof ffjavascript.BigBuffer) { - const coeffsDV = []; - const PAGE_LEN = coeffs.buffers[0].length; - for (let i = 0; i < coeffs.buffers.length; i++) { - coeffsDV.push(new DataView(coeffs.buffers[i].buffer)); - } - getUint32 = function (pos) { - return coeffsDV[Math.floor(pos / PAGE_LEN)].getUint32(pos % PAGE_LEN, true); - }; - } else { - const coeffsDV = new DataView(coeffs.buffer, coeffs.byteOffset, coeffs.byteLength); - getUint32 = function (pos) { - return coeffsDV.getUint32(pos, true); - }; - } - - const elementsPerChunk = Math.floor((zkey.domainSize - 1) / concurrency) + 1; - const promises = []; - - const cutPoints = []; - for (let i = 0; i < concurrency; i++) { - cutPoints.push(getCutPoint(Math.floor(i * elementsPerChunk))); - } - cutPoints.push(coeffs.byteLength); - - //const chunkSize = 2**18; - const chunkSize = elementsPerChunk; - - console.log("zkey.domainSize", zkey.domainSize); - console.log("concurrency", concurrency); - console.log("elementsPerChunk", elementsPerChunk); - console.log("chunkSize", chunkSize); - - for (let s = 0; s < zkey.nVars; s += chunkSize) { - if (logger) logger.debug(`QAP: ${s}/${zkey.nVars}`); - const ns = Math.min(zkey.nVars - s, chunkSize); - - console.log("ns", ns); - - //let i=0; - for (let i = 0; i < concurrency; i++) { - let n; - if (i < concurrency - 1) { - n = elementsPerChunk; - } else { - n = zkey.domainSize - i * elementsPerChunk; - } - if (n === 0) continue; - - const task = []; - - const coeffsBuff = coeffs.slice(cutPoints[i], cutPoints[i + 1]); - const witnessBuff = witness.slice(s * curve.Fr.n8, (s + ns) * curve.Fr.n8); - - task.push({cmd: "ALLOCSET", var: 0, buff: coeffsBuff}); - task.push({cmd: "ALLOCSET", var: 1, buff: witnessBuff}); - task.push({cmd: "ALLOC", var: 2, len: n * curve.Fr.n8}); - task.push({cmd: "ALLOC", var: 3, len: n * curve.Fr.n8}); - task.push({cmd: "ALLOC", var: 4, len: n * curve.Fr.n8}); - task.push({ - cmd: "CALL", fnName: "qap_buildABC", params: [ - {var: 0}, - {val: (cutPoints[i + 1] - cutPoints[i]) / sCoef}, - {var: 1}, - {var: 2}, - {var: 3}, - {var: 4}, - {val: i * elementsPerChunk}, - {val: n}, - {val: s}, - {val: ns} - ] - }); - task.push({cmd: "GET", out: 0, var: 2, len: n * curve.Fr.n8}); - task.push({cmd: "GET", out: 1, var: 3, len: n * curve.Fr.n8}); - task.push({cmd: "GET", out: 2, var: 4, len: n * curve.Fr.n8}); - //task.push({cmd: "TERMINATE"}); // to free memory immediately - //promises.push(curve.tm.queueAction(task)); - promises.push(curve.tm.queueAction(task, [coeffsBuff.buffer, witnessBuff.buffer])); - } - } - - let result = await Promise.all(promises); - - - console.log("result.length", result.length); - console.log("result", result); - - const nGroups = result.length / concurrency; - - console.log("nGroups", nGroups); - let result2; - if (nGroups > 1) { - const promises2 = []; - for (let i = 0; i < concurrency; i++) { - const task = []; - task.push({cmd: "ALLOC", var: 0, len: result[i][0].byteLength}); - task.push({cmd: "ALLOC", var: 1, len: result[i][0].byteLength}); - for (let m = 0; m < 3; m++) { - task.push({cmd: "SET", var: 0, buff: result[i][m]}); - //transfers.push(result[i][m].buffer); - for (let s = 1; s < nGroups; s++) { - task.push({cmd: "SET", var: 1, buff: result[s * concurrency + i][m]}); - //transfers.push(result[s*concurrency + i][m].buffer); - task.push({ - cmd: "CALL", fnName: "qap_batchAdd", params: [ - {var: 0}, - {var: 1}, - {val: result[i][m].length / curve.Fr.n8}, - {var: 0} - ] - }); - } - task.push({cmd: "GET", out: m, var: 0, len: result[i][m].length}); - //task.push({cmd: "TERMINATE"}); // to free memory immediately - } - console.log("task.length", task.length); - //promises2.push(curve.tm.queueAction(task)); - promises2.push(curve.tm.queueAction(task, result.buffer)); - } - console.log("promises2.length", promises2.length); - result2 = await Promise.all(promises2); - result = result2; - } - - //console.log("result", result); - //console.log("result2", result2); - //result = result2 || result; - - const outBuffA = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); - const outBuffB = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); - const outBuffC = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); - let p = 0; - for (let i = 0; i < result.length; i++) { - outBuffA.set(result[i][0], p); - outBuffB.set(result[i][1], p); - outBuffC.set(result[i][2], p); - p += result[i][0].byteLength; - } - - console.timeEnd("buildABC"); - - return [outBuffA, outBuffB, outBuffC]; - - function getCutPoint(v) { - let m = 0; - let n = getUint32(0); - while (m < n) { - let k = Math.floor((n + m) / 2); - const va = getUint32(4 + k * sCoef + 4); - if (va > v) { - n = k - 1; - } else if (va < v) { - m = k + 1; - } else { - n = k; - } - } - return 4 + m * sCoef; - } -} - - + console.time("buildABC"); + const concurrency = 1; + const sCoef = 12 + zkey.n8r; + let getUint32; + if (coeffs instanceof ffjavascript.BigBuffer) { + const coeffsDV = []; + const PAGE_LEN = coeffs.buffers[0].length; + for (let i = 0; i < coeffs.buffers.length; i++) coeffsDV.push(new DataView(coeffs.buffers[i].buffer)); + getUint32 = function(pos) { + return coeffsDV[Math.floor(pos / PAGE_LEN)].getUint32(pos % PAGE_LEN, true); + }; + } else { + const coeffsDV = new DataView(coeffs.buffer, coeffs.byteOffset, coeffs.byteLength); + getUint32 = function(pos) { + return coeffsDV.getUint32(pos, true); + }; + } + const elementsPerChunk = Math.floor((zkey.domainSize - 1) / concurrency) + 1; + const promises = []; + const cutPoints = []; + for (let i = 0; i < concurrency; i++) cutPoints.push(getCutPoint(Math.floor(i * elementsPerChunk))); + cutPoints.push(coeffs.byteLength); + const chunkSize = elementsPerChunk; + console.log("zkey.domainSize", zkey.domainSize); + console.log("concurrency", concurrency); + console.log("elementsPerChunk", elementsPerChunk); + console.log("chunkSize", chunkSize); + for (let s = 0; s < zkey.nVars; s += chunkSize) { + if (logger) logger.debug(`QAP: ${s}/${zkey.nVars}`); + const ns = Math.min(zkey.nVars - s, chunkSize); + console.log("ns", ns); + for (let i = 0; i < concurrency; i++) { + let n; + if (i < concurrency - 1) n = elementsPerChunk; + else n = zkey.domainSize - i * elementsPerChunk; + if (n === 0) continue; + const task = []; + const coeffsBuff = coeffs.slice(cutPoints[i], cutPoints[i + 1]); + const witnessBuff = witness.slice(s * curve.Fr.n8, (s + ns) * curve.Fr.n8); + task.push({ + cmd: "ALLOCSET", + var: 0, + buff: coeffsBuff + }); + task.push({ + cmd: "ALLOCSET", + var: 1, + buff: witnessBuff + }); + task.push({ + cmd: "ALLOC", + var: 2, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "ALLOC", + var: 3, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "ALLOC", + var: 4, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "CALL", + fnName: "qap_buildABC", + params: [ + { var: 0 }, + { val: (cutPoints[i + 1] - cutPoints[i]) / sCoef }, + { var: 1 }, + { var: 2 }, + { var: 3 }, + { var: 4 }, + { val: i * elementsPerChunk }, + { val: n }, + { val: s }, + { val: ns } + ] + }); + task.push({ + cmd: "GET", + out: 0, + var: 2, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "GET", + out: 1, + var: 3, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "GET", + out: 2, + var: 4, + len: n * curve.Fr.n8 + }); + promises.push(curve.tm.queueAction(task, [coeffsBuff.buffer, witnessBuff.buffer])); + } + } + let result = await Promise.all(promises); + console.log("result.length", result.length); + console.log("result", result); + const nGroups = result.length / concurrency; + console.log("nGroups", nGroups); + let result2; + if (nGroups > 1) { + const promises2 = []; + for (let i = 0; i < concurrency; i++) { + const task = []; + task.push({ + cmd: "ALLOC", + var: 0, + len: result[i][0].byteLength + }); + task.push({ + cmd: "ALLOC", + var: 1, + len: result[i][0].byteLength + }); + for (let m = 0; m < 3; m++) { + task.push({ + cmd: "SET", + var: 0, + buff: result[i][m] + }); + for (let s = 1; s < nGroups; s++) { + task.push({ + cmd: "SET", + var: 1, + buff: result[s * concurrency + i][m] + }); + task.push({ + cmd: "CALL", + fnName: "qap_batchAdd", + params: [ + { var: 0 }, + { var: 1 }, + { val: result[i][m].length / curve.Fr.n8 }, + { var: 0 } + ] + }); + } + task.push({ + cmd: "GET", + out: m, + var: 0, + len: result[i][m].length + }); + } + console.log("task.length", task.length); + promises2.push(curve.tm.queueAction(task, result.buffer)); + } + console.log("promises2.length", promises2.length); + result2 = await Promise.all(promises2); + result = result2; + } + const outBuffA = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); + const outBuffB = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); + const outBuffC = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); + let p = 0; + for (let i = 0; i < result.length; i++) { + outBuffA.set(result[i][0], p); + outBuffB.set(result[i][1], p); + outBuffC.set(result[i][2], p); + p += result[i][0].byteLength; + } + console.timeEnd("buildABC"); + return [ + outBuffA, + outBuffB, + outBuffC + ]; + function getCutPoint(v) { + let m = 0; + let n = getUint32(0); + while (m < n) { + let k = Math.floor((n + m) / 2); + const va = getUint32(4 + k * sCoef + 4); + if (va > v) n = k - 1; + else if (va < v) m = k + 1; + else n = k; + } + return 4 + m * sCoef; + } +} async function joinABC(curve, zkey, a, b, c, logger) { - console.time("joinABC"); - const MAX_CHUNK_SIZE = 1 << 16; - - const n8 = curve.Fr.n8; - const nElements = Math.floor(a.byteLength / curve.Fr.n8); - - const promises = []; - - for (let i=0; i { - memUsage(logger); - }, interval); -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ -const { unstringifyBigInts: unstringifyBigInts$b} = ffjavascript.utils; - + if (!logger) return; + const used = process.memoryUsage(); + logger.debug(" ", "\x1B[0m Heap:\x1B[32m", `${Math.round(used.heapUsed / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m / \x1B[32m", `${Math.round(used.heapTotal / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m RSS:\x1B[32m", `${Math.round(used.rss / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m External:\x1B[32m", `${Math.round(used.external / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m ArrBuffers:\x1B[32m", `${Math.round(used.arrayBuffers / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m"); +} +function monitorMemoryUsage(logger, interval = 5e3) { + return setInterval(() => { + memUsage(logger); + }, interval); +} +//#endregion +//#region src/wtns_calculate.js +var { unstringifyBigInts: unstringifyBigInts$11 } = ffjavascript.utils; async function wtnsCalculate(_input, wasmFileName, wtnsFileName, options) { - const input = unstringifyBigInts$b(_input); - - const fdWasm = await fastFile__namespace.readExisting(wasmFileName); - const wasm = await fdWasm.read(fdWasm.totalSize); - await fdWasm.close(); - - const wc = await circom_runtime.WitnessCalculatorBuilder(wasm, options); - if (wc.circom_version() === 1) { - const w = await wc.calculateBinWitness(input); - - const fdWtns = await binFileUtils__namespace.createBinFile(wtnsFileName, "wtns", 2, 2); - - await writeBin(fdWtns, w, wc.prime); - await fdWtns.close(); - } else { - const fdWtns = await fastFile__namespace.createOverride(wtnsFileName); - - const w = await wc.calculateWTNSBin(input); - - await fdWtns.write(w); - await fdWtns.close(); - } -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ -const {unstringifyBigInts: unstringifyBigInts$a} = ffjavascript.utils; - + const input = unstringifyBigInts$11(_input); + const fdWasm = await fastfile.readExisting(wasmFileName); + const wasm = await fdWasm.read(fdWasm.totalSize); + await fdWasm.close(); + const wc = await (0, circom_runtime.WitnessCalculatorBuilder)(wasm, options); + if (wc.circom_version() === 1) { + const w = await wc.calculateBinWitness(input); + const fdWtns = await _iden3_binfileutils.createBinFile(wtnsFileName, "wtns", 2, 2); + await writeBin(fdWtns, w, wc.prime); + await fdWtns.close(); + } else { + const fdWtns = await fastfile.createOverride(wtnsFileName); + const w = await wc.calculateWTNSBin(input); + await fdWtns.write(w); + await fdWtns.close(); + } +} +//#endregion +//#region src/groth16_fullprove.js +var { unstringifyBigInts: unstringifyBigInts$10 } = ffjavascript.utils; async function groth16FullProve(_input, wasmFile, zkeyFileName, logger, wtnsCalcOptions, proverOptions) { - const input = unstringifyBigInts$a(_input); - - const wtns= { - type: "mem" - }; - await wtnsCalculate(input, wasmFile, wtns, wtnsCalcOptions); - return await groth16Prove(zkeyFileName, wtns, logger, proverOptions); -} - -/* - Copyright 2018 0kims association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ -const {unstringifyBigInts: unstringifyBigInts$9} = ffjavascript.utils; - + const input = unstringifyBigInts$10(_input); + const wtns = { type: "mem" }; + await wtnsCalculate(input, wasmFile, wtns, wtnsCalcOptions); + return await groth16Prove(zkeyFileName, wtns, logger, proverOptions); +} +//#endregion +//#region src/groth16_verify.js +var { unstringifyBigInts: unstringifyBigInts$9 } = ffjavascript.utils; async function groth16Verify(_vk_verifier, _publicSignals, _proof, logger) { -/* - let cpub = vk_verifier.IC[0]; - for (let s= 0; s< vk_verifier.nPublic; s++) { - cpub = G1.add( cpub, G1.timesScalar( vk_verifier.IC[s+1], publicSignals[s])); - } -*/ - - const vk_verifier = unstringifyBigInts$9(_vk_verifier); - const proof = unstringifyBigInts$9(_proof); - const publicSignals = unstringifyBigInts$9(_publicSignals); - - const curve = await getCurveFromName(vk_verifier.curve); - - const IC0 = curve.G1.fromObject(vk_verifier.IC[0]); - const IC = new Uint8Array(curve.G1.F.n8*2 * publicSignals.length); - const w = new Uint8Array(curve.Fr.n8 * publicSignals.length); - - if (!publicInputsAreValid$2(curve, publicSignals)) { - if (logger) logger.error("Public inputs are not valid."); - return false; - } - - for (let i=0; i. -*/ -const { unstringifyBigInts: unstringifyBigInts$8} = ffjavascript.utils; - + for (let i = 0; i < publicInputs.length; i++) if (!checkValueBelongToField$2(curve, publicInputs[i])) return false; + return true; +} +//#endregion +//#region src/groth16_exportsoliditycalldata.js +var { unstringifyBigInts: unstringifyBigInts$8 } = ffjavascript.utils; function p256$2(n) { - let nstr = n.toString(16); - while (nstr.length < 64) nstr = "0"+nstr; - nstr = `"0x${nstr}"`; - return nstr; + let nstr = n.toString(16); + while (nstr.length < 64) nstr = "0" + nstr; + nstr = `"0x${nstr}"`; + return nstr; } - async function groth16ExportSolidityCallData(_proof, _pub) { - const proof = unstringifyBigInts$8(_proof); - const pub = unstringifyBigInts$8(_pub); - - let inputs = ""; - for (let i=0; i. -*/ - -var groth16 = /*#__PURE__*/Object.freeze({ - __proto__: null, - fullProve: groth16FullProve, - prove: groth16Prove, - verify: groth16Verify, - exportSolidityCallData: groth16ExportSolidityCallData + const proof = unstringifyBigInts$8(_proof); + const pub = unstringifyBigInts$8(_pub); + let inputs = ""; + for (let i = 0; i < pub.length; i++) { + if (inputs != "") inputs = inputs + ","; + inputs = inputs + p256$2(pub[i]); + } + let S; + S = `[${p256$2(proof.pi_a[0])}, ${p256$2(proof.pi_a[1])}],[[${p256$2(proof.pi_b[0][1])}, ${p256$2(proof.pi_b[0][0])}],[${p256$2(proof.pi_b[1][1])}, ${p256$2(proof.pi_b[1][0])}]],[${p256$2(proof.pi_c[0])}, ${p256$2(proof.pi_c[1])}],[${inputs}]`; + return S; +} +//#endregion +//#region src/groth16.js +var groth16_exports = /* @__PURE__ */ __exportAll({ + exportSolidityCallData: () => groth16ExportSolidityCallData, + fullProve: () => groth16FullProve, + prove: () => groth16Prove, + verify: () => groth16Verify }); - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - +//#endregion +//#region src/keypair.js function hashToG2(curve, hash) { - const hashV = new DataView(hash.buffer, hash.byteOffset, hash.byteLength); - const seed = []; - for (let i=0; i<8; i++) { - seed[i] = hashV.getUint32(i*4); - } - - const rng = new ffjavascript.ChaCha(seed); - - const g2_sp = curve.G2.fromRng(rng); - - return g2_sp; -} - + const hashV = new DataView(hash.buffer, hash.byteOffset, hash.byteLength); + const seed = []; + for (let i = 0; i < 8; i++) seed[i] = hashV.getUint32(i * 4); + const rng = new ffjavascript.ChaCha(seed); + return curve.G2.fromRng(rng); +} function getG2sp(curve, persinalization, challenge, g1s, g1sx) { - - const h = blake2b.blake2b.create({ dkLen: 64 }); - const b1 = new Uint8Array([persinalization]); - h.update(b1); - h.update(challenge); - const b3 = curve.G1.toUncompressed(g1s); - h.update( b3); - const b4 = curve.G1.toUncompressed(g1sx); - h.update( b4); - const hash =h.digest(); - - return hashToG2(curve, hash); -} - -function calculatePubKey(k, curve, personalization, challengeHash, rng ) { - k.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); - k.g1_sx = curve.G1.toAffine(curve.G1.timesFr(k.g1_s, k.prvKey)); - k.g2_sp = curve.G2.toAffine(getG2sp(curve, personalization, challengeHash, k.g1_s, k.g1_sx)); - k.g2_spx = curve.G2.toAffine(curve.G2.timesFr(k.g2_sp, k.prvKey)); - return k; -} - + const h = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + const b1 = new Uint8Array([persinalization]); + h.update(b1); + h.update(challenge); + const b3 = curve.G1.toUncompressed(g1s); + h.update(b3); + const b4 = curve.G1.toUncompressed(g1sx); + h.update(b4); + return hashToG2(curve, h.digest()); +} +function calculatePubKey(k, curve, personalization, challengeHash, rng) { + k.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); + k.g1_sx = curve.G1.toAffine(curve.G1.timesFr(k.g1_s, k.prvKey)); + k.g2_sp = curve.G2.toAffine(getG2sp(curve, personalization, challengeHash, k.g1_s, k.g1_sx)); + k.g2_spx = curve.G2.toAffine(curve.G2.timesFr(k.g2_sp, k.prvKey)); + return k; +} function createPTauKey(curve, challengeHash, rng) { - const key = { - tau: {}, - alpha: {}, - beta: {} - }; - key.tau.prvKey = curve.Fr.fromRng(rng); - key.alpha.prvKey = curve.Fr.fromRng(rng); - key.beta.prvKey = curve.Fr.fromRng(rng); - calculatePubKey(key.tau, curve, 0, challengeHash, rng); - calculatePubKey(key.alpha, curve, 1, challengeHash, rng); - calculatePubKey(key.beta, curve, 2, challengeHash, rng); - return key; -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - + const key = { + tau: {}, + alpha: {}, + beta: {} + }; + key.tau.prvKey = curve.Fr.fromRng(rng); + key.alpha.prvKey = curve.Fr.fromRng(rng); + key.beta.prvKey = curve.Fr.fromRng(rng); + calculatePubKey(key.tau, curve, 0, challengeHash, rng); + calculatePubKey(key.alpha, curve, 1, challengeHash, rng); + calculatePubKey(key.beta, curve, 2, challengeHash, rng); + return key; +} +//#endregion +//#region src/powersoftau_utils.js async function writePTauHeader(fd, curve, power, ceremonyPower) { - // Write the header - /////////// - - if (! ceremonyPower) ceremonyPower = power; - await fd.writeULE32(1); // Header type - const pHeaderSize = fd.pos; - await fd.writeULE64(0); // Temporally set to 0 length - - await fd.writeULE32(curve.F1.n64*8); - - const buff = new Uint8Array(curve.F1.n8); - ffjavascript.Scalar.toRprLE(buff, 0, curve.q, curve.F1.n8); - await fd.write(buff); - await fd.writeULE32(power); // power - await fd.writeULE32(ceremonyPower); // power - - const headerSize = fd.pos - pHeaderSize - 8; - - const oldPos = fd.pos; - - await fd.writeULE64(headerSize, pHeaderSize); - - fd.pos = oldPos; -} - + if (!ceremonyPower) ceremonyPower = power; + await fd.writeULE32(1); + const pHeaderSize = fd.pos; + await fd.writeULE64(0); + await fd.writeULE32(curve.F1.n64 * 8); + const buff = new Uint8Array(curve.F1.n8); + ffjavascript.Scalar.toRprLE(buff, 0, curve.q, curve.F1.n8); + await fd.write(buff); + await fd.writeULE32(power); + await fd.writeULE32(ceremonyPower); + const headerSize = fd.pos - pHeaderSize - 8; + const oldPos = fd.pos; + await fd.writeULE64(headerSize, pHeaderSize); + fd.pos = oldPos; +} async function readPTauHeader(fd, sections) { - if (!sections[1]) throw new Error(fd.fileName + ": File has no header"); - if (sections[1].length>1) throw new Error(fd.fileName +": File has more than one header"); - - fd.pos = sections[1][0].p; - const n8 = await fd.readULE32(); - const buff = await fd.read(n8); - const q = ffjavascript.Scalar.fromRprLE(buff); - - const curve = await getCurveFromQ(q); - - if (curve.F1.n64*8 != n8) throw new Error(fd.fileName +": Invalid size"); - - const power = await fd.readULE32(); - const ceremonyPower = await fd.readULE32(); - - if (fd.pos-sections[1][0].p != sections[1][0].size) throw new Error("Invalid PTau header size"); - - return {curve, power, ceremonyPower}; -} - - + if (!sections[1]) throw new Error(fd.fileName + ": File has no header"); + if (sections[1].length > 1) throw new Error(fd.fileName + ": File has more than one header"); + fd.pos = sections[1][0].p; + const n8 = await fd.readULE32(); + const buff = await fd.read(n8); + const curve = await getCurveFromQ(ffjavascript.Scalar.fromRprLE(buff)); + if (curve.F1.n64 * 8 != n8) throw new Error(fd.fileName + ": Invalid size"); + const power = await fd.readULE32(); + const ceremonyPower = await fd.readULE32(); + if (fd.pos - sections[1][0].p != sections[1][0].size) throw new Error("Invalid PTau header size"); + return { + curve, + power, + ceremonyPower + }; +} async function readPtauPubKey(fd, curve, montgomery) { - - const buff = await fd.read(curve.F1.n8*2*6 + curve.F2.n8*2*3); - - return fromPtauPubKeyRpr(buff, 0, curve, montgomery); + return fromPtauPubKeyRpr(await fd.read(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3), 0, curve, montgomery); } - function fromPtauPubKeyRpr(buff, pos, curve, montgomery) { - - const key = { - tau: {}, - alpha: {}, - beta: {} - }; - - key.tau.g1_s = readG1(); - key.tau.g1_sx = readG1(); - key.alpha.g1_s = readG1(); - key.alpha.g1_sx = readG1(); - key.beta.g1_s = readG1(); - key.beta.g1_sx = readG1(); - key.tau.g2_spx = readG2(); - key.alpha.g2_spx = readG2(); - key.beta.g2_spx = readG2(); - - return key; - - function readG1() { - let p; - if (montgomery) { - p = curve.G1.fromRprLEM( buff, pos ); - } else { - p = curve.G1.fromRprUncompressed( buff, pos ); - } - pos += curve.G1.F.n8*2; - return p; - } - - function readG2() { - let p; - if (montgomery) { - p = curve.G2.fromRprLEM( buff, pos ); - } else { - p = curve.G2.fromRprUncompressed( buff, pos ); - } - pos += curve.G2.F.n8*2; - return p; - } -} - + const key = { + tau: {}, + alpha: {}, + beta: {} + }; + key.tau.g1_s = readG1(); + key.tau.g1_sx = readG1(); + key.alpha.g1_s = readG1(); + key.alpha.g1_sx = readG1(); + key.beta.g1_s = readG1(); + key.beta.g1_sx = readG1(); + key.tau.g2_spx = readG2(); + key.alpha.g2_spx = readG2(); + key.beta.g2_spx = readG2(); + return key; + function readG1() { + let p; + if (montgomery) p = curve.G1.fromRprLEM(buff, pos); + else p = curve.G1.fromRprUncompressed(buff, pos); + pos += curve.G1.F.n8 * 2; + return p; + } + function readG2() { + let p; + if (montgomery) p = curve.G2.fromRprLEM(buff, pos); + else p = curve.G2.fromRprUncompressed(buff, pos); + pos += curve.G2.F.n8 * 2; + return p; + } +} function toPtauPubKeyRpr(buff, pos, curve, key, montgomery) { - - writeG1(key.tau.g1_s); - writeG1(key.tau.g1_sx); - writeG1(key.alpha.g1_s); - writeG1(key.alpha.g1_sx); - writeG1(key.beta.g1_s); - writeG1(key.beta.g1_sx); - writeG2(key.tau.g2_spx); - writeG2(key.alpha.g2_spx); - writeG2(key.beta.g2_spx); - - async function writeG1(p) { - if (montgomery) { - curve.G1.toRprLEM(buff, pos, p); - } else { - curve.G1.toRprUncompressed(buff, pos, p); - } - pos += curve.F1.n8*2; - } - - async function writeG2(p) { - if (montgomery) { - curve.G2.toRprLEM(buff, pos, p); - } else { - curve.G2.toRprUncompressed(buff, pos, p); - } - pos += curve.F2.n8*2; - } - - return buff; -} - + writeG1(key.tau.g1_s); + writeG1(key.tau.g1_sx); + writeG1(key.alpha.g1_s); + writeG1(key.alpha.g1_sx); + writeG1(key.beta.g1_s); + writeG1(key.beta.g1_sx); + writeG2(key.tau.g2_spx); + writeG2(key.alpha.g2_spx); + writeG2(key.beta.g2_spx); + async function writeG1(p) { + if (montgomery) curve.G1.toRprLEM(buff, pos, p); + else curve.G1.toRprUncompressed(buff, pos, p); + pos += curve.F1.n8 * 2; + } + async function writeG2(p) { + if (montgomery) curve.G2.toRprLEM(buff, pos, p); + else curve.G2.toRprUncompressed(buff, pos, p); + pos += curve.F2.n8 * 2; + } + return buff; +} async function writePtauPubKey(fd, curve, key, montgomery) { - const buff = new Uint8Array(curve.F1.n8*2*6 + curve.F2.n8*2*3); - toPtauPubKeyRpr(buff, 0, curve, key, montgomery); - await fd.write(buff); + const buff = new Uint8Array(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3); + toPtauPubKeyRpr(buff, 0, curve, key, montgomery); + await fd.write(buff); } - async function readContribution(fd, curve) { - const c = {}; - - c.tauG1 = await readG1(); - c.tauG2 = await readG2(); - c.alphaG1 = await readG1(); - c.betaG1 = await readG1(); - c.betaG2 = await readG2(); - c.key = await readPtauPubKey(fd, curve, true); - c.partialHash = await fd.read(216); - c.nextChallenge = await fd.read(64); - c.type = await fd.readULE32(); - - const buffV = new Uint8Array(curve.G1.F.n8*2*6+curve.G2.F.n8*2*3); - toPtauPubKeyRpr(buffV, 0, curve, c.key, false); - - const responseHasher = fromPartialHash(c.partialHash); - responseHasher.update(buffV); - c.responseHash = responseHasher.digest(); - - const paramLength = await fd.readULE32(); - const curPos = fd.pos; - let lastType =0; - while (fd.pos-curPos < paramLength) { - const buffType = await readDV(1); - if (buffType[0]<= lastType) throw new Error("Parameters in the contribution must be sorted"); - lastType = buffType[0]; - if (buffType[0]==1) { // Name - const buffLen = await readDV(1); - const buffStr = await readDV(buffLen[0]); - c.name = new TextDecoder().decode(buffStr); - } else if (buffType[0]==2) { - const buffExp = await readDV(1); - c.numIterationsExp = buffExp[0]; - } else if (buffType[0]==3) { - const buffLen = await readDV(1); - c.beaconHash = await readDV(buffLen[0]); - } else { - throw new Error("Parameter not recognized"); - } - } - if (fd.pos != curPos + paramLength) { - throw new Error("Parameters do not match"); - } - - return c; - - async function readG1() { - const pBuff = await fd.read(curve.G1.F.n8*2); - return curve.G1.fromRprLEM( pBuff ); - } - - async function readG2() { - const pBuff = await fd.read(curve.G2.F.n8*2); - return curve.G2.fromRprLEM( pBuff ); - } - - async function readDV(n) { - const b = await fd.read(n); - return new Uint8Array(b); - } -} - + const c = {}; + c.tauG1 = await readG1(); + c.tauG2 = await readG2(); + c.alphaG1 = await readG1(); + c.betaG1 = await readG1(); + c.betaG2 = await readG2(); + c.key = await readPtauPubKey(fd, curve, true); + c.partialHash = await fd.read(216); + c.nextChallenge = await fd.read(64); + c.type = await fd.readULE32(); + const buffV = new Uint8Array(curve.G1.F.n8 * 2 * 6 + curve.G2.F.n8 * 2 * 3); + toPtauPubKeyRpr(buffV, 0, curve, c.key, false); + const responseHasher = fromPartialHash(c.partialHash); + responseHasher.update(buffV); + c.responseHash = responseHasher.digest(); + const paramLength = await fd.readULE32(); + const curPos = fd.pos; + let lastType = 0; + while (fd.pos - curPos < paramLength) { + const buffType = await readDV(1); + if (buffType[0] <= lastType) throw new Error("Parameters in the contribution must be sorted"); + lastType = buffType[0]; + if (buffType[0] == 1) { + const buffStr = await readDV((await readDV(1))[0]); + c.name = new TextDecoder().decode(buffStr); + } else if (buffType[0] == 2) c.numIterationsExp = (await readDV(1))[0]; + else if (buffType[0] == 3) c.beaconHash = await readDV((await readDV(1))[0]); + else throw new Error("Parameter not recognized"); + } + if (fd.pos != curPos + paramLength) throw new Error("Parameters do not match"); + return c; + async function readG1() { + const pBuff = await fd.read(curve.G1.F.n8 * 2); + return curve.G1.fromRprLEM(pBuff); + } + async function readG2() { + const pBuff = await fd.read(curve.G2.F.n8 * 2); + return curve.G2.fromRprLEM(pBuff); + } + async function readDV(n) { + const b = await fd.read(n); + return new Uint8Array(b); + } +} async function readContributions(fd, curve, sections) { - if (!sections[7]) throw new Error(fd.fileName + ": File has no contributions"); - if (sections[7][0].length>1) throw new Error(fd.fileName +": File has more than one contributions section"); - - fd.pos = sections[7][0].p; - const nContributions = await fd.readULE32(); - const contributions = []; - for (let i=0; i 1) throw new Error(fd.fileName + ": File has more than one contributions section"); + fd.pos = sections[7][0].p; + const nContributions = await fd.readULE32(); + const contributions = []; + for (let i = 0; i < nContributions; i++) { + const c = await readContribution(fd, curve); + c.id = i + 1; + contributions.push(c); + } + if (fd.pos - sections[7][0].p != sections[7][0].size) throw new Error("Invalid contribution section size"); + return contributions; +} async function writeContribution(fd, curve, contribution) { - - const buffG1 = new Uint8Array(curve.F1.n8*2); - const buffG2 = new Uint8Array(curve.F2.n8*2); - await writeG1(contribution.tauG1); - await writeG2(contribution.tauG2); - await writeG1(contribution.alphaG1); - await writeG1(contribution.betaG1); - await writeG2(contribution.betaG2); - await writePtauPubKey(fd, curve, contribution.key, true); - await fd.write(contribution.partialHash); - await fd.write(contribution.nextChallenge); - await fd.writeULE32(contribution.type || 0); - - const params = []; - if (contribution.name) { - params.push(1); // Param Name - const nameData = new TextEncoder("utf-8").encode(contribution.name.substring(0,64)); - params.push(nameData.byteLength); - for (let i=0; i0) { - const paramsBuff = new Uint8Array(params); - await fd.writeULE32(paramsBuff.byteLength); - await fd.write(paramsBuff); - } else { - await fd.writeULE32(0); - } - - - async function writeG1(p) { - curve.G1.toRprLEM(buffG1, 0, p); - await fd.write(buffG1); - } - - async function writeG2(p) { - curve.G2.toRprLEM(buffG2, 0, p); - await fd.write(buffG2); - } - -} - + const buffG1 = new Uint8Array(curve.F1.n8 * 2); + const buffG2 = new Uint8Array(curve.F2.n8 * 2); + await writeG1(contribution.tauG1); + await writeG2(contribution.tauG2); + await writeG1(contribution.alphaG1); + await writeG1(contribution.betaG1); + await writeG2(contribution.betaG2); + await writePtauPubKey(fd, curve, contribution.key, true); + await fd.write(contribution.partialHash); + await fd.write(contribution.nextChallenge); + await fd.writeULE32(contribution.type || 0); + const params = []; + if (contribution.name) { + params.push(1); + const nameData = new TextEncoder("utf-8").encode(contribution.name.substring(0, 64)); + params.push(nameData.byteLength); + for (let i = 0; i < nameData.byteLength; i++) params.push(nameData[i]); + } + if (contribution.type == 1) { + params.push(2); + params.push(contribution.numIterationsExp); + params.push(3); + params.push(contribution.beaconHash.byteLength); + for (let i = 0; i < contribution.beaconHash.byteLength; i++) params.push(contribution.beaconHash[i]); + } + if (params.length > 0) { + const paramsBuff = new Uint8Array(params); + await fd.writeULE32(paramsBuff.byteLength); + await fd.write(paramsBuff); + } else await fd.writeULE32(0); + async function writeG1(p) { + curve.G1.toRprLEM(buffG1, 0, p); + await fd.write(buffG1); + } + async function writeG2(p) { + curve.G2.toRprLEM(buffG2, 0, p); + await fd.write(buffG2); + } +} async function writeContributions(fd, curve, contributions) { - - await fd.writeULE32(7); // Header type - const pContributionsSize = fd.pos; - await fd.writeULE64(0); // Temporally set to 0 length - - await fd.writeULE32(contributions.length); - for (let i=0; i< contributions.length; i++) { - await writeContribution(fd, curve, contributions[i]); - } - const contributionsSize = fd.pos - pContributionsSize - 8; - - const oldPos = fd.pos; - - await fd.writeULE64(contributionsSize, pContributionsSize); - fd.pos = oldPos; -} - + await fd.writeULE32(7); + const pContributionsSize = fd.pos; + await fd.writeULE64(0); + await fd.writeULE32(contributions.length); + for (let i = 0; i < contributions.length; i++) await writeContribution(fd, curve, contributions[i]); + const contributionsSize = fd.pos - pContributionsSize - 8; + const oldPos = fd.pos; + await fd.writeULE64(contributionsSize, pContributionsSize); + fd.pos = oldPos; +} function calculateFirstChallengeHash(curve, power, logger) { - if (logger) logger.debug("Calculating First Challenge Hash"); - - const hasher = blake2b.blake2b.create({ dkLen: 64 }); - - const vG1 = new Uint8Array(curve.G1.F.n8*2); - const vG2 = new Uint8Array(curve.G2.F.n8*2); - curve.G1.toRprUncompressed(vG1, 0, curve.G1.g); - curve.G2.toRprUncompressed(vG2, 0, curve.G2.g); - - hasher.update(blake2b.blake2b.create({ dkLen: 64 }).digest()); - - let n; - - n=(2 ** power)*2 -1; - if (logger) logger.debug("Calculate Initial Hash: tauG1"); - hashBlock(vG1, n); - n= 2 ** power; - if (logger) logger.debug("Calculate Initial Hash: tauG2"); - hashBlock(vG2, n); - if (logger) logger.debug("Calculate Initial Hash: alphaTauG1"); - hashBlock(vG1, n); - if (logger) logger.debug("Calculate Initial Hash: betaTauG1"); - hashBlock(vG1, n); - hasher.update(vG2); - - return hasher.digest(); - - function hashBlock(buff, n) { - // this block size is a good compromise between speed and the maximum - // input size of the Blake2b update method (65,535,720 bytes). - const blockSize = 341000; - const nBlocks = Math.floor(n / blockSize); - const rem = n % blockSize; - const bigBuff = new Uint8Array(blockSize * buff.byteLength); - for (let i=0; i. -*/ - + return createPTauKey(curve, challengeHash, await rngFromBeaconParams(beaconHash, numIterationsExp)); +} +//#endregion +//#region src/powersoftau_new.js async function newAccumulator(curve, power, fileName, logger) { - - const fd = await binFileUtils__namespace.createBinFile(fileName, "ptau", 1, 7); - - await writePTauHeader(fd, curve, power, 0); - - const buffG1 = curve.G1.oneAffine; - const buffG2 = curve.G2.oneAffine; - - // Write tauG1 - /////////// - await binFileUtils__namespace.startWriteSection(fd, 2); - const nTauG1 = (2 ** power) * 2 -1; - for (let i=0; i< nTauG1; i++) { - await fd.write(buffG1); - if ((logger)&&((i%100000) == 0)&&i) logger.log("tauG1: " + i); - } - await binFileUtils__namespace.endWriteSection(fd); - - // Write tauG2 - /////////// - await binFileUtils__namespace.startWriteSection(fd, 3); - const nTauG2 = (2 ** power); - for (let i=0; i< nTauG2; i++) { - await fd.write(buffG2); - if ((logger)&&((i%100000) == 0)&&i) logger.log("tauG2: " + i); - } - await binFileUtils__namespace.endWriteSection(fd); - - // Write alphaTauG1 - /////////// - await binFileUtils__namespace.startWriteSection(fd, 4); - const nAlfaTauG1 = (2 ** power); - for (let i=0; i< nAlfaTauG1; i++) { - await fd.write(buffG1); - if ((logger)&&((i%100000) == 0)&&i) logger.log("alphaTauG1: " + i); - } - await binFileUtils__namespace.endWriteSection(fd); - - // Write betaTauG1 - /////////// - await binFileUtils__namespace.startWriteSection(fd, 5); - const nBetaTauG1 = (2 ** power); - for (let i=0; i< nBetaTauG1; i++) { - await fd.write(buffG1); - if ((logger)&&((i%100000) == 0)&&i) logger.log("betaTauG1: " + i); - } - await binFileUtils__namespace.endWriteSection(fd); - - // Write betaG2 - /////////// - await binFileUtils__namespace.startWriteSection(fd, 6); - await fd.write(buffG2); - await binFileUtils__namespace.endWriteSection(fd); - - // Contributions - /////////// - await binFileUtils__namespace.startWriteSection(fd, 7); - await fd.writeULE32(0); // 0 Contributions - await binFileUtils__namespace.endWriteSection(fd); - - await fd.close(); - - const firstChallengeHash = calculateFirstChallengeHash(curve, power, logger); - - if (logger) logger.debug(formatHash(blake2b.blake2b.create({ dkLen: 64 }).digest(), "Blank Contribution Hash:")); - - if (logger) logger.info(formatHash(firstChallengeHash, "First Contribution Hash:")); - - return firstChallengeHash; - -} - -// Format of the outpu - + const fd = await _iden3_binfileutils.createBinFile(fileName, "ptau", 1, 7); + await writePTauHeader(fd, curve, power, 0); + const buffG1 = curve.G1.oneAffine; + const buffG2 = curve.G2.oneAffine; + await _iden3_binfileutils.startWriteSection(fd, 2); + const nTauG1 = 2 ** power * 2 - 1; + for (let i = 0; i < nTauG1; i++) { + await fd.write(buffG1); + if (logger && i % 1e5 == 0 && i) logger.log("tauG1: " + i); + } + await _iden3_binfileutils.endWriteSection(fd); + await _iden3_binfileutils.startWriteSection(fd, 3); + const nTauG2 = 2 ** power; + for (let i = 0; i < nTauG2; i++) { + await fd.write(buffG2); + if (logger && i % 1e5 == 0 && i) logger.log("tauG2: " + i); + } + await _iden3_binfileutils.endWriteSection(fd); + await _iden3_binfileutils.startWriteSection(fd, 4); + const nAlfaTauG1 = 2 ** power; + for (let i = 0; i < nAlfaTauG1; i++) { + await fd.write(buffG1); + if (logger && i % 1e5 == 0 && i) logger.log("alphaTauG1: " + i); + } + await _iden3_binfileutils.endWriteSection(fd); + await _iden3_binfileutils.startWriteSection(fd, 5); + const nBetaTauG1 = 2 ** power; + for (let i = 0; i < nBetaTauG1; i++) { + await fd.write(buffG1); + if (logger && i % 1e5 == 0 && i) logger.log("betaTauG1: " + i); + } + await _iden3_binfileutils.endWriteSection(fd); + await _iden3_binfileutils.startWriteSection(fd, 6); + await fd.write(buffG2); + await _iden3_binfileutils.endWriteSection(fd); + await _iden3_binfileutils.startWriteSection(fd, 7); + await fd.writeULE32(0); + await _iden3_binfileutils.endWriteSection(fd); + await fd.close(); + const firstChallengeHash = calculateFirstChallengeHash(curve, power, logger); + if (logger) logger.debug(formatHash(_noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }).digest(), "Blank Contribution Hash:")); + if (logger) logger.info(formatHash(firstChallengeHash, "First Contribution Hash:")); + return firstChallengeHash; +} +//#endregion +//#region src/powersoftau_export_challenge.js async function exportChallenge(pTauFilename, challengeFilename, logger) { - const {fd: fdFrom, sections} = await binFileUtils__namespace.readBinFile(pTauFilename, "ptau", 1); - - const {curve, power} = await readPTauHeader(fdFrom, sections); - - const contributions = await readContributions(fdFrom, curve, sections); - let lastResponseHash, curChallengeHash; - if (contributions.length == 0) { - lastResponseHash = blake2b.blake2b.create({ dkLen: 64 }).digest(); - curChallengeHash = calculateFirstChallengeHash(curve, power); - } else { - lastResponseHash = contributions[contributions.length-1].responseHash; - curChallengeHash = contributions[contributions.length-1].nextChallenge; - } - - if (logger) logger.info(formatHash(lastResponseHash, "Last Response Hash: ")); - - if (logger) logger.info(formatHash(curChallengeHash, "New Challenge Hash: ")); - - - const fdTo = await fastFile__namespace.createOverride(challengeFilename); - - const toHash = blake2b.blake2b.create({ dkLen: 64 }); - await fdTo.write(lastResponseHash); - toHash.update(lastResponseHash); - - await exportSection(2, "G1", (2 ** power) * 2 -1, "tauG1"); - await exportSection(3, "G2", (2 ** power) , "tauG2"); - await exportSection(4, "G1", (2 ** power) , "alphaTauG1"); - await exportSection(5, "G1", (2 ** power) , "betaTauG1"); - await exportSection(6, "G2", 1 , "betaG2"); - - await fdFrom.close(); - await fdTo.close(); - - const calcCurChallengeHash = toHash.digest(); - - if (!hashIsEqual (curChallengeHash, calcCurChallengeHash)) { - if (logger) logger.info(formatHash(calcCurChallengeHash, "Calc Curret Challenge Hash: ")); - - if (logger) logger.error("PTau file is corrupted. Calculated new challenge hash does not match with the eclared one"); - throw new Error("PTau file is corrupted. Calculated new challenge hash does not match with the eclared one"); - } - - return curChallengeHash; - - async function exportSection(sectionId, groupName, nPoints, sectionName) { - const G = curve[groupName]; - const sG = G.F.n8*2; - const nPointsChunk = Math.floor((1<<24)/sG); - - await binFileUtils__namespace.startReadUniqueSection(fdFrom, sections, sectionId); - for (let i=0; i< nPoints; i+= nPointsChunk) { - if (logger) logger.debug(`Exporting ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints-i, nPointsChunk); - let buff; - buff = await fdFrom.read(n*sG); - buff = await G.batchLEMtoU(buff); - await fdTo.write(buff); - toHash.update(buff); - } - await binFileUtils__namespace.endReadSection(fdFrom); - } - - -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - + const { fd: fdFrom, sections } = await _iden3_binfileutils.readBinFile(pTauFilename, "ptau", 1); + const { curve, power } = await readPTauHeader(fdFrom, sections); + const contributions = await readContributions(fdFrom, curve, sections); + let lastResponseHash, curChallengeHash; + if (contributions.length == 0) { + lastResponseHash = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }).digest(); + curChallengeHash = calculateFirstChallengeHash(curve, power); + } else { + lastResponseHash = contributions[contributions.length - 1].responseHash; + curChallengeHash = contributions[contributions.length - 1].nextChallenge; + } + if (logger) logger.info(formatHash(lastResponseHash, "Last Response Hash: ")); + if (logger) logger.info(formatHash(curChallengeHash, "New Challenge Hash: ")); + const fdTo = await fastfile.createOverride(challengeFilename); + const toHash = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + await fdTo.write(lastResponseHash); + toHash.update(lastResponseHash); + await exportSection(2, "G1", 2 ** power * 2 - 1, "tauG1"); + await exportSection(3, "G2", 2 ** power, "tauG2"); + await exportSection(4, "G1", 2 ** power, "alphaTauG1"); + await exportSection(5, "G1", 2 ** power, "betaTauG1"); + await exportSection(6, "G2", 1, "betaG2"); + await fdFrom.close(); + await fdTo.close(); + const calcCurChallengeHash = toHash.digest(); + if (!hashIsEqual(curChallengeHash, calcCurChallengeHash)) { + if (logger) logger.info(formatHash(calcCurChallengeHash, "Calc Curret Challenge Hash: ")); + if (logger) logger.error("PTau file is corrupted. Calculated new challenge hash does not match with the eclared one"); + throw new Error("PTau file is corrupted. Calculated new challenge hash does not match with the eclared one"); + } + return curChallengeHash; + async function exportSection(sectionId, groupName, nPoints, sectionName) { + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const nPointsChunk = Math.floor((1 << 24) / sG); + await _iden3_binfileutils.startReadUniqueSection(fdFrom, sections, sectionId); + for (let i = 0; i < nPoints; i += nPointsChunk) { + if (logger) logger.debug(`Exporting ${sectionName}: ${i}/${nPoints}`); + const n = Math.min(nPoints - i, nPointsChunk); + let buff; + buff = await fdFrom.read(n * sG); + buff = await G.batchLEMtoU(buff); + await fdTo.write(buff); + toHash.update(buff); + } + await _iden3_binfileutils.endReadSection(fdFrom); + } +} +//#endregion +//#region src/powersoftau_import.js async function importResponse(oldPtauFilename, contributionFilename, newPTauFilename, name, importPoints, logger) { - - const noHash = new Uint8Array(64); - for (let i=0; i<64; i++) noHash[i] = 0xFF; - - const {fd: fdOld, sections} = await binFileUtils__namespace.readBinFile(oldPtauFilename, "ptau", 1); - const {curve, power} = await readPTauHeader(fdOld, sections); - const contributions = await readContributions(fdOld, curve, sections); - const currentContribution = {}; - - if (name) currentContribution.name = name; - - const sG1 = curve.F1.n8*2; - const scG1 = curve.F1.n8; // Compressed size - const sG2 = curve.F2.n8*2; - const scG2 = curve.F2.n8; // Compressed size - - const fdResponse = await fastFile__namespace.readExisting(contributionFilename); - - if (fdResponse.totalSize != - 64 + // Old Hash - ((2 ** power)*2-1)*scG1 + - (2 ** power)*scG2 + - (2 ** power)*scG1 + - (2 ** power)*scG1 + - scG2 + - sG1*6 + sG2*3) - throw new Error("Size of the contribution is invalid"); - - let lastChallengeHash; - - if (contributions.length>0) { - lastChallengeHash = contributions[contributions.length-1].nextChallenge; - } else { - lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); - } - - const fdNew = await binFileUtils__namespace.createBinFile(newPTauFilename, "ptau", 1, importPoints ? 7: 2); - await writePTauHeader(fdNew, curve, power); - - const contributionPreviousHash = await fdResponse.read(64); - - if (hashIsEqual(noHash,lastChallengeHash)) { - lastChallengeHash = contributionPreviousHash; - contributions[contributions.length-1].nextChallenge = lastChallengeHash; - } - - if(!hashIsEqual(contributionPreviousHash,lastChallengeHash)) - throw new Error("Wrong contribution. This contribution is not based on the previous hash"); - - const hasherResponse = blake2b.blake2b.create({ dkLen: 64 }); - hasherResponse.update(contributionPreviousHash); - - const startSections = []; - let res; - res = await processSection(fdResponse, fdNew, "G1", 2, (2 ** power) * 2 -1, [1], "tauG1"); - currentContribution.tauG1 = res[0]; - res = await processSection(fdResponse, fdNew, "G2", 3, (2 ** power) , [1], "tauG2"); - currentContribution.tauG2 = res[0]; - res = await processSection(fdResponse, fdNew, "G1", 4, (2 ** power) , [0], "alphaG1"); - currentContribution.alphaG1 = res[0]; - res = await processSection(fdResponse, fdNew, "G1", 5, (2 ** power) , [0], "betaG1"); - currentContribution.betaG1 = res[0]; - res = await processSection(fdResponse, fdNew, "G2", 6, 1 , [0], "betaG2"); - currentContribution.betaG2 = res[0]; - - currentContribution.partialHash = toPartialHash(hasherResponse); - - - const buffKey = await fdResponse.read(curve.F1.n8*2*6+curve.F2.n8*2*3); - - currentContribution.key = fromPtauPubKeyRpr(buffKey, 0, curve, false); - - hasherResponse.update(new Uint8Array(buffKey)); - const hashResponse = hasherResponse.digest(); - - if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); - - if (importPoints) { - const nextChallengeHasher = blake2b.blake2b.create({ dkLen: 64 }); - nextChallengeHasher.update(hashResponse); - - await hashSection(nextChallengeHasher, fdNew, "G1", 2, (2 ** power) * 2 -1, "tauG1", logger); - await hashSection(nextChallengeHasher, fdNew, "G2", 3, (2 ** power) , "tauG2", logger); - await hashSection(nextChallengeHasher, fdNew, "G1", 4, (2 ** power) , "alphaTauG1", logger); - await hashSection(nextChallengeHasher, fdNew, "G1", 5, (2 ** power) , "betaTauG1", logger); - await hashSection(nextChallengeHasher, fdNew, "G2", 6, 1 , "betaG2", logger); - - currentContribution.nextChallenge = nextChallengeHasher.digest(); - - if (logger) logger.info(formatHash(currentContribution.nextChallenge, "Next Challenge Hash: ")); - } else { - currentContribution.nextChallenge = noHash; - } - - contributions.push(currentContribution); - - await writeContributions(fdNew, curve, contributions); - - await fdResponse.close(); - await fdNew.close(); - await fdOld.close(); - - return currentContribution.nextChallenge; - - async function processSection(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { - if (importPoints) { - return await processSectionImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName); - } else { - return await processSectionNoImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName); - } - } - - async function processSectionImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { - - const G = curve[groupName]; - const scG = G.F.n8; - const sG = G.F.n8*2; - - const singularPoints = []; - - await binFileUtils__namespace.startWriteSection(fdTo, sectionId); - const nPointsChunk = Math.floor((1<<24)/sG); - - startSections[sectionId] = fdTo.pos; - - for (let i=0; i< nPoints; i += nPointsChunk) { - if (logger) logger.debug(`Importing ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints-i, nPointsChunk); - - const buffC = await fdFrom.read(n * scG); - hasherResponse.update(buffC); - - const buffLEM = await G.batchCtoLEM(buffC); - - await fdTo.write(buffLEM); - for (let j=0; j=i) && (sp < i+n)) { - const P = G.fromRprLEM(buffLEM, (sp-i)*sG); - singularPoints.push(P); - } - } - } - - await binFileUtils__namespace.endWriteSection(fdTo); - - return singularPoints; - } - - - async function processSectionNoImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { - - const G = curve[groupName]; - const scG = G.F.n8; - - const singularPoints = []; - - const nPointsChunk = Math.floor((1<<24)/scG); - - for (let i=0; i< nPoints; i += nPointsChunk) { - if (logger) logger.debug(`Importing ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints-i, nPointsChunk); - - const buffC = await fdFrom.read(n * scG); - hasherResponse.update(buffC); - - for (let j=0; j=i) && (sp < i+n)) { - const P = G.fromRprCompressed(buffC, (sp-i)*scG); - singularPoints.push(P); - } - } - } - - return singularPoints; - } - - - async function hashSection(nextChallengeHasher, fdTo, groupName, sectionId, nPoints, sectionName, logger) { - - const G = curve[groupName]; - const sG = G.F.n8*2; - const nPointsChunk = Math.floor((1<<24)/sG); - - const oldPos = fdTo.pos; - fdTo.pos = startSections[sectionId]; - - for (let i=0; i< nPoints; i += nPointsChunk) { - if (logger) logger.debug(`Hashing ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints-i, nPointsChunk); - - const buffLEM = await fdTo.read(n * sG); - - const buffU = await G.batchLEMtoU(buffLEM); - - nextChallengeHasher.update(buffU); - } - - fdTo.pos = oldPos; - } - -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ -const sameRatio$1 = sameRatio$2; - + const noHash = new Uint8Array(64); + for (let i = 0; i < 64; i++) noHash[i] = 255; + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(oldPtauFilename, "ptau", 1); + const { curve, power } = await readPTauHeader(fdOld, sections); + const contributions = await readContributions(fdOld, curve, sections); + const currentContribution = {}; + if (name) currentContribution.name = name; + const sG1 = curve.F1.n8 * 2; + const scG1 = curve.F1.n8; + const sG2 = curve.F2.n8 * 2; + const scG2 = curve.F2.n8; + const fdResponse = await fastfile.readExisting(contributionFilename); + if (fdResponse.totalSize != 64 + (2 ** power * 2 - 1) * scG1 + 2 ** power * scG2 + 2 ** power * scG1 + 2 ** power * scG1 + scG2 + sG1 * 6 + sG2 * 3) throw new Error("Size of the contribution is invalid"); + let lastChallengeHash; + if (contributions.length > 0) lastChallengeHash = contributions[contributions.length - 1].nextChallenge; + else lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); + const fdNew = await _iden3_binfileutils.createBinFile(newPTauFilename, "ptau", 1, importPoints ? 7 : 2); + await writePTauHeader(fdNew, curve, power); + const contributionPreviousHash = await fdResponse.read(64); + if (hashIsEqual(noHash, lastChallengeHash)) { + lastChallengeHash = contributionPreviousHash; + contributions[contributions.length - 1].nextChallenge = lastChallengeHash; + } + if (!hashIsEqual(contributionPreviousHash, lastChallengeHash)) throw new Error("Wrong contribution. This contribution is not based on the previous hash"); + const hasherResponse = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + hasherResponse.update(contributionPreviousHash); + const startSections = []; + let res; + res = await processSection(fdResponse, fdNew, "G1", 2, 2 ** power * 2 - 1, [1], "tauG1"); + currentContribution.tauG1 = res[0]; + res = await processSection(fdResponse, fdNew, "G2", 3, 2 ** power, [1], "tauG2"); + currentContribution.tauG2 = res[0]; + res = await processSection(fdResponse, fdNew, "G1", 4, 2 ** power, [0], "alphaG1"); + currentContribution.alphaG1 = res[0]; + res = await processSection(fdResponse, fdNew, "G1", 5, 2 ** power, [0], "betaG1"); + currentContribution.betaG1 = res[0]; + res = await processSection(fdResponse, fdNew, "G2", 6, 1, [0], "betaG2"); + currentContribution.betaG2 = res[0]; + currentContribution.partialHash = toPartialHash(hasherResponse); + const buffKey = await fdResponse.read(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3); + currentContribution.key = fromPtauPubKeyRpr(buffKey, 0, curve, false); + hasherResponse.update(new Uint8Array(buffKey)); + const hashResponse = hasherResponse.digest(); + if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); + if (importPoints) { + const nextChallengeHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + nextChallengeHasher.update(hashResponse); + await hashSection(nextChallengeHasher, fdNew, "G1", 2, 2 ** power * 2 - 1, "tauG1", logger); + await hashSection(nextChallengeHasher, fdNew, "G2", 3, 2 ** power, "tauG2", logger); + await hashSection(nextChallengeHasher, fdNew, "G1", 4, 2 ** power, "alphaTauG1", logger); + await hashSection(nextChallengeHasher, fdNew, "G1", 5, 2 ** power, "betaTauG1", logger); + await hashSection(nextChallengeHasher, fdNew, "G2", 6, 1, "betaG2", logger); + currentContribution.nextChallenge = nextChallengeHasher.digest(); + if (logger) logger.info(formatHash(currentContribution.nextChallenge, "Next Challenge Hash: ")); + } else currentContribution.nextChallenge = noHash; + contributions.push(currentContribution); + await writeContributions(fdNew, curve, contributions); + await fdResponse.close(); + await fdNew.close(); + await fdOld.close(); + return currentContribution.nextChallenge; + async function processSection(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { + if (importPoints) return await processSectionImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName); + else return await processSectionNoImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName); + } + async function processSectionImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { + const G = curve[groupName]; + const scG = G.F.n8; + const sG = G.F.n8 * 2; + const singularPoints = []; + await _iden3_binfileutils.startWriteSection(fdTo, sectionId); + const nPointsChunk = Math.floor((1 << 24) / sG); + startSections[sectionId] = fdTo.pos; + for (let i = 0; i < nPoints; i += nPointsChunk) { + if (logger) logger.debug(`Importing ${sectionName}: ${i}/${nPoints}`); + const n = Math.min(nPoints - i, nPointsChunk); + const buffC = await fdFrom.read(n * scG); + hasherResponse.update(buffC); + const buffLEM = await G.batchCtoLEM(buffC); + await fdTo.write(buffLEM); + for (let j = 0; j < singularPointIndexes.length; j++) { + const sp = singularPointIndexes[j]; + if (sp >= i && sp < i + n) { + const P = G.fromRprLEM(buffLEM, (sp - i) * sG); + singularPoints.push(P); + } + } + } + await _iden3_binfileutils.endWriteSection(fdTo); + return singularPoints; + } + async function processSectionNoImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { + const G = curve[groupName]; + const scG = G.F.n8; + const singularPoints = []; + const nPointsChunk = Math.floor((1 << 24) / scG); + for (let i = 0; i < nPoints; i += nPointsChunk) { + if (logger) logger.debug(`Importing ${sectionName}: ${i}/${nPoints}`); + const n = Math.min(nPoints - i, nPointsChunk); + const buffC = await fdFrom.read(n * scG); + hasherResponse.update(buffC); + for (let j = 0; j < singularPointIndexes.length; j++) { + const sp = singularPointIndexes[j]; + if (sp >= i && sp < i + n) { + const P = G.fromRprCompressed(buffC, (sp - i) * scG); + singularPoints.push(P); + } + } + } + return singularPoints; + } + async function hashSection(nextChallengeHasher, fdTo, groupName, sectionId, nPoints, sectionName, logger) { + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const nPointsChunk = Math.floor((1 << 24) / sG); + const oldPos = fdTo.pos; + fdTo.pos = startSections[sectionId]; + for (let i = 0; i < nPoints; i += nPointsChunk) { + if (logger) logger.debug(`Hashing ${sectionName}: ${i}/${nPoints}`); + const n = Math.min(nPoints - i, nPointsChunk); + const buffLEM = await fdTo.read(n * sG); + const buffU = await G.batchLEMtoU(buffLEM); + nextChallengeHasher.update(buffU); + } + fdTo.pos = oldPos; + } +} +//#endregion +//#region src/powersoftau_verify.js +var sameRatio$1 = sameRatio$2; async function verifyContribution(curve, cur, prev, logger) { - let sr; - if (cur.type == 1) { // Verify the beacon. - const beaconKey = await keyFromBeacon(curve, prev.nextChallenge, cur.beaconHash, cur.numIterationsExp); - - if (!curve.G1.eq(cur.key.tau.g1_s, beaconKey.tau.g1_s)) { - if (logger) logger.error(`BEACON key (tauG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G1.eq(cur.key.tau.g1_sx, beaconKey.tau.g1_sx)) { - if (logger) logger.error(`BEACON key (tauG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G2.eq(cur.key.tau.g2_spx, beaconKey.tau.g2_spx)) { - if (logger) logger.error(`BEACON key (tauG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - - if (!curve.G1.eq(cur.key.alpha.g1_s, beaconKey.alpha.g1_s)) { - if (logger) logger.error(`BEACON key (alphaG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G1.eq(cur.key.alpha.g1_sx, beaconKey.alpha.g1_sx)) { - if (logger) logger.error(`BEACON key (alphaG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G2.eq(cur.key.alpha.g2_spx, beaconKey.alpha.g2_spx)) { - if (logger) logger.error(`BEACON key (alphaG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - - if (!curve.G1.eq(cur.key.beta.g1_s, beaconKey.beta.g1_s)) { - if (logger) logger.error(`BEACON key (betaG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G1.eq(cur.key.beta.g1_sx, beaconKey.beta.g1_sx)) { - if (logger) logger.error(`BEACON key (betaG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G2.eq(cur.key.beta.g2_spx, beaconKey.beta.g2_spx)) { - if (logger) logger.error(`BEACON key (betaG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - } - - cur.key.tau.g2_sp = curve.G2.toAffine(getG2sp(curve, 0, prev.nextChallenge, cur.key.tau.g1_s, cur.key.tau.g1_sx)); - cur.key.alpha.g2_sp = curve.G2.toAffine(getG2sp(curve, 1, prev.nextChallenge, cur.key.alpha.g1_s, cur.key.alpha.g1_sx)); - cur.key.beta.g2_sp = curve.G2.toAffine(getG2sp(curve, 2, prev.nextChallenge, cur.key.beta.g1_s, cur.key.beta.g1_sx)); - - sr = await sameRatio$1(curve, cur.key.tau.g1_s, cur.key.tau.g1_sx, cur.key.tau.g2_sp, cur.key.tau.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID key (tau) in challenge #"+cur.id); - return false; - } - - sr = await sameRatio$1(curve, cur.key.alpha.g1_s, cur.key.alpha.g1_sx, cur.key.alpha.g2_sp, cur.key.alpha.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID key (alpha) in challenge #"+cur.id); - return false; - } - - sr = await sameRatio$1(curve, cur.key.beta.g1_s, cur.key.beta.g1_sx, cur.key.beta.g2_sp, cur.key.beta.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID key (beta) in challenge #"+cur.id); - return false; - } - - sr = await sameRatio$1(curve, prev.tauG1, cur.tauG1, cur.key.tau.g2_sp, cur.key.tau.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID tau*G1. challenge #"+cur.id+" It does not follow the previous contribution"); - return false; - } - - sr = await sameRatio$1(curve, cur.key.tau.g1_s, cur.key.tau.g1_sx, prev.tauG2, cur.tauG2); - if (sr !== true) { - if (logger) logger.error("INVALID tau*G2. challenge #"+cur.id+" It does not follow the previous contribution"); - return false; - } - - sr = await sameRatio$1(curve, prev.alphaG1, cur.alphaG1, cur.key.alpha.g2_sp, cur.key.alpha.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID alpha*G1. challenge #"+cur.id+" It does not follow the previous contribution"); - return false; - } - - sr = await sameRatio$1(curve, prev.betaG1, cur.betaG1, cur.key.beta.g2_sp, cur.key.beta.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID beta*G1. challenge #"+cur.id+" It does not follow the previous contribution"); - return false; - } - - sr = await sameRatio$1(curve, cur.key.beta.g1_s, cur.key.beta.g1_sx, prev.betaG2, cur.betaG2); - if (sr !== true) { - if (logger) logger.error("INVALID beta*G2. challenge #"+cur.id+"It does not follow the previous contribution"); - return false; - } - - if (logger) logger.info("Powers Of tau file OK!"); - return true; -} - + let sr; + if (cur.type == 1) { + const beaconKey = await keyFromBeacon(curve, prev.nextChallenge, cur.beaconHash, cur.numIterationsExp); + if (!curve.G1.eq(cur.key.tau.g1_s, beaconKey.tau.g1_s)) { + if (logger) logger.error(`BEACON key (tauG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G1.eq(cur.key.tau.g1_sx, beaconKey.tau.g1_sx)) { + if (logger) logger.error(`BEACON key (tauG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G2.eq(cur.key.tau.g2_spx, beaconKey.tau.g2_spx)) { + if (logger) logger.error(`BEACON key (tauG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G1.eq(cur.key.alpha.g1_s, beaconKey.alpha.g1_s)) { + if (logger) logger.error(`BEACON key (alphaG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G1.eq(cur.key.alpha.g1_sx, beaconKey.alpha.g1_sx)) { + if (logger) logger.error(`BEACON key (alphaG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G2.eq(cur.key.alpha.g2_spx, beaconKey.alpha.g2_spx)) { + if (logger) logger.error(`BEACON key (alphaG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G1.eq(cur.key.beta.g1_s, beaconKey.beta.g1_s)) { + if (logger) logger.error(`BEACON key (betaG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G1.eq(cur.key.beta.g1_sx, beaconKey.beta.g1_sx)) { + if (logger) logger.error(`BEACON key (betaG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G2.eq(cur.key.beta.g2_spx, beaconKey.beta.g2_spx)) { + if (logger) logger.error(`BEACON key (betaG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + } + cur.key.tau.g2_sp = curve.G2.toAffine(getG2sp(curve, 0, prev.nextChallenge, cur.key.tau.g1_s, cur.key.tau.g1_sx)); + cur.key.alpha.g2_sp = curve.G2.toAffine(getG2sp(curve, 1, prev.nextChallenge, cur.key.alpha.g1_s, cur.key.alpha.g1_sx)); + cur.key.beta.g2_sp = curve.G2.toAffine(getG2sp(curve, 2, prev.nextChallenge, cur.key.beta.g1_s, cur.key.beta.g1_sx)); + sr = await sameRatio$1(curve, cur.key.tau.g1_s, cur.key.tau.g1_sx, cur.key.tau.g2_sp, cur.key.tau.g2_spx); + if (sr !== true) { + if (logger) logger.error("INVALID key (tau) in challenge #" + cur.id); + return false; + } + sr = await sameRatio$1(curve, cur.key.alpha.g1_s, cur.key.alpha.g1_sx, cur.key.alpha.g2_sp, cur.key.alpha.g2_spx); + if (sr !== true) { + if (logger) logger.error("INVALID key (alpha) in challenge #" + cur.id); + return false; + } + sr = await sameRatio$1(curve, cur.key.beta.g1_s, cur.key.beta.g1_sx, cur.key.beta.g2_sp, cur.key.beta.g2_spx); + if (sr !== true) { + if (logger) logger.error("INVALID key (beta) in challenge #" + cur.id); + return false; + } + sr = await sameRatio$1(curve, prev.tauG1, cur.tauG1, cur.key.tau.g2_sp, cur.key.tau.g2_spx); + if (sr !== true) { + if (logger) logger.error("INVALID tau*G1. challenge #" + cur.id + " It does not follow the previous contribution"); + return false; + } + sr = await sameRatio$1(curve, cur.key.tau.g1_s, cur.key.tau.g1_sx, prev.tauG2, cur.tauG2); + if (sr !== true) { + if (logger) logger.error("INVALID tau*G2. challenge #" + cur.id + " It does not follow the previous contribution"); + return false; + } + sr = await sameRatio$1(curve, prev.alphaG1, cur.alphaG1, cur.key.alpha.g2_sp, cur.key.alpha.g2_spx); + if (sr !== true) { + if (logger) logger.error("INVALID alpha*G1. challenge #" + cur.id + " It does not follow the previous contribution"); + return false; + } + sr = await sameRatio$1(curve, prev.betaG1, cur.betaG1, cur.key.beta.g2_sp, cur.key.beta.g2_spx); + if (sr !== true) { + if (logger) logger.error("INVALID beta*G1. challenge #" + cur.id + " It does not follow the previous contribution"); + return false; + } + sr = await sameRatio$1(curve, cur.key.beta.g1_s, cur.key.beta.g1_sx, prev.betaG2, cur.betaG2); + if (sr !== true) { + if (logger) logger.error("INVALID beta*G2. challenge #" + cur.id + "It does not follow the previous contribution"); + return false; + } + if (logger) logger.info("Powers Of tau file OK!"); + return true; +} async function verify(tauFilename, logger) { - let sr; - - const {fd, sections} = await binFileUtils__namespace.readBinFile(tauFilename, "ptau", 1); - const {curve, power, ceremonyPower} = await readPTauHeader(fd, sections); - const contrs = await readContributions(fd, curve, sections); - - if (logger) logger.debug("power: 2**" + power); - // Verify Last contribution - - if (logger) logger.debug("Computing initial contribution hash"); - const initialContribution = { - tauG1: curve.G1.g, - tauG2: curve.G2.g, - alphaG1: curve.G1.g, - betaG1: curve.G1.g, - betaG2: curve.G2.g, - nextChallenge: calculateFirstChallengeHash(curve, ceremonyPower, logger), - responseHash: blake2b.blake2b.create({ dkLen: 64 }).digest() - }; - - if (contrs.length == 0) { - if (logger) logger.error("This file has no contribution! It cannot be used in production"); - return false; - } - - let prevContr; - if (contrs.length>1) { - prevContr = contrs[contrs.length-2]; - } else { - prevContr = initialContribution; - } - const curContr = contrs[contrs.length-1]; - if (logger) logger.debug("Validating contribution #"+contrs[contrs.length-1].id); - const res = await verifyContribution(curve, curContr, prevContr, logger); - if (!res) return false; - - - const nextContributionHasher = blake2b.blake2b.create({ dkLen: 64 }); - nextContributionHasher.update(curContr.responseHash); - - // Verify powers and compute nextChallengeHash - - // await test(); - - // Verify Section tau*G1 - if (logger) logger.debug("Verifying powers in tau*G1 section"); - const rTau1 = await processSection(2, "G1", "tauG1", (2 ** power)*2-1, [0, 1], logger); - sr = await sameRatio$1(curve, rTau1.R1, rTau1.R2, curve.G2.g, curContr.tauG2); - if (sr !== true) { - if (logger) logger.error("tauG1 section. Powers do not match"); - return false; - } - if (!curve.G1.eq(curve.G1.g, rTau1.singularPoints[0])) { - if (logger) logger.error("First element of tau*G1 section must be the generator"); - return false; - } - if (!curve.G1.eq(curContr.tauG1, rTau1.singularPoints[1])) { - if (logger) logger.error("Second element of tau*G1 section does not match the one in the contribution section"); - return false; - } - - // await test(); - - // Verify Section tau*G2 - if (logger) logger.debug("Verifying powers in tau*G2 section"); - const rTau2 = await processSection(3, "G2", "tauG2", 2 ** power, [0, 1], logger); - sr = await sameRatio$1(curve, curve.G1.g, curContr.tauG1, rTau2.R1, rTau2.R2); - if (sr !== true) { - if (logger) logger.error("tauG2 section. Powers do not match"); - return false; - } - if (!curve.G2.eq(curve.G2.g, rTau2.singularPoints[0])) { - if (logger) logger.error("First element of tau*G2 section must be the generator"); - return false; - } - if (!curve.G2.eq(curContr.tauG2, rTau2.singularPoints[1])) { - if (logger) logger.error("Second element of tau*G2 section does not match the one in the contribution section"); - return false; - } - - // Verify Section alpha*tau*G1 - if (logger) logger.debug("Verifying powers in alpha*tau*G1 section"); - const rAlphaTauG1 = await processSection(4, "G1", "alphatauG1", 2 ** power, [0], logger); - sr = await sameRatio$1(curve, rAlphaTauG1.R1, rAlphaTauG1.R2, curve.G2.g, curContr.tauG2); - if (sr !== true) { - if (logger) logger.error("alphaTauG1 section. Powers do not match"); - return false; - } - if (!curve.G1.eq(curContr.alphaG1, rAlphaTauG1.singularPoints[0])) { - if (logger) logger.error("First element of alpha*tau*G1 section (alpha*G1) does not match the one in the contribution section"); - return false; - } - - // Verify Section beta*tau*G1 - if (logger) logger.debug("Verifying powers in beta*tau*G1 section"); - const rBetaTauG1 = await processSection(5, "G1", "betatauG1", 2 ** power, [0], logger); - sr = await sameRatio$1(curve, rBetaTauG1.R1, rBetaTauG1.R2, curve.G2.g, curContr.tauG2); - if (sr !== true) { - if (logger) logger.error("betaTauG1 section. Powers do not match"); - return false; - } - if (!curve.G1.eq(curContr.betaG1, rBetaTauG1.singularPoints[0])) { - if (logger) logger.error("First element of beta*tau*G1 section (beta*G1) does not match the one in the contribution section"); - return false; - } - - //Verify Beta G2 - const betaG2 = await processSectionBetaG2(logger); - if (!curve.G2.eq(curContr.betaG2, betaG2)) { - if (logger) logger.error("betaG2 element in betaG2 section does not match the one in the contribution section"); - return false; - } - - - const nextContributionHash = nextContributionHasher.digest(); - - // Check the nextChallengeHash - if (power == ceremonyPower) { - if (!hashIsEqual(nextContributionHash,curContr.nextChallenge)) { - if (logger) logger.error("Hash of the values does not match the next challenge of the last contributor in the contributions section"); - return false; - } - } - - if (logger) logger.info(formatHash(nextContributionHash, "Next challenge hash: ")); - - // Verify Previous contributions - - printContribution(curContr, prevContr); - for (let i = contrs.length-2; i>=0; i--) { - const curContr = contrs[i]; - const prevContr = (i>0) ? contrs[i-1] : initialContribution; - const res = await verifyContribution(curve, curContr, prevContr, logger); - if (!res) return false; - printContribution(curContr, prevContr); - } - if (logger) logger.info("-----------------------------------------------------"); - - if ((!sections[12]) || (!sections[13]) || (!sections[14]) || (!sections[15])) { - if (logger) logger.warn( - "this file does not contain phase2 precalculated values. Please run: \n" + - " snarkjs \"powersoftau preparephase2\" to prepare this file to be used in the phase2 ceremony." - ); - } else { - let res; - res = await verifyLagrangeEvaluations("G1", 2, 12, "tauG1", logger); - if (!res) return false; - res = await verifyLagrangeEvaluations("G2", 3, 13, "tauG2", logger); - if (!res) return false; - res = await verifyLagrangeEvaluations("G1", 4, 14, "alphaTauG1", logger); - if (!res) return false; - res = await verifyLagrangeEvaluations("G1", 5, 15, "betaTauG1", logger); - if (!res) return false; - } - - await fd.close(); - - if (logger) logger.info("Powers of Tau Ok!"); - - return true; - - function printContribution(curContr, prevContr) { - if (!logger) return; - logger.info("-----------------------------------------------------"); - logger.info(`Contribution #${curContr.id}: ${curContr.name ||""}`); - - logger.info(formatHash(curContr.nextChallenge, "Next Challenge: ")); - - const buffV = new Uint8Array(curve.G1.F.n8*2*6+curve.G2.F.n8*2*3); - toPtauPubKeyRpr(buffV, 0, curve, curContr.key, false); - - const responseHasher = fromPartialHash(curContr.partialHash); - responseHasher.update(buffV); - const responseHash = responseHasher.digest(); - - logger.info(formatHash(responseHash, "Response Hash:")); - - logger.info(formatHash(prevContr.nextChallenge, "Response Hash:")); - - if (curContr.type == 1) { - logger.info(`Beacon generator: ${byteArray2hex(curContr.beaconHash)}`); - logger.info(`Beacon iterations Exp: ${curContr.numIterationsExp}`); - } - - } - - async function processSectionBetaG2(logger) { - const G = curve.G2; - const sG = G.F.n8*2; - const buffUv = new Uint8Array(sG); - - if (!sections[6]) { - logger.error("File has no BetaG2 section"); - throw new Error("File has no BetaG2 section"); - } - if (sections[6].length>1) { - logger.error("File has no BetaG2 section"); - throw new Error("File has more than one GetaG2 section"); - } - fd.pos = sections[6][0].p; - - const buff = await fd.read(sG); - const P = G.fromRprLEM(buff); - - G.toRprUncompressed(buffUv, 0, P); - nextContributionHasher.update(buffUv); - - return P; - } - - async function processSection(idSection, groupName, sectionName, nPoints, singularPointIndexes, logger) { - const MAX_CHUNK_SIZE = 1<<16; - const G = curve[groupName]; - const sG = G.F.n8*2; - await binFileUtils__namespace.startReadUniqueSection(fd, sections, idSection); - - const singularPoints = []; - - let R1 = G.zero; - let R2 = G.zero; - - let lastBase = G.zero; - - for (let i=0; i0) { - const firstBase = G.fromRprLEM(bases, 0); - const r = readUInt32BE(getRandomBytes(4), 0); - - R1 = G.add(R1, G.timesScalar(lastBase, r)); - R2 = G.add(R2, G.timesScalar(firstBase, r)); - } - - const r1 = await G.multiExpAffine(bases.slice(0, (n-1)*sG), scalars); - const r2 = await G.multiExpAffine(bases.slice(sG), scalars); - - R1 = G.add(R1, r1); - R2 = G.add(R2, r2); - - lastBase = G.fromRprLEM( bases, (n-1)*sG); - - for (let j=0; j=i) && (sp < i+n)) { - const P = G.fromRprLEM(bases, (sp-i)*sG); - singularPoints.push(P); - } - } - - } - await binFileUtils__namespace.endReadSection(fd); - - return { - R1: R1, - R2: R2, - singularPoints: singularPoints - }; - - } - - async function verifyLagrangeEvaluations(gName, tauSection, lagrangeSection, sectionName, logger) { - - if (logger) logger.debug(`Verifying phase2 calculated values ${sectionName}...`); - const G = curve[gName]; - const sG = G.F.n8*2; - - const seed= new Array(8); - for (let i=0; i<8; i++) { - seed[i] = readUInt32BE(getRandomBytes(4), 0); - } - - for (let p=0; p<= power; p ++) { - const res = await verifyPower(p); - if (!res) return false; - } - - if (tauSection == 2) { - const res = await verifyPower(power+1); - if (!res) return false; - } - - return true; - - async function verifyPower(p) { - if (logger) logger.debug(`Power ${p}...`); - const n8r = curve.Fr.n8; - const nPoints = 2 ** p; - let buff_r = new Uint32Array(nPoints); - let buffG; - - let rng = new ffjavascript.ChaCha(seed); - - if (logger) logger.debug(`Creating random numbers Powers${p}...`); - for (let i=0; i. -*/ - -/* - This function creates a new section in the fdTo file with id idSection. - It multiplies the points in fdFrom by first, first*inc, first*inc^2, .... - nPoint Times. - It also updates the newChallengeHasher with the new points -*/ - + let sr; + const { fd, sections } = await _iden3_binfileutils.readBinFile(tauFilename, "ptau", 1); + const { curve, power, ceremonyPower } = await readPTauHeader(fd, sections); + const contrs = await readContributions(fd, curve, sections); + if (logger) logger.debug("power: 2**" + power); + if (logger) logger.debug("Computing initial contribution hash"); + const initialContribution = { + tauG1: curve.G1.g, + tauG2: curve.G2.g, + alphaG1: curve.G1.g, + betaG1: curve.G1.g, + betaG2: curve.G2.g, + nextChallenge: calculateFirstChallengeHash(curve, ceremonyPower, logger), + responseHash: _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }).digest() + }; + if (contrs.length == 0) { + if (logger) logger.error("This file has no contribution! It cannot be used in production"); + return false; + } + let prevContr; + if (contrs.length > 1) prevContr = contrs[contrs.length - 2]; + else prevContr = initialContribution; + const curContr = contrs[contrs.length - 1]; + if (logger) logger.debug("Validating contribution #" + contrs[contrs.length - 1].id); + if (!await verifyContribution(curve, curContr, prevContr, logger)) return false; + const nextContributionHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + nextContributionHasher.update(curContr.responseHash); + if (logger) logger.debug("Verifying powers in tau*G1 section"); + const rTau1 = await processSection(2, "G1", "tauG1", 2 ** power * 2 - 1, [0, 1], logger); + sr = await sameRatio$1(curve, rTau1.R1, rTau1.R2, curve.G2.g, curContr.tauG2); + if (sr !== true) { + if (logger) logger.error("tauG1 section. Powers do not match"); + return false; + } + if (!curve.G1.eq(curve.G1.g, rTau1.singularPoints[0])) { + if (logger) logger.error("First element of tau*G1 section must be the generator"); + return false; + } + if (!curve.G1.eq(curContr.tauG1, rTau1.singularPoints[1])) { + if (logger) logger.error("Second element of tau*G1 section does not match the one in the contribution section"); + return false; + } + if (logger) logger.debug("Verifying powers in tau*G2 section"); + const rTau2 = await processSection(3, "G2", "tauG2", 2 ** power, [0, 1], logger); + sr = await sameRatio$1(curve, curve.G1.g, curContr.tauG1, rTau2.R1, rTau2.R2); + if (sr !== true) { + if (logger) logger.error("tauG2 section. Powers do not match"); + return false; + } + if (!curve.G2.eq(curve.G2.g, rTau2.singularPoints[0])) { + if (logger) logger.error("First element of tau*G2 section must be the generator"); + return false; + } + if (!curve.G2.eq(curContr.tauG2, rTau2.singularPoints[1])) { + if (logger) logger.error("Second element of tau*G2 section does not match the one in the contribution section"); + return false; + } + if (logger) logger.debug("Verifying powers in alpha*tau*G1 section"); + const rAlphaTauG1 = await processSection(4, "G1", "alphatauG1", 2 ** power, [0], logger); + sr = await sameRatio$1(curve, rAlphaTauG1.R1, rAlphaTauG1.R2, curve.G2.g, curContr.tauG2); + if (sr !== true) { + if (logger) logger.error("alphaTauG1 section. Powers do not match"); + return false; + } + if (!curve.G1.eq(curContr.alphaG1, rAlphaTauG1.singularPoints[0])) { + if (logger) logger.error("First element of alpha*tau*G1 section (alpha*G1) does not match the one in the contribution section"); + return false; + } + if (logger) logger.debug("Verifying powers in beta*tau*G1 section"); + const rBetaTauG1 = await processSection(5, "G1", "betatauG1", 2 ** power, [0], logger); + sr = await sameRatio$1(curve, rBetaTauG1.R1, rBetaTauG1.R2, curve.G2.g, curContr.tauG2); + if (sr !== true) { + if (logger) logger.error("betaTauG1 section. Powers do not match"); + return false; + } + if (!curve.G1.eq(curContr.betaG1, rBetaTauG1.singularPoints[0])) { + if (logger) logger.error("First element of beta*tau*G1 section (beta*G1) does not match the one in the contribution section"); + return false; + } + const betaG2 = await processSectionBetaG2(logger); + if (!curve.G2.eq(curContr.betaG2, betaG2)) { + if (logger) logger.error("betaG2 element in betaG2 section does not match the one in the contribution section"); + return false; + } + const nextContributionHash = nextContributionHasher.digest(); + if (power == ceremonyPower) { + if (!hashIsEqual(nextContributionHash, curContr.nextChallenge)) { + if (logger) logger.error("Hash of the values does not match the next challenge of the last contributor in the contributions section"); + return false; + } + } + if (logger) logger.info(formatHash(nextContributionHash, "Next challenge hash: ")); + printContribution(curContr, prevContr); + for (let i = contrs.length - 2; i >= 0; i--) { + const curContr = contrs[i]; + const prevContr = i > 0 ? contrs[i - 1] : initialContribution; + if (!await verifyContribution(curve, curContr, prevContr, logger)) return false; + printContribution(curContr, prevContr, logger); + } + if (logger) logger.info("-----------------------------------------------------"); + if (!sections[12] || !sections[13] || !sections[14] || !sections[15]) { + if (logger) logger.warn("this file does not contain phase2 precalculated values. Please run: \n snarkjs \"powersoftau preparephase2\" to prepare this file to be used in the phase2 ceremony."); + } else { + let res; + res = await verifyLagrangeEvaluations("G1", 2, 12, "tauG1", logger); + if (!res) return false; + res = await verifyLagrangeEvaluations("G2", 3, 13, "tauG2", logger); + if (!res) return false; + res = await verifyLagrangeEvaluations("G1", 4, 14, "alphaTauG1", logger); + if (!res) return false; + res = await verifyLagrangeEvaluations("G1", 5, 15, "betaTauG1", logger); + if (!res) return false; + } + await fd.close(); + if (logger) logger.info("Powers of Tau Ok!"); + return true; + function printContribution(curContr, prevContr) { + if (!logger) return; + logger.info("-----------------------------------------------------"); + logger.info(`Contribution #${curContr.id}: ${curContr.name || ""}`); + logger.info(formatHash(curContr.nextChallenge, "Next Challenge: ")); + const buffV = new Uint8Array(curve.G1.F.n8 * 2 * 6 + curve.G2.F.n8 * 2 * 3); + toPtauPubKeyRpr(buffV, 0, curve, curContr.key, false); + const responseHasher = fromPartialHash(curContr.partialHash); + responseHasher.update(buffV); + const responseHash = responseHasher.digest(); + logger.info(formatHash(responseHash, "Response Hash:")); + logger.info(formatHash(prevContr.nextChallenge, "Response Hash:")); + if (curContr.type == 1) { + logger.info(`Beacon generator: ${byteArray2hex(curContr.beaconHash)}`); + logger.info(`Beacon iterations Exp: ${curContr.numIterationsExp}`); + } + } + async function processSectionBetaG2(logger) { + const G = curve.G2; + const sG = G.F.n8 * 2; + const buffUv = new Uint8Array(sG); + if (!sections[6]) { + logger.error("File has no BetaG2 section"); + throw new Error("File has no BetaG2 section"); + } + if (sections[6].length > 1) { + logger.error("File has no BetaG2 section"); + throw new Error("File has more than one GetaG2 section"); + } + fd.pos = sections[6][0].p; + const buff = await fd.read(sG); + const P = G.fromRprLEM(buff); + G.toRprUncompressed(buffUv, 0, P); + nextContributionHasher.update(buffUv); + return P; + } + async function processSection(idSection, groupName, sectionName, nPoints, singularPointIndexes, logger) { + const MAX_CHUNK_SIZE = 65536; + const G = curve[groupName]; + const sG = G.F.n8 * 2; + await _iden3_binfileutils.startReadUniqueSection(fd, sections, idSection); + const singularPoints = []; + let R1 = G.zero; + let R2 = G.zero; + let lastBase = G.zero; + for (let i = 0; i < nPoints; i += MAX_CHUNK_SIZE) { + if (logger) logger.debug(`points relations: ${sectionName}: ${i}/${nPoints} `); + const n = Math.min(nPoints - i, MAX_CHUNK_SIZE); + const bases = await fd.read(n * sG); + const basesU = await G.batchLEMtoU(bases); + nextContributionHasher.update(basesU); + const scalars = getRandomBytes(4 * (n - 1)); + if (i > 0) { + const firstBase = G.fromRprLEM(bases, 0); + const r = readUInt32BE(getRandomBytes(4), 0); + R1 = G.add(R1, G.timesScalar(lastBase, r)); + R2 = G.add(R2, G.timesScalar(firstBase, r)); + } + const r1 = await G.multiExpAffine(bases.slice(0, (n - 1) * sG), scalars); + const r2 = await G.multiExpAffine(bases.slice(sG), scalars); + R1 = G.add(R1, r1); + R2 = G.add(R2, r2); + lastBase = G.fromRprLEM(bases, (n - 1) * sG); + for (let j = 0; j < singularPointIndexes.length; j++) { + const sp = singularPointIndexes[j]; + if (sp >= i && sp < i + n) { + const P = G.fromRprLEM(bases, (sp - i) * sG); + singularPoints.push(P); + } + } + } + await _iden3_binfileutils.endReadSection(fd); + return { + R1, + R2, + singularPoints + }; + } + async function verifyLagrangeEvaluations(gName, tauSection, lagrangeSection, sectionName, logger) { + if (logger) logger.debug(`Verifying phase2 calculated values ${sectionName}...`); + const G = curve[gName]; + const sG = G.F.n8 * 2; + const seed = new Array(8); + for (let i = 0; i < 8; i++) seed[i] = readUInt32BE(getRandomBytes(4), 0); + for (let p = 0; p <= power; p++) if (!await verifyPower(p)) return false; + if (tauSection == 2) { + if (!await verifyPower(power + 1)) return false; + } + return true; + async function verifyPower(p) { + if (logger) logger.debug(`Power ${p}...`); + const n8r = curve.Fr.n8; + const nPoints = 2 ** p; + let buff_r = new Uint32Array(nPoints); + let buffG; + let rng = new ffjavascript.ChaCha(seed); + if (logger) logger.debug(`Creating random numbers Powers${p}...`); + for (let i = 0; i < nPoints; i++) if (p == power + 1 && i == nPoints - 1) buff_r[i] = 0; + else buff_r[i] = rng.nextU32(); + buff_r = new Uint8Array(buff_r.buffer, buff_r.byteOffset, buff_r.byteLength); + if (logger) logger.debug(`reading points Powers${p}...`); + await _iden3_binfileutils.startReadUniqueSection(fd, sections, tauSection); + buffG = new ffjavascript.BigBuffer(nPoints * sG); + if (p == power + 1) { + await fd.readToBuffer(buffG, 0, (nPoints - 1) * sG); + buffG.set(curve.G1.zeroAffine, (nPoints - 1) * sG); + } else await fd.readToBuffer(buffG, 0, nPoints * sG); + await _iden3_binfileutils.endReadSection(fd, true); + const resTau = await G.multiExpAffine(buffG, buff_r, logger, sectionName + "_" + p); + buff_r = new ffjavascript.BigBuffer(nPoints * n8r); + rng = new ffjavascript.ChaCha(seed); + const buff4 = new Uint8Array(4); + const buff4V = new DataView(buff4.buffer); + if (logger) logger.debug(`Creating random numbers Powers${p}...`); + for (let i = 0; i < nPoints; i++) if (i != nPoints - 1 || p != power + 1) { + buff4V.setUint32(0, rng.nextU32(), true); + buff_r.set(buff4, i * n8r); + } + if (logger) logger.debug(`batchToMontgomery ${p}...`); + buff_r = await curve.Fr.batchToMontgomery(buff_r); + if (logger) logger.debug(`fft ${p}...`); + buff_r = await curve.Fr.fft(buff_r); + if (logger) logger.debug(`batchFromMontgomery ${p}...`); + buff_r = await curve.Fr.batchFromMontgomery(buff_r); + if (logger) logger.debug(`reading points Lagrange${p}...`); + await _iden3_binfileutils.startReadUniqueSection(fd, sections, lagrangeSection); + fd.pos += sG * (2 ** p - 1); + await fd.readToBuffer(buffG, 0, nPoints * sG); + await _iden3_binfileutils.endReadSection(fd, true); + const resLagrange = await G.multiExpAffine(buffG, buff_r, logger, sectionName + "_" + p + "_transformed"); + if (!G.eq(resTau, resLagrange)) { + if (logger) logger.error("Phase2 caclutation does not match with powers of tau"); + return false; + } + return true; + } + } +} +//#endregion +//#region src/mpc_applykey.js async function applyKeyToSection(fdOld, sections, fdNew, idSection, curve, groupName, first, inc, sectionName, logger) { - const MAX_CHUNK_SIZE = 1 << 16; - const G = curve[groupName]; - const sG = G.F.n8*2; - const nPoints = sections[idSection][0].size / sG; - - await binFileUtils__namespace.startReadUniqueSection(fdOld, sections,idSection ); - await binFileUtils__namespace.startWriteSection(fdNew, idSection); - - let t = first; - for (let i=0; i. -*/ - + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const chunkSize = Math.floor((1 << 20) / sG); + let t = first; + for (let i = 0; i < nPoints; i += chunkSize) { + if (logger) logger.debug(`Applying key ${sectionName}: ${i}/${nPoints}`); + const n = Math.min(nPoints - i, chunkSize); + const buffInU = await fdOld.read(n * sG); + const buffInLEM = await G.batchUtoLEM(buffInU); + const buffOutLEM = await G.batchApplyKey(buffInLEM, t, inc); + let buffOut; + if (formatOut == "COMPRESSED") buffOut = await G.batchLEMtoC(buffOutLEM); + else buffOut = await G.batchLEMtoU(buffOutLEM); + if (responseHasher) responseHasher.update(buffOut); + await fdNew.write(buffOut); + t = curve.Fr.mul(t, curve.Fr.exp(inc, n)); + } +} +//#endregion +//#region src/powersoftau_challenge_contribute.js async function challengeContribute(curve, challengeFilename, responseFileName, entropy, logger) { - const fdFrom = await fastFile__namespace.readExisting(challengeFilename); - - - const sG1 = curve.F1.n64*8*2; - const sG2 = curve.F2.n64*8*2; - const domainSize = (fdFrom.totalSize + sG1 - 64 - sG2) / (4*sG1 + sG2); - let e = domainSize; - let power = 0; - while (e>1) { - e = e /2; - power += 1; - } - - if (2 ** power != domainSize) throw new Error("Invalid file size"); - if (logger) logger.debug("Power to tau size: "+power); - - const rng = await getRandomRng(entropy); - - const fdTo = await fastFile__namespace.createOverride(responseFileName); - - // Calculate the hash - const challengeHasher = blake2b.blake2b.create({ dkLen: 64 }); - for (let i=0; i { - logger.debug(k + ".g1_s: " + curve.G1.toString(key[k].g1_s, 16)); - logger.debug(k + ".g1_sx: " + curve.G1.toString(key[k].g1_sx, 16)); - logger.debug(k + ".g2_sp: " + curve.G2.toString(key[k].g2_sp, 16)); - logger.debug(k + ".g2_spx: " + curve.G2.toString(key[k].g2_spx, 16)); - logger.debug(""); - }); - } - - const responseHasher = blake2b.blake2b.create({ dkLen: 64 }); - - await fdTo.write(challengeHash); - responseHasher.update(challengeHash); - - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", (2 ** power)*2-1, curve.Fr.one , key.tau.prvKey, "COMPRESSED", "tauG1" , logger ); - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G2", (2 ** power) , curve.Fr.one , key.tau.prvKey, "COMPRESSED", "tauG2" , logger ); - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", (2 ** power) , key.alpha.prvKey, key.tau.prvKey, "COMPRESSED", "alphaTauG1", logger ); - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", (2 ** power) , key.beta.prvKey , key.tau.prvKey, "COMPRESSED", "betaTauG1" , logger ); - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G2", 1 , key.beta.prvKey , key.tau.prvKey, "COMPRESSED", "betaTauG2" , logger ); - - // Write and hash key - const buffKey = new Uint8Array(curve.F1.n8*2*6+curve.F2.n8*2*3); - toPtauPubKeyRpr(buffKey, 0, curve, key, false); - await fdTo.write(buffKey); - responseHasher.update(buffKey); - const responseHash = responseHasher.digest(); - if (logger) logger.info(formatHash(responseHash, "Contribution Response Hash: ")); - - await fdTo.close(); - await fdFrom.close(); -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -async function beacon$1(oldPtauFilename, newPTauFilename, name, beaconHashStr,numIterationsExp, logger) { - const beaconHash = hex2ByteArray(beaconHashStr); - if ( (beaconHash.byteLength == 0) - || (beaconHash.byteLength*2 !=beaconHashStr.length)) - { - if (logger) logger.error("Invalid Beacon Hash. (It must be a valid hexadecimal sequence)"); - return false; - } - if (beaconHash.length>=256) { - if (logger) logger.error("Maximum length of beacon hash is 255 bytes"); - return false; - } - - numIterationsExp = parseInt(numIterationsExp); - if ((numIterationsExp<10)||(numIterationsExp>63)) { - if (logger) logger.error("Invalid numIterationsExp. (Must be between 10 and 63)"); - return false; - } - - - const {fd: fdOld, sections} = await binFileUtils__namespace.readBinFile(oldPtauFilename, "ptau", 1); - const {curve, power, ceremonyPower} = await readPTauHeader(fdOld, sections); - if (power != ceremonyPower) { - if (logger) logger.error("This file has been reduced. You cannot contribute into a reduced file."); - return false; - } - if (sections[12]) { - if (logger) logger.warn("Contributing into a file that has phase2 calculated. You will have to prepare phase2 again."); - } - const contributions = await readContributions(fdOld, curve, sections); - const curContribution = { - name: name, - type: 1, // Beacon - numIterationsExp: numIterationsExp, - beaconHash: beaconHash - }; - - let lastChallengeHash; - - if (contributions.length>0) { - lastChallengeHash = contributions[contributions.length-1].nextChallenge; - } else { - lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); - } - - curContribution.key = await keyFromBeacon(curve, lastChallengeHash, beaconHash, numIterationsExp); - - const responseHasher = blake2b.blake2b.create({ dkLen: 64 }); - responseHasher.update(lastChallengeHash); - - const fdNew = await binFileUtils__namespace.createBinFile(newPTauFilename, "ptau", 1, 7); - await writePTauHeader(fdNew, curve, power); - - const startSections = []; - - let firstPoints; - firstPoints = await processSection(2, "G1", (2 ** power) * 2 -1, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG1", logger ); - curContribution.tauG1 = firstPoints[1]; - firstPoints = await processSection(3, "G2", (2 ** power) , curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG2", logger ); - curContribution.tauG2 = firstPoints[1]; - firstPoints = await processSection(4, "G1", (2 ** power) , curContribution.key.alpha.prvKey, curContribution.key.tau.prvKey, "alphaTauG1", logger ); - curContribution.alphaG1 = firstPoints[0]; - firstPoints = await processSection(5, "G1", (2 ** power) , curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG1", logger ); - curContribution.betaG1 = firstPoints[0]; - firstPoints = await processSection(6, "G2", 1, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG2", logger ); - curContribution.betaG2 = firstPoints[0]; - - curContribution.partialHash = toPartialHash(responseHasher); - - const buffKey = new Uint8Array(curve.F1.n8*2*6+curve.F2.n8*2*3); - - toPtauPubKeyRpr(buffKey, 0, curve, curContribution.key, false); - - responseHasher.update(new Uint8Array(buffKey)); - const hashResponse = responseHasher.digest(); - - if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); - - const nextChallengeHasher = blake2b.blake2b.create({ dkLen: 64 }); - nextChallengeHasher.update(hashResponse); - - await hashSection(fdNew, "G1", 2, (2 ** power) * 2 -1, "tauG1", logger); - await hashSection(fdNew, "G2", 3, (2 ** power) , "tauG2", logger); - await hashSection(fdNew, "G1", 4, (2 ** power) , "alphaTauG1", logger); - await hashSection(fdNew, "G1", 5, (2 ** power) , "betaTauG1", logger); - await hashSection(fdNew, "G2", 6, 1 , "betaG2", logger); - - curContribution.nextChallenge = nextChallengeHasher.digest(); - - if (logger) logger.info(formatHash(curContribution.nextChallenge, "Next Challenge Hash: ")); - - contributions.push(curContribution); - - await writeContributions(fdNew, curve, contributions); - - await fdOld.close(); - await fdNew.close(); - - return hashResponse; - - async function processSection(sectionId, groupName, NPoints, first, inc, sectionName, logger) { - const res = []; - fdOld.pos = sections[sectionId][0].p; - - await binFileUtils__namespace.startWriteSection(fdNew, sectionId); - - startSections[sectionId] = fdNew.pos; - - const G = curve[groupName]; - const sG = G.F.n8*2; - const chunkSize = Math.floor((1<<20) / sG); // 128Mb chunks - let t = first; - for (let i=0 ; i. -*/ - + const fdFrom = await fastfile.readExisting(challengeFilename); + const sG1 = curve.F1.n64 * 8 * 2; + const sG2 = curve.F2.n64 * 8 * 2; + const domainSize = (fdFrom.totalSize + sG1 - 64 - sG2) / (4 * sG1 + sG2); + let e = domainSize; + let power = 0; + while (e > 1) { + e = e / 2; + power += 1; + } + if (2 ** power != domainSize) throw new Error("Invalid file size"); + if (logger) logger.debug("Power to tau size: " + power); + const rng = await getRandomRng(entropy); + const fdTo = await fastfile.createOverride(responseFileName); + const challengeHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + for (let i = 0; i < fdFrom.totalSize; i += fdFrom.pageSize) { + if (logger) logger.debug(`Hashing challenge ${i}/${fdFrom.totalSize}`); + const s = Math.min(fdFrom.totalSize - i, fdFrom.pageSize); + const buff = await fdFrom.read(s); + challengeHasher.update(buff); + } + const claimedHash = await fdFrom.read(64, 0); + if (logger) logger.info(formatHash(claimedHash, "Claimed Previous Response Hash: ")); + const challengeHash = challengeHasher.digest(); + if (logger) logger.info(formatHash(challengeHash, "Current Challenge Hash: ")); + const key = createPTauKey(curve, challengeHash, rng); + if (logger) [ + "tau", + "alpha", + "beta" + ].forEach((k) => { + logger.debug(k + ".g1_s: " + curve.G1.toString(key[k].g1_s, 16)); + logger.debug(k + ".g1_sx: " + curve.G1.toString(key[k].g1_sx, 16)); + logger.debug(k + ".g2_sp: " + curve.G2.toString(key[k].g2_sp, 16)); + logger.debug(k + ".g2_spx: " + curve.G2.toString(key[k].g2_spx, 16)); + logger.debug(""); + }); + const responseHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + await fdTo.write(challengeHash); + responseHasher.update(challengeHash); + await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", 2 ** power * 2 - 1, curve.Fr.one, key.tau.prvKey, "COMPRESSED", "tauG1", logger); + await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G2", 2 ** power, curve.Fr.one, key.tau.prvKey, "COMPRESSED", "tauG2", logger); + await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", 2 ** power, key.alpha.prvKey, key.tau.prvKey, "COMPRESSED", "alphaTauG1", logger); + await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", 2 ** power, key.beta.prvKey, key.tau.prvKey, "COMPRESSED", "betaTauG1", logger); + await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G2", 1, key.beta.prvKey, key.tau.prvKey, "COMPRESSED", "betaTauG2", logger); + const buffKey = new Uint8Array(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3); + toPtauPubKeyRpr(buffKey, 0, curve, key, false); + await fdTo.write(buffKey); + responseHasher.update(buffKey); + const responseHash = responseHasher.digest(); + if (logger) logger.info(formatHash(responseHash, "Contribution Response Hash: ")); + await fdTo.close(); + await fdFrom.close(); +} +//#endregion +//#region src/powersoftau_beacon.js +async function beacon$1(oldPtauFilename, newPTauFilename, name, beaconHashStr, numIterationsExp, logger) { + const beaconHash = hex2ByteArray(beaconHashStr); + if (beaconHash.byteLength == 0 || beaconHash.byteLength * 2 != beaconHashStr.length) { + if (logger) logger.error("Invalid Beacon Hash. (It must be a valid hexadecimal sequence)"); + return false; + } + if (beaconHash.length >= 256) { + if (logger) logger.error("Maximum length of beacon hash is 255 bytes"); + return false; + } + numIterationsExp = parseInt(numIterationsExp); + if (numIterationsExp < 10 || numIterationsExp > 63) { + if (logger) logger.error("Invalid numIterationsExp. (Must be between 10 and 63)"); + return false; + } + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(oldPtauFilename, "ptau", 1); + const { curve, power, ceremonyPower } = await readPTauHeader(fdOld, sections); + if (power != ceremonyPower) { + if (logger) logger.error("This file has been reduced. You cannot contribute into a reduced file."); + return false; + } + if (sections[12]) { + if (logger) logger.warn("Contributing into a file that has phase2 calculated. You will have to prepare phase2 again."); + } + const contributions = await readContributions(fdOld, curve, sections); + const curContribution = { + name, + type: 1, + numIterationsExp, + beaconHash + }; + let lastChallengeHash; + if (contributions.length > 0) lastChallengeHash = contributions[contributions.length - 1].nextChallenge; + else lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); + curContribution.key = await keyFromBeacon(curve, lastChallengeHash, beaconHash, numIterationsExp); + const responseHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + responseHasher.update(lastChallengeHash); + const fdNew = await _iden3_binfileutils.createBinFile(newPTauFilename, "ptau", 1, 7); + await writePTauHeader(fdNew, curve, power); + const startSections = []; + let firstPoints; + firstPoints = await processSection(2, "G1", 2 ** power * 2 - 1, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG1", logger); + curContribution.tauG1 = firstPoints[1]; + firstPoints = await processSection(3, "G2", 2 ** power, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG2", logger); + curContribution.tauG2 = firstPoints[1]; + firstPoints = await processSection(4, "G1", 2 ** power, curContribution.key.alpha.prvKey, curContribution.key.tau.prvKey, "alphaTauG1", logger); + curContribution.alphaG1 = firstPoints[0]; + firstPoints = await processSection(5, "G1", 2 ** power, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG1", logger); + curContribution.betaG1 = firstPoints[0]; + firstPoints = await processSection(6, "G2", 1, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG2", logger); + curContribution.betaG2 = firstPoints[0]; + curContribution.partialHash = toPartialHash(responseHasher); + const buffKey = new Uint8Array(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3); + toPtauPubKeyRpr(buffKey, 0, curve, curContribution.key, false); + responseHasher.update(new Uint8Array(buffKey)); + const hashResponse = responseHasher.digest(); + if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); + const nextChallengeHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + nextChallengeHasher.update(hashResponse); + await hashSection(fdNew, "G1", 2, 2 ** power * 2 - 1, "tauG1", logger); + await hashSection(fdNew, "G2", 3, 2 ** power, "tauG2", logger); + await hashSection(fdNew, "G1", 4, 2 ** power, "alphaTauG1", logger); + await hashSection(fdNew, "G1", 5, 2 ** power, "betaTauG1", logger); + await hashSection(fdNew, "G2", 6, 1, "betaG2", logger); + curContribution.nextChallenge = nextChallengeHasher.digest(); + if (logger) logger.info(formatHash(curContribution.nextChallenge, "Next Challenge Hash: ")); + contributions.push(curContribution); + await writeContributions(fdNew, curve, contributions); + await fdOld.close(); + await fdNew.close(); + return hashResponse; + async function processSection(sectionId, groupName, NPoints, first, inc, sectionName, logger) { + const res = []; + fdOld.pos = sections[sectionId][0].p; + await _iden3_binfileutils.startWriteSection(fdNew, sectionId); + startSections[sectionId] = fdNew.pos; + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const chunkSize = Math.floor((1 << 20) / sG); + let t = first; + for (let i = 0; i < NPoints; i += chunkSize) { + if (logger) logger.debug(`applying key${sectionName}: ${i}/${NPoints}`); + const n = Math.min(NPoints - i, chunkSize); + const buffIn = await fdOld.read(n * sG); + const buffOutLEM = await G.batchApplyKey(buffIn, t, inc); + const promiseWrite = fdNew.write(buffOutLEM); + const buffOutC = await G.batchLEMtoC(buffOutLEM); + responseHasher.update(buffOutC); + await promiseWrite; + if (i == 0) for (let j = 0; j < Math.min(2, NPoints); j++) res.push(G.fromRprLEM(buffOutLEM, j * sG)); + t = curve.Fr.mul(t, curve.Fr.exp(inc, n)); + } + await _iden3_binfileutils.endWriteSection(fdNew); + return res; + } + async function hashSection(fdTo, groupName, sectionId, nPoints, sectionName, logger) { + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const nPointsChunk = Math.floor((1 << 24) / sG); + const oldPos = fdTo.pos; + fdTo.pos = startSections[sectionId]; + for (let i = 0; i < nPoints; i += nPointsChunk) { + if (logger) logger.debug(`Hashing ${sectionName}: ${i}/${nPoints}`); + const n = Math.min(nPoints - i, nPointsChunk); + const buffLEM = await fdTo.read(n * sG); + const buffU = await G.batchLEMtoU(buffLEM); + nextChallengeHasher.update(buffU); + } + fdTo.pos = oldPos; + } +} +//#endregion +//#region src/powersoftau_contribute.js async function contribute(oldPtauFilename, newPTauFilename, name, entropy, logger) { - - const {fd: fdOld, sections} = await binFileUtils__namespace.readBinFile(oldPtauFilename, "ptau", 1); - const {curve, power, ceremonyPower} = await readPTauHeader(fdOld, sections); - if (power != ceremonyPower) { - if (logger) logger.error("This file has been reduced. You cannot contribute into a reduced file."); - throw new Error("This file has been reduced. You cannot contribute into a reduced file."); - } - if (sections[12]) { - if (logger) logger.warn("WARNING: Contributing into a file that has phase2 calculated. You will have to prepare phase2 again."); - } - const contributions = await readContributions(fdOld, curve, sections); - const curContribution = { - name: name, - type: 0, // Beacon - }; - - let lastChallengeHash; - - const rng = await getRandomRng(entropy); - - if (contributions.length>0) { - lastChallengeHash = contributions[contributions.length-1].nextChallenge; - } else { - lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); - } - - // Generate a random key - - - curContribution.key = createPTauKey(curve, lastChallengeHash, rng); - - - const responseHasher = blake2b.blake2b.create({ dkLen: 64 }); - responseHasher.update(lastChallengeHash); - - const fdNew = await binFileUtils__namespace.createBinFile(newPTauFilename, "ptau", 1, 7); - await writePTauHeader(fdNew, curve, power); - - const startSections = []; - - let firstPoints; - firstPoints = await processSection(2, "G1", (2 ** power) * 2 -1, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG1" ); - curContribution.tauG1 = firstPoints[1]; - firstPoints = await processSection(3, "G2", (2 ** power) , curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG2" ); - curContribution.tauG2 = firstPoints[1]; - firstPoints = await processSection(4, "G1", (2 ** power) , curContribution.key.alpha.prvKey, curContribution.key.tau.prvKey, "alphaTauG1" ); - curContribution.alphaG1 = firstPoints[0]; - firstPoints = await processSection(5, "G1", (2 ** power) , curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG1" ); - curContribution.betaG1 = firstPoints[0]; - firstPoints = await processSection(6, "G2", 1, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG2" ); - curContribution.betaG2 = firstPoints[0]; - - curContribution.partialHash = toPartialHash(responseHasher); - - const buffKey = new Uint8Array(curve.F1.n8*2*6+curve.F2.n8*2*3); - - toPtauPubKeyRpr(buffKey, 0, curve, curContribution.key, false); - - responseHasher.update(new Uint8Array(buffKey)); - const hashResponse = responseHasher.digest(); - - if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); - - const nextChallengeHasher = blake2b.blake2b.create({ dkLen: 64 }); - nextChallengeHasher.update(hashResponse); - - await hashSection(fdNew, "G1", 2, (2 ** power) * 2 -1, "tauG1"); - await hashSection(fdNew, "G2", 3, (2 ** power) , "tauG2"); - await hashSection(fdNew, "G1", 4, (2 ** power) , "alphaTauG1"); - await hashSection(fdNew, "G1", 5, (2 ** power) , "betaTauG1"); - await hashSection(fdNew, "G2", 6, 1 , "betaG2"); - - curContribution.nextChallenge = nextChallengeHasher.digest(); - - if (logger) logger.info(formatHash(curContribution.nextChallenge, "Next Challenge Hash: ")); - - contributions.push(curContribution); - - await writeContributions(fdNew, curve, contributions); - - await fdOld.close(); - await fdNew.close(); - - return hashResponse; - - async function processSection(sectionId, groupName, NPoints, first, inc, sectionName) { - const res = []; - fdOld.pos = sections[sectionId][0].p; - - await binFileUtils__namespace.startWriteSection(fdNew, sectionId); - - startSections[sectionId] = fdNew.pos; - - const G = curve[groupName]; - const sG = G.F.n8*2; - const chunkSize = Math.floor((1<<20) / sG); // 128Mb chunks - let t = first; - for (let i=0 ; i. -*/ - + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(oldPtauFilename, "ptau", 1); + const { curve, power, ceremonyPower } = await readPTauHeader(fdOld, sections); + if (power != ceremonyPower) { + if (logger) logger.error("This file has been reduced. You cannot contribute into a reduced file."); + throw new Error("This file has been reduced. You cannot contribute into a reduced file."); + } + if (sections[12]) { + if (logger) logger.warn("WARNING: Contributing into a file that has phase2 calculated. You will have to prepare phase2 again."); + } + const contributions = await readContributions(fdOld, curve, sections); + const curContribution = { + name, + type: 0 + }; + let lastChallengeHash; + const rng = await getRandomRng(entropy); + if (contributions.length > 0) lastChallengeHash = contributions[contributions.length - 1].nextChallenge; + else lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); + curContribution.key = createPTauKey(curve, lastChallengeHash, rng); + const responseHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + responseHasher.update(lastChallengeHash); + const fdNew = await _iden3_binfileutils.createBinFile(newPTauFilename, "ptau", 1, 7); + await writePTauHeader(fdNew, curve, power); + const startSections = []; + let firstPoints; + firstPoints = await processSection(2, "G1", 2 ** power * 2 - 1, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG1"); + curContribution.tauG1 = firstPoints[1]; + firstPoints = await processSection(3, "G2", 2 ** power, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG2"); + curContribution.tauG2 = firstPoints[1]; + firstPoints = await processSection(4, "G1", 2 ** power, curContribution.key.alpha.prvKey, curContribution.key.tau.prvKey, "alphaTauG1"); + curContribution.alphaG1 = firstPoints[0]; + firstPoints = await processSection(5, "G1", 2 ** power, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG1"); + curContribution.betaG1 = firstPoints[0]; + firstPoints = await processSection(6, "G2", 1, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG2"); + curContribution.betaG2 = firstPoints[0]; + curContribution.partialHash = toPartialHash(responseHasher); + const buffKey = new Uint8Array(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3); + toPtauPubKeyRpr(buffKey, 0, curve, curContribution.key, false); + responseHasher.update(new Uint8Array(buffKey)); + const hashResponse = responseHasher.digest(); + if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); + const nextChallengeHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + nextChallengeHasher.update(hashResponse); + await hashSection(fdNew, "G1", 2, 2 ** power * 2 - 1, "tauG1"); + await hashSection(fdNew, "G2", 3, 2 ** power, "tauG2"); + await hashSection(fdNew, "G1", 4, 2 ** power, "alphaTauG1"); + await hashSection(fdNew, "G1", 5, 2 ** power, "betaTauG1"); + await hashSection(fdNew, "G2", 6, 1, "betaG2"); + curContribution.nextChallenge = nextChallengeHasher.digest(); + if (logger) logger.info(formatHash(curContribution.nextChallenge, "Next Challenge Hash: ")); + contributions.push(curContribution); + await writeContributions(fdNew, curve, contributions); + await fdOld.close(); + await fdNew.close(); + return hashResponse; + async function processSection(sectionId, groupName, NPoints, first, inc, sectionName) { + const res = []; + fdOld.pos = sections[sectionId][0].p; + await _iden3_binfileutils.startWriteSection(fdNew, sectionId); + startSections[sectionId] = fdNew.pos; + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const chunkSize = Math.floor((1 << 20) / sG); + let t = first; + for (let i = 0; i < NPoints; i += chunkSize) { + if (logger) logger.debug(`processing: ${sectionName}: ${i}/${NPoints}`); + const n = Math.min(NPoints - i, chunkSize); + const buffIn = await fdOld.read(n * sG); + const buffOutLEM = await G.batchApplyKey(buffIn, t, inc); + const promiseWrite = fdNew.write(buffOutLEM); + const buffOutC = await G.batchLEMtoC(buffOutLEM); + responseHasher.update(buffOutC); + await promiseWrite; + if (i == 0) for (let j = 0; j < Math.min(2, NPoints); j++) res.push(G.fromRprLEM(buffOutLEM, j * sG)); + t = curve.Fr.mul(t, curve.Fr.exp(inc, n)); + } + await _iden3_binfileutils.endWriteSection(fdNew); + return res; + } + async function hashSection(fdTo, groupName, sectionId, nPoints, sectionName) { + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const nPointsChunk = Math.floor((1 << 24) / sG); + const oldPos = fdTo.pos; + fdTo.pos = startSections[sectionId]; + for (let i = 0; i < nPoints; i += nPointsChunk) { + if (logger && i) logger.debug(`Hashing ${sectionName}: ` + i); + const n = Math.min(nPoints - i, nPointsChunk); + const buffLEM = await fdTo.read(n * sG); + const buffU = await G.batchLEMtoU(buffLEM); + nextChallengeHasher.update(buffU); + } + fdTo.pos = oldPos; + } +} +//#endregion +//#region src/powersoftau_preparephase2.js async function preparePhase2(oldPtauFilename, newPTauFilename, logger) { - - const {fd: fdOld, sections} = await binFileUtils__namespace.readBinFile(oldPtauFilename, "ptau", 1); - const {curve, power} = await readPTauHeader(fdOld, sections); - - const fdNew = await binFileUtils__namespace.createBinFile(newPTauFilename, "ptau", 1, 11); - await writePTauHeader(fdNew, curve, power); - - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 2); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 3); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 4); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 5); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 6); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 7); - - await processSection(2, 12, "G1", "tauG1" ); - await processSection(3, 13, "G2", "tauG2" ); - await processSection(4, 14, "G1", "alphaTauG1" ); - await processSection(5, 15, "G1", "betaTauG1" ); - - await fdOld.close(); - await fdNew.close(); - - // await fs.promises.unlink(newPTauFilename+ ".tmp"); - - return; - - async function processSection(oldSectionId, newSectionId, Gstr, sectionName) { - if (logger) logger.debug("Starting section: "+sectionName); - - await binFileUtils__namespace.startWriteSection(fdNew, newSectionId); - - for (let p=0; p<=power; p++) { - await processSectionPower(p); - } - - if (oldSectionId == 2) { - await processSectionPower(power+1); - } - - await binFileUtils__namespace.endWriteSection(fdNew); - - - async function processSectionPower(p) { - const nPoints = 2 ** p; - const G = curve[Gstr]; - curve.Fr; - const sGin = G.F.n8*2; - G.F.n8*3; - - let buff; - buff = new ffjavascript.BigBuffer(nPoints*sGin); - - await binFileUtils__namespace.startReadUniqueSection(fdOld, sections, oldSectionId); - if ((oldSectionId == 2)&&(p==power+1)) { - await fdOld.readToBuffer(buff, 0,(nPoints-1)*sGin ); - buff.set(curve.G1.zeroAffine, (nPoints-1)*sGin ); - } else { - await fdOld.readToBuffer(buff, 0,nPoints*sGin ); - } - await binFileUtils__namespace.endReadSection(fdOld, true); - - - buff = await G.lagrangeEvaluations(buff, "affine", "affine", logger, sectionName); - await fdNew.write(buff); - -/* - if (p <= curve.Fr.s) { - buff = await G.ifft(buff, "affine", "affine", logger, sectionName); - await fdNew.write(buff); - } else if (p == curve.Fr.s+1) { - const smallM = 1<. -*/ - + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(oldPtauFilename, "ptau", 1); + const { curve, power } = await readPTauHeader(fdOld, sections); + const fdNew = await _iden3_binfileutils.createBinFile(newPTauFilename, "ptau", 1, 11); + await writePTauHeader(fdNew, curve, power); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 2); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 3); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 4); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 5); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 6); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 7); + await processSection(2, 12, "G1", "tauG1"); + await processSection(3, 13, "G2", "tauG2"); + await processSection(4, 14, "G1", "alphaTauG1"); + await processSection(5, 15, "G1", "betaTauG1"); + await fdOld.close(); + await fdNew.close(); + return; + async function processSection(oldSectionId, newSectionId, Gstr, sectionName) { + if (logger) logger.debug("Starting section: " + sectionName); + await _iden3_binfileutils.startWriteSection(fdNew, newSectionId); + for (let p = 0; p <= power; p++) await processSectionPower(p); + if (oldSectionId == 2) await processSectionPower(power + 1); + await _iden3_binfileutils.endWriteSection(fdNew); + async function processSectionPower(p) { + const nPoints = 2 ** p; + const G = curve[Gstr]; + const sGin = G.F.n8 * 2; + let buff; + buff = new ffjavascript.BigBuffer(nPoints * sGin); + await _iden3_binfileutils.startReadUniqueSection(fdOld, sections, oldSectionId); + if (oldSectionId == 2 && p == power + 1) { + await fdOld.readToBuffer(buff, 0, (nPoints - 1) * sGin); + buff.set(curve.G1.zeroAffine, (nPoints - 1) * sGin); + } else await fdOld.readToBuffer(buff, 0, nPoints * sGin); + await _iden3_binfileutils.endReadSection(fdOld, true); + buff = await G.lagrangeEvaluations(buff, "affine", "affine", logger, sectionName); + await fdNew.write(buff); + } + } +} +//#endregion +//#region src/powersoftau_truncate.js async function truncate(ptauFilename, template, logger) { - - const {fd: fdOld, sections} = await binFileUtils__namespace.readBinFile(ptauFilename, "ptau", 1); - const {curve, power, ceremonyPower} = await readPTauHeader(fdOld, sections); - - const sG1 = curve.G1.F.n8*2; - const sG2 = curve.G2.F.n8*2; - - for (let p=1; p. -*/ - + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(ptauFilename, "ptau", 1); + const { curve, power, ceremonyPower } = await readPTauHeader(fdOld, sections); + const sG1 = curve.G1.F.n8 * 2; + const sG2 = curve.G2.F.n8 * 2; + for (let p = 1; p < power; p++) await generateTruncate(p); + await fdOld.close(); + return true; + async function generateTruncate(p) { + let sP = p.toString(); + while (sP.length < 2) sP = "0" + sP; + if (logger) logger.debug("Writing Power: " + sP); + const fdNew = await _iden3_binfileutils.createBinFile(template + sP + ".ptau", "ptau", 1, 11); + await writePTauHeader(fdNew, curve, p, ceremonyPower); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 2, (2 ** p * 2 - 1) * sG1); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 3, 2 ** p * sG2); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 4, 2 ** p * sG1); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 5, 2 ** p * sG1); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 6, sG2); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 7); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 12, (2 ** (p + 1) * 2 - 1) * sG1); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 13, (2 ** p * 2 - 1) * sG2); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 14, (2 ** p * 2 - 1) * sG1); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 15, (2 ** p * 2 - 1) * sG1); + await fdNew.close(); + } +} +//#endregion +//#region src/powersoftau_convert.js async function convert(oldPtauFilename, newPTauFilename, logger) { - - const {fd: fdOld, sections} = await binFileUtils__namespace.readBinFile(oldPtauFilename, "ptau", 1); - const {curve, power} = await readPTauHeader(fdOld, sections); - - const fdNew = await binFileUtils__namespace.createBinFile(newPTauFilename, "ptau", 1, 11); - await writePTauHeader(fdNew, curve, power); - - // const fdTmp = await fastFile.createOverride(newPTauFilename+ ".tmp"); - - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 2); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 3); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 4); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 5); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 6); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 7); - - await processSection(2, 12, "G1", "tauG1" ); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 13); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 14); - await binFileUtils__namespace.copySection(fdOld, sections, fdNew, 15); - - await fdOld.close(); - await fdNew.close(); - - // await fs.promises.unlink(newPTauFilename+ ".tmp"); - - return; - - async function processSection(oldSectionId, newSectionId, Gstr, sectionName) { - if (logger) logger.debug("Starting section: "+sectionName); - - await binFileUtils__namespace.startWriteSection(fdNew, newSectionId); - - const size = sections[newSectionId][0].size; - const chunkSize = fdOld.pageSize; - await binFileUtils__namespace.startReadUniqueSection(fdOld, sections, newSectionId); - for (let p=0; p. -*/ - + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(oldPtauFilename, "ptau", 1); + const { curve, power } = await readPTauHeader(fdOld, sections); + const fdNew = await _iden3_binfileutils.createBinFile(newPTauFilename, "ptau", 1, 11); + await writePTauHeader(fdNew, curve, power); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 2); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 3); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 4); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 5); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 6); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 7); + await processSection(2, 12, "G1", "tauG1"); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 13); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 14); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 15); + await fdOld.close(); + await fdNew.close(); + return; + async function processSection(oldSectionId, newSectionId, Gstr, sectionName) { + if (logger) logger.debug("Starting section: " + sectionName); + await _iden3_binfileutils.startWriteSection(fdNew, newSectionId); + const size = sections[newSectionId][0].size; + const chunkSize = fdOld.pageSize; + await _iden3_binfileutils.startReadUniqueSection(fdOld, sections, newSectionId); + for (let p = 0; p < size; p += chunkSize) { + const l = Math.min(size - p, chunkSize); + const buff = await fdOld.read(l); + await fdNew.write(buff); + } + await _iden3_binfileutils.endReadSection(fdOld); + if (oldSectionId == 2) await processSectionPower(power + 1); + await _iden3_binfileutils.endWriteSection(fdNew); + async function processSectionPower(p) { + const nPoints = 2 ** p; + const G = curve[Gstr]; + const sGin = G.F.n8 * 2; + let buff; + buff = new ffjavascript.BigBuffer(nPoints * sGin); + await _iden3_binfileutils.startReadUniqueSection(fdOld, sections, oldSectionId); + if (oldSectionId == 2 && p == power + 1) { + await fdOld.readToBuffer(buff, 0, (nPoints - 1) * sGin); + buff.set(curve.G1.zeroAffine, (nPoints - 1) * sGin); + } else await fdOld.readToBuffer(buff, 0, nPoints * sGin); + await _iden3_binfileutils.endReadSection(fdOld, true); + buff = await G.lagrangeEvaluations(buff, "affine", "affine", logger, sectionName); + await fdNew.write(buff); + } + } +} +//#endregion +//#region src/powersoftau_export_json.js async function exportJson(pTauFilename, verbose) { - const {fd, sections} = await binFileUtils__namespace.readBinFile(pTauFilename, "ptau", 1); - - const {curve, power} = await readPTauHeader(fd, sections); - - const pTau = {}; - pTau.q = curve.q; - pTau.power = power; - pTau.contributions = await readContributions(fd, curve, sections); - - pTau.tauG1 = await exportSection(2, "G1", (2 ** power)*2 -1, "tauG1"); - pTau.tauG2 = await exportSection(3, "G2", (2 ** power), "tauG2"); - pTau.alphaTauG1 = await exportSection(4, "G1", (2 ** power), "alphaTauG1"); - pTau.betaTauG1 = await exportSection(5, "G1", (2 ** power), "betaTauG1"); - pTau.betaG2 = await exportSection(6, "G2", 1, "betaG2"); - - pTau.lTauG1 = await exportLagrange(12, "G1", "lTauG1"); - pTau.lTauG2 = await exportLagrange(13, "G2", "lTauG2"); - pTau.lAlphaTauG1 = await exportLagrange(14, "G1", "lAlphaTauG2"); - pTau.lBetaTauG1 = await exportLagrange(15, "G1", "lBetaTauG2"); - - await fd.close(); - - return stringifyBigIntsWithField(curve.Fr, pTau); - - - - async function exportSection(sectionId, groupName, nPoints, sectionName) { - const G = curve[groupName]; - const sG = G.F.n8*2; - - const res = []; - await binFileUtils__namespace.startReadUniqueSection(fd, sections, sectionId); - for (let i=0; i< nPoints; i++) { - if ((verbose)&&i&&(i%10000 == 0)) console.log(`${sectionName}: ` + i); - const buff = await fd.read(sG); - res.push(G.fromRprLEM(buff, 0)); - } - await binFileUtils__namespace.endReadSection(fd); - - return res; - } - - async function exportLagrange(sectionId, groupName, sectionName) { - const G = curve[groupName]; - const sG = G.F.n8*2; - - const res = []; - await binFileUtils__namespace.startReadUniqueSection(fd, sections, sectionId); - for (let p=0; p<=power; p++) { - if (verbose) console.log(`${sectionName}: Power: ${p}`); - res[p] = []; - const nPoints = (2 ** p); - for (let i=0; i. -*/ - -var powersoftau = /*#__PURE__*/Object.freeze({ - __proto__: null, - newAccumulator: newAccumulator, - exportChallenge: exportChallenge, - importResponse: importResponse, - verify: verify, - challengeContribute: challengeContribute, - beacon: beacon$1, - contribute: contribute, - preparePhase2: preparePhase2, - truncate: truncate, - convert: convert, - exportJson: exportJson + const { fd, sections } = await _iden3_binfileutils.readBinFile(pTauFilename, "ptau", 1); + const { curve, power } = await readPTauHeader(fd, sections); + const pTau = {}; + pTau.q = curve.q; + pTau.power = power; + pTau.contributions = await readContributions(fd, curve, sections); + pTau.tauG1 = await exportSection(2, "G1", 2 ** power * 2 - 1, "tauG1"); + pTau.tauG2 = await exportSection(3, "G2", 2 ** power, "tauG2"); + pTau.alphaTauG1 = await exportSection(4, "G1", 2 ** power, "alphaTauG1"); + pTau.betaTauG1 = await exportSection(5, "G1", 2 ** power, "betaTauG1"); + pTau.betaG2 = await exportSection(6, "G2", 1, "betaG2"); + pTau.lTauG1 = await exportLagrange(12, "G1", "lTauG1"); + pTau.lTauG2 = await exportLagrange(13, "G2", "lTauG2"); + pTau.lAlphaTauG1 = await exportLagrange(14, "G1", "lAlphaTauG2"); + pTau.lBetaTauG1 = await exportLagrange(15, "G1", "lBetaTauG2"); + await fd.close(); + return stringifyBigIntsWithField(curve.Fr, pTau); + async function exportSection(sectionId, groupName, nPoints, sectionName) { + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const res = []; + await _iden3_binfileutils.startReadUniqueSection(fd, sections, sectionId); + for (let i = 0; i < nPoints; i++) { + if (verbose && i && i % 1e4 == 0) console.log(`${sectionName}: ` + i); + const buff = await fd.read(sG); + res.push(G.fromRprLEM(buff, 0)); + } + await _iden3_binfileutils.endReadSection(fd); + return res; + } + async function exportLagrange(sectionId, groupName, sectionName) { + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const res = []; + await _iden3_binfileutils.startReadUniqueSection(fd, sections, sectionId); + for (let p = 0; p <= power; p++) { + if (verbose) console.log(`${sectionName}: Power: ${p}`); + res[p] = []; + const nPoints = 2 ** p; + for (let i = 0; i < nPoints; i++) { + if (verbose && i && i % 1e4 == 0) console.log(`${sectionName}: ${i}/${nPoints}`); + const buff = await fd.read(sG); + res[p].push(G.fromRprLEM(buff, 0)); + } + } + await _iden3_binfileutils.endReadSection(fd, true); + return res; + } +} +//#endregion +//#region src/powersoftau.js +var powersoftau_exports = /* @__PURE__ */ __exportAll({ + beacon: () => beacon$1, + challengeContribute: () => challengeContribute, + contribute: () => contribute, + convert: () => convert, + exportChallenge: () => exportChallenge, + exportJson: () => exportJson, + importResponse: () => importResponse, + newAccumulator: () => newAccumulator, + preparePhase2: () => preparePhase2, + truncate: () => truncate, + verify: () => verify }); - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - +//#endregion +//#region src/r1cs_print.js function r1csPrint(r1cs, syms, logger) { - for (let i=0; i { - let S = ""; - const keys = Object.keys(lc); - keys.forEach( (k) => { - let name = syms.varIdx2Name[k]; - if (name == "one") name = "1"; - - let vs = r1cs.curve.Fr.toString(lc[k]); - if (vs == "1") vs = ""; // Do not show ones - if (vs == "-1") vs = "-"; // Do not show ones - if ((S!="")&&(vs[0]!="-")) vs = "+"+vs; - if (S!="") vs = " "+vs; - S= S + vs + name; - }); - return S; - }; - const S = `[ ${lc2str(c[0])} ] * [ ${lc2str(c[1])} ] - [ ${lc2str(c[2])} ] = 0`; - if (logger) logger.info(S); - } - -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -const bls12381r = ffjavascript.Scalar.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16); -const bn128r = ffjavascript.Scalar.e("21888242871839275222246405745257275088548364400416034343698204186575808495617"); - + for (let i = 0; i < r1cs.constraints.length; i++) printCostraint(r1cs.constraints[i]); + function printCostraint(c) { + const lc2str = (lc) => { + let S = ""; + Object.keys(lc).forEach((k) => { + let name = syms.varIdx2Name[k]; + if (name == "one") name = "1"; + let vs = r1cs.curve.Fr.toString(lc[k]); + if (vs == "1") vs = ""; + if (vs == "-1") vs = "-"; + if (S != "" && vs[0] != "-") vs = "+" + vs; + if (S != "") vs = " " + vs; + S = S + vs + name; + }); + return S; + }; + const S = `[ ${lc2str(c[0])} ] * [ ${lc2str(c[1])} ] - [ ${lc2str(c[2])} ] = 0`; + if (logger) logger.info(S); + } +} +//#endregion +//#region src/r1cs_info.js +var bls12381r = ffjavascript.Scalar.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16); +var bn128r = ffjavascript.Scalar.e("21888242871839275222246405745257275088548364400416034343698204186575808495617"); async function r1csInfo(r1csName, logger) { - - const cir = await r1csfile.readR1cs(r1csName); - - if (ffjavascript.Scalar.eq(cir.prime, bn128r)) { - if (logger) logger.info("Curve: bn-128"); - } else if (ffjavascript.Scalar.eq(cir.prime, bls12381r)) { - if (logger) logger.info("Curve: bls12-381"); - } else { - if (logger) logger.info(`Unknown Curve. Prime: ${ffjavascript.Scalar.toString(cir.prime)}`); - } - if (logger) logger.info(`# of Wires: ${cir.nVars}`); - if (logger) logger.info(`# of Constraints: ${cir.nConstraints}`); - if (logger) logger.info(`# of Private Inputs: ${cir.nPrvInputs}`); - if (logger) logger.info(`# of Public Inputs: ${cir.nPubInputs}`); - if (logger) logger.info(`# of Labels: ${cir.nLabels}`); - if (logger) logger.info(`# of Outputs: ${cir.nOutputs}`); - - return cir; -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - - + const cir = await (0, r1csfile.readR1cs)(r1csName); + if (ffjavascript.Scalar.eq(cir.prime, bn128r)) { + if (logger) logger.info("Curve: bn-128"); + } else if (ffjavascript.Scalar.eq(cir.prime, bls12381r)) { + if (logger) logger.info("Curve: bls12-381"); + } else if (logger) logger.info(`Unknown Curve. Prime: ${ffjavascript.Scalar.toString(cir.prime)}`); + if (logger) logger.info(`# of Wires: ${cir.nVars}`); + if (logger) logger.info(`# of Constraints: ${cir.nConstraints}`); + if (logger) logger.info(`# of Private Inputs: ${cir.nPrvInputs}`); + if (logger) logger.info(`# of Public Inputs: ${cir.nPubInputs}`); + if (logger) logger.info(`# of Labels: ${cir.nLabels}`); + if (logger) logger.info(`# of Outputs: ${cir.nOutputs}`); + return cir; +} +//#endregion +//#region src/r1cs_export_json.js async function r1csExportJson(r1csFileName, logger) { - - const cir = await r1csfile.readR1cs(r1csFileName, true, true, true, logger); - const Fr=cir.curve.Fr; - delete cir.curve; - delete cir.F; - - return stringifyBigIntsWithField(Fr, cir); -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -var r1cs = /*#__PURE__*/Object.freeze({ - __proto__: null, - print: r1csPrint, - info: r1csInfo, - exportJson: r1csExportJson + const cir = await (0, r1csfile.readR1cs)(r1csFileName, true, true, true, logger); + const Fr = cir.curve.Fr; + delete cir.curve; + delete cir.F; + return stringifyBigIntsWithField(Fr, cir); +} +//#endregion +//#region src/r1cs.js +var r1cs_exports = /* @__PURE__ */ __exportAll({ + exportJson: () => r1csExportJson, + info: () => r1csInfo, + print: () => r1csPrint }); - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - +//#endregion +//#region src/loadsyms.js async function loadSymbols(symFileName) { - const sym = { - labelIdx2Name: [ "one" ], - varIdx2Name: [ "one" ], - componentIdx2Name: [] - }; - const fd = await fastFile__namespace.readExisting(symFileName); - const buff = await fd.read(fd.totalSize); - const symsStr = new TextDecoder("utf-8").decode(buff); - const lines = symsStr.split("\n"); - for (let i=0; i. -*/ -const {unstringifyBigInts: unstringifyBigInts$7} = ffjavascript.utils; - - + const sym = { + labelIdx2Name: ["one"], + varIdx2Name: ["one"], + componentIdx2Name: [] + }; + const fd = await fastfile.readExisting(symFileName); + const buff = await fd.read(fd.totalSize); + const lines = new TextDecoder("utf-8").decode(buff).split("\n"); + for (let i = 0; i < lines.length; i++) { + const arr = lines[i].split(","); + if (arr.length != 4) continue; + if (sym.varIdx2Name[arr[1]]) sym.varIdx2Name[arr[1]] += "|" + arr[3]; + else sym.varIdx2Name[arr[1]] = arr[3]; + sym.labelIdx2Name[arr[0]] = arr[3]; + if (!sym.componentIdx2Name[arr[2]]) sym.componentIdx2Name[arr[2]] = extractComponent(arr[3]); + } + await fd.close(); + return sym; + function extractComponent(name) { + const arr = name.split("."); + arr.pop(); + return arr.join("."); + } +} +//#endregion +//#region src/wtns_debug.js +var { unstringifyBigInts: unstringifyBigInts$7 } = ffjavascript.utils; async function wtnsDebug(_input, wasmFileName, wtnsFileName, symName, options, logger) { - - const input = unstringifyBigInts$7(_input); - - const fdWasm = await fastFile__namespace.readExisting(wasmFileName); - const wasm = await fdWasm.read(fdWasm.totalSize); - await fdWasm.close(); - - const wcOps = {...options, sanityCheck: true}; - let sym = await loadSymbols(symName); - if (options.set) { - if (!sym) sym = await loadSymbols(symName); - wcOps.logSetSignal= function(labelIdx, value) { - // The line below splits the arrow log into 2 strings to avoid some Secure ECMAScript issues - if (logger) logger.info("SET " + sym.labelIdx2Name[labelIdx] + " <" + "-- " + value.toString()); - }; - } - if (options.get) { - if (!sym) sym = await loadSymbols(symName); - wcOps.logGetSignal= function(varIdx, value) { - // The line below splits the arrow log into 2 strings to avoid some Secure ECMAScript issues - if (logger) logger.info("GET " + sym.labelIdx2Name[varIdx] + " --" + "> " + value.toString()); - }; - } - if (options.trigger) { - if (!sym) sym = await loadSymbols(symName); - wcOps.logStartComponent= function(cIdx) { - if (logger) logger.info("START: " + sym.componentIdx2Name[cIdx]); - }; - wcOps.logFinishComponent= function(cIdx) { - if (logger) logger.info("FINISH: " + sym.componentIdx2Name[cIdx]); - }; - } - wcOps.sym = sym; - - const wc = await circom_runtime.WitnessCalculatorBuilder(wasm, wcOps); - const w = await wc.calculateWitness(input, true); - - const fdWtns = await binFileUtils__namespace.createBinFile(wtnsFileName, "wtns", 2, 2); - - await write(fdWtns, w, wc.prime); - - await fdWtns.close(); -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - + const input = unstringifyBigInts$7(_input); + const fdWasm = await fastfile.readExisting(wasmFileName); + const wasm = await fdWasm.read(fdWasm.totalSize); + await fdWasm.close(); + const wcOps = { + ...options, + sanityCheck: true + }; + let sym = await loadSymbols(symName); + if (options.set) { + if (!sym) sym = await loadSymbols(symName); + wcOps.logSetSignal = function(labelIdx, value) { + if (logger) logger.info("SET " + sym.labelIdx2Name[labelIdx] + " <-- " + value.toString()); + }; + } + if (options.get) { + if (!sym) sym = await loadSymbols(symName); + wcOps.logGetSignal = function(varIdx, value) { + if (logger) logger.info("GET " + sym.labelIdx2Name[varIdx] + " --> " + value.toString()); + }; + } + if (options.trigger) { + if (!sym) sym = await loadSymbols(symName); + wcOps.logStartComponent = function(cIdx) { + if (logger) logger.info("START: " + sym.componentIdx2Name[cIdx]); + }; + wcOps.logFinishComponent = function(cIdx) { + if (logger) logger.info("FINISH: " + sym.componentIdx2Name[cIdx]); + }; + } + wcOps.sym = sym; + const wc = await (0, circom_runtime.WitnessCalculatorBuilder)(wasm, wcOps); + const w = await wc.calculateWitness(input, true); + const fdWtns = await _iden3_binfileutils.createBinFile(wtnsFileName, "wtns", 2, 2); + await write(fdWtns, w, wc.prime); + await fdWtns.close(); +} +//#endregion +//#region src/wtns_export_json.js async function wtnsExportJson(wtnsFileName) { - - const w = await read(wtnsFileName); - - return w; -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - + return await read(wtnsFileName); +} +//#endregion +//#region src/wtns_check.js async function wtnsCheck(r1csFilename, wtnsFilename, logger) { - - if (logger) logger.info("WITNESS CHECKING STARTED"); - - // Read r1cs file - if (logger) logger.info("> Reading r1cs file"); - const { - fd: fdR1cs, - sections: sectionsR1cs - } = await binFileUtils__namespace.readBinFile(r1csFilename, "r1cs", 1, 1 << 22, 1 << 24); - const r1cs = await r1csfile.readR1csFd(fdR1cs, sectionsR1cs, { loadConstraints: false, loadCustomGates: false }); - - // Read witness file - if (logger) logger.info("> Reading witness file"); - const { - fd: fdWtns, - sections: wtnsSections - } = await binFileUtils__namespace.readBinFile(wtnsFilename, "wtns", 2, 1 << 22, 1 << 24); - const wtnsHeader = await readHeader(fdWtns, wtnsSections); - - if (!ffjavascript.Scalar.eq(r1cs.prime, wtnsHeader.q)) { - throw new Error("Curve of the witness does not match the curve of the proving key"); - } - - const buffWitness = await binFileUtils__namespace.readSection(fdWtns, wtnsSections, 2); - await fdWtns.close(); - - const curve = await getCurveFromR(r1cs.prime); - const Fr = curve.Fr; - const sFr = Fr.n8; - - const bR1cs = await binFileUtils__namespace.readSection(fdR1cs, sectionsR1cs, 2); - - if (logger) { - logger.info("----------------------------"); - logger.info(" WITNESS CHECK"); - logger.info(` Curve: ${r1cs.curve.name}`); - logger.info(` Vars (wires): ${r1cs.nVars}`); - logger.info(` Outputs: ${r1cs.nOutputs}`); - logger.info(` Public Inputs: ${r1cs.nPubInputs}`); - logger.info(` Private Inputs: ${r1cs.nPrvInputs}`); - logger.info(` Labels: ${r1cs.nLabels}`); - logger.info(` Constraints: ${r1cs.nConstraints}`); - logger.info(` Custom Gates: ${r1cs.useCustomGates}`); - logger.info("----------------------------"); - } - - if (logger) logger.info("> Checking witness correctness"); - - let bR1csPos = 0; - let res = true; - for (let i = 0; i < r1cs.nConstraints; i++) { - if ((logger) && (i !== 0) && (i % 500000 === 0)) { - logger.info(`··· processing r1cs constraints ${i}/${r1cs.nConstraints}`); - } - - //Read the three linear combinations of the constraint where A * B - C = 0 - const lcA = readLC(); - const lcB = readLC(); - const lcC = readLC(); - - // Evaluate the linear combinations - const evalA = EvaluateLinearCombination(lcA); - const evalB = EvaluateLinearCombination(lcB); - const evalC = EvaluateLinearCombination(lcC); - - // Check that A * B - C == 0 - if (!Fr.eq(Fr.sub(Fr.mul(evalA, evalB), evalC), Fr.zero)) { - logger.warn("··· aborting checking process at constraint " + i); - res = false; - break; - } - } - - fdR1cs.close(); - - if (logger) { - if (res) { - logger.info("WITNESS IS CORRECT"); - logger.info("WITNESS CHECKING FINISHED SUCCESSFULLY"); - } else { - logger.warn("WITNESS IS NOT CORRECT"); - logger.warn("WITNESS CHECKING FINISHED UNSUCCESSFULLY"); - } - } - - return res; - - function EvaluateLinearCombination(lc) { - let res = Fr.zero; - - const keys = Object.keys(lc); - keys.forEach((signalId) => { - const signalValue = getWitnessValue(signalId); - const signalFactor = lc[signalId]; - - res = Fr.add(res, Fr.mul(signalValue, signalFactor)); - }); - - return res; - } - - function readLC() { - const lc = {}; - - const buffUL32 = bR1cs.slice(bR1csPos, bR1csPos + 4); - bR1csPos += 4; - const buffUL32V = new DataView(buffUL32.buffer); - const nIdx = buffUL32V.getUint32(0, true); - - const buff = bR1cs.slice(bR1csPos, bR1csPos + (4 + r1cs.n8) * nIdx); - bR1csPos += (4 + r1cs.n8) * nIdx; - const buffV = new DataView(buff.buffer); - for (let i = 0; i < nIdx; i++) { - const idx = buffV.getUint32(i * (4 + r1cs.n8), true); - const val = r1cs.F.fromRprLE(buff, i * (4 + r1cs.n8) + 4); - lc[idx] = val; - } - return lc; - } - - function getWitnessValue(signalId) { - return Fr.fromRprLE(buffWitness.slice(signalId * sFr, signalId * sFr + sFr)); - } -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -var wtns = /*#__PURE__*/Object.freeze({ - __proto__: null, - calculate: wtnsCalculate, - debug: wtnsDebug, - exportJson: wtnsExportJson, - check: wtnsCheck + if (logger) logger.info("WITNESS CHECKING STARTED"); + if (logger) logger.info("> Reading r1cs file"); + const { fd: fdR1cs, sections: sectionsR1cs } = await _iden3_binfileutils.readBinFile(r1csFilename, "r1cs", 1, 1 << 22, 1 << 24); + const r1cs = await (0, r1csfile.readR1csFd)(fdR1cs, sectionsR1cs, { + loadConstraints: false, + loadCustomGates: false + }); + if (logger) logger.info("> Reading witness file"); + const { fd: fdWtns, sections: wtnsSections } = await _iden3_binfileutils.readBinFile(wtnsFilename, "wtns", 2, 1 << 22, 1 << 24); + const wtnsHeader = await readHeader(fdWtns, wtnsSections); + if (!ffjavascript.Scalar.eq(r1cs.prime, wtnsHeader.q)) throw new Error("Curve of the witness does not match the curve of the proving key"); + const buffWitness = await _iden3_binfileutils.readSection(fdWtns, wtnsSections, 2); + await fdWtns.close(); + const Fr = (await getCurveFromR(r1cs.prime)).Fr; + const sFr = Fr.n8; + const bR1cs = await _iden3_binfileutils.readSection(fdR1cs, sectionsR1cs, 2); + if (logger) { + logger.info("----------------------------"); + logger.info(" WITNESS CHECK"); + logger.info(` Curve: ${r1cs.curve.name}`); + logger.info(` Vars (wires): ${r1cs.nVars}`); + logger.info(` Outputs: ${r1cs.nOutputs}`); + logger.info(` Public Inputs: ${r1cs.nPubInputs}`); + logger.info(` Private Inputs: ${r1cs.nPrvInputs}`); + logger.info(` Labels: ${r1cs.nLabels}`); + logger.info(` Constraints: ${r1cs.nConstraints}`); + logger.info(` Custom Gates: ${r1cs.useCustomGates}`); + logger.info("----------------------------"); + } + if (logger) logger.info("> Checking witness correctness"); + let bR1csPos = 0; + let res = true; + for (let i = 0; i < r1cs.nConstraints; i++) { + if (logger && i !== 0 && i % 5e5 === 0) logger.info(`··· processing r1cs constraints ${i}/${r1cs.nConstraints}`); + const lcA = readLC(); + const lcB = readLC(); + const lcC = readLC(); + const evalA = EvaluateLinearCombination(lcA); + const evalB = EvaluateLinearCombination(lcB); + const evalC = EvaluateLinearCombination(lcC); + if (!Fr.eq(Fr.sub(Fr.mul(evalA, evalB), evalC), Fr.zero)) { + logger.warn("··· aborting checking process at constraint " + i); + res = false; + break; + } + } + fdR1cs.close(); + if (logger) if (res) { + logger.info("WITNESS IS CORRECT"); + logger.info("WITNESS CHECKING FINISHED SUCCESSFULLY"); + } else { + logger.warn("WITNESS IS NOT CORRECT"); + logger.warn("WITNESS CHECKING FINISHED UNSUCCESSFULLY"); + } + return res; + function EvaluateLinearCombination(lc) { + let res = Fr.zero; + Object.keys(lc).forEach((signalId) => { + const signalValue = getWitnessValue(signalId); + const signalFactor = lc[signalId]; + res = Fr.add(res, Fr.mul(signalValue, signalFactor)); + }); + return res; + } + function readLC() { + const lc = {}; + const buffUL32 = bR1cs.slice(bR1csPos, bR1csPos + 4); + bR1csPos += 4; + const nIdx = new DataView(buffUL32.buffer).getUint32(0, true); + const buff = bR1cs.slice(bR1csPos, bR1csPos + (4 + r1cs.n8) * nIdx); + bR1csPos += (4 + r1cs.n8) * nIdx; + const buffV = new DataView(buff.buffer); + for (let i = 0; i < nIdx; i++) { + const idx = buffV.getUint32(i * (4 + r1cs.n8), true); + lc[idx] = r1cs.F.fromRprLE(buff, i * (4 + r1cs.n8) + 4); + } + return lc; + } + function getWitnessValue(signalId) { + return Fr.fromRprLE(buffWitness.slice(signalId * sFr, signalId * sFr + sFr)); + } +} +//#endregion +//#region src/wtns.js +var wtns_exports = /* @__PURE__ */ __exportAll({ + calculate: () => wtnsCalculate, + check: () => wtnsCheck, + debug: () => wtnsDebug, + exportJson: () => wtnsExportJson }); - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -const SUBARRAY_SIZE = 0x40000; - -const BigArrayHandler = { - get: function(obj, prop) { - if (!isNaN(prop)) { - return obj.getElement(prop); - } else return obj[prop]; - }, - set: function(obj, prop, value) { - if (!isNaN(prop)) { - return obj.setElement(prop, value); - } else { - obj[prop] = value; - return true; - } - } +//#endregion +//#region src/bigarray.js +var SUBARRAY_SIZE = 262144; +var BigArrayHandler = { + get: function(obj, prop) { + if (!isNaN(prop)) return obj.getElement(prop); + else return obj[prop]; + }, + set: function(obj, prop, value) { + if (!isNaN(prop)) return obj.setElement(prop, value); + else { + obj[prop] = value; + return true; + } + } }; - -class _BigArray { - constructor (initSize) { - this.length = initSize || 0; - this.arr = new Array(SUBARRAY_SIZE); - - for (let i=0; i= this.length) this.length = idx+1; - return true; - } - getKeys() { - const newA = new BigArray(); - for (let i=0; i. -*/ - +var _BigArray = class { + constructor(initSize) { + this.length = initSize || 0; + this.arr = new Array(SUBARRAY_SIZE); + for (let i = 0; i < initSize; i += SUBARRAY_SIZE) this.arr[i / SUBARRAY_SIZE] = new Array(Math.min(SUBARRAY_SIZE, initSize - i)); + return this; + } + push() { + for (let i = 0; i < arguments.length; i++) this.setElement(this.length, arguments[i]); + } + slice(f, t) { + const arr = new Array(t - f); + for (let i = f; i < t; i++) arr[i - f] = this.getElement(i); + return arr; + } + getElement(idx) { + idx = parseInt(idx); + const idx1 = Math.floor(idx / SUBARRAY_SIZE); + const idx2 = idx % SUBARRAY_SIZE; + return this.arr[idx1] ? this.arr[idx1][idx2] : void 0; + } + setElement(idx, value) { + idx = parseInt(idx); + const idx1 = Math.floor(idx / SUBARRAY_SIZE); + if (!this.arr[idx1]) this.arr[idx1] = new Array(SUBARRAY_SIZE); + const idx2 = idx % SUBARRAY_SIZE; + this.arr[idx1][idx2] = value; + if (idx >= this.length) this.length = idx + 1; + return true; + } + getKeys() { + const newA = new BigArray(); + for (let i = 0; i < this.arr.length; i++) if (this.arr[i]) { + for (let j = 0; j < this.arr[i].length; j++) if (typeof this.arr[i][j] !== "undefined") newA.push(i * SUBARRAY_SIZE + j); + } + return newA; + } +}; +var BigArray = class { + constructor(initSize) { + const obj = new _BigArray(initSize); + return new Proxy(obj, BigArrayHandler); + } +}; +//#endregion +//#region src/zkey_new.js async function newZKey(r1csName, ptauName, zkeyName, logger) { - - const TAU_G1 = 0; - const TAU_G2 = 1; - const ALPHATAU_G1 = 2; - const BETATAU_G1 = 3; - const csHasher = blake2b.blake2b.create({ dkLen: 64 }); - - const {fd: fdPTau, sections: sectionsPTau} = await binFileUtils.readBinFile(ptauName, "ptau", 1, 1<<22, 1<<24); - const {curve, power} = await readPTauHeader(fdPTau, sectionsPTau); - const {fd: fdR1cs, sections: sectionsR1cs} = await binFileUtils.readBinFile(r1csName, "r1cs", 1, 1<<22, 1<<24); - const r1cs = await r1csfile.readR1csHeader(fdR1cs, sectionsR1cs, false); - - const fdZKey = await binFileUtils.createBinFile(zkeyName, "zkey", 1, 10, 1<<22, 1<<24); - - const sG1 = curve.G1.F.n8*2; - const sG2 = curve.G2.F.n8*2; - - if (r1cs.prime != curve.r) { - if (logger) logger.error("r1cs curve does not match powers of tau ceremony curve"); - return -1; - } - - const cirPower = log2(r1cs.nConstraints + r1cs.nPubInputs + r1cs.nOutputs +1 -1) +1; - - if (cirPower > power) { - if (logger) logger.error(`circuit too big for this power of tau ceremony. ${r1cs.nConstraints}*2 > 2**${power}`); - return -1; - } - - if (!sectionsPTau[12]) { - if (logger) logger.error("Powers of tau is not prepared."); - return -1; - } - - const nPublic = r1cs.nOutputs + r1cs.nPubInputs; - const domainSize = 2 ** cirPower; - - // Write the header - /////////// - await binFileUtils.startWriteSection(fdZKey, 1); - await fdZKey.writeULE32(1); // Groth - await binFileUtils.endWriteSection(fdZKey); - - // Write the Groth header section - /////////// - - await binFileUtils.startWriteSection(fdZKey, 2); - const primeQ = curve.q; - const n8q = (Math.floor( (ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) +1)*8; - - const primeR = curve.r; - const n8r = (Math.floor( (ffjavascript.Scalar.bitLength(primeR) - 1) / 64) +1)*8; - const Rr = ffjavascript.Scalar.mod(ffjavascript.Scalar.shl(1, n8r*8), primeR); - const R2r = curve.Fr.e(ffjavascript.Scalar.mod(ffjavascript.Scalar.mul(Rr,Rr), primeR)); - - await fdZKey.writeULE32(n8q); - await binFileUtils.writeBigInt(fdZKey, primeQ, n8q); - await fdZKey.writeULE32(n8r); - await binFileUtils.writeBigInt(fdZKey, primeR, n8r); - await fdZKey.writeULE32(r1cs.nVars); // Total number of bars - await fdZKey.writeULE32(nPublic); // Total number of public vars (not including ONE) - await fdZKey.writeULE32(domainSize); // domainSize - - let bAlpha1; - bAlpha1 = await fdPTau.read(sG1, sectionsPTau[4][0].p); - await fdZKey.write(bAlpha1); - bAlpha1 = await curve.G1.batchLEMtoU(bAlpha1); - csHasher.update(bAlpha1); - - let bBeta1; - bBeta1 = await fdPTau.read(sG1, sectionsPTau[5][0].p); - await fdZKey.write(bBeta1); - bBeta1 = await curve.G1.batchLEMtoU(bBeta1); - csHasher.update(bBeta1); - - let bBeta2; - bBeta2 = await fdPTau.read(sG2, sectionsPTau[6][0].p); - await fdZKey.write(bBeta2); - bBeta2 = await curve.G2.batchLEMtoU(bBeta2); - csHasher.update(bBeta2); - - const bg1 = new Uint8Array(sG1); - curve.G1.toRprLEM(bg1, 0, curve.G1.g); - const bg2 = new Uint8Array(sG2); - curve.G2.toRprLEM(bg2, 0, curve.G2.g); - const bg1U = new Uint8Array(sG1); - curve.G1.toRprUncompressed(bg1U, 0, curve.G1.g); - const bg2U = new Uint8Array(sG2); - curve.G2.toRprUncompressed(bg2U, 0, curve.G2.g); - - await fdZKey.write(bg2); // gamma2 - await fdZKey.write(bg1); // delta1 - await fdZKey.write(bg2); // delta2 - csHasher.update(bg2U); // gamma2 - csHasher.update(bg1U); // delta1 - csHasher.update(bg2U); // delta2 - await binFileUtils.endWriteSection(fdZKey); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("Reading r1cs"); - let sR1cs = await binFileUtils.readSection(fdR1cs, sectionsR1cs, 2); - await fdR1cs.close(); - - let A = new BigArray(r1cs.nVars); - let B1 = new BigArray(r1cs.nVars); - let B2 = new BigArray(r1cs.nVars); - let C = new BigArray(r1cs.nVars- nPublic -1); - let IC = new Array(nPublic+1); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("Reading tauG1"); - let sTauG1 = await binFileUtils.readSection(fdPTau, sectionsPTau, 12, (domainSize -1)*sG1, domainSize*sG1); - if (logger) logger.info("Reading tauG2"); - let sTauG2 = await binFileUtils.readSection(fdPTau, sectionsPTau, 13, (domainSize -1)*sG2, domainSize*sG2); - if (logger) logger.info("Reading alphatauG1"); - let sAlphaTauG1 = await binFileUtils.readSection(fdPTau, sectionsPTau, 14, (domainSize -1)*sG1, domainSize*sG1); - if (logger) logger.info("Reading betatauG1"); - let sBetaTauG1 = await binFileUtils.readSection(fdPTau, sectionsPTau, 15, (domainSize -1)*sG1, domainSize*sG1); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("processConstraints"); - await processConstraints(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints"); - await composeAndWritePoints(3, "G1", IC, "IC"); - - IC = null; - // const gc = runInNewContext("gc"); // nocommit - // gc(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("writeHs"); - await writeHs(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("hashHPoints"); - await hashHPoints(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints 8 G1 C"); - await composeAndWritePoints(8, "G1", C, "C"); - - C = null; - // gc(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints 5 G1 A"); - await composeAndWritePoints(5, "G1", A, "A"); - - A = null; - // gc(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints 6 G1 B1"); - await composeAndWritePoints(6, "G1", B1, "B1"); - - B1 = null; - // gc(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints 7 G2 B2"); - await composeAndWritePoints(7, "G2", B2, "B2"); - - B2 = null; - // gc(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("Contributions section"); - const csHash = csHasher.digest(); - // Contributions section - await binFileUtils.startWriteSection(fdZKey, 10); - await fdZKey.write(csHash); - await fdZKey.writeULE32(0); - await binFileUtils.endWriteSection(fdZKey); - - if (logger) logger.info(formatHash(csHash, "Circuit hash: ")); - - - await fdZKey.close(); - await fdPTau.close(); - - return csHash; - - async function writeHs() { - await binFileUtils.startWriteSection(fdZKey, 9); - const buffOut = new ffjavascript.BigBuffer(domainSize*sG1); - if (cirPower < curve.Fr.s) { - let sTauG1 = await binFileUtils.readSection(fdPTau, sectionsPTau, 12, (domainSize*2-1)*sG1, domainSize*2*sG1); - for (let i=0; i< domainSize; i++) { - if ((logger)&&(i%10000 == 0)) logger.debug(`splitting buffer: ${i}/${domainSize}`); - const buff = sTauG1.slice( (i*2+1)*sG1, (i*2+1)*sG1 + sG1 ); - buffOut.set(buff, i*sG1); - } - } else if (cirPower == curve.Fr.s) { - const o = sectionsPTau[12][0].p + ((2 ** (cirPower+1)) -1)*sG1; - await fdPTau.readToBuffer(buffOut, 0, domainSize*sG1, o + domainSize*sG1); - } else { - if (logger) logger.error("Circuit too big"); - throw new Error("Circuit too big for this curve"); - } - await fdZKey.write(buffOut); - await binFileUtils.endWriteSection(fdZKey); - } - - async function processConstraints() { - const buffCoeff = new Uint8Array(12 + curve.Fr.n8); - const buffCoeffV = new DataView(buffCoeff.buffer); - const bOne = new Uint8Array(curve.Fr.n8); - curve.Fr.toRprLE(bOne, 0, curve.Fr.e(1)); - - let r1csPos = 0; - - function r1cs_readULE32() { - const buff = sR1cs.slice(r1csPos, r1csPos+4); - r1csPos += 4; - const buffV = new DataView(buff.buffer); - return buffV.getUint32(0, true); - } - - const coefs = new BigArray(); - for (let c=0; c=0) { - n = curve.Fr.fromRprLE(sR1cs.slice(c[3], c[3] + curve.Fr.n8), 0); - } else { - n = curve.Fr.fromRprLE(bOne, 0); - } - const nR2 = curve.Fr.mul(n, R2r); - curve.Fr.toRprLE(buffCoeff, 12, nR2); - buffSection.set(buffCoeff, coefsPos); - coefsPos += buffCoeff.length; - } - - } - - async function composeAndWritePoints(idSection, groupName, arr, sectionName) { - const CHUNK_SIZE= 1<<15; - const G = curve[groupName]; - - hashU32(arr.length); - await binFileUtils.startWriteSection(fdZKey, idSection); - - let opPromises = []; - - let i=0; - while (i { - if (logger) logger.debug(`Writing points end ${sectionName}: ${_i}/${arr.length}`); - return r; - })); - i += n; - t++; - } - - const result = await Promise.all(opPromises); - - for (let k=0; k 2<<14) { - bBases = new ffjavascript.BigBuffer(acc*sGin); - bScalars = new ffjavascript.BigBuffer(acc*curve.Fr.n8); - } else { - bBases = new Uint8Array(acc*sGin); - bScalars = new Uint8Array(acc*curve.Fr.n8); - } - let pB =0; - let pS =0; - - const sBuffs = [ - sTauG1, - sTauG2, - sAlphaTauG1, - sBetaTauG1 - ]; - - const bOne = new Uint8Array(curve.Fr.n8); - curve.Fr.toRprLE(bOne, 0, curve.Fr.e(1)); - - let offset = 0; - for (let i=0; i=0) { - bScalars.set( - sR1cs.slice( - arr[i][j][2], - arr[i][j][2] + curve.Fr.n8 - ), - offset*curve.Fr.n8 - ); - } else { - bScalars.set(bOne, offset*curve.Fr.n8); - } - offset ++; - } - } - - if (arr.length>1) { - const task = []; - task.push({cmd: "ALLOCSET", var: 0, buff: bBases}); - task.push({cmd: "ALLOCSET", var: 1, buff: bScalars}); - task.push({cmd: "ALLOC", var: 2, len: arr.length*sGmid}); - pB = 0; - pS = 0; - let pD =0; - for (let i=0; i power) { + if (logger) logger.error(`circuit too big for this power of tau ceremony. ${r1cs.nConstraints}*2 > 2**${power}`); + return -1; + } + if (!sectionsPTau[12]) { + if (logger) logger.error("Powers of tau is not prepared."); + return -1; + } + const nPublic = r1cs.nOutputs + r1cs.nPubInputs; + const domainSize = 2 ** cirPower; + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 1); + await fdZKey.writeULE32(1); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 2); + const primeQ = curve.q; + const n8q = (Math.floor((ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) + 1) * 8; + const primeR = curve.r; + const n8r = (Math.floor((ffjavascript.Scalar.bitLength(primeR) - 1) / 64) + 1) * 8; + const Rr = ffjavascript.Scalar.mod(ffjavascript.Scalar.shl(1, n8r * 8), primeR); + const R2r = curve.Fr.e(ffjavascript.Scalar.mod(ffjavascript.Scalar.mul(Rr, Rr), primeR)); + await fdZKey.writeULE32(n8q); + await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeQ, n8q); + await fdZKey.writeULE32(n8r); + await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeR, n8r); + await fdZKey.writeULE32(r1cs.nVars); + await fdZKey.writeULE32(nPublic); + await fdZKey.writeULE32(domainSize); + let bAlpha1; + bAlpha1 = await fdPTau.read(sG1, sectionsPTau[4][0].p); + await fdZKey.write(bAlpha1); + bAlpha1 = await curve.G1.batchLEMtoU(bAlpha1); + csHasher.update(bAlpha1); + let bBeta1; + bBeta1 = await fdPTau.read(sG1, sectionsPTau[5][0].p); + await fdZKey.write(bBeta1); + bBeta1 = await curve.G1.batchLEMtoU(bBeta1); + csHasher.update(bBeta1); + let bBeta2; + bBeta2 = await fdPTau.read(sG2, sectionsPTau[6][0].p); + await fdZKey.write(bBeta2); + bBeta2 = await curve.G2.batchLEMtoU(bBeta2); + csHasher.update(bBeta2); + const bg1 = new Uint8Array(sG1); + curve.G1.toRprLEM(bg1, 0, curve.G1.g); + const bg2 = new Uint8Array(sG2); + curve.G2.toRprLEM(bg2, 0, curve.G2.g); + const bg1U = new Uint8Array(sG1); + curve.G1.toRprUncompressed(bg1U, 0, curve.G1.g); + const bg2U = new Uint8Array(sG2); + curve.G2.toRprUncompressed(bg2U, 0, curve.G2.g); + await fdZKey.write(bg2); + await fdZKey.write(bg1); + await fdZKey.write(bg2); + csHasher.update(bg2U); + csHasher.update(bg1U); + csHasher.update(bg2U); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + if (logger) logger.info(memUsage()); + if (logger) logger.info("Reading r1cs"); + let sR1cs = await (0, _iden3_binfileutils.readSection)(fdR1cs, sectionsR1cs, 2); + await fdR1cs.close(); + let A = new BigArray(r1cs.nVars); + let B1 = new BigArray(r1cs.nVars); + let B2 = new BigArray(r1cs.nVars); + let C = new BigArray(r1cs.nVars - nPublic - 1); + let IC = new Array(nPublic + 1); + if (logger) logger.info(memUsage()); + if (logger) logger.info("Reading tauG1"); + let sTauG1 = await (0, _iden3_binfileutils.readSection)(fdPTau, sectionsPTau, 12, (domainSize - 1) * sG1, domainSize * sG1); + if (logger) logger.info("Reading tauG2"); + let sTauG2 = await (0, _iden3_binfileutils.readSection)(fdPTau, sectionsPTau, 13, (domainSize - 1) * sG2, domainSize * sG2); + if (logger) logger.info("Reading alphatauG1"); + let sAlphaTauG1 = await (0, _iden3_binfileutils.readSection)(fdPTau, sectionsPTau, 14, (domainSize - 1) * sG1, domainSize * sG1); + if (logger) logger.info("Reading betatauG1"); + let sBetaTauG1 = await (0, _iden3_binfileutils.readSection)(fdPTau, sectionsPTau, 15, (domainSize - 1) * sG1, domainSize * sG1); + if (logger) logger.info(memUsage()); + if (logger) logger.info("processConstraints"); + await processConstraints(); + if (logger) logger.info(memUsage()); + if (logger) logger.info("composeAndWritePoints"); + await composeAndWritePoints(3, "G1", IC, "IC"); + IC = null; + if (logger) logger.info(memUsage()); + if (logger) logger.info("writeHs"); + await writeHs(); + if (logger) logger.info(memUsage()); + if (logger) logger.info("hashHPoints"); + await hashHPoints(); + if (logger) logger.info(memUsage()); + if (logger) logger.info("composeAndWritePoints 8 G1 C"); + await composeAndWritePoints(8, "G1", C, "C"); + C = null; + if (logger) logger.info(memUsage()); + if (logger) logger.info("composeAndWritePoints 5 G1 A"); + await composeAndWritePoints(5, "G1", A, "A"); + A = null; + if (logger) logger.info(memUsage()); + if (logger) logger.info("composeAndWritePoints 6 G1 B1"); + await composeAndWritePoints(6, "G1", B1, "B1"); + B1 = null; + if (logger) logger.info(memUsage()); + if (logger) logger.info("composeAndWritePoints 7 G2 B2"); + await composeAndWritePoints(7, "G2", B2, "B2"); + B2 = null; + if (logger) logger.info(memUsage()); + if (logger) logger.info("Contributions section"); + const csHash = csHasher.digest(); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 10); + await fdZKey.write(csHash); + await fdZKey.writeULE32(0); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + if (logger) logger.info(formatHash(csHash, "Circuit hash: ")); + await fdZKey.close(); + await fdPTau.close(); + return csHash; + async function writeHs() { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 9); + const buffOut = new ffjavascript.BigBuffer(domainSize * sG1); + if (cirPower < curve.Fr.s) { + let sTauG1 = await (0, _iden3_binfileutils.readSection)(fdPTau, sectionsPTau, 12, (domainSize * 2 - 1) * sG1, domainSize * 2 * sG1); + for (let i = 0; i < domainSize; i++) { + if (logger && i % 1e4 == 0) logger.debug(`splitting buffer: ${i}/${domainSize}`); + const buff = sTauG1.slice((i * 2 + 1) * sG1, (i * 2 + 1) * sG1 + sG1); + buffOut.set(buff, i * sG1); + } + } else if (cirPower == curve.Fr.s) { + const o = sectionsPTau[12][0].p + (2 ** (cirPower + 1) - 1) * sG1; + await fdPTau.readToBuffer(buffOut, 0, domainSize * sG1, o + domainSize * sG1); + } else { + if (logger) logger.error("Circuit too big"); + throw new Error("Circuit too big for this curve"); + } + await fdZKey.write(buffOut); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function processConstraints() { + const buffCoeff = new Uint8Array(12 + curve.Fr.n8); + const buffCoeffV = new DataView(buffCoeff.buffer); + const bOne = new Uint8Array(curve.Fr.n8); + curve.Fr.toRprLE(bOne, 0, curve.Fr.e(1)); + let r1csPos = 0; + function r1cs_readULE32() { + const buff = sR1cs.slice(r1csPos, r1csPos + 4); + r1csPos += 4; + return new DataView(buff.buffer).getUint32(0, true); + } + const coefs = new BigArray(); + for (let c = 0; c < r1cs.nConstraints; c++) { + if (logger && c % 1e4 == 0) logger.debug(`processing constraints: ${c}/${r1cs.nConstraints}`); + const nA = r1cs_readULE32(); + for (let i = 0; i < nA; i++) { + const s = r1cs_readULE32(); + const coefp = r1csPos; + r1csPos += curve.Fr.n8; + const l1t = TAU_G1; + const l1 = sG1 * c; + const l2t = BETATAU_G1; + const l2 = sG1 * c; + if (typeof A[s] === "undefined") A[s] = []; + A[s].push([ + l1t, + l1, + coefp + ]); + if (s <= nPublic) { + if (typeof IC[s] === "undefined") IC[s] = []; + IC[s].push([ + l2t, + l2, + coefp + ]); + } else { + if (typeof C[s - nPublic - 1] === "undefined") C[s - nPublic - 1] = []; + C[s - nPublic - 1].push([ + l2t, + l2, + coefp + ]); + } + coefs.push([ + 0, + c, + s, + coefp + ]); + } + const nB = r1cs_readULE32(); + for (let i = 0; i < nB; i++) { + const s = r1cs_readULE32(); + const coefp = r1csPos; + r1csPos += curve.Fr.n8; + const l1t = TAU_G1; + const l1 = sG1 * c; + const l2t = TAU_G2; + const l2 = sG2 * c; + const l3t = ALPHATAU_G1; + const l3 = sG1 * c; + if (typeof B1[s] === "undefined") B1[s] = []; + B1[s].push([ + l1t, + l1, + coefp + ]); + if (typeof B2[s] === "undefined") B2[s] = []; + B2[s].push([ + l2t, + l2, + coefp + ]); + if (s <= nPublic) { + if (typeof IC[s] === "undefined") IC[s] = []; + IC[s].push([ + l3t, + l3, + coefp + ]); + } else { + if (typeof C[s - nPublic - 1] === "undefined") C[s - nPublic - 1] = []; + C[s - nPublic - 1].push([ + l3t, + l3, + coefp + ]); + } + coefs.push([ + 1, + c, + s, + coefp + ]); + } + const nC = r1cs_readULE32(); + for (let i = 0; i < nC; i++) { + const s = r1cs_readULE32(); + const coefp = r1csPos; + r1csPos += curve.Fr.n8; + const l1t = TAU_G1; + const l1 = sG1 * c; + if (s <= nPublic) { + if (typeof IC[s] === "undefined") IC[s] = []; + IC[s].push([ + l1t, + l1, + coefp + ]); + } else { + if (typeof C[s - nPublic - 1] === "undefined") C[s - nPublic - 1] = []; + C[s - nPublic - 1].push([ + l1t, + l1, + coefp + ]); + } + } + } + for (let s = 0; s <= nPublic; s++) { + const l1t = TAU_G1; + const l1 = sG1 * (r1cs.nConstraints + s); + const l2t = BETATAU_G1; + const l2 = sG1 * (r1cs.nConstraints + s); + if (typeof A[s] === "undefined") A[s] = []; + A[s].push([ + l1t, + l1, + -1 + ]); + if (typeof IC[s] === "undefined") IC[s] = []; + IC[s].push([ + l2t, + l2, + -1 + ]); + coefs.push([ + 0, + r1cs.nConstraints + s, + s, + -1 + ]); + } + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 4); + const buffSection = new ffjavascript.BigBuffer(coefs.length * (12 + curve.Fr.n8) + 4); + const buff4 = new Uint8Array(4); + new DataView(buff4.buffer).setUint32(0, coefs.length, true); + buffSection.set(buff4); + let coefsPos = 4; + for (let i = 0; i < coefs.length; i++) { + if (logger && i % 1e5 == 0) logger.debug(`writing coeffs: ${i}/${coefs.length}`); + writeCoef(coefs[i]); + } + await fdZKey.write(buffSection); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + function writeCoef(c) { + buffCoeffV.setUint32(0, c[0], true); + buffCoeffV.setUint32(4, c[1], true); + buffCoeffV.setUint32(8, c[2], true); + let n; + if (c[3] >= 0) n = curve.Fr.fromRprLE(sR1cs.slice(c[3], c[3] + curve.Fr.n8), 0); + else n = curve.Fr.fromRprLE(bOne, 0); + const nR2 = curve.Fr.mul(n, R2r); + curve.Fr.toRprLE(buffCoeff, 12, nR2); + buffSection.set(buffCoeff, coefsPos); + coefsPos += buffCoeff.length; + } + } + async function composeAndWritePoints(idSection, groupName, arr, sectionName) { + const CHUNK_SIZE = 32768; + const G = curve[groupName]; + hashU32(arr.length); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, idSection); + let opPromises = []; + let i = 0; + while (i < arr.length) { + let t = 0; + while (i < arr.length && t < curve.tm.concurrency) { + if (logger) logger.debug(`Writing points start ${sectionName}: ${i}/${arr.length}`); + let n = 1; + let nP = arr[i] ? arr[i].length : 0; + while (i + n < arr.length && nP + (arr[i + n] ? arr[i + n].length : 0) < CHUNK_SIZE && n < CHUNK_SIZE) { + nP += arr[i + n] ? arr[i + n].length : 0; + n++; + } + if (logger) logger.info("before slice:"); + if (logger) logger.info(memUsage()); + const subArr = arr.slice(i, i + n); + if (logger) logger.info("after slice:"); + if (logger) logger.info(memUsage()); + const _i = i; + opPromises.push(composeAndWritePointsThread(groupName, subArr, logger, sectionName).then((r) => { + if (logger) logger.debug(`Writing points end ${sectionName}: ${_i}/${arr.length}`); + return r; + })); + i += n; + t++; + } + const result = await Promise.all(opPromises); + for (let k = 0; k < result.length; k++) { + await fdZKey.write(result[k][0]); + const buff = await G.batchLEMtoU(result[k][0]); + csHasher.update(buff); + } + opPromises = []; + } + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function composeAndWritePointsThread(groupName, arr, logger, sectionName) { + const G = curve[groupName]; + const sGin = G.F.n8 * 2; + const sGmid = G.F.n8 * 3; + const sGout = G.F.n8 * 2; + let fnExp, fnMultiExp, fnBatchToAffine, fnZero; + if (groupName == "G1") { + fnExp = "g1m_timesScalarAffine"; + fnMultiExp = "g1m_multiexpAffine"; + fnBatchToAffine = "g1m_batchToAffine"; + fnZero = "g1m_zero"; + } else if (groupName == "G2") { + fnExp = "g2m_timesScalarAffine"; + fnMultiExp = "g2m_multiexpAffine"; + fnBatchToAffine = "g2m_batchToAffine"; + fnZero = "g2m_zero"; + } else throw new Error("Invalid group"); + let acc = 0; + for (let i = 0; i < arr.length; i++) acc += arr[i] ? arr[i].length : 0; + let bBases, bScalars; + if (acc > 32768) { + bBases = new ffjavascript.BigBuffer(acc * sGin); + bScalars = new ffjavascript.BigBuffer(acc * curve.Fr.n8); + } else { + bBases = new Uint8Array(acc * sGin); + bScalars = new Uint8Array(acc * curve.Fr.n8); + } + let pB; + let pS; + const sBuffs = [ + sTauG1, + sTauG2, + sAlphaTauG1, + sBetaTauG1 + ]; + const bOne = new Uint8Array(curve.Fr.n8); + curve.Fr.toRprLE(bOne, 0, curve.Fr.e(1)); + let offset = 0; + for (let i = 0; i < arr.length; i++) { + if (!arr[i]) continue; + for (let j = 0; j < arr[i].length; j++) { + if (logger && j && j % 1e4 == 0) logger.debug(`Configuring big array ${sectionName}: ${j}/${arr[i].length}`); + bBases.set(sBuffs[arr[i][j][0]].slice(arr[i][j][1], arr[i][j][1] + sGin), offset * sGin); + if (arr[i][j][2] >= 0) bScalars.set(sR1cs.slice(arr[i][j][2], arr[i][j][2] + curve.Fr.n8), offset * curve.Fr.n8); + else bScalars.set(bOne, offset * curve.Fr.n8); + offset++; + } + } + if (arr.length > 1) { + const task = []; + task.push({ + cmd: "ALLOCSET", + var: 0, + buff: bBases + }); + task.push({ + cmd: "ALLOCSET", + var: 1, + buff: bScalars + }); + task.push({ + cmd: "ALLOC", + var: 2, + len: arr.length * sGmid + }); + pB = 0; + pS = 0; + let pD = 0; + for (let i = 0; i < arr.length; i++) { + if (!arr[i]) { + task.push({ + cmd: "CALL", + fnName: fnZero, + params: [{ + var: 2, + offset: pD + }] + }); + pD += sGmid; + continue; + } + if (arr[i].length == 1) task.push({ + cmd: "CALL", + fnName: fnExp, + params: [ + { + var: 0, + offset: pB + }, + { + var: 1, + offset: pS + }, + { val: curve.Fr.n8 }, + { + var: 2, + offset: pD + } + ] + }); + else task.push({ + cmd: "CALL", + fnName: fnMultiExp, + params: [ + { + var: 0, + offset: pB + }, + { + var: 1, + offset: pS + }, + { val: curve.Fr.n8 }, + { val: arr[i].length }, + { + var: 2, + offset: pD + } + ] + }); + pB += sGin * arr[i].length; + pS += curve.Fr.n8 * arr[i].length; + pD += sGmid; + } + task.push({ + cmd: "CALL", + fnName: fnBatchToAffine, + params: [ + { var: 2 }, + { val: arr.length }, + { var: 2 } + ] + }); + task.push({ + cmd: "GET", + out: 0, + var: 2, + len: arr.length * sGout + }); + return await curve.tm.queueAction(task); + } else { + let res = await G.multiExpAffine(bBases, bScalars, logger, sectionName); + res = [G.toAffine(res)]; + return res; + } + } + async function hashHPoints() { + const CHUNK_SIZE = 16384; + hashU32(domainSize - 1); + for (let i = 0; i < domainSize - 1; i += CHUNK_SIZE) { + if (logger) logger.debug(`HashingHPoints: ${i}/${domainSize}`); + const n = Math.min(domainSize - 1, CHUNK_SIZE); + await hashHPointsChunk(i, n); + } + } + async function hashHPointsChunk(offset, nPoints) { + const buff1 = await fdPTau.read(nPoints * sG1, sectionsPTau[2][0].p + (offset + domainSize) * sG1); + const buff2 = await fdPTau.read(nPoints * sG1, sectionsPTau[2][0].p + offset * sG1); + const concurrency = curve.tm.concurrency; + const nPointsPerThread = Math.floor(nPoints / concurrency); + const opPromises = []; + for (let i = 0; i < concurrency; i++) { + let n; + if (i < concurrency - 1) n = nPointsPerThread; + else n = nPoints - i * nPointsPerThread; + if (n == 0) continue; + const subBuff1 = buff1.slice(i * nPointsPerThread * sG1, (i * nPointsPerThread + n) * sG1); + const subBuff2 = buff2.slice(i * nPointsPerThread * sG1, (i * nPointsPerThread + n) * sG1); + opPromises.push(hashHPointsThread(subBuff1, subBuff2)); + } + const result = await Promise.all(opPromises); + for (let i = 0; i < result.length; i++) csHasher.update(result[i][0]); + } + async function hashHPointsThread(buff1, buff2) { + const nPoints = buff1.byteLength / sG1; + const sGmid = curve.G1.F.n8 * 3; + const task = []; + task.push({ + cmd: "ALLOCSET", + var: 0, + buff: buff1 + }); + task.push({ + cmd: "ALLOCSET", + var: 1, + buff: buff2 + }); + task.push({ + cmd: "ALLOC", + var: 2, + len: nPoints * sGmid + }); + for (let i = 0; i < nPoints; i++) task.push({ + cmd: "CALL", + fnName: "g1m_subAffine", + params: [ + { + var: 0, + offset: i * sG1 + }, + { + var: 1, + offset: i * sG1 + }, + { + var: 2, + offset: i * sGmid + } + ] + }); + task.push({ + cmd: "CALL", + fnName: "g1m_batchToAffine", + params: [ + { var: 2 }, + { val: nPoints }, + { var: 2 } + ] + }); + task.push({ + cmd: "CALL", + fnName: "g1m_batchLEMtoU", + params: [ + { var: 2 }, + { val: nPoints }, + { var: 2 } + ] + }); + task.push({ + cmd: "GET", + out: 0, + var: 2, + len: nPoints * sG1 + }); + return await curve.tm.queueAction(task); + } + function hashU32(n) { + const buff = new Uint8Array(4); + new DataView(buff.buffer, buff.byteOffset, buff.byteLength).setUint32(0, n, false); + csHasher.update(buff); + } + function memUsage() { + let m = process.memoryUsage(); + for (const i in m) m[i] = Math.round(m[i] / (1024 * 1024)); + return m; + } +} +//#endregion +//#region src/zkey_export_bellman.js async function phase2exportMPCParams(zkeyName, mpcparamsName, logger) { - - const {fd: fdZKey, sections: sectionsZKey} = await binFileUtils__namespace.readBinFile(zkeyName, "zkey", 2); - const zkey = await readHeader$1(fdZKey, sectionsZKey); - if (zkey.protocol != "groth16") { - throw new Error("zkey file is not groth16"); - } - - const curve = await getCurveFromQ(zkey.q); - const sG1 = curve.G1.F.n8*2; - const sG2 = curve.G2.F.n8*2; - - const mpcParams = await readMPCParams(fdZKey, curve, sectionsZKey); - - const fdMPCParams = await fastFile__namespace.createOverride(mpcparamsName); - - ///////////////////// - // Verification Key Section - ///////////////////// - await writeG1(zkey.vk_alpha_1); - await writeG1(zkey.vk_beta_1); - await writeG2(zkey.vk_beta_2); - await writeG2(zkey.vk_gamma_2); - await writeG1(zkey.vk_delta_1); - await writeG2(zkey.vk_delta_2); - - // IC - let buffBasesIC; - buffBasesIC = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 3); - buffBasesIC = await curve.G1.batchLEMtoU(buffBasesIC); - - await writePointArray("G1", buffBasesIC); - - ///////////////////// - // h Section - ///////////////////// - const buffBasesH_Lodd = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 9); - - let buffBasesH_Tau; - buffBasesH_Tau = await curve.G1.fft(buffBasesH_Lodd, "affine", "jacobian", logger); - buffBasesH_Tau = await curve.G1.batchApplyKey(buffBasesH_Tau, curve.Fr.neg(curve.Fr.e(2)), curve.Fr.w[zkey.power+1], "jacobian", "affine", logger); - - // Remove last element. (The degree of H will be always m-2) - buffBasesH_Tau = buffBasesH_Tau.slice(0, buffBasesH_Tau.byteLength - sG1); - buffBasesH_Tau = await curve.G1.batchLEMtoU(buffBasesH_Tau); - await writePointArray("G1", buffBasesH_Tau); - - ///////////////////// - // L section - ///////////////////// - let buffBasesC; - buffBasesC = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 8); - buffBasesC = await curve.G1.batchLEMtoU(buffBasesC); - await writePointArray("G1", buffBasesC); - - ///////////////////// - // A Section (C section) - ///////////////////// - let buffBasesA; - buffBasesA = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 5); - buffBasesA = await curve.G1.batchLEMtoU(buffBasesA); - await writePointArray("G1", buffBasesA); - - ///////////////////// - // B1 Section - ///////////////////// - let buffBasesB1; - buffBasesB1 = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 6); - buffBasesB1 = await curve.G1.batchLEMtoU(buffBasesB1); - await writePointArray("G1", buffBasesB1); - - ///////////////////// - // B2 Section - ///////////////////// - let buffBasesB2; - buffBasesB2 = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 7); - buffBasesB2 = await curve.G2.batchLEMtoU(buffBasesB2); - await writePointArray("G2", buffBasesB2); - - await fdMPCParams.write(mpcParams.csHash); - await writeU32(mpcParams.contributions.length); - - for (let i=0; i. -*/ - + const { fd: fdZKey, sections: sectionsZKey } = await _iden3_binfileutils.readBinFile(zkeyName, "zkey", 2); + const zkey = await readHeader$1(fdZKey, sectionsZKey); + if (zkey.protocol != "groth16") throw new Error("zkey file is not groth16"); + const curve = await getCurveFromQ(zkey.q); + const sG1 = curve.G1.F.n8 * 2; + const sG2 = curve.G2.F.n8 * 2; + const mpcParams = await readMPCParams(fdZKey, curve, sectionsZKey); + const fdMPCParams = await fastfile.createOverride(mpcparamsName); + await writeG1(zkey.vk_alpha_1); + await writeG1(zkey.vk_beta_1); + await writeG2(zkey.vk_beta_2); + await writeG2(zkey.vk_gamma_2); + await writeG1(zkey.vk_delta_1); + await writeG2(zkey.vk_delta_2); + let buffBasesIC; + buffBasesIC = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 3); + buffBasesIC = await curve.G1.batchLEMtoU(buffBasesIC); + await writePointArray("G1", buffBasesIC); + const buffBasesH_Lodd = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 9); + let buffBasesH_Tau; + buffBasesH_Tau = await curve.G1.fft(buffBasesH_Lodd, "affine", "jacobian", logger); + buffBasesH_Tau = await curve.G1.batchApplyKey(buffBasesH_Tau, curve.Fr.neg(curve.Fr.e(2)), curve.Fr.w[zkey.power + 1], "jacobian", "affine", logger); + buffBasesH_Tau = buffBasesH_Tau.slice(0, buffBasesH_Tau.byteLength - sG1); + buffBasesH_Tau = await curve.G1.batchLEMtoU(buffBasesH_Tau); + await writePointArray("G1", buffBasesH_Tau); + let buffBasesC; + buffBasesC = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 8); + buffBasesC = await curve.G1.batchLEMtoU(buffBasesC); + await writePointArray("G1", buffBasesC); + let buffBasesA; + buffBasesA = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 5); + buffBasesA = await curve.G1.batchLEMtoU(buffBasesA); + await writePointArray("G1", buffBasesA); + let buffBasesB1; + buffBasesB1 = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 6); + buffBasesB1 = await curve.G1.batchLEMtoU(buffBasesB1); + await writePointArray("G1", buffBasesB1); + let buffBasesB2; + buffBasesB2 = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 7); + buffBasesB2 = await curve.G2.batchLEMtoU(buffBasesB2); + await writePointArray("G2", buffBasesB2); + await fdMPCParams.write(mpcParams.csHash); + await writeU32(mpcParams.contributions.length); + for (let i = 0; i < mpcParams.contributions.length; i++) { + const c = mpcParams.contributions[i]; + await writeG1(c.deltaAfter); + await writeG1(c.delta.g1_s); + await writeG1(c.delta.g1_sx); + await writeG2(c.delta.g2_spx); + await fdMPCParams.write(c.transcript); + } + await fdZKey.close(); + await fdMPCParams.close(); + async function writeG1(P) { + const buff = new Uint8Array(sG1); + curve.G1.toRprUncompressed(buff, 0, P); + await fdMPCParams.write(buff); + } + async function writeG2(P) { + const buff = new Uint8Array(sG2); + curve.G2.toRprUncompressed(buff, 0, P); + await fdMPCParams.write(buff); + } + async function writePointArray(groupName, buff) { + let sG; + if (groupName == "G1") sG = sG1; + else sG = sG2; + const buffSize = new Uint8Array(4); + new DataView(buffSize.buffer, buffSize.byteOffset, buffSize.byteLength).setUint32(0, buff.byteLength / sG, false); + await fdMPCParams.write(buffSize); + await fdMPCParams.write(buff); + } + async function writeU32(n) { + const buffSize = new Uint8Array(4); + new DataView(buffSize.buffer, buffSize.byteOffset, buffSize.byteLength).setUint32(0, n, false); + await fdMPCParams.write(buffSize); + } +} +//#endregion +//#region src/zkey_import_bellman.js async function phase2importMPCParams(zkeyNameOld, mpcparamsName, zkeyNameNew, name, logger) { - - const {fd: fdZKeyOld, sections: sectionsZKeyOld} = await binFileUtils__namespace.readBinFile(zkeyNameOld, "zkey", 2); - const zkeyHeader = await readHeader$1(fdZKeyOld, sectionsZKeyOld, false); - if (zkeyHeader.protocol != "groth16") { - throw new Error("zkey file is not groth16"); - } - - const curve = await getCurveFromQ(zkeyHeader.q); - const sG1 = curve.G1.F.n8*2; - const sG2 = curve.G2.F.n8*2; - - const oldMPCParams = await readMPCParams(fdZKeyOld, curve, sectionsZKeyOld); - const newMPCParams = {}; - - const fdMPCParams = await fastFile__namespace.readExisting(mpcparamsName); - - fdMPCParams.pos = - sG1*3 + sG2*3 + // vKey - 8 + sG1*zkeyHeader.nVars + // IC + C - 4 + sG1*(zkeyHeader.domainSize-1) + // H - 4 + sG1*zkeyHeader.nVars + // A - 4 + sG1*zkeyHeader.nVars + // B1 - 4 + sG2*zkeyHeader.nVars; // B2 - - // csHash - newMPCParams.csHash = await fdMPCParams.read(64); - - const nContributions = await fdMPCParams.readUBE32(); - newMPCParams.contributions = []; - for (let i=0; i newMPCParams.contributions.length) { - if (logger) logger.error("The impoerted file does not include new contributions"); - return false; - } - - for (let i=0; i. -*/ -const sameRatio = sameRatio$2; - - - + const { fd: fdZKeyOld, sections: sectionsZKeyOld } = await _iden3_binfileutils.readBinFile(zkeyNameOld, "zkey", 2); + const zkeyHeader = await readHeader$1(fdZKeyOld, sectionsZKeyOld, false); + if (zkeyHeader.protocol != "groth16") throw new Error("zkey file is not groth16"); + const curve = await getCurveFromQ(zkeyHeader.q); + const sG1 = curve.G1.F.n8 * 2; + const sG2 = curve.G2.F.n8 * 2; + const oldMPCParams = await readMPCParams(fdZKeyOld, curve, sectionsZKeyOld); + const newMPCParams = {}; + const fdMPCParams = await fastfile.readExisting(mpcparamsName); + fdMPCParams.pos = sG1 * 3 + sG2 * 3 + 8 + sG1 * zkeyHeader.nVars + 4 + sG1 * (zkeyHeader.domainSize - 1) + 4 + sG1 * zkeyHeader.nVars + 4 + sG1 * zkeyHeader.nVars + 4 + sG2 * zkeyHeader.nVars; + newMPCParams.csHash = await fdMPCParams.read(64); + const nContributions = await fdMPCParams.readUBE32(); + newMPCParams.contributions = []; + for (let i = 0; i < nContributions; i++) { + const c = { delta: {} }; + c.deltaAfter = await readG1(fdMPCParams); + c.delta.g1_s = await readG1(fdMPCParams); + c.delta.g1_sx = await readG1(fdMPCParams); + c.delta.g2_spx = await readG2(fdMPCParams); + c.transcript = await fdMPCParams.read(64); + if (i < oldMPCParams.contributions.length) { + c.type = oldMPCParams.contributions[i].type; + if (c.type == 1) { + c.beaconHash = oldMPCParams.contributions[i].beaconHash; + c.numIterationsExp = oldMPCParams.contributions[i].numIterationsExp; + } + if (oldMPCParams.contributions[i].name) c.name = oldMPCParams.contributions[i].name; + } + newMPCParams.contributions.push(c); + } + if (!hashIsEqual(newMPCParams.csHash, oldMPCParams.csHash)) { + if (logger) logger.error("Hash of the original circuit does not match with the MPC one"); + return false; + } + if (oldMPCParams.contributions.length > newMPCParams.contributions.length) { + if (logger) logger.error("The impoerted file does not include new contributions"); + return false; + } + for (let i = 0; i < oldMPCParams.contributions.length; i++) if (!contributionIsEqual(oldMPCParams.contributions[i], newMPCParams.contributions[i])) { + if (logger) logger.error(`Previous contribution ${i} does not match`); + return false; + } + if (name) for (let i = oldMPCParams.contributions.length; i < newMPCParams.contributions.length; i++) newMPCParams.contributions[i].name = name; + const fdZKeyNew = await _iden3_binfileutils.createBinFile(zkeyNameNew, "zkey", 1, 10); + fdMPCParams.pos = 0; + fdMPCParams.pos += sG1; + fdMPCParams.pos += sG1; + fdMPCParams.pos += sG2; + fdMPCParams.pos += sG2; + zkeyHeader.vk_delta_1 = await readG1(fdMPCParams); + zkeyHeader.vk_delta_2 = await readG2(fdMPCParams); + await writeHeader(fdZKeyNew, zkeyHeader); + if (await fdMPCParams.readUBE32() != zkeyHeader.nPublic + 1) { + if (logger) logger.error("Invalid number of points in IC"); + await fdZKeyNew.discard(); + return false; + } + fdMPCParams.pos += sG1 * (zkeyHeader.nPublic + 1); + await _iden3_binfileutils.copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 3); + await _iden3_binfileutils.copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 4); + if (await fdMPCParams.readUBE32() != zkeyHeader.domainSize - 1) { + if (logger) logger.error("Invalid number of points in H"); + await fdZKeyNew.discard(); + return false; + } + let buffH; + const buffTauU = await fdMPCParams.read(sG1 * (zkeyHeader.domainSize - 1)); + const buffTauLEM = await curve.G1.batchUtoLEM(buffTauU); + buffH = new Uint8Array(zkeyHeader.domainSize * sG1); + buffH.set(buffTauLEM); + curve.G1.toRprLEM(buffH, sG1 * (zkeyHeader.domainSize - 1), curve.G1.zeroAffine); + const n2Inv = curve.Fr.neg(curve.Fr.inv(curve.Fr.e(2))); + const wInv = curve.Fr.inv(curve.Fr.w[zkeyHeader.power + 1]); + buffH = await curve.G1.batchApplyKey(buffH, n2Inv, wInv, "affine", "jacobian", logger); + buffH = await curve.G1.ifft(buffH, "jacobian", "affine", logger); + await _iden3_binfileutils.startWriteSection(fdZKeyNew, 9); + await fdZKeyNew.write(buffH); + await _iden3_binfileutils.endWriteSection(fdZKeyNew); + if (await fdMPCParams.readUBE32() != zkeyHeader.nVars - zkeyHeader.nPublic - 1) { + if (logger) logger.error("Invalid number of points in L"); + await fdZKeyNew.discard(); + return false; + } + let buffL; + buffL = await fdMPCParams.read(sG1 * (zkeyHeader.nVars - zkeyHeader.nPublic - 1)); + buffL = await curve.G1.batchUtoLEM(buffL); + await _iden3_binfileutils.startWriteSection(fdZKeyNew, 8); + await fdZKeyNew.write(buffL); + await _iden3_binfileutils.endWriteSection(fdZKeyNew); + if (await fdMPCParams.readUBE32() != zkeyHeader.nVars) { + if (logger) logger.error("Invalid number of points in A"); + await fdZKeyNew.discard(); + return false; + } + fdMPCParams.pos += sG1 * zkeyHeader.nVars; + await _iden3_binfileutils.copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 5); + if (await fdMPCParams.readUBE32() != zkeyHeader.nVars) { + if (logger) logger.error("Invalid number of points in B1"); + await fdZKeyNew.discard(); + return false; + } + fdMPCParams.pos += sG1 * zkeyHeader.nVars; + await _iden3_binfileutils.copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 6); + if (await fdMPCParams.readUBE32() != zkeyHeader.nVars) { + if (logger) logger.error("Invalid number of points in B2"); + await fdZKeyNew.discard(); + return false; + } + fdMPCParams.pos += sG2 * zkeyHeader.nVars; + await _iden3_binfileutils.copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 7); + await writeMPCParams(fdZKeyNew, curve, newMPCParams); + await fdMPCParams.close(); + await fdZKeyNew.close(); + await fdZKeyOld.close(); + return true; + async function readG1(fd) { + const buff = await fd.read(curve.G1.F.n8 * 2); + return curve.G1.fromRprUncompressed(buff, 0); + } + async function readG2(fd) { + const buff = await fd.read(curve.G2.F.n8 * 2); + return curve.G2.fromRprUncompressed(buff, 0); + } + function contributionIsEqual(c1, c2) { + if (!curve.G1.eq(c1.deltaAfter, c2.deltaAfter)) return false; + if (!curve.G1.eq(c1.delta.g1_s, c2.delta.g1_s)) return false; + if (!curve.G1.eq(c1.delta.g1_sx, c2.delta.g1_sx)) return false; + if (!curve.G2.eq(c1.delta.g2_spx, c2.delta.g2_spx)) return false; + if (!hashIsEqual(c1.transcript, c2.transcript)) return false; + return true; + } +} +//#endregion +//#region src/zkey_verify_frominit.js +var sameRatio = sameRatio$2; async function phase2verifyFromInit(initFileName, pTauFileName, zkeyFileName, logger) { - - let sr; - const {fd, sections} = await binFileUtils__namespace.readBinFile(zkeyFileName, "zkey", 2); - const zkey = await readHeader$1(fd, sections, false); - if (zkey.protocol != "groth16") { - throw new Error("zkey file is not groth16"); - } - - const curve = await getCurveFromQ(zkey.q); - const sG1 = curve.G1.F.n8*2; - - const mpcParams = await readMPCParams(fd, curve, sections); - - const accumulatedHasher = blake2b.blake2b.create({ dkLen: 64 }); - accumulatedHasher.update(mpcParams.csHash); - let curDelta = curve.G1.g; - for (let i=0; i=0; i--) { - const c = mpcParams.contributions[i]; - if (logger) logger.info("-------------------------"); - if (logger) logger.info(formatHash(c.contributionHash, `contribution #${i+1} ${c.name ? c.name : ""}:`)); - if (c.type == 1) { - if (logger) logger.info(`Beacon generator: ${byteArray2hex(c.beaconHash)}`); - if (logger) logger.info(`Beacon iterations Exp: ${c.numIterationsExp}`); - } - } - if (logger) logger.info("-------------------------"); - - if (logger) logger.info("ZKey Ok!"); - - return true; - - - async function sectionHasSameRatio(groupName, fd1, sections1, fd2, sections2, idSection, g2sp, g2spx, sectionName) { - const MAX_CHUNK_SIZE = 1<<20; - const G = curve[groupName]; - const sG = G.F.n8*2; - await binFileUtils__namespace.startReadUniqueSection(fd1, sections1, idSection); - await binFileUtils__namespace.startReadUniqueSection(fd2, sections2, idSection); - - let R1 = G.zero; - let R2 = G.zero; - - const nPoints = sections1[idSection][0].size / sG; - - for (let i=0; i. -*/ - + let sr; + const { fd, sections } = await _iden3_binfileutils.readBinFile(zkeyFileName, "zkey", 2); + const zkey = await readHeader$1(fd, sections, false); + if (zkey.protocol != "groth16") throw new Error("zkey file is not groth16"); + const curve = await getCurveFromQ(zkey.q); + const sG1 = curve.G1.F.n8 * 2; + const mpcParams = await readMPCParams(fd, curve, sections); + const accumulatedHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + accumulatedHasher.update(mpcParams.csHash); + let curDelta = curve.G1.g; + for (let i = 0; i < mpcParams.contributions.length; i++) { + const c = mpcParams.contributions[i]; + const ourHasher = cloneHasher(accumulatedHasher); + hashG1(ourHasher, curve, c.delta.g1_s); + hashG1(ourHasher, curve, c.delta.g1_sx); + if (!hashIsEqual(ourHasher.digest(), c.transcript)) { + console.log(`INVALID(${i}): Inconsistent transcript `); + return false; + } + const delta_g2_sp = hashToG2(curve, c.transcript); + sr = await sameRatio(curve, c.delta.g1_s, c.delta.g1_sx, delta_g2_sp, c.delta.g2_spx); + if (sr !== true) { + console.log(`INVALID(${i}): public key G1 and G2 do not have the same ration `); + return false; + } + sr = await sameRatio(curve, curDelta, c.deltaAfter, delta_g2_sp, c.delta.g2_spx); + if (sr !== true) { + console.log(`INVALID(${i}): deltaAfter does not fillow the public key `); + return false; + } + if (c.type == 1) { + const rng = await rngFromBeaconParams(c.beaconHash, c.numIterationsExp); + const expected_prvKey = curve.Fr.fromRng(rng); + const expected_g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); + const expected_g1_sx = curve.G1.toAffine(curve.G1.timesFr(expected_g1_s, expected_prvKey)); + if (curve.G1.eq(expected_g1_s, c.delta.g1_s) !== true) { + console.log(`INVALID(${i}): Key of the beacon does not match. g1_s `); + return false; + } + if (curve.G1.eq(expected_g1_sx, c.delta.g1_sx) !== true) { + console.log(`INVALID(${i}): Key of the beacon does not match. g1_sx `); + return false; + } + } + hashPubKey(accumulatedHasher, curve, c); + const contributionHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + hashPubKey(contributionHasher, curve, c); + c.contributionHash = contributionHasher.digest(); + curDelta = c.deltaAfter; + } + const { fd: fdInit, sections: sectionsInit } = await _iden3_binfileutils.readBinFile(initFileName, "zkey", 2); + const zkeyInit = await readHeader$1(fdInit, sectionsInit, false); + if (zkeyInit.protocol != "groth16") throw new Error("zkeyinit file is not groth16"); + if (!ffjavascript.Scalar.eq(zkeyInit.q, zkey.q) || !ffjavascript.Scalar.eq(zkeyInit.r, zkey.r) || zkeyInit.n8q != zkey.n8q || zkeyInit.n8r != zkey.n8r) { + if (logger) logger.error("INVALID: Different curves"); + return false; + } + if (zkeyInit.nVars != zkey.nVars || zkeyInit.nPublic != zkey.nPublic || zkeyInit.domainSize != zkey.domainSize) { + if (logger) logger.error("INVALID: Different circuit parameters"); + return false; + } + if (!curve.G1.eq(zkey.vk_alpha_1, zkeyInit.vk_alpha_1)) { + if (logger) logger.error("INVALID: Invalid alpha1"); + return false; + } + if (!curve.G1.eq(zkey.vk_beta_1, zkeyInit.vk_beta_1)) { + if (logger) logger.error("INVALID: Invalid beta1"); + return false; + } + if (!curve.G2.eq(zkey.vk_beta_2, zkeyInit.vk_beta_2)) { + if (logger) logger.error("INVALID: Invalid beta2"); + return false; + } + if (!curve.G2.eq(zkey.vk_gamma_2, zkeyInit.vk_gamma_2)) { + if (logger) logger.error("INVALID: Invalid gamma2"); + return false; + } + if (!curve.G1.eq(zkey.vk_delta_1, curDelta)) { + if (logger) logger.error("INVALID: Invalid delta1"); + return false; + } + sr = await sameRatio(curve, curve.G1.g, curDelta, curve.G2.g, zkey.vk_delta_2); + if (sr !== true) { + if (logger) logger.error("INVALID: Invalid delta2"); + return false; + } + const mpcParamsInit = await readMPCParams(fdInit, curve, sectionsInit); + if (!hashIsEqual(mpcParams.csHash, mpcParamsInit.csHash)) { + if (logger) logger.error("INVALID: Circuit does not match"); + return false; + } + if (sections[8][0].size != sG1 * (zkey.nVars - zkey.nPublic - 1)) { + if (logger) logger.error("INVALID: Invalid L section size"); + return false; + } + if (sections[9][0].size != sG1 * zkey.domainSize) { + if (logger) logger.error("INVALID: Invalid H section size"); + return false; + } + let ss; + ss = await _iden3_binfileutils.sectionIsEqual(fd, sections, fdInit, sectionsInit, 3); + if (!ss) { + if (logger) logger.error("INVALID: IC section is not identical"); + return false; + } + ss = await _iden3_binfileutils.sectionIsEqual(fd, sections, fdInit, sectionsInit, 4); + if (!ss) { + if (logger) logger.error("Coeffs section is not identical"); + return false; + } + ss = await _iden3_binfileutils.sectionIsEqual(fd, sections, fdInit, sectionsInit, 5); + if (!ss) { + if (logger) logger.error("A section is not identical"); + return false; + } + ss = await _iden3_binfileutils.sectionIsEqual(fd, sections, fdInit, sectionsInit, 6); + if (!ss) { + if (logger) logger.error("B1 section is not identical"); + return false; + } + ss = await _iden3_binfileutils.sectionIsEqual(fd, sections, fdInit, sectionsInit, 7); + if (!ss) { + if (logger) logger.error("B2 section is not identical"); + return false; + } + sr = await sectionHasSameRatio("G1", fdInit, sectionsInit, fd, sections, 8, zkey.vk_delta_2, zkeyInit.vk_delta_2, "L section"); + if (sr !== true) { + if (logger) logger.error("L section does not match"); + return false; + } + sr = await sameRatioH(); + if (sr !== true) { + if (logger) logger.error("H section does not match"); + return false; + } + if (logger) logger.info(formatHash(mpcParams.csHash, "Circuit Hash: ")); + await fd.close(); + await fdInit.close(); + for (let i = mpcParams.contributions.length - 1; i >= 0; i--) { + const c = mpcParams.contributions[i]; + if (logger) logger.info("-------------------------"); + if (logger) logger.info(formatHash(c.contributionHash, `contribution #${i + 1} ${c.name ? c.name : ""}:`)); + if (c.type == 1) { + if (logger) logger.info(`Beacon generator: ${byteArray2hex(c.beaconHash)}`); + if (logger) logger.info(`Beacon iterations Exp: ${c.numIterationsExp}`); + } + } + if (logger) logger.info("-------------------------"); + if (logger) logger.info("ZKey Ok!"); + return true; + async function sectionHasSameRatio(groupName, fd1, sections1, fd2, sections2, idSection, g2sp, g2spx, sectionName) { + const MAX_CHUNK_SIZE = 1 << 20; + const G = curve[groupName]; + const sG = G.F.n8 * 2; + await _iden3_binfileutils.startReadUniqueSection(fd1, sections1, idSection); + await _iden3_binfileutils.startReadUniqueSection(fd2, sections2, idSection); + let R1 = G.zero; + let R2 = G.zero; + const nPoints = sections1[idSection][0].size / sG; + for (let i = 0; i < nPoints; i += MAX_CHUNK_SIZE) { + if (logger) logger.debug(`Same ratio check ${sectionName}: ${i}/${nPoints}`); + const n = Math.min(nPoints - i, MAX_CHUNK_SIZE); + const bases1 = await fd1.read(n * sG); + const bases2 = await fd2.read(n * sG); + const scalars = getRandomBytes(4 * n); + const r1 = await G.multiExpAffine(bases1, scalars); + const r2 = await G.multiExpAffine(bases2, scalars); + R1 = G.add(R1, r1); + R2 = G.add(R2, r2); + } + await _iden3_binfileutils.endReadSection(fd1); + await _iden3_binfileutils.endReadSection(fd2); + if (nPoints == 0) return true; + sr = await sameRatio(curve, R1, R2, g2sp, g2spx); + if (sr !== true) return false; + return true; + } + async function sameRatioH() { + const MAX_CHUNK_SIZE = 1 << 20; + const G = curve.G1; + const Fr = curve.Fr; + const sG = G.F.n8 * 2; + const { fd: fdPTau, sections: sectionsPTau } = await _iden3_binfileutils.readBinFile(pTauFileName, "ptau", 1); + let buff_r = new ffjavascript.BigBuffer(zkey.domainSize * zkey.n8r); + const seed = new Array(8); + for (let i = 0; i < 8; i++) seed[i] = readUInt32BE(getRandomBytes(4), 0); + const rng = new ffjavascript.ChaCha(seed); + for (let i = 0; i < zkey.domainSize - 1; i++) { + const e = Fr.fromRng(rng); + Fr.toRprLE(buff_r, i * zkey.n8r, e); + } + Fr.toRprLE(buff_r, (zkey.domainSize - 1) * zkey.n8r, Fr.zero); + let R1 = G.zero; + for (let i = 0; i < zkey.domainSize; i += MAX_CHUNK_SIZE) { + if (logger) logger.debug(`H Verification(tau): ${i}/${zkey.domainSize}`); + const n = Math.min(zkey.domainSize - i, MAX_CHUNK_SIZE); + const buffB = await batchSubtract(await fdPTau.read(sG * n, sectionsPTau[2][0].p + zkey.domainSize * sG + i * sG), await fdPTau.read(sG * n, sectionsPTau[2][0].p + i * sG)); + const buffS = buff_r.slice(i * zkey.n8r, (i + n) * zkey.n8r); + const r = await G.multiExpAffine(buffB, buffS); + R1 = G.add(R1, r); + } + buff_r = await Fr.batchToMontgomery(buff_r); + let first; + if (zkey.power < Fr.s) first = Fr.neg(Fr.e(2)); + else { + const small_m = 2 ** Fr.s; + const shift_to_small_m = Fr.exp(Fr.shift, small_m); + first = Fr.sub(shift_to_small_m, Fr.one); + } + const inc = zkey.power < Fr.s ? Fr.w[zkey.power + 1] : Fr.shift; + buff_r = await Fr.batchApplyKey(buff_r, first, inc); + buff_r = await Fr.fft(buff_r); + buff_r = await Fr.batchFromMontgomery(buff_r); + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 9); + let R2 = G.zero; + for (let i = 0; i < zkey.domainSize; i += MAX_CHUNK_SIZE) { + if (logger) logger.debug(`H Verification(lagrange): ${i}/${zkey.domainSize}`); + const n = Math.min(zkey.domainSize - i, MAX_CHUNK_SIZE); + const buff = await fd.read(sG * n); + const buffS = buff_r.slice(i * zkey.n8r, (i + n) * zkey.n8r); + const r = await G.multiExpAffine(buff, buffS); + R2 = G.add(R2, r); + } + await _iden3_binfileutils.endReadSection(fd); + sr = await sameRatio(curve, R1, R2, zkey.vk_delta_2, zkeyInit.vk_delta_2); + if (sr !== true) return false; + return true; + } + async function batchSubtract(buff1, buff2) { + const sG = curve.G1.F.n8 * 2; + const nPoints = buff1.byteLength / sG; + const concurrency = curve.tm.concurrency; + const nPointsPerThread = Math.floor(nPoints / concurrency); + const opPromises = []; + for (let i = 0; i < concurrency; i++) { + let n; + if (i < concurrency - 1) n = nPointsPerThread; + else n = nPoints - i * nPointsPerThread; + if (n == 0) continue; + const subBuff1 = buff1.slice(i * nPointsPerThread * sG1, (i * nPointsPerThread + n) * sG1); + const subBuff2 = buff2.slice(i * nPointsPerThread * sG1, (i * nPointsPerThread + n) * sG1); + opPromises.push(batchSubtractThread(subBuff1, subBuff2)); + } + const result = await Promise.all(opPromises); + const fullBuffOut = new Uint8Array(nPoints * sG); + let p = 0; + for (let i = 0; i < result.length; i++) { + fullBuffOut.set(result[i][0], p); + p += result[i][0].byteLength; + } + return fullBuffOut; + } + async function batchSubtractThread(buff1, buff2) { + const sG1 = curve.G1.F.n8 * 2; + const sGmid = curve.G1.F.n8 * 3; + const nPoints = buff1.byteLength / sG1; + const task = []; + task.push({ + cmd: "ALLOCSET", + var: 0, + buff: buff1 + }); + task.push({ + cmd: "ALLOCSET", + var: 1, + buff: buff2 + }); + task.push({ + cmd: "ALLOC", + var: 2, + len: nPoints * sGmid + }); + for (let i = 0; i < nPoints; i++) task.push({ + cmd: "CALL", + fnName: "g1m_subAffine", + params: [ + { + var: 0, + offset: i * sG1 + }, + { + var: 1, + offset: i * sG1 + }, + { + var: 2, + offset: i * sGmid + } + ] + }); + task.push({ + cmd: "CALL", + fnName: "g1m_batchToAffine", + params: [ + { var: 2 }, + { val: nPoints }, + { var: 2 } + ] + }); + task.push({ + cmd: "GET", + out: 0, + var: 2, + len: nPoints * sG1 + }); + return await curve.tm.queueAction(task); + } +} +//#endregion +//#region src/zkey_verify_fromr1cs.js async function phase2verifyFromR1cs(r1csFileName, pTauFileName, zkeyFileName, logger) { - - // const initFileName = "~" + zkeyFileName + ".init"; - const initFileName = {type: "bigMem"}; - await newZKey(r1csFileName, pTauFileName, initFileName, logger); - - return await phase2verifyFromInit(initFileName, pTauFileName, zkeyFileName, logger); -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - + const initFileName = { type: "bigMem" }; + await newZKey(r1csFileName, pTauFileName, initFileName, logger); + return await phase2verifyFromInit(initFileName, pTauFileName, zkeyFileName, logger); +} +//#endregion +//#region src/zkey_contribute.js async function phase2contribute(zkeyNameOld, zkeyNameNew, name, entropy, logger) { - - const {fd: fdOld, sections: sections} = await binFileUtils__namespace.readBinFile(zkeyNameOld, "zkey", 2); - const zkey = await readHeader$1(fdOld, sections); - if (zkey.protocol != "groth16") { - throw new Error("zkey file is not groth16"); - } - - const curve = await getCurveFromQ(zkey.q); - - const mpcParams = await readMPCParams(fdOld, curve, sections); - - const fdNew = await binFileUtils__namespace.createBinFile(zkeyNameNew, "zkey", 1, 10); - - - const rng = await getRandomRng(entropy); - - const transcriptHasher = blake2b.blake2b.create({ dkLen: 64 }); - transcriptHasher.update(mpcParams.csHash); - for (let i=0; i. -*/ - - + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(zkeyNameOld, "zkey", 2); + const zkey = await readHeader$1(fdOld, sections); + if (zkey.protocol != "groth16") throw new Error("zkey file is not groth16"); + const curve = await getCurveFromQ(zkey.q); + const mpcParams = await readMPCParams(fdOld, curve, sections); + const fdNew = await _iden3_binfileutils.createBinFile(zkeyNameNew, "zkey", 1, 10); + const rng = await getRandomRng(entropy); + const transcriptHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + transcriptHasher.update(mpcParams.csHash); + for (let i = 0; i < mpcParams.contributions.length; i++) hashPubKey(transcriptHasher, curve, mpcParams.contributions[i]); + const curContribution = {}; + curContribution.delta = {}; + curContribution.delta.prvKey = curve.Fr.fromRng(rng); + curContribution.delta.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); + curContribution.delta.g1_sx = curve.G1.toAffine(curve.G1.timesFr(curContribution.delta.g1_s, curContribution.delta.prvKey)); + hashG1(transcriptHasher, curve, curContribution.delta.g1_s); + hashG1(transcriptHasher, curve, curContribution.delta.g1_sx); + curContribution.transcript = transcriptHasher.digest(); + curContribution.delta.g2_sp = hashToG2(curve, curContribution.transcript); + curContribution.delta.g2_spx = curve.G2.toAffine(curve.G2.timesFr(curContribution.delta.g2_sp, curContribution.delta.prvKey)); + zkey.vk_delta_1 = curve.G1.timesFr(zkey.vk_delta_1, curContribution.delta.prvKey); + zkey.vk_delta_2 = curve.G2.timesFr(zkey.vk_delta_2, curContribution.delta.prvKey); + curContribution.deltaAfter = zkey.vk_delta_1; + curContribution.type = 0; + if (name) curContribution.name = name; + mpcParams.contributions.push(curContribution); + await writeHeader(fdNew, zkey); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 3); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 4); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 5); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 6); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 7); + const invDelta = curve.Fr.inv(curContribution.delta.prvKey); + await applyKeyToSection(fdOld, sections, fdNew, 8, curve, "G1", invDelta, curve.Fr.e(1), "L Section", logger); + await applyKeyToSection(fdOld, sections, fdNew, 9, curve, "G1", invDelta, curve.Fr.e(1), "H Section", logger); + await writeMPCParams(fdNew, curve, mpcParams); + await fdOld.close(); + await fdNew.close(); + const contributionHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + hashPubKey(contributionHasher, curve, curContribution); + const contributionHash = contributionHasher.digest(); + if (logger) logger.info(formatHash(mpcParams.csHash, "Circuit Hash: ")); + if (logger) logger.info(formatHash(contributionHash, "Contribution Hash: ")); + return contributionHash; +} +//#endregion +//#region src/zkey_beacon.js async function beacon(zkeyNameOld, zkeyNameNew, name, beaconHashStr, numIterationsExp, logger) { - const beaconHash = hex2ByteArray(beaconHashStr); - if ( (beaconHash.byteLength == 0) - || (beaconHash.byteLength*2 !=beaconHashStr.length)) - { - if (logger) logger.error("Invalid Beacon Hash. (It must be a valid hexadecimal sequence)"); - return false; - } - if (beaconHash.length>=256) { - if (logger) logger.error("Maximum length of beacon hash is 255 bytes"); - return false; - } - - numIterationsExp = parseInt(numIterationsExp); - if ((numIterationsExp<10)||(numIterationsExp>63)) { - if (logger) logger.error("Invalid numIterationsExp. (Must be between 10 and 63)"); - return false; - } - - - const {fd: fdOld, sections: sections} = await binFileUtils__namespace.readBinFile(zkeyNameOld, "zkey", 2); - const zkey = await readHeader$1(fdOld, sections); - - if (zkey.protocol != "groth16") { - throw new Error("zkey file is not groth16"); - } - - - const curve = await getCurveFromQ(zkey.q); - - const mpcParams = await readMPCParams(fdOld, curve, sections); - - const fdNew = await binFileUtils__namespace.createBinFile(zkeyNameNew, "zkey", 1, 10); - - const rng = await rngFromBeaconParams(beaconHash, numIterationsExp); - - const transcriptHasher = blake2b.blake2b.create({ dkLen: 64 }); transcriptHasher.update(mpcParams.csHash); - for (let i=0; i= 256) { + if (logger) logger.error("Maximum length of beacon hash is 255 bytes"); + return false; + } + numIterationsExp = parseInt(numIterationsExp); + if (numIterationsExp < 10 || numIterationsExp > 63) { + if (logger) logger.error("Invalid numIterationsExp. (Must be between 10 and 63)"); + return false; + } + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(zkeyNameOld, "zkey", 2); + const zkey = await readHeader$1(fdOld, sections); + if (zkey.protocol != "groth16") throw new Error("zkey file is not groth16"); + const curve = await getCurveFromQ(zkey.q); + const mpcParams = await readMPCParams(fdOld, curve, sections); + const fdNew = await _iden3_binfileutils.createBinFile(zkeyNameNew, "zkey", 1, 10); + const rng = await rngFromBeaconParams(beaconHash, numIterationsExp); + const transcriptHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + transcriptHasher.update(mpcParams.csHash); + for (let i = 0; i < mpcParams.contributions.length; i++) hashPubKey(transcriptHasher, curve, mpcParams.contributions[i]); + const curContribution = {}; + curContribution.delta = {}; + curContribution.delta.prvKey = curve.Fr.fromRng(rng); + curContribution.delta.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); + curContribution.delta.g1_sx = curve.G1.toAffine(curve.G1.timesFr(curContribution.delta.g1_s, curContribution.delta.prvKey)); + hashG1(transcriptHasher, curve, curContribution.delta.g1_s); + hashG1(transcriptHasher, curve, curContribution.delta.g1_sx); + curContribution.transcript = transcriptHasher.digest(); + curContribution.delta.g2_sp = hashToG2(curve, curContribution.transcript); + curContribution.delta.g2_spx = curve.G2.toAffine(curve.G2.timesFr(curContribution.delta.g2_sp, curContribution.delta.prvKey)); + zkey.vk_delta_1 = curve.G1.timesFr(zkey.vk_delta_1, curContribution.delta.prvKey); + zkey.vk_delta_2 = curve.G2.timesFr(zkey.vk_delta_2, curContribution.delta.prvKey); + curContribution.deltaAfter = zkey.vk_delta_1; + curContribution.type = 1; + curContribution.numIterationsExp = numIterationsExp; + curContribution.beaconHash = beaconHash; + if (name) curContribution.name = name; + mpcParams.contributions.push(curContribution); + await writeHeader(fdNew, zkey); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 3); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 4); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 5); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 6); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 7); + const invDelta = curve.Fr.inv(curContribution.delta.prvKey); + await applyKeyToSection(fdOld, sections, fdNew, 8, curve, "G1", invDelta, curve.Fr.e(1), "L Section", logger); + await applyKeyToSection(fdOld, sections, fdNew, 9, curve, "G1", invDelta, curve.Fr.e(1), "H Section", logger); + await writeMPCParams(fdNew, curve, mpcParams); + await fdOld.close(); + await fdNew.close(); + const contributionHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + hashPubKey(contributionHasher, curve, curContribution); + const contributionHash = contributionHasher.digest(); + if (logger) logger.info(formatHash(contributionHash, "Contribution Hash: ")); + return contributionHash; +} +//#endregion +//#region src/zkey_export_json.js async function zkeyExportJson(zkeyFileName) { - - const zKey = await readZKey(zkeyFileName, true); - delete zKey.curve; - delete zKey.F; - - return ffjavascript.utils.stringifyBigInts(zKey); -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - + const zKey = await readZKey(zkeyFileName, true); + delete zKey.curve; + delete zKey.F; + return ffjavascript.utils.stringifyBigInts(zKey); +} +//#endregion +//#region src/zkey_bellman_contribute.js async function bellmanContribute(curve, challengeFilename, responseFileName, entropy, logger) { - const rng = await getRandomRng(entropy); - - const delta = curve.Fr.fromRng(rng); - const invDelta = curve.Fr.inv(delta); - - const sG1 = curve.G1.F.n8*2; - const sG2 = curve.G2.F.n8*2; - - const fdFrom = await fastFile__namespace.readExisting(challengeFilename); - const fdTo = await fastFile__namespace.createOverride(responseFileName); - - - await copy(sG1); // alpha1 - await copy(sG1); // beta1 - await copy(sG2); // beta2 - await copy(sG2); // gamma2 - const oldDelta1 = await readG1(); - const delta1 = curve.G1.timesFr(oldDelta1, delta); - await writeG1(delta1); - const oldDelta2 = await readG2(); - const delta2 = curve.G2.timesFr(oldDelta2, delta); - await writeG2(delta2); - - // IC - const nIC = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nIC); - await copy(nIC*sG1); - - // H - const nH = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nH); - await applyKeyToChallengeSection(fdFrom, fdTo, null, curve, "G1", nH, invDelta, curve.Fr.e(1), "UNCOMPRESSED", "H", logger); - - // L - const nL = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nL); - await applyKeyToChallengeSection(fdFrom, fdTo, null, curve, "G1", nL, invDelta, curve.Fr.e(1), "UNCOMPRESSED", "L", logger); - - // A - const nA = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nA); - await copy(nA*sG1); - - // B1 - const nB1 = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nB1); - await copy(nB1*sG1); - - // B2 - const nB2 = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nB2); - await copy(nB2*sG2); - - - ////////// - /// Read contributions - ////////// - const transcriptHasher = blake2b.blake2b.create({ dkLen: 64 }); - const mpcParams = {}; - // csHash - mpcParams.csHash = await fdFrom.read(64); - transcriptHasher.update(mpcParams.csHash); - - const nContributions = await fdFrom.readUBE32(); - mpcParams.contributions = []; - for (let i=0; i. -*/ - -const {stringifyBigInts: stringifyBigInts$3} = ffjavascript.utils; - + const rng = await getRandomRng(entropy); + const delta = curve.Fr.fromRng(rng); + const invDelta = curve.Fr.inv(delta); + const sG1 = curve.G1.F.n8 * 2; + const sG2 = curve.G2.F.n8 * 2; + const fdFrom = await fastfile.readExisting(challengeFilename); + const fdTo = await fastfile.createOverride(responseFileName); + await copy(sG1); + await copy(sG1); + await copy(sG2); + await copy(sG2); + const oldDelta1 = await readG1(); + const delta1 = curve.G1.timesFr(oldDelta1, delta); + await writeG1(delta1); + const oldDelta2 = await readG2(); + await writeG2(curve.G2.timesFr(oldDelta2, delta)); + const nIC = await fdFrom.readUBE32(); + await fdTo.writeUBE32(nIC); + await copy(nIC * sG1); + const nH = await fdFrom.readUBE32(); + await fdTo.writeUBE32(nH); + await applyKeyToChallengeSection(fdFrom, fdTo, null, curve, "G1", nH, invDelta, curve.Fr.e(1), "UNCOMPRESSED", "H", logger); + const nL = await fdFrom.readUBE32(); + await fdTo.writeUBE32(nL); + await applyKeyToChallengeSection(fdFrom, fdTo, null, curve, "G1", nL, invDelta, curve.Fr.e(1), "UNCOMPRESSED", "L", logger); + const nA = await fdFrom.readUBE32(); + await fdTo.writeUBE32(nA); + await copy(nA * sG1); + const nB1 = await fdFrom.readUBE32(); + await fdTo.writeUBE32(nB1); + await copy(nB1 * sG1); + const nB2 = await fdFrom.readUBE32(); + await fdTo.writeUBE32(nB2); + await copy(nB2 * sG2); + const transcriptHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + const mpcParams = {}; + mpcParams.csHash = await fdFrom.read(64); + transcriptHasher.update(mpcParams.csHash); + const nContributions = await fdFrom.readUBE32(); + mpcParams.contributions = []; + for (let i = 0; i < nContributions; i++) { + const c = { delta: {} }; + c.deltaAfter = await readG1(); + c.delta.g1_s = await readG1(); + c.delta.g1_sx = await readG1(); + c.delta.g2_spx = await readG2(); + c.transcript = await fdFrom.read(64); + mpcParams.contributions.push(c); + hashPubKey(transcriptHasher, curve, c); + } + const curContribution = {}; + curContribution.delta = {}; + curContribution.delta.prvKey = delta; + curContribution.delta.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); + curContribution.delta.g1_sx = curve.G1.toAffine(curve.G1.timesFr(curContribution.delta.g1_s, delta)); + hashG1(transcriptHasher, curve, curContribution.delta.g1_s); + hashG1(transcriptHasher, curve, curContribution.delta.g1_sx); + curContribution.transcript = transcriptHasher.digest(); + curContribution.delta.g2_sp = hashToG2(curve, curContribution.transcript); + curContribution.delta.g2_spx = curve.G2.toAffine(curve.G2.timesFr(curContribution.delta.g2_sp, delta)); + curContribution.deltaAfter = delta1; + curContribution.type = 0; + mpcParams.contributions.push(curContribution); + await fdTo.write(mpcParams.csHash); + await fdTo.writeUBE32(mpcParams.contributions.length); + for (let i = 0; i < mpcParams.contributions.length; i++) { + const c = mpcParams.contributions[i]; + await writeG1(c.deltaAfter); + await writeG1(c.delta.g1_s); + await writeG1(c.delta.g1_sx); + await writeG2(c.delta.g2_spx); + await fdTo.write(c.transcript); + } + const contributionHasher = _noble_hashes_blake2_js.blake2b.create({ dkLen: 64 }); + hashPubKey(contributionHasher, curve, curContribution); + const contributionHash = contributionHasher.digest(); + if (logger) logger.info(formatHash(contributionHash, "Contribution Hash: ")); + await fdTo.close(); + await fdFrom.close(); + return contributionHash; + async function copy(nBytes) { + const CHUNK_SIZE = fdFrom.pageSize * 2; + for (let i = 0; i < nBytes; i += CHUNK_SIZE) { + const n = Math.min(nBytes - i, CHUNK_SIZE); + const buff = await fdFrom.read(n); + await fdTo.write(buff); + } + } + async function readG1() { + const buff = await fdFrom.read(curve.G1.F.n8 * 2); + return curve.G1.fromRprUncompressed(buff, 0); + } + async function readG2() { + const buff = await fdFrom.read(curve.G2.F.n8 * 2); + return curve.G2.fromRprUncompressed(buff, 0); + } + async function writeG1(P) { + const buff = new Uint8Array(sG1); + curve.G1.toRprUncompressed(buff, 0, P); + await fdTo.write(buff); + } + async function writeG2(P) { + const buff = new Uint8Array(sG2); + curve.G2.toRprUncompressed(buff, 0, P); + await fdTo.write(buff); + } +} +//#endregion +//#region src/zkey_export_verificationkey.js +var { stringifyBigInts: stringifyBigInts$3 } = ffjavascript.utils; async function zkeyExportVerificationKey(zkeyName, logger) { - if (logger) logger.info("EXPORT VERIFICATION KEY STARTED"); - - const {fd, sections} = await binFileUtils__namespace.readBinFile(zkeyName, "zkey", 2); - const zkey = await readHeader$1(fd, sections); - - if (logger) logger.info("> Detected protocol: " + zkey.protocol); - - let res; - if (zkey.protocol === "groth16") { - res = await groth16Vk(zkey, fd, sections); - } else if (zkey.protocol === "plonk") { - res = await plonkVk(zkey); - } else if (zkey.protocolId && zkey.protocolId === FFLONK_PROTOCOL_ID) { - res = await exportFFlonkVk(zkey); - } else { - throw new Error("zkey file protocol unrecognized"); - } - - await fd.close(); - - if (logger) logger.info("EXPORT VERIFICATION KEY FINISHED"); - - return res; -} - - + if (logger) logger.info("EXPORT VERIFICATION KEY STARTED"); + const { fd, sections } = await _iden3_binfileutils.readBinFile(zkeyName, "zkey", 2); + const zkey = await readHeader$1(fd, sections); + if (logger) logger.info("> Detected protocol: " + zkey.protocol); + let res; + if (zkey.protocol === "groth16") res = await groth16Vk(zkey, fd, sections); + else if (zkey.protocol === "plonk") res = await plonkVk(zkey); + else if (zkey.protocolId && zkey.protocolId === 10) res = await exportFFlonkVk(zkey, logger); + else throw new Error("zkey file protocol unrecognized"); + await fd.close(); + if (logger) logger.info("EXPORT VERIFICATION KEY FINISHED"); + return res; +} async function groth16Vk(zkey, fd, sections) { - const curve = await getCurveFromQ(zkey.q); - const sG1 = curve.G1.F.n8 * 2; - - const alphaBeta = await curve.pairing(zkey.vk_alpha_1, zkey.vk_beta_2); - - let vKey = { - protocol: zkey.protocol, - curve: curve.name, - nPublic: zkey.nPublic, - - vk_alpha_1: curve.G1.toObject(zkey.vk_alpha_1), - - vk_beta_2: curve.G2.toObject(zkey.vk_beta_2), - vk_gamma_2: curve.G2.toObject(zkey.vk_gamma_2), - vk_delta_2: curve.G2.toObject(zkey.vk_delta_2), - - vk_alphabeta_12: curve.Gt.toObject(alphaBeta) - }; - - // Read IC Section - /////////// - await binFileUtils__namespace.startReadUniqueSection(fd, sections, 3); - vKey.IC = []; - for (let i = 0; i <= zkey.nPublic; i++) { - const buff = await fd.read(sG1); - const P = curve.G1.toObject(buff); - vKey.IC.push(P); - } - await binFileUtils__namespace.endReadSection(fd); - - vKey = stringifyBigInts$3(vKey); - - return vKey; -} - - + const curve = await getCurveFromQ(zkey.q); + const sG1 = curve.G1.F.n8 * 2; + const alphaBeta = await curve.pairing(zkey.vk_alpha_1, zkey.vk_beta_2); + let vKey = { + protocol: zkey.protocol, + curve: curve.name, + nPublic: zkey.nPublic, + vk_alpha_1: curve.G1.toObject(zkey.vk_alpha_1), + vk_beta_2: curve.G2.toObject(zkey.vk_beta_2), + vk_gamma_2: curve.G2.toObject(zkey.vk_gamma_2), + vk_delta_2: curve.G2.toObject(zkey.vk_delta_2), + vk_alphabeta_12: curve.Gt.toObject(alphaBeta) + }; + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 3); + vKey.IC = []; + for (let i = 0; i <= zkey.nPublic; i++) { + const buff = await fd.read(sG1); + const P = curve.G1.toObject(buff); + vKey.IC.push(P); + } + await _iden3_binfileutils.endReadSection(fd); + vKey = stringifyBigInts$3(vKey); + return vKey; +} async function plonkVk(zkey) { - const curve = await getCurveFromQ(zkey.q); - - let vKey = { - protocol: zkey.protocol, - curve: curve.name, - nPublic: zkey.nPublic, - power: zkey.power, - - k1: curve.Fr.toObject(zkey.k1), - k2: curve.Fr.toObject(zkey.k2), - - Qm: curve.G1.toObject(zkey.Qm), - Ql: curve.G1.toObject(zkey.Ql), - Qr: curve.G1.toObject(zkey.Qr), - Qo: curve.G1.toObject(zkey.Qo), - Qc: curve.G1.toObject(zkey.Qc), - S1: curve.G1.toObject(zkey.S1), - S2: curve.G1.toObject(zkey.S2), - S3: curve.G1.toObject(zkey.S3), - - X_2: curve.G2.toObject(zkey.X_2), - - w: curve.Fr.toObject(curve.Fr.w[zkey.power]) - }; - - vKey = stringifyBigInts$3(vKey); - - return vKey; -} - -async function exportFFlonkVk(zkey, logger) { - const curve = await getCurveFromQ(zkey.q); - - let vKey = { - protocol: zkey.protocol, - curve: curve.name, - nPublic: zkey.nPublic, - power: zkey.power, - - k1: curve.Fr.toObject(zkey.k1), - k2: curve.Fr.toObject(zkey.k2), - - w: curve.Fr.toObject(curve.Fr.w[zkey.power]), - //wW: curve.Fr.toObject(curve.Fr.w[zkey.power + 1]), - w3: curve.Fr.toObject(zkey.w3), - w4: curve.Fr.toObject(zkey.w4), - w8: curve.Fr.toObject(zkey.w8), - wr: curve.Fr.toObject(zkey.wr), - - X_2: curve.G2.toObject(zkey.X_2), - - C0: curve.G1.toObject(zkey.C0), - }; - - return stringifyBigInts$3(vKey); -} - -/* - Copyright 2021 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -const {unstringifyBigInts: unstringifyBigInts$6, stringifyBigInts: stringifyBigInts$2} = ffjavascript.utils; - + const curve = await getCurveFromQ(zkey.q); + let vKey = { + protocol: zkey.protocol, + curve: curve.name, + nPublic: zkey.nPublic, + power: zkey.power, + k1: curve.Fr.toObject(zkey.k1), + k2: curve.Fr.toObject(zkey.k2), + Qm: curve.G1.toObject(zkey.Qm), + Ql: curve.G1.toObject(zkey.Ql), + Qr: curve.G1.toObject(zkey.Qr), + Qo: curve.G1.toObject(zkey.Qo), + Qc: curve.G1.toObject(zkey.Qc), + S1: curve.G1.toObject(zkey.S1), + S2: curve.G1.toObject(zkey.S2), + S3: curve.G1.toObject(zkey.S3), + X_2: curve.G2.toObject(zkey.X_2), + w: curve.Fr.toObject(curve.Fr.w[zkey.power]) + }; + vKey = stringifyBigInts$3(vKey); + return vKey; +} +async function exportFFlonkVk(zkey, _logger) { + const curve = await getCurveFromQ(zkey.q); + return stringifyBigInts$3({ + protocol: zkey.protocol, + curve: curve.name, + nPublic: zkey.nPublic, + power: zkey.power, + k1: curve.Fr.toObject(zkey.k1), + k2: curve.Fr.toObject(zkey.k2), + w: curve.Fr.toObject(curve.Fr.w[zkey.power]), + w3: curve.Fr.toObject(zkey.w3), + w4: curve.Fr.toObject(zkey.w4), + w8: curve.Fr.toObject(zkey.w8), + wr: curve.Fr.toObject(zkey.wr), + X_2: curve.G2.toObject(zkey.X_2), + C0: curve.G1.toObject(zkey.C0) + }); +} +//#endregion +//#region src/fflonk_export_solidity_verifier.js +var { unstringifyBigInts: unstringifyBigInts$6, stringifyBigInts: stringifyBigInts$2 } = ffjavascript.utils; async function fflonkExportSolidityVerifier(vk, templates, logger) { - if (logger) logger.info("FFLONK EXPORT SOLIDITY VERIFIER STARTED"); - - const curve = await getCurveFromName(vk.curve); - - // Precompute w3_2, w4_2 and w4_3 - let w3 = fromVkey(vk.w3); - vk.w3_2 = toVkey(curve.Fr.square(w3)); - - let w4 = fromVkey(vk.w4); - vk.w4_2 = toVkey(curve.Fr.square(w4)); - vk.w4_3 = toVkey(curve.Fr.mul(curve.Fr.square(w4), w4)); - - let w8 = fromVkey(vk.w8); - let acc = curve.Fr.one; - - for (let i = 1; i < 8; i++) { - acc = curve.Fr.mul(acc, w8); - vk["w8_" + i] = toVkey(acc); - } - - let template = templates[vk.protocol]; - - if (logger) logger.info("FFLONK EXPORT SOLIDITY VERIFIER FINISHED"); - - const {default: ejs} = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('ejs')); }); - return ejs.render(template, vk); - - function fromVkey(str) { - const val = unstringifyBigInts$6(str); - return curve.Fr.fromObject(val); - } - - function toVkey(val) { - const str = curve.Fr.toObject(val); - return stringifyBigInts$2(str); - } -} - -// Not ready yet -// module.exports.generateVerifier_kimleeoh = generateVerifier_kimleeoh; - + if (logger) logger.info("FFLONK EXPORT SOLIDITY VERIFIER STARTED"); + const curve = await getCurveFromName(vk.curve); + let w3 = fromVkey(vk.w3); + vk.w3_2 = toVkey(curve.Fr.square(w3)); + let w4 = fromVkey(vk.w4); + vk.w4_2 = toVkey(curve.Fr.square(w4)); + vk.w4_3 = toVkey(curve.Fr.mul(curve.Fr.square(w4), w4)); + let w8 = fromVkey(vk.w8); + let acc = curve.Fr.one; + for (let i = 1; i < 8; i++) { + acc = curve.Fr.mul(acc, w8); + vk["w8_" + i] = toVkey(acc); + } + let template = templates[vk.protocol]; + if (logger) logger.info("FFLONK EXPORT SOLIDITY VERIFIER FINISHED"); + const { default: ejs } = await import("ejs"); + return ejs.render(template, vk); + function fromVkey(str) { + const val = unstringifyBigInts$6(str); + return curve.Fr.fromObject(val); + } + function toVkey(val) { + return stringifyBigInts$2(curve.Fr.toObject(val)); + } +} +//#endregion +//#region src/zkey_export_solidityverifier.js async function exportSolidityVerifier(zKeyName, templates, logger) { - - const verificationKey = await zkeyExportVerificationKey(zKeyName, logger); - - if ("fflonk" === verificationKey.protocol) { - return fflonkExportSolidityVerifier(verificationKey, templates, logger); - } - - let template = templates[verificationKey.protocol]; - - const {default: ejs} = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('ejs')); }); - - return ejs.render(template, verificationKey); -} - -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -var zkey = /*#__PURE__*/Object.freeze({ - __proto__: null, - newZKey: newZKey, - exportBellman: phase2exportMPCParams, - importBellman: phase2importMPCParams, - verifyFromR1cs: phase2verifyFromR1cs, - verifyFromInit: phase2verifyFromInit, - contribute: phase2contribute, - beacon: beacon, - exportJson: zkeyExportJson, - bellmanContribute: bellmanContribute, - exportVerificationKey: zkeyExportVerificationKey, - exportSolidityVerifier: exportSolidityVerifier + const verificationKey = await zkeyExportVerificationKey(zKeyName, logger); + if ("fflonk" === verificationKey.protocol) return fflonkExportSolidityVerifier(verificationKey, templates, logger); + let template = templates[verificationKey.protocol]; + const { default: ejs } = await import("ejs"); + return ejs.render(template, verificationKey); +} +//#endregion +//#region src/zkey.js +var zkey_exports = /* @__PURE__ */ __exportAll({ + beacon: () => beacon, + bellmanContribute: () => bellmanContribute, + contribute: () => phase2contribute, + exportBellman: () => phase2exportMPCParams, + exportJson: () => zkeyExportJson, + exportSolidityVerifier: () => exportSolidityVerifier, + exportVerificationKey: () => zkeyExportVerificationKey, + importBellman: () => phase2importMPCParams, + newZKey: () => newZKey, + verifyFromInit: () => phase2verifyFromInit, + verifyFromR1cs: () => phase2verifyFromR1cs }); - -/* - Copyright 2021 0kims association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - - +//#endregion +//#region src/plonk_setup.js async function plonkSetup(r1csName, ptauName, zkeyName, logger) { - - if (globalThis.gc) {globalThis.gc();} - - const {fd: fdPTau, sections: sectionsPTau} = await binFileUtils.readBinFile(ptauName, "ptau", 1, 1<<22, 1<<24); - const {curve, power} = await readPTauHeader(fdPTau, sectionsPTau); - const {fd: fdR1cs, sections: sectionsR1cs} = await binFileUtils.readBinFile(r1csName, "r1cs", 1, 1<<22, 1<<24); - - const r1cs = await r1csfile.readR1csFd(fdR1cs, sectionsR1cs, {loadConstraints: true, loadCustomGates: true}); - - const sG1 = curve.G1.F.n8*2; - const G1 = curve.G1; - const sG2 = curve.G2.F.n8*2; - const Fr = curve.Fr; - const n8r = curve.Fr.n8; - - if (logger) logger.info("Reading r1cs"); - await binFileUtils.readSection(fdR1cs, sectionsR1cs, 2); - - const plonkConstraints = new BigArray(); - const plonkAdditions = new BigArray(); - let plonkNVars = r1cs.nVars; - - const nPublic = r1cs.nOutputs + r1cs.nPubInputs; - - await processConstraints(curve.Fr, r1cs, logger); - - if (globalThis.gc) {globalThis.gc();} - - const fdZKey = await binFileUtils.createBinFile(zkeyName, "zkey", 1, 14, 1<<22, 1<<24); - - - if (r1cs.prime != curve.r) { - if (logger) logger.error("r1cs curve does not match powers of tau ceremony curve"); - return -1; - } - - let cirPower = log2(plonkConstraints.length -1) +1; - if (cirPower < 3) cirPower = 3; // As the t polynomial is n+5 we need at least a power of 4 - const domainSize = 2 ** cirPower; - - if (logger) logger.info("Plonk constraints: " + plonkConstraints.length); - if (cirPower > power) { - if (logger) logger.error(`circuit too big for this power of tau ceremony. ${plonkConstraints.length} > 2**${power}`); - return -1; - } - - if (!sectionsPTau[12]) { - if (logger) logger.error("Powers of tau is not prepared."); - return -1; - } - - - const LPoints = new ffjavascript.BigBuffer(domainSize*sG1); - const o = sectionsPTau[12][0].p + ((2 ** (cirPower)) -1)*sG1; - await fdPTau.readToBuffer(LPoints, 0, domainSize*sG1, o); - - const [k1, k2] = getK1K2(); - - const vk = {}; - - - await writeAdditions(3, "Additions"); - if (globalThis.gc) {globalThis.gc();} - await writeWitnessMap(4, 0, "Amap"); - if (globalThis.gc) {globalThis.gc();} - await writeWitnessMap(5, 1, "Bmap"); - if (globalThis.gc) {globalThis.gc();} - await writeWitnessMap(6, 2, "Cmap"); - if (globalThis.gc) {globalThis.gc();} - await writeQMap(7, 3, "Qm"); - if (globalThis.gc) {globalThis.gc();} - await writeQMap(8, 4, "Ql"); - if (globalThis.gc) {globalThis.gc();} - await writeQMap(9, 5, "Qr"); - if (globalThis.gc) {globalThis.gc();} - await writeQMap(10, 6, "Qo"); - if (globalThis.gc) {globalThis.gc();} - await writeQMap(11, 7, "Qc"); - if (globalThis.gc) {globalThis.gc();} - await writeSigma(12, "sigma"); - if (globalThis.gc) {globalThis.gc();} - await writeLs(13, "lagrange polynomials"); - if (globalThis.gc) {globalThis.gc();} - - // Write PTau points - //////////// - - await binFileUtils.startWriteSection(fdZKey, 14); - const buffOut = new ffjavascript.BigBuffer((domainSize+6)*sG1); - await fdPTau.readToBuffer(buffOut, 0, (domainSize+6)*sG1, sectionsPTau[2][0].p); - await fdZKey.write(buffOut); - await binFileUtils.endWriteSection(fdZKey); - if (globalThis.gc) {globalThis.gc();} - - - await writeHeaders(); - - await fdZKey.close(); - await fdR1cs.close(); - await fdPTau.close(); - - if (logger) logger.info("Setup Finished"); - - return ; - - async function processConstraints(Fr, r1cs, logger) { - - function normalize(linearComb) { - const ss = Object.keys(linearComb); - for (let i = 0; i < ss.length; i++) { - if (linearComb[ss[i]] == 0n) delete linearComb[ss[i]]; - } - } - - function join(linearComb1, k, linearComb2) { - const res = {}; - - for (let s in linearComb1) { - if (typeof res[s] == "undefined") { - res[s] = Fr.mul(k, linearComb1[s]); - } else { - res[s] = Fr.add(res[s], Fr.mul(k, linearComb1[s])); - } - } - - for (let s in linearComb2) { - if (typeof res[s] == "undefined") { - res[s] = linearComb2[s]; - } else { - res[s] = Fr.add(res[s], linearComb2[s]); - } - } - normalize(res); - return res; - } - - function reduceCoefs(linearComb, maxC) { - const res = { - k: Fr.zero, - s: [], - coefs: [] - }; - const cs = []; - - for (let s in linearComb) { - if (s == 0) { - res.k = Fr.add(res.k, linearComb[s]); - } else if (linearComb[s] != 0n) { - cs.push([Number(s), linearComb[s]]); - } - } - while (cs.length > maxC) { - const c1 = cs.shift(); - const c2 = cs.shift(); - - const sl = c1[0]; - const sr = c2[0]; - const so = plonkNVars++; - const qm = Fr.zero; - const ql = Fr.neg(c1[1]); - const qr = Fr.neg(c2[1]); - const qo = Fr.one; - const qc = Fr.zero; - - plonkConstraints.push([sl, sr, so, qm, ql, qr, qo, qc]); - - plonkAdditions.push([sl, sr, c1[1], c2[1]]); - - cs.push([so, Fr.one]); - } - for (let i = 0; i < cs.length; i++) { - res.s[i] = cs[i][0]; - res.coefs[i] = cs[i][1]; - } - while (res.coefs.length < maxC) { - res.s.push(0); - res.coefs.push(Fr.zero); - } - return res; - } - - function addConstraintSum(lc) { - const C = reduceCoefs(lc, 3); - const sl = C.s[0]; - const sr = C.s[1]; - const so = C.s[2]; - const qm = Fr.zero; - const ql = C.coefs[0]; - const qr = C.coefs[1]; - const qo = C.coefs[2]; - const qc = C.k; - plonkConstraints.push([sl, sr, so, qm, ql, qr, qo, qc]); - } - - function addConstraintMul(lcA, lcB, lcC) { - const A = reduceCoefs(lcA, 1); - const B = reduceCoefs(lcB, 1); - const C = reduceCoefs(lcC, 1); - - - const sl = A.s[0]; - const sr = B.s[0]; - const so = C.s[0]; - const qm = Fr.mul(A.coefs[0], B.coefs[0]); - const ql = Fr.mul(A.coefs[0], B.k); - const qr = Fr.mul(A.k, B.coefs[0]); - const qo = Fr.neg(C.coefs[0]); - const qc = Fr.sub(Fr.mul(A.k, B.k), C.k); - plonkConstraints.push([sl, sr, so, qm, ql, qr, qo, qc]); - } - - function getLinearCombinationType(lc) { - let k = Fr.zero; - let n = 0; - const ss = Object.keys(lc); - for (let i = 0; i < ss.length; i++) { - if (lc[ss[i]] == 0n) { - delete lc[ss[i]]; - } else if (ss[i] == 0) { - k = Fr.add(k, lc[ss[i]]); - } else { - n++; - } - } - if (n > 0) return n.toString(); - if (k != Fr.zero) return "k"; - return "0"; - } - - function process(lcA, lcB, lcC) { - const lctA = getLinearCombinationType(lcA); - const lctB = getLinearCombinationType(lcB); - if ((lctA === "0") || (lctB === "0")) { - normalize(lcC); - addConstraintSum(lcC); - } else if (lctA === "k") { - const lcCC = join(lcB, lcA[0], lcC); - addConstraintSum(lcCC); - } else if (lctB === "k") { - const lcCC = join(lcA, lcB[0], lcC); - addConstraintSum(lcCC); - } else { - addConstraintMul(lcA, lcB, lcC); - } - } - - for (let s = 1; s <= nPublic; s++) { - const sl = s; - const sr = 0; - const so = 0; - const qm = Fr.zero; - const ql = Fr.one; - const qr = Fr.zero; - const qo = Fr.zero; - const qc = Fr.zero; - - plonkConstraints.push([sl, sr, so, qm, ql, qr, qo, qc]); - } - - for (let c = 0; c < r1cs.constraints.length; c++) { - if ((logger) && (c % 10000 === 0)) logger.debug(`processing constraints: ${c}/${r1cs.nConstraints}`); - process(...r1cs.constraints[c]); - } - } - - async function writeWitnessMap(sectionNum, posConstraint, name) { - await binFileUtils.startWriteSection(fdZKey, sectionNum); - for (let i=0; i. -*/ - -class Proof { - constructor(curve, logger) { - this.curve = curve; - this.logger = logger; - - this.resetProof(); - } - - resetProof() { - this.polynomials = {}; - this.evaluations = {}; - } - - addPolynomial(key, polynomial) { - if (key in this.polynomials) { - this.logger.warn(`proof: polynomial.${key} already exist in proof`); - } - this.polynomials[key] = polynomial; - } - - getPolynomial(key) { - if (!(key in this.polynomials)) { - this.logger.warn(`proof: polynomial ${key} does not exist in proof`); - } - return this.polynomials[key]; - } - - addEvaluation(key, evaluation) { - if (key in this.evaluations) { - this.logger.warn(`proof: evaluations.${key} already exist in proof`); - } - this.evaluations[key] = evaluation; - } - - getEvaluation(key) { - if (!(key in this.evaluations)) { - this.logger.warn(`proof: evaluation ${key} does not exist in proof`); - } - return this.evaluations[key]; - } - - toObjectProof(splitFields = true) { - let res = splitFields ? {polynomials: {}, evaluations: {}} : {}; - - Object.keys(this.polynomials).forEach(key => { - const value = this.curve.G1.toObject(this.polynomials[key]); - if(splitFields) { - res.polynomials[key] = value; - } else { - res[key] = value; - } - }); - - Object.keys(this.evaluations).forEach(key => { - const value = this.curve.Fr.toObject(this.evaluations[key]); - if(splitFields) { - res.evaluations[key] = value; - } else { - res[key] = value; - } - }); - - return res; - } - - fromObjectProof(objectProof) { - this.resetProof(); - - Object.keys(objectProof.polynomials).forEach(key => { - this.polynomials[key] = this.curve.G1.fromObject(objectProof.polynomials[key]); - }); - - Object.keys(objectProof.evaluations).forEach(key => { - this.evaluations[key] = this.curve.Fr.fromObject(objectProof.evaluations[key]); - }); - } -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -const POLYNOMIAL = 0; -const SCALAR = 1; - -class Keccak256Transcript { - constructor(curve) { - this.G1 = curve.G1; - this.Fr = curve.Fr; - - this.reset(); - } - - reset() { - this.data = []; - } - - addPolCommitment(polynomialCommitment) { - this.data.push({type: POLYNOMIAL, data: polynomialCommitment}); - } - - addScalar(scalar) { - this.data.push({type: SCALAR, data: scalar}); - } - - getChallenge() { - if(0 === this.data.length) { - throw new Error("Keccak256Transcript: No data to generate a transcript"); - } - - let nPolynomials = 0; - let nScalars = 0; - - this.data.forEach(element => POLYNOMIAL === element.type ? nPolynomials++ : nScalars++); - - let buffer = new Uint8Array(nScalars * this.Fr.n8 + nPolynomials * this.G1.F.n8 * 2); - let offset = 0; - - for (let i = 0; i < this.data.length; i++) { - if (POLYNOMIAL === this.data[i].type) { - this.G1.toRprUncompressed(buffer, offset, this.data[i].data); - offset += this.G1.F.n8 * 2; - } else { - this.Fr.toRprBE(buffer, offset, this.data[i].data); - offset += this.Fr.n8; - } - } - - const value = ffjavascript.Scalar.fromRprBE(sha3.keccak_256(buffer)); - return this.Fr.e(value); - } -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -class MulZ { - static getZ1(Fr) { - return [ - Fr.zero, - Fr.add(Fr.e(-1), Fr.w[2]), - Fr.e(-2), - Fr.sub(Fr.e(-1), Fr.w[2]), - ]; - } - - static getZ2(Fr) { - return [ - Fr.zero, - Fr.add(Fr.zero, Fr.mul(Fr.e(-2), Fr.w[2])), - Fr.e(4), - Fr.sub(Fr.zero, Fr.mul(Fr.e(-2), Fr.w[2])), - ]; - } - - static getZ3(Fr) { - return [ - Fr.zero, - Fr.add(Fr.e(2), Fr.mul(Fr.e(2), Fr.w[2])), - Fr.e(-8), - Fr.sub(Fr.e(2), Fr.mul(Fr.e(2), Fr.w[2])), - ]; - - } - - static mul2(a, b, ap, bp, p, Fr) { - const Z1 = this.getZ1(Fr); - let r, rz; - - const a_b = Fr.mul(a, b); - const a_bp = Fr.mul(a, bp); - const ap_b = Fr.mul(ap, b); - const ap_bp = Fr.mul(ap, bp); - - r = a_b; - - let a0 = Fr.add(a_bp, ap_b); - - let a1 = ap_bp; - - rz = a0; - if (p) { - rz = Fr.add(rz, Fr.mul(Z1[p], a1)); - } - - return [r, rz]; - } - - static mul3(a, b, c, ap, bp, cp, p, Fr) { - const Z1 = this.getZ1(Fr); - const Z2 = this.getZ2(Fr); - let r, rz; - - const a_b = Fr.mul(a, b); - const a_bp = Fr.mul(a, bp); - const ap_b = Fr.mul(ap, b); - const ap_bp = Fr.mul(ap, bp); - - r = Fr.mul(a_b, c); - - let a0 = Fr.mul(ap_b, c); - a0 = Fr.add(a0, Fr.mul(a_bp, c)); - a0 = Fr.add(a0, Fr.mul(a_b, cp)); - - let a1 = Fr.mul(ap_bp, c); - a1 = Fr.add(a1, Fr.mul(a_bp, cp)); - a1 = Fr.add(a1, Fr.mul(ap_b, cp)); - - rz = a0; - if (p) { - const a2 = Fr.mul(ap_bp, cp); - rz = Fr.add(rz, Fr.mul(Z1[p], a1)); - rz = Fr.add(rz, Fr.mul(Z2[p], a2)); - } - - return [r, rz]; - } - - static mul4(a, b, c, d, ap, bp, cp, dp, p, Fr) { - const Z1 = this.getZ1(Fr); - const Z2 = this.getZ2(Fr); - const Z3 = this.getZ3(Fr); - - let r, rz; - - const a_b = Fr.mul(a, b); - const a_bp = Fr.mul(a, bp); - const ap_b = Fr.mul(ap, b); - const ap_bp = Fr.mul(ap, bp); - - const c_d = Fr.mul(c, d); - const c_dp = Fr.mul(c, dp); - const cp_d = Fr.mul(cp, d); - const cp_dp = Fr.mul(cp, dp); - - r = Fr.mul(a_b, c_d); - - let a0 = Fr.mul(ap_b, c_d); - a0 = Fr.add(a0, Fr.mul(a_bp, c_d)); - a0 = Fr.add(a0, Fr.mul(a_b, cp_d)); - a0 = Fr.add(a0, Fr.mul(a_b, c_dp)); - - let a1 = Fr.mul(ap_bp, c_d); - a1 = Fr.add(a1, Fr.mul(ap_b, cp_d)); - a1 = Fr.add(a1, Fr.mul(ap_b, c_dp)); - a1 = Fr.add(a1, Fr.mul(a_bp, cp_d)); - a1 = Fr.add(a1, Fr.mul(a_bp, c_dp)); - a1 = Fr.add(a1, Fr.mul(a_b, cp_dp)); - - let a2 = Fr.mul(a_bp, cp_dp); - a2 = Fr.add(a2, Fr.mul(ap_b, cp_dp)); - a2 = Fr.add(a2, Fr.mul(ap_bp, c_dp)); - a2 = Fr.add(a2, Fr.mul(ap_bp, cp_d)); - - let a3 = Fr.mul(ap_bp, cp_dp); - - rz = a0; - if (p) { - rz = Fr.add(rz, Fr.mul(Z1[p], a1)); - rz = Fr.add(rz, Fr.mul(Z2[p], a2)); - rz = Fr.add(rz, Fr.mul(Z3[p], a3)); - } - - return [r, rz]; - } -} - -const ZKEY_PL_ADDITIONS_SECTION = 3; -const ZKEY_PL_A_MAP_SECTION = 4; -const ZKEY_PL_B_MAP_SECTION = 5; -const ZKEY_PL_C_MAP_SECTION = 6; -const ZKEY_PL_QM_SECTION = 7; -const ZKEY_PL_QL_SECTION = 8; -const ZKEY_PL_QR_SECTION = 9; -const ZKEY_PL_QO_SECTION = 10; -const ZKEY_PL_QC_SECTION = 11; -const ZKEY_PL_SIGMA_SECTION = 12; -const ZKEY_PL_LAGRANGE_SECTION = 13; -const ZKEY_PL_PTAU_SECTION = 14; - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -class Polynomial { - constructor(coefficients, curve, logger) { - this.coef = coefficients; - this.curve = curve; - this.Fr = curve.Fr; - this.G1 = curve.G1; - this.logger = logger; - } - - static async fromEvaluations(buffer, curve, logger) { - let coefficients = await curve.Fr.ifft(buffer); - - return new Polynomial(coefficients, curve, logger); - } - - static fromCoefficientsArray(array, curve, logger) { - const Fr = curve.Fr; - let buff = array.length > 2 << 14 ? - new ffjavascript.BigBuffer(array.length * Fr.n8) : new Uint8Array(array.length * Fr.n8); - for (let i = 0; i < array.length; i++) buff.set(array[i], i * Fr.n8); - - return new Polynomial(buff, curve, logger); - } - - static fromPolynomial(polynomial, curve, logger) { - let length = polynomial.length(); - let Fr = curve.Fr; - - let buff = length > 2 << 14 ? - new ffjavascript.BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8); - buff.set(polynomial.coef.slice(), 0); - - return new Polynomial(buff, curve, logger); - } - - isEqual(polynomial) { - const degree = this.degree(); - if (degree !== polynomial.degree()) return false; - - for (let i = 0; i < degree + 1; i++) { - if (!this.Fr.eq(this.getCoef(i), polynomial.getCoef(i))) return false; - } - - return true; - } - - blindCoefficients(blindingFactors) { - blindingFactors = blindingFactors || []; - - const blindedCoefficients = (this.length() + blindingFactors.length) > 2 << 14 ? - new ffjavascript.BigBuffer((this.length() + blindingFactors.length) * this.Fr.n8) : - new Uint8Array((this.length() + blindingFactors.length) * this.Fr.n8); - - blindedCoefficients.set(this.coef, 0); - for (let i = 0; i < blindingFactors.length; i++) { - blindedCoefficients.set( - this.Fr.add( - blindedCoefficients.slice((this.length() + i) * this.Fr.n8, (this.length() + i + 1) * this.Fr.n8), - blindingFactors[i] - ), - (this.length() + i) * this.Fr.n8 - ); - blindedCoefficients.set( - this.Fr.sub( - blindedCoefficients.slice(i * this.Fr.n8, (i + 1) * this.Fr.n8), - blindingFactors[i] - ), - i * this.Fr.n8 - ); - } - this.coef = blindedCoefficients; - } - - getCoef(index) { - const i_n8 = index * this.Fr.n8; - - if (i_n8 + this.Fr.n8 > this.coef.byteLength) return this.Fr.zero; - - return this.coef.slice(i_n8, i_n8 + this.Fr.n8); - } - - setCoef(index, value) { - if (index > (this.length() - 1)) { - throw new Error("Coef index is not available"); - } - - this.coef.set(value, index * this.Fr.n8); - } - - static async to4T(buffer, domainSize, blindingFactors, Fr) { - blindingFactors = blindingFactors || []; - let a = await Fr.ifft(buffer); - - const a4 = (domainSize * 4) > 2 << 14 ? - new ffjavascript.BigBuffer(domainSize * 4 * Fr.n8) : new Uint8Array(domainSize * 4 * Fr.n8); - a4.set(a, 0); - - const A4 = await Fr.fft(a4); - - if (blindingFactors.length === 0) { - return [a, A4]; - } - - const a1 = domainSize + blindingFactors.length > 2 << 14 ? - new ffjavascript.BigBuffer((domainSize + blindingFactors.length) * Fr.n8) : - new Uint8Array((domainSize + blindingFactors.length) * Fr.n8); - - a1.set(a, 0); - for (let i = 0; i < blindingFactors.length; i++) { - a1.set( - Fr.add( - a1.slice((domainSize + i) * Fr.n8, (domainSize + i + 1) * Fr.n8), - blindingFactors[i] - ), - (domainSize + i) * Fr.n8 - ); - a1.set( - Fr.sub( - a1.slice(i * Fr.n8, (i + 1) * Fr.n8), - blindingFactors[i] - ), - i * Fr.n8 - ); - } - - return [a1, A4]; - } - - length() { - let length = this.coef.byteLength / this.Fr.n8; - if (length !== Math.floor(this.coef.byteLength / this.Fr.n8)) { - throw new Error("Polynomial coefficients buffer has incorrect size"); - } - if (0 === length) { - if (this.logger) { - this.logger.warn("Polynomial has length zero"); - } - } - return length; - } - - degree() { - for (let i = this.length() - 1; i > 0; i--) { - const i_n8 = i * this.Fr.n8; - if (!this.Fr.eq(this.Fr.zero, this.coef.slice(i_n8, i_n8 + this.Fr.n8))) { - return i; - } - } - - return 0; - } - - evaluate(point) { - let res = this.Fr.zero; - - for (let i = this.degree() + 1; i > 0; i--) { - let i_n8 = i * this.Fr.n8; - const currentCoefficient = this.coef.slice(i_n8 - this.Fr.n8, i_n8); - res = this.Fr.add(currentCoefficient, this.Fr.mul(res, point)); - } - - return res; - } - - fastEvaluate(point) { - const Fr = this.Fr; - let nThreads = 3; - - let nCoefs = this.degree() + 1; - let coefsThread = parseInt(nCoefs / nThreads); - let residualCoefs = nCoefs - coefsThread * nThreads; - - let res = []; - let xN = []; - - xN[0] = Fr.one; - - for (let i = 0; i < nThreads; i++) { - res[i] = Fr.zero; - - let nCoefs = i === (nThreads - 1) ? coefsThread + residualCoefs : coefsThread; - for (let j = nCoefs; j > 0; j--) { - res[i] = Fr.add(this.getCoef((i * coefsThread) + j - 1), Fr.mul(res[i], point)); - - if (i === 0) xN[0] = Fr.mul(xN[0], point); - } - } - - for (let i = 1; i < nThreads; i++) { - res[0] = Fr.add(res[0], Fr.mul(xN[i - 1], res[i])); - xN[i] = Fr.mul(xN[i - 1], xN[0]); - } - - return res[0]; - } - - add(polynomial, blindingValue) { - let other = false; - - if (polynomial.length() > this.length()) { - other = true; - } - - const thisLength = this.length(); - const polyLength = polynomial.length(); - for (let i = 0; i < Math.max(thisLength, polyLength); i++) { - const i_n8 = i * this.Fr.n8; - - const a = i < thisLength ? this.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; - let b = i < polyLength ? polynomial.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; - - if (blindingValue !== undefined) { - b = this.Fr.mul(b, blindingValue); - } - if (other) { - polynomial.coef.set(this.Fr.add(a, b), i_n8); - } else { - this.coef.set(this.Fr.add(a, b), i_n8); - } - } - if (other) { - delete this.coef; - this.coef = polynomial.coef; - } - } - - sub(polynomial, blindingValue) { - let other = false; - - if (polynomial.length() > this.length()) { - other = true; - } - - const thisLength = this.length(); - const polyLength = polynomial.length(); - for (let i = 0; i < Math.max(thisLength, polyLength); i++) { - const i_n8 = i * this.Fr.n8; - - const a = i < thisLength ? this.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; - let b = i < polyLength ? polynomial.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; - - if (blindingValue !== undefined) { - b = this.Fr.mul(b, blindingValue); - } - if (other) { - polynomial.coef.set(this.Fr.sub(a, b), i_n8); - } else { - this.coef.set(this.Fr.sub(a, b), i_n8); - } - } - if (other) { - delete this.coef; - this.coef = polynomial.coef; - } - } - - mulScalar(value) { - for (let i = 0; i < this.length(); i++) { - const i_n8 = i * this.Fr.n8; - - this.coef.set(this.Fr.mul(this.coef.slice(i_n8, i_n8 + this.Fr.n8), value), i_n8); - } - } - - addScalar(value) { - const currentValue = 0 === this.length() ? this.Fr.zero : this.coef.slice(0, this.Fr.n8); - this.coef.set(this.Fr.add(currentValue, value), 0); - } - - subScalar(value) { - const currentValue = 0 === this.length() ? this.Fr.zero : this.coef.slice(0, this.Fr.n8); - this.coef.set(this.Fr.sub(currentValue, value), 0); - } - - // Multiply current polynomial by the polynomial (X - value) - byXSubValue(value) { - const Fr = this.Fr; - const resize = !Fr.eq(Fr.zero, this.getCoef(this.length() - 1)); - - const length = resize ? this.length() + 1 : this.length(); - const buff = length > 2 << 14 ? new ffjavascript.BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8); - let pol = new Polynomial(buff, this.curve, this.logger); - - // Step 0: Set current coefficients to the new buffer shifted one position - pol.coef.set(this.coef.slice(0, (length - 1) * Fr.n8), 32); - - // Step 1: multiply each coefficient by (-value) - this.mulScalar(Fr.neg(value)); - - // Step 2: Add current polynomial to destination polynomial - pol.add(this); - - // Swap buffers - this.coef = pol.coef; - } - - // Multiply current polynomial by the polynomial (X^n + value) - byXNSubValue(n, value) { - const Fr = this.Fr; - const resize = !(this.length() - n - 1 >= this.degree()); - - const length = resize ? this.length() + n : this.length(); - const buff = length > 2 << 14 ? new ffjavascript.BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8); - let pol = new Polynomial(buff, this.curve, this.logger); - - // Step 0: Set current coefficients to the new buffer shifted one position - pol.coef.set(this.coef.slice(0, (this.degree() + 1) * 32, ), n * 32); - - // Step 1: multiply each coefficient by (- value) - this.mulScalar(value); - - // Step 2: Add current polynomial to destination polynomial - pol.add(this); - - // Swap buffers - this.coef = pol.coef; - } - - // Euclidean division - divBy(polynomial) { - const Fr = this.Fr; - const degreeA = this.degree(); - const degreeB = polynomial.degree(); - - let polR = new Polynomial(this.coef, this.curve, this.logger); - - this.coef = this.length() > 2 << 14 ? - new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); - - for (let i = degreeA - degreeB; i >= 0; i--) { - this.setCoef(i, Fr.div(polR.getCoef(i + degreeB), polynomial.getCoef(degreeB))); - for (let j = 0; j <= degreeB; j++) { - polR.setCoef(i + j, Fr.sub(polR.getCoef(i + j), Fr.mul(this.getCoef(i), polynomial.getCoef(j)))); - } - } - - return polR; - } - - // Division by a Polynomial of the form (x^m - beta) - divByMonic(m, beta) { - const Fr = this.Fr; - - let d = this.degree(); - - let buffer = this.length() > 2 << 14 ? - new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); - let quotient = new Polynomial(buffer, this.curve, this.logger); - - let bArr = []; - - // Add the m leading coefficients of this to quotient - for (let i = 0; i < m; i++) { - quotient.setCoef((d - i) - m, this.getCoef(d - i)); - bArr[i] = this.getCoef(d - i); - } - - let nThreads = m; - for (let k = 0; k < nThreads; k++) { - for (let i = d - 2 * m - k; i >= 0; i = i - nThreads) { - if (i < 0) break; - let idx = k; - bArr[idx] = Fr.add(this.getCoef(i + m), Fr.mul(bArr[idx], beta)); - - quotient.setCoef(i, bArr[idx]); - } - } - - this.coef = quotient.coef; - } - - divByVanishing(n, beta) { - if (this.degree() < n) { - throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); - } - - const Fr = this.Fr; - - let polR = new Polynomial(this.coef, this.curve, this.logger); - - this.coef = this.length() > 2 << 14 ? - new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); - - for (let i = this.length() - 1; i >= n; i--) { - let leadingCoef = polR.getCoef(i); - if (Fr.eq(Fr.zero, leadingCoef)) continue; - - polR.setCoef(i, Fr.zero); - polR.setCoef(i - n, Fr.add(polR.getCoef(i - n), Fr.mul(beta, leadingCoef))); - this.setCoef(i - n, Fr.add(this.getCoef(i - n), leadingCoef)); - } - - return polR; - } - - divByVanishing2(m, beta) { - if (this.degree() < m) { - throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); - } - - const Fr = this.Fr; - - let polR = new Polynomial(this.coef, this.curve, this.logger); - - this.coef = this.length() > 2 << 14 ? - new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); - - let nThreads = 3; - let nTotal = this.length() - m; - let nElementsChunk = Math.floor(nTotal / nThreads); - let nElementsLast = nTotal - (nThreads - 1) * nElementsChunk; - - console.log(nTotal); - console.log(nElementsChunk + " " + nElementsLast); - for (let k = 0; k < nThreads; k++) { - console.log("> Thread " + k); - for (let i = (k === 0 ? nElementsLast : nElementsChunk); i > 0; i--) { - let idxDst = i - 1; - if (k !== 0) idxDst += (k - 1) * nElementsChunk + nElementsLast; - let idxSrc = idxDst + m; - - let leadingCoef = polR.getCoef(idxSrc); - if (Fr.eq(Fr.zero, leadingCoef)) continue; - - polR.setCoef(idxSrc, Fr.zero); - polR.setCoef(idxDst, Fr.add(polR.getCoef(idxDst), Fr.mul(beta, leadingCoef))); - this.setCoef(idxDst, Fr.add(this.getCoef(idxDst), leadingCoef)); - console.log(idxDst + " <-- " + idxSrc); - } - } - - this.print(); - return polR; - } - - fastDivByVanishing(data) { - const Fr = this.Fr; - - for (let i = 0; i < data.length; i++) { - - let m = data[i][0]; - let beta = data[i][1]; - - if (this.degree() < m) { - throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); - } - - let nThreads = 5; - let nElements = this.length() - m; - let nElementsBucket = Math.floor(nElements / nThreads / m); - let nElementsChunk = nElementsBucket * m; - let nElementsLast = nElements - nThreads * nElementsChunk; - - //In C++ implementation this buffer will be allocated only once outside the loop - let polTmp = new Polynomial(this.length() > 2 << 14 ? - new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8), this.curve, this.logger); - - let ptr = this.coef; - this.coef = polTmp.coef; - polTmp.coef = ptr; - - // STEP 1: Setejar els m valors del següent bucket al chunk actual, PARALEL·LITZAR - for (let k = 0; k < nThreads; k++) { - let idx0 = (k + 1) * nElementsChunk + nElementsLast; - for (let i = 0; i < m; i++) { - this.setCoef(idx0 + i - m, polTmp.getCoef(idx0 + i)); - } - - for (let i = 0; i < nElementsChunk - m; i++) { - let offset = idx0 - i - 1; - let val = Fr.add(polTmp.getCoef(offset), Fr.mul(beta, this.getCoef(offset))); - this.setCoef(offset - m, val); - } - } - - //STEP 2: Setejar els valors del elements last NO PARAL·LELITZAR - let idx0 = nElementsLast; - let pending = nElementsLast; - for (let i = 0; i < m && pending; i++) { - this.setCoef(idx0 - i - 1, polTmp.getCoef(idx0 + m - i - 1)); - pending--; - } - - for (let i = 0; i < pending; i++) { - let offset = idx0 - i - 1; - let val = Fr.add(polTmp.getCoef(offset), Fr.mul(beta, this.getCoef(offset))); - this.setCoef(offset - m, val); - } - - //Step 3: calcular acumulats NO PARALEL·LITZAR - - let acc = []; - let betaPow = Fr.one; - for (let i = 0; i < nElementsBucket; i++) { - betaPow = Fr.mul(betaPow, beta); - } - let currentBeta = Fr.one; - - for (let k = nThreads; k > 0; k--) { - let idThread = k - 1; - let idx0 = idThread * nElementsChunk + nElementsLast; - acc[idThread] = []; - - for (let i = 0; i < m; i++) { - acc[idThread][i] = this.getCoef(idx0 + i); - - if (k !== nThreads) { - acc[idThread][i] = Fr.add(acc[idThread][i], Fr.mul(betaPow, acc[idThread + 1][i])); - } - } - currentBeta = Fr.mul(currentBeta, betaPow); - } - - //STEP 4 recalcular PARALEL·LITZAR - for (let k = 0; k < nThreads; k++) { - - let idx0 = k * nElementsChunk + nElementsLast; - let currentBeta = beta; //Quan hopassem a C++ i ho paralelitzem aquesta variable ha de ser privada - let currentM = m - 1; - - let limit = k === 0 ? nElementsLast : nElementsChunk; - for (let i = 0; i < limit; i++) { - let offset = idx0 - i - 1; - let val = Fr.add(this.getCoef(offset), Fr.mul(currentBeta, acc[k][currentM])); - - this.setCoef(offset, val); - - // To avoid modular operations in each loop... - if (currentM === 0) { - currentM = m - 1; - currentBeta = Fr.mul(currentBeta, beta); - } else { - currentM--; - } - } - } - } - } - - - // Divide polynomial by X - value - divByXSubValue(value) { - const coefs = this.length() > 2 << 14 ? - new ffjavascript.BigBuffer(this.length() * this.Fr.n8) : new Uint8Array(this.length() * this.Fr.n8); - - coefs.set(this.Fr.zero, (this.length() - 1) * this.Fr.n8); - coefs.set(this.coef.slice((this.length() - 1) * this.Fr.n8, this.length() * this.Fr.n8), (this.length() - 2) * this.Fr.n8); - for (let i = this.length() - 3; i >= 0; i--) { - let i_n8 = i * this.Fr.n8; - coefs.set( - this.Fr.add( - this.coef.slice(i_n8 + this.Fr.n8, i_n8 + 2 * this.Fr.n8), - this.Fr.mul(value, coefs.slice(i_n8 + this.Fr.n8, i_n8 + 2 * this.Fr.n8)) - ), - i * this.Fr.n8 - ); - } - if (!this.Fr.eq( - this.coef.slice(0, this.Fr.n8), - this.Fr.mul(this.Fr.neg(value), coefs.slice(0, this.Fr.n8)) - )) { - throw new Error("Polynomial does not divide"); - } - - this.coef = coefs; - } - - divZh(domainSize, extensions = 4) { - for (let i = 0; i < domainSize; i++) { - const i_n8 = i * this.Fr.n8; - this.coef.set(this.Fr.neg(this.coef.slice(i_n8, i_n8 + this.Fr.n8)), i_n8); - } - - const upperBound = this.coef.byteLength / this.Fr.n8; - for (let i = domainSize; i < upperBound; i++) { - const i_n8 = i * this.Fr.n8; - - const a = this.Fr.sub( - this.coef.slice((i - domainSize) * this.Fr.n8, (i - domainSize) * this.Fr.n8 + this.Fr.n8), - this.coef.slice(i_n8, i_n8 + this.Fr.n8) - ); - this.coef.set(a, i_n8); - if (i > (domainSize * (extensions-1) - extensions)) { - if (!this.Fr.isZero(a)) { - throw new Error("Polynomial is not divisible"); - } - } - } - - return this; - } - - divByZerofier(n, beta) { - let Fr = this.Fr; - const invBeta = Fr.inv(beta); - const invBetaNeg = Fr.neg(invBeta); - - let isOne = Fr.eq(Fr.one, invBetaNeg); - let isNegOne = Fr.eq(Fr.negone, invBetaNeg); - - if (!isOne) { - for (let i = 0; i < n; i++) { - const i_n8 = i * this.Fr.n8; - let element; - - // If invBetaNeg === -1 we'll save a multiplication changing it by a neg function call - if (isNegOne) { - element = Fr.neg(this.coef.slice(i_n8, i_n8 + this.Fr.n8)); - } else { - element = Fr.mul(invBetaNeg, this.coef.slice(i_n8, i_n8 + this.Fr.n8)); - } - - this.coef.set(element, i_n8); - } - } - - isOne = Fr.eq(Fr.one, invBeta); - isNegOne = Fr.eq(Fr.negone, invBeta); - - for (let i = n; i < this.length(); i++) { - const i_n8 = i * this.Fr.n8; - const i_prev_n8 = (i - n) * this.Fr.n8; - - let element = this.Fr.sub( - this.coef.slice(i_prev_n8, i_prev_n8 + this.Fr.n8), - this.coef.slice(i_n8, i_n8 + this.Fr.n8) - ); - - // If invBeta === 1 we'll not do anything - if(!isOne) { - // If invBeta === -1 we'll save a multiplication changing it by a neg function call - if(isNegOne) { - element = Fr.neg(element); - } else { - element = Fr.mul(invBeta, element); - } - } - - this.coef.set(element, i_n8); - - // Check if polynomial is divisible by checking if n high coefficients are zero - if (i > this.length() - n - 1) { - if (!this.Fr.isZero(element)) { - throw new Error("Polynomial is not divisible"); - } - } - } - - return this; - } - -// function divideByVanishing(f, n, p) { -// // polynomial division f(X) / (X^n - 1) with remainder -// // very cheap, 0 multiplications -// // strategy: -// // start with q(X) = 0, r(X) = f(X) -// // then start changing q, r while preserving the identity: -// // f(X) = q(X) * (X^n - 1) + r(X) -// // in every step, move highest-degree term of r into the product -// // => r eventually has degree < n and we're done -// let q = Array(f.length).fill(0n); -// let r = [...f]; -// for (let i = f.length - 1; i >= n; i--) { -// let leadingCoeff = r[i]; -// if (leadingCoeff === 0n) continue; -// r[i] = 0n; -// r[i - n] = mod(r[i - n] + leadingCoeff, p); -// q[i - n] = mod(q[i - n] + leadingCoeff, p); -// } -// return [q, r]; -// } - - byX() { - const coefs = (this.length() + 1) > 2 << 14 ? - new ffjavascript.BigBuffer(this.coef.byteLength + this.Fr.n8) : new Uint8Array(this.coef.byteLength + this.Fr.n8); - coefs.set(this.Fr.zero, 0); - coefs.set(this.coef, this.Fr.n8); - - this.coef = coefs; - } - -// Compute a new polynomial f(x^n) from f(x) -// f(x) = a_0 + a_1·x + a_2·x^2 + ... + a_j·x^j -// f(x^n) = a_0 + a_1·x^n + a_2·x^2n + ... + a_j·x^jn - static - async expX(polynomial, n, truncate = false) { - const Fr = polynomial.Fr; - - if (n < 1) { - // n == 0 not allowed because it has no sense, but if it's necessary we have to return - // a zero degree polynomial with a constant coefficient equals to the sum of all the original coefficients - throw new Error("Compute a new polynomial to a zero or negative number is not allowed"); - } else if (1 === n) { - return await Polynomial.fromEvaluations(polynomial.coef, curve, polynomial.logger); - } - - // length is the length of non-constant coefficients - // if truncate === true, the highest zero coefficients (if exist) will be removed - const length = truncate ? polynomial.degree() : (polynomial.length() - 1); - const bufferDst = (length * n + 1) > 2 << 14 ? - new ffjavascript.BigBuffer((length * n + 1) * Fr.n8) : new Uint8Array((length * n + 1) * Fr.n8); - - // Copy constant coefficient as is because is not related to x - bufferDst.set(polynomial.getCoef(0), 0); - - for (let i = 1; i <= length; i++) { - const i_sFr = i * Fr.n8; - - const coef = polynomial.getCoef(i); - bufferDst.set(coef, i_sFr * n); - } - - return new Polynomial(bufferDst, polynomial.curve, polynomial.logger); - } - - split(numPols, degPols, blindingFactors) { - if (numPols < 1) { - throw new Error(`Polynomials can't be split in ${numPols} parts`); - } else if (1 === numPols) { - return [this]; - } - - //blinding factors can be void or must have a length of numPols - 1 - if (0 !== blindingFactors.length && blindingFactors.length < numPols - 1) { - throw new Error(`Blinding factors length must be ${numPols - 1}`); - } - - const chunkByteLength = (degPols + 1) * this.Fr.n8; - let res = []; - - // Check polynomial can be split in numChunks parts of chunkSize bytes... - const numRealPols = Math.ceil((this.degree() + 1) * this.Fr.n8 / chunkByteLength); - if (numRealPols < numPols) { - //throw new Error(`Polynomial is short to be split in ${numPols} parts of ${degPols} coefficients each.`); - for (let i = numRealPols; i < numPols; i++) { - res[i] = new Polynomial(new Uint8Array(this.Fr.n8), this.curve, this.logger); - } - } - - numPols = Math.min(numPols, numRealPols); - for (let i = 0; i < numPols; i++) { - const isLast = (numPols - 1) === i; - const byteLength = isLast ? this.coef.byteLength - ((numPols - 1) * chunkByteLength) : chunkByteLength + this.Fr.n8; - - let buff = (byteLength / this.Fr.n8) > 2 << 14 ? new ffjavascript.BigBuffer(byteLength) : new Uint8Array(byteLength); - res[i] = new Polynomial(buff, this.curve, this.logger); - - const fr = i * chunkByteLength; - const to = isLast ? this.coef.byteLength : (i + 1) * chunkByteLength; - res[i].coef.set(this.coef.slice(fr, to), 0); - - // Add a blinding factor as higher degree - if (!isLast) { - res[i].coef.set(blindingFactors[i], chunkByteLength); - } - - // Sub blinding factor to the lowest degree - if (0 !== i) { - const lowestDegree = this.Fr.sub(res[i].coef.slice(0, this.Fr.n8), blindingFactors[i - 1]); - res[i].coef.set(lowestDegree, 0); - } - - if (isLast) { - res[i].truncate(); - } - } - - return res; - - // // compute t_low(X) - // let polTLow = new BigBuffer((chunkSize + 1) * n8r); - // polTLow.set(t.slice(0, zkey.domainSize * n8r), 0); - // // Add blinding scalar b_10 as a new coefficient n - // polTLow.set(ch.b[10], zkey.domainSize * n8r); - // - // // compute t_mid(X) - // let polTMid = new BigBuffer((zkey.domainSize + 1) * n8r); - // polTMid.set(t.slice(zkey.domainSize * n8r, zkey.domainSize * 2 * n8r), 0); - // // Subtract blinding scalar b_10 to the lowest coefficient of t_mid - // const lowestMid = Fr.sub(polTMid.slice(0, n8r), ch.b[10]); - // polTMid.set(lowestMid, 0); - // // Add blinding scalar b_11 as a new coefficient n - // polTMid.set(ch.b[11], zkey.domainSize * n8r); - // - // // compute t_high(X) - // let polTHigh = new BigBuffer((zkey.domainSize + 6) * n8r); - // polTHigh.set(t.slice(zkey.domainSize * 2 * n8r, (zkey.domainSize * 3 + 6) * n8r), 0); - // //Subtract blinding scalar b_11 to the lowest coefficient of t_high - // const lowestHigh = Fr.sub(polTHigh.slice(0, n8r), ch.b[11]); - // polTHigh.set(lowestHigh, 0); - // - // proof.T1 = await expTau(polTLow, "multiexp T1"); - // proof.T2 = await expTau(polTMid, "multiexp T2"); - // proof.T3 = await expTau(polTHigh, "multiexp T3"); - } - -// split2(degPols, blindingFactors) { -// let currentDegree = this.degree(); -// const numFilledPols = Math.ceil((currentDegree + 1) / (degPols + 1)); -// -// //blinding factors can be void or must have a length of numPols - 1 -// if (0 !== blindingFactors.length && blindingFactors.length < numFilledPols - 1) { -// throw new Error(`Blinding factors length must be ${numFilledPols - 1}`); -// } -// -// const chunkByteLength = (degPols + 1) * this.Fr.n8; -// -// // Check polynomial can be split in numChunks parts of chunkSize bytes... -// if (this.coef.byteLength / chunkByteLength <= numFilledPols - 1) { -// throw new Error(`Polynomial is short to be split in ${numFilledPols} parts of ${degPols} coefficients each.`); -// } -// -// let res = []; -// for (let i = 0; i < numFilledPols; i++) { -// const isLast = (numFilledPols - 1) === i; -// const byteLength = isLast ? (currentDegree + 1) * this.Fr.n8 - ((numFilledPols - 1) * chunkByteLength) : chunkByteLength + this.Fr.n8; -// -// res[i] = new Polynomial(new BigBuffer(byteLength), this.Fr, this.logger); -// const fr = i * chunkByteLength; -// const to = isLast ? (currentDegree + 1) * this.Fr.n8 : (i + 1) * chunkByteLength; -// res[i].coef.set(this.coef.slice(fr, to), 0); -// -// // Add a blinding factor as higher degree -// if (!isLast) { -// res[i].coef.set(blindingFactors[i], chunkByteLength); -// } -// -// // Sub blinding factor to the lowest degree -// if (0 !== i) { -// const lowestDegree = this.Fr.sub(res[i].coef.slice(0, this.Fr.n8), blindingFactors[i - 1]); -// res[i].coef.set(lowestDegree, 0); -// } -// } -// -// return res; -// } - -// merge(pols, overlap = true) { -// let length = 0; -// for (let i = 0; i < pols.length; i++) { -// length += pols[i].length(); -// } -// -// if (overlap) { -// length -= pols.length - 1; -// } -// -// let res = new Polynomial(new BigBuffer(length * this.Fr.n8)); -// for (let i = 0; i < pols.length; i++) { -// const byteLength = pols[i].coef.byteLength; -// if (0 === i) { -// res.coef.set(pols[i].coef, 0); -// } else { -// -// } -// } -// -// return res; -// } - - truncate() { - const deg = this.degree(); - if (deg + 1 < this.coef.byteLength / this.Fr.n8) { - const newCoefs = (deg + 1) > 2 << 14 ? - new ffjavascript.BigBuffer((deg + 1) * this.Fr.n8) : new Uint8Array((deg + 1) * this.Fr.n8); - - newCoefs.set(this.coef.slice(0, (deg + 1) * this.Fr.n8), 0); - this.coef = newCoefs; - } - } - - static lagrangePolynomialInterpolation(xArr, yArr, curve) { - const Fr = curve.Fr; - let polynomial = computeLagrangePolynomial(0); - for (let i = 1; i < xArr.length; i++) { - polynomial.add(computeLagrangePolynomial(i)); - } - - return polynomial; - - function computeLagrangePolynomial(i) { - let polynomial; - - for (let j = 0; j < xArr.length; j++) { - if (j === i) continue; - - if (polynomial === undefined) { - let buff = (xArr.length) > 2 << 14 ? - new ffjavascript.BigBuffer((xArr.length) * Fr.n8) : new Uint8Array((xArr.length) * Fr.n8); - polynomial = new Polynomial(buff, curve); - polynomial.setCoef(0, Fr.neg(xArr[j])); - polynomial.setCoef(1, Fr.one); - } else { - polynomial.byXSubValue(xArr[j]); - } - } - - let denominator = polynomial.evaluate(xArr[i]); - denominator = Fr.inv(denominator); - const mulFactor = Fr.mul(yArr[i], denominator); - - polynomial.mulScalar(mulFactor); - - return polynomial; - } - } - - static zerofierPolynomial(xArr, curve) { - const Fr = curve.Fr; - let buff = (xArr.length + 1) > 2 << 14 ? - new ffjavascript.BigBuffer((xArr.length + 1) * Fr.n8) : new Uint8Array((xArr.length + 1) * Fr.n8); - let polynomial = new Polynomial(buff, curve); - - // Build a zerofier polynomial with the following form: - // zerofier(X) = (X-xArr[0])(X-xArr[1])...(X-xArr[n]) - polynomial.setCoef(0, Fr.neg(xArr[0])); - polynomial.setCoef(1, Fr.one); - - for (let i = 1; i < xArr.length; i++) { - polynomial.byXSubValue(xArr[i]); - } - - return polynomial; - } - - print() { - const Fr = this.Fr; - let res = ""; - for (let i = this.degree(); i >= 0; i--) { - const coef = this.getCoef(i); - if (!Fr.eq(Fr.zero, coef)) { - if (Fr.isNegative(coef)) { - res += " - "; - } else if (i !== this.degree()) { - res += " + "; - } - res += Fr.toString(coef); - if (i > 0) { - res += i > 1 ? "x^" + i : "x"; - } - } - } - console.log(res); - } - - async multiExponentiation(PTau, name) { - const n = this.coef.byteLength / this.Fr.n8; - const PTauN = PTau.slice(0, n * this.G1.F.n8 * 2); - const bm = await this.Fr.batchFromMontgomery(this.coef); - let res = await this.G1.multiExpAffine(PTauN, bm, this.logger, name); - res = this.G1.toAffine(res); - return res; - } -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -class Evaluations { - constructor(evaluations, curve, logger) { - this.eval = evaluations; - this.curve = curve; - this.Fr = curve.Fr; - this.logger = logger; - } - - static async fromPolynomial(polynomial, extension, curve, logger) { - const coefficientsN = new ffjavascript.BigBuffer(polynomial.length() * extension * curve.Fr.n8); - coefficientsN.set(polynomial.coef, 0); - - const evaluations = await curve.Fr.fft(coefficientsN); - - return new Evaluations(evaluations, curve, logger); - } - - getEvaluation(index) { - const i_n8 = index * this.Fr.n8; - - if (i_n8 + this.Fr.n8 > this.eval.byteLength) { - throw new Error("Evaluations.getEvaluation() out of bounds"); - } - - return this.eval.slice(i_n8, i_n8 + this.Fr.n8); - } - - length() { - let length = this.eval.byteLength / this.Fr.n8; - if (length !== Math.floor(this.eval.byteLength / this.Fr.n8)) { - throw new Error("Polynomial evaluations buffer has incorrect size"); - } - if (0 === length) { - this.logger.warn("Polynomial has length zero"); - } - return length; - } -} - -/* - Copyright 2021 0kims association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ -const {stringifyBigInts: stringifyBigInts$1} = ffjavascript.utils; - + if (globalThis.gc) globalThis.gc(); + const { fd: fdPTau, sections: sectionsPTau } = await (0, _iden3_binfileutils.readBinFile)(ptauName, "ptau", 1, 1 << 22, 1 << 24); + const { curve, power } = await readPTauHeader(fdPTau, sectionsPTau); + const { fd: fdR1cs, sections: sectionsR1cs } = await (0, _iden3_binfileutils.readBinFile)(r1csName, "r1cs", 1, 1 << 22, 1 << 24); + const r1cs = await (0, r1csfile.readR1csFd)(fdR1cs, sectionsR1cs, { + loadConstraints: true, + loadCustomGates: true + }); + const sG1 = curve.G1.F.n8 * 2; + const G1 = curve.G1; + const sG2 = curve.G2.F.n8 * 2; + const Fr = curve.Fr; + const n8r = curve.Fr.n8; + if (logger) logger.info("Reading r1cs"); + await (0, _iden3_binfileutils.readSection)(fdR1cs, sectionsR1cs, 2); + const plonkConstraints = new BigArray(); + const plonkAdditions = new BigArray(); + let plonkNVars = r1cs.nVars; + const nPublic = r1cs.nOutputs + r1cs.nPubInputs; + await processConstraints(curve.Fr, r1cs, logger); + if (globalThis.gc) globalThis.gc(); + const fdZKey = await (0, _iden3_binfileutils.createBinFile)(zkeyName, "zkey", 1, 14, 1 << 22, 1 << 24); + if (r1cs.prime != curve.r) { + if (logger) logger.error("r1cs curve does not match powers of tau ceremony curve"); + return -1; + } + let cirPower = log2(plonkConstraints.length - 1) + 1; + if (cirPower < 3) cirPower = 3; + const domainSize = 2 ** cirPower; + if (logger) logger.info("Plonk constraints: " + plonkConstraints.length); + if (cirPower > power) { + if (logger) logger.error(`circuit too big for this power of tau ceremony. ${plonkConstraints.length} > 2**${power}`); + return -1; + } + if (!sectionsPTau[12]) { + if (logger) logger.error("Powers of tau is not prepared."); + return -1; + } + const LPoints = new ffjavascript.BigBuffer(domainSize * sG1); + const o = sectionsPTau[12][0].p + (2 ** cirPower - 1) * sG1; + await fdPTau.readToBuffer(LPoints, 0, domainSize * sG1, o); + const [k1, k2] = getK1K2(); + const vk = {}; + await writeAdditions(3, "Additions"); + if (globalThis.gc) globalThis.gc(); + await writeWitnessMap(4, 0, "Amap"); + if (globalThis.gc) globalThis.gc(); + await writeWitnessMap(5, 1, "Bmap"); + if (globalThis.gc) globalThis.gc(); + await writeWitnessMap(6, 2, "Cmap"); + if (globalThis.gc) globalThis.gc(); + await writeQMap(7, 3, "Qm"); + if (globalThis.gc) globalThis.gc(); + await writeQMap(8, 4, "Ql"); + if (globalThis.gc) globalThis.gc(); + await writeQMap(9, 5, "Qr"); + if (globalThis.gc) globalThis.gc(); + await writeQMap(10, 6, "Qo"); + if (globalThis.gc) globalThis.gc(); + await writeQMap(11, 7, "Qc"); + if (globalThis.gc) globalThis.gc(); + await writeSigma(12, "sigma"); + if (globalThis.gc) globalThis.gc(); + await writeLs(13, "lagrange polynomials"); + if (globalThis.gc) globalThis.gc(); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 14); + const buffOut = new ffjavascript.BigBuffer((domainSize + 6) * sG1); + await fdPTau.readToBuffer(buffOut, 0, (domainSize + 6) * sG1, sectionsPTau[2][0].p); + await fdZKey.write(buffOut); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + if (globalThis.gc) globalThis.gc(); + await writeHeaders(); + await fdZKey.close(); + await fdR1cs.close(); + await fdPTau.close(); + if (logger) logger.info("Setup Finished"); + return; + async function processConstraints(Fr, r1cs, logger) { + function normalize(linearComb) { + const ss = Object.keys(linearComb); + for (let i = 0; i < ss.length; i++) if (linearComb[ss[i]] == 0n) delete linearComb[ss[i]]; + } + function join(linearComb1, k, linearComb2) { + const res = {}; + for (let s in linearComb1) if (typeof res[s] == "undefined") res[s] = Fr.mul(k, linearComb1[s]); + else res[s] = Fr.add(res[s], Fr.mul(k, linearComb1[s])); + for (let s in linearComb2) if (typeof res[s] == "undefined") res[s] = linearComb2[s]; + else res[s] = Fr.add(res[s], linearComb2[s]); + normalize(res); + return res; + } + function reduceCoefs(linearComb, maxC) { + const res = { + k: Fr.zero, + s: [], + coefs: [] + }; + const cs = []; + for (let s in linearComb) if (s == 0) res.k = Fr.add(res.k, linearComb[s]); + else if (linearComb[s] != 0n) cs.push([Number(s), linearComb[s]]); + while (cs.length > maxC) { + const c1 = cs.shift(); + const c2 = cs.shift(); + const sl = c1[0]; + const sr = c2[0]; + const so = plonkNVars++; + const qm = Fr.zero; + const ql = Fr.neg(c1[1]); + const qr = Fr.neg(c2[1]); + const qo = Fr.one; + const qc = Fr.zero; + plonkConstraints.push([ + sl, + sr, + so, + qm, + ql, + qr, + qo, + qc + ]); + plonkAdditions.push([ + sl, + sr, + c1[1], + c2[1] + ]); + cs.push([so, Fr.one]); + } + for (let i = 0; i < cs.length; i++) { + res.s[i] = cs[i][0]; + res.coefs[i] = cs[i][1]; + } + while (res.coefs.length < maxC) { + res.s.push(0); + res.coefs.push(Fr.zero); + } + return res; + } + function addConstraintSum(lc) { + const C = reduceCoefs(lc, 3); + const sl = C.s[0]; + const sr = C.s[1]; + const so = C.s[2]; + const qm = Fr.zero; + const ql = C.coefs[0]; + const qr = C.coefs[1]; + const qo = C.coefs[2]; + const qc = C.k; + plonkConstraints.push([ + sl, + sr, + so, + qm, + ql, + qr, + qo, + qc + ]); + } + function addConstraintMul(lcA, lcB, lcC) { + const A = reduceCoefs(lcA, 1); + const B = reduceCoefs(lcB, 1); + const C = reduceCoefs(lcC, 1); + const sl = A.s[0]; + const sr = B.s[0]; + const so = C.s[0]; + const qm = Fr.mul(A.coefs[0], B.coefs[0]); + const ql = Fr.mul(A.coefs[0], B.k); + const qr = Fr.mul(A.k, B.coefs[0]); + const qo = Fr.neg(C.coefs[0]); + const qc = Fr.sub(Fr.mul(A.k, B.k), C.k); + plonkConstraints.push([ + sl, + sr, + so, + qm, + ql, + qr, + qo, + qc + ]); + } + function getLinearCombinationType(lc) { + let k = Fr.zero; + let n = 0; + const ss = Object.keys(lc); + for (let i = 0; i < ss.length; i++) if (lc[ss[i]] == 0n) delete lc[ss[i]]; + else if (ss[i] == 0) k = Fr.add(k, lc[ss[i]]); + else n++; + if (n > 0) return n.toString(); + if (k != Fr.zero) return "k"; + return "0"; + } + function process(lcA, lcB, lcC) { + const lctA = getLinearCombinationType(lcA); + const lctB = getLinearCombinationType(lcB); + if (lctA === "0" || lctB === "0") { + normalize(lcC); + addConstraintSum(lcC); + } else if (lctA === "k") addConstraintSum(join(lcB, lcA[0], lcC)); + else if (lctB === "k") addConstraintSum(join(lcA, lcB[0], lcC)); + else addConstraintMul(lcA, lcB, lcC); + } + for (let s = 1; s <= nPublic; s++) { + const sl = s; + const sr = 0; + const so = 0; + const qm = Fr.zero; + const ql = Fr.one; + const qr = Fr.zero; + const qo = Fr.zero; + const qc = Fr.zero; + plonkConstraints.push([ + sl, + sr, + so, + qm, + ql, + qr, + qo, + qc + ]); + } + for (let c = 0; c < r1cs.constraints.length; c++) { + if (logger && c % 1e4 === 0) logger.debug(`processing constraints: ${c}/${r1cs.nConstraints}`); + process(...r1cs.constraints[c]); + } + } + async function writeWitnessMap(sectionNum, posConstraint, name) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); + for (let i = 0; i < plonkConstraints.length; i++) { + await fdZKey.writeULE32(plonkConstraints[i][posConstraint]); + if (logger && i % 1e6 == 0) logger.debug(`writing ${name}: ${i}/${plonkConstraints.length}`); + } + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeQMap(sectionNum, posConstraint, name) { + let Q = new ffjavascript.BigBuffer(domainSize * n8r); + for (let i = 0; i < plonkConstraints.length; i++) { + Q.set(plonkConstraints[i][posConstraint], i * n8r); + if (logger && i % 1e6 == 0) logger.debug(`writing ${name}: ${i}/${plonkConstraints.length}`); + } + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); + await writeP4(Q); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + Q = await Fr.batchFromMontgomery(Q); + vk[name] = await curve.G1.multiExpAffine(LPoints, Q, logger, "multiexp " + name); + } + async function writeP4(buff) { + const q = await Fr.ifft(buff); + const q4 = new ffjavascript.BigBuffer(domainSize * n8r * 4); + q4.set(q, 0); + const Q4 = await Fr.fft(q4); + await fdZKey.write(q); + await fdZKey.write(Q4); + } + async function writeAdditions(sectionNum, name) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); + const buffOut = new Uint8Array(8 + 2 * n8r); + const buffOutV = new DataView(buffOut.buffer); + for (let i = 0; i < plonkAdditions.length; i++) { + const addition = plonkAdditions[i]; + let o = 0; + buffOutV.setUint32(o, addition[0], true); + o += 4; + buffOutV.setUint32(o, addition[1], true); + o += 4; + buffOut.set(addition[2], o); + o += n8r; + buffOut.set(addition[3], o); + await fdZKey.write(buffOut); + if (logger && i % 1e6 == 0) logger.debug(`writing ${name}: ${i}/${plonkAdditions.length}`); + } + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeSigma(sectionNum, name) { + const sigma = new ffjavascript.BigBuffer(n8r * domainSize * 3); + const lastAparence = new BigArray(plonkNVars); + const firstPos = new BigArray(plonkNVars); + let w = Fr.one; + for (let i = 0; i < domainSize; i++) { + if (i < plonkConstraints.length) { + buildSigma(plonkConstraints[i][0], i); + buildSigma(plonkConstraints[i][1], domainSize + i); + buildSigma(plonkConstraints[i][2], domainSize * 2 + i); + } else { + buildSigma(0, i); + buildSigma(0, domainSize + i); + buildSigma(0, domainSize * 2 + i); + } + w = Fr.mul(w, Fr.w[cirPower]); + if (logger && i % 1e6 == 0) logger.debug(`writing ${name} phase1: ${i}/${plonkConstraints.length}`); + } + for (let s = 0; s < plonkNVars; s++) { + if (typeof firstPos[s] !== "undefined") sigma.set(lastAparence[s], firstPos[s] * n8r); + else console.log("Variable not used"); + if (logger && s % 1e6 == 0) logger.debug(`writing ${name} phase2: ${s}/${plonkNVars}`); + } + if (globalThis.gc) globalThis.gc(); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); + let S1 = sigma.slice(0, domainSize * n8r); + await writeP4(S1); + if (globalThis.gc) globalThis.gc(); + let S2 = sigma.slice(domainSize * n8r, domainSize * n8r * 2); + await writeP4(S2); + if (globalThis.gc) globalThis.gc(); + let S3 = sigma.slice(domainSize * n8r * 2, domainSize * n8r * 3); + await writeP4(S3); + if (globalThis.gc) globalThis.gc(); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + S1 = await Fr.batchFromMontgomery(S1); + S2 = await Fr.batchFromMontgomery(S2); + S3 = await Fr.batchFromMontgomery(S3); + vk.S1 = await curve.G1.multiExpAffine(LPoints, S1, logger, "multiexp S1"); + if (globalThis.gc) globalThis.gc(); + vk.S2 = await curve.G1.multiExpAffine(LPoints, S2, logger, "multiexp S2"); + if (globalThis.gc) globalThis.gc(); + vk.S3 = await curve.G1.multiExpAffine(LPoints, S3, logger, "multiexp S3"); + if (globalThis.gc) globalThis.gc(); + function buildSigma(s, p) { + if (typeof lastAparence[s] === "undefined") firstPos[s] = p; + else sigma.set(lastAparence[s], p * n8r); + let v; + if (p < domainSize) v = w; + else if (p < 2 * domainSize) v = Fr.mul(w, k1); + else v = Fr.mul(w, k2); + lastAparence[s] = v; + } + } + async function writeLs(sectionNum, name) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); + const l = Math.max(nPublic, 1); + for (let i = 0; i < l; i++) { + let buff = new ffjavascript.BigBuffer(domainSize * n8r); + buff.set(Fr.one, i * n8r); + await writeP4(buff); + if (logger) logger.debug(`writing ${name} ${i}/${l}`); + } + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeHeaders() { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 1); + await fdZKey.writeULE32(2); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 2); + const primeQ = curve.q; + const n8q = (Math.floor((ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) + 1) * 8; + const primeR = curve.r; + const n8r = (Math.floor((ffjavascript.Scalar.bitLength(primeR) - 1) / 64) + 1) * 8; + await fdZKey.writeULE32(n8q); + await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeQ, n8q); + await fdZKey.writeULE32(n8r); + await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeR, n8r); + await fdZKey.writeULE32(plonkNVars); + await fdZKey.writeULE32(nPublic); + await fdZKey.writeULE32(domainSize); + await fdZKey.writeULE32(plonkAdditions.length); + await fdZKey.writeULE32(plonkConstraints.length); + await fdZKey.write(k1); + await fdZKey.write(k2); + await fdZKey.write(G1.toAffine(vk.Qm)); + await fdZKey.write(G1.toAffine(vk.Ql)); + await fdZKey.write(G1.toAffine(vk.Qr)); + await fdZKey.write(G1.toAffine(vk.Qo)); + await fdZKey.write(G1.toAffine(vk.Qc)); + await fdZKey.write(G1.toAffine(vk.S1)); + await fdZKey.write(G1.toAffine(vk.S2)); + await fdZKey.write(G1.toAffine(vk.S3)); + let bX_2; + bX_2 = await fdPTau.read(sG2, sectionsPTau[3][0].p + sG2); + await fdZKey.write(bX_2); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + function getK1K2() { + let k1 = Fr.two; + while (isIncluded(k1, [], cirPower)) Fr.add(k1, Fr.one); + let k2 = Fr.add(k1, Fr.one); + while (isIncluded(k2, [k1], cirPower)) Fr.add(k2, Fr.one); + return [k1, k2]; + function isIncluded(k, kArr, pow) { + const domainSize = 2 ** pow; + let w = Fr.one; + for (let i = 0; i < domainSize; i++) { + if (Fr.eq(k, w)) return true; + for (let j = 0; j < kArr.length; j++) if (Fr.eq(k, Fr.mul(kArr[j], w))) return true; + w = Fr.mul(w, Fr.w[pow]); + } + return false; + } + } +} +//#endregion +//#region src/proof.js +var Proof = class { + constructor(curve, logger) { + this.curve = curve; + this.logger = logger; + this.resetProof(); + } + resetProof() { + this.polynomials = {}; + this.evaluations = {}; + } + addPolynomial(key, polynomial) { + if (key in this.polynomials) this.logger.warn(`proof: polynomial.${key} already exist in proof`); + this.polynomials[key] = polynomial; + } + getPolynomial(key) { + if (!(key in this.polynomials)) this.logger.warn(`proof: polynomial ${key} does not exist in proof`); + return this.polynomials[key]; + } + addEvaluation(key, evaluation) { + if (key in this.evaluations) this.logger.warn(`proof: evaluations.${key} already exist in proof`); + this.evaluations[key] = evaluation; + } + getEvaluation(key) { + if (!(key in this.evaluations)) this.logger.warn(`proof: evaluation ${key} does not exist in proof`); + return this.evaluations[key]; + } + toObjectProof(splitFields = true) { + let res = splitFields ? { + polynomials: {}, + evaluations: {} + } : {}; + Object.keys(this.polynomials).forEach((key) => { + const value = this.curve.G1.toObject(this.polynomials[key]); + if (splitFields) res.polynomials[key] = value; + else res[key] = value; + }); + Object.keys(this.evaluations).forEach((key) => { + const value = this.curve.Fr.toObject(this.evaluations[key]); + if (splitFields) res.evaluations[key] = value; + else res[key] = value; + }); + return res; + } + fromObjectProof(objectProof) { + this.resetProof(); + Object.keys(objectProof.polynomials).forEach((key) => { + this.polynomials[key] = this.curve.G1.fromObject(objectProof.polynomials[key]); + }); + Object.keys(objectProof.evaluations).forEach((key) => { + this.evaluations[key] = this.curve.Fr.fromObject(objectProof.evaluations[key]); + }); + } +}; +//#endregion +//#region src/Keccak256Transcript.js +var POLYNOMIAL = 0; +var SCALAR = 1; +var Keccak256Transcript = class { + constructor(curve) { + this.G1 = curve.G1; + this.Fr = curve.Fr; + this.reset(); + } + reset() { + this.data = []; + } + addPolCommitment(polynomialCommitment) { + this.data.push({ + type: POLYNOMIAL, + data: polynomialCommitment + }); + } + addScalar(scalar) { + this.data.push({ + type: SCALAR, + data: scalar + }); + } + getChallenge() { + if (0 === this.data.length) throw new Error("Keccak256Transcript: No data to generate a transcript"); + let nPolynomials = 0; + let nScalars = 0; + this.data.forEach((element) => POLYNOMIAL === element.type ? nPolynomials++ : nScalars++); + let buffer = new Uint8Array(nScalars * this.Fr.n8 + nPolynomials * this.G1.F.n8 * 2); + let offset = 0; + for (let i = 0; i < this.data.length; i++) if (POLYNOMIAL === this.data[i].type) { + this.G1.toRprUncompressed(buffer, offset, this.data[i].data); + offset += this.G1.F.n8 * 2; + } else { + this.Fr.toRprBE(buffer, offset, this.data[i].data); + offset += this.Fr.n8; + } + const value = ffjavascript.Scalar.fromRprBE((0, _noble_hashes_sha3_js.keccak_256)(buffer)); + return this.Fr.e(value); + } +}; +//#endregion +//#region src/mul_z.js +var MulZ = class { + static getZ1(Fr) { + return [ + Fr.zero, + Fr.add(Fr.e(-1), Fr.w[2]), + Fr.e(-2), + Fr.sub(Fr.e(-1), Fr.w[2]) + ]; + } + static getZ2(Fr) { + return [ + Fr.zero, + Fr.add(Fr.zero, Fr.mul(Fr.e(-2), Fr.w[2])), + Fr.e(4), + Fr.sub(Fr.zero, Fr.mul(Fr.e(-2), Fr.w[2])) + ]; + } + static getZ3(Fr) { + return [ + Fr.zero, + Fr.add(Fr.e(2), Fr.mul(Fr.e(2), Fr.w[2])), + Fr.e(-8), + Fr.sub(Fr.e(2), Fr.mul(Fr.e(2), Fr.w[2])) + ]; + } + static mul2(a, b, ap, bp, p, Fr) { + const Z1 = this.getZ1(Fr); + let r, rz; + const a_b = Fr.mul(a, b); + const a_bp = Fr.mul(a, bp); + const ap_b = Fr.mul(ap, b); + const ap_bp = Fr.mul(ap, bp); + r = a_b; + let a0 = Fr.add(a_bp, ap_b); + let a1 = ap_bp; + rz = a0; + if (p) rz = Fr.add(rz, Fr.mul(Z1[p], a1)); + return [r, rz]; + } + static mul3(a, b, c, ap, bp, cp, p, Fr) { + const Z1 = this.getZ1(Fr); + const Z2 = this.getZ2(Fr); + let r, rz; + const a_b = Fr.mul(a, b); + const a_bp = Fr.mul(a, bp); + const ap_b = Fr.mul(ap, b); + const ap_bp = Fr.mul(ap, bp); + r = Fr.mul(a_b, c); + let a0 = Fr.mul(ap_b, c); + a0 = Fr.add(a0, Fr.mul(a_bp, c)); + a0 = Fr.add(a0, Fr.mul(a_b, cp)); + let a1 = Fr.mul(ap_bp, c); + a1 = Fr.add(a1, Fr.mul(a_bp, cp)); + a1 = Fr.add(a1, Fr.mul(ap_b, cp)); + rz = a0; + if (p) { + const a2 = Fr.mul(ap_bp, cp); + rz = Fr.add(rz, Fr.mul(Z1[p], a1)); + rz = Fr.add(rz, Fr.mul(Z2[p], a2)); + } + return [r, rz]; + } + static mul4(a, b, c, d, ap, bp, cp, dp, p, Fr) { + const Z1 = this.getZ1(Fr); + const Z2 = this.getZ2(Fr); + const Z3 = this.getZ3(Fr); + let r, rz; + const a_b = Fr.mul(a, b); + const a_bp = Fr.mul(a, bp); + const ap_b = Fr.mul(ap, b); + const ap_bp = Fr.mul(ap, bp); + const c_d = Fr.mul(c, d); + const c_dp = Fr.mul(c, dp); + const cp_d = Fr.mul(cp, d); + const cp_dp = Fr.mul(cp, dp); + r = Fr.mul(a_b, c_d); + let a0 = Fr.mul(ap_b, c_d); + a0 = Fr.add(a0, Fr.mul(a_bp, c_d)); + a0 = Fr.add(a0, Fr.mul(a_b, cp_d)); + a0 = Fr.add(a0, Fr.mul(a_b, c_dp)); + let a1 = Fr.mul(ap_bp, c_d); + a1 = Fr.add(a1, Fr.mul(ap_b, cp_d)); + a1 = Fr.add(a1, Fr.mul(ap_b, c_dp)); + a1 = Fr.add(a1, Fr.mul(a_bp, cp_d)); + a1 = Fr.add(a1, Fr.mul(a_bp, c_dp)); + a1 = Fr.add(a1, Fr.mul(a_b, cp_dp)); + let a2 = Fr.mul(a_bp, cp_dp); + a2 = Fr.add(a2, Fr.mul(ap_b, cp_dp)); + a2 = Fr.add(a2, Fr.mul(ap_bp, c_dp)); + a2 = Fr.add(a2, Fr.mul(ap_bp, cp_d)); + let a3 = Fr.mul(ap_bp, cp_dp); + rz = a0; + if (p) { + rz = Fr.add(rz, Fr.mul(Z1[p], a1)); + rz = Fr.add(rz, Fr.mul(Z2[p], a2)); + rz = Fr.add(rz, Fr.mul(Z3[p], a3)); + } + return [r, rz]; + } +}; +//#endregion +//#region src/polynomial/polynomial.js +var Polynomial = class Polynomial { + constructor(coefficients, curve, logger) { + this.coef = coefficients; + this.curve = curve; + this.Fr = curve.Fr; + this.G1 = curve.G1; + this.logger = logger; + } + static async fromEvaluations(buffer, curve, logger) { + return new Polynomial(await curve.Fr.ifft(buffer), curve, logger); + } + static fromCoefficientsArray(array, curve, logger) { + const Fr = curve.Fr; + let buff = array.length > 32768 ? new ffjavascript.BigBuffer(array.length * Fr.n8) : new Uint8Array(array.length * Fr.n8); + for (let i = 0; i < array.length; i++) buff.set(array[i], i * Fr.n8); + return new Polynomial(buff, curve, logger); + } + static fromPolynomial(polynomial, curve, logger) { + let length = polynomial.length(); + let Fr = curve.Fr; + let buff = length > 32768 ? new ffjavascript.BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8); + buff.set(polynomial.coef.slice(), 0); + return new Polynomial(buff, curve, logger); + } + isEqual(polynomial) { + const degree = this.degree(); + if (degree !== polynomial.degree()) return false; + for (let i = 0; i < degree + 1; i++) if (!this.Fr.eq(this.getCoef(i), polynomial.getCoef(i))) return false; + return true; + } + blindCoefficients(blindingFactors) { + blindingFactors = blindingFactors || []; + const blindedCoefficients = this.length() + blindingFactors.length > 32768 ? new ffjavascript.BigBuffer((this.length() + blindingFactors.length) * this.Fr.n8) : new Uint8Array((this.length() + blindingFactors.length) * this.Fr.n8); + blindedCoefficients.set(this.coef, 0); + for (let i = 0; i < blindingFactors.length; i++) { + blindedCoefficients.set(this.Fr.add(blindedCoefficients.slice((this.length() + i) * this.Fr.n8, (this.length() + i + 1) * this.Fr.n8), blindingFactors[i]), (this.length() + i) * this.Fr.n8); + blindedCoefficients.set(this.Fr.sub(blindedCoefficients.slice(i * this.Fr.n8, (i + 1) * this.Fr.n8), blindingFactors[i]), i * this.Fr.n8); + } + this.coef = blindedCoefficients; + } + getCoef(index) { + const i_n8 = index * this.Fr.n8; + if (i_n8 + this.Fr.n8 > this.coef.byteLength) return this.Fr.zero; + return this.coef.slice(i_n8, i_n8 + this.Fr.n8); + } + setCoef(index, value) { + if (index > this.length() - 1) throw new Error("Coef index is not available"); + this.coef.set(value, index * this.Fr.n8); + } + static async to4T(buffer, domainSize, blindingFactors, Fr) { + blindingFactors = blindingFactors || []; + let a = await Fr.ifft(buffer); + const a4 = domainSize * 4 > 32768 ? new ffjavascript.BigBuffer(domainSize * 4 * Fr.n8) : new Uint8Array(domainSize * 4 * Fr.n8); + a4.set(a, 0); + const A4 = await Fr.fft(a4); + if (blindingFactors.length === 0) return [a, A4]; + const a1 = domainSize + blindingFactors.length > 32768 ? new ffjavascript.BigBuffer((domainSize + blindingFactors.length) * Fr.n8) : new Uint8Array((domainSize + blindingFactors.length) * Fr.n8); + a1.set(a, 0); + for (let i = 0; i < blindingFactors.length; i++) { + a1.set(Fr.add(a1.slice((domainSize + i) * Fr.n8, (domainSize + i + 1) * Fr.n8), blindingFactors[i]), (domainSize + i) * Fr.n8); + a1.set(Fr.sub(a1.slice(i * Fr.n8, (i + 1) * Fr.n8), blindingFactors[i]), i * Fr.n8); + } + return [a1, A4]; + } + length() { + let length = this.coef.byteLength / this.Fr.n8; + if (length !== Math.floor(this.coef.byteLength / this.Fr.n8)) throw new Error("Polynomial coefficients buffer has incorrect size"); + if (0 === length) { + if (this.logger) this.logger.warn("Polynomial has length zero"); + } + return length; + } + degree() { + for (let i = this.length() - 1; i > 0; i--) { + const i_n8 = i * this.Fr.n8; + if (!this.Fr.eq(this.Fr.zero, this.coef.slice(i_n8, i_n8 + this.Fr.n8))) return i; + } + return 0; + } + evaluate(point) { + let res = this.Fr.zero; + for (let i = this.degree() + 1; i > 0; i--) { + let i_n8 = i * this.Fr.n8; + const currentCoefficient = this.coef.slice(i_n8 - this.Fr.n8, i_n8); + res = this.Fr.add(currentCoefficient, this.Fr.mul(res, point)); + } + return res; + } + fastEvaluate(point) { + const Fr = this.Fr; + let nThreads = 3; + let nCoefs = this.degree() + 1; + let coefsThread = parseInt(nCoefs / nThreads); + let residualCoefs = nCoefs - coefsThread * nThreads; + let res = []; + let xN = []; + xN[0] = Fr.one; + for (let i = 0; i < nThreads; i++) { + res[i] = Fr.zero; + let nCoefs = i === nThreads - 1 ? coefsThread + residualCoefs : coefsThread; + for (let j = nCoefs; j > 0; j--) { + res[i] = Fr.add(this.getCoef(i * coefsThread + j - 1), Fr.mul(res[i], point)); + if (i === 0) xN[0] = Fr.mul(xN[0], point); + } + } + for (let i = 1; i < nThreads; i++) { + res[0] = Fr.add(res[0], Fr.mul(xN[i - 1], res[i])); + xN[i] = Fr.mul(xN[i - 1], xN[0]); + } + return res[0]; + } + add(polynomial, blindingValue) { + let other = false; + if (polynomial.length() > this.length()) other = true; + const thisLength = this.length(); + const polyLength = polynomial.length(); + for (let i = 0; i < Math.max(thisLength, polyLength); i++) { + const i_n8 = i * this.Fr.n8; + const a = i < thisLength ? this.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; + let b = i < polyLength ? polynomial.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; + if (blindingValue !== void 0) b = this.Fr.mul(b, blindingValue); + if (other) polynomial.coef.set(this.Fr.add(a, b), i_n8); + else this.coef.set(this.Fr.add(a, b), i_n8); + } + if (other) { + delete this.coef; + this.coef = polynomial.coef; + } + } + sub(polynomial, blindingValue) { + let other = false; + if (polynomial.length() > this.length()) other = true; + const thisLength = this.length(); + const polyLength = polynomial.length(); + for (let i = 0; i < Math.max(thisLength, polyLength); i++) { + const i_n8 = i * this.Fr.n8; + const a = i < thisLength ? this.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; + let b = i < polyLength ? polynomial.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; + if (blindingValue !== void 0) b = this.Fr.mul(b, blindingValue); + if (other) polynomial.coef.set(this.Fr.sub(a, b), i_n8); + else this.coef.set(this.Fr.sub(a, b), i_n8); + } + if (other) { + delete this.coef; + this.coef = polynomial.coef; + } + } + mulScalar(value) { + for (let i = 0; i < this.length(); i++) { + const i_n8 = i * this.Fr.n8; + this.coef.set(this.Fr.mul(this.coef.slice(i_n8, i_n8 + this.Fr.n8), value), i_n8); + } + } + addScalar(value) { + const currentValue = 0 === this.length() ? this.Fr.zero : this.coef.slice(0, this.Fr.n8); + this.coef.set(this.Fr.add(currentValue, value), 0); + } + subScalar(value) { + const currentValue = 0 === this.length() ? this.Fr.zero : this.coef.slice(0, this.Fr.n8); + this.coef.set(this.Fr.sub(currentValue, value), 0); + } + byXSubValue(value) { + const Fr = this.Fr; + const length = !Fr.eq(Fr.zero, this.getCoef(this.length() - 1)) ? this.length() + 1 : this.length(); + let pol = new Polynomial(length > 32768 ? new ffjavascript.BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8), this.curve, this.logger); + pol.coef.set(this.coef.slice(0, (length - 1) * Fr.n8), 32); + this.mulScalar(Fr.neg(value)); + pol.add(this); + this.coef = pol.coef; + } + byXNSubValue(n, value) { + const Fr = this.Fr; + const length = !(this.length() - n - 1 >= this.degree()) ? this.length() + n : this.length(); + let pol = new Polynomial(length > 32768 ? new ffjavascript.BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8), this.curve, this.logger); + pol.coef.set(this.coef.slice(0, (this.degree() + 1) * 32), n * 32); + this.mulScalar(value); + pol.add(this); + this.coef = pol.coef; + } + divBy(polynomial) { + const Fr = this.Fr; + const degreeA = this.degree(); + const degreeB = polynomial.degree(); + let polR = new Polynomial(this.coef, this.curve, this.logger); + this.coef = this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); + for (let i = degreeA - degreeB; i >= 0; i--) { + this.setCoef(i, Fr.div(polR.getCoef(i + degreeB), polynomial.getCoef(degreeB))); + for (let j = 0; j <= degreeB; j++) polR.setCoef(i + j, Fr.sub(polR.getCoef(i + j), Fr.mul(this.getCoef(i), polynomial.getCoef(j)))); + } + return polR; + } + divByMonic(m, beta) { + const Fr = this.Fr; + let d = this.degree(); + let quotient = new Polynomial(this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8), this.curve, this.logger); + let bArr = []; + for (let i = 0; i < m; i++) { + quotient.setCoef(d - i - m, this.getCoef(d - i)); + bArr[i] = this.getCoef(d - i); + } + let nThreads = m; + let j = 0; + for (let k = 0; k < nThreads; k++) for (let i = d - 2 * m - k; i >= 0; i = i - nThreads) { + if (i < 0) break; + let idx = k; + bArr[idx] = Fr.add(this.getCoef(i + m), Fr.mul(bArr[idx], beta)); + quotient.setCoef(i, bArr[idx]); + j = (j + 1) % m; + } + this.coef = quotient.coef; + } + divByVanishing(n, beta) { + if (this.degree() < n) throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); + const Fr = this.Fr; + let polR = new Polynomial(this.coef, this.curve, this.logger); + this.coef = this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); + for (let i = this.length() - 1; i >= n; i--) { + let leadingCoef = polR.getCoef(i); + if (Fr.eq(Fr.zero, leadingCoef)) continue; + polR.setCoef(i, Fr.zero); + polR.setCoef(i - n, Fr.add(polR.getCoef(i - n), Fr.mul(beta, leadingCoef))); + this.setCoef(i - n, Fr.add(this.getCoef(i - n), leadingCoef)); + } + return polR; + } + divByVanishing2(m, beta) { + if (this.degree() < m) throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); + const Fr = this.Fr; + let polR = new Polynomial(this.coef, this.curve, this.logger); + this.coef = this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); + let nThreads = 3; + let nTotal = this.length() - m; + let nElementsChunk = Math.floor(nTotal / nThreads); + let nElementsLast = nTotal - (nThreads - 1) * nElementsChunk; + console.log(nTotal); + console.log(nElementsChunk + " " + nElementsLast); + for (let k = 0; k < nThreads; k++) { + console.log("> Thread " + k); + for (let i = k === 0 ? nElementsLast : nElementsChunk; i > 0; i--) { + let idxDst = i - 1; + if (k !== 0) idxDst += (k - 1) * nElementsChunk + nElementsLast; + let idxSrc = idxDst + m; + let leadingCoef = polR.getCoef(idxSrc); + if (Fr.eq(Fr.zero, leadingCoef)) continue; + polR.setCoef(idxSrc, Fr.zero); + polR.setCoef(idxDst, Fr.add(polR.getCoef(idxDst), Fr.mul(beta, leadingCoef))); + this.setCoef(idxDst, Fr.add(this.getCoef(idxDst), leadingCoef)); + console.log(idxDst + " <-- " + idxSrc); + } + } + this.print(); + return polR; + } + fastDivByVanishing(data) { + const Fr = this.Fr; + for (let i = 0; i < data.length; i++) { + let m = data[i][0]; + let beta = data[i][1]; + if (this.degree() < m) throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); + let nThreads = 5; + let nElements = this.length() - m; + let nElementsBucket = Math.floor(nElements / nThreads / m); + let nElementsChunk = nElementsBucket * m; + let nElementsLast = nElements - nThreads * nElementsChunk; + let polTmp = new Polynomial(this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8), this.curve, this.logger); + let ptr = this.coef; + this.coef = polTmp.coef; + polTmp.coef = ptr; + for (let k = 0; k < nThreads; k++) { + let idx0 = (k + 1) * nElementsChunk + nElementsLast; + for (let i = 0; i < m; i++) this.setCoef(idx0 + i - m, polTmp.getCoef(idx0 + i)); + for (let i = 0; i < nElementsChunk - m; i++) { + let offset = idx0 - i - 1; + let val = Fr.add(polTmp.getCoef(offset), Fr.mul(beta, this.getCoef(offset))); + this.setCoef(offset - m, val); + } + } + let idx0 = nElementsLast; + let pending = nElementsLast; + for (let i = 0; i < m && pending; i++) { + this.setCoef(idx0 - i - 1, polTmp.getCoef(idx0 + m - i - 1)); + pending--; + } + for (let i = 0; i < pending; i++) { + let offset = idx0 - i - 1; + let val = Fr.add(polTmp.getCoef(offset), Fr.mul(beta, this.getCoef(offset))); + this.setCoef(offset - m, val); + } + let acc = []; + let betaPow = Fr.one; + for (let i = 0; i < nElementsBucket; i++) betaPow = Fr.mul(betaPow, beta); + let currentBeta = Fr.one; + for (let k = nThreads; k > 0; k--) { + let idThread = k - 1; + let idx0 = idThread * nElementsChunk + nElementsLast; + acc[idThread] = []; + for (let i = 0; i < m; i++) { + acc[idThread][i] = this.getCoef(idx0 + i); + if (k !== nThreads) acc[idThread][i] = Fr.add(acc[idThread][i], Fr.mul(betaPow, acc[idThread + 1][i])); + } + currentBeta = Fr.mul(currentBeta, betaPow); + } + for (let k = 0; k < nThreads; k++) { + let idx0 = k * nElementsChunk + nElementsLast; + let currentBeta = beta; + let currentM = m - 1; + let limit = k === 0 ? nElementsLast : nElementsChunk; + for (let i = 0; i < limit; i++) { + let offset = idx0 - i - 1; + let val = Fr.add(this.getCoef(offset), Fr.mul(currentBeta, acc[k][currentM])); + this.setCoef(offset, val); + if (currentM === 0) { + currentM = m - 1; + currentBeta = Fr.mul(currentBeta, beta); + } else currentM--; + } + } + } + } + divByXSubValue(value) { + const coefs = this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * this.Fr.n8) : new Uint8Array(this.length() * this.Fr.n8); + coefs.set(this.Fr.zero, (this.length() - 1) * this.Fr.n8); + coefs.set(this.coef.slice((this.length() - 1) * this.Fr.n8, this.length() * this.Fr.n8), (this.length() - 2) * this.Fr.n8); + for (let i = this.length() - 3; i >= 0; i--) { + let i_n8 = i * this.Fr.n8; + coefs.set(this.Fr.add(this.coef.slice(i_n8 + this.Fr.n8, i_n8 + 2 * this.Fr.n8), this.Fr.mul(value, coefs.slice(i_n8 + this.Fr.n8, i_n8 + 2 * this.Fr.n8))), i * this.Fr.n8); + } + if (!this.Fr.eq(this.coef.slice(0, this.Fr.n8), this.Fr.mul(this.Fr.neg(value), coefs.slice(0, this.Fr.n8)))) throw new Error("Polynomial does not divide"); + this.coef = coefs; + } + divZh(domainSize, extensions = 4) { + for (let i = 0; i < domainSize; i++) { + const i_n8 = i * this.Fr.n8; + this.coef.set(this.Fr.neg(this.coef.slice(i_n8, i_n8 + this.Fr.n8)), i_n8); + } + const upperBound = this.coef.byteLength / this.Fr.n8; + for (let i = domainSize; i < upperBound; i++) { + const i_n8 = i * this.Fr.n8; + const a = this.Fr.sub(this.coef.slice((i - domainSize) * this.Fr.n8, (i - domainSize) * this.Fr.n8 + this.Fr.n8), this.coef.slice(i_n8, i_n8 + this.Fr.n8)); + this.coef.set(a, i_n8); + if (i > domainSize * (extensions - 1) - extensions) { + if (!this.Fr.isZero(a)) throw new Error("Polynomial is not divisible"); + } + } + return this; + } + divByZerofier(n, beta) { + let Fr = this.Fr; + const invBeta = Fr.inv(beta); + const invBetaNeg = Fr.neg(invBeta); + let isOne = Fr.eq(Fr.one, invBetaNeg); + let isNegOne = Fr.eq(Fr.negone, invBetaNeg); + if (!isOne) for (let i = 0; i < n; i++) { + const i_n8 = i * this.Fr.n8; + let element; + if (isNegOne) element = Fr.neg(this.coef.slice(i_n8, i_n8 + this.Fr.n8)); + else element = Fr.mul(invBetaNeg, this.coef.slice(i_n8, i_n8 + this.Fr.n8)); + this.coef.set(element, i_n8); + } + isOne = Fr.eq(Fr.one, invBeta); + isNegOne = Fr.eq(Fr.negone, invBeta); + for (let i = n; i < this.length(); i++) { + const i_n8 = i * this.Fr.n8; + const i_prev_n8 = (i - n) * this.Fr.n8; + let element = this.Fr.sub(this.coef.slice(i_prev_n8, i_prev_n8 + this.Fr.n8), this.coef.slice(i_n8, i_n8 + this.Fr.n8)); + if (!isOne) if (isNegOne) element = Fr.neg(element); + else element = Fr.mul(invBeta, element); + this.coef.set(element, i_n8); + if (i > this.length() - n - 1) { + if (!this.Fr.isZero(element)) throw new Error("Polynomial is not divisible"); + } + } + return this; + } + byX() { + const coefs = this.length() + 1 > 32768 ? new ffjavascript.BigBuffer(this.coef.byteLength + this.Fr.n8) : new Uint8Array(this.coef.byteLength + this.Fr.n8); + coefs.set(this.Fr.zero, 0); + coefs.set(this.coef, this.Fr.n8); + this.coef = coefs; + } + static async expX(polynomial, n, truncate = false) { + const Fr = polynomial.Fr; + if (n < 1) throw new Error("Compute a new polynomial to a zero or negative number is not allowed"); + else if (1 === n) return await Polynomial.fromEvaluations(polynomial.coef, polynomial.curve, polynomial.logger); + const length = truncate ? polynomial.degree() : polynomial.length() - 1; + const bufferDst = length * n + 1 > 32768 ? new ffjavascript.BigBuffer((length * n + 1) * Fr.n8) : new Uint8Array((length * n + 1) * Fr.n8); + bufferDst.set(polynomial.getCoef(0), 0); + for (let i = 1; i <= length; i++) { + const i_sFr = i * Fr.n8; + const coef = polynomial.getCoef(i); + bufferDst.set(coef, i_sFr * n); + } + return new Polynomial(bufferDst, polynomial.curve, polynomial.logger); + } + split(numPols, degPols, blindingFactors) { + if (numPols < 1) throw new Error(`Polynomials can't be split in ${numPols} parts`); + else if (1 === numPols) return [this]; + if (0 !== blindingFactors.length && blindingFactors.length < numPols - 1) throw new Error(`Blinding factors length must be ${numPols - 1}`); + const chunkByteLength = (degPols + 1) * this.Fr.n8; + let res = []; + const numRealPols = Math.ceil((this.degree() + 1) * this.Fr.n8 / chunkByteLength); + if (numRealPols < numPols) for (let i = numRealPols; i < numPols; i++) res[i] = new Polynomial(new Uint8Array(this.Fr.n8), this.curve, this.logger); + numPols = Math.min(numPols, numRealPols); + for (let i = 0; i < numPols; i++) { + const isLast = numPols - 1 === i; + const byteLength = isLast ? this.coef.byteLength - (numPols - 1) * chunkByteLength : chunkByteLength + this.Fr.n8; + res[i] = new Polynomial(byteLength / this.Fr.n8 > 32768 ? new ffjavascript.BigBuffer(byteLength) : new Uint8Array(byteLength), this.curve, this.logger); + const fr = i * chunkByteLength; + const to = isLast ? this.coef.byteLength : (i + 1) * chunkByteLength; + res[i].coef.set(this.coef.slice(fr, to), 0); + if (!isLast) res[i].coef.set(blindingFactors[i], chunkByteLength); + if (0 !== i) { + const lowestDegree = this.Fr.sub(res[i].coef.slice(0, this.Fr.n8), blindingFactors[i - 1]); + res[i].coef.set(lowestDegree, 0); + } + if (isLast) res[i].truncate(); + } + return res; + } + truncate() { + const deg = this.degree(); + if (deg + 1 < this.coef.byteLength / this.Fr.n8) { + const newCoefs = deg + 1 > 32768 ? new ffjavascript.BigBuffer((deg + 1) * this.Fr.n8) : new Uint8Array((deg + 1) * this.Fr.n8); + newCoefs.set(this.coef.slice(0, (deg + 1) * this.Fr.n8), 0); + this.coef = newCoefs; + } + } + static lagrangePolynomialInterpolation(xArr, yArr, curve) { + const Fr = curve.Fr; + let polynomial = computeLagrangePolynomial(0); + for (let i = 1; i < xArr.length; i++) polynomial.add(computeLagrangePolynomial(i)); + return polynomial; + function computeLagrangePolynomial(i) { + let polynomial; + for (let j = 0; j < xArr.length; j++) { + if (j === i) continue; + if (polynomial === void 0) { + polynomial = new Polynomial(xArr.length > 32768 ? new ffjavascript.BigBuffer(xArr.length * Fr.n8) : new Uint8Array(xArr.length * Fr.n8), curve); + polynomial.setCoef(0, Fr.neg(xArr[j])); + polynomial.setCoef(1, Fr.one); + } else polynomial.byXSubValue(xArr[j]); + } + let denominator = polynomial.evaluate(xArr[i]); + denominator = Fr.inv(denominator); + const mulFactor = Fr.mul(yArr[i], denominator); + polynomial.mulScalar(mulFactor); + return polynomial; + } + } + static zerofierPolynomial(xArr, curve) { + const Fr = curve.Fr; + let polynomial = new Polynomial(xArr.length + 1 > 32768 ? new ffjavascript.BigBuffer((xArr.length + 1) * Fr.n8) : new Uint8Array((xArr.length + 1) * Fr.n8), curve); + polynomial.setCoef(0, Fr.neg(xArr[0])); + polynomial.setCoef(1, Fr.one); + for (let i = 1; i < xArr.length; i++) polynomial.byXSubValue(xArr[i]); + return polynomial; + } + print() { + const Fr = this.Fr; + let res = ""; + for (let i = this.degree(); i >= 0; i--) { + const coef = this.getCoef(i); + if (!Fr.eq(Fr.zero, coef)) { + if (Fr.isNegative(coef)) res += " - "; + else if (i !== this.degree()) res += " + "; + res += Fr.toString(coef); + if (i > 0) res += i > 1 ? "x^" + i : "x"; + } + } + console.log(res); + } + async multiExponentiation(PTau, name) { + const n = this.coef.byteLength / this.Fr.n8; + const PTauN = PTau.slice(0, n * this.G1.F.n8 * 2); + const bm = await this.Fr.batchFromMontgomery(this.coef); + let res = await this.G1.multiExpAffine(PTauN, bm, this.logger, name); + res = this.G1.toAffine(res); + return res; + } +}; +//#endregion +//#region src/polynomial/evaluations.js +var Evaluations = class Evaluations { + constructor(evaluations, curve, logger) { + this.eval = evaluations; + this.curve = curve; + this.Fr = curve.Fr; + this.logger = logger; + } + static async fromPolynomial(polynomial, extension, curve, logger) { + const coefficientsN = new ffjavascript.BigBuffer(polynomial.length() * extension * curve.Fr.n8); + coefficientsN.set(polynomial.coef, 0); + return new Evaluations(await curve.Fr.fft(coefficientsN), curve, logger); + } + getEvaluation(index) { + const i_n8 = index * this.Fr.n8; + if (i_n8 + this.Fr.n8 > this.eval.byteLength) throw new Error("Evaluations.getEvaluation() out of bounds"); + return this.eval.slice(i_n8, i_n8 + this.Fr.n8); + } + length() { + let length = this.eval.byteLength / this.Fr.n8; + if (length !== Math.floor(this.eval.byteLength / this.Fr.n8)) throw new Error("Polynomial evaluations buffer has incorrect size"); + if (0 === length) this.logger.warn("Polynomial has length zero"); + return length; + } +}; +//#endregion +//#region src/plonk_prove.js +var { stringifyBigInts: stringifyBigInts$1 } = ffjavascript.utils; async function plonk16Prove(zkeyFileName, witnessFileName, logger, options) { - const {fd: fdWtns, sections: sectionsWtns} = await binFileUtils__namespace.readBinFile(witnessFileName, "wtns", 2, 1<<25, 1<<23); - - // Read witness file - if (logger) logger.debug("> Reading witness file"); - const wtns = await readHeader(fdWtns, sectionsWtns); - - // Read zkey file - if (logger) logger.debug("> Reading zkey file"); - const {fd: fdZKey, sections: zkeySections} = await binFileUtils__namespace.readBinFile(zkeyFileName, "zkey", 2, 1<<25, 1<<23); - - const zkey = await readHeader$1(fdZKey, zkeySections, undefined, options); - if (zkey.protocol != "plonk") { - throw new Error("zkey file is not plonk"); - } - - if (!ffjavascript.Scalar.eq(zkey.r, wtns.q)) { - throw new Error("Curve of the witness does not match the curve of the proving key"); - } - - if (wtns.nWitness != zkey.nVars -zkey.nAdditions) { - throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}, ${zkey.nAdditions}`); - } - - const curve = zkey.curve; - - const Fr = curve.Fr; - const n8r = curve.Fr.n8; - const sDomain = zkey.domainSize * n8r; - - if (logger) { - logger.debug("----------------------------"); - logger.debug(" PLONK PROVE SETTINGS"); - logger.debug(` Curve: ${curve.name}`); - logger.debug(` Circuit power: ${zkey.power}`); - logger.debug(` Domain size: ${zkey.domainSize}`); - logger.debug(` Vars: ${zkey.nVars}`); - logger.debug(` Public vars: ${zkey.nPublic}`); - logger.debug(` Constraints: ${zkey.nConstraints}`); - logger.debug(` Additions: ${zkey.nAdditions}`); - logger.debug("----------------------------"); - } - - //Read witness data - if (logger) logger.debug("> Reading witness file data"); - const buffWitness = await binFileUtils__namespace.readSection(fdWtns, sectionsWtns, 2); - - // First element in plonk is not used and can be any value. (But always the same). - // We set it to zero to go faster in the exponentiations. - buffWitness.set(Fr.zero, 0); - const buffInternalWitness = new ffjavascript.BigBuffer(n8r*zkey.nAdditions); - - let buffers = {}; - let polynomials = {}; - let evaluations = {}; - - let challenges = {}; - let proof = new Proof(curve, logger); - const transcript = new Keccak256Transcript(curve); - - if (logger) logger.debug(`> Reading Section ${ZKEY_PL_ADDITIONS_SECTION}. Additions`); - await calculateAdditions(); - - if (logger) logger.debug(`> Reading Section ${ZKEY_PL_SIGMA_SECTION}. Sigma1, Sigma2 & Sigma 3`); - if (logger) logger.debug("··· Reading Sigma polynomials "); - polynomials.Sigma1 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.Sigma2 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.Sigma3 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - - await fdZKey.readToBuffer(polynomials.Sigma1.coef, 0, sDomain, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.Sigma2.coef, 0, sDomain, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p + 5 * sDomain); - await fdZKey.readToBuffer(polynomials.Sigma3.coef, 0, sDomain, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p + 10 * sDomain); - - if (logger) logger.debug("··· Reading Sigma evaluations"); - evaluations.Sigma1 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.Sigma2 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.Sigma3 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - - await fdZKey.readToBuffer(evaluations.Sigma1.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.Sigma2.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p + 6 * sDomain); - await fdZKey.readToBuffer(evaluations.Sigma3.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p + 11 * sDomain); - - if (logger) logger.debug(`> Reading Section ${ZKEY_PL_PTAU_SECTION}. Powers of Tau`); - const PTau = await binFileUtils__namespace.readSection(fdZKey, zkeySections, ZKEY_PL_PTAU_SECTION); - - let publicSignals = []; - - for (let i=1; i<= zkey.nPublic; i++) { - const pub = buffWitness.slice(i*Fr.n8, i*Fr.n8+Fr.n8); - publicSignals.push(ffjavascript.Scalar.fromRprLE(pub)); - } - - if (logger) logger.debug(""); - if (logger) logger.debug("> ROUND 1"); - await round1(); - - if (logger) logger.debug("> ROUND 2"); - await round2(); - - if (logger) logger.debug("> ROUND 3"); - await round3(); - - if (logger) logger.debug("> ROUND 4"); - await round4(); - - if (logger) logger.debug("> ROUND 5"); - await round5(); - - /////////////////////// - // Final adjustments // - /////////////////////// - - await fdZKey.close(); - await fdWtns.close(); - - // Prepare proof - let _proof = proof.toObjectProof(false); - _proof.protocol = "plonk"; - _proof.curve = curve.name; - - if (logger) logger.debug("PLONK PROVER FINISHED"); - - return { - proof: stringifyBigInts$1(_proof), - publicSignals: stringifyBigInts$1(publicSignals) - }; - - async function calculateAdditions() { - if (logger) logger.debug("··· Computing additions"); - const additionsBuff = await binFileUtils__namespace.readSection(fdZKey, zkeySections, ZKEY_PL_ADDITIONS_SECTION); - - // sizes: wireId_x = 4 bytes (32 bits), factor_x = field size bits - // Addition form: wireId_a wireId_b factor_a factor_b (size is 4 + 4 + sFr + sFr) - const sSum = 8 + n8r * 2; - - for (let i = 0; i < zkey.nAdditions; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.debug(` addition ${i}/${zkey.nAdditions}`); - - // Read addition values - let offset = i * sSum; - const signalId1 = readUInt32(additionsBuff, offset); - offset += 4; - const signalId2 = readUInt32(additionsBuff, offset); - offset += 4; - const factor1 = additionsBuff.slice(offset, offset + n8r); - offset += n8r; - const factor2 = additionsBuff.slice(offset, offset + n8r); - - // Get witness value - const witness1 = getWitness(signalId1); - const witness2 = getWitness(signalId2); - - //Calculate final result - const result = Fr.add(Fr.mul(factor1, witness1), Fr.mul(factor2, witness2)); - - buffInternalWitness.set(result, n8r * i); - } - } - - function readUInt32(b, o) { - const buff = b.slice(o, o+4); - const buffV = new DataView(buff.buffer, buff.byteOffset, buff.byteLength); - return buffV.getUint32(0, true); - } - - function getWitness(idx) { - if (idx < zkey.nVars-zkey.nAdditions) { - return buffWitness.slice(idx*n8r, idx*n8r+n8r); - } else if (idx < zkey.nVars) { - return buffInternalWitness.slice((idx - (zkey.nVars-zkey.nAdditions))*n8r, (idx-(zkey.nVars-zkey.nAdditions))*n8r + n8r); - } else { - return curve.Fr.zero; - } - } - - async function round1() { - // STEP 1.1 - Generate random blinding scalars (b1, ..., b11) ∈ F - challenges.b = []; - for (let i=1; i<=11; i++) { - challenges.b[i] = curve.Fr.random(); - } - - // STEP 1.2 - Compute wire polynomials a(X), b(X) and c(X) - if (logger) logger.debug("> Computing A, B, C wire polynomials"); - await computeWirePolynomials(); - - // STEP 1.3 - Compute [a]_1, [b]_1, [c]_1 - if (logger) logger.debug("> Computing A, B, C MSM"); - let commitA = await polynomials.A.multiExponentiation(PTau, "A"); - let commitB = await polynomials.B.multiExponentiation(PTau, "B"); - let commitC = await polynomials.C.multiExponentiation(PTau, "C"); - - // First output of the prover is ([A]_1, [B]_1, [C]_1) - proof.addPolynomial("A", commitA); - proof.addPolynomial("B", commitB); - proof.addPolynomial("C", commitC); - - return 0; - } - - async function computeWirePolynomials() { - if (logger) logger.debug("··· Reading data from zkey file"); - - // Build A, B and C evaluations buffer from zkey and witness files - buffers.A = new ffjavascript.BigBuffer(sDomain); - buffers.B = new ffjavascript.BigBuffer(sDomain); - buffers.C = new ffjavascript.BigBuffer(sDomain); - - // Read zkey file to the buffers - const aMapBuff = await binFileUtils__namespace.readSection(fdZKey, zkeySections, ZKEY_PL_A_MAP_SECTION); - const bMapBuff = await binFileUtils__namespace.readSection(fdZKey, zkeySections, ZKEY_PL_B_MAP_SECTION); - const cMapBuff = await binFileUtils__namespace.readSection(fdZKey, zkeySections, ZKEY_PL_C_MAP_SECTION); - - // Compute all witness from signal ids and set them to A,B & C buffers - for (let i = 0; i < zkey.nConstraints; i++) { - const i_sFr = i * n8r; - const offset = i * 4; - - // Compute A value from a signal id - const signalIdA = readUInt32(aMapBuff, offset); - buffers.A.set(getWitness(signalIdA), i_sFr); - - // Compute B value from a signal id - const signalIdB = readUInt32(bMapBuff, offset); - buffers.B.set(getWitness(signalIdB), i_sFr); - - // Compute C value from a signal id - const signalIdC = readUInt32(cMapBuff, offset); - buffers.C.set(getWitness(signalIdC), i_sFr); - } - - buffers.A = await Fr.batchToMontgomery(buffers.A); - buffers.B = await Fr.batchToMontgomery(buffers.B); - buffers.C = await Fr.batchToMontgomery(buffers.C); - - // Compute the coefficients of the wire polynomials a(X), b(X) and c(X) from A,B & C buffers - if (logger) logger.debug("··· Computing A ifft"); - polynomials.A = await Polynomial.fromEvaluations(buffers.A, curve, logger); - if (logger) logger.debug("··· Computing B ifft"); - polynomials.B = await Polynomial.fromEvaluations(buffers.B, curve, logger); - if (logger) logger.debug("··· Computing C ifft"); - polynomials.C = await Polynomial.fromEvaluations(buffers.C, curve, logger); - - // Compute extended evaluations of a(X), b(X) and c(X) polynomials - if (logger) logger.debug("··· Computing A fft"); - evaluations.A = await Evaluations.fromPolynomial(polynomials.A, 4, curve, logger); - if (logger) logger.debug("··· Computing B fft"); - evaluations.B = await Evaluations.fromPolynomial(polynomials.B, 4, curve, logger); - if (logger) logger.debug("··· Computing C fft"); - evaluations.C = await Evaluations.fromPolynomial(polynomials.C, 4, curve, logger); - - // Blind a(X), b(X) and c(X) polynomials coefficients with blinding scalars b - polynomials.A.blindCoefficients([challenges.b[2], challenges.b[1]]); - polynomials.B.blindCoefficients([challenges.b[4], challenges.b[3]]); - polynomials.C.blindCoefficients([challenges.b[6], challenges.b[5]]); - - // Check degrees - if (polynomials.A.degree() >= zkey.domainSize + 2) { - throw new Error("A Polynomial is not well calculated"); - } - if (polynomials.B.degree() >= zkey.domainSize + 2) { - throw new Error("B Polynomial is not well calculated"); - } - if (polynomials.C.degree() >= zkey.domainSize + 2) { - throw new Error("C Polynomial is not well calculated"); - } - } - - async function round2() { - // STEP 2.1 - Compute permutation challenge beta and gamma ∈ F - // Compute permutation challenge beta - if (logger) logger.debug("> Computing challenges beta and gamma"); - transcript.reset(); - - transcript.addPolCommitment(zkey.Qm); - transcript.addPolCommitment(zkey.Ql); - transcript.addPolCommitment(zkey.Qr); - transcript.addPolCommitment(zkey.Qo); - transcript.addPolCommitment(zkey.Qc); - transcript.addPolCommitment(zkey.S1); - transcript.addPolCommitment(zkey.S2); - transcript.addPolCommitment(zkey.S3); - - // Add A to the transcript - for (let i = 0; i < zkey.nPublic; i++) { - transcript.addScalar(buffers.A.slice(i * n8r, i * n8r + n8r)); - } - - // Add A, B, C to the transcript - transcript.addPolCommitment(proof.getPolynomial("A")); - transcript.addPolCommitment(proof.getPolynomial("B")); - transcript.addPolCommitment(proof.getPolynomial("C")); - - challenges.beta = transcript.getChallenge(); - if (logger) logger.debug("··· challenges.beta: " + Fr.toString(challenges.beta, 16)); - - // Compute permutation challenge gamma - transcript.reset(); - transcript.addScalar(challenges.beta); - challenges.gamma = transcript.getChallenge(); - if (logger) logger.debug("··· challenges.gamma: " + Fr.toString(challenges.gamma, 16)); - - // STEP 2.2 - Compute permutation polynomial z(X) - if (logger) logger.debug("> Computing Z polynomial"); - await computeZ(); - - // STEP 2.3 - Compute permutation [z]_1 - if (logger) logger.debug("> Computing Z MSM"); - let commitZ = await polynomials.Z.multiExponentiation(PTau, "Z"); - - // Second output of the prover is ([Z]_1) - proof.addPolynomial("Z", commitZ); - } - - async function computeZ() { - if (logger) logger.debug("··· Computing Z evaluations"); - - let numArr = new ffjavascript.BigBuffer(sDomain); - let denArr = new ffjavascript.BigBuffer(sDomain); - - // Set the first values to 1 - numArr.set(Fr.one, 0); - denArr.set(Fr.one, 0); - - // Set initial omega - let w = Fr.one; - for (let i = 0; i < zkey.domainSize; i++) { - const i_n8r = i * n8r; - - const a = buffers.A.slice(i_n8r, i_n8r + n8r); - const b = buffers.B.slice(i_n8r, i_n8r + n8r); - const c = buffers.C.slice(i_n8r, i_n8r + n8r); - - // Z(X) := numArr / denArr - // numArr := (a + beta·ω + gamma)(b + beta·ω·k1 + gamma)(c + beta·ω·k2 + gamma) - const betaw = Fr.mul(challenges.beta, w); - - let n1 = Fr.add(a, betaw); - n1 = Fr.add(n1, challenges.gamma); - - let n2 = Fr.add(b, Fr.mul(zkey.k1, betaw)); - n2 = Fr.add(n2, challenges.gamma); - - let n3 = Fr.add(c, Fr.mul(zkey.k2, betaw)); - n3 = Fr.add(n3, challenges.gamma); - - let num = Fr.mul(n1, Fr.mul(n2, n3)); - - // denArr := (a + beta·sigma1 + gamma)(b + beta·sigma2 + gamma)(c + beta·sigma3 + gamma) - let d1 = Fr.add(a, Fr.mul(evaluations.Sigma1.getEvaluation(i * 4), challenges.beta)); - d1 = Fr.add(d1, challenges.gamma); - - let d2 = Fr.add(b, Fr.mul(evaluations.Sigma2.getEvaluation(i * 4), challenges.beta)); - d2 = Fr.add(d2, challenges.gamma); - - let d3 = Fr.add(c, Fr.mul(evaluations.Sigma3.getEvaluation(i * 4), challenges.beta)); - d3 = Fr.add(d3, challenges.gamma); - - let den = Fr.mul(d1, Fr.mul(d2, d3)); - - // Multiply current num value with the previous one saved in numArr - num = Fr.mul(numArr.slice(i_n8r, i_n8r + n8r), num); - numArr.set(num, ((i + 1) % zkey.domainSize) * n8r); - - // Multiply current den value with the previous one saved in denArr - den = Fr.mul(denArr.slice(i_n8r, i_n8r + n8r), den); - denArr.set(den, ((i + 1) % zkey.domainSize) * n8r); - - w = Fr.mul(w, Fr.w[zkey.power]); - } - - // Compute the inverse of denArr to compute in the next command the - // division numArr/denArr by multiplying num · 1/denArr - denArr = await Fr.batchInverse(denArr); - - // TODO: Do it in assembly and in parallel - // Multiply numArr · denArr where denArr was inverted in the previous command - for (let i = 0; i < zkey.domainSize; i++) { - const i_sFr = i * n8r; - - const z = Fr.mul(numArr.slice(i_sFr, i_sFr + n8r), denArr.slice(i_sFr, i_sFr + n8r)); - numArr.set(z, i_sFr); - } - - // From now on the values saved on numArr will be Z(X) buffer - buffers.Z = numArr; - - if (!Fr.eq(numArr.slice(0, n8r), Fr.one)) { - throw new Error("Copy constraints does not match"); - } - - // Compute polynomial coefficients z(X) from buffers.Z - if (logger) logger.debug("··· Computing Z ifft"); - polynomials.Z = await Polynomial.fromEvaluations(buffers.Z, curve, logger); - - // Compute extended evaluations of z(X) polynomial - if (logger) logger.debug("··· Computing Z fft"); - evaluations.Z = await Evaluations.fromPolynomial(polynomials.Z, 4, curve, logger); - - // Blind z(X) polynomial coefficients with blinding scalars b - polynomials.Z.blindCoefficients([challenges.b[9], challenges.b[8], challenges.b[7]]); - - // Check degree - if (polynomials.Z.degree() >= zkey.domainSize + 3) { - throw new Error("Z Polynomial is not well calculated"); - } - - delete buffers.Z; - } - - async function round3() { - if (logger) logger.debug("> Computing challenge alpha"); - - // STEP 3.1 - Compute evaluation challenge alpha ∈ F - transcript.reset(); - transcript.addScalar(challenges.beta); - transcript.addScalar(challenges.gamma); - transcript.addPolCommitment(proof.getPolynomial("Z")); - - challenges.alpha = transcript.getChallenge(); - challenges.alpha2 = Fr.square(challenges.alpha); - if (logger) logger.debug("··· challenges.alpha: " + Fr.toString(challenges.alpha, 16)); - - // Compute quotient polynomial T(X) - if (logger) logger.debug("> Computing T polynomial"); - await computeT(); - - // Compute [T1]_1, [T2]_1, [T3]_1 - if (logger) logger.debug("> Computing T MSM"); - let commitT1 = await polynomials.T1.multiExponentiation(PTau, "T1"); - let commitT2 = await polynomials.T2.multiExponentiation(PTau, "T2"); - let commitT3 = await polynomials.T3.multiExponentiation(PTau, "T3"); - - // Third output of the prover is ([T1]_1, [T2]_1, [T3]_1) - proof.addPolynomial("T1", commitT1); - proof.addPolynomial("T2", commitT2); - proof.addPolynomial("T3", commitT3); - } - - async function computeT() { - if (logger) - logger.debug(`··· Reading sections ${ZKEY_PL_QL_SECTION}, ${ZKEY_PL_QR_SECTION}` + - `, ${ZKEY_PL_QM_SECTION}, ${ZKEY_PL_QO_SECTION}, ${ZKEY_PL_QC_SECTION}. Q selectors`); - // Reserve memory for Q's evaluations - evaluations.QL = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QR = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QM = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QO = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QC = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - - // Read Q's evaluations from zkey file - await fdZKey.readToBuffer(evaluations.QL.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_QL_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QR.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_QR_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QM.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_QM_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QO.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_QO_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QC.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_QC_SECTION][0].p + sDomain); - - // Read Lagrange polynomials & evaluations from zkey file - evaluations.Lagrange = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4 * zkey.nPublic), curve, logger); - - for (let i = 0; i < zkey.nPublic; i++) { - await fdZKey.readToBuffer(evaluations.Lagrange.eval, i * sDomain * 4, sDomain * 4, zkeySections[ZKEY_PL_LAGRANGE_SECTION][0].p + i * 5 * sDomain + sDomain); - } - - buffers.T = new ffjavascript.BigBuffer(sDomain * 4); - buffers.Tz = new ffjavascript.BigBuffer(sDomain * 4); - - if (logger) logger.debug("··· Computing T evaluations"); - - let w = Fr.one; - for (let i = 0; i < zkey.domainSize * 4; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) - logger.debug(` T evaluation ${i}/${zkey.domainSize * 4}`); - - const a = evaluations.A.getEvaluation(i); - const b = evaluations.B.getEvaluation(i); - const c = evaluations.C.getEvaluation(i); - const z = evaluations.Z.getEvaluation(i); - const zw = evaluations.Z.getEvaluation((zkey.domainSize * 4 + 4 + i) % (zkey.domainSize * 4)); - - const qm = evaluations.QM.getEvaluation(i); - const ql = evaluations.QL.getEvaluation(i); - const qr = evaluations.QR.getEvaluation(i); - const qo = evaluations.QO.getEvaluation(i); - const qc = evaluations.QC.getEvaluation(i); - const s1 = evaluations.Sigma1.getEvaluation(i); - const s2 = evaluations.Sigma2.getEvaluation(i); - const s3 = evaluations.Sigma3.getEvaluation(i); - - const ap = Fr.add(challenges.b[2], Fr.mul(challenges.b[1], w)); - const bp = Fr.add(challenges.b[4], Fr.mul(challenges.b[3], w)); - const cp = Fr.add(challenges.b[6], Fr.mul(challenges.b[5], w)); - - const w2 = Fr.square(w); - const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], w2), Fr.mul(challenges.b[8], w)), challenges.b[9]); - const wW = Fr.mul(w, Fr.w[zkey.power]); - const wW2 = Fr.square(wW); - const zWp = Fr.add(Fr.add(Fr.mul(challenges.b[7], wW2), Fr.mul(challenges.b[8], wW)), challenges.b[9]); - - let pi = Fr.zero; - for (let j = 0; j < zkey.nPublic; j++) { - const offset = (j * 4 * zkey.domainSize) + i; - - const lPol = evaluations.Lagrange.getEvaluation(offset); - const aVal = buffers.A.slice(j * n8r, (j + 1) * n8r); - - pi = Fr.sub(pi, Fr.mul(lPol, aVal)); - } - - // e1 := a(X)b(X)qM(X) + a(X)qL(X) + b(X)qR(X) + c(X)qO(X) + PI(X) + qC(X) - let [e1, e1z] = MulZ.mul2(a, b, ap, bp, i % 4, Fr); - e1 = Fr.mul(e1, qm); - e1z = Fr.mul(e1z, qm); - - e1 = Fr.add(e1, Fr.mul(a, ql)); - e1z = Fr.add(e1z, Fr.mul(ap, ql)); - - e1 = Fr.add(e1, Fr.mul(b, qr)); - e1z = Fr.add(e1z, Fr.mul(bp, qr)); - - e1 = Fr.add(e1, Fr.mul(c, qo)); - e1z = Fr.add(e1z, Fr.mul(cp, qo)); - - e1 = Fr.add(e1, pi); - e1 = Fr.add(e1, qc); - - // e2 := α[(a(X) + βX + γ)(b(X) + βk1X + γ)(c(X) + βk2X + γ)z(X)] - const betaw = Fr.mul(challenges.beta, w); - let e2a = a; - e2a = Fr.add(e2a, betaw); - e2a = Fr.add(e2a, challenges.gamma); - - let e2b = b; - e2b = Fr.add(e2b, Fr.mul(betaw, zkey.k1)); - e2b = Fr.add(e2b, challenges.gamma); - - let e2c = c; - e2c = Fr.add(e2c, Fr.mul(betaw, zkey.k2)); - e2c = Fr.add(e2c, challenges.gamma); - - let e2d = z; - - let [e2, e2z] = MulZ.mul4(e2a, e2b, e2c, e2d, ap, bp, cp, zp, i % 4, Fr); - e2 = Fr.mul(e2, challenges.alpha); - e2z = Fr.mul(e2z, challenges.alpha); - - // e3 := α[(a(X) + βSσ1(X) + γ)(b(X) + βSσ2(X) + γ)(c(X) + βSσ3(X) + γ)z(Xω)] - let e3a = a; - e3a = Fr.add(e3a, Fr.mul(challenges.beta, s1)); - e3a = Fr.add(e3a, challenges.gamma); - - let e3b = b; - e3b = Fr.add(e3b, Fr.mul(challenges.beta, s2)); - e3b = Fr.add(e3b, challenges.gamma); - - let e3c = c; - e3c = Fr.add(e3c, Fr.mul(challenges.beta, s3)); - e3c = Fr.add(e3c, challenges.gamma); - - let e3d = zw; - let [e3, e3z] = MulZ.mul4(e3a, e3b, e3c, e3d, ap, bp, cp, zWp, i % 4, Fr); - - e3 = Fr.mul(e3, challenges.alpha); - e3z = Fr.mul(e3z, challenges.alpha); - - // e4 := α^2(z(X)−1)L1(X) - let e4 = Fr.sub(z, Fr.one); - e4 = Fr.mul(e4, evaluations.Lagrange.getEvaluation(i)); - e4 = Fr.mul(e4, challenges.alpha2); - - let e4z = Fr.mul(zp, evaluations.Lagrange.getEvaluation(i)); - e4z = Fr.mul(e4z, challenges.alpha2); - - - let t = Fr.add(Fr.sub(Fr.add(e1, e2), e3), e4); - let tz = Fr.add(Fr.sub(Fr.add(e1z, e2z), e3z), e4z); - - buffers.T.set(t, i * n8r); - buffers.Tz.set(tz, i * n8r); - - w = Fr.mul(w, Fr.w[zkey.power + 2]); - } - - // Compute the coefficients of the polynomial T0(X) from buffers.T0 - if (logger) - logger.debug("··· Computing T ifft"); - polynomials.T = await Polynomial.fromEvaluations(buffers.T, curve, logger); - - // Divide the polynomial T0 by Z_H(X) - if (logger) - logger.debug("··· Computing T / ZH"); - polynomials.T.divZh(zkey.domainSize, 4); - - // Compute the coefficients of the polynomial Tz(X) from buffers.Tz - if (logger) - logger.debug("··· Computing Tz ifft"); - polynomials.Tz = await Polynomial.fromEvaluations(buffers.Tz, curve, logger); - - // Add the polynomial T1z to T1 to get the final polynomial T1 - polynomials.T.add(polynomials.Tz); - - // Check degree - if (polynomials.T.degree() >= zkey.domainSize * 3 + 6) { - throw new Error("T Polynomial is not well calculated"); - } - - // t(x) has degree 3n + 5, we are going to split t(x) into three smaller polynomials: - // T1' and T2' with a degree < n and T3' with a degree n+5 - // such that t(x) = T1'(X) + X^n T2'(X) + X^{2n} T3'(X) - // To randomize the parts we use blinding scalars b_10 and b_11 in a way that doesn't change t(X): - // T1(X) = T1'(X) + b_10 X^n - // T2(X) = T2'(X) - b_10 + b_11 X^n - // T3(X) = T3'(X) - b_11 - // such that - // t(X) = T1(X) + X^n T2(X) + X^2n T3(X) - if (logger) logger.debug("··· Computing T1, T2, T3 polynomials"); - polynomials.T1 = new Polynomial(new ffjavascript.BigBuffer((zkey.domainSize + 1) * n8r), curve, logger); - polynomials.T2 = new Polynomial(new ffjavascript.BigBuffer((zkey.domainSize + 1) * n8r), curve, logger); - polynomials.T3 = new Polynomial(new ffjavascript.BigBuffer((zkey.domainSize + 6) * n8r), curve, logger); - - polynomials.T1.coef.set(polynomials.T.coef.slice(0, sDomain), 0); - polynomials.T2.coef.set(polynomials.T.coef.slice(sDomain, sDomain * 2), 0); - polynomials.T3.coef.set(polynomials.T.coef.slice(sDomain * 2, sDomain * 3 + 6 * n8r), 0); - - // Add blinding scalar b_10 as a new coefficient n - polynomials.T1.setCoef(zkey.domainSize, challenges.b[10]); - - // compute t_mid(X) - // Subtract blinding scalar b_10 to the lowest coefficient of t_mid - const lowestMid = Fr.sub(polynomials.T2.getCoef(0), challenges.b[10]); - polynomials.T2.setCoef(0, lowestMid); - polynomials.T2.setCoef(zkey.domainSize, challenges.b[11]); - - // compute t_high(X) - //Subtract blinding scalar b_11 to the lowest coefficient of t_high - const lowestHigh = Fr.sub(polynomials.T3.getCoef(0), challenges.b[11]); - polynomials.T3.setCoef(0, lowestHigh); - } - - async function round4() { - if (logger) logger.debug("> Computing challenge xi"); - - // STEP 4.1 - Compute evaluation challenge xi ∈ F - transcript.reset(); - transcript.addScalar(challenges.alpha); - transcript.addPolCommitment(proof.getPolynomial("T1")); - transcript.addPolCommitment(proof.getPolynomial("T2")); - transcript.addPolCommitment(proof.getPolynomial("T3")); - - challenges.xi = transcript.getChallenge(); - challenges.xiw = Fr.mul(challenges.xi, Fr.w[zkey.power]); - - if (logger) logger.debug("··· challenges.xi: " + Fr.toString(challenges.xi, 16)); - - // Fourth output of the prover is ( a(xi), b(xi), c(xi), s1(xi), s2(xi), z(xiw) ) - proof.addEvaluation("eval_a", polynomials.A.evaluate(challenges.xi)); - proof.addEvaluation("eval_b", polynomials.B.evaluate(challenges.xi)); - proof.addEvaluation("eval_c", polynomials.C.evaluate(challenges.xi)); - proof.addEvaluation("eval_s1", polynomials.Sigma1.evaluate(challenges.xi)); - proof.addEvaluation("eval_s2", polynomials.Sigma2.evaluate(challenges.xi)); - proof.addEvaluation("eval_zw", polynomials.Z.evaluate(challenges.xiw)); - } - - async function round5() { - if (logger) logger.debug("> Computing challenge v"); - - // STEP 5.1 - Compute evaluation challenge v ∈ F - transcript.reset(); - transcript.addScalar(challenges.xi); - transcript.addScalar(proof.getEvaluation("eval_a")); - transcript.addScalar(proof.getEvaluation("eval_b")); - transcript.addScalar(proof.getEvaluation("eval_c")); - transcript.addScalar(proof.getEvaluation("eval_s1")); - transcript.addScalar(proof.getEvaluation("eval_s2")); - transcript.addScalar(proof.getEvaluation("eval_zw")); - - challenges.v = []; - challenges.v[1] = transcript.getChallenge(); - if (logger) logger.debug("··· challenges.v: " + Fr.toString(challenges.v[1], 16)); - - for (let i = 2; i < 6; i++) { - challenges.v[i] = Fr.mul(challenges.v[i - 1], challenges.v[1]); - } - - // STEP 5.2 Compute linearisation polynomial r(X) - if (logger) logger.debug("> Computing linearisation polynomial R(X)"); - await computeR(); - - //STEP 5.3 Compute opening proof polynomial Wxi(X) - if (logger) logger.debug("> Computing opening proof polynomial Wxi(X) polynomial"); - computeWxi(); - - //STEP 5.4 Compute opening proof polynomial Wxiw(X) - if (logger) logger.debug("> Computing opening proof polynomial Wxiw(X) polynomial"); - computeWxiw(); - - if (logger) logger.debug("> Computing Wxi, Wxiw MSM"); - let commitWxi = await polynomials.Wxi.multiExponentiation(PTau, "Wxi"); - let commitWxiw = await polynomials.Wxiw.multiExponentiation(PTau, "Wxiw"); - - // Fifth output of the prover is ([Wxi]_1, [Wxiw]_1) - proof.addPolynomial("Wxi", commitWxi); - proof.addPolynomial("Wxiw", commitWxiw); - } - - async function computeR() { - const Fr = curve.Fr; - - // Reserve memory for Q's polynomials - polynomials.QL = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QR = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QM = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QO = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QC = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - - // Read Q's evaluations from zkey file - await fdZKey.readToBuffer(polynomials.QL.coef, 0, sDomain, zkeySections[ZKEY_PL_QL_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QR.coef, 0, sDomain, zkeySections[ZKEY_PL_QR_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QM.coef, 0, sDomain, zkeySections[ZKEY_PL_QM_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QO.coef, 0, sDomain, zkeySections[ZKEY_PL_QO_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QC.coef, 0, sDomain, zkeySections[ZKEY_PL_QC_SECTION][0].p); - - challenges.xin = challenges.xi; - for (let i = 0; i < zkey.power; i++) { - challenges.xin = Fr.square(challenges.xin); - } - - challenges.zh = Fr.sub(challenges.xin, Fr.one); - - const L = []; - - const n = Fr.e(zkey.domainSize); - let w = Fr.one; - for (let i = 1; i <= Math.max(1, zkey.nPublic); i++) { - L[i] = Fr.div(Fr.mul(w, challenges.zh), Fr.mul(n, Fr.sub(challenges.xi, w))); - w = Fr.mul(w, Fr.w[zkey.power]); - } - - const eval_l1 = Fr.div( - Fr.sub(challenges.xin, Fr.one), - Fr.mul(n, Fr.sub(challenges.xi, Fr.one)) - ); - - if (logger) { - logger.debug("Lagrange Evaluations: "); - for (let i=1; i. -*/ -const {unstringifyBigInts: unstringifyBigInts$5} = ffjavascript.utils; - + const { fd: fdWtns, sections: sectionsWtns } = await _iden3_binfileutils.readBinFile(witnessFileName, "wtns", 2, 1 << 25, 1 << 23); + if (logger) logger.debug("> Reading witness file"); + const wtns = await readHeader(fdWtns, sectionsWtns); + if (logger) logger.debug("> Reading zkey file"); + const { fd: fdZKey, sections: zkeySections } = await _iden3_binfileutils.readBinFile(zkeyFileName, "zkey", 2, 1 << 25, 1 << 23); + const zkey = await readHeader$1(fdZKey, zkeySections, void 0, options); + if (zkey.protocol != "plonk") throw new Error("zkey file is not plonk"); + if (!ffjavascript.Scalar.eq(zkey.r, wtns.q)) throw new Error("Curve of the witness does not match the curve of the proving key"); + if (wtns.nWitness != zkey.nVars - zkey.nAdditions) throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}, ${zkey.nAdditions}`); + const curve = zkey.curve; + const Fr = curve.Fr; + const n8r = curve.Fr.n8; + const sDomain = zkey.domainSize * n8r; + if (logger) { + logger.debug("----------------------------"); + logger.debug(" PLONK PROVE SETTINGS"); + logger.debug(` Curve: ${curve.name}`); + logger.debug(` Circuit power: ${zkey.power}`); + logger.debug(` Domain size: ${zkey.domainSize}`); + logger.debug(` Vars: ${zkey.nVars}`); + logger.debug(` Public vars: ${zkey.nPublic}`); + logger.debug(` Constraints: ${zkey.nConstraints}`); + logger.debug(` Additions: ${zkey.nAdditions}`); + logger.debug("----------------------------"); + } + if (logger) logger.debug("> Reading witness file data"); + const buffWitness = await _iden3_binfileutils.readSection(fdWtns, sectionsWtns, 2); + buffWitness.set(Fr.zero, 0); + const buffInternalWitness = new ffjavascript.BigBuffer(n8r * zkey.nAdditions); + let buffers = {}; + let polynomials = {}; + let evaluations = {}; + let challenges = {}; + let proof = new Proof(curve, logger); + const transcript = new Keccak256Transcript(curve); + if (logger) logger.debug(`> Reading Section 3. Additions`); + await calculateAdditions(); + if (logger) logger.debug(`> Reading Section 12. Sigma1, Sigma2 & Sigma 3`); + if (logger) logger.debug("··· Reading Sigma polynomials "); + polynomials.Sigma1 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.Sigma2 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.Sigma3 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + await fdZKey.readToBuffer(polynomials.Sigma1.coef, 0, sDomain, zkeySections[12][0].p); + await fdZKey.readToBuffer(polynomials.Sigma2.coef, 0, sDomain, zkeySections[12][0].p + 5 * sDomain); + await fdZKey.readToBuffer(polynomials.Sigma3.coef, 0, sDomain, zkeySections[12][0].p + 10 * sDomain); + if (logger) logger.debug("··· Reading Sigma evaluations"); + evaluations.Sigma1 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.Sigma2 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.Sigma3 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + await fdZKey.readToBuffer(evaluations.Sigma1.eval, 0, sDomain * 4, zkeySections[12][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.Sigma2.eval, 0, sDomain * 4, zkeySections[12][0].p + 6 * sDomain); + await fdZKey.readToBuffer(evaluations.Sigma3.eval, 0, sDomain * 4, zkeySections[12][0].p + 11 * sDomain); + if (logger) logger.debug(`> Reading Section 14. Powers of Tau`); + const PTau = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 14); + let publicSignals = []; + for (let i = 1; i <= zkey.nPublic; i++) { + const pub = buffWitness.slice(i * Fr.n8, i * Fr.n8 + Fr.n8); + publicSignals.push(ffjavascript.Scalar.fromRprLE(pub)); + } + if (logger) logger.debug(""); + if (logger) logger.debug("> ROUND 1"); + await round1(); + if (logger) logger.debug("> ROUND 2"); + await round2(); + if (logger) logger.debug("> ROUND 3"); + await round3(); + if (logger) logger.debug("> ROUND 4"); + await round4(); + if (logger) logger.debug("> ROUND 5"); + await round5(); + await fdZKey.close(); + await fdWtns.close(); + let _proof = proof.toObjectProof(false); + _proof.protocol = "plonk"; + _proof.curve = curve.name; + if (logger) logger.debug("PLONK PROVER FINISHED"); + return { + proof: stringifyBigInts$1(_proof), + publicSignals: stringifyBigInts$1(publicSignals) + }; + async function calculateAdditions() { + if (logger) logger.debug("··· Computing additions"); + const additionsBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 3); + const sSum = 8 + n8r * 2; + for (let i = 0; i < zkey.nAdditions; i++) { + if (logger && 0 !== i && i % 1e5 === 0) logger.debug(` addition ${i}/${zkey.nAdditions}`); + let offset = i * sSum; + const signalId1 = readUInt32(additionsBuff, offset); + offset += 4; + const signalId2 = readUInt32(additionsBuff, offset); + offset += 4; + const factor1 = additionsBuff.slice(offset, offset + n8r); + offset += n8r; + const factor2 = additionsBuff.slice(offset, offset + n8r); + const witness1 = getWitness(signalId1); + const witness2 = getWitness(signalId2); + const result = Fr.add(Fr.mul(factor1, witness1), Fr.mul(factor2, witness2)); + buffInternalWitness.set(result, n8r * i); + } + } + function readUInt32(b, o) { + const buff = b.slice(o, o + 4); + return new DataView(buff.buffer, buff.byteOffset, buff.byteLength).getUint32(0, true); + } + function getWitness(idx) { + if (idx < zkey.nVars - zkey.nAdditions) return buffWitness.slice(idx * n8r, idx * n8r + n8r); + else if (idx < zkey.nVars) return buffInternalWitness.slice((idx - (zkey.nVars - zkey.nAdditions)) * n8r, (idx - (zkey.nVars - zkey.nAdditions)) * n8r + n8r); + else return curve.Fr.zero; + } + async function round1() { + challenges.b = []; + for (let i = 1; i <= 11; i++) challenges.b[i] = curve.Fr.random(); + if (logger) logger.debug("> Computing A, B, C wire polynomials"); + await computeWirePolynomials(); + if (logger) logger.debug("> Computing A, B, C MSM"); + let commitA = await polynomials.A.multiExponentiation(PTau, "A"); + let commitB = await polynomials.B.multiExponentiation(PTau, "B"); + let commitC = await polynomials.C.multiExponentiation(PTau, "C"); + proof.addPolynomial("A", commitA); + proof.addPolynomial("B", commitB); + proof.addPolynomial("C", commitC); + return 0; + } + async function computeWirePolynomials() { + if (logger) logger.debug("··· Reading data from zkey file"); + buffers.A = new ffjavascript.BigBuffer(sDomain); + buffers.B = new ffjavascript.BigBuffer(sDomain); + buffers.C = new ffjavascript.BigBuffer(sDomain); + const aMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 4); + const bMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 5); + const cMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 6); + for (let i = 0; i < zkey.nConstraints; i++) { + const i_sFr = i * n8r; + const offset = i * 4; + const signalIdA = readUInt32(aMapBuff, offset); + buffers.A.set(getWitness(signalIdA), i_sFr); + const signalIdB = readUInt32(bMapBuff, offset); + buffers.B.set(getWitness(signalIdB), i_sFr); + const signalIdC = readUInt32(cMapBuff, offset); + buffers.C.set(getWitness(signalIdC), i_sFr); + } + buffers.A = await Fr.batchToMontgomery(buffers.A); + buffers.B = await Fr.batchToMontgomery(buffers.B); + buffers.C = await Fr.batchToMontgomery(buffers.C); + if (logger) logger.debug("··· Computing A ifft"); + polynomials.A = await Polynomial.fromEvaluations(buffers.A, curve, logger); + if (logger) logger.debug("··· Computing B ifft"); + polynomials.B = await Polynomial.fromEvaluations(buffers.B, curve, logger); + if (logger) logger.debug("··· Computing C ifft"); + polynomials.C = await Polynomial.fromEvaluations(buffers.C, curve, logger); + if (logger) logger.debug("··· Computing A fft"); + evaluations.A = await Evaluations.fromPolynomial(polynomials.A, 4, curve, logger); + if (logger) logger.debug("··· Computing B fft"); + evaluations.B = await Evaluations.fromPolynomial(polynomials.B, 4, curve, logger); + if (logger) logger.debug("··· Computing C fft"); + evaluations.C = await Evaluations.fromPolynomial(polynomials.C, 4, curve, logger); + polynomials.A.blindCoefficients([challenges.b[2], challenges.b[1]]); + polynomials.B.blindCoefficients([challenges.b[4], challenges.b[3]]); + polynomials.C.blindCoefficients([challenges.b[6], challenges.b[5]]); + if (polynomials.A.degree() >= zkey.domainSize + 2) throw new Error("A Polynomial is not well calculated"); + if (polynomials.B.degree() >= zkey.domainSize + 2) throw new Error("B Polynomial is not well calculated"); + if (polynomials.C.degree() >= zkey.domainSize + 2) throw new Error("C Polynomial is not well calculated"); + } + async function round2() { + if (logger) logger.debug("> Computing challenges beta and gamma"); + transcript.reset(); + transcript.addPolCommitment(zkey.Qm); + transcript.addPolCommitment(zkey.Ql); + transcript.addPolCommitment(zkey.Qr); + transcript.addPolCommitment(zkey.Qo); + transcript.addPolCommitment(zkey.Qc); + transcript.addPolCommitment(zkey.S1); + transcript.addPolCommitment(zkey.S2); + transcript.addPolCommitment(zkey.S3); + for (let i = 0; i < zkey.nPublic; i++) transcript.addScalar(buffers.A.slice(i * n8r, i * n8r + n8r)); + transcript.addPolCommitment(proof.getPolynomial("A")); + transcript.addPolCommitment(proof.getPolynomial("B")); + transcript.addPolCommitment(proof.getPolynomial("C")); + challenges.beta = transcript.getChallenge(); + if (logger) logger.debug("··· challenges.beta: " + Fr.toString(challenges.beta, 16)); + transcript.reset(); + transcript.addScalar(challenges.beta); + challenges.gamma = transcript.getChallenge(); + if (logger) logger.debug("··· challenges.gamma: " + Fr.toString(challenges.gamma, 16)); + if (logger) logger.debug("> Computing Z polynomial"); + await computeZ(); + if (logger) logger.debug("> Computing Z MSM"); + let commitZ = await polynomials.Z.multiExponentiation(PTau, "Z"); + proof.addPolynomial("Z", commitZ); + } + async function computeZ() { + if (logger) logger.debug("··· Computing Z evaluations"); + let numArr = new ffjavascript.BigBuffer(sDomain); + let denArr = new ffjavascript.BigBuffer(sDomain); + numArr.set(Fr.one, 0); + denArr.set(Fr.one, 0); + let w = Fr.one; + for (let i = 0; i < zkey.domainSize; i++) { + const i_n8r = i * n8r; + const a = buffers.A.slice(i_n8r, i_n8r + n8r); + const b = buffers.B.slice(i_n8r, i_n8r + n8r); + const c = buffers.C.slice(i_n8r, i_n8r + n8r); + const betaw = Fr.mul(challenges.beta, w); + let n1 = Fr.add(a, betaw); + n1 = Fr.add(n1, challenges.gamma); + let n2 = Fr.add(b, Fr.mul(zkey.k1, betaw)); + n2 = Fr.add(n2, challenges.gamma); + let n3 = Fr.add(c, Fr.mul(zkey.k2, betaw)); + n3 = Fr.add(n3, challenges.gamma); + let num = Fr.mul(n1, Fr.mul(n2, n3)); + let d1 = Fr.add(a, Fr.mul(evaluations.Sigma1.getEvaluation(i * 4), challenges.beta)); + d1 = Fr.add(d1, challenges.gamma); + let d2 = Fr.add(b, Fr.mul(evaluations.Sigma2.getEvaluation(i * 4), challenges.beta)); + d2 = Fr.add(d2, challenges.gamma); + let d3 = Fr.add(c, Fr.mul(evaluations.Sigma3.getEvaluation(i * 4), challenges.beta)); + d3 = Fr.add(d3, challenges.gamma); + let den = Fr.mul(d1, Fr.mul(d2, d3)); + num = Fr.mul(numArr.slice(i_n8r, i_n8r + n8r), num); + numArr.set(num, (i + 1) % zkey.domainSize * n8r); + den = Fr.mul(denArr.slice(i_n8r, i_n8r + n8r), den); + denArr.set(den, (i + 1) % zkey.domainSize * n8r); + w = Fr.mul(w, Fr.w[zkey.power]); + } + denArr = await Fr.batchInverse(denArr); + for (let i = 0; i < zkey.domainSize; i++) { + const i_sFr = i * n8r; + const z = Fr.mul(numArr.slice(i_sFr, i_sFr + n8r), denArr.slice(i_sFr, i_sFr + n8r)); + numArr.set(z, i_sFr); + } + buffers.Z = numArr; + if (!Fr.eq(numArr.slice(0, n8r), Fr.one)) throw new Error("Copy constraints does not match"); + if (logger) logger.debug("··· Computing Z ifft"); + polynomials.Z = await Polynomial.fromEvaluations(buffers.Z, curve, logger); + if (logger) logger.debug("··· Computing Z fft"); + evaluations.Z = await Evaluations.fromPolynomial(polynomials.Z, 4, curve, logger); + polynomials.Z.blindCoefficients([ + challenges.b[9], + challenges.b[8], + challenges.b[7] + ]); + if (polynomials.Z.degree() >= zkey.domainSize + 3) throw new Error("Z Polynomial is not well calculated"); + delete buffers.Z; + } + async function round3() { + if (logger) logger.debug("> Computing challenge alpha"); + transcript.reset(); + transcript.addScalar(challenges.beta); + transcript.addScalar(challenges.gamma); + transcript.addPolCommitment(proof.getPolynomial("Z")); + challenges.alpha = transcript.getChallenge(); + challenges.alpha2 = Fr.square(challenges.alpha); + if (logger) logger.debug("··· challenges.alpha: " + Fr.toString(challenges.alpha, 16)); + if (logger) logger.debug("> Computing T polynomial"); + await computeT(); + if (logger) logger.debug("> Computing T MSM"); + let commitT1 = await polynomials.T1.multiExponentiation(PTau, "T1"); + let commitT2 = await polynomials.T2.multiExponentiation(PTau, "T2"); + let commitT3 = await polynomials.T3.multiExponentiation(PTau, "T3"); + proof.addPolynomial("T1", commitT1); + proof.addPolynomial("T2", commitT2); + proof.addPolynomial("T3", commitT3); + } + async function computeT() { + if (logger) logger.debug(`··· Reading sections 8, 9, 7, 10, 11. Q selectors`); + evaluations.QL = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QR = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QM = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QO = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QC = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + await fdZKey.readToBuffer(evaluations.QL.eval, 0, sDomain * 4, zkeySections[8][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QR.eval, 0, sDomain * 4, zkeySections[9][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QM.eval, 0, sDomain * 4, zkeySections[7][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QO.eval, 0, sDomain * 4, zkeySections[10][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QC.eval, 0, sDomain * 4, zkeySections[11][0].p + sDomain); + evaluations.Lagrange = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4 * zkey.nPublic), curve, logger); + for (let i = 0; i < zkey.nPublic; i++) await fdZKey.readToBuffer(evaluations.Lagrange.eval, i * sDomain * 4, sDomain * 4, zkeySections[13][0].p + i * 5 * sDomain + sDomain); + buffers.T = new ffjavascript.BigBuffer(sDomain * 4); + buffers.Tz = new ffjavascript.BigBuffer(sDomain * 4); + if (logger) logger.debug("··· Computing T evaluations"); + let w = Fr.one; + for (let i = 0; i < zkey.domainSize * 4; i++) { + if (logger && 0 !== i && i % 1e5 === 0) logger.debug(` T evaluation ${i}/${zkey.domainSize * 4}`); + const a = evaluations.A.getEvaluation(i); + const b = evaluations.B.getEvaluation(i); + const c = evaluations.C.getEvaluation(i); + const z = evaluations.Z.getEvaluation(i); + const zw = evaluations.Z.getEvaluation((zkey.domainSize * 4 + 4 + i) % (zkey.domainSize * 4)); + const qm = evaluations.QM.getEvaluation(i); + const ql = evaluations.QL.getEvaluation(i); + const qr = evaluations.QR.getEvaluation(i); + const qo = evaluations.QO.getEvaluation(i); + const qc = evaluations.QC.getEvaluation(i); + const s1 = evaluations.Sigma1.getEvaluation(i); + const s2 = evaluations.Sigma2.getEvaluation(i); + const s3 = evaluations.Sigma3.getEvaluation(i); + const ap = Fr.add(challenges.b[2], Fr.mul(challenges.b[1], w)); + const bp = Fr.add(challenges.b[4], Fr.mul(challenges.b[3], w)); + const cp = Fr.add(challenges.b[6], Fr.mul(challenges.b[5], w)); + const w2 = Fr.square(w); + const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], w2), Fr.mul(challenges.b[8], w)), challenges.b[9]); + const wW = Fr.mul(w, Fr.w[zkey.power]); + const wW2 = Fr.square(wW); + const zWp = Fr.add(Fr.add(Fr.mul(challenges.b[7], wW2), Fr.mul(challenges.b[8], wW)), challenges.b[9]); + let pi = Fr.zero; + for (let j = 0; j < zkey.nPublic; j++) { + const offset = j * 4 * zkey.domainSize + i; + const lPol = evaluations.Lagrange.getEvaluation(offset); + const aVal = buffers.A.slice(j * n8r, (j + 1) * n8r); + pi = Fr.sub(pi, Fr.mul(lPol, aVal)); + } + let [e1, e1z] = MulZ.mul2(a, b, ap, bp, i % 4, Fr); + e1 = Fr.mul(e1, qm); + e1z = Fr.mul(e1z, qm); + e1 = Fr.add(e1, Fr.mul(a, ql)); + e1z = Fr.add(e1z, Fr.mul(ap, ql)); + e1 = Fr.add(e1, Fr.mul(b, qr)); + e1z = Fr.add(e1z, Fr.mul(bp, qr)); + e1 = Fr.add(e1, Fr.mul(c, qo)); + e1z = Fr.add(e1z, Fr.mul(cp, qo)); + e1 = Fr.add(e1, pi); + e1 = Fr.add(e1, qc); + const betaw = Fr.mul(challenges.beta, w); + let e2a = a; + e2a = Fr.add(e2a, betaw); + e2a = Fr.add(e2a, challenges.gamma); + let e2b = b; + e2b = Fr.add(e2b, Fr.mul(betaw, zkey.k1)); + e2b = Fr.add(e2b, challenges.gamma); + let e2c = c; + e2c = Fr.add(e2c, Fr.mul(betaw, zkey.k2)); + e2c = Fr.add(e2c, challenges.gamma); + let e2d = z; + let [e2, e2z] = MulZ.mul4(e2a, e2b, e2c, e2d, ap, bp, cp, zp, i % 4, Fr); + e2 = Fr.mul(e2, challenges.alpha); + e2z = Fr.mul(e2z, challenges.alpha); + let e3a = a; + e3a = Fr.add(e3a, Fr.mul(challenges.beta, s1)); + e3a = Fr.add(e3a, challenges.gamma); + let e3b = b; + e3b = Fr.add(e3b, Fr.mul(challenges.beta, s2)); + e3b = Fr.add(e3b, challenges.gamma); + let e3c = c; + e3c = Fr.add(e3c, Fr.mul(challenges.beta, s3)); + e3c = Fr.add(e3c, challenges.gamma); + let e3d = zw; + let [e3, e3z] = MulZ.mul4(e3a, e3b, e3c, e3d, ap, bp, cp, zWp, i % 4, Fr); + e3 = Fr.mul(e3, challenges.alpha); + e3z = Fr.mul(e3z, challenges.alpha); + let e4 = Fr.sub(z, Fr.one); + e4 = Fr.mul(e4, evaluations.Lagrange.getEvaluation(i)); + e4 = Fr.mul(e4, challenges.alpha2); + let e4z = Fr.mul(zp, evaluations.Lagrange.getEvaluation(i)); + e4z = Fr.mul(e4z, challenges.alpha2); + let t = Fr.add(Fr.sub(Fr.add(e1, e2), e3), e4); + let tz = Fr.add(Fr.sub(Fr.add(e1z, e2z), e3z), e4z); + buffers.T.set(t, i * n8r); + buffers.Tz.set(tz, i * n8r); + w = Fr.mul(w, Fr.w[zkey.power + 2]); + } + if (logger) logger.debug("··· Computing T ifft"); + polynomials.T = await Polynomial.fromEvaluations(buffers.T, curve, logger); + if (logger) logger.debug("··· Computing T / ZH"); + polynomials.T.divZh(zkey.domainSize, 4); + if (logger) logger.debug("··· Computing Tz ifft"); + polynomials.Tz = await Polynomial.fromEvaluations(buffers.Tz, curve, logger); + polynomials.T.add(polynomials.Tz); + if (polynomials.T.degree() >= zkey.domainSize * 3 + 6) throw new Error("T Polynomial is not well calculated"); + if (logger) logger.debug("··· Computing T1, T2, T3 polynomials"); + polynomials.T1 = new Polynomial(new ffjavascript.BigBuffer((zkey.domainSize + 1) * n8r), curve, logger); + polynomials.T2 = new Polynomial(new ffjavascript.BigBuffer((zkey.domainSize + 1) * n8r), curve, logger); + polynomials.T3 = new Polynomial(new ffjavascript.BigBuffer((zkey.domainSize + 6) * n8r), curve, logger); + polynomials.T1.coef.set(polynomials.T.coef.slice(0, sDomain), 0); + polynomials.T2.coef.set(polynomials.T.coef.slice(sDomain, sDomain * 2), 0); + polynomials.T3.coef.set(polynomials.T.coef.slice(sDomain * 2, sDomain * 3 + 6 * n8r), 0); + polynomials.T1.setCoef(zkey.domainSize, challenges.b[10]); + const lowestMid = Fr.sub(polynomials.T2.getCoef(0), challenges.b[10]); + polynomials.T2.setCoef(0, lowestMid); + polynomials.T2.setCoef(zkey.domainSize, challenges.b[11]); + const lowestHigh = Fr.sub(polynomials.T3.getCoef(0), challenges.b[11]); + polynomials.T3.setCoef(0, lowestHigh); + } + async function round4() { + if (logger) logger.debug("> Computing challenge xi"); + transcript.reset(); + transcript.addScalar(challenges.alpha); + transcript.addPolCommitment(proof.getPolynomial("T1")); + transcript.addPolCommitment(proof.getPolynomial("T2")); + transcript.addPolCommitment(proof.getPolynomial("T3")); + challenges.xi = transcript.getChallenge(); + challenges.xiw = Fr.mul(challenges.xi, Fr.w[zkey.power]); + if (logger) logger.debug("··· challenges.xi: " + Fr.toString(challenges.xi, 16)); + proof.addEvaluation("eval_a", polynomials.A.evaluate(challenges.xi)); + proof.addEvaluation("eval_b", polynomials.B.evaluate(challenges.xi)); + proof.addEvaluation("eval_c", polynomials.C.evaluate(challenges.xi)); + proof.addEvaluation("eval_s1", polynomials.Sigma1.evaluate(challenges.xi)); + proof.addEvaluation("eval_s2", polynomials.Sigma2.evaluate(challenges.xi)); + proof.addEvaluation("eval_zw", polynomials.Z.evaluate(challenges.xiw)); + } + async function round5() { + if (logger) logger.debug("> Computing challenge v"); + transcript.reset(); + transcript.addScalar(challenges.xi); + transcript.addScalar(proof.getEvaluation("eval_a")); + transcript.addScalar(proof.getEvaluation("eval_b")); + transcript.addScalar(proof.getEvaluation("eval_c")); + transcript.addScalar(proof.getEvaluation("eval_s1")); + transcript.addScalar(proof.getEvaluation("eval_s2")); + transcript.addScalar(proof.getEvaluation("eval_zw")); + challenges.v = []; + challenges.v[1] = transcript.getChallenge(); + if (logger) logger.debug("··· challenges.v: " + Fr.toString(challenges.v[1], 16)); + for (let i = 2; i < 6; i++) challenges.v[i] = Fr.mul(challenges.v[i - 1], challenges.v[1]); + if (logger) logger.debug("> Computing linearisation polynomial R(X)"); + await computeR(); + if (logger) logger.debug("> Computing opening proof polynomial Wxi(X) polynomial"); + computeWxi(); + if (logger) logger.debug("> Computing opening proof polynomial Wxiw(X) polynomial"); + computeWxiw(); + if (logger) logger.debug("> Computing Wxi, Wxiw MSM"); + let commitWxi = await polynomials.Wxi.multiExponentiation(PTau, "Wxi"); + let commitWxiw = await polynomials.Wxiw.multiExponentiation(PTau, "Wxiw"); + proof.addPolynomial("Wxi", commitWxi); + proof.addPolynomial("Wxiw", commitWxiw); + } + async function computeR() { + const Fr = curve.Fr; + polynomials.QL = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QR = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QM = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QO = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QC = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + await fdZKey.readToBuffer(polynomials.QL.coef, 0, sDomain, zkeySections[8][0].p); + await fdZKey.readToBuffer(polynomials.QR.coef, 0, sDomain, zkeySections[9][0].p); + await fdZKey.readToBuffer(polynomials.QM.coef, 0, sDomain, zkeySections[7][0].p); + await fdZKey.readToBuffer(polynomials.QO.coef, 0, sDomain, zkeySections[10][0].p); + await fdZKey.readToBuffer(polynomials.QC.coef, 0, sDomain, zkeySections[11][0].p); + challenges.xin = challenges.xi; + for (let i = 0; i < zkey.power; i++) challenges.xin = Fr.square(challenges.xin); + challenges.zh = Fr.sub(challenges.xin, Fr.one); + const L = []; + const n = Fr.e(zkey.domainSize); + let w = Fr.one; + for (let i = 1; i <= Math.max(1, zkey.nPublic); i++) { + L[i] = Fr.div(Fr.mul(w, challenges.zh), Fr.mul(n, Fr.sub(challenges.xi, w))); + w = Fr.mul(w, Fr.w[zkey.power]); + } + const eval_l1 = Fr.div(Fr.sub(challenges.xin, Fr.one), Fr.mul(n, Fr.sub(challenges.xi, Fr.one))); + if (logger) { + logger.debug("Lagrange Evaluations: "); + for (let i = 1; i < L.length; i++) logger.debug(`L${i}(xi)=` + Fr.toString(L[i], 16)); + } + let eval_pi = Fr.zero; + for (let i = 0; i < publicSignals.length; i++) { + const w = Fr.e(publicSignals[i]); + eval_pi = Fr.sub(eval_pi, Fr.mul(w, L[i + 1])); + } + if (logger) logger.debug("PI: " + Fr.toString(eval_pi, 16)); + const coef_ab = Fr.mul(proof.evaluations.eval_a, proof.evaluations.eval_b); + let e2a = proof.evaluations.eval_a; + const betaxi = Fr.mul(challenges.beta, challenges.xi); + e2a = Fr.add(e2a, betaxi); + e2a = Fr.add(e2a, challenges.gamma); + let e2b = proof.evaluations.eval_b; + e2b = Fr.add(e2b, Fr.mul(betaxi, zkey.k1)); + e2b = Fr.add(e2b, challenges.gamma); + let e2c = proof.evaluations.eval_c; + e2c = Fr.add(e2c, Fr.mul(betaxi, zkey.k2)); + e2c = Fr.add(e2c, challenges.gamma); + const e2 = Fr.mul(Fr.mul(Fr.mul(e2a, e2b), e2c), challenges.alpha); + let e3a = proof.evaluations.eval_a; + e3a = Fr.add(e3a, Fr.mul(challenges.beta, proof.evaluations.eval_s1)); + e3a = Fr.add(e3a, challenges.gamma); + let e3b = proof.evaluations.eval_b; + e3b = Fr.add(e3b, Fr.mul(challenges.beta, proof.evaluations.eval_s2)); + e3b = Fr.add(e3b, challenges.gamma); + let e3 = Fr.mul(e3a, e3b); + e3 = Fr.mul(e3, proof.evaluations.eval_zw); + e3 = Fr.mul(e3, challenges.alpha); + const e4 = Fr.mul(eval_l1, challenges.alpha2); + polynomials.R = new Polynomial(new ffjavascript.BigBuffer((zkey.domainSize + 6) * n8r), curve, logger); + polynomials.R.add(polynomials.QM, coef_ab); + polynomials.R.add(polynomials.QL, proof.evaluations.eval_a); + polynomials.R.add(polynomials.QR, proof.evaluations.eval_b); + polynomials.R.add(polynomials.QO, proof.evaluations.eval_c); + polynomials.R.add(polynomials.QC); + polynomials.R.add(polynomials.Z, e2); + polynomials.R.sub(polynomials.Sigma3, Fr.mul(e3, challenges.beta)); + polynomials.R.add(polynomials.Z, e4); + let tmp = Polynomial.fromPolynomial(polynomials.T3, curve, logger); + tmp.mulScalar(Fr.square(challenges.xin)); + tmp.add(polynomials.T2, challenges.xin); + tmp.add(polynomials.T1); + tmp.mulScalar(challenges.zh); + polynomials.R.sub(tmp); + let r0 = Fr.sub(eval_pi, Fr.mul(e3, Fr.add(proof.evaluations.eval_c, challenges.gamma))); + r0 = Fr.sub(r0, e4); + if (logger) logger.debug("r0: " + Fr.toString(r0, 16)); + polynomials.R.addScalar(r0); + } + function computeWxi() { + polynomials.Wxi = new Polynomial(new ffjavascript.BigBuffer(sDomain + 6 * n8r), curve, logger); + polynomials.Wxi.add(polynomials.R); + polynomials.Wxi.add(polynomials.A, challenges.v[1]); + polynomials.Wxi.add(polynomials.B, challenges.v[2]); + polynomials.Wxi.add(polynomials.C, challenges.v[3]); + polynomials.Wxi.add(polynomials.Sigma1, challenges.v[4]); + polynomials.Wxi.add(polynomials.Sigma2, challenges.v[5]); + polynomials.Wxi.subScalar(Fr.mul(challenges.v[1], proof.evaluations.eval_a)); + polynomials.Wxi.subScalar(Fr.mul(challenges.v[2], proof.evaluations.eval_b)); + polynomials.Wxi.subScalar(Fr.mul(challenges.v[3], proof.evaluations.eval_c)); + polynomials.Wxi.subScalar(Fr.mul(challenges.v[4], proof.evaluations.eval_s1)); + polynomials.Wxi.subScalar(Fr.mul(challenges.v[5], proof.evaluations.eval_s2)); + polynomials.Wxi.divByZerofier(1, challenges.xi); + } + async function computeWxiw() { + polynomials.Wxiw = Polynomial.fromPolynomial(polynomials.Z, curve, logger); + polynomials.Wxiw.subScalar(proof.evaluations.eval_zw); + polynomials.Wxiw.divByZerofier(1, challenges.xiw); + } +} +//#endregion +//#region src/plonk_fullprove.js +var { unstringifyBigInts: unstringifyBigInts$5 } = ffjavascript.utils; async function plonkFullProve(_input, wasmFile, zkeyFileName, logger, wtnsCalcOptions, proverOptions) { - const input = unstringifyBigInts$5(_input); - - const wtns= { - type: "mem" - }; - await wtnsCalculate(input, wasmFile, wtns, wtnsCalcOptions); - return await plonk16Prove(zkeyFileName, wtns, logger, proverOptions); -} - -/* - Copyright 2021 0kims association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -const { unstringifyBigInts: unstringifyBigInts$4 } = ffjavascript.utils; - + const input = unstringifyBigInts$5(_input); + const wtns = { type: "mem" }; + await wtnsCalculate(input, wasmFile, wtns, wtnsCalcOptions); + return await plonk16Prove(zkeyFileName, wtns, logger, proverOptions); +} +//#endregion +//#region src/plonk_verify.js +var { unstringifyBigInts: unstringifyBigInts$4 } = ffjavascript.utils; async function plonkVerify(_vk_verifier, _publicSignals, _proof, logger) { - let vk_verifier = unstringifyBigInts$4(_vk_verifier); - _proof = unstringifyBigInts$4(_proof); - let publicSignals = unstringifyBigInts$4(_publicSignals); - - const curve = await getCurveFromName(vk_verifier.curve); - - const Fr = curve.Fr; - const G1 = curve.G1; - - if (logger) logger.info("PLONK VERIFIER STARTED"); - - let proof = fromObjectProof(curve,_proof); - vk_verifier = fromObjectVk$1(curve, vk_verifier); - - if (!isWellConstructed(curve, proof)) { - logger.error("Proof commitments are not valid."); - return false; - } - - if (publicSignals.length != vk_verifier.nPublic) { - if (logger) logger.error("Invalid number of public inputs"); - return false; - } - - if (!evaluationsAreValid$1(curve, proof)) { - if (logger) logger.error("Proof evaluations are not valid"); - return false; - } - - if (!publicInputsAreValid$1(curve, publicSignals)) { - if (logger) logger.error("Public inputs are not valid."); - return false; - } - - const challenges = calculatechallenges(curve, proof, publicSignals, vk_verifier); - if (logger) { - logger.debug("beta: " + Fr.toString(challenges.beta, 16)); - logger.debug("gamma: " + Fr.toString(challenges.gamma, 16)); - logger.debug("alpha: " + Fr.toString(challenges.alpha, 16)); - logger.debug("xi: " + Fr.toString(challenges.xi, 16)); - for(let i=1;i<6;i++) { - if (logger) logger.debug("v: " + Fr.toString(challenges.v[i], 16)); - } - logger.debug("u: " + Fr.toString(challenges.u, 16)); - } - const L = calculateLagrangeEvaluations(curve, challenges, vk_verifier); - if (logger) { - for (let i=1; i. -*/ -const { unstringifyBigInts: unstringifyBigInts$3} = ffjavascript.utils; - + const G1 = curve.G1; + const Fr = curve.Fr; + let A1 = proof.Wxi; + A1 = G1.add(A1, G1.timesFr(proof.Wxiw, challenges.u)); + let B1 = G1.timesFr(proof.Wxi, challenges.xi); + const s = Fr.mul(Fr.mul(challenges.u, challenges.xi), Fr.w[vk.power]); + B1 = G1.add(B1, G1.timesFr(proof.Wxiw, s)); + B1 = G1.add(B1, F); + B1 = G1.sub(B1, E); + return await curve.pairingEq(G1.neg(A1), vk.X_2, B1, curve.G2.one); +} +//#endregion +//#region src/plonk_exportsoliditycalldata.js +var { unstringifyBigInts: unstringifyBigInts$3 } = ffjavascript.utils; function p256$1(n) { - let nstr = n.toString(16); - while (nstr.length < 64) nstr = "0"+nstr; - nstr = `"0x${nstr}"`; - return nstr; + let nstr = n.toString(16); + while (nstr.length < 64) nstr = "0" + nstr; + nstr = `"0x${nstr}"`; + return nstr; } - async function plonkExportSolidityCallData(_proof, _pub) { - const proof = unstringifyBigInts$3(_proof); - const pub = unstringifyBigInts$3(_pub); - - const curve = await getCurveFromName(proof.curve); - curve.G1; - curve.Fr; - - let inputs = ""; - for (let i=0; i. -*/ - -var plonk = /*#__PURE__*/Object.freeze({ - __proto__: null, - setup: plonkSetup, - fullProve: plonkFullProve, - prove: plonk16Prove, - verify: plonkVerify, - exportSolidityCallData: plonkExportSolidityCallData + const proof = unstringifyBigInts$3(_proof); + const pub = unstringifyBigInts$3(_pub); + await getCurveFromName(proof.curve); + let inputs = ""; + for (let i = 0; i < pub.length; i++) { + if (inputs != "") inputs = inputs + ","; + inputs = inputs + p256$1(pub[i]); + } + return `[${p256$1(proof.A[0])}, ${p256$1(proof.A[1])},${p256$1(proof.B[0])},${p256$1(proof.B[1])},${p256$1(proof.C[0])},${p256$1(proof.C[1])},${p256$1(proof.Z[0])},${p256$1(proof.Z[1])},${p256$1(proof.T1[0])},${p256$1(proof.T1[1])},${p256$1(proof.T2[0])},${p256$1(proof.T2[1])},${p256$1(proof.T3[0])},${p256$1(proof.T3[1])},${p256$1(proof.Wxi[0])},${p256$1(proof.Wxi[1])},${p256$1(proof.Wxiw[0])},${p256$1(proof.Wxiw[1])},${p256$1(proof.eval_a)},${p256$1(proof.eval_b)},${p256$1(proof.eval_c)},${p256$1(proof.eval_s1)},${p256$1(proof.eval_s2)},${p256$1(proof.eval_zw)}][${inputs}]`; +} +//#endregion +//#region src/plonk.js +var plonk_exports = /* @__PURE__ */ __exportAll({ + exportSolidityCallData: () => plonkExportSolidityCallData, + fullProve: () => plonkFullProve, + prove: () => plonk16Prove, + setup: () => plonkSetup, + verify: () => plonkVerify }); - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -// We export to zkey the signals and values of the a, b, c, ql, qr, qm, qo and qc - -// a, b and c are signals id (32-bit integers) -// ql, qr, qm, qo and qc are field values - +//#endregion +//#region src/plonk_equation.js function getFFlonkConstantConstraint(signal1, Fr) { - return [signal1, 0, 0, Fr.one, Fr.zero, Fr.zero, Fr.zero, Fr.zero]; + return [ + signal1, + 0, + 0, + Fr.one, + Fr.zero, + Fr.zero, + Fr.zero, + Fr.zero + ]; } - function getFFlonkAdditionConstraint(signal1, signal2, signalOut, ql, qr, qm, qo, qc) { - return [signal1, signal2, signalOut, ql, qr, qm, qo, qc]; -} - -function getFFlonkMultiplicationConstraint(signal1, signal2, signalOut, ql, qr, qm, qo, qc, Fr) { - return [signal1, signal2, signalOut, ql, qr, qm, qo, qc]; -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -const LINEAR_COMBINATION_NULLABLE = 0; -const LINEAR_COMBINATION_CONSTANT = 1; -const LINEAR_COMBINATION_VARIABLE = 2; - -class r1csConstraintProcessor { - constructor(Fr, fnGetConstantConstraint, fnGetAdditionConstraint, fnGetMultiplicationConstraint, logger) { - this.Fr = Fr; - this.logger = logger; - this.fnGetAdditionConstraint = fnGetAdditionConstraint; - this.fnGetMultiplicationConstraint = fnGetMultiplicationConstraint; - } - - processR1csConstraint(settings, lcA, lcB, lcC) { - this.normalizeLinearCombination(lcA); - this.normalizeLinearCombination(lcB); - this.normalizeLinearCombination(lcC); - - const lctA = this.getLinearCombinationType(lcA); - const lctB = this.getLinearCombinationType(lcB); - - if ((lctA === LINEAR_COMBINATION_NULLABLE) || (lctB === LINEAR_COMBINATION_NULLABLE)) { - return this.processR1csAdditionConstraint(settings, lcC); - } else if (lctA === LINEAR_COMBINATION_CONSTANT) { - const lcCC = this.joinLinearCombinations(lcB, lcC, lcA[0]); - return this.processR1csAdditionConstraint(settings, lcCC); - } else if (lctB === LINEAR_COMBINATION_CONSTANT) { - const lcCC = this.joinLinearCombinations(lcA, lcC, lcB[0]); - return this.processR1csAdditionConstraint(settings, lcCC); - } else { - return this.processR1csMultiplicationConstraint(settings, lcA, lcB, lcC); - } - } - - getLinearCombinationType(linCom) { - // let k = this.Fr.zero; - // - // const signalIds = Object.keys(linCom); - // for (let i = 0; i < signalIds.length; i++) { - // if (signalIds[i] === "0") { - // k = this.Fr.add(k, linCom[signalIds[i]]); - // } else { - // return LINEAR_COMBINATION_VARIABLE; - // } - // } - // - // if (!this.Fr.eq(k, this.Fr.zero)) return LINEAR_COMBINATION_CONSTANT; - // - // return LINEAR_COMBINATION_NULLABLE; - - let k = this.Fr.zero; - let n = 0; - const ss = Object.keys(linCom); - for (let i = 0; i < ss.length; i++) { - if (linCom[ss[i]] == 0n) { - delete linCom[ss[i]]; - } else if (ss[i] == 0) { - k = this.Fr.add(k, linCom[ss[i]]); - } else { - n++; - } - } - if (n > 0) return LINEAR_COMBINATION_VARIABLE; - if (!this.Fr.isZero(k)) return LINEAR_COMBINATION_CONSTANT; - return LINEAR_COMBINATION_NULLABLE; - } - - normalizeLinearCombination(linCom) { - const signalIds = Object.keys(linCom); - for (let i = 0; i < signalIds.length; i++) { - if (this.Fr.isZero(linCom[signalIds[i]])) delete linCom[signalIds[i]]; - } - - return linCom; - } - - joinLinearCombinations(linCom1, linCom2, k) { - const res = {}; - - // for (let s in linCom1) { - // const val = this.Fr.mul(k, linCom1[s]); - // res[s] = !(s in res) ? val : this.Fr.add(val, res[s]); - // } - // - // for (let s in linCom2) { - // const val = this.Fr.mul(k, linCom2[s]); - // res[s] = !(s in res) ? val : this.Fr.add(val, res[s]); - // } - - for (let s in linCom1) { - if (typeof res[s] == "undefined") { - res[s] = this.Fr.mul(k, linCom1[s]); - } else { - res[s] = this.Fr.add(res[s], this.Fr.mul(k, linCom1[s])); - } - } - - for (let s in linCom2) { - if (typeof res[s] == "undefined") { - res[s] = linCom2[s]; - } else { - res[s] = this.Fr.add(res[s], linCom2[s]); - } - } - - return this.normalizeLinearCombination(res); - } - - reduceCoefs(settings, constraintsArr, additionsArr, linCom, maxC) { - const res = { - k: this.Fr.zero, - signals: [], - coefs: [] - }; - const cs = []; - - for (let signalId in linCom) { - if (signalId == 0) { - res.k = this.Fr.add(res.k, linCom[signalId]); - } else if (linCom[signalId] != 0n) { - cs.push([Number(signalId), linCom[signalId]]); - } - } - - while (cs.length > maxC) { - const c1 = cs.shift(); - const c2 = cs.shift(); - const so = settings.nVars++; - - const constraints = this.fnGetAdditionConstraint( - c1[0], c2[0], so, - this.Fr.neg(c1[1]), this.Fr.neg(c2[1]), this.Fr.zero, this.Fr.one, this.Fr.zero); - - constraintsArr.push(constraints); - additionsArr.push([c1[0], c2[0], c1[1], c2[1]]); - - cs.push([so, this.Fr.one]); - } - - for (let i = 0; i < cs.length; i++) { - res.signals[i] = cs[i][0]; - res.coefs[i] = cs[i][1]; - } - - while (res.coefs.length < maxC) { - res.signals.push(0); - res.coefs.push(this.Fr.zero); - } - - return res; - } - - processR1csAdditionConstraint(settings, linCom) { - const constraintsArr = []; - const additionsArr = []; - - const C = this.reduceCoefs(settings, constraintsArr, additionsArr, linCom, 3); - - const constraints = this.fnGetAdditionConstraint( - C.signals[0], C.signals[1], C.signals[2], - C.coefs[0], C.coefs[1], this.Fr.zero, C.coefs[2], C.k); - - constraintsArr.push(constraints); - - return [constraintsArr, additionsArr]; - } - - processR1csMultiplicationConstraint(settings, lcA, lcB, lcC) { - const constraintsArr = []; - const additionsArr = []; - - const A = this.reduceCoefs(settings, constraintsArr, additionsArr, lcA, 1); - const B = this.reduceCoefs(settings, constraintsArr, additionsArr, lcB, 1); - const C = this.reduceCoefs(settings, constraintsArr, additionsArr, lcC, 1); - - const constraints = this.fnGetMultiplicationConstraint( - A.signals[0], B.signals[0], C.signals[0], - this.Fr.mul(A.coefs[0], B.k), - this.Fr.mul(A.k, B.coefs[0]), - this.Fr.mul(A.coefs[0], B.coefs[0]), - this.Fr.neg(C.coefs[0]), - this.Fr.sub(this.Fr.mul(A.k, B.k), C.k)); - - constraintsArr.push(constraints); - - return [constraintsArr, additionsArr]; - } -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -class CPolynomial { - constructor(n, curve, logger) { - this.n = n; - this.polynomials = Array(n).fill(undefined); - this.curve = curve; - this.Fr = curve.Fr; - this.G1 = curve.G1; - this.logger = logger; - } - - addPolynomial(position, polynomial) { - if (position > this.n - 1) { - throw new Error("CPolynomial:addPolynomial, cannot add a polynomial to a position greater than n-1"); - } - - this.polynomials[position] = polynomial; - } - - degree() { - let degrees = this.polynomials.map( - (polynomial, index) => polynomial === undefined ? 0 : polynomial.degree() * this.n + index); - return Math.max(...degrees); - } - - getPolynomial() { - let degrees = this.polynomials.map(polynomial => polynomial === undefined ? 0 : polynomial.degree()); - const maxDegree = this.degree(); - const lengthBuffer = 2 ** (log2(maxDegree - 1) + 1); - const sFr = this.Fr.n8; - - let polynomial = new Polynomial(new ffjavascript.BigBuffer(lengthBuffer * sFr), this.curve, this.logger); - - for (let i = 0; i < maxDegree; i++) { - const i_n8 = i * sFr; - const i_sFr = i_n8 * this.n; - - for (let j = 0; j < this.n; j++) { - if (this.polynomials[j] !== undefined) { - if (i <= degrees[j]) polynomial.coef.set(this.polynomials[j].coef.slice(i_n8, i_n8 + sFr), i_sFr + j * sFr); - } - } - } - - return polynomial; - } - - async multiExponentiation(PTau, name) { - let polynomial = this.getPolynomial(); - const n = polynomial.coef.byteLength / this.Fr.n8; - const PTauN = PTau.slice(0, n * this.G1.F.n8 * 2); - const bm = await this.Fr.batchFromMontgomery(polynomial.coef); - let res = await this.G1.multiExpAffine(PTauN, bm, this.logger, name); - res = this.G1.toAffine(res); - return res; - } -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - - + return [ + signal1, + signal2, + signalOut, + ql, + qr, + qm, + qo, + qc + ]; +} +function getFFlonkMultiplicationConstraint(signal1, signal2, signalOut, ql, qr, qm, qo, qc, _Fr) { + return [ + signal1, + signal2, + signalOut, + ql, + qr, + qm, + qo, + qc + ]; +} +//#endregion +//#region src/r1cs_constraint_processor.js +var LINEAR_COMBINATION_NULLABLE = 0; +var LINEAR_COMBINATION_CONSTANT = 1; +var LINEAR_COMBINATION_VARIABLE = 2; +var r1csConstraintProcessor = class { + constructor(Fr, fnGetConstantConstraint, fnGetAdditionConstraint, fnGetMultiplicationConstraint, logger) { + this.Fr = Fr; + this.logger = logger; + this.fnGetAdditionConstraint = fnGetAdditionConstraint; + this.fnGetMultiplicationConstraint = fnGetMultiplicationConstraint; + } + processR1csConstraint(settings, lcA, lcB, lcC) { + this.normalizeLinearCombination(lcA); + this.normalizeLinearCombination(lcB); + this.normalizeLinearCombination(lcC); + const lctA = this.getLinearCombinationType(lcA); + const lctB = this.getLinearCombinationType(lcB); + if (lctA === LINEAR_COMBINATION_NULLABLE || lctB === LINEAR_COMBINATION_NULLABLE) return this.processR1csAdditionConstraint(settings, lcC); + else if (lctA === LINEAR_COMBINATION_CONSTANT) { + const lcCC = this.joinLinearCombinations(lcB, lcC, lcA[0]); + return this.processR1csAdditionConstraint(settings, lcCC); + } else if (lctB === LINEAR_COMBINATION_CONSTANT) { + const lcCC = this.joinLinearCombinations(lcA, lcC, lcB[0]); + return this.processR1csAdditionConstraint(settings, lcCC); + } else return this.processR1csMultiplicationConstraint(settings, lcA, lcB, lcC); + } + getLinearCombinationType(linCom) { + let k = this.Fr.zero; + let n = 0; + const ss = Object.keys(linCom); + for (let i = 0; i < ss.length; i++) if (linCom[ss[i]] == 0n) delete linCom[ss[i]]; + else if (ss[i] == 0) k = this.Fr.add(k, linCom[ss[i]]); + else n++; + if (n > 0) return LINEAR_COMBINATION_VARIABLE; + if (!this.Fr.isZero(k)) return LINEAR_COMBINATION_CONSTANT; + return LINEAR_COMBINATION_NULLABLE; + } + normalizeLinearCombination(linCom) { + const signalIds = Object.keys(linCom); + for (let i = 0; i < signalIds.length; i++) if (this.Fr.isZero(linCom[signalIds[i]])) delete linCom[signalIds[i]]; + return linCom; + } + joinLinearCombinations(linCom1, linCom2, k) { + const res = {}; + for (let s in linCom1) if (typeof res[s] == "undefined") res[s] = this.Fr.mul(k, linCom1[s]); + else res[s] = this.Fr.add(res[s], this.Fr.mul(k, linCom1[s])); + for (let s in linCom2) if (typeof res[s] == "undefined") res[s] = linCom2[s]; + else res[s] = this.Fr.add(res[s], linCom2[s]); + return this.normalizeLinearCombination(res); + } + reduceCoefs(settings, constraintsArr, additionsArr, linCom, maxC) { + const res = { + k: this.Fr.zero, + signals: [], + coefs: [] + }; + const cs = []; + for (let signalId in linCom) if (signalId == 0) res.k = this.Fr.add(res.k, linCom[signalId]); + else if (linCom[signalId] != 0n) cs.push([Number(signalId), linCom[signalId]]); + while (cs.length > maxC) { + const c1 = cs.shift(); + const c2 = cs.shift(); + const so = settings.nVars++; + const constraints = this.fnGetAdditionConstraint(c1[0], c2[0], so, this.Fr.neg(c1[1]), this.Fr.neg(c2[1]), this.Fr.zero, this.Fr.one, this.Fr.zero); + constraintsArr.push(constraints); + additionsArr.push([ + c1[0], + c2[0], + c1[1], + c2[1] + ]); + cs.push([so, this.Fr.one]); + } + for (let i = 0; i < cs.length; i++) { + res.signals[i] = cs[i][0]; + res.coefs[i] = cs[i][1]; + } + while (res.coefs.length < maxC) { + res.signals.push(0); + res.coefs.push(this.Fr.zero); + } + return res; + } + processR1csAdditionConstraint(settings, linCom) { + const constraintsArr = []; + const additionsArr = []; + const C = this.reduceCoefs(settings, constraintsArr, additionsArr, linCom, 3); + const constraints = this.fnGetAdditionConstraint(C.signals[0], C.signals[1], C.signals[2], C.coefs[0], C.coefs[1], this.Fr.zero, C.coefs[2], C.k); + constraintsArr.push(constraints); + return [constraintsArr, additionsArr]; + } + processR1csMultiplicationConstraint(settings, lcA, lcB, lcC) { + const constraintsArr = []; + const additionsArr = []; + const A = this.reduceCoefs(settings, constraintsArr, additionsArr, lcA, 1); + const B = this.reduceCoefs(settings, constraintsArr, additionsArr, lcB, 1); + const C = this.reduceCoefs(settings, constraintsArr, additionsArr, lcC, 1); + const constraints = this.fnGetMultiplicationConstraint(A.signals[0], B.signals[0], C.signals[0], this.Fr.mul(A.coefs[0], B.k), this.Fr.mul(A.k, B.coefs[0]), this.Fr.mul(A.coefs[0], B.coefs[0]), this.Fr.neg(C.coefs[0]), this.Fr.sub(this.Fr.mul(A.k, B.k), C.k)); + constraintsArr.push(constraints); + return [constraintsArr, additionsArr]; + } +}; +//#endregion +//#region src/polynomial/cpolynomial.js +var CPolynomial = class { + constructor(n, curve, logger) { + this.n = n; + this.polynomials = Array(n).fill(void 0); + this.curve = curve; + this.Fr = curve.Fr; + this.G1 = curve.G1; + this.logger = logger; + } + addPolynomial(position, polynomial) { + if (position > this.n - 1) throw new Error("CPolynomial:addPolynomial, cannot add a polynomial to a position greater than n-1"); + this.polynomials[position] = polynomial; + } + degree() { + let degrees = this.polynomials.map((polynomial, index) => polynomial === void 0 ? 0 : polynomial.degree() * this.n + index); + return Math.max(...degrees); + } + getPolynomial() { + let degrees = this.polynomials.map((polynomial) => polynomial === void 0 ? 0 : polynomial.degree()); + const maxDegree = this.degree(); + const lengthBuffer = 2 ** (log2(maxDegree - 1) + 1); + const sFr = this.Fr.n8; + let polynomial = new Polynomial(new ffjavascript.BigBuffer(lengthBuffer * sFr), this.curve, this.logger); + for (let i = 0; i < maxDegree; i++) { + const i_n8 = i * sFr; + const i_sFr = i_n8 * this.n; + for (let j = 0; j < this.n; j++) if (this.polynomials[j] !== void 0) { + if (i <= degrees[j]) polynomial.coef.set(this.polynomials[j].coef.slice(i_n8, i_n8 + sFr), i_sFr + j * sFr); + } + } + return polynomial; + } + async multiExponentiation(PTau, name) { + let polynomial = this.getPolynomial(); + const n = polynomial.coef.byteLength / this.Fr.n8; + const PTauN = PTau.slice(0, n * this.G1.F.n8 * 2); + const bm = await this.Fr.batchFromMontgomery(polynomial.coef); + let res = await this.G1.multiExpAffine(PTauN, bm, this.logger, name); + res = this.G1.toAffine(res); + return res; + } +}; +//#endregion +//#region src/fflonk_setup.js async function fflonkSetup(r1csFilename, ptauFilename, zkeyFilename, logger) { - if (logger) logger.info("FFLONK SETUP STARTED"); - - if (globalThis.gc) globalThis.gc(); - - // Read PTau file - if (logger) logger.info("> Reading PTau file"); - const {fd: fdPTau, sections: pTauSections} = await binFileUtils.readBinFile(ptauFilename, "ptau", 1, 1 << 22, 1 << 24); - if (!pTauSections[12]) { - throw new Error("Powers of Tau is not well prepared. Section 12 missing."); - } - - // Get curve defined in PTau - if (logger) logger.info("> Getting curve from PTau settings"); - const {curve} = await readPTauHeader(fdPTau, pTauSections); - - // Read r1cs file - if (logger) logger.info("> Reading r1cs file"); - const {fd: fdR1cs, sections: sectionsR1cs} = await binFileUtils.readBinFile(r1csFilename, "r1cs", 1, 1 << 22, 1 << 24); - const r1cs = await r1csfile.readR1csFd(fdR1cs, sectionsR1cs, {loadConstraints: false, loadCustomGates: true}); - - // Potential error checks - if (r1cs.prime !== curve.r) { - throw new Error("r1cs curve does not match powers of tau ceremony curve"); - } - - // Initializations - const Fr = curve.Fr; - - const sFr = curve.Fr.n8; - const sG1 = curve.G1.F.n8 * 2; - const sG2 = curve.G2.F.n8 * 2; - - let polynomials = {}; - let evaluations = {}; - let PTau; - - let settings = { - nVars: r1cs.nVars, - nPublic: r1cs.nOutputs + r1cs.nPubInputs - }; - - const plonkConstraints = new BigArray(); - let plonkAdditions = new BigArray(); - - // Process constraints inside r1cs - if (logger) logger.info("> Processing FFlonk constraints"); - await computeFFConstraints(curve.Fr, r1cs, logger); - if (globalThis.gc) globalThis.gc(); - - // As the t polynomial is n+5 we need at least a power of 4 - //TODO check!!!! - // NOTE : plonkConstraints + 2 = #constraints + blinding coefficients for each wire polynomial - settings.cirPower = Math.max(FF_T_POL_DEG_MIN, log2((plonkConstraints.length + 2) - 1) + 1); - settings.domainSize = 2 ** settings.cirPower; - - if (pTauSections[2][0].size < (settings.domainSize * 9 + 18) * sG1) { - throw new Error("Powers of Tau is not big enough for this circuit size. Section 2 too small."); - } - if (pTauSections[3][0].size < sG2) { - throw new Error("Powers of Tau is not well prepared. Section 3 too small."); - } - - if (logger) { - logger.info("----------------------------"); - logger.info(" FFLONK SETUP SETTINGS"); - logger.info(` Curve: ${curve.name}`); - logger.info(` Circuit power: ${settings.cirPower}`); - logger.info(` Domain size: ${settings.domainSize}`); - logger.info(` Vars: ${settings.nVars}`); - logger.info(` Public vars: ${settings.nPublic}`); - logger.info(` Constraints: ${plonkConstraints.length}`); - logger.info(` Additions: ${plonkAdditions.length}`); - logger.info("----------------------------"); - } - - // Compute k1 and k2 to be used in the permutation checks - if (logger) logger.info("> computing k1 and k2"); - const [k1, k2] = computeK1K2(); - - // Compute omega 3 (w3) and omega 4 (w4) to be used in the prover and the verifier - // w3^3 = 1 and w4^4 = 1 - if (logger) logger.info("> computing w3"); - const w3 = computeW3(); - if (logger) logger.info("> computing w4"); - const w4 = computeW4(); - if (logger) logger.info("> computing w8"); - const w8 = computeW8(); - if (logger) logger.info("> computing wr"); - const wr = getOmegaCubicRoot(settings.cirPower, curve.Fr); - - // Write output zkey file - await writeZkeyFile(); - - await fdR1cs.close(); - await fdPTau.close(); - - if (logger) logger.info("FFLONK SETUP FINISHED"); - - return 0; - - async function computeFFConstraints(Fr, r1cs, logger) { - // Add public inputs and outputs - for (let i = 0; i < settings.nPublic; i++) { - plonkConstraints.push(getFFlonkConstantConstraint(i + 1, Fr)); - } - - // Add all constraints from r1cs file - const r1csProcessor = new r1csConstraintProcessor(Fr, getFFlonkConstantConstraint, getFFlonkAdditionConstraint, getFFlonkMultiplicationConstraint, logger); - - const bR1cs = await binFileUtils__namespace.readSection(fdR1cs, sectionsR1cs, 2); - let bR1csPos = 0; - for (let i = 0; i < r1cs.nConstraints; i++) { - if ((logger) && (i !== 0) && (i % 500000 === 0)) { - logger.info(` processing r1cs constraints ${i}/${r1cs.nConstraints}`); - } - const [constraints, additions] = r1csProcessor.processR1csConstraint(settings, ...readConstraint()); - - plonkConstraints.push(...constraints); - plonkAdditions.push(...additions); - } - - function readConstraint() { - const c = []; - c[0] = readLC(); - c[1] = readLC(); - c[2] = readLC(); - return c; - } - - function readLC() { - const lc = {}; - - const buffUL32 = bR1cs.slice(bR1csPos, bR1csPos + 4); - bR1csPos += 4; - const buffUL32V = new DataView(buffUL32.buffer); - const nIdx = buffUL32V.getUint32(0, true); - - const buff = bR1cs.slice(bR1csPos, bR1csPos + (4 + r1cs.n8) * nIdx); - bR1csPos += (4 + r1cs.n8) * nIdx; - const buffV = new DataView(buff.buffer); - for (let i = 0; i < nIdx; i++) { - const idx = buffV.getUint32(i * (4 + r1cs.n8), true); - const val = r1cs.F.fromRprLE(buff, i * (4 + r1cs.n8) + 4); - lc[idx] = val; - } - return lc; - } - - return 0; - } - - async function writeZkeyFile() { - if (logger) logger.info("> Writing the zkey file"); - const fdZKey = await binFileUtils.createBinFile(zkeyFilename, "zkey", 1, ZKEY_FF_NSECTIONS, 1 << 22, 1 << 24); - - if (logger) logger.info(`··· Writing Section ${HEADER_ZKEY_SECTION}. Zkey Header`); - await writeZkeyHeader(fdZKey); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_ADDITIONS_SECTION}. Additions`); - await writeAdditions(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_A_MAP_SECTION}. A Map`); - await writeWitnessMap(fdZKey, ZKEY_FF_A_MAP_SECTION, 0, "A map"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_B_MAP_SECTION}. B Map`); - await writeWitnessMap(fdZKey, ZKEY_FF_B_MAP_SECTION, 1, "B map"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_C_MAP_SECTION}. C Map`); - await writeWitnessMap(fdZKey, ZKEY_FF_C_MAP_SECTION, 2, "C map"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_QL_SECTION}. QL`); - await writeQMap(fdZKey, ZKEY_FF_QL_SECTION, 3, "QL"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_QR_SECTION}. QR`); - await writeQMap(fdZKey, ZKEY_FF_QR_SECTION, 4, "QR"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_QM_SECTION}. QM`); - await writeQMap(fdZKey, ZKEY_FF_QM_SECTION, 5, "QM"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_QO_SECTION}. QO`); - await writeQMap(fdZKey, ZKEY_FF_QO_SECTION, 6, "QO"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_QC_SECTION}. QC`); - await writeQMap(fdZKey, ZKEY_FF_QC_SECTION, 7, "QC"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Sections ${ZKEY_FF_SIGMA1_SECTION},${ZKEY_FF_SIGMA2_SECTION},${ZKEY_FF_SIGMA3_SECTION}. Sigma1, Sigma2 & Sigma 3`); - await writeSigma(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_LAGRANGE_SECTION}. Lagrange Polynomials`); - await writeLagrangePolynomials(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_PTAU_SECTION}. Powers of Tau`); - await writePtau(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_C0_SECTION}. C0`); - await writeC0(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_HEADER_SECTION}. FFlonk Header`); - await writeFFlonkHeader(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info("> Writing the zkey file finished"); - - await fdZKey.close(); - } - - async function writeZkeyHeader(fdZKey) { - await binFileUtils.startWriteSection(fdZKey, HEADER_ZKEY_SECTION); - await fdZKey.writeULE32(FFLONK_PROTOCOL_ID); - await binFileUtils.endWriteSection(fdZKey); - } - - async function writeAdditions(fdZKey) { - await binFileUtils.startWriteSection(fdZKey, ZKEY_FF_ADDITIONS_SECTION); - - // Written values are 2 * 32 bit integers (2 * 4 bytes) + 2 field size values ( 2 * sFr bytes) - const buffOut = new Uint8Array(8 + 2 * sFr); - const buffOutV = new DataView(buffOut.buffer); - - for (let i = 0; i < plonkAdditions.length; i++) { - if ((logger) && (i !== 0) && (i % 500000 === 0)) logger.info(` writing Additions: ${i}/${plonkAdditions.length}`); - - const addition = plonkAdditions[i]; - - buffOutV.setUint32(0, addition[0], true); - buffOutV.setUint32(4, addition[1], true); - buffOut.set(addition[2], 8); - buffOut.set(addition[3], 8 + sFr); - - await fdZKey.write(buffOut); - } - await binFileUtils.endWriteSection(fdZKey); - } - - async function writeWitnessMap(fdZKey, sectionNum, posConstraint, name) { - await binFileUtils.startWriteSection(fdZKey, sectionNum); - for (let i = 0; i < plonkConstraints.length; i++) { - if (logger && (i !== 0) && (i % 500000 === 0)) { - logger.info(` writing witness ${name}: ${i}/${plonkConstraints.length}`); - } - - await fdZKey.writeULE32(plonkConstraints[i][posConstraint]); - } - await binFileUtils.endWriteSection(fdZKey); - } - - async function writeQMap(fdZKey, sectionNum, posConstraint, name) { - // Compute Q from q evaluations - let Q = new ffjavascript.BigBuffer(settings.domainSize * sFr); - - for (let i = 0; i < plonkConstraints.length; i++) { - Q.set(plonkConstraints[i][posConstraint], i * sFr); - if ((logger) && (i !== 0) && (i % 500000 === 0)) { - logger.info(` writing ${name}: ${i}/${plonkConstraints.length}`); - } - } - - polynomials[name] = await Polynomial.fromEvaluations(Q, curve, logger); - evaluations[name] = await Evaluations.fromPolynomial(polynomials[name], 4, curve, logger); - - // Write Q coefficients and evaluations - await binFileUtils.startWriteSection(fdZKey, sectionNum); - await fdZKey.write(polynomials[name].coef); - await fdZKey.write(evaluations[name].eval); - await binFileUtils.endWriteSection(fdZKey); - } - - async function writeSigma(fdZKey) { - // Compute sigma - const sigma = new ffjavascript.BigBuffer(sFr * settings.domainSize * 3); - const lastSeen = new BigArray(settings.nVars); - const firstPos = new BigArray(settings.nVars); - - let w = Fr.one; - for (let i = 0; i < settings.domainSize; i++) { - if (i < plonkConstraints.length) { - buildSigma(plonkConstraints[i][0], i); - buildSigma(plonkConstraints[i][1], settings.domainSize + i); - buildSigma(plonkConstraints[i][2], settings.domainSize * 2 + i); - } else if (i < settings.domainSize - 2) { - buildSigma(0, i); - buildSigma(0, settings.domainSize + i); - buildSigma(0, settings.domainSize * 2 + i); - } else { - sigma.set(w, i * sFr); - sigma.set(Fr.mul(w, k1), (settings.domainSize + i) * sFr); - sigma.set(Fr.mul(w, k2), (settings.domainSize * 2 + i) * sFr); - } - - w = Fr.mul(w, Fr.w[settings.cirPower]); - - if ((logger) && (i !== 0) && (i % 500000 === 0)) { - logger.info(` writing sigma phase1: ${i}/${plonkConstraints.length}`); - } - } - - for (let i = 0; i < settings.nVars; i++) { - if (typeof firstPos[i] !== "undefined") { - sigma.set(lastSeen[i], firstPos[i] * sFr); - } else { - // throw new Error("Variable not used"); - console.log("Variable not used"); - } - if ((logger) && (i !== 0) && (i % 500000 === 0)) logger.info(` writing sigma phase2: ${i}/${settings.nVars}`); - } - - if (globalThis.gc) globalThis.gc(); - - // Write sigma coefficients and evaluations - for (let i = 0; i < 3; i++) { - const sectionId = 0 === i ? ZKEY_FF_SIGMA1_SECTION : 1 === i ? ZKEY_FF_SIGMA2_SECTION : ZKEY_FF_SIGMA3_SECTION; - - let name = "S" + (i + 1); - polynomials[name] = await Polynomial.fromEvaluations(sigma.slice(settings.domainSize * sFr * i, settings.domainSize * sFr * (i + 1)), curve, logger); - evaluations[name] = await Evaluations.fromPolynomial(polynomials[name], 4, curve, logger); - await binFileUtils.startWriteSection(fdZKey, sectionId); - await fdZKey.write(polynomials[name].coef); - await fdZKey.write(evaluations[name].eval); - await binFileUtils.endWriteSection(fdZKey); - - if (globalThis.gc) globalThis.gc(); - } - - return 0; - - function buildSigma(signalId, idx) { - if (typeof lastSeen[signalId] === "undefined") { - firstPos[signalId] = idx; - } else { - sigma.set(lastSeen[signalId], idx * sFr); - } - let v; - if (idx < settings.domainSize) { - v = w; - } else if (idx < 2 * settings.domainSize) { - v = Fr.mul(w, k1); - } else { - v = Fr.mul(w, k2); - } - - lastSeen[signalId] = v; - } - } - - async function writeLagrangePolynomials(fdZKey) { - await binFileUtils.startWriteSection(fdZKey, ZKEY_FF_LAGRANGE_SECTION); - - const l = Math.max(settings.nPublic, 1); - for (let i = 0; i < l; i++) { - let buff = new ffjavascript.BigBuffer(settings.domainSize * sFr); - buff.set(Fr.one, i * sFr); - - await writeP4(fdZKey, buff); - } - await binFileUtils.endWriteSection(fdZKey); - } - - async function writePtau(fdZKey) { - await binFileUtils.startWriteSection(fdZKey, ZKEY_FF_PTAU_SECTION); - - // domainSize * 9 + 18 = maximum SRS length needed, specifically to commit C2 - PTau = new ffjavascript.BigBuffer((settings.domainSize * 9 + 18) * sG1); - await fdPTau.readToBuffer(PTau, 0, (settings.domainSize * 9 + 18) * sG1, pTauSections[2][0].p); - - await fdZKey.write(PTau); - await binFileUtils.endWriteSection(fdZKey); - } - - async function writeC0(fdZKey) { - // C0(X) := QL(X^8) + X · QR(X^8) + X^2 · QO(X^8) + X^3 · QM(X^8) + X^4 · QC(X^8) - // + X^5 · SIGMA1(X^8) + X^6 · SIGMA2(X^8) + X^7 · SIGMA3(X^8) - let C0 = new CPolynomial(8, curve, logger); - C0.addPolynomial(0, polynomials.QL); - C0.addPolynomial(1, polynomials.QR); - C0.addPolynomial(2, polynomials.QO); - C0.addPolynomial(3, polynomials.QM); - C0.addPolynomial(4, polynomials.QC); - C0.addPolynomial(5, polynomials.S1); - C0.addPolynomial(6, polynomials.S2); - C0.addPolynomial(7, polynomials.S3); - - polynomials.C0 = C0.getPolynomial(); - - // Check degree - if (polynomials.C0.degree() >= 8 * settings.domainSize) { - throw new Error("C0 Polynomial is not well calculated"); - } - - await binFileUtils.startWriteSection(fdZKey, ZKEY_FF_C0_SECTION); - await fdZKey.write(polynomials.C0.coef); - await binFileUtils.endWriteSection(fdZKey); - } - - async function writeFFlonkHeader(fdZKey) { - await binFileUtils.startWriteSection(fdZKey, ZKEY_FF_HEADER_SECTION); - - const primeQ = curve.q; - const n8q = (Math.floor((ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) + 1) * 8; - await fdZKey.writeULE32(n8q); - await binFileUtils.writeBigInt(fdZKey, primeQ, n8q); - - const primeR = curve.r; - const n8r = (Math.floor((ffjavascript.Scalar.bitLength(primeR) - 1) / 64) + 1) * 8; - await fdZKey.writeULE32(n8r); - await binFileUtils.writeBigInt(fdZKey, primeR, n8r); - - // Total number of r1cs vars - await fdZKey.writeULE32(settings.nVars); - // Total number of r1cs public vars = outputs + public inputs - await fdZKey.writeULE32(settings.nPublic); - await fdZKey.writeULE32(settings.domainSize); - await fdZKey.writeULE32(plonkAdditions.length); - await fdZKey.writeULE32(plonkConstraints.length); - - await fdZKey.write(k1); - await fdZKey.write(k2); - - await fdZKey.write(w3); - await fdZKey.write(w4); - await fdZKey.write(w8); - await fdZKey.write(wr); - - let bX_2; - bX_2 = await fdPTau.read(sG2, pTauSections[3][0].p + sG2); - await fdZKey.write(bX_2); - - let commitC0 = await polynomials.C0.multiExponentiation(PTau, "C0"); - await fdZKey.write(commitC0); - - await binFileUtils.endWriteSection(fdZKey); - } - - async function writeP4(fdZKey, buff) { - const [coefficients, evaluations4] = await Polynomial.to4T(buff, settings.domainSize, [], Fr); - await fdZKey.write(coefficients); - await fdZKey.write(evaluations4); - - return [coefficients, evaluations4]; - } - - function computeK1K2() { - let k1 = Fr.two; - while (isIncluded(k1, [], settings.cirPower)) Fr.add(k1, Fr.one); - let k2 = Fr.add(k1, Fr.one); - while (isIncluded(k2, [k1], settings.cirPower)) Fr.add(k2, Fr.one); - return [k1, k2]; - - function isIncluded(k, kArr, pow) { - const domainSize = 2 ** pow; - let w = Fr.one; - for (let i = 0; i < domainSize; i++) { - if (Fr.eq(k, w)) return true; - for (let j = 0; j < kArr.length; j++) { - if (Fr.eq(k, Fr.mul(kArr[j], w))) return true; - } - w = Fr.mul(w, Fr.w[pow]); - } - return false; - } - } - - function computeW3() { - let generator = Fr.e(31624); - - // Exponent is order(r - 1) / 3 - let orderRsub1 = 3648040478639879203707734290876212514758060733402672390616367364429301415936n; - let exponent = ffjavascript.Scalar.div(orderRsub1, ffjavascript.Scalar.e(3)); - - return Fr.exp(generator, exponent); - } - - function computeW4() { - return Fr.w[2]; - } - - function computeW8() { - return Fr.w[3]; - } - - function getOmegaCubicRoot(power, Fr) { - // Hardcorded 3th-root of Fr.w[28] - const firstRoot = Fr.e(467799165886069610036046866799264026481344299079011762026774533774345988080n); - - return Fr.exp(firstRoot, 2 ** (28 - power)); - } -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -const { stringifyBigInts } = ffjavascript.utils; - - + if (logger) logger.info("FFLONK SETUP STARTED"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info("> Reading PTau file"); + const { fd: fdPTau, sections: pTauSections } = await (0, _iden3_binfileutils.readBinFile)(ptauFilename, "ptau", 1, 1 << 22, 1 << 24); + if (!pTauSections[12]) throw new Error("Powers of Tau is not well prepared. Section 12 missing."); + if (logger) logger.info("> Getting curve from PTau settings"); + const { curve } = await readPTauHeader(fdPTau, pTauSections); + if (logger) logger.info("> Reading r1cs file"); + const { fd: fdR1cs, sections: sectionsR1cs } = await (0, _iden3_binfileutils.readBinFile)(r1csFilename, "r1cs", 1, 1 << 22, 1 << 24); + const r1cs = await (0, r1csfile.readR1csFd)(fdR1cs, sectionsR1cs, { + loadConstraints: false, + loadCustomGates: true + }); + if (r1cs.prime !== curve.r) throw new Error("r1cs curve does not match powers of tau ceremony curve"); + const Fr = curve.Fr; + const sFr = curve.Fr.n8; + const sG1 = curve.G1.F.n8 * 2; + const sG2 = curve.G2.F.n8 * 2; + let polynomials = {}; + let evaluations = {}; + let PTau; + let settings = { + nVars: r1cs.nVars, + nPublic: r1cs.nOutputs + r1cs.nPubInputs + }; + const plonkConstraints = new BigArray(); + let plonkAdditions = new BigArray(); + if (logger) logger.info("> Processing FFlonk constraints"); + await computeFFConstraints(curve.Fr, r1cs, logger); + if (globalThis.gc) globalThis.gc(); + settings.cirPower = Math.max(3, log2(plonkConstraints.length + 2 - 1) + 1); + settings.domainSize = 2 ** settings.cirPower; + if (pTauSections[2][0].size < (settings.domainSize * 9 + 18) * sG1) throw new Error("Powers of Tau is not big enough for this circuit size. Section 2 too small."); + if (pTauSections[3][0].size < sG2) throw new Error("Powers of Tau is not well prepared. Section 3 too small."); + if (logger) { + logger.info("----------------------------"); + logger.info(" FFLONK SETUP SETTINGS"); + logger.info(` Curve: ${curve.name}`); + logger.info(` Circuit power: ${settings.cirPower}`); + logger.info(` Domain size: ${settings.domainSize}`); + logger.info(` Vars: ${settings.nVars}`); + logger.info(` Public vars: ${settings.nPublic}`); + logger.info(` Constraints: ${plonkConstraints.length}`); + logger.info(` Additions: ${plonkAdditions.length}`); + logger.info("----------------------------"); + } + if (logger) logger.info("> computing k1 and k2"); + const [k1, k2] = computeK1K2(); + if (logger) logger.info("> computing w3"); + const w3 = computeW3(); + if (logger) logger.info("> computing w4"); + const w4 = computeW4(); + if (logger) logger.info("> computing w8"); + const w8 = computeW8(); + if (logger) logger.info("> computing wr"); + const wr = getOmegaCubicRoot(settings.cirPower, curve.Fr); + await writeZkeyFile(); + await fdR1cs.close(); + await fdPTau.close(); + if (logger) logger.info("FFLONK SETUP FINISHED"); + return 0; + async function computeFFConstraints(Fr, r1cs, logger) { + for (let i = 0; i < settings.nPublic; i++) plonkConstraints.push(getFFlonkConstantConstraint(i + 1, Fr)); + const r1csProcessor = new r1csConstraintProcessor(Fr, getFFlonkConstantConstraint, getFFlonkAdditionConstraint, getFFlonkMultiplicationConstraint, logger); + const bR1cs = await _iden3_binfileutils.readSection(fdR1cs, sectionsR1cs, 2); + let bR1csPos = 0; + for (let i = 0; i < r1cs.nConstraints; i++) { + if (logger && i !== 0 && i % 5e5 === 0) logger.info(` processing r1cs constraints ${i}/${r1cs.nConstraints}`); + const [constraints, additions] = r1csProcessor.processR1csConstraint(settings, ...readConstraint()); + plonkConstraints.push(...constraints); + plonkAdditions.push(...additions); + } + function readConstraint() { + const c = []; + c[0] = readLC(); + c[1] = readLC(); + c[2] = readLC(); + return c; + } + function readLC() { + const lc = {}; + const buffUL32 = bR1cs.slice(bR1csPos, bR1csPos + 4); + bR1csPos += 4; + const nIdx = new DataView(buffUL32.buffer).getUint32(0, true); + const buff = bR1cs.slice(bR1csPos, bR1csPos + (4 + r1cs.n8) * nIdx); + bR1csPos += (4 + r1cs.n8) * nIdx; + const buffV = new DataView(buff.buffer); + for (let i = 0; i < nIdx; i++) { + const idx = buffV.getUint32(i * (4 + r1cs.n8), true); + lc[idx] = r1cs.F.fromRprLE(buff, i * (4 + r1cs.n8) + 4); + } + return lc; + } + return 0; + } + async function writeZkeyFile() { + if (logger) logger.info("> Writing the zkey file"); + const fdZKey = await (0, _iden3_binfileutils.createBinFile)(zkeyFilename, "zkey", 1, 17, 1 << 22, 1 << 24); + if (logger) logger.info(`··· Writing Section 1. Zkey Header`); + await writeZkeyHeader(fdZKey); + if (logger) logger.info(`··· Writing Section 3. Additions`); + await writeAdditions(fdZKey); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 4. A Map`); + await writeWitnessMap(fdZKey, 4, 0, "A map"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 5. B Map`); + await writeWitnessMap(fdZKey, 5, 1, "B map"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 6. C Map`); + await writeWitnessMap(fdZKey, 6, 2, "C map"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 7. QL`); + await writeQMap(fdZKey, 7, 3, "QL"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 8. QR`); + await writeQMap(fdZKey, 8, 4, "QR"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 9. QM`); + await writeQMap(fdZKey, 9, 5, "QM"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 10. QO`); + await writeQMap(fdZKey, 10, 6, "QO"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 11. QC`); + await writeQMap(fdZKey, 11, 7, "QC"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Sections 12,13,14. Sigma1, Sigma2 & Sigma 3`); + await writeSigma(fdZKey); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 15. Lagrange Polynomials`); + await writeLagrangePolynomials(fdZKey); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 16. Powers of Tau`); + await writePtau(fdZKey); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 17. C0`); + await writeC0(fdZKey); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 2. FFlonk Header`); + await writeFFlonkHeader(fdZKey); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info("> Writing the zkey file finished"); + await fdZKey.close(); + } + async function writeZkeyHeader(fdZKey) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 1); + await fdZKey.writeULE32(10); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeAdditions(fdZKey) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 3); + const buffOut = new Uint8Array(8 + 2 * sFr); + const buffOutV = new DataView(buffOut.buffer); + for (let i = 0; i < plonkAdditions.length; i++) { + if (logger && i !== 0 && i % 5e5 === 0) logger.info(` writing Additions: ${i}/${plonkAdditions.length}`); + const addition = plonkAdditions[i]; + buffOutV.setUint32(0, addition[0], true); + buffOutV.setUint32(4, addition[1], true); + buffOut.set(addition[2], 8); + buffOut.set(addition[3], 8 + sFr); + await fdZKey.write(buffOut); + } + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeWitnessMap(fdZKey, sectionNum, posConstraint, name) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); + for (let i = 0; i < plonkConstraints.length; i++) { + if (logger && i !== 0 && i % 5e5 === 0) logger.info(` writing witness ${name}: ${i}/${plonkConstraints.length}`); + await fdZKey.writeULE32(plonkConstraints[i][posConstraint]); + } + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeQMap(fdZKey, sectionNum, posConstraint, name) { + let Q = new ffjavascript.BigBuffer(settings.domainSize * sFr); + for (let i = 0; i < plonkConstraints.length; i++) { + Q.set(plonkConstraints[i][posConstraint], i * sFr); + if (logger && i !== 0 && i % 5e5 === 0) logger.info(` writing ${name}: ${i}/${plonkConstraints.length}`); + } + polynomials[name] = await Polynomial.fromEvaluations(Q, curve, logger); + evaluations[name] = await Evaluations.fromPolynomial(polynomials[name], 4, curve, logger); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); + await fdZKey.write(polynomials[name].coef); + await fdZKey.write(evaluations[name].eval); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeSigma(fdZKey) { + const sigma = new ffjavascript.BigBuffer(sFr * settings.domainSize * 3); + const lastSeen = new BigArray(settings.nVars); + const firstPos = new BigArray(settings.nVars); + let w = Fr.one; + for (let i = 0; i < settings.domainSize; i++) { + if (i < plonkConstraints.length) { + buildSigma(plonkConstraints[i][0], i); + buildSigma(plonkConstraints[i][1], settings.domainSize + i); + buildSigma(plonkConstraints[i][2], settings.domainSize * 2 + i); + } else if (i < settings.domainSize - 2) { + buildSigma(0, i); + buildSigma(0, settings.domainSize + i); + buildSigma(0, settings.domainSize * 2 + i); + } else { + sigma.set(w, i * sFr); + sigma.set(Fr.mul(w, k1), (settings.domainSize + i) * sFr); + sigma.set(Fr.mul(w, k2), (settings.domainSize * 2 + i) * sFr); + } + w = Fr.mul(w, Fr.w[settings.cirPower]); + if (logger && i !== 0 && i % 5e5 === 0) logger.info(` writing sigma phase1: ${i}/${plonkConstraints.length}`); + } + for (let i = 0; i < settings.nVars; i++) { + if (typeof firstPos[i] !== "undefined") sigma.set(lastSeen[i], firstPos[i] * sFr); + else console.log("Variable not used"); + if (logger && i !== 0 && i % 5e5 === 0) logger.info(` writing sigma phase2: ${i}/${settings.nVars}`); + } + if (globalThis.gc) globalThis.gc(); + for (let i = 0; i < 3; i++) { + const sectionId = 0 === i ? 12 : 1 === i ? 13 : 14; + let name = "S" + (i + 1); + polynomials[name] = await Polynomial.fromEvaluations(sigma.slice(settings.domainSize * sFr * i, settings.domainSize * sFr * (i + 1)), curve, logger); + evaluations[name] = await Evaluations.fromPolynomial(polynomials[name], 4, curve, logger); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionId); + await fdZKey.write(polynomials[name].coef); + await fdZKey.write(evaluations[name].eval); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + if (globalThis.gc) globalThis.gc(); + } + return 0; + function buildSigma(signalId, idx) { + if (typeof lastSeen[signalId] === "undefined") firstPos[signalId] = idx; + else sigma.set(lastSeen[signalId], idx * sFr); + let v; + if (idx < settings.domainSize) v = w; + else if (idx < 2 * settings.domainSize) v = Fr.mul(w, k1); + else v = Fr.mul(w, k2); + lastSeen[signalId] = v; + } + } + async function writeLagrangePolynomials(fdZKey) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 15); + const l = Math.max(settings.nPublic, 1); + for (let i = 0; i < l; i++) { + let buff = new ffjavascript.BigBuffer(settings.domainSize * sFr); + buff.set(Fr.one, i * sFr); + await writeP4(fdZKey, buff); + } + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writePtau(fdZKey) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 16); + PTau = new ffjavascript.BigBuffer((settings.domainSize * 9 + 18) * sG1); + await fdPTau.readToBuffer(PTau, 0, (settings.domainSize * 9 + 18) * sG1, pTauSections[2][0].p); + await fdZKey.write(PTau); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeC0(fdZKey) { + let C0 = new CPolynomial(8, curve, logger); + C0.addPolynomial(0, polynomials.QL); + C0.addPolynomial(1, polynomials.QR); + C0.addPolynomial(2, polynomials.QO); + C0.addPolynomial(3, polynomials.QM); + C0.addPolynomial(4, polynomials.QC); + C0.addPolynomial(5, polynomials.S1); + C0.addPolynomial(6, polynomials.S2); + C0.addPolynomial(7, polynomials.S3); + polynomials.C0 = C0.getPolynomial(); + if (polynomials.C0.degree() >= 8 * settings.domainSize) throw new Error("C0 Polynomial is not well calculated"); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 17); + await fdZKey.write(polynomials.C0.coef); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeFFlonkHeader(fdZKey) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 2); + const primeQ = curve.q; + const n8q = (Math.floor((ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) + 1) * 8; + await fdZKey.writeULE32(n8q); + await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeQ, n8q); + const primeR = curve.r; + const n8r = (Math.floor((ffjavascript.Scalar.bitLength(primeR) - 1) / 64) + 1) * 8; + await fdZKey.writeULE32(n8r); + await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeR, n8r); + await fdZKey.writeULE32(settings.nVars); + await fdZKey.writeULE32(settings.nPublic); + await fdZKey.writeULE32(settings.domainSize); + await fdZKey.writeULE32(plonkAdditions.length); + await fdZKey.writeULE32(plonkConstraints.length); + await fdZKey.write(k1); + await fdZKey.write(k2); + await fdZKey.write(w3); + await fdZKey.write(w4); + await fdZKey.write(w8); + await fdZKey.write(wr); + let bX_2; + bX_2 = await fdPTau.read(sG2, pTauSections[3][0].p + sG2); + await fdZKey.write(bX_2); + let commitC0 = await polynomials.C0.multiExponentiation(PTau, "C0"); + await fdZKey.write(commitC0); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeP4(fdZKey, buff) { + const [coefficients, evaluations4] = await Polynomial.to4T(buff, settings.domainSize, [], Fr); + await fdZKey.write(coefficients); + await fdZKey.write(evaluations4); + return [coefficients, evaluations4]; + } + function computeK1K2() { + let k1 = Fr.two; + while (isIncluded(k1, [], settings.cirPower)) Fr.add(k1, Fr.one); + let k2 = Fr.add(k1, Fr.one); + while (isIncluded(k2, [k1], settings.cirPower)) Fr.add(k2, Fr.one); + return [k1, k2]; + function isIncluded(k, kArr, pow) { + const domainSize = 2 ** pow; + let w = Fr.one; + for (let i = 0; i < domainSize; i++) { + if (Fr.eq(k, w)) return true; + for (let j = 0; j < kArr.length; j++) if (Fr.eq(k, Fr.mul(kArr[j], w))) return true; + w = Fr.mul(w, Fr.w[pow]); + } + return false; + } + } + function computeW3() { + let generator = Fr.e(31624); + let exponent = ffjavascript.Scalar.div(3648040478639879203707734290876212514758060733402672390616367364429301415936n, ffjavascript.Scalar.e(3)); + return Fr.exp(generator, exponent); + } + function computeW4() { + return Fr.w[2]; + } + function computeW8() { + return Fr.w[3]; + } + function getOmegaCubicRoot(power, Fr) { + const firstRoot = Fr.e(467799165886069610036046866799264026481344299079011762026774533774345988080n); + return Fr.exp(firstRoot, 2 ** (28 - power)); + } +} +//#endregion +//#region src/fflonk_prove.js +var { stringifyBigInts } = ffjavascript.utils; async function fflonkProve(zkeyFileName, witnessFileName, logger, options) { - if (logger) logger.info("FFLONK PROVER STARTED"); - - // Read witness file - if (logger) logger.info("> Reading witness file"); - const { - fd: fdWtns, - sections: wtnsSections - } = await binFileUtils__namespace.readBinFile(witnessFileName, "wtns", 2, 1 << 25, 1 << 23); - const wtns = await readHeader(fdWtns, wtnsSections); - - //Read zkey file - if (logger) logger.info("> Reading zkey file"); - const { - fd: fdZKey, - sections: zkeySections - } = await binFileUtils__namespace.readBinFile(zkeyFileName, "zkey", 2, 1 << 25, 1 << 23); - - const zkey = await readHeader$1(fdZKey, zkeySections, undefined, options); - - if (zkey.protocolId !== FFLONK_PROTOCOL_ID) { - throw new Error("zkey file is not fflonk"); - } - - if (!ffjavascript.Scalar.eq(zkey.r, wtns.q)) { - throw new Error("Curve of the witness does not match the curve of the proving key"); - } - - if (wtns.nWitness !== zkey.nVars - zkey.nAdditions) { - throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}, ${zkey.nAdditions}`); - } - - const curve = zkey.curve; - - const Fr = curve.Fr; - - const sFr = curve.Fr.n8; - const sG1 = curve.G1.F.n8 * 2; - const sDomain = zkey.domainSize * sFr; - - if (logger) { - logger.info("----------------------------"); - logger.info(" FFLONK PROVE SETTINGS"); - logger.info(` Curve: ${curve.name}`); - logger.info(` Circuit power: ${zkey.power}`); - logger.info(` Domain size: ${zkey.domainSize}`); - logger.info(` Vars: ${zkey.nVars}`); - logger.info(` Public vars: ${zkey.nPublic}`); - logger.info(` Constraints: ${zkey.nConstraints}`); - logger.info(` Additions: ${zkey.nAdditions}`); - logger.info("----------------------------"); - } - - //Read witness data - if (logger) logger.info("> Reading witness file data"); - const buffWitness = await binFileUtils__namespace.readSection(fdWtns, wtnsSections, 2); - await fdWtns.close(); - - // First element in plonk is not used and can be any value. (But always the same). - // We set it to zero to go faster in the exponentiations. - buffWitness.set(Fr.zero, 0); - const buffInternalWitness = new ffjavascript.BigBuffer(zkey.nAdditions * sFr); - - let buffers = {}; - let polynomials = {}; - let evaluations = {}; - - // To divide prime fields the Extended Euclidean Algorithm for computing modular inverses is needed. - // NOTE: This is the equivalent of compute 1/denominator and then multiply it by the numerator. - // The Extended Euclidean Algorithm is expensive in terms of computation. - // For the special case where we need to do many modular inverses, there's a simple mathematical trick - // that allows us to compute many inverses, called Montgomery batch inversion. - // More info: https://vitalik.ca/general/2018/07/21/starks_part_3.html - // Montgomery batch inversion reduces the n inverse computations to a single one - // To save this (single) inverse computation on-chain, will compute it in proving time and send it to the verifier. - // The verifier will have to check: - // 1) the denominator is correct multiplying by himself non-inverted -> a * 1/a == 1 - // 2) compute the rest of the denominators using the Montgomery batch inversion - // The inversions are: - // · denominator needed in step 8 and 9 of the verifier to multiply by 1/Z_H(xi) - // · denominator needed in step 10 and 11 of the verifier - // · denominator needed in the verifier when computing L_i^{S1}(X) and L_i^{S2}(X) - // · L_i i=1 to num public inputs, needed in step 6 and 7 of the verifier to compute L_1(xi) and PI(xi) - let toInverse = {}; - - let challenges = {}; - let roots = {}; - - let proof = new Proof(curve, logger); - - if (logger) logger.info(`> Reading Section ${ZKEY_FF_ADDITIONS_SECTION}. Additions`); - await calculateAdditions(); - - if (logger) logger.info(`> Reading Sections ${ZKEY_FF_SIGMA1_SECTION},${ZKEY_FF_SIGMA2_SECTION},${ZKEY_FF_SIGMA3_SECTION}. Sigma1, Sigma2 & Sigma 3`); - if (logger) logger.info("··· Reading Sigma polynomials "); - polynomials.Sigma1 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.Sigma2 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.Sigma3 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - - await fdZKey.readToBuffer(polynomials.Sigma1.coef, 0, sDomain, zkeySections[ZKEY_FF_SIGMA1_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.Sigma2.coef, 0, sDomain, zkeySections[ZKEY_FF_SIGMA2_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.Sigma3.coef, 0, sDomain, zkeySections[ZKEY_FF_SIGMA3_SECTION][0].p); - - if (logger) logger.info("··· Reading Sigma evaluations"); - evaluations.Sigma1 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.Sigma2 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.Sigma3 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - - await fdZKey.readToBuffer(evaluations.Sigma1.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_SIGMA1_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.Sigma2.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_SIGMA2_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.Sigma3.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_SIGMA3_SECTION][0].p + sDomain); - - if (logger) logger.info(`> Reading Section ${ZKEY_FF_PTAU_SECTION}. Powers of Tau`); - const PTau = new ffjavascript.BigBuffer(zkey.domainSize * 16 * sG1); - // domainSize * 9 + 18 = SRS length in the zkey saved in setup process. - // it corresponds to the maximum SRS length needed, specifically to commit C2 - // notice that the reserved buffers size is zkey.domainSize * 16 * sG1 because a power of two buffer size is needed - // the remaining buffer not filled from SRS are set to 0 - await fdZKey.readToBuffer(PTau, 0, (zkey.domainSize * 9 + 18) * sG1, zkeySections[ZKEY_FF_PTAU_SECTION][0].p); - - // START FFLONK PROVER PROTOCOL - if (globalThis.gc) globalThis.gc(); - - // ROUND 1. Compute C1(X) polynomial - if (logger) logger.info(""); - if (logger) logger.info("> ROUND 1"); - await round1(); - - delete polynomials.T0; - delete evaluations.QL; - delete evaluations.QR; - delete evaluations.QM; - delete evaluations.QO; - delete evaluations.QC; - if (globalThis.gc) globalThis.gc(); - - // ROUND 2. Compute C2(X) polynomial - if (logger) logger.info("> ROUND 2"); - await round2(); - - delete buffers.A; - delete buffers.B; - delete buffers.C; - delete evaluations.A; - delete evaluations.B; - delete evaluations.C; - delete evaluations.Sigma1; - delete evaluations.Sigma2; - delete evaluations.Sigma3; - delete evaluations.lagrange1; - delete evaluations.Z; - if (globalThis.gc) globalThis.gc(); - - // ROUND 3. Compute opening evaluations - if (logger) logger.info("> ROUND 3"); - await round3(); - - delete polynomials.A; - delete polynomials.B; - delete polynomials.C; - delete polynomials.Z; - delete polynomials.T1; - delete polynomials.T2; - delete polynomials.Sigma1; - delete polynomials.Sigma2; - delete polynomials.Sigma3; - delete polynomials.QL; - delete polynomials.QR; - delete polynomials.QM; - delete polynomials.QC; - delete polynomials.QO; - if (globalThis.gc) globalThis.gc(); - - // ROUND 4. Compute W(X) polynomial - if (logger) logger.info("> ROUND 4"); - await round4(); - if (globalThis.gc) globalThis.gc(); - - // ROUND 5. Compute W'(X) polynomial - if (logger) logger.info("> ROUND 5"); - await round5(); - - delete polynomials.C0; - delete polynomials.C1; - delete polynomials.C2; - delete polynomials.R1; - delete polynomials.R2; - delete polynomials.F; - delete polynomials.L; - delete polynomials.ZT; - delete polynomials.ZTS2; - await fdZKey.close(); - if (globalThis.gc) globalThis.gc(); - - proof.addEvaluation("inv", getMontgomeryBatchedInverse()); - - // Prepare proof - let _proof = proof.toObjectProof(); - _proof.protocol = "fflonk"; - _proof.curve = curve.name; - - // Prepare public inputs - let publicSignals = []; - - for (let i = 1; i <= zkey.nPublic; i++) { - const i_sFr = i * sFr; - - const pub = buffWitness.slice(i_sFr, i_sFr + sFr); - publicSignals.push(ffjavascript.Scalar.fromRprLE(pub)); - } - - if (logger) logger.info("FFLONK PROVER FINISHED"); - - return { - proof: stringifyBigInts(_proof), - publicSignals: stringifyBigInts(publicSignals) - }; - - async function calculateAdditions() { - if (logger) logger.info("··· Computing additions"); - const additionsBuff = await binFileUtils__namespace.readSection(fdZKey, zkeySections, ZKEY_FF_ADDITIONS_SECTION); - - // sizes: wireId_x = 4 bytes (32 bits), factor_x = field size bits - // Addition form: wireId_a wireId_b factor_a factor_b (size is 4 + 4 + sFr + sFr) - const sSum = 8 + sFr * 2; - - for (let i = 0; i < zkey.nAdditions; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.info(` addition ${i}/${zkey.nAdditions}`); - - // Read addition values - let offset = i * sSum; - const signalId1 = readUInt32(additionsBuff, offset); - offset += 4; - const signalId2 = readUInt32(additionsBuff, offset); - offset += 4; - const factor1 = additionsBuff.slice(offset, offset + sFr); - offset += sFr; - const factor2 = additionsBuff.slice(offset, offset + sFr); - - // Get witness value - const witness1 = getWitness(signalId1); - const witness2 = getWitness(signalId2); - - //Calculate final result - const result = Fr.add(Fr.mul(factor1, witness1), Fr.mul(factor2, witness2)); - - buffInternalWitness.set(result, sFr * i); - } - } - - function readUInt32(b, o) { - const buff = b.slice(o, o + 4); - const buffV = new DataView(buff.buffer, buff.byteOffset, buff.byteLength); - return buffV.getUint32(0, true); - } - - function getWitness(idx) { - let diff = zkey.nVars - zkey.nAdditions; - if (idx < diff) { - return buffWitness.slice(idx * sFr, idx * sFr + sFr); - } else if (idx < zkey.nVars) { - const offset = (idx - diff) * sFr; - return buffInternalWitness.slice(offset, offset + sFr); - } - - return Fr.zero; - } - - async function round1() { - // STEP 1.1 - Generate random blinding scalars (b_1, ..., b9) ∈ F - challenges.b = []; - for (let i = 1; i <= 9; i++) { - challenges.b[i] = Fr.random(); - } - - // STEP 1.2 - Compute wire polynomials a(X), b(X) and c(X) - if (logger) logger.info("> Computing A, B, C wire polynomials"); - await computeWirePolynomials(); - - // STEP 1.3 - Compute the quotient polynomial T0(X) - if (logger) logger.info("> Computing T0 polynomial"); - await computeT0(); - - // STEP 1.4 - Compute the FFT-style combination polynomial C1(X) - if (logger) logger.info("> Computing C1 polynomial"); - await computeC1(); - - // The first output of the prover is ([C1]_1) - if (logger) logger.info("> Computing C1 multi exponentiation"); - let commitC1 = await polynomials.C1.multiExponentiation(PTau, "C1"); - proof.addPolynomial("C1", commitC1); - - return 0; - - async function computeWirePolynomials() { - if (logger) logger.info("··· Reading data from zkey file"); - // Build A, B and C evaluations buffer from zkey and witness files - buffers.A = new ffjavascript.BigBuffer(sDomain); - buffers.B = new ffjavascript.BigBuffer(sDomain); - buffers.C = new ffjavascript.BigBuffer(sDomain); - - // Read zkey sections and fill the buffers - const aMapBuff = await binFileUtils__namespace.readSection(fdZKey, zkeySections, ZKEY_FF_A_MAP_SECTION); - const bMapBuff = await binFileUtils__namespace.readSection(fdZKey, zkeySections, ZKEY_FF_B_MAP_SECTION); - const cMapBuff = await binFileUtils__namespace.readSection(fdZKey, zkeySections, ZKEY_FF_C_MAP_SECTION); - - // Compute all witness from signal ids and set them to A,B & C buffers - for (let i = 0; i < zkey.nConstraints; i++) { - const i_sFr = i * sFr; - const offset = i * 4; - - // Compute A value from a signal id - const signalIdA = readUInt32(aMapBuff, offset); - buffers.A.set(getWitness(signalIdA), i_sFr); - - // Compute B value from a signal id - const signalIdB = readUInt32(bMapBuff, offset); - buffers.B.set(getWitness(signalIdB), i_sFr); - - // Compute C value from a signal id - const signalIdC = readUInt32(cMapBuff, offset); - buffers.C.set(getWitness(signalIdC), i_sFr); - } - - // Blind a(X), b(X) and c(X) polynomials coefficients with blinding scalars b - buffers.A.set(challenges.b[1], sDomain - 64); - buffers.A.set(challenges.b[2], sDomain - 32); - buffers.B.set(challenges.b[3], sDomain - 64); - buffers.B.set(challenges.b[4], sDomain - 32); - buffers.C.set(challenges.b[5], sDomain - 64); - buffers.C.set(challenges.b[6], sDomain - 32); - - buffers.A = await Fr.batchToMontgomery(buffers.A); - buffers.B = await Fr.batchToMontgomery(buffers.B); - buffers.C = await Fr.batchToMontgomery(buffers.C); - - // Compute the coefficients of the wire polynomials a(X), b(X) and c(X) from A,B & C buffers - if (logger) logger.info("··· Computing A ifft"); - polynomials.A = await Polynomial.fromEvaluations(buffers.A, curve, logger); - if (logger) logger.info("··· Computing B ifft"); - polynomials.B = await Polynomial.fromEvaluations(buffers.B, curve, logger); - if (logger) logger.info("··· Computing C ifft"); - polynomials.C = await Polynomial.fromEvaluations(buffers.C, curve, logger); - - // Compute extended evaluations of a(X), b(X) and c(X) polynomials - if (logger) logger.info("··· Computing A fft"); - evaluations.A = await Evaluations.fromPolynomial(polynomials.A, 4, curve, logger); - if (logger) logger.info("··· Computing B fft"); - evaluations.B = await Evaluations.fromPolynomial(polynomials.B, 4, curve, logger); - if (logger) logger.info("··· Computing C fft"); - evaluations.C = await Evaluations.fromPolynomial(polynomials.C, 4, curve, logger); - - // Check degrees - if (polynomials.A.degree() >= zkey.domainSize) { - throw new Error("A Polynomial is not well calculated"); - } - if (polynomials.B.degree() >= zkey.domainSize) { - throw new Error("B Polynomial is not well calculated"); - } - if (polynomials.C.degree() >= zkey.domainSize) { - throw new Error("C Polynomial is not well calculated"); - } - } - - async function computeT0() { - if (logger) logger.info(`··· Reading sections ${ZKEY_FF_QL_SECTION}, ${ZKEY_FF_QR_SECTION}` + - `, ${ZKEY_FF_QM_SECTION}, ${ZKEY_FF_QO_SECTION}, ${ZKEY_FF_QC_SECTION}. Q selectors`); - // Reserve memory for Q's evaluations - evaluations.QL = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QR = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QM = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QO = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QC = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - - // Read Q's evaluations from zkey file - await fdZKey.readToBuffer(evaluations.QL.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_QL_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QR.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_QR_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QM.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_QM_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QO.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_QO_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QC.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_QC_SECTION][0].p + sDomain); - - // Read Lagrange polynomials & evaluations from zkey file - const lagrangePolynomials = await binFileUtils__namespace.readSection(fdZKey, zkeySections, ZKEY_FF_LAGRANGE_SECTION); - evaluations.lagrange1 = new Evaluations(lagrangePolynomials, curve, logger); - - // Reserve memory for buffers T0 - buffers.T0 = new ffjavascript.BigBuffer(sDomain * 4); - - if (logger) logger.info("··· Computing T0 evaluations"); - for (let i = 0; i < zkey.domainSize * 4; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.info(` T0 evaluation ${i}/${zkey.domainSize * 4}`); - - // Get related evaluations to compute current T0 evaluation - const a = evaluations.A.getEvaluation(i); - const b = evaluations.B.getEvaluation(i); - const c = evaluations.C.getEvaluation(i); - - const ql = evaluations.QL.getEvaluation(i); - const qr = evaluations.QR.getEvaluation(i); - const qm = evaluations.QM.getEvaluation(i); - const qo = evaluations.QO.getEvaluation(i); - const qc = evaluations.QC.getEvaluation(i); - - // Compute current public input - let pi = Fr.zero; - for (let j = 0; j < zkey.nPublic; j++) { - const offset = (j * 5 * zkey.domainSize) + zkey.domainSize + i; - - const lPol = evaluations.lagrange1.getEvaluation(offset); - const aVal = buffers.A.slice(j * sFr, (j + 1) * sFr); - - pi = Fr.sub(pi, Fr.mul(lPol, aVal)); - } - - //T0(X) = [q_L(X)·a(X) + q_R(X)·b(X) + q_M(X)·a(X)·b(X) + q_O(X)·c(X) + q_C(X) + PI(X)] · 1/Z_H(X) - // Compute first T0(X)·Z_H(X), so divide later the resulting polynomial by Z_H(X) - // expression 1 -> q_L(X)·a(X) - const e1 = Fr.mul(a, ql); - - // expression 2 -> q_R(X)·b(X) - const e2 = Fr.mul(b, qr); - - // expression 3 -> q_M(X)·a(X)·b(X) - const e3 = Fr.mul(Fr.mul(a, b), qm); - - // expression 4 -> q_O(X)·c(X) - const e4 = Fr.mul(c, qo); - - // t0 = expressions 1 + expression 2 + expression 3 + expression 4 + qc + pi - const t0 = Fr.add(e1, Fr.add(e2, Fr.add(e3, Fr.add(e4, Fr.add(qc, pi))))); - - buffers.T0.set(t0, i * sFr); - } - - if (logger) logger.info("buffer T0: " + buffers.T0.byteLength / sFr); - - // Compute the coefficients of the polynomial T0(X) from buffers.T0 - if (logger) logger.info("··· Computing T0 ifft"); - polynomials.T0 = await Polynomial.fromEvaluations(buffers.T0, curve, logger); - - if (logger) logger.info("T0 length: " + polynomials.T0.length()); - if (logger) logger.info("T0 degree: " + polynomials.T0.degree()); - - // Divide the polynomial T0 by Z_H(X) - if (logger) logger.info("··· Computing T0 / ZH"); - polynomials.T0.divByZerofier(zkey.domainSize, Fr.one); - - // Check degree - if (polynomials.T0.degree() >= 2 * zkey.domainSize - 2) { - throw new Error(`T0 Polynomial is not well calculated (degree is ${polynomials.T0.degree()} and must be less than ${2 * zkey.domainSize + 2}`); - } - - delete buffers.T0; - } - - async function computeC1() { - let C1 = new CPolynomial(4, curve, logger); - C1.addPolynomial(0, polynomials.A); - C1.addPolynomial(1, polynomials.B); - C1.addPolynomial(2, polynomials.C); - C1.addPolynomial(3, polynomials.T0); - - polynomials.C1 = C1.getPolynomial(); - - // Check degree - if (polynomials.C1.degree() >= 8 * zkey.domainSize - 8) { - throw new Error("C1 Polynomial is not well calculated"); - } - } - } - - async function round2() { - // STEP 2.1 - Compute permutation challenge beta and gamma ∈ F - // Compute permutation challenge beta - if (logger) logger.info("> Computing challenges beta and gamma"); - const transcript = new Keccak256Transcript(curve); - - // Add C0 to the transcript - transcript.addPolCommitment(zkey.C0); - - // Add A to the transcript - for (let i = 0; i < zkey.nPublic; i++) { - transcript.addScalar(buffers.A.slice(i * sFr, i * sFr + sFr)); - } - - // Add C1 to the transcript - transcript.addPolCommitment(proof.getPolynomial("C1")); - - challenges.beta = transcript.getChallenge(); - if (logger) logger.info("··· challenges.beta: " + Fr.toString(challenges.beta)); - - // Compute permutation challenge gamma - transcript.reset(); - transcript.addScalar(challenges.beta); - challenges.gamma = transcript.getChallenge(); - if (logger) logger.info("··· challenges.gamma: " + Fr.toString(challenges.gamma)); - - // STEP 2.2 - Compute permutation polynomial z(X) - if (logger) logger.info("> Computing Z polynomial"); - await computeZ(); - - // STEP 2.3 - Compute quotient polynomial T1(X) and T2(X) - if (logger) logger.info("> Computing T1 polynomial"); - await computeT1(); - if (logger) logger.info("> Computing T2 polynomial"); - await computeT2(); - - // STEP 2.4 - Compute the FFT-style combination polynomial C2(X) - if (logger) logger.info("> Computing C2 polynomial"); - await computeC2(); - - // The second output of the prover is ([C2]_1) - if (logger) logger.info("> Computing C2 multi exponentiation"); - let commitC2 = await polynomials.C2.multiExponentiation(PTau, "C2"); - proof.addPolynomial("C2", commitC2); - - return 0; - - async function computeZ() { - if (logger) logger.info("··· Computing Z evaluations"); - - let numArr = new ffjavascript.BigBuffer(sDomain); - let denArr = new ffjavascript.BigBuffer(sDomain); - - // Set the first values to 1 - numArr.set(Fr.one, 0); - denArr.set(Fr.one, 0); - - // Set initial omega - let w = Fr.one; - for (let i = 0; i < zkey.domainSize; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.info(` Z evaluation ${i}/${zkey.domainSize}`); - const i_sFr = i * sFr; - - // Z(X) := numArr / denArr - // numArr := (a + beta·ω + gamma)(b + beta·ω·k1 + gamma)(c + beta·ω·k2 + gamma) - const betaw = Fr.mul(challenges.beta, w); - - let num1 = buffers.A.slice(i_sFr, i_sFr + sFr); - num1 = Fr.add(num1, betaw); - num1 = Fr.add(num1, challenges.gamma); - - let num2 = buffers.B.slice(i_sFr, i_sFr + sFr); - num2 = Fr.add(num2, Fr.mul(zkey.k1, betaw)); - num2 = Fr.add(num2, challenges.gamma); - - let num3 = buffers.C.slice(i_sFr, i_sFr + sFr); - num3 = Fr.add(num3, Fr.mul(zkey.k2, betaw)); - num3 = Fr.add(num3, challenges.gamma); - - let num = Fr.mul(num1, Fr.mul(num2, num3)); - - // denArr := (a + beta·sigma1 + gamma)(b + beta·sigma2 + gamma)(c + beta·sigma3 + gamma) - let den1 = buffers.A.slice(i_sFr, i_sFr + sFr); - den1 = Fr.add(den1, Fr.mul(challenges.beta, evaluations.Sigma1.getEvaluation(i * 4))); - den1 = Fr.add(den1, challenges.gamma); - - let den2 = buffers.B.slice(i_sFr, i_sFr + sFr); - den2 = Fr.add(den2, Fr.mul(challenges.beta, evaluations.Sigma2.getEvaluation(i * 4))); - den2 = Fr.add(den2, challenges.gamma); - - let den3 = buffers.C.slice(i_sFr, i_sFr + sFr); - den3 = Fr.add(den3, Fr.mul(challenges.beta, evaluations.Sigma3.getEvaluation(i * 4))); - den3 = Fr.add(den3, challenges.gamma); - - let den = Fr.mul(den1, Fr.mul(den2, den3)); - - // Multiply current num value with the previous one saved in numArr - num = Fr.mul(numArr.slice(i_sFr, i_sFr + sFr), num); - numArr.set(num, ((i + 1) % zkey.domainSize) * sFr); - - // Multiply current den value with the previous one saved in denArr - den = Fr.mul(denArr.slice(i_sFr, i_sFr + sFr), den); - denArr.set(den, ((i + 1) % zkey.domainSize) * sFr); - - // Next omega - w = Fr.mul(w, Fr.w[zkey.power]); - } - // Compute the inverse of denArr to compute in the next command the - // division numArr/denArr by multiplying num · 1/denArr - denArr = await Fr.batchInverse(denArr); - - // TODO: Do it in assembly and in parallel - // Multiply numArr · denArr where denArr was inverted in the previous command - for (let i = 0; i < zkey.domainSize; i++) { - const i_sFr = i * sFr; - - const z = Fr.mul(numArr.slice(i_sFr, i_sFr + sFr), denArr.slice(i_sFr, i_sFr + sFr)); - numArr.set(z, i_sFr); - } - // From now on the values saved on numArr will be Z(X) buffer - buffers.Z = numArr; - - if (!Fr.eq(numArr.slice(0, sFr), Fr.one)) { - throw new Error("Copy constraints does not match"); - } - - // Compute polynomial coefficients z(X) from buffers.Z - if (logger) logger.info("··· Computing Z ifft"); - polynomials.Z = await Polynomial.fromEvaluations(buffers.Z, curve, logger); - - // Compute extended evaluations of z(X) polynomial - if (logger) logger.info("··· Computing Z fft"); - evaluations.Z = await Evaluations.fromPolynomial(polynomials.Z, 4, curve, logger); - - // Blind z(X) polynomial coefficients with blinding scalars b - polynomials.Z.blindCoefficients([challenges.b[9], challenges.b[8], challenges.b[7]]); - - // Check degree - if (polynomials.Z.degree() >= zkey.domainSize + 3) { - throw new Error("Z Polynomial is not well calculated"); - } - - delete buffers.Z; - } - - async function computeT1() { - if (logger) logger.info("··· Computing T1 evaluations"); - - buffers.T1 = new ffjavascript.BigBuffer(sDomain * 2); - buffers.T1z = new ffjavascript.BigBuffer(sDomain * 2); - - // Set initial omega - let omega = Fr.one; - for (let i = 0; i < zkey.domainSize * 2; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.info(` T1 evaluation ${i}/${zkey.domainSize * 4}`); - - const omega2 = Fr.square(omega); - - const z = evaluations.Z.getEvaluation(i * 2); - const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omega2), Fr.mul(challenges.b[8], omega)), challenges.b[9]); - - // T1(X) := (z(X) - 1) · L_1(X) - // Compute first T1(X)·Z_H(X), so divide later the resulting polynomial by Z_H(X) - const lagrange1 = evaluations.lagrange1.getEvaluation(zkey.domainSize + i * 2); - let t1 = Fr.mul(Fr.sub(z, Fr.one), lagrange1); - let t1z = Fr.mul(zp, lagrange1); - - buffers.T1.set(t1, i * sFr); - buffers.T1z.set(t1z, i * sFr); - - // Compute next omega - omega = Fr.mul(omega, Fr.w[zkey.power + 1]); - } - - // Compute the coefficients of the polynomial T1(X) from buffers.T1 - if (logger) logger.info("··· Computing T1 ifft"); - polynomials.T1 = await Polynomial.fromEvaluations(buffers.T1, curve, logger); - - // Divide the polynomial T1 by Z_H(X) - polynomials.T1.divByZerofier(zkey.domainSize, Fr.one); - - // Compute the coefficients of the polynomial T1z(X) from buffers.T1z - if (logger) logger.info("··· Computing T1z ifft"); - polynomials.T1z = await Polynomial.fromEvaluations(buffers.T1z, curve, logger); - - // Add the polynomial T1z to T1 to get the final polynomial T1 - polynomials.T1.add(polynomials.T1z); - - // Check degree - if (polynomials.T1.degree() >= zkey.domainSize + 2) { - throw new Error("T1 Polynomial is not well calculated"); - } - - delete buffers.T1; - delete buffers.T1z; - delete polynomials.T1z; - } - - async function computeT2() { - if (logger) logger.info("··· Computing T2 evaluations"); - - buffers.T2 = new ffjavascript.BigBuffer(sDomain * 4); - buffers.T2z = new ffjavascript.BigBuffer(sDomain * 4); - - // Set initial omega - let omega = Fr.one; - for (let i = 0; i < zkey.domainSize * 4; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.info(` T2 evaluation ${i}/${zkey.domainSize * 4}`); - - const omega2 = Fr.square(omega); - const omegaW = Fr.mul(omega, Fr.w[zkey.power]); - const omegaW2 = Fr.square(omegaW); - - const a = evaluations.A.getEvaluation(i); - const b = evaluations.B.getEvaluation(i); - const c = evaluations.C.getEvaluation(i); - const z = evaluations.Z.getEvaluation(i); - const zW = evaluations.Z.getEvaluation((zkey.domainSize * 4 + 4 + i) % (zkey.domainSize * 4)); - - const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omega2), Fr.mul(challenges.b[8], omega)), challenges.b[9]); - const zWp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omegaW2), Fr.mul(challenges.b[8], omegaW)), challenges.b[9]); - - const sigma1 = evaluations.Sigma1.getEvaluation(i); - const sigma2 = evaluations.Sigma2.getEvaluation(i); - const sigma3 = evaluations.Sigma3.getEvaluation(i); - - // T2(X) := [ (a(X) + beta·X + gamma)(b(X) + beta·k1·X + gamma)(c(X) + beta·k2·X + gamma)z(X) - // -(a(X) + beta·sigma1(X) + gamma)(b(X) + beta·sigma2(X) + gamma)(c(X) + beta·sigma3(X) + gamma)z(Xω)] · 1/Z_H(X) - // Compute first T2(X)·Z_H(X), so divide later the resulting polynomial by Z_H(X) - - // expression 1 -> (a(X) + beta·X + gamma)(b(X) + beta·k1·X + gamma)(c(X) + beta·k2·X + gamma)z(X) - const betaX = Fr.mul(challenges.beta, omega); - - let e11 = Fr.add(a, betaX); - e11 = Fr.add(e11, challenges.gamma); - - let e12 = Fr.add(b, Fr.mul(betaX, zkey.k1)); - e12 = Fr.add(e12, challenges.gamma); - - let e13 = Fr.add(c, Fr.mul(betaX, zkey.k2)); - e13 = Fr.add(e13, challenges.gamma); - - let e1 = Fr.mul(Fr.mul(Fr.mul(e11, e12), e13), z); - let e1z = Fr.mul(Fr.mul(Fr.mul(e11, e12), e13), zp); - // const [e1, e1z] = MulZ.mul4(e11, e12, e13, z, ap, bp, cp, zp, i % 4, Fr); - - // expression 2 -> (a(X) + beta·sigma1(X) + gamma)(b(X) + beta·sigma2(X) + gamma)(c(X) + beta·sigma3(X) + gamma)z(Xω) - let e21 = Fr.add(a, Fr.mul(challenges.beta, sigma1)); - e21 = Fr.add(e21, challenges.gamma); - - let e22 = Fr.add(b, Fr.mul(challenges.beta, sigma2)); - e22 = Fr.add(e22, challenges.gamma); - - let e23 = Fr.add(c, Fr.mul(challenges.beta, sigma3)); - e23 = Fr.add(e23, challenges.gamma); - - let e2 = Fr.mul(Fr.mul(Fr.mul(e21, e22), e23), zW); - let e2z = Fr.mul(Fr.mul(Fr.mul(e21, e22), e23), zWp); - // const [e2, e2z] = MulZ.mul4(e21, e22, e23, zW, ap, bp, cp, zWp, i % 4, Fr); - - let t2 = Fr.sub(e1, e2); - let t2z = Fr.sub(e1z, e2z); - - buffers.T2.set(t2, i * sFr); - buffers.T2z.set(t2z, i * sFr); - - // Compute next omega - omega = Fr.mul(omega, Fr.w[zkey.power + 2]); - } - - // Compute the coefficients of the polynomial T2(X) from buffers.T2 - if (logger) logger.info("··· Computing T2 ifft"); - polynomials.T2 = await Polynomial.fromEvaluations(buffers.T2, curve, logger); - - // Divide the polynomial T2 by Z_H(X) - if (logger) logger.info("··· Computing T2 / ZH"); - polynomials.T2.divByZerofier(zkey.domainSize, Fr.one); - - // Compute the coefficients of the polynomial T2z(X) from buffers.T2z - if (logger) logger.info("··· Computing T2z ifft"); - polynomials.T2z = await Polynomial.fromEvaluations(buffers.T2z, curve, logger); - - // Add the polynomial T2z to T2 to get the final polynomial T2 - polynomials.T2.add(polynomials.T2z); - - // Check degree - if (polynomials.T2.degree() >= 3 * zkey.domainSize) { - throw new Error("T2 Polynomial is not well calculated"); - } - - delete buffers.T2; - delete buffers.T2z; - delete polynomials.T2z; - } - - async function computeC2() { - let C2 = new CPolynomial(3, curve, logger); - C2.addPolynomial(0, polynomials.Z); - C2.addPolynomial(1, polynomials.T1); - C2.addPolynomial(2, polynomials.T2); - - polynomials.C2 = C2.getPolynomial(); - - // Check degree - if (polynomials.C2.degree() >= 9 * zkey.domainSize) { - throw new Error("C2 Polynomial is not well calculated"); - } - } - } - - async function round3() { - if (logger) logger.info("> Computing challenge xi"); - // STEP 3.1 - Compute evaluation challenge xi ∈ S - const transcript = new Keccak256Transcript(curve); - transcript.addScalar(challenges.gamma); - transcript.addPolCommitment(proof.getPolynomial("C2")); - - // Obtain a xi_seeder from the transcript - // To force h1^4 = xi, h2^3 = xi and h_3^2 = xiω - // we compute xi = xi_seeder^12, h1 = xi_seeder^3, h2 = xi_seeder^4 and h3 = xi_seeder^6 - challenges.xiSeed = transcript.getChallenge(); - const xiSeed2 = Fr.square(challenges.xiSeed); - - // Compute omega8, omega4 and omega3 - roots.w8 = []; - roots.w8[0] = Fr.one; - for (let i = 1; i < 8; i++) { - roots.w8[i] = Fr.mul(roots.w8[i - 1], zkey.w8); - } - - roots.w4 = []; - roots.w4[0] = Fr.one; - for (let i = 1; i < 4; i++) { - roots.w4[i] = Fr.mul(roots.w4[i - 1], zkey.w4); - } - - roots.w3 = []; - roots.w3[0] = Fr.one; - roots.w3[1] = zkey.w3; - roots.w3[2] = Fr.square(zkey.w3); - - // Compute h0 = xiSeeder^3 - roots.S0 = {}; - roots.S0.h0w8 = []; - roots.S0.h0w8[0] = Fr.mul(xiSeed2, challenges.xiSeed); - for (let i = 1; i < 8; i++) { - roots.S0.h0w8[i] = Fr.mul(roots.S0.h0w8[0], roots.w8[i]); - } - - // Compute h1 = xi_seeder^6 - roots.S1 = {}; - roots.S1.h1w4 = []; - roots.S1.h1w4[0] = Fr.square(roots.S0.h0w8[0]); - for (let i = 1; i < 4; i++) { - roots.S1.h1w4[i] = Fr.mul(roots.S1.h1w4[0], roots.w4[i]); - } - - // Compute h2 = xi_seeder^8 - roots.S2 = {}; - roots.S2.h2w3 = []; - roots.S2.h2w3[0] = Fr.mul(roots.S1.h1w4[0], xiSeed2); - roots.S2.h2w3[1] = Fr.mul(roots.S2.h2w3[0], roots.w3[1]); - roots.S2.h2w3[2] = Fr.mul(roots.S2.h2w3[0], roots.w3[2]); - - roots.S2.h3w3 = []; - // Multiply h3 by third-root-omega to obtain h_3^3 = xiω - // So, h3 = xi_seeder^8 ω^{1/3} - roots.S2.h3w3[0] = Fr.mul(roots.S2.h2w3[0], zkey.wr); - roots.S2.h3w3[1] = Fr.mul(roots.S2.h3w3[0], roots.w3[1]); - roots.S2.h3w3[2] = Fr.mul(roots.S2.h3w3[0], roots.w3[2]); - - // Compute xi = xi_seeder^24 - challenges.xi = Fr.mul(Fr.square(roots.S2.h2w3[0]), roots.S2.h2w3[0]); - - if (logger) logger.info("··· challenges.xi: " + Fr.toString(challenges.xi)); - - // Reserve memory for Q's polynomials - polynomials.QL = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QR = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QM = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QO = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QC = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - - // Read Q's evaluations from zkey file - await fdZKey.readToBuffer(polynomials.QL.coef, 0, sDomain, zkeySections[ZKEY_FF_QL_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QR.coef, 0, sDomain, zkeySections[ZKEY_FF_QR_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QM.coef, 0, sDomain, zkeySections[ZKEY_FF_QM_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QO.coef, 0, sDomain, zkeySections[ZKEY_FF_QO_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QC.coef, 0, sDomain, zkeySections[ZKEY_FF_QC_SECTION][0].p); - - // STEP 3.2 - Compute opening evaluations and add them to the proof (third output of the prover) - if (logger) logger.info("··· Computing evaluations"); - proof.addEvaluation("ql", polynomials.QL.evaluate(challenges.xi)); - proof.addEvaluation("qr", polynomials.QR.evaluate(challenges.xi)); - proof.addEvaluation("qm", polynomials.QM.evaluate(challenges.xi)); - proof.addEvaluation("qo", polynomials.QO.evaluate(challenges.xi)); - proof.addEvaluation("qc", polynomials.QC.evaluate(challenges.xi)); - proof.addEvaluation("s1", polynomials.Sigma1.evaluate(challenges.xi)); - proof.addEvaluation("s2", polynomials.Sigma2.evaluate(challenges.xi)); - proof.addEvaluation("s3", polynomials.Sigma3.evaluate(challenges.xi)); - proof.addEvaluation("a", polynomials.A.evaluate(challenges.xi)); - proof.addEvaluation("b", polynomials.B.evaluate(challenges.xi)); - proof.addEvaluation("c", polynomials.C.evaluate(challenges.xi)); - proof.addEvaluation("z", polynomials.Z.evaluate(challenges.xi)); - - challenges.xiw = Fr.mul(challenges.xi, Fr.w[zkey.power]); - proof.addEvaluation("zw", polynomials.Z.evaluate(challenges.xiw)); - proof.addEvaluation("t1w", polynomials.T1.evaluate(challenges.xiw)); - proof.addEvaluation("t2w", polynomials.T2.evaluate(challenges.xiw)); - } - - async function round4() { - if (logger) logger.info("> Computing challenge alpha"); - // STEP 4.1 - Compute challenge alpha ∈ F - const transcript = new Keccak256Transcript(curve); - transcript.addScalar(challenges.xiSeed); - transcript.addScalar(proof.getEvaluation("ql")); - transcript.addScalar(proof.getEvaluation("qr")); - transcript.addScalar(proof.getEvaluation("qm")); - transcript.addScalar(proof.getEvaluation("qo")); - transcript.addScalar(proof.getEvaluation("qc")); - transcript.addScalar(proof.getEvaluation("s1")); - transcript.addScalar(proof.getEvaluation("s2")); - transcript.addScalar(proof.getEvaluation("s3")); - transcript.addScalar(proof.getEvaluation("a")); - transcript.addScalar(proof.getEvaluation("b")); - transcript.addScalar(proof.getEvaluation("c")); - transcript.addScalar(proof.getEvaluation("z")); - transcript.addScalar(proof.getEvaluation("zw")); - transcript.addScalar(proof.getEvaluation("t1w")); - transcript.addScalar(proof.getEvaluation("t2w")); - challenges.alpha = transcript.getChallenge(); - if (logger) logger.info("··· challenges.alpha: " + Fr.toString(challenges.alpha)); - - // STEP 4.2 - Compute F(X) - if (logger) logger.info("> Reading C0 polynomial"); - polynomials.C0 = new Polynomial(new ffjavascript.BigBuffer(sDomain * 8), curve, logger); - await fdZKey.readToBuffer(polynomials.C0.coef, 0, sDomain * 8, zkeySections[ZKEY_FF_C0_SECTION][0].p); - - if (logger) logger.info("> Computing R0 polynomial"); - computeR0(); - if (logger) logger.info("> Computing R1 polynomial"); - computeR1(); - if (logger) logger.info("> Computing R2 polynomial"); - computeR2(); - - if (logger) logger.info("> Computing F polynomial"); - await computeF(); - - // The fourth output of the prover is ([W1]_1), where W1:=(f/Z_t)(x) - if (logger) logger.info("> Computing W1 multi exponentiation"); - let commitW1 = await polynomials.F.multiExponentiation(PTau, "W1"); - proof.addPolynomial("W1", commitW1); - - return 0; - - function computeR0() { - // COMPUTE R0 - // Compute the coefficients of R0(X) from 8 evaluations using lagrange interpolation. R0(X) ∈ F_{<8}[X] - // We decide to use Lagrange interpolations because the R0 degree is very small (deg(R0)===7), - // and we were not able to compute it using current ifft implementation because the omega are different - polynomials.R0 = Polynomial.lagrangePolynomialInterpolation( - [roots.S0.h0w8[0], roots.S0.h0w8[1], roots.S0.h0w8[2], roots.S0.h0w8[3], - roots.S0.h0w8[4], roots.S0.h0w8[5], roots.S0.h0w8[6], roots.S0.h0w8[7]], - [polynomials.C0.evaluate(roots.S0.h0w8[0]), polynomials.C0.evaluate(roots.S0.h0w8[1]), - polynomials.C0.evaluate(roots.S0.h0w8[2]), polynomials.C0.evaluate(roots.S0.h0w8[3]), - polynomials.C0.evaluate(roots.S0.h0w8[4]), polynomials.C0.evaluate(roots.S0.h0w8[5]), - polynomials.C0.evaluate(roots.S0.h0w8[6]), polynomials.C0.evaluate(roots.S0.h0w8[7])], curve); - - // Check the degree of r0(X) < 8 - if (polynomials.R0.degree() > 7) { - throw new Error("R0 Polynomial is not well calculated"); - } - } - - function computeR1() { - // COMPUTE R1 - // Compute the coefficients of R1(X) from 4 evaluations using lagrange interpolation. R1(X) ∈ F_{<4}[X] - // We decide to use Lagrange interpolations because the R1 degree is very small (deg(R1)===3), - // and we were not able to compute it using current ifft implementation because the omega are different - polynomials.R1 = Polynomial.lagrangePolynomialInterpolation( - [roots.S1.h1w4[0], roots.S1.h1w4[1], roots.S1.h1w4[2], roots.S1.h1w4[3]], - [polynomials.C1.evaluate(roots.S1.h1w4[0]), polynomials.C1.evaluate(roots.S1.h1w4[1]), - polynomials.C1.evaluate(roots.S1.h1w4[2]), polynomials.C1.evaluate(roots.S1.h1w4[3])], curve); - - // Check the degree of r1(X) < 4 - if (polynomials.R1.degree() > 3) { - throw new Error("R1 Polynomial is not well calculated"); - } - } - - function computeR2() { - // COMPUTE R2 - // Compute the coefficients of r2(X) from 6 evaluations using lagrange interpolation. r2(X) ∈ F_{<6}[X] - // We decide to use Lagrange interpolations because the R2.degree is very small (deg(R2)===5), - // and we were not able to compute it using current ifft implementation because the omega are different - polynomials.R2 = Polynomial.lagrangePolynomialInterpolation( - [roots.S2.h2w3[0], roots.S2.h2w3[1], roots.S2.h2w3[2], - roots.S2.h3w3[0], roots.S2.h3w3[1], roots.S2.h3w3[2]], - [polynomials.C2.evaluate(roots.S2.h2w3[0]), polynomials.C2.evaluate(roots.S2.h2w3[1]), - polynomials.C2.evaluate(roots.S2.h2w3[2]), polynomials.C2.evaluate(roots.S2.h3w3[0]), - polynomials.C2.evaluate(roots.S2.h3w3[1]), polynomials.C2.evaluate(roots.S2.h3w3[2])], curve); - - // Check the degree of r2(X) < 6 - if (polynomials.R2.degree() > 5) { - throw new Error("R2 Polynomial is not well calculated"); - } - } - - async function computeF() { - if (logger) logger.info("··· Computing F polynomial"); - - // COMPUTE F(X) - polynomials.F = Polynomial.fromPolynomial(polynomials.C0, curve, logger); - polynomials.F.sub(polynomials.R0); - polynomials.F.divByZerofier(8, challenges.xi); - - let f2 = Polynomial.fromPolynomial(polynomials.C1, curve, logger); - f2.sub(polynomials.R1); - f2.mulScalar(challenges.alpha); - f2.divByZerofier(4, challenges.xi); - - let f3 = Polynomial.fromPolynomial(polynomials.C2, curve, logger); - f3.sub(polynomials.R2); - f3.mulScalar(Fr.square(challenges.alpha)); - f3.divByZerofier(3, challenges.xi); - f3.divByZerofier(3, challenges.xiw); - - polynomials.F.add(f2); - polynomials.F.add(f3); - - if (polynomials.F.degree() >= 9 * zkey.domainSize - 6) { - throw new Error("F Polynomial is not well calculated"); - } - } - } - - async function round5() { - if (logger) logger.info("> Computing challenge y"); - - // STEP 5.1 - Compute random evaluation point y ∈ F - const transcript = new Keccak256Transcript(curve); - transcript.addScalar(challenges.alpha); - transcript.addPolCommitment(proof.getPolynomial("W1")); - - challenges.y = transcript.getChallenge(); - if (logger) logger.info("··· challenges.y: " + Fr.toString(challenges.y)); - - // STEP 5.2 - Compute L(X) - if (logger) logger.info("> Computing L polynomial"); - await computeL(); - - if (logger) logger.info("> Computing ZTS2 polynomial"); - await computeZTS2(); - - let ZTS2Y = polynomials.ZTS2.evaluate(challenges.y); - ZTS2Y = Fr.inv(ZTS2Y); - polynomials.L.mulScalar(ZTS2Y); - - const polDividend = Polynomial.fromCoefficientsArray([Fr.neg(challenges.y), Fr.one], curve); - if (logger) logger.info("> Computing W' = L / ZTS2 polynomial"); - const polRemainder = polynomials.L.divBy(polDividend); - - //Check polReminder degree is equal to zero - if (polRemainder.degree() > 0) { - throw new Error(`Degree of L(X)/(ZTS2(y)(X-y)) remainder is ${polRemainder.degree()} and should be 0`); - } - - if (polynomials.L.degree() >= 9 * zkey.domainSize - 1) { - throw new Error("Degree of L(X)/(ZTS2(y)(X-y)) is not correct"); - } - - // The fifth output of the prover is ([W2]_1), where W2:=(f/Z_t)(x) - if (logger) logger.info("> Computing W' multi exponentiation"); - let commitW2 = await polynomials.L.multiExponentiation(PTau, "W2"); - proof.addPolynomial("W2", commitW2); - - return 0; - - async function computeL() { - if (logger) logger.info("··· Computing L polynomial"); - - const evalR0Y = polynomials.R0.evaluate(challenges.y); - const evalR1Y = polynomials.R1.evaluate(challenges.y); - const evalR2Y = polynomials.R2.evaluate(challenges.y); - - let mulL0 = Fr.sub(challenges.y, roots.S0.h0w8[0]); - for (let i = 1; i < 8; i++) { - mulL0 = Fr.mul(mulL0, Fr.sub(challenges.y, roots.S0.h0w8[i])); - } - - let mulL1 = Fr.sub(challenges.y, roots.S1.h1w4[0]); - for (let i = 1; i < 4; i++) { - mulL1 = Fr.mul(mulL1, Fr.sub(challenges.y, roots.S1.h1w4[i])); - } - - let mulL2 = Fr.sub(challenges.y, roots.S2.h2w3[0]); - for (let i = 1; i < 3; i++) { - mulL2 = Fr.mul(mulL2, Fr.sub(challenges.y, roots.S2.h2w3[i])); - } - for (let i = 0; i < 3; i++) { - mulL2 = Fr.mul(mulL2, Fr.sub(challenges.y, roots.S2.h3w3[i])); - } - - let preL0 = Fr.mul(mulL1, mulL2); - let preL1 = Fr.mul(challenges.alpha, Fr.mul(mulL0, mulL2)); - let preL2 = Fr.mul(Fr.square(challenges.alpha), Fr.mul(mulL0, mulL1)); - - toInverse["denH1"] = mulL1; - toInverse["denH2"] = mulL2; - - // COMPUTE L(X) - polynomials.L = Polynomial.fromPolynomial(polynomials.C0, curve, logger); - polynomials.L.subScalar(evalR0Y); - polynomials.L.mulScalar(preL0); - - let l2 = Polynomial.fromPolynomial(polynomials.C1, curve, logger); - l2.subScalar(evalR1Y); - l2.mulScalar(preL1); - - let l3 = Polynomial.fromPolynomial(polynomials.C2, curve, logger); - l3.subScalar(evalR2Y); - l3.mulScalar(preL2); - - polynomials.L.add(l2); - polynomials.L.add(l3); - - if (logger) logger.info("> Computing ZT polynomial"); - await computeZT(); - - const evalZTY = polynomials.ZT.evaluate(challenges.y); - polynomials.F.mulScalar(evalZTY); - polynomials.L.sub(polynomials.F); - - // Check degree - if (polynomials.L.degree() >= 9 * zkey.domainSize) { - throw new Error("L Polynomial is not well calculated"); - } - - delete buffers.L; - } - - async function computeZT() { - polynomials.ZT = Polynomial.zerofierPolynomial( - [ - roots.S0.h0w8[0], roots.S0.h0w8[1], roots.S0.h0w8[2], roots.S0.h0w8[3], - roots.S0.h0w8[4], roots.S0.h0w8[5], roots.S0.h0w8[6], roots.S0.h0w8[7], - roots.S1.h1w4[0], roots.S1.h1w4[1], roots.S1.h1w4[2], roots.S1.h1w4[3], - roots.S2.h2w3[0], roots.S2.h2w3[1], roots.S2.h2w3[2], - roots.S2.h3w3[0], roots.S2.h3w3[1], roots.S2.h3w3[2]], curve); - } - - async function computeZTS2() { - polynomials.ZTS2 = Polynomial.zerofierPolynomial( - [roots.S1.h1w4[0], roots.S1.h1w4[1], roots.S1.h1w4[2], roots.S1.h1w4[3], - roots.S2.h2w3[0], roots.S2.h2w3[1], roots.S2.h2w3[2], - roots.S2.h3w3[0], roots.S2.h3w3[1], roots.S2.h3w3[2]], curve); - } - } - - function getMontgomeryBatchedInverse() { - // · denominator needed in step 8 and 9 of the verifier to multiply by 1/Z_H(xi) - let xiN = challenges.xi; - for (let i = 0; i < zkey.power; i++) { - xiN = Fr.square(xiN); - } - toInverse["zh"] = Fr.sub(xiN, Fr.one); - - // · denominator needed in step 10 and 11 of the verifier - // toInverse.denH1 & toInverse.denH2 -> Computed in round5, computeL() - - // · denominator needed in the verifier when computing L_i^{S0}(X), L_i^{S1}(X) and L_i^{S2}(X) - computeLiS0(toInverse, roots.S0.h0w8, challenges.y, curve); - - computeLiS1(toInverse, roots.S1.h1w4, challenges.y, curve); - - computeLiS2(toInverse, roots.S2.h2w3, roots.S2.h3w3, challenges.y, challenges.xi, challenges.xiw, curve); - - // · L_i i=1 to num public inputs, needed in step 6 and 7 of the verifier to compute L_1(xi) and PI(xi) - const size = Math.max(1, zkey.nPublic); - - let w = Fr.one; - for (let i = 0; i < size; i++) { - toInverse["Li_" + (i + 1)] = Fr.mul(Fr.e(zkey.domainSize), Fr.sub(challenges.xi, w)); - w = Fr.mul(w, Fr.w[zkey.power]); - } - - let mulAccumulator = Fr.one; - for (const element of Object.values(toInverse)) { - if(Array.isArray(element)) { - for (const subElement of element) { - mulAccumulator = Fr.mul(mulAccumulator, subElement); - } - } else { - mulAccumulator = Fr.mul(mulAccumulator, element); - } - } - return Fr.inv(mulAccumulator); - - - function computeLiS0(toInverse, roots, x, curve) { - const Fr = curve.Fr; - const len = roots.length; - - const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); - - const Li = []; - for (let i = 0; i < len; i++) { - const den2 = roots[((len - 1) * i) % len]; - const den3 = Fr.sub(x, roots[i]); - - toInverse[["LiS0_" + (i + 1)]] = Fr.mul(Fr.mul(den1, den2), den3); - } - - return Li; - } - - function computeLiS1(toInverse, roots, x, curve) { - const Fr = curve.Fr; - const len = roots.length; - - const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); - - const Li = []; - for (let i = 0; i < len; i++) { - const den2 = roots[((len - 1) * i) % len]; - const den3 = Fr.sub(x, roots[i]); - - toInverse[["LiS1_" + (i + 1)]] = Fr.mul(Fr.mul(den1, den2), den3); - - } - - return Li; - } - - function computeLiS2(toInverse, S2, S2p, value, xi, xiw, curve) { - const Fr = curve.Fr; - - const Li = []; - - const _3h2 = Fr.mul(Fr.e(3), S2[0]); - const xisubxiw = Fr.sub(xi, xiw); - let den1 = Fr.mul(_3h2, xisubxiw); - for (let i = 0; i < 3; i++) { - const den2 = S2[2 * i % 3]; - const den3 = Fr.sub(value, S2[i]); - - toInverse[["LiS2_" + (i + 1)]] = Fr.mul(den1,Fr.mul(den2, den3)); - - } - - const _3h3 = Fr.mul(Fr.e(3), S2p[0]); - const xiwsubxi = Fr.sub(xiw, xi); - den1 = Fr.mul(_3h3, xiwsubxi); - for (let i = 0; i < 3; i++) { - const den2 = S2p[2 * i % 3]; - const den3 = Fr.sub(value, S2p[i]); - - toInverse[["LiS2_" + (i + 1 + 3)]] = Fr.mul(den1,Fr.mul(den2, den3)); - } - - return Li; - } - } -} - -/* - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ -const {unstringifyBigInts: unstringifyBigInts$2} = ffjavascript.utils; - + if (logger) logger.info("FFLONK PROVER STARTED"); + if (logger) logger.info("> Reading witness file"); + const { fd: fdWtns, sections: wtnsSections } = await _iden3_binfileutils.readBinFile(witnessFileName, "wtns", 2, 1 << 25, 1 << 23); + const wtns = await readHeader(fdWtns, wtnsSections); + if (logger) logger.info("> Reading zkey file"); + const { fd: fdZKey, sections: zkeySections } = await _iden3_binfileutils.readBinFile(zkeyFileName, "zkey", 2, 1 << 25, 1 << 23); + const zkey = await readHeader$1(fdZKey, zkeySections, void 0, options); + if (zkey.protocolId !== 10) throw new Error("zkey file is not fflonk"); + if (!ffjavascript.Scalar.eq(zkey.r, wtns.q)) throw new Error("Curve of the witness does not match the curve of the proving key"); + if (wtns.nWitness !== zkey.nVars - zkey.nAdditions) throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}, ${zkey.nAdditions}`); + const curve = zkey.curve; + const Fr = curve.Fr; + const sFr = curve.Fr.n8; + const sG1 = curve.G1.F.n8 * 2; + const sDomain = zkey.domainSize * sFr; + if (logger) { + logger.info("----------------------------"); + logger.info(" FFLONK PROVE SETTINGS"); + logger.info(` Curve: ${curve.name}`); + logger.info(` Circuit power: ${zkey.power}`); + logger.info(` Domain size: ${zkey.domainSize}`); + logger.info(` Vars: ${zkey.nVars}`); + logger.info(` Public vars: ${zkey.nPublic}`); + logger.info(` Constraints: ${zkey.nConstraints}`); + logger.info(` Additions: ${zkey.nAdditions}`); + logger.info("----------------------------"); + } + if (logger) logger.info("> Reading witness file data"); + const buffWitness = await _iden3_binfileutils.readSection(fdWtns, wtnsSections, 2); + await fdWtns.close(); + buffWitness.set(Fr.zero, 0); + const buffInternalWitness = new ffjavascript.BigBuffer(zkey.nAdditions * sFr); + let buffers = {}; + let polynomials = {}; + let evaluations = {}; + let toInverse = {}; + let challenges = {}; + let roots = {}; + let proof = new Proof(curve, logger); + if (logger) logger.info(`> Reading Section 3. Additions`); + await calculateAdditions(); + if (logger) logger.info(`> Reading Sections 12,13,14. Sigma1, Sigma2 & Sigma 3`); + if (logger) logger.info("··· Reading Sigma polynomials "); + polynomials.Sigma1 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.Sigma2 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.Sigma3 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + await fdZKey.readToBuffer(polynomials.Sigma1.coef, 0, sDomain, zkeySections[12][0].p); + await fdZKey.readToBuffer(polynomials.Sigma2.coef, 0, sDomain, zkeySections[13][0].p); + await fdZKey.readToBuffer(polynomials.Sigma3.coef, 0, sDomain, zkeySections[14][0].p); + if (logger) logger.info("··· Reading Sigma evaluations"); + evaluations.Sigma1 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.Sigma2 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.Sigma3 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + await fdZKey.readToBuffer(evaluations.Sigma1.eval, 0, sDomain * 4, zkeySections[12][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.Sigma2.eval, 0, sDomain * 4, zkeySections[13][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.Sigma3.eval, 0, sDomain * 4, zkeySections[14][0].p + sDomain); + if (logger) logger.info(`> Reading Section 16. Powers of Tau`); + const PTau = new ffjavascript.BigBuffer(zkey.domainSize * 16 * sG1); + await fdZKey.readToBuffer(PTau, 0, (zkey.domainSize * 9 + 18) * sG1, zkeySections[16][0].p); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(""); + if (logger) logger.info("> ROUND 1"); + await round1(); + delete polynomials.T0; + delete evaluations.QL; + delete evaluations.QR; + delete evaluations.QM; + delete evaluations.QO; + delete evaluations.QC; + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info("> ROUND 2"); + await round2(); + delete buffers.A; + delete buffers.B; + delete buffers.C; + delete evaluations.A; + delete evaluations.B; + delete evaluations.C; + delete evaluations.Sigma1; + delete evaluations.Sigma2; + delete evaluations.Sigma3; + delete evaluations.lagrange1; + delete evaluations.Z; + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info("> ROUND 3"); + await round3(); + delete polynomials.A; + delete polynomials.B; + delete polynomials.C; + delete polynomials.Z; + delete polynomials.T1; + delete polynomials.T2; + delete polynomials.Sigma1; + delete polynomials.Sigma2; + delete polynomials.Sigma3; + delete polynomials.QL; + delete polynomials.QR; + delete polynomials.QM; + delete polynomials.QC; + delete polynomials.QO; + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info("> ROUND 4"); + await round4(); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info("> ROUND 5"); + await round5(); + delete polynomials.C0; + delete polynomials.C1; + delete polynomials.C2; + delete polynomials.R1; + delete polynomials.R2; + delete polynomials.F; + delete polynomials.L; + delete polynomials.ZT; + delete polynomials.ZTS2; + await fdZKey.close(); + if (globalThis.gc) globalThis.gc(); + proof.addEvaluation("inv", getMontgomeryBatchedInverse()); + let _proof = proof.toObjectProof(); + _proof.protocol = "fflonk"; + _proof.curve = curve.name; + let publicSignals = []; + for (let i = 1; i <= zkey.nPublic; i++) { + const i_sFr = i * sFr; + const pub = buffWitness.slice(i_sFr, i_sFr + sFr); + publicSignals.push(ffjavascript.Scalar.fromRprLE(pub)); + } + if (logger) logger.info("FFLONK PROVER FINISHED"); + return { + proof: stringifyBigInts(_proof), + publicSignals: stringifyBigInts(publicSignals) + }; + async function calculateAdditions() { + if (logger) logger.info("··· Computing additions"); + const additionsBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 3); + const sSum = 8 + sFr * 2; + for (let i = 0; i < zkey.nAdditions; i++) { + if (logger && 0 !== i && i % 1e5 === 0) logger.info(` addition ${i}/${zkey.nAdditions}`); + let offset = i * sSum; + const signalId1 = readUInt32(additionsBuff, offset); + offset += 4; + const signalId2 = readUInt32(additionsBuff, offset); + offset += 4; + const factor1 = additionsBuff.slice(offset, offset + sFr); + offset += sFr; + const factor2 = additionsBuff.slice(offset, offset + sFr); + const witness1 = getWitness(signalId1); + const witness2 = getWitness(signalId2); + const result = Fr.add(Fr.mul(factor1, witness1), Fr.mul(factor2, witness2)); + buffInternalWitness.set(result, sFr * i); + } + } + function readUInt32(b, o) { + const buff = b.slice(o, o + 4); + return new DataView(buff.buffer, buff.byteOffset, buff.byteLength).getUint32(0, true); + } + function getWitness(idx) { + let diff = zkey.nVars - zkey.nAdditions; + if (idx < diff) return buffWitness.slice(idx * sFr, idx * sFr + sFr); + else if (idx < zkey.nVars) { + const offset = (idx - diff) * sFr; + return buffInternalWitness.slice(offset, offset + sFr); + } + return Fr.zero; + } + async function round1() { + challenges.b = []; + for (let i = 1; i <= 9; i++) challenges.b[i] = Fr.random(); + if (logger) logger.info("> Computing A, B, C wire polynomials"); + await computeWirePolynomials(); + if (logger) logger.info("> Computing T0 polynomial"); + await computeT0(); + if (logger) logger.info("> Computing C1 polynomial"); + await computeC1(); + if (logger) logger.info("> Computing C1 multi exponentiation"); + let commitC1 = await polynomials.C1.multiExponentiation(PTau, "C1"); + proof.addPolynomial("C1", commitC1); + return 0; + async function computeWirePolynomials() { + if (logger) logger.info("··· Reading data from zkey file"); + buffers.A = new ffjavascript.BigBuffer(sDomain); + buffers.B = new ffjavascript.BigBuffer(sDomain); + buffers.C = new ffjavascript.BigBuffer(sDomain); + const aMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 4); + const bMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 5); + const cMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 6); + for (let i = 0; i < zkey.nConstraints; i++) { + const i_sFr = i * sFr; + const offset = i * 4; + const signalIdA = readUInt32(aMapBuff, offset); + buffers.A.set(getWitness(signalIdA), i_sFr); + const signalIdB = readUInt32(bMapBuff, offset); + buffers.B.set(getWitness(signalIdB), i_sFr); + const signalIdC = readUInt32(cMapBuff, offset); + buffers.C.set(getWitness(signalIdC), i_sFr); + } + buffers.A.set(challenges.b[1], sDomain - 64); + buffers.A.set(challenges.b[2], sDomain - 32); + buffers.B.set(challenges.b[3], sDomain - 64); + buffers.B.set(challenges.b[4], sDomain - 32); + buffers.C.set(challenges.b[5], sDomain - 64); + buffers.C.set(challenges.b[6], sDomain - 32); + buffers.A = await Fr.batchToMontgomery(buffers.A); + buffers.B = await Fr.batchToMontgomery(buffers.B); + buffers.C = await Fr.batchToMontgomery(buffers.C); + if (logger) logger.info("··· Computing A ifft"); + polynomials.A = await Polynomial.fromEvaluations(buffers.A, curve, logger); + if (logger) logger.info("··· Computing B ifft"); + polynomials.B = await Polynomial.fromEvaluations(buffers.B, curve, logger); + if (logger) logger.info("··· Computing C ifft"); + polynomials.C = await Polynomial.fromEvaluations(buffers.C, curve, logger); + if (logger) logger.info("··· Computing A fft"); + evaluations.A = await Evaluations.fromPolynomial(polynomials.A, 4, curve, logger); + if (logger) logger.info("··· Computing B fft"); + evaluations.B = await Evaluations.fromPolynomial(polynomials.B, 4, curve, logger); + if (logger) logger.info("··· Computing C fft"); + evaluations.C = await Evaluations.fromPolynomial(polynomials.C, 4, curve, logger); + if (polynomials.A.degree() >= zkey.domainSize) throw new Error("A Polynomial is not well calculated"); + if (polynomials.B.degree() >= zkey.domainSize) throw new Error("B Polynomial is not well calculated"); + if (polynomials.C.degree() >= zkey.domainSize) throw new Error("C Polynomial is not well calculated"); + } + async function computeT0() { + if (logger) logger.info(`··· Reading sections 7, 8, 9, 10, 11. Q selectors`); + evaluations.QL = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QR = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QM = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QO = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QC = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + await fdZKey.readToBuffer(evaluations.QL.eval, 0, sDomain * 4, zkeySections[7][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QR.eval, 0, sDomain * 4, zkeySections[8][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QM.eval, 0, sDomain * 4, zkeySections[9][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QO.eval, 0, sDomain * 4, zkeySections[10][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QC.eval, 0, sDomain * 4, zkeySections[11][0].p + sDomain); + evaluations.lagrange1 = new Evaluations(await _iden3_binfileutils.readSection(fdZKey, zkeySections, 15), curve, logger); + buffers.T0 = new ffjavascript.BigBuffer(sDomain * 4); + if (logger) logger.info("··· Computing T0 evaluations"); + for (let i = 0; i < zkey.domainSize * 4; i++) { + if (logger && 0 !== i && i % 1e5 === 0) logger.info(` T0 evaluation ${i}/${zkey.domainSize * 4}`); + const a = evaluations.A.getEvaluation(i); + const b = evaluations.B.getEvaluation(i); + const c = evaluations.C.getEvaluation(i); + const ql = evaluations.QL.getEvaluation(i); + const qr = evaluations.QR.getEvaluation(i); + const qm = evaluations.QM.getEvaluation(i); + const qo = evaluations.QO.getEvaluation(i); + const qc = evaluations.QC.getEvaluation(i); + let pi = Fr.zero; + for (let j = 0; j < zkey.nPublic; j++) { + const offset = j * 5 * zkey.domainSize + zkey.domainSize + i; + const lPol = evaluations.lagrange1.getEvaluation(offset); + const aVal = buffers.A.slice(j * sFr, (j + 1) * sFr); + pi = Fr.sub(pi, Fr.mul(lPol, aVal)); + } + const e1 = Fr.mul(a, ql); + const e2 = Fr.mul(b, qr); + const e3 = Fr.mul(Fr.mul(a, b), qm); + const e4 = Fr.mul(c, qo); + const t0 = Fr.add(e1, Fr.add(e2, Fr.add(e3, Fr.add(e4, Fr.add(qc, pi))))); + buffers.T0.set(t0, i * sFr); + } + if (logger) logger.info("buffer T0: " + buffers.T0.byteLength / sFr); + if (logger) logger.info("··· Computing T0 ifft"); + polynomials.T0 = await Polynomial.fromEvaluations(buffers.T0, curve, logger); + if (logger) logger.info("T0 length: " + polynomials.T0.length()); + if (logger) logger.info("T0 degree: " + polynomials.T0.degree()); + if (logger) logger.info("··· Computing T0 / ZH"); + polynomials.T0.divByZerofier(zkey.domainSize, Fr.one); + if (polynomials.T0.degree() >= 2 * zkey.domainSize - 2) throw new Error(`T0 Polynomial is not well calculated (degree is ${polynomials.T0.degree()} and must be less than ${2 * zkey.domainSize + 2}`); + delete buffers.T0; + } + async function computeC1() { + let C1 = new CPolynomial(4, curve, logger); + C1.addPolynomial(0, polynomials.A); + C1.addPolynomial(1, polynomials.B); + C1.addPolynomial(2, polynomials.C); + C1.addPolynomial(3, polynomials.T0); + polynomials.C1 = C1.getPolynomial(); + if (polynomials.C1.degree() >= 8 * zkey.domainSize - 8) throw new Error("C1 Polynomial is not well calculated"); + } + } + async function round2() { + if (logger) logger.info("> Computing challenges beta and gamma"); + const transcript = new Keccak256Transcript(curve); + transcript.addPolCommitment(zkey.C0); + for (let i = 0; i < zkey.nPublic; i++) transcript.addScalar(buffers.A.slice(i * sFr, i * sFr + sFr)); + transcript.addPolCommitment(proof.getPolynomial("C1")); + challenges.beta = transcript.getChallenge(); + if (logger) logger.info("··· challenges.beta: " + Fr.toString(challenges.beta)); + transcript.reset(); + transcript.addScalar(challenges.beta); + challenges.gamma = transcript.getChallenge(); + if (logger) logger.info("··· challenges.gamma: " + Fr.toString(challenges.gamma)); + if (logger) logger.info("> Computing Z polynomial"); + await computeZ(); + if (logger) logger.info("> Computing T1 polynomial"); + await computeT1(); + if (logger) logger.info("> Computing T2 polynomial"); + await computeT2(); + if (logger) logger.info("> Computing C2 polynomial"); + await computeC2(); + if (logger) logger.info("> Computing C2 multi exponentiation"); + let commitC2 = await polynomials.C2.multiExponentiation(PTau, "C2"); + proof.addPolynomial("C2", commitC2); + return 0; + async function computeZ() { + if (logger) logger.info("··· Computing Z evaluations"); + let numArr = new ffjavascript.BigBuffer(sDomain); + let denArr = new ffjavascript.BigBuffer(sDomain); + numArr.set(Fr.one, 0); + denArr.set(Fr.one, 0); + let w = Fr.one; + for (let i = 0; i < zkey.domainSize; i++) { + if (logger && 0 !== i && i % 1e5 === 0) logger.info(` Z evaluation ${i}/${zkey.domainSize}`); + const i_sFr = i * sFr; + const betaw = Fr.mul(challenges.beta, w); + let num1 = buffers.A.slice(i_sFr, i_sFr + sFr); + num1 = Fr.add(num1, betaw); + num1 = Fr.add(num1, challenges.gamma); + let num2 = buffers.B.slice(i_sFr, i_sFr + sFr); + num2 = Fr.add(num2, Fr.mul(zkey.k1, betaw)); + num2 = Fr.add(num2, challenges.gamma); + let num3 = buffers.C.slice(i_sFr, i_sFr + sFr); + num3 = Fr.add(num3, Fr.mul(zkey.k2, betaw)); + num3 = Fr.add(num3, challenges.gamma); + let num = Fr.mul(num1, Fr.mul(num2, num3)); + let den1 = buffers.A.slice(i_sFr, i_sFr + sFr); + den1 = Fr.add(den1, Fr.mul(challenges.beta, evaluations.Sigma1.getEvaluation(i * 4))); + den1 = Fr.add(den1, challenges.gamma); + let den2 = buffers.B.slice(i_sFr, i_sFr + sFr); + den2 = Fr.add(den2, Fr.mul(challenges.beta, evaluations.Sigma2.getEvaluation(i * 4))); + den2 = Fr.add(den2, challenges.gamma); + let den3 = buffers.C.slice(i_sFr, i_sFr + sFr); + den3 = Fr.add(den3, Fr.mul(challenges.beta, evaluations.Sigma3.getEvaluation(i * 4))); + den3 = Fr.add(den3, challenges.gamma); + let den = Fr.mul(den1, Fr.mul(den2, den3)); + num = Fr.mul(numArr.slice(i_sFr, i_sFr + sFr), num); + numArr.set(num, (i + 1) % zkey.domainSize * sFr); + den = Fr.mul(denArr.slice(i_sFr, i_sFr + sFr), den); + denArr.set(den, (i + 1) % zkey.domainSize * sFr); + w = Fr.mul(w, Fr.w[zkey.power]); + } + denArr = await Fr.batchInverse(denArr); + for (let i = 0; i < zkey.domainSize; i++) { + const i_sFr = i * sFr; + const z = Fr.mul(numArr.slice(i_sFr, i_sFr + sFr), denArr.slice(i_sFr, i_sFr + sFr)); + numArr.set(z, i_sFr); + } + buffers.Z = numArr; + if (!Fr.eq(numArr.slice(0, sFr), Fr.one)) throw new Error("Copy constraints does not match"); + if (logger) logger.info("··· Computing Z ifft"); + polynomials.Z = await Polynomial.fromEvaluations(buffers.Z, curve, logger); + if (logger) logger.info("··· Computing Z fft"); + evaluations.Z = await Evaluations.fromPolynomial(polynomials.Z, 4, curve, logger); + polynomials.Z.blindCoefficients([ + challenges.b[9], + challenges.b[8], + challenges.b[7] + ]); + if (polynomials.Z.degree() >= zkey.domainSize + 3) throw new Error("Z Polynomial is not well calculated"); + delete buffers.Z; + } + async function computeT1() { + if (logger) logger.info("··· Computing T1 evaluations"); + buffers.T1 = new ffjavascript.BigBuffer(sDomain * 2); + buffers.T1z = new ffjavascript.BigBuffer(sDomain * 2); + let omega = Fr.one; + for (let i = 0; i < zkey.domainSize * 2; i++) { + if (logger && 0 !== i && i % 1e5 === 0) logger.info(` T1 evaluation ${i}/${zkey.domainSize * 4}`); + const omega2 = Fr.square(omega); + const z = evaluations.Z.getEvaluation(i * 2); + const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omega2), Fr.mul(challenges.b[8], omega)), challenges.b[9]); + const lagrange1 = evaluations.lagrange1.getEvaluation(zkey.domainSize + i * 2); + let t1 = Fr.mul(Fr.sub(z, Fr.one), lagrange1); + let t1z = Fr.mul(zp, lagrange1); + buffers.T1.set(t1, i * sFr); + buffers.T1z.set(t1z, i * sFr); + omega = Fr.mul(omega, Fr.w[zkey.power + 1]); + } + if (logger) logger.info("··· Computing T1 ifft"); + polynomials.T1 = await Polynomial.fromEvaluations(buffers.T1, curve, logger); + polynomials.T1.divByZerofier(zkey.domainSize, Fr.one); + if (logger) logger.info("··· Computing T1z ifft"); + polynomials.T1z = await Polynomial.fromEvaluations(buffers.T1z, curve, logger); + polynomials.T1.add(polynomials.T1z); + if (polynomials.T1.degree() >= zkey.domainSize + 2) throw new Error("T1 Polynomial is not well calculated"); + delete buffers.T1; + delete buffers.T1z; + delete polynomials.T1z; + } + async function computeT2() { + if (logger) logger.info("··· Computing T2 evaluations"); + buffers.T2 = new ffjavascript.BigBuffer(sDomain * 4); + buffers.T2z = new ffjavascript.BigBuffer(sDomain * 4); + let omega = Fr.one; + for (let i = 0; i < zkey.domainSize * 4; i++) { + if (logger && 0 !== i && i % 1e5 === 0) logger.info(` T2 evaluation ${i}/${zkey.domainSize * 4}`); + const omega2 = Fr.square(omega); + const omegaW = Fr.mul(omega, Fr.w[zkey.power]); + const omegaW2 = Fr.square(omegaW); + const a = evaluations.A.getEvaluation(i); + const b = evaluations.B.getEvaluation(i); + const c = evaluations.C.getEvaluation(i); + const z = evaluations.Z.getEvaluation(i); + const zW = evaluations.Z.getEvaluation((zkey.domainSize * 4 + 4 + i) % (zkey.domainSize * 4)); + const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omega2), Fr.mul(challenges.b[8], omega)), challenges.b[9]); + const zWp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omegaW2), Fr.mul(challenges.b[8], omegaW)), challenges.b[9]); + const sigma1 = evaluations.Sigma1.getEvaluation(i); + const sigma2 = evaluations.Sigma2.getEvaluation(i); + const sigma3 = evaluations.Sigma3.getEvaluation(i); + const betaX = Fr.mul(challenges.beta, omega); + let e11 = Fr.add(a, betaX); + e11 = Fr.add(e11, challenges.gamma); + let e12 = Fr.add(b, Fr.mul(betaX, zkey.k1)); + e12 = Fr.add(e12, challenges.gamma); + let e13 = Fr.add(c, Fr.mul(betaX, zkey.k2)); + e13 = Fr.add(e13, challenges.gamma); + let e1 = Fr.mul(Fr.mul(Fr.mul(e11, e12), e13), z); + let e1z = Fr.mul(Fr.mul(Fr.mul(e11, e12), e13), zp); + let e21 = Fr.add(a, Fr.mul(challenges.beta, sigma1)); + e21 = Fr.add(e21, challenges.gamma); + let e22 = Fr.add(b, Fr.mul(challenges.beta, sigma2)); + e22 = Fr.add(e22, challenges.gamma); + let e23 = Fr.add(c, Fr.mul(challenges.beta, sigma3)); + e23 = Fr.add(e23, challenges.gamma); + let e2 = Fr.mul(Fr.mul(Fr.mul(e21, e22), e23), zW); + let e2z = Fr.mul(Fr.mul(Fr.mul(e21, e22), e23), zWp); + let t2 = Fr.sub(e1, e2); + let t2z = Fr.sub(e1z, e2z); + buffers.T2.set(t2, i * sFr); + buffers.T2z.set(t2z, i * sFr); + omega = Fr.mul(omega, Fr.w[zkey.power + 2]); + } + if (logger) logger.info("··· Computing T2 ifft"); + polynomials.T2 = await Polynomial.fromEvaluations(buffers.T2, curve, logger); + if (logger) logger.info("··· Computing T2 / ZH"); + polynomials.T2.divByZerofier(zkey.domainSize, Fr.one); + if (logger) logger.info("··· Computing T2z ifft"); + polynomials.T2z = await Polynomial.fromEvaluations(buffers.T2z, curve, logger); + polynomials.T2.add(polynomials.T2z); + if (polynomials.T2.degree() >= 3 * zkey.domainSize) throw new Error("T2 Polynomial is not well calculated"); + delete buffers.T2; + delete buffers.T2z; + delete polynomials.T2z; + } + async function computeC2() { + let C2 = new CPolynomial(3, curve, logger); + C2.addPolynomial(0, polynomials.Z); + C2.addPolynomial(1, polynomials.T1); + C2.addPolynomial(2, polynomials.T2); + polynomials.C2 = C2.getPolynomial(); + if (polynomials.C2.degree() >= 9 * zkey.domainSize) throw new Error("C2 Polynomial is not well calculated"); + } + } + async function round3() { + if (logger) logger.info("> Computing challenge xi"); + const transcript = new Keccak256Transcript(curve); + transcript.addScalar(challenges.gamma); + transcript.addPolCommitment(proof.getPolynomial("C2")); + challenges.xiSeed = transcript.getChallenge(); + const xiSeed2 = Fr.square(challenges.xiSeed); + roots.w8 = []; + roots.w8[0] = Fr.one; + for (let i = 1; i < 8; i++) roots.w8[i] = Fr.mul(roots.w8[i - 1], zkey.w8); + roots.w4 = []; + roots.w4[0] = Fr.one; + for (let i = 1; i < 4; i++) roots.w4[i] = Fr.mul(roots.w4[i - 1], zkey.w4); + roots.w3 = []; + roots.w3[0] = Fr.one; + roots.w3[1] = zkey.w3; + roots.w3[2] = Fr.square(zkey.w3); + roots.S0 = {}; + roots.S0.h0w8 = []; + roots.S0.h0w8[0] = Fr.mul(xiSeed2, challenges.xiSeed); + for (let i = 1; i < 8; i++) roots.S0.h0w8[i] = Fr.mul(roots.S0.h0w8[0], roots.w8[i]); + roots.S1 = {}; + roots.S1.h1w4 = []; + roots.S1.h1w4[0] = Fr.square(roots.S0.h0w8[0]); + for (let i = 1; i < 4; i++) roots.S1.h1w4[i] = Fr.mul(roots.S1.h1w4[0], roots.w4[i]); + roots.S2 = {}; + roots.S2.h2w3 = []; + roots.S2.h2w3[0] = Fr.mul(roots.S1.h1w4[0], xiSeed2); + roots.S2.h2w3[1] = Fr.mul(roots.S2.h2w3[0], roots.w3[1]); + roots.S2.h2w3[2] = Fr.mul(roots.S2.h2w3[0], roots.w3[2]); + roots.S2.h3w3 = []; + roots.S2.h3w3[0] = Fr.mul(roots.S2.h2w3[0], zkey.wr); + roots.S2.h3w3[1] = Fr.mul(roots.S2.h3w3[0], roots.w3[1]); + roots.S2.h3w3[2] = Fr.mul(roots.S2.h3w3[0], roots.w3[2]); + challenges.xi = Fr.mul(Fr.square(roots.S2.h2w3[0]), roots.S2.h2w3[0]); + if (logger) logger.info("··· challenges.xi: " + Fr.toString(challenges.xi)); + polynomials.QL = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QR = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QM = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QO = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QC = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + await fdZKey.readToBuffer(polynomials.QL.coef, 0, sDomain, zkeySections[7][0].p); + await fdZKey.readToBuffer(polynomials.QR.coef, 0, sDomain, zkeySections[8][0].p); + await fdZKey.readToBuffer(polynomials.QM.coef, 0, sDomain, zkeySections[9][0].p); + await fdZKey.readToBuffer(polynomials.QO.coef, 0, sDomain, zkeySections[10][0].p); + await fdZKey.readToBuffer(polynomials.QC.coef, 0, sDomain, zkeySections[11][0].p); + if (logger) logger.info("··· Computing evaluations"); + proof.addEvaluation("ql", polynomials.QL.evaluate(challenges.xi)); + proof.addEvaluation("qr", polynomials.QR.evaluate(challenges.xi)); + proof.addEvaluation("qm", polynomials.QM.evaluate(challenges.xi)); + proof.addEvaluation("qo", polynomials.QO.evaluate(challenges.xi)); + proof.addEvaluation("qc", polynomials.QC.evaluate(challenges.xi)); + proof.addEvaluation("s1", polynomials.Sigma1.evaluate(challenges.xi)); + proof.addEvaluation("s2", polynomials.Sigma2.evaluate(challenges.xi)); + proof.addEvaluation("s3", polynomials.Sigma3.evaluate(challenges.xi)); + proof.addEvaluation("a", polynomials.A.evaluate(challenges.xi)); + proof.addEvaluation("b", polynomials.B.evaluate(challenges.xi)); + proof.addEvaluation("c", polynomials.C.evaluate(challenges.xi)); + proof.addEvaluation("z", polynomials.Z.evaluate(challenges.xi)); + challenges.xiw = Fr.mul(challenges.xi, Fr.w[zkey.power]); + proof.addEvaluation("zw", polynomials.Z.evaluate(challenges.xiw)); + proof.addEvaluation("t1w", polynomials.T1.evaluate(challenges.xiw)); + proof.addEvaluation("t2w", polynomials.T2.evaluate(challenges.xiw)); + } + async function round4() { + if (logger) logger.info("> Computing challenge alpha"); + const transcript = new Keccak256Transcript(curve); + transcript.addScalar(challenges.xiSeed); + transcript.addScalar(proof.getEvaluation("ql")); + transcript.addScalar(proof.getEvaluation("qr")); + transcript.addScalar(proof.getEvaluation("qm")); + transcript.addScalar(proof.getEvaluation("qo")); + transcript.addScalar(proof.getEvaluation("qc")); + transcript.addScalar(proof.getEvaluation("s1")); + transcript.addScalar(proof.getEvaluation("s2")); + transcript.addScalar(proof.getEvaluation("s3")); + transcript.addScalar(proof.getEvaluation("a")); + transcript.addScalar(proof.getEvaluation("b")); + transcript.addScalar(proof.getEvaluation("c")); + transcript.addScalar(proof.getEvaluation("z")); + transcript.addScalar(proof.getEvaluation("zw")); + transcript.addScalar(proof.getEvaluation("t1w")); + transcript.addScalar(proof.getEvaluation("t2w")); + challenges.alpha = transcript.getChallenge(); + if (logger) logger.info("··· challenges.alpha: " + Fr.toString(challenges.alpha)); + if (logger) logger.info("> Reading C0 polynomial"); + polynomials.C0 = new Polynomial(new ffjavascript.BigBuffer(sDomain * 8), curve, logger); + await fdZKey.readToBuffer(polynomials.C0.coef, 0, sDomain * 8, zkeySections[17][0].p); + if (logger) logger.info("> Computing R0 polynomial"); + computeR0(); + if (logger) logger.info("> Computing R1 polynomial"); + computeR1(); + if (logger) logger.info("> Computing R2 polynomial"); + computeR2(); + if (logger) logger.info("> Computing F polynomial"); + await computeF(); + if (logger) logger.info("> Computing W1 multi exponentiation"); + let commitW1 = await polynomials.F.multiExponentiation(PTau, "W1"); + proof.addPolynomial("W1", commitW1); + return 0; + function computeR0() { + polynomials.R0 = Polynomial.lagrangePolynomialInterpolation([ + roots.S0.h0w8[0], + roots.S0.h0w8[1], + roots.S0.h0w8[2], + roots.S0.h0w8[3], + roots.S0.h0w8[4], + roots.S0.h0w8[5], + roots.S0.h0w8[6], + roots.S0.h0w8[7] + ], [ + polynomials.C0.evaluate(roots.S0.h0w8[0]), + polynomials.C0.evaluate(roots.S0.h0w8[1]), + polynomials.C0.evaluate(roots.S0.h0w8[2]), + polynomials.C0.evaluate(roots.S0.h0w8[3]), + polynomials.C0.evaluate(roots.S0.h0w8[4]), + polynomials.C0.evaluate(roots.S0.h0w8[5]), + polynomials.C0.evaluate(roots.S0.h0w8[6]), + polynomials.C0.evaluate(roots.S0.h0w8[7]) + ], curve); + if (polynomials.R0.degree() > 7) throw new Error("R0 Polynomial is not well calculated"); + } + function computeR1() { + polynomials.R1 = Polynomial.lagrangePolynomialInterpolation([ + roots.S1.h1w4[0], + roots.S1.h1w4[1], + roots.S1.h1w4[2], + roots.S1.h1w4[3] + ], [ + polynomials.C1.evaluate(roots.S1.h1w4[0]), + polynomials.C1.evaluate(roots.S1.h1w4[1]), + polynomials.C1.evaluate(roots.S1.h1w4[2]), + polynomials.C1.evaluate(roots.S1.h1w4[3]) + ], curve); + if (polynomials.R1.degree() > 3) throw new Error("R1 Polynomial is not well calculated"); + } + function computeR2() { + polynomials.R2 = Polynomial.lagrangePolynomialInterpolation([ + roots.S2.h2w3[0], + roots.S2.h2w3[1], + roots.S2.h2w3[2], + roots.S2.h3w3[0], + roots.S2.h3w3[1], + roots.S2.h3w3[2] + ], [ + polynomials.C2.evaluate(roots.S2.h2w3[0]), + polynomials.C2.evaluate(roots.S2.h2w3[1]), + polynomials.C2.evaluate(roots.S2.h2w3[2]), + polynomials.C2.evaluate(roots.S2.h3w3[0]), + polynomials.C2.evaluate(roots.S2.h3w3[1]), + polynomials.C2.evaluate(roots.S2.h3w3[2]) + ], curve); + if (polynomials.R2.degree() > 5) throw new Error("R2 Polynomial is not well calculated"); + } + async function computeF() { + if (logger) logger.info("··· Computing F polynomial"); + polynomials.F = Polynomial.fromPolynomial(polynomials.C0, curve, logger); + polynomials.F.sub(polynomials.R0); + polynomials.F.divByZerofier(8, challenges.xi); + let f2 = Polynomial.fromPolynomial(polynomials.C1, curve, logger); + f2.sub(polynomials.R1); + f2.mulScalar(challenges.alpha); + f2.divByZerofier(4, challenges.xi); + let f3 = Polynomial.fromPolynomial(polynomials.C2, curve, logger); + f3.sub(polynomials.R2); + f3.mulScalar(Fr.square(challenges.alpha)); + f3.divByZerofier(3, challenges.xi); + f3.divByZerofier(3, challenges.xiw); + polynomials.F.add(f2); + polynomials.F.add(f3); + if (polynomials.F.degree() >= 9 * zkey.domainSize - 6) throw new Error("F Polynomial is not well calculated"); + } + } + async function round5() { + if (logger) logger.info("> Computing challenge y"); + const transcript = new Keccak256Transcript(curve); + transcript.addScalar(challenges.alpha); + transcript.addPolCommitment(proof.getPolynomial("W1")); + challenges.y = transcript.getChallenge(); + if (logger) logger.info("··· challenges.y: " + Fr.toString(challenges.y)); + if (logger) logger.info("> Computing L polynomial"); + await computeL(); + if (logger) logger.info("> Computing ZTS2 polynomial"); + await computeZTS2(); + let ZTS2Y = polynomials.ZTS2.evaluate(challenges.y); + ZTS2Y = Fr.inv(ZTS2Y); + polynomials.L.mulScalar(ZTS2Y); + const polDividend = Polynomial.fromCoefficientsArray([Fr.neg(challenges.y), Fr.one], curve); + if (logger) logger.info("> Computing W' = L / ZTS2 polynomial"); + const polRemainder = polynomials.L.divBy(polDividend); + if (polRemainder.degree() > 0) throw new Error(`Degree of L(X)/(ZTS2(y)(X-y)) remainder is ${polRemainder.degree()} and should be 0`); + if (polynomials.L.degree() >= 9 * zkey.domainSize - 1) throw new Error("Degree of L(X)/(ZTS2(y)(X-y)) is not correct"); + if (logger) logger.info("> Computing W' multi exponentiation"); + let commitW2 = await polynomials.L.multiExponentiation(PTau, "W2"); + proof.addPolynomial("W2", commitW2); + return 0; + async function computeL() { + if (logger) logger.info("··· Computing L polynomial"); + const evalR0Y = polynomials.R0.evaluate(challenges.y); + const evalR1Y = polynomials.R1.evaluate(challenges.y); + const evalR2Y = polynomials.R2.evaluate(challenges.y); + let mulL0 = Fr.sub(challenges.y, roots.S0.h0w8[0]); + for (let i = 1; i < 8; i++) mulL0 = Fr.mul(mulL0, Fr.sub(challenges.y, roots.S0.h0w8[i])); + let mulL1 = Fr.sub(challenges.y, roots.S1.h1w4[0]); + for (let i = 1; i < 4; i++) mulL1 = Fr.mul(mulL1, Fr.sub(challenges.y, roots.S1.h1w4[i])); + let mulL2 = Fr.sub(challenges.y, roots.S2.h2w3[0]); + for (let i = 1; i < 3; i++) mulL2 = Fr.mul(mulL2, Fr.sub(challenges.y, roots.S2.h2w3[i])); + for (let i = 0; i < 3; i++) mulL2 = Fr.mul(mulL2, Fr.sub(challenges.y, roots.S2.h3w3[i])); + let preL0 = Fr.mul(mulL1, mulL2); + let preL1 = Fr.mul(challenges.alpha, Fr.mul(mulL0, mulL2)); + let preL2 = Fr.mul(Fr.square(challenges.alpha), Fr.mul(mulL0, mulL1)); + toInverse["denH1"] = mulL1; + toInverse["denH2"] = mulL2; + polynomials.L = Polynomial.fromPolynomial(polynomials.C0, curve, logger); + polynomials.L.subScalar(evalR0Y); + polynomials.L.mulScalar(preL0); + let l2 = Polynomial.fromPolynomial(polynomials.C1, curve, logger); + l2.subScalar(evalR1Y); + l2.mulScalar(preL1); + let l3 = Polynomial.fromPolynomial(polynomials.C2, curve, logger); + l3.subScalar(evalR2Y); + l3.mulScalar(preL2); + polynomials.L.add(l2); + polynomials.L.add(l3); + if (logger) logger.info("> Computing ZT polynomial"); + await computeZT(); + const evalZTY = polynomials.ZT.evaluate(challenges.y); + polynomials.F.mulScalar(evalZTY); + polynomials.L.sub(polynomials.F); + if (polynomials.L.degree() >= 9 * zkey.domainSize) throw new Error("L Polynomial is not well calculated"); + delete buffers.L; + } + async function computeZT() { + polynomials.ZT = Polynomial.zerofierPolynomial([ + roots.S0.h0w8[0], + roots.S0.h0w8[1], + roots.S0.h0w8[2], + roots.S0.h0w8[3], + roots.S0.h0w8[4], + roots.S0.h0w8[5], + roots.S0.h0w8[6], + roots.S0.h0w8[7], + roots.S1.h1w4[0], + roots.S1.h1w4[1], + roots.S1.h1w4[2], + roots.S1.h1w4[3], + roots.S2.h2w3[0], + roots.S2.h2w3[1], + roots.S2.h2w3[2], + roots.S2.h3w3[0], + roots.S2.h3w3[1], + roots.S2.h3w3[2] + ], curve); + } + async function computeZTS2() { + polynomials.ZTS2 = Polynomial.zerofierPolynomial([ + roots.S1.h1w4[0], + roots.S1.h1w4[1], + roots.S1.h1w4[2], + roots.S1.h1w4[3], + roots.S2.h2w3[0], + roots.S2.h2w3[1], + roots.S2.h2w3[2], + roots.S2.h3w3[0], + roots.S2.h3w3[1], + roots.S2.h3w3[2] + ], curve); + } + } + function getMontgomeryBatchedInverse() { + let xiN = challenges.xi; + for (let i = 0; i < zkey.power; i++) xiN = Fr.square(xiN); + toInverse["zh"] = Fr.sub(xiN, Fr.one); + computeLiS0(toInverse, roots.S0.h0w8, challenges.y, curve); + computeLiS1(toInverse, roots.S1.h1w4, challenges.y, curve); + computeLiS2(toInverse, roots.S2.h2w3, roots.S2.h3w3, challenges.y, challenges.xi, challenges.xiw, curve); + const size = Math.max(1, zkey.nPublic); + let w = Fr.one; + for (let i = 0; i < size; i++) { + toInverse["Li_" + (i + 1)] = Fr.mul(Fr.e(zkey.domainSize), Fr.sub(challenges.xi, w)); + w = Fr.mul(w, Fr.w[zkey.power]); + } + let mulAccumulator = Fr.one; + for (const element of Object.values(toInverse)) if (Array.isArray(element)) for (const subElement of element) mulAccumulator = Fr.mul(mulAccumulator, subElement); + else mulAccumulator = Fr.mul(mulAccumulator, element); + return Fr.inv(mulAccumulator); + function computeLiS0(toInverse, roots, x, curve) { + const Fr = curve.Fr; + const len = roots.length; + const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); + const Li = []; + for (let i = 0; i < len; i++) { + const den2 = roots[(len - 1) * i % len]; + const den3 = Fr.sub(x, roots[i]); + toInverse[["LiS0_" + (i + 1)]] = Fr.mul(Fr.mul(den1, den2), den3); + } + return Li; + } + function computeLiS1(toInverse, roots, x, curve) { + const Fr = curve.Fr; + const len = roots.length; + const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); + const Li = []; + for (let i = 0; i < len; i++) { + const den2 = roots[(len - 1) * i % len]; + const den3 = Fr.sub(x, roots[i]); + toInverse[["LiS1_" + (i + 1)]] = Fr.mul(Fr.mul(den1, den2), den3); + } + return Li; + } + function computeLiS2(toInverse, S2, S2p, value, xi, xiw, curve) { + const Fr = curve.Fr; + const Li = []; + const _3h2 = Fr.mul(Fr.e(3), S2[0]); + const xisubxiw = Fr.sub(xi, xiw); + let den1 = Fr.mul(_3h2, xisubxiw); + for (let i = 0; i < 3; i++) { + const den2 = S2[2 * i % 3]; + const den3 = Fr.sub(value, S2[i]); + toInverse[["LiS2_" + (i + 1)]] = Fr.mul(den1, Fr.mul(den2, den3)); + } + const _3h3 = Fr.mul(Fr.e(3), S2p[0]); + const xiwsubxi = Fr.sub(xiw, xi); + den1 = Fr.mul(_3h3, xiwsubxi); + for (let i = 0; i < 3; i++) { + const den2 = S2p[2 * i % 3]; + const den3 = Fr.sub(value, S2p[i]); + toInverse[["LiS2_" + (i + 1 + 3)]] = Fr.mul(den1, Fr.mul(den2, den3)); + } + return Li; + } + } +} +//#endregion +//#region src/fflonk_full_prove.js +var { unstringifyBigInts: unstringifyBigInts$2 } = ffjavascript.utils; async function fflonkFullProve(_input, wasmFilename, zkeyFilename, logger, wtnsCalcOptions, proverOptions) { - const input = unstringifyBigInts$2(_input); - - const wtns= {type: "mem"}; - - // Compute the witness - await wtnsCalculate(input, wasmFilename, wtns, wtnsCalcOptions); - - // Compute the proof - return await fflonkProve(zkeyFilename, wtns, logger, proverOptions); -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -const { unstringifyBigInts: unstringifyBigInts$1 } = ffjavascript.utils; - + const input = unstringifyBigInts$2(_input); + const wtns = { type: "mem" }; + await wtnsCalculate(input, wasmFilename, wtns, wtnsCalcOptions); + return await fflonkProve(zkeyFilename, wtns, logger, proverOptions); +} +//#endregion +//#region src/fflonk_verify.js +var { unstringifyBigInts: unstringifyBigInts$1 } = ffjavascript.utils; async function fflonkVerify(_vk_verifier, _publicSignals, _proof, logger) { - if (logger) logger.info("FFLONK VERIFIER STARTED"); - - _vk_verifier = unstringifyBigInts$1(_vk_verifier); - _proof = unstringifyBigInts$1(_proof); - - const curve = await getCurveFromName(_vk_verifier.curve); - - const vk = fromObjectVk(curve, _vk_verifier); - - // TODO ??? Compute wr^3 and check if it matches with w - - const proof = new Proof(curve, logger); - proof.fromObjectProof(_proof); - - const publicSignals = unstringifyBigInts$1(_publicSignals); - - if (publicSignals.length !== vk.nPublic) { - logger.error("Number of public signals does not match with vk"); - return false; - } - - const Fr = curve.Fr; - - if (logger) { - logger.info("----------------------------"); - logger.info(" FFLONK VERIFY SETTINGS"); - logger.info(` Curve: ${curve.name}`); - logger.info(` Circuit power: ${vk.power}`); - logger.info(` Domain size: ${2 ** vk.power}`); - logger.info(` Public vars: ${vk.nPublic}`); - logger.info("----------------------------"); - } - - // STEP 1 - Validate that all polynomial commitments ∈ G_1 - if (logger) logger.info("> Checking commitments belong to G1"); - if (!commitmentsBelongToG1(curve, proof, vk)) { - if (logger) logger.error("Proof commitments are not valid"); - return false; - } - - // STEP 2 - Validate that all evaluations ∈ F - if (logger) logger.info("> Checking evaluations belong to F"); - if (!evaluationsAreValid(curve, proof)) { - if (logger) logger.error("Proof evaluations are not valid."); - return false; - } - - // STEP 3 - Validate that w_i ∈ F for i ∈ [l] - if (logger) logger.info("> Checking public inputs belong to F"); - if (!publicInputsAreValid(curve, publicSignals)) { - if (logger) logger.error("Public inputs are not valid."); - return false; - } - - // STEP 4 - Compute the challenges: beta, gamma, xi, alpha and y ∈ F - // as in prover description, from the common preprocessed inputs, public inputs and elements of π_SNARK - if (logger) logger.info("> Computing challenges"); - const { challenges, roots } = computeChallenges(curve, proof, vk, publicSignals, logger); - - // STEP 5 - Compute the zero polynomial evaluation Z_H(xi) = xi^n - 1 - if (logger) logger.info("> Computing Zero polynomial evaluation Z_H(xi)"); - challenges.zh = Fr.sub(challenges.xiN, Fr.one); - challenges.invzh = Fr.inv(challenges.zh); - - // STEP 6 - Compute the lagrange polynomial evaluation L_1(xi) - if (logger) logger.info("> Computing Lagrange evaluations"); - const lagrangeEvals = await computeLagrangeEvaluations(curve, challenges, vk); - - // STEP 7 - Compute public input evaluation PI(xi) - if (logger) logger.info("> Computing polynomial identities PI(X)"); - const pi = calculatePI(curve, publicSignals, lagrangeEvals); - - // STEP 8 - Compute polynomial r0 ∈ F_{<4}[X] - if (logger) logger.info("> Computing r0(y)"); - const r0 = computeR0(proof, challenges, roots, curve, logger); - - // STEP 9 - Compute polynomial r1 ∈ F_{<4}[X] - if (logger) logger.info("> Computing r1(y)"); - const r1 = computeR1(proof, challenges, roots, pi, curve, logger); - - // STEP 9 - Compute polynomial r2 ∈ F_{<6}[X] - if (logger) logger.info("> Computing r2(y)"); - const r2 = computeR2(proof, challenges, roots, lagrangeEvals[1], vk, curve, logger); - - if (logger) logger.info("> Computing F"); - const F = computeF(curve, proof, vk, challenges, roots); - - if (logger) logger.info("> Computing E"); - const E = computeE(curve, proof, challenges, vk, r0, r1, r2); - - if (logger) logger.info("> Computing J"); - const J = computeJ(curve, proof, challenges); - - if (logger) logger.info("> Validate all evaluations with a pairing"); - const res = await isValidPairing(curve, proof, challenges, vk, F, E, J); - - if (logger) { - if (res) { - logger.info("PROOF VERIFIED SUCCESSFULLY"); - } else { - logger.warn("Invalid Proof"); - } - } - - if (logger) logger.info("FFLONK VERIFIER FINISHED"); - - return res; - -} - + if (logger) logger.info("FFLONK VERIFIER STARTED"); + _vk_verifier = unstringifyBigInts$1(_vk_verifier); + _proof = unstringifyBigInts$1(_proof); + const curve = await getCurveFromName(_vk_verifier.curve); + const vk = fromObjectVk(curve, _vk_verifier); + const proof = new Proof(curve, logger); + proof.fromObjectProof(_proof); + const publicSignals = unstringifyBigInts$1(_publicSignals); + if (publicSignals.length !== vk.nPublic) { + logger.error("Number of public signals does not match with vk"); + return false; + } + const Fr = curve.Fr; + if (logger) { + logger.info("----------------------------"); + logger.info(" FFLONK VERIFY SETTINGS"); + logger.info(` Curve: ${curve.name}`); + logger.info(` Circuit power: ${vk.power}`); + logger.info(` Domain size: ${2 ** vk.power}`); + logger.info(` Public vars: ${vk.nPublic}`); + logger.info("----------------------------"); + } + if (logger) logger.info("> Checking commitments belong to G1"); + if (!commitmentsBelongToG1(curve, proof, vk)) { + if (logger) logger.error("Proof commitments are not valid"); + return false; + } + if (logger) logger.info("> Checking evaluations belong to F"); + if (!evaluationsAreValid(curve, proof)) { + if (logger) logger.error("Proof evaluations are not valid."); + return false; + } + if (logger) logger.info("> Checking public inputs belong to F"); + if (!publicInputsAreValid(curve, publicSignals)) { + if (logger) logger.error("Public inputs are not valid."); + return false; + } + if (logger) logger.info("> Computing challenges"); + const { challenges, roots } = computeChallenges(curve, proof, vk, publicSignals, logger); + if (logger) logger.info("> Computing Zero polynomial evaluation Z_H(xi)"); + challenges.zh = Fr.sub(challenges.xiN, Fr.one); + challenges.invzh = Fr.inv(challenges.zh); + if (logger) logger.info("> Computing Lagrange evaluations"); + const lagrangeEvals = await computeLagrangeEvaluations(curve, challenges, vk); + if (logger) logger.info("> Computing polynomial identities PI(X)"); + const pi = calculatePI(curve, publicSignals, lagrangeEvals); + if (logger) logger.info("> Computing r0(y)"); + const r0 = computeR0(proof, challenges, roots, curve, logger); + if (logger) logger.info("> Computing r1(y)"); + const r1 = computeR1(proof, challenges, roots, pi, curve, logger); + if (logger) logger.info("> Computing r2(y)"); + const r2 = computeR2(proof, challenges, roots, lagrangeEvals[1], vk, curve, logger); + if (logger) logger.info("> Computing F"); + const F = computeF(curve, proof, vk, challenges, roots); + if (logger) logger.info("> Computing E"); + const E = computeE(curve, proof, challenges, vk, r0, r1, r2); + if (logger) logger.info("> Computing J"); + const J = computeJ(curve, proof, challenges); + if (logger) logger.info("> Validate all evaluations with a pairing"); + const res = await isValidPairing(curve, proof, challenges, vk, F, E, J); + if (logger) if (res) logger.info("PROOF VERIFIED SUCCESSFULLY"); + else logger.warn("Invalid Proof"); + if (logger) logger.info("FFLONK VERIFIER FINISHED"); + return res; +} function fromObjectVk(curve, vk) { - const res = vk; - res.k1 = curve.Fr.fromObject(vk.k1); - res.k2 = curve.Fr.fromObject(vk.k2); - res.w = curve.Fr.fromObject(vk.w); - // res.wW = curve.Fr.fromObject(vk.wW); - res.w3 = curve.Fr.fromObject(vk.w3); - res.w4 = curve.Fr.fromObject(vk.w4); - res.w8 = curve.Fr.fromObject(vk.w8); - res.wr = curve.Fr.fromObject(vk.wr); - res.X_2 = curve.G2.fromObject(vk.X_2); - res.C0 = curve.G1.fromObject(vk.C0); - return res; -} - + const res = vk; + res.k1 = curve.Fr.fromObject(vk.k1); + res.k2 = curve.Fr.fromObject(vk.k2); + res.w = curve.Fr.fromObject(vk.w); + res.w3 = curve.Fr.fromObject(vk.w3); + res.w4 = curve.Fr.fromObject(vk.w4); + res.w8 = curve.Fr.fromObject(vk.w8); + res.wr = curve.Fr.fromObject(vk.wr); + res.X_2 = curve.G2.fromObject(vk.X_2); + res.C0 = curve.G1.fromObject(vk.C0); + return res; +} function commitmentsBelongToG1(curve, proof, vk) { - const G1 = curve.G1; - return G1.isValid(proof.polynomials.C1) - && G1.isValid(proof.polynomials.C2) - && G1.isValid(proof.polynomials.W1) - && G1.isValid(proof.polynomials.W2) - && G1.isValid(vk.C0); -} - + const G1 = curve.G1; + return G1.isValid(proof.polynomials.C1) && G1.isValid(proof.polynomials.C2) && G1.isValid(proof.polynomials.W1) && G1.isValid(proof.polynomials.W2) && G1.isValid(vk.C0); +} function checkValueBelongToField(curve, value) { - return ffjavascript.Scalar.geq(value, 0) && ffjavascript.Scalar.lt(value, curve.r); + return ffjavascript.Scalar.geq(value, 0) && ffjavascript.Scalar.lt(value, curve.r); } - function checkEvaluationIsValid(curve, evaluation) { - return checkValueBelongToField(curve, ffjavascript.Scalar.fromRprLE(evaluation)); + return checkValueBelongToField(curve, ffjavascript.Scalar.fromRprLE(evaluation)); } - function evaluationsAreValid(curve, proof) { - return checkEvaluationIsValid(curve, proof.evaluations.ql) - && checkEvaluationIsValid(curve, proof.evaluations.qr) - && checkEvaluationIsValid(curve, proof.evaluations.qm) - && checkEvaluationIsValid(curve, proof.evaluations.qo) - && checkEvaluationIsValid(curve, proof.evaluations.qc) - && checkEvaluationIsValid(curve, proof.evaluations.s1) - && checkEvaluationIsValid(curve, proof.evaluations.s2) - && checkEvaluationIsValid(curve, proof.evaluations.s3) - && checkEvaluationIsValid(curve, proof.evaluations.a) - && checkEvaluationIsValid(curve, proof.evaluations.b) - && checkEvaluationIsValid(curve, proof.evaluations.c) - && checkEvaluationIsValid(curve, proof.evaluations.z) - && checkEvaluationIsValid(curve, proof.evaluations.zw) - && checkEvaluationIsValid(curve, proof.evaluations.t1w) - && checkEvaluationIsValid(curve, proof.evaluations.t2w); -} - + return checkEvaluationIsValid(curve, proof.evaluations.ql) && checkEvaluationIsValid(curve, proof.evaluations.qr) && checkEvaluationIsValid(curve, proof.evaluations.qm) && checkEvaluationIsValid(curve, proof.evaluations.qo) && checkEvaluationIsValid(curve, proof.evaluations.qc) && checkEvaluationIsValid(curve, proof.evaluations.s1) && checkEvaluationIsValid(curve, proof.evaluations.s2) && checkEvaluationIsValid(curve, proof.evaluations.s3) && checkEvaluationIsValid(curve, proof.evaluations.a) && checkEvaluationIsValid(curve, proof.evaluations.b) && checkEvaluationIsValid(curve, proof.evaluations.c) && checkEvaluationIsValid(curve, proof.evaluations.z) && checkEvaluationIsValid(curve, proof.evaluations.zw) && checkEvaluationIsValid(curve, proof.evaluations.t1w) && checkEvaluationIsValid(curve, proof.evaluations.t2w); +} function publicInputsAreValid(curve, publicInputs) { - for(let i = 0; i < publicInputs.length; i++) { - if(!checkValueBelongToField(curve, publicInputs[i])) { - return false; - } - } - return true; -} - + for (let i = 0; i < publicInputs.length; i++) if (!checkValueBelongToField(curve, publicInputs[i])) return false; + return true; +} function computeChallenges(curve, proof, vk, publicSignals, logger) { - const Fr = curve.Fr; - - const challenges = {}; - const roots = {}; - const transcript = new Keccak256Transcript(curve); - - // Add C0 to the transcript - transcript.addPolCommitment(vk.C0); - - for (let i = 0; i < publicSignals.length; i++) { - transcript.addScalar(Fr.e(publicSignals[i])); - } - - transcript.addPolCommitment(proof.polynomials.C1); - challenges.beta = transcript.getChallenge(); - transcript.reset(); - - transcript.addScalar(challenges.beta); - challenges.gamma = transcript.getChallenge(); - - transcript.reset(); - transcript.addScalar(challenges.gamma); - transcript.addPolCommitment(proof.polynomials.C2); - const xiSeed = transcript.getChallenge(); - const xiSeed2 = Fr.square(xiSeed); - - let w8 = []; - w8[1] = vk.w8; - w8[2] = Fr.square(vk.w8); - w8[3] = Fr.mul(w8[2], vk.w8); - w8[4] = Fr.mul(w8[3], vk.w8); - w8[5] = Fr.mul(w8[4], vk.w8); - w8[6] = Fr.mul(w8[5], vk.w8); - w8[7] = Fr.mul(w8[6], vk.w8); - let w4 = []; - w4[1] = vk.w4; - w4[2] = Fr.square(vk.w4); - w4[3] = Fr.mul(w4[2], vk.w4); - let w3 = []; - w3[1] = vk.w3; - w3[2] = Fr.square(vk.w3); - - // const w4_2 = Fr.square(vk.w4); - // const w4_3 = Fr.mul(w4_2, vk.w4); - // const w3_2 = Fr.square(vk.w3); - - // Compute h0 = xiSeeder^3 - roots.S0 = {}; - roots.S0.h0w8 = []; - roots.S0.h0w8[0] = Fr.mul(xiSeed2, xiSeed); - for (let i = 1; i < 8; i++) { - roots.S0.h0w8[i] = Fr.mul(roots.S0.h0w8[0], w8[i]); - } - - // Compute h1 = xi_seeder^6 - roots.S1 = {}; - roots.S1.h1w4 = []; - roots.S1.h1w4[0] = Fr.square(roots.S0.h0w8[0]); - for (let i = 1; i < 4; i++) { - roots.S1.h1w4[i] = Fr.mul(roots.S1.h1w4[0], w4[i]); - } - - // Compute h2 = xi_seeder^8 - roots.S2 = {}; - roots.S2.h2w3 = []; - roots.S2.h2w3[0] = Fr.mul(roots.S1.h1w4[0], xiSeed2); - roots.S2.h2w3[1] = Fr.mul(roots.S2.h2w3[0], w3[1]); - roots.S2.h2w3[2] = Fr.mul(roots.S2.h2w3[0], w3[2]); - - roots.S2.h3w3 = []; - // Multiply h3 by third-root-omega to obtain h_3^3 = xiω - // So, h3 = xi_seeder^8 ω^{1/3} - roots.S2.h3w3[0] = Fr.mul(roots.S2.h2w3[0], vk.wr); - roots.S2.h3w3[1] = Fr.mul(roots.S2.h3w3[0], w3[1]); - roots.S2.h3w3[2] = Fr.mul(roots.S2.h3w3[0], w3[2]); - - // Compute xi = xi_seeder^12 - challenges.xi = Fr.mul(Fr.square(roots.S2.h2w3[0]), roots.S2.h2w3[0]); - challenges.xiw = Fr.mul(challenges.xi, Fr.w[vk.power]); - - challenges.xiN = challenges.xi; - vk.domainSize = 1; - for (let i = 0; i < vk.power; i++) { - challenges.xiN = Fr.square(challenges.xiN); - vk.domainSize *= 2; - } - - transcript.reset(); - transcript.addScalar(xiSeed); - transcript.addScalar(proof.evaluations.ql); - transcript.addScalar(proof.evaluations.qr); - transcript.addScalar(proof.evaluations.qm); - transcript.addScalar(proof.evaluations.qo); - transcript.addScalar(proof.evaluations.qc); - transcript.addScalar(proof.evaluations.s1); - transcript.addScalar(proof.evaluations.s2); - transcript.addScalar(proof.evaluations.s3); - transcript.addScalar(proof.evaluations.a); - transcript.addScalar(proof.evaluations.b); - transcript.addScalar(proof.evaluations.c); - transcript.addScalar(proof.evaluations.z); - transcript.addScalar(proof.evaluations.zw); - transcript.addScalar(proof.evaluations.t1w); - transcript.addScalar(proof.evaluations.t2w); - challenges.alpha = transcript.getChallenge(); - - transcript.reset(); - transcript.addScalar(challenges.alpha); - transcript.addPolCommitment(proof.polynomials.W1); - challenges.y = transcript.getChallenge(); - - if (logger) { - logger.info("··· challenges.beta: " + Fr.toString(challenges.beta)); - logger.info("··· challenges.gamma: " + Fr.toString(challenges.gamma)); - logger.info("··· challenges.xi: " + Fr.toString(challenges.xi)); - logger.info("··· challenges.alpha: " + Fr.toString(challenges.alpha)); - logger.info("··· challenges.y: " + Fr.toString(challenges.y)); - } - - return { challenges: challenges, roots: roots }; -} - + const Fr = curve.Fr; + const challenges = {}; + const roots = {}; + const transcript = new Keccak256Transcript(curve); + transcript.addPolCommitment(vk.C0); + for (let i = 0; i < publicSignals.length; i++) transcript.addScalar(Fr.e(publicSignals[i])); + transcript.addPolCommitment(proof.polynomials.C1); + challenges.beta = transcript.getChallenge(); + transcript.reset(); + transcript.addScalar(challenges.beta); + challenges.gamma = transcript.getChallenge(); + transcript.reset(); + transcript.addScalar(challenges.gamma); + transcript.addPolCommitment(proof.polynomials.C2); + const xiSeed = transcript.getChallenge(); + const xiSeed2 = Fr.square(xiSeed); + let w8 = []; + w8[1] = vk.w8; + w8[2] = Fr.square(vk.w8); + w8[3] = Fr.mul(w8[2], vk.w8); + w8[4] = Fr.mul(w8[3], vk.w8); + w8[5] = Fr.mul(w8[4], vk.w8); + w8[6] = Fr.mul(w8[5], vk.w8); + w8[7] = Fr.mul(w8[6], vk.w8); + let w4 = []; + w4[1] = vk.w4; + w4[2] = Fr.square(vk.w4); + w4[3] = Fr.mul(w4[2], vk.w4); + let w3 = []; + w3[1] = vk.w3; + w3[2] = Fr.square(vk.w3); + roots.S0 = {}; + roots.S0.h0w8 = []; + roots.S0.h0w8[0] = Fr.mul(xiSeed2, xiSeed); + for (let i = 1; i < 8; i++) roots.S0.h0w8[i] = Fr.mul(roots.S0.h0w8[0], w8[i]); + roots.S1 = {}; + roots.S1.h1w4 = []; + roots.S1.h1w4[0] = Fr.square(roots.S0.h0w8[0]); + for (let i = 1; i < 4; i++) roots.S1.h1w4[i] = Fr.mul(roots.S1.h1w4[0], w4[i]); + roots.S2 = {}; + roots.S2.h2w3 = []; + roots.S2.h2w3[0] = Fr.mul(roots.S1.h1w4[0], xiSeed2); + roots.S2.h2w3[1] = Fr.mul(roots.S2.h2w3[0], w3[1]); + roots.S2.h2w3[2] = Fr.mul(roots.S2.h2w3[0], w3[2]); + roots.S2.h3w3 = []; + roots.S2.h3w3[0] = Fr.mul(roots.S2.h2w3[0], vk.wr); + roots.S2.h3w3[1] = Fr.mul(roots.S2.h3w3[0], w3[1]); + roots.S2.h3w3[2] = Fr.mul(roots.S2.h3w3[0], w3[2]); + challenges.xi = Fr.mul(Fr.square(roots.S2.h2w3[0]), roots.S2.h2w3[0]); + challenges.xiw = Fr.mul(challenges.xi, Fr.w[vk.power]); + challenges.xiN = challenges.xi; + vk.domainSize = 1; + for (let i = 0; i < vk.power; i++) { + challenges.xiN = Fr.square(challenges.xiN); + vk.domainSize *= 2; + } + transcript.reset(); + transcript.addScalar(xiSeed); + transcript.addScalar(proof.evaluations.ql); + transcript.addScalar(proof.evaluations.qr); + transcript.addScalar(proof.evaluations.qm); + transcript.addScalar(proof.evaluations.qo); + transcript.addScalar(proof.evaluations.qc); + transcript.addScalar(proof.evaluations.s1); + transcript.addScalar(proof.evaluations.s2); + transcript.addScalar(proof.evaluations.s3); + transcript.addScalar(proof.evaluations.a); + transcript.addScalar(proof.evaluations.b); + transcript.addScalar(proof.evaluations.c); + transcript.addScalar(proof.evaluations.z); + transcript.addScalar(proof.evaluations.zw); + transcript.addScalar(proof.evaluations.t1w); + transcript.addScalar(proof.evaluations.t2w); + challenges.alpha = transcript.getChallenge(); + transcript.reset(); + transcript.addScalar(challenges.alpha); + transcript.addPolCommitment(proof.polynomials.W1); + challenges.y = transcript.getChallenge(); + if (logger) { + logger.info("··· challenges.beta: " + Fr.toString(challenges.beta)); + logger.info("··· challenges.gamma: " + Fr.toString(challenges.gamma)); + logger.info("··· challenges.xi: " + Fr.toString(challenges.xi)); + logger.info("··· challenges.alpha: " + Fr.toString(challenges.alpha)); + logger.info("··· challenges.y: " + Fr.toString(challenges.y)); + } + return { + challenges, + roots + }; +} async function computeLagrangeEvaluations(curve, challenges, vk) { - const Fr = curve.Fr; - - const size = Math.max(1, vk.nPublic); - const numArr = new ffjavascript.BigBuffer(size * Fr.n8); - let denArr = new ffjavascript.BigBuffer(size * Fr.n8); - - let w = Fr.one; - for (let i = 0; i < size; i++) { - const i_sFr = i * Fr.n8; - numArr.set(Fr.mul(w, challenges.zh), i_sFr); - denArr.set(Fr.mul(Fr.e(vk.domainSize), Fr.sub(challenges.xi, w)), i_sFr); - w = Fr.mul(w, vk.w); - } - - denArr = await Fr.batchInverse(denArr); - - let L = []; - for (let i = 0; i < size; i++) { - const i_sFr = i * Fr.n8; - L[i + 1] = Fr.mul(numArr.slice(i_sFr, i_sFr + Fr.n8), denArr.slice(i_sFr, i_sFr + Fr.n8)); - } - return L; -} - + const Fr = curve.Fr; + const size = Math.max(1, vk.nPublic); + const numArr = new ffjavascript.BigBuffer(size * Fr.n8); + let denArr = new ffjavascript.BigBuffer(size * Fr.n8); + let w = Fr.one; + for (let i = 0; i < size; i++) { + const i_sFr = i * Fr.n8; + numArr.set(Fr.mul(w, challenges.zh), i_sFr); + denArr.set(Fr.mul(Fr.e(vk.domainSize), Fr.sub(challenges.xi, w)), i_sFr); + w = Fr.mul(w, vk.w); + } + denArr = await Fr.batchInverse(denArr); + let L = []; + for (let i = 0; i < size; i++) { + const i_sFr = i * Fr.n8; + L[i + 1] = Fr.mul(numArr.slice(i_sFr, i_sFr + Fr.n8), denArr.slice(i_sFr, i_sFr + Fr.n8)); + } + return L; +} function calculatePI(curve, publicSignals, lagrangeEvals) { - const Fr = curve.Fr; - - let pi = Fr.zero; - for (let i = 0; i < publicSignals.length; i++) { - const w = Fr.e(publicSignals[i]); - pi = Fr.sub(pi, Fr.mul(w, lagrangeEvals[i + 1])); - } - return pi; -} - + const Fr = curve.Fr; + let pi = Fr.zero; + for (let i = 0; i < publicSignals.length; i++) { + const w = Fr.e(publicSignals[i]); + pi = Fr.sub(pi, Fr.mul(w, lagrangeEvals[i + 1])); + } + return pi; +} function computeR0(proof, challenges, roots, curve, logger) { - const Fr = curve.Fr; - - const Li = computeLagrangeLiSi(roots.S0.h0w8, challenges.y, challenges.xi, curve); - - // r0(y) = ∑_1^8 C_0(h_0 ω_8^{i-1}) L_i(y). To this end we need to compute - - // Compute the 8 C0 values - if (logger) logger.info("··· Computing r0(y)"); - - let res = Fr.zero; - for (let i = 0; i < 8; i++) { - let coefValues = []; - coefValues[1] = roots.S0.h0w8[i]; - for (let j = 2; j < 8; j++) { - coefValues[j] = Fr.mul(coefValues[j - 1], roots.S0.h0w8[i]); - } - - let c0 = Fr.add(proof.evaluations.ql, Fr.mul(proof.evaluations.qr, coefValues[1])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.qo, coefValues[2])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.qm, coefValues[3])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.qc, coefValues[4])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.s1, coefValues[5])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.s2, coefValues[6])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.s3, coefValues[7])); - - res = Fr.add(res, Fr.mul(c0, Li[i])); - } - - return res; -} - + const Fr = curve.Fr; + const Li = computeLagrangeLiSi(roots.S0.h0w8, challenges.y, challenges.xi, curve); + if (logger) logger.info("··· Computing r0(y)"); + let res = Fr.zero; + for (let i = 0; i < 8; i++) { + let coefValues = []; + coefValues[1] = roots.S0.h0w8[i]; + for (let j = 2; j < 8; j++) coefValues[j] = Fr.mul(coefValues[j - 1], roots.S0.h0w8[i]); + let c0 = Fr.add(proof.evaluations.ql, Fr.mul(proof.evaluations.qr, coefValues[1])); + c0 = Fr.add(c0, Fr.mul(proof.evaluations.qo, coefValues[2])); + c0 = Fr.add(c0, Fr.mul(proof.evaluations.qm, coefValues[3])); + c0 = Fr.add(c0, Fr.mul(proof.evaluations.qc, coefValues[4])); + c0 = Fr.add(c0, Fr.mul(proof.evaluations.s1, coefValues[5])); + c0 = Fr.add(c0, Fr.mul(proof.evaluations.s2, coefValues[6])); + c0 = Fr.add(c0, Fr.mul(proof.evaluations.s3, coefValues[7])); + res = Fr.add(res, Fr.mul(c0, Li[i])); + } + return res; +} function computeR1(proof, challenges, roots, pi, curve, logger) { - const Fr = curve.Fr; - - const Li = computeLagrangeLiSi(roots.S1.h1w4, challenges.y, challenges.xi, curve); - - // r1(y) = ∑_1^4 C_1(h_1 ω_4^{i-1}) L_i(y). To this end we need to compute - // Z1 = {C1(h_1}, C1(h_1 ω_4), C1(h_1 ω_4^2), C1(h_1 ω_4^3)} - // where C_1(h_1 ω_4^{i-1}) = eval.a + h_1 ω_4^i eval.b + (h_1 ω_4^i)^2 eval.c + (h_1 ω_4^i)^3 T0(xi), - // where T0(xi) = [ qL·a + qR·b + qM·a·b + qO·c + qC + PI(xi) ] / Z_H(xi) - - // Compute T0(xi) - if (logger) logger.info("··· Computing T0(xi)"); - let t0 = Fr.mul(proof.evaluations.ql, proof.evaluations.a); - t0 = Fr.add(t0, Fr.mul(proof.evaluations.qr, proof.evaluations.b)); - t0 = Fr.add(t0, Fr.mul(proof.evaluations.qm, Fr.mul(proof.evaluations.a, proof.evaluations.b))); - t0 = Fr.add(t0, Fr.mul(proof.evaluations.qo, proof.evaluations.c)); - t0 = Fr.add(t0, proof.evaluations.qc); - t0 = Fr.add(t0, pi); - t0 = Fr.mul(t0, challenges.invzh); - - // Compute the 4 C1 values - if (logger) logger.info("··· Computing C1(h_1ω_4^i) values"); - - let res = Fr.zero; - for (let i = 0; i < 4; i++) { - let c1 = proof.evaluations.a; - c1 = Fr.add(c1, Fr.mul(roots.S1.h1w4[i], proof.evaluations.b)); - const h1w4Squared = Fr.square(roots.S1.h1w4[i]); - c1 = Fr.add(c1, Fr.mul(h1w4Squared, proof.evaluations.c)); - c1 = Fr.add(c1, Fr.mul(Fr.mul(h1w4Squared, roots.S1.h1w4[i]), t0)); - - res = Fr.add(res, Fr.mul(c1, Li[i])); - } - - return res; -} - + const Fr = curve.Fr; + const Li = computeLagrangeLiSi(roots.S1.h1w4, challenges.y, challenges.xi, curve); + if (logger) logger.info("··· Computing T0(xi)"); + let t0 = Fr.mul(proof.evaluations.ql, proof.evaluations.a); + t0 = Fr.add(t0, Fr.mul(proof.evaluations.qr, proof.evaluations.b)); + t0 = Fr.add(t0, Fr.mul(proof.evaluations.qm, Fr.mul(proof.evaluations.a, proof.evaluations.b))); + t0 = Fr.add(t0, Fr.mul(proof.evaluations.qo, proof.evaluations.c)); + t0 = Fr.add(t0, proof.evaluations.qc); + t0 = Fr.add(t0, pi); + t0 = Fr.mul(t0, challenges.invzh); + if (logger) logger.info("··· Computing C1(h_1ω_4^i) values"); + let res = Fr.zero; + for (let i = 0; i < 4; i++) { + let c1 = proof.evaluations.a; + c1 = Fr.add(c1, Fr.mul(roots.S1.h1w4[i], proof.evaluations.b)); + const h1w4Squared = Fr.square(roots.S1.h1w4[i]); + c1 = Fr.add(c1, Fr.mul(h1w4Squared, proof.evaluations.c)); + c1 = Fr.add(c1, Fr.mul(Fr.mul(h1w4Squared, roots.S1.h1w4[i]), t0)); + res = Fr.add(res, Fr.mul(c1, Li[i])); + } + return res; +} function computeR2(proof, challenges, roots, lagrange1, vk, curve, logger) { - const Fr = curve.Fr; - - const LiS2 = computeLagrangeLiS2([roots.S2.h2w3, roots.S2.h3w3], challenges.y, challenges.xi, challenges.xiw, curve); - - // r2(y) = ∑_1^3 C_2(h_2 ω_3^{i-1}) L_i(y) + ∑_1^3 C_2(h_3 ω_3^{i-1}) L_{i+3}(y). To this end we need to compute - // Z2 = {[C2(h_2}, C2(h_2 ω_3), C2(h_2 ω_3^2)], [C2(h_3}, C2(h_3 ω_3), C2(h_3 ω_3^2)]} - // where C_2(h_2 ω_3^{i-1}) = eval.z + h_2 ω_2^i T1(xi) + (h_2 ω_3^i)^2 T2(xi), - // where C_2(h_3 ω_3^{i-1}) = eval.z + h_3 ω_2^i T1(xi) + (h_3 ω_3^i)^2 T2(xi), - // where T1(xi) = [ L_1(xi)(z-1)] / Z_H(xi) - // and T2(xi) = [ (a + beta·xi + gamma)(b + beta·xi·k1 + gamma)(c + beta·xi·k2 + gamma)z - // - (a + beta·sigma1 + gamma)(b + beta·sigma2 + gamma)(c + beta·sigma3 + gamma)zω ] / Z_H(xi) - - // Compute T1(xi) - if (logger) logger.info("··· Computing T1(xi)"); - let t1 = Fr.sub(proof.evaluations.z, Fr.one); - t1 = Fr.mul(t1, lagrange1); - t1 = Fr.mul(t1, challenges.invzh); - - // Compute T2(xi) - if (logger) logger.info("··· Computing T2(xi)"); - const betaxi = Fr.mul(challenges.beta, challenges.xi); - const t211 = Fr.add(proof.evaluations.a, Fr.add(betaxi, challenges.gamma)); - const t212 = Fr.add(proof.evaluations.b, Fr.add(Fr.mul(betaxi, vk.k1), challenges.gamma)); - const t213 = Fr.add(proof.evaluations.c, Fr.add(Fr.mul(betaxi, vk.k2), challenges.gamma)); - const t21 = Fr.mul(t211, Fr.mul(t212, Fr.mul(t213, proof.evaluations.z))); - - const t221 = Fr.add(proof.evaluations.a, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s1), challenges.gamma)); - const t222 = Fr.add(proof.evaluations.b, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s2), challenges.gamma)); - const t223 = Fr.add(proof.evaluations.c, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s3), challenges.gamma)); - const t22 = Fr.mul(t221, Fr.mul(t222, Fr.mul(t223, proof.evaluations.zw))); - - let t2 = Fr.sub(t21, t22); - t2 = Fr.mul(t2, challenges.invzh); - - // Compute the 6 C2 values - if (logger) logger.info("··· Computing C2(h_2ω_3^i) values"); - let res = Fr.zero; - for (let i = 0; i < 3; i++) { - let c2 = Fr.add(proof.evaluations.z, Fr.mul(roots.S2.h2w3[i], t1)); - c2 = Fr.add(c2, Fr.mul(Fr.square(roots.S2.h2w3[i]), t2)); - - res = Fr.add(res, Fr.mul(c2, LiS2[i])); - } - - if (logger) logger.info("··· Computing C2(h_3ω_3^i) values"); - for (let i = 0; i < 3; i++) { - let c2 = Fr.add(proof.evaluations.zw, Fr.mul(roots.S2.h3w3[i], proof.evaluations.t1w)); - c2 = Fr.add(c2, Fr.mul(Fr.square(roots.S2.h3w3[i]), proof.evaluations.t2w)); - - res = Fr.add(res, Fr.mul(c2, LiS2[i + 3])); - } - - return res; -} - + const Fr = curve.Fr; + const LiS2 = computeLagrangeLiS2([roots.S2.h2w3, roots.S2.h3w3], challenges.y, challenges.xi, challenges.xiw, curve); + if (logger) logger.info("··· Computing T1(xi)"); + let t1 = Fr.sub(proof.evaluations.z, Fr.one); + t1 = Fr.mul(t1, lagrange1); + t1 = Fr.mul(t1, challenges.invzh); + if (logger) logger.info("··· Computing T2(xi)"); + const betaxi = Fr.mul(challenges.beta, challenges.xi); + const t211 = Fr.add(proof.evaluations.a, Fr.add(betaxi, challenges.gamma)); + const t212 = Fr.add(proof.evaluations.b, Fr.add(Fr.mul(betaxi, vk.k1), challenges.gamma)); + const t213 = Fr.add(proof.evaluations.c, Fr.add(Fr.mul(betaxi, vk.k2), challenges.gamma)); + const t21 = Fr.mul(t211, Fr.mul(t212, Fr.mul(t213, proof.evaluations.z))); + const t221 = Fr.add(proof.evaluations.a, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s1), challenges.gamma)); + const t222 = Fr.add(proof.evaluations.b, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s2), challenges.gamma)); + const t223 = Fr.add(proof.evaluations.c, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s3), challenges.gamma)); + const t22 = Fr.mul(t221, Fr.mul(t222, Fr.mul(t223, proof.evaluations.zw))); + let t2 = Fr.sub(t21, t22); + t2 = Fr.mul(t2, challenges.invzh); + if (logger) logger.info("··· Computing C2(h_2ω_3^i) values"); + let res = Fr.zero; + for (let i = 0; i < 3; i++) { + let c2 = Fr.add(proof.evaluations.z, Fr.mul(roots.S2.h2w3[i], t1)); + c2 = Fr.add(c2, Fr.mul(Fr.square(roots.S2.h2w3[i]), t2)); + res = Fr.add(res, Fr.mul(c2, LiS2[i])); + } + if (logger) logger.info("··· Computing C2(h_3ω_3^i) values"); + for (let i = 0; i < 3; i++) { + let c2 = Fr.add(proof.evaluations.zw, Fr.mul(roots.S2.h3w3[i], proof.evaluations.t1w)); + c2 = Fr.add(c2, Fr.mul(Fr.square(roots.S2.h3w3[i]), proof.evaluations.t2w)); + res = Fr.add(res, Fr.mul(c2, LiS2[i + 3])); + } + return res; +} function computeF(curve, proof, vk, challenges, roots) { - const G1 = curve.G1; - const Fr = curve.Fr; - - let mulH0 = Fr.sub(challenges.y, roots.S0.h0w8[0]); - for (let i = 1; i < 8; i++) { - mulH0 = Fr.mul(mulH0, Fr.sub(challenges.y, roots.S0.h0w8[i])); - } - - challenges.temp = mulH0; - - let mulH1 = Fr.sub(challenges.y, roots.S1.h1w4[0]); - for (let i = 1; i < 4; i++) { - mulH1 = Fr.mul(mulH1, Fr.sub(challenges.y, roots.S1.h1w4[i])); - } - - let mulH2 = Fr.sub(challenges.y, roots.S2.h2w3[0]); - for (let i = 1; i < 3; i++) { - mulH2 = Fr.mul(mulH2, Fr.sub(challenges.y, roots.S2.h2w3[i])); - } - for (let i = 0; i < 3; i++) { - mulH2 = Fr.mul(mulH2, Fr.sub(challenges.y, roots.S2.h3w3[i])); - } - - challenges.quotient1 = Fr.mul(challenges.alpha, Fr.div(mulH0, mulH1)); - challenges.quotient2 = Fr.mul(Fr.square(challenges.alpha), Fr.div(mulH0, mulH2)); - - let F2 = G1.timesFr(proof.polynomials.C1, challenges.quotient1); - let F3 = G1.timesFr(proof.polynomials.C2, challenges.quotient2); - - return G1.add(vk.C0, G1.add(F2, F3)); -} - + const G1 = curve.G1; + const Fr = curve.Fr; + let mulH0 = Fr.sub(challenges.y, roots.S0.h0w8[0]); + for (let i = 1; i < 8; i++) mulH0 = Fr.mul(mulH0, Fr.sub(challenges.y, roots.S0.h0w8[i])); + challenges.temp = mulH0; + let mulH1 = Fr.sub(challenges.y, roots.S1.h1w4[0]); + for (let i = 1; i < 4; i++) mulH1 = Fr.mul(mulH1, Fr.sub(challenges.y, roots.S1.h1w4[i])); + let mulH2 = Fr.sub(challenges.y, roots.S2.h2w3[0]); + for (let i = 1; i < 3; i++) mulH2 = Fr.mul(mulH2, Fr.sub(challenges.y, roots.S2.h2w3[i])); + for (let i = 0; i < 3; i++) mulH2 = Fr.mul(mulH2, Fr.sub(challenges.y, roots.S2.h3w3[i])); + challenges.quotient1 = Fr.mul(challenges.alpha, Fr.div(mulH0, mulH1)); + challenges.quotient2 = Fr.mul(Fr.square(challenges.alpha), Fr.div(mulH0, mulH2)); + let F2 = G1.timesFr(proof.polynomials.C1, challenges.quotient1); + let F3 = G1.timesFr(proof.polynomials.C2, challenges.quotient2); + return G1.add(vk.C0, G1.add(F2, F3)); +} function computeE(curve, proof, challenges, vk, r0, r1, r2) { - const G1 = curve.G1; - const Fr = curve.Fr; - - let E2 = Fr.mul(r1, challenges.quotient1); - let E3 = Fr.mul(r2, challenges.quotient2); - - return G1.timesFr(G1.one, Fr.add(r0, Fr.add(E2, E3))); -} - + const G1 = curve.G1; + const Fr = curve.Fr; + let E2 = Fr.mul(r1, challenges.quotient1); + let E3 = Fr.mul(r2, challenges.quotient2); + return G1.timesFr(G1.one, Fr.add(r0, Fr.add(E2, E3))); +} function computeJ(curve, proof, challenges) { - const G1 = curve.G1; - - return G1.timesFr(proof.polynomials.W1, challenges.temp); + return curve.G1.timesFr(proof.polynomials.W1, challenges.temp); } - async function isValidPairing(curve, proof, challenges, vk, F, E, J) { - const G1 = curve.G1; - - let A1 = G1.timesFr(proof.polynomials.W2, challenges.y); - A1 = G1.add(G1.sub(G1.sub(F, E), J), A1); - const A2 = curve.G2.one; - - const B1 = proof.polynomials.W2; - const B2 = vk.X_2; - - return await curve.pairingEq(G1.neg(A1), A2, B1, B2); -} - - + const G1 = curve.G1; + let A1 = G1.timesFr(proof.polynomials.W2, challenges.y); + A1 = G1.add(G1.sub(G1.sub(F, E), J), A1); + const A2 = curve.G2.one; + const B1 = proof.polynomials.W2; + const B2 = vk.X_2; + return await curve.pairingEq(G1.neg(A1), A2, B1, B2); +} function computeLagrangeLiSi(roots, x, xi, curve) { - const Fr = curve.Fr; - const len = roots.length; - - const num = Fr.sub(Fr.exp(x, len), xi); - const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); - - const Li = []; - for (let i = 0; i < len; i++) { - const den2 = roots[((len - 1) * i) % len]; - const den3 = Fr.sub(x, roots[i]); - - Li[i] = Fr.div(num, Fr.mul(Fr.mul(den1, den2), den3)); - } - - return Li; -} - + const Fr = curve.Fr; + const len = roots.length; + const num = Fr.sub(Fr.exp(x, len), xi); + const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); + const Li = []; + for (let i = 0; i < len; i++) { + const den2 = roots[(len - 1) * i % len]; + const den3 = Fr.sub(x, roots[i]); + Li[i] = Fr.div(num, Fr.mul(Fr.mul(den1, den2), den3)); + } + return Li; +} function computeLagrangeLiS2(roots, value, xi0, xi1, curve) { - const Fr = curve.Fr; - - const Li = []; - - const len = roots[0].length; - const n = len * roots.length; - - const num1 = Fr.exp(value, n); - const num2 = Fr.mul(Fr.add(xi0, xi1), Fr.exp(value, len)); - const num3 = Fr.mul(xi0, xi1); - const num = Fr.add(Fr.sub(num1, num2), num3); - - let den1 = Fr.mul(Fr.mul(Fr.e(len), roots[0][0]), Fr.sub(xi0, xi1)); - for (let i = 0; i < len; i++) { - const den2 = roots[0][(len - 1) * i % len]; - const den3 = Fr.sub(value, roots[0][i]); - - const den = Fr.mul(den1,Fr.mul(den2, den3)); - - Li[i] = Fr.div(num, den); - } - - den1 = Fr.mul(Fr.mul(Fr.e(len), roots[1][0]), Fr.sub(xi1, xi0)); - for (let i = 0; i < len; i++) { - const den2 = roots[1][(len - 1) * i % len]; - const den3 = Fr.sub(value, roots[1][i]); - - const den = Fr.mul(den1,Fr.mul(den2, den3)); - - Li[i + len] = Fr.div(num, den); - } - - return Li; -} - -/* - Copyright 2021 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -const {unstringifyBigInts} = ffjavascript.utils; - + const Fr = curve.Fr; + const Li = []; + const len = roots[0].length; + const n = len * roots.length; + const num1 = Fr.exp(value, n); + const num2 = Fr.mul(Fr.add(xi0, xi1), Fr.exp(value, len)); + const num3 = Fr.mul(xi0, xi1); + const num = Fr.add(Fr.sub(num1, num2), num3); + let den1 = Fr.mul(Fr.mul(Fr.e(len), roots[0][0]), Fr.sub(xi0, xi1)); + for (let i = 0; i < len; i++) { + const den2 = roots[0][(len - 1) * i % len]; + const den3 = Fr.sub(value, roots[0][i]); + const den = Fr.mul(den1, Fr.mul(den2, den3)); + Li[i] = Fr.div(num, den); + } + den1 = Fr.mul(Fr.mul(Fr.e(len), roots[1][0]), Fr.sub(xi1, xi0)); + for (let i = 0; i < len; i++) { + const den2 = roots[1][(len - 1) * i % len]; + const den3 = Fr.sub(value, roots[1][i]); + const den = Fr.mul(den1, Fr.mul(den2, den3)); + Li[i + len] = Fr.div(num, den); + } + return Li; +} +//#endregion +//#region src/fflonk_export_calldata.js +var { unstringifyBigInts } = ffjavascript.utils; function p256(n) { - let nstr = n.toString(16); - while (nstr.length < 64) nstr = "0" + nstr; - nstr = `0x${nstr}`; - return nstr; + let nstr = n.toString(16); + while (nstr.length < 64) nstr = "0" + nstr; + nstr = `0x${nstr}`; + return nstr; } - async function fflonkExportCallData(_pub, _proof) { - const proof = unstringifyBigInts(_proof); - const pub = unstringifyBigInts(_pub); - - const curve = await getCurveFromName(proof.curve); - curve.G1; - curve.Fr; - - let inputs = ""; - for (let i = 0; i < pub.length; i++) { - if (inputs !== "") inputs = inputs + ","; - inputs = inputs + p256(pub[i]); - } - - return `[${p256(proof.polynomials.C1[0])}, ${p256(proof.polynomials.C1[1])},` + - `${p256(proof.polynomials.C2[0])},${p256(proof.polynomials.C2[1])},` + - `${p256(proof.polynomials.W1[0])},${p256(proof.polynomials.W1[1])},` + - `${p256(proof.polynomials.W2[0])},${p256(proof.polynomials.W2[1])},` + - `${p256(proof.evaluations.ql)},${p256(proof.evaluations.qr)},${p256(proof.evaluations.qm)},` + - `${p256(proof.evaluations.qo)},${p256(proof.evaluations.qc)},${p256(proof.evaluations.s1)},` + - `${p256(proof.evaluations.s2)},${p256(proof.evaluations.s3)},${p256(proof.evaluations.a)},` + - `${p256(proof.evaluations.b)},${p256(proof.evaluations.c)},${p256(proof.evaluations.z)},` + - `${p256(proof.evaluations.zw)},${p256(proof.evaluations.t1w)},${p256(proof.evaluations.t2w)},` + - `${p256(proof.evaluations.inv)}],` + - `[${inputs}]`; -} - -/* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . -*/ - -var fflonk = /*#__PURE__*/Object.freeze({ - __proto__: null, - setup: fflonkSetup, - prove: fflonkProve, - fullProve: fflonkFullProve, - verify: fflonkVerify, - exportSolidityVerifier: fflonkExportSolidityVerifier, - exportSolidityCallData: fflonkExportCallData + const proof = unstringifyBigInts(_proof); + const pub = unstringifyBigInts(_pub); + await getCurveFromName(proof.curve); + let inputs = ""; + for (let i = 0; i < pub.length; i++) { + if (inputs !== "") inputs = inputs + ","; + inputs = inputs + p256(pub[i]); + } + return `[${p256(proof.polynomials.C1[0])}, ${p256(proof.polynomials.C1[1])},${p256(proof.polynomials.C2[0])},${p256(proof.polynomials.C2[1])},${p256(proof.polynomials.W1[0])},${p256(proof.polynomials.W1[1])},${p256(proof.polynomials.W2[0])},${p256(proof.polynomials.W2[1])},${p256(proof.evaluations.ql)},${p256(proof.evaluations.qr)},${p256(proof.evaluations.qm)},${p256(proof.evaluations.qo)},${p256(proof.evaluations.qc)},${p256(proof.evaluations.s1)},${p256(proof.evaluations.s2)},${p256(proof.evaluations.s3)},${p256(proof.evaluations.a)},${p256(proof.evaluations.b)},${p256(proof.evaluations.c)},${p256(proof.evaluations.z)},${p256(proof.evaluations.zw)},${p256(proof.evaluations.t1w)},${p256(proof.evaluations.t2w)},${p256(proof.evaluations.inv)}],[${inputs}]`; +} +//#endregion +//#region src/fflonk.js +var fflonk_exports = /* @__PURE__ */ __exportAll({ + exportSolidityCallData: () => fflonkExportCallData, + exportSolidityVerifier: () => fflonkExportSolidityVerifier, + fullProve: () => fflonkFullProve, + prove: () => fflonkProve, + setup: () => fflonkSetup, + verify: () => fflonkVerify +}); +//#endregion +Object.defineProperty(exports, "curves", { + enumerable: true, + get: function() { + return curves_exports; + } +}); +Object.defineProperty(exports, "fflonk", { + enumerable: true, + get: function() { + return fflonk_exports; + } +}); +Object.defineProperty(exports, "groth16", { + enumerable: true, + get: function() { + return groth16_exports; + } +}); +Object.defineProperty(exports, "plonk", { + enumerable: true, + get: function() { + return plonk_exports; + } +}); +Object.defineProperty(exports, "powersOfTau", { + enumerable: true, + get: function() { + return powersoftau_exports; + } +}); +Object.defineProperty(exports, "r1cs", { + enumerable: true, + get: function() { + return r1cs_exports; + } +}); +Object.defineProperty(exports, "wtns", { + enumerable: true, + get: function() { + return wtns_exports; + } +}); +Object.defineProperty(exports, "zKey", { + enumerable: true, + get: function() { + return zkey_exports; + } }); - -exports.curves = curves; -exports.fflonk = fflonk; -exports.groth16 = groth16; -exports.plonk = plonk; -exports.powersOfTau = powersoftau; -exports.r1cs = r1cs; -exports.wtns = wtns; -exports.zKey = zkey; diff --git a/build/snarkjs.js b/build/snarkjs.js deleted file mode 100644 index ef3220fe..00000000 --- a/build/snarkjs.js +++ /dev/null @@ -1,34275 +0,0 @@ -var snarkjs = (function (exports, node_fs) { - 'use strict'; - - /* global BigInt */ - const hexLen = [ 0, 1, 2, 2, 3, 3, 3, 3, 4 ,4 ,4 ,4 ,4 ,4 ,4 ,4]; - - function fromString(s, radix) { - if ((!radix)||(radix==10)) { - return BigInt(s); - } else if (radix==16) { - if (s.slice(0,2) == "0x") { - return BigInt(s); - } else { - return BigInt("0x"+s); - } - } - } - - const e = fromString; - - function fromArray(a, radix) { - let acc =BigInt(0); - radix = BigInt(radix); - for (let i=0; i> BigInt(n); - } - - const shl = shiftLeft; - const shr = shiftRight; - - function isOdd$5(a) { - return (BigInt(a) & BigInt(1)) == BigInt(1); - } - - - function naf(n) { - let E = BigInt(n); - const res = []; - while (E) { - if (E & BigInt(1)) { - const z = 2 - Number(E % BigInt(4)); - res.push( z ); - E = E - BigInt(z); - } else { - res.push( 0 ); - } - E = E >> BigInt(1); - } - return res; - } - - - function bits(n) { - let E = BigInt(n); - const res = []; - while (E) { - if (E & BigInt(1)) { - res.push(1); - } else { - res.push( 0 ); - } - E = E >> BigInt(1); - } - return res; - } - - function toNumber$1(s) { - if (s>BigInt(Number.MAX_SAFE_INTEGER )) { - throw new Error("Number too big"); - } - return Number(s); - } - - function toArray(s, radix) { - const res = []; - let rem = BigInt(s); - radix = BigInt(radix); - while (rem) { - res.unshift( Number(rem % radix)); - rem = rem / radix; - } - return res; - } - - - function add$1(a, b) { - return BigInt(a) + BigInt(b); - } - - function sub(a, b) { - return BigInt(a) - BigInt(b); - } - - function neg(a) { - return -BigInt(a); - } - - function mul(a, b) { - return BigInt(a) * BigInt(b); - } - - function square$2(a) { - return BigInt(a) * BigInt(a); - } - - function pow(a, b) { - return BigInt(a) ** BigInt(b); - } - - function exp$1(a, b) { - return BigInt(a) ** BigInt(b); - } - - function abs$1(a) { - return BigInt(a) >= 0 ? BigInt(a) : -BigInt(a); - } - - function div(a, b) { - return BigInt(a) / BigInt(b); - } - - function mod(a, b) { - return BigInt(a) % BigInt(b); - } - - function eq(a, b) { - return BigInt(a) == BigInt(b); - } - - function neq(a, b) { - return BigInt(a) != BigInt(b); - } - - function lt(a, b) { - return BigInt(a) < BigInt(b); - } - - function gt(a, b) { - return BigInt(a) > BigInt(b); - } - - function leq(a, b) { - return BigInt(a) <= BigInt(b); - } - - function geq(a, b) { - return BigInt(a) >= BigInt(b); - } - - function band(a, b) { - return BigInt(a) & BigInt(b); - } - - function bor(a, b) { - return BigInt(a) | BigInt(b); - } - - function bxor(a, b) { - return BigInt(a) ^ BigInt(b); - } - - function land(a, b) { - return BigInt(a) && BigInt(b); - } - - function lor(a, b) { - return BigInt(a) || BigInt(b); - } - - function lnot(a) { - return !BigInt(a); - } - - // Returns a buffer with Little Endian Representation - function toRprLE(buff, o, e, n8) { - const s = "0000000" + e.toString(16); - const v = new Uint32Array(buff.buffer, buff.byteOffset + o, n8/4); - const l = (((s.length-7)*4 - 1) >> 5)+1; // Number of 32bit words; - for (let i=0; i> 5)+1; // Number of 32bit words; - for (let i=0; i a[a.length-i-1] = ch.toString(16).padStart(8,"0") ); - return fromString(a.join(""), 16); - } - - // Pases a buffer with Big Endian Representation - function fromRprBE(buff, o, n8) { - n8 = n8 || buff.byteLength; - o = o || 0; - const v = new DataView(buff.buffer, buff.byteOffset + o, n8); - const a = new Array(n8/4); - for (let i=0; i{ - let res = F.zero; - let rem = bigInt(e); - let exp = base; - - while (! rem.eq(bigInt.zero)) { - if (rem.and(bigInt.one).eq(bigInt.one)) { - res = F.add(res, exp); - } - exp = F.double(exp); - rem = rem.shiftRight(1); - } - - return res; - }; - */ - - - function exp(F, base, e) { - - if (isZero$1(e)) return F.one; - - const n = bits(e); - - if (n.length==0) return F.one; - - let res = base; - - for (let i=n.length-2; i>=0; i--) { - - res = F.square(res); - - if (n[i]) { - res = F.mul(res, base); - } - } - - return res; - } - - // Check here: https://eprint.iacr.org/2012/685.pdf - - function buildSqrt (F) { - if ((F.m % 2) == 1) { - if (eq(mod(F.p, 4), 1 )) { - if (eq(mod(F.p, 8), 1 )) { - if (eq(mod(F.p, 16), 1 )) { - // alg7_muller(F); - alg5_tonelliShanks(F); - } else if (eq(mod(F.p, 16), 9 )) { - alg4_kong(F); - } else { - throw new Error("Field withot sqrt"); - } - } else if (eq(mod(F.p, 8), 5 )) { - alg3_atkin(F); - } else { - throw new Error("Field withot sqrt"); - } - } else if (eq(mod(F.p, 4), 3 )) { - alg2_shanks(F); - } - } else { - const pm2mod4 = mod(pow(F.p, F.m/2), 4); - if (pm2mod4 == 1) { - alg10_adj(F); - } else if (pm2mod4 == 3) { - alg9_adj(F); - } else { - alg8_complex(F); - } - - } - } - - - function alg5_tonelliShanks(F) { - F.sqrt_q = pow(F.p, F.m); - - F.sqrt_s = 0; - F.sqrt_t = sub(F.sqrt_q, 1); - - while (!isOdd$5(F.sqrt_t)) { - F.sqrt_s = F.sqrt_s + 1; - F.sqrt_t = div(F.sqrt_t, 2); - } - - let c0 = F.one; - - while (F.eq(c0, F.one)) { - const c = F.random(); - F.sqrt_z = F.pow(c, F.sqrt_t); - c0 = F.pow(F.sqrt_z, 2 ** (F.sqrt_s-1) ); - } - - F.sqrt_tm1d2 = div(sub(F.sqrt_t, 1),2); - - F.sqrt = function(a) { - const F=this; - if (F.isZero(a)) return F.zero; - let w = F.pow(a, F.sqrt_tm1d2); - const a0 = F.pow( F.mul(F.square(w), a), 2 ** (F.sqrt_s-1) ); - if (F.eq(a0, F.negone)) return null; - - let v = F.sqrt_s; - let x = F.mul(a, w); - let b = F.mul(x, w); - let z = F.sqrt_z; - while (!F.eq(b, F.one)) { - let b2k = F.square(b); - let k=1; - while (!F.eq(b2k, F.one)) { - b2k = F.square(b2k); - k++; - } - - w = z; - for (let i=0; i>> 0; - st[d] = (st[d] ^ st[a]) >>> 0; - st[d] = ((st[d] << 16) | ((st[d]>>>16) & 0xFFFF)) >>> 0; - - st[c] = (st[c] + st[d]) >>> 0; - st[b] = (st[b] ^ st[c]) >>> 0; - st[b] = ((st[b] << 12) | ((st[b]>>>20) & 0xFFF)) >>> 0; - - st[a] = (st[a] + st[b]) >>> 0; - st[d] = (st[d] ^ st[a]) >>> 0; - st[d] = ((st[d] << 8) | ((st[d]>>>24) & 0xFF)) >>> 0; - - st[c] = (st[c] + st[d]) >>> 0; - st[b] = (st[b] ^ st[c]) >>> 0; - st[b] = ((st[b] << 7) | ((st[b]>>>25) & 0x7F)) >>> 0; - } - - function doubleRound(st) { - quarterRound(st, 0, 4, 8,12); - quarterRound(st, 1, 5, 9,13); - quarterRound(st, 2, 6,10,14); - quarterRound(st, 3, 7,11,15); - - quarterRound(st, 0, 5,10,15); - quarterRound(st, 1, 6,11,12); - quarterRound(st, 2, 7, 8,13); - quarterRound(st, 3, 4, 9,14); - } - - class ChaCha { - - constructor(seed) { - seed = seed || [0,0,0,0,0,0,0,0]; - this.state = [ - 0x61707865, - 0x3320646E, - 0x79622D32, - 0x6B206574, - seed[0], - seed[1], - seed[2], - seed[3], - seed[4], - seed[5], - seed[6], - seed[7], - 0, - 0, - 0, - 0 - ]; - this.idx = 16; - this.buff = new Array(16); - } - - nextU32() { - if (this.idx == 16) this.update(); - return this.buff[this.idx++]; - } - - nextU64() { - return add$1(mul(this.nextU32(), 0x100000000), this.nextU32()); - } - - nextBool() { - return (this.nextU32() & 1) == 1; - } - - update() { - // Copy the state - for (let i=0; i<16; i++) this.buff[i] = this.state[i]; - - // Apply the rounds - for (let i=0; i<10; i++) doubleRound(this.buff); - - // Add to the initial - for (let i=0; i<16; i++) this.buff[i] = (this.buff[i] + this.state[i]) >>> 0; - - this.idx = 0; - - this.state[12] = (this.state[12] + 1) >>> 0; - if (this.state[12] != 0) return; - this.state[13] = (this.state[13] + 1) >>> 0; - if (this.state[13] != 0) return; - this.state[14] = (this.state[14] + 1) >>> 0; - if (this.state[14] != 0) return; - this.state[15] = (this.state[15] + 1) >>> 0; - } - } - - function getRandomBytes$1(n) { - let array = new Uint8Array(n); - { // Browser - if (typeof globalThis.crypto !== "undefined") { // Supported - globalThis.crypto.getRandomValues(array); - } else { // fallback - for (let i=0; i>>0; - } - } - } - return array; - } - - function getRandomSeed() { - const arr = getRandomBytes$1(32); - const arrV = new Uint32Array(arr.buffer); - const seed = []; - for (let i=0; i<8; i++) { - seed.push(arrV[i]); - } - return seed; - } - - let threadRng = null; - - function getThreadRng() { - if (threadRng) return threadRng; - threadRng = new ChaCha(getRandomSeed()); - return threadRng; - } - - /* - Copyright 2018 0kims association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . - */ - - /* - This library does operations on polynomials with coefficients in a field F. - - A polynomial P(x) = p0 + p1 * x + p2 * x^2 + ... + pn * x^n is represented - by the array [ p0, p1, p2, ... , pn ]. - */ - - class FFT { - constructor (G, F, opMulGF) { - this.F = F; - this.G = G; - this.opMulGF = opMulGF; - - let rem = F.sqrt_t || F.t; - let s = F.sqrt_s || F.s; - - let nqr = F.one; - while (F.eq(F.pow(nqr, F.half), F.one)) nqr = F.add(nqr, F.one); - - this.w = new Array(s+1); - this.wi = new Array(s+1); - this.w[s] = this.F.pow(nqr, rem); - this.wi[s] = this.F.inv(this.w[s]); - - let n=s-1; - while (n>=0) { - this.w[n] = this.F.square(this.w[n+1]); - this.wi[n] = this.F.square(this.wi[n+1]); - n--; - } - - - this.roots = []; - /* - for (let i=0; i<16; i++) { - let r = this.F.one; - n = 1 << i; - const rootsi = new Array(n); - for (let j=0; j=0) && (!this.roots[i]); i--) { - let r = this.F.one; - const nroots = 1 << i; - const rootsi = new Array(nroots); - for (let j=0; j> 1; - const p1 = __fft(PF, pall, bits-1, offset, step*2); - const p2 = __fft(PF, pall, bits-1, offset+step, step*2); - - const out = new Array(n); - - for (let i=0; i> this.one; - this.bitLength = bitLength$6(this.p); - this.mask = (this.one << BigInt(this.bitLength)) - this.one; - - this.n64 = Math.floor((this.bitLength - 1) / 64)+1; - this.n32 = this.n64*2; - this.n8 = this.n64*8; - this.R = this.e(this.one << BigInt(this.n64*64)); - this.Ri = this.inv(this.R); - - const e = this.negone >> this.one; - this.nqr = this.two; - let r = this.pow(this.nqr, e); - while (!this.eq(r, this.negone)) { - this.nqr = this.nqr + this.one; - r = this.pow(this.nqr, e); - } - - - this.s = 0; - this.t = this.negone; - - while ((this.t & this.one) == this.zero) { - this.s = this.s + 1; - this.t = this.t >> this.one; - } - - this.nqr_to_t = this.pow(this.nqr, this.t); - - buildSqrt(this); - - this.FFT = new FFT(this, this, this.mul.bind(this)); - - this.fft = this.FFT.fft.bind(this.FFT); - this.ifft = this.FFT.ifft.bind(this.FFT); - this.w = this.FFT.w; - this.wi = this.FFT.wi; - - this.shift = this.square(this.nqr); - this.k = this.exp(this.nqr, 2**this.s); - } - - e(a,b) { - let res; - if (!b) { - res = BigInt(a); - } else if (b==16) { - res = BigInt("0x"+a); - } - if (res < 0) { - let nres = -res; - if (nres >= this.p) nres = nres % this.p; - return this.p - nres; - } else { - return (res>= this.p) ? res%this.p : res; - } - - } - - add(a, b) { - const res = a + b; - return res >= this.p ? res-this.p : res; - } - - sub(a, b) { - return (a >= b) ? a-b : this.p-b+a; - } - - neg(a) { - return a ? this.p-a : a; - } - - mul(a, b) { - return (a*b)%this.p; - } - - mulScalar(base, s) { - return (base * this.e(s)) % this.p; - } - - square(a) { - return (a*a) % this.p; - } - - eq(a, b) { - return a==b; - } - - neq(a, b) { - return a!=b; - } - - lt(a, b) { - const aa = (a > this.half) ? a - this.p : a; - const bb = (b > this.half) ? b - this.p : b; - return aa < bb; - } - - gt(a, b) { - const aa = (a > this.half) ? a - this.p : a; - const bb = (b > this.half) ? b - this.p : b; - return aa > bb; - } - - leq(a, b) { - const aa = (a > this.half) ? a - this.p : a; - const bb = (b > this.half) ? b - this.p : b; - return aa <= bb; - } - - geq(a, b) { - const aa = (a > this.half) ? a - this.p : a; - const bb = (b > this.half) ? b - this.p : b; - return aa >= bb; - } - - div(a, b) { - return this.mul(a, this.inv(b)); - } - - idiv(a, b) { - if (!b) throw new Error("Division by zero"); - return a / b; - } - - inv(a) { - if (!a) throw new Error("Division by zero"); - - let t = this.zero; - let r = this.p; - let newt = this.one; - let newr = a % this.p; - while (newr) { - let q = r/newr; - [t, newt] = [newt, t-q*newt]; - [r, newr] = [newr, r-q*newr]; - } - if (t= this.p ? res-this.p : res; - } - - bor(a, b) { - const res = ((a | b) & this.mask); - return res >= this.p ? res-this.p : res; - } - - bxor(a, b) { - const res = ((a ^ b) & this.mask); - return res >= this.p ? res-this.p : res; - } - - bnot(a) { - const res = a ^ this.mask; - return res >= this.p ? res-this.p : res; - } - - shl(a, b) { - if (Number(b) < this.bitLength) { - const res = (a << b) & this.mask; - return res >= this.p ? res-this.p : res; - } else { - const nb = this.p - b; - if (Number(nb) < this.bitLength) { - return a >> nb; - } else { - return this.zero; - } - } - } - - shr(a, b) { - if (Number(b) < this.bitLength) { - return a >> b; - } else { - const nb = this.p - b; - if (Number(nb) < this.bitLength) { - const res = (a << nb) & this.mask; - return res >= this.p ? res-this.p : res; - } else { - return 0; - } - } - } - - land(a, b) { - return (a && b) ? this.one : this.zero; - } - - lor(a, b) { - return (a || b) ? this.one : this.zero; - } - - lnot(a) { - return (a) ? this.zero : this.one; - } - - sqrt_old(n) { - - if (n == this.zero) return this.zero; - - // Test that have solution - const res = this.pow(n, this.negone >> this.one); - if ( res != this.one ) return null; - - let m = this.s; - let c = this.nqr_to_t; - let t = this.pow(n, this.t); - let r = this.pow(n, this.add(this.t, this.one) >> this.one ); - - while ( t != this.one ) { - let sq = this.square(t); - let i = 1; - while (sq != this.one ) { - i++; - sq = this.square(sq); - } - - // b = c ^ m-i-1 - let b = c; - for (let j=0; j< m-i-1; j ++) b = this.square(b); - - m = i; - c = this.square(b); - t = this.mul(t, c); - r = this.mul(r, b); - } - - if (r > (this.p >> this.one)) { - r = this.neg(r); - } - - return r; - } - - normalize(a, b) { - a = BigInt(a,b); - if (a < 0) { - let na = -a; - if (na >= this.p) na = na % this.p; - return this.p - na; - } else { - return (a>= this.p) ? a%this.p : a; - } - } - - random() { - const nBytes = (this.bitLength*2 / 8); - let res =this.zero; - for (let i=0; i this.half)&&(base == 10)) { - const v = this.p-a; - vs = "-"+v.toString(base); - } else { - vs = a.toString(base); - } - return vs; - } - - isZero(a) { - return a == this.zero; - } - - fromRng(rng) { - let v; - do { - v=this.zero; - for (let i=0; i= this.p); - v = (v * this.Ri) % this.p; // Convert from montgomery - return v; - } - - fft(a) { - return this.FFT.fft(a); - } - - ifft(a) { - return this.FFT.ifft(a); - } - - // Returns a buffer with Little Endian Representation - toRprLE(buff, o, e) { - toRprLE(buff, o, e, this.n64*8); - } - - // Returns a buffer with Big Endian Representation - toRprBE(buff, o, e) { - toRprBE(buff, o, e, this.n64*8); - } - - // Returns a buffer with Big Endian Montgomery Representation - toRprBEM(buff, o, e) { - return this.toRprBE(buff, o, this.mul(this.R, e)); - } - - toRprLEM(buff, o, e) { - return this.toRprLE(buff, o, this.mul(this.R, e)); - } - - - // Pases a buffer with Little Endian Representation - fromRprLE(buff, o) { - return fromRprLE(buff, o, this.n8); - } - - // Pases a buffer with Big Endian Representation - fromRprBE(buff, o) { - return fromRprBE(buff, o, this.n8); - } - - fromRprLEM(buff, o) { - return this.mul(this.fromRprLE(buff, o), this.Ri); - } - - fromRprBEM(buff, o) { - return this.mul(this.fromRprBE(buff, o), this.Ri); - } - - toObject(a) { - return a; - } - } - - /* global BigInt */ - - function stringifyBigInts$5(o) { - if (typeof o == "bigint" || o.eq !== undefined) { - return o.toString(10); - } else if (o instanceof Uint8Array) { - return fromRprLE(o, 0); - } else if (Array.isArray(o)) { - return o.map(stringifyBigInts$5); - } else if (typeof o == "object") { - const res = {}; - const keys = Object.keys(o); - keys.forEach((k) => { - res[k] = stringifyBigInts$5(o[k]); - }); - return res; - } else { - return o; - } - } - - function unstringifyBigInts$c(o) { - if (typeof o == "string" && /^[0-9]+$/.test(o)) { - return BigInt(o); - } else if (typeof o == "string" && /^0x[0-9a-fA-F]+$/.test(o)) { - return BigInt(o); - } else if (Array.isArray(o)) { - return o.map(unstringifyBigInts$c); - } else if (typeof o == "object") { - if (o === null) return null; - const res = {}; - const keys = Object.keys(o); - keys.forEach((k) => { - res[k] = unstringifyBigInts$c(o[k]); - }); - return res; - } else { - return o; - } - } - - function beBuff2int(buff) { - let res = BigInt(0); - let i = buff.length; - let offset = 0; - const buffV = new DataView(buff.buffer, buff.byteOffset, buff.byteLength); - while (i > 0) { - if (i >= 4) { - i -= 4; - res += BigInt(buffV.getUint32(i)) << BigInt(offset * 8); - offset += 4; - } else if (i >= 2) { - i -= 2; - res += BigInt(buffV.getUint16(i)) << BigInt(offset * 8); - offset += 2; - } else { - i -= 1; - res += BigInt(buffV.getUint8(i)) << BigInt(offset * 8); - offset += 1; - } - } - return res; - } - - function beInt2Buff(n, len) { - let r = n; - const buff = new Uint8Array(len); - const buffV = new DataView(buff.buffer); - let o = len; - while (o > 0) { - if (o - 4 >= 0) { - o -= 4; - buffV.setUint32(o, Number(r & BigInt(0xffffffff))); - r = r >> BigInt(32); - } else if (o - 2 >= 0) { - o -= 2; - buffV.setUint16(o, Number(r & BigInt(0xffff))); - r = r >> BigInt(16); - } else { - o -= 1; - buffV.setUint8(o, Number(r & BigInt(0xff))); - r = r >> BigInt(8); - } - } - if (r) { - throw new Error("Number does not fit in this length"); - } - return buff; - } - - function leBuff2int(buff) { - let res = BigInt(0); - let i = 0; - const buffV = new DataView(buff.buffer, buff.byteOffset, buff.byteLength); - while (i < buff.length) { - if (i + 4 <= buff.length) { - res += BigInt(buffV.getUint32(i, true)) << BigInt(i * 8); - i += 4; - } else if (i + 2 <= buff.length) { - res += BigInt(buffV.getUint16(i, true)) << BigInt(i * 8); - i += 2; - } else { - res += BigInt(buffV.getUint8(i, true)) << BigInt(i * 8); - i += 1; - } - } - return res; - } - - function leInt2Buff(n, len) { - let r = n; - if (typeof len === "undefined") { - len = Math.floor((bitLength$6(n) - 1) / 8) + 1; - if (len == 0) len = 1; - } - const buff = new Uint8Array(len); - const buffV = new DataView(buff.buffer); - let o = 0; - while (o < len) { - if (o + 4 <= len) { - buffV.setUint32(o, Number(r & BigInt(0xffffffff)), true); - o += 4; - r = r >> BigInt(32); - } else if (o + 2 <= len) { - buffV.setUint16(o, Number(r & BigInt(0xffff)), true); - o += 2; - r = r >> BigInt(16); - } else { - buffV.setUint8(o, Number(r & BigInt(0xff)), true); - o += 1; - r = r >> BigInt(8); - } - } - if (r) { - throw new Error("Number does not fit in this length"); - } - return buff; - } - - function stringifyFElements(F, o) { - if (typeof o == "bigint" || o.eq !== undefined) { - return o.toString(10); - } else if (o instanceof Uint8Array) { - return F.toString(F.e(o)); - } else if (Array.isArray(o)) { - return o.map(stringifyFElements.bind(this, F)); - } else if (typeof o == "object") { - const res = {}; - const keys = Object.keys(o); - keys.forEach((k) => { - res[k] = stringifyFElements(F, o[k]); - }); - return res; - } else { - return o; - } - } - - function unstringifyFElements(F, o) { - if (typeof o == "string" && /^[0-9]+$/.test(o)) { - return F.e(o); - } else if (typeof o == "string" && /^0x[0-9a-fA-F]+$/.test(o)) { - return F.e(o); - } else if (Array.isArray(o)) { - return o.map(unstringifyFElements.bind(this, F)); - } else if (typeof o == "object") { - if (o === null) return null; - const res = {}; - const keys = Object.keys(o); - keys.forEach((k) => { - res[k] = unstringifyFElements(F, o[k]); - }); - return res; - } else { - return o; - } - } - - const _revTable = []; - for (let i = 0; i < 256; i++) { - _revTable[i] = _revSlow(i, 8); - } - - function _revSlow(idx, bits) { - let res = 0; - let a = idx; - for (let i = 0; i < bits; i++) { - res <<= 1; - res = res | (a & 1); - a >>= 1; - } - return res; - } - - function bitReverse(idx, bits) { - return ( - (_revTable[idx >>> 24] | - (_revTable[(idx >>> 16) & 0xff] << 8) | - (_revTable[(idx >>> 8) & 0xff] << 16) | - (_revTable[idx & 0xff] << 24)) >>> - (32 - bits) - ); - } - - function log2$2(V) { - return ( - ((V & 0xffff0000) !== 0 ? ((V &= 0xffff0000), 16) : 0) | - ((V & 0xff00ff00) !== 0 ? ((V &= 0xff00ff00), 8) : 0) | - ((V & 0xf0f0f0f0) !== 0 ? ((V &= 0xf0f0f0f0), 4) : 0) | - ((V & 0xcccccccc) !== 0 ? ((V &= 0xcccccccc), 2) : 0) | - ((V & 0xaaaaaaaa) !== 0) - ); - } - - function buffReverseBits(buff, eSize) { - const n = buff.byteLength / eSize; - const bits = log2$2(n); - if (n != 1 << bits) { - throw new Error("Invalid number of pointers"); - } - for (let i = 0; i < n; i++) { - const r = bitReverse(i, bits); - if (i > r) { - const tmp = buff.slice(i * eSize, (i + 1) * eSize); - buff.set(buff.slice(r * eSize, (r + 1) * eSize), i * eSize); - buff.set(tmp, r * eSize); - } - } - } - - function array2buffer(arr, sG) { - const buff = new Uint8Array(sG * arr.length); - - for (let i = 0; i < arr.length; i++) { - buff.set(arr[i], i * sG); - } - - return buff; - } - - function buffer2array(buff, sG) { - const n = buff.byteLength / sG; - const arr = new Array(n); - for (let i = 0; i < n; i++) { - arr[i] = buff.slice(i * sG, i * sG + sG); - } - return arr; - } - - var _utils = /*#__PURE__*/Object.freeze({ - __proto__: null, - array2buffer: array2buffer, - beBuff2int: beBuff2int, - beInt2Buff: beInt2Buff, - bitReverse: bitReverse, - buffReverseBits: buffReverseBits, - buffer2array: buffer2array, - leBuff2int: leBuff2int, - leInt2Buff: leInt2Buff, - log2: log2$2, - stringifyBigInts: stringifyBigInts$5, - stringifyFElements: stringifyFElements, - unstringifyBigInts: unstringifyBigInts$c, - unstringifyFElements: unstringifyFElements - }); - - const PAGE_SIZE$3 = ( typeof Buffer !== "undefined" && Buffer.constants && Buffer.constants.MAX_LENGTH ) ? Buffer.constants.MAX_LENGTH : (1 << 30); - - class BigBuffer { - - constructor(size) { - this.buffers = []; - this.byteLength = size; - for (let i=0; i0) { - // bytes to copy from this page - const l = (o+r > PAGE_SIZE$3) ? (PAGE_SIZE$3 -o) : r; - const srcView = new Uint8Array(this.buffers[p].buffer, this.buffers[p].byteOffset+o, l); - if (l == len) return srcView.slice(); - if (!buff) { - if (len <= PAGE_SIZE$3) { - buff = new Uint8Array(len); - } else { - buff = new BigBuffer(len); - } - } - buff.set(srcView, len-r); - r = r-l; - p ++; - o = 0; - } - - return buff; - } - - set(buff, offset) { - if (offset === undefined) offset = 0; - - const len = buff.byteLength; - - if (len==0) return; - - const firstPage = Math.floor(offset / PAGE_SIZE$3); - const lastPage = Math.floor((offset+len-1) / PAGE_SIZE$3); - - if (firstPage == lastPage) { - if ((buff instanceof BigBuffer)&&(buff.buffers.length==1)) { - return this.buffers[firstPage].set(buff.buffers[0], offset % PAGE_SIZE$3); - } else { - return this.buffers[firstPage].set(buff, offset % PAGE_SIZE$3); - } - - } - - - let p = firstPage; - let o = offset % PAGE_SIZE$3; - let r = len; - while (r>0) { - const l = (o+r > PAGE_SIZE$3) ? (PAGE_SIZE$3 -o) : r; - const srcView = buff.slice( len -r, len -r+l); - const dstView = new Uint8Array(this.buffers[p].buffer, this.buffers[p].byteOffset + o, l); - dstView.set(srcView); - r = r-l; - p ++; - o = 0; - } - - } - } - - function buildBatchConvert(tm, fnName, sIn, sOut) { - return async function batchConvert(buffIn) { - const nPoints = Math.floor(buffIn.byteLength / sIn); - if ( nPoints * sIn !== buffIn.byteLength) { - throw new Error("Invalid buffer size"); - } - const pointsPerChunk = Math.floor(nPoints/tm.concurrency); - const opPromises = []; - for (let i=0; i=0; i--) { - this.w[i] = this.square(this.w[i+1]); - } - - if (!this.eq(this.w[0], this.one)) { - throw new Error("Error calculating roots of unity"); - } - - this.batchToMontgomery = buildBatchConvert(tm, prefix + "_batchToMontgomery", this.n8, this.n8); - this.batchFromMontgomery = buildBatchConvert(tm, prefix + "_batchFromMontgomery", this.n8, this.n8); - } - - - op2(opName, a, b) { - this.tm.setBuff(this.pOp1, a); - this.tm.setBuff(this.pOp2, b); - this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp2, this.pOp3); - return this.tm.getBuff(this.pOp3, this.n8); - } - - op2Bool(opName, a, b) { - this.tm.setBuff(this.pOp1, a); - this.tm.setBuff(this.pOp2, b); - return !!this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp2); - } - - op1(opName, a) { - this.tm.setBuff(this.pOp1, a); - this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp3); - return this.tm.getBuff(this.pOp3, this.n8); - } - - op1Bool(opName, a) { - this.tm.setBuff(this.pOp1, a); - return !!this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp3); - } - - add(a,b) { - return this.op2("_add", a, b); - } - - - eq(a,b) { - return this.op2Bool("_eq", a, b); - } - - isZero(a) { - return this.op1Bool("_isZero", a); - } - - sub(a,b) { - return this.op2("_sub", a, b); - } - - neg(a) { - return this.op1("_neg", a); - } - - inv(a) { - return this.op1("_inverse", a); - } - - toMontgomery(a) { - return this.op1("_toMontgomery", a); - } - - fromMontgomery(a) { - return this.op1("_fromMontgomery", a); - } - - mul(a,b) { - return this.op2("_mul", a, b); - } - - div(a, b) { - this.tm.setBuff(this.pOp1, a); - this.tm.setBuff(this.pOp2, b); - this.tm.instance.exports[this.prefix + "_inverse"](this.pOp2, this.pOp2); - this.tm.instance.exports[this.prefix + "_mul"](this.pOp1, this.pOp2, this.pOp3); - return this.tm.getBuff(this.pOp3, this.n8); - } - - square(a) { - return this.op1("_square", a); - } - - isSquare(a) { - return this.op1Bool("_isSquare", a); - } - - sqrt(a) { - return this.op1("_sqrt", a); - } - - exp(a, b) { - if (!(b instanceof Uint8Array)) { - b = toLEBuff(e(b)); - } - this.tm.setBuff(this.pOp1, a); - this.tm.setBuff(this.pOp2, b); - this.tm.instance.exports[this.prefix + "_exp"](this.pOp1, this.pOp2, b.byteLength, this.pOp3); - return this.tm.getBuff(this.pOp3, this.n8); - } - - isNegative(a) { - return this.op1Bool("_isNegative", a); - } - - e(a, b) { - if (a instanceof Uint8Array) return a; - let ra = e(a, b); - if (isNegative$4(ra)) { - ra = neg(ra); - if (gt(ra, this.p)) { - ra = mod(ra, this.p); - } - ra = sub(this.p, ra); - } else { - if (gt(ra, this.p)) { - ra = mod(ra, this.p); - } - } - const buff = leInt2Buff(ra, this.n8); - return this.toMontgomery(buff); - } - - toString(a, radix) { - const an = this.fromMontgomery(a); - const s = fromRprLE(an, 0); - return toString(s, radix); - } - - fromRng(rng) { - let v; - const buff = new Uint8Array(this.n8); - do { - v = zero; - for (let i=0; i memory.buffer.byteLength) { - const currentPages = memory.buffer.byteLength / 0x10000; - let requiredPages = Math.floor((u32[0] + length) / 0x10000)+1; - if (requiredPages>MAXMEM) requiredPages=MAXMEM; - memory.grow(requiredPages-currentPages); - console.log("Growing memory to", memory.buffer.byteLength / 1024 / 1024, "MB"); - } - return res; - } - - function allocBuffer(buffer) { - const p = alloc(buffer.byteLength); - setBuffer(p, buffer); - return p; - } - - function getBuffer(pointer, length) { - // const u8 = new Uint8Array(memory.buffer); - // return new Uint8Array(u8.buffer, u8.byteOffset + pointer, length); - return new Uint8Array(memory.buffer, pointer, length); - } - - function setBuffer(pointer, buffer) { - const u8 = new Uint8Array(memory.buffer); - u8.set(new Uint8Array(buffer), pointer); - } - - function runTask(task) { - clearTimeout(terminationTimer); - if (task[0].cmd === "INIT") { - return init(task[0]); - } - const ctx = { - vars: [], - out: [] - }; - const u32a = new Uint32Array(memory.buffer, 0, 1); - const oldAlloc = u32a[0]; - for (let i=0; i0) { - terminationTimer = setTimeout( () => { - console.log("Shutting down thread due to inactivity"); - terminate(); - }, terminationTimeout); - } - } - - function terminate() { - clearTimeout(terminationTimer); - instance = null; - memory = null; - if (self) { - console.log("TERMINATE"); - self.postMessage({status: "terminated"}); - self.close(); - } - } - - return runTask; - } - - /* - Copyright 2019 0KIMS association. - - This file is part of wasmsnark (Web Assembly zkSnark Prover). - - wasmsnark is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - wasmsnark is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with wasmsnark. If not, see . - */ - - // const MEM_SIZE = 1000; // Memory size in 64K Pakes (512Mb) - const MEM_SIZE = 25; // Memory size in 64K Pakes (1600Kb) - - class Deferred { - constructor() { - this.promise = new Promise((resolve, reject)=> { - this.reject = reject; - this.resolve = resolve; - }); - } - } - - let workerSource; - - const threadStr = `(${"function thread(self) {\n const MAXMEM = 32767;\n let instance;\n let memory;\n let terminationTimeout = 500; // milliseconds\n let terminationTimer;\n\n if (self) {\n self.onmessage = function(e) {\n let data;\n if (e.data) {\n data = e.data;\n } else {\n data = e;\n }\n\n try {\n if (data[0].cmd === \"INIT\") {\n init(data[0]).then(function() {\n console.log(\"INIT DONE\");\n self.postMessage({status: \"initialized\"});\n });\n } else if (data[0].cmd === \"TERMINATE\") {\n terminate();\n } else {\n let terminateAfterTask = false;\n if (data[data.length-1].cmd === \"TERMINATE\") {\n terminateAfterTask = true;\n data.pop();\n //terminationTimeout = 1;\n }\n const res = runTask(data);\n //self.postMessage(res);\n let transfers = [];\n for (let i=0; i memory.buffer.byteLength) {\n const currentPages = memory.buffer.byteLength / 0x10000;\n let requiredPages = Math.floor((u32[0] + length) / 0x10000)+1;\n if (requiredPages>MAXMEM) requiredPages=MAXMEM;\n memory.grow(requiredPages-currentPages);\n console.log(\"Growing memory to\", memory.buffer.byteLength / 1024 / 1024, \"MB\");\n }\n return res;\n }\n\n function allocBuffer(buffer) {\n const p = alloc(buffer.byteLength);\n setBuffer(p, buffer);\n return p;\n }\n\n function getBuffer(pointer, length) {\n // const u8 = new Uint8Array(memory.buffer);\n // return new Uint8Array(u8.buffer, u8.byteOffset + pointer, length);\n return new Uint8Array(memory.buffer, pointer, length);\n }\n\n function setBuffer(pointer, buffer) {\n const u8 = new Uint8Array(memory.buffer);\n u8.set(new Uint8Array(buffer), pointer);\n }\n\n function runTask(task) {\n clearTimeout(terminationTimer);\n if (task[0].cmd === \"INIT\") {\n return init(task[0]);\n }\n const ctx = {\n vars: [],\n out: []\n };\n const u32a = new Uint32Array(memory.buffer, 0, 1);\n const oldAlloc = u32a[0];\n for (let i=0; i0) {\n terminationTimer = setTimeout( () => {\n console.log(\"Shutting down thread due to inactivity\");\n terminate();\n }, terminationTimeout);\n }\n }\n\n function terminate() {\n clearTimeout(terminationTimer);\n instance = null;\n memory = null;\n if (self) {\n console.log(\"TERMINATE\");\n self.postMessage({status: \"terminated\"});\n self.close();\n }\n }\n\n return runTask;\n}"})(self)`; - { - if(globalThis?.Blob) { - const threadBytes= new TextEncoder().encode(threadStr); - const workerBlob = new Blob([threadBytes], { type: "application/javascript" }) ; - workerSource = URL.createObjectURL(workerBlob); - } else { - workerSource = "data:application/javascript;base64," + globalThis.btoa(threadStr); - } - } - - - - async function buildThreadManager(wasm, singleThread) { - const tm = new ThreadManager(); - - tm.memory = new WebAssembly.Memory({initial:MEM_SIZE}); - tm.u8 = new Uint8Array(tm.memory.buffer); - tm.u32 = new Uint32Array(tm.memory.buffer); - - const wasmModule = await WebAssembly.compile(wasm.code); - - tm.instance = await WebAssembly.instantiate(wasmModule, { - env: { - "memory": tm.memory - } - }); - - if(!globalThis?.Worker) { - singleThread = true; - } - - tm.singleThread = singleThread; - tm.initalPFree = tm.u32[0]; // Save the Pointer to free space. - tm.pq = wasm.pq; - tm.pr = wasm.pr; - tm.pG1gen = wasm.pG1gen; - tm.pG1zero = wasm.pG1zero; - tm.pG2gen = wasm.pG2gen; - tm.pG2zero = wasm.pG2zero; - tm.pOneT = wasm.pOneT; - - tm.code = wasm.code; - tm.wasmModule = wasmModule; - - // tm.pTmp0 = tm.alloc(curve.G2.F.n8*3); - // tm.pTmp1 = tm.alloc(curve.G2.F.n8*3); - - if (singleThread) { - tm.taskManager = thread(); - await tm.taskManager([{ - cmd: "INIT", - init: MEM_SIZE, - code: tm.code.slice() - }]); - tm.concurrency = 1; - } else { - tm.workers = []; - tm.pendingDeferreds = []; - tm.working = []; - tm.initialized = []; - tm.initializing = []; - - let concurrency = 2; - { - if (typeof navigator === "object" && navigator.hardwareConcurrency) { - concurrency = navigator.hardwareConcurrency; - } - } - - if(concurrency === 0){ - concurrency = 2; - } - - //concurrency = 10; // For testing - - // Limit to 64 threads for memory reasons. - if (concurrency>64) concurrency=64; - tm.concurrency = concurrency; - - // for (let i = 0; i<1; i++) { - // - // tm.workers[i] = new Worker(workerSource); - // - // tm.workers[i].addEventListener("message", getOnMsg(i)); - // //tm.workers[i].addEventListener("error", getOnError(i)); - // - // tm.working[i]=false; - // } - // - // const initPromises = []; - // for (let i=0; i { - this.initialized[i] = true; - }); - } - - startSyncOp() { - if (this.oldPFree !== 0) throw new Error("Sync operation in progress"); - this.oldPFree = this.u32[0]; - } - - endSyncOp() { - if (this.oldPFree === 0) throw new Error("No sync operation in progress"); - this.u32[0] = this.oldPFree; - this.oldPFree = 0; - } - - async postAction(workerId, e, transfers, _deferred) { - if (this.working[workerId]) { - throw new Error("Posting a job to a working worker"); - } - this.working[workerId] = true; - - this.pendingDeferreds[workerId] = _deferred ? _deferred : new Deferred(); - await this.workers[workerId].postMessage(e, transfers); - - return this.pendingDeferreds[workerId].promise; - } - - async processWorks() { - for (let i=0; (i 0); i++) { - if (this.workers[i] && this.initialized[i] && !this.working[i]) { - const work = this.actionQueue.shift(); - this.postAction(i, work.data, work.transfers, work.deferred); - } - } - - // Initialize more workers if needed - if (this.actionQueue.length > 0) { - // Find a worker that is not initialized yet - let initializingCount = 0; - for (let i=0; i= this.actionQueue.length) break; - - // Initialize this worker - console.log(`Worker ${i} not initialized yet. Initializing...`); - initializingCount++; - await this.startWorker(i); - //this.startWorker(i); - } - } - } - - queueAction(actionData, transfers) { - const d = new Deferred(); - - if (this.singleThread) { - const res = this.taskManager(actionData); - d.resolve(res); - } else { - this.actionQueue.push({ - data: actionData, - transfers: transfers, - deferred: d - }); - this.processWorks(); - } - return d.promise; - } - - resetMemory() { - this.u32[0] = this.initalPFree; - } - - allocBuff(buff) { - const pointer = this.alloc(buff.byteLength); - this.setBuff(pointer, buff); - return pointer; - } - - getBuff(pointer, length) { - return this.u8.slice(pointer, pointer+ length); - } - - setBuff(pointer, buffer) { - this.u8.set(new Uint8Array(buffer), pointer); - } - - alloc(length) { - while (this.u32[0] & 3) this.u32[0]++; // Return always aligned pointers - const res = this.u32[0]; - this.u32[0] += length; - return res; - } - - async terminate() { - console.log("terminate!!!"); - for (let i=0; i=0; i--) { - if (!G.isZero(res)) { - for (let j=0; jMAX_CHUNK_SIZE) chunkSize = MAX_CHUNK_SIZE; - if (chunkSize { - if (logger) logger.debug(`Multiexp end: ${logText}: ${i}/${nPoints}`); - return r; - })); - } - - let result = await Promise.all(opPromises); - - let res = G.zero; - for (let i=result.length-1; i>=0; i--) { - res = G.add(res, result[i]); - } - - return res; - } - - G.multiExp = async function multiExpAffine(buffBases, buffScalars, logger, logText) { - return await _multiExp(buffBases, buffScalars, "jacobian", logger, logText); - }; - G.multiExpAffine = async function multiExpAffine(buffBases, buffScalars, logger, logText) { - return await _multiExp(buffBases, buffScalars, "affine", logger, logText); - }; - } - - function buildFFT$2(curve, groupName) { - const G = curve[groupName]; - const Fr = curve.Fr; - const tm = G.tm; - async function _fft(buff, inverse, inType, outType, logger, loggerTxt) { - - inType = inType || "affine"; - outType = outType || "affine"; - const MAX_BITS_THREAD = 14; - - let sIn, sMid, sOut, fnIn2Mid, fnMid2Out, fnFFTMix, fnFFTJoin, fnFFTFinal, fnReversePermutation; - if (groupName == "G1") { - if (inType == "affine") { - sIn = G.F.n8*2; - fnIn2Mid = "g1m_batchToJacobian"; - } else { - sIn = G.F.n8*3; - } - sMid = G.F.n8*3; - if (inverse) { - fnFFTFinal = "g1m_fftFinal"; - } - fnFFTJoin = "g1m_fftJoin"; - fnFFTMix = "g1m_fftMix"; - fnReversePermutation = "g1m_reversePermutation"; - - if (outType == "affine") { - sOut = G.F.n8*2; - fnMid2Out = "g1m_batchToAffine"; - } else { - sOut = G.F.n8*3; - } - - } else if (groupName == "G2") { - if (inType == "affine") { - sIn = G.F.n8*2; - fnIn2Mid = "g2m_batchToJacobian"; - } else { - sIn = G.F.n8*3; - } - sMid = G.F.n8*3; - if (inverse) { - fnFFTFinal = "g2m_fftFinal"; - } - fnFFTJoin = "g2m_fftJoin"; - fnFFTMix = "g2m_fftMix"; - fnReversePermutation = "g2m_reversePermutation"; - if (outType == "affine") { - sOut = G.F.n8*2; - fnMid2Out = "g2m_batchToAffine"; - } else { - sOut = G.F.n8*3; - } - } else if (groupName == "Fr") { - sIn = G.n8; - sMid = G.n8; - sOut = G.n8; - if (inverse) { - fnFFTFinal = "frm_fftFinal"; - } - fnFFTMix = "frm_fftMix"; - fnFFTJoin = "frm_fftJoin"; - fnReversePermutation = "frm_fftReversePermutation"; - } - - - let returnArray = false; - if (Array.isArray(buff)) { - buff = array2buffer(buff, sIn); - returnArray = true; - } else { - buff = buff.slice(0, buff.byteLength); - } - - console.log("FFT input size:", buff.byteLength, " bytes"); - - const nPoints = buff.byteLength / sIn; - const bits = log2$2(nPoints); - - console.log("FFT points:", nPoints, " bits:", bits); - - if ((1 << bits) != nPoints) { - throw new Error("fft must be multiple of 2" ); - } - - if (bits == Fr.s +1) { - let buffOut; - - if (inverse) { - buffOut = await _fftExtInv(buff, inType, outType, logger, loggerTxt); - } else { - buffOut = await _fftExt(buff, inType, outType, logger, loggerTxt); - } - - if (returnArray) { - return buffer2array(buffOut, sOut); - } else { - return buffOut; - } - } - - let inv; - if (inverse) { - inv = Fr.inv(Fr.e(nPoints)); - } - - let buffOut; - - // TODO: optimize. Move to wasm? - //buffReverseBits(buff, sIn); - - console.log("fnReversePermutation:", fnReversePermutation); - - const task = []; - task.push({cmd: "ALLOC", var: 0, len: buff.byteLength}); - task.push({cmd: "SET", var: 0, buff: buff}); - task.push({cmd: "CALL", fnName: fnReversePermutation, params: [{var:0}, {val: bits}, {var: 0}]}); - task.push({cmd: "GET", out:0, var: 0, len: buff.byteLength}); - const res = await tm.queueAction(task, [buff.buffer]); - - buff.set(res[0]); - - let chunks; - let pointsInChunk = Math.min(1 << MAX_BITS_THREAD, nPoints); - let nChunks = nPoints / pointsInChunk; - - while ((nChunks < tm.concurrency)&&(pointsInChunk>=16)) { - nChunks *= 2; - pointsInChunk /= 2; - } - - const l2Chunk = log2$2(pointsInChunk); - - const promises = []; - for (let i = 0; i< nChunks; i++) { - if (logger) logger.debug(`${loggerTxt}: fft ${bits} mix start: ${i}/${nChunks}`); - const task = []; - task.push({cmd: "ALLOC", var: 0, len: sMid*pointsInChunk}); - const buffChunk = buff.slice( (pointsInChunk * i)*sIn, (pointsInChunk * (i+1))*sIn); - task.push({cmd: "SET", var: 0, buff: buffChunk}); - if (fnIn2Mid) { - task.push({cmd: "CALL", fnName:fnIn2Mid, params: [{var:0}, {val: pointsInChunk}, {var: 0}]}); - } - for (let j=1; j<=l2Chunk;j++) { - task.push({cmd: "CALL", fnName:fnFFTMix, params: [{var:0}, {val: pointsInChunk}, {val: j}]}); - } - - if (l2Chunk==bits) { - if (fnFFTFinal) { - task.push({cmd: "ALLOCSET", var: 1, buff: inv}); - task.push({cmd: "CALL", fnName: fnFFTFinal, params:[ - {var: 0}, - {val: pointsInChunk}, - {var: 1}, - ]}); - } - if (fnMid2Out) { - task.push({cmd: "CALL", fnName:fnMid2Out, params: [{var:0}, {val: pointsInChunk}, {var: 0}]}); - } - task.push({cmd: "GET", out: 0, var: 0, len: pointsInChunk*sOut}); - } else { - task.push({cmd: "GET", out:0, var: 0, len: sMid*pointsInChunk}); - } - promises.push(tm.queueAction(task, [buffChunk.buffer]).then( (r) => { - if (logger) logger.debug(`${loggerTxt}: fft ${bits} mix end: ${i}/${nChunks}`); - return r; - })); - } - - chunks = await Promise.all(promises); - for (let i = 0; i< nChunks; i++) chunks[i] = chunks[i][0]; - - for (let i = l2Chunk+1; i<=bits; i++) { - if (logger) logger.debug(`${loggerTxt}: fft ${bits} join: ${i}/${bits}`); - const nGroups = 1 << (bits - i); - const nChunksPerGroup = nChunks / nGroups; - const opPromises = []; - for (let j=0; j { - if (logger) logger.debug(`${loggerTxt}: fft ${bits} join ${i}/${bits} ${j+1}/${nGroups} ${k}/${nChunksPerGroup/2}`); - return r; - })); - } - } - - const res = await Promise.all(opPromises); - for (let j=0; j0; i--) { - buffOut.set(chunks[i], p); - p += pointsInChunk*sOut; - delete chunks[i]; // Liberate mem - } - buffOut.set(chunks[0].slice(0, (pointsInChunk-1)*sOut), p); - delete chunks[0]; - } else { - for (let i=0; i (1<<28)) { - buffOut = new BigBuffer(res1[0].byteLength*2); - } else { - buffOut = new Uint8Array(res1[0].byteLength*2); - } - - buffOut.set(res1[0]); - buffOut.set(res1[1], res1[0].byteLength); - - return buffOut; - } - - async function _fftExtInv(buff, inType, outType, logger, loggerTxt) { - let b1, b2; - b1 = buff.slice( 0 , buff.byteLength/2); - b2 = buff.slice( buff.byteLength/2, buff.byteLength); - - const promises = []; - - promises.push( _fft(b1, true, inType, "jacobian", logger, loggerTxt)); - promises.push( _fft(b2, true, inType, "jacobian", logger, loggerTxt)); - - [b1, b2] = await Promise.all(promises); - - const res1 = await _fftJoinExt(b1, b2, "fftJoinExtInv", Fr.one, Fr.shiftInv, "jacobian", outType, logger, loggerTxt); - - let buffOut; - if (res1[0].byteLength > (1<<28)) { - buffOut = new BigBuffer(res1[0].byteLength*2); - } else { - buffOut = new Uint8Array(res1[0].byteLength*2); - } - - buffOut.set(res1[0]); - buffOut.set(res1[1], res1[0].byteLength); - - return buffOut; - } - - - async function _fftJoinExt(buff1, buff2, fn, first, inc, inType, outType, logger, loggerTxt) { - const MAX_CHUNK_SIZE = 1<<16; - const MIN_CHUNK_SIZE = 1<<4; - - let fnName; - let fnIn2Mid, fnMid2Out; - let sOut, sIn, sMid; - - if (groupName == "G1") { - if (inType == "affine") { - sIn = G.F.n8*2; - fnIn2Mid = "g1m_batchToJacobian"; - } else { - sIn = G.F.n8*3; - } - sMid = G.F.n8*3; - fnName = "g1m_"+fn; - if (outType == "affine") { - fnMid2Out = "g1m_batchToAffine"; - sOut = G.F.n8*2; - } else { - sOut = G.F.n8*3; - } - } else if (groupName == "G2") { - if (inType == "affine") { - sIn = G.F.n8*2; - fnIn2Mid = "g2m_batchToJacobian"; - } else { - sIn = G.F.n8*3; - } - fnName = "g2m_"+fn; - sMid = G.F.n8*3; - if (outType == "affine") { - fnMid2Out = "g2m_batchToAffine"; - sOut = G.F.n8*2; - } else { - sOut = G.F.n8*3; - } - } else if (groupName == "Fr") { - sIn = Fr.n8; - sOut = Fr.n8; - sMid = Fr.n8; - fnName = "frm_" + fn; - } else { - throw new Error("Invalid group"); - } - - if (buff1.byteLength != buff2.byteLength) { - throw new Error("Invalid buffer size"); - } - const nPoints = Math.floor(buff1.byteLength / sIn); - if (nPoints != 1 << log2$2(nPoints)) { - throw new Error("Invalid number of points"); - } - - let chunkSize = Math.floor(nPoints /tm.concurrency); - if (chunkSize < MIN_CHUNK_SIZE) chunkSize = MIN_CHUNK_SIZE; - if (chunkSize > MAX_CHUNK_SIZE) chunkSize = MAX_CHUNK_SIZE; - - const opPromises = []; - - for (let i=0; i { - if (logger) logger.debug(`${loggerTxt}: fftJoinExt End: ${i}/${nPoints}`); - return r; - }) - ); - } - - const result = await Promise.all(opPromises); - - let fullBuffOut1; - let fullBuffOut2; - if (nPoints * sOut > 1<<28) { - fullBuffOut1 = new BigBuffer(nPoints*sOut); - fullBuffOut2 = new BigBuffer(nPoints*sOut); - } else { - fullBuffOut1 = new Uint8Array(nPoints*sOut); - fullBuffOut2 = new Uint8Array(nPoints*sOut); - } - - let p =0; - for (let i=0; i Fr.s+1) { - if (logger) logger.error("lagrangeEvaluations input too big"); - throw new Error("lagrangeEvaluations input too big"); - } - - let t0 = buff.slice(0, buff.byteLength/2); - let t1 = buff.slice(buff.byteLength/2, buff.byteLength); - - - const shiftToSmallM = Fr.exp(Fr.shift, nPoints/2); - const sConst = Fr.inv( Fr.sub(Fr.one, shiftToSmallM)); - - [t0, t1] = await _fftJoinExt(t0, t1, "prepareLagrangeEvaluation", sConst, Fr.shiftInv, inType, "jacobian", logger, loggerTxt + " prep"); - - const promises = []; - - promises.push( _fft(t0, true, "jacobian", outType, logger, loggerTxt + " t0")); - promises.push( _fft(t1, true, "jacobian", outType, logger, loggerTxt + " t1")); - - [t0, t1] = await Promise.all(promises); - - let buffOut; - if (t0.byteLength > (1<<28)) { - buffOut = new BigBuffer(t0.byteLength*2); - } else { - buffOut = new Uint8Array(t0.byteLength*2); - } - - buffOut.set(t0); - buffOut.set(t1, t0.byteLength); - - return buffOut; - }; - - G.fftMix = async function fftMix(buff) { - const sG = G.F.n8*3; - let fnName, fnFFTJoin; - if (groupName == "G1") { - fnName = "g1m_fftMix"; - fnFFTJoin = "g1m_fftJoin"; - } else if (groupName == "G2") { - fnName = "g2m_fftMix"; - fnFFTJoin = "g2m_fftJoin"; - } else if (groupName == "Fr") { - fnName = "frm_fftMix"; - fnFFTJoin = "frm_fftJoin"; - } else { - throw new Error("Invalid group"); - } - - const nPoints = Math.floor(buff.byteLength / sG); - const power = log2$2(nPoints); - - let nChunks = 1 << log2$2(tm.concurrency); - - if (nPoints <= nChunks*2) nChunks = 1; - - const pointsPerChunk = nPoints / nChunks; - - const powerChunk = log2$2(pointsPerChunk); - - const opPromises = []; - for (let i=0; i=0; i--) { - fullBuffOut.set(result[i][0], p); - p+=result[i][0].byteLength; - } - - return fullBuffOut; - }; - } - - async function buildEngine(params) { - - const tm = await buildThreadManager(params.wasm, params.singleThread); - - - const curve = {}; - - curve.q = e(params.wasm.q.toString()); - curve.r = e(params.wasm.r.toString()); - curve.name = params.name; - curve.tm = tm; - curve.prePSize = params.wasm.prePSize; - curve.preQSize = params.wasm.preQSize; - curve.Fr = new WasmField1(tm, "frm", params.n8r, params.r); - curve.F1 = new WasmField1(tm, "f1m", params.n8q, params.q); - curve.F2 = new WasmField2(tm, "f2m", curve.F1); - curve.G1 = new WasmCurve(tm, "g1m", curve.F1, params.wasm.pG1gen, params.wasm.pG1b, params.cofactorG1); - curve.G2 = new WasmCurve(tm, "g2m", curve.F2, params.wasm.pG2gen, params.wasm.pG2b, params.cofactorG2); - curve.F6 = new WasmField3(tm, "f6m", curve.F2); - curve.F12 = new WasmField2(tm, "ftm", curve.F6); - - curve.Gt = curve.F12; - - buildBatchApplyKey(curve, "G1"); - buildBatchApplyKey(curve, "G2"); - buildBatchApplyKey(curve, "Fr"); - - buildMultiexp$1(curve, "G1"); - buildMultiexp$1(curve, "G2"); - - buildFFT$2(curve, "G1"); - buildFFT$2(curve, "G2"); - buildFFT$2(curve, "Fr"); - - buildPairing(curve); - - curve.array2buffer = function(arr, sG) { - const buff = new Uint8Array(sG*arr.length); - - for (let i=0; i. - */ - - utils$5.bigInt2BytesLE = function bigInt2BytesLE(_a, len) { - const b = Array(len); - let v = BigInt(_a); - for (let i=0; i> 8n; - } - return b; - }; - - utils$5.bigInt2U32LE = function bigInt2BytesLE(_a, len) { - const b = Array(len); - let v = BigInt(_a); - for (let i=0; i> 32n; - } - return b; - }; - - utils$5.isOcamNum = function(a) { - if (!Array.isArray(a)) return false; - if (a.length != 3) return false; - if (typeof a[0] !== "number") return false; - if (typeof a[1] !== "number") return false; - if (!Array.isArray(a[2])) return false; - return true; - }; - - /* - Copyright 2019 0KIMS association. - - This file is part of wasmsnark (Web Assembly zkSnark Prover). - - wasmsnark is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - wasmsnark is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with wasmsnark. If not, see . - */ - - var build_int = function buildInt(module, n64, _prefix) { - - const prefix = _prefix || "int"; - if (module.modules[prefix]) return prefix; // already builded - module.modules[prefix] = {}; - - const n32 = n64*2; - const n8 = n64*8; - - function buildCopy() { - const f = module.addFunction(prefix+"_copy"); - f.addParam("px", "i32"); - f.addParam("pr", "i32"); - - const c = f.getCodeBuilder(); - - for (let i=0; i>1) )&&(i>1, k>>1) - ) - ) - ); - - f.addCode( - c.setLocal(c1, - c.i64_add( - c.getLocal(c1), - c.i64_shr_u( - c.getLocal(c0), - c.i64_const(32) - ) - ) - ) - ); - } - - // Add the old carry - - if (k>0) { - f.addCode( - c.setLocal(c0, - c.i64_add( - c.i64_and( - c.getLocal(c0), - c.i64_const(0xFFFFFFFF) - ), - c.i64_and( - c.getLocal(c0_old), - c.i64_const(0xFFFFFFFF) - ), - ) - ) - ); - - f.addCode( - c.setLocal(c1, - c.i64_add( - c.i64_add( - c.getLocal(c1), - c.i64_shr_u( - c.getLocal(c0), - c.i64_const(32) - ) - ), - c.getLocal(c1_old) - ) - ) - ); - } - - f.addCode( - c.i64_store32( - c.getLocal("r"), - k*4, - c.getLocal(c0) - ) - ); - - f.addCode( - c.setLocal( - c0_old, - c.getLocal(c1) - ), - c.setLocal( - c1_old, - c.i64_shr_u( - c.getLocal(c0_old), - c.i64_const(32) - ) - ) - ); - - } - f.addCode( - c.i64_store32( - c.getLocal("r"), - n32*4*2-4, - c.getLocal(c0_old) - ) - ); - - } - - - function buildSquareOld() { - const f = module.addFunction(prefix+"_squareOld"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - f.addCode(c.call(prefix + "_mul", c.getLocal("x"), c.getLocal("x"), c.getLocal("r"))); - } - - function _buildMul1() { - const f = module.addFunction(prefix+"__mul1"); - f.addParam("px", "i32"); - f.addParam("y", "i64"); - f.addParam("pr", "i32"); - f.addLocal("c", "i64"); - - const c = f.getCodeBuilder(); - - f.addCode(c.setLocal( - "c", - c.i64_mul( - c.i64_load32_u(c.getLocal("px"), 0, 0), - c.getLocal("y") - ) - )); - - f.addCode(c.i64_store32( - c.getLocal("pr"), - 0, - 0, - c.getLocal("c"), - )); - - for (let i=1; i3)&&(Y[eY]==0) ey--; - f.addCode(c.block(c.loop( - c.br_if( - 1, - c.i32_or( - c.i32_load8_u( - c.i32_add(Y , c.getLocal("eY")), - 0, - 0 - ), - c.i32_eq( - c.getLocal("eY"), - c.i32_const(3) - ) - ) - ), - c.setLocal("eY", c.i32_sub(c.getLocal("eY"), c.i32_const(1))), - c.br(0) - ))); - - f.addCode( - c.setLocal( - "sy", - c.i64_add( - c.i64_load32_u( - c.i32_sub( - c.i32_add( Y, c.getLocal("eY")), - c.i32_const(3) - ), - 0, - 0 - ), - c.i64_const(1) - ) - ) - ); - - // Force a divide by 0 if quotien is 0 - f.addCode( - c.if( - c.i64_eq( - c.getLocal("sy"), - c.i64_const(1) - ), - c.drop(c.i64_div_u(c.i64_const(0), c.i64_const(0))) - ) - ); - - f.addCode(c.block(c.loop( - - // while (eX>7)&&(Y[eX]==0) ex--; - c.block(c.loop( - c.br_if( - 1, - c.i32_or( - c.i32_load8_u( - c.i32_add(R , c.getLocal("eX")), - 0, - 0 - ), - c.i32_eq( - c.getLocal("eX"), - c.i32_const(7) - ) - ) - ), - c.setLocal("eX", c.i32_sub(c.getLocal("eX"), c.i32_const(1))), - c.br(0) - )), - - c.setLocal( - "sx", - c.i64_load( - c.i32_sub( - c.i32_add( R, c.getLocal("eX")), - c.i32_const(7) - ), - 0, - 0 - ) - ), - - c.setLocal( - "sx", - c.i64_div_u( - c.getLocal("sx"), - c.getLocal("sy") - ) - ), - c.setLocal( - "ec", - c.i32_sub( - c.i32_sub( - c.getLocal("eX"), - c.getLocal("eY") - ), - c.i32_const(4) - ) - ), - - // While greater than 32 bits or ec is neg, shr and inc exp - c.block(c.loop( - c.br_if( - 1, - c.i32_and( - c.i64_eqz( - c.i64_and( - c.getLocal("sx"), - c.i64_const("0xFFFFFFFF00000000") - ) - ), - c.i32_ge_s( - c.getLocal("ec"), - c.i32_const(0) - ) - ) - ), - - c.setLocal( - "sx", - c.i64_shr_u( - c.getLocal("sx"), - c.i64_const(8) - ) - ), - - c.setLocal( - "ec", - c.i32_add( - c.getLocal("ec"), - c.i32_const(1) - ) - ), - c.br(0) - )), - - c.if( - c.i64_eqz(c.getLocal("sx")), - [ - ...c.br_if( - 2, - c.i32_eqz(c.call(prefix + "_gte", R, Y)) - ), - ...c.setLocal("sx", c.i64_const(1)), - ...c.setLocal("ec", c.i32_const(0)) - ] - ), - - c.call(prefix + "__mul1", Y, c.getLocal("sx"), R2), - c.drop(c.call( - prefix + "_sub", - R, - c.i32_sub(R2, c.getLocal("ec")), - R - )), - c.call( - prefix + "__add1", - c.i32_add(C, c.getLocal("ec")), - c.getLocal("sx") - ), - c.br(0) - ))); - } - - function buildInverseMod() { - - const f = module.addFunction(prefix+"_inverseMod"); - f.addParam("px", "i32"); - f.addParam("pm", "i32"); - f.addParam("pr", "i32"); - f.addLocal("t", "i32"); - f.addLocal("newt", "i32"); - f.addLocal("r", "i32"); - f.addLocal("qq", "i32"); - f.addLocal("qr", "i32"); - f.addLocal("newr", "i32"); - f.addLocal("swp", "i32"); - f.addLocal("x", "i32"); - f.addLocal("signt", "i32"); - f.addLocal("signnewt", "i32"); - f.addLocal("signx", "i32"); - - const c = f.getCodeBuilder(); - - const aux1 = c.i32_const(module.alloc(n8)); - const aux2 = c.i32_const(module.alloc(n8)); - const aux3 = c.i32_const(module.alloc(n8)); - const aux4 = c.i32_const(module.alloc(n8)); - const aux5 = c.i32_const(module.alloc(n8)); - const aux6 = c.i32_const(module.alloc(n8)); - const mulBuff = c.i32_const(module.alloc(n8*2)); - const aux7 = c.i32_const(module.alloc(n8)); - - f.addCode( - c.setLocal("t", aux1), - c.call(prefix + "_zero", aux1), - c.setLocal("signt", c.i32_const(0)), - ); - - f.addCode( - c.setLocal("r", aux2), - c.call(prefix + "_copy", c.getLocal("pm"), aux2) - ); - - f.addCode( - c.setLocal("newt", aux3), - c.call(prefix + "_one", aux3), - c.setLocal("signnewt", c.i32_const(0)), - ); - - f.addCode( - c.setLocal("newr", aux4), - c.call(prefix + "_copy", c.getLocal("px"), aux4) - ); - - - - - f.addCode(c.setLocal("qq", aux5)); - f.addCode(c.setLocal("qr", aux6)); - f.addCode(c.setLocal("x", aux7)); - - f.addCode(c.block(c.loop( - c.br_if( - 1, - c.call(prefix + "_isZero", c.getLocal("newr") ) - ), - c.call(prefix + "_div", c.getLocal("r"), c.getLocal("newr"), c.getLocal("qq"), c.getLocal("qr")), - - c.call(prefix + "_mul", c.getLocal("qq"), c.getLocal("newt"), mulBuff), - - c.if( - c.getLocal("signt"), - c.if( - c.getLocal("signnewt"), - c.if ( - c.call(prefix + "_gte", mulBuff, c.getLocal("t")), - [ - ...c.drop(c.call(prefix + "_sub", mulBuff, c.getLocal("t"), c.getLocal("x"))), - ...c.setLocal("signx", c.i32_const(0)) - ], - [ - ...c.drop(c.call(prefix + "_sub", c.getLocal("t"), mulBuff, c.getLocal("x"))), - ...c.setLocal("signx", c.i32_const(1)) - ], - ), - [ - ...c.drop(c.call(prefix + "_add", mulBuff, c.getLocal("t"), c.getLocal("x"))), - ...c.setLocal("signx", c.i32_const(1)) - ] - ), - c.if( - c.getLocal("signnewt"), - [ - ...c.drop(c.call(prefix + "_add", mulBuff, c.getLocal("t"), c.getLocal("x"))), - ...c.setLocal("signx", c.i32_const(0)) - ], - c.if ( - c.call(prefix + "_gte", c.getLocal("t"), mulBuff), - [ - ...c.drop(c.call(prefix + "_sub", c.getLocal("t"), mulBuff, c.getLocal("x"))), - ...c.setLocal("signx", c.i32_const(0)) - ], - [ - ...c.drop(c.call(prefix + "_sub", mulBuff, c.getLocal("t"), c.getLocal("x"))), - ...c.setLocal("signx", c.i32_const(1)) - ] - ) - ) - ), - - c.setLocal("swp", c.getLocal("t")), - c.setLocal("t", c.getLocal("newt")), - c.setLocal("newt", c.getLocal("x")), - c.setLocal("x", c.getLocal("swp")), - - c.setLocal("signt", c.getLocal("signnewt")), - c.setLocal("signnewt", c.getLocal("signx")), - - c.setLocal("swp", c.getLocal("r")), - c.setLocal("r", c.getLocal("newr")), - c.setLocal("newr", c.getLocal("qr")), - c.setLocal("qr", c.getLocal("swp")), - - c.br(0) - ))); - - f.addCode(c.if( - c.getLocal("signt"), - c.drop(c.call(prefix + "_sub", c.getLocal("pm"), c.getLocal("t"), c.getLocal("pr"))), - c.call(prefix + "_copy", c.getLocal("t"), c.getLocal("pr")) - )); - } - - - buildCopy(); - buildZero(); - buildIsZero(); - buildOne(); - buildEq(); - buildGte(); - buildAdd(); - buildSub(); - buildMul(); - buildSquare(); - buildSquareOld(); - buildDiv(); - buildInverseMod(); - module.exportFunction(prefix+"_copy"); - module.exportFunction(prefix+"_zero"); - module.exportFunction(prefix+"_one"); - module.exportFunction(prefix+"_isZero"); - module.exportFunction(prefix+"_eq"); - module.exportFunction(prefix+"_gte"); - module.exportFunction(prefix+"_add"); - module.exportFunction(prefix+"_sub"); - module.exportFunction(prefix+"_mul"); - module.exportFunction(prefix+"_square"); - module.exportFunction(prefix+"_squareOld"); - module.exportFunction(prefix+"_div"); - module.exportFunction(prefix+"_inverseMod"); - - return prefix; - }; - - /* - Copyright 2019 0KIMS association. - - This file is part of wasmsnark (Web Assembly zkSnark Prover). - - wasmsnark is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - wasmsnark is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with wasmsnark. If not, see . - */ - - var build_timesscalar = function buildTimesScalar(module, fnName, elementLen, opAB, opAA, opCopy, opInit) { - - const f = module.addFunction(fnName); - f.addParam("base", "i32"); - f.addParam("scalar", "i32"); - f.addParam("scalarLength", "i32"); - f.addParam("r", "i32"); - f.addLocal("i", "i32"); - f.addLocal("b", "i32"); - - const c = f.getCodeBuilder(); - - const aux = c.i32_const(module.alloc(elementLen)); - - f.addCode( - c.if( - c.i32_eqz(c.getLocal("scalarLength")), - [ - ...c.call(opInit, c.getLocal("r")), - ...c.ret([]) - ] - ) - ); - f.addCode(c.call(opCopy, c.getLocal("base"), aux)); - f.addCode(c.call(opInit, c.getLocal("r"))); - f.addCode(c.setLocal("i", c.getLocal("scalarLength"))); - f.addCode(c.block(c.loop( - c.setLocal("i", c.i32_sub(c.getLocal("i"), c.i32_const(1))), - - c.setLocal( - "b", - c.i32_load8_u( - c.i32_add( - c.getLocal("scalar"), - c.getLocal("i") - ) - ) - ), - ...innerLoop(), - c.br_if(1, c.i32_eqz ( c.getLocal("i") )), - c.br(0) - ))); - - - function innerLoop() { - const code = []; - for (let i=0; i<8; i++) { - code.push( - ...c.call(opAA, c.getLocal("r"), c.getLocal("r")), - ...c.if( - c.i32_ge_u( c.getLocal("b"), c.i32_const(0x80 >> i)), - [ - ...c.setLocal( - "b", - c.i32_sub( - c.getLocal("b"), - c.i32_const(0x80 >> i) - ) - ), - ...c.call(opAB, c.getLocal("r"),aux, c.getLocal("r")) - ] - ) - ); - } - return code; - } - - }; - - var build_batchinverse = buildBatchInverse$3; - - function buildBatchInverse$3(module, prefix) { - - - const n8 = module.modules[prefix].n64*8; - - const f = module.addFunction(prefix+"_batchInverse"); - f.addParam("pIn", "i32"); - f.addParam("inStep", "i32"); - f.addParam("n", "i32"); - f.addParam("pOut", "i32"); - f.addParam("outStep", "i32"); - f.addLocal("itAux", "i32"); - f.addLocal("itIn", "i32"); - f.addLocal("itOut","i32"); - f.addLocal("i","i32"); - - const c = f.getCodeBuilder(); - - const AUX = c.i32_const(module.alloc(n8)); - - - // Alloc Working space for accumulated umltiplications - f.addCode( - c.setLocal("itAux", c.i32_load( c.i32_const(0) )), - c.i32_store( - c.i32_const(0), - c.i32_add( - c.getLocal("itAux"), - c.i32_mul( - c.i32_add( - c.getLocal("n"), - c.i32_const(1) - ), - c.i32_const(n8) - ) - ) - ) - ); - - f.addCode( - - // aux[0] = a; - c.call(prefix+"_one", c.getLocal("itAux")), - // for (i=0;i b ? 1 : -1; - } - - function square$1(n) { - return n * n; - } - - function isOdd$4(n) { - return n % 2n !== 0n; - } - - function isEven(n) { - return n % 2n === 0n; - } - - function isNegative$3(n) { - return n < 0n; - } - - function isPositive(n) { - return n > 0n; - } - - function bitLength$5(n) { - if (isNegative$3(n)) { - return n.toString(2).length - 1; // discard the - sign - } else { - return n.toString(2).length; - } - } - - function abs(n) { - return n < 0n ? -n : n; - } - - function isUnit(n) { - return abs(n) === 1n; - } - - function modInv$3(a, n) { - var t = 0n, newT = 1n, r = n, newR = abs(a), q, lastT, lastR; - while (newR !== 0n) { - q = r / newR; - lastT = t; - lastR = r; - t = newT; - r = newR; - newT = lastT - (q * newT); - newR = lastR - (q * newR); - } - if (!isUnit(r)) throw new Error(a.toString() + " and " + n.toString() + " are not co-prime"); - if (compare(t, 0n) === -1) { - t = t + n; - } - if (isNegative$3(a)) { - return -t; - } - return t; - } - - function modPow$2(n, exp, mod) { - if (mod === 0n) throw new Error("Cannot take modPow with modulus 0"); - var r = 1n, - base = n % mod; - if (isNegative$3(exp)) { - exp = exp * -1n; - base = modInv$3(base, mod); - } - while (isPositive(exp)) { - if (base === 0n) return 0n; - if (isOdd$4(exp)) r = r * base % mod; - exp = exp / 2n; - base = square$1(base) % mod; - } - return r; - } - - function compareAbs(a, b) { - a = a >= 0n ? a : -a; - b = b >= 0n ? b : -b; - return a === b ? 0 : a > b ? 1 : -1; - } - - function isDivisibleBy(a, n) { - if (n === 0n) return false; - if (isUnit(n)) return true; - if (compareAbs(n, 2n) === 0) return isEven(a); - return a % n === 0n; - } - - function isBasicPrime(v) { - var n = abs(v); - if (isUnit(n)) return false; - if (n === 2n || n === 3n || n === 5n) return true; - if (isEven(n) || isDivisibleBy(n, 3n) || isDivisibleBy(n, 5n)) return false; - if (n < 49n) return true; - // we don't know if it's prime: let the other functions figure it out - } - - function prev(n) { - return n - 1n; - } - - function millerRabinTest(n, a) { - var nPrev = prev(n), - b = nPrev, - r = 0, - d, i, x; - while (isEven(b)) b = b / 2n, r++; - next: for (i = 0; i < a.length; i++) { - if (n < a[i]) continue; - x = modPow$2(BigInt(a[i]), b, n); - if (isUnit(x) || x === nPrev) continue; - for (d = r - 1; d != 0; d--) { - x = square$1(x) % n; - if (isUnit(x)) return false; - if (x === nPrev) continue next; - } - return false; - } - return true; - } - - function isPrime$1(p) { - var isPrime = isBasicPrime(p); - if (isPrime !== undefined) return isPrime; - var n = abs(p); - var bits = bitLength$5(n); - if (bits <= 64) - return millerRabinTest(n, [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]); - var logN = Math.log(2) * Number(bits); - var t = Math.ceil(logN); - for (var a = [], i = 0; i < t; i++) { - a.push(BigInt(i + 2)); - } - return millerRabinTest(n, a); - } - - bigint.bitLength = bitLength$5; - bigint.isOdd = isOdd$4; - bigint.isNegative = isNegative$3; - bigint.abs = abs; - bigint.isUnit = isUnit; - bigint.compare = compare; - bigint.modInv = modInv$3; - bigint.modPow = modPow$2; - bigint.isPrime = isPrime$1; - bigint.square = square$1; - - /* - Copyright 2019 0KIMS association. - - This file is part of wasmsnark (Web Assembly zkSnark Prover). - - wasmsnark is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - wasmsnark is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with wasmsnark. If not, see . - */ - - const buildInt = build_int; - const utils$4 = utils$5; - const buildExp$2 = build_timesscalar; - const buildBatchInverse$2 = build_batchinverse; - const buildBatchConvertion$1 = build_batchconvertion; - const buildBatchOp = build_batchop; - const { bitLength: bitLength$4, modInv: modInv$2, modPow: modPow$1, isPrime, isOdd: isOdd$3, square } = bigint; - - var build_f1m = function buildF1m(module, _q, _prefix, _intPrefix) { - const q = BigInt(_q); - const n64 = Math.floor((bitLength$4(q - 1n) - 1)/64) +1; - const n32 = n64*2; - const n8 = n64*8; - - const prefix = _prefix || "f1m"; - if (module.modules[prefix]) return prefix; // already builded - - const intPrefix = buildInt(module, n64, _intPrefix); - const pq = module.alloc(n8, utils$4.bigInt2BytesLE(q, n8)); - - const pR2 = module.alloc(utils$4.bigInt2BytesLE(square(1n << BigInt(n64*64)) % q, n8)); - const pOne = module.alloc(utils$4.bigInt2BytesLE((1n << BigInt(n64*64)) % q, n8)); - const pZero = module.alloc(utils$4.bigInt2BytesLE(0n, n8)); - const _minusOne = q - 1n; - const _e = _minusOne >> 1n; // e = (p-1)/2 - const pe = module.alloc(n8, utils$4.bigInt2BytesLE(_e, n8)); - - const _ePlusOne = _e + 1n; // e = (p-1)/2 - const pePlusOne = module.alloc(n8, utils$4.bigInt2BytesLE(_ePlusOne, n8)); - - module.modules[prefix] = { - pq: pq, - pR2: pR2, - n64: n64, - q: q, - pOne: pOne, - pZero: pZero, - pePlusOne: pePlusOne - }; - - function buildOne() { - const f = module.addFunction(prefix+"_one"); - f.addParam("pr", "i32"); - - const c = f.getCodeBuilder(); - - f.addCode(c.call(intPrefix + "_copy", c.i32_const(pOne), c.getLocal("pr"))); - } - - function buildAdd() { - const f = module.addFunction(prefix+"_add"); - f.addParam("x", "i32"); - f.addParam("y", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - f.addCode( - c.if( - c.call(intPrefix+"_add", c.getLocal("x"), c.getLocal("y"), c.getLocal("r")), - c.drop(c.call(intPrefix+"_sub", c.getLocal("r"), c.i32_const(pq), c.getLocal("r"))), - c.if( - c.call(intPrefix+"_gte", c.getLocal("r"), c.i32_const(pq) ), - c.drop(c.call(intPrefix+"_sub", c.getLocal("r"), c.i32_const(pq), c.getLocal("r"))), - ) - ) - ); - } - - function buildSub() { - const f = module.addFunction(prefix+"_sub"); - f.addParam("x", "i32"); - f.addParam("y", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - f.addCode( - c.if( - c.call(intPrefix+"_sub", c.getLocal("x"), c.getLocal("y"), c.getLocal("r")), - c.drop(c.call(intPrefix+"_add", c.getLocal("r"), c.i32_const(pq), c.getLocal("r"))) - ) - ); - } - - function buildNeg() { - const f = module.addFunction(prefix+"_neg"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - f.addCode( - c.call(prefix + "_sub", c.i32_const(pZero), c.getLocal("x"), c.getLocal("r")) - ); - } - - - function buildIsNegative() { - const f = module.addFunction(prefix+"_isNegative"); - f.addParam("x", "i32"); - f.setReturnType("i32"); - - const c = f.getCodeBuilder(); - - const AUX = c.i32_const(module.alloc(n8)); - - f.addCode( - c.call(prefix + "_fromMontgomery", c.getLocal("x"), AUX), - c.call(intPrefix + "_gte", AUX, c.i32_const(pePlusOne) ) - ); - } - - function buildSign() { - const f = module.addFunction(prefix+"_sign"); - f.addParam("x", "i32"); - f.setReturnType("i32"); - - const c = f.getCodeBuilder(); - - const AUX = c.i32_const(module.alloc(n8)); - - f.addCode( - c.if ( - c.call(intPrefix + "_isZero", c.getLocal("x")), - c.ret(c.i32_const(0)) - ), - c.call(prefix + "_fromMontgomery", c.getLocal("x"), AUX), - c.if( - c.call(intPrefix + "_gte", AUX, c.i32_const(pePlusOne)), - c.ret(c.i32_const(-1)) - ), - c.ret(c.i32_const(1)) - ); - } - - - function buildMReduct() { - const carries = module.alloc(n32*n32*8); - - const f = module.addFunction(prefix+"_mReduct"); - f.addParam("t", "i32"); - f.addParam("r", "i32"); - f.addLocal("np32", "i64"); - f.addLocal("c", "i64"); - f.addLocal("m", "i64"); - - const c = f.getCodeBuilder(); - - const np32 = Number(0x100000000n - modInv$2(q, 0x100000000n)); - - f.addCode(c.setLocal("np32", c.i64_const(np32))); - - for (let i=0; i=n32) { - f.addCode( - c.i64_store32( - c.getLocal("r"), - (k-n32)*4, - c.getLocal(c0) - ) - ); - } - [c0, c1] = [c1, c0]; - f.addCode( - c.setLocal(c1, - c.i64_shr_u( - c.getLocal(c0), - c.i64_const(32) - ) - ) - ); - } - f.addCode( - c.i64_store32( - c.getLocal("r"), - n32*4-4, - c.getLocal(c0) - ) - ); - - f.addCode( - c.if( - c.i32_wrap_i64(c.getLocal(c1)), - c.drop(c.call(intPrefix+"_sub", c.getLocal("r"), c.i32_const(pq), c.getLocal("r"))), - c.if( - c.call(intPrefix+"_gte", c.getLocal("r"), c.i32_const(pq) ), - c.drop(c.call(intPrefix+"_sub", c.getLocal("r"), c.i32_const(pq), c.getLocal("r"))), - ) - ) - ); - } - - - function buildSquare() { - - const f = module.addFunction(prefix+"_square"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - f.addLocal("c0", "i64"); - f.addLocal("c1", "i64"); - f.addLocal("c0_old", "i64"); - f.addLocal("c1_old", "i64"); - f.addLocal("np32", "i64"); - - - for (let i=0;i>1) )&&(i>1, k>>1) - ) - ) - ); - - f.addCode( - c.setLocal(c1, - c.i64_add( - c.getLocal(c1), - c.i64_shr_u( - c.getLocal(c0), - c.i64_const(32) - ) - ) - ) - ); - } - - // Add the old carry - - if (k>0) { - f.addCode( - c.setLocal(c0, - c.i64_add( - c.i64_and( - c.getLocal(c0), - c.i64_const(0xFFFFFFFF) - ), - c.i64_and( - c.getLocal(c0_old), - c.i64_const(0xFFFFFFFF) - ), - ) - ) - ); - - f.addCode( - c.setLocal(c1, - c.i64_add( - c.i64_add( - c.getLocal(c1), - c.i64_shr_u( - c.getLocal(c0), - c.i64_const(32) - ) - ), - c.getLocal(c1_old) - ) - ) - ); - } - - - for (let i=Math.max(1, k-n32+1); (i<=k)&&(i=n32) { - f.addCode( - c.i64_store32( - c.getLocal("r"), - (k-n32)*4, - c.getLocal(c0) - ) - ); - } - f.addCode( - c.setLocal( - c0_old, - c.getLocal(c1) - ), - c.setLocal( - c1_old, - c.i64_shr_u( - c.getLocal(c0_old), - c.i64_const(32) - ) - ) - ); - } - f.addCode( - c.i64_store32( - c.getLocal("r"), - n32*4-4, - c.getLocal(c0_old) - ) - ); - - f.addCode( - c.if( - c.i32_wrap_i64(c.getLocal(c1_old)), - c.drop(c.call(intPrefix+"_sub", c.getLocal("r"), c.i32_const(pq), c.getLocal("r"))), - c.if( - c.call(intPrefix+"_gte", c.getLocal("r"), c.i32_const(pq) ), - c.drop(c.call(intPrefix+"_sub", c.getLocal("r"), c.i32_const(pq), c.getLocal("r"))), - ) - ) - ); - } - - - function buildSquareOld() { - const f = module.addFunction(prefix+"_squareOld"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - f.addCode(c.call(prefix + "_mul", c.getLocal("x"), c.getLocal("x"), c.getLocal("r"))); - } - - function buildToMontgomery() { - const f = module.addFunction(prefix+"_toMontgomery"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - f.addCode(c.call(prefix+"_mul", c.getLocal("x"), c.i32_const(pR2), c.getLocal("r"))); - } - - function buildFromMontgomery() { - - const pAux2 = module.alloc(n8*2); - - const f = module.addFunction(prefix+"_fromMontgomery"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - f.addCode(c.call(intPrefix + "_copy", c.getLocal("x"), c.i32_const(pAux2) )); - f.addCode(c.call(intPrefix + "_zero", c.i32_const(pAux2 + n8) )); - f.addCode(c.call(prefix+"_mReduct", c.i32_const(pAux2), c.getLocal("r"))); - } - - function buildInverse() { - - const f = module.addFunction(prefix+ "_inverse"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - f.addCode(c.call(prefix + "_fromMontgomery", c.getLocal("x"), c.getLocal("r"))); - f.addCode(c.call(intPrefix + "_inverseMod", c.getLocal("r"), c.i32_const(pq), c.getLocal("r"))); - f.addCode(c.call(prefix + "_toMontgomery", c.getLocal("r"), c.getLocal("r"))); - } - - // Calculate various valuse needed for sqrt - - - let _nqr = 2n; - if (isPrime(q)) { - while (modPow$1(_nqr, _e, q) !== _minusOne) _nqr = _nqr + 1n; - } - - let s2 = 0; - let _t = _minusOne; - - while ((!isOdd$3(_t))&&(_t !== 0n)) { - s2++; - _t = _t >> 1n; - } - const pt = module.alloc(n8, utils$4.bigInt2BytesLE(_t, n8)); - - const _nqrToT = modPow$1(_nqr, _t, q); - const pNqrToT = module.alloc(utils$4.bigInt2BytesLE((_nqrToT << BigInt(n64*64)) % q, n8)); - - const _tPlusOneOver2 = (_t + 1n) >> 1n; - const ptPlusOneOver2 = module.alloc(n8, utils$4.bigInt2BytesLE(_tPlusOneOver2, n8)); - - function buildSqrt() { - - const f = module.addFunction(prefix+ "_sqrt"); - f.addParam("n", "i32"); - f.addParam("r", "i32"); - f.addLocal("m", "i32"); - f.addLocal("i", "i32"); - f.addLocal("j", "i32"); - - const c = f.getCodeBuilder(); - - const ONE = c.i32_const(pOne); - const C = c.i32_const(module.alloc(n8)); - const T = c.i32_const(module.alloc(n8)); - const R = c.i32_const(module.alloc(n8)); - const SQ = c.i32_const(module.alloc(n8)); - const B = c.i32_const(module.alloc(n8)); - - f.addCode( - - // If (n==0) return 0 - c.if( - c.call(prefix + "_isZero", c.getLocal("n")), - c.ret( - c.call(prefix + "_zero", c.getLocal("r")) - ) - ), - - c.setLocal("m", c.i32_const(s2)), - c.call(prefix + "_copy", c.i32_const(pNqrToT), C), - c.call(prefix + "_exp", c.getLocal("n"), c.i32_const(pt), c.i32_const(n8), T), - c.call(prefix + "_exp", c.getLocal("n"), c.i32_const(ptPlusOneOver2), c.i32_const(n8), R), - - c.block(c.loop( - c.br_if(1, c.call(prefix + "_eq", T, ONE)), - - c.call(prefix + "_square", T, SQ), - c.setLocal("i", c.i32_const(1)), - c.block(c.loop( - c.br_if(1, c.call(prefix + "_eq", SQ, ONE)), - c.call(prefix + "_square", SQ, SQ), - c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), - c.br(0) - )), - - c.call(prefix + "_copy", C, B), - c.setLocal("j", c.i32_sub(c.i32_sub( c.getLocal("m"), c.getLocal("i")), c.i32_const(1)) ), - c.block(c.loop( - c.br_if(1, c.i32_eqz(c.getLocal("j"))), - c.call(prefix + "_square", B, B), - c.setLocal("j", c.i32_sub(c.getLocal("j"), c.i32_const(1))), - c.br(0) - )), - - c.setLocal("m", c.getLocal("i")), - c.call(prefix + "_square", B, C), - c.call(prefix + "_mul", T, C, T), - c.call(prefix + "_mul", R, B, R), - - c.br(0) - )), - - c.if( - c.call(prefix + "_isNegative", R), - c.call(prefix + "_neg", R, c.getLocal("r")), - c.call(prefix + "_copy", R, c.getLocal("r")), - ) - ); - } - - function buildIsSquare() { - const f = module.addFunction(prefix+"_isSquare"); - f.addParam("n", "i32"); - f.setReturnType("i32"); - - const c = f.getCodeBuilder(); - - const ONE = c.i32_const(pOne); - const AUX = c.i32_const(module.alloc(n8)); - - f.addCode( - c.if( - c.call(prefix + "_isZero", c.getLocal("n")), - c.ret(c.i32_const(1)) - ), - c.call(prefix + "_exp", c.getLocal("n"), c.i32_const(pe), c.i32_const(n8), AUX), - c.call(prefix + "_eq", AUX, ONE) - ); - } - - - function buildLoad() { - const f = module.addFunction(prefix+"_load"); - f.addParam("scalar", "i32"); - f.addParam("scalarLen", "i32"); - f.addParam("r", "i32"); - f.addLocal("p", "i32"); - f.addLocal("l", "i32"); - f.addLocal("i", "i32"); - f.addLocal("j", "i32"); - const c = f.getCodeBuilder(); - - const R = c.i32_const(module.alloc(n8)); - const pAux = module.alloc(n8); - const AUX = c.i32_const(pAux); - - f.addCode( - c.call(intPrefix + "_zero", c.getLocal("r")), - c.setLocal("i", c.i32_const(n8)), - c.setLocal("p", c.getLocal("scalar")), - c.block(c.loop( - c.br_if(1, c.i32_gt_u(c.getLocal("i"), c.getLocal("scalarLen"))), - - c.if( - c.i32_eq(c.getLocal("i"), c.i32_const(n8)), - c.call(prefix + "_one", R), - c.call(prefix + "_mul", R, c.i32_const(pR2), R) - ), - c.call(prefix + "_mul", c.getLocal("p"), R, AUX), - c.call(prefix + "_add", c.getLocal("r"), AUX, c.getLocal("r")), - - c.setLocal("p", c.i32_add(c.getLocal("p"), c.i32_const(n8))), - c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(n8))), - c.br(0) - )), - - c.setLocal("l", c.i32_rem_u( c.getLocal("scalarLen"), c.i32_const(n8))), - c.if(c.i32_eqz(c.getLocal("l")), c.ret([])), - c.call(intPrefix + "_zero", AUX), - c.setLocal("j", c.i32_const(0)), - c.block(c.loop( - c.br_if(1, c.i32_eq(c.getLocal("j"), c.getLocal("l"))), - - c.i32_store8( - c.getLocal("j"), - pAux, - c.i32_load8_u(c.getLocal("p")), - ), - c.setLocal("p", c.i32_add(c.getLocal("p"), c.i32_const(1))), - c.setLocal("j", c.i32_add(c.getLocal("j"), c.i32_const(1))), - c.br(0) - )), - - c.if( - c.i32_eq(c.getLocal("i"), c.i32_const(n8)), - c.call(prefix + "_one", R), - c.call(prefix + "_mul", R, c.i32_const(pR2), R) - ), - c.call(prefix + "_mul", AUX, R, AUX), - c.call(prefix + "_add", c.getLocal("r"), AUX, c.getLocal("r")), - ); - } - - function buildTimesScalar() { - const f = module.addFunction(prefix+"_timesScalar"); - f.addParam("x", "i32"); - f.addParam("scalar", "i32"); - f.addParam("scalarLen", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const AUX = c.i32_const(module.alloc(n8)); - - f.addCode( - c.call(prefix + "_load", c.getLocal("scalar"), c.getLocal("scalarLen"), AUX), - c.call(prefix + "_toMontgomery", AUX, AUX), - c.call(prefix + "_mul", c.getLocal("x"), AUX, c.getLocal("r")), - ); - } - - function buildIsOne() { - const f = module.addFunction(prefix+"_isOne"); - f.addParam("x", "i32"); - f.setReturnType("i32"); - - const c = f.getCodeBuilder(); - f.addCode( - c.ret(c.call(intPrefix + "_eq", c.getLocal("x"), c.i32_const(pOne))) - ); - } - - - module.exportFunction(intPrefix + "_copy", prefix+"_copy"); - module.exportFunction(intPrefix + "_zero", prefix+"_zero"); - module.exportFunction(intPrefix + "_isZero", prefix+"_isZero"); - module.exportFunction(intPrefix + "_eq", prefix+"_eq"); - - buildIsOne(); - buildAdd(); - buildSub(); - buildNeg(); - buildMReduct(); - buildMul(); - buildSquare(); - buildSquareOld(); - buildToMontgomery(); - buildFromMontgomery(); - buildIsNegative(); - buildSign(); - buildInverse(); - buildOne(); - buildLoad(); - buildTimesScalar(); - buildBatchInverse$2(module, prefix); - buildBatchConvertion$1(module, prefix + "_batchToMontgomery", prefix + "_toMontgomery", n8, n8); - buildBatchConvertion$1(module, prefix + "_batchFromMontgomery", prefix + "_fromMontgomery", n8, n8); - buildBatchConvertion$1(module, prefix + "_batchNeg", prefix + "_neg", n8, n8); - buildBatchOp(module, prefix + "_batchAdd", prefix + "_add", n8, n8); - buildBatchOp(module, prefix + "_batchSub", prefix + "_sub", n8, n8); - buildBatchOp(module, prefix + "_batchMul", prefix + "_mul", n8, n8); - - module.exportFunction(prefix + "_add"); - module.exportFunction(prefix + "_sub"); - module.exportFunction(prefix + "_neg"); - module.exportFunction(prefix + "_isNegative"); - module.exportFunction(prefix + "_isOne"); - module.exportFunction(prefix + "_sign"); - module.exportFunction(prefix + "_mReduct"); - module.exportFunction(prefix + "_mul"); - module.exportFunction(prefix + "_square"); - module.exportFunction(prefix + "_squareOld"); - module.exportFunction(prefix + "_fromMontgomery"); - module.exportFunction(prefix + "_toMontgomery"); - module.exportFunction(prefix + "_inverse"); - module.exportFunction(prefix + "_one"); - module.exportFunction(prefix + "_load"); - module.exportFunction(prefix + "_timesScalar"); - buildExp$2( - module, - prefix + "_exp", - n8, - prefix + "_mul", - prefix + "_square", - intPrefix + "_copy", - prefix + "_one", - ); - module.exportFunction(prefix + "_exp"); - module.exportFunction(prefix + "_batchInverse"); - if (isPrime(q)) { - buildSqrt(); - buildIsSquare(); - module.exportFunction(prefix + "_sqrt"); - module.exportFunction(prefix + "_isSquare"); - } - module.exportFunction(prefix + "_batchToMontgomery"); - module.exportFunction(prefix + "_batchFromMontgomery"); - // console.log(module.functionIdxByName); - - return prefix; - }; - - /* - Copyright 2019 0KIMS association. - - This file is part of wasmsnark (Web Assembly zkSnark Prover). - - wasmsnark is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - wasmsnark is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with wasmsnark. If not, see . - */ - - const buildF1m$2 =build_f1m; - const { bitLength: bitLength$3 } = bigint; - - var build_f1 = function buildF1(module, _q, _prefix, _f1mPrefix, _intPrefix) { - - const q = BigInt(_q); - const n64 = Math.floor((bitLength$3(q - 1n) - 1)/64) +1; - const n8 = n64*8; - - const prefix = _prefix || "f1"; - if (module.modules[prefix]) return prefix; // already builded - module.modules[prefix] = { - n64: n64 - }; - - const intPrefix = _intPrefix || "int"; - const f1mPrefix = buildF1m$2(module, q, _f1mPrefix, intPrefix); - - - const pR2 = module.modules[f1mPrefix].pR2; - const pq = module.modules[f1mPrefix].pq; - const pePlusOne = module.modules[f1mPrefix].pePlusOne; - - function buildMul() { - const pAux1 = module.alloc(n8); - - const f = module.addFunction(prefix+ "_mul"); - f.addParam("x", "i32"); - f.addParam("y", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - f.addCode(c.call(f1mPrefix + "_mul", c.getLocal("x"), c.getLocal("y"), c.i32_const(pAux1))); - f.addCode(c.call(f1mPrefix + "_mul", c.i32_const(pAux1), c.i32_const(pR2), c.getLocal("r"))); - } - - function buildSquare() { - const f = module.addFunction(prefix+"_square"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - f.addCode(c.call(prefix + "_mul", c.getLocal("x"), c.getLocal("x"), c.getLocal("r"))); - } - - - function buildInverse() { - - const f = module.addFunction(prefix+ "_inverse"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - f.addCode(c.call(intPrefix + "_inverseMod", c.getLocal("x"), c.i32_const(pq), c.getLocal("r"))); - } - - function buildIsNegative() { - const f = module.addFunction(prefix+"_isNegative"); - f.addParam("x", "i32"); - f.setReturnType("i32"); - - const c = f.getCodeBuilder(); - - f.addCode( - c.call(intPrefix + "_gte", c.getLocal("x"), c.i32_const(pePlusOne) ) - ); - } - - - buildMul(); - buildSquare(); - buildInverse(); - buildIsNegative(); - module.exportFunction(f1mPrefix + "_add", prefix + "_add"); - module.exportFunction(f1mPrefix + "_sub", prefix + "_sub"); - module.exportFunction(f1mPrefix + "_neg", prefix + "_neg"); - module.exportFunction(prefix + "_mul"); - module.exportFunction(prefix + "_square"); - module.exportFunction(prefix + "_inverse"); - module.exportFunction(prefix + "_isNegative"); - module.exportFunction(f1mPrefix + "_copy", prefix+"_copy"); - module.exportFunction(f1mPrefix + "_zero", prefix+"_zero"); - module.exportFunction(f1mPrefix + "_one", prefix+"_one"); - module.exportFunction(f1mPrefix + "_isZero", prefix+"_isZero"); - module.exportFunction(f1mPrefix + "_eq", prefix+"_eq"); - - return prefix; - }; - - /* - Copyright 2019 0KIMS association. - - This file is part of wasmsnark (Web Assembly zkSnark Prover). - - wasmsnark is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - wasmsnark is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with wasmsnark. If not, see . - */ - - const buildExp$1 = build_timesscalar; - const buildBatchInverse$1 = build_batchinverse; - const utils$3 = utils$5; - - var build_f2m = function buildF2m(module, mulNonResidueFn, prefix, f1mPrefix) { - - if (module.modules[prefix]) return prefix; // already builded - - const f1n8 = module.modules[f1mPrefix].n64*8; - const q = module.modules[f1mPrefix].q; - - module.modules[prefix] = { - n64: module.modules[f1mPrefix].n64*2 - }; - - function buildAdd() { - const f = module.addFunction(prefix+"_add"); - f.addParam("x", "i32"); - f.addParam("y", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const y0 = c.getLocal("y"); - const y1 = c.i32_add(c.getLocal("y"), c.i32_const(f1n8)); - const r0 = c.getLocal("r"); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); - - f.addCode( - c.call(f1mPrefix+"_add", x0, y0, r0), - c.call(f1mPrefix+"_add", x1, y1, r1), - ); - } - - function buildTimesScalar() { - const f = module.addFunction(prefix+"_timesScalar"); - f.addParam("x", "i32"); - f.addParam("scalar", "i32"); - f.addParam("scalarLen", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const r0 = c.getLocal("r"); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); - - f.addCode( - c.call(f1mPrefix+"_timesScalar", x0, c.getLocal("scalar"), c.getLocal("scalarLen"), r0), - c.call(f1mPrefix+"_timesScalar", x1, c.getLocal("scalar"), c.getLocal("scalarLen"), r1), - ); - } - - function buildSub() { - const f = module.addFunction(prefix+"_sub"); - f.addParam("x", "i32"); - f.addParam("y", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const y0 = c.getLocal("y"); - const y1 = c.i32_add(c.getLocal("y"), c.i32_const(f1n8)); - const r0 = c.getLocal("r"); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); - - f.addCode( - c.call(f1mPrefix+"_sub", x0, y0, r0), - c.call(f1mPrefix+"_sub", x1, y1, r1), - ); - } - - function buildNeg() { - const f = module.addFunction(prefix+"_neg"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const r0 = c.getLocal("r"); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); - - f.addCode( - c.call(f1mPrefix+"_neg", x0, r0), - c.call(f1mPrefix+"_neg", x1, r1), - ); - } - - function buildConjugate() { - const f = module.addFunction(prefix+"_conjugate"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const r0 = c.getLocal("r"); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); - - f.addCode( - c.call(f1mPrefix+"_copy", x0, r0), - c.call(f1mPrefix+"_neg", x1, r1), - ); - } - - - function buildIsNegative() { - const f = module.addFunction(prefix+"_isNegative"); - f.addParam("x", "i32"); - f.setReturnType("i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - - f.addCode( - c.if( - c.call(f1mPrefix+"_isZero", x1), - c.ret(c.call(f1mPrefix+"_isNegative", x0)) - ), - c.ret(c.call(f1mPrefix+"_isNegative", x1)) - ); - } - - function buildMul() { - const f = module.addFunction(prefix+"_mul"); - f.addParam("x", "i32"); - f.addParam("y", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const y0 = c.getLocal("y"); - const y1 = c.i32_add(c.getLocal("y"), c.i32_const(f1n8)); - const r0 = c.getLocal("r"); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); - - const A = c.i32_const(module.alloc(f1n8)); - const B = c.i32_const(module.alloc(f1n8)); - const C = c.i32_const(module.alloc(f1n8)); - const D = c.i32_const(module.alloc(f1n8)); - - - f.addCode( - c.call(f1mPrefix + "_mul", x0, y0, A), // A = x0*y0 - c.call(f1mPrefix + "_mul", x1, y1, B), // B = x1*y1 - - c.call(f1mPrefix + "_add", x0, x1, C), // C = x0 + x1 - c.call(f1mPrefix + "_add", y0, y1, D), // D = y0 + y1 - c.call(f1mPrefix + "_mul", C, D, C), // C = (x0 + x1)*(y0 + y1) = x0*y0+x0*y1+x1*y0+x1*y1 - - // c.call(f1mPrefix + "_mul", B, c.i32_const(pNonResidue), r0), // r0 = nr*(x1*y1) - c.call(mulNonResidueFn, B, r0), // r0 = nr*(x1*y1) - c.call(f1mPrefix + "_add", A, r0, r0), // r0 = x0*y0 + nr*(x1*y1) - c.call(f1mPrefix + "_add", A, B, r1), // r1 = x0*y0+x1*y1 - c.call(f1mPrefix + "_sub", C, r1, r1) // r1 = x0*y0+x0*y1+x1*y0+x1*y1 - x0*y0+x1*y1 = x0*y1+x1*y0 - ); - - } - - function buildMul1() { - const f = module.addFunction(prefix+"_mul1"); - f.addParam("x", "i32"); - f.addParam("y", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const y = c.getLocal("y"); - const r0 = c.getLocal("r"); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); - - - f.addCode( - c.call(f1mPrefix + "_mul", x0, y, r0), // A = x0*y - c.call(f1mPrefix + "_mul", x1, y, r1), // B = x1*y - ); - } - - function buildSquare() { - const f = module.addFunction(prefix+"_square"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const r0 = c.getLocal("r"); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); - - const AB = c.i32_const(module.alloc(f1n8)); - const APB = c.i32_const(module.alloc(f1n8)); - const APNB = c.i32_const(module.alloc(f1n8)); - const ABPNAB = c.i32_const(module.alloc(f1n8)); - - - f.addCode( - // AB = x0*y1 - c.call(f1mPrefix + "_mul", x0, x1, AB), - - // APB = x0+y1 - c.call(f1mPrefix + "_add", x0, x1, APB), - - // APBN0 = x0 + nr*x1 - c.call(mulNonResidueFn, x1, APNB), - c.call(f1mPrefix + "_add", x0, APNB, APNB), - - // ABPNAB = ab + nr*ab - c.call(mulNonResidueFn, AB, ABPNAB), - c.call(f1mPrefix + "_add", ABPNAB, AB, ABPNAB), - - // r0 = APB * APNB - ABPNAB - c.call(f1mPrefix + "_mul", APB, APNB, r0), - c.call(f1mPrefix + "_sub", r0, ABPNAB, r0), - - // r1 = AB + AB - c.call(f1mPrefix + "_add", AB, AB, r1), - ); - - } - - - function buildToMontgomery() { - const f = module.addFunction(prefix+"_toMontgomery"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const r0 = c.getLocal("r"); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); - - f.addCode( - c.call(f1mPrefix+"_toMontgomery", x0, r0), - c.call(f1mPrefix+"_toMontgomery", x1, r1) - ); - } - - function buildFromMontgomery() { - const f = module.addFunction(prefix+"_fromMontgomery"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const r0 = c.getLocal("r"); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); - - f.addCode( - c.call(f1mPrefix+"_fromMontgomery", x0, r0), - c.call(f1mPrefix+"_fromMontgomery", x1, r1) - ); - } - - function buildCopy() { - const f = module.addFunction(prefix+"_copy"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const r0 = c.getLocal("r"); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); - - f.addCode( - c.call(f1mPrefix+"_copy", x0, r0), - c.call(f1mPrefix+"_copy", x1, r1) - ); - } - - function buildZero() { - const f = module.addFunction(prefix+"_zero"); - f.addParam("x", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - - f.addCode( - c.call(f1mPrefix+"_zero", x0), - c.call(f1mPrefix+"_zero", x1) - ); - } - - function buildOne() { - const f = module.addFunction(prefix+"_one"); - f.addParam("x", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - - f.addCode( - c.call(f1mPrefix+"_one", x0), - c.call(f1mPrefix+"_zero", x1) - ); - } - - function buildEq() { - const f = module.addFunction(prefix+"_eq"); - f.addParam("x", "i32"); - f.addParam("y", "i32"); - f.setReturnType("i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const y0 = c.getLocal("y"); - const y1 = c.i32_add(c.getLocal("y"), c.i32_const(f1n8)); - - f.addCode( - c.i32_and( - c.call(f1mPrefix+"_eq", x0, y0), - c.call(f1mPrefix+"_eq", x1, y1) - ) - ); - } - - function buildIsZero() { - const f = module.addFunction(prefix+"_isZero"); - f.addParam("x", "i32"); - f.setReturnType("i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - - f.addCode( - c.i32_and( - c.call(f1mPrefix+"_isZero", x0), - c.call(f1mPrefix+"_isZero", x1) - ) - ); - } - - function buildInverse() { - const f = module.addFunction(prefix+"_inverse"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const r0 = c.getLocal("r"); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); - - const t0 = c.i32_const(module.alloc(f1n8)); - const t1 = c.i32_const(module.alloc(f1n8)); - const t2 = c.i32_const(module.alloc(f1n8)); - const t3 = c.i32_const(module.alloc(f1n8)); - - f.addCode( - c.call(f1mPrefix+"_square", x0, t0), - c.call(f1mPrefix+"_square", x1, t1), - // c.call(f1mPrefix+"_mul", t1, c.i32_const(pNonResidue), t2), - c.call(mulNonResidueFn, t1, t2), - - c.call(f1mPrefix+"_sub", t0, t2, t2), - c.call(f1mPrefix+"_inverse", t2, t3), - - c.call(f1mPrefix+"_mul", x0, t3, r0), - c.call(f1mPrefix+"_mul", x1, t3, r1), - c.call(f1mPrefix+"_neg", r1, r1), - ); - } - - - function buildSign() { - const f = module.addFunction(prefix+"_sign"); - f.addParam("x", "i32"); - f.addLocal("s", "i32"); - f.setReturnType("i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - - f.addCode( - c.setLocal("s" , c.call( f1mPrefix + "_sign", x1)), - c.if( - c.getLocal("s"), - c.ret(c.getLocal("s")) - ), - c.ret(c.call( f1mPrefix + "_sign", x0)) - ); - } - - function buildIsOne() { - const f = module.addFunction(prefix+"_isOne"); - f.addParam("x", "i32"); - f.setReturnType("i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - - f.addCode( - c.ret(c.i32_and( - c.call(f1mPrefix + "_isOne", x0), - c.call(f1mPrefix + "_isZero", x1), - )) - ); - } - - - // Check here: https://eprint.iacr.org/2012/685.pdf - // Alg 9adj - function buildSqrt() { - - const f = module.addFunction(prefix+"_sqrt"); - f.addParam("a", "i32"); - f.addParam("pr", "i32"); - - const c = f.getCodeBuilder(); - - // BigInt can't take `undefined` so we use `|| 0` - const e34 = c.i32_const(module.alloc(utils$3.bigInt2BytesLE((BigInt(q || 0) - 3n) / 4n, f1n8 ))); - // BigInt can't take `undefined` so we use `|| 0` - const e12 = c.i32_const(module.alloc(utils$3.bigInt2BytesLE((BigInt(q || 0) - 1n) / 2n, f1n8 ))); - - const a = c.getLocal("a"); - const a1 = c.i32_const(module.alloc(f1n8*2)); - const alpha = c.i32_const(module.alloc(f1n8*2)); - const a0 = c.i32_const(module.alloc(f1n8*2)); - const pn1 = module.alloc(f1n8*2); - const n1 = c.i32_const(pn1); - const n1a = c.i32_const(pn1); - const n1b = c.i32_const(pn1+f1n8); - const x0 = c.i32_const(module.alloc(f1n8*2)); - const b = c.i32_const(module.alloc(f1n8*2)); - - f.addCode( - - c.call(prefix + "_one", n1), - c.call(prefix + "_neg", n1, n1), - - // const a1 = F.pow(a, F.sqrt_e34); - c.call(prefix + "_exp", a, e34, c.i32_const(f1n8), a1), - - // const a1 = F.pow(a, F.sqrt_e34); - c.call(prefix + "_square", a1, alpha), - c.call(prefix + "_mul", a, alpha, alpha), - - // const a0 = F.mul(F.frobenius(1, alfa), alfa); - c.call(prefix + "_conjugate", alpha, a0), - c.call(prefix + "_mul", a0, alpha, a0), - - // if (F.eq(a0, F.negone)) return null; - c.if(c.call(prefix + "_eq",a0,n1), c.unreachable() ), - - // const x0 = F.mul(a1, a); - c.call(prefix + "_mul", a1, a, x0), - - // if (F.eq(alfa, F.negone)) { - c.if( - c.call(prefix + "_eq", alpha, n1), - [ - // x = F.mul(x0, [F.F.zero, F.F.one]); - ...c.call(f1mPrefix + "_zero", n1a), - ...c.call(f1mPrefix + "_one", n1b), - ...c.call(prefix + "_mul", n1, x0, c.getLocal("pr")), - ], - [ - // const b = F.pow(F.add(F.one, alfa), F.sqrt_e12); - ...c.call(prefix + "_one", b), - ...c.call(prefix + "_add", b, alpha, b), - ...c.call(prefix + "_exp", b, e12, c.i32_const(f1n8), b), - - // x = F.mul(b, x0); - ...c.call(prefix + "_mul", b, x0, c.getLocal("pr")), - ] - ) - ); - - } - - - function buildIsSquare() { - - const f = module.addFunction(prefix+"_isSquare"); - f.addParam("a", "i32"); - f.setReturnType("i32"); - - const c = f.getCodeBuilder(); - - // BigInt can't take `undefined` so we use `|| 0` - const e34 = c.i32_const(module.alloc(utils$3.bigInt2BytesLE((BigInt(q || 0) - 3n) / 4n, f1n8 ))); - - const a = c.getLocal("a"); - const a1 = c.i32_const(module.alloc(f1n8*2)); - const alpha = c.i32_const(module.alloc(f1n8*2)); - const a0 = c.i32_const(module.alloc(f1n8*2)); - const pn1 = module.alloc(f1n8*2); - const n1 = c.i32_const(pn1); - - f.addCode( - - c.call(prefix + "_one", n1), - c.call(prefix + "_neg", n1, n1), - - // const a1 = F.pow(a, F.sqrt_e34); - c.call(prefix + "_exp", a, e34, c.i32_const(f1n8), a1), - - // const a1 = F.pow(a, F.sqrt_e34); - c.call(prefix + "_square", a1, alpha), - c.call(prefix + "_mul", a, alpha, alpha), - - // const a0 = F.mul(F.frobenius(1, alfa), alfa); - c.call(prefix + "_conjugate", alpha, a0), - c.call(prefix + "_mul", a0, alpha, a0), - - // if (F.eq(a0, F.negone)) return null; - c.if( - c.call( - prefix + "_eq", - a0, - n1 - ), - c.ret(c.i32_const(0)) - ), - c.ret(c.i32_const(1)) - ); - - } - - - buildIsZero(); - buildIsOne(); - buildZero(); - buildOne(); - buildCopy(); - buildMul(); - buildMul1(); - buildSquare(); - buildAdd(); - buildSub(); - buildNeg(); - buildConjugate(); - buildToMontgomery(); - buildFromMontgomery(); - buildEq(); - buildInverse(); - buildTimesScalar(); - buildSign(); - buildIsNegative(); - - module.exportFunction(prefix + "_isZero"); - module.exportFunction(prefix + "_isOne"); - module.exportFunction(prefix + "_zero"); - module.exportFunction(prefix + "_one"); - module.exportFunction(prefix + "_copy"); - module.exportFunction(prefix + "_mul"); - module.exportFunction(prefix + "_mul1"); - module.exportFunction(prefix + "_square"); - module.exportFunction(prefix + "_add"); - module.exportFunction(prefix + "_sub"); - module.exportFunction(prefix + "_neg"); - module.exportFunction(prefix + "_sign"); - module.exportFunction(prefix + "_conjugate"); - module.exportFunction(prefix + "_fromMontgomery"); - module.exportFunction(prefix + "_toMontgomery"); - module.exportFunction(prefix + "_eq"); - module.exportFunction(prefix + "_inverse"); - buildBatchInverse$1(module, prefix); - buildExp$1( - module, - prefix + "_exp", - f1n8*2, - prefix + "_mul", - prefix + "_square", - prefix + "_copy", - prefix + "_one", - ); - buildSqrt(); - buildIsSquare(); - - module.exportFunction(prefix + "_exp"); - module.exportFunction(prefix + "_timesScalar"); - module.exportFunction(prefix + "_batchInverse"); - module.exportFunction(prefix + "_sqrt"); - module.exportFunction(prefix + "_isSquare"); - module.exportFunction(prefix + "_isNegative"); - - - return prefix; - }; - - /* - Copyright 2019 0KIMS association. - - This file is part of wasmsnark (Web Assembly zkSnark Prover). - - wasmsnark is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - wasmsnark is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with wasmsnark. If not, see . - */ - - const buildExp = build_timesscalar; - const buildBatchInverse = build_batchinverse; - - var build_f3m = function buildF3m(module, mulNonResidueFn, prefix, f1mPrefix) { - - if (module.modules[prefix]) return prefix; // already builded - - const f1n8 = module.modules[f1mPrefix].n64*8; - module.modules[prefix] = { - n64: module.modules[f1mPrefix].n64*3 - }; - - function buildAdd() { - const f = module.addFunction(prefix+"_add"); - f.addParam("x", "i32"); - f.addParam("y", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); - const y0 = c.getLocal("y"); - const y1 = c.i32_add(c.getLocal("y"), c.i32_const(f1n8)); - const y2 = c.i32_add(c.getLocal("y"), c.i32_const(2*f1n8)); - const r0 = c.getLocal("r"); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); - const r2 = c.i32_add(c.getLocal("r"), c.i32_const(2*f1n8)); - - f.addCode( - c.call(f1mPrefix+"_add", x0, y0, r0), - c.call(f1mPrefix+"_add", x1, y1, r1), - c.call(f1mPrefix+"_add", x2, y2, r2), - ); - } - - function buildTimesScalar() { - const f = module.addFunction(prefix+"_timesScalar"); - f.addParam("x", "i32"); - f.addParam("scalar", "i32"); - f.addParam("scalarLen", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); - const r0 = c.getLocal("r"); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); - const r2 = c.i32_add(c.getLocal("r"), c.i32_const(2*f1n8)); - - f.addCode( - c.call(f1mPrefix+"_timesScalar", x0, c.getLocal("scalar"), c.getLocal("scalarLen"), r0), - c.call(f1mPrefix+"_timesScalar", x1, c.getLocal("scalar"), c.getLocal("scalarLen"), r1), - c.call(f1mPrefix+"_timesScalar", x2, c.getLocal("scalar"), c.getLocal("scalarLen"), r2), - ); - } - - - function buildSub() { - const f = module.addFunction(prefix+"_sub"); - f.addParam("x", "i32"); - f.addParam("y", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); - const y0 = c.getLocal("y"); - const y1 = c.i32_add(c.getLocal("y"), c.i32_const(f1n8)); - const y2 = c.i32_add(c.getLocal("y"), c.i32_const(2*f1n8)); - const r0 = c.getLocal("r"); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); - const r2 = c.i32_add(c.getLocal("r"), c.i32_const(2*f1n8)); - - f.addCode( - c.call(f1mPrefix+"_sub", x0, y0, r0), - c.call(f1mPrefix+"_sub", x1, y1, r1), - c.call(f1mPrefix+"_sub", x2, y2, r2), - ); - } - - function buildNeg() { - const f = module.addFunction(prefix+"_neg"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); - const r0 = c.getLocal("r"); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); - const r2 = c.i32_add(c.getLocal("r"), c.i32_const(2*f1n8)); - - f.addCode( - c.call(f1mPrefix+"_neg", x0, r0), - c.call(f1mPrefix+"_neg", x1, r1), - c.call(f1mPrefix+"_neg", x2, r2), - ); - } - - function buildIsNegative() { - const f = module.addFunction(prefix+"_isNegative"); - f.addParam("x", "i32"); - f.setReturnType("i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); - - f.addCode( - c.if( - c.call(f1mPrefix+"_isZero", x2), - c.if( - c.call(f1mPrefix+"_isZero", x1), - c.ret(c.call(f1mPrefix+"_isNegative", x0)), - c.ret(c.call(f1mPrefix+"_isNegative", x1)) - ) - ), - c.ret(c.call(f1mPrefix+"_isNegative", x2)) - ); - } - - - function buildMul() { - const f = module.addFunction(prefix+"_mul"); - f.addParam("x", "i32"); - f.addParam("y", "i32"); - f.addParam("r", "i32"); - - const cd = f.getCodeBuilder(); - - const a = cd.getLocal("x"); - const b = cd.i32_add(cd.getLocal("x"), cd.i32_const(f1n8)); - const c = cd.i32_add(cd.getLocal("x"), cd.i32_const(2*f1n8)); - const A = cd.getLocal("y"); - const B = cd.i32_add(cd.getLocal("y"), cd.i32_const(f1n8)); - const C = cd.i32_add(cd.getLocal("y"), cd.i32_const(2*f1n8)); - const r0 = cd.getLocal("r"); - const r1 = cd.i32_add(cd.getLocal("r"), cd.i32_const(f1n8)); - const r2 = cd.i32_add(cd.getLocal("r"), cd.i32_const(2*f1n8)); - - const aA = cd.i32_const(module.alloc(f1n8)); - const bB = cd.i32_const(module.alloc(f1n8)); - const cC = cd.i32_const(module.alloc(f1n8)); - const a_b = cd.i32_const(module.alloc(f1n8)); - const A_B = cd.i32_const(module.alloc(f1n8)); - const a_c = cd.i32_const(module.alloc(f1n8)); - const A_C = cd.i32_const(module.alloc(f1n8)); - const b_c = cd.i32_const(module.alloc(f1n8)); - const B_C = cd.i32_const(module.alloc(f1n8)); - const aA_bB = cd.i32_const(module.alloc(f1n8)); - const aA_cC = cd.i32_const(module.alloc(f1n8)); - const bB_cC = cd.i32_const(module.alloc(f1n8)); - const AUX = cd.i32_const(module.alloc(f1n8)); - - - f.addCode( - cd.call(f1mPrefix + "_mul", a, A, aA), - cd.call(f1mPrefix + "_mul", b, B, bB), - cd.call(f1mPrefix + "_mul", c, C, cC), - - cd.call(f1mPrefix + "_add", a, b, a_b), - cd.call(f1mPrefix + "_add", A, B, A_B), - cd.call(f1mPrefix + "_add", a, c, a_c), - cd.call(f1mPrefix + "_add", A, C, A_C), - cd.call(f1mPrefix + "_add", b, c, b_c), - cd.call(f1mPrefix + "_add", B, C, B_C), - - cd.call(f1mPrefix + "_add", aA, bB, aA_bB), - cd.call(f1mPrefix + "_add", aA, cC, aA_cC), - cd.call(f1mPrefix + "_add", bB, cC, bB_cC), - - cd.call(f1mPrefix + "_mul", b_c, B_C, r0), - cd.call(f1mPrefix + "_sub", r0, bB_cC, r0), - cd.call(mulNonResidueFn, r0, r0), - cd.call(f1mPrefix + "_add", aA, r0, r0), - - cd.call(f1mPrefix + "_mul", a_b, A_B, r1), - cd.call(f1mPrefix + "_sub", r1, aA_bB, r1), - cd.call(mulNonResidueFn, cC, AUX), - cd.call(f1mPrefix + "_add", r1, AUX, r1), - - cd.call(f1mPrefix + "_mul", a_c, A_C, r2), - cd.call(f1mPrefix + "_sub", r2, aA_cC, r2), - cd.call(f1mPrefix + "_add", r2, bB, r2), - ); - - } - - function buildSquare() { - const f = module.addFunction(prefix+"_square"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const A = c.getLocal("x"); - const B = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const C = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); - const r0 = c.getLocal("r"); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); - const r2 = c.i32_add(c.getLocal("r"), c.i32_const(2*f1n8)); - - const s0 = c.i32_const(module.alloc(f1n8)); - const ab = c.i32_const(module.alloc(f1n8)); - const s1 = c.i32_const(module.alloc(f1n8)); - const s2 = c.i32_const(module.alloc(f1n8)); - const bc = c.i32_const(module.alloc(f1n8)); - const s3 = c.i32_const(module.alloc(f1n8)); - const s4 = c.i32_const(module.alloc(f1n8)); - - - f.addCode( - - c.call(f1mPrefix + "_square", A, s0), - c.call(f1mPrefix + "_mul", A, B, ab), - c.call(f1mPrefix + "_add", ab, ab, s1), - - c.call(f1mPrefix + "_sub", A, B, s2), - c.call(f1mPrefix + "_add", s2, C, s2), - c.call(f1mPrefix + "_square", s2, s2), - - c.call(f1mPrefix + "_mul", B, C, bc), - c.call(f1mPrefix + "_add", bc, bc, s3), - - c.call(f1mPrefix + "_square", C, s4), - - c.call(mulNonResidueFn, s3, r0), - c.call(f1mPrefix + "_add", s0, r0, r0), - - c.call(mulNonResidueFn, s4, r1), - c.call(f1mPrefix + "_add", s1, r1, r1), - - c.call(f1mPrefix + "_add", s0, s4, r2), - c.call(f1mPrefix + "_sub", s3, r2, r2), - c.call(f1mPrefix + "_add", s2, r2, r2), - c.call(f1mPrefix + "_add", s1, r2, r2), - ); - - } - - - function buildToMontgomery() { - const f = module.addFunction(prefix+"_toMontgomery"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); - const r0 = c.getLocal("r"); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); - const r2 = c.i32_add(c.getLocal("r"), c.i32_const(2*f1n8)); - - f.addCode( - c.call(f1mPrefix+"_toMontgomery", x0, r0), - c.call(f1mPrefix+"_toMontgomery", x1, r1), - c.call(f1mPrefix+"_toMontgomery", x2, r2) - ); - } - - function buildFromMontgomery() { - const f = module.addFunction(prefix+"_fromMontgomery"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); - const r0 = c.getLocal("r"); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); - const r2 = c.i32_add(c.getLocal("r"), c.i32_const(2*f1n8)); - - f.addCode( - c.call(f1mPrefix+"_fromMontgomery", x0, r0), - c.call(f1mPrefix+"_fromMontgomery", x1, r1), - c.call(f1mPrefix+"_fromMontgomery", x2, r2) - ); - } - - function buildCopy() { - const f = module.addFunction(prefix+"_copy"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); - const r0 = c.getLocal("r"); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); - const r2 = c.i32_add(c.getLocal("r"), c.i32_const(2*f1n8)); - - f.addCode( - c.call(f1mPrefix+"_copy", x0, r0), - c.call(f1mPrefix+"_copy", x1, r1), - c.call(f1mPrefix+"_copy", x2, r2), - ); - } - - function buildZero() { - const f = module.addFunction(prefix+"_zero"); - f.addParam("x", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); - - f.addCode( - c.call(f1mPrefix+"_zero", x0), - c.call(f1mPrefix+"_zero", x1), - c.call(f1mPrefix+"_zero", x2), - ); - } - - function buildOne() { - const f = module.addFunction(prefix+"_one"); - f.addParam("x", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); - - f.addCode( - c.call(f1mPrefix+"_one", x0), - c.call(f1mPrefix+"_zero", x1), - c.call(f1mPrefix+"_zero", x2), - ); - } - - function buildEq() { - const f = module.addFunction(prefix+"_eq"); - f.addParam("x", "i32"); - f.addParam("y", "i32"); - f.setReturnType("i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); - const y0 = c.getLocal("y"); - const y1 = c.i32_add(c.getLocal("y"), c.i32_const(f1n8)); - const y2 = c.i32_add(c.getLocal("y"), c.i32_const(2*f1n8)); - - f.addCode( - c.i32_and( - c.i32_and( - c.call(f1mPrefix+"_eq", x0, y0), - c.call(f1mPrefix+"_eq", x1, y1), - ), - c.call(f1mPrefix+"_eq", x2, y2) - ) - ); - } - - function buildIsZero() { - const f = module.addFunction(prefix+"_isZero"); - f.addParam("x", "i32"); - f.setReturnType("i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); - - f.addCode( - c.i32_and( - c.i32_and( - c.call(f1mPrefix+"_isZero", x0), - c.call(f1mPrefix+"_isZero", x1) - ), - c.call(f1mPrefix+"_isZero", x2) - ) - ); - } - - function buildInverse() { - const f = module.addFunction(prefix+"_inverse"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); - const r0 = c.getLocal("r"); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); - const r2 = c.i32_add(c.getLocal("r"), c.i32_const(2*f1n8)); - - const t0 = c.i32_const(module.alloc(f1n8)); - const t1 = c.i32_const(module.alloc(f1n8)); - const t2 = c.i32_const(module.alloc(f1n8)); - const t3 = c.i32_const(module.alloc(f1n8)); - const t4 = c.i32_const(module.alloc(f1n8)); - const t5 = c.i32_const(module.alloc(f1n8)); - const c0 = c.i32_const(module.alloc(f1n8)); - const c1 = c.i32_const(module.alloc(f1n8)); - const c2 = c.i32_const(module.alloc(f1n8)); - const t6 = c.i32_const(module.alloc(f1n8)); - const AUX = c.i32_const(module.alloc(f1n8)); - - f.addCode( - c.call(f1mPrefix+"_square", x0, t0), - c.call(f1mPrefix+"_square", x1, t1), - c.call(f1mPrefix+"_square", x2, t2), - c.call(f1mPrefix+"_mul", x0, x1, t3), - c.call(f1mPrefix+"_mul", x0, x2, t4), - c.call(f1mPrefix+"_mul", x1, x2, t5), - - c.call(mulNonResidueFn, t5, c0), - c.call(f1mPrefix+"_sub", t0, c0, c0), - - c.call(mulNonResidueFn, t2, c1), - c.call(f1mPrefix+"_sub", c1, t3, c1), - - c.call(f1mPrefix+"_sub", t1, t4, c2), - - c.call(f1mPrefix+"_mul", x2, c1, t6), - c.call(f1mPrefix+"_mul", x1, c2, AUX), - c.call(f1mPrefix+"_add", t6, AUX, t6), - c.call(mulNonResidueFn, t6, t6), - c.call(f1mPrefix+"_mul", x0, c0, AUX), - c.call(f1mPrefix+"_add", AUX, t6, t6), - - c.call(f1mPrefix+"_inverse", t6, t6), - - c.call(f1mPrefix+"_mul", t6, c0, r0), - c.call(f1mPrefix+"_mul", t6, c1, r1), - c.call(f1mPrefix+"_mul", t6, c2, r2) - ); - } - - - function buildSign() { - const f = module.addFunction(prefix+"_sign"); - f.addParam("x", "i32"); - f.addLocal("s", "i32"); - f.setReturnType("i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); - - f.addCode( - c.setLocal("s" , c.call( f1mPrefix + "_sign", x2)), - c.if( - c.getLocal("s"), - c.ret(c.getLocal("s")) - ), - c.setLocal("s" , c.call( f1mPrefix + "_sign", x1)), - c.if( - c.getLocal("s"), - c.ret(c.getLocal("s")) - ), - c.ret(c.call( f1mPrefix + "_sign", x0)) - ); - } - - function buildIsOne() { - const f = module.addFunction(prefix+"_isOne"); - f.addParam("x", "i32"); - f.setReturnType("i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); - const x2 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8*2)); - - f.addCode( - c.ret( - c.i32_and( - c.i32_and( - c.call(f1mPrefix + "_isOne", x0), - c.call(f1mPrefix + "_isZero", x1) - ), - c.call(f1mPrefix + "_isZero", x2) - ) - ) - ); - } - - buildIsZero(); - buildIsOne(); - buildZero(); - buildOne(); - buildCopy(); - buildMul(); - buildSquare(); - buildAdd(); - buildSub(); - buildNeg(); - buildSign(); - buildToMontgomery(); - buildFromMontgomery(); - buildEq(); - buildInverse(); - buildTimesScalar(); - buildIsNegative(); - - module.exportFunction(prefix + "_isZero"); - module.exportFunction(prefix + "_isOne"); - module.exportFunction(prefix + "_zero"); - module.exportFunction(prefix + "_one"); - module.exportFunction(prefix + "_copy"); - module.exportFunction(prefix + "_mul"); - module.exportFunction(prefix + "_square"); - module.exportFunction(prefix + "_add"); - module.exportFunction(prefix + "_sub"); - module.exportFunction(prefix + "_neg"); - module.exportFunction(prefix + "_sign"); - module.exportFunction(prefix + "_fromMontgomery"); - module.exportFunction(prefix + "_toMontgomery"); - module.exportFunction(prefix + "_eq"); - module.exportFunction(prefix + "_inverse"); - buildBatchInverse(module, prefix); - buildExp( - module, - prefix + "_exp", - f1n8*3, - prefix + "_mul", - prefix + "_square", - prefix + "_copy", - prefix + "_one" - ); - module.exportFunction(prefix + "_exp"); - module.exportFunction(prefix + "_timesScalar"); - module.exportFunction(prefix + "_batchInverse"); - module.exportFunction(prefix + "_isNegative"); - - return prefix; - }; - - /* - Copyright 2019 0KIMS association. - - This file is part of wasmsnark (Web Assembly zkSnark Prover). - - wasmsnark is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - wasmsnark is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with wasmsnark. If not, see . - */ - - var build_timesscalarnaf = function buildTimesScalarNAF(module, fnName, elementLen, opAB, opAA, opAmB, opCopy, opInit) { - - const f = module.addFunction(fnName); - f.addParam("base", "i32"); - f.addParam("scalar", "i32"); - f.addParam("scalarLength", "i32"); - f.addParam("r", "i32"); - f.addLocal("old0", "i32"); - f.addLocal("nbits", "i32"); - f.addLocal("i", "i32"); - f.addLocal("last", "i32"); - f.addLocal("cur", "i32"); - f.addLocal("carry", "i32"); - f.addLocal("p", "i32"); - - const c = f.getCodeBuilder(); - - const aux = c.i32_const(module.alloc(elementLen)); - - function getBit(IDX) { - return c.i32_and( - c.i32_shr_u( - c.i32_load( - c.i32_add( - c.getLocal("scalar"), - c.i32_and( - c.i32_shr_u( - IDX, - c.i32_const(3) - ), - c.i32_const(0xFFFFFFFC) - ) - ) - ), - c.i32_and( - IDX, - c.i32_const(0x1F) - ) - ), - c.i32_const(1) - ); - } - - function pushBit(b) { - return [ - ...c.i32_store8( - c.getLocal("p"), - c.i32_const(b) - ), - ...c.setLocal( - "p", - c.i32_add( - c.getLocal("p"), - c.i32_const(1) - ) - ) - ]; - } - - f.addCode( - c.if( - c.i32_eqz(c.getLocal("scalarLength")), - [ - ...c.call(opInit, c.getLocal("r")), - ...c.ret([]) - ] - ), - c.setLocal("nbits", c.i32_shl(c.getLocal("scalarLength"), c.i32_const(3))), - c.setLocal("old0", c.i32_load(c.i32_const(0))), - c.setLocal("p", c.getLocal("old0")), - c.i32_store( - c.i32_const(0), - c.i32_and( - c.i32_add( - c.i32_add( - c.getLocal("old0"), - c.i32_const(32) - ), - c.getLocal("nbits") - ), - c.i32_const(0xFFFFFFF8) - ) - ), - c.setLocal("i", c.i32_const(1)), - - c.setLocal("last",getBit(c.i32_const(0))), - c.setLocal("carry",c.i32_const(0)), - - c.block(c.loop( - c.br_if(1, c.i32_eq( c.getLocal("i"), c.getLocal("nbits"))), - - c.setLocal("cur", getBit(c.getLocal("i"))), - c.if( c.getLocal("last"), - c.if( c.getLocal("cur"), - c.if(c.getLocal("carry"), - [ - ...c.setLocal("last", c.i32_const(0)), - ...c.setLocal("carry", c.i32_const(1)), - ...pushBit(1) - ] - , - [ - ...c.setLocal("last", c.i32_const(0)), - ...c.setLocal("carry", c.i32_const(1)), - ...pushBit(255) - ], - ), - c.if(c.getLocal("carry"), - [ - ...c.setLocal("last", c.i32_const(0)), - ...c.setLocal("carry", c.i32_const(1)), - ...pushBit(255) - ] - , - [ - ...c.setLocal("last", c.i32_const(0)), - ...c.setLocal("carry", c.i32_const(0)), - ...pushBit(1) - ], - ), - ), - c.if( c.getLocal("cur"), - c.if(c.getLocal("carry"), - [ - ...c.setLocal("last", c.i32_const(0)), - ...c.setLocal("carry", c.i32_const(1)), - ...pushBit(0) - ] - , - [ - ...c.setLocal("last", c.i32_const(1)), - ...c.setLocal("carry", c.i32_const(0)), - ...pushBit(0) - ], - ), - c.if(c.getLocal("carry"), - [ - ...c.setLocal("last", c.i32_const(1)), - ...c.setLocal("carry", c.i32_const(0)), - ...pushBit(0) - ] - , - [ - ...c.setLocal("last", c.i32_const(0)), - ...c.setLocal("carry", c.i32_const(0)), - ...pushBit(0) - ], - ), - ) - ), - c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), - c.br(0) - )), - - c.if( c.getLocal("last"), - c.if(c.getLocal("carry"), - [ - ...pushBit(255), - ...pushBit(0), - ...pushBit(1) - ] - , - [ - ...pushBit(1) - ], - ), - c.if(c.getLocal("carry"), - [ - ...pushBit(0), - ...pushBit(1) - ] - ), - ), - - c.setLocal("p", c.i32_sub(c.getLocal("p"), c.i32_const(1))), - - // p already points to the last bit - - c.call(opCopy, c.getLocal("base"), aux), - - c.call(opInit, c.getLocal("r")), - - c.block(c.loop( - - - c.call(opAA, c.getLocal("r"), c.getLocal("r")), - - - c.setLocal("cur", - c.i32_load8_u( - c.getLocal("p") - ) - ), - - c.if( - c.getLocal("cur"), - c.if( - c.i32_eq(c.getLocal("cur"), c.i32_const(1)), - c.call(opAB, c.getLocal("r"), aux, c.getLocal("r")), - c.call(opAmB, c.getLocal("r"), aux, c.getLocal("r")), - ) - ), - - c.br_if(1, c.i32_eq( c.getLocal("old0"), c.getLocal("p"))), - c.setLocal("p", c.i32_sub(c.getLocal("p"), c.i32_const(1))), - c.br(0) - - )), - - c.i32_store( c.i32_const(0), c.getLocal("old0")) - - ); - - }; - - /* - Copyright 2019 0KIMS association. - - This file is part of wasmsnark (Web Assembly zkSnark Prover). - - wasmsnark is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - wasmsnark is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with wasmsnark. If not, see . - */ - - var build_multiexp = function buildMultiexp(module, prefix, fnName, opAdd, n8b) { - - const n64g = module.modules[prefix].n64; - const n8g = n64g*8; - - function buildGetChunk() { - const f = module.addFunction(fnName + "_getChunk"); - f.addParam("pScalar", "i32"); - f.addParam("scalarSize", "i32"); // Number of bytes of the scalar - f.addParam("startBit", "i32"); // Bit to start extract - f.addParam("chunkSize", "i32"); // Chunk size in bits - f.addLocal("bitsToEnd", "i32"); - f.addLocal("mask", "i32"); - f.setReturnType("i32"); - - const c = f.getCodeBuilder(); - - f.addCode( - c.setLocal("bitsToEnd", - c.i32_sub( - c.i32_mul( - c.getLocal("scalarSize"), - c.i32_const(8) - ), - c.getLocal("startBit") - ) - ), - c.if( - c.i32_gt_s( - c.getLocal("chunkSize"), - c.getLocal("bitsToEnd") - ), - c.setLocal( - "mask", - c.i32_sub( - c.i32_shl( - c.i32_const(1), - c.getLocal("bitsToEnd") - ), - c.i32_const(1) - ) - ), - c.setLocal( - "mask", - c.i32_sub( - c.i32_shl( - c.i32_const(1), - c.getLocal("chunkSize") - ), - c.i32_const(1) - ) - ) - ), - c.i32_and( - c.i32_shr_u( - c.i32_load( - c.i32_add( - c.getLocal("pScalar"), - c.i32_shr_u( - c.getLocal("startBit"), - c.i32_const(3) - ) - ), - 0, // offset - 0 // align to byte. - ), - c.i32_and( - c.getLocal("startBit"), - c.i32_const(0x7) - ) - ), - c.getLocal("mask") - ) - ); - } - - function buildMutiexpChunk() { - const f = module.addFunction(fnName + "_chunk"); - f.addParam("pBases", "i32"); - f.addParam("pScalars", "i32"); - f.addParam("scalarSize", "i32"); // Number of points - f.addParam("n", "i32"); // Number of points - f.addParam("startBit", "i32"); // bit where it starts the chunk - f.addParam("chunkSize", "i32"); // bit where it starts the chunk - f.addParam("pr", "i32"); - f.addLocal("nChunks", "i32"); - f.addLocal("itScalar", "i32"); - f.addLocal("endScalar", "i32"); - f.addLocal("itBase", "i32"); - f.addLocal("i", "i32"); - f.addLocal("j", "i32"); - f.addLocal("nTable", "i32"); - f.addLocal("pTable", "i32"); - f.addLocal("idx", "i32"); - f.addLocal("pIdxTable", "i32"); - - const c = f.getCodeBuilder(); - - f.addCode( - c.if( - c.i32_eqz(c.getLocal("n")), - [ - ...c.call(prefix + "_zero", c.getLocal("pr")), - ...c.ret([]) - ] - ), - - // Allocate memory - - c.setLocal( - "nTable", - c.i32_shl( - c.i32_const(1), - c.getLocal("chunkSize") - ) - ), - c.setLocal("pTable", c.i32_load( c.i32_const(0) )), - c.i32_store( - c.i32_const(0), - c.i32_add( - c.getLocal("pTable"), - c.i32_mul( - c.getLocal("nTable"), - c.i32_const(n8g) - ) - ) - ), - - // Reset Table - c.setLocal("j", c.i32_const(0)), - c.block(c.loop( - c.br_if( - 1, - c.i32_eq( - c.getLocal("j"), - c.getLocal("nTable") - ) - ), - - c.call( - prefix + "_zero", - c.i32_add( - c.getLocal("pTable"), - c.i32_mul( - c.getLocal("j"), - c.i32_const(n8g) - ) - ) - ), - - c.setLocal("j", c.i32_add(c.getLocal("j"), c.i32_const(1))), - c.br(0) - )), - - // Distribute elements - c.setLocal("itBase", c.getLocal("pBases")), - c.setLocal("itScalar", c.getLocal("pScalars")), - c.setLocal("endScalar", - c.i32_add( - c.getLocal("pScalars"), - c.i32_mul( - c.getLocal("n"), - c.getLocal("scalarSize") - ) - ) - ), - c.block(c.loop( - c.br_if( - 1, - c.i32_eq( - c.getLocal("itScalar"), - c.getLocal("endScalar") - ) - ), - - c.setLocal( - "idx", - c.call(fnName + "_getChunk", - c.getLocal("itScalar"), - c.getLocal("scalarSize"), - c.getLocal("startBit"), - c.getLocal("chunkSize") - ) - ), - - c.if( - c.getLocal("idx"), - [ - ...c.setLocal( - "pIdxTable", - c.i32_add( - c.getLocal("pTable"), - c.i32_mul( - c.i32_sub( - c.getLocal("idx"), - c.i32_const(1) - ), - c.i32_const(n8g) - ) - ) - ), - ...c.call( - opAdd, - c.getLocal("pIdxTable"), - c.getLocal("itBase"), - c.getLocal("pIdxTable"), - ) - ] - ), - - c.setLocal("itScalar", c.i32_add(c.getLocal("itScalar"), c.getLocal("scalarSize"))), - c.setLocal("itBase", c.i32_add(c.getLocal("itBase"), c.i32_const(n8b))), - c.br(0) - )), - - c.call(fnName + "_reduceTable", c.getLocal("pTable"), c.getLocal("chunkSize")), - c.call( - prefix + "_copy", - c.getLocal("pTable"), - c.getLocal("pr") - ), - - - c.i32_store( - c.i32_const(0), - c.getLocal("pTable") - ) - - ); - } - - function buildMultiexp() { - const f = module.addFunction(fnName); - f.addParam("pBases", "i32"); - f.addParam("pScalars", "i32"); - f.addParam("scalarSize", "i32"); // Number of points - f.addParam("n", "i32"); // Number of points - f.addParam("pr", "i32"); - f.addLocal("chunkSize", "i32"); - f.addLocal("nChunks", "i32"); - f.addLocal("itScalar", "i32"); - f.addLocal("endScalar", "i32"); - f.addLocal("itBase", "i32"); - f.addLocal("itBit", "i32"); - f.addLocal("i", "i32"); - f.addLocal("j", "i32"); - f.addLocal("nTable", "i32"); - f.addLocal("pTable", "i32"); - f.addLocal("idx", "i32"); - f.addLocal("pIdxTable", "i32"); - - const c = f.getCodeBuilder(); - - const aux = c.i32_const(module.alloc(n8g)); - - const pTSizes = module.alloc([ - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 16, 16, 15, 14, 13, 13, - 12, 11, 10, 9, 8, 7, 7, 6, - 5 , 4, 3, 2, 1, 1, 1, 1 - ]); - - f.addCode( - c.call(prefix + "_zero", c.getLocal("pr")), - c.if( - c.i32_eqz(c.getLocal("n")), - c.ret([]) - ), - c.setLocal("chunkSize", c.i32_load8_u( c.i32_clz(c.getLocal("n")), pTSizes )), - c.setLocal( - "nChunks", - c.i32_add( - c.i32_div_u( - c.i32_sub( - c.i32_shl( - c.getLocal("scalarSize"), - c.i32_const(3) - ), - c.i32_const(1) - ), - c.getLocal("chunkSize") - ), - c.i32_const(1) - ) - ), - - - // Allocate memory - - c.setLocal( - "itBit", - c.i32_mul( - c.i32_sub( - c.getLocal("nChunks"), - c.i32_const(1) - ), - c.getLocal("chunkSize") - ) - ), - c.block(c.loop( - c.br_if( - 1, - c.i32_lt_s( - c.getLocal("itBit"), - c.i32_const(0) - ) - ), - - // Double nChunk times - c.if( - c.i32_eqz(c.call(prefix + "_isZero", c.getLocal("pr"))), - [ - ...c.setLocal("j", c.i32_const(0)), - ...c.block(c.loop( - c.br_if( - 1, - c.i32_eq( - c.getLocal("j"), - c.getLocal("chunkSize") - ) - ), - - c.call(prefix + "_double", c.getLocal("pr"), c.getLocal("pr")), - - c.setLocal("j", c.i32_add(c.getLocal("j"), c.i32_const(1))), - c.br(0) - )) - ] - ), - - c.call( - fnName + "_chunk", - c.getLocal("pBases"), - c.getLocal("pScalars"), - c.getLocal("scalarSize"), - c.getLocal("n"), - c.getLocal("itBit"), - c.getLocal("chunkSize"), - aux - ), - - c.call( - prefix + "_add", - c.getLocal("pr"), - aux, - c.getLocal("pr") - ), - c.setLocal("itBit", c.i32_sub(c.getLocal("itBit"), c.getLocal("chunkSize"))), - c.br(0) - )) - ); - } - - function buildReduceTable() { - const f = module.addFunction(fnName + "_reduceTable"); - f.addParam("pTable", "i32"); - f.addParam("p", "i32"); // Number of bits of the table - f.addLocal("half", "i32"); - f.addLocal("it1", "i32"); - f.addLocal("it2", "i32"); - f.addLocal("pAcc", "i32"); - - const c = f.getCodeBuilder(); - - f.addCode( - c.if( - c.i32_eq(c.getLocal("p"), c.i32_const(1)), - c.ret([]) - ), - c.setLocal( - "half", - c.i32_shl( - c.i32_const(1), - c.i32_sub( - c.getLocal("p"), - c.i32_const(1) - ) - ) - ), - - c.setLocal("it1", c.getLocal("pTable")), - c.setLocal( - "it2", - c.i32_add( - c.getLocal("pTable"), - c.i32_mul( - c.getLocal("half"), - c.i32_const(n8g) - ) - ) - ), - c.setLocal("pAcc", - c.i32_sub( - c.getLocal("it2"), - c.i32_const(n8g) - ) - ), - c.block(c.loop( - c.br_if( - 1, - c.i32_eq( - c.getLocal("it1"), - c.getLocal("pAcc") - ) - ), - c.call( - prefix + "_add", - c.getLocal("it1"), - c.getLocal("it2"), - c.getLocal("it1") - ), - c.call( - prefix + "_add", - c.getLocal("pAcc"), - c.getLocal("it2"), - c.getLocal("pAcc") - ), - c.setLocal("it1", c.i32_add(c.getLocal("it1"), c.i32_const(n8g))), - c.setLocal("it2", c.i32_add(c.getLocal("it2"), c.i32_const(n8g))), - c.br(0) - )), - - c.call( - fnName + "_reduceTable", - c.getLocal("pTable"), - c.i32_sub( - c.getLocal("p"), - c.i32_const(1) - ) - ), - - c.setLocal("p", c.i32_sub(c.getLocal("p"), c.i32_const(1))), - c.block(c.loop( - c.br_if(1, c.i32_eqz(c.getLocal("p"))), - c.call(prefix + "_double", c.getLocal("pAcc"), c.getLocal("pAcc")), - c.setLocal("p", c.i32_sub(c.getLocal("p"), c.i32_const(1))), - c.br(0) - )), - - c.call(prefix + "_add", c.getLocal("pTable"), c.getLocal("pAcc"), c.getLocal("pTable")) - ); - } - - buildGetChunk(); - buildReduceTable(); - buildMutiexpChunk(); - buildMultiexp(); - - module.exportFunction(fnName); - module.exportFunction(fnName +"_chunk"); - - - }; - - /* - Copyright 2019 0KIMS association. - - This file is part of wasmsnark (Web Assembly zkSnark Prover). - - wasmsnark is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - wasmsnark is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with wasmsnark. If not, see . - */ - - const buildTimesScalarNAF = build_timesscalarnaf; - //const buildTimesScalar = require("./build_timesscalar"); - const buildBatchConvertion = build_batchconvertion; - const buildMultiexp = build_multiexp; - - var build_curve_jacobian_a0 = function buildCurve(module, prefix, prefixField, pB) { - - - const n64 = module.modules[prefixField].n64; - const n8 = n64*8; - - if (module.modules[prefix]) return prefix; // already builded - module.modules[prefix] = { - n64: n64*3 - }; - - function buildIsZero() { - const f = module.addFunction(prefix + "_isZero"); - f.addParam("p1", "i32"); - f.setReturnType("i32"); - - const c = f.getCodeBuilder(); - - f.addCode(c.call( - prefixField + "_isZero", - c.i32_add( - c.getLocal("p1"), - c.i32_const(n8*2) - ) - )); - } - function buildIsZeroAffine() { - const f = module.addFunction(prefix + "_isZeroAffine"); - f.addParam("p1", "i32"); - f.setReturnType("i32"); - - const c = f.getCodeBuilder(); - - f.addCode( - c.i32_and( - c.call( - prefixField + "_isZero", - c.getLocal("p1") - ), - c.call( - prefixField + "_isZero", - c.i32_add( - c.getLocal("p1"), - c.i32_const(n8) - ) - ) - ) - ); - } - - function buildCopy() { - const f = module.addFunction(prefix + "_copy"); - f.addParam("ps", "i32"); - f.addParam("pd", "i32"); - - const c = f.getCodeBuilder(); - - for (let i=0; i. - */ - - const { isOdd: isOdd$2, modInv: modInv$1, modPow } = bigint; - const utils$2 = utils$5; - - var build_fft = function buildFFT(module, prefix, gPrefix, fPrefix, opGtimesF) { - - const n64f = module.modules[fPrefix].n64; - const n8f = n64f*8; - - const n64g = module.modules[gPrefix].n64; - const n8g = n64g*8; - - const q = module.modules[fPrefix].q; - - let rem = q - 1n; - let maxBits = 0; - while (!isOdd$2(rem)) { - maxBits ++; - rem = rem >> 1n; - } - - let nr = 2n; - - while ( modPow(nr, q >> 1n, q) === 1n ) nr = nr + 1n; - - // console.log(nr); - - const w = new Array(maxBits+1); - w[maxBits] = modPow(nr, rem, q); - - let n=maxBits-1; - while (n>=0) { - w[n] = modPow(w[n+1], 2n, q); - n--; - } - - const bytes = []; - const R = (1n << BigInt(n8f*8)) % q; - - for (let i=0; i> i); - } - } - return r; - } - - const rtable = Array(256); - for (let i=0; i<256; i++) { - rtable[i] = rev(i); - } - - const REVTABLE = module.alloc(rtable); - - - function buildLog2() { - const f = module.addFunction(prefix+"__log2"); - f.addParam("n", "i32"); - f.setReturnType("i32"); - f.addLocal("bits", "i32"); - f.addLocal("aux", "i32"); - - const c = f.getCodeBuilder(); - - f.addCode( - c.setLocal( - "aux", - c.i32_shr_u( - c.getLocal("n"), - c.i32_const(1) - ) - ) - ); - f.addCode(c.setLocal("bits", c.i32_const(0))); - - f.addCode(c.block(c.loop( - c.br_if( - 1, - c.i32_eqz(c.getLocal("aux")) - ), - - c.setLocal( - "aux", - c.i32_shr_u( - c.getLocal("aux"), - c.i32_const(1) - ) - ), - - c.setLocal( - "bits", - c.i32_add( - c.getLocal("bits"), - c.i32_const(1) - ) - ), - - c.br(0) - ))); - - f.addCode(c.if( - c.i32_ne( - c.getLocal("n"), - c.i32_shl( - c.i32_const(1), - c.getLocal("bits") - ) - ), - c.unreachable() - )); - - f.addCode(c.if( - c.i32_gt_u( - c.getLocal("bits"), - c.i32_const(maxBits) - ), - c.unreachable() - )); - - f.addCode(c.getLocal("bits")); - } - - function buildFFT() { - const f = module.addFunction(prefix+"_fft"); - f.addParam("px", "i32"); - f.addParam("n", "i32"); - - f.addLocal("bits", "i32"); - - const c = f.getCodeBuilder(); - - const One = c.i32_const(module.alloc(n8f)); - - f.addCode( - c.setLocal( - "bits", - c.call( - prefix + "__log2", - c.getLocal("n") - ) - ), - c.call(fPrefix + "_one", One), - c.call( - prefix+"_rawfft", - c.getLocal("px"), - c.getLocal("bits"), - c.i32_const(0), - One - ) - ); - - } - - function buildIFFT() { - const f = module.addFunction(prefix+"_ifft"); - f.addParam("px", "i32"); - f.addParam("n", "i32"); - f.addLocal("bits", "i32"); - f.addLocal("pInv2", "i32"); - - const c = f.getCodeBuilder(); - - f.addCode( - c.setLocal( - "bits", - c.call( - prefix + "__log2", - c.getLocal("n") - ) - ), - c.setLocal( - "pInv2", - c.i32_add( - c.i32_const(INV2), - c.i32_mul( - c.getLocal("bits"), - c.i32_const(n8f) - ) - ) - ), - - c.call( - prefix+"_rawfft", - c.getLocal("px"), - c.getLocal("bits"), - c.i32_const(1), - c.getLocal("pInv2") - ), - ); - } - - function buildRawFFT() { - const f = module.addFunction(prefix+"_rawfft"); - f.addParam("px", "i32"); - f.addParam("bits", "i32"); // 2 power - f.addParam("reverse", "i32"); - f.addParam("mulFactor", "i32"); - - f.addLocal("s", "i32"); - f.addLocal("k", "i32"); - f.addLocal("j", "i32"); - f.addLocal("m", "i32"); - f.addLocal("mdiv2", "i32"); - f.addLocal("n", "i32"); - f.addLocal("pwm", "i32"); - f.addLocal("idx1", "i32"); - f.addLocal("idx2", "i32"); - - const c = f.getCodeBuilder(); - - const W = c.i32_const(module.alloc(n8f)); - const T = c.i32_const(module.alloc(n8g)); - const U = c.i32_const(module.alloc(n8g)); - - f.addCode( - c.call(prefix + "__reversePermutation", c.getLocal("px"), c.getLocal("bits")), - c.setLocal("n", c.i32_shl(c.i32_const(1), c.getLocal("bits"))), - c.setLocal("s", c.i32_const(1)), - c.block(c.loop( - c.br_if( - 1, - c.i32_gt_u( - c.getLocal("s"), - c.getLocal("bits") - ) - ), - c.setLocal("m", c.i32_shl(c.i32_const(1), c.getLocal("s"))), - c.setLocal("pwm", - c.i32_add( - c.i32_const(ROOTs), - c.i32_mul( - c.getLocal("s"), - c.i32_const(n8f) - ) - ) - ), - c.setLocal("k", c.i32_const(0)), - c.block(c.loop( - c.br_if( - 1, - c.i32_ge_u( - c.getLocal("k"), - c.getLocal("n") - ) - ), - - c.call(fPrefix + "_one", W), - - c.setLocal("mdiv2", c.i32_shr_u(c.getLocal("m"), c.i32_const(1)) ), - c.setLocal("j", c.i32_const(0)), - c.block(c.loop( - c.br_if( - 1, - c.i32_ge_u( - c.getLocal("j"), - c.getLocal("mdiv2") - ) - ), - - c.setLocal( - "idx1", - c.i32_add( - c.getLocal("px"), - c.i32_mul( - c.i32_add( - c.getLocal("k"), - c.getLocal("j") - ), - c.i32_const(n8g) - ) - ) - ), - - c.setLocal( - "idx2", - c.i32_add( - c.getLocal("idx1"), - c.i32_mul( - c.getLocal("mdiv2"), - c.i32_const(n8g) - ) - ) - ), - - c.call( - opGtimesF, - c.getLocal("idx2"), - W, - T - ), - - c.call( - gPrefix + "_copy", - c.getLocal("idx1"), - U - ), - - c.call( - gPrefix + "_add", - U, - T, - c.getLocal("idx1"), - ), - - c.call( - gPrefix + "_sub", - U, - T, - c.getLocal("idx2"), - ), - - c.call( - fPrefix + "_mul", - W, - c.getLocal("pwm"), - W, - ), - - c.setLocal("j", c.i32_add(c.getLocal("j"), c.i32_const(1))), - c.br(0) - )), - - c.setLocal("k", c.i32_add(c.getLocal("k"), c.getLocal("m"))), - c.br(0) - )), - - c.setLocal("s", c.i32_add(c.getLocal("s"), c.i32_const(1))), - c.br(0) - )), - c.call( - prefix + "__fftFinal", - c.getLocal("px"), - c.getLocal("bits"), - c.getLocal("reverse"), - c.getLocal("mulFactor") - ) - ); - } - - - function buildFinalInverse() { - const f = module.addFunction(prefix+"__fftFinal"); - f.addParam("px", "i32"); - f.addParam("bits", "i32"); - f.addParam("reverse", "i32"); - f.addParam("mulFactor", "i32"); - f.addLocal("n", "i32"); - f.addLocal("ndiv2", "i32"); - f.addLocal("pInv2", "i32"); - f.addLocal("i", "i32"); - f.addLocal("mask", "i32"); - f.addLocal("idx1", "i32"); - f.addLocal("idx2", "i32"); - - const c = f.getCodeBuilder(); - - const T = c.i32_const(module.alloc(n8g)); - - f.addCode( - c.if( - c.i32_and( - c.i32_eqz(c.getLocal("reverse")), - c.call(fPrefix + "_isOne", c.getLocal("mulFactor")) - ), - c.ret([]) - ), - c.setLocal("n", c.i32_shl( c.i32_const(1), c.getLocal("bits"))), - - c.setLocal("mask", c.i32_sub( c.getLocal("n") , c.i32_const(1))), - c.setLocal("i", c.i32_const(1)), - c.setLocal( - "ndiv2", - c.i32_shr_u( - c.getLocal("n"), - c.i32_const(1) - ) - ), - c.block(c.loop( - c.br_if( - 1, - c.i32_ge_u( - c.getLocal("i"), - c.getLocal("ndiv2") - ) - ), - - c.setLocal("idx1", - c.i32_add( - c.getLocal("px"), - c.i32_mul( - c.getLocal("i"), - c.i32_const(n8g) - ) - ) - ), - - c.setLocal("idx2", - c.i32_add( - c.getLocal("px"), - c.i32_mul( - c.i32_sub( - c.getLocal("n"), - c.getLocal("i") - ), - c.i32_const(n8g) - ) - ) - ), - - c.if( - c.getLocal("reverse"), - c.if( - c.call(fPrefix + "_isOne", c.getLocal("mulFactor")), - [ - ...c.call(gPrefix + "_copy", c.getLocal("idx1"), T), - ...c.call(gPrefix + "_copy", c.getLocal("idx2") , c.getLocal("idx1") ), - ...c.call(gPrefix + "_copy", T , c.getLocal("idx2")), - ], - [ - ...c.call(gPrefix + "_copy", c.getLocal("idx1"), T), - ...c.call(opGtimesF , c.getLocal("idx2") , c.getLocal("mulFactor"), c.getLocal("idx1") ), - ...c.call(opGtimesF , T , c.getLocal("mulFactor"), c.getLocal("idx2")), - ] - ), - c.if( - c.call(fPrefix + "_isOne", c.getLocal("mulFactor")), - [ - // Do nothing (It should not be here) - ], - [ - ...c.call(opGtimesF , c.getLocal("idx1") , c.getLocal("mulFactor"), c.getLocal("idx1") ), - ...c.call(opGtimesF , c.getLocal("idx2") , c.getLocal("mulFactor"), c.getLocal("idx2")), - ] - ) - ), - c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), - - c.br(0) - )), - - c.if( - c.call(fPrefix + "_isOne", c.getLocal("mulFactor")), - [ - // Do nothing (It should not be here) - ], - [ - ...c.call(opGtimesF, c.getLocal("px") , c.getLocal("mulFactor"), c.getLocal("px")), - ...c.setLocal("idx2", - c.i32_add( - c.getLocal("px"), - c.i32_mul( - c.getLocal("ndiv2"), - c.i32_const(n8g) - ) - ) - ), - ...c.call(opGtimesF, c.getLocal("idx2"),c.getLocal("mulFactor"), c.getLocal("idx2")) - ] - ) - ); - } - - function buildReversePermutation() { - const f = module.addFunction(prefix+"__reversePermutation"); - f.addParam("px", "i32"); - f.addParam("bits", "i32"); - f.addLocal("n", "i32"); - f.addLocal("i", "i32"); - f.addLocal("ri", "i32"); - f.addLocal("idx1", "i32"); - f.addLocal("idx2", "i32"); - - const c = f.getCodeBuilder(); - - const T = c.i32_const(module.alloc(n8g)); - - f.addCode( - c.setLocal("n", c.i32_shl( c.i32_const(1), c.getLocal("bits"))), - c.setLocal("i", c.i32_const(0)), - c.block(c.loop( - c.br_if( - 1, - c.i32_eq( - c.getLocal("i"), - c.getLocal("n") - ) - ), - - c.setLocal("idx1", - c.i32_add( - c.getLocal("px"), - c.i32_mul( - c.getLocal("i"), - c.i32_const(n8g) - ) - ) - ), - - c.setLocal("ri", c.call(prefix + "__rev", c.getLocal("i"), c.getLocal("bits"))), - - c.setLocal("idx2", - c.i32_add( - c.getLocal("px"), - c.i32_mul( - c.getLocal("ri"), - c.i32_const(n8g) - ) - ) - ), - - c.if( - c.i32_lt_u( - c.getLocal("i"), - c.getLocal("ri") - ), - [ - ...c.call(gPrefix + "_copy", c.getLocal("idx1"), T), - ...c.call(gPrefix + "_copy", c.getLocal("idx2") , c.getLocal("idx1")), - ...c.call(gPrefix + "_copy", T , c.getLocal("idx2")) - ] - ), - - c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), - - c.br(0) - )) - ); - } - - function buildRev() { - const f = module.addFunction(prefix+"__rev"); - f.addParam("x", "i32"); - f.addParam("bits", "i32"); - f.setReturnType("i32"); - - const c = f.getCodeBuilder(); - - f.addCode( - c.i32_rotl( - c.i32_add( - c.i32_add( - c.i32_shl( - c.i32_load8_u( - c.i32_and( - c.getLocal("x"), - c.i32_const(0xFF) - ), - REVTABLE, - 0 - ), - c.i32_const(24) - ), - c.i32_shl( - c.i32_load8_u( - c.i32_and( - c.i32_shr_u( - c.getLocal("x"), - c.i32_const(8) - ), - c.i32_const(0xFF) - ), - REVTABLE, - 0 - ), - c.i32_const(16) - ), - ), - c.i32_add( - c.i32_shl( - c.i32_load8_u( - c.i32_and( - c.i32_shr_u( - c.getLocal("x"), - c.i32_const(16) - ), - c.i32_const(0xFF) - ), - REVTABLE, - 0 - ), - c.i32_const(8) - ), - c.i32_load8_u( - c.i32_and( - c.i32_shr_u( - c.getLocal("x"), - c.i32_const(24) - ), - c.i32_const(0xFF) - ), - REVTABLE, - 0 - ), - ) - ), - c.getLocal("bits") - ) - ); - } - - - function buildFFTJoin() { - const f = module.addFunction(prefix+"_fftJoin"); - f.addParam("pBuff1", "i32"); - f.addParam("pBuff2", "i32"); - f.addParam("n", "i32"); - f.addParam("first", "i32"); - f.addParam("inc", "i32"); - f.addLocal("idx1", "i32"); - f.addLocal("idx2", "i32"); - f.addLocal("i", "i32"); - - const c = f.getCodeBuilder(); - - const W = c.i32_const(module.alloc(n8f)); - const T = c.i32_const(module.alloc(n8g)); - const U = c.i32_const(module.alloc(n8g)); - - f.addCode( - c.call( fPrefix + "_copy", c.getLocal("first"), W), - c.setLocal("i", c.i32_const(0)), - c.block(c.loop( - c.br_if( - 1, - c.i32_eq( - c.getLocal("i"), - c.getLocal("n") - ) - ), - - c.setLocal( - "idx1", - c.i32_add( - c.getLocal("pBuff1"), - c.i32_mul( - c.getLocal("i"), - c.i32_const(n8g) - ) - ) - ), - - c.setLocal( - "idx2", - c.i32_add( - c.getLocal("pBuff2"), - c.i32_mul( - c.getLocal("i"), - c.i32_const(n8g) - ) - ) - ), - - c.call( - opGtimesF, - c.getLocal("idx2"), - W, - T - ), - - c.call( - gPrefix + "_copy", - c.getLocal("idx1"), - U - ), - - c.call( - gPrefix + "_add", - U, - T, - c.getLocal("idx1"), - ), - - c.call( - gPrefix + "_sub", - U, - T, - c.getLocal("idx2"), - ), - - c.call( - fPrefix + "_mul", - W, - c.getLocal("inc"), - W, - ), - - c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), - c.br(0) - )) - ); - } - - - function buildFFTJoinExt() { - const f = module.addFunction(prefix+"_fftJoinExt"); - f.addParam("pBuff1", "i32"); - f.addParam("pBuff2", "i32"); - f.addParam("n", "i32"); - f.addParam("first", "i32"); - f.addParam("inc", "i32"); - f.addParam("totalBits", "i32"); - f.addLocal("idx1", "i32"); - f.addLocal("idx2", "i32"); - f.addLocal("i", "i32"); - f.addLocal("pShiftToM", "i32"); - - const c = f.getCodeBuilder(); - - const W = c.i32_const(module.alloc(n8f)); - const U = c.i32_const(module.alloc(n8g)); - - f.addCode( - - c.setLocal("pShiftToM", - c.i32_add( - c.i32_const(SHIFT_TO_M), - c.i32_mul( - c.getLocal("totalBits"), - c.i32_const(n8f) - ) - ) - ), - - - c.call( fPrefix + "_copy", c.getLocal("first"), W), - c.setLocal("i", c.i32_const(0)), - c.block(c.loop( - c.br_if( - 1, - c.i32_eq( - c.getLocal("i"), - c.getLocal("n") - ) - ), - - c.setLocal( - "idx1", - c.i32_add( - c.getLocal("pBuff1"), - c.i32_mul( - c.getLocal("i"), - c.i32_const(n8g) - ) - ) - ), - - c.setLocal( - "idx2", - c.i32_add( - c.getLocal("pBuff2"), - c.i32_mul( - c.getLocal("i"), - c.i32_const(n8g) - ) - ) - ), - - c.call( - gPrefix + "_add", - c.getLocal("idx1"), - c.getLocal("idx2"), - U - ), - - c.call( - opGtimesF, - c.getLocal("idx2"), - c.getLocal("pShiftToM"), - c.getLocal("idx2") - ), - - c.call( - gPrefix + "_add", - c.getLocal("idx1"), - c.getLocal("idx2"), - c.getLocal("idx2") - ), - - c.call( - opGtimesF, - c.getLocal("idx2"), - W, - c.getLocal("idx2"), - ), - - c.call( - gPrefix + "_copy", - U, - c.getLocal("idx1") - ), - - c.call( - fPrefix + "_mul", - W, - c.getLocal("inc"), - W - ), - - c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), - c.br(0) - )) - ); - } - - function buildFFTJoinExtInv() { - const f = module.addFunction(prefix+"_fftJoinExtInv"); - f.addParam("pBuff1", "i32"); - f.addParam("pBuff2", "i32"); - f.addParam("n", "i32"); - f.addParam("first", "i32"); - f.addParam("inc", "i32"); - f.addParam("totalBits", "i32"); - f.addLocal("idx1", "i32"); - f.addLocal("idx2", "i32"); - f.addLocal("i", "i32"); - f.addLocal("pShiftToM", "i32"); - f.addLocal("pSConst", "i32"); - - const c = f.getCodeBuilder(); - - const W = c.i32_const(module.alloc(n8f)); - const U = c.i32_const(module.alloc(n8g)); - - f.addCode( - - c.setLocal("pShiftToM", - c.i32_add( - c.i32_const(SHIFT_TO_M), - c.i32_mul( - c.getLocal("totalBits"), - c.i32_const(n8f) - ) - ) - ), - c.setLocal("pSConst", - c.i32_add( - c.i32_const(SCONST), - c.i32_mul( - c.getLocal("totalBits"), - c.i32_const(n8f) - ) - ) - ), - - - c.call( fPrefix + "_copy", c.getLocal("first"), W), - c.setLocal("i", c.i32_const(0)), - c.block(c.loop( - c.br_if( - 1, - c.i32_eq( - c.getLocal("i"), - c.getLocal("n") - ) - ), - - c.setLocal( - "idx1", - c.i32_add( - c.getLocal("pBuff1"), - c.i32_mul( - c.getLocal("i"), - c.i32_const(n8g) - ) - ) - ), - - c.setLocal( - "idx2", - c.i32_add( - c.getLocal("pBuff2"), - c.i32_mul( - c.getLocal("i"), - c.i32_const(n8g) - ) - ) - ), - - c.call( - opGtimesF, - c.getLocal("idx2"), - W, - U - ), - - c.call( - gPrefix + "_sub", - c.getLocal("idx1"), - U, - c.getLocal("idx2"), - ), - - c.call( - opGtimesF, - c.getLocal("idx2"), - c.getLocal("pSConst"), - c.getLocal("idx2") - ), - - c.call( - opGtimesF, - c.getLocal("idx1"), - c.getLocal("pShiftToM"), - c.getLocal("idx1") - ), - - c.call( - gPrefix + "_sub", - U, - c.getLocal("idx1"), - c.getLocal("idx1") - ), - - c.call( - opGtimesF, - c.getLocal("idx1"), - c.getLocal("pSConst"), - c.getLocal("idx1") - ), - - c.call( - fPrefix + "_mul", - W, - c.getLocal("inc"), - W - ), - - c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), - c.br(0) - )) - ); - } - - - - function buildPrepareLagrangeEvaluation() { - const f = module.addFunction(prefix+"_prepareLagrangeEvaluation"); - f.addParam("pBuff1", "i32"); - f.addParam("pBuff2", "i32"); - f.addParam("n", "i32"); - f.addParam("first", "i32"); - f.addParam("inc", "i32"); - f.addParam("totalBits", "i32"); - f.addLocal("idx1", "i32"); - f.addLocal("idx2", "i32"); - f.addLocal("i", "i32"); - f.addLocal("pShiftToM", "i32"); - f.addLocal("pSConst", "i32"); - - const c = f.getCodeBuilder(); - - const W = c.i32_const(module.alloc(n8f)); - const U = c.i32_const(module.alloc(n8g)); - - f.addCode( - - c.setLocal("pShiftToM", - c.i32_add( - c.i32_const(SHIFT_TO_M), - c.i32_mul( - c.getLocal("totalBits"), - c.i32_const(n8f) - ) - ) - ), - c.setLocal("pSConst", - c.i32_add( - c.i32_const(SCONST), - c.i32_mul( - c.getLocal("totalBits"), - c.i32_const(n8f) - ) - ) - ), - - - c.call( fPrefix + "_copy", c.getLocal("first"), W), - c.setLocal("i", c.i32_const(0)), - c.block(c.loop( - c.br_if( - 1, - c.i32_eq( - c.getLocal("i"), - c.getLocal("n") - ) - ), - - c.setLocal( - "idx1", - c.i32_add( - c.getLocal("pBuff1"), - c.i32_mul( - c.getLocal("i"), - c.i32_const(n8g) - ) - ) - ), - - c.setLocal( - "idx2", - c.i32_add( - c.getLocal("pBuff2"), - c.i32_mul( - c.getLocal("i"), - c.i32_const(n8g) - ) - ) - ), - - - c.call( - opGtimesF, - c.getLocal("idx1"), - c.getLocal("pShiftToM"), - U - ), - - c.call( - gPrefix + "_sub", - c.getLocal("idx2"), - U, - U - ), - - c.call( - gPrefix + "_sub", - c.getLocal("idx1"), - c.getLocal("idx2"), - c.getLocal("idx2"), - ), - - c.call( - opGtimesF, - U, - c.getLocal("pSConst"), - c.getLocal("idx1"), - ), - - c.call( - opGtimesF, - c.getLocal("idx2"), - W, - c.getLocal("idx2"), - ), - - c.call( - fPrefix + "_mul", - W, - c.getLocal("inc"), - W - ), - - c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), - c.br(0) - )) - ); - } - - function buildFFTMix() { - const f = module.addFunction(prefix+"_fftMix"); - f.addParam("pBuff", "i32"); - f.addParam("n", "i32"); - f.addParam("exp", "i32"); - f.addLocal("nGroups", "i32"); - f.addLocal("nPerGroup", "i32"); - f.addLocal("nPerGroupDiv2", "i32"); - f.addLocal("pairOffset", "i32"); - f.addLocal("idx1", "i32"); - f.addLocal("idx2", "i32"); - f.addLocal("i", "i32"); - f.addLocal("j", "i32"); - f.addLocal("pwm", "i32"); - - const c = f.getCodeBuilder(); - - const W = c.i32_const(module.alloc(n8f)); - const T = c.i32_const(module.alloc(n8g)); - const U = c.i32_const(module.alloc(n8g)); - - f.addCode( - c.setLocal("nPerGroup", c.i32_shl(c.i32_const(1), c.getLocal("exp"))), - c.setLocal("nPerGroupDiv2", c.i32_shr_u(c.getLocal("nPerGroup"), c.i32_const(1))), - c.setLocal("nGroups", c.i32_shr_u(c.getLocal("n"), c.getLocal("exp"))), - c.setLocal("pairOffset", c.i32_mul(c.getLocal("nPerGroupDiv2"), c.i32_const(n8g))), - c.setLocal("pwm", - c.i32_add( - c.i32_const(ROOTs), - c.i32_mul( - c.getLocal("exp"), - c.i32_const(n8f) - ) - ) - ), - c.setLocal("i", c.i32_const(0)), - c.block(c.loop( - c.br_if( - 1, - c.i32_eq( - c.getLocal("i"), - c.getLocal("nGroups") - ) - ), - c.call( fPrefix + "_one", W), - c.setLocal("j", c.i32_const(0)), - c.block(c.loop( - c.br_if( - 1, - c.i32_eq( - c.getLocal("j"), - c.getLocal("nPerGroupDiv2") - ) - ), - - c.setLocal( - "idx1", - c.i32_add( - c.getLocal("pBuff"), - c.i32_mul( - c.i32_add( - c.i32_mul( - c.getLocal("i"), - c.getLocal("nPerGroup") - ), - c.getLocal("j") - ), - c.i32_const(n8g) - ) - ) - ), - - c.setLocal( - "idx2", - c.i32_add( - c.getLocal("idx1"), - c.getLocal("pairOffset") - ) - ), - - c.call( - opGtimesF, - c.getLocal("idx2"), - W, - T - ), - - c.call( - gPrefix + "_copy", - c.getLocal("idx1"), - U - ), - - c.call( - gPrefix + "_add", - U, - T, - c.getLocal("idx1"), - ), - - c.call( - gPrefix + "_sub", - U, - T, - c.getLocal("idx2"), - ), - - c.call( - fPrefix + "_mul", - W, - c.getLocal("pwm"), - W, - ), - c.setLocal("j", c.i32_add(c.getLocal("j"), c.i32_const(1))), - c.br(0) - )), - c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), - c.br(0) - )) - ); - } - - - // Reverse all and multiply by factor - function buildFFTFinal() { - const f = module.addFunction(prefix+"_fftFinal"); - f.addParam("pBuff", "i32"); - f.addParam("n", "i32"); - f.addParam("factor", "i32"); - f.addLocal("idx1", "i32"); - f.addLocal("idx2", "i32"); - f.addLocal("i", "i32"); - f.addLocal("ndiv2", "i32"); - - const c = f.getCodeBuilder(); - - const T = c.i32_const(module.alloc(n8g)); - - f.addCode( - c.setLocal("ndiv2", c.i32_shr_u(c.getLocal("n"), c.i32_const(1))), - c.if( - c.i32_and( - c.getLocal("n"), - c.i32_const(1) - ), - c.call( - opGtimesF, - c.i32_add( - c.getLocal("pBuff"), - c.i32_mul( - c.getLocal("ndiv2"), - c.i32_const(n8g) - ) - ), - c.getLocal("factor"), - c.i32_add( - c.getLocal("pBuff"), - c.i32_mul( - c.getLocal("ndiv2"), - c.i32_const(n8g) - ) - ), - ), - ), - c.setLocal("i", c.i32_const(0)), - c.block(c.loop( - c.br_if( - 1, - c.i32_ge_u( - c.getLocal("i"), - c.getLocal("ndiv2") - ) - ), - - c.setLocal( - "idx1", - c.i32_add( - c.getLocal("pBuff"), - c.i32_mul( - c.getLocal("i"), - c.i32_const(n8g) - ) - ) - ), - - c.setLocal( - "idx2", - c.i32_add( - c.getLocal("pBuff"), - c.i32_mul( - c.i32_sub( - c.i32_sub( - c.getLocal("n"), - c.i32_const(1) - ), - c.getLocal("i") - ), - c.i32_const(n8g) - ) - ) - ), - - c.call( - opGtimesF, - c.getLocal("idx2"), - c.getLocal("factor"), - T - ), - - c.call( - opGtimesF, - c.getLocal("idx1"), - c.getLocal("factor"), - c.getLocal("idx2"), - ), - - c.call( - gPrefix + "_copy", - T, - c.getLocal("idx1"), - ), - - c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), - c.br(0) - )) - ); - } - - buildRev(); - buildReversePermutation(); - buildFinalInverse(); - buildRawFFT(); - buildLog2(); - buildFFT(); - buildIFFT(); - buildFFTJoin(); - buildFFTJoinExt(); - buildFFTJoinExtInv(); - buildFFTMix(); - buildFFTFinal(); - buildPrepareLagrangeEvaluation(); - - module.exportFunction(prefix+"__reversePermutation"); - module.exportFunction(prefix+"_fft"); - module.exportFunction(prefix+"_ifft"); - module.exportFunction(prefix+"_rawfft"); - module.exportFunction(prefix+"_fftJoin"); - module.exportFunction(prefix+"_fftJoinExt"); - module.exportFunction(prefix+"_fftJoinExtInv"); - module.exportFunction(prefix+"_fftMix"); - module.exportFunction(prefix+"_fftFinal"); - module.exportFunction(prefix+"_prepareLagrangeEvaluation"); - - }; - - /* - Copyright 2019 0KIMS association. - - This file is part of wasmsnark (Web Assembly zkSnark Prover). - - wasmsnark is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - wasmsnark is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with wasmsnark. If not, see . - */ - - var build_pol = function buildPol(module, prefix, prefixField) { - - const n64 = module.modules[prefixField].n64; - const n8 = n64*8; - - - function buildZero() { - const f = module.addFunction(prefix+"_zero"); - f.addParam("px", "i32"); - f.addParam("n", "i32"); - f.addLocal("lastp", "i32"); - f.addLocal("p", "i32"); - - const c = f.getCodeBuilder(); - - f.addCode( - c.setLocal("p", c.getLocal("px")), - c.setLocal( - "lastp", - c.i32_add( - c.getLocal("px"), - c.i32_mul( - c.getLocal("n"), - c.i32_const(n8) - ) - ) - ), - c.block(c.loop( - c.br_if( - 1, - c.i32_eq( - c.getLocal("p"), - c.getLocal("lastp") - ) - ), - c.call(prefixField + "_zero", c.getLocal("p")), - c.setLocal("p", c.i32_add(c.getLocal("p"), c.i32_const(n8))), - c.br(0) - )) - ); - } - - function buildConstructLC() { - const f = module.addFunction(prefix+"_constructLC"); - f.addParam("ppolynomials", "i32"); - f.addParam("psignals", "i32"); - f.addParam("nSignals", "i32"); - f.addParam("pres", "i32"); - f.addLocal("i", "i32"); - f.addLocal("j", "i32"); - f.addLocal("pp", "i32"); - f.addLocal("ps", "i32"); - f.addLocal("pd", "i32"); - f.addLocal("ncoefs", "i32"); - - const c = f.getCodeBuilder(); - - const aux = c.i32_const(module.alloc(n8)); - - f.addCode( - c.setLocal("i", c.i32_const(0)), - c.setLocal("pp", c.getLocal("ppolynomials")), - c.setLocal("ps", c.getLocal("psignals")), - c.block(c.loop( - c.br_if( - 1, - c.i32_eq( - c.getLocal("i"), - c.getLocal("nSignals") - ) - ), - - c.setLocal("ncoefs", c.i32_load(c.getLocal("pp"))), - c.setLocal("pp", c.i32_add(c.getLocal("pp"), c.i32_const(4))), - - c.setLocal("j", c.i32_const(0)), - c.block(c.loop( - c.br_if( - 1, - c.i32_eq( - c.getLocal("j"), - c.getLocal("ncoefs") - ) - ), - - c.setLocal( - "pd", - c.i32_add( - c.getLocal("pres"), - c.i32_mul( - c.i32_load(c.getLocal("pp")), - c.i32_const(n8) - ) - ) - ), - - c.setLocal("pp", c.i32_add(c.getLocal("pp"), c.i32_const(4))), - - - c.call( - prefixField + "_mul", - c.getLocal("ps"), - c.getLocal("pp"), - aux - ), - - c.call( - prefixField + "_add", - aux, - c.getLocal("pd"), - c.getLocal("pd") - ), - - c.setLocal("pp", c.i32_add(c.getLocal("pp"), c.i32_const(n8))), - c.setLocal("j", c.i32_add(c.getLocal("j"), c.i32_const(1))), - c.br(0) - )), - - c.setLocal("ps", c.i32_add(c.getLocal("ps"), c.i32_const(n8))), - c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), - c.br(0) - )) - ); - - } - - buildZero(); - buildConstructLC(); - - - module.exportFunction(prefix + "_zero"); - module.exportFunction(prefix + "_constructLC"); - - return prefix; - - - - - }; - - var build_qap = function buildQAP(module, prefix, prefixField) { - - const n64 = module.modules[prefixField].n64; - const n8 = n64*8; - - - function buildBuildABC() { - const f = module.addFunction(prefix+"_buildABC"); - f.addParam("pCoefs", "i32"); - f.addParam("nCoefs", "i32"); - f.addParam("pWitness", "i32"); - f.addParam("pA", "i32"); - f.addParam("pB", "i32"); - f.addParam("pC", "i32"); - f.addParam("offsetOut", "i32"); - f.addParam("nOut", "i32"); - f.addParam("offsetWitness", "i32"); - f.addParam("nWitness", "i32"); - f.addLocal("it", "i32"); - f.addLocal("ita", "i32"); - f.addLocal("itb", "i32"); - f.addLocal("last", "i32"); - f.addLocal("m", "i32"); - f.addLocal("c", "i32"); - f.addLocal("s", "i32"); - f.addLocal("pOut", "i32"); - - const c = f.getCodeBuilder(); - - const aux = c.i32_const(module.alloc(n8)); - - f.addCode( - - // Set output a and b to 0 - c.setLocal("ita", c.getLocal("pA")), - c.setLocal("itb", c.getLocal("pB")), - c.setLocal( - "last", - c.i32_add( - c.getLocal("pA"), - c.i32_mul( - c.getLocal("nOut"), - c.i32_const(n8) - ) - ) - ), - c.block(c.loop( - c.br_if( - 1, - c.i32_eq( - c.getLocal("ita"), - c.getLocal("last") - ) - ), - c.call(prefixField + "_zero", c.getLocal("ita")), - c.call(prefixField + "_zero", c.getLocal("itb")), - c.setLocal("ita", c.i32_add(c.getLocal("ita"), c.i32_const(n8))), - c.setLocal("itb", c.i32_add(c.getLocal("itb"), c.i32_const(n8))), - c.br(0) - )), - - - c.setLocal("it", c.getLocal("pCoefs")), - c.setLocal( - "last", - c.i32_add( - c.getLocal("pCoefs"), - c.i32_mul( - c.getLocal("nCoefs"), - c.i32_const(n8+12) - ) - ) - ), - c.block(c.loop( - c.br_if( - 1, - c.i32_eq( - c.getLocal("it"), - c.getLocal("last") - ) - ), - c.setLocal( - "s", - c.i32_load(c.getLocal("it"), 8) - ), - c.if( - c.i32_or( - c.i32_lt_u( - c.getLocal("s"), - c.getLocal("offsetWitness"), - ), - c.i32_ge_u( - c.getLocal("s"), - c.i32_add( - c.getLocal("offsetWitness"), - c.getLocal("nWitness"), - ) - ) - ), - [ - ...c.setLocal("it", c.i32_add(c.getLocal("it"), c.i32_const(n8+12))), - ...c.br(1) - ] - ), - - c.setLocal( - "m", - c.i32_load(c.getLocal("it")) - ), - c.if( - c.i32_eq(c.getLocal("m"), c.i32_const(0)), - c.setLocal("pOut", c.getLocal("pA")), - c.if( - c.i32_eq(c.getLocal("m"), c.i32_const(1)), - c.setLocal("pOut", c.getLocal("pB")), - [ - ...c.setLocal("it", c.i32_add(c.getLocal("it"), c.i32_const(n8+12))), - ...c.br(1) - ] - ) - ), - c.setLocal( - "c", - c.i32_load(c.getLocal("it"), 4) - ), - c.if( - c.i32_or( - c.i32_lt_u( - c.getLocal("c"), - c.getLocal("offsetOut"), - ), - c.i32_ge_u( - c.getLocal("c"), - c.i32_add( - c.getLocal("offsetOut"), - c.getLocal("nOut"), - ) - ) - ), - [ - ...c.setLocal("it", c.i32_add(c.getLocal("it"), c.i32_const(n8+12))), - ...c.br(1) - ] - ), - c.setLocal( - "pOut", - c.i32_add( - c.getLocal("pOut"), - c.i32_mul( - c.i32_sub( - c.getLocal("c"), - c.getLocal("offsetOut") - ), - c.i32_const(n8) - ) - ) - ), - c.call( - prefixField + "_mul", - c.i32_add( - c.getLocal("pWitness"), - c.i32_mul( - c.i32_sub(c.getLocal("s"), c.getLocal("offsetWitness")), - c.i32_const(n8) - ) - ), - c.i32_add( c.getLocal("it"), c.i32_const(12)), - aux - ), - c.call( - prefixField + "_add", - c.getLocal("pOut"), - aux, - c.getLocal("pOut"), - ), - c.setLocal("it", c.i32_add(c.getLocal("it"), c.i32_const(n8+12))), - c.br(0) - )), - - c.setLocal("ita", c.getLocal("pA")), - c.setLocal("itb", c.getLocal("pB")), - c.setLocal("it", c.getLocal("pC")), - c.setLocal( - "last", - c.i32_add( - c.getLocal("pA"), - c.i32_mul( - c.getLocal("nOut"), - c.i32_const(n8) - ) - ) - ), - c.block(c.loop( - c.br_if( - 1, - c.i32_eq( - c.getLocal("ita"), - c.getLocal("last") - ) - ), - c.call( - prefixField + "_mul", - c.getLocal("ita"), - c.getLocal("itb"), - c.getLocal("it") - ), - c.setLocal("ita", c.i32_add(c.getLocal("ita"), c.i32_const(n8))), - c.setLocal("itb", c.i32_add(c.getLocal("itb"), c.i32_const(n8))), - c.setLocal("it", c.i32_add(c.getLocal("it"), c.i32_const(n8))), - c.br(0) - )), - - ); - } - - function buildJoinABC() { - const f = module.addFunction(prefix+"_joinABC"); - f.addParam("pA", "i32"); - f.addParam("pB", "i32"); - f.addParam("pC", "i32"); - f.addParam("n", "i32"); - f.addParam("pP", "i32"); - f.addLocal("ita", "i32"); - f.addLocal("itb", "i32"); - f.addLocal("itc", "i32"); - f.addLocal("itp", "i32"); - f.addLocal("last", "i32"); - - const c = f.getCodeBuilder(); - - const aux = c.i32_const(module.alloc(n8)); - - f.addCode( - c.setLocal("ita", c.getLocal("pA")), - c.setLocal("itb", c.getLocal("pB")), - c.setLocal("itc", c.getLocal("pC")), - c.setLocal("itp", c.getLocal("pP")), - c.setLocal( - "last", - c.i32_add( - c.getLocal("pA"), - c.i32_mul( - c.getLocal("n"), - c.i32_const(n8) - ) - ) - ), - c.block(c.loop( - c.br_if( - 1, - c.i32_eq( - c.getLocal("ita"), - c.getLocal("last") - ) - ), - c.call( - prefixField + "_mul", - c.getLocal("ita"), - c.getLocal("itb"), - aux - ), - c.call( - prefixField + "_sub", - aux, - c.getLocal("itc"), - c.getLocal("itp"), - ), - c.setLocal("ita", c.i32_add(c.getLocal("ita"), c.i32_const(n8))), - c.setLocal("itb", c.i32_add(c.getLocal("itb"), c.i32_const(n8))), - c.setLocal("itc", c.i32_add(c.getLocal("itc"), c.i32_const(n8))), - c.setLocal("itp", c.i32_add(c.getLocal("itp"), c.i32_const(n8))), - c.br(0) - )) - ); - } - - function buildBatchAdd() { - const f = module.addFunction(prefix+"_batchAdd"); - f.addParam("pa", "i32"); - f.addParam("pb", "i32"); - f.addParam("n", "i32"); - f.addParam("pr", "i32"); - f.addLocal("ita", "i32"); - f.addLocal("itb", "i32"); - f.addLocal("itr", "i32"); - f.addLocal("last", "i32"); - - const c = f.getCodeBuilder(); - - f.addCode( - c.setLocal("ita", c.getLocal("pa")), - c.setLocal("itb", c.getLocal("pb")), - c.setLocal("itr", c.getLocal("pr")), - c.setLocal( - "last", - c.i32_add( - c.getLocal("pa"), - c.i32_mul( - c.getLocal("n"), - c.i32_const(n8) - ) - ) - ), - c.block(c.loop( - c.br_if( - 1, - c.i32_eq( - c.getLocal("ita"), - c.getLocal("last") - ) - ), - c.call( - prefixField + "_add", - c.getLocal("ita"), - c.getLocal("itb"), - c.getLocal("itr"), - ), - c.setLocal("ita", c.i32_add(c.getLocal("ita"), c.i32_const(n8))), - c.setLocal("itb", c.i32_add(c.getLocal("itb"), c.i32_const(n8))), - c.setLocal("itr", c.i32_add(c.getLocal("itr"), c.i32_const(n8))), - c.br(0) - )) - ); - } - - buildBuildABC(); - buildJoinABC(); - buildBatchAdd(); - - module.exportFunction(prefix + "_buildABC"); - module.exportFunction(prefix + "_joinABC"); - module.exportFunction(prefix + "_batchAdd"); - - return prefix; - - }; - - /* - Copyright 2019 0KIMS association. - - This file is part of wasmsnark (Web Assembly zkSnark Prover). - - wasmsnark is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - wasmsnark is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with wasmsnark. If not, see . - */ - - var build_applykey = function buildApplyKey(module, fnName, gPrefix, frPrefix, sizeGIn, sizeGOut, sizeF, opGtimesF) { - - const f = module.addFunction(fnName); - f.addParam("pIn", "i32"); - f.addParam("n", "i32"); - f.addParam("pFirst", "i32"); - f.addParam("pInc", "i32"); - f.addParam("pOut", "i32"); - f.addLocal("pOldFree", "i32"); - f.addLocal("i", "i32"); - f.addLocal("pFrom", "i32"); - f.addLocal("pTo", "i32"); - - const c = f.getCodeBuilder(); - - const t = c.i32_const(module.alloc(sizeF)); - - f.addCode( - c.setLocal("pFrom", c.getLocal("pIn")), - c.setLocal("pTo", c.getLocal("pOut")), - ); - - // t = first - f.addCode( - c.call( - frPrefix + "_copy", - c.getLocal("pFirst"), - t - ) - ); - f.addCode( - c.setLocal("i", c.i32_const(0)), - c.block(c.loop( - c.br_if(1, c.i32_eq ( c.getLocal("i"), c.getLocal("n") )), - - c.call( - opGtimesF, - c.getLocal("pFrom"), - t, - c.getLocal("pTo") - ), - c.setLocal("pFrom", c.i32_add(c.getLocal("pFrom"), c.i32_const(sizeGIn))), - c.setLocal("pTo", c.i32_add(c.getLocal("pTo"), c.i32_const(sizeGOut))), - - // t = t* inc - c.call( - frPrefix + "_mul", - t, - c.getLocal("pInc"), - t - ), - c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), - c.br(0) - )) - ); - - module.exportFunction(fnName); - - }; - - const utils$1 = utils$5; - - const buildF1m$1 =build_f1m; - const buildF1$1 =build_f1; - const buildF2m$1 =build_f2m; - const buildF3m$1 =build_f3m; - const buildCurve$1 =build_curve_jacobian_a0; - const buildFFT$1 = build_fft; - const buildPol$1 = build_pol; - const buildQAP$1 = build_qap; - const buildApplyKey$1 = build_applykey; - const { bitLength: bitLength$2, modInv, isOdd: isOdd$1, isNegative: isNegative$2 } = bigint; - - var build_bn128 = function buildBN128(module, _prefix) { - - const prefix = _prefix || "bn128"; - - if (module.modules[prefix]) return prefix; // already builded - - const q = 21888242871839275222246405745257275088696311157297823662689037894645226208583n; - const r = 21888242871839275222246405745257275088548364400416034343698204186575808495617n; - - - const n64 = Math.floor((bitLength$2(q - 1n) - 1)/64) +1; - const n8 = n64*8; - const frsize = n8; - const f1size = n8; - const f2size = f1size * 2; - const ftsize = f1size * 12; - - const pr = module.alloc(utils$1.bigInt2BytesLE( r, frsize )); - - const f1mPrefix = buildF1m$1(module, q, "f1m"); - buildF1$1(module, r, "fr", "frm"); - - const pG1b = module.alloc(utils$1.bigInt2BytesLE( toMontgomery(3n), f1size )); - const g1mPrefix = buildCurve$1(module, "g1m", "f1m", pG1b); - - buildFFT$1(module, "frm", "frm", "frm", "frm_mul"); - - buildPol$1(module, "pol", "frm"); - buildQAP$1(module, "qap", "frm"); - - const f2mPrefix = buildF2m$1(module, "f1m_neg", "f2m", "f1m"); - const pG2b = module.alloc([ - ...utils$1.bigInt2BytesLE( toMontgomery(19485874751759354771024239261021720505790618469301721065564631296452457478373n), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(266929791119991161246907387137283842545076965332900288569378510910307636690n), f1size ) - ]); - const g2mPrefix = buildCurve$1(module, "g2m", "f2m", pG2b); - - - function buildGTimesFr(fnName, opMul) { - const f = module.addFunction(fnName); - f.addParam("pG", "i32"); - f.addParam("pFr", "i32"); - f.addParam("pr", "i32"); - - const c = f.getCodeBuilder(); - - const AUX = c.i32_const(module.alloc(n8)); - - f.addCode( - c.call("frm_fromMontgomery", c.getLocal("pFr"), AUX), - c.call( - opMul, - c.getLocal("pG"), - AUX, - c.i32_const(n8), - c.getLocal("pr") - ) - ); - - module.exportFunction(fnName); - } - buildGTimesFr("g1m_timesFr", "g1m_timesScalar"); - buildFFT$1(module, "g1m", "g1m", "frm", "g1m_timesFr"); - - buildGTimesFr("g2m_timesFr", "g2m_timesScalar"); - buildFFT$1(module, "g2m", "g2m", "frm", "g2m_timesFr"); - - buildGTimesFr("g1m_timesFrAffine", "g1m_timesScalarAffine"); - buildGTimesFr("g2m_timesFrAffine", "g2m_timesScalarAffine"); - - buildApplyKey$1(module, "frm_batchApplyKey", "fmr", "frm", n8, n8, n8, "frm_mul"); - buildApplyKey$1(module, "g1m_batchApplyKey", "g1m", "frm", n8*3, n8*3, n8, "g1m_timesFr"); - buildApplyKey$1(module, "g1m_batchApplyKeyMixed", "g1m", "frm", n8*2, n8*3, n8, "g1m_timesFrAffine"); - buildApplyKey$1(module, "g2m_batchApplyKey", "g2m", "frm", n8*2*3, n8*3*2, n8, "g2m_timesFr"); - buildApplyKey$1(module, "g2m_batchApplyKeyMixed", "g2m", "frm", n8*2*2, n8*3*2, n8, "g2m_timesFrAffine"); - - function toMontgomery(a) { - return BigInt(a) * ( 1n << BigInt(f1size*8)) % q; - } - - const G1gen = [ - 1n, - 2n, - 1n - ]; - - const pG1gen = module.alloc( - [ - ...utils$1.bigInt2BytesLE( toMontgomery(G1gen[0]), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(G1gen[1]), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(G1gen[2]), f1size ), - ] - ); - - const G1zero = [ - 0n, - 1n, - 0n - ]; - - const pG1zero = module.alloc( - [ - ...utils$1.bigInt2BytesLE( toMontgomery(G1zero[0]), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(G1zero[1]), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(G1zero[2]), f1size ) - ] - ); - - const G2gen = [ - [ - 10857046999023057135944570762232829481370756359578518086990519993285655852781n, - 11559732032986387107991004021392285783925812861821192530917403151452391805634n, - ],[ - 8495653923123431417604973247489272438418190587263600148770280649306958101930n, - 4082367875863433681332203403145435568316851327593401208105741076214120093531n, - ],[ - 1n, - 0n, - ] - ]; - - const pG2gen = module.alloc( - [ - ...utils$1.bigInt2BytesLE( toMontgomery(G2gen[0][0]), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(G2gen[0][1]), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(G2gen[1][0]), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(G2gen[1][1]), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(G2gen[2][0]), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(G2gen[2][1]), f1size ), - ] - ); - - const G2zero = [ - [ - 0n, - 0n, - ],[ - 1n, - 0n, - ],[ - 0n, - 0n, - ] - ]; - - const pG2zero = module.alloc( - [ - ...utils$1.bigInt2BytesLE( toMontgomery(G2zero[0][0]), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(G2zero[0][1]), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(G2zero[1][0]), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(G2zero[1][1]), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(G2zero[2][0]), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(G2zero[2][1]), f1size ), - ] - ); - - const pOneT = module.alloc([ - ...utils$1.bigInt2BytesLE( toMontgomery(1), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(0), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(0), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(0), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(0), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(0), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(0), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(0), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(0), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(0), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(0), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(0), f1size ), - ]); - - const pNonResidueF6 = module.alloc([ - ...utils$1.bigInt2BytesLE( toMontgomery(9), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(1), f1size ), - ]); - - const pTwoInv = module.alloc([ - ...utils$1.bigInt2BytesLE( toMontgomery( modInv(2n, q)), f1size ), - ...utils$1.bigInt2BytesLE( 0n, f1size ) - ]); - - const pAltBn128Twist = pNonResidueF6; - - const pTwistCoefB = module.alloc([ - ...utils$1.bigInt2BytesLE( toMontgomery(19485874751759354771024239261021720505790618469301721065564631296452457478373n), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery(266929791119991161246907387137283842545076965332900288569378510910307636690n), f1size ), - ]); - - function build_mulNR6() { - const f = module.addFunction(prefix + "_mulNR6"); - f.addParam("x", "i32"); - f.addParam("pr", "i32"); - - const c = f.getCodeBuilder(); - - f.addCode( - c.call( - f2mPrefix + "_mul", - c.i32_const(pNonResidueF6), - c.getLocal("x"), - c.getLocal("pr") - ) - ); - } - build_mulNR6(); - - const f6mPrefix = buildF3m$1(module, prefix+"_mulNR6", "f6m", "f2m"); - - function build_mulNR12() { - const f = module.addFunction(prefix + "_mulNR12"); - f.addParam("x", "i32"); - f.addParam("pr", "i32"); - - const c = f.getCodeBuilder(); - - f.addCode( - c.call( - f2mPrefix + "_mul", - c.i32_const(pNonResidueF6), - c.i32_add(c.getLocal("x"), c.i32_const(n8*4)), - c.getLocal("pr") - ), - c.call( - f2mPrefix + "_copy", - c.getLocal("x"), - c.i32_add(c.getLocal("pr"), c.i32_const(n8*2)), - ), - c.call( - f2mPrefix + "_copy", - c.i32_add(c.getLocal("x"), c.i32_const(n8*2)), - c.i32_add(c.getLocal("pr"), c.i32_const(n8*4)), - ) - ); - } - build_mulNR12(); - - const ftmPrefix = buildF2m$1(module, prefix+"_mulNR12", "ftm", f6mPrefix); - - - const ateLoopCount = 29793968203157093288n; - const ateLoopBitBytes = bits(ateLoopCount); - const pAteLoopBitBytes = module.alloc(ateLoopBitBytes); - - const ateCoefSize = 3 * f2size; - const ateNDblCoefs = ateLoopBitBytes.length-1; - const ateNAddCoefs = ateLoopBitBytes.reduce((acc, b) => acc + ( b!=0 ? 1 : 0) ,0); - const ateNCoefs = ateNAddCoefs + ateNDblCoefs + 1; - const prePSize = 3*2*n8; - const preQSize = 3*n8*2 + ateNCoefs*ateCoefSize; - - - module.modules[prefix] = { - n64: n64, - pG1gen: pG1gen, - pG1zero: pG1zero, - pG1b: pG1b, - pG2gen: pG2gen, - pG2zero: pG2zero, - pG2b: pG2b, - pq: module.modules["f1m"].pq, - pr: pr, - pOneT: pOneT, - prePSize: prePSize, - preQSize: preQSize, - r: r.toString(), - q: q.toString() - }; - - // console.log("PrePSize: " +prePSize); - // console.log("PreQSize: " +preQSize); - - const finalExpZ = 4965661367192848881n; - - function naf(n) { - let E = n; - const res = []; - while (E > 0n) { - if (isOdd$1(E)) { - const z = 2 - Number(E % 4n); - res.push( z ); - E = E - BigInt(z); - } else { - res.push( 0 ); - } - E = E >> 1n; - } - return res; - } - - function bits(n) { - let E = n; - const res = []; - while (E > 0n) { - if (isOdd$1(E)) { - res.push( 1 ); - } else { - res.push( 0 ); - } - E = E >> 1n; - } - return res; - } - - function buildPrepareG1() { - const f = module.addFunction(prefix+ "_prepareG1"); - f.addParam("pP", "i32"); - f.addParam("ppreP", "i32"); - - const c = f.getCodeBuilder(); - - f.addCode( - c.call(g1mPrefix + "_normalize", c.getLocal("pP"), c.getLocal("ppreP")), // TODO Remove if already in affine - ); - } - - function buildPrepAddStep() { - const f = module.addFunction(prefix+ "_prepAddStep"); - f.addParam("pQ", "i32"); - f.addParam("pR", "i32"); - f.addParam("pCoef", "i32"); - - const c = f.getCodeBuilder(); - - const X2 = c.getLocal("pQ"); - const Y2 = c.i32_add(c.getLocal("pQ"), c.i32_const(f2size)); - - const X1 = c.getLocal("pR"); - const Y1 = c.i32_add(c.getLocal("pR"), c.i32_const(f2size)); - const Z1 = c.i32_add(c.getLocal("pR"), c.i32_const(2*f2size)); - - const ELL_0 = c.getLocal("pCoef"); - const ELL_VW = c.i32_add(c.getLocal("pCoef"), c.i32_const(f2size)); - const ELL_VV = c.i32_add(c.getLocal("pCoef"), c.i32_const(2*f2size)); - - const D = ELL_VW; - const E = c.i32_const(module.alloc(f2size)); - const F = c.i32_const(module.alloc(f2size)); - const G = c.i32_const(module.alloc(f2size)); - const H = c.i32_const(module.alloc(f2size)); - const I = c.i32_const(module.alloc(f2size)); - const J = c.i32_const(module.alloc(f2size)); - const AUX = c.i32_const(module.alloc(f2size)); - - f.addCode( - // D = X1 - X2*Z1 - c.call(f2mPrefix + "_mul", X2, Z1, D), - c.call(f2mPrefix + "_sub", X1, D, D), - - // E = Y1 - Y2*Z1 - c.call(f2mPrefix + "_mul", Y2, Z1, E), - c.call(f2mPrefix + "_sub", Y1, E, E), - - // F = D^2 - c.call(f2mPrefix + "_square", D, F), - - // G = E^2 - c.call(f2mPrefix + "_square", E, G), - - // H = D*F - c.call(f2mPrefix + "_mul", D, F, H), - - // I = X1 * F - c.call(f2mPrefix + "_mul", X1, F, I), - - // J = H + Z1*G - (I+I) - c.call(f2mPrefix + "_add", I, I, AUX), - c.call(f2mPrefix + "_mul", Z1, G, J), - c.call(f2mPrefix + "_add", H, J, J), - c.call(f2mPrefix + "_sub", J, AUX, J), - - - // X3 (X1) = D*J - c.call(f2mPrefix + "_mul", D, J, X1), - - // Y3 (Y1) = E*(I-J)-(H*Y1) - c.call(f2mPrefix + "_mul", H, Y1, Y1), - c.call(f2mPrefix + "_sub", I, J, AUX), - c.call(f2mPrefix + "_mul", E, AUX, AUX), - c.call(f2mPrefix + "_sub", AUX, Y1, Y1), - - // Z3 (Z1) = Z1*H - c.call(f2mPrefix + "_mul", Z1, H, Z1), - - // ell_0 = xi * (E * X2 - D * Y2) - c.call(f2mPrefix + "_mul", D, Y2, AUX), - c.call(f2mPrefix + "_mul", E, X2, ELL_0), - c.call(f2mPrefix + "_sub", ELL_0, AUX, ELL_0), - c.call(f2mPrefix + "_mul", ELL_0, c.i32_const(pAltBn128Twist), ELL_0), - - - // ell_VV = - E (later: * xP) - c.call(f2mPrefix + "_neg", E, ELL_VV), - - // ell_VW = D (later: * yP ) - // Already assigned - - ); - } - - - - function buildPrepDoubleStep() { - const f = module.addFunction(prefix+ "_prepDblStep"); - f.addParam("pR", "i32"); - f.addParam("pCoef", "i32"); - - const c = f.getCodeBuilder(); - - const X1 = c.getLocal("pR"); - const Y1 = c.i32_add(c.getLocal("pR"), c.i32_const(f2size)); - const Z1 = c.i32_add(c.getLocal("pR"), c.i32_const(2*f2size)); - - const ELL_0 = c.getLocal("pCoef"); - const ELL_VW = c.i32_add(c.getLocal("pCoef"), c.i32_const(f2size)); - const ELL_VV = c.i32_add(c.getLocal("pCoef"), c.i32_const(2*f2size)); - - const A = c.i32_const(module.alloc(f2size)); - const B = c.i32_const(module.alloc(f2size)); - const C = c.i32_const(module.alloc(f2size)); - const D = c.i32_const(module.alloc(f2size)); - const E = c.i32_const(module.alloc(f2size)); - const F = c.i32_const(module.alloc(f2size)); - const G = c.i32_const(module.alloc(f2size)); - const H = c.i32_const(module.alloc(f2size)); - const I = c.i32_const(module.alloc(f2size)); - const J = c.i32_const(module.alloc(f2size)); - const E2 = c.i32_const(module.alloc(f2size)); - const AUX = c.i32_const(module.alloc(f2size)); - - f.addCode( - - // A = X1 * Y1 / 2 - c.call(f2mPrefix + "_mul", Y1, c.i32_const(pTwoInv), A), - c.call(f2mPrefix + "_mul", X1, A, A), - - // B = Y1^2 - c.call(f2mPrefix + "_square", Y1, B), - - // C = Z1^2 - c.call(f2mPrefix + "_square", Z1, C), - - // D = 3 * C - c.call(f2mPrefix + "_add", C, C, D), - c.call(f2mPrefix + "_add", D, C, D), - - // E = twist_b * D - c.call(f2mPrefix + "_mul", c.i32_const(pTwistCoefB), D, E), - - // F = 3 * E - c.call(f2mPrefix + "_add", E, E, F), - c.call(f2mPrefix + "_add", E, F, F), - - // G = (B+F)/2 - c.call(f2mPrefix + "_add", B, F, G), - c.call(f2mPrefix + "_mul", G, c.i32_const(pTwoInv), G), - - // H = (Y1+Z1)^2-(B+C) - c.call(f2mPrefix + "_add", B, C, AUX), - c.call(f2mPrefix + "_add", Y1, Z1, H), - c.call(f2mPrefix + "_square", H, H), - c.call(f2mPrefix + "_sub", H, AUX, H), - - // I = E-B - c.call(f2mPrefix + "_sub", E, B, I), - - // J = X1^2 - c.call(f2mPrefix + "_square", X1, J), - - // E_squared = E^2 - c.call(f2mPrefix + "_square", E, E2), - - // X3 (X1) = A * (B-F) - c.call(f2mPrefix + "_sub", B, F, AUX), - c.call(f2mPrefix + "_mul", A, AUX, X1), - - // Y3 (Y1) = G^2 - 3*E^2 - c.call(f2mPrefix + "_add", E2, E2, AUX), - c.call(f2mPrefix + "_add", E2, AUX, AUX), - c.call(f2mPrefix + "_square", G, Y1), - c.call(f2mPrefix + "_sub", Y1, AUX, Y1), - - // Z3 (Z1) = B * H - c.call(f2mPrefix + "_mul", B, H, Z1), - - // ell_0 = xi * I - c.call(f2mPrefix + "_mul", c.i32_const(pAltBn128Twist), I, ELL_0), - - // ell_VW = - H (later: * yP) - c.call(f2mPrefix + "_neg", H, ELL_VW), - - // ell_VV = 3*J (later: * xP) - c.call(f2mPrefix + "_add", J, J, ELL_VV), - c.call(f2mPrefix + "_add", J, ELL_VV, ELL_VV), - - ); - } - - function buildMulByQ() { - const f = module.addFunction(prefix + "_mulByQ"); - f.addParam("p1", "i32"); - f.addParam("pr", "i32"); - - const c = f.getCodeBuilder(); - - const x = c.getLocal("p1"); - const y = c.i32_add(c.getLocal("p1"), c.i32_const(f2size)); - const z = c.i32_add(c.getLocal("p1"), c.i32_const(f2size*2)); - const x3 = c.getLocal("pr"); - const y3 = c.i32_add(c.getLocal("pr"), c.i32_const(f2size)); - const z3 = c.i32_add(c.getLocal("pr"), c.i32_const(f2size*2)); - - const MulByQX = c.i32_const(module.alloc([ - ...utils$1.bigInt2BytesLE( toMontgomery("21575463638280843010398324269430826099269044274347216827212613867836435027261"), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery("10307601595873709700152284273816112264069230130616436755625194854815875713954"), f1size ), - ])); - - const MulByQY = c.i32_const(module.alloc([ - ...utils$1.bigInt2BytesLE( toMontgomery("2821565182194536844548159561693502659359617185244120367078079554186484126554"), f1size ), - ...utils$1.bigInt2BytesLE( toMontgomery("3505843767911556378687030309984248845540243509899259641013678093033130930403"), f1size ), - ])); - - f.addCode( - // The frobeniusMap(1) in this field, is the conjugate - c.call(f2mPrefix + "_conjugate", x, x3), - c.call(f2mPrefix + "_mul", MulByQX, x3, x3), - c.call(f2mPrefix + "_conjugate", y, y3), - c.call(f2mPrefix + "_mul", MulByQY, y3, y3), - c.call(f2mPrefix + "_conjugate", z, z3), - ); - } - - - function buildPrepareG2() { - buildMulByQ(); - const f = module.addFunction(prefix+ "_prepareG2"); - f.addParam("pQ", "i32"); - f.addParam("ppreQ", "i32"); - f.addLocal("pCoef", "i32"); - f.addLocal("i", "i32"); - - const c = f.getCodeBuilder(); - - const QX = c.getLocal("pQ"); - - const pR = module.alloc(f2size*3); - const R = c.i32_const(pR); - const RX = c.i32_const(pR); - const RY = c.i32_const(pR+f2size); - const RZ = c.i32_const(pR+2*f2size); - - const cQX = c.i32_add( c.getLocal("ppreQ"), c.i32_const(0)); - const cQY = c.i32_add( c.getLocal("ppreQ"), c.i32_const(f2size)); - - const pQ1 = module.alloc(f2size*3); - const Q1 = c.i32_const(pQ1); - - const pQ2 = module.alloc(f2size*3); - const Q2 = c.i32_const(pQ2); - const Q2Y = c.i32_const(pQ2 + f2size); - - f.addCode( - c.call(g2mPrefix + "_normalize", QX, cQX), // TODO Remove if already in affine - c.call(f2mPrefix + "_copy", cQX, RX), - c.call(f2mPrefix + "_copy", cQY, RY), - c.call(f2mPrefix + "_one", RZ), - ); - - f.addCode( - c.setLocal("pCoef", c.i32_add( c.getLocal("ppreQ"), c.i32_const(f2size*3))), - c.setLocal("i", c.i32_const(ateLoopBitBytes.length-2)), - c.block(c.loop( - - c.call(prefix + "_prepDblStep", R, c.getLocal("pCoef")), - c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), - - c.if( - c.i32_load8_s(c.getLocal("i"), pAteLoopBitBytes), - [ - ...c.call(prefix + "_prepAddStep", cQX, R, c.getLocal("pCoef")), - ...c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), - ] - ), - c.br_if(1, c.i32_eqz ( c.getLocal("i") )), - c.setLocal("i", c.i32_sub(c.getLocal("i"), c.i32_const(1))), - c.br(0) - )) - ); - - f.addCode( - c.call(prefix + "_mulByQ", cQX, Q1), - c.call(prefix + "_mulByQ", Q1, Q2) - ); - - f.addCode( - c.call(f2mPrefix + "_neg", Q2Y, Q2Y), - - c.call(prefix + "_prepAddStep", Q1, R, c.getLocal("pCoef")), - c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), - - c.call(prefix + "_prepAddStep", Q2, R, c.getLocal("pCoef")), - c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), - ); - } - - function buildMulBy024Old() { - const f = module.addFunction(prefix+ "__mulBy024Old"); - f.addParam("pEll0", "i32"); - f.addParam("pEllVW", "i32"); - f.addParam("pEllVV", "i32"); - f.addParam("pR", "i32"); // Result in F12 - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("pEll0"); - const x2 = c.getLocal("pEllVV"); - const x4 = c.getLocal("pEllVW"); - - const z0 = c.getLocal("pR"); - - const pAUX12 = module.alloc(ftsize); - const AUX12 = c.i32_const(pAUX12); - const AUX12_0 = c.i32_const(pAUX12); - const AUX12_2 = c.i32_const(pAUX12+f2size); - const AUX12_4 = c.i32_const(pAUX12+f2size*2); - const AUX12_6 = c.i32_const(pAUX12+f2size*3); - const AUX12_8 = c.i32_const(pAUX12+f2size*4); - const AUX12_10 = c.i32_const(pAUX12+f2size*5); - - f.addCode( - - c.call(f2mPrefix + "_copy", x0, AUX12_0), - c.call(f2mPrefix + "_zero", AUX12_2), - c.call(f2mPrefix + "_copy", x2, AUX12_4), - c.call(f2mPrefix + "_zero", AUX12_6), - c.call(f2mPrefix + "_copy", x4, AUX12_8), - c.call(f2mPrefix + "_zero", AUX12_10), - c.call(ftmPrefix + "_mul", AUX12, z0, z0), - ); - } - - function buildMulBy024() { - const f = module.addFunction(prefix+ "__mulBy024"); - f.addParam("pEll0", "i32"); - f.addParam("pEllVW", "i32"); - f.addParam("pEllVV", "i32"); - f.addParam("pR", "i32"); // Result in F12 - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("pEll0"); - const x2 = c.getLocal("pEllVV"); - const x4 = c.getLocal("pEllVW"); - - const z0 = c.getLocal("pR"); - const z1 = c.i32_add(c.getLocal("pR"), c.i32_const(2*n8)); - const z2 = c.i32_add(c.getLocal("pR"), c.i32_const(4*n8)); - const z3 = c.i32_add(c.getLocal("pR"), c.i32_const(6*n8)); - const z4 = c.i32_add(c.getLocal("pR"), c.i32_const(8*n8)); - const z5 = c.i32_add(c.getLocal("pR"), c.i32_const(10*n8)); - - const t0 = c.i32_const(module.alloc(f2size)); - const t1 = c.i32_const(module.alloc(f2size)); - const t2 = c.i32_const(module.alloc(f2size)); - const s0 = c.i32_const(module.alloc(f2size)); - const T3 = c.i32_const(module.alloc(f2size)); - const T4 = c.i32_const(module.alloc(f2size)); - const D0 = c.i32_const(module.alloc(f2size)); - const D2 = c.i32_const(module.alloc(f2size)); - const D4 = c.i32_const(module.alloc(f2size)); - const S1 = c.i32_const(module.alloc(f2size)); - const AUX = c.i32_const(module.alloc(f2size)); - - f.addCode( - - // D0 = z0 * x0; - c.call(f2mPrefix + "_mul", z0, x0, D0), - // D2 = z2 * x2; - c.call(f2mPrefix + "_mul", z2, x2, D2), - // D4 = z4 * x4; - c.call(f2mPrefix + "_mul", z4, x4, D4), - // t2 = z0 + z4; - c.call(f2mPrefix + "_add", z0, z4, t2), - // t1 = z0 + z2; - c.call(f2mPrefix + "_add", z0, z2, t1), - // s0 = z1 + z3 + z5; - c.call(f2mPrefix + "_add", z1, z3, s0), - c.call(f2mPrefix + "_add", s0, z5, s0), - - - // For z.a_.a_ = z0. - // S1 = z1 * x2; - c.call(f2mPrefix + "_mul", z1, x2, S1), - // T3 = S1 + D4; - c.call(f2mPrefix + "_add", S1, D4, T3), - // T4 = my_Fp6::non_residue * T3 + D0; - c.call(f2mPrefix + "_mul", c.i32_const(pNonResidueF6), T3, T4), - c.call(f2mPrefix + "_add", T4, D0, z0), - // z0 = T4; - - // For z.a_.b_ = z1 - // T3 = z5 * x4; - c.call(f2mPrefix + "_mul", z5, x4, T3), - // S1 = S1 + T3; - c.call(f2mPrefix + "_add", S1, T3, S1), - // T3 = T3 + D2; - c.call(f2mPrefix + "_add", T3, D2, T3), - // T4 = my_Fp6::non_residue * T3; - c.call(f2mPrefix + "_mul", c.i32_const(pNonResidueF6), T3, T4), - // T3 = z1 * x0; - c.call(f2mPrefix + "_mul", z1, x0, T3), - // S1 = S1 + T3; - c.call(f2mPrefix + "_add", S1, T3, S1), - // T4 = T4 + T3; - c.call(f2mPrefix + "_add", T4, T3, z1), - // z1 = T4; - - - - // For z.a_.c_ = z2 - // t0 = x0 + x2; - c.call(f2mPrefix + "_add", x0, x2, t0), - // T3 = t1 * t0 - D0 - D2; - c.call(f2mPrefix + "_mul", t1, t0, T3), - c.call(f2mPrefix + "_add", D0, D2, AUX), - c.call(f2mPrefix + "_sub", T3, AUX, T3), - // T4 = z3 * x4; - c.call(f2mPrefix + "_mul", z3, x4, T4), - // S1 = S1 + T4; - c.call(f2mPrefix + "_add", S1, T4, S1), - - - // For z.b_.a_ = z3 (z3 needs z2) - // t0 = z2 + z4; - c.call(f2mPrefix + "_add", z2, z4, t0), - // T3 = T3 + T4; - // z2 = T3; - c.call(f2mPrefix + "_add", T3, T4, z2), - // t1 = x2 + x4; - c.call(f2mPrefix + "_add", x2, x4, t1), - // T3 = t0 * t1 - D2 - D4; - c.call(f2mPrefix + "_mul", t1, t0, T3), - c.call(f2mPrefix + "_add", D2, D4, AUX), - c.call(f2mPrefix + "_sub", T3, AUX, T3), - // T4 = my_Fp6::non_residue * T3; - c.call(f2mPrefix + "_mul", c.i32_const(pNonResidueF6), T3, T4), - // T3 = z3 * x0; - c.call(f2mPrefix + "_mul", z3, x0, T3), - // S1 = S1 + T3; - c.call(f2mPrefix + "_add", S1, T3, S1), - // T4 = T4 + T3; - c.call(f2mPrefix + "_add", T4, T3, z3), - // z3 = T4; - - // For z.b_.b_ = z4 - // T3 = z5 * x2; - c.call(f2mPrefix + "_mul", z5, x2, T3), - // S1 = S1 + T3; - c.call(f2mPrefix + "_add", S1, T3, S1), - // T4 = my_Fp6::non_residue * T3; - c.call(f2mPrefix + "_mul", c.i32_const(pNonResidueF6), T3, T4), - // t0 = x0 + x4; - c.call(f2mPrefix + "_add", x0, x4, t0), - // T3 = t2 * t0 - D0 - D4; - c.call(f2mPrefix + "_mul", t2, t0, T3), - c.call(f2mPrefix + "_add", D0, D4, AUX), - c.call(f2mPrefix + "_sub", T3, AUX, T3), - // T4 = T4 + T3; - c.call(f2mPrefix + "_add", T4, T3, z4), - // z4 = T4; - - // For z.b_.c_ = z5. - // t0 = x0 + x2 + x4; - c.call(f2mPrefix + "_add", x0, x2, t0), - c.call(f2mPrefix + "_add", t0, x4, t0), - // T3 = s0 * t0 - S1; - c.call(f2mPrefix + "_mul", s0, t0, T3), - c.call(f2mPrefix + "_sub", T3, S1, z5), - // z5 = T3; - - ); - } - - - function buildMillerLoop() { - const f = module.addFunction(prefix+ "_millerLoop"); - f.addParam("ppreP", "i32"); - f.addParam("ppreQ", "i32"); - f.addParam("r", "i32"); - f.addLocal("pCoef", "i32"); - f.addLocal("i", "i32"); - - const c = f.getCodeBuilder(); - - const preP_PX = c.getLocal("ppreP"); - const preP_PY = c.i32_add(c.getLocal("ppreP"), c.i32_const(f1size)); - - const ELL_0 = c.getLocal("pCoef"); - const ELL_VW = c.i32_add(c.getLocal("pCoef"), c.i32_const(f2size)); - const ELL_VV = c.i32_add(c.getLocal("pCoef"), c.i32_const(2*f2size)); - - - const pVW = module.alloc(f2size); - const VW = c.i32_const(pVW); - const pVV = module.alloc(f2size); - const VV = c.i32_const(pVV); - - const F = c.getLocal("r"); - - - f.addCode( - c.call(ftmPrefix + "_one", F), - - c.setLocal("pCoef", c.i32_add( c.getLocal("ppreQ"), c.i32_const(f2size*3))), - - c.setLocal("i", c.i32_const(ateLoopBitBytes.length-2)), - c.block(c.loop( - - - c.call(ftmPrefix + "_square", F, F), - - c.call(f2mPrefix + "_mul1", ELL_VW,preP_PY, VW), - c.call(f2mPrefix + "_mul1", ELL_VV, preP_PX, VV), - c.call(prefix + "__mulBy024", ELL_0, VW, VV, F), - c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), - - c.if( - c.i32_load8_s(c.getLocal("i"), pAteLoopBitBytes), - [ - ...c.call(f2mPrefix + "_mul1", ELL_VW, preP_PY, VW), - ...c.call(f2mPrefix + "_mul1", ELL_VV, preP_PX, VV), - - ...c.call(prefix + "__mulBy024", ELL_0, VW, VV, F), - ...c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), - - ] - ), - c.br_if(1, c.i32_eqz ( c.getLocal("i") )), - c.setLocal("i", c.i32_sub(c.getLocal("i"), c.i32_const(1))), - c.br(0) - )) - - ); - - f.addCode( - c.call(f2mPrefix + "_mul1", ELL_VW, preP_PY, VW), - c.call(f2mPrefix + "_mul1", ELL_VV, preP_PX, VV), - c.call(prefix + "__mulBy024", ELL_0, VW, VV, F), - c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), - - c.call(f2mPrefix + "_mul1", ELL_VW, preP_PY, VW), - c.call(f2mPrefix + "_mul1", ELL_VV, preP_PX, VV), - c.call(prefix + "__mulBy024", ELL_0, VW, VV, F), - c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), - - ); - - } - - - function buildFrobeniusMap(n) { - const F12 = [ - [ - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - ], - [ - [1n, 0n], - [8376118865763821496583973867626364092589906065868298776909617916018768340080n, 16469823323077808223889137241176536799009286646108169935659301613961712198316n], - [21888242871839275220042445260109153167277707414472061641714758635765020556617n, 0n], - [11697423496358154304825782922584725312912383441159505038794027105778954184319n, 303847389135065887422783454877609941456349188919719272345083954437860409601n], - [21888242871839275220042445260109153167277707414472061641714758635765020556616n, 0n], - [3321304630594332808241809054958361220322477375291206261884409189760185844239n, 5722266937896532885780051958958348231143373700109372999374820235121374419868n], - [21888242871839275222246405745257275088696311157297823662689037894645226208582n, 0n], - [13512124006075453725662431877630910996106405091429524885779419978626457868503n, 5418419548761466998357268504080738289687024511189653727029736280683514010267n], - [2203960485148121921418603742825762020974279258880205651966n, 0n], - [10190819375481120917420622822672549775783927716138318623895010788866272024264n, 21584395482704209334823622290379665147239961968378104390343953940207365798982n], - [2203960485148121921418603742825762020974279258880205651967n, 0n], - [18566938241244942414004596690298913868373833782006617400804628704885040364344n, 16165975933942742336466353786298926857552937457188450663314217659523851788715n], - ] - ]; - - const F6 = [ - [ - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - ], - [ - [1n, 0n], - [21575463638280843010398324269430826099269044274347216827212613867836435027261n, 10307601595873709700152284273816112264069230130616436755625194854815875713954n], - [21888242871839275220042445260109153167277707414472061641714758635765020556616n, 0n], - [3772000881919853776433695186713858239009073593817195771773381919316419345261n, 2236595495967245188281701248203181795121068902605861227855261137820944008926n], - [2203960485148121921418603742825762020974279258880205651966n, 0n], - [18429021223477853657660792034369865839114504446431234726392080002137598044644n, 9344045779998320333812420223237981029506012124075525679208581902008406485703n], - ], - [ - [1n, 0n], - [2581911344467009335267311115468803099551665605076196740867805258568234346338n, 19937756971775647987995932169929341994314640652964949448313374472400716661030n], - [2203960485148121921418603742825762020974279258880205651966n, 0n], - [5324479202449903542726783395506214481928257762400643279780343368557297135718n, 16208900380737693084919495127334387981393726419856888799917914180988844123039n], - [21888242871839275220042445260109153167277707414472061641714758635765020556616n, 0n], - [13981852324922362344252311234282257507216387789820983642040889267519694726527n, 7629828391165209371577384193250820201684255241773809077146787135900891633097n], - ] - ]; - - const f = module.addFunction(prefix+ "__frobeniusMap"+n); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - for (let i=0; i<6; i++) { - const X = (i==0) ? c.getLocal("x") : c.i32_add(c.getLocal("x"), c.i32_const(i*f2size)); - const Xc0 = X; - const Xc1 = c.i32_add(c.getLocal("x"), c.i32_const(i*f2size + f1size)); - const R = (i==0) ? c.getLocal("r") : c.i32_add(c.getLocal("r"), c.i32_const(i*f2size)); - const Rc0 = R; - const Rc1 = c.i32_add(c.getLocal("r"), c.i32_const(i*f2size + f1size)); - const coef = mul2(F12[Math.floor(i/3)][n%12] , F6[i%3][n%6]); - const pCoef = module.alloc([ - ...utils$1.bigInt2BytesLE(toMontgomery(coef[0]), 32), - ...utils$1.bigInt2BytesLE(toMontgomery(coef[1]), 32), - ]); - if (n%2 == 1) { - f.addCode( - c.call(f1mPrefix + "_copy", Xc0, Rc0), - c.call(f1mPrefix + "_neg", Xc1, Rc1), - c.call(f2mPrefix + "_mul", R, c.i32_const(pCoef), R), - ); - } else { - f.addCode(c.call(f2mPrefix + "_mul", X, c.i32_const(pCoef), R)); - } - } - - function mul2(a, b) { - const ac0 = BigInt(a[0]); - const ac1 = BigInt(a[1]); - const bc0 = BigInt(b[0]); - const bc1 = BigInt(b[1]); - const res = [ - (ac0 * bc0 - ( ac1 * bc1) ) % q, - (ac0 * bc1 + ( ac1 * bc0) ) % q, - ]; - if (isNegative$2(res[0])) res[0] = res[0] + q; - return res; - } - - } - - - - function buildFinalExponentiationFirstChunk() { - - const f = module.addFunction(prefix+ "__finalExponentiationFirstChunk"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const elt = c.getLocal("x"); - const eltC0 = elt; - const eltC1 = c.i32_add(elt, c.i32_const(n8*6)); - const r = c.getLocal("r"); - const pA = module.alloc(ftsize); - const A = c.i32_const(pA); - const Ac0 = A; - const Ac1 = c.i32_const(pA + n8*6); - const B = c.i32_const(module.alloc(ftsize)); - const C = c.i32_const(module.alloc(ftsize)); - const D = c.i32_const(module.alloc(ftsize)); - - f.addCode( - // const alt_bn128_Fq12 A = alt_bn128_Fq12(elt.c0,-elt.c1); - c.call(f6mPrefix + "_copy", eltC0, Ac0), - c.call(f6mPrefix + "_neg", eltC1, Ac1), - - // const alt_bn128_Fq12 B = elt.inverse(); - c.call(ftmPrefix + "_inverse", elt, B), - - // const alt_bn128_Fq12 C = A * B; - c.call(ftmPrefix + "_mul", A, B, C), - // const alt_bn128_Fq12 D = C.Frobenius_map(2); - c.call(prefix + "__frobeniusMap2", C, D), - // const alt_bn128_Fq12 result = D * C; - c.call(ftmPrefix + "_mul", C, D, r), - ); - } - - function buildCyclotomicSquare() { - const f = module.addFunction(prefix+ "__cyclotomicSquare"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x4 = c.i32_add(c.getLocal("x"), c.i32_const(f2size)); - const x3 = c.i32_add(c.getLocal("x"), c.i32_const(2*f2size)); - const x2 = c.i32_add(c.getLocal("x"), c.i32_const(3*f2size)); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(4*f2size)); - const x5 = c.i32_add(c.getLocal("x"), c.i32_const(5*f2size)); - - const r0 = c.getLocal("r"); - const r4 = c.i32_add(c.getLocal("r"), c.i32_const(f2size)); - const r3 = c.i32_add(c.getLocal("r"), c.i32_const(2*f2size)); - const r2 = c.i32_add(c.getLocal("r"), c.i32_const(3*f2size)); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(4*f2size)); - const r5 = c.i32_add(c.getLocal("r"), c.i32_const(5*f2size)); - - const t0 = c.i32_const(module.alloc(f2size)); - const t1 = c.i32_const(module.alloc(f2size)); - const t2 = c.i32_const(module.alloc(f2size)); - const t3 = c.i32_const(module.alloc(f2size)); - const t4 = c.i32_const(module.alloc(f2size)); - const t5 = c.i32_const(module.alloc(f2size)); - const tmp = c.i32_const(module.alloc(f2size)); - const AUX = c.i32_const(module.alloc(f2size)); - - - f.addCode( - // // t0 + t1*y = (z0 + z1*y)^2 = a^2 - // tmp = z0 * z1; - // t0 = (z0 + z1) * (z0 + my_Fp6::non_residue * z1) - tmp - my_Fp6::non_residue * tmp; - // t1 = tmp + tmp; - c.call(f2mPrefix + "_mul", x0, x1, tmp), - c.call(f2mPrefix + "_mul", x1, c.i32_const(pNonResidueF6), t0), - c.call(f2mPrefix + "_add", x0, t0, t0), - c.call(f2mPrefix + "_add", x0, x1, AUX), - c.call(f2mPrefix + "_mul", AUX, t0, t0), - c.call(f2mPrefix + "_mul", c.i32_const(pNonResidueF6), tmp, AUX), - c.call(f2mPrefix + "_add", tmp, AUX, AUX), - c.call(f2mPrefix + "_sub", t0, AUX, t0), - c.call(f2mPrefix + "_add", tmp, tmp, t1), - - // // t2 + t3*y = (z2 + z3*y)^2 = b^2 - // tmp = z2 * z3; - // t2 = (z2 + z3) * (z2 + my_Fp6::non_residue * z3) - tmp - my_Fp6::non_residue * tmp; - // t3 = tmp + tmp; - c.call(f2mPrefix + "_mul", x2, x3, tmp), - c.call(f2mPrefix + "_mul", x3, c.i32_const(pNonResidueF6), t2), - c.call(f2mPrefix + "_add", x2, t2, t2), - c.call(f2mPrefix + "_add", x2, x3, AUX), - c.call(f2mPrefix + "_mul", AUX, t2, t2), - c.call(f2mPrefix + "_mul", c.i32_const(pNonResidueF6), tmp, AUX), - c.call(f2mPrefix + "_add", tmp, AUX, AUX), - c.call(f2mPrefix + "_sub", t2, AUX, t2), - c.call(f2mPrefix + "_add", tmp, tmp, t3), - - // // t4 + t5*y = (z4 + z5*y)^2 = c^2 - // tmp = z4 * z5; - // t4 = (z4 + z5) * (z4 + my_Fp6::non_residue * z5) - tmp - my_Fp6::non_residue * tmp; - // t5 = tmp + tmp; - c.call(f2mPrefix + "_mul", x4, x5, tmp), - c.call(f2mPrefix + "_mul", x5, c.i32_const(pNonResidueF6), t4), - c.call(f2mPrefix + "_add", x4, t4, t4), - c.call(f2mPrefix + "_add", x4, x5, AUX), - c.call(f2mPrefix + "_mul", AUX, t4, t4), - c.call(f2mPrefix + "_mul", c.i32_const(pNonResidueF6), tmp, AUX), - c.call(f2mPrefix + "_add", tmp, AUX, AUX), - c.call(f2mPrefix + "_sub", t4, AUX, t4), - c.call(f2mPrefix + "_add", tmp, tmp, t5), - - // For A - // z0 = 3 * t0 - 2 * z0 - c.call(f2mPrefix + "_sub", t0, x0, r0), - c.call(f2mPrefix + "_add", r0, r0, r0), - c.call(f2mPrefix + "_add", t0, r0, r0), - // z1 = 3 * t1 + 2 * z1 - c.call(f2mPrefix + "_add", t1, x1, r1), - c.call(f2mPrefix + "_add", r1, r1, r1), - c.call(f2mPrefix + "_add", t1, r1, r1), - - // For B - // z2 = 3 * (xi * t5) + 2 * z2 - c.call(f2mPrefix + "_mul", t5, c.i32_const(pAltBn128Twist), AUX), - c.call(f2mPrefix + "_add", AUX, x2, r2), - c.call(f2mPrefix + "_add", r2, r2, r2), - c.call(f2mPrefix + "_add", AUX, r2, r2), - // z3 = 3 * t4 - 2 * z3 - c.call(f2mPrefix + "_sub", t4, x3, r3), - c.call(f2mPrefix + "_add", r3, r3, r3), - c.call(f2mPrefix + "_add", t4, r3, r3), - - // For C - // z4 = 3 * t2 - 2 * z4 - c.call(f2mPrefix + "_sub", t2, x4, r4), - c.call(f2mPrefix + "_add", r4, r4, r4), - c.call(f2mPrefix + "_add", t2, r4, r4), - // z5 = 3 * t3 + 2 * z5 - c.call(f2mPrefix + "_add", t3, x5, r5), - c.call(f2mPrefix + "_add", r5, r5, r5), - c.call(f2mPrefix + "_add", t3, r5, r5), - - ); - } - - - function buildCyclotomicExp(exponent, fnName) { - const exponentNafBytes = naf(exponent).map( (b) => (b==-1 ? 0xFF: b) ); - const pExponentNafBytes = module.alloc(exponentNafBytes); - - const f = module.addFunction(prefix+ "__cyclotomicExp_"+fnName); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - f.addLocal("bit", "i32"); - f.addLocal("i", "i32"); - - const c = f.getCodeBuilder(); - - const x = c.getLocal("x"); - - const res = c.getLocal("r"); - - const inverse = c.i32_const(module.alloc(ftsize)); - - - f.addCode( - c.call(ftmPrefix + "_conjugate", x, inverse), - c.call(ftmPrefix + "_one", res), - - c.if( - c.teeLocal("bit", c.i32_load8_s(c.i32_const(exponentNafBytes.length-1), pExponentNafBytes)), - c.if( - c.i32_eq( - c.getLocal("bit"), - c.i32_const(1) - ), - c.call(ftmPrefix + "_mul", res, x, res), - c.call(ftmPrefix + "_mul", res, inverse, res), - ) - ), - - c.setLocal("i", c.i32_const(exponentNafBytes.length-2)), - c.block(c.loop( - c.call(prefix + "__cyclotomicSquare", res, res), - c.if( - c.teeLocal("bit", c.i32_load8_s(c.getLocal("i"), pExponentNafBytes)), - c.if( - c.i32_eq( - c.getLocal("bit"), - c.i32_const(1) - ), - c.call(ftmPrefix + "_mul", res, x, res), - c.call(ftmPrefix + "_mul", res, inverse, res), - ) - ), - c.br_if(1, c.i32_eqz ( c.getLocal("i") )), - c.setLocal("i", c.i32_sub(c.getLocal("i"), c.i32_const(1))), - c.br(0) - )) - ); - } - - - - function buildFinalExponentiationLastChunk() { - buildCyclotomicSquare(); - buildCyclotomicExp(finalExpZ, "w0"); - - const f = module.addFunction(prefix+ "__finalExponentiationLastChunk"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const elt = c.getLocal("x"); - const result = c.getLocal("r"); - const A = c.i32_const(module.alloc(ftsize)); - const B = c.i32_const(module.alloc(ftsize)); - const C = c.i32_const(module.alloc(ftsize)); - const D = c.i32_const(module.alloc(ftsize)); - const E = c.i32_const(module.alloc(ftsize)); - const F = c.i32_const(module.alloc(ftsize)); - const G = c.i32_const(module.alloc(ftsize)); - const H = c.i32_const(module.alloc(ftsize)); - const I = c.i32_const(module.alloc(ftsize)); - const J = c.i32_const(module.alloc(ftsize)); - const K = c.i32_const(module.alloc(ftsize)); - const L = c.i32_const(module.alloc(ftsize)); - const M = c.i32_const(module.alloc(ftsize)); - const N = c.i32_const(module.alloc(ftsize)); - const O = c.i32_const(module.alloc(ftsize)); - const P = c.i32_const(module.alloc(ftsize)); - const Q = c.i32_const(module.alloc(ftsize)); - const R = c.i32_const(module.alloc(ftsize)); - const S = c.i32_const(module.alloc(ftsize)); - const T = c.i32_const(module.alloc(ftsize)); - const U = c.i32_const(module.alloc(ftsize)); - - f.addCode( - - - // A = exp_by_neg_z(elt) // = elt^(-z) - c.call(prefix + "__cyclotomicExp_w0", elt, A), - c.call(ftmPrefix + "_conjugate", A, A), - // B = A^2 // = elt^(-2*z) - c.call(prefix + "__cyclotomicSquare", A, B), - // C = B^2 // = elt^(-4*z) - c.call(prefix + "__cyclotomicSquare", B, C), - // D = C * B // = elt^(-6*z) - c.call(ftmPrefix + "_mul", C, B, D), - // E = exp_by_neg_z(D) // = elt^(6*z^2) - c.call(prefix + "__cyclotomicExp_w0", D, E), - c.call(ftmPrefix + "_conjugate", E, E), - // F = E^2 // = elt^(12*z^2) - c.call(prefix + "__cyclotomicSquare", E, F), - // G = epx_by_neg_z(F) // = elt^(-12*z^3) - c.call(prefix + "__cyclotomicExp_w0", F, G), - c.call(ftmPrefix + "_conjugate", G, G), - // H = conj(D) // = elt^(6*z) - c.call(ftmPrefix + "_conjugate", D, H), - // I = conj(G) // = elt^(12*z^3) - c.call(ftmPrefix + "_conjugate", G, I), - // J = I * E // = elt^(12*z^3 + 6*z^2) - c.call(ftmPrefix + "_mul", I, E, J), - // K = J * H // = elt^(12*z^3 + 6*z^2 + 6*z) - c.call(ftmPrefix + "_mul", J, H, K), - // L = K * B // = elt^(12*z^3 + 6*z^2 + 4*z) - c.call(ftmPrefix + "_mul", K, B, L), - // M = K * E // = elt^(12*z^3 + 12*z^2 + 6*z) - c.call(ftmPrefix + "_mul", K, E, M), - - // N = M * elt // = elt^(12*z^3 + 12*z^2 + 6*z + 1) - c.call(ftmPrefix + "_mul", M, elt, N), - - // O = L.Frobenius_map(1) // = elt^(q*(12*z^3 + 6*z^2 + 4*z)) - c.call(prefix + "__frobeniusMap1", L, O), - // P = O * N // = elt^(q*(12*z^3 + 6*z^2 + 4*z) * (12*z^3 + 12*z^2 + 6*z + 1)) - c.call(ftmPrefix + "_mul", O, N, P), - // Q = K.Frobenius_map(2) // = elt^(q^2 * (12*z^3 + 6*z^2 + 6*z)) - c.call(prefix + "__frobeniusMap2", K, Q), - // R = Q * P // = elt^(q^2 * (12*z^3 + 6*z^2 + 6*z) + q*(12*z^3 + 6*z^2 + 4*z) * (12*z^3 + 12*z^2 + 6*z + 1)) - c.call(ftmPrefix + "_mul", Q, P, R), - // S = conj(elt) // = elt^(-1) - c.call(ftmPrefix + "_conjugate", elt, S), - // T = S * L // = elt^(12*z^3 + 6*z^2 + 4*z - 1) - c.call(ftmPrefix + "_mul", S, L, T), - // U = T.Frobenius_map(3) // = elt^(q^3(12*z^3 + 6*z^2 + 4*z - 1)) - c.call(prefix + "__frobeniusMap3", T, U), - // V = U * R // = elt^(q^3(12*z^3 + 6*z^2 + 4*z - 1) + q^2 * (12*z^3 + 6*z^2 + 6*z) + q*(12*z^3 + 6*z^2 + 4*z) * (12*z^3 + 12*z^2 + 6*z + 1)) - c.call(ftmPrefix + "_mul", U, R, result), - // result = V - ); - } - - - function buildFinalExponentiation() { - buildFinalExponentiationFirstChunk(); - buildFinalExponentiationLastChunk(); - const f = module.addFunction(prefix+ "_finalExponentiation"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const elt = c.getLocal("x"); - const result = c.getLocal("r"); - const eltToFirstChunk = c.i32_const(module.alloc(ftsize)); - - f.addCode( - c.call(prefix + "__finalExponentiationFirstChunk", elt, eltToFirstChunk ), - c.call(prefix + "__finalExponentiationLastChunk", eltToFirstChunk, result ) - ); - } - - - function buildFinalExponentiationOld() { - const f = module.addFunction(prefix+ "_finalExponentiationOld"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const exponent = 552484233613224096312617126783173147097382103762957654188882734314196910839907541213974502761540629817009608548654680343627701153829446747810907373256841551006201639677726139946029199968412598804882391702273019083653272047566316584365559776493027495458238373902875937659943504873220554161550525926302303331747463515644711876653177129578303191095900909191624817826566688241804408081892785725967931714097716709526092261278071952560171111444072049229123565057483750161460024353346284167282452756217662335528813519139808291170539072125381230815729071544861602750936964829313608137325426383735122175229541155376346436093930287402089517426973178917569713384748081827255472576937471496195752727188261435633271238710131736096299798168852925540549342330775279877006784354801422249722573783561685179618816480037695005515426162362431072245638324744480n; - - const pExponent = module.alloc(utils$1.bigInt2BytesLE( exponent, 352 )); - - const c = f.getCodeBuilder(); - - f.addCode( - c.call(ftmPrefix + "_exp", c.getLocal("x"), c.i32_const(pExponent), c.i32_const(352), c.getLocal("r")), - ); - } - - - - - const pPreP = module.alloc(prePSize); - const pPreQ = module.alloc(preQSize); - - function buildPairingEquation(nPairings) { - - const f = module.addFunction(prefix+ "_pairingEq"+nPairings); - for (let i=0; i acc + ( b!=0 ? 1 : 0) ,0); - const ateNCoefs = ateNAddCoefs + ateNDblCoefs + 1; - const prePSize = 3*2*n8q; - const preQSize = 3*n8q*2 + ateNCoefs*ateCoefSize; - const finalExpIsNegative = true; - - const finalExpZ = 15132376222941642752n; - - - module.modules[prefix] = { - n64q: n64q, - n64r: n64r, - n8q: n8q, - n8r: n8r, - pG1gen: pG1gen, - pG1zero: pG1zero, - pG1b: pG1b, - pG2gen: pG2gen, - pG2zero: pG2zero, - pG2b: pG2b, - pq: module.modules["f1m"].pq, - pr: pr, - pOneT: pOneT, - r: r, - q: q, - prePSize: prePSize, - preQSize: preQSize - }; - - - function naf(n) { - let E = n; - const res = []; - while (E > 0n) { - if (isOdd(E)) { - const z = 2 - Number(E % 4n); - res.push( z ); - E = E - BigInt(z); - } else { - res.push( 0 ); - } - E = E >> 1n; - } - return res; - } - - function bits(n) { - let E = n; - const res = []; - while (E > 0n) { - if (isOdd(E)) { - res.push( 1 ); - } else { - res.push( 0 ); - } - E = E >> 1n; - } - return res; - } - - function buildPrepareG1() { - const f = module.addFunction(prefix+ "_prepareG1"); - f.addParam("pP", "i32"); - f.addParam("ppreP", "i32"); - - const c = f.getCodeBuilder(); - - f.addCode( - c.call(g1mPrefix + "_normalize", c.getLocal("pP"), c.getLocal("ppreP")), // TODO Remove if already in affine - ); - } - - - - function buildPrepDoubleStep() { - const f = module.addFunction(prefix+ "_prepDblStep"); - f.addParam("R", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const Rx = c.getLocal("R"); - const Ry = c.i32_add(c.getLocal("R"), c.i32_const(2*n8q)); - const Rz = c.i32_add(c.getLocal("R"), c.i32_const(4*n8q)); - - const t0 = c.getLocal("r"); - const t3 = c.i32_add(c.getLocal("r"), c.i32_const(2*n8q)); - const t6 = c.i32_add(c.getLocal("r"), c.i32_const(4*n8q)); - - - const zsquared = c.i32_const(module.alloc(f2size)); - const t1 = c.i32_const(module.alloc(f2size)); - const t2 = c.i32_const(module.alloc(f2size)); - const t4 = c.i32_const(module.alloc(f2size)); - const t5 = c.i32_const(module.alloc(f2size)); - - f.addCode( - - // tmp0 = r.x.square(); - c.call(f2mPrefix + "_square", Rx, t0), - - // tmp1 = r.y.square(); - c.call(f2mPrefix + "_square", Ry, t1), - - // tmp2 = tmp1.square(); - c.call(f2mPrefix + "_square", t1, t2), - - // tmp3 = (tmp1 + r.x).square() - tmp0 - tmp2; - c.call(f2mPrefix + "_add", t1, Rx, t3), - c.call(f2mPrefix + "_square", t3, t3), - c.call(f2mPrefix + "_sub", t3, t0, t3), - c.call(f2mPrefix + "_sub", t3, t2, t3), - - // tmp3 = tmp3 + tmp3; - c.call(f2mPrefix + "_add", t3, t3, t3), - - // tmp4 = tmp0 + tmp0 + tmp0; - c.call(f2mPrefix + "_add", t0, t0, t4), - c.call(f2mPrefix + "_add", t4, t0, t4), - - // tmp6 = r.x + tmp4; - c.call(f2mPrefix + "_add", Rx, t4, t6), - - // tmp5 = tmp4.square(); - c.call(f2mPrefix + "_square", t4, t5), - - // zsquared = r.z.square(); - c.call(f2mPrefix + "_square", Rz, zsquared), - - // r.x = tmp5 - tmp3 - tmp3; - c.call(f2mPrefix + "_sub", t5, t3, Rx), - c.call(f2mPrefix + "_sub", Rx, t3, Rx), - - // r.z = (r.z + r.y).square() - tmp1 - zsquared; - c.call(f2mPrefix + "_add", Rz, Ry, Rz), - c.call(f2mPrefix + "_square", Rz, Rz), - c.call(f2mPrefix + "_sub", Rz, t1, Rz), - c.call(f2mPrefix + "_sub", Rz, zsquared, Rz), - - // r.y = (tmp3 - r.x) * tmp4; - c.call(f2mPrefix + "_sub", t3, Rx, Ry), - c.call(f2mPrefix + "_mul", Ry, t4, Ry), - - // tmp2 = tmp2 + tmp2; - c.call(f2mPrefix + "_add", t2, t2, t2), - - // tmp2 = tmp2 + tmp2; - c.call(f2mPrefix + "_add", t2, t2, t2), - - // tmp2 = tmp2 + tmp2; - c.call(f2mPrefix + "_add", t2, t2, t2), - - // r.y -= tmp2; - c.call(f2mPrefix + "_sub", Ry, t2, Ry), - - // tmp3 = tmp4 * zsquared; - c.call(f2mPrefix + "_mul", t4, zsquared, t3), - - // tmp3 = tmp3 + tmp3; - c.call(f2mPrefix + "_add", t3, t3, t3), - - // tmp3 = -tmp3; - c.call(f2mPrefix + "_neg", t3, t3), - - // tmp6 = tmp6.square() - tmp0 - tmp5; - c.call(f2mPrefix + "_square", t6, t6), - c.call(f2mPrefix + "_sub", t6, t0, t6), - c.call(f2mPrefix + "_sub", t6, t5, t6), - - // tmp1 = tmp1 + tmp1; - c.call(f2mPrefix + "_add", t1, t1, t1), - - // tmp1 = tmp1 + tmp1; - c.call(f2mPrefix + "_add", t1, t1, t1), - - // tmp6 = tmp6 - tmp1; - c.call(f2mPrefix + "_sub", t6, t1, t6), - - // tmp0 = r.z * zsquared; - c.call(f2mPrefix + "_mul", Rz, zsquared, t0), - - // tmp0 = tmp0 + tmp0; - c.call(f2mPrefix + "_add", t0, t0, t0), - - ); - } - - function buildPrepAddStep() { - const f = module.addFunction(prefix+ "_prepAddStep"); - f.addParam("R", "i32"); - f.addParam("Q", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const Rx = c.getLocal("R"); - const Ry = c.i32_add(c.getLocal("R"), c.i32_const(2*n8q)); - const Rz = c.i32_add(c.getLocal("R"), c.i32_const(4*n8q)); - - const Qx = c.getLocal("Q"); - const Qy = c.i32_add(c.getLocal("Q"), c.i32_const(2*n8q)); - - const t10 = c.getLocal("r"); - const t1 = c.i32_add(c.getLocal("r"), c.i32_const(2*n8q)); - const t9 = c.i32_add(c.getLocal("r"), c.i32_const(4*n8q)); - - const zsquared = c.i32_const(module.alloc(f2size)); - const ysquared = c.i32_const(module.alloc(f2size)); - const ztsquared = c.i32_const(module.alloc(f2size)); - const t0 = c.i32_const(module.alloc(f2size)); - const t2 = c.i32_const(module.alloc(f2size)); - const t3 = c.i32_const(module.alloc(f2size)); - const t4 = c.i32_const(module.alloc(f2size)); - const t5 = c.i32_const(module.alloc(f2size)); - const t6 = c.i32_const(module.alloc(f2size)); - const t7 = c.i32_const(module.alloc(f2size)); - const t8 = c.i32_const(module.alloc(f2size)); - - f.addCode( - - // zsquared = r.z.square(); - c.call(f2mPrefix + "_square", Rz, zsquared), - - // ysquared = q.y.square(); - c.call(f2mPrefix + "_square", Qy, ysquared), - - // t0 = zsquared * q.x; - c.call(f2mPrefix + "_mul", zsquared, Qx, t0), - - // t1 = ((q.y + r.z).square() - ysquared - zsquared) * zsquared; - c.call(f2mPrefix + "_add", Qy, Rz, t1), - c.call(f2mPrefix + "_square", t1, t1), - c.call(f2mPrefix + "_sub", t1, ysquared, t1), - c.call(f2mPrefix + "_sub", t1, zsquared, t1), - c.call(f2mPrefix + "_mul", t1, zsquared, t1), - - // t2 = t0 - r.x; - c.call(f2mPrefix + "_sub", t0, Rx, t2), - - // t3 = t2.square(); - c.call(f2mPrefix + "_square", t2, t3), - - // t4 = t3 + t3; - c.call(f2mPrefix + "_add", t3, t3, t4), - - // t4 = t4 + t4; - c.call(f2mPrefix + "_add", t4, t4, t4), - - // t5 = t4 * t2; - c.call(f2mPrefix + "_mul", t4, t2, t5), - - // t6 = t1 - r.y - r.y; - c.call(f2mPrefix + "_sub", t1, Ry, t6), - c.call(f2mPrefix + "_sub", t6, Ry, t6), - - // t9 = t6 * q.x; - c.call(f2mPrefix + "_mul", t6, Qx, t9), - - // t7 = t4 * r.x; - c.call(f2mPrefix + "_mul", t4, Rx, t7), - - // r.x = t6.square() - t5 - t7 - t7; - c.call(f2mPrefix + "_square", t6, Rx), - c.call(f2mPrefix + "_sub", Rx, t5, Rx), - c.call(f2mPrefix + "_sub", Rx, t7, Rx), - c.call(f2mPrefix + "_sub", Rx, t7, Rx), - - // r.z = (r.z + t2).square() - zsquared - t3; - c.call(f2mPrefix + "_add", Rz, t2, Rz), - c.call(f2mPrefix + "_square", Rz, Rz), - c.call(f2mPrefix + "_sub", Rz, zsquared, Rz), - c.call(f2mPrefix + "_sub", Rz, t3, Rz), - - // t10 = q.y + r.z; - c.call(f2mPrefix + "_add", Qy, Rz, t10), - - // t8 = (t7 - r.x) * t6; - c.call(f2mPrefix + "_sub", t7, Rx, t8), - c.call(f2mPrefix + "_mul", t8, t6, t8), - - // t0 = r.y * t5; - c.call(f2mPrefix + "_mul", Ry, t5, t0), - - // t0 = t0 + t0; - c.call(f2mPrefix + "_add", t0, t0, t0), - - // r.y = t8 - t0; - c.call(f2mPrefix + "_sub", t8, t0, Ry), - - // t10 = t10.square() - ysquared; - c.call(f2mPrefix + "_square", t10, t10), - c.call(f2mPrefix + "_sub", t10, ysquared, t10), - - // ztsquared = r.z.square(); - c.call(f2mPrefix + "_square", Rz, ztsquared), - - // t10 = t10 - ztsquared; - c.call(f2mPrefix + "_sub", t10, ztsquared, t10), - - // t9 = t9 + t9 - t10; - c.call(f2mPrefix + "_add", t9, t9, t9), - c.call(f2mPrefix + "_sub", t9, t10, t9), - - // t10 = r.z + r.z; - c.call(f2mPrefix + "_add", Rz, Rz, t10), - - // t6 = -t6; - c.call(f2mPrefix + "_neg", t6, t6), - - // t1 = t6 + t6; - c.call(f2mPrefix + "_add", t6, t6, t1), - ); - } - - - function buildPrepareG2() { - const f = module.addFunction(prefix+ "_prepareG2"); - f.addParam("pQ", "i32"); - f.addParam("ppreQ", "i32"); - f.addLocal("pCoef", "i32"); - f.addLocal("i", "i32"); - - const c = f.getCodeBuilder(); - - - const Q = c.getLocal("pQ"); - - const pR = module.alloc(f2size*3); - const R = c.i32_const(pR); - - const base = c.getLocal("ppreQ"); - - f.addCode( - c.call(g2mPrefix + "_normalize", Q, base), - c.if( - c.call(g2mPrefix + "_isZero", base), - c.ret([]) - ), - c.call(g2mPrefix + "_copy", base, R), - c.setLocal("pCoef", c.i32_add(c.getLocal("ppreQ"), c.i32_const(f2size*3))), - ); - - f.addCode( - c.setLocal("i", c.i32_const(ateLoopBitBytes.length-2)), - c.block(c.loop( - - c.call(prefix + "_prepDblStep", R, c.getLocal("pCoef")), - c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), - - c.if( - c.i32_load8_s(c.getLocal("i"), pAteLoopBitBytes), - [ - ...c.call(prefix + "_prepAddStep", R, base, c.getLocal("pCoef")), - ...c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), - ] - ), - c.br_if(1, c.i32_eqz ( c.getLocal("i") )), - c.setLocal("i", c.i32_sub(c.getLocal("i"), c.i32_const(1))), - c.br(0) - )) - ); - } - - - function buildF6Mul1() { - const f = module.addFunction(f6mPrefix+ "_mul1"); - f.addParam("pA", "i32"); // F6 - f.addParam("pC1", "i32"); // F2 - f.addParam("pR", "i32"); // F6 - - const c = f.getCodeBuilder(); - - const A_c0 = c.getLocal("pA"); - const A_c1 = c.i32_add(c.getLocal("pA"), c.i32_const(f1size*2)); - const A_c2 = c.i32_add(c.getLocal("pA"), c.i32_const(f1size*4)); - - const c1 = c.getLocal("pC1"); - - const t1 = c.getLocal("pR"); - const t2 = c.i32_add(c.getLocal("pR"), c.i32_const(f1size*2)); - const b_b = c.i32_add(c.getLocal("pR"), c.i32_const(f1size*4)); - - const Ac0_Ac1 = c.i32_const(module.alloc(f1size*2)); - const Ac1_Ac2 = c.i32_const(module.alloc(f1size*2)); - - f.addCode( - - c.call(f2mPrefix + "_add", A_c0, A_c1, Ac0_Ac1), - c.call(f2mPrefix + "_add", A_c1, A_c2, Ac1_Ac2), - - // let b_b = self.c1 * c1; - c.call(f2mPrefix + "_mul", A_c1, c1, b_b), - - // let t1 = (self.c1 + self.c2) * c1 - b_b; - c.call(f2mPrefix + "_mul", Ac1_Ac2, c1, t1), - c.call(f2mPrefix + "_sub", t1, b_b, t1), - - // let t1 = t1.mul_by_nonresidue(); - c.call(f2mPrefix + "_mulNR", t1, t1), - - // let t2 = (self.c0 + self.c1) * c1 - b_b; - c.call(f2mPrefix + "_mul", Ac0_Ac1, c1, t2), - c.call(f2mPrefix + "_sub", t2, b_b, t2), - ); - } - buildF6Mul1(); - - function buildF6Mul01() { - const f = module.addFunction(f6mPrefix+ "_mul01"); - f.addParam("pA", "i32"); // F6 - f.addParam("pC0", "i32"); // F2 - f.addParam("pC1", "i32"); // F2 - f.addParam("pR", "i32"); // F6 - - const c = f.getCodeBuilder(); - - const A_c0 = c.getLocal("pA"); - const A_c1 = c.i32_add(c.getLocal("pA"), c.i32_const(f1size*2)); - const A_c2 = c.i32_add(c.getLocal("pA"), c.i32_const(f1size*4)); - - const c0 = c.getLocal("pC0"); - const c1 = c.getLocal("pC1"); - - const t1 = c.getLocal("pR"); - const t2 = c.i32_add(c.getLocal("pR"), c.i32_const(f1size*2)); - const t3 = c.i32_add(c.getLocal("pR"), c.i32_const(f1size*4)); - - const a_a = c.i32_const(module.alloc(f1size*2)); - const b_b = c.i32_const(module.alloc(f1size*2)); - const Ac0_Ac1 = c.i32_const(module.alloc(f1size*2)); - const Ac0_Ac2 = c.i32_const(module.alloc(f1size*2)); - - f.addCode( - // let a_a = self.c0 * c0; - c.call(f2mPrefix + "_mul", A_c0, c0, a_a), - - // let b_b = self.c1 * c1; - c.call(f2mPrefix + "_mul", A_c1, c1, b_b), - - - c.call(f2mPrefix + "_add", A_c0, A_c1, Ac0_Ac1), - c.call(f2mPrefix + "_add", A_c0, A_c2, Ac0_Ac2), - - // let t1 = (self.c1 + self.c2) * c1 - b_b; - c.call(f2mPrefix + "_add", A_c1, A_c2, t1), - c.call(f2mPrefix + "_mul", t1, c1, t1), - c.call(f2mPrefix + "_sub", t1, b_b, t1), - - // let t1 = t1.mul_by_nonresidue() + a_a; - c.call(f2mPrefix + "_mulNR", t1, t1), - c.call(f2mPrefix + "_add", t1, a_a, t1), - - // let t2 = (c0 + c1) * (self.c0 + self.c1) - a_a - b_b; - c.call(f2mPrefix + "_add", c0, c1, t2), - c.call(f2mPrefix + "_mul", t2, Ac0_Ac1, t2), - c.call(f2mPrefix + "_sub", t2, a_a, t2), - c.call(f2mPrefix + "_sub", t2, b_b, t2), - - // let t3 = (self.c0 + self.c2) * c0 - a_a + b_b; - c.call(f2mPrefix + "_mul", Ac0_Ac2, c0, t3), - c.call(f2mPrefix + "_sub", t3, a_a, t3), - c.call(f2mPrefix + "_add", t3, b_b, t3), - - - ); - } - buildF6Mul01(); - - - function buildF12Mul014() { - - const f = module.addFunction(ftmPrefix+ "_mul014"); - f.addParam("pA", "i32"); // F12 - f.addParam("pC0", "i32"); // F2 - f.addParam("pC1", "i32"); // F2 - f.addParam("pC4", "i32"); // F2 - f.addParam("pR", "i32"); // F12 - - const c = f.getCodeBuilder(); - - - const A_c0 = c.getLocal("pA"); - const A_c1 = c.i32_add(c.getLocal("pA"), c.i32_const(f1size*6)); - - const c0 = c.getLocal("pC0"); - const c1 = c.getLocal("pC1"); - const c4 = c.getLocal("pC4"); - - const aa = c.i32_const(module.alloc(f1size*6)); - const bb = c.i32_const(module.alloc(f1size*6)); - const o = c.i32_const(module.alloc(f1size*2)); - - const R_c0 = c.getLocal("pR"); - const R_c1 = c.i32_add(c.getLocal("pR"), c.i32_const(f1size*6)); - - f.addCode( - // let aa = self.c0.mul_by_01(c0, c1); - c.call(f6mPrefix + "_mul01", A_c0, c0, c1, aa), - - // let bb = self.c1.mul_by_1(c4); - c.call(f6mPrefix + "_mul1", A_c1, c4, bb), - - // let o = c1 + c4; - c.call(f2mPrefix + "_add", c1, c4, o), - - // let c1 = self.c1 + self.c0; - c.call(f6mPrefix + "_add", A_c1, A_c0, R_c1), - - // let c1 = c1.mul_by_01(c0, &o); - c.call(f6mPrefix + "_mul01", R_c1, c0, o, R_c1), - - // let c1 = c1 - aa - bb; - c.call(f6mPrefix + "_sub", R_c1, aa, R_c1), - c.call(f6mPrefix + "_sub", R_c1, bb, R_c1), - - // let c0 = bb; - c.call(f6mPrefix + "_copy", bb, R_c0), - - // let c0 = c0.mul_by_nonresidue(); - c.call(f6mPrefix + "_mulNR", R_c0, R_c0), - - // let c0 = c0 + aa; - c.call(f6mPrefix + "_add", R_c0, aa, R_c0), - ); - } - buildF12Mul014(); - - - function buildELL() { - const f = module.addFunction(prefix+ "_ell"); - f.addParam("pP", "i32"); - f.addParam("pCoefs", "i32"); - f.addParam("pF", "i32"); - - const c = f.getCodeBuilder(); - - const Px = c.getLocal("pP"); - const Py = c.i32_add(c.getLocal("pP"), c.i32_const(n8q)); - - const F = c.getLocal("pF"); - - const coef0_0 = c.getLocal("pCoefs"); - const coef0_1 = c.i32_add(c.getLocal("pCoefs"), c.i32_const(f1size)); - const coef1_0 = c.i32_add(c.getLocal("pCoefs"), c.i32_const(f1size*2)); - const coef1_1 = c.i32_add(c.getLocal("pCoefs"), c.i32_const(f1size*3)); - const coef2 = c.i32_add(c.getLocal("pCoefs"), c.i32_const(f1size*4)); - - const pc0 = module.alloc(f1size*2); - const c0 = c.i32_const(pc0); - const c0_c0 = c.i32_const(pc0); - const c0_c1 = c.i32_const(pc0+f1size); - - const pc1 = module.alloc(f1size*2); - const c1 = c.i32_const(pc1); - const c1_c0 = c.i32_const(pc1); - const c1_c1 = c.i32_const(pc1+f1size); - f.addCode( - // let mut c0 = coeffs.0; - // let mut c1 = coeffs.1; - // - // c0.c0 *= p.y; - // c0.c1 *= p.y; - // - // c1.c0 *= p.x; - // c1.c1 *= p.x; - // - // f.mul_by_014(&coeffs.2, &c1, &c0) - - c.call(f1mPrefix + "_mul", coef0_0, Py, c0_c0), - c.call(f1mPrefix + "_mul", coef0_1, Py, c0_c1), - c.call(f1mPrefix + "_mul", coef1_0, Px, c1_c0), - c.call(f1mPrefix + "_mul", coef1_1, Px, c1_c1), - - c.call(ftmPrefix + "_mul014", F, coef2, c1, c0, F), - - ); - - } - buildELL(); - - function buildMillerLoop() { - const f = module.addFunction(prefix+ "_millerLoop"); - f.addParam("ppreP", "i32"); - f.addParam("ppreQ", "i32"); - f.addParam("r", "i32"); - f.addLocal("pCoef", "i32"); - f.addLocal("i", "i32"); - - const c = f.getCodeBuilder(); - - const preP = c.getLocal("ppreP"); - - const coefs = c.getLocal("pCoef"); - - const F = c.getLocal("r"); - - - f.addCode( - c.call(ftmPrefix + "_one", F), - - c.if( - c.call(g1mPrefix + "_isZero", preP), - c.ret([]) - ), - c.if( - c.call(g1mPrefix + "_isZero", c.getLocal("ppreQ")), - c.ret([]) - ), - c.setLocal("pCoef", c.i32_add( c.getLocal("ppreQ"), c.i32_const(f2size*3))), - - c.setLocal("i", c.i32_const(ateLoopBitBytes.length-2)), - c.block(c.loop( - - - c.call(prefix + "_ell", preP, coefs, F), - c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), - - c.if( - c.i32_load8_s(c.getLocal("i"), pAteLoopBitBytes), - [ - ...c.call(prefix + "_ell", preP, coefs, F), - ...c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), - ] - ), - c.call(ftmPrefix + "_square", F, F), - - c.br_if(1, c.i32_eq ( c.getLocal("i"), c.i32_const(1) )), - c.setLocal("i", c.i32_sub(c.getLocal("i"), c.i32_const(1))), - c.br(0) - )), - c.call(prefix + "_ell", preP, coefs, F), - - ); - - - { - f.addCode( - c.call(ftmPrefix + "_conjugate", F, F), - ); - } - } - - - function buildFrobeniusMap(n) { - const F12 = [ - [ - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - ], - [ - [1n, 0n], - [3850754370037169011952147076051364057158807420970682438676050522613628423219637725072182697113062777891589506424760n, 151655185184498381465642749684540099398075398968325446656007613510403227271200139370504932015952886146304766135027n], - [793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620351n, 0n], - [2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530n, 1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257n], - [793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350n, 0n], - [3125332594171059424908108096204648978570118281977575435832422631601824034463382777937621250592425535493320683825557n, 877076961050607968509681729531255177986764537961432449499635504522207616027455086505066378536590128544573588734230n], - [4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559786n, 0n], - [151655185184498381465642749684540099398075398968325446656007613510403227271200139370504932015952886146304766135027n, 3850754370037169011952147076051364057158807420970682438676050522613628423219637725072182697113062777891589506424760n], - [4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436n, 0n], - [1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257n, 2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530n], - [4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437n, 0n], - [877076961050607968509681729531255177986764537961432449499635504522207616027455086505066378536590128544573588734230n, 3125332594171059424908108096204648978570118281977575435832422631601824034463382777937621250592425535493320683825557n], - ] - ]; - - const F6 = [ - [ - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - [1n, 0n], - ], - [ - [1n, 0n], - [0n, 4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436n], - [793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350n, 0n], - [0n, 1n], - [4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436n, 0n], - [0n, 793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350n], - ], - [ - [1n, 0n], - [4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437n, 0n], - [4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436n, 0n], - [4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559786n, 0n], - [793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350n, 0n], - [793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620351n, 0n], - ] - ]; - - const f = module.addFunction(ftmPrefix + "_frobeniusMap"+n); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - for (let i=0; i<6; i++) { - const X = (i==0) ? c.getLocal("x") : c.i32_add(c.getLocal("x"), c.i32_const(i*f2size)); - const Xc0 = X; - const Xc1 = c.i32_add(c.getLocal("x"), c.i32_const(i*f2size + f1size)); - const R = (i==0) ? c.getLocal("r") : c.i32_add(c.getLocal("r"), c.i32_const(i*f2size)); - const Rc0 = R; - const Rc1 = c.i32_add(c.getLocal("r"), c.i32_const(i*f2size + f1size)); - const coef = mul2(F12[Math.floor(i/3)][n%12] , F6[i%3][n%6]); - const pCoef = module.alloc([ - ...utils.bigInt2BytesLE(toMontgomery(coef[0]), n8q), - ...utils.bigInt2BytesLE(toMontgomery(coef[1]), n8q), - ]); - if (n%2 == 1) { - f.addCode( - c.call(f1mPrefix + "_copy", Xc0, Rc0), - c.call(f1mPrefix + "_neg", Xc1, Rc1), - c.call(f2mPrefix + "_mul", R, c.i32_const(pCoef), R), - ); - } else { - f.addCode(c.call(f2mPrefix + "_mul", X, c.i32_const(pCoef), R)); - } - } - - function mul2(a, b) { - const ac0 = a[0]; - const ac1 = a[1]; - const bc0 = b[0]; - const bc1 = b[1]; - const res = [ - (ac0 * bc0 - (ac1 * bc1)) % q, - (ac0 * bc1 + (ac1 * bc0)) % q, - ]; - if (isNegative$1(res[0])) res[0] = res[0] + q; - return res; - } - - } - - - function buildCyclotomicSquare() { - const f = module.addFunction(prefix+ "__cyclotomicSquare"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const x0 = c.getLocal("x"); - const x4 = c.i32_add(c.getLocal("x"), c.i32_const(f2size)); - const x3 = c.i32_add(c.getLocal("x"), c.i32_const(2*f2size)); - const x2 = c.i32_add(c.getLocal("x"), c.i32_const(3*f2size)); - const x1 = c.i32_add(c.getLocal("x"), c.i32_const(4*f2size)); - const x5 = c.i32_add(c.getLocal("x"), c.i32_const(5*f2size)); - - const r0 = c.getLocal("r"); - const r4 = c.i32_add(c.getLocal("r"), c.i32_const(f2size)); - const r3 = c.i32_add(c.getLocal("r"), c.i32_const(2*f2size)); - const r2 = c.i32_add(c.getLocal("r"), c.i32_const(3*f2size)); - const r1 = c.i32_add(c.getLocal("r"), c.i32_const(4*f2size)); - const r5 = c.i32_add(c.getLocal("r"), c.i32_const(5*f2size)); - - const t0 = c.i32_const(module.alloc(f2size)); - const t1 = c.i32_const(module.alloc(f2size)); - const t2 = c.i32_const(module.alloc(f2size)); - const t3 = c.i32_const(module.alloc(f2size)); - const t4 = c.i32_const(module.alloc(f2size)); - const t5 = c.i32_const(module.alloc(f2size)); - const tmp = c.i32_const(module.alloc(f2size)); - const AUX = c.i32_const(module.alloc(f2size)); - - - f.addCode( - // // t0 + t1*y = (z0 + z1*y)^2 = a^2 - // tmp = z0 * z1; - // t0 = (z0 + z1) * (z0 + my_Fp6::non_residue * z1) - tmp - my_Fp6::non_residue * tmp; - // t1 = tmp + tmp; - c.call(f2mPrefix + "_mul", x0, x1, tmp), - c.call(f2mPrefix + "_mulNR", x1, t0), - c.call(f2mPrefix + "_add", x0, t0, t0), - c.call(f2mPrefix + "_add", x0, x1, AUX), - c.call(f2mPrefix + "_mul", AUX, t0, t0), - c.call(f2mPrefix + "_mulNR", tmp, AUX), - c.call(f2mPrefix + "_add", tmp, AUX, AUX), - c.call(f2mPrefix + "_sub", t0, AUX, t0), - c.call(f2mPrefix + "_add", tmp, tmp, t1), - - // // t2 + t3*y = (z2 + z3*y)^2 = b^2 - // tmp = z2 * z3; - // t2 = (z2 + z3) * (z2 + my_Fp6::non_residue * z3) - tmp - my_Fp6::non_residue * tmp; - // t3 = tmp + tmp; - c.call(f2mPrefix + "_mul", x2, x3, tmp), - c.call(f2mPrefix + "_mulNR", x3, t2), - c.call(f2mPrefix + "_add", x2, t2, t2), - c.call(f2mPrefix + "_add", x2, x3, AUX), - c.call(f2mPrefix + "_mul", AUX, t2, t2), - c.call(f2mPrefix + "_mulNR", tmp, AUX), - c.call(f2mPrefix + "_add", tmp, AUX, AUX), - c.call(f2mPrefix + "_sub", t2, AUX, t2), - c.call(f2mPrefix + "_add", tmp, tmp, t3), - - // // t4 + t5*y = (z4 + z5*y)^2 = c^2 - // tmp = z4 * z5; - // t4 = (z4 + z5) * (z4 + my_Fp6::non_residue * z5) - tmp - my_Fp6::non_residue * tmp; - // t5 = tmp + tmp; - c.call(f2mPrefix + "_mul", x4, x5, tmp), - c.call(f2mPrefix + "_mulNR", x5, t4), - c.call(f2mPrefix + "_add", x4, t4, t4), - c.call(f2mPrefix + "_add", x4, x5, AUX), - c.call(f2mPrefix + "_mul", AUX, t4, t4), - c.call(f2mPrefix + "_mulNR", tmp, AUX), - c.call(f2mPrefix + "_add", tmp, AUX, AUX), - c.call(f2mPrefix + "_sub", t4, AUX, t4), - c.call(f2mPrefix + "_add", tmp, tmp, t5), - - // For A - // z0 = 3 * t0 - 2 * z0 - c.call(f2mPrefix + "_sub", t0, x0, r0), - c.call(f2mPrefix + "_add", r0, r0, r0), - c.call(f2mPrefix + "_add", t0, r0, r0), - // z1 = 3 * t1 + 2 * z1 - c.call(f2mPrefix + "_add", t1, x1, r1), - c.call(f2mPrefix + "_add", r1, r1, r1), - c.call(f2mPrefix + "_add", t1, r1, r1), - - // For B - // z2 = 3 * (xi * t5) + 2 * z2 - c.call(f2mPrefix + "_mul", t5, c.i32_const(pBls12381Twist), AUX), - c.call(f2mPrefix + "_add", AUX, x2, r2), - c.call(f2mPrefix + "_add", r2, r2, r2), - c.call(f2mPrefix + "_add", AUX, r2, r2), - // z3 = 3 * t4 - 2 * z3 - c.call(f2mPrefix + "_sub", t4, x3, r3), - c.call(f2mPrefix + "_add", r3, r3, r3), - c.call(f2mPrefix + "_add", t4, r3, r3), - - // For C - // z4 = 3 * t2 - 2 * z4 - c.call(f2mPrefix + "_sub", t2, x4, r4), - c.call(f2mPrefix + "_add", r4, r4, r4), - c.call(f2mPrefix + "_add", t2, r4, r4), - // z5 = 3 * t3 + 2 * z5 - c.call(f2mPrefix + "_add", t3, x5, r5), - c.call(f2mPrefix + "_add", r5, r5, r5), - c.call(f2mPrefix + "_add", t3, r5, r5), - - ); - } - - - function buildCyclotomicExp(exponent, isExpNegative, fnName) { - const exponentNafBytes = naf(exponent).map( (b) => (b==-1 ? 0xFF: b) ); - const pExponentNafBytes = module.alloc(exponentNafBytes); - // const pExponent = module.alloc(utils.bigInt2BytesLE(exponent, n8)); - - const f = module.addFunction(prefix+ "__cyclotomicExp_"+fnName); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - f.addLocal("bit", "i32"); - f.addLocal("i", "i32"); - - const c = f.getCodeBuilder(); - - const x = c.getLocal("x"); - - const res = c.getLocal("r"); - - const inverse = c.i32_const(module.alloc(ftsize)); - - - f.addCode( - c.call(ftmPrefix + "_conjugate", x, inverse), - c.call(ftmPrefix + "_one", res), - - c.if( - c.teeLocal("bit", c.i32_load8_s(c.i32_const(exponentNafBytes.length-1), pExponentNafBytes)), - c.if( - c.i32_eq( - c.getLocal("bit"), - c.i32_const(1) - ), - c.call(ftmPrefix + "_mul", res, x, res), - c.call(ftmPrefix + "_mul", res, inverse, res), - ) - ), - - c.setLocal("i", c.i32_const(exponentNafBytes.length-2)), - c.block(c.loop( - c.call(prefix + "__cyclotomicSquare", res, res), - c.if( - c.teeLocal("bit", c.i32_load8_s(c.getLocal("i"), pExponentNafBytes)), - c.if( - c.i32_eq( - c.getLocal("bit"), - c.i32_const(1) - ), - c.call(ftmPrefix + "_mul", res, x, res), - c.call(ftmPrefix + "_mul", res, inverse, res), - ) - ), - c.br_if(1, c.i32_eqz ( c.getLocal("i") )), - c.setLocal("i", c.i32_sub(c.getLocal("i"), c.i32_const(1))), - c.br(0) - )) - ); - - if (isExpNegative) { - f.addCode( - c.call(ftmPrefix + "_conjugate", res, res), - ); - } - - } - - function buildFinalExponentiation() { - buildCyclotomicSquare(); - buildCyclotomicExp(finalExpZ, finalExpIsNegative, "w0"); - - const f = module.addFunction(prefix+ "_finalExponentiation"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const c = f.getCodeBuilder(); - - const elt = c.getLocal("x"); - const res = c.getLocal("r"); - const t0 = c.i32_const(module.alloc(ftsize)); - const t1 = c.i32_const(module.alloc(ftsize)); - const t2 = c.i32_const(module.alloc(ftsize)); - const t3 = c.i32_const(module.alloc(ftsize)); - const t4 = c.i32_const(module.alloc(ftsize)); - const t5 = c.i32_const(module.alloc(ftsize)); - const t6 = c.i32_const(module.alloc(ftsize)); - - f.addCode( - - // let mut t0 = f.frobenius_map(6) - c.call(ftmPrefix + "_frobeniusMap6", elt, t0), - - // let t1 = f.invert() - c.call(ftmPrefix + "_inverse", elt, t1), - - // let mut t2 = t0 * t1; - c.call(ftmPrefix + "_mul", t0, t1, t2), - - // t1 = t2.clone(); - c.call(ftmPrefix + "_copy", t2, t1), - - // t2 = t2.frobenius_map().frobenius_map(); - c.call(ftmPrefix + "_frobeniusMap2", t2, t2), - - // t2 *= t1; - c.call(ftmPrefix + "_mul", t2, t1, t2), - - - // t1 = cyclotomic_square(t2).conjugate(); - c.call(prefix + "__cyclotomicSquare", t2, t1), - c.call(ftmPrefix + "_conjugate", t1, t1), - - // let mut t3 = cycolotomic_exp(t2); - c.call(prefix + "__cyclotomicExp_w0", t2, t3), - - // let mut t4 = cyclotomic_square(t3); - c.call(prefix + "__cyclotomicSquare", t3, t4), - - // let mut t5 = t1 * t3; - c.call(ftmPrefix + "_mul", t1, t3, t5), - - // t1 = cycolotomic_exp(t5); - c.call(prefix + "__cyclotomicExp_w0", t5, t1), - - // t0 = cycolotomic_exp(t1); - c.call(prefix + "__cyclotomicExp_w0", t1, t0), - - // let mut t6 = cycolotomic_exp(t0); - c.call(prefix + "__cyclotomicExp_w0", t0, t6), - - // t6 *= t4; - c.call(ftmPrefix + "_mul", t6, t4, t6), - - // t4 = cycolotomic_exp(t6); - c.call(prefix + "__cyclotomicExp_w0", t6, t4), - - // t5 = t5.conjugate(); - c.call(ftmPrefix + "_conjugate", t5, t5), - - // t4 *= t5 * t2; - c.call(ftmPrefix + "_mul", t4, t5, t4), - c.call(ftmPrefix + "_mul", t4, t2, t4), - - // t5 = t2.conjugate(); - c.call(ftmPrefix + "_conjugate", t2, t5), - - // t1 *= t2; - c.call(ftmPrefix + "_mul", t1, t2, t1), - - // t1 = t1.frobenius_map().frobenius_map().frobenius_map(); - c.call(ftmPrefix + "_frobeniusMap3", t1, t1), - - // t6 *= t5; - c.call(ftmPrefix + "_mul", t6, t5, t6), - - // t6 = t6.frobenius_map(); - c.call(ftmPrefix + "_frobeniusMap1", t6, t6), - - // t3 *= t0; - c.call(ftmPrefix + "_mul", t3, t0, t3), - - // t3 = t3.frobenius_map().frobenius_map(); - c.call(ftmPrefix + "_frobeniusMap2", t3, t3), - - // t3 *= t1; - c.call(ftmPrefix + "_mul", t3, t1, t3), - - // t3 *= t6; - c.call(ftmPrefix + "_mul", t3, t6, t3), - - // f = t3 * t4; - c.call(ftmPrefix + "_mul", t3, t4, res), - - ); - } - - - function buildFinalExponentiationOld() { - const f = module.addFunction(prefix+ "_finalExponentiationOld"); - f.addParam("x", "i32"); - f.addParam("r", "i32"); - - const exponent = 322277361516934140462891564586510139908379969514828494218366688025288661041104682794998680497580008899973249814104447692778988208376779573819485263026159588510513834876303014016798809919343532899164848730280942609956670917565618115867287399623286813270357901731510188149934363360381614501334086825442271920079363289954510565375378443704372994881406797882676971082200626541916413184642520269678897559532260949334760604962086348898118982248842634379637598665468817769075878555493752214492790122785850202957575200176084204422751485957336465472324810982833638490904279282696134323072515220044451592646885410572234451732790590013479358343841220074174848221722017083597872017638514103174122784843925578370430843522959600095676285723737049438346544753168912974976791528535276317256904336520179281145394686565050419250614107803233314658825463117900250701199181529205942363159325765991819433914303908860460720581408201373164047773794825411011922305820065611121544561808414055302212057471395719432072209245600258134364584636810093520285711072578721435517884103526483832733289802426157301542744476740008494780363354305116978805620671467071400711358839553375340724899735460480144599782014906586543813292157922220645089192130209334926661588737007768565838519456601560804957985667880395221049249803753582637708560n; - - const pExponent = module.alloc(utils.bigInt2BytesLE( exponent, 544 )); - - const c = f.getCodeBuilder(); - - f.addCode( - c.call(ftmPrefix + "_exp", c.getLocal("x"), c.i32_const(pExponent), c.i32_const(544), c.getLocal("r")), - ); - } - - - const pPreP = module.alloc(prePSize); - const pPreQ = module.alloc(preQSize); - - function buildPairingEquation(nPairings) { - - const f = module.addFunction(prefix+ "_pairingEq"+nPairings); - for (let i=0; i. - */ - - // module.exports.bn128_wasm = require("./build/bn128_wasm.js"); - var bn128_wasm_gzip = bn128_wasm_gzip$1; - // module.exports.bls12381_wasm = require("./build/bls12381_wasm.js"); - // module.exports.mnt6753_wasm = require("./build/mnt6753_wasm.js"); - - var buildBn128 = build_bn128; - var buildBls12381 = build_bls12381; - - var index = /*#__PURE__*/Object.freeze({ - __proto__: null, - bn128_wasm_gzip: bn128_wasm_gzip, - buildBls12381: buildBls12381, - buildBn128: buildBn128 - }); - - /* - Copyright 2019 0KIMS association. - - This file is part of wasmbuilder - - wasmbuilder is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - wasmbuilder is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with wasmbuilder. If not, see . - */ - - function toNumber(n) { - return BigInt(n); - } - - function isNegative(n) { - return n < 0n; - } - - function isZero(n) { - return n === 0n; - } - - function bitLength(n) { - if (isNegative(n)) { - return n.toString(2).length - 1; // discard the - sign - } else { - return n.toString(2).length; - } - } - - function u32$1(n) { - const b = []; - const v = toNumber(n); - b.push(Number(v & 0xFFn)); - b.push(Number(v >> 8n & 0xFFn)); - b.push(Number(v >> 16n & 0xFFn)); - b.push(Number(v >> 24n & 0xFFn)); - return b; - } - - function toUTF8Array(str) { - var utf8 = []; - for (var i=0; i < str.length; i++) { - var charcode = str.charCodeAt(i); - if (charcode < 0x80) utf8.push(charcode); - else if (charcode < 0x800) { - utf8.push(0xc0 | (charcode >> 6), - 0x80 | (charcode & 0x3f)); - } - else if (charcode < 0xd800 || charcode >= 0xe000) { - utf8.push(0xe0 | (charcode >> 12), - 0x80 | ((charcode>>6) & 0x3f), - 0x80 | (charcode & 0x3f)); - } - // surrogate pair - else { - i++; - // UTF-16 encodes 0x10000-0x10FFFF by - // subtracting 0x10000 and splitting the - // 20 bits of 0x0-0xFFFFF into two halves - charcode = 0x10000 + (((charcode & 0x3ff)<<10) - | (str.charCodeAt(i) & 0x3ff)); - utf8.push(0xf0 | (charcode >>18), - 0x80 | ((charcode>>12) & 0x3f), - 0x80 | ((charcode>>6) & 0x3f), - 0x80 | (charcode & 0x3f)); - } - } - return utf8; - } - - function string(str) { - const bytes = toUTF8Array(str); - return [ ...varuint32(bytes.length), ...bytes ]; - } - - function varuint(n) { - const code = []; - let v = toNumber(n); - if (isNegative(v)) throw new Error("Number cannot be negative"); - while (!isZero(v)) { - code.push(Number(v & 0x7Fn)); - v = v >> 7n; - } - if (code.length==0) code.push(0); - for (let i=0; i 0xFFFFFFFFn) throw new Error("Number too big"); - if (v > 0x7FFFFFFFn) v = v - 0x100000000n; - // bigInt("-80000000", 16) as base10 - if (v < -2147483648n) throw new Error("Number too small"); - return varint(v); - } - - function varint64(n) { - let v = toNumber(n); - if (v > 0xFFFFFFFFFFFFFFFFn) throw new Error("Number too big"); - if (v > 0x7FFFFFFFFFFFFFFFn) v = v - 0x10000000000000000n; - // bigInt("-8000000000000000", 16) as base10 - if (v < -9223372036854775808n) throw new Error("Number too small"); - return varint(v); - } - - function varuint32(n) { - let v = toNumber(n); - if (v > 0xFFFFFFFFn) throw new Error("Number too big"); - return varuint(v); - } - - function toHexString(byteArray) { - return Array.from(byteArray, function(byte) { - return ("0" + (byte & 0xFF).toString(16)).slice(-2); - }).join(""); - } - - /* - Copyright 2019 0KIMS association. - - This file is part of wasmbuilder - - wasmbuilder is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - wasmbuilder is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with wasmbuilder. If not, see . - */ - - - class CodeBuilder { - constructor(func) { - this.func = func; - this.functionName = func.functionName; - this.module = func.module; - } - - setLocal(localName, valCode) { - const idx = this.func.localIdxByName[localName]; - if (idx === undefined) - throw new Error(`Local Variable not defined: Function: ${this.functionName} local: ${localName} `); - return [...valCode, 0x21, ...varuint32( idx )]; - } - - teeLocal(localName, valCode) { - const idx = this.func.localIdxByName[localName]; - if (idx === undefined) - throw new Error(`Local Variable not defined: Function: ${this.functionName} local: ${localName} `); - return [...valCode, 0x22, ...varuint32( idx )]; - } - - getLocal(localName) { - const idx = this.func.localIdxByName[localName]; - if (idx === undefined) - throw new Error(`Local Variable not defined: Function: ${this.functionName} local: ${localName} `); - return [0x20, ...varuint32( idx )]; - } - - i64_load8_s(idxCode, _offset, _align) { - const offset = _offset || 0; - const align = (_align === undefined) ? 0 : _align; // 8 bits alignment by default - return [...idxCode, 0x30, align, ...varuint32(offset)]; - } - - i64_load8_u(idxCode, _offset, _align) { - const offset = _offset || 0; - const align = (_align === undefined) ? 0 : _align; // 8 bits alignment by default - return [...idxCode, 0x31, align, ...varuint32(offset)]; - } - - i64_load16_s(idxCode, _offset, _align) { - const offset = _offset || 0; - const align = (_align === undefined) ? 1 : _align; // 16 bits alignment by default - return [...idxCode, 0x32, align, ...varuint32(offset)]; - } - - i64_load16_u(idxCode, _offset, _align) { - const offset = _offset || 0; - const align = (_align === undefined) ? 1 : _align; // 16 bits alignment by default - return [...idxCode, 0x33, align, ...varuint32(offset)]; - } - - i64_load32_s(idxCode, _offset, _align) { - const offset = _offset || 0; - const align = (_align === undefined) ? 2 : _align; // 32 bits alignment by default - return [...idxCode, 0x34, align, ...varuint32(offset)]; - } - - i64_load32_u(idxCode, _offset, _align) { - const offset = _offset || 0; - const align = (_align === undefined) ? 2 : _align; // 32 bits alignment by default - return [...idxCode, 0x35, align, ...varuint32(offset)]; - } - - i64_load(idxCode, _offset, _align) { - const offset = _offset || 0; - const align = (_align === undefined) ? 3 : _align; // 64 bits alignment by default - return [...idxCode, 0x29, align, ...varuint32(offset)]; - } - - - i64_store(idxCode, _offset, _align, _codeVal) { - let offset, align, codeVal; - if (Array.isArray(_offset)) { - offset = 0; - align = 3; - codeVal = _offset; - } else if (Array.isArray(_align)) { - offset = _offset; - align = 3; - codeVal = _align; - } else if (Array.isArray(_codeVal)) { - offset = _offset; - align = _align; - codeVal = _codeVal; - } - return [...idxCode, ...codeVal, 0x37, align, ...varuint32(offset)]; - } - - i64_store32(idxCode, _offset, _align, _codeVal) { - let offset, align, codeVal; - if (Array.isArray(_offset)) { - offset = 0; - align = 2; - codeVal = _offset; - } else if (Array.isArray(_align)) { - offset = _offset; - align = 2; - codeVal = _align; - } else if (Array.isArray(_codeVal)) { - offset = _offset; - align = _align; - codeVal = _codeVal; - } - return [...idxCode, ...codeVal, 0x3e, align, ...varuint32(offset)]; - } - - - i64_store16(idxCode, _offset, _align, _codeVal) { - let offset, align, codeVal; - if (Array.isArray(_offset)) { - offset = 0; - align = 1; - codeVal = _offset; - } else if (Array.isArray(_align)) { - offset = _offset; - align = 1; - codeVal = _align; - } else if (Array.isArray(_codeVal)) { - offset = _offset; - align = _align; - codeVal = _codeVal; - } - return [...idxCode, ...codeVal, 0x3d, align, ...varuint32(offset)]; - } - - - i64_store8(idxCode, _offset, _align, _codeVal) { - let offset, align, codeVal; - if (Array.isArray(_offset)) { - offset = 0; - align = 0; - codeVal = _offset; - } else if (Array.isArray(_align)) { - offset = _offset; - align = 0; - codeVal = _align; - } else if (Array.isArray(_codeVal)) { - offset = _offset; - align = _align; - codeVal = _codeVal; - } - return [...idxCode, ...codeVal, 0x3c, align, ...varuint32(offset)]; - } - - i32_load8_s(idxCode, _offset, _align) { - const offset = _offset || 0; - const align = (_align === undefined) ? 0 : _align; // 32 bits alignment by default - return [...idxCode, 0x2c, align, ...varuint32(offset)]; - } - - i32_load8_u(idxCode, _offset, _align) { - const offset = _offset || 0; - const align = (_align === undefined) ? 0 : _align; // 32 bits alignment by default - return [...idxCode, 0x2d, align, ...varuint32(offset)]; - } - - i32_load16_s(idxCode, _offset, _align) { - const offset = _offset || 0; - const align = (_align === undefined) ? 1 : _align; // 32 bits alignment by default - return [...idxCode, 0x2e, align, ...varuint32(offset)]; - } - - i32_load16_u(idxCode, _offset, _align) { - const offset = _offset || 0; - const align = (_align === undefined) ? 1 : _align; // 32 bits alignment by default - return [...idxCode, 0x2f, align, ...varuint32(offset)]; - } - - i32_load(idxCode, _offset, _align) { - const offset = _offset || 0; - const align = (_align === undefined) ? 2 : _align; // 32 bits alignment by default - return [...idxCode, 0x28, align, ...varuint32(offset)]; - } - - i32_store(idxCode, _offset, _align, _codeVal) { - let offset, align, codeVal; - if (Array.isArray(_offset)) { - offset = 0; - align = 2; - codeVal = _offset; - } else if (Array.isArray(_align)) { - offset = _offset; - align = 2; - codeVal = _align; - } else if (Array.isArray(_codeVal)) { - offset = _offset; - align = _align; - codeVal = _codeVal; - } - return [...idxCode, ...codeVal, 0x36, align, ...varuint32(offset)]; - } - - - i32_store16(idxCode, _offset, _align, _codeVal) { - let offset, align, codeVal; - if (Array.isArray(_offset)) { - offset = 0; - align = 1; - codeVal = _offset; - } else if (Array.isArray(_align)) { - offset = _offset; - align = 1; - codeVal = _align; - } else if (Array.isArray(_codeVal)) { - offset = _offset; - align = _align; - codeVal = _codeVal; - } - return [...idxCode, ...codeVal, 0x3b, align, ...varuint32(offset)]; - } - - i32_store8(idxCode, _offset, _align, _codeVal) { - let offset, align, codeVal; - if (Array.isArray(_offset)) { - offset = 0; - align = 0; - codeVal = _offset; - } else if (Array.isArray(_align)) { - offset = _offset; - align = 0; - codeVal = _align; - } else if (Array.isArray(_codeVal)) { - offset = _offset; - align = _align; - codeVal = _codeVal; - } - return [...idxCode, ...codeVal, 0x3a, align, ...varuint32(offset)]; - } - - call(fnName, ...args) { - const idx = this.module.functionIdxByName[fnName]; - if (idx === undefined) - throw new Error(`Function not defined: Function: ${fnName}`); - return [...[].concat(...args), 0x10, ...varuint32(idx)]; - } - - call_indirect(fnIdx, ...args) { - return [...[].concat(...args), ...fnIdx, 0x11, 0, 0]; - } - - if(condCode, thenCode, elseCode) { - if (elseCode) { - return [...condCode, 0x04, 0x40, ...thenCode, 0x05, ...elseCode, 0x0b]; - } else { - return [...condCode, 0x04, 0x40, ...thenCode, 0x0b]; - } - } - - block(bCode) { return [0x02, 0x40, ...bCode, 0x0b]; } - loop(...args) { - return [0x03, 0x40, ...[].concat(...[...args]), 0x0b]; - } - br_if(relPath, condCode) { return [...condCode, 0x0d, ...varuint32(relPath)]; } - br(relPath) { return [0x0c, ...varuint32(relPath)]; } - ret(rCode) { return [...rCode, 0x0f]; } - drop(dCode) { return [...dCode, 0x1a]; } - - i64_const(num) { return [0x42, ...varint64(num)]; } - i32_const(num) { return [0x41, ...varint32(num)]; } - - - i64_eqz(opcode) { return [...opcode, 0x50]; } - i64_eq(op1code, op2code) { return [...op1code, ...op2code, 0x51]; } - i64_ne(op1code, op2code) { return [...op1code, ...op2code, 0x52]; } - i64_lt_s(op1code, op2code) { return [...op1code, ...op2code, 0x53]; } - i64_lt_u(op1code, op2code) { return [...op1code, ...op2code, 0x54]; } - i64_gt_s(op1code, op2code) { return [...op1code, ...op2code, 0x55]; } - i64_gt_u(op1code, op2code) { return [...op1code, ...op2code, 0x56]; } - i64_le_s(op1code, op2code) { return [...op1code, ...op2code, 0x57]; } - i64_le_u(op1code, op2code) { return [...op1code, ...op2code, 0x58]; } - i64_ge_s(op1code, op2code) { return [...op1code, ...op2code, 0x59]; } - i64_ge_u(op1code, op2code) { return [...op1code, ...op2code, 0x5a]; } - i64_add(op1code, op2code) { return [...op1code, ...op2code, 0x7c]; } - i64_sub(op1code, op2code) { return [...op1code, ...op2code, 0x7d]; } - i64_mul(op1code, op2code) { return [...op1code, ...op2code, 0x7e]; } - i64_div_s(op1code, op2code) { return [...op1code, ...op2code, 0x7f]; } - i64_div_u(op1code, op2code) { return [...op1code, ...op2code, 0x80]; } - i64_rem_s(op1code, op2code) { return [...op1code, ...op2code, 0x81]; } - i64_rem_u(op1code, op2code) { return [...op1code, ...op2code, 0x82]; } - i64_and(op1code, op2code) { return [...op1code, ...op2code, 0x83]; } - i64_or(op1code, op2code) { return [...op1code, ...op2code, 0x84]; } - i64_xor(op1code, op2code) { return [...op1code, ...op2code, 0x85]; } - i64_shl(op1code, op2code) { return [...op1code, ...op2code, 0x86]; } - i64_shr_s(op1code, op2code) { return [...op1code, ...op2code, 0x87]; } - i64_shr_u(op1code, op2code) { return [...op1code, ...op2code, 0x88]; } - i64_extend_i32_s(op1code) { return [...op1code, 0xac]; } - i64_extend_i32_u(op1code) { return [...op1code, 0xad]; } - i64_clz(op1code) { return [...op1code, 0x79]; } - i64_ctz(op1code) { return [...op1code, 0x7a]; } - - i32_eqz(op1code) { return [...op1code, 0x45]; } - i32_eq(op1code, op2code) { return [...op1code, ...op2code, 0x46]; } - i32_ne(op1code, op2code) { return [...op1code, ...op2code, 0x47]; } - i32_lt_s(op1code, op2code) { return [...op1code, ...op2code, 0x48]; } - i32_lt_u(op1code, op2code) { return [...op1code, ...op2code, 0x49]; } - i32_gt_s(op1code, op2code) { return [...op1code, ...op2code, 0x4a]; } - i32_gt_u(op1code, op2code) { return [...op1code, ...op2code, 0x4b]; } - i32_le_s(op1code, op2code) { return [...op1code, ...op2code, 0x4c]; } - i32_le_u(op1code, op2code) { return [...op1code, ...op2code, 0x4d]; } - i32_ge_s(op1code, op2code) { return [...op1code, ...op2code, 0x4e]; } - i32_ge_u(op1code, op2code) { return [...op1code, ...op2code, 0x4f]; } - i32_add(op1code, op2code) { return [...op1code, ...op2code, 0x6a]; } - i32_sub(op1code, op2code) { return [...op1code, ...op2code, 0x6b]; } - i32_mul(op1code, op2code) { return [...op1code, ...op2code, 0x6c]; } - i32_div_s(op1code, op2code) { return [...op1code, ...op2code, 0x6d]; } - i32_div_u(op1code, op2code) { return [...op1code, ...op2code, 0x6e]; } - i32_rem_s(op1code, op2code) { return [...op1code, ...op2code, 0x6f]; } - i32_rem_u(op1code, op2code) { return [...op1code, ...op2code, 0x70]; } - i32_and(op1code, op2code) { return [...op1code, ...op2code, 0x71]; } - i32_or(op1code, op2code) { return [...op1code, ...op2code, 0x72]; } - i32_xor(op1code, op2code) { return [...op1code, ...op2code, 0x73]; } - i32_shl(op1code, op2code) { return [...op1code, ...op2code, 0x74]; } - i32_shr_s(op1code, op2code) { return [...op1code, ...op2code, 0x75]; } - i32_shr_u(op1code, op2code) { return [...op1code, ...op2code, 0x76]; } - i32_rotl(op1code, op2code) { return [...op1code, ...op2code, 0x77]; } - i32_rotr(op1code, op2code) { return [...op1code, ...op2code, 0x78]; } - i32_wrap_i64(op1code) { return [...op1code, 0xa7]; } - i32_clz(op1code) { return [...op1code, 0x67]; } - i32_ctz(op1code) { return [...op1code, 0x68]; } - - unreachable() { return [ 0x0 ]; } - - current_memory() { return [ 0x3f, 0]; } - - comment() { return []; } - } - - /* - Copyright 2019 0KIMS association. - - This file is part of wasmbuilder - - wasmbuilder is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - wasmbuilder is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with wasmbuilder. If not, see . - */ - - - const typeCodes = { - "i32": 0x7f, - "i64": 0x7e, - "f32": 0x7d, - "f64": 0x7c, - "anyfunc": 0x70, - "func": 0x60, - "emptyblock": 0x40 - }; - - - class FunctionBuilder { - - constructor (module, fnName, fnType, moduleName, fieldName) { - if (fnType == "import") { - this.fnType = "import"; - this.moduleName = moduleName; - this.fieldName = fieldName; - } else if (fnType == "internal") { - this.fnType = "internal"; - } else { - throw new Error("Invalid function fnType: " + fnType); - } - this.module = module; - this.fnName = fnName; - this.params = []; - this.locals = []; - this.localIdxByName = {}; - this.code = []; - this.returnType = null; - this.nextLocal =0; - } - - addParam(paramName, paramType) { - if (this.localIdxByName[paramName]) - throw new Error(`param already exists. Function: ${this.fnName}, Param: ${paramName} `); - const idx = this.nextLocal++; - this.localIdxByName[paramName] = idx; - this.params.push({ - type: paramType - }); - } - - addLocal(localName, localType, _length) { - const length = _length || 1; - if (this.localIdxByName[localName]) - throw new Error(`local already exists. Function: ${this.fnName}, Param: ${localName} `); - const idx = this.nextLocal++; - this.localIdxByName[localName] = idx; - this.locals.push({ - type: localType, - length: length - }); - } - - setReturnType(returnType) { - if (this.returnType) - throw new Error(`returnType already defined. Function: ${this.fnName}`); - this.returnType = returnType; - } - - getSignature() { - const params = [...varuint32(this.params.length), ...this.params.map((p) => typeCodes[p.type])]; - const returns = this.returnType ? [0x01, typeCodes[this.returnType]] : [0]; - return [0x60, ...params, ...returns]; - } - - getBody() { - const locals = this.locals.map((l) => [ - ...varuint32(l.length), - typeCodes[l.type] - ]); - - const body = [ - ...varuint32(this.locals.length), - ...[].concat(...locals), - ...this.code, - 0x0b - ]; - return [ - ...varuint32(body.length), - ...body - ]; - } - - addCode(...code) { - this.code.push(...[].concat(...[...code])); - } - - getCodeBuilder() { - return new CodeBuilder(this); - } - } - - /* - Copyright 2019 0KIMS association. - - This file is part of wasmbuilder - - wasmbuilder is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - wasmbuilder is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with wasmbuilder. If not, see . - */ - - - class ModuleBuilder { - - constructor() { - this.functions = []; - this.functionIdxByName = {}; - this.nImportFunctions = 0; - this.nInternalFunctions =0; - this.memory = { - pagesSize: 1, - moduleName: "env", - fieldName: "memory" - }; - this.free = 8; - this.datas = []; - this.modules = {}; - this.exports = []; - this.functionsTable = []; - } - - build() { - this._setSignatures(); - return new Uint8Array([ - ...u32$1(0x6d736100), - ...u32$1(1), - ...this._buildType(), - ...this._buildImport(), - ...this._buildFunctionDeclarations(), - ...this._buildFunctionsTable(), - ...this._buildExports(), - ...this._buildElements(), - ...this._buildCode(), - ...this._buildData() - ]); - } - - addFunction(fnName) { - if (typeof(this.functionIdxByName[fnName]) !== "undefined") - throw new Error(`Function already defined: ${fnName}`); - - const idx = this.functions.length; - this.functionIdxByName[fnName] = idx; - - this.functions.push(new FunctionBuilder(this, fnName, "internal")); - - this.nInternalFunctions++; - return this.functions[idx]; - } - - addIimportFunction(fnName, moduleName, _fieldName) { - if (typeof(this.functionIdxByName[fnName]) !== "undefined") - throw new Error(`Function already defined: ${fnName}`); - - if ( (this.functions.length>0) - &&(this.functions[this.functions.length-1].type == "internal")) - throw new Error(`Import functions must be declared before internal: ${fnName}`); - - let fieldName = _fieldName || fnName; - - const idx = this.functions.length; - this.functionIdxByName[fnName] = idx; - - this.functions.push(new FunctionBuilder(this, fnName, "import", moduleName, fieldName)); - - this.nImportFunctions ++; - return this.functions[idx]; - } - - setMemory(pagesSize, moduleName, fieldName) { - this.memory = { - pagesSize: pagesSize, - moduleName: moduleName || "env", - fieldName: fieldName || "memory" - }; - } - - exportFunction(fnName, _exportName) { - const exportName = _exportName || fnName; - if (typeof(this.functionIdxByName[fnName]) === "undefined") - throw new Error(`Function not defined: ${fnName}`); - const idx = this.functionIdxByName[fnName]; - if (exportName != fnName) { - this.functionIdxByName[exportName] = idx; - } - this.exports.push({ - exportName: exportName, - idx: idx - }); - } - - addFunctionToTable(fnName) { - const idx = this.functionIdxByName[fnName]; - this.functionsTable.push(idx); - } - - addData(offset, bytes) { - this.datas.push({ - offset: offset, - bytes: bytes - }); - } - - alloc(a, b) { - let size; - let bytes; - if ((Array.isArray(a) || ArrayBuffer.isView(a)) && (typeof(b) === "undefined")) { - size = a.length; - bytes = a; - } else { - size = a; - bytes = b; - } - size = (((size-1)>>3) +1)<<3; // Align to 64 bits. - const p = this.free; - this.free += size; - if (bytes) { - this.addData(p, bytes); - } - return p; - } - - allocString(s) { - const encoder = new globalThis.TextEncoder(); - const uint8array = encoder.encode(s); - return this.alloc([...uint8array, 0]); - } - - _setSignatures() { - this.signatures = []; - const signatureIdxByName = {}; - if (this.functionsTable.length>0) { - const signature = this.functions[this.functionsTable[0]].getSignature(); - const signatureName = "s_"+toHexString(signature); - signatureIdxByName[signatureName] = 0; - this.signatures.push(signature); - } - for (let i=0; i. - */ - - var main = /*#__PURE__*/Object.freeze({ - __proto__: null, - ModuleBuilder: ModuleBuilder - }); - - var fs = {}; - - async function open$2(fileName, openFlags, cacheSize, pageSize) { - cacheSize = cacheSize || 4096*64; - if (typeof openFlags !== "number" && ["w+", "wx+", "r", "ax+", "a+"].indexOf(openFlags) <0) - throw new Error("Invalid open option"); - const fd =await fs.promises.open(fileName, openFlags); - - const stats = await fd.stat(); - - return new FastFile$2(fd, stats, cacheSize, pageSize, fileName); - } - - - class FastFile$2 { - - constructor(fd, stats, cacheSize, pageSize, fileName) { - this.fileName = fileName; - this.fd = fd; - this.pos = 0; - this.pageSize = pageSize || (1 << 8); - while (this.pageSize < stats.blksize) { - this.pageSize *= 2; - } - this.totalSize = stats.size; - this.totalPages = Math.floor((stats.size -1) / this.pageSize)+1; - this.maxPagesLoaded = Math.floor( cacheSize / this.pageSize)+1; - this.pages = {}; - this.pendingLoads = []; - this.writing = false; - this.reading = false; - this.avBuffs = []; - this.history = {}; - } - - _loadPage(p) { - const self = this; - const P = new Promise((resolve, reject)=> { - self.pendingLoads.push({ - page: p, - resolve: resolve, - reject: reject - }); - }); - self.__statusPage("After Load request: ", p); - return P; - } - - __statusPage(s, p) { - const logEntry = []; - const self=this; - if (!self.logHistory) return; - logEntry.push("==" + s+ " " +p); - let S = ""; - for (let i=0; i " + self.history[p][i][j]); - } - } - } - - - - _triggerLoad() { - const self = this; - - if (self.reading) return; - if (self.pendingLoads.length==0) return; - - const pageIdxs = Object.keys(self.pages); - - const deletablePages = []; - for (let i=0; i0) && - ( (typeof self.pages[self.pendingLoads[0].page] != "undefined" ) - ||( (freePages>0) - ||(deletablePages.length>0)))) { - const load = self.pendingLoads.shift(); - if (typeof self.pages[load.page] != "undefined") { - self.pages[load.page].pendingOps ++; - const idx = deletablePages.indexOf(load.page); - if (idx>=0) deletablePages.splice(idx, 1); - if (self.pages[load.page].loading) { - self.pages[load.page].loading.push(load); - } else { - load.resolve(); - } - self.__statusPage("After Load (cached): ", load.page); - - } else { - if (freePages) { - freePages--; - } else { - const fp = deletablePages.shift(); - self.__statusPage("Before Unload: ", fp); - self.avBuffs.unshift(self.pages[fp]); - delete self.pages[fp]; - self.__statusPage("After Unload: ", fp); - } - - if (load.page>=self.totalPages) { - self.pages[load.page] = getNewPage(); - load.resolve(); - self.__statusPage("After Load (new): ", load.page); - } else { - self.reading = true; - self.pages[load.page] = getNewPage(); - self.pages[load.page].loading = [load]; - ops.push(self.fd.read(self.pages[load.page].buff, 0, self.pageSize, load.page*self.pageSize).then((res)=> { - self.pages[load.page].size = res.bytesRead; - const loading = self.pages[load.page].loading; - delete self.pages[load.page].loading; - for (let i=0; i { - load.reject(err); - })); - self.__statusPage("After Load (loading): ", load.page); - } - } - } - // if (ops.length>1) console.log(ops.length); - - Promise.all(ops).then( () => { - self.reading = false; - if (self.pendingLoads.length>0) setImmediate(self._triggerLoad.bind(self)); - self._tryClose(); - }); - - function getNewPage() { - if (self.avBuffs.length>0) { - const p = self.avBuffs.shift(); - p.dirty = false; - p.pendingOps = 1; - p.size =0; - return p; - } else { - return { - dirty: false, - buff: new Uint8Array(self.pageSize), - pendingOps: 1, - size: 0 - }; - } - } - - } - - - _triggerWrite() { - const self = this; - if (self.writing) return; - - const pageIdxs = Object.keys(self.pages); - - const ops = []; - - for (let i=0; i { - page.writing = false; - return; - }, (err) => { - console.log("ERROR Writing: "+err); - self.error = err; - self._tryClose(); - })); - } - } - - if (self.writing) { - Promise.all(ops).then( () => { - self.writing = false; - setImmediate(self._triggerWrite.bind(self)); - self._tryClose(); - if (self.pendingLoads.length>0) setImmediate(self._triggerLoad.bind(self)); - }); - } - } - - _getDirtyPage() { - for (let p in this.pages) { - if (this.pages[p].dirty) return p; - } - return -1; - } - - async write(buff, pos) { - if (buff.byteLength == 0) return; - const self = this; - /* - if (buff.byteLength > self.pageSize*self.maxPagesLoaded*0.8) { - const cacheSize = Math.floor(buff.byteLength * 1.1); - this.maxPagesLoaded = Math.floor( cacheSize / self.pageSize)+1; - } - */ - if (typeof pos == "undefined") pos = self.pos; - self.pos = pos+buff.byteLength; - if (self.totalSize < pos + buff.byteLength) self.totalSize = pos + buff.byteLength; - if (self.pendingClose) - throw new Error("Writing a closing file"); - const firstPage = Math.floor(pos / self.pageSize); - const lastPage = Math.floor((pos + buff.byteLength -1) / self.pageSize); - - const pagePromises = []; - for (let i=firstPage; i<=lastPage; i++) pagePromises.push(self._loadPage(i)); - self._triggerLoad(); - - let p = firstPage; - let o = pos % self.pageSize; - let r = buff.byteLength; - while (r>0) { - await pagePromises[p-firstPage]; - const l = (o+r > self.pageSize) ? (self.pageSize -o) : r; - const srcView = buff.slice( buff.byteLength - r, buff.byteLength - r + l); - const dstView = new Uint8Array(self.pages[p].buff.buffer, o, l); - dstView.set(srcView); - self.pages[p].dirty = true; - self.pages[p].pendingOps --; - self.pages[p].size = Math.max(o+l, self.pages[p].size); - if (p>=self.totalPages) { - self.totalPages = p+1; - } - r = r-l; - p ++; - o = 0; - if (!self.writing) setImmediate(self._triggerWrite.bind(self)); - } - } - - async read(len, pos) { - const self = this; - let buff = new Uint8Array(len); - await self.readToBuffer(buff, 0, len, pos); - - return buff; - } - - async readToBuffer(buffDst, offset, len, pos) { - if (len == 0) { - return; - } - const self = this; - if (len > self.pageSize*self.maxPagesLoaded*0.8) { - const cacheSize = Math.floor(len * 1.1); - this.maxPagesLoaded = Math.floor( cacheSize / self.pageSize)+1; - } - if (typeof pos == "undefined") pos = self.pos; - self.pos = pos+len; - if (self.pendingClose) - throw new Error("Reading a closing file"); - const firstPage = Math.floor(pos / self.pageSize); - const lastPage = Math.floor((pos + len -1) / self.pageSize); - - const pagePromises = []; - for (let i=firstPage; i<=lastPage; i++) pagePromises.push(self._loadPage(i)); - - self._triggerLoad(); - - let p = firstPage; - let o = pos % self.pageSize; - // Remaining bytes to read - let r = pos + len > self.totalSize ? len - (pos + len - self.totalSize): len; - while (r>0) { - await pagePromises[p - firstPage]; - self.__statusPage("After Await (read): ", p); - - // bytes to copy from this page - const l = (o+r > self.pageSize) ? (self.pageSize -o) : r; - const srcView = new Uint8Array(self.pages[p].buff.buffer, self.pages[p].buff.byteOffset + o, l); - buffDst.set(srcView, offset+len-r); - self.pages[p].pendingOps --; - - self.__statusPage("After Op done: ", p); - - r = r-l; - p ++; - o = 0; - if (self.pendingLoads.length>0) setImmediate(self._triggerLoad.bind(self)); - } - - this.pos = pos + len; - - } - - - _tryClose() { - const self = this; - if (!self.pendingClose) return; - if (self.error) { - self.pendingCloseReject(self.error); - } - const p = self._getDirtyPage(); - if ((p>=0) || (self.writing) || (self.reading) || (self.pendingLoads.length>0)) return; - self.pendingClose(); - } - - close() { - const self = this; - if (self.pendingClose) - throw new Error("Closing the file twice"); - return new Promise((resolve, reject) => { - self.pendingClose = resolve; - self.pendingCloseReject = reject; - self._tryClose(); - }).then(()=> { - self.fd.close(); - }, (err) => { - self.fd.close(); - throw (err); - }); - } - - async discard() { - const self = this; - await self.close(); - await fs.promises.unlink(this.fileName); - } - - async writeULE32(v, pos) { - const self = this; - const tmpBuff32 = new Uint8Array(4); - const tmpBuff32v = new DataView(tmpBuff32.buffer); - - tmpBuff32v.setUint32(0, v, true); - - await self.write(tmpBuff32, pos); - } - - async writeUBE32(v, pos) { - const self = this; - - const tmpBuff32 = new Uint8Array(4); - const tmpBuff32v = new DataView(tmpBuff32.buffer); - - tmpBuff32v.setUint32(0, v, false); - - await self.write(tmpBuff32, pos); - } - - - async writeULE64(v, pos) { - const self = this; - - const tmpBuff64 = new Uint8Array(8); - const tmpBuff64v = new DataView(tmpBuff64.buffer); - - tmpBuff64v.setUint32(0, v & 0xFFFFFFFF, true); - tmpBuff64v.setUint32(4, Math.floor(v / 0x100000000) , true); - - await self.write(tmpBuff64, pos); - } - - async readULE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new Uint32Array(b.buffer); - - return view[0]; - } - - async readUBE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new DataView(b.buffer); - - return view.getUint32(0, false); - } - - async readULE64(pos) { - const self = this; - const b = await self.read(8, pos); - - const view = new Uint32Array(b.buffer); - - return view[1] * 0x100000000 + view[0]; - } - - async readString(pos) { - const self = this; - - if (self.pendingClose) { - throw new Error("Reading a closing file"); - } - - let currentPosition = typeof pos == "undefined" ? self.pos : pos; - let currentPage = Math.floor(currentPosition / self.pageSize); - - let endOfStringFound = false; - let str = ""; - - while (!endOfStringFound) { - //Read page - let pagePromise = self._loadPage(currentPage); - self._triggerLoad(); - await pagePromise; - self.__statusPage("After Await (read): ", currentPage); - - let offsetOnPage = currentPosition % self.pageSize; - - const dataArray = new Uint8Array( - self.pages[currentPage].buff.buffer, - self.pages[currentPage].buff.byteOffset + offsetOnPage, - self.pageSize - offsetOnPage - ); - - let indexEndOfString = dataArray.findIndex(element => element === 0); - endOfStringFound = indexEndOfString !== -1; - - if (endOfStringFound) { - str += new TextDecoder().decode(dataArray.slice(0, indexEndOfString)); - self.pos = currentPage * this.pageSize + offsetOnPage + indexEndOfString + 1; - } else { - str += new TextDecoder().decode(dataArray); - self.pos = currentPage * this.pageSize + offsetOnPage + dataArray.length; - } - - self.pages[currentPage].pendingOps--; - self.__statusPage("After Op done: ", currentPage); - - currentPosition = self.pos; - currentPage++; - - if (self.pendingLoads.length > 0) setImmediate(self._triggerLoad.bind(self)); - } - - return str; - } - } - - function createNew$3(o) { - const initialSize = o.initialSize || 1<<20; - const fd = new MemFile$2(); - fd.o = o; - fd.o.data = new Uint8Array(initialSize); - fd.allocSize = initialSize; - fd.totalSize = 0; - fd.readOnly = false; - fd.pos = 0; - return fd; - } - - function readExisting$8(o) { - const fd = new MemFile$2(); - fd.o = o; - fd.allocSize = o.data.byteLength; - fd.totalSize = o.data.byteLength; - fd.readOnly = true; - fd.pos = 0; - return fd; - } - - const tmpBuff32$5 = new Uint8Array(4); - const tmpBuff32v$5 = new DataView(tmpBuff32$5.buffer); - const tmpBuff64$5 = new Uint8Array(8); - const tmpBuff64v$5 = new DataView(tmpBuff64$5.buffer); - - class MemFile$2 { - - constructor() { - this.pageSize = 1 << 14; // for compatibility - } - - _resizeIfNeeded(newLen) { - if (newLen > this.allocSize) { - const newAllocSize = Math.max( - this.allocSize + (1 << 20), - Math.floor(this.allocSize * 1.1), - newLen - ); - const newData = new Uint8Array(newAllocSize); - newData.set(this.o.data); - this.o.data = newData; - this.allocSize = newAllocSize; - } - } - - async write(buff, pos) { - const self =this; - if (typeof pos == "undefined") pos = self.pos; - if (this.readOnly) throw new Error("Writing a read only file"); - - this._resizeIfNeeded(pos + buff.byteLength); - - this.o.data.set(buff.slice(), pos); - - if (pos + buff.byteLength > this.totalSize) this.totalSize = pos + buff.byteLength; - - this.pos = pos + buff.byteLength; - } - - async readToBuffer(buffDest, offset, len, pos) { - const self = this; - if (typeof pos == "undefined") pos = self.pos; - if (this.readOnly) { - if (pos + len > this.totalSize) throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos + len); - - const buffSrc = new Uint8Array(this.o.data.buffer, this.o.data.byteOffset + pos, len); - - buffDest.set(buffSrc, offset); - - this.pos = pos + len; - } - - async read(len, pos) { - const self = this; - - const buff = new Uint8Array(len); - await self.readToBuffer(buff, 0, len, pos); - - return buff; - } - - close() { - if (this.o.data.byteLength != this.totalSize) { - this.o.data = this.o.data.slice(0, this.totalSize); - } - } - - async discard() { - } - - - async writeULE32(v, pos) { - const self = this; - - tmpBuff32v$5.setUint32(0, v, true); - - await self.write(tmpBuff32$5, pos); - } - - async writeUBE32(v, pos) { - const self = this; - - tmpBuff32v$5.setUint32(0, v, false); - - await self.write(tmpBuff32$5, pos); - } - - - async writeULE64(v, pos) { - const self = this; - - tmpBuff64v$5.setUint32(0, v & 0xFFFFFFFF, true); - tmpBuff64v$5.setUint32(4, Math.floor(v / 0x100000000) , true); - - await self.write(tmpBuff64$5, pos); - } - - - async readULE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new Uint32Array(b.buffer); - - return view[0]; - } - - async readUBE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new DataView(b.buffer); - - return view.getUint32(0, false); - } - - async readULE64(pos) { - const self = this; - const b = await self.read(8, pos); - - const view = new Uint32Array(b.buffer); - - return view[1] * 0x100000000 + view[0]; - } - - async readString(pos) { - const self = this; - - let currentPosition = typeof pos == "undefined" ? self.pos : pos; - - if (currentPosition > this.totalSize) { - if (this.readOnly) { - throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos); - } - const dataArray = new Uint8Array( - self.o.data.buffer, - currentPosition, - this.totalSize - currentPosition - ); - - let indexEndOfString = dataArray.findIndex(element => element === 0); - let endOfStringFound = indexEndOfString !== -1; - - let str = ""; - if (endOfStringFound) { - str = new TextDecoder().decode(dataArray.slice(0, indexEndOfString)); - self.pos = currentPosition + indexEndOfString + 1; - } else { - self.pos = currentPosition; - } - return str; - } - } - - const PAGE_SIZE$2 = 1<<22; - - function createNew$2(o) { - const initialSize = o.initialSize || 0; - const fd = new BigMemFile$2(); - fd.o = o; - const nPages = initialSize ? Math.floor((initialSize - 1) / PAGE_SIZE$2)+1 : 0; - fd.o.data = []; - for (let i=0; i0) { - const l = (o+r > PAGE_SIZE$2) ? (PAGE_SIZE$2 -o) : r; - const srcView = buff.slice(buff.byteLength - r, buff.byteLength - r + l); - const dstView = new Uint8Array(self.o.data[p].buffer, o, l); - dstView.set(srcView); - r = r-l; - p ++; - o = 0; - } - - this.pos = pos + buff.byteLength; - } - - async readToBuffer(buffDst, offset, len, pos) { - const self = this; - if (typeof pos == "undefined") pos = self.pos; - if (this.readOnly) { - if (pos + len > this.totalSize) throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos + len); - - const firstPage = Math.floor(pos / PAGE_SIZE$2); - - let p = firstPage; - let o = pos % PAGE_SIZE$2; - // Remaining bytes to read - let r = len; - while (r>0) { - // bytes to copy from this page - const l = (o+r > PAGE_SIZE$2) ? (PAGE_SIZE$2 -o) : r; - const srcView = new Uint8Array(self.o.data[p].buffer, o, l); - buffDst.set(srcView, offset+len-r); - r = r-l; - p ++; - o = 0; - } - - this.pos = pos + len; - } - - async read(len, pos) { - const self = this; - const buff = new Uint8Array(len); - - await self.readToBuffer(buff, 0, len, pos); - - return buff; - } - - close() { - } - - async discard() { - } - - - async writeULE32(v, pos) { - const self = this; - - tmpBuff32v$4.setUint32(0, v, true); - - await self.write(tmpBuff32$4, pos); - } - - async writeUBE32(v, pos) { - const self = this; - - tmpBuff32v$4.setUint32(0, v, false); - - await self.write(tmpBuff32$4, pos); - } - - - async writeULE64(v, pos) { - const self = this; - - tmpBuff64v$4.setUint32(0, v & 0xFFFFFFFF, true); - tmpBuff64v$4.setUint32(4, Math.floor(v / 0x100000000) , true); - - await self.write(tmpBuff64$4, pos); - } - - - async readULE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new Uint32Array(b.buffer); - - return view[0]; - } - - async readUBE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new DataView(b.buffer); - - return view.getUint32(0, false); - } - - async readULE64(pos) { - const self = this; - const b = await self.read(8, pos); - - const view = new Uint32Array(b.buffer); - - return view[1] * 0x100000000 + view[0]; - } - - async readString(pos) { - const self = this; - const fixedSize = 2048; - - let currentPosition = typeof pos == "undefined" ? self.pos : pos; - - if (currentPosition > this.totalSize) { - if (this.readOnly) { - throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos); - } - - let endOfStringFound = false; - let str = ""; - - while (!endOfStringFound) { - let currentPage = Math.floor(currentPosition / PAGE_SIZE$2); - let offsetOnPage = currentPosition % PAGE_SIZE$2; - - if (self.o.data[currentPage] === undefined) { - throw new Error("ERROR"); - } - - let readLength = Math.min(fixedSize, self.o.data[currentPage].length - offsetOnPage); - const dataArray = new Uint8Array(self.o.data[currentPage].buffer, offsetOnPage, readLength); - - let indexEndOfString = dataArray.findIndex(element => element === 0); - endOfStringFound = indexEndOfString !== -1; - - if (endOfStringFound) { - str += new TextDecoder().decode(dataArray.slice(0, indexEndOfString)); - self.pos = currentPage * PAGE_SIZE$2 + offsetOnPage + indexEndOfString + 1; - } else { - str += new TextDecoder().decode(dataArray); - self.pos = currentPage * PAGE_SIZE$2 + offsetOnPage + dataArray.length; - } - - currentPosition = self.pos; - } - return str; - } - } - - const { O_TRUNC: O_TRUNC$1, O_CREAT: O_CREAT$1, O_RDWR: O_RDWR$1, O_EXCL, O_RDONLY: O_RDONLY$1 } = node_fs.constants; - - const DEFAULT_CACHE_SIZE$1 = (1 << 16); - const DEFAULT_PAGE_SIZE$1 = (1 << 13); - - - async function createOverride$1(o, b, c) { - if (typeof o === "string") { - o = { - type: "file", - fileName: o, - cacheSize: b || DEFAULT_CACHE_SIZE$1, - pageSize: c || DEFAULT_PAGE_SIZE$1 - }; - } - if (o.type == "file") { - return await open$2(o.fileName, O_TRUNC$1 | O_CREAT$1 | O_RDWR$1, o.cacheSize, o.pageSize); - } else if (o.type == "mem") { - return createNew$3(o); - } else if (o.type == "bigMem") { - return createNew$2(o); - } else { - throw new Error("Invalid FastFile type: "+o.type); - } - } - - async function readExisting$6(o, b, c) { - if (o instanceof Uint8Array) { - o = { - type: "mem", - data: o - }; - } - { - if (typeof o === "string") { - const buff = await fetch(o).then( function(res) { - return res.arrayBuffer(); - }).then(function (ab) { - return new Uint8Array(ab); - }); - o = { - type: "mem", - data: buff - }; - } - } - if (o.type == "file") { - return await open$2(o.fileName, O_RDONLY$1, o.cacheSize, o.pageSize); - } else if (o.type == "mem") { - return await readExisting$8(o); - } else if (o.type == "bigMem") { - return await readExisting$7(o); - } else { - throw new Error("Invalid FastFile type: "+o.type); - } - } - - const MAX_BUFFER_SIZE = ( typeof Buffer !== "undefined" && Buffer.constants && Buffer.constants.MAX_LENGTH ) ? Buffer.constants.MAX_LENGTH : (1 << 30); - - async function readBinFile$1(fileName, type, maxVersion, cacheSize, pageSize) { - - const fd = await readExisting$6(fileName); - - const b = await fd.read(4); - let readedType = ""; - for (let i=0; i<4; i++) readedType += String.fromCharCode(b[i]); - - if (readedType != type) throw new Error(fileName + ": Invalid File format"); - - let v = await fd.readULE32(); - - if (v>maxVersion) throw new Error("Version not supported"); - - const nSections = await fd.readULE32(); - - // Scan sections - let sections = []; - for (let i=0; i1) throw new Error(fd.fileName +": Section Duplicated " +idSection); - - fd.pos = sections[idSection][0].p; - - fd.readingSection = sections[idSection][0]; - } - - async function endReadSection$1(fd, noCheck) { - if (typeof fd.readingSection === "undefined") throw new Error("Not reading a section"); - if (!noCheck) { - if (fd.pos-fd.readingSection.p != fd.readingSection.size) throw new Error("Invalid section size reading"); - } - delete fd.readingSection; - } - - async function writeBigInt(fd, n, n8, pos) { - const buff = new Uint8Array(n8); - Scalar.toRprLE(buff, 0, n, n8); - await fd.write(buff, pos); - } - - async function readBigInt$1(fd, n8, pos) { - const buff = await fd.read(n8, pos); - return Scalar.fromRprLE(buff, 0, n8); - } - - async function copySection(fdFrom, sections, fdTo, sectionId, size) { - if (typeof size === "undefined") { - size = sections[sectionId][0].size; - } - const chunkSize = fdFrom.pageSize; - await startReadUniqueSection$1(fdFrom, sections, sectionId); - await startWriteSection(fdTo, sectionId); - for (let p=0; p= 0) { - curve = await buildBn128$1(singleThread); - } else if (["BLS12381"].indexOf(normName) >= 0) { - curve = await buildBls12381$1(singleThread); - } else { - throw new Error(`Curve not supported: ${name}`); - } - return curve; - - function normalizeName(n) { - return n.toUpperCase().match(/[A-Za-z0-9]+/g).join(""); - } - - } - - var curves = /*#__PURE__*/Object.freeze({ - __proto__: null, - getCurveFromR: getCurveFromR, - getCurveFromQ: getCurveFromQ, - getCurveFromName: getCurveFromName - }); - - /** - * Internal assertion helpers. - * @module - */ - /** Asserts something is positive integer. */ - function anumber(n) { - if (!Number.isSafeInteger(n) || n < 0) - throw new Error('positive integer expected, got ' + n); - } - /** Is number an Uint8Array? Copied from utils for perf. */ - function isBytes(a) { - return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array'); - } - /** Asserts something is Uint8Array. */ - function abytes(b, ...lengths) { - if (!isBytes(b)) - throw new Error('Uint8Array expected'); - if (lengths.length > 0 && !lengths.includes(b.length)) - throw new Error('Uint8Array expected of length ' + lengths + ', got length=' + b.length); - } - /** Asserts a hash instance has not been destroyed / finished */ - function aexists(instance, checkFinished = true) { - if (instance.destroyed) - throw new Error('Hash instance has been destroyed'); - if (checkFinished && instance.finished) - throw new Error('Hash#digest() has already been called'); - } - /** Asserts output is properly-sized byte array */ - function aoutput(out, instance) { - abytes(out); - const min = instance.outputLen; - if (out.length < min) { - throw new Error('digestInto() expects output buffer of length at least ' + min); - } - } - - /** - * Utilities for hex, bytes, CSPRNG. - * @module - */ - function u32(arr) { - return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4)); - } - /** Is current platform little-endian? Most are. Big-Endian platform: IBM */ - const isLE = /* @__PURE__ */ (() => new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44)(); - // The byte swap operation for uint32 - function byteSwap(word) { - return (((word << 24) & 0xff000000) | - ((word << 8) & 0xff0000) | - ((word >>> 8) & 0xff00) | - ((word >>> 24) & 0xff)); - } - /** Conditionally byte swap if on a big-endian platform */ - const byteSwapIfBE = isLE - ? (n) => n - : (n) => byteSwap(n); - /** In place byte swap for Uint32Array */ - function byteSwap32(arr) { - for (let i = 0; i < arr.length; i++) { - arr[i] = byteSwap(arr[i]); - } - } - /** - * Convert JS string to byte array. - * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99]) - */ - function utf8ToBytes(str) { - if (typeof str !== 'string') - throw new Error('utf8ToBytes expected string, got ' + typeof str); - return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809 - } - /** - * Normalizes (non-hex) string or Uint8Array to Uint8Array. - * Warning: when Uint8Array is passed, it would NOT get copied. - * Keep in mind for future mutable operations. - */ - function toBytes(data) { - if (typeof data === 'string') - data = utf8ToBytes(data); - abytes(data); - return data; - } - /** For runtime check if class implements interface */ - class Hash { - // Safe version that clones internal state - clone() { - return this._cloneInto(); - } - } - /** Wraps hash function, creating an interface on top of it */ - function wrapConstructor(hashCons) { - const hashC = (msg) => hashCons().update(toBytes(msg)).digest(); - const tmp = hashCons(); - hashC.outputLen = tmp.outputLen; - hashC.blockLen = tmp.blockLen; - hashC.create = () => hashCons(); - return hashC; - } - function wrapConstructorWithOpts(hashCons) { - const hashC = (msg, opts) => hashCons(opts).update(toBytes(msg)).digest(); - const tmp = hashCons({}); - hashC.outputLen = tmp.outputLen; - hashC.blockLen = tmp.blockLen; - hashC.create = (opts) => hashCons(opts); - return hashC; - } - - /** - * Internal helpers for blake hash. - * @module - */ - /** - * Internal blake variable. - * For BLAKE2b, the two extra permutations for rounds 10 and 11 are SIGMA[10..11] = SIGMA[0..1]. - */ - // prettier-ignore - const SIGMA = /* @__PURE__ */ new Uint8Array([ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3, - 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4, - 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8, - 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13, - 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9, - 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11, - 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10, - 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5, - 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3, - // Blake1, unused in others - 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4, - 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8, - 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13, - 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9, - ]); - /** Class, from which others are subclassed. */ - class BLAKE extends Hash { - constructor(blockLen, outputLen, opts = {}, keyLen, saltLen, persLen) { - super(); - this.blockLen = blockLen; - this.outputLen = outputLen; - this.length = 0; - this.pos = 0; - this.finished = false; - this.destroyed = false; - anumber(blockLen); - anumber(outputLen); - anumber(keyLen); - if (outputLen < 0 || outputLen > keyLen) - throw new Error('outputLen bigger than keyLen'); - if (opts.key !== undefined && (opts.key.length < 1 || opts.key.length > keyLen)) - throw new Error('key length must be undefined or 1..' + keyLen); - if (opts.salt !== undefined && opts.salt.length !== saltLen) - throw new Error('salt must be undefined or ' + saltLen); - if (opts.personalization !== undefined && opts.personalization.length !== persLen) - throw new Error('personalization must be undefined or ' + persLen); - this.buffer = new Uint8Array(blockLen); - this.buffer32 = u32(this.buffer); - } - update(data) { - aexists(this); - // Main difference with other hashes: there is flag for last block, - // so we cannot process current block before we know that there - // is the next one. This significantly complicates logic and reduces ability - // to do zero-copy processing - const { blockLen, buffer, buffer32 } = this; - data = toBytes(data); - const len = data.length; - const offset = data.byteOffset; - const buf = data.buffer; - for (let pos = 0; pos < len;) { - // If buffer is full and we still have input (don't process last block, same as blake2s) - if (this.pos === blockLen) { - if (!isLE) - byteSwap32(buffer32); - this.compress(buffer32, 0, false); - if (!isLE) - byteSwap32(buffer32); - this.pos = 0; - } - const take = Math.min(blockLen - this.pos, len - pos); - const dataOffset = offset + pos; - // full block && aligned to 4 bytes && not last in input - if (take === blockLen && !(dataOffset % 4) && pos + take < len) { - const data32 = new Uint32Array(buf, dataOffset, Math.floor((len - pos) / 4)); - if (!isLE) - byteSwap32(data32); - for (let pos32 = 0; pos + blockLen < len; pos32 += buffer32.length, pos += blockLen) { - this.length += blockLen; - this.compress(data32, pos32, false); - } - if (!isLE) - byteSwap32(data32); - continue; - } - buffer.set(data.subarray(pos, pos + take), this.pos); - this.pos += take; - this.length += take; - pos += take; - } - return this; - } - digestInto(out) { - aexists(this); - aoutput(out, this); - const { pos, buffer32 } = this; - this.finished = true; - // Padding - this.buffer.subarray(pos).fill(0); - if (!isLE) - byteSwap32(buffer32); - this.compress(buffer32, 0, true); - if (!isLE) - byteSwap32(buffer32); - const out32 = u32(out); - this.get().forEach((v, i) => (out32[i] = byteSwapIfBE(v))); - } - digest() { - const { buffer, outputLen } = this; - this.digestInto(buffer); - const res = buffer.slice(0, outputLen); - this.destroy(); - return res; - } - _cloneInto(to) { - const { buffer, length, finished, destroyed, outputLen, pos } = this; - to || (to = new this.constructor({ dkLen: outputLen })); - to.set(...this.get()); - to.length = length; - to.finished = finished; - to.destroyed = destroyed; - to.outputLen = outputLen; - to.buffer.set(buffer); - to.pos = pos; - return to; - } - } - - /** - * Internal helpers for u64. BigUint64Array is too slow as per 2025, so we implement it using Uint32Array. - * @todo re-check https://issues.chromium.org/issues/42212588 - * @module - */ - const U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1); - const _32n = /* @__PURE__ */ BigInt(32); - function fromBig(n, le = false) { - if (le) - return { h: Number(n & U32_MASK64), l: Number((n >> _32n) & U32_MASK64) }; - return { h: Number((n >> _32n) & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 }; - } - function split(lst, le = false) { - let Ah = new Uint32Array(lst.length); - let Al = new Uint32Array(lst.length); - for (let i = 0; i < lst.length; i++) { - const { h, l } = fromBig(lst[i], le); - [Ah[i], Al[i]] = [h, l]; - } - return [Ah, Al]; - } - const toBig = (h, l) => (BigInt(h >>> 0) << _32n) | BigInt(l >>> 0); - // for Shift in [0, 32) - const shrSH = (h, _l, s) => h >>> s; - const shrSL = (h, l, s) => (h << (32 - s)) | (l >>> s); - // Right rotate for Shift in [1, 32) - const rotrSH = (h, l, s) => (h >>> s) | (l << (32 - s)); - const rotrSL = (h, l, s) => (h << (32 - s)) | (l >>> s); - // Right rotate for Shift in (32, 64), NOTE: 32 is special case. - const rotrBH = (h, l, s) => (h << (64 - s)) | (l >>> (s - 32)); - const rotrBL = (h, l, s) => (h >>> (s - 32)) | (l << (64 - s)); - // Right rotate for shift===32 (just swaps l&h) - const rotr32H = (_h, l) => l; - const rotr32L = (h, _l) => h; - // Left rotate for Shift in [1, 32) - const rotlSH = (h, l, s) => (h << s) | (l >>> (32 - s)); - const rotlSL = (h, l, s) => (l << s) | (h >>> (32 - s)); - // Left rotate for Shift in (32, 64), NOTE: 32 is special case. - const rotlBH = (h, l, s) => (l << (s - 32)) | (h >>> (64 - s)); - const rotlBL = (h, l, s) => (h << (s - 32)) | (l >>> (64 - s)); - // JS uses 32-bit signed integers for bitwise operations which means we cannot - // simple take carry out of low bit sum by shift, we need to use division. - function add(Ah, Al, Bh, Bl) { - const l = (Al >>> 0) + (Bl >>> 0); - return { h: (Ah + Bh + ((l / 2 ** 32) | 0)) | 0, l: l | 0 }; - } - // Addition with more than 2 elements - const add3L = (Al, Bl, Cl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0); - const add3H = (low, Ah, Bh, Ch) => (Ah + Bh + Ch + ((low / 2 ** 32) | 0)) | 0; - const add4L = (Al, Bl, Cl, Dl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0); - const add4H = (low, Ah, Bh, Ch, Dh) => (Ah + Bh + Ch + Dh + ((low / 2 ** 32) | 0)) | 0; - const add5L = (Al, Bl, Cl, Dl, El) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0); - const add5H = (low, Ah, Bh, Ch, Dh, Eh) => (Ah + Bh + Ch + Dh + Eh + ((low / 2 ** 32) | 0)) | 0; - // prettier-ignore - const u64 = { - fromBig, split, toBig, - shrSH, shrSL, - rotrSH, rotrSL, rotrBH, rotrBL, - rotr32H, rotr32L, - rotlSH, rotlSL, rotlBH, rotlBL, - add, add3L, add3H, add4L, add4H, add5H, add5L, - }; - var u64$1 = u64; - - /** - * Blake2b hash function. Focuses on 64-bit platforms, but in JS speed different from Blake2s is negligible. - * @module - */ - // Same as SHA-512 but LE - // prettier-ignore - const B2B_IV = /* @__PURE__ */ new Uint32Array([ - 0xf3bcc908, 0x6a09e667, 0x84caa73b, 0xbb67ae85, 0xfe94f82b, 0x3c6ef372, 0x5f1d36f1, 0xa54ff53a, - 0xade682d1, 0x510e527f, 0x2b3e6c1f, 0x9b05688c, 0xfb41bd6b, 0x1f83d9ab, 0x137e2179, 0x5be0cd19 - ]); - // Temporary buffer - const BBUF = /* @__PURE__ */ new Uint32Array(32); - // Mixing function G splitted in two halfs - function G1b(a, b, c, d, msg, x) { - // NOTE: V is LE here - const Xl = msg[x], Xh = msg[x + 1]; // prettier-ignore - let Al = BBUF[2 * a], Ah = BBUF[2 * a + 1]; // prettier-ignore - let Bl = BBUF[2 * b], Bh = BBUF[2 * b + 1]; // prettier-ignore - let Cl = BBUF[2 * c], Ch = BBUF[2 * c + 1]; // prettier-ignore - let Dl = BBUF[2 * d], Dh = BBUF[2 * d + 1]; // prettier-ignore - // v[a] = (v[a] + v[b] + x) | 0; - let ll = u64$1.add3L(Al, Bl, Xl); - Ah = u64$1.add3H(ll, Ah, Bh, Xh); - Al = ll | 0; - // v[d] = rotr(v[d] ^ v[a], 32) - ({ Dh, Dl } = { Dh: Dh ^ Ah, Dl: Dl ^ Al }); - ({ Dh, Dl } = { Dh: u64$1.rotr32H(Dh, Dl), Dl: u64$1.rotr32L(Dh, Dl) }); - // v[c] = (v[c] + v[d]) | 0; - ({ h: Ch, l: Cl } = u64$1.add(Ch, Cl, Dh, Dl)); - // v[b] = rotr(v[b] ^ v[c], 24) - ({ Bh, Bl } = { Bh: Bh ^ Ch, Bl: Bl ^ Cl }); - ({ Bh, Bl } = { Bh: u64$1.rotrSH(Bh, Bl, 24), Bl: u64$1.rotrSL(Bh, Bl, 24) }); - (BBUF[2 * a] = Al), (BBUF[2 * a + 1] = Ah); - (BBUF[2 * b] = Bl), (BBUF[2 * b + 1] = Bh); - (BBUF[2 * c] = Cl), (BBUF[2 * c + 1] = Ch); - (BBUF[2 * d] = Dl), (BBUF[2 * d + 1] = Dh); - } - function G2b(a, b, c, d, msg, x) { - // NOTE: V is LE here - const Xl = msg[x], Xh = msg[x + 1]; // prettier-ignore - let Al = BBUF[2 * a], Ah = BBUF[2 * a + 1]; // prettier-ignore - let Bl = BBUF[2 * b], Bh = BBUF[2 * b + 1]; // prettier-ignore - let Cl = BBUF[2 * c], Ch = BBUF[2 * c + 1]; // prettier-ignore - let Dl = BBUF[2 * d], Dh = BBUF[2 * d + 1]; // prettier-ignore - // v[a] = (v[a] + v[b] + x) | 0; - let ll = u64$1.add3L(Al, Bl, Xl); - Ah = u64$1.add3H(ll, Ah, Bh, Xh); - Al = ll | 0; - // v[d] = rotr(v[d] ^ v[a], 16) - ({ Dh, Dl } = { Dh: Dh ^ Ah, Dl: Dl ^ Al }); - ({ Dh, Dl } = { Dh: u64$1.rotrSH(Dh, Dl, 16), Dl: u64$1.rotrSL(Dh, Dl, 16) }); - // v[c] = (v[c] + v[d]) | 0; - ({ h: Ch, l: Cl } = u64$1.add(Ch, Cl, Dh, Dl)); - // v[b] = rotr(v[b] ^ v[c], 63) - ({ Bh, Bl } = { Bh: Bh ^ Ch, Bl: Bl ^ Cl }); - ({ Bh, Bl } = { Bh: u64$1.rotrBH(Bh, Bl, 63), Bl: u64$1.rotrBL(Bh, Bl, 63) }); - (BBUF[2 * a] = Al), (BBUF[2 * a + 1] = Ah); - (BBUF[2 * b] = Bl), (BBUF[2 * b + 1] = Bh); - (BBUF[2 * c] = Cl), (BBUF[2 * c + 1] = Ch); - (BBUF[2 * d] = Dl), (BBUF[2 * d + 1] = Dh); - } - class BLAKE2b extends BLAKE { - constructor(opts = {}) { - super(128, opts.dkLen === undefined ? 64 : opts.dkLen, opts, 64, 16, 16); - // Same as SHA-512, but LE - this.v0l = B2B_IV[0] | 0; - this.v0h = B2B_IV[1] | 0; - this.v1l = B2B_IV[2] | 0; - this.v1h = B2B_IV[3] | 0; - this.v2l = B2B_IV[4] | 0; - this.v2h = B2B_IV[5] | 0; - this.v3l = B2B_IV[6] | 0; - this.v3h = B2B_IV[7] | 0; - this.v4l = B2B_IV[8] | 0; - this.v4h = B2B_IV[9] | 0; - this.v5l = B2B_IV[10] | 0; - this.v5h = B2B_IV[11] | 0; - this.v6l = B2B_IV[12] | 0; - this.v6h = B2B_IV[13] | 0; - this.v7l = B2B_IV[14] | 0; - this.v7h = B2B_IV[15] | 0; - const keyLength = opts.key ? opts.key.length : 0; - this.v0l ^= this.outputLen | (keyLength << 8) | (0x01 << 16) | (0x01 << 24); - if (opts.salt) { - const salt = u32(toBytes(opts.salt)); - this.v4l ^= byteSwapIfBE(salt[0]); - this.v4h ^= byteSwapIfBE(salt[1]); - this.v5l ^= byteSwapIfBE(salt[2]); - this.v5h ^= byteSwapIfBE(salt[3]); - } - if (opts.personalization) { - const pers = u32(toBytes(opts.personalization)); - this.v6l ^= byteSwapIfBE(pers[0]); - this.v6h ^= byteSwapIfBE(pers[1]); - this.v7l ^= byteSwapIfBE(pers[2]); - this.v7h ^= byteSwapIfBE(pers[3]); - } - if (opts.key) { - // Pad to blockLen and update - const tmp = new Uint8Array(this.blockLen); - tmp.set(toBytes(opts.key)); - this.update(tmp); - } - } - // prettier-ignore - get() { - let { v0l, v0h, v1l, v1h, v2l, v2h, v3l, v3h, v4l, v4h, v5l, v5h, v6l, v6h, v7l, v7h } = this; - return [v0l, v0h, v1l, v1h, v2l, v2h, v3l, v3h, v4l, v4h, v5l, v5h, v6l, v6h, v7l, v7h]; - } - // prettier-ignore - set(v0l, v0h, v1l, v1h, v2l, v2h, v3l, v3h, v4l, v4h, v5l, v5h, v6l, v6h, v7l, v7h) { - this.v0l = v0l | 0; - this.v0h = v0h | 0; - this.v1l = v1l | 0; - this.v1h = v1h | 0; - this.v2l = v2l | 0; - this.v2h = v2h | 0; - this.v3l = v3l | 0; - this.v3h = v3h | 0; - this.v4l = v4l | 0; - this.v4h = v4h | 0; - this.v5l = v5l | 0; - this.v5h = v5h | 0; - this.v6l = v6l | 0; - this.v6h = v6h | 0; - this.v7l = v7l | 0; - this.v7h = v7h | 0; - } - compress(msg, offset, isLast) { - this.get().forEach((v, i) => (BBUF[i] = v)); // First half from state. - BBUF.set(B2B_IV, 16); // Second half from IV. - let { h, l } = u64$1.fromBig(BigInt(this.length)); - BBUF[24] = B2B_IV[8] ^ l; // Low word of the offset. - BBUF[25] = B2B_IV[9] ^ h; // High word. - // Invert all bits for last block - if (isLast) { - BBUF[28] = ~BBUF[28]; - BBUF[29] = ~BBUF[29]; - } - let j = 0; - const s = SIGMA; - for (let i = 0; i < 12; i++) { - G1b(0, 4, 8, 12, msg, offset + 2 * s[j++]); - G2b(0, 4, 8, 12, msg, offset + 2 * s[j++]); - G1b(1, 5, 9, 13, msg, offset + 2 * s[j++]); - G2b(1, 5, 9, 13, msg, offset + 2 * s[j++]); - G1b(2, 6, 10, 14, msg, offset + 2 * s[j++]); - G2b(2, 6, 10, 14, msg, offset + 2 * s[j++]); - G1b(3, 7, 11, 15, msg, offset + 2 * s[j++]); - G2b(3, 7, 11, 15, msg, offset + 2 * s[j++]); - G1b(0, 5, 10, 15, msg, offset + 2 * s[j++]); - G2b(0, 5, 10, 15, msg, offset + 2 * s[j++]); - G1b(1, 6, 11, 12, msg, offset + 2 * s[j++]); - G2b(1, 6, 11, 12, msg, offset + 2 * s[j++]); - G1b(2, 7, 8, 13, msg, offset + 2 * s[j++]); - G2b(2, 7, 8, 13, msg, offset + 2 * s[j++]); - G1b(3, 4, 9, 14, msg, offset + 2 * s[j++]); - G2b(3, 4, 9, 14, msg, offset + 2 * s[j++]); - } - this.v0l ^= BBUF[0] ^ BBUF[16]; - this.v0h ^= BBUF[1] ^ BBUF[17]; - this.v1l ^= BBUF[2] ^ BBUF[18]; - this.v1h ^= BBUF[3] ^ BBUF[19]; - this.v2l ^= BBUF[4] ^ BBUF[20]; - this.v2h ^= BBUF[5] ^ BBUF[21]; - this.v3l ^= BBUF[6] ^ BBUF[22]; - this.v3h ^= BBUF[7] ^ BBUF[23]; - this.v4l ^= BBUF[8] ^ BBUF[24]; - this.v4h ^= BBUF[9] ^ BBUF[25]; - this.v5l ^= BBUF[10] ^ BBUF[26]; - this.v5h ^= BBUF[11] ^ BBUF[27]; - this.v6l ^= BBUF[12] ^ BBUF[28]; - this.v6h ^= BBUF[13] ^ BBUF[29]; - this.v7l ^= BBUF[14] ^ BBUF[30]; - this.v7h ^= BBUF[15] ^ BBUF[31]; - BBUF.fill(0); - } - destroy() { - this.destroyed = true; - this.buffer32.fill(0); - this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - } - } - /** - * Blake2b hash function. Focuses on 64-bit platforms, but in JS speed different from Blake2s is negligible. - * @param msg - message that would be hashed - * @param opts - dkLen output length, key for MAC mode, salt, personalization - */ - const blake2b = /* @__PURE__ */ wrapConstructorWithOpts((opts) => new BLAKE2b(opts)); - - /* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . - */ - - - function log2( V ) - { - return( ( ( V & 0xFFFF0000 ) !== 0 ? ( V &= 0xFFFF0000, 16 ) : 0 ) | ( ( V & 0xFF00FF00 ) !== 0 ? ( V &= 0xFF00FF00, 8 ) : 0 ) | ( ( V & 0xF0F0F0F0 ) !== 0 ? ( V &= 0xF0F0F0F0, 4 ) : 0 ) | ( ( V & 0xCCCCCCCC ) !== 0 ? ( V &= 0xCCCCCCCC, 2 ) : 0 ) | ( ( V & 0xAAAAAAAA ) !== 0 ) ); - } - - - function formatHash(b, title) { - const a = new DataView(b.buffer, b.byteOffset, b.byteLength); - let S = ""; - for (let i=0; i<4; i++) { - if (i>0) S += "\n"; - S += "\t\t"; - for (let j=0; j<4; j++) { - if (j>0) S += " "; - S += a.getUint32(i*16+j*4).toString(16).padStart(8, "0"); - } - } - if (title) S = title + "\n" + S; - return S; - } - - function hashIsEqual(h1, h2) { - if (h1.byteLength != h2.byteLength) return false; - var dv1 = new Int8Array(h1); - var dv2 = new Int8Array(h2); - for (var i = 0 ; i != h1.byteLength ; i++) - { - if (dv1[i] != dv2[i]) return false; - } - return true; - } - - function cloneHasher(h) { - return h.clone(); - } - - function fromPartialHash(partial) { - // NOTE: this is unsafe and uses internal API - const buf = partial.subarray(0, 128); - const rest = u32(partial.subarray(128)); - const res = blake2b.create({ dkLen: 64 }); - res.buffer.set(buf); - (res.v0l = rest[0] | 0), (res.v0h = rest[1] | 0); - (res.v1l = rest[2] | 0), (res.v1h = rest[3] | 0); - (res.v2l = rest[4] | 0), (res.v2h = rest[5] | 0); - (res.v3l = rest[6] | 0), (res.v3h = rest[7] | 0); - (res.v4l = rest[8] | 0), (res.v4h = rest[9] | 0); - (res.v5l = rest[10] | 0), (res.v5h = rest[11] | 0); - (res.v6l = rest[12] | 0), (res.v6h = rest[13] | 0); - (res.v7l = rest[14] | 0), (res.v7h = rest[15] | 0); - const shift = 2 ** 32; - const len = rest[16] + rest[17] * shift; - const pos = rest[18] + rest[19] * shift; - res.length = len + pos; - res.pos = pos; - return res; - } - - function toPartialHash(hash){ - // NOTE: this is unsafe and uses internal API - const res = new Uint8Array(216); - const res32 = u32(res.subarray(128)); - res.set(hash.buffer); - (res32[0] = hash.v0l), (res32[1] = hash.v0h); - (res32[2] = hash.v1l), (res32[3] = hash.v1h); - (res32[4] = hash.v2l), (res32[5] = hash.v2h); - (res32[6] = hash.v3l), (res32[7] = hash.v3h); - (res32[8] = hash.v4l), (res32[9] = hash.v4h); - (res32[10] = hash.v5l), (res32[11] = hash.v5h); - (res32[12] = hash.v6l), (res32[13] = hash.v6h); - (res32[14] = hash.v7l), (res32[15] = hash.v7h); - res32[18] = hash.pos; - res32[16] = hash.length-hash.pos; - return res; - } - - async function sameRatio$2(curve, g1s, g1sx, g2s, g2sx) { - if (curve.G1.isZero(g1s)) return false; - if (curve.G1.isZero(g1sx)) return false; - if (curve.G2.isZero(g2s)) return false; - if (curve.G2.isZero(g2sx)) return false; - // return curve.F12.eq(curve.pairing(g1s, g2sx), curve.pairing(g1sx, g2s)); - const res = await curve.pairingEq(g1s, g2sx, curve.G1.neg(g1sx), g2s); - return res; - } - - - function askEntropy() { - { - return window.prompt("Enter a random text. (Entropy): ", ""); - } - } - - function getRandomBytes(n) { - let array = new Uint8Array(n); - { // Supported - globalThis.crypto.getRandomValues(array); - } - return array; - } - - async function sha256digest(data) { - { // Supported - const buffer = await globalThis.crypto.subtle.digest("SHA-256", data.buffer); - return new Uint8Array(buffer); - } - } - - /** - * @param {Uint8Array} data - * @param {number} offset - */ - function readUInt32BE(data, offset) { - return new DataView(data.buffer).getUint32(offset, false); - } - - async function getRandomRng(entropy) { - // Generate a random Rng - while (!entropy) { - entropy = await askEntropy(); - } - const hasher = blake2b.create(64); - hasher.update(getRandomBytes(64)); - const enc = new TextEncoder(); // always utf-8 - hasher.update(enc.encode(entropy)); - const hash = hasher.digest(); - - const seed = []; - for (let i=0;i<8;i++) { - seed[i] = readUInt32BE(hash, i*4); - } - const rng = new ChaCha(seed); - return rng; - } - - async function rngFromBeaconParams(beaconHash, numIterationsExp) { - let nIterationsInner; - let nIterationsOuter; - if (numIterationsExp<32) { - nIterationsInner = (1 << numIterationsExp) >>> 0; - nIterationsOuter = 1; - } else { - nIterationsInner = 0x100000000; - nIterationsOuter = (1 << (numIterationsExp-32)) >>> 0; - } - - let curHash = beaconHash; - for (let i=0; i { - res[k] = stringifyBigIntsWithField(Fr, o[k]); - }); - return res; - } else if ((typeof(o) == "bigint") || o.eq !== undefined) { - return o.toString(10); - } else { - return o; - } - } - - const HEADER_ZKEY_SECTION = 1; - - const GROTH16_PROTOCOL_ID = 1; - const PLONK_PROTOCOL_ID = 2; - const FFLONK_PROTOCOL_ID = 10; - - /* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . - */ - - // FFlonk constants - const FF_T_POL_DEG_MIN = 3; - - // ZKEY constants - const ZKEY_FF_NSECTIONS = 17; - - const ZKEY_FF_HEADER_SECTION = 2; - const ZKEY_FF_ADDITIONS_SECTION = 3; - const ZKEY_FF_A_MAP_SECTION = 4; - const ZKEY_FF_B_MAP_SECTION = 5; - const ZKEY_FF_C_MAP_SECTION = 6; - const ZKEY_FF_QL_SECTION = 7; - const ZKEY_FF_QR_SECTION = 8; - const ZKEY_FF_QM_SECTION = 9; - const ZKEY_FF_QO_SECTION = 10; - const ZKEY_FF_QC_SECTION = 11; - const ZKEY_FF_SIGMA1_SECTION = 12; - const ZKEY_FF_SIGMA2_SECTION = 13; - const ZKEY_FF_SIGMA3_SECTION = 14; - const ZKEY_FF_LAGRANGE_SECTION = 15; - const ZKEY_FF_PTAU_SECTION = 16; - const ZKEY_FF_C0_SECTION = 17; - - /* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . - */ - - async function writeHeader(fd, zkey) { - - // Write the header - /////////// - await startWriteSection(fd, 1); - await fd.writeULE32(1); // Groth - await endWriteSection(fd); - - // Write the Groth header section - /////////// - - const curve = await getCurveFromQ(zkey.q); - - await startWriteSection(fd, 2); - const primeQ = curve.q; - const n8q = (Math.floor( (Scalar.bitLength(primeQ) - 1) / 64) +1)*8; - - const primeR = curve.r; - const n8r = (Math.floor( (Scalar.bitLength(primeR) - 1) / 64) +1)*8; - - await fd.writeULE32(n8q); - await writeBigInt(fd, primeQ, n8q); - await fd.writeULE32(n8r); - await writeBigInt(fd, primeR, n8r); - await fd.writeULE32(zkey.nVars); // Total number of bars - await fd.writeULE32(zkey.nPublic); // Total number of public vars (not including ONE) - await fd.writeULE32(zkey.domainSize); // domainSize - await writeG1(fd, curve, zkey.vk_alpha_1); - await writeG1(fd, curve, zkey.vk_beta_1); - await writeG2(fd, curve, zkey.vk_beta_2); - await writeG2(fd, curve, zkey.vk_gamma_2); - await writeG1(fd, curve, zkey.vk_delta_1); - await writeG2(fd, curve, zkey.vk_delta_2); - - await endWriteSection(fd); - - - } - - async function writeG1(fd, curve, p) { - const buff = new Uint8Array(curve.G1.F.n8*2); - curve.G1.toRprLEM(buff, 0, p); - await fd.write(buff); - } - - async function writeG2(fd, curve, p) { - const buff = new Uint8Array(curve.G2.F.n8*2); - curve.G2.toRprLEM(buff, 0, p); - await fd.write(buff); - } - - async function readG1(fd, curve, toObject) { - const buff = await fd.read(curve.G1.F.n8*2); - const res = curve.G1.fromRprLEM(buff, 0); - return toObject ? curve.G1.toObject(res) : res; - } - - async function readG2(fd, curve, toObject) { - const buff = await fd.read(curve.G2.F.n8*2); - const res = curve.G2.fromRprLEM(buff, 0); - return toObject ? curve.G2.toObject(res) : res; - } - - - async function readHeader$1(fd, sections, toObject, options) { - // Read Header - ///////////////////// - await startReadUniqueSection$1(fd, sections, 1); - const protocolId = await fd.readULE32(); - await endReadSection$1(fd); - - if (protocolId === GROTH16_PROTOCOL_ID) { - return await readHeaderGroth16(fd, sections, toObject, options); - } else if (protocolId === PLONK_PROTOCOL_ID) { - return await readHeaderPlonk(fd, sections, toObject, options); - } else if (protocolId === FFLONK_PROTOCOL_ID) { - return await readHeaderFFlonk(fd, sections, toObject, options); - } else { - throw new Error("Protocol not supported: "); - } - } - - - - - async function readHeaderGroth16(fd, sections, toObject, options) { - const zkey = {}; - - zkey.protocol = "groth16"; - - // Read Groth Header - ///////////////////// - await startReadUniqueSection$1(fd, sections, 2); - const n8q = await fd.readULE32(); - zkey.n8q = n8q; - zkey.q = await readBigInt$1(fd, n8q); - - const n8r = await fd.readULE32(); - zkey.n8r = n8r; - zkey.r = await readBigInt$1(fd, n8r); - zkey.curve = await getCurveFromQ(zkey.q, options); - zkey.nVars = await fd.readULE32(); - zkey.nPublic = await fd.readULE32(); - zkey.domainSize = await fd.readULE32(); - zkey.power = log2(zkey.domainSize); - zkey.vk_alpha_1 = await readG1(fd, zkey.curve, toObject); - zkey.vk_beta_1 = await readG1(fd, zkey.curve, toObject); - zkey.vk_beta_2 = await readG2(fd, zkey.curve, toObject); - zkey.vk_gamma_2 = await readG2(fd, zkey.curve, toObject); - zkey.vk_delta_1 = await readG1(fd, zkey.curve, toObject); - zkey.vk_delta_2 = await readG2(fd, zkey.curve, toObject); - await endReadSection$1(fd); - - return zkey; - - } - - async function readHeaderPlonk(fd, sections, toObject, options) { - const zkey = {}; - - zkey.protocol = "plonk"; - - // Read Plonk Header - ///////////////////// - await startReadUniqueSection$1(fd, sections, 2); - const n8q = await fd.readULE32(); - zkey.n8q = n8q; - zkey.q = await readBigInt$1(fd, n8q); - - const n8r = await fd.readULE32(); - zkey.n8r = n8r; - zkey.r = await readBigInt$1(fd, n8r); - zkey.curve = await getCurveFromQ(zkey.q, options); - zkey.nVars = await fd.readULE32(); - zkey.nPublic = await fd.readULE32(); - zkey.domainSize = await fd.readULE32(); - zkey.power = log2(zkey.domainSize); - zkey.nAdditions = await fd.readULE32(); - zkey.nConstraints = await fd.readULE32(); - zkey.k1 = await fd.read(n8r); - zkey.k2 = await fd.read(n8r); - - zkey.Qm = await readG1(fd, zkey.curve, toObject); - zkey.Ql = await readG1(fd, zkey.curve, toObject); - zkey.Qr = await readG1(fd, zkey.curve, toObject); - zkey.Qo = await readG1(fd, zkey.curve, toObject); - zkey.Qc = await readG1(fd, zkey.curve, toObject); - zkey.S1 = await readG1(fd, zkey.curve, toObject); - zkey.S2 = await readG1(fd, zkey.curve, toObject); - zkey.S3 = await readG1(fd, zkey.curve, toObject); - zkey.X_2 = await readG2(fd, zkey.curve, toObject); - - await endReadSection$1(fd); - - return zkey; - } - - async function readHeaderFFlonk(fd, sections, toObject, options) { - const zkey = {}; - - zkey.protocol = "fflonk"; - zkey.protocolId = FFLONK_PROTOCOL_ID; - - await startReadUniqueSection$1(fd, sections, ZKEY_FF_HEADER_SECTION); - const n8q = await fd.readULE32(); - zkey.n8q = n8q; - zkey.q = await readBigInt$1(fd, n8q); - zkey.curve = await getCurveFromQ(zkey.q, options); - - const n8r = await fd.readULE32(); - zkey.n8r = n8r; - zkey.r = await readBigInt$1(fd, n8r); - - zkey.nVars = await fd.readULE32(); - zkey.nPublic = await fd.readULE32(); - zkey.domainSize = await fd.readULE32(); - zkey.power = log2(zkey.domainSize); - zkey.nAdditions = await fd.readULE32(); - zkey.nConstraints = await fd.readULE32(); - - zkey.k1 = await fd.read(n8r); - zkey.k2 = await fd.read(n8r); - - zkey.w3 = await fd.read(n8r); - zkey.w4 = await fd.read(n8r); - zkey.w8 = await fd.read(n8r); - zkey.wr = await fd.read(n8r); - - zkey.X_2 = await readG2(fd, zkey.curve, toObject); - - zkey.C0 = await readG1(fd, zkey.curve, toObject); - - await endReadSection$1(fd); - - return zkey; - } - - async function readZKey(fileName, toObject) { - const {fd, sections} = await readBinFile$1(fileName, "zkey", 1); - - const zkey = await readHeader$1(fd, sections, toObject); - - const Fr = new ZqField(zkey.r); - const Rr = Scalar.mod(Scalar.shl(1, zkey.n8r*8), zkey.r); - const Rri = Fr.inv(Rr); - const Rri2 = Fr.mul(Rri, Rri); - - let curve = await getCurveFromQ(zkey.q); - - // Read IC Section - /////////// - await startReadUniqueSection$1(fd, sections, 3); - zkey.IC = []; - for (let i=0; i<= zkey.nPublic; i++) { - const P = await readG1(fd, curve, toObject); - zkey.IC.push(P); - } - await endReadSection$1(fd); - - - // Read Coefs - /////////// - await startReadUniqueSection$1(fd, sections, 4); - const nCCoefs = await fd.readULE32(); - zkey.ccoefs = []; - for (let i=0; i0) { - const paramsBuff = new Uint8Array(params); - await fd.writeULE32(paramsBuff.byteLength); - await fd.write(paramsBuff); - } else { - await fd.writeULE32(0); - } - - } - - async function writeMPCParams(fd, curve, mpcParams) { - await startWriteSection(fd, 10); - await fd.write(mpcParams.csHash); - await fd.writeULE32(mpcParams.contributions.length); - for (let i=0; i. - */ - - - async function write(fd, witness, prime) { - - await startWriteSection(fd, 1); - const n8 = (Math.floor( (Scalar.bitLength(prime) - 1) / 64) +1)*8; - await fd.writeULE32(n8); - await writeBigInt(fd, prime, n8); - await fd.writeULE32(witness.length); - await endWriteSection(fd); - - await startWriteSection(fd, 2); - for (let i=0; i. - */ - const {stringifyBigInts: stringifyBigInts$4} = utils$6; - - async function groth16Prove(zkeyFileName, witnessFileName, logger, options) { - - if (logger) monitorMemoryUsage(logger, 50); - const {fd: fdWtns, sections: sectionsWtns} = await readBinFile$1(witnessFileName, "wtns", 2); - - const wtns = await readHeader(fdWtns, sectionsWtns); - - const {fd: fdZKey, sections: sectionsZKey} = await readBinFile$1(zkeyFileName, "zkey", 2); - - const zkey = await readHeader$1(fdZKey, sectionsZKey, undefined, options); - - if (zkey.protocol != "groth16") { - throw new Error("zkey file is not groth16"); - } - - if (!Scalar.eq(zkey.r, wtns.q)) { - throw new Error("Curve of the witness does not match the curve of the proving key"); - } - - if (wtns.nWitness != zkey.nVars) { - throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}`); - } - - const curve = zkey.curve; - const Fr = curve.Fr; - const G1 = curve.G1; - const G2 = curve.G2; - - const power = log2(zkey.domainSize); - - if (logger) logger.debug("Reading Wtns"); - const buffWitness = await readSection$1(fdWtns, sectionsWtns, 2); - - let resH; - let resHPromise; - let buffPodd_T; - - let abcPromise = (async function (){ - let buffA_T, buffB_T, buffC_T; - - await (async function (){ - if (logger) logger.debug("Reading Coeffs"); - console.time("buildABC_outer"); - const buffCoeffs = await readSection$1(fdZKey, sectionsZKey, 4); - - if (logger) logger.debug("Building ABC"); - - options = options || {}; - //options.buildABC="wasm1"; // for testing - - if (options && options.buildABC==="wasm") { - // build ABC in WASM - [buffA_T, buffB_T, buffC_T] = await buildABC(curve, zkey, buffWitness, buffCoeffs, logger); - } else if (options && options.buildABC==="wasm1") { - // build ABC in WASM - [buffA_T, buffB_T, buffC_T] = await buildABCWASM1(curve, zkey, buffWitness, buffCoeffs, logger); - } else { - // default, build ABC in JS - [buffA_T, buffB_T, buffC_T] = await buildABC1(curve, zkey, buffWitness, buffCoeffs, logger); - } - console.timeEnd("buildABC_outer"); - })(); - - console.time("abcPromise"); - - if (globalThis.gc) {globalThis.gc();} - - const inc = power === Fr.s ? curve.Fr.shift : curve.Fr.w[power+1]; - - let buffAodd_T; - await (async function () { - let buffA = await Fr.ifft(buffA_T, "", "", logger, "IFFT_A"); - buffA_T = null; - const buffAodd = await Fr.batchApplyKey(buffA, Fr.e(1), inc); - buffAodd_T = await Fr.fft(buffAodd, "", "", logger, "FFT_A"); - })(); - - let buffBodd_T; - await (async function () { - const buffB = await Fr.ifft(buffB_T, "", "", logger, "IFFT_B"); - buffB_T = null; - const buffBodd = await Fr.batchApplyKey(buffB, Fr.e(1), inc); - buffBodd_T = await Fr.fft(buffBodd, "", "", logger, "FFT_B"); - })(); - - let buffCodd_T; - await (async function () { - const buffC = await Fr.ifft(buffC_T, "", "", logger, "IFFT_C"); - buffC_T = null; - const buffCodd = await Fr.batchApplyKey(buffC, Fr.e(1), inc); - buffCodd_T = await Fr.fft(buffCodd, "", "", logger, "FFT_C"); - })(); - - if (logger) logger.debug("Join ABC"); - buffPodd_T = await joinABC(curve, zkey, buffAodd_T, buffBodd_T, buffCodd_T, logger); - if (logger) logger.debug("Join ABC finished"); - buffAodd_T = null; - buffBodd_T = null; - buffCodd_T = null; - - if (globalThis.gc) {globalThis.gc();} - console.timeEnd("abcPromise"); - })(); - //await abcPromise; - - let proof = {}; - - async function calcPiA(){ - if (logger) logger.debug("Reading A Points"); - const buffBasesA = await readSection$1(fdZKey, sectionsZKey, 5); - console.time("Calculate PiA"); - proof.pi_a = await curve.G1.multiExpAffine(buffBasesA, buffWitness, logger, "multiexp A"); - console.timeEnd("Calculate PiA"); - } - - let piaPromise = calcPiA(); - //await piaPromise; - - let pib1; - - async function calcPiB1() { - if (logger) logger.debug("Reading B1 Points"); - const buffBasesB1 = await readSection$1(fdZKey, sectionsZKey, 6); - console.time("Calculate PiB1"); - pib1 = await curve.G1.multiExpAffine(buffBasesB1, buffWitness, logger, "multiexp B1"); - console.timeEnd("Calculate PiB1"); - } - - let pib1Promise = calcPiB1(); - //await pib1Promise; - - async function calcPiB() { - if (logger) logger.debug("Reading B2 Points"); - const buffBasesB2 = await readSection$1(fdZKey, sectionsZKey, 7); - console.time("Calculate PiB"); - proof.pi_b = await curve.G2.multiExpAffine(buffBasesB2, buffWitness, logger, "multiexp B2"); - console.timeEnd("Calculate PiB"); - } - - let pibPromise = calcPiB(); - //await pibPromise; - - let picPromise = (async function (){ - if (logger) logger.debug("Reading C Points"); - const buffBasesC = await readSection$1(fdZKey, sectionsZKey, 8); - console.time("Calculate PiC"); - proof.pi_c = await curve.G1.multiExpAffine(buffBasesC, buffWitness.slice((zkey.nPublic+1)*curve.Fr.n8), logger, "multiexp C"); - console.timeEnd("Calculate PiC"); - })(); - //await picPromise; - - - resHPromise = (async function (){ - if (logger) logger.debug("Reading H Points"); - await abcPromise; - console.time("resHPromise"); - const buffBasesH = await readSection$1(fdZKey, sectionsZKey, 9); - //await Promise.all([abcPromise, piaPromise, pib1Promise, pibPromise, picPromise]); - resH = await curve.G1.multiExpAffine(buffBasesH, buffPodd_T, logger, "multiexp H"); - //buffPodd_T = null; - console.timeEnd("resHPromise"); - })(); - //await resHPromise; - - - const r = curve.Fr.random(); - const s = curve.Fr.random(); - - await piaPromise; - proof.pi_a = G1.add( proof.pi_a, zkey.vk_alpha_1 ); - proof.pi_a = G1.add( proof.pi_a, G1.timesFr( zkey.vk_delta_1, r )); - - await pibPromise; - proof.pi_b = G2.add( proof.pi_b, zkey.vk_beta_2 ); - proof.pi_b = G2.add( proof.pi_b, G2.timesFr( zkey.vk_delta_2, s )); - - await pib1Promise; - pib1 = G1.add( pib1, zkey.vk_beta_1 ); - pib1 = G1.add( pib1, G1.timesFr( zkey.vk_delta_1, s )); - - await Promise.all([picPromise, resHPromise]); - proof.pi_c = G1.add(proof.pi_c, resH); - - - proof.pi_c = G1.add( proof.pi_c, G1.timesFr( proof.pi_a, s )); - proof.pi_c = G1.add( proof.pi_c, G1.timesFr( pib1, r )); - proof.pi_c = G1.add( proof.pi_c, G1.timesFr( zkey.vk_delta_1, Fr.neg(Fr.mul(r,s) ))); - - - let publicSignals = []; - - for (let i=1; i<= zkey.nPublic; i++) { - const b = buffWitness.slice(i*Fr.n8, i*Fr.n8+Fr.n8); - publicSignals.push(Scalar.fromRprLE(b)); - } - - proof.pi_a = G1.toObject(G1.toAffine(proof.pi_a)); - proof.pi_b = G2.toObject(G2.toAffine(proof.pi_b)); - proof.pi_c = G1.toObject(G1.toAffine(proof.pi_c)); - - proof.protocol = "groth16"; - proof.curve = curve.name; - - await fdZKey.close(); - await fdWtns.close(); - - proof = stringifyBigInts$4(proof); - publicSignals = stringifyBigInts$4(publicSignals); - - return {proof, publicSignals}; - } - - - async function buildABC1(curve, zkey, witness, coeffs, logger) { - const n8 = curve.Fr.n8; - const sCoef = 4*3 + zkey.n8r; - const nCoef = (coeffs.byteLength-4) / sCoef; - - const outBuffA = new BigBuffer(zkey.domainSize * n8); - const outBuffB = new BigBuffer(zkey.domainSize * n8); - const outBuffC = new BigBuffer(zkey.domainSize * n8); - - const outBuf = [ outBuffA, outBuffB ]; - for (let i=0; i 2**16) { - concurrency*=2; - elementsPerChunk = Math.floor(zkey.domainSize/concurrency); - } - console.log("@@@ new elementsPerChunk", elementsPerChunk); - - - const promises = []; - - const cutPoints = []; - for (let i=0; i1) { - const promises2 = []; - for (let i=0; i v) { - n = k - 1; - } else if (va < v) { - m = k + 1; - } else { - n = k; - } - } - return 4 + m*sCoef; - } - } - - - // buildABCWASM1 is single-threaded implementation of buildABS using wasm - // It has much better memory usage than multithreaded wasm implementation. - // It's much faster than pure js one, but uses much more memory. - async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { - console.time("buildABC"); - const concurrency = 1;//curve.tm.concurrency; - const sCoef = 4 * 3 + zkey.n8r; - - let getUint32; - - if (coeffs instanceof BigBuffer) { - const coeffsDV = []; - const PAGE_LEN = coeffs.buffers[0].length; - for (let i = 0; i < coeffs.buffers.length; i++) { - coeffsDV.push(new DataView(coeffs.buffers[i].buffer)); - } - getUint32 = function (pos) { - return coeffsDV[Math.floor(pos / PAGE_LEN)].getUint32(pos % PAGE_LEN, true); - }; - } else { - const coeffsDV = new DataView(coeffs.buffer, coeffs.byteOffset, coeffs.byteLength); - getUint32 = function (pos) { - return coeffsDV.getUint32(pos, true); - }; - } - - const elementsPerChunk = Math.floor((zkey.domainSize - 1) / concurrency) + 1; - const promises = []; - - const cutPoints = []; - for (let i = 0; i < concurrency; i++) { - cutPoints.push(getCutPoint(Math.floor(i * elementsPerChunk))); - } - cutPoints.push(coeffs.byteLength); - - //const chunkSize = 2**18; - const chunkSize = elementsPerChunk; - - console.log("zkey.domainSize", zkey.domainSize); - console.log("concurrency", concurrency); - console.log("elementsPerChunk", elementsPerChunk); - console.log("chunkSize", chunkSize); - - for (let s = 0; s < zkey.nVars; s += chunkSize) { - if (logger) logger.debug(`QAP: ${s}/${zkey.nVars}`); - const ns = Math.min(zkey.nVars - s, chunkSize); - - console.log("ns", ns); - - //let i=0; - for (let i = 0; i < concurrency; i++) { - let n; - if (i < concurrency - 1) { - n = elementsPerChunk; - } else { - n = zkey.domainSize - i * elementsPerChunk; - } - if (n === 0) continue; - - const task = []; - - const coeffsBuff = coeffs.slice(cutPoints[i], cutPoints[i + 1]); - const witnessBuff = witness.slice(s * curve.Fr.n8, (s + ns) * curve.Fr.n8); - - task.push({cmd: "ALLOCSET", var: 0, buff: coeffsBuff}); - task.push({cmd: "ALLOCSET", var: 1, buff: witnessBuff}); - task.push({cmd: "ALLOC", var: 2, len: n * curve.Fr.n8}); - task.push({cmd: "ALLOC", var: 3, len: n * curve.Fr.n8}); - task.push({cmd: "ALLOC", var: 4, len: n * curve.Fr.n8}); - task.push({ - cmd: "CALL", fnName: "qap_buildABC", params: [ - {var: 0}, - {val: (cutPoints[i + 1] - cutPoints[i]) / sCoef}, - {var: 1}, - {var: 2}, - {var: 3}, - {var: 4}, - {val: i * elementsPerChunk}, - {val: n}, - {val: s}, - {val: ns} - ] - }); - task.push({cmd: "GET", out: 0, var: 2, len: n * curve.Fr.n8}); - task.push({cmd: "GET", out: 1, var: 3, len: n * curve.Fr.n8}); - task.push({cmd: "GET", out: 2, var: 4, len: n * curve.Fr.n8}); - //task.push({cmd: "TERMINATE"}); // to free memory immediately - //promises.push(curve.tm.queueAction(task)); - promises.push(curve.tm.queueAction(task, [coeffsBuff.buffer, witnessBuff.buffer])); - } - } - - let result = await Promise.all(promises); - - - console.log("result.length", result.length); - console.log("result", result); - - const nGroups = result.length / concurrency; - - console.log("nGroups", nGroups); - let result2; - if (nGroups > 1) { - const promises2 = []; - for (let i = 0; i < concurrency; i++) { - const task = []; - task.push({cmd: "ALLOC", var: 0, len: result[i][0].byteLength}); - task.push({cmd: "ALLOC", var: 1, len: result[i][0].byteLength}); - for (let m = 0; m < 3; m++) { - task.push({cmd: "SET", var: 0, buff: result[i][m]}); - //transfers.push(result[i][m].buffer); - for (let s = 1; s < nGroups; s++) { - task.push({cmd: "SET", var: 1, buff: result[s * concurrency + i][m]}); - //transfers.push(result[s*concurrency + i][m].buffer); - task.push({ - cmd: "CALL", fnName: "qap_batchAdd", params: [ - {var: 0}, - {var: 1}, - {val: result[i][m].length / curve.Fr.n8}, - {var: 0} - ] - }); - } - task.push({cmd: "GET", out: m, var: 0, len: result[i][m].length}); - //task.push({cmd: "TERMINATE"}); // to free memory immediately - } - console.log("task.length", task.length); - //promises2.push(curve.tm.queueAction(task)); - promises2.push(curve.tm.queueAction(task, result.buffer)); - } - console.log("promises2.length", promises2.length); - result2 = await Promise.all(promises2); - result = result2; - } - - //console.log("result", result); - //console.log("result2", result2); - //result = result2 || result; - - const outBuffA = new BigBuffer(zkey.domainSize * curve.Fr.n8); - const outBuffB = new BigBuffer(zkey.domainSize * curve.Fr.n8); - const outBuffC = new BigBuffer(zkey.domainSize * curve.Fr.n8); - let p = 0; - for (let i = 0; i < result.length; i++) { - outBuffA.set(result[i][0], p); - outBuffB.set(result[i][1], p); - outBuffC.set(result[i][2], p); - p += result[i][0].byteLength; - } - - console.timeEnd("buildABC"); - - return [outBuffA, outBuffB, outBuffC]; - - function getCutPoint(v) { - let m = 0; - let n = getUint32(0); - while (m < n) { - let k = Math.floor((n + m) / 2); - const va = getUint32(4 + k * sCoef + 4); - if (va > v) { - n = k - 1; - } else if (va < v) { - m = k + 1; - } else { - n = k; - } - } - return 4 + m * sCoef; - } - } - - - async function joinABC(curve, zkey, a, b, c, logger) { - console.time("joinABC"); - const MAX_CHUNK_SIZE = 1 << 16; - - const n8 = curve.Fr.n8; - const nElements = Math.floor(a.byteLength / curve.Fr.n8); - - const promises = []; - - for (let i=0; i { - memUsage(logger); - }, interval); - } - - async function open$1(fileName, openFlags, cacheSize, pageSize) { - cacheSize = cacheSize || 4096*64; - if (typeof openFlags !== "number" && ["w+", "wx+", "r", "ax+", "a+"].indexOf(openFlags) <0) - throw new Error("Invalid open option"); - const fd =await fs.promises.open(fileName, openFlags); - - const stats = await fd.stat(); - - return new FastFile$1(fd, stats, cacheSize, pageSize, fileName); - } - - - class FastFile$1 { - - constructor(fd, stats, cacheSize, pageSize, fileName) { - this.fileName = fileName; - this.fd = fd; - this.pos = 0; - this.pageSize = pageSize || (1 << 8); - while (this.pageSize < stats.blksize) { - this.pageSize *= 2; - } - this.totalSize = stats.size; - this.totalPages = Math.floor((stats.size -1) / this.pageSize)+1; - this.maxPagesLoaded = Math.floor( cacheSize / this.pageSize)+1; - this.pages = {}; - this.pendingLoads = []; - this.writing = false; - this.reading = false; - this.avBuffs = []; - this.history = {}; - } - - _loadPage(p) { - const self = this; - const P = new Promise((resolve, reject)=> { - self.pendingLoads.push({ - page: p, - resolve: resolve, - reject: reject - }); - }); - self.__statusPage("After Load request: ", p); - return P; - } - - __statusPage(s, p) { - const logEntry = []; - const self=this; - if (!self.logHistory) return; - logEntry.push("==" + s+ " " +p); - let S = ""; - for (let i=0; i " + self.history[p][i][j]); - } - } - } - - - - _triggerLoad() { - const self = this; - - if (self.reading) return; - if (self.pendingLoads.length==0) return; - - const pageIdxs = Object.keys(self.pages); - - const deletablePages = []; - for (let i=0; i0) && - ( (typeof self.pages[self.pendingLoads[0].page] != "undefined" ) - ||( (freePages>0) - ||(deletablePages.length>0)))) { - const load = self.pendingLoads.shift(); - if (typeof self.pages[load.page] != "undefined") { - self.pages[load.page].pendingOps ++; - const idx = deletablePages.indexOf(load.page); - if (idx>=0) deletablePages.splice(idx, 1); - if (self.pages[load.page].loading) { - self.pages[load.page].loading.push(load); - } else { - load.resolve(); - } - self.__statusPage("After Load (cached): ", load.page); - - } else { - if (freePages) { - freePages--; - } else { - const fp = deletablePages.shift(); - self.__statusPage("Before Unload: ", fp); - self.avBuffs.unshift(self.pages[fp]); - delete self.pages[fp]; - self.__statusPage("After Unload: ", fp); - } - - if (load.page>=self.totalPages) { - self.pages[load.page] = getNewPage(); - load.resolve(); - self.__statusPage("After Load (new): ", load.page); - } else { - self.reading = true; - self.pages[load.page] = getNewPage(); - self.pages[load.page].loading = [load]; - ops.push(self.fd.read(self.pages[load.page].buff, 0, self.pageSize, load.page*self.pageSize).then((res)=> { - self.pages[load.page].size = res.bytesRead; - const loading = self.pages[load.page].loading; - delete self.pages[load.page].loading; - for (let i=0; i { - load.reject(err); - })); - self.__statusPage("After Load (loading): ", load.page); - } - } - } - // if (ops.length>1) console.log(ops.length); - - Promise.all(ops).then( () => { - self.reading = false; - if (self.pendingLoads.length>0) setImmediate(self._triggerLoad.bind(self)); - self._tryClose(); - }); - - function getNewPage() { - if (self.avBuffs.length>0) { - const p = self.avBuffs.shift(); - p.dirty = false; - p.pendingOps = 1; - p.size =0; - return p; - } else { - return { - dirty: false, - buff: new Uint8Array(self.pageSize), - pendingOps: 1, - size: 0 - }; - } - } - - } - - - _triggerWrite() { - const self = this; - if (self.writing) return; - - const pageIdxs = Object.keys(self.pages); - - const ops = []; - - for (let i=0; i { - page.writing = false; - return; - }, (err) => { - console.log("ERROR Writing: "+err); - self.error = err; - self._tryClose(); - })); - } - } - - if (self.writing) { - Promise.all(ops).then( () => { - self.writing = false; - setImmediate(self._triggerWrite.bind(self)); - self._tryClose(); - if (self.pendingLoads.length>0) setImmediate(self._triggerLoad.bind(self)); - }); - } - } - - _getDirtyPage() { - for (let p in this.pages) { - if (this.pages[p].dirty) return p; - } - return -1; - } - - async write(buff, pos) { - if (buff.byteLength == 0) return; - const self = this; - /* - if (buff.byteLength > self.pageSize*self.maxPagesLoaded*0.8) { - const cacheSize = Math.floor(buff.byteLength * 1.1); - this.maxPagesLoaded = Math.floor( cacheSize / self.pageSize)+1; - } - */ - if (typeof pos == "undefined") pos = self.pos; - self.pos = pos+buff.byteLength; - if (self.totalSize < pos + buff.byteLength) self.totalSize = pos + buff.byteLength; - if (self.pendingClose) - throw new Error("Writing a closing file"); - const firstPage = Math.floor(pos / self.pageSize); - const lastPage = Math.floor((pos + buff.byteLength -1) / self.pageSize); - - const pagePromises = []; - for (let i=firstPage; i<=lastPage; i++) pagePromises.push(self._loadPage(i)); - self._triggerLoad(); - - let p = firstPage; - let o = pos % self.pageSize; - let r = buff.byteLength; - while (r>0) { - await pagePromises[p-firstPage]; - const l = (o+r > self.pageSize) ? (self.pageSize -o) : r; - const srcView = buff.slice( buff.byteLength - r, buff.byteLength - r + l); - const dstView = new Uint8Array(self.pages[p].buff.buffer, o, l); - dstView.set(srcView); - self.pages[p].dirty = true; - self.pages[p].pendingOps --; - self.pages[p].size = Math.max(o+l, self.pages[p].size); - if (p>=self.totalPages) { - self.totalPages = p+1; - } - r = r-l; - p ++; - o = 0; - if (!self.writing) setImmediate(self._triggerWrite.bind(self)); - } - } - - async read(len, pos) { - const self = this; - let buff = new Uint8Array(len); - await self.readToBuffer(buff, 0, len, pos); - - return buff; - } - - async readToBuffer(buffDst, offset, len, pos) { - if (len == 0) { - return; - } - const self = this; - if (len > self.pageSize*self.maxPagesLoaded*0.8) { - const cacheSize = Math.floor(len * 1.1); - this.maxPagesLoaded = Math.floor( cacheSize / self.pageSize)+1; - } - if (typeof pos == "undefined") pos = self.pos; - self.pos = pos+len; - if (self.pendingClose) - throw new Error("Reading a closing file"); - const firstPage = Math.floor(pos / self.pageSize); - const lastPage = Math.floor((pos + len -1) / self.pageSize); - - const pagePromises = []; - for (let i=firstPage; i<=lastPage; i++) pagePromises.push(self._loadPage(i)); - - self._triggerLoad(); - - let p = firstPage; - let o = pos % self.pageSize; - // Remaining bytes to read - let r = pos + len > self.totalSize ? len - (pos + len - self.totalSize): len; - while (r>0) { - await pagePromises[p - firstPage]; - self.__statusPage("After Await (read): ", p); - - // bytes to copy from this page - const l = (o+r > self.pageSize) ? (self.pageSize -o) : r; - const srcView = new Uint8Array(self.pages[p].buff.buffer, self.pages[p].buff.byteOffset + o, l); - buffDst.set(srcView, offset+len-r); - self.pages[p].pendingOps --; - - self.__statusPage("After Op done: ", p); - - r = r-l; - p ++; - o = 0; - if (self.pendingLoads.length>0) setImmediate(self._triggerLoad.bind(self)); - } - - this.pos = pos + len; - - } - - - _tryClose() { - const self = this; - if (!self.pendingClose) return; - if (self.error) { - self.pendingCloseReject(self.error); - } - const p = self._getDirtyPage(); - if ((p>=0) || (self.writing) || (self.reading) || (self.pendingLoads.length>0)) return; - self.pendingClose(); - } - - close() { - const self = this; - if (self.pendingClose) - throw new Error("Closing the file twice"); - return new Promise((resolve, reject) => { - self.pendingClose = resolve; - self.pendingCloseReject = reject; - self._tryClose(); - }).then(()=> { - self.fd.close(); - }, (err) => { - self.fd.close(); - throw (err); - }); - } - - async discard() { - const self = this; - await self.close(); - await fs.promises.unlink(this.fileName); - } - - async writeULE32(v, pos) { - const self = this; - const tmpBuff32 = new Uint8Array(4); - const tmpBuff32v = new DataView(tmpBuff32.buffer); - - tmpBuff32v.setUint32(0, v, true); - - await self.write(tmpBuff32, pos); - } - - async writeUBE32(v, pos) { - const self = this; - - const tmpBuff32 = new Uint8Array(4); - const tmpBuff32v = new DataView(tmpBuff32.buffer); - - tmpBuff32v.setUint32(0, v, false); - - await self.write(tmpBuff32, pos); - } - - - async writeULE64(v, pos) { - const self = this; - - const tmpBuff64 = new Uint8Array(8); - const tmpBuff64v = new DataView(tmpBuff64.buffer); - - tmpBuff64v.setUint32(0, v & 0xFFFFFFFF, true); - tmpBuff64v.setUint32(4, Math.floor(v / 0x100000000) , true); - - await self.write(tmpBuff64, pos); - } - - async readULE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new Uint32Array(b.buffer); - - return view[0]; - } - - async readUBE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new DataView(b.buffer); - - return view.getUint32(0, false); - } - - async readULE64(pos) { - const self = this; - const b = await self.read(8, pos); - - const view = new Uint32Array(b.buffer); - - return view[1] * 0x100000000 + view[0]; - } - - async readString(pos) { - const self = this; - - if (self.pendingClose) { - throw new Error("Reading a closing file"); - } - - let currentPosition = typeof pos == "undefined" ? self.pos : pos; - let currentPage = Math.floor(currentPosition / self.pageSize); - - let endOfStringFound = false; - let str = ""; - - while (!endOfStringFound) { - //Read page - let pagePromise = self._loadPage(currentPage); - self._triggerLoad(); - await pagePromise; - self.__statusPage("After Await (read): ", currentPage); - - let offsetOnPage = currentPosition % self.pageSize; - - const dataArray = new Uint8Array( - self.pages[currentPage].buff.buffer, - self.pages[currentPage].buff.byteOffset + offsetOnPage, - self.pageSize - offsetOnPage - ); - - let indexEndOfString = dataArray.findIndex(element => element === 0); - endOfStringFound = indexEndOfString !== -1; - - if (endOfStringFound) { - str += new TextDecoder().decode(dataArray.slice(0, indexEndOfString)); - self.pos = currentPage * this.pageSize + offsetOnPage + indexEndOfString + 1; - } else { - str += new TextDecoder().decode(dataArray); - self.pos = currentPage * this.pageSize + offsetOnPage + dataArray.length; - } - - self.pages[currentPage].pendingOps--; - self.__statusPage("After Op done: ", currentPage); - - currentPosition = self.pos; - currentPage++; - - if (self.pendingLoads.length > 0) setImmediate(self._triggerLoad.bind(self)); - } - - return str; - } - } - - function createNew$1(o) { - const initialSize = o.initialSize || 1<<20; - const fd = new MemFile$1(); - fd.o = o; - fd.o.data = new Uint8Array(initialSize); - fd.allocSize = initialSize; - fd.totalSize = 0; - fd.readOnly = false; - fd.pos = 0; - return fd; - } - - function readExisting$5(o) { - const fd = new MemFile$1(); - fd.o = o; - fd.allocSize = o.data.byteLength; - fd.totalSize = o.data.byteLength; - fd.readOnly = true; - fd.pos = 0; - return fd; - } - - const tmpBuff32$3 = new Uint8Array(4); - const tmpBuff32v$3 = new DataView(tmpBuff32$3.buffer); - const tmpBuff64$3 = new Uint8Array(8); - const tmpBuff64v$3 = new DataView(tmpBuff64$3.buffer); - - class MemFile$1 { - - constructor() { - this.pageSize = 1 << 14; // for compatibility - } - - _resizeIfNeeded(newLen) { - if (newLen > this.allocSize) { - const newAllocSize = Math.max( - this.allocSize + (1 << 20), - Math.floor(this.allocSize * 1.1), - newLen - ); - const newData = new Uint8Array(newAllocSize); - newData.set(this.o.data); - this.o.data = newData; - this.allocSize = newAllocSize; - } - } - - async write(buff, pos) { - const self =this; - if (typeof pos == "undefined") pos = self.pos; - if (this.readOnly) throw new Error("Writing a read only file"); - - this._resizeIfNeeded(pos + buff.byteLength); - - this.o.data.set(buff.slice(), pos); - - if (pos + buff.byteLength > this.totalSize) this.totalSize = pos + buff.byteLength; - - this.pos = pos + buff.byteLength; - } - - async readToBuffer(buffDest, offset, len, pos) { - const self = this; - if (typeof pos == "undefined") pos = self.pos; - if (this.readOnly) { - if (pos + len > this.totalSize) throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos + len); - - const buffSrc = new Uint8Array(this.o.data.buffer, this.o.data.byteOffset + pos, len); - - buffDest.set(buffSrc, offset); - - this.pos = pos + len; - } - - async read(len, pos) { - const self = this; - - const buff = new Uint8Array(len); - await self.readToBuffer(buff, 0, len, pos); - - return buff; - } - - close() { - if (this.o.data.byteLength != this.totalSize) { - this.o.data = this.o.data.slice(0, this.totalSize); - } - } - - async discard() { - } - - - async writeULE32(v, pos) { - const self = this; - - tmpBuff32v$3.setUint32(0, v, true); - - await self.write(tmpBuff32$3, pos); - } - - async writeUBE32(v, pos) { - const self = this; - - tmpBuff32v$3.setUint32(0, v, false); - - await self.write(tmpBuff32$3, pos); - } - - - async writeULE64(v, pos) { - const self = this; - - tmpBuff64v$3.setUint32(0, v & 0xFFFFFFFF, true); - tmpBuff64v$3.setUint32(4, Math.floor(v / 0x100000000) , true); - - await self.write(tmpBuff64$3, pos); - } - - - async readULE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new Uint32Array(b.buffer); - - return view[0]; - } - - async readUBE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new DataView(b.buffer); - - return view.getUint32(0, false); - } - - async readULE64(pos) { - const self = this; - const b = await self.read(8, pos); - - const view = new Uint32Array(b.buffer); - - return view[1] * 0x100000000 + view[0]; - } - - async readString(pos) { - const self = this; - - let currentPosition = typeof pos == "undefined" ? self.pos : pos; - - if (currentPosition > this.totalSize) { - if (this.readOnly) { - throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos); - } - const dataArray = new Uint8Array( - self.o.data.buffer, - currentPosition, - this.totalSize - currentPosition - ); - - let indexEndOfString = dataArray.findIndex(element => element === 0); - let endOfStringFound = indexEndOfString !== -1; - - let str = ""; - if (endOfStringFound) { - str = new TextDecoder().decode(dataArray.slice(0, indexEndOfString)); - self.pos = currentPosition + indexEndOfString + 1; - } else { - self.pos = currentPosition; - } - return str; - } - } - - const PAGE_SIZE$1 = 1<<22; - - function createNew(o) { - const initialSize = o.initialSize || 0; - const fd = new BigMemFile$1(); - fd.o = o; - const nPages = initialSize ? Math.floor((initialSize - 1) / PAGE_SIZE$1)+1 : 0; - fd.o.data = []; - for (let i=0; i0) { - const l = (o+r > PAGE_SIZE$1) ? (PAGE_SIZE$1 -o) : r; - const srcView = buff.slice(buff.byteLength - r, buff.byteLength - r + l); - const dstView = new Uint8Array(self.o.data[p].buffer, o, l); - dstView.set(srcView); - r = r-l; - p ++; - o = 0; - } - - this.pos = pos + buff.byteLength; - } - - async readToBuffer(buffDst, offset, len, pos) { - const self = this; - if (typeof pos == "undefined") pos = self.pos; - if (this.readOnly) { - if (pos + len > this.totalSize) throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos + len); - - const firstPage = Math.floor(pos / PAGE_SIZE$1); - - let p = firstPage; - let o = pos % PAGE_SIZE$1; - // Remaining bytes to read - let r = len; - while (r>0) { - // bytes to copy from this page - const l = (o+r > PAGE_SIZE$1) ? (PAGE_SIZE$1 -o) : r; - const srcView = new Uint8Array(self.o.data[p].buffer, o, l); - buffDst.set(srcView, offset+len-r); - r = r-l; - p ++; - o = 0; - } - - this.pos = pos + len; - } - - async read(len, pos) { - const self = this; - const buff = new Uint8Array(len); - - await self.readToBuffer(buff, 0, len, pos); - - return buff; - } - - close() { - } - - async discard() { - } - - - async writeULE32(v, pos) { - const self = this; - - tmpBuff32v$2.setUint32(0, v, true); - - await self.write(tmpBuff32$2, pos); - } - - async writeUBE32(v, pos) { - const self = this; - - tmpBuff32v$2.setUint32(0, v, false); - - await self.write(tmpBuff32$2, pos); - } - - - async writeULE64(v, pos) { - const self = this; - - tmpBuff64v$2.setUint32(0, v & 0xFFFFFFFF, true); - tmpBuff64v$2.setUint32(4, Math.floor(v / 0x100000000) , true); - - await self.write(tmpBuff64$2, pos); - } - - - async readULE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new Uint32Array(b.buffer); - - return view[0]; - } - - async readUBE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new DataView(b.buffer); - - return view.getUint32(0, false); - } - - async readULE64(pos) { - const self = this; - const b = await self.read(8, pos); - - const view = new Uint32Array(b.buffer); - - return view[1] * 0x100000000 + view[0]; - } - - async readString(pos) { - const self = this; - const fixedSize = 2048; - - let currentPosition = typeof pos == "undefined" ? self.pos : pos; - - if (currentPosition > this.totalSize) { - if (this.readOnly) { - throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos); - } - - let endOfStringFound = false; - let str = ""; - - while (!endOfStringFound) { - let currentPage = Math.floor(currentPosition / PAGE_SIZE$1); - let offsetOnPage = currentPosition % PAGE_SIZE$1; - - if (self.o.data[currentPage] === undefined) { - throw new Error("ERROR"); - } - - let readLength = Math.min(fixedSize, self.o.data[currentPage].length - offsetOnPage); - const dataArray = new Uint8Array(self.o.data[currentPage].buffer, offsetOnPage, readLength); - - let indexEndOfString = dataArray.findIndex(element => element === 0); - endOfStringFound = indexEndOfString !== -1; - - if (endOfStringFound) { - str += new TextDecoder().decode(dataArray.slice(0, indexEndOfString)); - self.pos = currentPage * PAGE_SIZE$1 + offsetOnPage + indexEndOfString + 1; - } else { - str += new TextDecoder().decode(dataArray); - self.pos = currentPage * PAGE_SIZE$1 + offsetOnPage + dataArray.length; - } - - currentPosition = self.pos; - } - return str; - } - } - - const O_TRUNC = 512; - const O_CREAT = 64; - const O_RDWR = 2; - const O_RDONLY = 0; - - /* global fetch */ - - const DEFAULT_CACHE_SIZE = (1 << 16); - const DEFAULT_PAGE_SIZE = (1 << 13); - - - async function createOverride(o, b, c) { - if (typeof o === "string") { - o = { - type: "file", - fileName: o, - cacheSize: b || DEFAULT_CACHE_SIZE, - pageSize: c || DEFAULT_PAGE_SIZE - }; - } - if (o.type == "file") { - return await open$1(o.fileName, O_TRUNC | O_CREAT | O_RDWR, o.cacheSize, o.pageSize); - } else if (o.type == "mem") { - return createNew$1(o); - } else if (o.type == "bigMem") { - return createNew(o); - } else { - throw new Error("Invalid FastFile type: "+o.type); - } - } - - async function readExisting$3(o, b, c) { - if (o instanceof Uint8Array) { - o = { - type: "mem", - data: o - }; - } - { - if (typeof o === "string") { - const buff = await fetch(o).then( function(res) { - return res.arrayBuffer(); - }).then(function (ab) { - return new Uint8Array(ab); - }); - o = { - type: "mem", - data: buff - }; - } - } - if (o.type == "file") { - return await open$1(o.fileName, O_RDONLY, o.cacheSize, o.pageSize); - } else if (o.type == "mem") { - return await readExisting$5(o); - } else if (o.type == "bigMem") { - return await readExisting$4(o); - } else { - throw new Error("Invalid FastFile type: "+o.type); - } - } - - /* - - Copyright 2020 0KIMS association. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - */ - - function flatArray(a) { - let res = []; - fillArray(res, a); - return res; - - function fillArray(res, a) { - if (Array.isArray(a)) { - for (let i = 0; i < a.length; i++) { - fillArray(res, a[i]); - } - } else { - res.push(a); - } - } - } - - // Ref https://github.com/iden3/circom/commit/ec6388cf6eb62463539cb4c40cc3ceae9826de19 - function normalize(n, prime) { - let res = BigInt(n) % prime; - if (res < 0) res += prime; - return res; - } - - function fnvHash(str) { - const uint64_max = BigInt(2) ** BigInt(64); - let hash = BigInt("0xCBF29CE484222325"); - for (let i = 0; i < str.length; i++) { - hash ^= BigInt(str[i].charCodeAt(0)); - hash *= BigInt(0x100000001B3); - hash %= uint64_max; - } - let shash = hash.toString(16); - let n = 16 - shash.length; - shash = "0".repeat(n).concat(shash); - return shash; - } - - // Note that this pads zeros - function toArray32(s, size) { - const res = []; //new Uint32Array(size); //has no unshift - let rem = BigInt(s); - const radix = BigInt(0x100000000); - while (rem) { - res.unshift(Number(rem % radix)); - rem = rem / radix; - } - if (size) { - let i = size - res.length; - while (i > 0) { - res.unshift(0); - i--; - } - } - return res; - } - - /* globals WebAssembly */ - - async function builder(code, options) { - let instance; - let wc; - let memory; - options = options || {}; - - // Only circom 2 implements version lookup through exports in the WASM - // We default to `1` and update if we see the `getVersion` export (major version) - // These are updated after the instance is instantiated, assuming the functions are available - let majorVersion = 1; - // After Circom 2.0.7, Blaine added exported functions for getting minor and patch versions - let minorVersion = 0; - // If we can't look up the patch version, assume the lowest - let patchVersion = 0; - - let codeIsWebAssemblyInstance = false; - - // If code is already prepared WebAssembly.Instance, we use it directly - if (code instanceof WebAssembly.Instance) { - instance = code; - codeIsWebAssemblyInstance = true; - } else { - let memorySize = 32767; - - if (options.memorySize) { - // make sure we have int - memorySize = parseInt(options.memorySize); - if (memorySize < 0) { - throw new Error("Invalid memory size"); - } - } - - let memoryAllocated = false; - while (!memoryAllocated) { - try { - memory = new WebAssembly.Memory({initial: memorySize}); - memoryAllocated = true; - } catch (err) { - if (memorySize <= 1) { - throw err; - } - console.warn("Could not allocate " + memorySize * 1024 * 64 + " bytes. This may cause severe instability. Trying with " + memorySize * 1024 * 64 / 2 + " bytes"); - memorySize = Math.floor(memorySize / 2); - } - } - - const wasmModule = await WebAssembly.compile(code); - - let errStr = ""; - let msgStr = ""; - - instance = await WebAssembly.instantiate(wasmModule, { - env: { - "memory": memory - }, - runtime: { - printDebug : function(value) { - console.log("printDebug:", value); - }, - exceptionHandler: function (code) { - let err; - if (code === 1) { - err = "Signal not found. "; - } else if (code === 2) { - err = "Too many signals set. "; - } else if (code === 3) { - err = "Signal already set. "; - } else if (code === 4) { - err = "Assert Failed. "; - } else if (code === 5) { - err = "Not enough memory. "; - } else if (code === 6) { - err = "Input signal array access exceeds the size. "; - } else { - err = "Unknown error. "; - } - console.error("ERROR: ", code, errStr); - throw new Error(err + errStr); - }, - // A new way of logging messages was added in Circom 2.0.7 that requires 2 new imports - // `printErrorMessage` and `writeBufferMessage`. - printErrorMessage: function () { - errStr += getMessage() + "\n"; - }, - writeBufferMessage: function () { - const msg = getMessage(); - // Any calls to `log()` will always end with a `\n`, so that's when we print and reset - if (msg === "\n") { - console.log(msgStr); - msgStr = ""; - } else { - // If we've buffered other content, put a space in between the items - if (msgStr !== "") { - msgStr += " "; - } - // Then append the message to the message we are creating - msgStr += msg; - } - }, - showSharedRWMemory: function () { - const shared_rw_memory_size = instance.exports.getFieldNumLen32(); - const arr = new Uint32Array(shared_rw_memory_size); - for (let j = 0; j < shared_rw_memory_size; j++) { - arr[shared_rw_memory_size - 1 - j] = instance.exports.readSharedRWMemory(j); - } - - // In circom 2.0.7, they changed the log() function to allow strings and changed the - // output API. This smoothes over the breaking change. - if (majorVersion >= 2 && (minorVersion >= 1 || patchVersion >= 7)) { - // If we've buffered other content, put a space in between the items - if (msgStr !== "") { - msgStr += " "; - } - // Then append the value to the message we are creating - const msg = (Scalar.fromArray(arr, 0x100000000).toString()); - msgStr += msg; - } else { - console.log(Scalar.fromArray(arr, 0x100000000)); - } - }, - error: function (code, pstr, a, b, c, d) { - let errStr; - if (code === 7) { - errStr = p2str(pstr) + " " + wc.getFr(b).toString() + " != " + wc.getFr(c).toString() + " " + p2str(d); - } else if (code === 9) { - errStr = p2str(pstr) + " " + wc.getFr(b).toString() + " " + p2str(c); - } else if ((code === 5) && (options.sym)) { - errStr = p2str(pstr) + " " + options.sym.labelIdx2Name[c]; - } else { - errStr = p2str(pstr) + " " + a + " " + b + " " + c + " " + d; - } - console.log("ERROR: ", code, errStr); - throw new Error(errStr); - }, - log: function (a) { - console.log(wc.getFr(a).toString()); - }, - logGetSignal: function (signal, pVal) { - if (options.logGetSignal) { - options.logGetSignal(signal, wc.getFr(pVal)); - } - }, - logSetSignal: function (signal, pVal) { - if (options.logSetSignal) { - options.logSetSignal(signal, wc.getFr(pVal)); - } - }, - logStartComponent: function (cIdx) { - if (options.logStartComponent) { - options.logStartComponent(cIdx); - } - }, - logFinishComponent: function (cIdx) { - if (options.logFinishComponent) { - options.logFinishComponent(cIdx); - } - } - } - }); - } - - if (typeof instance.exports.getVersion == "function") { - majorVersion = instance.exports.getVersion(); - } - if (typeof instance.exports.getMinorVersion == "function") { - minorVersion = instance.exports.getMinorVersion(); - } - if (typeof instance.exports.getPatchVersion == "function") { - patchVersion = instance.exports.getPatchVersion(); - } - - const sanityCheck = - options && - ( - options.sanityCheck || - options.logGetSignal || - options.logSetSignal || - options.logStartComponent || - options.logFinishComponent - ); - - // We explicitly check for major version 2 in case there's a circom v3 in the future - if (majorVersion === 2) { - wc = new WitnessCalculatorCircom2(instance, sanityCheck); - } else if (majorVersion === 1) { - if (codeIsWebAssemblyInstance) { - throw new Error('Loading code from WebAssembly instance is not supported for circom version 1'); - } - wc = new WitnessCalculatorCircom1(memory, instance, sanityCheck); - } else { - throw new Error(`Unsupported circom version: ${majorVersion}`); - } - return wc; - - function getMessage() { - let message = ""; - let c = instance.exports.getMessageChar(); - while (c !== 0) { - message += String.fromCharCode(c); - c = instance.exports.getMessageChar(); - } - return message; - } - - function p2str(p) { - const i8 = new Uint8Array(memory.buffer); - - const bytes = []; - - for (let i = 0; i8[p + i] > 0; i++) bytes.push(i8[p + i]); - - return String.fromCharCode.apply(null, bytes); - } - } - - class WitnessCalculatorCircom1 { - constructor(memory, instance, sanityCheck) { - this.memory = memory; - this.i32 = new Uint32Array(memory.buffer); - this.instance = instance; - - this.n32 = (this.instance.exports.getFrLen() >> 2) - 2; - const pRawPrime = this.instance.exports.getPRawPrime(); - - const arr = new Array(this.n32); - for (let i = 0; i < this.n32; i++) { - arr[this.n32 - 1 - i] = this.i32[(pRawPrime >> 2) + i]; - } - - this.prime = Scalar.fromArray(arr, 0x100000000); - - this.Fr = new ZqField(this.prime); - - this.mask32 = Scalar.fromString("FFFFFFFF", 16); - this.NVars = this.instance.exports.getNVars(); - this.n64 = Math.floor((this.Fr.bitLength - 1) / 64) + 1; - this.R = this.Fr.e(Scalar.shiftLeft(1, this.n64 * 64)); - this.RInv = this.Fr.inv(this.R); - this.sanityCheck = sanityCheck; - } - - circom_version() { - return 1; - } - - async _doCalculateWitness(input, sanityCheck) { - this.instance.exports.init((this.sanityCheck || sanityCheck) ? 1 : 0); - const pSigOffset = this.allocInt(); - const pFr = this.allocFr(); - const keys = Object.keys(input); - keys.forEach((k) => { - const h = fnvHash(k); - const hMSB = parseInt(h.slice(0, 8), 16); - const hLSB = parseInt(h.slice(8, 16), 16); - try { - this.instance.exports.getSignalOffset32(pSigOffset, 0, hMSB, hLSB); - } catch (err) { - throw new Error(`Signal ${k} is not an input of the circuit.`); - } - const sigOffset = this.getInt(pSigOffset); - const fArr = flatArray(input[k]); - for (let i = 0; i < fArr.length; i++) { - this.setFr(pFr, fArr[i]); - this.instance.exports.setSignal(0, 0, sigOffset + i, pFr); - } - }); - } - - async calculateWitness(input, sanityCheck) { - const self = this; - - const old0 = self.i32[0]; - const w = []; - - await self._doCalculateWitness(input, sanityCheck); - - for (let i = 0; i < self.NVars; i++) { - const pWitness = self.instance.exports.getPWitness(i); - w.push(self.getFr(pWitness)); - } - - self.i32[0] = old0; - return w; - } - - async calculateBinWitness(input, sanityCheck) { - const self = this; - - const old0 = self.i32[0]; - - await self._doCalculateWitness(input, sanityCheck); - - const pWitnessBuffer = self.instance.exports.getWitnessBuffer(); - - self.i32[0] = old0; - - const buff = self.memory.buffer.slice(pWitnessBuffer, pWitnessBuffer + (self.NVars * self.n64 * 8)); - return new Uint8Array(buff); - } - - allocInt() { - const p = this.i32[0]; - this.i32[0] = p + 8; - return p; - } - - allocFr() { - const p = this.i32[0]; - this.i32[0] = p + this.n32 * 4 + 8; - return p; - } - - getInt(p) { - return this.i32[p >> 2]; - } - - setInt(p, v) { - this.i32[p >> 2] = v; - } - - getFr(p) { - const self = this; - const idx = (p >> 2); - - if (self.i32[idx + 1] & 0x80000000) { - const arr = new Array(self.n32); - for (let i = 0; i < self.n32; i++) { - arr[self.n32 - 1 - i] = self.i32[idx + 2 + i]; - } - const res = self.Fr.e(Scalar.fromArray(arr, 0x100000000)); - if (self.i32[idx + 1] & 0x40000000) { - return fromMontgomery(res); - } else { - return res; - } - - } else { - if (self.i32[idx] & 0x80000000) { - return self.Fr.e(self.i32[idx] - 0x100000000); - } else { - return self.Fr.e(self.i32[idx]); - } - } - - function fromMontgomery(n) { - return self.Fr.mul(self.RInv, n); - } - - } - - - setFr(p, v) { - const self = this; - - v = self.Fr.e(v); - - const minShort = self.Fr.neg(self.Fr.e("80000000", 16)); - const maxShort = self.Fr.e("7FFFFFFF", 16); - - if ((self.Fr.geq(v, minShort)) - && (self.Fr.leq(v, maxShort))) { - let a; - if (self.Fr.geq(v, self.Fr.zero)) { - a = Scalar.toNumber(v); - } else { - a = Scalar.toNumber(self.Fr.sub(v, minShort)); - a = a - 0x80000000; - a = 0x100000000 + a; - } - self.i32[(p >> 2)] = a; - self.i32[(p >> 2) + 1] = 0; - return; - } - - self.i32[(p >> 2)] = 0; - self.i32[(p >> 2) + 1] = 0x80000000; - const arr = Scalar.toArray(v, 0x100000000); - for (let i = 0; i < self.n32; i++) { - const idx = arr.length - 1 - i; - - if (idx >= 0) { - self.i32[(p >> 2) + 2 + i] = arr[idx]; - } else { - self.i32[(p >> 2) + 2 + i] = 0; - } - } - } - } - - class WitnessCalculatorCircom2 { - constructor(instance, sanityCheck) { - this.instance = instance; - - this.version = this.instance.exports.getVersion(); - this.n32 = this.instance.exports.getFieldNumLen32(); - - this.instance.exports.getRawPrime(); - const arr = new Uint32Array(this.n32); - for (let i = 0; i < this.n32; i++) { - arr[this.n32 - 1 - i] = this.instance.exports.readSharedRWMemory(i); - } - this.prime = Scalar.fromArray(arr, 0x100000000); - - this.witnessSize = this.instance.exports.getWitnessSize(); - - this.sanityCheck = sanityCheck; - } - - circom_version() { - return this.instance.exports.getVersion(); - } - - async _doCalculateWitness(input, sanityCheck) { - //input is assumed to be a map from signals to arrays of bigints - this.instance.exports.init((this.sanityCheck || sanityCheck) ? 1 : 0); - const keys = Object.keys(input); - let input_counter = 0; - keys.forEach((k) => { - const h = fnvHash(k); - const hMSB = parseInt(h.slice(0, 8), 16); - const hLSB = parseInt(h.slice(8, 16), 16); - const fArr = flatArray(input[k]); - // Slight deviation from https://github.com/iden3/circom/blob/v2.1.6/code_producers/src/wasm_elements/common/witness_calculator.js - // because I don't know when this exported function was added - if (typeof this.instance.exports.getInputSignalSize === "function") { - let signalSize = this.instance.exports.getInputSignalSize(hMSB, hLSB); - if (signalSize < 0) { - throw new Error(`Signal ${k} not found\n`); - } - if (fArr.length < signalSize) { - throw new Error(`Not enough values for input signal ${k}\n`); - } - if (fArr.length > signalSize) { - throw new Error(`Too many values for input signal ${k}\n`); - } - } - for (let i = 0; i < fArr.length; i++) { - const arrFr = toArray32(normalize(fArr[i], this.prime), this.n32); - for (let j = 0; j < this.n32; j++) { - this.instance.exports.writeSharedRWMemory(j, arrFr[this.n32 - 1 - j]); - } - try { - this.instance.exports.setInputSignal(hMSB, hLSB, i); - input_counter++; - } catch (err) { - // console.log(`After adding signal ${i} of ${k}`) - throw new Error(err); - } - } - - }); - if (input_counter < this.instance.exports.getInputSize()) { - throw new Error(`Not all inputs have been set. Only ${input_counter} out of ${this.instance.exports.getInputSize()}`); - } - } - - async calculateWitness(input, sanityCheck) { - const w = []; - - await this._doCalculateWitness(input, sanityCheck); - - for (let i = 0; i < this.witnessSize; i++) { - this.instance.exports.getWitness(i); - const arr = new Uint32Array(this.n32); - for (let j = 0; j < this.n32; j++) { - arr[this.n32 - 1 - j] = this.instance.exports.readSharedRWMemory(j); - } - w.push(Scalar.fromArray(arr, 0x100000000)); - } - - return w; - } - - async calculateWTNSBin(input, sanityCheck) { - const buff32 = new Uint32Array(this.witnessSize * this.n32 + this.n32 + 11); - const buff = new Uint8Array(buff32.buffer); - await this._doCalculateWitness(input, sanityCheck); - - //"wtns" - buff[0] = "w".charCodeAt(0); - buff[1] = "t".charCodeAt(0); - buff[2] = "n".charCodeAt(0); - buff[3] = "s".charCodeAt(0); - - //version 2 - buff32[1] = 2; - - //number of sections: 2 - buff32[2] = 2; - - //id section 1 - buff32[3] = 1; - - const n8 = this.n32 * 4; - //id section 1 length in 64bytes - const idSection1length = 8 + n8; - const idSection1lengthHex = idSection1length.toString(16); - buff32[4] = parseInt(idSection1lengthHex.slice(0, 8), 16); - buff32[5] = parseInt(idSection1lengthHex.slice(8, 16), 16); - - //this.n32 - buff32[6] = n8; - - //prime number - this.instance.exports.getRawPrime(); - - let pos = 7; - for (let j = 0; j < this.n32; j++) { - buff32[pos + j] = this.instance.exports.readSharedRWMemory(j); - } - pos += this.n32; - - // witness size - buff32[pos] = this.witnessSize; - pos++; - - //id section 2 - buff32[pos] = 2; - pos++; - - // section 2 length - const idSection2length = n8 * this.witnessSize; - const idSection2lengthHex = idSection2length.toString(16); - buff32[pos] = parseInt(idSection2lengthHex.slice(0, 8), 16); - buff32[pos + 1] = parseInt(idSection2lengthHex.slice(8, 16), 16); - - pos += 2; - for (let i = 0; i < this.witnessSize; i++) { - this.instance.exports.getWitness(i); - for (let j = 0; j < this.n32; j++) { - buff32[pos + j] = this.instance.exports.readSharedRWMemory(j); - } - pos += this.n32; - } - - return buff; - } - - } - - /* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . - */ - const { unstringifyBigInts: unstringifyBigInts$b} = utils$6; - - async function wtnsCalculate(_input, wasmFileName, wtnsFileName, options) { - const input = unstringifyBigInts$b(_input); - - const fdWasm = await readExisting$3(wasmFileName); - const wasm = await fdWasm.read(fdWasm.totalSize); - await fdWasm.close(); - - const wc = await builder(wasm, options); - if (wc.circom_version() === 1) { - const w = await wc.calculateBinWitness(input); - - const fdWtns = await createBinFile(wtnsFileName, "wtns", 2, 2); - - await writeBin(fdWtns, w, wc.prime); - await fdWtns.close(); - } else { - const fdWtns = await createOverride(wtnsFileName); - - const w = await wc.calculateWTNSBin(input); - - await fdWtns.write(w); - await fdWtns.close(); - } - } - - /* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . - */ - const {unstringifyBigInts: unstringifyBigInts$a} = utils$6; - - async function groth16FullProve(_input, wasmFile, zkeyFileName, logger, wtnsCalcOptions, proverOptions) { - const input = unstringifyBigInts$a(_input); - - const wtns= { - type: "mem" - }; - await wtnsCalculate(input, wasmFile, wtns, wtnsCalcOptions); - return await groth16Prove(zkeyFileName, wtns, logger, proverOptions); - } - - /* - Copyright 2018 0kims association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . - */ - const {unstringifyBigInts: unstringifyBigInts$9} = utils$6; - - async function groth16Verify(_vk_verifier, _publicSignals, _proof, logger) { - /* - let cpub = vk_verifier.IC[0]; - for (let s= 0; s< vk_verifier.nPublic; s++) { - cpub = G1.add( cpub, G1.timesScalar( vk_verifier.IC[s+1], publicSignals[s])); - } - */ - - const vk_verifier = unstringifyBigInts$9(_vk_verifier); - const proof = unstringifyBigInts$9(_proof); - const publicSignals = unstringifyBigInts$9(_publicSignals); - - const curve = await getCurveFromName(vk_verifier.curve); - - const IC0 = curve.G1.fromObject(vk_verifier.IC[0]); - const IC = new Uint8Array(curve.G1.F.n8*2 * publicSignals.length); - const w = new Uint8Array(curve.Fr.n8 * publicSignals.length); - - if (!publicInputsAreValid$2(curve, publicSignals)) { - if (logger) logger.error("Public inputs are not valid."); - return false; - } - - for (let i=0; i. - */ - const { unstringifyBigInts: unstringifyBigInts$8} = utils$6; - - function p256$2(n) { - let nstr = n.toString(16); - while (nstr.length < 64) nstr = "0"+nstr; - nstr = `"0x${nstr}"`; - return nstr; - } - - async function groth16ExportSolidityCallData(_proof, _pub) { - const proof = unstringifyBigInts$8(_proof); - const pub = unstringifyBigInts$8(_pub); - - let inputs = ""; - for (let i=0; i. - */ - - var groth16 = /*#__PURE__*/Object.freeze({ - __proto__: null, - fullProve: groth16FullProve, - prove: groth16Prove, - verify: groth16Verify, - exportSolidityCallData: groth16ExportSolidityCallData - }); - - /* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . - */ - - function hashToG2(curve, hash) { - const hashV = new DataView(hash.buffer, hash.byteOffset, hash.byteLength); - const seed = []; - for (let i=0; i<8; i++) { - seed[i] = hashV.getUint32(i*4); - } - - const rng = new ChaCha(seed); - - const g2_sp = curve.G2.fromRng(rng); - - return g2_sp; - } - - function getG2sp(curve, persinalization, challenge, g1s, g1sx) { - - const h = blake2b.create({ dkLen: 64 }); - const b1 = new Uint8Array([persinalization]); - h.update(b1); - h.update(challenge); - const b3 = curve.G1.toUncompressed(g1s); - h.update( b3); - const b4 = curve.G1.toUncompressed(g1sx); - h.update( b4); - const hash =h.digest(); - - return hashToG2(curve, hash); - } - - function calculatePubKey(k, curve, personalization, challengeHash, rng ) { - k.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); - k.g1_sx = curve.G1.toAffine(curve.G1.timesFr(k.g1_s, k.prvKey)); - k.g2_sp = curve.G2.toAffine(getG2sp(curve, personalization, challengeHash, k.g1_s, k.g1_sx)); - k.g2_spx = curve.G2.toAffine(curve.G2.timesFr(k.g2_sp, k.prvKey)); - return k; - } - - function createPTauKey(curve, challengeHash, rng) { - const key = { - tau: {}, - alpha: {}, - beta: {} - }; - key.tau.prvKey = curve.Fr.fromRng(rng); - key.alpha.prvKey = curve.Fr.fromRng(rng); - key.beta.prvKey = curve.Fr.fromRng(rng); - calculatePubKey(key.tau, curve, 0, challengeHash, rng); - calculatePubKey(key.alpha, curve, 1, challengeHash, rng); - calculatePubKey(key.beta, curve, 2, challengeHash, rng); - return key; - } - - /* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . - */ - - async function writePTauHeader(fd, curve, power, ceremonyPower) { - // Write the header - /////////// - - if (! ceremonyPower) ceremonyPower = power; - await fd.writeULE32(1); // Header type - const pHeaderSize = fd.pos; - await fd.writeULE64(0); // Temporally set to 0 length - - await fd.writeULE32(curve.F1.n64*8); - - const buff = new Uint8Array(curve.F1.n8); - Scalar.toRprLE(buff, 0, curve.q, curve.F1.n8); - await fd.write(buff); - await fd.writeULE32(power); // power - await fd.writeULE32(ceremonyPower); // power - - const headerSize = fd.pos - pHeaderSize - 8; - - const oldPos = fd.pos; - - await fd.writeULE64(headerSize, pHeaderSize); - - fd.pos = oldPos; - } - - async function readPTauHeader(fd, sections) { - if (!sections[1]) throw new Error(fd.fileName + ": File has no header"); - if (sections[1].length>1) throw new Error(fd.fileName +": File has more than one header"); - - fd.pos = sections[1][0].p; - const n8 = await fd.readULE32(); - const buff = await fd.read(n8); - const q = Scalar.fromRprLE(buff); - - const curve = await getCurveFromQ(q); - - if (curve.F1.n64*8 != n8) throw new Error(fd.fileName +": Invalid size"); - - const power = await fd.readULE32(); - const ceremonyPower = await fd.readULE32(); - - if (fd.pos-sections[1][0].p != sections[1][0].size) throw new Error("Invalid PTau header size"); - - return {curve, power, ceremonyPower}; - } - - - async function readPtauPubKey(fd, curve, montgomery) { - - const buff = await fd.read(curve.F1.n8*2*6 + curve.F2.n8*2*3); - - return fromPtauPubKeyRpr(buff, 0, curve, montgomery); - } - - function fromPtauPubKeyRpr(buff, pos, curve, montgomery) { - - const key = { - tau: {}, - alpha: {}, - beta: {} - }; - - key.tau.g1_s = readG1(); - key.tau.g1_sx = readG1(); - key.alpha.g1_s = readG1(); - key.alpha.g1_sx = readG1(); - key.beta.g1_s = readG1(); - key.beta.g1_sx = readG1(); - key.tau.g2_spx = readG2(); - key.alpha.g2_spx = readG2(); - key.beta.g2_spx = readG2(); - - return key; - - function readG1() { - let p; - if (montgomery) { - p = curve.G1.fromRprLEM( buff, pos ); - } else { - p = curve.G1.fromRprUncompressed( buff, pos ); - } - pos += curve.G1.F.n8*2; - return p; - } - - function readG2() { - let p; - if (montgomery) { - p = curve.G2.fromRprLEM( buff, pos ); - } else { - p = curve.G2.fromRprUncompressed( buff, pos ); - } - pos += curve.G2.F.n8*2; - return p; - } - } - - function toPtauPubKeyRpr(buff, pos, curve, key, montgomery) { - - writeG1(key.tau.g1_s); - writeG1(key.tau.g1_sx); - writeG1(key.alpha.g1_s); - writeG1(key.alpha.g1_sx); - writeG1(key.beta.g1_s); - writeG1(key.beta.g1_sx); - writeG2(key.tau.g2_spx); - writeG2(key.alpha.g2_spx); - writeG2(key.beta.g2_spx); - - async function writeG1(p) { - if (montgomery) { - curve.G1.toRprLEM(buff, pos, p); - } else { - curve.G1.toRprUncompressed(buff, pos, p); - } - pos += curve.F1.n8*2; - } - - async function writeG2(p) { - if (montgomery) { - curve.G2.toRprLEM(buff, pos, p); - } else { - curve.G2.toRprUncompressed(buff, pos, p); - } - pos += curve.F2.n8*2; - } - - return buff; - } - - async function writePtauPubKey(fd, curve, key, montgomery) { - const buff = new Uint8Array(curve.F1.n8*2*6 + curve.F2.n8*2*3); - toPtauPubKeyRpr(buff, 0, curve, key, montgomery); - await fd.write(buff); - } - - async function readContribution(fd, curve) { - const c = {}; - - c.tauG1 = await readG1(); - c.tauG2 = await readG2(); - c.alphaG1 = await readG1(); - c.betaG1 = await readG1(); - c.betaG2 = await readG2(); - c.key = await readPtauPubKey(fd, curve, true); - c.partialHash = await fd.read(216); - c.nextChallenge = await fd.read(64); - c.type = await fd.readULE32(); - - const buffV = new Uint8Array(curve.G1.F.n8*2*6+curve.G2.F.n8*2*3); - toPtauPubKeyRpr(buffV, 0, curve, c.key, false); - - const responseHasher = fromPartialHash(c.partialHash); - responseHasher.update(buffV); - c.responseHash = responseHasher.digest(); - - const paramLength = await fd.readULE32(); - const curPos = fd.pos; - let lastType =0; - while (fd.pos-curPos < paramLength) { - const buffType = await readDV(1); - if (buffType[0]<= lastType) throw new Error("Parameters in the contribution must be sorted"); - lastType = buffType[0]; - if (buffType[0]==1) { // Name - const buffLen = await readDV(1); - const buffStr = await readDV(buffLen[0]); - c.name = new TextDecoder().decode(buffStr); - } else if (buffType[0]==2) { - const buffExp = await readDV(1); - c.numIterationsExp = buffExp[0]; - } else if (buffType[0]==3) { - const buffLen = await readDV(1); - c.beaconHash = await readDV(buffLen[0]); - } else { - throw new Error("Parameter not recognized"); - } - } - if (fd.pos != curPos + paramLength) { - throw new Error("Parameters do not match"); - } - - return c; - - async function readG1() { - const pBuff = await fd.read(curve.G1.F.n8*2); - return curve.G1.fromRprLEM( pBuff ); - } - - async function readG2() { - const pBuff = await fd.read(curve.G2.F.n8*2); - return curve.G2.fromRprLEM( pBuff ); - } - - async function readDV(n) { - const b = await fd.read(n); - return new Uint8Array(b); - } - } - - async function readContributions(fd, curve, sections) { - if (!sections[7]) throw new Error(fd.fileName + ": File has no contributions"); - if (sections[7][0].length>1) throw new Error(fd.fileName +": File has more than one contributions section"); - - fd.pos = sections[7][0].p; - const nContributions = await fd.readULE32(); - const contributions = []; - for (let i=0; i0) { - const paramsBuff = new Uint8Array(params); - await fd.writeULE32(paramsBuff.byteLength); - await fd.write(paramsBuff); - } else { - await fd.writeULE32(0); - } - - - async function writeG1(p) { - curve.G1.toRprLEM(buffG1, 0, p); - await fd.write(buffG1); - } - - async function writeG2(p) { - curve.G2.toRprLEM(buffG2, 0, p); - await fd.write(buffG2); - } - - } - - async function writeContributions(fd, curve, contributions) { - - await fd.writeULE32(7); // Header type - const pContributionsSize = fd.pos; - await fd.writeULE64(0); // Temporally set to 0 length - - await fd.writeULE32(contributions.length); - for (let i=0; i< contributions.length; i++) { - await writeContribution(fd, curve, contributions[i]); - } - const contributionsSize = fd.pos - pContributionsSize - 8; - - const oldPos = fd.pos; - - await fd.writeULE64(contributionsSize, pContributionsSize); - fd.pos = oldPos; - } - - function calculateFirstChallengeHash(curve, power, logger) { - if (logger) logger.debug("Calculating First Challenge Hash"); - - const hasher = blake2b.create({ dkLen: 64 }); - - const vG1 = new Uint8Array(curve.G1.F.n8*2); - const vG2 = new Uint8Array(curve.G2.F.n8*2); - curve.G1.toRprUncompressed(vG1, 0, curve.G1.g); - curve.G2.toRprUncompressed(vG2, 0, curve.G2.g); - - hasher.update(blake2b.create({ dkLen: 64 }).digest()); - - let n; - - n=(2 ** power)*2 -1; - if (logger) logger.debug("Calculate Initial Hash: tauG1"); - hashBlock(vG1, n); - n= 2 ** power; - if (logger) logger.debug("Calculate Initial Hash: tauG2"); - hashBlock(vG2, n); - if (logger) logger.debug("Calculate Initial Hash: alphaTauG1"); - hashBlock(vG1, n); - if (logger) logger.debug("Calculate Initial Hash: betaTauG1"); - hashBlock(vG1, n); - hasher.update(vG2); - - return hasher.digest(); - - function hashBlock(buff, n) { - // this block size is a good compromise between speed and the maximum - // input size of the Blake2b update method (65,535,720 bytes). - const blockSize = 341000; - const nBlocks = Math.floor(n / blockSize); - const rem = n % blockSize; - const bigBuff = new Uint8Array(blockSize * buff.byteLength); - for (let i=0; i. - */ - - async function newAccumulator(curve, power, fileName, logger) { - - const fd = await createBinFile(fileName, "ptau", 1, 7); - - await writePTauHeader(fd, curve, power, 0); - - const buffG1 = curve.G1.oneAffine; - const buffG2 = curve.G2.oneAffine; - - // Write tauG1 - /////////// - await startWriteSection(fd, 2); - const nTauG1 = (2 ** power) * 2 -1; - for (let i=0; i< nTauG1; i++) { - await fd.write(buffG1); - if ((logger)&&((i%100000) == 0)&&i) logger.log("tauG1: " + i); - } - await endWriteSection(fd); - - // Write tauG2 - /////////// - await startWriteSection(fd, 3); - const nTauG2 = (2 ** power); - for (let i=0; i< nTauG2; i++) { - await fd.write(buffG2); - if ((logger)&&((i%100000) == 0)&&i) logger.log("tauG2: " + i); - } - await endWriteSection(fd); - - // Write alphaTauG1 - /////////// - await startWriteSection(fd, 4); - const nAlfaTauG1 = (2 ** power); - for (let i=0; i< nAlfaTauG1; i++) { - await fd.write(buffG1); - if ((logger)&&((i%100000) == 0)&&i) logger.log("alphaTauG1: " + i); - } - await endWriteSection(fd); - - // Write betaTauG1 - /////////// - await startWriteSection(fd, 5); - const nBetaTauG1 = (2 ** power); - for (let i=0; i< nBetaTauG1; i++) { - await fd.write(buffG1); - if ((logger)&&((i%100000) == 0)&&i) logger.log("betaTauG1: " + i); - } - await endWriteSection(fd); - - // Write betaG2 - /////////// - await startWriteSection(fd, 6); - await fd.write(buffG2); - await endWriteSection(fd); - - // Contributions - /////////// - await startWriteSection(fd, 7); - await fd.writeULE32(0); // 0 Contributions - await endWriteSection(fd); - - await fd.close(); - - const firstChallengeHash = calculateFirstChallengeHash(curve, power, logger); - - if (logger) logger.debug(formatHash(blake2b.create({ dkLen: 64 }).digest(), "Blank Contribution Hash:")); - - if (logger) logger.info(formatHash(firstChallengeHash, "First Contribution Hash:")); - - return firstChallengeHash; - - } - - // Format of the outpu - - async function exportChallenge(pTauFilename, challengeFilename, logger) { - const {fd: fdFrom, sections} = await readBinFile$1(pTauFilename, "ptau", 1); - - const {curve, power} = await readPTauHeader(fdFrom, sections); - - const contributions = await readContributions(fdFrom, curve, sections); - let lastResponseHash, curChallengeHash; - if (contributions.length == 0) { - lastResponseHash = blake2b.create({ dkLen: 64 }).digest(); - curChallengeHash = calculateFirstChallengeHash(curve, power); - } else { - lastResponseHash = contributions[contributions.length-1].responseHash; - curChallengeHash = contributions[contributions.length-1].nextChallenge; - } - - if (logger) logger.info(formatHash(lastResponseHash, "Last Response Hash: ")); - - if (logger) logger.info(formatHash(curChallengeHash, "New Challenge Hash: ")); - - - const fdTo = await createOverride(challengeFilename); - - const toHash = blake2b.create({ dkLen: 64 }); - await fdTo.write(lastResponseHash); - toHash.update(lastResponseHash); - - await exportSection(2, "G1", (2 ** power) * 2 -1, "tauG1"); - await exportSection(3, "G2", (2 ** power) , "tauG2"); - await exportSection(4, "G1", (2 ** power) , "alphaTauG1"); - await exportSection(5, "G1", (2 ** power) , "betaTauG1"); - await exportSection(6, "G2", 1 , "betaG2"); - - await fdFrom.close(); - await fdTo.close(); - - const calcCurChallengeHash = toHash.digest(); - - if (!hashIsEqual (curChallengeHash, calcCurChallengeHash)) { - if (logger) logger.info(formatHash(calcCurChallengeHash, "Calc Curret Challenge Hash: ")); - - if (logger) logger.error("PTau file is corrupted. Calculated new challenge hash does not match with the eclared one"); - throw new Error("PTau file is corrupted. Calculated new challenge hash does not match with the eclared one"); - } - - return curChallengeHash; - - async function exportSection(sectionId, groupName, nPoints, sectionName) { - const G = curve[groupName]; - const sG = G.F.n8*2; - const nPointsChunk = Math.floor((1<<24)/sG); - - await startReadUniqueSection$1(fdFrom, sections, sectionId); - for (let i=0; i< nPoints; i+= nPointsChunk) { - if (logger) logger.debug(`Exporting ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints-i, nPointsChunk); - let buff; - buff = await fdFrom.read(n*sG); - buff = await G.batchLEMtoU(buff); - await fdTo.write(buff); - toHash.update(buff); - } - await endReadSection$1(fdFrom); - } - - - } - - /* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . - */ - - async function importResponse(oldPtauFilename, contributionFilename, newPTauFilename, name, importPoints, logger) { - - const noHash = new Uint8Array(64); - for (let i=0; i<64; i++) noHash[i] = 0xFF; - - const {fd: fdOld, sections} = await readBinFile$1(oldPtauFilename, "ptau", 1); - const {curve, power} = await readPTauHeader(fdOld, sections); - const contributions = await readContributions(fdOld, curve, sections); - const currentContribution = {}; - - if (name) currentContribution.name = name; - - const sG1 = curve.F1.n8*2; - const scG1 = curve.F1.n8; // Compressed size - const sG2 = curve.F2.n8*2; - const scG2 = curve.F2.n8; // Compressed size - - const fdResponse = await readExisting$3(contributionFilename); - - if (fdResponse.totalSize != - 64 + // Old Hash - ((2 ** power)*2-1)*scG1 + - (2 ** power)*scG2 + - (2 ** power)*scG1 + - (2 ** power)*scG1 + - scG2 + - sG1*6 + sG2*3) - throw new Error("Size of the contribution is invalid"); - - let lastChallengeHash; - - if (contributions.length>0) { - lastChallengeHash = contributions[contributions.length-1].nextChallenge; - } else { - lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); - } - - const fdNew = await createBinFile(newPTauFilename, "ptau", 1, importPoints ? 7: 2); - await writePTauHeader(fdNew, curve, power); - - const contributionPreviousHash = await fdResponse.read(64); - - if (hashIsEqual(noHash,lastChallengeHash)) { - lastChallengeHash = contributionPreviousHash; - contributions[contributions.length-1].nextChallenge = lastChallengeHash; - } - - if(!hashIsEqual(contributionPreviousHash,lastChallengeHash)) - throw new Error("Wrong contribution. This contribution is not based on the previous hash"); - - const hasherResponse = blake2b.create({ dkLen: 64 }); - hasherResponse.update(contributionPreviousHash); - - const startSections = []; - let res; - res = await processSection(fdResponse, fdNew, "G1", 2, (2 ** power) * 2 -1, [1], "tauG1"); - currentContribution.tauG1 = res[0]; - res = await processSection(fdResponse, fdNew, "G2", 3, (2 ** power) , [1], "tauG2"); - currentContribution.tauG2 = res[0]; - res = await processSection(fdResponse, fdNew, "G1", 4, (2 ** power) , [0], "alphaG1"); - currentContribution.alphaG1 = res[0]; - res = await processSection(fdResponse, fdNew, "G1", 5, (2 ** power) , [0], "betaG1"); - currentContribution.betaG1 = res[0]; - res = await processSection(fdResponse, fdNew, "G2", 6, 1 , [0], "betaG2"); - currentContribution.betaG2 = res[0]; - - currentContribution.partialHash = toPartialHash(hasherResponse); - - - const buffKey = await fdResponse.read(curve.F1.n8*2*6+curve.F2.n8*2*3); - - currentContribution.key = fromPtauPubKeyRpr(buffKey, 0, curve, false); - - hasherResponse.update(new Uint8Array(buffKey)); - const hashResponse = hasherResponse.digest(); - - if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); - - if (importPoints) { - const nextChallengeHasher = blake2b.create({ dkLen: 64 }); - nextChallengeHasher.update(hashResponse); - - await hashSection(nextChallengeHasher, fdNew, "G1", 2, (2 ** power) * 2 -1, "tauG1", logger); - await hashSection(nextChallengeHasher, fdNew, "G2", 3, (2 ** power) , "tauG2", logger); - await hashSection(nextChallengeHasher, fdNew, "G1", 4, (2 ** power) , "alphaTauG1", logger); - await hashSection(nextChallengeHasher, fdNew, "G1", 5, (2 ** power) , "betaTauG1", logger); - await hashSection(nextChallengeHasher, fdNew, "G2", 6, 1 , "betaG2", logger); - - currentContribution.nextChallenge = nextChallengeHasher.digest(); - - if (logger) logger.info(formatHash(currentContribution.nextChallenge, "Next Challenge Hash: ")); - } else { - currentContribution.nextChallenge = noHash; - } - - contributions.push(currentContribution); - - await writeContributions(fdNew, curve, contributions); - - await fdResponse.close(); - await fdNew.close(); - await fdOld.close(); - - return currentContribution.nextChallenge; - - async function processSection(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { - if (importPoints) { - return await processSectionImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName); - } else { - return await processSectionNoImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName); - } - } - - async function processSectionImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { - - const G = curve[groupName]; - const scG = G.F.n8; - const sG = G.F.n8*2; - - const singularPoints = []; - - await startWriteSection(fdTo, sectionId); - const nPointsChunk = Math.floor((1<<24)/sG); - - startSections[sectionId] = fdTo.pos; - - for (let i=0; i< nPoints; i += nPointsChunk) { - if (logger) logger.debug(`Importing ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints-i, nPointsChunk); - - const buffC = await fdFrom.read(n * scG); - hasherResponse.update(buffC); - - const buffLEM = await G.batchCtoLEM(buffC); - - await fdTo.write(buffLEM); - for (let j=0; j=i) && (sp < i+n)) { - const P = G.fromRprLEM(buffLEM, (sp-i)*sG); - singularPoints.push(P); - } - } - } - - await endWriteSection(fdTo); - - return singularPoints; - } - - - async function processSectionNoImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { - - const G = curve[groupName]; - const scG = G.F.n8; - - const singularPoints = []; - - const nPointsChunk = Math.floor((1<<24)/scG); - - for (let i=0; i< nPoints; i += nPointsChunk) { - if (logger) logger.debug(`Importing ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints-i, nPointsChunk); - - const buffC = await fdFrom.read(n * scG); - hasherResponse.update(buffC); - - for (let j=0; j=i) && (sp < i+n)) { - const P = G.fromRprCompressed(buffC, (sp-i)*scG); - singularPoints.push(P); - } - } - } - - return singularPoints; - } - - - async function hashSection(nextChallengeHasher, fdTo, groupName, sectionId, nPoints, sectionName, logger) { - - const G = curve[groupName]; - const sG = G.F.n8*2; - const nPointsChunk = Math.floor((1<<24)/sG); - - const oldPos = fdTo.pos; - fdTo.pos = startSections[sectionId]; - - for (let i=0; i< nPoints; i += nPointsChunk) { - if (logger) logger.debug(`Hashing ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints-i, nPointsChunk); - - const buffLEM = await fdTo.read(n * sG); - - const buffU = await G.batchLEMtoU(buffLEM); - - nextChallengeHasher.update(buffU); - } - - fdTo.pos = oldPos; - } - - } - - /* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . - */ - const sameRatio$1 = sameRatio$2; - - async function verifyContribution(curve, cur, prev, logger) { - let sr; - if (cur.type == 1) { // Verify the beacon. - const beaconKey = await keyFromBeacon(curve, prev.nextChallenge, cur.beaconHash, cur.numIterationsExp); - - if (!curve.G1.eq(cur.key.tau.g1_s, beaconKey.tau.g1_s)) { - if (logger) logger.error(`BEACON key (tauG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G1.eq(cur.key.tau.g1_sx, beaconKey.tau.g1_sx)) { - if (logger) logger.error(`BEACON key (tauG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G2.eq(cur.key.tau.g2_spx, beaconKey.tau.g2_spx)) { - if (logger) logger.error(`BEACON key (tauG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - - if (!curve.G1.eq(cur.key.alpha.g1_s, beaconKey.alpha.g1_s)) { - if (logger) logger.error(`BEACON key (alphaG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G1.eq(cur.key.alpha.g1_sx, beaconKey.alpha.g1_sx)) { - if (logger) logger.error(`BEACON key (alphaG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G2.eq(cur.key.alpha.g2_spx, beaconKey.alpha.g2_spx)) { - if (logger) logger.error(`BEACON key (alphaG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - - if (!curve.G1.eq(cur.key.beta.g1_s, beaconKey.beta.g1_s)) { - if (logger) logger.error(`BEACON key (betaG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G1.eq(cur.key.beta.g1_sx, beaconKey.beta.g1_sx)) { - if (logger) logger.error(`BEACON key (betaG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - if (!curve.G2.eq(cur.key.beta.g2_spx, beaconKey.beta.g2_spx)) { - if (logger) logger.error(`BEACON key (betaG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` ); - return false; - } - } - - cur.key.tau.g2_sp = curve.G2.toAffine(getG2sp(curve, 0, prev.nextChallenge, cur.key.tau.g1_s, cur.key.tau.g1_sx)); - cur.key.alpha.g2_sp = curve.G2.toAffine(getG2sp(curve, 1, prev.nextChallenge, cur.key.alpha.g1_s, cur.key.alpha.g1_sx)); - cur.key.beta.g2_sp = curve.G2.toAffine(getG2sp(curve, 2, prev.nextChallenge, cur.key.beta.g1_s, cur.key.beta.g1_sx)); - - sr = await sameRatio$1(curve, cur.key.tau.g1_s, cur.key.tau.g1_sx, cur.key.tau.g2_sp, cur.key.tau.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID key (tau) in challenge #"+cur.id); - return false; - } - - sr = await sameRatio$1(curve, cur.key.alpha.g1_s, cur.key.alpha.g1_sx, cur.key.alpha.g2_sp, cur.key.alpha.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID key (alpha) in challenge #"+cur.id); - return false; - } - - sr = await sameRatio$1(curve, cur.key.beta.g1_s, cur.key.beta.g1_sx, cur.key.beta.g2_sp, cur.key.beta.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID key (beta) in challenge #"+cur.id); - return false; - } - - sr = await sameRatio$1(curve, prev.tauG1, cur.tauG1, cur.key.tau.g2_sp, cur.key.tau.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID tau*G1. challenge #"+cur.id+" It does not follow the previous contribution"); - return false; - } - - sr = await sameRatio$1(curve, cur.key.tau.g1_s, cur.key.tau.g1_sx, prev.tauG2, cur.tauG2); - if (sr !== true) { - if (logger) logger.error("INVALID tau*G2. challenge #"+cur.id+" It does not follow the previous contribution"); - return false; - } - - sr = await sameRatio$1(curve, prev.alphaG1, cur.alphaG1, cur.key.alpha.g2_sp, cur.key.alpha.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID alpha*G1. challenge #"+cur.id+" It does not follow the previous contribution"); - return false; - } - - sr = await sameRatio$1(curve, prev.betaG1, cur.betaG1, cur.key.beta.g2_sp, cur.key.beta.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID beta*G1. challenge #"+cur.id+" It does not follow the previous contribution"); - return false; - } - - sr = await sameRatio$1(curve, cur.key.beta.g1_s, cur.key.beta.g1_sx, prev.betaG2, cur.betaG2); - if (sr !== true) { - if (logger) logger.error("INVALID beta*G2. challenge #"+cur.id+"It does not follow the previous contribution"); - return false; - } - - if (logger) logger.info("Powers Of tau file OK!"); - return true; - } - - async function verify(tauFilename, logger) { - let sr; - - const {fd, sections} = await readBinFile$1(tauFilename, "ptau", 1); - const {curve, power, ceremonyPower} = await readPTauHeader(fd, sections); - const contrs = await readContributions(fd, curve, sections); - - if (logger) logger.debug("power: 2**" + power); - // Verify Last contribution - - if (logger) logger.debug("Computing initial contribution hash"); - const initialContribution = { - tauG1: curve.G1.g, - tauG2: curve.G2.g, - alphaG1: curve.G1.g, - betaG1: curve.G1.g, - betaG2: curve.G2.g, - nextChallenge: calculateFirstChallengeHash(curve, ceremonyPower, logger), - responseHash: blake2b.create({ dkLen: 64 }).digest() - }; - - if (contrs.length == 0) { - if (logger) logger.error("This file has no contribution! It cannot be used in production"); - return false; - } - - let prevContr; - if (contrs.length>1) { - prevContr = contrs[contrs.length-2]; - } else { - prevContr = initialContribution; - } - const curContr = contrs[contrs.length-1]; - if (logger) logger.debug("Validating contribution #"+contrs[contrs.length-1].id); - const res = await verifyContribution(curve, curContr, prevContr, logger); - if (!res) return false; - - - const nextContributionHasher = blake2b.create({ dkLen: 64 }); - nextContributionHasher.update(curContr.responseHash); - - // Verify powers and compute nextChallengeHash - - // await test(); - - // Verify Section tau*G1 - if (logger) logger.debug("Verifying powers in tau*G1 section"); - const rTau1 = await processSection(2, "G1", "tauG1", (2 ** power)*2-1, [0, 1], logger); - sr = await sameRatio$1(curve, rTau1.R1, rTau1.R2, curve.G2.g, curContr.tauG2); - if (sr !== true) { - if (logger) logger.error("tauG1 section. Powers do not match"); - return false; - } - if (!curve.G1.eq(curve.G1.g, rTau1.singularPoints[0])) { - if (logger) logger.error("First element of tau*G1 section must be the generator"); - return false; - } - if (!curve.G1.eq(curContr.tauG1, rTau1.singularPoints[1])) { - if (logger) logger.error("Second element of tau*G1 section does not match the one in the contribution section"); - return false; - } - - // await test(); - - // Verify Section tau*G2 - if (logger) logger.debug("Verifying powers in tau*G2 section"); - const rTau2 = await processSection(3, "G2", "tauG2", 2 ** power, [0, 1], logger); - sr = await sameRatio$1(curve, curve.G1.g, curContr.tauG1, rTau2.R1, rTau2.R2); - if (sr !== true) { - if (logger) logger.error("tauG2 section. Powers do not match"); - return false; - } - if (!curve.G2.eq(curve.G2.g, rTau2.singularPoints[0])) { - if (logger) logger.error("First element of tau*G2 section must be the generator"); - return false; - } - if (!curve.G2.eq(curContr.tauG2, rTau2.singularPoints[1])) { - if (logger) logger.error("Second element of tau*G2 section does not match the one in the contribution section"); - return false; - } - - // Verify Section alpha*tau*G1 - if (logger) logger.debug("Verifying powers in alpha*tau*G1 section"); - const rAlphaTauG1 = await processSection(4, "G1", "alphatauG1", 2 ** power, [0], logger); - sr = await sameRatio$1(curve, rAlphaTauG1.R1, rAlphaTauG1.R2, curve.G2.g, curContr.tauG2); - if (sr !== true) { - if (logger) logger.error("alphaTauG1 section. Powers do not match"); - return false; - } - if (!curve.G1.eq(curContr.alphaG1, rAlphaTauG1.singularPoints[0])) { - if (logger) logger.error("First element of alpha*tau*G1 section (alpha*G1) does not match the one in the contribution section"); - return false; - } - - // Verify Section beta*tau*G1 - if (logger) logger.debug("Verifying powers in beta*tau*G1 section"); - const rBetaTauG1 = await processSection(5, "G1", "betatauG1", 2 ** power, [0], logger); - sr = await sameRatio$1(curve, rBetaTauG1.R1, rBetaTauG1.R2, curve.G2.g, curContr.tauG2); - if (sr !== true) { - if (logger) logger.error("betaTauG1 section. Powers do not match"); - return false; - } - if (!curve.G1.eq(curContr.betaG1, rBetaTauG1.singularPoints[0])) { - if (logger) logger.error("First element of beta*tau*G1 section (beta*G1) does not match the one in the contribution section"); - return false; - } - - //Verify Beta G2 - const betaG2 = await processSectionBetaG2(logger); - if (!curve.G2.eq(curContr.betaG2, betaG2)) { - if (logger) logger.error("betaG2 element in betaG2 section does not match the one in the contribution section"); - return false; - } - - - const nextContributionHash = nextContributionHasher.digest(); - - // Check the nextChallengeHash - if (power == ceremonyPower) { - if (!hashIsEqual(nextContributionHash,curContr.nextChallenge)) { - if (logger) logger.error("Hash of the values does not match the next challenge of the last contributor in the contributions section"); - return false; - } - } - - if (logger) logger.info(formatHash(nextContributionHash, "Next challenge hash: ")); - - // Verify Previous contributions - - printContribution(curContr, prevContr); - for (let i = contrs.length-2; i>=0; i--) { - const curContr = contrs[i]; - const prevContr = (i>0) ? contrs[i-1] : initialContribution; - const res = await verifyContribution(curve, curContr, prevContr, logger); - if (!res) return false; - printContribution(curContr, prevContr); - } - if (logger) logger.info("-----------------------------------------------------"); - - if ((!sections[12]) || (!sections[13]) || (!sections[14]) || (!sections[15])) { - if (logger) logger.warn( - "this file does not contain phase2 precalculated values. Please run: \n" + - " snarkjs \"powersoftau preparephase2\" to prepare this file to be used in the phase2 ceremony." - ); - } else { - let res; - res = await verifyLagrangeEvaluations("G1", 2, 12, "tauG1", logger); - if (!res) return false; - res = await verifyLagrangeEvaluations("G2", 3, 13, "tauG2", logger); - if (!res) return false; - res = await verifyLagrangeEvaluations("G1", 4, 14, "alphaTauG1", logger); - if (!res) return false; - res = await verifyLagrangeEvaluations("G1", 5, 15, "betaTauG1", logger); - if (!res) return false; - } - - await fd.close(); - - if (logger) logger.info("Powers of Tau Ok!"); - - return true; - - function printContribution(curContr, prevContr) { - if (!logger) return; - logger.info("-----------------------------------------------------"); - logger.info(`Contribution #${curContr.id}: ${curContr.name ||""}`); - - logger.info(formatHash(curContr.nextChallenge, "Next Challenge: ")); - - const buffV = new Uint8Array(curve.G1.F.n8*2*6+curve.G2.F.n8*2*3); - toPtauPubKeyRpr(buffV, 0, curve, curContr.key, false); - - const responseHasher = fromPartialHash(curContr.partialHash); - responseHasher.update(buffV); - const responseHash = responseHasher.digest(); - - logger.info(formatHash(responseHash, "Response Hash:")); - - logger.info(formatHash(prevContr.nextChallenge, "Response Hash:")); - - if (curContr.type == 1) { - logger.info(`Beacon generator: ${byteArray2hex(curContr.beaconHash)}`); - logger.info(`Beacon iterations Exp: ${curContr.numIterationsExp}`); - } - - } - - async function processSectionBetaG2(logger) { - const G = curve.G2; - const sG = G.F.n8*2; - const buffUv = new Uint8Array(sG); - - if (!sections[6]) { - logger.error("File has no BetaG2 section"); - throw new Error("File has no BetaG2 section"); - } - if (sections[6].length>1) { - logger.error("File has no BetaG2 section"); - throw new Error("File has more than one GetaG2 section"); - } - fd.pos = sections[6][0].p; - - const buff = await fd.read(sG); - const P = G.fromRprLEM(buff); - - G.toRprUncompressed(buffUv, 0, P); - nextContributionHasher.update(buffUv); - - return P; - } - - async function processSection(idSection, groupName, sectionName, nPoints, singularPointIndexes, logger) { - const MAX_CHUNK_SIZE = 1<<16; - const G = curve[groupName]; - const sG = G.F.n8*2; - await startReadUniqueSection$1(fd, sections, idSection); - - const singularPoints = []; - - let R1 = G.zero; - let R2 = G.zero; - - let lastBase = G.zero; - - for (let i=0; i0) { - const firstBase = G.fromRprLEM(bases, 0); - const r = readUInt32BE(getRandomBytes(4), 0); - - R1 = G.add(R1, G.timesScalar(lastBase, r)); - R2 = G.add(R2, G.timesScalar(firstBase, r)); - } - - const r1 = await G.multiExpAffine(bases.slice(0, (n-1)*sG), scalars); - const r2 = await G.multiExpAffine(bases.slice(sG), scalars); - - R1 = G.add(R1, r1); - R2 = G.add(R2, r2); - - lastBase = G.fromRprLEM( bases, (n-1)*sG); - - for (let j=0; j=i) && (sp < i+n)) { - const P = G.fromRprLEM(bases, (sp-i)*sG); - singularPoints.push(P); - } - } - - } - await endReadSection$1(fd); - - return { - R1: R1, - R2: R2, - singularPoints: singularPoints - }; - - } - - async function verifyLagrangeEvaluations(gName, tauSection, lagrangeSection, sectionName, logger) { - - if (logger) logger.debug(`Verifying phase2 calculated values ${sectionName}...`); - const G = curve[gName]; - const sG = G.F.n8*2; - - const seed= new Array(8); - for (let i=0; i<8; i++) { - seed[i] = readUInt32BE(getRandomBytes(4), 0); - } - - for (let p=0; p<= power; p ++) { - const res = await verifyPower(p); - if (!res) return false; - } - - if (tauSection == 2) { - const res = await verifyPower(power+1); - if (!res) return false; - } - - return true; - - async function verifyPower(p) { - if (logger) logger.debug(`Power ${p}...`); - const n8r = curve.Fr.n8; - const nPoints = 2 ** p; - let buff_r = new Uint32Array(nPoints); - let buffG; - - let rng = new ChaCha(seed); - - if (logger) logger.debug(`Creating random numbers Powers${p}...`); - for (let i=0; i. - */ - - /* - This function creates a new section in the fdTo file with id idSection. - It multiplies the points in fdFrom by first, first*inc, first*inc^2, .... - nPoint Times. - It also updates the newChallengeHasher with the new points - */ - - async function applyKeyToSection(fdOld, sections, fdNew, idSection, curve, groupName, first, inc, sectionName, logger) { - const MAX_CHUNK_SIZE = 1 << 16; - const G = curve[groupName]; - const sG = G.F.n8*2; - const nPoints = sections[idSection][0].size / sG; - - await startReadUniqueSection$1(fdOld, sections,idSection ); - await startWriteSection(fdNew, idSection); - - let t = first; - for (let i=0; i. - */ - - async function challengeContribute(curve, challengeFilename, responseFileName, entropy, logger) { - const fdFrom = await readExisting$3(challengeFilename); - - - const sG1 = curve.F1.n64*8*2; - const sG2 = curve.F2.n64*8*2; - const domainSize = (fdFrom.totalSize + sG1 - 64 - sG2) / (4*sG1 + sG2); - let e = domainSize; - let power = 0; - while (e>1) { - e = e /2; - power += 1; - } - - if (2 ** power != domainSize) throw new Error("Invalid file size"); - if (logger) logger.debug("Power to tau size: "+power); - - const rng = await getRandomRng(entropy); - - const fdTo = await createOverride(responseFileName); - - // Calculate the hash - const challengeHasher = blake2b.create({ dkLen: 64 }); - for (let i=0; i { - logger.debug(k + ".g1_s: " + curve.G1.toString(key[k].g1_s, 16)); - logger.debug(k + ".g1_sx: " + curve.G1.toString(key[k].g1_sx, 16)); - logger.debug(k + ".g2_sp: " + curve.G2.toString(key[k].g2_sp, 16)); - logger.debug(k + ".g2_spx: " + curve.G2.toString(key[k].g2_spx, 16)); - logger.debug(""); - }); - } - - const responseHasher = blake2b.create({ dkLen: 64 }); - - await fdTo.write(challengeHash); - responseHasher.update(challengeHash); - - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", (2 ** power)*2-1, curve.Fr.one , key.tau.prvKey, "COMPRESSED", "tauG1" , logger ); - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G2", (2 ** power) , curve.Fr.one , key.tau.prvKey, "COMPRESSED", "tauG2" , logger ); - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", (2 ** power) , key.alpha.prvKey, key.tau.prvKey, "COMPRESSED", "alphaTauG1", logger ); - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", (2 ** power) , key.beta.prvKey , key.tau.prvKey, "COMPRESSED", "betaTauG1" , logger ); - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G2", 1 , key.beta.prvKey , key.tau.prvKey, "COMPRESSED", "betaTauG2" , logger ); - - // Write and hash key - const buffKey = new Uint8Array(curve.F1.n8*2*6+curve.F2.n8*2*3); - toPtauPubKeyRpr(buffKey, 0, curve, key, false); - await fdTo.write(buffKey); - responseHasher.update(buffKey); - const responseHash = responseHasher.digest(); - if (logger) logger.info(formatHash(responseHash, "Contribution Response Hash: ")); - - await fdTo.close(); - await fdFrom.close(); - } - - /* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . - */ - - async function beacon$1(oldPtauFilename, newPTauFilename, name, beaconHashStr,numIterationsExp, logger) { - const beaconHash = hex2ByteArray(beaconHashStr); - if ( (beaconHash.byteLength == 0) - || (beaconHash.byteLength*2 !=beaconHashStr.length)) - { - if (logger) logger.error("Invalid Beacon Hash. (It must be a valid hexadecimal sequence)"); - return false; - } - if (beaconHash.length>=256) { - if (logger) logger.error("Maximum length of beacon hash is 255 bytes"); - return false; - } - - numIterationsExp = parseInt(numIterationsExp); - if ((numIterationsExp<10)||(numIterationsExp>63)) { - if (logger) logger.error("Invalid numIterationsExp. (Must be between 10 and 63)"); - return false; - } - - - const {fd: fdOld, sections} = await readBinFile$1(oldPtauFilename, "ptau", 1); - const {curve, power, ceremonyPower} = await readPTauHeader(fdOld, sections); - if (power != ceremonyPower) { - if (logger) logger.error("This file has been reduced. You cannot contribute into a reduced file."); - return false; - } - if (sections[12]) { - if (logger) logger.warn("Contributing into a file that has phase2 calculated. You will have to prepare phase2 again."); - } - const contributions = await readContributions(fdOld, curve, sections); - const curContribution = { - name: name, - type: 1, // Beacon - numIterationsExp: numIterationsExp, - beaconHash: beaconHash - }; - - let lastChallengeHash; - - if (contributions.length>0) { - lastChallengeHash = contributions[contributions.length-1].nextChallenge; - } else { - lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); - } - - curContribution.key = await keyFromBeacon(curve, lastChallengeHash, beaconHash, numIterationsExp); - - const responseHasher = blake2b.create({ dkLen: 64 }); - responseHasher.update(lastChallengeHash); - - const fdNew = await createBinFile(newPTauFilename, "ptau", 1, 7); - await writePTauHeader(fdNew, curve, power); - - const startSections = []; - - let firstPoints; - firstPoints = await processSection(2, "G1", (2 ** power) * 2 -1, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG1", logger ); - curContribution.tauG1 = firstPoints[1]; - firstPoints = await processSection(3, "G2", (2 ** power) , curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG2", logger ); - curContribution.tauG2 = firstPoints[1]; - firstPoints = await processSection(4, "G1", (2 ** power) , curContribution.key.alpha.prvKey, curContribution.key.tau.prvKey, "alphaTauG1", logger ); - curContribution.alphaG1 = firstPoints[0]; - firstPoints = await processSection(5, "G1", (2 ** power) , curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG1", logger ); - curContribution.betaG1 = firstPoints[0]; - firstPoints = await processSection(6, "G2", 1, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG2", logger ); - curContribution.betaG2 = firstPoints[0]; - - curContribution.partialHash = toPartialHash(responseHasher); - - const buffKey = new Uint8Array(curve.F1.n8*2*6+curve.F2.n8*2*3); - - toPtauPubKeyRpr(buffKey, 0, curve, curContribution.key, false); - - responseHasher.update(new Uint8Array(buffKey)); - const hashResponse = responseHasher.digest(); - - if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); - - const nextChallengeHasher = blake2b.create({ dkLen: 64 }); - nextChallengeHasher.update(hashResponse); - - await hashSection(fdNew, "G1", 2, (2 ** power) * 2 -1, "tauG1", logger); - await hashSection(fdNew, "G2", 3, (2 ** power) , "tauG2", logger); - await hashSection(fdNew, "G1", 4, (2 ** power) , "alphaTauG1", logger); - await hashSection(fdNew, "G1", 5, (2 ** power) , "betaTauG1", logger); - await hashSection(fdNew, "G2", 6, 1 , "betaG2", logger); - - curContribution.nextChallenge = nextChallengeHasher.digest(); - - if (logger) logger.info(formatHash(curContribution.nextChallenge, "Next Challenge Hash: ")); - - contributions.push(curContribution); - - await writeContributions(fdNew, curve, contributions); - - await fdOld.close(); - await fdNew.close(); - - return hashResponse; - - async function processSection(sectionId, groupName, NPoints, first, inc, sectionName, logger) { - const res = []; - fdOld.pos = sections[sectionId][0].p; - - await startWriteSection(fdNew, sectionId); - - startSections[sectionId] = fdNew.pos; - - const G = curve[groupName]; - const sG = G.F.n8*2; - const chunkSize = Math.floor((1<<20) / sG); // 128Mb chunks - let t = first; - for (let i=0 ; i. - */ - - async function contribute(oldPtauFilename, newPTauFilename, name, entropy, logger) { - - const {fd: fdOld, sections} = await readBinFile$1(oldPtauFilename, "ptau", 1); - const {curve, power, ceremonyPower} = await readPTauHeader(fdOld, sections); - if (power != ceremonyPower) { - if (logger) logger.error("This file has been reduced. You cannot contribute into a reduced file."); - throw new Error("This file has been reduced. You cannot contribute into a reduced file."); - } - if (sections[12]) { - if (logger) logger.warn("WARNING: Contributing into a file that has phase2 calculated. You will have to prepare phase2 again."); - } - const contributions = await readContributions(fdOld, curve, sections); - const curContribution = { - name: name, - type: 0, // Beacon - }; - - let lastChallengeHash; - - const rng = await getRandomRng(entropy); - - if (contributions.length>0) { - lastChallengeHash = contributions[contributions.length-1].nextChallenge; - } else { - lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); - } - - // Generate a random key - - - curContribution.key = createPTauKey(curve, lastChallengeHash, rng); - - - const responseHasher = blake2b.create({ dkLen: 64 }); - responseHasher.update(lastChallengeHash); - - const fdNew = await createBinFile(newPTauFilename, "ptau", 1, 7); - await writePTauHeader(fdNew, curve, power); - - const startSections = []; - - let firstPoints; - firstPoints = await processSection(2, "G1", (2 ** power) * 2 -1, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG1" ); - curContribution.tauG1 = firstPoints[1]; - firstPoints = await processSection(3, "G2", (2 ** power) , curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG2" ); - curContribution.tauG2 = firstPoints[1]; - firstPoints = await processSection(4, "G1", (2 ** power) , curContribution.key.alpha.prvKey, curContribution.key.tau.prvKey, "alphaTauG1" ); - curContribution.alphaG1 = firstPoints[0]; - firstPoints = await processSection(5, "G1", (2 ** power) , curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG1" ); - curContribution.betaG1 = firstPoints[0]; - firstPoints = await processSection(6, "G2", 1, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG2" ); - curContribution.betaG2 = firstPoints[0]; - - curContribution.partialHash = toPartialHash(responseHasher); - - const buffKey = new Uint8Array(curve.F1.n8*2*6+curve.F2.n8*2*3); - - toPtauPubKeyRpr(buffKey, 0, curve, curContribution.key, false); - - responseHasher.update(new Uint8Array(buffKey)); - const hashResponse = responseHasher.digest(); - - if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); - - const nextChallengeHasher = blake2b.create({ dkLen: 64 }); - nextChallengeHasher.update(hashResponse); - - await hashSection(fdNew, "G1", 2, (2 ** power) * 2 -1, "tauG1"); - await hashSection(fdNew, "G2", 3, (2 ** power) , "tauG2"); - await hashSection(fdNew, "G1", 4, (2 ** power) , "alphaTauG1"); - await hashSection(fdNew, "G1", 5, (2 ** power) , "betaTauG1"); - await hashSection(fdNew, "G2", 6, 1 , "betaG2"); - - curContribution.nextChallenge = nextChallengeHasher.digest(); - - if (logger) logger.info(formatHash(curContribution.nextChallenge, "Next Challenge Hash: ")); - - contributions.push(curContribution); - - await writeContributions(fdNew, curve, contributions); - - await fdOld.close(); - await fdNew.close(); - - return hashResponse; - - async function processSection(sectionId, groupName, NPoints, first, inc, sectionName) { - const res = []; - fdOld.pos = sections[sectionId][0].p; - - await startWriteSection(fdNew, sectionId); - - startSections[sectionId] = fdNew.pos; - - const G = curve[groupName]; - const sG = G.F.n8*2; - const chunkSize = Math.floor((1<<20) / sG); // 128Mb chunks - let t = first; - for (let i=0 ; i. - */ - - async function preparePhase2(oldPtauFilename, newPTauFilename, logger) { - - const {fd: fdOld, sections} = await readBinFile$1(oldPtauFilename, "ptau", 1); - const {curve, power} = await readPTauHeader(fdOld, sections); - - const fdNew = await createBinFile(newPTauFilename, "ptau", 1, 11); - await writePTauHeader(fdNew, curve, power); - - await copySection(fdOld, sections, fdNew, 2); - await copySection(fdOld, sections, fdNew, 3); - await copySection(fdOld, sections, fdNew, 4); - await copySection(fdOld, sections, fdNew, 5); - await copySection(fdOld, sections, fdNew, 6); - await copySection(fdOld, sections, fdNew, 7); - - await processSection(2, 12, "G1", "tauG1" ); - await processSection(3, 13, "G2", "tauG2" ); - await processSection(4, 14, "G1", "alphaTauG1" ); - await processSection(5, 15, "G1", "betaTauG1" ); - - await fdOld.close(); - await fdNew.close(); - - // await fs.promises.unlink(newPTauFilename+ ".tmp"); - - return; - - async function processSection(oldSectionId, newSectionId, Gstr, sectionName) { - if (logger) logger.debug("Starting section: "+sectionName); - - await startWriteSection(fdNew, newSectionId); - - for (let p=0; p<=power; p++) { - await processSectionPower(p); - } - - if (oldSectionId == 2) { - await processSectionPower(power+1); - } - - await endWriteSection(fdNew); - - - async function processSectionPower(p) { - const nPoints = 2 ** p; - const G = curve[Gstr]; - curve.Fr; - const sGin = G.F.n8*2; - G.F.n8*3; - - let buff; - buff = new BigBuffer(nPoints*sGin); - - await startReadUniqueSection$1(fdOld, sections, oldSectionId); - if ((oldSectionId == 2)&&(p==power+1)) { - await fdOld.readToBuffer(buff, 0,(nPoints-1)*sGin ); - buff.set(curve.G1.zeroAffine, (nPoints-1)*sGin ); - } else { - await fdOld.readToBuffer(buff, 0,nPoints*sGin ); - } - await endReadSection$1(fdOld, true); - - - buff = await G.lagrangeEvaluations(buff, "affine", "affine", logger, sectionName); - await fdNew.write(buff); - - /* - if (p <= curve.Fr.s) { - buff = await G.ifft(buff, "affine", "affine", logger, sectionName); - await fdNew.write(buff); - } else if (p == curve.Fr.s+1) { - const smallM = 1<. - */ - - async function truncate(ptauFilename, template, logger) { - - const {fd: fdOld, sections} = await readBinFile$1(ptauFilename, "ptau", 1); - const {curve, power, ceremonyPower} = await readPTauHeader(fdOld, sections); - - const sG1 = curve.G1.F.n8*2; - const sG2 = curve.G2.F.n8*2; - - for (let p=1; p. - */ - - async function convert(oldPtauFilename, newPTauFilename, logger) { - - const {fd: fdOld, sections} = await readBinFile$1(oldPtauFilename, "ptau", 1); - const {curve, power} = await readPTauHeader(fdOld, sections); - - const fdNew = await createBinFile(newPTauFilename, "ptau", 1, 11); - await writePTauHeader(fdNew, curve, power); - - // const fdTmp = await fastFile.createOverride(newPTauFilename+ ".tmp"); - - await copySection(fdOld, sections, fdNew, 2); - await copySection(fdOld, sections, fdNew, 3); - await copySection(fdOld, sections, fdNew, 4); - await copySection(fdOld, sections, fdNew, 5); - await copySection(fdOld, sections, fdNew, 6); - await copySection(fdOld, sections, fdNew, 7); - - await processSection(2, 12, "G1", "tauG1" ); - await copySection(fdOld, sections, fdNew, 13); - await copySection(fdOld, sections, fdNew, 14); - await copySection(fdOld, sections, fdNew, 15); - - await fdOld.close(); - await fdNew.close(); - - // await fs.promises.unlink(newPTauFilename+ ".tmp"); - - return; - - async function processSection(oldSectionId, newSectionId, Gstr, sectionName) { - if (logger) logger.debug("Starting section: "+sectionName); - - await startWriteSection(fdNew, newSectionId); - - const size = sections[newSectionId][0].size; - const chunkSize = fdOld.pageSize; - await startReadUniqueSection$1(fdOld, sections, newSectionId); - for (let p=0; p. - */ - - async function exportJson(pTauFilename, verbose) { - const {fd, sections} = await readBinFile$1(pTauFilename, "ptau", 1); - - const {curve, power} = await readPTauHeader(fd, sections); - - const pTau = {}; - pTau.q = curve.q; - pTau.power = power; - pTau.contributions = await readContributions(fd, curve, sections); - - pTau.tauG1 = await exportSection(2, "G1", (2 ** power)*2 -1, "tauG1"); - pTau.tauG2 = await exportSection(3, "G2", (2 ** power), "tauG2"); - pTau.alphaTauG1 = await exportSection(4, "G1", (2 ** power), "alphaTauG1"); - pTau.betaTauG1 = await exportSection(5, "G1", (2 ** power), "betaTauG1"); - pTau.betaG2 = await exportSection(6, "G2", 1, "betaG2"); - - pTau.lTauG1 = await exportLagrange(12, "G1", "lTauG1"); - pTau.lTauG2 = await exportLagrange(13, "G2", "lTauG2"); - pTau.lAlphaTauG1 = await exportLagrange(14, "G1", "lAlphaTauG2"); - pTau.lBetaTauG1 = await exportLagrange(15, "G1", "lBetaTauG2"); - - await fd.close(); - - return stringifyBigIntsWithField(curve.Fr, pTau); - - - - async function exportSection(sectionId, groupName, nPoints, sectionName) { - const G = curve[groupName]; - const sG = G.F.n8*2; - - const res = []; - await startReadUniqueSection$1(fd, sections, sectionId); - for (let i=0; i< nPoints; i++) { - if ((verbose)&&i&&(i%10000 == 0)) console.log(`${sectionName}: ` + i); - const buff = await fd.read(sG); - res.push(G.fromRprLEM(buff, 0)); - } - await endReadSection$1(fd); - - return res; - } - - async function exportLagrange(sectionId, groupName, sectionName) { - const G = curve[groupName]; - const sG = G.F.n8*2; - - const res = []; - await startReadUniqueSection$1(fd, sections, sectionId); - for (let p=0; p<=power; p++) { - if (verbose) console.log(`${sectionName}: Power: ${p}`); - res[p] = []; - const nPoints = (2 ** p); - for (let i=0; i. - */ - - var powersoftau = /*#__PURE__*/Object.freeze({ - __proto__: null, - newAccumulator: newAccumulator, - exportChallenge: exportChallenge, - importResponse: importResponse, - verify: verify, - challengeContribute: challengeContribute, - beacon: beacon$1, - contribute: contribute, - preparePhase2: preparePhase2, - truncate: truncate, - convert: convert, - exportJson: exportJson - }); - - /* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . - */ - - function r1csPrint(r1cs, syms, logger) { - for (let i=0; i { - let S = ""; - const keys = Object.keys(lc); - keys.forEach( (k) => { - let name = syms.varIdx2Name[k]; - if (name == "one") name = "1"; - - let vs = r1cs.curve.Fr.toString(lc[k]); - if (vs == "1") vs = ""; // Do not show ones - if (vs == "-1") vs = "-"; // Do not show ones - if ((S!="")&&(vs[0]!="-")) vs = "+"+vs; - if (S!="") vs = " "+vs; - S= S + vs + name; - }); - return S; - }; - const S = `[ ${lc2str(c[0])} ] * [ ${lc2str(c[1])} ] - [ ${lc2str(c[2])} ] = 0`; - if (logger) logger.info(S); - } - - } - - const SUBARRAY_SIZE$1 = 0x40000; - - const BigArrayHandler$1 = { - get: function(obj, prop) { - if (!isNaN(prop)) { - return obj.getElement(prop); - } else return obj[prop]; - }, - set: function(obj, prop, value) { - if (!isNaN(prop)) { - return obj.setElement(prop, value); - } else { - obj[prop] = value; - return true; - } - } - }; - - class _BigArray$1 { - constructor (initSize) { - this.length = initSize || 0; - this.arr = new Array(SUBARRAY_SIZE$1); - - for (let i=0; i= this.length) this.length = idx+1; - return true; - } - getKeys() { - const newA = new BigArray$1(); - for (let i=0; i { - self.pendingLoads.push({ - page: p, - resolve: resolve, - reject: reject - }); - }); - self.__statusPage("After Load request: ", p); - return P; - } - - __statusPage(s, p) { - const logEntry = []; - const self=this; - if (!self.logHistory) return; - logEntry.push("==" + s+ " " +p); - let S = ""; - for (let i=0; i " + self.history[p][i][j]); - } - } - } - - - - _triggerLoad() { - const self = this; - - if (self.reading) return; - if (self.pendingLoads.length==0) return; - - const pageIdxs = Object.keys(self.pages); - - const deletablePages = []; - for (let i=0; i0) && - ( (typeof self.pages[self.pendingLoads[0].page] != "undefined" ) - ||( (freePages>0) - ||(deletablePages.length>0)))) { - const load = self.pendingLoads.shift(); - if (typeof self.pages[load.page] != "undefined") { - self.pages[load.page].pendingOps ++; - const idx = deletablePages.indexOf(load.page); - if (idx>=0) deletablePages.splice(idx, 1); - if (self.pages[load.page].loading) { - self.pages[load.page].loading.push(load); - } else { - load.resolve(); - } - self.__statusPage("After Load (cached): ", load.page); - - } else { - if (freePages) { - freePages--; - } else { - const fp = deletablePages.shift(); - self.__statusPage("Before Unload: ", fp); - self.avBuffs.unshift(self.pages[fp]); - delete self.pages[fp]; - self.__statusPage("After Unload: ", fp); - } - - if (load.page>=self.totalPages) { - self.pages[load.page] = getNewPage(); - load.resolve(); - self.__statusPage("After Load (new): ", load.page); - } else { - self.reading = true; - self.pages[load.page] = getNewPage(); - self.pages[load.page].loading = [load]; - ops.push(self.fd.read(self.pages[load.page].buff, 0, self.pageSize, load.page*self.pageSize).then((res)=> { - self.pages[load.page].size = res.bytesRead; - const loading = self.pages[load.page].loading; - delete self.pages[load.page].loading; - for (let i=0; i { - load.reject(err); - })); - self.__statusPage("After Load (loading): ", load.page); - } - } - } - // if (ops.length>1) console.log(ops.length); - - Promise.all(ops).then( () => { - self.reading = false; - if (self.pendingLoads.length>0) setImmediate(self._triggerLoad.bind(self)); - self._tryClose(); - }); - - function getNewPage() { - if (self.avBuffs.length>0) { - const p = self.avBuffs.shift(); - p.dirty = false; - p.pendingOps = 1; - p.size =0; - return p; - } else { - return { - dirty: false, - buff: new Uint8Array(self.pageSize), - pendingOps: 1, - size: 0 - }; - } - } - - } - - - _triggerWrite() { - const self = this; - if (self.writing) return; - - const pageIdxs = Object.keys(self.pages); - - const ops = []; - - for (let i=0; i { - page.writing = false; - return; - }, (err) => { - console.log("ERROR Writing: "+err); - self.error = err; - self._tryClose(); - })); - } - } - - if (self.writing) { - Promise.all(ops).then( () => { - self.writing = false; - setImmediate(self._triggerWrite.bind(self)); - self._tryClose(); - if (self.pendingLoads.length>0) setImmediate(self._triggerLoad.bind(self)); - }); - } - } - - _getDirtyPage() { - for (let p in this.pages) { - if (this.pages[p].dirty) return p; - } - return -1; - } - - async write(buff, pos) { - if (buff.byteLength == 0) return; - const self = this; - /* - if (buff.byteLength > self.pageSize*self.maxPagesLoaded*0.8) { - const cacheSize = Math.floor(buff.byteLength * 1.1); - this.maxPagesLoaded = Math.floor( cacheSize / self.pageSize)+1; - } - */ - if (typeof pos == "undefined") pos = self.pos; - self.pos = pos+buff.byteLength; - if (self.totalSize < pos + buff.byteLength) self.totalSize = pos + buff.byteLength; - if (self.pendingClose) - throw new Error("Writing a closing file"); - const firstPage = Math.floor(pos / self.pageSize); - const lastPage = Math.floor((pos + buff.byteLength -1) / self.pageSize); - - const pagePromises = []; - for (let i=firstPage; i<=lastPage; i++) pagePromises.push(self._loadPage(i)); - self._triggerLoad(); - - let p = firstPage; - let o = pos % self.pageSize; - let r = buff.byteLength; - while (r>0) { - await pagePromises[p-firstPage]; - const l = (o+r > self.pageSize) ? (self.pageSize -o) : r; - const srcView = buff.slice( buff.byteLength - r, buff.byteLength - r + l); - const dstView = new Uint8Array(self.pages[p].buff.buffer, o, l); - dstView.set(srcView); - self.pages[p].dirty = true; - self.pages[p].pendingOps --; - self.pages[p].size = Math.max(o+l, self.pages[p].size); - if (p>=self.totalPages) { - self.totalPages = p+1; - } - r = r-l; - p ++; - o = 0; - if (!self.writing) setImmediate(self._triggerWrite.bind(self)); - } - } - - async read(len, pos) { - const self = this; - let buff = new Uint8Array(len); - await self.readToBuffer(buff, 0, len, pos); - - return buff; - } - - async readToBuffer(buffDst, offset, len, pos) { - if (len == 0) { - return; - } - const self = this; - if (len > self.pageSize*self.maxPagesLoaded*0.8) { - const cacheSize = Math.floor(len * 1.1); - this.maxPagesLoaded = Math.floor( cacheSize / self.pageSize)+1; - } - if (typeof pos == "undefined") pos = self.pos; - self.pos = pos+len; - if (self.pendingClose) - throw new Error("Reading a closing file"); - const firstPage = Math.floor(pos / self.pageSize); - const lastPage = Math.floor((pos + len -1) / self.pageSize); - - const pagePromises = []; - for (let i=firstPage; i<=lastPage; i++) pagePromises.push(self._loadPage(i)); - - self._triggerLoad(); - - let p = firstPage; - let o = pos % self.pageSize; - // Remaining bytes to read - let r = pos + len > self.totalSize ? len - (pos + len - self.totalSize): len; - while (r>0) { - await pagePromises[p - firstPage]; - self.__statusPage("After Await (read): ", p); - - // bytes to copy from this page - const l = (o+r > self.pageSize) ? (self.pageSize -o) : r; - const srcView = new Uint8Array(self.pages[p].buff.buffer, self.pages[p].buff.byteOffset + o, l); - buffDst.set(srcView, offset+len-r); - self.pages[p].pendingOps --; - - self.__statusPage("After Op done: ", p); - - r = r-l; - p ++; - o = 0; - if (self.pendingLoads.length>0) setImmediate(self._triggerLoad.bind(self)); - } - - this.pos = pos + len; - - } - - - _tryClose() { - const self = this; - if (!self.pendingClose) return; - if (self.error) { - self.pendingCloseReject(self.error); - } - const p = self._getDirtyPage(); - if ((p>=0) || (self.writing) || (self.reading) || (self.pendingLoads.length>0)) return; - self.pendingClose(); - } - - close() { - const self = this; - if (self.pendingClose) - throw new Error("Closing the file twice"); - return new Promise((resolve, reject) => { - self.pendingClose = resolve; - self.pendingCloseReject = reject; - self._tryClose(); - }).then(()=> { - self.fd.close(); - }, (err) => { - self.fd.close(); - throw (err); - }); - } - - async discard() { - const self = this; - await self.close(); - await fs.promises.unlink(this.fileName); - } - - async writeULE32(v, pos) { - const self = this; - const tmpBuff32 = new Uint8Array(4); - const tmpBuff32v = new DataView(tmpBuff32.buffer); - - tmpBuff32v.setUint32(0, v, true); - - await self.write(tmpBuff32, pos); - } - - async writeUBE32(v, pos) { - const self = this; - - const tmpBuff32 = new Uint8Array(4); - const tmpBuff32v = new DataView(tmpBuff32.buffer); - - tmpBuff32v.setUint32(0, v, false); - - await self.write(tmpBuff32, pos); - } - - - async writeULE64(v, pos) { - const self = this; - - const tmpBuff64 = new Uint8Array(8); - const tmpBuff64v = new DataView(tmpBuff64.buffer); - - tmpBuff64v.setUint32(0, v & 0xFFFFFFFF, true); - tmpBuff64v.setUint32(4, Math.floor(v / 0x100000000) , true); - - await self.write(tmpBuff64, pos); - } - - async readULE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new Uint32Array(b.buffer); - - return view[0]; - } - - async readUBE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new DataView(b.buffer); - - return view.getUint32(0, false); - } - - async readULE64(pos) { - const self = this; - const b = await self.read(8, pos); - - const view = new Uint32Array(b.buffer); - - return view[1] * 0x100000000 + view[0]; - } - - async readString(pos) { - const self = this; - - if (self.pendingClose) { - throw new Error("Reading a closing file"); - } - - let currentPosition = typeof pos == "undefined" ? self.pos : pos; - let currentPage = Math.floor(currentPosition / self.pageSize); - - let endOfStringFound = false; - let str = ""; - - while (!endOfStringFound) { - //Read page - let pagePromise = self._loadPage(currentPage); - self._triggerLoad(); - await pagePromise; - self.__statusPage("After Await (read): ", currentPage); - - let offsetOnPage = currentPosition % self.pageSize; - - const dataArray = new Uint8Array( - self.pages[currentPage].buff.buffer, - self.pages[currentPage].buff.byteOffset + offsetOnPage, - self.pageSize - offsetOnPage - ); - - let indexEndOfString = dataArray.findIndex(element => element === 0); - endOfStringFound = indexEndOfString !== -1; - - if (endOfStringFound) { - str += new TextDecoder().decode(dataArray.slice(0, indexEndOfString)); - self.pos = currentPage * this.pageSize + offsetOnPage + indexEndOfString + 1; - } else { - str += new TextDecoder().decode(dataArray); - self.pos = currentPage * this.pageSize + offsetOnPage + dataArray.length; - } - - self.pages[currentPage].pendingOps--; - self.__statusPage("After Op done: ", currentPage); - - currentPosition = self.pos; - currentPage++; - - if (self.pendingLoads.length > 0) setImmediate(self._triggerLoad.bind(self)); - } - - return str; - } - } - - function readExisting$2(o) { - const fd = new MemFile(); - fd.o = o; - fd.allocSize = o.data.byteLength; - fd.totalSize = o.data.byteLength; - fd.readOnly = true; - fd.pos = 0; - return fd; - } - - const tmpBuff32$1 = new Uint8Array(4); - const tmpBuff32v$1 = new DataView(tmpBuff32$1.buffer); - const tmpBuff64$1 = new Uint8Array(8); - const tmpBuff64v$1 = new DataView(tmpBuff64$1.buffer); - - class MemFile { - - constructor() { - this.pageSize = 1 << 14; // for compatibility - } - - _resizeIfNeeded(newLen) { - if (newLen > this.allocSize) { - const newAllocSize = Math.max( - this.allocSize + (1 << 20), - Math.floor(this.allocSize * 1.1), - newLen - ); - const newData = new Uint8Array(newAllocSize); - newData.set(this.o.data); - this.o.data = newData; - this.allocSize = newAllocSize; - } - } - - async write(buff, pos) { - const self =this; - if (typeof pos == "undefined") pos = self.pos; - if (this.readOnly) throw new Error("Writing a read only file"); - - this._resizeIfNeeded(pos + buff.byteLength); - - this.o.data.set(buff.slice(), pos); - - if (pos + buff.byteLength > this.totalSize) this.totalSize = pos + buff.byteLength; - - this.pos = pos + buff.byteLength; - } - - async readToBuffer(buffDest, offset, len, pos) { - const self = this; - if (typeof pos == "undefined") pos = self.pos; - if (this.readOnly) { - if (pos + len > this.totalSize) throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos + len); - - const buffSrc = new Uint8Array(this.o.data.buffer, this.o.data.byteOffset + pos, len); - - buffDest.set(buffSrc, offset); - - this.pos = pos + len; - } - - async read(len, pos) { - const self = this; - - const buff = new Uint8Array(len); - await self.readToBuffer(buff, 0, len, pos); - - return buff; - } - - close() { - if (this.o.data.byteLength != this.totalSize) { - this.o.data = this.o.data.slice(0, this.totalSize); - } - } - - async discard() { - } - - - async writeULE32(v, pos) { - const self = this; - - tmpBuff32v$1.setUint32(0, v, true); - - await self.write(tmpBuff32$1, pos); - } - - async writeUBE32(v, pos) { - const self = this; - - tmpBuff32v$1.setUint32(0, v, false); - - await self.write(tmpBuff32$1, pos); - } - - - async writeULE64(v, pos) { - const self = this; - - tmpBuff64v$1.setUint32(0, v & 0xFFFFFFFF, true); - tmpBuff64v$1.setUint32(4, Math.floor(v / 0x100000000) , true); - - await self.write(tmpBuff64$1, pos); - } - - - async readULE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new Uint32Array(b.buffer); - - return view[0]; - } - - async readUBE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new DataView(b.buffer); - - return view.getUint32(0, false); - } - - async readULE64(pos) { - const self = this; - const b = await self.read(8, pos); - - const view = new Uint32Array(b.buffer); - - return view[1] * 0x100000000 + view[0]; - } - - async readString(pos) { - const self = this; - - let currentPosition = typeof pos == "undefined" ? self.pos : pos; - - if (currentPosition > this.totalSize) { - if (this.readOnly) { - throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos); - } - const dataArray = new Uint8Array( - self.o.data.buffer, - currentPosition, - this.totalSize - currentPosition - ); - - let indexEndOfString = dataArray.findIndex(element => element === 0); - let endOfStringFound = indexEndOfString !== -1; - - let str = ""; - if (endOfStringFound) { - str = new TextDecoder().decode(dataArray.slice(0, indexEndOfString)); - self.pos = currentPosition + indexEndOfString + 1; - } else { - self.pos = currentPosition; - } - return str; - } - } - - const PAGE_SIZE = 1<<22; - - function readExisting$1(o) { - const fd = new BigMemFile(); - fd.o = o; - fd.totalSize = (o.data.length-1)* PAGE_SIZE + o.data[o.data.length-1].byteLength; - fd.readOnly = true; - fd.pos = 0; - return fd; - } - - const tmpBuff32 = new Uint8Array(4); - const tmpBuff32v = new DataView(tmpBuff32.buffer); - const tmpBuff64 = new Uint8Array(8); - const tmpBuff64v = new DataView(tmpBuff64.buffer); - - class BigMemFile { - - constructor() { - this.pageSize = 1 << 14; // for compatibility - } - - _resizeIfNeeded(newLen) { - - if (newLen <= this.totalSize) return; - - if (this.readOnly) throw new Error("Reading out of file bounds"); - - const nPages = Math.floor((newLen - 1) / PAGE_SIZE)+1; - for (let i= Math.max(this.o.data.length-1, 0); i0) { - const l = (o+r > PAGE_SIZE) ? (PAGE_SIZE -o) : r; - const srcView = buff.slice(buff.byteLength - r, buff.byteLength - r + l); - const dstView = new Uint8Array(self.o.data[p].buffer, o, l); - dstView.set(srcView); - r = r-l; - p ++; - o = 0; - } - - this.pos = pos + buff.byteLength; - } - - async readToBuffer(buffDst, offset, len, pos) { - const self = this; - if (typeof pos == "undefined") pos = self.pos; - if (this.readOnly) { - if (pos + len > this.totalSize) throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos + len); - - const firstPage = Math.floor(pos / PAGE_SIZE); - - let p = firstPage; - let o = pos % PAGE_SIZE; - // Remaining bytes to read - let r = len; - while (r>0) { - // bytes to copy from this page - const l = (o+r > PAGE_SIZE) ? (PAGE_SIZE -o) : r; - const srcView = new Uint8Array(self.o.data[p].buffer, o, l); - buffDst.set(srcView, offset+len-r); - r = r-l; - p ++; - o = 0; - } - - this.pos = pos + len; - } - - async read(len, pos) { - const self = this; - const buff = new Uint8Array(len); - - await self.readToBuffer(buff, 0, len, pos); - - return buff; - } - - close() { - } - - async discard() { - } - - - async writeULE32(v, pos) { - const self = this; - - tmpBuff32v.setUint32(0, v, true); - - await self.write(tmpBuff32, pos); - } - - async writeUBE32(v, pos) { - const self = this; - - tmpBuff32v.setUint32(0, v, false); - - await self.write(tmpBuff32, pos); - } - - - async writeULE64(v, pos) { - const self = this; - - tmpBuff64v.setUint32(0, v & 0xFFFFFFFF, true); - tmpBuff64v.setUint32(4, Math.floor(v / 0x100000000) , true); - - await self.write(tmpBuff64, pos); - } - - - async readULE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new Uint32Array(b.buffer); - - return view[0]; - } - - async readUBE32(pos) { - const self = this; - const b = await self.read(4, pos); - - const view = new DataView(b.buffer); - - return view.getUint32(0, false); - } - - async readULE64(pos) { - const self = this; - const b = await self.read(8, pos); - - const view = new Uint32Array(b.buffer); - - return view[1] * 0x100000000 + view[0]; - } - - async readString(pos) { - const self = this; - const fixedSize = 2048; - - let currentPosition = typeof pos == "undefined" ? self.pos : pos; - - if (currentPosition > this.totalSize) { - if (this.readOnly) { - throw new Error("Reading out of bounds"); - } - this._resizeIfNeeded(pos); - } - - let endOfStringFound = false; - let str = ""; - - while (!endOfStringFound) { - let currentPage = Math.floor(currentPosition / PAGE_SIZE); - let offsetOnPage = currentPosition % PAGE_SIZE; - - if (self.o.data[currentPage] === undefined) { - throw new Error("ERROR"); - } - - let readLength = Math.min(fixedSize, self.o.data[currentPage].length - offsetOnPage); - const dataArray = new Uint8Array(self.o.data[currentPage].buffer, offsetOnPage, readLength); - - let indexEndOfString = dataArray.findIndex(element => element === 0); - endOfStringFound = indexEndOfString !== -1; - - if (endOfStringFound) { - str += new TextDecoder().decode(dataArray.slice(0, indexEndOfString)); - self.pos = currentPage * PAGE_SIZE + offsetOnPage + indexEndOfString + 1; - } else { - str += new TextDecoder().decode(dataArray); - self.pos = currentPage * PAGE_SIZE + offsetOnPage + dataArray.length; - } - - currentPosition = self.pos; - } - return str; - } - } - - /* global fetch */ - - async function readExisting(o, b, c) { - if (o instanceof Uint8Array) { - o = { - type: "mem", - data: o - }; - } - { - if (typeof o === "string") { - const buff = await fetch(o).then( function(res) { - return res.arrayBuffer(); - }).then(function (ab) { - return new Uint8Array(ab); - }); - o = { - type: "mem", - data: buff - }; - } - } - if (o.type == "file") { - return await open(o.fileName, O_RDONLY, o.cacheSize, o.pageSize); - } else if (o.type == "mem") { - return await readExisting$2(o); - } else if (o.type == "bigMem") { - return await readExisting$1(o); - } else { - throw new Error("Invalid FastFile type: "+o.type); - } - } - - async function readBinFile(fileName, type, maxVersion, cacheSize, pageSize) { - - const fd = await readExisting(fileName); - - const b = await fd.read(4); - let readedType = ""; - for (let i=0; i<4; i++) readedType += String.fromCharCode(b[i]); - - if (readedType != type) throw new Error(fileName + ": Invalid File format"); - - let v = await fd.readULE32(); - - if (v>maxVersion) throw new Error("Version not supported"); - - const nSections = await fd.readULE32(); - - // Scan sections - let sections = []; - for (let i=0; i1) throw new Error(fd.fileName +": Section Duplicated " +idSection); - - fd.pos = sections[idSection][0].p; - - fd.readingSection = sections[idSection][0]; - } - - async function endReadSection(fd, noCheck) { - if (typeof fd.readingSection === "undefined") throw new Error("Not reading a section"); - if (!noCheck) { - if (fd.pos-fd.readingSection.p != fd.readingSection.size) throw new Error("Invalid section size reading"); - } - delete fd.readingSection; - } - - async function readBigInt(fd, n8, pos) { - const buff = await fd.read(n8, pos); - return Scalar.fromRprLE(buff, 0, n8); - } - - async function readSection(fd, sections, idSection, offset, length) { - - offset = (typeof offset === "undefined") ? 0 : offset; - length = (typeof length === "undefined") ? sections[idSection][0].size - offset : length; - - if (offset + length > sections[idSection][0].size) { - throw new Error("Reading out of the range of the section"); - } - - let buff; - if (length < (1 << 30) ) { - buff = new Uint8Array(length); - } else { - buff = new BigBuffer(length); - } - - await fd.readToBuffer(buff, 0, length, sections[idSection][0].p + offset); - return buff; - } - - const R1CS_FILE_CUSTOM_GATES_LIST_SECTION = 4; - const R1CS_FILE_CUSTOM_GATES_USES_SECTION = 5; - - async function readR1csHeader(fd,sections,singleThread) { - let options; - if (typeof singleThread === "object") { - options = singleThread; - } else if (typeof singleThread === "undefined") { - options= { - singleThread: false, - }; - } else { - options = { - singleThread: singleThread, - }; - } - - const res = {}; - await startReadUniqueSection(fd, sections, 1); - // Read Header - res.n8 = await fd.readULE32(); - res.prime = await readBigInt(fd, res.n8); - - if (options.F) { - if (options.F.p != res.prime) throw new Error("Different Prime"); - res.F = options.F; - } else if (options.getFieldFromPrime) { - res.F = await options.getFieldFromPrime(res.prime, options.singleThread); - } else if (options.getCurveFromPrime) { - res.curve = await options.getCurveFromPrime(res.prime, options.singleThread); - res.F = res.curve.Fr; - } else { - try { - res.curve = await getCurveFromR$1(res.prime, options.singleThread); - res.F = res.curve.Fr; - } catch (err) { - res.F = new ZqField(res.prime); - } - } - - res.nVars = await fd.readULE32(); - res.nOutputs = await fd.readULE32(); - res.nPubInputs = await fd.readULE32(); - res.nPrvInputs = await fd.readULE32(); - res.nLabels = await fd.readULE64(); - res.nConstraints = await fd.readULE32(); - res.useCustomGates = typeof sections[R1CS_FILE_CUSTOM_GATES_LIST_SECTION] !== "undefined" && sections[R1CS_FILE_CUSTOM_GATES_LIST_SECTION] !== null - && typeof sections[R1CS_FILE_CUSTOM_GATES_USES_SECTION] !== "undefined" && sections[R1CS_FILE_CUSTOM_GATES_USES_SECTION] !== null; - - await endReadSection(fd); - - return res; - } - - async function readConstraints(fd,sections, r1cs, logger, loggerCtx) { - let options; - if (typeof logger === "object") { - options = logger; - } else if (typeof logger === "undefined") { - options= {}; - } else { - options = { - logger: logger, - loggerCtx: loggerCtx, - }; - } - - const bR1cs = await readSection(fd, sections, 2); - let bR1csPos = 0; - let constraints; - if (r1cs.nConstraints>1<<20) { - constraints = new BigArray$1(); - } else { - constraints = []; - } - for (let i=0; i1<<20) { - map = new BigArray$1(); - } else { - map = []; - } - for (let i=0; i true by default - * loadMap: false by default - * loadCustomGates: true by default - */ - - if(typeof options !== "object") { - throw new Error("readR1csFd: options must be an object"); - } - - options.loadConstraints = "loadConstraints" in options ? options.loadConstraints : true; - options.loadMap = "loadMap" in options ? options.loadMap : false; - options.loadCustomGates = "loadCustomGates" in options ? options.loadCustomGates : true; - - const res = await readR1csHeader(fd, sections, options); - - if (options.loadConstraints) { - res.constraints = await readConstraints(fd, sections, res, options); - } - - // Read Labels - - if (options.loadMap) { - res.map = await readMap(fd, sections, res, options); - } - - if (options.loadCustomGates) { - if (res.useCustomGates) { - res.customGates = await readCustomGatesListSection(fd, sections, res); - res.customGatesUses = await readCustomGatesUsesSection(fd, sections, options); - } else { - res.customGates = []; - res.customGatesUses = []; - } - } - return res; - } - - async function readR1cs(fileName, loadConstraints, loadMap, singleThread, logger, loggerCtx) { - let options; - if (typeof loadConstraints === "object") { - options = loadConstraints; - } else if (typeof loadConstraints === "undefined") { - options= { - loadConstraints: true, - loadMap: false, - loadCustomGates: true - }; - } else { - options = { - loadConstraints: loadConstraints, - loadMap: loadMap, - singleThread: singleThread, - logger: logger, - loggerCtx: loggerCtx - }; - } - - const {fd, sections} = await readBinFile(fileName, "r1cs", 1); - - const res = await readR1csFd(fd, sections, options); - - await fd.close(); - - return res; - } - - async function readCustomGatesListSection(fd, sections, res) { - await startReadUniqueSection(fd, sections, R1CS_FILE_CUSTOM_GATES_LIST_SECTION); - - let num = await fd.readULE32(); - - let customGates = []; - for (let i = 0; i < num; i++) { - let customGate = {}; - customGate.templateName = await fd.readString(); - let numParameters = await fd.readULE32(); - - customGate.parameters = Array(numParameters); - let buff = await fd.read(res.n8 * numParameters); - - for (let j = 0; j < numParameters; j++) { - customGate.parameters[j] = res.F.fromRprLE(buff, j * res.n8, res.n8); } - customGates.push(customGate); - } - await endReadSection(fd); - - return customGates; - } - - async function readCustomGatesUsesSection(fd,sections, options) { - const bR1cs = await readSection(fd, sections, R1CS_FILE_CUSTOM_GATES_USES_SECTION); - const bR1cs32 = new Uint32Array(bR1cs.buffer, bR1cs.byteOffset, bR1cs.byteLength/4); - const nCustomGateUses = bR1cs32[0]; - let bR1csPos = 1; - let customGatesUses; - if (nCustomGateUses>1<<20) { - customGatesUses = new BigArray$1(); - } else { - customGatesUses = []; - } - for (let i=0; i. - */ - - const bls12381r = Scalar.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16); - const bn128r = Scalar.e("21888242871839275222246405745257275088548364400416034343698204186575808495617"); - - async function r1csInfo(r1csName, logger) { - - const cir = await readR1cs(r1csName); - - if (Scalar.eq(cir.prime, bn128r)) { - if (logger) logger.info("Curve: bn-128"); - } else if (Scalar.eq(cir.prime, bls12381r)) { - if (logger) logger.info("Curve: bls12-381"); - } else { - if (logger) logger.info(`Unknown Curve. Prime: ${Scalar.toString(cir.prime)}`); - } - if (logger) logger.info(`# of Wires: ${cir.nVars}`); - if (logger) logger.info(`# of Constraints: ${cir.nConstraints}`); - if (logger) logger.info(`# of Private Inputs: ${cir.nPrvInputs}`); - if (logger) logger.info(`# of Public Inputs: ${cir.nPubInputs}`); - if (logger) logger.info(`# of Labels: ${cir.nLabels}`); - if (logger) logger.info(`# of Outputs: ${cir.nOutputs}`); - - return cir; - } - - /* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . - */ - - - async function r1csExportJson(r1csFileName, logger) { - - const cir = await readR1cs(r1csFileName, true, true, true, logger); - const Fr=cir.curve.Fr; - delete cir.curve; - delete cir.F; - - return stringifyBigIntsWithField(Fr, cir); - } - - /* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . - */ - - var r1cs = /*#__PURE__*/Object.freeze({ - __proto__: null, - print: r1csPrint, - info: r1csInfo, - exportJson: r1csExportJson - }); - - /* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . - */ - - async function loadSymbols(symFileName) { - const sym = { - labelIdx2Name: [ "one" ], - varIdx2Name: [ "one" ], - componentIdx2Name: [] - }; - const fd = await readExisting$3(symFileName); - const buff = await fd.read(fd.totalSize); - const symsStr = new TextDecoder("utf-8").decode(buff); - const lines = symsStr.split("\n"); - for (let i=0; i. - */ - const {unstringifyBigInts: unstringifyBigInts$7} = utils$6; - - - async function wtnsDebug(_input, wasmFileName, wtnsFileName, symName, options, logger) { - - const input = unstringifyBigInts$7(_input); - - const fdWasm = await readExisting$3(wasmFileName); - const wasm = await fdWasm.read(fdWasm.totalSize); - await fdWasm.close(); - - const wcOps = {...options, sanityCheck: true}; - let sym = await loadSymbols(symName); - if (options.set) { - if (!sym) sym = await loadSymbols(symName); - wcOps.logSetSignal= function(labelIdx, value) { - // The line below splits the arrow log into 2 strings to avoid some Secure ECMAScript issues - if (logger) logger.info("SET " + sym.labelIdx2Name[labelIdx] + " <" + "-- " + value.toString()); - }; - } - if (options.get) { - if (!sym) sym = await loadSymbols(symName); - wcOps.logGetSignal= function(varIdx, value) { - // The line below splits the arrow log into 2 strings to avoid some Secure ECMAScript issues - if (logger) logger.info("GET " + sym.labelIdx2Name[varIdx] + " --" + "> " + value.toString()); - }; - } - if (options.trigger) { - if (!sym) sym = await loadSymbols(symName); - wcOps.logStartComponent= function(cIdx) { - if (logger) logger.info("START: " + sym.componentIdx2Name[cIdx]); - }; - wcOps.logFinishComponent= function(cIdx) { - if (logger) logger.info("FINISH: " + sym.componentIdx2Name[cIdx]); - }; - } - wcOps.sym = sym; - - const wc = await builder(wasm, wcOps); - const w = await wc.calculateWitness(input, true); - - const fdWtns = await createBinFile(wtnsFileName, "wtns", 2, 2); - - await write(fdWtns, w, wc.prime); - - await fdWtns.close(); - } - - /* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . - */ - - async function wtnsExportJson(wtnsFileName) { - - const w = await read(wtnsFileName); - - return w; - } - - /* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . - */ - - async function wtnsCheck(r1csFilename, wtnsFilename, logger) { - - if (logger) logger.info("WITNESS CHECKING STARTED"); - - // Read r1cs file - if (logger) logger.info("> Reading r1cs file"); - const { - fd: fdR1cs, - sections: sectionsR1cs - } = await readBinFile$1(r1csFilename, "r1cs", 1); - const r1cs = await readR1csFd(fdR1cs, sectionsR1cs, { loadConstraints: false, loadCustomGates: false }); - - // Read witness file - if (logger) logger.info("> Reading witness file"); - const { - fd: fdWtns, - sections: wtnsSections - } = await readBinFile$1(wtnsFilename, "wtns", 2); - const wtnsHeader = await readHeader(fdWtns, wtnsSections); - - if (!Scalar.eq(r1cs.prime, wtnsHeader.q)) { - throw new Error("Curve of the witness does not match the curve of the proving key"); - } - - const buffWitness = await readSection$1(fdWtns, wtnsSections, 2); - await fdWtns.close(); - - const curve = await getCurveFromR(r1cs.prime); - const Fr = curve.Fr; - const sFr = Fr.n8; - - const bR1cs = await readSection$1(fdR1cs, sectionsR1cs, 2); - - if (logger) { - logger.info("----------------------------"); - logger.info(" WITNESS CHECK"); - logger.info(` Curve: ${r1cs.curve.name}`); - logger.info(` Vars (wires): ${r1cs.nVars}`); - logger.info(` Outputs: ${r1cs.nOutputs}`); - logger.info(` Public Inputs: ${r1cs.nPubInputs}`); - logger.info(` Private Inputs: ${r1cs.nPrvInputs}`); - logger.info(` Labels: ${r1cs.nLabels}`); - logger.info(` Constraints: ${r1cs.nConstraints}`); - logger.info(` Custom Gates: ${r1cs.useCustomGates}`); - logger.info("----------------------------"); - } - - if (logger) logger.info("> Checking witness correctness"); - - let bR1csPos = 0; - let res = true; - for (let i = 0; i < r1cs.nConstraints; i++) { - if ((logger) && (i !== 0) && (i % 500000 === 0)) { - logger.info(`··· processing r1cs constraints ${i}/${r1cs.nConstraints}`); - } - - //Read the three linear combinations of the constraint where A * B - C = 0 - const lcA = readLC(); - const lcB = readLC(); - const lcC = readLC(); - - // Evaluate the linear combinations - const evalA = EvaluateLinearCombination(lcA); - const evalB = EvaluateLinearCombination(lcB); - const evalC = EvaluateLinearCombination(lcC); - - // Check that A * B - C == 0 - if (!Fr.eq(Fr.sub(Fr.mul(evalA, evalB), evalC), Fr.zero)) { - logger.warn("··· aborting checking process at constraint " + i); - res = false; - break; - } - } - - fdR1cs.close(); - - if (logger) { - if (res) { - logger.info("WITNESS IS CORRECT"); - logger.info("WITNESS CHECKING FINISHED SUCCESSFULLY"); - } else { - logger.warn("WITNESS IS NOT CORRECT"); - logger.warn("WITNESS CHECKING FINISHED UNSUCCESSFULLY"); - } - } - - return res; - - function EvaluateLinearCombination(lc) { - let res = Fr.zero; - - const keys = Object.keys(lc); - keys.forEach((signalId) => { - const signalValue = getWitnessValue(signalId); - const signalFactor = lc[signalId]; - - res = Fr.add(res, Fr.mul(signalValue, signalFactor)); - }); - - return res; - } - - function readLC() { - const lc = {}; - - const buffUL32 = bR1cs.slice(bR1csPos, bR1csPos + 4); - bR1csPos += 4; - const buffUL32V = new DataView(buffUL32.buffer); - const nIdx = buffUL32V.getUint32(0, true); - - const buff = bR1cs.slice(bR1csPos, bR1csPos + (4 + r1cs.n8) * nIdx); - bR1csPos += (4 + r1cs.n8) * nIdx; - const buffV = new DataView(buff.buffer); - for (let i = 0; i < nIdx; i++) { - const idx = buffV.getUint32(i * (4 + r1cs.n8), true); - const val = r1cs.F.fromRprLE(buff, i * (4 + r1cs.n8) + 4); - lc[idx] = val; - } - return lc; - } - - function getWitnessValue(signalId) { - return Fr.fromRprLE(buffWitness.slice(signalId * sFr, signalId * sFr + sFr)); - } - } - - /* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . - */ - - var wtns = /*#__PURE__*/Object.freeze({ - __proto__: null, - calculate: wtnsCalculate, - debug: wtnsDebug, - exportJson: wtnsExportJson, - check: wtnsCheck - }); - - /* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . - */ - - const SUBARRAY_SIZE = 0x40000; - - const BigArrayHandler = { - get: function(obj, prop) { - if (!isNaN(prop)) { - return obj.getElement(prop); - } else return obj[prop]; - }, - set: function(obj, prop, value) { - if (!isNaN(prop)) { - return obj.setElement(prop, value); - } else { - obj[prop] = value; - return true; - } - } - }; - - class _BigArray { - constructor (initSize) { - this.length = initSize || 0; - this.arr = new Array(SUBARRAY_SIZE); - - for (let i=0; i= this.length) this.length = idx+1; - return true; - } - getKeys() { - const newA = new BigArray(); - for (let i=0; i. - */ - - async function newZKey(r1csName, ptauName, zkeyName, logger) { - - const TAU_G1 = 0; - const TAU_G2 = 1; - const ALPHATAU_G1 = 2; - const BETATAU_G1 = 3; - const csHasher = blake2b.create({ dkLen: 64 }); - - const {fd: fdPTau, sections: sectionsPTau} = await readBinFile$1(ptauName, "ptau", 1); - const {curve, power} = await readPTauHeader(fdPTau, sectionsPTau); - const {fd: fdR1cs, sections: sectionsR1cs} = await readBinFile$1(r1csName, "r1cs", 1); - const r1cs = await readR1csHeader(fdR1cs, sectionsR1cs, false); - - const fdZKey = await createBinFile(zkeyName, "zkey", 1, 10, 1<<22, 1<<24); - - const sG1 = curve.G1.F.n8*2; - const sG2 = curve.G2.F.n8*2; - - if (r1cs.prime != curve.r) { - if (logger) logger.error("r1cs curve does not match powers of tau ceremony curve"); - return -1; - } - - const cirPower = log2(r1cs.nConstraints + r1cs.nPubInputs + r1cs.nOutputs +1 -1) +1; - - if (cirPower > power) { - if (logger) logger.error(`circuit too big for this power of tau ceremony. ${r1cs.nConstraints}*2 > 2**${power}`); - return -1; - } - - if (!sectionsPTau[12]) { - if (logger) logger.error("Powers of tau is not prepared."); - return -1; - } - - const nPublic = r1cs.nOutputs + r1cs.nPubInputs; - const domainSize = 2 ** cirPower; - - // Write the header - /////////// - await startWriteSection(fdZKey, 1); - await fdZKey.writeULE32(1); // Groth - await endWriteSection(fdZKey); - - // Write the Groth header section - /////////// - - await startWriteSection(fdZKey, 2); - const primeQ = curve.q; - const n8q = (Math.floor( (Scalar.bitLength(primeQ) - 1) / 64) +1)*8; - - const primeR = curve.r; - const n8r = (Math.floor( (Scalar.bitLength(primeR) - 1) / 64) +1)*8; - const Rr = Scalar.mod(Scalar.shl(1, n8r*8), primeR); - const R2r = curve.Fr.e(Scalar.mod(Scalar.mul(Rr,Rr), primeR)); - - await fdZKey.writeULE32(n8q); - await writeBigInt(fdZKey, primeQ, n8q); - await fdZKey.writeULE32(n8r); - await writeBigInt(fdZKey, primeR, n8r); - await fdZKey.writeULE32(r1cs.nVars); // Total number of bars - await fdZKey.writeULE32(nPublic); // Total number of public vars (not including ONE) - await fdZKey.writeULE32(domainSize); // domainSize - - let bAlpha1; - bAlpha1 = await fdPTau.read(sG1, sectionsPTau[4][0].p); - await fdZKey.write(bAlpha1); - bAlpha1 = await curve.G1.batchLEMtoU(bAlpha1); - csHasher.update(bAlpha1); - - let bBeta1; - bBeta1 = await fdPTau.read(sG1, sectionsPTau[5][0].p); - await fdZKey.write(bBeta1); - bBeta1 = await curve.G1.batchLEMtoU(bBeta1); - csHasher.update(bBeta1); - - let bBeta2; - bBeta2 = await fdPTau.read(sG2, sectionsPTau[6][0].p); - await fdZKey.write(bBeta2); - bBeta2 = await curve.G2.batchLEMtoU(bBeta2); - csHasher.update(bBeta2); - - const bg1 = new Uint8Array(sG1); - curve.G1.toRprLEM(bg1, 0, curve.G1.g); - const bg2 = new Uint8Array(sG2); - curve.G2.toRprLEM(bg2, 0, curve.G2.g); - const bg1U = new Uint8Array(sG1); - curve.G1.toRprUncompressed(bg1U, 0, curve.G1.g); - const bg2U = new Uint8Array(sG2); - curve.G2.toRprUncompressed(bg2U, 0, curve.G2.g); - - await fdZKey.write(bg2); // gamma2 - await fdZKey.write(bg1); // delta1 - await fdZKey.write(bg2); // delta2 - csHasher.update(bg2U); // gamma2 - csHasher.update(bg1U); // delta1 - csHasher.update(bg2U); // delta2 - await endWriteSection(fdZKey); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("Reading r1cs"); - let sR1cs = await readSection$1(fdR1cs, sectionsR1cs, 2); - await fdR1cs.close(); - - let A = new BigArray(r1cs.nVars); - let B1 = new BigArray(r1cs.nVars); - let B2 = new BigArray(r1cs.nVars); - let C = new BigArray(r1cs.nVars- nPublic -1); - let IC = new Array(nPublic+1); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("Reading tauG1"); - let sTauG1 = await readSection$1(fdPTau, sectionsPTau, 12, (domainSize -1)*sG1, domainSize*sG1); - if (logger) logger.info("Reading tauG2"); - let sTauG2 = await readSection$1(fdPTau, sectionsPTau, 13, (domainSize -1)*sG2, domainSize*sG2); - if (logger) logger.info("Reading alphatauG1"); - let sAlphaTauG1 = await readSection$1(fdPTau, sectionsPTau, 14, (domainSize -1)*sG1, domainSize*sG1); - if (logger) logger.info("Reading betatauG1"); - let sBetaTauG1 = await readSection$1(fdPTau, sectionsPTau, 15, (domainSize -1)*sG1, domainSize*sG1); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("processConstraints"); - await processConstraints(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints"); - await composeAndWritePoints(3, "G1", IC, "IC"); - - IC = null; - // const gc = runInNewContext("gc"); // nocommit - // gc(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("writeHs"); - await writeHs(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("hashHPoints"); - await hashHPoints(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints 8 G1 C"); - await composeAndWritePoints(8, "G1", C, "C"); - - C = null; - // gc(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints 5 G1 A"); - await composeAndWritePoints(5, "G1", A, "A"); - - A = null; - // gc(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints 6 G1 B1"); - await composeAndWritePoints(6, "G1", B1, "B1"); - - B1 = null; - // gc(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints 7 G2 B2"); - await composeAndWritePoints(7, "G2", B2, "B2"); - - B2 = null; - // gc(); - - if (logger) logger.info(memUsage()); - if (logger) logger.info("Contributions section"); - const csHash = csHasher.digest(); - // Contributions section - await startWriteSection(fdZKey, 10); - await fdZKey.write(csHash); - await fdZKey.writeULE32(0); - await endWriteSection(fdZKey); - - if (logger) logger.info(formatHash(csHash, "Circuit hash: ")); - - - await fdZKey.close(); - await fdPTau.close(); - - return csHash; - - async function writeHs() { - await startWriteSection(fdZKey, 9); - const buffOut = new BigBuffer(domainSize*sG1); - if (cirPower < curve.Fr.s) { - let sTauG1 = await readSection$1(fdPTau, sectionsPTau, 12, (domainSize*2-1)*sG1, domainSize*2*sG1); - for (let i=0; i< domainSize; i++) { - if ((logger)&&(i%10000 == 0)) logger.debug(`splitting buffer: ${i}/${domainSize}`); - const buff = sTauG1.slice( (i*2+1)*sG1, (i*2+1)*sG1 + sG1 ); - buffOut.set(buff, i*sG1); - } - } else if (cirPower == curve.Fr.s) { - const o = sectionsPTau[12][0].p + ((2 ** (cirPower+1)) -1)*sG1; - await fdPTau.readToBuffer(buffOut, 0, domainSize*sG1, o + domainSize*sG1); - } else { - if (logger) logger.error("Circuit too big"); - throw new Error("Circuit too big for this curve"); - } - await fdZKey.write(buffOut); - await endWriteSection(fdZKey); - } - - async function processConstraints() { - const buffCoeff = new Uint8Array(12 + curve.Fr.n8); - const buffCoeffV = new DataView(buffCoeff.buffer); - const bOne = new Uint8Array(curve.Fr.n8); - curve.Fr.toRprLE(bOne, 0, curve.Fr.e(1)); - - let r1csPos = 0; - - function r1cs_readULE32() { - const buff = sR1cs.slice(r1csPos, r1csPos+4); - r1csPos += 4; - const buffV = new DataView(buff.buffer); - return buffV.getUint32(0, true); - } - - const coefs = new BigArray(); - for (let c=0; c=0) { - n = curve.Fr.fromRprLE(sR1cs.slice(c[3], c[3] + curve.Fr.n8), 0); - } else { - n = curve.Fr.fromRprLE(bOne, 0); - } - const nR2 = curve.Fr.mul(n, R2r); - curve.Fr.toRprLE(buffCoeff, 12, nR2); - buffSection.set(buffCoeff, coefsPos); - coefsPos += buffCoeff.length; - } - - } - - async function composeAndWritePoints(idSection, groupName, arr, sectionName) { - const CHUNK_SIZE= 1<<15; - const G = curve[groupName]; - - hashU32(arr.length); - await startWriteSection(fdZKey, idSection); - - let opPromises = []; - - let i=0; - while (i { - if (logger) logger.debug(`Writing points end ${sectionName}: ${_i}/${arr.length}`); - return r; - })); - i += n; - t++; - } - - const result = await Promise.all(opPromises); - - for (let k=0; k 2<<14) { - bBases = new BigBuffer(acc*sGin); - bScalars = new BigBuffer(acc*curve.Fr.n8); - } else { - bBases = new Uint8Array(acc*sGin); - bScalars = new Uint8Array(acc*curve.Fr.n8); - } - let pB =0; - let pS =0; - - const sBuffs = [ - sTauG1, - sTauG2, - sAlphaTauG1, - sBetaTauG1 - ]; - - const bOne = new Uint8Array(curve.Fr.n8); - curve.Fr.toRprLE(bOne, 0, curve.Fr.e(1)); - - let offset = 0; - for (let i=0; i=0) { - bScalars.set( - sR1cs.slice( - arr[i][j][2], - arr[i][j][2] + curve.Fr.n8 - ), - offset*curve.Fr.n8 - ); - } else { - bScalars.set(bOne, offset*curve.Fr.n8); - } - offset ++; - } - } - - if (arr.length>1) { - const task = []; - task.push({cmd: "ALLOCSET", var: 0, buff: bBases}); - task.push({cmd: "ALLOCSET", var: 1, buff: bScalars}); - task.push({cmd: "ALLOC", var: 2, len: arr.length*sGmid}); - pB = 0; - pS = 0; - let pD =0; - for (let i=0; i. - */ - - async function phase2importMPCParams(zkeyNameOld, mpcparamsName, zkeyNameNew, name, logger) { - - const {fd: fdZKeyOld, sections: sectionsZKeyOld} = await readBinFile$1(zkeyNameOld, "zkey", 2); - const zkeyHeader = await readHeader$1(fdZKeyOld, sectionsZKeyOld, false); - if (zkeyHeader.protocol != "groth16") { - throw new Error("zkey file is not groth16"); - } - - const curve = await getCurveFromQ(zkeyHeader.q); - const sG1 = curve.G1.F.n8*2; - const sG2 = curve.G2.F.n8*2; - - const oldMPCParams = await readMPCParams(fdZKeyOld, curve, sectionsZKeyOld); - const newMPCParams = {}; - - const fdMPCParams = await readExisting$3(mpcparamsName); - - fdMPCParams.pos = - sG1*3 + sG2*3 + // vKey - 8 + sG1*zkeyHeader.nVars + // IC + C - 4 + sG1*(zkeyHeader.domainSize-1) + // H - 4 + sG1*zkeyHeader.nVars + // A - 4 + sG1*zkeyHeader.nVars + // B1 - 4 + sG2*zkeyHeader.nVars; // B2 - - // csHash - newMPCParams.csHash = await fdMPCParams.read(64); - - const nContributions = await fdMPCParams.readUBE32(); - newMPCParams.contributions = []; - for (let i=0; i newMPCParams.contributions.length) { - if (logger) logger.error("The impoerted file does not include new contributions"); - return false; - } - - for (let i=0; i. - */ - const sameRatio = sameRatio$2; - - - - async function phase2verifyFromInit(initFileName, pTauFileName, zkeyFileName, logger) { - - let sr; - const {fd, sections} = await readBinFile$1(zkeyFileName, "zkey", 2); - const zkey = await readHeader$1(fd, sections, false); - if (zkey.protocol != "groth16") { - throw new Error("zkey file is not groth16"); - } - - const curve = await getCurveFromQ(zkey.q); - const sG1 = curve.G1.F.n8*2; - - const mpcParams = await readMPCParams(fd, curve, sections); - - const accumulatedHasher = blake2b.create({ dkLen: 64 }); - accumulatedHasher.update(mpcParams.csHash); - let curDelta = curve.G1.g; - for (let i=0; i=0; i--) { - const c = mpcParams.contributions[i]; - if (logger) logger.info("-------------------------"); - if (logger) logger.info(formatHash(c.contributionHash, `contribution #${i+1} ${c.name ? c.name : ""}:`)); - if (c.type == 1) { - if (logger) logger.info(`Beacon generator: ${byteArray2hex(c.beaconHash)}`); - if (logger) logger.info(`Beacon iterations Exp: ${c.numIterationsExp}`); - } - } - if (logger) logger.info("-------------------------"); - - if (logger) logger.info("ZKey Ok!"); - - return true; - - - async function sectionHasSameRatio(groupName, fd1, sections1, fd2, sections2, idSection, g2sp, g2spx, sectionName) { - const MAX_CHUNK_SIZE = 1<<20; - const G = curve[groupName]; - const sG = G.F.n8*2; - await startReadUniqueSection$1(fd1, sections1, idSection); - await startReadUniqueSection$1(fd2, sections2, idSection); - - let R1 = G.zero; - let R2 = G.zero; - - const nPoints = sections1[idSection][0].size / sG; - - for (let i=0; i. - */ - - async function phase2verifyFromR1cs(r1csFileName, pTauFileName, zkeyFileName, logger) { - - // const initFileName = "~" + zkeyFileName + ".init"; - const initFileName = {type: "bigMem"}; - await newZKey(r1csFileName, pTauFileName, initFileName, logger); - - return await phase2verifyFromInit(initFileName, pTauFileName, zkeyFileName, logger); - } - - /* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . - */ - - async function phase2contribute(zkeyNameOld, zkeyNameNew, name, entropy, logger) { - - const {fd: fdOld, sections: sections} = await readBinFile$1(zkeyNameOld, "zkey", 2); - const zkey = await readHeader$1(fdOld, sections); - if (zkey.protocol != "groth16") { - throw new Error("zkey file is not groth16"); - } - - const curve = await getCurveFromQ(zkey.q); - - const mpcParams = await readMPCParams(fdOld, curve, sections); - - const fdNew = await createBinFile(zkeyNameNew, "zkey", 1, 10); - - - const rng = await getRandomRng(entropy); - - const transcriptHasher = blake2b.create({ dkLen: 64 }); - transcriptHasher.update(mpcParams.csHash); - for (let i=0; i. - */ - - - async function beacon(zkeyNameOld, zkeyNameNew, name, beaconHashStr, numIterationsExp, logger) { - const beaconHash = hex2ByteArray(beaconHashStr); - if ( (beaconHash.byteLength == 0) - || (beaconHash.byteLength*2 !=beaconHashStr.length)) - { - if (logger) logger.error("Invalid Beacon Hash. (It must be a valid hexadecimal sequence)"); - return false; - } - if (beaconHash.length>=256) { - if (logger) logger.error("Maximum length of beacon hash is 255 bytes"); - return false; - } - - numIterationsExp = parseInt(numIterationsExp); - if ((numIterationsExp<10)||(numIterationsExp>63)) { - if (logger) logger.error("Invalid numIterationsExp. (Must be between 10 and 63)"); - return false; - } - - - const {fd: fdOld, sections: sections} = await readBinFile$1(zkeyNameOld, "zkey", 2); - const zkey = await readHeader$1(fdOld, sections); - - if (zkey.protocol != "groth16") { - throw new Error("zkey file is not groth16"); - } - - - const curve = await getCurveFromQ(zkey.q); - - const mpcParams = await readMPCParams(fdOld, curve, sections); - - const fdNew = await createBinFile(zkeyNameNew, "zkey", 1, 10); - - const rng = await rngFromBeaconParams(beaconHash, numIterationsExp); - - const transcriptHasher = blake2b.create({ dkLen: 64 }); transcriptHasher.update(mpcParams.csHash); - for (let i=0; i. - */ - - async function bellmanContribute(curve, challengeFilename, responseFileName, entropy, logger) { - const rng = await getRandomRng(entropy); - - const delta = curve.Fr.fromRng(rng); - const invDelta = curve.Fr.inv(delta); - - const sG1 = curve.G1.F.n8*2; - const sG2 = curve.G2.F.n8*2; - - const fdFrom = await readExisting$3(challengeFilename); - const fdTo = await createOverride(responseFileName); - - - await copy(sG1); // alpha1 - await copy(sG1); // beta1 - await copy(sG2); // beta2 - await copy(sG2); // gamma2 - const oldDelta1 = await readG1(); - const delta1 = curve.G1.timesFr(oldDelta1, delta); - await writeG1(delta1); - const oldDelta2 = await readG2(); - const delta2 = curve.G2.timesFr(oldDelta2, delta); - await writeG2(delta2); - - // IC - const nIC = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nIC); - await copy(nIC*sG1); - - // H - const nH = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nH); - await applyKeyToChallengeSection(fdFrom, fdTo, null, curve, "G1", nH, invDelta, curve.Fr.e(1), "UNCOMPRESSED", "H", logger); - - // L - const nL = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nL); - await applyKeyToChallengeSection(fdFrom, fdTo, null, curve, "G1", nL, invDelta, curve.Fr.e(1), "UNCOMPRESSED", "L", logger); - - // A - const nA = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nA); - await copy(nA*sG1); - - // B1 - const nB1 = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nB1); - await copy(nB1*sG1); - - // B2 - const nB2 = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nB2); - await copy(nB2*sG2); - - - ////////// - /// Read contributions - ////////// - const transcriptHasher = blake2b.create({ dkLen: 64 }); - const mpcParams = {}; - // csHash - mpcParams.csHash = await fdFrom.read(64); - transcriptHasher.update(mpcParams.csHash); - - const nContributions = await fdFrom.readUBE32(); - mpcParams.contributions = []; - for (let i=0; i. - */ - - const {stringifyBigInts: stringifyBigInts$3} = utils$6; - - async function zkeyExportVerificationKey(zkeyName, logger) { - if (logger) logger.info("EXPORT VERIFICATION KEY STARTED"); - - const {fd, sections} = await readBinFile$1(zkeyName, "zkey", 2); - const zkey = await readHeader$1(fd, sections); - - if (logger) logger.info("> Detected protocol: " + zkey.protocol); - - let res; - if (zkey.protocol === "groth16") { - res = await groth16Vk(zkey, fd, sections); - } else if (zkey.protocol === "plonk") { - res = await plonkVk(zkey); - } else if (zkey.protocolId && zkey.protocolId === FFLONK_PROTOCOL_ID) { - res = await exportFFlonkVk(zkey); - } else { - throw new Error("zkey file protocol unrecognized"); - } - - await fd.close(); - - if (logger) logger.info("EXPORT VERIFICATION KEY FINISHED"); - - return res; - } - - - async function groth16Vk(zkey, fd, sections) { - const curve = await getCurveFromQ(zkey.q); - const sG1 = curve.G1.F.n8 * 2; - - const alphaBeta = await curve.pairing(zkey.vk_alpha_1, zkey.vk_beta_2); - - let vKey = { - protocol: zkey.protocol, - curve: curve.name, - nPublic: zkey.nPublic, - - vk_alpha_1: curve.G1.toObject(zkey.vk_alpha_1), - - vk_beta_2: curve.G2.toObject(zkey.vk_beta_2), - vk_gamma_2: curve.G2.toObject(zkey.vk_gamma_2), - vk_delta_2: curve.G2.toObject(zkey.vk_delta_2), - - vk_alphabeta_12: curve.Gt.toObject(alphaBeta) - }; - - // Read IC Section - /////////// - await startReadUniqueSection$1(fd, sections, 3); - vKey.IC = []; - for (let i = 0; i <= zkey.nPublic; i++) { - const buff = await fd.read(sG1); - const P = curve.G1.toObject(buff); - vKey.IC.push(P); - } - await endReadSection$1(fd); - - vKey = stringifyBigInts$3(vKey); - - return vKey; - } - - - async function plonkVk(zkey) { - const curve = await getCurveFromQ(zkey.q); - - let vKey = { - protocol: zkey.protocol, - curve: curve.name, - nPublic: zkey.nPublic, - power: zkey.power, - - k1: curve.Fr.toObject(zkey.k1), - k2: curve.Fr.toObject(zkey.k2), - - Qm: curve.G1.toObject(zkey.Qm), - Ql: curve.G1.toObject(zkey.Ql), - Qr: curve.G1.toObject(zkey.Qr), - Qo: curve.G1.toObject(zkey.Qo), - Qc: curve.G1.toObject(zkey.Qc), - S1: curve.G1.toObject(zkey.S1), - S2: curve.G1.toObject(zkey.S2), - S3: curve.G1.toObject(zkey.S3), - - X_2: curve.G2.toObject(zkey.X_2), - - w: curve.Fr.toObject(curve.Fr.w[zkey.power]) - }; - - vKey = stringifyBigInts$3(vKey); - - return vKey; - } - - async function exportFFlonkVk(zkey, logger) { - const curve = await getCurveFromQ(zkey.q); - - let vKey = { - protocol: zkey.protocol, - curve: curve.name, - nPublic: zkey.nPublic, - power: zkey.power, - - k1: curve.Fr.toObject(zkey.k1), - k2: curve.Fr.toObject(zkey.k2), - - w: curve.Fr.toObject(curve.Fr.w[zkey.power]), - //wW: curve.Fr.toObject(curve.Fr.w[zkey.power + 1]), - w3: curve.Fr.toObject(zkey.w3), - w4: curve.Fr.toObject(zkey.w4), - w8: curve.Fr.toObject(zkey.w8), - wr: curve.Fr.toObject(zkey.wr), - - X_2: curve.G2.toObject(zkey.X_2), - - C0: curve.G1.toObject(zkey.C0), - }; - - return stringifyBigInts$3(vKey); - } - - /* - Copyright 2021 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . - */ - - const {unstringifyBigInts: unstringifyBigInts$6, stringifyBigInts: stringifyBigInts$2} = utils$6; - - async function fflonkExportSolidityVerifier(vk, templates, logger) { - if (logger) logger.info("FFLONK EXPORT SOLIDITY VERIFIER STARTED"); - - const curve = await getCurveFromName(vk.curve); - - // Precompute w3_2, w4_2 and w4_3 - let w3 = fromVkey(vk.w3); - vk.w3_2 = toVkey(curve.Fr.square(w3)); - - let w4 = fromVkey(vk.w4); - vk.w4_2 = toVkey(curve.Fr.square(w4)); - vk.w4_3 = toVkey(curve.Fr.mul(curve.Fr.square(w4), w4)); - - let w8 = fromVkey(vk.w8); - let acc = curve.Fr.one; - - for (let i = 1; i < 8; i++) { - acc = curve.Fr.mul(acc, w8); - vk["w8_" + i] = toVkey(acc); - } - - let template = templates[vk.protocol]; - - if (logger) logger.info("FFLONK EXPORT SOLIDITY VERIFIER FINISHED"); - - const {default: ejs} = await Promise.resolve().then(function () { return _virtual_ejs$1; }); - return ejs.render(template, vk); - - function fromVkey(str) { - const val = unstringifyBigInts$6(str); - return curve.Fr.fromObject(val); - } - - function toVkey(val) { - const str = curve.Fr.toObject(val); - return stringifyBigInts$2(str); - } - } - - // Not ready yet - // module.exports.generateVerifier_kimleeoh = generateVerifier_kimleeoh; - - async function exportSolidityVerifier(zKeyName, templates, logger) { - - const verificationKey = await zkeyExportVerificationKey(zKeyName, logger); - - if ("fflonk" === verificationKey.protocol) { - return fflonkExportSolidityVerifier(verificationKey, templates, logger); - } - - let template = templates[verificationKey.protocol]; - - const {default: ejs} = await Promise.resolve().then(function () { return _virtual_ejs$1; }); - - return ejs.render(template, verificationKey); - } - - /* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . - */ - - var zkey = /*#__PURE__*/Object.freeze({ - __proto__: null, - newZKey: newZKey, - exportBellman: phase2exportMPCParams, - importBellman: phase2importMPCParams, - verifyFromR1cs: phase2verifyFromR1cs, - verifyFromInit: phase2verifyFromInit, - contribute: phase2contribute, - beacon: beacon, - exportJson: zkeyExportJson, - bellmanContribute: bellmanContribute, - exportVerificationKey: zkeyExportVerificationKey, - exportSolidityVerifier: exportSolidityVerifier - }); - - /* - Copyright 2021 0kims association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . - */ - - - async function plonkSetup(r1csName, ptauName, zkeyName, logger) { - - if (globalThis.gc) {globalThis.gc();} - - const {fd: fdPTau, sections: sectionsPTau} = await readBinFile$1(ptauName, "ptau", 1); - const {curve, power} = await readPTauHeader(fdPTau, sectionsPTau); - const {fd: fdR1cs, sections: sectionsR1cs} = await readBinFile$1(r1csName, "r1cs", 1); - - const r1cs = await readR1csFd(fdR1cs, sectionsR1cs, {loadConstraints: true, loadCustomGates: true}); - - const sG1 = curve.G1.F.n8*2; - const G1 = curve.G1; - const sG2 = curve.G2.F.n8*2; - const Fr = curve.Fr; - const n8r = curve.Fr.n8; - - if (logger) logger.info("Reading r1cs"); - await readSection$1(fdR1cs, sectionsR1cs, 2); - - const plonkConstraints = new BigArray(); - const plonkAdditions = new BigArray(); - let plonkNVars = r1cs.nVars; - - const nPublic = r1cs.nOutputs + r1cs.nPubInputs; - - await processConstraints(curve.Fr, r1cs, logger); - - if (globalThis.gc) {globalThis.gc();} - - const fdZKey = await createBinFile(zkeyName, "zkey", 1, 14, 1<<22, 1<<24); - - - if (r1cs.prime != curve.r) { - if (logger) logger.error("r1cs curve does not match powers of tau ceremony curve"); - return -1; - } - - let cirPower = log2(plonkConstraints.length -1) +1; - if (cirPower < 3) cirPower = 3; // As the t polynomial is n+5 we need at least a power of 4 - const domainSize = 2 ** cirPower; - - if (logger) logger.info("Plonk constraints: " + plonkConstraints.length); - if (cirPower > power) { - if (logger) logger.error(`circuit too big for this power of tau ceremony. ${plonkConstraints.length} > 2**${power}`); - return -1; - } - - if (!sectionsPTau[12]) { - if (logger) logger.error("Powers of tau is not prepared."); - return -1; - } - - - const LPoints = new BigBuffer(domainSize*sG1); - const o = sectionsPTau[12][0].p + ((2 ** (cirPower)) -1)*sG1; - await fdPTau.readToBuffer(LPoints, 0, domainSize*sG1, o); - - const [k1, k2] = getK1K2(); - - const vk = {}; - - - await writeAdditions(3, "Additions"); - if (globalThis.gc) {globalThis.gc();} - await writeWitnessMap(4, 0, "Amap"); - if (globalThis.gc) {globalThis.gc();} - await writeWitnessMap(5, 1, "Bmap"); - if (globalThis.gc) {globalThis.gc();} - await writeWitnessMap(6, 2, "Cmap"); - if (globalThis.gc) {globalThis.gc();} - await writeQMap(7, 3, "Qm"); - if (globalThis.gc) {globalThis.gc();} - await writeQMap(8, 4, "Ql"); - if (globalThis.gc) {globalThis.gc();} - await writeQMap(9, 5, "Qr"); - if (globalThis.gc) {globalThis.gc();} - await writeQMap(10, 6, "Qo"); - if (globalThis.gc) {globalThis.gc();} - await writeQMap(11, 7, "Qc"); - if (globalThis.gc) {globalThis.gc();} - await writeSigma(12, "sigma"); - if (globalThis.gc) {globalThis.gc();} - await writeLs(13, "lagrange polynomials"); - if (globalThis.gc) {globalThis.gc();} - - // Write PTau points - //////////// - - await startWriteSection(fdZKey, 14); - const buffOut = new BigBuffer((domainSize+6)*sG1); - await fdPTau.readToBuffer(buffOut, 0, (domainSize+6)*sG1, sectionsPTau[2][0].p); - await fdZKey.write(buffOut); - await endWriteSection(fdZKey); - if (globalThis.gc) {globalThis.gc();} - - - await writeHeaders(); - - await fdZKey.close(); - await fdR1cs.close(); - await fdPTau.close(); - - if (logger) logger.info("Setup Finished"); - - return ; - - async function processConstraints(Fr, r1cs, logger) { - - function normalize(linearComb) { - const ss = Object.keys(linearComb); - for (let i = 0; i < ss.length; i++) { - if (linearComb[ss[i]] == 0n) delete linearComb[ss[i]]; - } - } - - function join(linearComb1, k, linearComb2) { - const res = {}; - - for (let s in linearComb1) { - if (typeof res[s] == "undefined") { - res[s] = Fr.mul(k, linearComb1[s]); - } else { - res[s] = Fr.add(res[s], Fr.mul(k, linearComb1[s])); - } - } - - for (let s in linearComb2) { - if (typeof res[s] == "undefined") { - res[s] = linearComb2[s]; - } else { - res[s] = Fr.add(res[s], linearComb2[s]); - } - } - normalize(res); - return res; - } - - function reduceCoefs(linearComb, maxC) { - const res = { - k: Fr.zero, - s: [], - coefs: [] - }; - const cs = []; - - for (let s in linearComb) { - if (s == 0) { - res.k = Fr.add(res.k, linearComb[s]); - } else if (linearComb[s] != 0n) { - cs.push([Number(s), linearComb[s]]); - } - } - while (cs.length > maxC) { - const c1 = cs.shift(); - const c2 = cs.shift(); - - const sl = c1[0]; - const sr = c2[0]; - const so = plonkNVars++; - const qm = Fr.zero; - const ql = Fr.neg(c1[1]); - const qr = Fr.neg(c2[1]); - const qo = Fr.one; - const qc = Fr.zero; - - plonkConstraints.push([sl, sr, so, qm, ql, qr, qo, qc]); - - plonkAdditions.push([sl, sr, c1[1], c2[1]]); - - cs.push([so, Fr.one]); - } - for (let i = 0; i < cs.length; i++) { - res.s[i] = cs[i][0]; - res.coefs[i] = cs[i][1]; - } - while (res.coefs.length < maxC) { - res.s.push(0); - res.coefs.push(Fr.zero); - } - return res; - } - - function addConstraintSum(lc) { - const C = reduceCoefs(lc, 3); - const sl = C.s[0]; - const sr = C.s[1]; - const so = C.s[2]; - const qm = Fr.zero; - const ql = C.coefs[0]; - const qr = C.coefs[1]; - const qo = C.coefs[2]; - const qc = C.k; - plonkConstraints.push([sl, sr, so, qm, ql, qr, qo, qc]); - } - - function addConstraintMul(lcA, lcB, lcC) { - const A = reduceCoefs(lcA, 1); - const B = reduceCoefs(lcB, 1); - const C = reduceCoefs(lcC, 1); - - - const sl = A.s[0]; - const sr = B.s[0]; - const so = C.s[0]; - const qm = Fr.mul(A.coefs[0], B.coefs[0]); - const ql = Fr.mul(A.coefs[0], B.k); - const qr = Fr.mul(A.k, B.coefs[0]); - const qo = Fr.neg(C.coefs[0]); - const qc = Fr.sub(Fr.mul(A.k, B.k), C.k); - plonkConstraints.push([sl, sr, so, qm, ql, qr, qo, qc]); - } - - function getLinearCombinationType(lc) { - let k = Fr.zero; - let n = 0; - const ss = Object.keys(lc); - for (let i = 0; i < ss.length; i++) { - if (lc[ss[i]] == 0n) { - delete lc[ss[i]]; - } else if (ss[i] == 0) { - k = Fr.add(k, lc[ss[i]]); - } else { - n++; - } - } - if (n > 0) return n.toString(); - if (k != Fr.zero) return "k"; - return "0"; - } - - function process(lcA, lcB, lcC) { - const lctA = getLinearCombinationType(lcA); - const lctB = getLinearCombinationType(lcB); - if ((lctA === "0") || (lctB === "0")) { - normalize(lcC); - addConstraintSum(lcC); - } else if (lctA === "k") { - const lcCC = join(lcB, lcA[0], lcC); - addConstraintSum(lcCC); - } else if (lctB === "k") { - const lcCC = join(lcA, lcB[0], lcC); - addConstraintSum(lcCC); - } else { - addConstraintMul(lcA, lcB, lcC); - } - } - - for (let s = 1; s <= nPublic; s++) { - const sl = s; - const sr = 0; - const so = 0; - const qm = Fr.zero; - const ql = Fr.one; - const qr = Fr.zero; - const qo = Fr.zero; - const qc = Fr.zero; - - plonkConstraints.push([sl, sr, so, qm, ql, qr, qo, qc]); - } - - for (let c = 0; c < r1cs.constraints.length; c++) { - if ((logger) && (c % 10000 === 0)) logger.debug(`processing constraints: ${c}/${r1cs.nConstraints}`); - process(...r1cs.constraints[c]); - } - } - - async function writeWitnessMap(sectionNum, posConstraint, name) { - await startWriteSection(fdZKey, sectionNum); - for (let i=0; i. - */ - - class Proof { - constructor(curve, logger) { - this.curve = curve; - this.logger = logger; - - this.resetProof(); - } - - resetProof() { - this.polynomials = {}; - this.evaluations = {}; - } - - addPolynomial(key, polynomial) { - if (key in this.polynomials) { - this.logger.warn(`proof: polynomial.${key} already exist in proof`); - } - this.polynomials[key] = polynomial; - } - - getPolynomial(key) { - if (!(key in this.polynomials)) { - this.logger.warn(`proof: polynomial ${key} does not exist in proof`); - } - return this.polynomials[key]; - } - - addEvaluation(key, evaluation) { - if (key in this.evaluations) { - this.logger.warn(`proof: evaluations.${key} already exist in proof`); - } - this.evaluations[key] = evaluation; - } - - getEvaluation(key) { - if (!(key in this.evaluations)) { - this.logger.warn(`proof: evaluation ${key} does not exist in proof`); - } - return this.evaluations[key]; - } - - toObjectProof(splitFields = true) { - let res = splitFields ? {polynomials: {}, evaluations: {}} : {}; - - Object.keys(this.polynomials).forEach(key => { - const value = this.curve.G1.toObject(this.polynomials[key]); - if(splitFields) { - res.polynomials[key] = value; - } else { - res[key] = value; - } - }); - - Object.keys(this.evaluations).forEach(key => { - const value = this.curve.Fr.toObject(this.evaluations[key]); - if(splitFields) { - res.evaluations[key] = value; - } else { - res[key] = value; - } - }); - - return res; - } - - fromObjectProof(objectProof) { - this.resetProof(); - - Object.keys(objectProof.polynomials).forEach(key => { - this.polynomials[key] = this.curve.G1.fromObject(objectProof.polynomials[key]); - }); - - Object.keys(objectProof.evaluations).forEach(key => { - this.evaluations[key] = this.curve.Fr.fromObject(objectProof.evaluations[key]); - }); - } - } - - /** - * SHA3 (keccak) hash function, based on a new "Sponge function" design. - * Different from older hashes, the internal state is bigger than output size. - * - * Check out [FIPS-202](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf), - * [Website](https://keccak.team/keccak.html), - * [the differences between SHA-3 and Keccak](https://crypto.stackexchange.com/questions/15727/what-are-the-key-differences-between-the-draft-sha-3-standard-and-the-keccak-sub). - * - * Check out `sha3-addons` module for cSHAKE, k12, and others. - * @module - */ - // Various per round constants calculations - const SHA3_PI = []; - const SHA3_ROTL = []; - const _SHA3_IOTA = []; - const _0n = /* @__PURE__ */ BigInt(0); - const _1n = /* @__PURE__ */ BigInt(1); - const _2n = /* @__PURE__ */ BigInt(2); - const _7n = /* @__PURE__ */ BigInt(7); - const _256n = /* @__PURE__ */ BigInt(256); - const _0x71n = /* @__PURE__ */ BigInt(0x71); - for (let round = 0, R = _1n, x = 1, y = 0; round < 24; round++) { - // Pi - [x, y] = [y, (2 * x + 3 * y) % 5]; - SHA3_PI.push(2 * (5 * y + x)); - // Rotational - SHA3_ROTL.push((((round + 1) * (round + 2)) / 2) % 64); - // Iota - let t = _0n; - for (let j = 0; j < 7; j++) { - R = ((R << _1n) ^ ((R >> _7n) * _0x71n)) % _256n; - if (R & _2n) - t ^= _1n << ((_1n << /* @__PURE__ */ BigInt(j)) - _1n); - } - _SHA3_IOTA.push(t); - } - const [SHA3_IOTA_H, SHA3_IOTA_L] = /* @__PURE__ */ split(_SHA3_IOTA, true); - // Left rotation (without 0, 32, 64) - const rotlH = (h, l, s) => (s > 32 ? rotlBH(h, l, s) : rotlSH(h, l, s)); - const rotlL = (h, l, s) => (s > 32 ? rotlBL(h, l, s) : rotlSL(h, l, s)); - /** `keccakf1600` internal function, additionally allows to adjust round count. */ - function keccakP(s, rounds = 24) { - const B = new Uint32Array(5 * 2); - // NOTE: all indices are x2 since we store state as u32 instead of u64 (bigints to slow in js) - for (let round = 24 - rounds; round < 24; round++) { - // Theta θ - for (let x = 0; x < 10; x++) - B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40]; - for (let x = 0; x < 10; x += 2) { - const idx1 = (x + 8) % 10; - const idx0 = (x + 2) % 10; - const B0 = B[idx0]; - const B1 = B[idx0 + 1]; - const Th = rotlH(B0, B1, 1) ^ B[idx1]; - const Tl = rotlL(B0, B1, 1) ^ B[idx1 + 1]; - for (let y = 0; y < 50; y += 10) { - s[x + y] ^= Th; - s[x + y + 1] ^= Tl; - } - } - // Rho (ρ) and Pi (π) - let curH = s[2]; - let curL = s[3]; - for (let t = 0; t < 24; t++) { - const shift = SHA3_ROTL[t]; - const Th = rotlH(curH, curL, shift); - const Tl = rotlL(curH, curL, shift); - const PI = SHA3_PI[t]; - curH = s[PI]; - curL = s[PI + 1]; - s[PI] = Th; - s[PI + 1] = Tl; - } - // Chi (χ) - for (let y = 0; y < 50; y += 10) { - for (let x = 0; x < 10; x++) - B[x] = s[y + x]; - for (let x = 0; x < 10; x++) - s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10]; - } - // Iota (ι) - s[0] ^= SHA3_IOTA_H[round]; - s[1] ^= SHA3_IOTA_L[round]; - } - B.fill(0); - } - /** Keccak sponge function. */ - class Keccak extends Hash { - // NOTE: we accept arguments in bytes instead of bits here. - constructor(blockLen, suffix, outputLen, enableXOF = false, rounds = 24) { - super(); - this.blockLen = blockLen; - this.suffix = suffix; - this.outputLen = outputLen; - this.enableXOF = enableXOF; - this.rounds = rounds; - this.pos = 0; - this.posOut = 0; - this.finished = false; - this.destroyed = false; - // Can be passed from user as dkLen - anumber(outputLen); - // 1600 = 5x5 matrix of 64bit. 1600 bits === 200 bytes - // 0 < blockLen < 200 - if (0 >= this.blockLen || this.blockLen >= 200) - throw new Error('Sha3 supports only keccak-f1600 function'); - this.state = new Uint8Array(200); - this.state32 = u32(this.state); - } - keccak() { - if (!isLE) - byteSwap32(this.state32); - keccakP(this.state32, this.rounds); - if (!isLE) - byteSwap32(this.state32); - this.posOut = 0; - this.pos = 0; - } - update(data) { - aexists(this); - const { blockLen, state } = this; - data = toBytes(data); - const len = data.length; - for (let pos = 0; pos < len;) { - const take = Math.min(blockLen - this.pos, len - pos); - for (let i = 0; i < take; i++) - state[this.pos++] ^= data[pos++]; - if (this.pos === blockLen) - this.keccak(); - } - return this; - } - finish() { - if (this.finished) - return; - this.finished = true; - const { state, suffix, pos, blockLen } = this; - // Do the padding - state[pos] ^= suffix; - if ((suffix & 0x80) !== 0 && pos === blockLen - 1) - this.keccak(); - state[blockLen - 1] ^= 0x80; - this.keccak(); - } - writeInto(out) { - aexists(this, false); - abytes(out); - this.finish(); - const bufferOut = this.state; - const { blockLen } = this; - for (let pos = 0, len = out.length; pos < len;) { - if (this.posOut >= blockLen) - this.keccak(); - const take = Math.min(blockLen - this.posOut, len - pos); - out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos); - this.posOut += take; - pos += take; - } - return out; - } - xofInto(out) { - // Sha3/Keccak usage with XOF is probably mistake, only SHAKE instances can do XOF - if (!this.enableXOF) - throw new Error('XOF is not possible for this instance'); - return this.writeInto(out); - } - xof(bytes) { - anumber(bytes); - return this.xofInto(new Uint8Array(bytes)); - } - digestInto(out) { - aoutput(out, this); - if (this.finished) - throw new Error('digest() was already called'); - this.writeInto(out); - this.destroy(); - return out; - } - digest() { - return this.digestInto(new Uint8Array(this.outputLen)); - } - destroy() { - this.destroyed = true; - this.state.fill(0); - } - _cloneInto(to) { - const { blockLen, suffix, outputLen, rounds, enableXOF } = this; - to || (to = new Keccak(blockLen, suffix, outputLen, enableXOF, rounds)); - to.state32.set(this.state32); - to.pos = this.pos; - to.posOut = this.posOut; - to.finished = this.finished; - to.rounds = rounds; - // Suffix can change in cSHAKE - to.suffix = suffix; - to.outputLen = outputLen; - to.enableXOF = enableXOF; - to.destroyed = this.destroyed; - return to; - } - } - const gen = (suffix, blockLen, outputLen) => wrapConstructor(() => new Keccak(blockLen, suffix, outputLen)); - /** keccak-256 hash function. Different from SHA3-256. */ - const keccak_256 = /* @__PURE__ */ gen(0x01, 136, 256 / 8); - - /* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . - */ - - const POLYNOMIAL = 0; - const SCALAR = 1; - - class Keccak256Transcript { - constructor(curve) { - this.G1 = curve.G1; - this.Fr = curve.Fr; - - this.reset(); - } - - reset() { - this.data = []; - } - - addPolCommitment(polynomialCommitment) { - this.data.push({type: POLYNOMIAL, data: polynomialCommitment}); - } - - addScalar(scalar) { - this.data.push({type: SCALAR, data: scalar}); - } - - getChallenge() { - if(0 === this.data.length) { - throw new Error("Keccak256Transcript: No data to generate a transcript"); - } - - let nPolynomials = 0; - let nScalars = 0; - - this.data.forEach(element => POLYNOMIAL === element.type ? nPolynomials++ : nScalars++); - - let buffer = new Uint8Array(nScalars * this.Fr.n8 + nPolynomials * this.G1.F.n8 * 2); - let offset = 0; - - for (let i = 0; i < this.data.length; i++) { - if (POLYNOMIAL === this.data[i].type) { - this.G1.toRprUncompressed(buffer, offset, this.data[i].data); - offset += this.G1.F.n8 * 2; - } else { - this.Fr.toRprBE(buffer, offset, this.data[i].data); - offset += this.Fr.n8; - } - } - - const value = Scalar.fromRprBE(keccak_256(buffer)); - return this.Fr.e(value); - } - } - - /* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . - */ - - class MulZ { - static getZ1(Fr) { - return [ - Fr.zero, - Fr.add(Fr.e(-1), Fr.w[2]), - Fr.e(-2), - Fr.sub(Fr.e(-1), Fr.w[2]), - ]; - } - - static getZ2(Fr) { - return [ - Fr.zero, - Fr.add(Fr.zero, Fr.mul(Fr.e(-2), Fr.w[2])), - Fr.e(4), - Fr.sub(Fr.zero, Fr.mul(Fr.e(-2), Fr.w[2])), - ]; - } - - static getZ3(Fr) { - return [ - Fr.zero, - Fr.add(Fr.e(2), Fr.mul(Fr.e(2), Fr.w[2])), - Fr.e(-8), - Fr.sub(Fr.e(2), Fr.mul(Fr.e(2), Fr.w[2])), - ]; - - } - - static mul2(a, b, ap, bp, p, Fr) { - const Z1 = this.getZ1(Fr); - let r, rz; - - const a_b = Fr.mul(a, b); - const a_bp = Fr.mul(a, bp); - const ap_b = Fr.mul(ap, b); - const ap_bp = Fr.mul(ap, bp); - - r = a_b; - - let a0 = Fr.add(a_bp, ap_b); - - let a1 = ap_bp; - - rz = a0; - if (p) { - rz = Fr.add(rz, Fr.mul(Z1[p], a1)); - } - - return [r, rz]; - } - - static mul3(a, b, c, ap, bp, cp, p, Fr) { - const Z1 = this.getZ1(Fr); - const Z2 = this.getZ2(Fr); - let r, rz; - - const a_b = Fr.mul(a, b); - const a_bp = Fr.mul(a, bp); - const ap_b = Fr.mul(ap, b); - const ap_bp = Fr.mul(ap, bp); - - r = Fr.mul(a_b, c); - - let a0 = Fr.mul(ap_b, c); - a0 = Fr.add(a0, Fr.mul(a_bp, c)); - a0 = Fr.add(a0, Fr.mul(a_b, cp)); - - let a1 = Fr.mul(ap_bp, c); - a1 = Fr.add(a1, Fr.mul(a_bp, cp)); - a1 = Fr.add(a1, Fr.mul(ap_b, cp)); - - rz = a0; - if (p) { - const a2 = Fr.mul(ap_bp, cp); - rz = Fr.add(rz, Fr.mul(Z1[p], a1)); - rz = Fr.add(rz, Fr.mul(Z2[p], a2)); - } - - return [r, rz]; - } - - static mul4(a, b, c, d, ap, bp, cp, dp, p, Fr) { - const Z1 = this.getZ1(Fr); - const Z2 = this.getZ2(Fr); - const Z3 = this.getZ3(Fr); - - let r, rz; - - const a_b = Fr.mul(a, b); - const a_bp = Fr.mul(a, bp); - const ap_b = Fr.mul(ap, b); - const ap_bp = Fr.mul(ap, bp); - - const c_d = Fr.mul(c, d); - const c_dp = Fr.mul(c, dp); - const cp_d = Fr.mul(cp, d); - const cp_dp = Fr.mul(cp, dp); - - r = Fr.mul(a_b, c_d); - - let a0 = Fr.mul(ap_b, c_d); - a0 = Fr.add(a0, Fr.mul(a_bp, c_d)); - a0 = Fr.add(a0, Fr.mul(a_b, cp_d)); - a0 = Fr.add(a0, Fr.mul(a_b, c_dp)); - - let a1 = Fr.mul(ap_bp, c_d); - a1 = Fr.add(a1, Fr.mul(ap_b, cp_d)); - a1 = Fr.add(a1, Fr.mul(ap_b, c_dp)); - a1 = Fr.add(a1, Fr.mul(a_bp, cp_d)); - a1 = Fr.add(a1, Fr.mul(a_bp, c_dp)); - a1 = Fr.add(a1, Fr.mul(a_b, cp_dp)); - - let a2 = Fr.mul(a_bp, cp_dp); - a2 = Fr.add(a2, Fr.mul(ap_b, cp_dp)); - a2 = Fr.add(a2, Fr.mul(ap_bp, c_dp)); - a2 = Fr.add(a2, Fr.mul(ap_bp, cp_d)); - - let a3 = Fr.mul(ap_bp, cp_dp); - - rz = a0; - if (p) { - rz = Fr.add(rz, Fr.mul(Z1[p], a1)); - rz = Fr.add(rz, Fr.mul(Z2[p], a2)); - rz = Fr.add(rz, Fr.mul(Z3[p], a3)); - } - - return [r, rz]; - } - } - - const ZKEY_PL_ADDITIONS_SECTION = 3; - const ZKEY_PL_A_MAP_SECTION = 4; - const ZKEY_PL_B_MAP_SECTION = 5; - const ZKEY_PL_C_MAP_SECTION = 6; - const ZKEY_PL_QM_SECTION = 7; - const ZKEY_PL_QL_SECTION = 8; - const ZKEY_PL_QR_SECTION = 9; - const ZKEY_PL_QO_SECTION = 10; - const ZKEY_PL_QC_SECTION = 11; - const ZKEY_PL_SIGMA_SECTION = 12; - const ZKEY_PL_LAGRANGE_SECTION = 13; - const ZKEY_PL_PTAU_SECTION = 14; - - /* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . - */ - - class Polynomial { - constructor(coefficients, curve, logger) { - this.coef = coefficients; - this.curve = curve; - this.Fr = curve.Fr; - this.G1 = curve.G1; - this.logger = logger; - } - - static async fromEvaluations(buffer, curve, logger) { - let coefficients = await curve.Fr.ifft(buffer); - - return new Polynomial(coefficients, curve, logger); - } - - static fromCoefficientsArray(array, curve, logger) { - const Fr = curve.Fr; - let buff = array.length > 2 << 14 ? - new BigBuffer(array.length * Fr.n8) : new Uint8Array(array.length * Fr.n8); - for (let i = 0; i < array.length; i++) buff.set(array[i], i * Fr.n8); - - return new Polynomial(buff, curve, logger); - } - - static fromPolynomial(polynomial, curve, logger) { - let length = polynomial.length(); - let Fr = curve.Fr; - - let buff = length > 2 << 14 ? - new BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8); - buff.set(polynomial.coef.slice(), 0); - - return new Polynomial(buff, curve, logger); - } - - isEqual(polynomial) { - const degree = this.degree(); - if (degree !== polynomial.degree()) return false; - - for (let i = 0; i < degree + 1; i++) { - if (!this.Fr.eq(this.getCoef(i), polynomial.getCoef(i))) return false; - } - - return true; - } - - blindCoefficients(blindingFactors) { - blindingFactors = blindingFactors || []; - - const blindedCoefficients = (this.length() + blindingFactors.length) > 2 << 14 ? - new BigBuffer((this.length() + blindingFactors.length) * this.Fr.n8) : - new Uint8Array((this.length() + blindingFactors.length) * this.Fr.n8); - - blindedCoefficients.set(this.coef, 0); - for (let i = 0; i < blindingFactors.length; i++) { - blindedCoefficients.set( - this.Fr.add( - blindedCoefficients.slice((this.length() + i) * this.Fr.n8, (this.length() + i + 1) * this.Fr.n8), - blindingFactors[i] - ), - (this.length() + i) * this.Fr.n8 - ); - blindedCoefficients.set( - this.Fr.sub( - blindedCoefficients.slice(i * this.Fr.n8, (i + 1) * this.Fr.n8), - blindingFactors[i] - ), - i * this.Fr.n8 - ); - } - this.coef = blindedCoefficients; - } - - getCoef(index) { - const i_n8 = index * this.Fr.n8; - - if (i_n8 + this.Fr.n8 > this.coef.byteLength) return this.Fr.zero; - - return this.coef.slice(i_n8, i_n8 + this.Fr.n8); - } - - setCoef(index, value) { - if (index > (this.length() - 1)) { - throw new Error("Coef index is not available"); - } - - this.coef.set(value, index * this.Fr.n8); - } - - static async to4T(buffer, domainSize, blindingFactors, Fr) { - blindingFactors = blindingFactors || []; - let a = await Fr.ifft(buffer); - - const a4 = (domainSize * 4) > 2 << 14 ? - new BigBuffer(domainSize * 4 * Fr.n8) : new Uint8Array(domainSize * 4 * Fr.n8); - a4.set(a, 0); - - const A4 = await Fr.fft(a4); - - if (blindingFactors.length === 0) { - return [a, A4]; - } - - const a1 = domainSize + blindingFactors.length > 2 << 14 ? - new BigBuffer((domainSize + blindingFactors.length) * Fr.n8) : - new Uint8Array((domainSize + blindingFactors.length) * Fr.n8); - - a1.set(a, 0); - for (let i = 0; i < blindingFactors.length; i++) { - a1.set( - Fr.add( - a1.slice((domainSize + i) * Fr.n8, (domainSize + i + 1) * Fr.n8), - blindingFactors[i] - ), - (domainSize + i) * Fr.n8 - ); - a1.set( - Fr.sub( - a1.slice(i * Fr.n8, (i + 1) * Fr.n8), - blindingFactors[i] - ), - i * Fr.n8 - ); - } - - return [a1, A4]; - } - - length() { - let length = this.coef.byteLength / this.Fr.n8; - if (length !== Math.floor(this.coef.byteLength / this.Fr.n8)) { - throw new Error("Polynomial coefficients buffer has incorrect size"); - } - if (0 === length) { - if (this.logger) { - this.logger.warn("Polynomial has length zero"); - } - } - return length; - } - - degree() { - for (let i = this.length() - 1; i > 0; i--) { - const i_n8 = i * this.Fr.n8; - if (!this.Fr.eq(this.Fr.zero, this.coef.slice(i_n8, i_n8 + this.Fr.n8))) { - return i; - } - } - - return 0; - } - - evaluate(point) { - let res = this.Fr.zero; - - for (let i = this.degree() + 1; i > 0; i--) { - let i_n8 = i * this.Fr.n8; - const currentCoefficient = this.coef.slice(i_n8 - this.Fr.n8, i_n8); - res = this.Fr.add(currentCoefficient, this.Fr.mul(res, point)); - } - - return res; - } - - fastEvaluate(point) { - const Fr = this.Fr; - let nThreads = 3; - - let nCoefs = this.degree() + 1; - let coefsThread = parseInt(nCoefs / nThreads); - let residualCoefs = nCoefs - coefsThread * nThreads; - - let res = []; - let xN = []; - - xN[0] = Fr.one; - - for (let i = 0; i < nThreads; i++) { - res[i] = Fr.zero; - - let nCoefs = i === (nThreads - 1) ? coefsThread + residualCoefs : coefsThread; - for (let j = nCoefs; j > 0; j--) { - res[i] = Fr.add(this.getCoef((i * coefsThread) + j - 1), Fr.mul(res[i], point)); - - if (i === 0) xN[0] = Fr.mul(xN[0], point); - } - } - - for (let i = 1; i < nThreads; i++) { - res[0] = Fr.add(res[0], Fr.mul(xN[i - 1], res[i])); - xN[i] = Fr.mul(xN[i - 1], xN[0]); - } - - return res[0]; - } - - add(polynomial, blindingValue) { - let other = false; - - if (polynomial.length() > this.length()) { - other = true; - } - - const thisLength = this.length(); - const polyLength = polynomial.length(); - for (let i = 0; i < Math.max(thisLength, polyLength); i++) { - const i_n8 = i * this.Fr.n8; - - const a = i < thisLength ? this.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; - let b = i < polyLength ? polynomial.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; - - if (blindingValue !== undefined) { - b = this.Fr.mul(b, blindingValue); - } - if (other) { - polynomial.coef.set(this.Fr.add(a, b), i_n8); - } else { - this.coef.set(this.Fr.add(a, b), i_n8); - } - } - if (other) { - delete this.coef; - this.coef = polynomial.coef; - } - } - - sub(polynomial, blindingValue) { - let other = false; - - if (polynomial.length() > this.length()) { - other = true; - } - - const thisLength = this.length(); - const polyLength = polynomial.length(); - for (let i = 0; i < Math.max(thisLength, polyLength); i++) { - const i_n8 = i * this.Fr.n8; - - const a = i < thisLength ? this.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; - let b = i < polyLength ? polynomial.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; - - if (blindingValue !== undefined) { - b = this.Fr.mul(b, blindingValue); - } - if (other) { - polynomial.coef.set(this.Fr.sub(a, b), i_n8); - } else { - this.coef.set(this.Fr.sub(a, b), i_n8); - } - } - if (other) { - delete this.coef; - this.coef = polynomial.coef; - } - } - - mulScalar(value) { - for (let i = 0; i < this.length(); i++) { - const i_n8 = i * this.Fr.n8; - - this.coef.set(this.Fr.mul(this.coef.slice(i_n8, i_n8 + this.Fr.n8), value), i_n8); - } - } - - addScalar(value) { - const currentValue = 0 === this.length() ? this.Fr.zero : this.coef.slice(0, this.Fr.n8); - this.coef.set(this.Fr.add(currentValue, value), 0); - } - - subScalar(value) { - const currentValue = 0 === this.length() ? this.Fr.zero : this.coef.slice(0, this.Fr.n8); - this.coef.set(this.Fr.sub(currentValue, value), 0); - } - - // Multiply current polynomial by the polynomial (X - value) - byXSubValue(value) { - const Fr = this.Fr; - const resize = !Fr.eq(Fr.zero, this.getCoef(this.length() - 1)); - - const length = resize ? this.length() + 1 : this.length(); - const buff = length > 2 << 14 ? new BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8); - let pol = new Polynomial(buff, this.curve, this.logger); - - // Step 0: Set current coefficients to the new buffer shifted one position - pol.coef.set(this.coef.slice(0, (length - 1) * Fr.n8), 32); - - // Step 1: multiply each coefficient by (-value) - this.mulScalar(Fr.neg(value)); - - // Step 2: Add current polynomial to destination polynomial - pol.add(this); - - // Swap buffers - this.coef = pol.coef; - } - - // Multiply current polynomial by the polynomial (X^n + value) - byXNSubValue(n, value) { - const Fr = this.Fr; - const resize = !(this.length() - n - 1 >= this.degree()); - - const length = resize ? this.length() + n : this.length(); - const buff = length > 2 << 14 ? new BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8); - let pol = new Polynomial(buff, this.curve, this.logger); - - // Step 0: Set current coefficients to the new buffer shifted one position - pol.coef.set(this.coef.slice(0, (this.degree() + 1) * 32, ), n * 32); - - // Step 1: multiply each coefficient by (- value) - this.mulScalar(value); - - // Step 2: Add current polynomial to destination polynomial - pol.add(this); - - // Swap buffers - this.coef = pol.coef; - } - - // Euclidean division - divBy(polynomial) { - const Fr = this.Fr; - const degreeA = this.degree(); - const degreeB = polynomial.degree(); - - let polR = new Polynomial(this.coef, this.curve, this.logger); - - this.coef = this.length() > 2 << 14 ? - new BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); - - for (let i = degreeA - degreeB; i >= 0; i--) { - this.setCoef(i, Fr.div(polR.getCoef(i + degreeB), polynomial.getCoef(degreeB))); - for (let j = 0; j <= degreeB; j++) { - polR.setCoef(i + j, Fr.sub(polR.getCoef(i + j), Fr.mul(this.getCoef(i), polynomial.getCoef(j)))); - } - } - - return polR; - } - - // Division by a Polynomial of the form (x^m - beta) - divByMonic(m, beta) { - const Fr = this.Fr; - - let d = this.degree(); - - let buffer = this.length() > 2 << 14 ? - new BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); - let quotient = new Polynomial(buffer, this.curve, this.logger); - - let bArr = []; - - // Add the m leading coefficients of this to quotient - for (let i = 0; i < m; i++) { - quotient.setCoef((d - i) - m, this.getCoef(d - i)); - bArr[i] = this.getCoef(d - i); - } - - let nThreads = m; - for (let k = 0; k < nThreads; k++) { - for (let i = d - 2 * m - k; i >= 0; i = i - nThreads) { - if (i < 0) break; - let idx = k; - bArr[idx] = Fr.add(this.getCoef(i + m), Fr.mul(bArr[idx], beta)); - - quotient.setCoef(i, bArr[idx]); - } - } - - this.coef = quotient.coef; - } - - divByVanishing(n, beta) { - if (this.degree() < n) { - throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); - } - - const Fr = this.Fr; - - let polR = new Polynomial(this.coef, this.curve, this.logger); - - this.coef = this.length() > 2 << 14 ? - new BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); - - for (let i = this.length() - 1; i >= n; i--) { - let leadingCoef = polR.getCoef(i); - if (Fr.eq(Fr.zero, leadingCoef)) continue; - - polR.setCoef(i, Fr.zero); - polR.setCoef(i - n, Fr.add(polR.getCoef(i - n), Fr.mul(beta, leadingCoef))); - this.setCoef(i - n, Fr.add(this.getCoef(i - n), leadingCoef)); - } - - return polR; - } - - divByVanishing2(m, beta) { - if (this.degree() < m) { - throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); - } - - const Fr = this.Fr; - - let polR = new Polynomial(this.coef, this.curve, this.logger); - - this.coef = this.length() > 2 << 14 ? - new BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); - - let nThreads = 3; - let nTotal = this.length() - m; - let nElementsChunk = Math.floor(nTotal / nThreads); - let nElementsLast = nTotal - (nThreads - 1) * nElementsChunk; - - console.log(nTotal); - console.log(nElementsChunk + " " + nElementsLast); - for (let k = 0; k < nThreads; k++) { - console.log("> Thread " + k); - for (let i = (k === 0 ? nElementsLast : nElementsChunk); i > 0; i--) { - let idxDst = i - 1; - if (k !== 0) idxDst += (k - 1) * nElementsChunk + nElementsLast; - let idxSrc = idxDst + m; - - let leadingCoef = polR.getCoef(idxSrc); - if (Fr.eq(Fr.zero, leadingCoef)) continue; - - polR.setCoef(idxSrc, Fr.zero); - polR.setCoef(idxDst, Fr.add(polR.getCoef(idxDst), Fr.mul(beta, leadingCoef))); - this.setCoef(idxDst, Fr.add(this.getCoef(idxDst), leadingCoef)); - console.log(idxDst + " <-- " + idxSrc); - } - } - - this.print(); - return polR; - } - - fastDivByVanishing(data) { - const Fr = this.Fr; - - for (let i = 0; i < data.length; i++) { - - let m = data[i][0]; - let beta = data[i][1]; - - if (this.degree() < m) { - throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); - } - - let nThreads = 5; - let nElements = this.length() - m; - let nElementsBucket = Math.floor(nElements / nThreads / m); - let nElementsChunk = nElementsBucket * m; - let nElementsLast = nElements - nThreads * nElementsChunk; - - //In C++ implementation this buffer will be allocated only once outside the loop - let polTmp = new Polynomial(this.length() > 2 << 14 ? - new BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8), this.curve, this.logger); - - let ptr = this.coef; - this.coef = polTmp.coef; - polTmp.coef = ptr; - - // STEP 1: Setejar els m valors del següent bucket al chunk actual, PARALEL·LITZAR - for (let k = 0; k < nThreads; k++) { - let idx0 = (k + 1) * nElementsChunk + nElementsLast; - for (let i = 0; i < m; i++) { - this.setCoef(idx0 + i - m, polTmp.getCoef(idx0 + i)); - } - - for (let i = 0; i < nElementsChunk - m; i++) { - let offset = idx0 - i - 1; - let val = Fr.add(polTmp.getCoef(offset), Fr.mul(beta, this.getCoef(offset))); - this.setCoef(offset - m, val); - } - } - - //STEP 2: Setejar els valors del elements last NO PARAL·LELITZAR - let idx0 = nElementsLast; - let pending = nElementsLast; - for (let i = 0; i < m && pending; i++) { - this.setCoef(idx0 - i - 1, polTmp.getCoef(idx0 + m - i - 1)); - pending--; - } - - for (let i = 0; i < pending; i++) { - let offset = idx0 - i - 1; - let val = Fr.add(polTmp.getCoef(offset), Fr.mul(beta, this.getCoef(offset))); - this.setCoef(offset - m, val); - } - - //Step 3: calcular acumulats NO PARALEL·LITZAR - - let acc = []; - let betaPow = Fr.one; - for (let i = 0; i < nElementsBucket; i++) { - betaPow = Fr.mul(betaPow, beta); - } - let currentBeta = Fr.one; - - for (let k = nThreads; k > 0; k--) { - let idThread = k - 1; - let idx0 = idThread * nElementsChunk + nElementsLast; - acc[idThread] = []; - - for (let i = 0; i < m; i++) { - acc[idThread][i] = this.getCoef(idx0 + i); - - if (k !== nThreads) { - acc[idThread][i] = Fr.add(acc[idThread][i], Fr.mul(betaPow, acc[idThread + 1][i])); - } - } - currentBeta = Fr.mul(currentBeta, betaPow); - } - - //STEP 4 recalcular PARALEL·LITZAR - for (let k = 0; k < nThreads; k++) { - - let idx0 = k * nElementsChunk + nElementsLast; - let currentBeta = beta; //Quan hopassem a C++ i ho paralelitzem aquesta variable ha de ser privada - let currentM = m - 1; - - let limit = k === 0 ? nElementsLast : nElementsChunk; - for (let i = 0; i < limit; i++) { - let offset = idx0 - i - 1; - let val = Fr.add(this.getCoef(offset), Fr.mul(currentBeta, acc[k][currentM])); - - this.setCoef(offset, val); - - // To avoid modular operations in each loop... - if (currentM === 0) { - currentM = m - 1; - currentBeta = Fr.mul(currentBeta, beta); - } else { - currentM--; - } - } - } - } - } - - - // Divide polynomial by X - value - divByXSubValue(value) { - const coefs = this.length() > 2 << 14 ? - new BigBuffer(this.length() * this.Fr.n8) : new Uint8Array(this.length() * this.Fr.n8); - - coefs.set(this.Fr.zero, (this.length() - 1) * this.Fr.n8); - coefs.set(this.coef.slice((this.length() - 1) * this.Fr.n8, this.length() * this.Fr.n8), (this.length() - 2) * this.Fr.n8); - for (let i = this.length() - 3; i >= 0; i--) { - let i_n8 = i * this.Fr.n8; - coefs.set( - this.Fr.add( - this.coef.slice(i_n8 + this.Fr.n8, i_n8 + 2 * this.Fr.n8), - this.Fr.mul(value, coefs.slice(i_n8 + this.Fr.n8, i_n8 + 2 * this.Fr.n8)) - ), - i * this.Fr.n8 - ); - } - if (!this.Fr.eq( - this.coef.slice(0, this.Fr.n8), - this.Fr.mul(this.Fr.neg(value), coefs.slice(0, this.Fr.n8)) - )) { - throw new Error("Polynomial does not divide"); - } - - this.coef = coefs; - } - - divZh(domainSize, extensions = 4) { - for (let i = 0; i < domainSize; i++) { - const i_n8 = i * this.Fr.n8; - this.coef.set(this.Fr.neg(this.coef.slice(i_n8, i_n8 + this.Fr.n8)), i_n8); - } - - const upperBound = this.coef.byteLength / this.Fr.n8; - for (let i = domainSize; i < upperBound; i++) { - const i_n8 = i * this.Fr.n8; - - const a = this.Fr.sub( - this.coef.slice((i - domainSize) * this.Fr.n8, (i - domainSize) * this.Fr.n8 + this.Fr.n8), - this.coef.slice(i_n8, i_n8 + this.Fr.n8) - ); - this.coef.set(a, i_n8); - if (i > (domainSize * (extensions-1) - extensions)) { - if (!this.Fr.isZero(a)) { - throw new Error("Polynomial is not divisible"); - } - } - } - - return this; - } - - divByZerofier(n, beta) { - let Fr = this.Fr; - const invBeta = Fr.inv(beta); - const invBetaNeg = Fr.neg(invBeta); - - let isOne = Fr.eq(Fr.one, invBetaNeg); - let isNegOne = Fr.eq(Fr.negone, invBetaNeg); - - if (!isOne) { - for (let i = 0; i < n; i++) { - const i_n8 = i * this.Fr.n8; - let element; - - // If invBetaNeg === -1 we'll save a multiplication changing it by a neg function call - if (isNegOne) { - element = Fr.neg(this.coef.slice(i_n8, i_n8 + this.Fr.n8)); - } else { - element = Fr.mul(invBetaNeg, this.coef.slice(i_n8, i_n8 + this.Fr.n8)); - } - - this.coef.set(element, i_n8); - } - } - - isOne = Fr.eq(Fr.one, invBeta); - isNegOne = Fr.eq(Fr.negone, invBeta); - - for (let i = n; i < this.length(); i++) { - const i_n8 = i * this.Fr.n8; - const i_prev_n8 = (i - n) * this.Fr.n8; - - let element = this.Fr.sub( - this.coef.slice(i_prev_n8, i_prev_n8 + this.Fr.n8), - this.coef.slice(i_n8, i_n8 + this.Fr.n8) - ); - - // If invBeta === 1 we'll not do anything - if(!isOne) { - // If invBeta === -1 we'll save a multiplication changing it by a neg function call - if(isNegOne) { - element = Fr.neg(element); - } else { - element = Fr.mul(invBeta, element); - } - } - - this.coef.set(element, i_n8); - - // Check if polynomial is divisible by checking if n high coefficients are zero - if (i > this.length() - n - 1) { - if (!this.Fr.isZero(element)) { - throw new Error("Polynomial is not divisible"); - } - } - } - - return this; - } - - // function divideByVanishing(f, n, p) { - // // polynomial division f(X) / (X^n - 1) with remainder - // // very cheap, 0 multiplications - // // strategy: - // // start with q(X) = 0, r(X) = f(X) - // // then start changing q, r while preserving the identity: - // // f(X) = q(X) * (X^n - 1) + r(X) - // // in every step, move highest-degree term of r into the product - // // => r eventually has degree < n and we're done - // let q = Array(f.length).fill(0n); - // let r = [...f]; - // for (let i = f.length - 1; i >= n; i--) { - // let leadingCoeff = r[i]; - // if (leadingCoeff === 0n) continue; - // r[i] = 0n; - // r[i - n] = mod(r[i - n] + leadingCoeff, p); - // q[i - n] = mod(q[i - n] + leadingCoeff, p); - // } - // return [q, r]; - // } - - byX() { - const coefs = (this.length() + 1) > 2 << 14 ? - new BigBuffer(this.coef.byteLength + this.Fr.n8) : new Uint8Array(this.coef.byteLength + this.Fr.n8); - coefs.set(this.Fr.zero, 0); - coefs.set(this.coef, this.Fr.n8); - - this.coef = coefs; - } - - // Compute a new polynomial f(x^n) from f(x) - // f(x) = a_0 + a_1·x + a_2·x^2 + ... + a_j·x^j - // f(x^n) = a_0 + a_1·x^n + a_2·x^2n + ... + a_j·x^jn - static - async expX(polynomial, n, truncate = false) { - const Fr = polynomial.Fr; - - if (n < 1) { - // n == 0 not allowed because it has no sense, but if it's necessary we have to return - // a zero degree polynomial with a constant coefficient equals to the sum of all the original coefficients - throw new Error("Compute a new polynomial to a zero or negative number is not allowed"); - } else if (1 === n) { - return await Polynomial.fromEvaluations(polynomial.coef, curve, polynomial.logger); - } - - // length is the length of non-constant coefficients - // if truncate === true, the highest zero coefficients (if exist) will be removed - const length = truncate ? polynomial.degree() : (polynomial.length() - 1); - const bufferDst = (length * n + 1) > 2 << 14 ? - new BigBuffer((length * n + 1) * Fr.n8) : new Uint8Array((length * n + 1) * Fr.n8); - - // Copy constant coefficient as is because is not related to x - bufferDst.set(polynomial.getCoef(0), 0); - - for (let i = 1; i <= length; i++) { - const i_sFr = i * Fr.n8; - - const coef = polynomial.getCoef(i); - bufferDst.set(coef, i_sFr * n); - } - - return new Polynomial(bufferDst, polynomial.curve, polynomial.logger); - } - - split(numPols, degPols, blindingFactors) { - if (numPols < 1) { - throw new Error(`Polynomials can't be split in ${numPols} parts`); - } else if (1 === numPols) { - return [this]; - } - - //blinding factors can be void or must have a length of numPols - 1 - if (0 !== blindingFactors.length && blindingFactors.length < numPols - 1) { - throw new Error(`Blinding factors length must be ${numPols - 1}`); - } - - const chunkByteLength = (degPols + 1) * this.Fr.n8; - let res = []; - - // Check polynomial can be split in numChunks parts of chunkSize bytes... - const numRealPols = Math.ceil((this.degree() + 1) * this.Fr.n8 / chunkByteLength); - if (numRealPols < numPols) { - //throw new Error(`Polynomial is short to be split in ${numPols} parts of ${degPols} coefficients each.`); - for (let i = numRealPols; i < numPols; i++) { - res[i] = new Polynomial(new Uint8Array(this.Fr.n8), this.curve, this.logger); - } - } - - numPols = Math.min(numPols, numRealPols); - for (let i = 0; i < numPols; i++) { - const isLast = (numPols - 1) === i; - const byteLength = isLast ? this.coef.byteLength - ((numPols - 1) * chunkByteLength) : chunkByteLength + this.Fr.n8; - - let buff = (byteLength / this.Fr.n8) > 2 << 14 ? new BigBuffer(byteLength) : new Uint8Array(byteLength); - res[i] = new Polynomial(buff, this.curve, this.logger); - - const fr = i * chunkByteLength; - const to = isLast ? this.coef.byteLength : (i + 1) * chunkByteLength; - res[i].coef.set(this.coef.slice(fr, to), 0); - - // Add a blinding factor as higher degree - if (!isLast) { - res[i].coef.set(blindingFactors[i], chunkByteLength); - } - - // Sub blinding factor to the lowest degree - if (0 !== i) { - const lowestDegree = this.Fr.sub(res[i].coef.slice(0, this.Fr.n8), blindingFactors[i - 1]); - res[i].coef.set(lowestDegree, 0); - } - - if (isLast) { - res[i].truncate(); - } - } - - return res; - - // // compute t_low(X) - // let polTLow = new BigBuffer((chunkSize + 1) * n8r); - // polTLow.set(t.slice(0, zkey.domainSize * n8r), 0); - // // Add blinding scalar b_10 as a new coefficient n - // polTLow.set(ch.b[10], zkey.domainSize * n8r); - // - // // compute t_mid(X) - // let polTMid = new BigBuffer((zkey.domainSize + 1) * n8r); - // polTMid.set(t.slice(zkey.domainSize * n8r, zkey.domainSize * 2 * n8r), 0); - // // Subtract blinding scalar b_10 to the lowest coefficient of t_mid - // const lowestMid = Fr.sub(polTMid.slice(0, n8r), ch.b[10]); - // polTMid.set(lowestMid, 0); - // // Add blinding scalar b_11 as a new coefficient n - // polTMid.set(ch.b[11], zkey.domainSize * n8r); - // - // // compute t_high(X) - // let polTHigh = new BigBuffer((zkey.domainSize + 6) * n8r); - // polTHigh.set(t.slice(zkey.domainSize * 2 * n8r, (zkey.domainSize * 3 + 6) * n8r), 0); - // //Subtract blinding scalar b_11 to the lowest coefficient of t_high - // const lowestHigh = Fr.sub(polTHigh.slice(0, n8r), ch.b[11]); - // polTHigh.set(lowestHigh, 0); - // - // proof.T1 = await expTau(polTLow, "multiexp T1"); - // proof.T2 = await expTau(polTMid, "multiexp T2"); - // proof.T3 = await expTau(polTHigh, "multiexp T3"); - } - - // split2(degPols, blindingFactors) { - // let currentDegree = this.degree(); - // const numFilledPols = Math.ceil((currentDegree + 1) / (degPols + 1)); - // - // //blinding factors can be void or must have a length of numPols - 1 - // if (0 !== blindingFactors.length && blindingFactors.length < numFilledPols - 1) { - // throw new Error(`Blinding factors length must be ${numFilledPols - 1}`); - // } - // - // const chunkByteLength = (degPols + 1) * this.Fr.n8; - // - // // Check polynomial can be split in numChunks parts of chunkSize bytes... - // if (this.coef.byteLength / chunkByteLength <= numFilledPols - 1) { - // throw new Error(`Polynomial is short to be split in ${numFilledPols} parts of ${degPols} coefficients each.`); - // } - // - // let res = []; - // for (let i = 0; i < numFilledPols; i++) { - // const isLast = (numFilledPols - 1) === i; - // const byteLength = isLast ? (currentDegree + 1) * this.Fr.n8 - ((numFilledPols - 1) * chunkByteLength) : chunkByteLength + this.Fr.n8; - // - // res[i] = new Polynomial(new BigBuffer(byteLength), this.Fr, this.logger); - // const fr = i * chunkByteLength; - // const to = isLast ? (currentDegree + 1) * this.Fr.n8 : (i + 1) * chunkByteLength; - // res[i].coef.set(this.coef.slice(fr, to), 0); - // - // // Add a blinding factor as higher degree - // if (!isLast) { - // res[i].coef.set(blindingFactors[i], chunkByteLength); - // } - // - // // Sub blinding factor to the lowest degree - // if (0 !== i) { - // const lowestDegree = this.Fr.sub(res[i].coef.slice(0, this.Fr.n8), blindingFactors[i - 1]); - // res[i].coef.set(lowestDegree, 0); - // } - // } - // - // return res; - // } - - // merge(pols, overlap = true) { - // let length = 0; - // for (let i = 0; i < pols.length; i++) { - // length += pols[i].length(); - // } - // - // if (overlap) { - // length -= pols.length - 1; - // } - // - // let res = new Polynomial(new BigBuffer(length * this.Fr.n8)); - // for (let i = 0; i < pols.length; i++) { - // const byteLength = pols[i].coef.byteLength; - // if (0 === i) { - // res.coef.set(pols[i].coef, 0); - // } else { - // - // } - // } - // - // return res; - // } - - truncate() { - const deg = this.degree(); - if (deg + 1 < this.coef.byteLength / this.Fr.n8) { - const newCoefs = (deg + 1) > 2 << 14 ? - new BigBuffer((deg + 1) * this.Fr.n8) : new Uint8Array((deg + 1) * this.Fr.n8); - - newCoefs.set(this.coef.slice(0, (deg + 1) * this.Fr.n8), 0); - this.coef = newCoefs; - } - } - - static lagrangePolynomialInterpolation(xArr, yArr, curve) { - const Fr = curve.Fr; - let polynomial = computeLagrangePolynomial(0); - for (let i = 1; i < xArr.length; i++) { - polynomial.add(computeLagrangePolynomial(i)); - } - - return polynomial; - - function computeLagrangePolynomial(i) { - let polynomial; - - for (let j = 0; j < xArr.length; j++) { - if (j === i) continue; - - if (polynomial === undefined) { - let buff = (xArr.length) > 2 << 14 ? - new BigBuffer((xArr.length) * Fr.n8) : new Uint8Array((xArr.length) * Fr.n8); - polynomial = new Polynomial(buff, curve); - polynomial.setCoef(0, Fr.neg(xArr[j])); - polynomial.setCoef(1, Fr.one); - } else { - polynomial.byXSubValue(xArr[j]); - } - } - - let denominator = polynomial.evaluate(xArr[i]); - denominator = Fr.inv(denominator); - const mulFactor = Fr.mul(yArr[i], denominator); - - polynomial.mulScalar(mulFactor); - - return polynomial; - } - } - - static zerofierPolynomial(xArr, curve) { - const Fr = curve.Fr; - let buff = (xArr.length + 1) > 2 << 14 ? - new BigBuffer((xArr.length + 1) * Fr.n8) : new Uint8Array((xArr.length + 1) * Fr.n8); - let polynomial = new Polynomial(buff, curve); - - // Build a zerofier polynomial with the following form: - // zerofier(X) = (X-xArr[0])(X-xArr[1])...(X-xArr[n]) - polynomial.setCoef(0, Fr.neg(xArr[0])); - polynomial.setCoef(1, Fr.one); - - for (let i = 1; i < xArr.length; i++) { - polynomial.byXSubValue(xArr[i]); - } - - return polynomial; - } - - print() { - const Fr = this.Fr; - let res = ""; - for (let i = this.degree(); i >= 0; i--) { - const coef = this.getCoef(i); - if (!Fr.eq(Fr.zero, coef)) { - if (Fr.isNegative(coef)) { - res += " - "; - } else if (i !== this.degree()) { - res += " + "; - } - res += Fr.toString(coef); - if (i > 0) { - res += i > 1 ? "x^" + i : "x"; - } - } - } - console.log(res); - } - - async multiExponentiation(PTau, name) { - const n = this.coef.byteLength / this.Fr.n8; - const PTauN = PTau.slice(0, n * this.G1.F.n8 * 2); - const bm = await this.Fr.batchFromMontgomery(this.coef); - let res = await this.G1.multiExpAffine(PTauN, bm, this.logger, name); - res = this.G1.toAffine(res); - return res; - } - } - - /* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . - */ - - class Evaluations { - constructor(evaluations, curve, logger) { - this.eval = evaluations; - this.curve = curve; - this.Fr = curve.Fr; - this.logger = logger; - } - - static async fromPolynomial(polynomial, extension, curve, logger) { - const coefficientsN = new BigBuffer(polynomial.length() * extension * curve.Fr.n8); - coefficientsN.set(polynomial.coef, 0); - - const evaluations = await curve.Fr.fft(coefficientsN); - - return new Evaluations(evaluations, curve, logger); - } - - getEvaluation(index) { - const i_n8 = index * this.Fr.n8; - - if (i_n8 + this.Fr.n8 > this.eval.byteLength) { - throw new Error("Evaluations.getEvaluation() out of bounds"); - } - - return this.eval.slice(i_n8, i_n8 + this.Fr.n8); - } - - length() { - let length = this.eval.byteLength / this.Fr.n8; - if (length !== Math.floor(this.eval.byteLength / this.Fr.n8)) { - throw new Error("Polynomial evaluations buffer has incorrect size"); - } - if (0 === length) { - this.logger.warn("Polynomial has length zero"); - } - return length; - } - } - - /* - Copyright 2021 0kims association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . - */ - const {stringifyBigInts: stringifyBigInts$1} = utils$6; - - async function plonk16Prove(zkeyFileName, witnessFileName, logger, options) { - const {fd: fdWtns, sections: sectionsWtns} = await readBinFile$1(witnessFileName, "wtns", 2); - - // Read witness file - if (logger) logger.debug("> Reading witness file"); - const wtns = await readHeader(fdWtns, sectionsWtns); - - // Read zkey file - if (logger) logger.debug("> Reading zkey file"); - const {fd: fdZKey, sections: zkeySections} = await readBinFile$1(zkeyFileName, "zkey", 2); - - const zkey = await readHeader$1(fdZKey, zkeySections, undefined, options); - if (zkey.protocol != "plonk") { - throw new Error("zkey file is not plonk"); - } - - if (!Scalar.eq(zkey.r, wtns.q)) { - throw new Error("Curve of the witness does not match the curve of the proving key"); - } - - if (wtns.nWitness != zkey.nVars -zkey.nAdditions) { - throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}, ${zkey.nAdditions}`); - } - - const curve = zkey.curve; - - const Fr = curve.Fr; - const n8r = curve.Fr.n8; - const sDomain = zkey.domainSize * n8r; - - if (logger) { - logger.debug("----------------------------"); - logger.debug(" PLONK PROVE SETTINGS"); - logger.debug(` Curve: ${curve.name}`); - logger.debug(` Circuit power: ${zkey.power}`); - logger.debug(` Domain size: ${zkey.domainSize}`); - logger.debug(` Vars: ${zkey.nVars}`); - logger.debug(` Public vars: ${zkey.nPublic}`); - logger.debug(` Constraints: ${zkey.nConstraints}`); - logger.debug(` Additions: ${zkey.nAdditions}`); - logger.debug("----------------------------"); - } - - //Read witness data - if (logger) logger.debug("> Reading witness file data"); - const buffWitness = await readSection$1(fdWtns, sectionsWtns, 2); - - // First element in plonk is not used and can be any value. (But always the same). - // We set it to zero to go faster in the exponentiations. - buffWitness.set(Fr.zero, 0); - const buffInternalWitness = new BigBuffer(n8r*zkey.nAdditions); - - let buffers = {}; - let polynomials = {}; - let evaluations = {}; - - let challenges = {}; - let proof = new Proof(curve, logger); - const transcript = new Keccak256Transcript(curve); - - if (logger) logger.debug(`> Reading Section ${ZKEY_PL_ADDITIONS_SECTION}. Additions`); - await calculateAdditions(); - - if (logger) logger.debug(`> Reading Section ${ZKEY_PL_SIGMA_SECTION}. Sigma1, Sigma2 & Sigma 3`); - if (logger) logger.debug("··· Reading Sigma polynomials "); - polynomials.Sigma1 = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.Sigma2 = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.Sigma3 = new Polynomial(new BigBuffer(sDomain), curve, logger); - - await fdZKey.readToBuffer(polynomials.Sigma1.coef, 0, sDomain, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.Sigma2.coef, 0, sDomain, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p + 5 * sDomain); - await fdZKey.readToBuffer(polynomials.Sigma3.coef, 0, sDomain, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p + 10 * sDomain); - - if (logger) logger.debug("··· Reading Sigma evaluations"); - evaluations.Sigma1 = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.Sigma2 = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.Sigma3 = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - - await fdZKey.readToBuffer(evaluations.Sigma1.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.Sigma2.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p + 6 * sDomain); - await fdZKey.readToBuffer(evaluations.Sigma3.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_SIGMA_SECTION][0].p + 11 * sDomain); - - if (logger) logger.debug(`> Reading Section ${ZKEY_PL_PTAU_SECTION}. Powers of Tau`); - const PTau = await readSection$1(fdZKey, zkeySections, ZKEY_PL_PTAU_SECTION); - - let publicSignals = []; - - for (let i=1; i<= zkey.nPublic; i++) { - const pub = buffWitness.slice(i*Fr.n8, i*Fr.n8+Fr.n8); - publicSignals.push(Scalar.fromRprLE(pub)); - } - - if (logger) logger.debug(""); - if (logger) logger.debug("> ROUND 1"); - await round1(); - - if (logger) logger.debug("> ROUND 2"); - await round2(); - - if (logger) logger.debug("> ROUND 3"); - await round3(); - - if (logger) logger.debug("> ROUND 4"); - await round4(); - - if (logger) logger.debug("> ROUND 5"); - await round5(); - - /////////////////////// - // Final adjustments // - /////////////////////// - - await fdZKey.close(); - await fdWtns.close(); - - // Prepare proof - let _proof = proof.toObjectProof(false); - _proof.protocol = "plonk"; - _proof.curve = curve.name; - - if (logger) logger.debug("PLONK PROVER FINISHED"); - - return { - proof: stringifyBigInts$1(_proof), - publicSignals: stringifyBigInts$1(publicSignals) - }; - - async function calculateAdditions() { - if (logger) logger.debug("··· Computing additions"); - const additionsBuff = await readSection$1(fdZKey, zkeySections, ZKEY_PL_ADDITIONS_SECTION); - - // sizes: wireId_x = 4 bytes (32 bits), factor_x = field size bits - // Addition form: wireId_a wireId_b factor_a factor_b (size is 4 + 4 + sFr + sFr) - const sSum = 8 + n8r * 2; - - for (let i = 0; i < zkey.nAdditions; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.debug(` addition ${i}/${zkey.nAdditions}`); - - // Read addition values - let offset = i * sSum; - const signalId1 = readUInt32(additionsBuff, offset); - offset += 4; - const signalId2 = readUInt32(additionsBuff, offset); - offset += 4; - const factor1 = additionsBuff.slice(offset, offset + n8r); - offset += n8r; - const factor2 = additionsBuff.slice(offset, offset + n8r); - - // Get witness value - const witness1 = getWitness(signalId1); - const witness2 = getWitness(signalId2); - - //Calculate final result - const result = Fr.add(Fr.mul(factor1, witness1), Fr.mul(factor2, witness2)); - - buffInternalWitness.set(result, n8r * i); - } - } - - function readUInt32(b, o) { - const buff = b.slice(o, o+4); - const buffV = new DataView(buff.buffer, buff.byteOffset, buff.byteLength); - return buffV.getUint32(0, true); - } - - function getWitness(idx) { - if (idx < zkey.nVars-zkey.nAdditions) { - return buffWitness.slice(idx*n8r, idx*n8r+n8r); - } else if (idx < zkey.nVars) { - return buffInternalWitness.slice((idx - (zkey.nVars-zkey.nAdditions))*n8r, (idx-(zkey.nVars-zkey.nAdditions))*n8r + n8r); - } else { - return curve.Fr.zero; - } - } - - async function round1() { - // STEP 1.1 - Generate random blinding scalars (b1, ..., b11) ∈ F - challenges.b = []; - for (let i=1; i<=11; i++) { - challenges.b[i] = curve.Fr.random(); - } - - // STEP 1.2 - Compute wire polynomials a(X), b(X) and c(X) - if (logger) logger.debug("> Computing A, B, C wire polynomials"); - await computeWirePolynomials(); - - // STEP 1.3 - Compute [a]_1, [b]_1, [c]_1 - if (logger) logger.debug("> Computing A, B, C MSM"); - let commitA = await polynomials.A.multiExponentiation(PTau, "A"); - let commitB = await polynomials.B.multiExponentiation(PTau, "B"); - let commitC = await polynomials.C.multiExponentiation(PTau, "C"); - - // First output of the prover is ([A]_1, [B]_1, [C]_1) - proof.addPolynomial("A", commitA); - proof.addPolynomial("B", commitB); - proof.addPolynomial("C", commitC); - - return 0; - } - - async function computeWirePolynomials() { - if (logger) logger.debug("··· Reading data from zkey file"); - - // Build A, B and C evaluations buffer from zkey and witness files - buffers.A = new BigBuffer(sDomain); - buffers.B = new BigBuffer(sDomain); - buffers.C = new BigBuffer(sDomain); - - // Read zkey file to the buffers - const aMapBuff = await readSection$1(fdZKey, zkeySections, ZKEY_PL_A_MAP_SECTION); - const bMapBuff = await readSection$1(fdZKey, zkeySections, ZKEY_PL_B_MAP_SECTION); - const cMapBuff = await readSection$1(fdZKey, zkeySections, ZKEY_PL_C_MAP_SECTION); - - // Compute all witness from signal ids and set them to A,B & C buffers - for (let i = 0; i < zkey.nConstraints; i++) { - const i_sFr = i * n8r; - const offset = i * 4; - - // Compute A value from a signal id - const signalIdA = readUInt32(aMapBuff, offset); - buffers.A.set(getWitness(signalIdA), i_sFr); - - // Compute B value from a signal id - const signalIdB = readUInt32(bMapBuff, offset); - buffers.B.set(getWitness(signalIdB), i_sFr); - - // Compute C value from a signal id - const signalIdC = readUInt32(cMapBuff, offset); - buffers.C.set(getWitness(signalIdC), i_sFr); - } - - buffers.A = await Fr.batchToMontgomery(buffers.A); - buffers.B = await Fr.batchToMontgomery(buffers.B); - buffers.C = await Fr.batchToMontgomery(buffers.C); - - // Compute the coefficients of the wire polynomials a(X), b(X) and c(X) from A,B & C buffers - if (logger) logger.debug("··· Computing A ifft"); - polynomials.A = await Polynomial.fromEvaluations(buffers.A, curve, logger); - if (logger) logger.debug("··· Computing B ifft"); - polynomials.B = await Polynomial.fromEvaluations(buffers.B, curve, logger); - if (logger) logger.debug("··· Computing C ifft"); - polynomials.C = await Polynomial.fromEvaluations(buffers.C, curve, logger); - - // Compute extended evaluations of a(X), b(X) and c(X) polynomials - if (logger) logger.debug("··· Computing A fft"); - evaluations.A = await Evaluations.fromPolynomial(polynomials.A, 4, curve, logger); - if (logger) logger.debug("··· Computing B fft"); - evaluations.B = await Evaluations.fromPolynomial(polynomials.B, 4, curve, logger); - if (logger) logger.debug("··· Computing C fft"); - evaluations.C = await Evaluations.fromPolynomial(polynomials.C, 4, curve, logger); - - // Blind a(X), b(X) and c(X) polynomials coefficients with blinding scalars b - polynomials.A.blindCoefficients([challenges.b[2], challenges.b[1]]); - polynomials.B.blindCoefficients([challenges.b[4], challenges.b[3]]); - polynomials.C.blindCoefficients([challenges.b[6], challenges.b[5]]); - - // Check degrees - if (polynomials.A.degree() >= zkey.domainSize + 2) { - throw new Error("A Polynomial is not well calculated"); - } - if (polynomials.B.degree() >= zkey.domainSize + 2) { - throw new Error("B Polynomial is not well calculated"); - } - if (polynomials.C.degree() >= zkey.domainSize + 2) { - throw new Error("C Polynomial is not well calculated"); - } - } - - async function round2() { - // STEP 2.1 - Compute permutation challenge beta and gamma ∈ F - // Compute permutation challenge beta - if (logger) logger.debug("> Computing challenges beta and gamma"); - transcript.reset(); - - transcript.addPolCommitment(zkey.Qm); - transcript.addPolCommitment(zkey.Ql); - transcript.addPolCommitment(zkey.Qr); - transcript.addPolCommitment(zkey.Qo); - transcript.addPolCommitment(zkey.Qc); - transcript.addPolCommitment(zkey.S1); - transcript.addPolCommitment(zkey.S2); - transcript.addPolCommitment(zkey.S3); - - // Add A to the transcript - for (let i = 0; i < zkey.nPublic; i++) { - transcript.addScalar(buffers.A.slice(i * n8r, i * n8r + n8r)); - } - - // Add A, B, C to the transcript - transcript.addPolCommitment(proof.getPolynomial("A")); - transcript.addPolCommitment(proof.getPolynomial("B")); - transcript.addPolCommitment(proof.getPolynomial("C")); - - challenges.beta = transcript.getChallenge(); - if (logger) logger.debug("··· challenges.beta: " + Fr.toString(challenges.beta, 16)); - - // Compute permutation challenge gamma - transcript.reset(); - transcript.addScalar(challenges.beta); - challenges.gamma = transcript.getChallenge(); - if (logger) logger.debug("··· challenges.gamma: " + Fr.toString(challenges.gamma, 16)); - - // STEP 2.2 - Compute permutation polynomial z(X) - if (logger) logger.debug("> Computing Z polynomial"); - await computeZ(); - - // STEP 2.3 - Compute permutation [z]_1 - if (logger) logger.debug("> Computing Z MSM"); - let commitZ = await polynomials.Z.multiExponentiation(PTau, "Z"); - - // Second output of the prover is ([Z]_1) - proof.addPolynomial("Z", commitZ); - } - - async function computeZ() { - if (logger) logger.debug("··· Computing Z evaluations"); - - let numArr = new BigBuffer(sDomain); - let denArr = new BigBuffer(sDomain); - - // Set the first values to 1 - numArr.set(Fr.one, 0); - denArr.set(Fr.one, 0); - - // Set initial omega - let w = Fr.one; - for (let i = 0; i < zkey.domainSize; i++) { - const i_n8r = i * n8r; - - const a = buffers.A.slice(i_n8r, i_n8r + n8r); - const b = buffers.B.slice(i_n8r, i_n8r + n8r); - const c = buffers.C.slice(i_n8r, i_n8r + n8r); - - // Z(X) := numArr / denArr - // numArr := (a + beta·ω + gamma)(b + beta·ω·k1 + gamma)(c + beta·ω·k2 + gamma) - const betaw = Fr.mul(challenges.beta, w); - - let n1 = Fr.add(a, betaw); - n1 = Fr.add(n1, challenges.gamma); - - let n2 = Fr.add(b, Fr.mul(zkey.k1, betaw)); - n2 = Fr.add(n2, challenges.gamma); - - let n3 = Fr.add(c, Fr.mul(zkey.k2, betaw)); - n3 = Fr.add(n3, challenges.gamma); - - let num = Fr.mul(n1, Fr.mul(n2, n3)); - - // denArr := (a + beta·sigma1 + gamma)(b + beta·sigma2 + gamma)(c + beta·sigma3 + gamma) - let d1 = Fr.add(a, Fr.mul(evaluations.Sigma1.getEvaluation(i * 4), challenges.beta)); - d1 = Fr.add(d1, challenges.gamma); - - let d2 = Fr.add(b, Fr.mul(evaluations.Sigma2.getEvaluation(i * 4), challenges.beta)); - d2 = Fr.add(d2, challenges.gamma); - - let d3 = Fr.add(c, Fr.mul(evaluations.Sigma3.getEvaluation(i * 4), challenges.beta)); - d3 = Fr.add(d3, challenges.gamma); - - let den = Fr.mul(d1, Fr.mul(d2, d3)); - - // Multiply current num value with the previous one saved in numArr - num = Fr.mul(numArr.slice(i_n8r, i_n8r + n8r), num); - numArr.set(num, ((i + 1) % zkey.domainSize) * n8r); - - // Multiply current den value with the previous one saved in denArr - den = Fr.mul(denArr.slice(i_n8r, i_n8r + n8r), den); - denArr.set(den, ((i + 1) % zkey.domainSize) * n8r); - - w = Fr.mul(w, Fr.w[zkey.power]); - } - - // Compute the inverse of denArr to compute in the next command the - // division numArr/denArr by multiplying num · 1/denArr - denArr = await Fr.batchInverse(denArr); - - // TODO: Do it in assembly and in parallel - // Multiply numArr · denArr where denArr was inverted in the previous command - for (let i = 0; i < zkey.domainSize; i++) { - const i_sFr = i * n8r; - - const z = Fr.mul(numArr.slice(i_sFr, i_sFr + n8r), denArr.slice(i_sFr, i_sFr + n8r)); - numArr.set(z, i_sFr); - } - - // From now on the values saved on numArr will be Z(X) buffer - buffers.Z = numArr; - - if (!Fr.eq(numArr.slice(0, n8r), Fr.one)) { - throw new Error("Copy constraints does not match"); - } - - // Compute polynomial coefficients z(X) from buffers.Z - if (logger) logger.debug("··· Computing Z ifft"); - polynomials.Z = await Polynomial.fromEvaluations(buffers.Z, curve, logger); - - // Compute extended evaluations of z(X) polynomial - if (logger) logger.debug("··· Computing Z fft"); - evaluations.Z = await Evaluations.fromPolynomial(polynomials.Z, 4, curve, logger); - - // Blind z(X) polynomial coefficients with blinding scalars b - polynomials.Z.blindCoefficients([challenges.b[9], challenges.b[8], challenges.b[7]]); - - // Check degree - if (polynomials.Z.degree() >= zkey.domainSize + 3) { - throw new Error("Z Polynomial is not well calculated"); - } - - delete buffers.Z; - } - - async function round3() { - if (logger) logger.debug("> Computing challenge alpha"); - - // STEP 3.1 - Compute evaluation challenge alpha ∈ F - transcript.reset(); - transcript.addScalar(challenges.beta); - transcript.addScalar(challenges.gamma); - transcript.addPolCommitment(proof.getPolynomial("Z")); - - challenges.alpha = transcript.getChallenge(); - challenges.alpha2 = Fr.square(challenges.alpha); - if (logger) logger.debug("··· challenges.alpha: " + Fr.toString(challenges.alpha, 16)); - - // Compute quotient polynomial T(X) - if (logger) logger.debug("> Computing T polynomial"); - await computeT(); - - // Compute [T1]_1, [T2]_1, [T3]_1 - if (logger) logger.debug("> Computing T MSM"); - let commitT1 = await polynomials.T1.multiExponentiation(PTau, "T1"); - let commitT2 = await polynomials.T2.multiExponentiation(PTau, "T2"); - let commitT3 = await polynomials.T3.multiExponentiation(PTau, "T3"); - - // Third output of the prover is ([T1]_1, [T2]_1, [T3]_1) - proof.addPolynomial("T1", commitT1); - proof.addPolynomial("T2", commitT2); - proof.addPolynomial("T3", commitT3); - } - - async function computeT() { - if (logger) - logger.debug(`··· Reading sections ${ZKEY_PL_QL_SECTION}, ${ZKEY_PL_QR_SECTION}` + - `, ${ZKEY_PL_QM_SECTION}, ${ZKEY_PL_QO_SECTION}, ${ZKEY_PL_QC_SECTION}. Q selectors`); - // Reserve memory for Q's evaluations - evaluations.QL = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.QR = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.QM = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.QO = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.QC = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - - // Read Q's evaluations from zkey file - await fdZKey.readToBuffer(evaluations.QL.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_QL_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QR.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_QR_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QM.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_QM_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QO.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_QO_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QC.eval, 0, sDomain * 4, zkeySections[ZKEY_PL_QC_SECTION][0].p + sDomain); - - // Read Lagrange polynomials & evaluations from zkey file - evaluations.Lagrange = new Evaluations(new BigBuffer(sDomain * 4 * zkey.nPublic), curve, logger); - - for (let i = 0; i < zkey.nPublic; i++) { - await fdZKey.readToBuffer(evaluations.Lagrange.eval, i * sDomain * 4, sDomain * 4, zkeySections[ZKEY_PL_LAGRANGE_SECTION][0].p + i * 5 * sDomain + sDomain); - } - - buffers.T = new BigBuffer(sDomain * 4); - buffers.Tz = new BigBuffer(sDomain * 4); - - if (logger) logger.debug("··· Computing T evaluations"); - - let w = Fr.one; - for (let i = 0; i < zkey.domainSize * 4; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) - logger.debug(` T evaluation ${i}/${zkey.domainSize * 4}`); - - const a = evaluations.A.getEvaluation(i); - const b = evaluations.B.getEvaluation(i); - const c = evaluations.C.getEvaluation(i); - const z = evaluations.Z.getEvaluation(i); - const zw = evaluations.Z.getEvaluation((zkey.domainSize * 4 + 4 + i) % (zkey.domainSize * 4)); - - const qm = evaluations.QM.getEvaluation(i); - const ql = evaluations.QL.getEvaluation(i); - const qr = evaluations.QR.getEvaluation(i); - const qo = evaluations.QO.getEvaluation(i); - const qc = evaluations.QC.getEvaluation(i); - const s1 = evaluations.Sigma1.getEvaluation(i); - const s2 = evaluations.Sigma2.getEvaluation(i); - const s3 = evaluations.Sigma3.getEvaluation(i); - - const ap = Fr.add(challenges.b[2], Fr.mul(challenges.b[1], w)); - const bp = Fr.add(challenges.b[4], Fr.mul(challenges.b[3], w)); - const cp = Fr.add(challenges.b[6], Fr.mul(challenges.b[5], w)); - - const w2 = Fr.square(w); - const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], w2), Fr.mul(challenges.b[8], w)), challenges.b[9]); - const wW = Fr.mul(w, Fr.w[zkey.power]); - const wW2 = Fr.square(wW); - const zWp = Fr.add(Fr.add(Fr.mul(challenges.b[7], wW2), Fr.mul(challenges.b[8], wW)), challenges.b[9]); - - let pi = Fr.zero; - for (let j = 0; j < zkey.nPublic; j++) { - const offset = (j * 4 * zkey.domainSize) + i; - - const lPol = evaluations.Lagrange.getEvaluation(offset); - const aVal = buffers.A.slice(j * n8r, (j + 1) * n8r); - - pi = Fr.sub(pi, Fr.mul(lPol, aVal)); - } - - // e1 := a(X)b(X)qM(X) + a(X)qL(X) + b(X)qR(X) + c(X)qO(X) + PI(X) + qC(X) - let [e1, e1z] = MulZ.mul2(a, b, ap, bp, i % 4, Fr); - e1 = Fr.mul(e1, qm); - e1z = Fr.mul(e1z, qm); - - e1 = Fr.add(e1, Fr.mul(a, ql)); - e1z = Fr.add(e1z, Fr.mul(ap, ql)); - - e1 = Fr.add(e1, Fr.mul(b, qr)); - e1z = Fr.add(e1z, Fr.mul(bp, qr)); - - e1 = Fr.add(e1, Fr.mul(c, qo)); - e1z = Fr.add(e1z, Fr.mul(cp, qo)); - - e1 = Fr.add(e1, pi); - e1 = Fr.add(e1, qc); - - // e2 := α[(a(X) + βX + γ)(b(X) + βk1X + γ)(c(X) + βk2X + γ)z(X)] - const betaw = Fr.mul(challenges.beta, w); - let e2a = a; - e2a = Fr.add(e2a, betaw); - e2a = Fr.add(e2a, challenges.gamma); - - let e2b = b; - e2b = Fr.add(e2b, Fr.mul(betaw, zkey.k1)); - e2b = Fr.add(e2b, challenges.gamma); - - let e2c = c; - e2c = Fr.add(e2c, Fr.mul(betaw, zkey.k2)); - e2c = Fr.add(e2c, challenges.gamma); - - let e2d = z; - - let [e2, e2z] = MulZ.mul4(e2a, e2b, e2c, e2d, ap, bp, cp, zp, i % 4, Fr); - e2 = Fr.mul(e2, challenges.alpha); - e2z = Fr.mul(e2z, challenges.alpha); - - // e3 := α[(a(X) + βSσ1(X) + γ)(b(X) + βSσ2(X) + γ)(c(X) + βSσ3(X) + γ)z(Xω)] - let e3a = a; - e3a = Fr.add(e3a, Fr.mul(challenges.beta, s1)); - e3a = Fr.add(e3a, challenges.gamma); - - let e3b = b; - e3b = Fr.add(e3b, Fr.mul(challenges.beta, s2)); - e3b = Fr.add(e3b, challenges.gamma); - - let e3c = c; - e3c = Fr.add(e3c, Fr.mul(challenges.beta, s3)); - e3c = Fr.add(e3c, challenges.gamma); - - let e3d = zw; - let [e3, e3z] = MulZ.mul4(e3a, e3b, e3c, e3d, ap, bp, cp, zWp, i % 4, Fr); - - e3 = Fr.mul(e3, challenges.alpha); - e3z = Fr.mul(e3z, challenges.alpha); - - // e4 := α^2(z(X)−1)L1(X) - let e4 = Fr.sub(z, Fr.one); - e4 = Fr.mul(e4, evaluations.Lagrange.getEvaluation(i)); - e4 = Fr.mul(e4, challenges.alpha2); - - let e4z = Fr.mul(zp, evaluations.Lagrange.getEvaluation(i)); - e4z = Fr.mul(e4z, challenges.alpha2); - - - let t = Fr.add(Fr.sub(Fr.add(e1, e2), e3), e4); - let tz = Fr.add(Fr.sub(Fr.add(e1z, e2z), e3z), e4z); - - buffers.T.set(t, i * n8r); - buffers.Tz.set(tz, i * n8r); - - w = Fr.mul(w, Fr.w[zkey.power + 2]); - } - - // Compute the coefficients of the polynomial T0(X) from buffers.T0 - if (logger) - logger.debug("··· Computing T ifft"); - polynomials.T = await Polynomial.fromEvaluations(buffers.T, curve, logger); - - // Divide the polynomial T0 by Z_H(X) - if (logger) - logger.debug("··· Computing T / ZH"); - polynomials.T.divZh(zkey.domainSize, 4); - - // Compute the coefficients of the polynomial Tz(X) from buffers.Tz - if (logger) - logger.debug("··· Computing Tz ifft"); - polynomials.Tz = await Polynomial.fromEvaluations(buffers.Tz, curve, logger); - - // Add the polynomial T1z to T1 to get the final polynomial T1 - polynomials.T.add(polynomials.Tz); - - // Check degree - if (polynomials.T.degree() >= zkey.domainSize * 3 + 6) { - throw new Error("T Polynomial is not well calculated"); - } - - // t(x) has degree 3n + 5, we are going to split t(x) into three smaller polynomials: - // T1' and T2' with a degree < n and T3' with a degree n+5 - // such that t(x) = T1'(X) + X^n T2'(X) + X^{2n} T3'(X) - // To randomize the parts we use blinding scalars b_10 and b_11 in a way that doesn't change t(X): - // T1(X) = T1'(X) + b_10 X^n - // T2(X) = T2'(X) - b_10 + b_11 X^n - // T3(X) = T3'(X) - b_11 - // such that - // t(X) = T1(X) + X^n T2(X) + X^2n T3(X) - if (logger) logger.debug("··· Computing T1, T2, T3 polynomials"); - polynomials.T1 = new Polynomial(new BigBuffer((zkey.domainSize + 1) * n8r), curve, logger); - polynomials.T2 = new Polynomial(new BigBuffer((zkey.domainSize + 1) * n8r), curve, logger); - polynomials.T3 = new Polynomial(new BigBuffer((zkey.domainSize + 6) * n8r), curve, logger); - - polynomials.T1.coef.set(polynomials.T.coef.slice(0, sDomain), 0); - polynomials.T2.coef.set(polynomials.T.coef.slice(sDomain, sDomain * 2), 0); - polynomials.T3.coef.set(polynomials.T.coef.slice(sDomain * 2, sDomain * 3 + 6 * n8r), 0); - - // Add blinding scalar b_10 as a new coefficient n - polynomials.T1.setCoef(zkey.domainSize, challenges.b[10]); - - // compute t_mid(X) - // Subtract blinding scalar b_10 to the lowest coefficient of t_mid - const lowestMid = Fr.sub(polynomials.T2.getCoef(0), challenges.b[10]); - polynomials.T2.setCoef(0, lowestMid); - polynomials.T2.setCoef(zkey.domainSize, challenges.b[11]); - - // compute t_high(X) - //Subtract blinding scalar b_11 to the lowest coefficient of t_high - const lowestHigh = Fr.sub(polynomials.T3.getCoef(0), challenges.b[11]); - polynomials.T3.setCoef(0, lowestHigh); - } - - async function round4() { - if (logger) logger.debug("> Computing challenge xi"); - - // STEP 4.1 - Compute evaluation challenge xi ∈ F - transcript.reset(); - transcript.addScalar(challenges.alpha); - transcript.addPolCommitment(proof.getPolynomial("T1")); - transcript.addPolCommitment(proof.getPolynomial("T2")); - transcript.addPolCommitment(proof.getPolynomial("T3")); - - challenges.xi = transcript.getChallenge(); - challenges.xiw = Fr.mul(challenges.xi, Fr.w[zkey.power]); - - if (logger) logger.debug("··· challenges.xi: " + Fr.toString(challenges.xi, 16)); - - // Fourth output of the prover is ( a(xi), b(xi), c(xi), s1(xi), s2(xi), z(xiw) ) - proof.addEvaluation("eval_a", polynomials.A.evaluate(challenges.xi)); - proof.addEvaluation("eval_b", polynomials.B.evaluate(challenges.xi)); - proof.addEvaluation("eval_c", polynomials.C.evaluate(challenges.xi)); - proof.addEvaluation("eval_s1", polynomials.Sigma1.evaluate(challenges.xi)); - proof.addEvaluation("eval_s2", polynomials.Sigma2.evaluate(challenges.xi)); - proof.addEvaluation("eval_zw", polynomials.Z.evaluate(challenges.xiw)); - } - - async function round5() { - if (logger) logger.debug("> Computing challenge v"); - - // STEP 5.1 - Compute evaluation challenge v ∈ F - transcript.reset(); - transcript.addScalar(challenges.xi); - transcript.addScalar(proof.getEvaluation("eval_a")); - transcript.addScalar(proof.getEvaluation("eval_b")); - transcript.addScalar(proof.getEvaluation("eval_c")); - transcript.addScalar(proof.getEvaluation("eval_s1")); - transcript.addScalar(proof.getEvaluation("eval_s2")); - transcript.addScalar(proof.getEvaluation("eval_zw")); - - challenges.v = []; - challenges.v[1] = transcript.getChallenge(); - if (logger) logger.debug("··· challenges.v: " + Fr.toString(challenges.v[1], 16)); - - for (let i = 2; i < 6; i++) { - challenges.v[i] = Fr.mul(challenges.v[i - 1], challenges.v[1]); - } - - // STEP 5.2 Compute linearisation polynomial r(X) - if (logger) logger.debug("> Computing linearisation polynomial R(X)"); - await computeR(); - - //STEP 5.3 Compute opening proof polynomial Wxi(X) - if (logger) logger.debug("> Computing opening proof polynomial Wxi(X) polynomial"); - computeWxi(); - - //STEP 5.4 Compute opening proof polynomial Wxiw(X) - if (logger) logger.debug("> Computing opening proof polynomial Wxiw(X) polynomial"); - computeWxiw(); - - if (logger) logger.debug("> Computing Wxi, Wxiw MSM"); - let commitWxi = await polynomials.Wxi.multiExponentiation(PTau, "Wxi"); - let commitWxiw = await polynomials.Wxiw.multiExponentiation(PTau, "Wxiw"); - - // Fifth output of the prover is ([Wxi]_1, [Wxiw]_1) - proof.addPolynomial("Wxi", commitWxi); - proof.addPolynomial("Wxiw", commitWxiw); - } - - async function computeR() { - const Fr = curve.Fr; - - // Reserve memory for Q's polynomials - polynomials.QL = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.QR = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.QM = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.QO = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.QC = new Polynomial(new BigBuffer(sDomain), curve, logger); - - // Read Q's evaluations from zkey file - await fdZKey.readToBuffer(polynomials.QL.coef, 0, sDomain, zkeySections[ZKEY_PL_QL_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QR.coef, 0, sDomain, zkeySections[ZKEY_PL_QR_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QM.coef, 0, sDomain, zkeySections[ZKEY_PL_QM_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QO.coef, 0, sDomain, zkeySections[ZKEY_PL_QO_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QC.coef, 0, sDomain, zkeySections[ZKEY_PL_QC_SECTION][0].p); - - challenges.xin = challenges.xi; - for (let i = 0; i < zkey.power; i++) { - challenges.xin = Fr.square(challenges.xin); - } - - challenges.zh = Fr.sub(challenges.xin, Fr.one); - - const L = []; - - const n = Fr.e(zkey.domainSize); - let w = Fr.one; - for (let i = 1; i <= Math.max(1, zkey.nPublic); i++) { - L[i] = Fr.div(Fr.mul(w, challenges.zh), Fr.mul(n, Fr.sub(challenges.xi, w))); - w = Fr.mul(w, Fr.w[zkey.power]); - } - - const eval_l1 = Fr.div( - Fr.sub(challenges.xin, Fr.one), - Fr.mul(n, Fr.sub(challenges.xi, Fr.one)) - ); - - if (logger) { - logger.debug("Lagrange Evaluations: "); - for (let i=1; i. - */ - const {unstringifyBigInts: unstringifyBigInts$5} = utils$6; - - async function plonkFullProve(_input, wasmFile, zkeyFileName, logger, wtnsCalcOptions, proverOptions) { - const input = unstringifyBigInts$5(_input); - - const wtns= { - type: "mem" - }; - await wtnsCalculate(input, wasmFile, wtns, wtnsCalcOptions); - return await plonk16Prove(zkeyFileName, wtns, logger, proverOptions); - } - - /* - Copyright 2021 0kims association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . - */ - - const { unstringifyBigInts: unstringifyBigInts$4 } = utils$6; - - async function plonkVerify(_vk_verifier, _publicSignals, _proof, logger) { - let vk_verifier = unstringifyBigInts$4(_vk_verifier); - _proof = unstringifyBigInts$4(_proof); - let publicSignals = unstringifyBigInts$4(_publicSignals); - - const curve = await getCurveFromName(vk_verifier.curve); - - const Fr = curve.Fr; - const G1 = curve.G1; - - if (logger) logger.info("PLONK VERIFIER STARTED"); - - let proof = fromObjectProof(curve,_proof); - vk_verifier = fromObjectVk$1(curve, vk_verifier); - - if (!isWellConstructed(curve, proof)) { - logger.error("Proof commitments are not valid."); - return false; - } - - if (publicSignals.length != vk_verifier.nPublic) { - if (logger) logger.error("Invalid number of public inputs"); - return false; - } - - if (!evaluationsAreValid$1(curve, proof)) { - if (logger) logger.error("Proof evaluations are not valid"); - return false; - } - - if (!publicInputsAreValid$1(curve, publicSignals)) { - if (logger) logger.error("Public inputs are not valid."); - return false; - } - - const challenges = calculatechallenges(curve, proof, publicSignals, vk_verifier); - if (logger) { - logger.debug("beta: " + Fr.toString(challenges.beta, 16)); - logger.debug("gamma: " + Fr.toString(challenges.gamma, 16)); - logger.debug("alpha: " + Fr.toString(challenges.alpha, 16)); - logger.debug("xi: " + Fr.toString(challenges.xi, 16)); - for(let i=1;i<6;i++) { - if (logger) logger.debug("v: " + Fr.toString(challenges.v[i], 16)); - } - logger.debug("u: " + Fr.toString(challenges.u, 16)); - } - const L = calculateLagrangeEvaluations(curve, challenges, vk_verifier); - if (logger) { - for (let i=1; i. - */ - const { unstringifyBigInts: unstringifyBigInts$3} = utils$6; - - function p256$1(n) { - let nstr = n.toString(16); - while (nstr.length < 64) nstr = "0"+nstr; - nstr = `"0x${nstr}"`; - return nstr; - } - - async function plonkExportSolidityCallData(_proof, _pub) { - const proof = unstringifyBigInts$3(_proof); - const pub = unstringifyBigInts$3(_pub); - - const curve = await getCurveFromName(proof.curve); - curve.G1; - curve.Fr; - - let inputs = ""; - for (let i=0; i. - */ - - var plonk = /*#__PURE__*/Object.freeze({ - __proto__: null, - setup: plonkSetup, - fullProve: plonkFullProve, - prove: plonk16Prove, - verify: plonkVerify, - exportSolidityCallData: plonkExportSolidityCallData - }); - - /* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . - */ - - // We export to zkey the signals and values of the a, b, c, ql, qr, qm, qo and qc - - // a, b and c are signals id (32-bit integers) - // ql, qr, qm, qo and qc are field values - - function getFFlonkConstantConstraint(signal1, Fr) { - return [signal1, 0, 0, Fr.one, Fr.zero, Fr.zero, Fr.zero, Fr.zero]; - } - - function getFFlonkAdditionConstraint(signal1, signal2, signalOut, ql, qr, qm, qo, qc) { - return [signal1, signal2, signalOut, ql, qr, qm, qo, qc]; - } - - function getFFlonkMultiplicationConstraint(signal1, signal2, signalOut, ql, qr, qm, qo, qc, Fr) { - return [signal1, signal2, signalOut, ql, qr, qm, qo, qc]; - } - - /* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . - */ - - const LINEAR_COMBINATION_NULLABLE = 0; - const LINEAR_COMBINATION_CONSTANT = 1; - const LINEAR_COMBINATION_VARIABLE = 2; - - class r1csConstraintProcessor { - constructor(Fr, fnGetConstantConstraint, fnGetAdditionConstraint, fnGetMultiplicationConstraint, logger) { - this.Fr = Fr; - this.logger = logger; - this.fnGetAdditionConstraint = fnGetAdditionConstraint; - this.fnGetMultiplicationConstraint = fnGetMultiplicationConstraint; - } - - processR1csConstraint(settings, lcA, lcB, lcC) { - this.normalizeLinearCombination(lcA); - this.normalizeLinearCombination(lcB); - this.normalizeLinearCombination(lcC); - - const lctA = this.getLinearCombinationType(lcA); - const lctB = this.getLinearCombinationType(lcB); - - if ((lctA === LINEAR_COMBINATION_NULLABLE) || (lctB === LINEAR_COMBINATION_NULLABLE)) { - return this.processR1csAdditionConstraint(settings, lcC); - } else if (lctA === LINEAR_COMBINATION_CONSTANT) { - const lcCC = this.joinLinearCombinations(lcB, lcC, lcA[0]); - return this.processR1csAdditionConstraint(settings, lcCC); - } else if (lctB === LINEAR_COMBINATION_CONSTANT) { - const lcCC = this.joinLinearCombinations(lcA, lcC, lcB[0]); - return this.processR1csAdditionConstraint(settings, lcCC); - } else { - return this.processR1csMultiplicationConstraint(settings, lcA, lcB, lcC); - } - } - - getLinearCombinationType(linCom) { - // let k = this.Fr.zero; - // - // const signalIds = Object.keys(linCom); - // for (let i = 0; i < signalIds.length; i++) { - // if (signalIds[i] === "0") { - // k = this.Fr.add(k, linCom[signalIds[i]]); - // } else { - // return LINEAR_COMBINATION_VARIABLE; - // } - // } - // - // if (!this.Fr.eq(k, this.Fr.zero)) return LINEAR_COMBINATION_CONSTANT; - // - // return LINEAR_COMBINATION_NULLABLE; - - let k = this.Fr.zero; - let n = 0; - const ss = Object.keys(linCom); - for (let i = 0; i < ss.length; i++) { - if (linCom[ss[i]] == 0n) { - delete linCom[ss[i]]; - } else if (ss[i] == 0) { - k = this.Fr.add(k, linCom[ss[i]]); - } else { - n++; - } - } - if (n > 0) return LINEAR_COMBINATION_VARIABLE; - if (!this.Fr.isZero(k)) return LINEAR_COMBINATION_CONSTANT; - return LINEAR_COMBINATION_NULLABLE; - } - - normalizeLinearCombination(linCom) { - const signalIds = Object.keys(linCom); - for (let i = 0; i < signalIds.length; i++) { - if (this.Fr.isZero(linCom[signalIds[i]])) delete linCom[signalIds[i]]; - } - - return linCom; - } - - joinLinearCombinations(linCom1, linCom2, k) { - const res = {}; - - // for (let s in linCom1) { - // const val = this.Fr.mul(k, linCom1[s]); - // res[s] = !(s in res) ? val : this.Fr.add(val, res[s]); - // } - // - // for (let s in linCom2) { - // const val = this.Fr.mul(k, linCom2[s]); - // res[s] = !(s in res) ? val : this.Fr.add(val, res[s]); - // } - - for (let s in linCom1) { - if (typeof res[s] == "undefined") { - res[s] = this.Fr.mul(k, linCom1[s]); - } else { - res[s] = this.Fr.add(res[s], this.Fr.mul(k, linCom1[s])); - } - } - - for (let s in linCom2) { - if (typeof res[s] == "undefined") { - res[s] = linCom2[s]; - } else { - res[s] = this.Fr.add(res[s], linCom2[s]); - } - } - - return this.normalizeLinearCombination(res); - } - - reduceCoefs(settings, constraintsArr, additionsArr, linCom, maxC) { - const res = { - k: this.Fr.zero, - signals: [], - coefs: [] - }; - const cs = []; - - for (let signalId in linCom) { - if (signalId == 0) { - res.k = this.Fr.add(res.k, linCom[signalId]); - } else if (linCom[signalId] != 0n) { - cs.push([Number(signalId), linCom[signalId]]); - } - } - - while (cs.length > maxC) { - const c1 = cs.shift(); - const c2 = cs.shift(); - const so = settings.nVars++; - - const constraints = this.fnGetAdditionConstraint( - c1[0], c2[0], so, - this.Fr.neg(c1[1]), this.Fr.neg(c2[1]), this.Fr.zero, this.Fr.one, this.Fr.zero); - - constraintsArr.push(constraints); - additionsArr.push([c1[0], c2[0], c1[1], c2[1]]); - - cs.push([so, this.Fr.one]); - } - - for (let i = 0; i < cs.length; i++) { - res.signals[i] = cs[i][0]; - res.coefs[i] = cs[i][1]; - } - - while (res.coefs.length < maxC) { - res.signals.push(0); - res.coefs.push(this.Fr.zero); - } - - return res; - } - - processR1csAdditionConstraint(settings, linCom) { - const constraintsArr = []; - const additionsArr = []; - - const C = this.reduceCoefs(settings, constraintsArr, additionsArr, linCom, 3); - - const constraints = this.fnGetAdditionConstraint( - C.signals[0], C.signals[1], C.signals[2], - C.coefs[0], C.coefs[1], this.Fr.zero, C.coefs[2], C.k); - - constraintsArr.push(constraints); - - return [constraintsArr, additionsArr]; - } - - processR1csMultiplicationConstraint(settings, lcA, lcB, lcC) { - const constraintsArr = []; - const additionsArr = []; - - const A = this.reduceCoefs(settings, constraintsArr, additionsArr, lcA, 1); - const B = this.reduceCoefs(settings, constraintsArr, additionsArr, lcB, 1); - const C = this.reduceCoefs(settings, constraintsArr, additionsArr, lcC, 1); - - const constraints = this.fnGetMultiplicationConstraint( - A.signals[0], B.signals[0], C.signals[0], - this.Fr.mul(A.coefs[0], B.k), - this.Fr.mul(A.k, B.coefs[0]), - this.Fr.mul(A.coefs[0], B.coefs[0]), - this.Fr.neg(C.coefs[0]), - this.Fr.sub(this.Fr.mul(A.k, B.k), C.k)); - - constraintsArr.push(constraints); - - return [constraintsArr, additionsArr]; - } - } - - /* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . - */ - - class CPolynomial { - constructor(n, curve, logger) { - this.n = n; - this.polynomials = Array(n).fill(undefined); - this.curve = curve; - this.Fr = curve.Fr; - this.G1 = curve.G1; - this.logger = logger; - } - - addPolynomial(position, polynomial) { - if (position > this.n - 1) { - throw new Error("CPolynomial:addPolynomial, cannot add a polynomial to a position greater than n-1"); - } - - this.polynomials[position] = polynomial; - } - - degree() { - let degrees = this.polynomials.map( - (polynomial, index) => polynomial === undefined ? 0 : polynomial.degree() * this.n + index); - return Math.max(...degrees); - } - - getPolynomial() { - let degrees = this.polynomials.map(polynomial => polynomial === undefined ? 0 : polynomial.degree()); - const maxDegree = this.degree(); - const lengthBuffer = 2 ** (log2(maxDegree - 1) + 1); - const sFr = this.Fr.n8; - - let polynomial = new Polynomial(new BigBuffer(lengthBuffer * sFr), this.curve, this.logger); - - for (let i = 0; i < maxDegree; i++) { - const i_n8 = i * sFr; - const i_sFr = i_n8 * this.n; - - for (let j = 0; j < this.n; j++) { - if (this.polynomials[j] !== undefined) { - if (i <= degrees[j]) polynomial.coef.set(this.polynomials[j].coef.slice(i_n8, i_n8 + sFr), i_sFr + j * sFr); - } - } - } - - return polynomial; - } - - async multiExponentiation(PTau, name) { - let polynomial = this.getPolynomial(); - const n = polynomial.coef.byteLength / this.Fr.n8; - const PTauN = PTau.slice(0, n * this.G1.F.n8 * 2); - const bm = await this.Fr.batchFromMontgomery(polynomial.coef); - let res = await this.G1.multiExpAffine(PTauN, bm, this.logger, name); - res = this.G1.toAffine(res); - return res; - } - } - - /* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . - */ - - - async function fflonkSetup(r1csFilename, ptauFilename, zkeyFilename, logger) { - if (logger) logger.info("FFLONK SETUP STARTED"); - - if (globalThis.gc) globalThis.gc(); - - // Read PTau file - if (logger) logger.info("> Reading PTau file"); - const {fd: fdPTau, sections: pTauSections} = await readBinFile$1(ptauFilename, "ptau", 1); - if (!pTauSections[12]) { - throw new Error("Powers of Tau is not well prepared. Section 12 missing."); - } - - // Get curve defined in PTau - if (logger) logger.info("> Getting curve from PTau settings"); - const {curve} = await readPTauHeader(fdPTau, pTauSections); - - // Read r1cs file - if (logger) logger.info("> Reading r1cs file"); - const {fd: fdR1cs, sections: sectionsR1cs} = await readBinFile$1(r1csFilename, "r1cs", 1); - const r1cs = await readR1csFd(fdR1cs, sectionsR1cs, {loadConstraints: false, loadCustomGates: true}); - - // Potential error checks - if (r1cs.prime !== curve.r) { - throw new Error("r1cs curve does not match powers of tau ceremony curve"); - } - - // Initializations - const Fr = curve.Fr; - - const sFr = curve.Fr.n8; - const sG1 = curve.G1.F.n8 * 2; - const sG2 = curve.G2.F.n8 * 2; - - let polynomials = {}; - let evaluations = {}; - let PTau; - - let settings = { - nVars: r1cs.nVars, - nPublic: r1cs.nOutputs + r1cs.nPubInputs - }; - - const plonkConstraints = new BigArray(); - let plonkAdditions = new BigArray(); - - // Process constraints inside r1cs - if (logger) logger.info("> Processing FFlonk constraints"); - await computeFFConstraints(curve.Fr, r1cs, logger); - if (globalThis.gc) globalThis.gc(); - - // As the t polynomial is n+5 we need at least a power of 4 - //TODO check!!!! - // NOTE : plonkConstraints + 2 = #constraints + blinding coefficients for each wire polynomial - settings.cirPower = Math.max(FF_T_POL_DEG_MIN, log2((plonkConstraints.length + 2) - 1) + 1); - settings.domainSize = 2 ** settings.cirPower; - - if (pTauSections[2][0].size < (settings.domainSize * 9 + 18) * sG1) { - throw new Error("Powers of Tau is not big enough for this circuit size. Section 2 too small."); - } - if (pTauSections[3][0].size < sG2) { - throw new Error("Powers of Tau is not well prepared. Section 3 too small."); - } - - if (logger) { - logger.info("----------------------------"); - logger.info(" FFLONK SETUP SETTINGS"); - logger.info(` Curve: ${curve.name}`); - logger.info(` Circuit power: ${settings.cirPower}`); - logger.info(` Domain size: ${settings.domainSize}`); - logger.info(` Vars: ${settings.nVars}`); - logger.info(` Public vars: ${settings.nPublic}`); - logger.info(` Constraints: ${plonkConstraints.length}`); - logger.info(` Additions: ${plonkAdditions.length}`); - logger.info("----------------------------"); - } - - // Compute k1 and k2 to be used in the permutation checks - if (logger) logger.info("> computing k1 and k2"); - const [k1, k2] = computeK1K2(); - - // Compute omega 3 (w3) and omega 4 (w4) to be used in the prover and the verifier - // w3^3 = 1 and w4^4 = 1 - if (logger) logger.info("> computing w3"); - const w3 = computeW3(); - if (logger) logger.info("> computing w4"); - const w4 = computeW4(); - if (logger) logger.info("> computing w8"); - const w8 = computeW8(); - if (logger) logger.info("> computing wr"); - const wr = getOmegaCubicRoot(settings.cirPower, curve.Fr); - - // Write output zkey file - await writeZkeyFile(); - - await fdR1cs.close(); - await fdPTau.close(); - - if (logger) logger.info("FFLONK SETUP FINISHED"); - - return 0; - - async function computeFFConstraints(Fr, r1cs, logger) { - // Add public inputs and outputs - for (let i = 0; i < settings.nPublic; i++) { - plonkConstraints.push(getFFlonkConstantConstraint(i + 1, Fr)); - } - - // Add all constraints from r1cs file - const r1csProcessor = new r1csConstraintProcessor(Fr, getFFlonkConstantConstraint, getFFlonkAdditionConstraint, getFFlonkMultiplicationConstraint, logger); - - const bR1cs = await readSection$1(fdR1cs, sectionsR1cs, 2); - let bR1csPos = 0; - for (let i = 0; i < r1cs.nConstraints; i++) { - if ((logger) && (i !== 0) && (i % 500000 === 0)) { - logger.info(` processing r1cs constraints ${i}/${r1cs.nConstraints}`); - } - const [constraints, additions] = r1csProcessor.processR1csConstraint(settings, ...readConstraint()); - - plonkConstraints.push(...constraints); - plonkAdditions.push(...additions); - } - - function readConstraint() { - const c = []; - c[0] = readLC(); - c[1] = readLC(); - c[2] = readLC(); - return c; - } - - function readLC() { - const lc = {}; - - const buffUL32 = bR1cs.slice(bR1csPos, bR1csPos + 4); - bR1csPos += 4; - const buffUL32V = new DataView(buffUL32.buffer); - const nIdx = buffUL32V.getUint32(0, true); - - const buff = bR1cs.slice(bR1csPos, bR1csPos + (4 + r1cs.n8) * nIdx); - bR1csPos += (4 + r1cs.n8) * nIdx; - const buffV = new DataView(buff.buffer); - for (let i = 0; i < nIdx; i++) { - const idx = buffV.getUint32(i * (4 + r1cs.n8), true); - const val = r1cs.F.fromRprLE(buff, i * (4 + r1cs.n8) + 4); - lc[idx] = val; - } - return lc; - } - - return 0; - } - - async function writeZkeyFile() { - if (logger) logger.info("> Writing the zkey file"); - const fdZKey = await createBinFile(zkeyFilename, "zkey", 1, ZKEY_FF_NSECTIONS, 1 << 22, 1 << 24); - - if (logger) logger.info(`··· Writing Section ${HEADER_ZKEY_SECTION}. Zkey Header`); - await writeZkeyHeader(fdZKey); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_ADDITIONS_SECTION}. Additions`); - await writeAdditions(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_A_MAP_SECTION}. A Map`); - await writeWitnessMap(fdZKey, ZKEY_FF_A_MAP_SECTION, 0, "A map"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_B_MAP_SECTION}. B Map`); - await writeWitnessMap(fdZKey, ZKEY_FF_B_MAP_SECTION, 1, "B map"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_C_MAP_SECTION}. C Map`); - await writeWitnessMap(fdZKey, ZKEY_FF_C_MAP_SECTION, 2, "C map"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_QL_SECTION}. QL`); - await writeQMap(fdZKey, ZKEY_FF_QL_SECTION, 3, "QL"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_QR_SECTION}. QR`); - await writeQMap(fdZKey, ZKEY_FF_QR_SECTION, 4, "QR"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_QM_SECTION}. QM`); - await writeQMap(fdZKey, ZKEY_FF_QM_SECTION, 5, "QM"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_QO_SECTION}. QO`); - await writeQMap(fdZKey, ZKEY_FF_QO_SECTION, 6, "QO"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_QC_SECTION}. QC`); - await writeQMap(fdZKey, ZKEY_FF_QC_SECTION, 7, "QC"); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Sections ${ZKEY_FF_SIGMA1_SECTION},${ZKEY_FF_SIGMA2_SECTION},${ZKEY_FF_SIGMA3_SECTION}. Sigma1, Sigma2 & Sigma 3`); - await writeSigma(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_LAGRANGE_SECTION}. Lagrange Polynomials`); - await writeLagrangePolynomials(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_PTAU_SECTION}. Powers of Tau`); - await writePtau(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_C0_SECTION}. C0`); - await writeC0(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info(`··· Writing Section ${ZKEY_FF_HEADER_SECTION}. FFlonk Header`); - await writeFFlonkHeader(fdZKey); - if (globalThis.gc) globalThis.gc(); - - if (logger) logger.info("> Writing the zkey file finished"); - - await fdZKey.close(); - } - - async function writeZkeyHeader(fdZKey) { - await startWriteSection(fdZKey, HEADER_ZKEY_SECTION); - await fdZKey.writeULE32(FFLONK_PROTOCOL_ID); - await endWriteSection(fdZKey); - } - - async function writeAdditions(fdZKey) { - await startWriteSection(fdZKey, ZKEY_FF_ADDITIONS_SECTION); - - // Written values are 2 * 32 bit integers (2 * 4 bytes) + 2 field size values ( 2 * sFr bytes) - const buffOut = new Uint8Array(8 + 2 * sFr); - const buffOutV = new DataView(buffOut.buffer); - - for (let i = 0; i < plonkAdditions.length; i++) { - if ((logger) && (i !== 0) && (i % 500000 === 0)) logger.info(` writing Additions: ${i}/${plonkAdditions.length}`); - - const addition = plonkAdditions[i]; - - buffOutV.setUint32(0, addition[0], true); - buffOutV.setUint32(4, addition[1], true); - buffOut.set(addition[2], 8); - buffOut.set(addition[3], 8 + sFr); - - await fdZKey.write(buffOut); - } - await endWriteSection(fdZKey); - } - - async function writeWitnessMap(fdZKey, sectionNum, posConstraint, name) { - await startWriteSection(fdZKey, sectionNum); - for (let i = 0; i < plonkConstraints.length; i++) { - if (logger && (i !== 0) && (i % 500000 === 0)) { - logger.info(` writing witness ${name}: ${i}/${plonkConstraints.length}`); - } - - await fdZKey.writeULE32(plonkConstraints[i][posConstraint]); - } - await endWriteSection(fdZKey); - } - - async function writeQMap(fdZKey, sectionNum, posConstraint, name) { - // Compute Q from q evaluations - let Q = new BigBuffer(settings.domainSize * sFr); - - for (let i = 0; i < plonkConstraints.length; i++) { - Q.set(plonkConstraints[i][posConstraint], i * sFr); - if ((logger) && (i !== 0) && (i % 500000 === 0)) { - logger.info(` writing ${name}: ${i}/${plonkConstraints.length}`); - } - } - - polynomials[name] = await Polynomial.fromEvaluations(Q, curve, logger); - evaluations[name] = await Evaluations.fromPolynomial(polynomials[name], 4, curve, logger); - - // Write Q coefficients and evaluations - await startWriteSection(fdZKey, sectionNum); - await fdZKey.write(polynomials[name].coef); - await fdZKey.write(evaluations[name].eval); - await endWriteSection(fdZKey); - } - - async function writeSigma(fdZKey) { - // Compute sigma - const sigma = new BigBuffer(sFr * settings.domainSize * 3); - const lastSeen = new BigArray(settings.nVars); - const firstPos = new BigArray(settings.nVars); - - let w = Fr.one; - for (let i = 0; i < settings.domainSize; i++) { - if (i < plonkConstraints.length) { - buildSigma(plonkConstraints[i][0], i); - buildSigma(plonkConstraints[i][1], settings.domainSize + i); - buildSigma(plonkConstraints[i][2], settings.domainSize * 2 + i); - } else if (i < settings.domainSize - 2) { - buildSigma(0, i); - buildSigma(0, settings.domainSize + i); - buildSigma(0, settings.domainSize * 2 + i); - } else { - sigma.set(w, i * sFr); - sigma.set(Fr.mul(w, k1), (settings.domainSize + i) * sFr); - sigma.set(Fr.mul(w, k2), (settings.domainSize * 2 + i) * sFr); - } - - w = Fr.mul(w, Fr.w[settings.cirPower]); - - if ((logger) && (i !== 0) && (i % 500000 === 0)) { - logger.info(` writing sigma phase1: ${i}/${plonkConstraints.length}`); - } - } - - for (let i = 0; i < settings.nVars; i++) { - if (typeof firstPos[i] !== "undefined") { - sigma.set(lastSeen[i], firstPos[i] * sFr); - } else { - // throw new Error("Variable not used"); - console.log("Variable not used"); - } - if ((logger) && (i !== 0) && (i % 500000 === 0)) logger.info(` writing sigma phase2: ${i}/${settings.nVars}`); - } - - if (globalThis.gc) globalThis.gc(); - - // Write sigma coefficients and evaluations - for (let i = 0; i < 3; i++) { - const sectionId = 0 === i ? ZKEY_FF_SIGMA1_SECTION : 1 === i ? ZKEY_FF_SIGMA2_SECTION : ZKEY_FF_SIGMA3_SECTION; - - let name = "S" + (i + 1); - polynomials[name] = await Polynomial.fromEvaluations(sigma.slice(settings.domainSize * sFr * i, settings.domainSize * sFr * (i + 1)), curve, logger); - evaluations[name] = await Evaluations.fromPolynomial(polynomials[name], 4, curve, logger); - await startWriteSection(fdZKey, sectionId); - await fdZKey.write(polynomials[name].coef); - await fdZKey.write(evaluations[name].eval); - await endWriteSection(fdZKey); - - if (globalThis.gc) globalThis.gc(); - } - - return 0; - - function buildSigma(signalId, idx) { - if (typeof lastSeen[signalId] === "undefined") { - firstPos[signalId] = idx; - } else { - sigma.set(lastSeen[signalId], idx * sFr); - } - let v; - if (idx < settings.domainSize) { - v = w; - } else if (idx < 2 * settings.domainSize) { - v = Fr.mul(w, k1); - } else { - v = Fr.mul(w, k2); - } - - lastSeen[signalId] = v; - } - } - - async function writeLagrangePolynomials(fdZKey) { - await startWriteSection(fdZKey, ZKEY_FF_LAGRANGE_SECTION); - - const l = Math.max(settings.nPublic, 1); - for (let i = 0; i < l; i++) { - let buff = new BigBuffer(settings.domainSize * sFr); - buff.set(Fr.one, i * sFr); - - await writeP4(fdZKey, buff); - } - await endWriteSection(fdZKey); - } - - async function writePtau(fdZKey) { - await startWriteSection(fdZKey, ZKEY_FF_PTAU_SECTION); - - // domainSize * 9 + 18 = maximum SRS length needed, specifically to commit C2 - PTau = new BigBuffer((settings.domainSize * 9 + 18) * sG1); - await fdPTau.readToBuffer(PTau, 0, (settings.domainSize * 9 + 18) * sG1, pTauSections[2][0].p); - - await fdZKey.write(PTau); - await endWriteSection(fdZKey); - } - - async function writeC0(fdZKey) { - // C0(X) := QL(X^8) + X · QR(X^8) + X^2 · QO(X^8) + X^3 · QM(X^8) + X^4 · QC(X^8) - // + X^5 · SIGMA1(X^8) + X^6 · SIGMA2(X^8) + X^7 · SIGMA3(X^8) - let C0 = new CPolynomial(8, curve, logger); - C0.addPolynomial(0, polynomials.QL); - C0.addPolynomial(1, polynomials.QR); - C0.addPolynomial(2, polynomials.QO); - C0.addPolynomial(3, polynomials.QM); - C0.addPolynomial(4, polynomials.QC); - C0.addPolynomial(5, polynomials.S1); - C0.addPolynomial(6, polynomials.S2); - C0.addPolynomial(7, polynomials.S3); - - polynomials.C0 = C0.getPolynomial(); - - // Check degree - if (polynomials.C0.degree() >= 8 * settings.domainSize) { - throw new Error("C0 Polynomial is not well calculated"); - } - - await startWriteSection(fdZKey, ZKEY_FF_C0_SECTION); - await fdZKey.write(polynomials.C0.coef); - await endWriteSection(fdZKey); - } - - async function writeFFlonkHeader(fdZKey) { - await startWriteSection(fdZKey, ZKEY_FF_HEADER_SECTION); - - const primeQ = curve.q; - const n8q = (Math.floor((Scalar.bitLength(primeQ) - 1) / 64) + 1) * 8; - await fdZKey.writeULE32(n8q); - await writeBigInt(fdZKey, primeQ, n8q); - - const primeR = curve.r; - const n8r = (Math.floor((Scalar.bitLength(primeR) - 1) / 64) + 1) * 8; - await fdZKey.writeULE32(n8r); - await writeBigInt(fdZKey, primeR, n8r); - - // Total number of r1cs vars - await fdZKey.writeULE32(settings.nVars); - // Total number of r1cs public vars = outputs + public inputs - await fdZKey.writeULE32(settings.nPublic); - await fdZKey.writeULE32(settings.domainSize); - await fdZKey.writeULE32(plonkAdditions.length); - await fdZKey.writeULE32(plonkConstraints.length); - - await fdZKey.write(k1); - await fdZKey.write(k2); - - await fdZKey.write(w3); - await fdZKey.write(w4); - await fdZKey.write(w8); - await fdZKey.write(wr); - - let bX_2; - bX_2 = await fdPTau.read(sG2, pTauSections[3][0].p + sG2); - await fdZKey.write(bX_2); - - let commitC0 = await polynomials.C0.multiExponentiation(PTau, "C0"); - await fdZKey.write(commitC0); - - await endWriteSection(fdZKey); - } - - async function writeP4(fdZKey, buff) { - const [coefficients, evaluations4] = await Polynomial.to4T(buff, settings.domainSize, [], Fr); - await fdZKey.write(coefficients); - await fdZKey.write(evaluations4); - - return [coefficients, evaluations4]; - } - - function computeK1K2() { - let k1 = Fr.two; - while (isIncluded(k1, [], settings.cirPower)) Fr.add(k1, Fr.one); - let k2 = Fr.add(k1, Fr.one); - while (isIncluded(k2, [k1], settings.cirPower)) Fr.add(k2, Fr.one); - return [k1, k2]; - - function isIncluded(k, kArr, pow) { - const domainSize = 2 ** pow; - let w = Fr.one; - for (let i = 0; i < domainSize; i++) { - if (Fr.eq(k, w)) return true; - for (let j = 0; j < kArr.length; j++) { - if (Fr.eq(k, Fr.mul(kArr[j], w))) return true; - } - w = Fr.mul(w, Fr.w[pow]); - } - return false; - } - } - - function computeW3() { - let generator = Fr.e(31624); - - // Exponent is order(r - 1) / 3 - let orderRsub1 = 3648040478639879203707734290876212514758060733402672390616367364429301415936n; - let exponent = Scalar.div(orderRsub1, Scalar.e(3)); - - return Fr.exp(generator, exponent); - } - - function computeW4() { - return Fr.w[2]; - } - - function computeW8() { - return Fr.w[3]; - } - - function getOmegaCubicRoot(power, Fr) { - // Hardcorded 3th-root of Fr.w[28] - const firstRoot = Fr.e(467799165886069610036046866799264026481344299079011762026774533774345988080n); - - return Fr.exp(firstRoot, 2 ** (28 - power)); - } - } - - /* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . - */ - - const { stringifyBigInts } = utils$6; - - - async function fflonkProve(zkeyFileName, witnessFileName, logger, options) { - if (logger) logger.info("FFLONK PROVER STARTED"); - - // Read witness file - if (logger) logger.info("> Reading witness file"); - const { - fd: fdWtns, - sections: wtnsSections - } = await readBinFile$1(witnessFileName, "wtns", 2); - const wtns = await readHeader(fdWtns, wtnsSections); - - //Read zkey file - if (logger) logger.info("> Reading zkey file"); - const { - fd: fdZKey, - sections: zkeySections - } = await readBinFile$1(zkeyFileName, "zkey", 2); - - const zkey = await readHeader$1(fdZKey, zkeySections, undefined, options); - - if (zkey.protocolId !== FFLONK_PROTOCOL_ID) { - throw new Error("zkey file is not fflonk"); - } - - if (!Scalar.eq(zkey.r, wtns.q)) { - throw new Error("Curve of the witness does not match the curve of the proving key"); - } - - if (wtns.nWitness !== zkey.nVars - zkey.nAdditions) { - throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}, ${zkey.nAdditions}`); - } - - const curve = zkey.curve; - - const Fr = curve.Fr; - - const sFr = curve.Fr.n8; - const sG1 = curve.G1.F.n8 * 2; - const sDomain = zkey.domainSize * sFr; - - if (logger) { - logger.info("----------------------------"); - logger.info(" FFLONK PROVE SETTINGS"); - logger.info(` Curve: ${curve.name}`); - logger.info(` Circuit power: ${zkey.power}`); - logger.info(` Domain size: ${zkey.domainSize}`); - logger.info(` Vars: ${zkey.nVars}`); - logger.info(` Public vars: ${zkey.nPublic}`); - logger.info(` Constraints: ${zkey.nConstraints}`); - logger.info(` Additions: ${zkey.nAdditions}`); - logger.info("----------------------------"); - } - - //Read witness data - if (logger) logger.info("> Reading witness file data"); - const buffWitness = await readSection$1(fdWtns, wtnsSections, 2); - await fdWtns.close(); - - // First element in plonk is not used and can be any value. (But always the same). - // We set it to zero to go faster in the exponentiations. - buffWitness.set(Fr.zero, 0); - const buffInternalWitness = new BigBuffer(zkey.nAdditions * sFr); - - let buffers = {}; - let polynomials = {}; - let evaluations = {}; - - // To divide prime fields the Extended Euclidean Algorithm for computing modular inverses is needed. - // NOTE: This is the equivalent of compute 1/denominator and then multiply it by the numerator. - // The Extended Euclidean Algorithm is expensive in terms of computation. - // For the special case where we need to do many modular inverses, there's a simple mathematical trick - // that allows us to compute many inverses, called Montgomery batch inversion. - // More info: https://vitalik.ca/general/2018/07/21/starks_part_3.html - // Montgomery batch inversion reduces the n inverse computations to a single one - // To save this (single) inverse computation on-chain, will compute it in proving time and send it to the verifier. - // The verifier will have to check: - // 1) the denominator is correct multiplying by himself non-inverted -> a * 1/a == 1 - // 2) compute the rest of the denominators using the Montgomery batch inversion - // The inversions are: - // · denominator needed in step 8 and 9 of the verifier to multiply by 1/Z_H(xi) - // · denominator needed in step 10 and 11 of the verifier - // · denominator needed in the verifier when computing L_i^{S1}(X) and L_i^{S2}(X) - // · L_i i=1 to num public inputs, needed in step 6 and 7 of the verifier to compute L_1(xi) and PI(xi) - let toInverse = {}; - - let challenges = {}; - let roots = {}; - - let proof = new Proof(curve, logger); - - if (logger) logger.info(`> Reading Section ${ZKEY_FF_ADDITIONS_SECTION}. Additions`); - await calculateAdditions(); - - if (logger) logger.info(`> Reading Sections ${ZKEY_FF_SIGMA1_SECTION},${ZKEY_FF_SIGMA2_SECTION},${ZKEY_FF_SIGMA3_SECTION}. Sigma1, Sigma2 & Sigma 3`); - if (logger) logger.info("··· Reading Sigma polynomials "); - polynomials.Sigma1 = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.Sigma2 = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.Sigma3 = new Polynomial(new BigBuffer(sDomain), curve, logger); - - await fdZKey.readToBuffer(polynomials.Sigma1.coef, 0, sDomain, zkeySections[ZKEY_FF_SIGMA1_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.Sigma2.coef, 0, sDomain, zkeySections[ZKEY_FF_SIGMA2_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.Sigma3.coef, 0, sDomain, zkeySections[ZKEY_FF_SIGMA3_SECTION][0].p); - - if (logger) logger.info("··· Reading Sigma evaluations"); - evaluations.Sigma1 = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.Sigma2 = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.Sigma3 = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - - await fdZKey.readToBuffer(evaluations.Sigma1.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_SIGMA1_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.Sigma2.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_SIGMA2_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.Sigma3.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_SIGMA3_SECTION][0].p + sDomain); - - if (logger) logger.info(`> Reading Section ${ZKEY_FF_PTAU_SECTION}. Powers of Tau`); - const PTau = new BigBuffer(zkey.domainSize * 16 * sG1); - // domainSize * 9 + 18 = SRS length in the zkey saved in setup process. - // it corresponds to the maximum SRS length needed, specifically to commit C2 - // notice that the reserved buffers size is zkey.domainSize * 16 * sG1 because a power of two buffer size is needed - // the remaining buffer not filled from SRS are set to 0 - await fdZKey.readToBuffer(PTau, 0, (zkey.domainSize * 9 + 18) * sG1, zkeySections[ZKEY_FF_PTAU_SECTION][0].p); - - // START FFLONK PROVER PROTOCOL - if (globalThis.gc) globalThis.gc(); - - // ROUND 1. Compute C1(X) polynomial - if (logger) logger.info(""); - if (logger) logger.info("> ROUND 1"); - await round1(); - - delete polynomials.T0; - delete evaluations.QL; - delete evaluations.QR; - delete evaluations.QM; - delete evaluations.QO; - delete evaluations.QC; - if (globalThis.gc) globalThis.gc(); - - // ROUND 2. Compute C2(X) polynomial - if (logger) logger.info("> ROUND 2"); - await round2(); - - delete buffers.A; - delete buffers.B; - delete buffers.C; - delete evaluations.A; - delete evaluations.B; - delete evaluations.C; - delete evaluations.Sigma1; - delete evaluations.Sigma2; - delete evaluations.Sigma3; - delete evaluations.lagrange1; - delete evaluations.Z; - if (globalThis.gc) globalThis.gc(); - - // ROUND 3. Compute opening evaluations - if (logger) logger.info("> ROUND 3"); - await round3(); - - delete polynomials.A; - delete polynomials.B; - delete polynomials.C; - delete polynomials.Z; - delete polynomials.T1; - delete polynomials.T2; - delete polynomials.Sigma1; - delete polynomials.Sigma2; - delete polynomials.Sigma3; - delete polynomials.QL; - delete polynomials.QR; - delete polynomials.QM; - delete polynomials.QC; - delete polynomials.QO; - if (globalThis.gc) globalThis.gc(); - - // ROUND 4. Compute W(X) polynomial - if (logger) logger.info("> ROUND 4"); - await round4(); - if (globalThis.gc) globalThis.gc(); - - // ROUND 5. Compute W'(X) polynomial - if (logger) logger.info("> ROUND 5"); - await round5(); - - delete polynomials.C0; - delete polynomials.C1; - delete polynomials.C2; - delete polynomials.R1; - delete polynomials.R2; - delete polynomials.F; - delete polynomials.L; - delete polynomials.ZT; - delete polynomials.ZTS2; - await fdZKey.close(); - if (globalThis.gc) globalThis.gc(); - - proof.addEvaluation("inv", getMontgomeryBatchedInverse()); - - // Prepare proof - let _proof = proof.toObjectProof(); - _proof.protocol = "fflonk"; - _proof.curve = curve.name; - - // Prepare public inputs - let publicSignals = []; - - for (let i = 1; i <= zkey.nPublic; i++) { - const i_sFr = i * sFr; - - const pub = buffWitness.slice(i_sFr, i_sFr + sFr); - publicSignals.push(Scalar.fromRprLE(pub)); - } - - if (logger) logger.info("FFLONK PROVER FINISHED"); - - return { - proof: stringifyBigInts(_proof), - publicSignals: stringifyBigInts(publicSignals) - }; - - async function calculateAdditions() { - if (logger) logger.info("··· Computing additions"); - const additionsBuff = await readSection$1(fdZKey, zkeySections, ZKEY_FF_ADDITIONS_SECTION); - - // sizes: wireId_x = 4 bytes (32 bits), factor_x = field size bits - // Addition form: wireId_a wireId_b factor_a factor_b (size is 4 + 4 + sFr + sFr) - const sSum = 8 + sFr * 2; - - for (let i = 0; i < zkey.nAdditions; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.info(` addition ${i}/${zkey.nAdditions}`); - - // Read addition values - let offset = i * sSum; - const signalId1 = readUInt32(additionsBuff, offset); - offset += 4; - const signalId2 = readUInt32(additionsBuff, offset); - offset += 4; - const factor1 = additionsBuff.slice(offset, offset + sFr); - offset += sFr; - const factor2 = additionsBuff.slice(offset, offset + sFr); - - // Get witness value - const witness1 = getWitness(signalId1); - const witness2 = getWitness(signalId2); - - //Calculate final result - const result = Fr.add(Fr.mul(factor1, witness1), Fr.mul(factor2, witness2)); - - buffInternalWitness.set(result, sFr * i); - } - } - - function readUInt32(b, o) { - const buff = b.slice(o, o + 4); - const buffV = new DataView(buff.buffer, buff.byteOffset, buff.byteLength); - return buffV.getUint32(0, true); - } - - function getWitness(idx) { - let diff = zkey.nVars - zkey.nAdditions; - if (idx < diff) { - return buffWitness.slice(idx * sFr, idx * sFr + sFr); - } else if (idx < zkey.nVars) { - const offset = (idx - diff) * sFr; - return buffInternalWitness.slice(offset, offset + sFr); - } - - return Fr.zero; - } - - async function round1() { - // STEP 1.1 - Generate random blinding scalars (b_1, ..., b9) ∈ F - challenges.b = []; - for (let i = 1; i <= 9; i++) { - challenges.b[i] = Fr.random(); - } - - // STEP 1.2 - Compute wire polynomials a(X), b(X) and c(X) - if (logger) logger.info("> Computing A, B, C wire polynomials"); - await computeWirePolynomials(); - - // STEP 1.3 - Compute the quotient polynomial T0(X) - if (logger) logger.info("> Computing T0 polynomial"); - await computeT0(); - - // STEP 1.4 - Compute the FFT-style combination polynomial C1(X) - if (logger) logger.info("> Computing C1 polynomial"); - await computeC1(); - - // The first output of the prover is ([C1]_1) - if (logger) logger.info("> Computing C1 multi exponentiation"); - let commitC1 = await polynomials.C1.multiExponentiation(PTau, "C1"); - proof.addPolynomial("C1", commitC1); - - return 0; - - async function computeWirePolynomials() { - if (logger) logger.info("··· Reading data from zkey file"); - // Build A, B and C evaluations buffer from zkey and witness files - buffers.A = new BigBuffer(sDomain); - buffers.B = new BigBuffer(sDomain); - buffers.C = new BigBuffer(sDomain); - - // Read zkey sections and fill the buffers - const aMapBuff = await readSection$1(fdZKey, zkeySections, ZKEY_FF_A_MAP_SECTION); - const bMapBuff = await readSection$1(fdZKey, zkeySections, ZKEY_FF_B_MAP_SECTION); - const cMapBuff = await readSection$1(fdZKey, zkeySections, ZKEY_FF_C_MAP_SECTION); - - // Compute all witness from signal ids and set them to A,B & C buffers - for (let i = 0; i < zkey.nConstraints; i++) { - const i_sFr = i * sFr; - const offset = i * 4; - - // Compute A value from a signal id - const signalIdA = readUInt32(aMapBuff, offset); - buffers.A.set(getWitness(signalIdA), i_sFr); - - // Compute B value from a signal id - const signalIdB = readUInt32(bMapBuff, offset); - buffers.B.set(getWitness(signalIdB), i_sFr); - - // Compute C value from a signal id - const signalIdC = readUInt32(cMapBuff, offset); - buffers.C.set(getWitness(signalIdC), i_sFr); - } - - // Blind a(X), b(X) and c(X) polynomials coefficients with blinding scalars b - buffers.A.set(challenges.b[1], sDomain - 64); - buffers.A.set(challenges.b[2], sDomain - 32); - buffers.B.set(challenges.b[3], sDomain - 64); - buffers.B.set(challenges.b[4], sDomain - 32); - buffers.C.set(challenges.b[5], sDomain - 64); - buffers.C.set(challenges.b[6], sDomain - 32); - - buffers.A = await Fr.batchToMontgomery(buffers.A); - buffers.B = await Fr.batchToMontgomery(buffers.B); - buffers.C = await Fr.batchToMontgomery(buffers.C); - - // Compute the coefficients of the wire polynomials a(X), b(X) and c(X) from A,B & C buffers - if (logger) logger.info("··· Computing A ifft"); - polynomials.A = await Polynomial.fromEvaluations(buffers.A, curve, logger); - if (logger) logger.info("··· Computing B ifft"); - polynomials.B = await Polynomial.fromEvaluations(buffers.B, curve, logger); - if (logger) logger.info("··· Computing C ifft"); - polynomials.C = await Polynomial.fromEvaluations(buffers.C, curve, logger); - - // Compute extended evaluations of a(X), b(X) and c(X) polynomials - if (logger) logger.info("··· Computing A fft"); - evaluations.A = await Evaluations.fromPolynomial(polynomials.A, 4, curve, logger); - if (logger) logger.info("··· Computing B fft"); - evaluations.B = await Evaluations.fromPolynomial(polynomials.B, 4, curve, logger); - if (logger) logger.info("··· Computing C fft"); - evaluations.C = await Evaluations.fromPolynomial(polynomials.C, 4, curve, logger); - - // Check degrees - if (polynomials.A.degree() >= zkey.domainSize) { - throw new Error("A Polynomial is not well calculated"); - } - if (polynomials.B.degree() >= zkey.domainSize) { - throw new Error("B Polynomial is not well calculated"); - } - if (polynomials.C.degree() >= zkey.domainSize) { - throw new Error("C Polynomial is not well calculated"); - } - } - - async function computeT0() { - if (logger) logger.info(`··· Reading sections ${ZKEY_FF_QL_SECTION}, ${ZKEY_FF_QR_SECTION}` + - `, ${ZKEY_FF_QM_SECTION}, ${ZKEY_FF_QO_SECTION}, ${ZKEY_FF_QC_SECTION}. Q selectors`); - // Reserve memory for Q's evaluations - evaluations.QL = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.QR = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.QM = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.QO = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - evaluations.QC = new Evaluations(new BigBuffer(sDomain * 4), curve, logger); - - // Read Q's evaluations from zkey file - await fdZKey.readToBuffer(evaluations.QL.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_QL_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QR.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_QR_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QM.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_QM_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QO.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_QO_SECTION][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QC.eval, 0, sDomain * 4, zkeySections[ZKEY_FF_QC_SECTION][0].p + sDomain); - - // Read Lagrange polynomials & evaluations from zkey file - const lagrangePolynomials = await readSection$1(fdZKey, zkeySections, ZKEY_FF_LAGRANGE_SECTION); - evaluations.lagrange1 = new Evaluations(lagrangePolynomials, curve, logger); - - // Reserve memory for buffers T0 - buffers.T0 = new BigBuffer(sDomain * 4); - - if (logger) logger.info("··· Computing T0 evaluations"); - for (let i = 0; i < zkey.domainSize * 4; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.info(` T0 evaluation ${i}/${zkey.domainSize * 4}`); - - // Get related evaluations to compute current T0 evaluation - const a = evaluations.A.getEvaluation(i); - const b = evaluations.B.getEvaluation(i); - const c = evaluations.C.getEvaluation(i); - - const ql = evaluations.QL.getEvaluation(i); - const qr = evaluations.QR.getEvaluation(i); - const qm = evaluations.QM.getEvaluation(i); - const qo = evaluations.QO.getEvaluation(i); - const qc = evaluations.QC.getEvaluation(i); - - // Compute current public input - let pi = Fr.zero; - for (let j = 0; j < zkey.nPublic; j++) { - const offset = (j * 5 * zkey.domainSize) + zkey.domainSize + i; - - const lPol = evaluations.lagrange1.getEvaluation(offset); - const aVal = buffers.A.slice(j * sFr, (j + 1) * sFr); - - pi = Fr.sub(pi, Fr.mul(lPol, aVal)); - } - - //T0(X) = [q_L(X)·a(X) + q_R(X)·b(X) + q_M(X)·a(X)·b(X) + q_O(X)·c(X) + q_C(X) + PI(X)] · 1/Z_H(X) - // Compute first T0(X)·Z_H(X), so divide later the resulting polynomial by Z_H(X) - // expression 1 -> q_L(X)·a(X) - const e1 = Fr.mul(a, ql); - - // expression 2 -> q_R(X)·b(X) - const e2 = Fr.mul(b, qr); - - // expression 3 -> q_M(X)·a(X)·b(X) - const e3 = Fr.mul(Fr.mul(a, b), qm); - - // expression 4 -> q_O(X)·c(X) - const e4 = Fr.mul(c, qo); - - // t0 = expressions 1 + expression 2 + expression 3 + expression 4 + qc + pi - const t0 = Fr.add(e1, Fr.add(e2, Fr.add(e3, Fr.add(e4, Fr.add(qc, pi))))); - - buffers.T0.set(t0, i * sFr); - } - - if (logger) logger.info("buffer T0: " + buffers.T0.byteLength / sFr); - - // Compute the coefficients of the polynomial T0(X) from buffers.T0 - if (logger) logger.info("··· Computing T0 ifft"); - polynomials.T0 = await Polynomial.fromEvaluations(buffers.T0, curve, logger); - - if (logger) logger.info("T0 length: " + polynomials.T0.length()); - if (logger) logger.info("T0 degree: " + polynomials.T0.degree()); - - // Divide the polynomial T0 by Z_H(X) - if (logger) logger.info("··· Computing T0 / ZH"); - polynomials.T0.divByZerofier(zkey.domainSize, Fr.one); - - // Check degree - if (polynomials.T0.degree() >= 2 * zkey.domainSize - 2) { - throw new Error(`T0 Polynomial is not well calculated (degree is ${polynomials.T0.degree()} and must be less than ${2 * zkey.domainSize + 2}`); - } - - delete buffers.T0; - } - - async function computeC1() { - let C1 = new CPolynomial(4, curve, logger); - C1.addPolynomial(0, polynomials.A); - C1.addPolynomial(1, polynomials.B); - C1.addPolynomial(2, polynomials.C); - C1.addPolynomial(3, polynomials.T0); - - polynomials.C1 = C1.getPolynomial(); - - // Check degree - if (polynomials.C1.degree() >= 8 * zkey.domainSize - 8) { - throw new Error("C1 Polynomial is not well calculated"); - } - } - } - - async function round2() { - // STEP 2.1 - Compute permutation challenge beta and gamma ∈ F - // Compute permutation challenge beta - if (logger) logger.info("> Computing challenges beta and gamma"); - const transcript = new Keccak256Transcript(curve); - - // Add C0 to the transcript - transcript.addPolCommitment(zkey.C0); - - // Add A to the transcript - for (let i = 0; i < zkey.nPublic; i++) { - transcript.addScalar(buffers.A.slice(i * sFr, i * sFr + sFr)); - } - - // Add C1 to the transcript - transcript.addPolCommitment(proof.getPolynomial("C1")); - - challenges.beta = transcript.getChallenge(); - if (logger) logger.info("··· challenges.beta: " + Fr.toString(challenges.beta)); - - // Compute permutation challenge gamma - transcript.reset(); - transcript.addScalar(challenges.beta); - challenges.gamma = transcript.getChallenge(); - if (logger) logger.info("··· challenges.gamma: " + Fr.toString(challenges.gamma)); - - // STEP 2.2 - Compute permutation polynomial z(X) - if (logger) logger.info("> Computing Z polynomial"); - await computeZ(); - - // STEP 2.3 - Compute quotient polynomial T1(X) and T2(X) - if (logger) logger.info("> Computing T1 polynomial"); - await computeT1(); - if (logger) logger.info("> Computing T2 polynomial"); - await computeT2(); - - // STEP 2.4 - Compute the FFT-style combination polynomial C2(X) - if (logger) logger.info("> Computing C2 polynomial"); - await computeC2(); - - // The second output of the prover is ([C2]_1) - if (logger) logger.info("> Computing C2 multi exponentiation"); - let commitC2 = await polynomials.C2.multiExponentiation(PTau, "C2"); - proof.addPolynomial("C2", commitC2); - - return 0; - - async function computeZ() { - if (logger) logger.info("··· Computing Z evaluations"); - - let numArr = new BigBuffer(sDomain); - let denArr = new BigBuffer(sDomain); - - // Set the first values to 1 - numArr.set(Fr.one, 0); - denArr.set(Fr.one, 0); - - // Set initial omega - let w = Fr.one; - for (let i = 0; i < zkey.domainSize; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.info(` Z evaluation ${i}/${zkey.domainSize}`); - const i_sFr = i * sFr; - - // Z(X) := numArr / denArr - // numArr := (a + beta·ω + gamma)(b + beta·ω·k1 + gamma)(c + beta·ω·k2 + gamma) - const betaw = Fr.mul(challenges.beta, w); - - let num1 = buffers.A.slice(i_sFr, i_sFr + sFr); - num1 = Fr.add(num1, betaw); - num1 = Fr.add(num1, challenges.gamma); - - let num2 = buffers.B.slice(i_sFr, i_sFr + sFr); - num2 = Fr.add(num2, Fr.mul(zkey.k1, betaw)); - num2 = Fr.add(num2, challenges.gamma); - - let num3 = buffers.C.slice(i_sFr, i_sFr + sFr); - num3 = Fr.add(num3, Fr.mul(zkey.k2, betaw)); - num3 = Fr.add(num3, challenges.gamma); - - let num = Fr.mul(num1, Fr.mul(num2, num3)); - - // denArr := (a + beta·sigma1 + gamma)(b + beta·sigma2 + gamma)(c + beta·sigma3 + gamma) - let den1 = buffers.A.slice(i_sFr, i_sFr + sFr); - den1 = Fr.add(den1, Fr.mul(challenges.beta, evaluations.Sigma1.getEvaluation(i * 4))); - den1 = Fr.add(den1, challenges.gamma); - - let den2 = buffers.B.slice(i_sFr, i_sFr + sFr); - den2 = Fr.add(den2, Fr.mul(challenges.beta, evaluations.Sigma2.getEvaluation(i * 4))); - den2 = Fr.add(den2, challenges.gamma); - - let den3 = buffers.C.slice(i_sFr, i_sFr + sFr); - den3 = Fr.add(den3, Fr.mul(challenges.beta, evaluations.Sigma3.getEvaluation(i * 4))); - den3 = Fr.add(den3, challenges.gamma); - - let den = Fr.mul(den1, Fr.mul(den2, den3)); - - // Multiply current num value with the previous one saved in numArr - num = Fr.mul(numArr.slice(i_sFr, i_sFr + sFr), num); - numArr.set(num, ((i + 1) % zkey.domainSize) * sFr); - - // Multiply current den value with the previous one saved in denArr - den = Fr.mul(denArr.slice(i_sFr, i_sFr + sFr), den); - denArr.set(den, ((i + 1) % zkey.domainSize) * sFr); - - // Next omega - w = Fr.mul(w, Fr.w[zkey.power]); - } - // Compute the inverse of denArr to compute in the next command the - // division numArr/denArr by multiplying num · 1/denArr - denArr = await Fr.batchInverse(denArr); - - // TODO: Do it in assembly and in parallel - // Multiply numArr · denArr where denArr was inverted in the previous command - for (let i = 0; i < zkey.domainSize; i++) { - const i_sFr = i * sFr; - - const z = Fr.mul(numArr.slice(i_sFr, i_sFr + sFr), denArr.slice(i_sFr, i_sFr + sFr)); - numArr.set(z, i_sFr); - } - // From now on the values saved on numArr will be Z(X) buffer - buffers.Z = numArr; - - if (!Fr.eq(numArr.slice(0, sFr), Fr.one)) { - throw new Error("Copy constraints does not match"); - } - - // Compute polynomial coefficients z(X) from buffers.Z - if (logger) logger.info("··· Computing Z ifft"); - polynomials.Z = await Polynomial.fromEvaluations(buffers.Z, curve, logger); - - // Compute extended evaluations of z(X) polynomial - if (logger) logger.info("··· Computing Z fft"); - evaluations.Z = await Evaluations.fromPolynomial(polynomials.Z, 4, curve, logger); - - // Blind z(X) polynomial coefficients with blinding scalars b - polynomials.Z.blindCoefficients([challenges.b[9], challenges.b[8], challenges.b[7]]); - - // Check degree - if (polynomials.Z.degree() >= zkey.domainSize + 3) { - throw new Error("Z Polynomial is not well calculated"); - } - - delete buffers.Z; - } - - async function computeT1() { - if (logger) logger.info("··· Computing T1 evaluations"); - - buffers.T1 = new BigBuffer(sDomain * 2); - buffers.T1z = new BigBuffer(sDomain * 2); - - // Set initial omega - let omega = Fr.one; - for (let i = 0; i < zkey.domainSize * 2; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.info(` T1 evaluation ${i}/${zkey.domainSize * 4}`); - - const omega2 = Fr.square(omega); - - const z = evaluations.Z.getEvaluation(i * 2); - const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omega2), Fr.mul(challenges.b[8], omega)), challenges.b[9]); - - // T1(X) := (z(X) - 1) · L_1(X) - // Compute first T1(X)·Z_H(X), so divide later the resulting polynomial by Z_H(X) - const lagrange1 = evaluations.lagrange1.getEvaluation(zkey.domainSize + i * 2); - let t1 = Fr.mul(Fr.sub(z, Fr.one), lagrange1); - let t1z = Fr.mul(zp, lagrange1); - - buffers.T1.set(t1, i * sFr); - buffers.T1z.set(t1z, i * sFr); - - // Compute next omega - omega = Fr.mul(omega, Fr.w[zkey.power + 1]); - } - - // Compute the coefficients of the polynomial T1(X) from buffers.T1 - if (logger) logger.info("··· Computing T1 ifft"); - polynomials.T1 = await Polynomial.fromEvaluations(buffers.T1, curve, logger); - - // Divide the polynomial T1 by Z_H(X) - polynomials.T1.divByZerofier(zkey.domainSize, Fr.one); - - // Compute the coefficients of the polynomial T1z(X) from buffers.T1z - if (logger) logger.info("··· Computing T1z ifft"); - polynomials.T1z = await Polynomial.fromEvaluations(buffers.T1z, curve, logger); - - // Add the polynomial T1z to T1 to get the final polynomial T1 - polynomials.T1.add(polynomials.T1z); - - // Check degree - if (polynomials.T1.degree() >= zkey.domainSize + 2) { - throw new Error("T1 Polynomial is not well calculated"); - } - - delete buffers.T1; - delete buffers.T1z; - delete polynomials.T1z; - } - - async function computeT2() { - if (logger) logger.info("··· Computing T2 evaluations"); - - buffers.T2 = new BigBuffer(sDomain * 4); - buffers.T2z = new BigBuffer(sDomain * 4); - - // Set initial omega - let omega = Fr.one; - for (let i = 0; i < zkey.domainSize * 4; i++) { - if (logger && (0 !== i) && (i % 100000 === 0)) logger.info(` T2 evaluation ${i}/${zkey.domainSize * 4}`); - - const omega2 = Fr.square(omega); - const omegaW = Fr.mul(omega, Fr.w[zkey.power]); - const omegaW2 = Fr.square(omegaW); - - const a = evaluations.A.getEvaluation(i); - const b = evaluations.B.getEvaluation(i); - const c = evaluations.C.getEvaluation(i); - const z = evaluations.Z.getEvaluation(i); - const zW = evaluations.Z.getEvaluation((zkey.domainSize * 4 + 4 + i) % (zkey.domainSize * 4)); - - const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omega2), Fr.mul(challenges.b[8], omega)), challenges.b[9]); - const zWp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omegaW2), Fr.mul(challenges.b[8], omegaW)), challenges.b[9]); - - const sigma1 = evaluations.Sigma1.getEvaluation(i); - const sigma2 = evaluations.Sigma2.getEvaluation(i); - const sigma3 = evaluations.Sigma3.getEvaluation(i); - - // T2(X) := [ (a(X) + beta·X + gamma)(b(X) + beta·k1·X + gamma)(c(X) + beta·k2·X + gamma)z(X) - // -(a(X) + beta·sigma1(X) + gamma)(b(X) + beta·sigma2(X) + gamma)(c(X) + beta·sigma3(X) + gamma)z(Xω)] · 1/Z_H(X) - // Compute first T2(X)·Z_H(X), so divide later the resulting polynomial by Z_H(X) - - // expression 1 -> (a(X) + beta·X + gamma)(b(X) + beta·k1·X + gamma)(c(X) + beta·k2·X + gamma)z(X) - const betaX = Fr.mul(challenges.beta, omega); - - let e11 = Fr.add(a, betaX); - e11 = Fr.add(e11, challenges.gamma); - - let e12 = Fr.add(b, Fr.mul(betaX, zkey.k1)); - e12 = Fr.add(e12, challenges.gamma); - - let e13 = Fr.add(c, Fr.mul(betaX, zkey.k2)); - e13 = Fr.add(e13, challenges.gamma); - - let e1 = Fr.mul(Fr.mul(Fr.mul(e11, e12), e13), z); - let e1z = Fr.mul(Fr.mul(Fr.mul(e11, e12), e13), zp); - // const [e1, e1z] = MulZ.mul4(e11, e12, e13, z, ap, bp, cp, zp, i % 4, Fr); - - // expression 2 -> (a(X) + beta·sigma1(X) + gamma)(b(X) + beta·sigma2(X) + gamma)(c(X) + beta·sigma3(X) + gamma)z(Xω) - let e21 = Fr.add(a, Fr.mul(challenges.beta, sigma1)); - e21 = Fr.add(e21, challenges.gamma); - - let e22 = Fr.add(b, Fr.mul(challenges.beta, sigma2)); - e22 = Fr.add(e22, challenges.gamma); - - let e23 = Fr.add(c, Fr.mul(challenges.beta, sigma3)); - e23 = Fr.add(e23, challenges.gamma); - - let e2 = Fr.mul(Fr.mul(Fr.mul(e21, e22), e23), zW); - let e2z = Fr.mul(Fr.mul(Fr.mul(e21, e22), e23), zWp); - // const [e2, e2z] = MulZ.mul4(e21, e22, e23, zW, ap, bp, cp, zWp, i % 4, Fr); - - let t2 = Fr.sub(e1, e2); - let t2z = Fr.sub(e1z, e2z); - - buffers.T2.set(t2, i * sFr); - buffers.T2z.set(t2z, i * sFr); - - // Compute next omega - omega = Fr.mul(omega, Fr.w[zkey.power + 2]); - } - - // Compute the coefficients of the polynomial T2(X) from buffers.T2 - if (logger) logger.info("··· Computing T2 ifft"); - polynomials.T2 = await Polynomial.fromEvaluations(buffers.T2, curve, logger); - - // Divide the polynomial T2 by Z_H(X) - if (logger) logger.info("··· Computing T2 / ZH"); - polynomials.T2.divByZerofier(zkey.domainSize, Fr.one); - - // Compute the coefficients of the polynomial T2z(X) from buffers.T2z - if (logger) logger.info("··· Computing T2z ifft"); - polynomials.T2z = await Polynomial.fromEvaluations(buffers.T2z, curve, logger); - - // Add the polynomial T2z to T2 to get the final polynomial T2 - polynomials.T2.add(polynomials.T2z); - - // Check degree - if (polynomials.T2.degree() >= 3 * zkey.domainSize) { - throw new Error("T2 Polynomial is not well calculated"); - } - - delete buffers.T2; - delete buffers.T2z; - delete polynomials.T2z; - } - - async function computeC2() { - let C2 = new CPolynomial(3, curve, logger); - C2.addPolynomial(0, polynomials.Z); - C2.addPolynomial(1, polynomials.T1); - C2.addPolynomial(2, polynomials.T2); - - polynomials.C2 = C2.getPolynomial(); - - // Check degree - if (polynomials.C2.degree() >= 9 * zkey.domainSize) { - throw new Error("C2 Polynomial is not well calculated"); - } - } - } - - async function round3() { - if (logger) logger.info("> Computing challenge xi"); - // STEP 3.1 - Compute evaluation challenge xi ∈ S - const transcript = new Keccak256Transcript(curve); - transcript.addScalar(challenges.gamma); - transcript.addPolCommitment(proof.getPolynomial("C2")); - - // Obtain a xi_seeder from the transcript - // To force h1^4 = xi, h2^3 = xi and h_3^2 = xiω - // we compute xi = xi_seeder^12, h1 = xi_seeder^3, h2 = xi_seeder^4 and h3 = xi_seeder^6 - challenges.xiSeed = transcript.getChallenge(); - const xiSeed2 = Fr.square(challenges.xiSeed); - - // Compute omega8, omega4 and omega3 - roots.w8 = []; - roots.w8[0] = Fr.one; - for (let i = 1; i < 8; i++) { - roots.w8[i] = Fr.mul(roots.w8[i - 1], zkey.w8); - } - - roots.w4 = []; - roots.w4[0] = Fr.one; - for (let i = 1; i < 4; i++) { - roots.w4[i] = Fr.mul(roots.w4[i - 1], zkey.w4); - } - - roots.w3 = []; - roots.w3[0] = Fr.one; - roots.w3[1] = zkey.w3; - roots.w3[2] = Fr.square(zkey.w3); - - // Compute h0 = xiSeeder^3 - roots.S0 = {}; - roots.S0.h0w8 = []; - roots.S0.h0w8[0] = Fr.mul(xiSeed2, challenges.xiSeed); - for (let i = 1; i < 8; i++) { - roots.S0.h0w8[i] = Fr.mul(roots.S0.h0w8[0], roots.w8[i]); - } - - // Compute h1 = xi_seeder^6 - roots.S1 = {}; - roots.S1.h1w4 = []; - roots.S1.h1w4[0] = Fr.square(roots.S0.h0w8[0]); - for (let i = 1; i < 4; i++) { - roots.S1.h1w4[i] = Fr.mul(roots.S1.h1w4[0], roots.w4[i]); - } - - // Compute h2 = xi_seeder^8 - roots.S2 = {}; - roots.S2.h2w3 = []; - roots.S2.h2w3[0] = Fr.mul(roots.S1.h1w4[0], xiSeed2); - roots.S2.h2w3[1] = Fr.mul(roots.S2.h2w3[0], roots.w3[1]); - roots.S2.h2w3[2] = Fr.mul(roots.S2.h2w3[0], roots.w3[2]); - - roots.S2.h3w3 = []; - // Multiply h3 by third-root-omega to obtain h_3^3 = xiω - // So, h3 = xi_seeder^8 ω^{1/3} - roots.S2.h3w3[0] = Fr.mul(roots.S2.h2w3[0], zkey.wr); - roots.S2.h3w3[1] = Fr.mul(roots.S2.h3w3[0], roots.w3[1]); - roots.S2.h3w3[2] = Fr.mul(roots.S2.h3w3[0], roots.w3[2]); - - // Compute xi = xi_seeder^24 - challenges.xi = Fr.mul(Fr.square(roots.S2.h2w3[0]), roots.S2.h2w3[0]); - - if (logger) logger.info("··· challenges.xi: " + Fr.toString(challenges.xi)); - - // Reserve memory for Q's polynomials - polynomials.QL = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.QR = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.QM = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.QO = new Polynomial(new BigBuffer(sDomain), curve, logger); - polynomials.QC = new Polynomial(new BigBuffer(sDomain), curve, logger); - - // Read Q's evaluations from zkey file - await fdZKey.readToBuffer(polynomials.QL.coef, 0, sDomain, zkeySections[ZKEY_FF_QL_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QR.coef, 0, sDomain, zkeySections[ZKEY_FF_QR_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QM.coef, 0, sDomain, zkeySections[ZKEY_FF_QM_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QO.coef, 0, sDomain, zkeySections[ZKEY_FF_QO_SECTION][0].p); - await fdZKey.readToBuffer(polynomials.QC.coef, 0, sDomain, zkeySections[ZKEY_FF_QC_SECTION][0].p); - - // STEP 3.2 - Compute opening evaluations and add them to the proof (third output of the prover) - if (logger) logger.info("··· Computing evaluations"); - proof.addEvaluation("ql", polynomials.QL.evaluate(challenges.xi)); - proof.addEvaluation("qr", polynomials.QR.evaluate(challenges.xi)); - proof.addEvaluation("qm", polynomials.QM.evaluate(challenges.xi)); - proof.addEvaluation("qo", polynomials.QO.evaluate(challenges.xi)); - proof.addEvaluation("qc", polynomials.QC.evaluate(challenges.xi)); - proof.addEvaluation("s1", polynomials.Sigma1.evaluate(challenges.xi)); - proof.addEvaluation("s2", polynomials.Sigma2.evaluate(challenges.xi)); - proof.addEvaluation("s3", polynomials.Sigma3.evaluate(challenges.xi)); - proof.addEvaluation("a", polynomials.A.evaluate(challenges.xi)); - proof.addEvaluation("b", polynomials.B.evaluate(challenges.xi)); - proof.addEvaluation("c", polynomials.C.evaluate(challenges.xi)); - proof.addEvaluation("z", polynomials.Z.evaluate(challenges.xi)); - - challenges.xiw = Fr.mul(challenges.xi, Fr.w[zkey.power]); - proof.addEvaluation("zw", polynomials.Z.evaluate(challenges.xiw)); - proof.addEvaluation("t1w", polynomials.T1.evaluate(challenges.xiw)); - proof.addEvaluation("t2w", polynomials.T2.evaluate(challenges.xiw)); - } - - async function round4() { - if (logger) logger.info("> Computing challenge alpha"); - // STEP 4.1 - Compute challenge alpha ∈ F - const transcript = new Keccak256Transcript(curve); - transcript.addScalar(challenges.xiSeed); - transcript.addScalar(proof.getEvaluation("ql")); - transcript.addScalar(proof.getEvaluation("qr")); - transcript.addScalar(proof.getEvaluation("qm")); - transcript.addScalar(proof.getEvaluation("qo")); - transcript.addScalar(proof.getEvaluation("qc")); - transcript.addScalar(proof.getEvaluation("s1")); - transcript.addScalar(proof.getEvaluation("s2")); - transcript.addScalar(proof.getEvaluation("s3")); - transcript.addScalar(proof.getEvaluation("a")); - transcript.addScalar(proof.getEvaluation("b")); - transcript.addScalar(proof.getEvaluation("c")); - transcript.addScalar(proof.getEvaluation("z")); - transcript.addScalar(proof.getEvaluation("zw")); - transcript.addScalar(proof.getEvaluation("t1w")); - transcript.addScalar(proof.getEvaluation("t2w")); - challenges.alpha = transcript.getChallenge(); - if (logger) logger.info("··· challenges.alpha: " + Fr.toString(challenges.alpha)); - - // STEP 4.2 - Compute F(X) - if (logger) logger.info("> Reading C0 polynomial"); - polynomials.C0 = new Polynomial(new BigBuffer(sDomain * 8), curve, logger); - await fdZKey.readToBuffer(polynomials.C0.coef, 0, sDomain * 8, zkeySections[ZKEY_FF_C0_SECTION][0].p); - - if (logger) logger.info("> Computing R0 polynomial"); - computeR0(); - if (logger) logger.info("> Computing R1 polynomial"); - computeR1(); - if (logger) logger.info("> Computing R2 polynomial"); - computeR2(); - - if (logger) logger.info("> Computing F polynomial"); - await computeF(); - - // The fourth output of the prover is ([W1]_1), where W1:=(f/Z_t)(x) - if (logger) logger.info("> Computing W1 multi exponentiation"); - let commitW1 = await polynomials.F.multiExponentiation(PTau, "W1"); - proof.addPolynomial("W1", commitW1); - - return 0; - - function computeR0() { - // COMPUTE R0 - // Compute the coefficients of R0(X) from 8 evaluations using lagrange interpolation. R0(X) ∈ F_{<8}[X] - // We decide to use Lagrange interpolations because the R0 degree is very small (deg(R0)===7), - // and we were not able to compute it using current ifft implementation because the omega are different - polynomials.R0 = Polynomial.lagrangePolynomialInterpolation( - [roots.S0.h0w8[0], roots.S0.h0w8[1], roots.S0.h0w8[2], roots.S0.h0w8[3], - roots.S0.h0w8[4], roots.S0.h0w8[5], roots.S0.h0w8[6], roots.S0.h0w8[7]], - [polynomials.C0.evaluate(roots.S0.h0w8[0]), polynomials.C0.evaluate(roots.S0.h0w8[1]), - polynomials.C0.evaluate(roots.S0.h0w8[2]), polynomials.C0.evaluate(roots.S0.h0w8[3]), - polynomials.C0.evaluate(roots.S0.h0w8[4]), polynomials.C0.evaluate(roots.S0.h0w8[5]), - polynomials.C0.evaluate(roots.S0.h0w8[6]), polynomials.C0.evaluate(roots.S0.h0w8[7])], curve); - - // Check the degree of r0(X) < 8 - if (polynomials.R0.degree() > 7) { - throw new Error("R0 Polynomial is not well calculated"); - } - } - - function computeR1() { - // COMPUTE R1 - // Compute the coefficients of R1(X) from 4 evaluations using lagrange interpolation. R1(X) ∈ F_{<4}[X] - // We decide to use Lagrange interpolations because the R1 degree is very small (deg(R1)===3), - // and we were not able to compute it using current ifft implementation because the omega are different - polynomials.R1 = Polynomial.lagrangePolynomialInterpolation( - [roots.S1.h1w4[0], roots.S1.h1w4[1], roots.S1.h1w4[2], roots.S1.h1w4[3]], - [polynomials.C1.evaluate(roots.S1.h1w4[0]), polynomials.C1.evaluate(roots.S1.h1w4[1]), - polynomials.C1.evaluate(roots.S1.h1w4[2]), polynomials.C1.evaluate(roots.S1.h1w4[3])], curve); - - // Check the degree of r1(X) < 4 - if (polynomials.R1.degree() > 3) { - throw new Error("R1 Polynomial is not well calculated"); - } - } - - function computeR2() { - // COMPUTE R2 - // Compute the coefficients of r2(X) from 6 evaluations using lagrange interpolation. r2(X) ∈ F_{<6}[X] - // We decide to use Lagrange interpolations because the R2.degree is very small (deg(R2)===5), - // and we were not able to compute it using current ifft implementation because the omega are different - polynomials.R2 = Polynomial.lagrangePolynomialInterpolation( - [roots.S2.h2w3[0], roots.S2.h2w3[1], roots.S2.h2w3[2], - roots.S2.h3w3[0], roots.S2.h3w3[1], roots.S2.h3w3[2]], - [polynomials.C2.evaluate(roots.S2.h2w3[0]), polynomials.C2.evaluate(roots.S2.h2w3[1]), - polynomials.C2.evaluate(roots.S2.h2w3[2]), polynomials.C2.evaluate(roots.S2.h3w3[0]), - polynomials.C2.evaluate(roots.S2.h3w3[1]), polynomials.C2.evaluate(roots.S2.h3w3[2])], curve); - - // Check the degree of r2(X) < 6 - if (polynomials.R2.degree() > 5) { - throw new Error("R2 Polynomial is not well calculated"); - } - } - - async function computeF() { - if (logger) logger.info("··· Computing F polynomial"); - - // COMPUTE F(X) - polynomials.F = Polynomial.fromPolynomial(polynomials.C0, curve, logger); - polynomials.F.sub(polynomials.R0); - polynomials.F.divByZerofier(8, challenges.xi); - - let f2 = Polynomial.fromPolynomial(polynomials.C1, curve, logger); - f2.sub(polynomials.R1); - f2.mulScalar(challenges.alpha); - f2.divByZerofier(4, challenges.xi); - - let f3 = Polynomial.fromPolynomial(polynomials.C2, curve, logger); - f3.sub(polynomials.R2); - f3.mulScalar(Fr.square(challenges.alpha)); - f3.divByZerofier(3, challenges.xi); - f3.divByZerofier(3, challenges.xiw); - - polynomials.F.add(f2); - polynomials.F.add(f3); - - if (polynomials.F.degree() >= 9 * zkey.domainSize - 6) { - throw new Error("F Polynomial is not well calculated"); - } - } - } - - async function round5() { - if (logger) logger.info("> Computing challenge y"); - - // STEP 5.1 - Compute random evaluation point y ∈ F - const transcript = new Keccak256Transcript(curve); - transcript.addScalar(challenges.alpha); - transcript.addPolCommitment(proof.getPolynomial("W1")); - - challenges.y = transcript.getChallenge(); - if (logger) logger.info("··· challenges.y: " + Fr.toString(challenges.y)); - - // STEP 5.2 - Compute L(X) - if (logger) logger.info("> Computing L polynomial"); - await computeL(); - - if (logger) logger.info("> Computing ZTS2 polynomial"); - await computeZTS2(); - - let ZTS2Y = polynomials.ZTS2.evaluate(challenges.y); - ZTS2Y = Fr.inv(ZTS2Y); - polynomials.L.mulScalar(ZTS2Y); - - const polDividend = Polynomial.fromCoefficientsArray([Fr.neg(challenges.y), Fr.one], curve); - if (logger) logger.info("> Computing W' = L / ZTS2 polynomial"); - const polRemainder = polynomials.L.divBy(polDividend); - - //Check polReminder degree is equal to zero - if (polRemainder.degree() > 0) { - throw new Error(`Degree of L(X)/(ZTS2(y)(X-y)) remainder is ${polRemainder.degree()} and should be 0`); - } - - if (polynomials.L.degree() >= 9 * zkey.domainSize - 1) { - throw new Error("Degree of L(X)/(ZTS2(y)(X-y)) is not correct"); - } - - // The fifth output of the prover is ([W2]_1), where W2:=(f/Z_t)(x) - if (logger) logger.info("> Computing W' multi exponentiation"); - let commitW2 = await polynomials.L.multiExponentiation(PTau, "W2"); - proof.addPolynomial("W2", commitW2); - - return 0; - - async function computeL() { - if (logger) logger.info("··· Computing L polynomial"); - - const evalR0Y = polynomials.R0.evaluate(challenges.y); - const evalR1Y = polynomials.R1.evaluate(challenges.y); - const evalR2Y = polynomials.R2.evaluate(challenges.y); - - let mulL0 = Fr.sub(challenges.y, roots.S0.h0w8[0]); - for (let i = 1; i < 8; i++) { - mulL0 = Fr.mul(mulL0, Fr.sub(challenges.y, roots.S0.h0w8[i])); - } - - let mulL1 = Fr.sub(challenges.y, roots.S1.h1w4[0]); - for (let i = 1; i < 4; i++) { - mulL1 = Fr.mul(mulL1, Fr.sub(challenges.y, roots.S1.h1w4[i])); - } - - let mulL2 = Fr.sub(challenges.y, roots.S2.h2w3[0]); - for (let i = 1; i < 3; i++) { - mulL2 = Fr.mul(mulL2, Fr.sub(challenges.y, roots.S2.h2w3[i])); - } - for (let i = 0; i < 3; i++) { - mulL2 = Fr.mul(mulL2, Fr.sub(challenges.y, roots.S2.h3w3[i])); - } - - let preL0 = Fr.mul(mulL1, mulL2); - let preL1 = Fr.mul(challenges.alpha, Fr.mul(mulL0, mulL2)); - let preL2 = Fr.mul(Fr.square(challenges.alpha), Fr.mul(mulL0, mulL1)); - - toInverse["denH1"] = mulL1; - toInverse["denH2"] = mulL2; - - // COMPUTE L(X) - polynomials.L = Polynomial.fromPolynomial(polynomials.C0, curve, logger); - polynomials.L.subScalar(evalR0Y); - polynomials.L.mulScalar(preL0); - - let l2 = Polynomial.fromPolynomial(polynomials.C1, curve, logger); - l2.subScalar(evalR1Y); - l2.mulScalar(preL1); - - let l3 = Polynomial.fromPolynomial(polynomials.C2, curve, logger); - l3.subScalar(evalR2Y); - l3.mulScalar(preL2); - - polynomials.L.add(l2); - polynomials.L.add(l3); - - if (logger) logger.info("> Computing ZT polynomial"); - await computeZT(); - - const evalZTY = polynomials.ZT.evaluate(challenges.y); - polynomials.F.mulScalar(evalZTY); - polynomials.L.sub(polynomials.F); - - // Check degree - if (polynomials.L.degree() >= 9 * zkey.domainSize) { - throw new Error("L Polynomial is not well calculated"); - } - - delete buffers.L; - } - - async function computeZT() { - polynomials.ZT = Polynomial.zerofierPolynomial( - [ - roots.S0.h0w8[0], roots.S0.h0w8[1], roots.S0.h0w8[2], roots.S0.h0w8[3], - roots.S0.h0w8[4], roots.S0.h0w8[5], roots.S0.h0w8[6], roots.S0.h0w8[7], - roots.S1.h1w4[0], roots.S1.h1w4[1], roots.S1.h1w4[2], roots.S1.h1w4[3], - roots.S2.h2w3[0], roots.S2.h2w3[1], roots.S2.h2w3[2], - roots.S2.h3w3[0], roots.S2.h3w3[1], roots.S2.h3w3[2]], curve); - } - - async function computeZTS2() { - polynomials.ZTS2 = Polynomial.zerofierPolynomial( - [roots.S1.h1w4[0], roots.S1.h1w4[1], roots.S1.h1w4[2], roots.S1.h1w4[3], - roots.S2.h2w3[0], roots.S2.h2w3[1], roots.S2.h2w3[2], - roots.S2.h3w3[0], roots.S2.h3w3[1], roots.S2.h3w3[2]], curve); - } - } - - function getMontgomeryBatchedInverse() { - // · denominator needed in step 8 and 9 of the verifier to multiply by 1/Z_H(xi) - let xiN = challenges.xi; - for (let i = 0; i < zkey.power; i++) { - xiN = Fr.square(xiN); - } - toInverse["zh"] = Fr.sub(xiN, Fr.one); - - // · denominator needed in step 10 and 11 of the verifier - // toInverse.denH1 & toInverse.denH2 -> Computed in round5, computeL() - - // · denominator needed in the verifier when computing L_i^{S0}(X), L_i^{S1}(X) and L_i^{S2}(X) - computeLiS0(toInverse, roots.S0.h0w8, challenges.y, curve); - - computeLiS1(toInverse, roots.S1.h1w4, challenges.y, curve); - - computeLiS2(toInverse, roots.S2.h2w3, roots.S2.h3w3, challenges.y, challenges.xi, challenges.xiw, curve); - - // · L_i i=1 to num public inputs, needed in step 6 and 7 of the verifier to compute L_1(xi) and PI(xi) - const size = Math.max(1, zkey.nPublic); - - let w = Fr.one; - for (let i = 0; i < size; i++) { - toInverse["Li_" + (i + 1)] = Fr.mul(Fr.e(zkey.domainSize), Fr.sub(challenges.xi, w)); - w = Fr.mul(w, Fr.w[zkey.power]); - } - - let mulAccumulator = Fr.one; - for (const element of Object.values(toInverse)) { - if(Array.isArray(element)) { - for (const subElement of element) { - mulAccumulator = Fr.mul(mulAccumulator, subElement); - } - } else { - mulAccumulator = Fr.mul(mulAccumulator, element); - } - } - return Fr.inv(mulAccumulator); - - - function computeLiS0(toInverse, roots, x, curve) { - const Fr = curve.Fr; - const len = roots.length; - - const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); - - const Li = []; - for (let i = 0; i < len; i++) { - const den2 = roots[((len - 1) * i) % len]; - const den3 = Fr.sub(x, roots[i]); - - toInverse[["LiS0_" + (i + 1)]] = Fr.mul(Fr.mul(den1, den2), den3); - } - - return Li; - } - - function computeLiS1(toInverse, roots, x, curve) { - const Fr = curve.Fr; - const len = roots.length; - - const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); - - const Li = []; - for (let i = 0; i < len; i++) { - const den2 = roots[((len - 1) * i) % len]; - const den3 = Fr.sub(x, roots[i]); - - toInverse[["LiS1_" + (i + 1)]] = Fr.mul(Fr.mul(den1, den2), den3); - - } - - return Li; - } - - function computeLiS2(toInverse, S2, S2p, value, xi, xiw, curve) { - const Fr = curve.Fr; - - const Li = []; - - const _3h2 = Fr.mul(Fr.e(3), S2[0]); - const xisubxiw = Fr.sub(xi, xiw); - let den1 = Fr.mul(_3h2, xisubxiw); - for (let i = 0; i < 3; i++) { - const den2 = S2[2 * i % 3]; - const den3 = Fr.sub(value, S2[i]); - - toInverse[["LiS2_" + (i + 1)]] = Fr.mul(den1,Fr.mul(den2, den3)); - - } - - const _3h3 = Fr.mul(Fr.e(3), S2p[0]); - const xiwsubxi = Fr.sub(xiw, xi); - den1 = Fr.mul(_3h3, xiwsubxi); - for (let i = 0; i < 3; i++) { - const den2 = S2p[2 * i % 3]; - const den3 = Fr.sub(value, S2p[i]); - - toInverse[["LiS2_" + (i + 1 + 3)]] = Fr.mul(den1,Fr.mul(den2, den3)); - } - - return Li; - } - } - } - - /* - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . - */ - const {unstringifyBigInts: unstringifyBigInts$2} = utils$6; - - async function fflonkFullProve(_input, wasmFilename, zkeyFilename, logger, wtnsCalcOptions, proverOptions) { - const input = unstringifyBigInts$2(_input); - - const wtns= {type: "mem"}; - - // Compute the witness - await wtnsCalculate(input, wasmFilename, wtns, wtnsCalcOptions); - - // Compute the proof - return await fflonkProve(zkeyFilename, wtns, logger, proverOptions); - } - - /* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . - */ - - const { unstringifyBigInts: unstringifyBigInts$1 } = utils$6; - - async function fflonkVerify(_vk_verifier, _publicSignals, _proof, logger) { - if (logger) logger.info("FFLONK VERIFIER STARTED"); - - _vk_verifier = unstringifyBigInts$1(_vk_verifier); - _proof = unstringifyBigInts$1(_proof); - - const curve = await getCurveFromName(_vk_verifier.curve); - - const vk = fromObjectVk(curve, _vk_verifier); - - // TODO ??? Compute wr^3 and check if it matches with w - - const proof = new Proof(curve, logger); - proof.fromObjectProof(_proof); - - const publicSignals = unstringifyBigInts$1(_publicSignals); - - if (publicSignals.length !== vk.nPublic) { - logger.error("Number of public signals does not match with vk"); - return false; - } - - const Fr = curve.Fr; - - if (logger) { - logger.info("----------------------------"); - logger.info(" FFLONK VERIFY SETTINGS"); - logger.info(` Curve: ${curve.name}`); - logger.info(` Circuit power: ${vk.power}`); - logger.info(` Domain size: ${2 ** vk.power}`); - logger.info(` Public vars: ${vk.nPublic}`); - logger.info("----------------------------"); - } - - // STEP 1 - Validate that all polynomial commitments ∈ G_1 - if (logger) logger.info("> Checking commitments belong to G1"); - if (!commitmentsBelongToG1(curve, proof, vk)) { - if (logger) logger.error("Proof commitments are not valid"); - return false; - } - - // STEP 2 - Validate that all evaluations ∈ F - if (logger) logger.info("> Checking evaluations belong to F"); - if (!evaluationsAreValid(curve, proof)) { - if (logger) logger.error("Proof evaluations are not valid."); - return false; - } - - // STEP 3 - Validate that w_i ∈ F for i ∈ [l] - if (logger) logger.info("> Checking public inputs belong to F"); - if (!publicInputsAreValid(curve, publicSignals)) { - if (logger) logger.error("Public inputs are not valid."); - return false; - } - - // STEP 4 - Compute the challenges: beta, gamma, xi, alpha and y ∈ F - // as in prover description, from the common preprocessed inputs, public inputs and elements of π_SNARK - if (logger) logger.info("> Computing challenges"); - const { challenges, roots } = computeChallenges(curve, proof, vk, publicSignals, logger); - - // STEP 5 - Compute the zero polynomial evaluation Z_H(xi) = xi^n - 1 - if (logger) logger.info("> Computing Zero polynomial evaluation Z_H(xi)"); - challenges.zh = Fr.sub(challenges.xiN, Fr.one); - challenges.invzh = Fr.inv(challenges.zh); - - // STEP 6 - Compute the lagrange polynomial evaluation L_1(xi) - if (logger) logger.info("> Computing Lagrange evaluations"); - const lagrangeEvals = await computeLagrangeEvaluations(curve, challenges, vk); - - // STEP 7 - Compute public input evaluation PI(xi) - if (logger) logger.info("> Computing polynomial identities PI(X)"); - const pi = calculatePI(curve, publicSignals, lagrangeEvals); - - // STEP 8 - Compute polynomial r0 ∈ F_{<4}[X] - if (logger) logger.info("> Computing r0(y)"); - const r0 = computeR0(proof, challenges, roots, curve, logger); - - // STEP 9 - Compute polynomial r1 ∈ F_{<4}[X] - if (logger) logger.info("> Computing r1(y)"); - const r1 = computeR1(proof, challenges, roots, pi, curve, logger); - - // STEP 9 - Compute polynomial r2 ∈ F_{<6}[X] - if (logger) logger.info("> Computing r2(y)"); - const r2 = computeR2(proof, challenges, roots, lagrangeEvals[1], vk, curve, logger); - - if (logger) logger.info("> Computing F"); - const F = computeF(curve, proof, vk, challenges, roots); - - if (logger) logger.info("> Computing E"); - const E = computeE(curve, proof, challenges, vk, r0, r1, r2); - - if (logger) logger.info("> Computing J"); - const J = computeJ(curve, proof, challenges); - - if (logger) logger.info("> Validate all evaluations with a pairing"); - const res = await isValidPairing(curve, proof, challenges, vk, F, E, J); - - if (logger) { - if (res) { - logger.info("PROOF VERIFIED SUCCESSFULLY"); - } else { - logger.warn("Invalid Proof"); - } - } - - if (logger) logger.info("FFLONK VERIFIER FINISHED"); - - return res; - - } - - function fromObjectVk(curve, vk) { - const res = vk; - res.k1 = curve.Fr.fromObject(vk.k1); - res.k2 = curve.Fr.fromObject(vk.k2); - res.w = curve.Fr.fromObject(vk.w); - // res.wW = curve.Fr.fromObject(vk.wW); - res.w3 = curve.Fr.fromObject(vk.w3); - res.w4 = curve.Fr.fromObject(vk.w4); - res.w8 = curve.Fr.fromObject(vk.w8); - res.wr = curve.Fr.fromObject(vk.wr); - res.X_2 = curve.G2.fromObject(vk.X_2); - res.C0 = curve.G1.fromObject(vk.C0); - return res; - } - - function commitmentsBelongToG1(curve, proof, vk) { - const G1 = curve.G1; - return G1.isValid(proof.polynomials.C1) - && G1.isValid(proof.polynomials.C2) - && G1.isValid(proof.polynomials.W1) - && G1.isValid(proof.polynomials.W2) - && G1.isValid(vk.C0); - } - - function checkValueBelongToField(curve, value) { - return Scalar.geq(value, 0) && Scalar.lt(value, curve.r); - } - - function checkEvaluationIsValid(curve, evaluation) { - return checkValueBelongToField(curve, Scalar.fromRprLE(evaluation)); - } - - function evaluationsAreValid(curve, proof) { - return checkEvaluationIsValid(curve, proof.evaluations.ql) - && checkEvaluationIsValid(curve, proof.evaluations.qr) - && checkEvaluationIsValid(curve, proof.evaluations.qm) - && checkEvaluationIsValid(curve, proof.evaluations.qo) - && checkEvaluationIsValid(curve, proof.evaluations.qc) - && checkEvaluationIsValid(curve, proof.evaluations.s1) - && checkEvaluationIsValid(curve, proof.evaluations.s2) - && checkEvaluationIsValid(curve, proof.evaluations.s3) - && checkEvaluationIsValid(curve, proof.evaluations.a) - && checkEvaluationIsValid(curve, proof.evaluations.b) - && checkEvaluationIsValid(curve, proof.evaluations.c) - && checkEvaluationIsValid(curve, proof.evaluations.z) - && checkEvaluationIsValid(curve, proof.evaluations.zw) - && checkEvaluationIsValid(curve, proof.evaluations.t1w) - && checkEvaluationIsValid(curve, proof.evaluations.t2w); - } - - function publicInputsAreValid(curve, publicInputs) { - for(let i = 0; i < publicInputs.length; i++) { - if(!checkValueBelongToField(curve, publicInputs[i])) { - return false; - } - } - return true; - } - - function computeChallenges(curve, proof, vk, publicSignals, logger) { - const Fr = curve.Fr; - - const challenges = {}; - const roots = {}; - const transcript = new Keccak256Transcript(curve); - - // Add C0 to the transcript - transcript.addPolCommitment(vk.C0); - - for (let i = 0; i < publicSignals.length; i++) { - transcript.addScalar(Fr.e(publicSignals[i])); - } - - transcript.addPolCommitment(proof.polynomials.C1); - challenges.beta = transcript.getChallenge(); - transcript.reset(); - - transcript.addScalar(challenges.beta); - challenges.gamma = transcript.getChallenge(); - - transcript.reset(); - transcript.addScalar(challenges.gamma); - transcript.addPolCommitment(proof.polynomials.C2); - const xiSeed = transcript.getChallenge(); - const xiSeed2 = Fr.square(xiSeed); - - let w8 = []; - w8[1] = vk.w8; - w8[2] = Fr.square(vk.w8); - w8[3] = Fr.mul(w8[2], vk.w8); - w8[4] = Fr.mul(w8[3], vk.w8); - w8[5] = Fr.mul(w8[4], vk.w8); - w8[6] = Fr.mul(w8[5], vk.w8); - w8[7] = Fr.mul(w8[6], vk.w8); - let w4 = []; - w4[1] = vk.w4; - w4[2] = Fr.square(vk.w4); - w4[3] = Fr.mul(w4[2], vk.w4); - let w3 = []; - w3[1] = vk.w3; - w3[2] = Fr.square(vk.w3); - - // const w4_2 = Fr.square(vk.w4); - // const w4_3 = Fr.mul(w4_2, vk.w4); - // const w3_2 = Fr.square(vk.w3); - - // Compute h0 = xiSeeder^3 - roots.S0 = {}; - roots.S0.h0w8 = []; - roots.S0.h0w8[0] = Fr.mul(xiSeed2, xiSeed); - for (let i = 1; i < 8; i++) { - roots.S0.h0w8[i] = Fr.mul(roots.S0.h0w8[0], w8[i]); - } - - // Compute h1 = xi_seeder^6 - roots.S1 = {}; - roots.S1.h1w4 = []; - roots.S1.h1w4[0] = Fr.square(roots.S0.h0w8[0]); - for (let i = 1; i < 4; i++) { - roots.S1.h1w4[i] = Fr.mul(roots.S1.h1w4[0], w4[i]); - } - - // Compute h2 = xi_seeder^8 - roots.S2 = {}; - roots.S2.h2w3 = []; - roots.S2.h2w3[0] = Fr.mul(roots.S1.h1w4[0], xiSeed2); - roots.S2.h2w3[1] = Fr.mul(roots.S2.h2w3[0], w3[1]); - roots.S2.h2w3[2] = Fr.mul(roots.S2.h2w3[0], w3[2]); - - roots.S2.h3w3 = []; - // Multiply h3 by third-root-omega to obtain h_3^3 = xiω - // So, h3 = xi_seeder^8 ω^{1/3} - roots.S2.h3w3[0] = Fr.mul(roots.S2.h2w3[0], vk.wr); - roots.S2.h3w3[1] = Fr.mul(roots.S2.h3w3[0], w3[1]); - roots.S2.h3w3[2] = Fr.mul(roots.S2.h3w3[0], w3[2]); - - // Compute xi = xi_seeder^12 - challenges.xi = Fr.mul(Fr.square(roots.S2.h2w3[0]), roots.S2.h2w3[0]); - challenges.xiw = Fr.mul(challenges.xi, Fr.w[vk.power]); - - challenges.xiN = challenges.xi; - vk.domainSize = 1; - for (let i = 0; i < vk.power; i++) { - challenges.xiN = Fr.square(challenges.xiN); - vk.domainSize *= 2; - } - - transcript.reset(); - transcript.addScalar(xiSeed); - transcript.addScalar(proof.evaluations.ql); - transcript.addScalar(proof.evaluations.qr); - transcript.addScalar(proof.evaluations.qm); - transcript.addScalar(proof.evaluations.qo); - transcript.addScalar(proof.evaluations.qc); - transcript.addScalar(proof.evaluations.s1); - transcript.addScalar(proof.evaluations.s2); - transcript.addScalar(proof.evaluations.s3); - transcript.addScalar(proof.evaluations.a); - transcript.addScalar(proof.evaluations.b); - transcript.addScalar(proof.evaluations.c); - transcript.addScalar(proof.evaluations.z); - transcript.addScalar(proof.evaluations.zw); - transcript.addScalar(proof.evaluations.t1w); - transcript.addScalar(proof.evaluations.t2w); - challenges.alpha = transcript.getChallenge(); - - transcript.reset(); - transcript.addScalar(challenges.alpha); - transcript.addPolCommitment(proof.polynomials.W1); - challenges.y = transcript.getChallenge(); - - if (logger) { - logger.info("··· challenges.beta: " + Fr.toString(challenges.beta)); - logger.info("··· challenges.gamma: " + Fr.toString(challenges.gamma)); - logger.info("··· challenges.xi: " + Fr.toString(challenges.xi)); - logger.info("··· challenges.alpha: " + Fr.toString(challenges.alpha)); - logger.info("··· challenges.y: " + Fr.toString(challenges.y)); - } - - return { challenges: challenges, roots: roots }; - } - - async function computeLagrangeEvaluations(curve, challenges, vk) { - const Fr = curve.Fr; - - const size = Math.max(1, vk.nPublic); - const numArr = new BigBuffer(size * Fr.n8); - let denArr = new BigBuffer(size * Fr.n8); - - let w = Fr.one; - for (let i = 0; i < size; i++) { - const i_sFr = i * Fr.n8; - numArr.set(Fr.mul(w, challenges.zh), i_sFr); - denArr.set(Fr.mul(Fr.e(vk.domainSize), Fr.sub(challenges.xi, w)), i_sFr); - w = Fr.mul(w, vk.w); - } - - denArr = await Fr.batchInverse(denArr); - - let L = []; - for (let i = 0; i < size; i++) { - const i_sFr = i * Fr.n8; - L[i + 1] = Fr.mul(numArr.slice(i_sFr, i_sFr + Fr.n8), denArr.slice(i_sFr, i_sFr + Fr.n8)); - } - return L; - } - - function calculatePI(curve, publicSignals, lagrangeEvals) { - const Fr = curve.Fr; - - let pi = Fr.zero; - for (let i = 0; i < publicSignals.length; i++) { - const w = Fr.e(publicSignals[i]); - pi = Fr.sub(pi, Fr.mul(w, lagrangeEvals[i + 1])); - } - return pi; - } - - function computeR0(proof, challenges, roots, curve, logger) { - const Fr = curve.Fr; - - const Li = computeLagrangeLiSi(roots.S0.h0w8, challenges.y, challenges.xi, curve); - - // r0(y) = ∑_1^8 C_0(h_0 ω_8^{i-1}) L_i(y). To this end we need to compute - - // Compute the 8 C0 values - if (logger) logger.info("··· Computing r0(y)"); - - let res = Fr.zero; - for (let i = 0; i < 8; i++) { - let coefValues = []; - coefValues[1] = roots.S0.h0w8[i]; - for (let j = 2; j < 8; j++) { - coefValues[j] = Fr.mul(coefValues[j - 1], roots.S0.h0w8[i]); - } - - let c0 = Fr.add(proof.evaluations.ql, Fr.mul(proof.evaluations.qr, coefValues[1])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.qo, coefValues[2])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.qm, coefValues[3])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.qc, coefValues[4])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.s1, coefValues[5])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.s2, coefValues[6])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.s3, coefValues[7])); - - res = Fr.add(res, Fr.mul(c0, Li[i])); - } - - return res; - } - - function computeR1(proof, challenges, roots, pi, curve, logger) { - const Fr = curve.Fr; - - const Li = computeLagrangeLiSi(roots.S1.h1w4, challenges.y, challenges.xi, curve); - - // r1(y) = ∑_1^4 C_1(h_1 ω_4^{i-1}) L_i(y). To this end we need to compute - // Z1 = {C1(h_1}, C1(h_1 ω_4), C1(h_1 ω_4^2), C1(h_1 ω_4^3)} - // where C_1(h_1 ω_4^{i-1}) = eval.a + h_1 ω_4^i eval.b + (h_1 ω_4^i)^2 eval.c + (h_1 ω_4^i)^3 T0(xi), - // where T0(xi) = [ qL·a + qR·b + qM·a·b + qO·c + qC + PI(xi) ] / Z_H(xi) - - // Compute T0(xi) - if (logger) logger.info("··· Computing T0(xi)"); - let t0 = Fr.mul(proof.evaluations.ql, proof.evaluations.a); - t0 = Fr.add(t0, Fr.mul(proof.evaluations.qr, proof.evaluations.b)); - t0 = Fr.add(t0, Fr.mul(proof.evaluations.qm, Fr.mul(proof.evaluations.a, proof.evaluations.b))); - t0 = Fr.add(t0, Fr.mul(proof.evaluations.qo, proof.evaluations.c)); - t0 = Fr.add(t0, proof.evaluations.qc); - t0 = Fr.add(t0, pi); - t0 = Fr.mul(t0, challenges.invzh); - - // Compute the 4 C1 values - if (logger) logger.info("··· Computing C1(h_1ω_4^i) values"); - - let res = Fr.zero; - for (let i = 0; i < 4; i++) { - let c1 = proof.evaluations.a; - c1 = Fr.add(c1, Fr.mul(roots.S1.h1w4[i], proof.evaluations.b)); - const h1w4Squared = Fr.square(roots.S1.h1w4[i]); - c1 = Fr.add(c1, Fr.mul(h1w4Squared, proof.evaluations.c)); - c1 = Fr.add(c1, Fr.mul(Fr.mul(h1w4Squared, roots.S1.h1w4[i]), t0)); - - res = Fr.add(res, Fr.mul(c1, Li[i])); - } - - return res; - } - - function computeR2(proof, challenges, roots, lagrange1, vk, curve, logger) { - const Fr = curve.Fr; - - const LiS2 = computeLagrangeLiS2([roots.S2.h2w3, roots.S2.h3w3], challenges.y, challenges.xi, challenges.xiw, curve); - - // r2(y) = ∑_1^3 C_2(h_2 ω_3^{i-1}) L_i(y) + ∑_1^3 C_2(h_3 ω_3^{i-1}) L_{i+3}(y). To this end we need to compute - // Z2 = {[C2(h_2}, C2(h_2 ω_3), C2(h_2 ω_3^2)], [C2(h_3}, C2(h_3 ω_3), C2(h_3 ω_3^2)]} - // where C_2(h_2 ω_3^{i-1}) = eval.z + h_2 ω_2^i T1(xi) + (h_2 ω_3^i)^2 T2(xi), - // where C_2(h_3 ω_3^{i-1}) = eval.z + h_3 ω_2^i T1(xi) + (h_3 ω_3^i)^2 T2(xi), - // where T1(xi) = [ L_1(xi)(z-1)] / Z_H(xi) - // and T2(xi) = [ (a + beta·xi + gamma)(b + beta·xi·k1 + gamma)(c + beta·xi·k2 + gamma)z - // - (a + beta·sigma1 + gamma)(b + beta·sigma2 + gamma)(c + beta·sigma3 + gamma)zω ] / Z_H(xi) - - // Compute T1(xi) - if (logger) logger.info("··· Computing T1(xi)"); - let t1 = Fr.sub(proof.evaluations.z, Fr.one); - t1 = Fr.mul(t1, lagrange1); - t1 = Fr.mul(t1, challenges.invzh); - - // Compute T2(xi) - if (logger) logger.info("··· Computing T2(xi)"); - const betaxi = Fr.mul(challenges.beta, challenges.xi); - const t211 = Fr.add(proof.evaluations.a, Fr.add(betaxi, challenges.gamma)); - const t212 = Fr.add(proof.evaluations.b, Fr.add(Fr.mul(betaxi, vk.k1), challenges.gamma)); - const t213 = Fr.add(proof.evaluations.c, Fr.add(Fr.mul(betaxi, vk.k2), challenges.gamma)); - const t21 = Fr.mul(t211, Fr.mul(t212, Fr.mul(t213, proof.evaluations.z))); - - const t221 = Fr.add(proof.evaluations.a, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s1), challenges.gamma)); - const t222 = Fr.add(proof.evaluations.b, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s2), challenges.gamma)); - const t223 = Fr.add(proof.evaluations.c, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s3), challenges.gamma)); - const t22 = Fr.mul(t221, Fr.mul(t222, Fr.mul(t223, proof.evaluations.zw))); - - let t2 = Fr.sub(t21, t22); - t2 = Fr.mul(t2, challenges.invzh); - - // Compute the 6 C2 values - if (logger) logger.info("··· Computing C2(h_2ω_3^i) values"); - let res = Fr.zero; - for (let i = 0; i < 3; i++) { - let c2 = Fr.add(proof.evaluations.z, Fr.mul(roots.S2.h2w3[i], t1)); - c2 = Fr.add(c2, Fr.mul(Fr.square(roots.S2.h2w3[i]), t2)); - - res = Fr.add(res, Fr.mul(c2, LiS2[i])); - } - - if (logger) logger.info("··· Computing C2(h_3ω_3^i) values"); - for (let i = 0; i < 3; i++) { - let c2 = Fr.add(proof.evaluations.zw, Fr.mul(roots.S2.h3w3[i], proof.evaluations.t1w)); - c2 = Fr.add(c2, Fr.mul(Fr.square(roots.S2.h3w3[i]), proof.evaluations.t2w)); - - res = Fr.add(res, Fr.mul(c2, LiS2[i + 3])); - } - - return res; - } - - function computeF(curve, proof, vk, challenges, roots) { - const G1 = curve.G1; - const Fr = curve.Fr; - - let mulH0 = Fr.sub(challenges.y, roots.S0.h0w8[0]); - for (let i = 1; i < 8; i++) { - mulH0 = Fr.mul(mulH0, Fr.sub(challenges.y, roots.S0.h0w8[i])); - } - - challenges.temp = mulH0; - - let mulH1 = Fr.sub(challenges.y, roots.S1.h1w4[0]); - for (let i = 1; i < 4; i++) { - mulH1 = Fr.mul(mulH1, Fr.sub(challenges.y, roots.S1.h1w4[i])); - } - - let mulH2 = Fr.sub(challenges.y, roots.S2.h2w3[0]); - for (let i = 1; i < 3; i++) { - mulH2 = Fr.mul(mulH2, Fr.sub(challenges.y, roots.S2.h2w3[i])); - } - for (let i = 0; i < 3; i++) { - mulH2 = Fr.mul(mulH2, Fr.sub(challenges.y, roots.S2.h3w3[i])); - } - - challenges.quotient1 = Fr.mul(challenges.alpha, Fr.div(mulH0, mulH1)); - challenges.quotient2 = Fr.mul(Fr.square(challenges.alpha), Fr.div(mulH0, mulH2)); - - let F2 = G1.timesFr(proof.polynomials.C1, challenges.quotient1); - let F3 = G1.timesFr(proof.polynomials.C2, challenges.quotient2); - - return G1.add(vk.C0, G1.add(F2, F3)); - } - - function computeE(curve, proof, challenges, vk, r0, r1, r2) { - const G1 = curve.G1; - const Fr = curve.Fr; - - let E2 = Fr.mul(r1, challenges.quotient1); - let E3 = Fr.mul(r2, challenges.quotient2); - - return G1.timesFr(G1.one, Fr.add(r0, Fr.add(E2, E3))); - } - - function computeJ(curve, proof, challenges) { - const G1 = curve.G1; - - return G1.timesFr(proof.polynomials.W1, challenges.temp); - } - - async function isValidPairing(curve, proof, challenges, vk, F, E, J) { - const G1 = curve.G1; - - let A1 = G1.timesFr(proof.polynomials.W2, challenges.y); - A1 = G1.add(G1.sub(G1.sub(F, E), J), A1); - const A2 = curve.G2.one; - - const B1 = proof.polynomials.W2; - const B2 = vk.X_2; - - return await curve.pairingEq(G1.neg(A1), A2, B1, B2); - } - - - function computeLagrangeLiSi(roots, x, xi, curve) { - const Fr = curve.Fr; - const len = roots.length; - - const num = Fr.sub(Fr.exp(x, len), xi); - const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); - - const Li = []; - for (let i = 0; i < len; i++) { - const den2 = roots[((len - 1) * i) % len]; - const den3 = Fr.sub(x, roots[i]); - - Li[i] = Fr.div(num, Fr.mul(Fr.mul(den1, den2), den3)); - } - - return Li; - } - - function computeLagrangeLiS2(roots, value, xi0, xi1, curve) { - const Fr = curve.Fr; - - const Li = []; - - const len = roots[0].length; - const n = len * roots.length; - - const num1 = Fr.exp(value, n); - const num2 = Fr.mul(Fr.add(xi0, xi1), Fr.exp(value, len)); - const num3 = Fr.mul(xi0, xi1); - const num = Fr.add(Fr.sub(num1, num2), num3); - - let den1 = Fr.mul(Fr.mul(Fr.e(len), roots[0][0]), Fr.sub(xi0, xi1)); - for (let i = 0; i < len; i++) { - const den2 = roots[0][(len - 1) * i % len]; - const den3 = Fr.sub(value, roots[0][i]); - - const den = Fr.mul(den1,Fr.mul(den2, den3)); - - Li[i] = Fr.div(num, den); - } - - den1 = Fr.mul(Fr.mul(Fr.e(len), roots[1][0]), Fr.sub(xi1, xi0)); - for (let i = 0; i < len; i++) { - const den2 = roots[1][(len - 1) * i % len]; - const den3 = Fr.sub(value, roots[1][i]); - - const den = Fr.mul(den1,Fr.mul(den2, den3)); - - Li[i + len] = Fr.div(num, den); - } - - return Li; - } - - /* - Copyright 2021 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . - */ - - const {unstringifyBigInts} = utils$6; - - function p256(n) { - let nstr = n.toString(16); - while (nstr.length < 64) nstr = "0" + nstr; - nstr = `0x${nstr}`; - return nstr; - } - - async function fflonkExportCallData(_pub, _proof) { - const proof = unstringifyBigInts(_proof); - const pub = unstringifyBigInts(_pub); - - const curve = await getCurveFromName(proof.curve); - curve.G1; - curve.Fr; - - let inputs = ""; - for (let i = 0; i < pub.length; i++) { - if (inputs !== "") inputs = inputs + ","; - inputs = inputs + p256(pub[i]); - } - - return `[${p256(proof.polynomials.C1[0])}, ${p256(proof.polynomials.C1[1])},` + - `${p256(proof.polynomials.C2[0])},${p256(proof.polynomials.C2[1])},` + - `${p256(proof.polynomials.W1[0])},${p256(proof.polynomials.W1[1])},` + - `${p256(proof.polynomials.W2[0])},${p256(proof.polynomials.W2[1])},` + - `${p256(proof.evaluations.ql)},${p256(proof.evaluations.qr)},${p256(proof.evaluations.qm)},` + - `${p256(proof.evaluations.qo)},${p256(proof.evaluations.qc)},${p256(proof.evaluations.s1)},` + - `${p256(proof.evaluations.s2)},${p256(proof.evaluations.s3)},${p256(proof.evaluations.a)},` + - `${p256(proof.evaluations.b)},${p256(proof.evaluations.c)},${p256(proof.evaluations.z)},` + - `${p256(proof.evaluations.zw)},${p256(proof.evaluations.t1w)},${p256(proof.evaluations.t2w)},` + - `${p256(proof.evaluations.inv)}],` + - `[${inputs}]`; - } - - /* - Copyright 2022 iden3 association. - - This file is part of snarkjs. - - snarkjs is a free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as published by the - Free Software Foundation, either version 3 of the License, or (at your option) - any later version. - - snarkjs is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - snarkjs. If not, see . - */ - - var fflonk = /*#__PURE__*/Object.freeze({ - __proto__: null, - setup: fflonkSetup, - prove: fflonkProve, - fullProve: fflonkFullProve, - verify: fflonkVerify, - exportSolidityVerifier: fflonkExportSolidityVerifier, - exportSolidityCallData: fflonkExportCallData - }); - - var _virtual_ejs = {}; - - var _virtual_ejs$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - 'default': _virtual_ejs - }); - - exports.curves = curves; - exports.fflonk = fflonk; - exports.groth16 = groth16; - exports.plonk = plonk; - exports.powersOfTau = powersoftau; - exports.r1cs = r1cs; - exports.wtns = wtns; - exports.zKey = zkey; - - Object.defineProperty(exports, '__esModule', { value: true }); - - return exports; - -})({}, node_fs); -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic25hcmtqcy5qcyIsInNvdXJjZXMiOlsiLi4vLi4vZmZqYXZhc2NyaXB0L2J1aWxkL2Jyb3dzZXIuZXNtLmpzIiwiLi4vLi4vZmFzdGZpbGUvc3JjL29zZmlsZS5qcyIsIi4uLy4uL2Zhc3RmaWxlL3NyYy9tZW1maWxlLmpzIiwiLi4vLi4vZmFzdGZpbGUvc3JjL2JpZ21lbWZpbGUuanMiLCIuLi8uLi9mYXN0ZmlsZS9zcmMvZmFzdGZpbGUuanMiLCIuLi8uLi9iaW5maWxldXRpbHMvc3JjL2JpbmZpbGV1dGlscy5qcyIsIi4uL3NyYy9jdXJ2ZXMuanMiLCIuLi9ub2RlX21vZHVsZXMvQG5vYmxlL2hhc2hlcy9lc20vX2Fzc2VydC5qcyIsIi4uL25vZGVfbW9kdWxlcy9Abm9ibGUvaGFzaGVzL2VzbS91dGlscy5qcyIsIi4uL25vZGVfbW9kdWxlcy9Abm9ibGUvaGFzaGVzL2VzbS9fYmxha2UuanMiLCIuLi9ub2RlX21vZHVsZXMvQG5vYmxlL2hhc2hlcy9lc20vX3U2NC5qcyIsIi4uL25vZGVfbW9kdWxlcy9Abm9ibGUvaGFzaGVzL2VzbS9ibGFrZTJiLmpzIiwiLi4vc3JjL21pc2MuanMiLCIuLi9zcmMvemtleV9jb25zdGFudHMuanMiLCIuLi9zcmMvZmZsb25rX2NvbnN0YW50cy5qcyIsIi4uL3NyYy96a2V5X3V0aWxzLmpzIiwiLi4vc3JjL3d0bnNfdXRpbHMuanMiLCIuLi9zcmMvZ3JvdGgxNl9wcm92ZS5qcyIsIi4uL25vZGVfbW9kdWxlcy9mYXN0ZmlsZS9zcmMvb3NmaWxlLmpzIiwiLi4vbm9kZV9tb2R1bGVzL2Zhc3RmaWxlL3NyYy9tZW1maWxlLmpzIiwiLi4vbm9kZV9tb2R1bGVzL2Zhc3RmaWxlL3NyYy9iaWdtZW1maWxlLmpzIiwiLi4vbm9kZV9tb2R1bGVzL2Zhc3RmaWxlL3NyYy9mYXN0ZmlsZS5qcyIsIi4uL25vZGVfbW9kdWxlcy9jaXJjb21fcnVudGltZS9qcy91dGlscy5qcyIsIi4uL25vZGVfbW9kdWxlcy9jaXJjb21fcnVudGltZS9qcy93aXRuZXNzX2NhbGN1bGF0b3IuanMiLCIuLi9zcmMvd3Ruc19jYWxjdWxhdGUuanMiLCIuLi9zcmMvZ3JvdGgxNl9mdWxscHJvdmUuanMiLCIuLi9zcmMvZ3JvdGgxNl92ZXJpZnkuanMiLCIuLi9zcmMvZ3JvdGgxNl9leHBvcnRzb2xpZGl0eWNhbGxkYXRhLmpzIiwiLi4vc3JjL2dyb3RoMTYuanMiLCIuLi9zcmMva2V5cGFpci5qcyIsIi4uL3NyYy9wb3dlcnNvZnRhdV91dGlscy5qcyIsIi4uL3NyYy9wb3dlcnNvZnRhdV9uZXcuanMiLCIuLi9zcmMvcG93ZXJzb2Z0YXVfZXhwb3J0X2NoYWxsZW5nZS5qcyIsIi4uL3NyYy9wb3dlcnNvZnRhdV9pbXBvcnQuanMiLCIuLi9zcmMvcG93ZXJzb2Z0YXVfdmVyaWZ5LmpzIiwiLi4vc3JjL21wY19hcHBseWtleS5qcyIsIi4uL3NyYy9wb3dlcnNvZnRhdV9jaGFsbGVuZ2VfY29udHJpYnV0ZS5qcyIsIi4uL3NyYy9wb3dlcnNvZnRhdV9iZWFjb24uanMiLCIuLi9zcmMvcG93ZXJzb2Z0YXVfY29udHJpYnV0ZS5qcyIsIi4uL3NyYy9wb3dlcnNvZnRhdV9wcmVwYXJlcGhhc2UyLmpzIiwiLi4vc3JjL3Bvd2Vyc29mdGF1X3RydW5jYXRlLmpzIiwiLi4vc3JjL3Bvd2Vyc29mdGF1X2NvbnZlcnQuanMiLCIuLi9zcmMvcG93ZXJzb2Z0YXVfZXhwb3J0X2pzb24uanMiLCIuLi9zcmMvcG93ZXJzb2Z0YXUuanMiLCIuLi9zcmMvcjFjc19wcmludC5qcyIsIi4uLy4uL3IxY3NmaWxlL25vZGVfbW9kdWxlcy9AaWRlbjMvYmlnYXJyYXkvc3JjL2JpZ2FycmF5LmpzIiwiLi4vLi4vcjFjc2ZpbGUvbm9kZV9tb2R1bGVzL2Zhc3RmaWxlL3NyYy9vc2ZpbGUuanMiLCIuLi8uLi9yMWNzZmlsZS9ub2RlX21vZHVsZXMvZmFzdGZpbGUvc3JjL21lbWZpbGUuanMiLCIuLi8uLi9yMWNzZmlsZS9ub2RlX21vZHVsZXMvZmFzdGZpbGUvc3JjL2JpZ21lbWZpbGUuanMiLCIuLi8uLi9yMWNzZmlsZS9ub2RlX21vZHVsZXMvZmFzdGZpbGUvc3JjL2Zhc3RmaWxlLmpzIiwiLi4vLi4vcjFjc2ZpbGUvbm9kZV9tb2R1bGVzL0BpZGVuMy9iaW5maWxldXRpbHMvc3JjL2JpbmZpbGV1dGlscy5qcyIsIi4uLy4uL3IxY3NmaWxlL3NyYy9yMWNzZmlsZS5qcyIsIi4uL3NyYy9yMWNzX2luZm8uanMiLCIuLi9zcmMvcjFjc19leHBvcnRfanNvbi5qcyIsIi4uL3NyYy9yMWNzLmpzIiwiLi4vc3JjL2xvYWRzeW1zLmpzIiwiLi4vc3JjL3d0bnNfZGVidWcuanMiLCIuLi9zcmMvd3Ruc19leHBvcnRfanNvbi5qcyIsIi4uL3NyYy93dG5zX2NoZWNrLmpzIiwiLi4vc3JjL3d0bnMuanMiLCIuLi9zcmMvYmlnYXJyYXkuanMiLCIuLi9zcmMvemtleV9uZXcuanMiLCIuLi9zcmMvemtleV9leHBvcnRfYmVsbG1hbi5qcyIsIi4uL3NyYy96a2V5X2ltcG9ydF9iZWxsbWFuLmpzIiwiLi4vc3JjL3prZXlfdmVyaWZ5X2Zyb21pbml0LmpzIiwiLi4vc3JjL3prZXlfdmVyaWZ5X2Zyb21yMWNzLmpzIiwiLi4vc3JjL3prZXlfY29udHJpYnV0ZS5qcyIsIi4uL3NyYy96a2V5X2JlYWNvbi5qcyIsIi4uL3NyYy96a2V5X2V4cG9ydF9qc29uLmpzIiwiLi4vc3JjL3prZXlfYmVsbG1hbl9jb250cmlidXRlLmpzIiwiLi4vc3JjL3prZXlfZXhwb3J0X3ZlcmlmaWNhdGlvbmtleS5qcyIsIi4uL3NyYy9mZmxvbmtfZXhwb3J0X3NvbGlkaXR5X3ZlcmlmaWVyLmpzIiwiLi4vc3JjL3prZXlfZXhwb3J0X3NvbGlkaXR5dmVyaWZpZXIuanMiLCIuLi9zcmMvemtleS5qcyIsIi4uL3NyYy9wbG9ua19zZXR1cC5qcyIsIi4uL3NyYy9wcm9vZi5qcyIsIi4uL25vZGVfbW9kdWxlcy9Abm9ibGUvaGFzaGVzL2VzbS9zaGEzLmpzIiwiLi4vc3JjL0tlY2NhazI1NlRyYW5zY3JpcHQuanMiLCIuLi9zcmMvbXVsX3ouanMiLCIuLi9zcmMvcGxvbmtfY29uc3RhbnRzLmpzIiwiLi4vc3JjL3BvbHlub21pYWwvcG9seW5vbWlhbC5qcyIsIi4uL3NyYy9wb2x5bm9taWFsL2V2YWx1YXRpb25zLmpzIiwiLi4vc3JjL3Bsb25rX3Byb3ZlLmpzIiwiLi4vc3JjL3Bsb25rX2Z1bGxwcm92ZS5qcyIsIi4uL3NyYy9wbG9ua192ZXJpZnkuanMiLCIuLi9zcmMvcGxvbmtfZXhwb3J0c29saWRpdHljYWxsZGF0YS5qcyIsIi4uL3NyYy9wbG9uay5qcyIsIi4uL3NyYy9wbG9ua19lcXVhdGlvbi5qcyIsIi4uL3NyYy9yMWNzX2NvbnN0cmFpbnRfcHJvY2Vzc29yLmpzIiwiLi4vc3JjL3BvbHlub21pYWwvY3BvbHlub21pYWwuanMiLCIuLi9zcmMvZmZsb25rX3NldHVwLmpzIiwiLi4vc3JjL2ZmbG9ua19wcm92ZS5qcyIsIi4uL3NyYy9mZmxvbmtfZnVsbF9wcm92ZS5qcyIsIi4uL3NyYy9mZmxvbmtfdmVyaWZ5LmpzIiwiLi4vc3JjL2ZmbG9ua19leHBvcnRfY2FsbGRhdGEuanMiLCIuLi9zcmMvZmZsb25rLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qIGdsb2JhbCBCaWdJbnQgKi9cbmNvbnN0IGhleExlbiA9IFsgMCwgMSwgMiwgMiwgMywgMywgMywgMywgNCAsNCAsNCAsNCAsNCAsNCAsNCAsNF07XG5cbmZ1bmN0aW9uIGZyb21TdHJpbmcocywgcmFkaXgpIHtcbiAgICBpZiAoKCFyYWRpeCl8fChyYWRpeD09MTApKSB7XG4gICAgICAgIHJldHVybiBCaWdJbnQocyk7XG4gICAgfSBlbHNlIGlmIChyYWRpeD09MTYpIHtcbiAgICAgICAgaWYgKHMuc2xpY2UoMCwyKSA9PSBcIjB4XCIpIHtcbiAgICAgICAgICAgIHJldHVybiBCaWdJbnQocyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gQmlnSW50KFwiMHhcIitzKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuY29uc3QgZSA9IGZyb21TdHJpbmc7XG5cbmZ1bmN0aW9uIGZyb21BcnJheShhLCByYWRpeCkge1xuICAgIGxldCBhY2MgPUJpZ0ludCgwKTtcbiAgICByYWRpeCA9IEJpZ0ludChyYWRpeCk7XG4gICAgZm9yIChsZXQgaT0wOyBpPGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYWNjID0gYWNjKnJhZGl4ICsgQmlnSW50KGFbaV0pO1xuICAgIH1cbiAgICByZXR1cm4gYWNjO1xufVxuXG5mdW5jdGlvbiBiaXRMZW5ndGgkNihhKSB7XG4gICAgY29uc3QgYVMgPWEudG9TdHJpbmcoMTYpO1xuICAgIHJldHVybiAoYVMubGVuZ3RoLTEpKjQgK2hleExlbltwYXJzZUludChhU1swXSwgMTYpXTtcbn1cblxuZnVuY3Rpb24gaXNOZWdhdGl2ZSQ0KGEpIHtcbiAgICByZXR1cm4gQmlnSW50KGEpIDwgQmlnSW50KDApO1xufVxuXG5mdW5jdGlvbiBpc1plcm8kMShhKSB7XG4gICAgcmV0dXJuICFhO1xufVxuXG5mdW5jdGlvbiBzaGlmdExlZnQoYSwgbikge1xuICAgIHJldHVybiBCaWdJbnQoYSkgPDwgQmlnSW50KG4pO1xufVxuXG5mdW5jdGlvbiBzaGlmdFJpZ2h0KGEsIG4pIHtcbiAgICByZXR1cm4gQmlnSW50KGEpID4+IEJpZ0ludChuKTtcbn1cblxuY29uc3Qgc2hsID0gc2hpZnRMZWZ0O1xuY29uc3Qgc2hyID0gc2hpZnRSaWdodDtcblxuZnVuY3Rpb24gaXNPZGQkNShhKSB7XG4gICAgcmV0dXJuIChCaWdJbnQoYSkgJiBCaWdJbnQoMSkpID09IEJpZ0ludCgxKTtcbn1cblxuXG5mdW5jdGlvbiBuYWYobikge1xuICAgIGxldCBFID0gQmlnSW50KG4pO1xuICAgIGNvbnN0IHJlcyA9IFtdO1xuICAgIHdoaWxlIChFKSB7XG4gICAgICAgIGlmIChFICYgQmlnSW50KDEpKSB7XG4gICAgICAgICAgICBjb25zdCB6ID0gMiAtIE51bWJlcihFICUgQmlnSW50KDQpKTtcbiAgICAgICAgICAgIHJlcy5wdXNoKCB6ICk7XG4gICAgICAgICAgICBFID0gRSAtIEJpZ0ludCh6KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcy5wdXNoKCAwICk7XG4gICAgICAgIH1cbiAgICAgICAgRSA9IEUgPj4gQmlnSW50KDEpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzO1xufVxuXG5cbmZ1bmN0aW9uIGJpdHMobikge1xuICAgIGxldCBFID0gQmlnSW50KG4pO1xuICAgIGNvbnN0IHJlcyA9IFtdO1xuICAgIHdoaWxlIChFKSB7XG4gICAgICAgIGlmIChFICYgQmlnSW50KDEpKSB7XG4gICAgICAgICAgICByZXMucHVzaCgxKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcy5wdXNoKCAwICk7XG4gICAgICAgIH1cbiAgICAgICAgRSA9IEUgPj4gQmlnSW50KDEpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzO1xufVxuXG5mdW5jdGlvbiB0b051bWJlciQxKHMpIHtcbiAgICBpZiAocz5CaWdJbnQoTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIgKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJOdW1iZXIgdG9vIGJpZ1wiKTtcbiAgICB9XG4gICAgcmV0dXJuIE51bWJlcihzKTtcbn1cblxuZnVuY3Rpb24gdG9BcnJheShzLCByYWRpeCkge1xuICAgIGNvbnN0IHJlcyA9IFtdO1xuICAgIGxldCByZW0gPSBCaWdJbnQocyk7XG4gICAgcmFkaXggPSBCaWdJbnQocmFkaXgpO1xuICAgIHdoaWxlIChyZW0pIHtcbiAgICAgICAgcmVzLnVuc2hpZnQoIE51bWJlcihyZW0gJSByYWRpeCkpO1xuICAgICAgICByZW0gPSByZW0gLyByYWRpeDtcbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbn1cblxuXG5mdW5jdGlvbiBhZGQoYSwgYikge1xuICAgIHJldHVybiBCaWdJbnQoYSkgKyBCaWdJbnQoYik7XG59XG5cbmZ1bmN0aW9uIHN1YihhLCBiKSB7XG4gICAgcmV0dXJuIEJpZ0ludChhKSAtIEJpZ0ludChiKTtcbn1cblxuZnVuY3Rpb24gbmVnKGEpIHtcbiAgICByZXR1cm4gLUJpZ0ludChhKTtcbn1cblxuZnVuY3Rpb24gbXVsKGEsIGIpIHtcbiAgICByZXR1cm4gQmlnSW50KGEpICogQmlnSW50KGIpO1xufVxuXG5mdW5jdGlvbiBzcXVhcmUkMihhKSB7XG4gICAgcmV0dXJuIEJpZ0ludChhKSAqIEJpZ0ludChhKTtcbn1cblxuZnVuY3Rpb24gcG93KGEsIGIpIHtcbiAgICByZXR1cm4gQmlnSW50KGEpICoqIEJpZ0ludChiKTtcbn1cblxuZnVuY3Rpb24gZXhwJDEoYSwgYikge1xuICAgIHJldHVybiBCaWdJbnQoYSkgKiogQmlnSW50KGIpO1xufVxuXG5mdW5jdGlvbiBhYnMkMShhKSB7XG4gICAgcmV0dXJuIEJpZ0ludChhKSA+PSAwID8gQmlnSW50KGEpIDogLUJpZ0ludChhKTtcbn1cblxuZnVuY3Rpb24gZGl2KGEsIGIpIHtcbiAgICByZXR1cm4gQmlnSW50KGEpIC8gQmlnSW50KGIpO1xufVxuXG5mdW5jdGlvbiBtb2QoYSwgYikge1xuICAgIHJldHVybiBCaWdJbnQoYSkgJSBCaWdJbnQoYik7XG59XG5cbmZ1bmN0aW9uIGVxKGEsIGIpIHtcbiAgICByZXR1cm4gQmlnSW50KGEpID09IEJpZ0ludChiKTtcbn1cblxuZnVuY3Rpb24gbmVxKGEsIGIpIHtcbiAgICByZXR1cm4gQmlnSW50KGEpICE9IEJpZ0ludChiKTtcbn1cblxuZnVuY3Rpb24gbHQoYSwgYikge1xuICAgIHJldHVybiBCaWdJbnQoYSkgPCBCaWdJbnQoYik7XG59XG5cbmZ1bmN0aW9uIGd0KGEsIGIpIHtcbiAgICByZXR1cm4gQmlnSW50KGEpID4gQmlnSW50KGIpO1xufVxuXG5mdW5jdGlvbiBsZXEoYSwgYikge1xuICAgIHJldHVybiBCaWdJbnQoYSkgPD0gQmlnSW50KGIpO1xufVxuXG5mdW5jdGlvbiBnZXEoYSwgYikge1xuICAgIHJldHVybiBCaWdJbnQoYSkgPj0gQmlnSW50KGIpO1xufVxuXG5mdW5jdGlvbiBiYW5kKGEsIGIpIHtcbiAgICByZXR1cm4gQmlnSW50KGEpICYgQmlnSW50KGIpO1xufVxuXG5mdW5jdGlvbiBib3IoYSwgYikge1xuICAgIHJldHVybiBCaWdJbnQoYSkgfCBCaWdJbnQoYik7XG59XG5cbmZ1bmN0aW9uIGJ4b3IoYSwgYikge1xuICAgIHJldHVybiBCaWdJbnQoYSkgXiBCaWdJbnQoYik7XG59XG5cbmZ1bmN0aW9uIGxhbmQoYSwgYikge1xuICAgIHJldHVybiBCaWdJbnQoYSkgJiYgQmlnSW50KGIpO1xufVxuXG5mdW5jdGlvbiBsb3IoYSwgYikge1xuICAgIHJldHVybiBCaWdJbnQoYSkgfHwgQmlnSW50KGIpO1xufVxuXG5mdW5jdGlvbiBsbm90KGEpIHtcbiAgICByZXR1cm4gIUJpZ0ludChhKTtcbn1cblxuLy8gUmV0dXJucyBhIGJ1ZmZlciB3aXRoIExpdHRsZSBFbmRpYW4gUmVwcmVzZW50YXRpb25cbmZ1bmN0aW9uIHRvUnByTEUoYnVmZiwgbywgZSwgbjgpIHtcbiAgICBjb25zdCBzID0gXCIwMDAwMDAwXCIgKyBlLnRvU3RyaW5nKDE2KTtcbiAgICBjb25zdCB2ID0gbmV3IFVpbnQzMkFycmF5KGJ1ZmYuYnVmZmVyLCBidWZmLmJ5dGVPZmZzZXQgKyBvLCBuOC80KTtcbiAgICBjb25zdCBsID0gKCgocy5sZW5ndGgtNykqNCAtIDEpID4+IDUpKzE7ICAgIC8vIE51bWJlciBvZiAzMmJpdCB3b3JkcztcbiAgICBmb3IgKGxldCBpPTA7IGk8bDsgaSsrKSB2W2ldID0gcGFyc2VJbnQocy5zdWJzdHJpbmcocy5sZW5ndGgtOCppLTgsIHMubGVuZ3RoLTgqaSksIDE2KTtcbiAgICBmb3IgKGxldCBpPWw7IGk8di5sZW5ndGg7IGkrKykgdltpXSA9IDA7XG4gICAgZm9yIChsZXQgaT12Lmxlbmd0aCo0OyBpPG44OyBpKyspIGJ1ZmZbaV0gPSB0b051bWJlciQxKGJhbmQoc2hpZnRSaWdodChlLCBpKjgpLCAweEZGKSk7XG59XG5cbi8vIFJldHVybnMgYSBidWZmZXIgd2l0aCBCaWcgRW5kaWFuIFJlcHJlc2VudGF0aW9uXG5mdW5jdGlvbiB0b1JwckJFKGJ1ZmYsIG8sIGUsIG44KSB7XG4gICAgY29uc3QgcyA9IFwiMDAwMDAwMFwiICsgZS50b1N0cmluZygxNik7XG4gICAgY29uc3QgdiA9IG5ldyBEYXRhVmlldyhidWZmLmJ1ZmZlciwgYnVmZi5ieXRlT2Zmc2V0ICsgbywgbjgpO1xuICAgIGNvbnN0IGwgPSAoKChzLmxlbmd0aC03KSo0IC0gMSkgPj4gNSkrMTsgICAgLy8gTnVtYmVyIG9mIDMyYml0IHdvcmRzO1xuICAgIGZvciAobGV0IGk9MDsgaTxsOyBpKyspIHYuc2V0VWludDMyKG44LWkqNCAtNCwgcGFyc2VJbnQocy5zdWJzdHJpbmcocy5sZW5ndGgtOCppLTgsIHMubGVuZ3RoLTgqaSksIDE2KSwgZmFsc2UpO1xuICAgIGZvciAobGV0IGk9MDsgaTxuOC80LWw7IGkrKykgdltpXSA9IDA7XG59XG5cbi8vIFBhc2VzIGEgYnVmZmVyIHdpdGggTGl0dGxlIEVuZGlhbiBSZXByZXNlbnRhdGlvblxuZnVuY3Rpb24gZnJvbVJwckxFKGJ1ZmYsIG8sIG44KSB7XG4gICAgbjggPSBuOCB8fCBidWZmLmJ5dGVMZW5ndGg7XG4gICAgbyA9IG8gfHwgMDtcbiAgICBjb25zdCB2ID0gbmV3IFVpbnQzMkFycmF5KGJ1ZmYuYnVmZmVyLCBidWZmLmJ5dGVPZmZzZXQgKyBvLCBuOC80KTtcbiAgICBjb25zdCBhID0gbmV3IEFycmF5KG44LzQpO1xuICAgIHYuZm9yRWFjaCggKGNoLGkpID0+IGFbYS5sZW5ndGgtaS0xXSA9IGNoLnRvU3RyaW5nKDE2KS5wYWRTdGFydCg4LFwiMFwiKSApO1xuICAgIHJldHVybiBmcm9tU3RyaW5nKGEuam9pbihcIlwiKSwgMTYpO1xufVxuXG4vLyBQYXNlcyBhIGJ1ZmZlciB3aXRoIEJpZyBFbmRpYW4gUmVwcmVzZW50YXRpb25cbmZ1bmN0aW9uIGZyb21ScHJCRShidWZmLCBvLCBuOCkge1xuICAgIG44ID0gbjggfHwgYnVmZi5ieXRlTGVuZ3RoO1xuICAgIG8gPSBvIHx8IDA7XG4gICAgY29uc3QgdiA9IG5ldyBEYXRhVmlldyhidWZmLmJ1ZmZlciwgYnVmZi5ieXRlT2Zmc2V0ICsgbywgbjgpO1xuICAgIGNvbnN0IGEgPSBuZXcgQXJyYXkobjgvNCk7XG4gICAgZm9yIChsZXQgaT0wOyBpPG44LzQ7IGkrKykge1xuICAgICAgICBhW2ldID0gdi5nZXRVaW50MzIoaSo0LCBmYWxzZSkudG9TdHJpbmcoMTYpLnBhZFN0YXJ0KDgsIFwiMFwiKTtcbiAgICB9XG4gICAgcmV0dXJuIGZyb21TdHJpbmcoYS5qb2luKFwiXCIpLCAxNik7XG59XG5cbmZ1bmN0aW9uIHRvU3RyaW5nKGEsIHJhZGl4KSB7XG4gICAgcmV0dXJuIGEudG9TdHJpbmcocmFkaXgpO1xufVxuXG5mdW5jdGlvbiB0b0xFQnVmZihhKSB7XG4gICAgY29uc3QgYnVmZiA9IG5ldyBVaW50OEFycmF5KE1hdGguZmxvb3IoKGJpdExlbmd0aCQ2KGEpIC0gMSkgLyA4KSArMSk7XG4gICAgdG9ScHJMRShidWZmLCAwLCBhLCBidWZmLmJ5dGVMZW5ndGgpO1xuICAgIHJldHVybiBidWZmO1xufVxuXG5jb25zdCB6ZXJvID0gZSgwKTtcbmNvbnN0IG9uZSA9IGUoMSk7XG5cbnZhciBfU2NhbGFyID0gLyojX19QVVJFX18qL09iamVjdC5mcmVlemUoe1xuICAgIF9fcHJvdG9fXzogbnVsbCxcbiAgICBhYnM6IGFicyQxLFxuICAgIGFkZDogYWRkLFxuICAgIGJhbmQ6IGJhbmQsXG4gICAgYml0TGVuZ3RoOiBiaXRMZW5ndGgkNixcbiAgICBiaXRzOiBiaXRzLFxuICAgIGJvcjogYm9yLFxuICAgIGJ4b3I6IGJ4b3IsXG4gICAgZGl2OiBkaXYsXG4gICAgZTogZSxcbiAgICBlcTogZXEsXG4gICAgZXhwOiBleHAkMSxcbiAgICBmcm9tQXJyYXk6IGZyb21BcnJheSxcbiAgICBmcm9tUnByQkU6IGZyb21ScHJCRSxcbiAgICBmcm9tUnByTEU6IGZyb21ScHJMRSxcbiAgICBmcm9tU3RyaW5nOiBmcm9tU3RyaW5nLFxuICAgIGdlcTogZ2VxLFxuICAgIGd0OiBndCxcbiAgICBpc05lZ2F0aXZlOiBpc05lZ2F0aXZlJDQsXG4gICAgaXNPZGQ6IGlzT2RkJDUsXG4gICAgaXNaZXJvOiBpc1plcm8kMSxcbiAgICBsYW5kOiBsYW5kLFxuICAgIGxlcTogbGVxLFxuICAgIGxub3Q6IGxub3QsXG4gICAgbG9yOiBsb3IsXG4gICAgbHQ6IGx0LFxuICAgIG1vZDogbW9kLFxuICAgIG11bDogbXVsLFxuICAgIG5hZjogbmFmLFxuICAgIG5lZzogbmVnLFxuICAgIG5lcTogbmVxLFxuICAgIG9uZTogb25lLFxuICAgIHBvdzogcG93LFxuICAgIHNoaWZ0TGVmdDogc2hpZnRMZWZ0LFxuICAgIHNoaWZ0UmlnaHQ6IHNoaWZ0UmlnaHQsXG4gICAgc2hsOiBzaGwsXG4gICAgc2hyOiBzaHIsXG4gICAgc3F1YXJlOiBzcXVhcmUkMixcbiAgICBzdWI6IHN1YixcbiAgICB0b0FycmF5OiB0b0FycmF5LFxuICAgIHRvTEVCdWZmOiB0b0xFQnVmZixcbiAgICB0b051bWJlcjogdG9OdW1iZXIkMSxcbiAgICB0b1JwckJFOiB0b1JwckJFLFxuICAgIHRvUnByTEU6IHRvUnByTEUsXG4gICAgdG9TdHJpbmc6IHRvU3RyaW5nLFxuICAgIHplcm86IHplcm9cbn0pO1xuXG4vKlxuICAgIENvcHlyaWdodCAyMDE4IDBraW1zIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygc25hcmtqcy5cblxuICAgIHNuYXJranMgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3JcbiAgICBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlXG4gICAgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pXG4gICAgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICBzbmFya2pzIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gICAgYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yXG4gICAgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYWxvbmcgd2l0aFxuICAgIHNuYXJranMuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG4vKlxuICAgIFRoaXMgbGlicmFyeSBkb2VzIG9wZXJhdGlvbnMgb24gcG9seW5vbWlhbHMgd2l0aCBjb2VmZmljaWVudHMgaW4gYSBmaWVsZCBGLlxuXG4gICAgQSBwb2x5bm9taWFsIFAoeCkgPSBwMCArIHAxICogeCArIHAyICogeF4yICsgLi4uICsgcG4gKiB4Xm4gIGlzIHJlcHJlc2VudGVkXG4gICAgYnkgdGhlIGFycmF5IFsgcDAsIHAxLCBwMiwgLi4uICwgcG4gXS5cbiAqL1xuXG5jbGFzcyBQb2xGaWVsZCB7XG4gICAgY29uc3RydWN0b3IgKEYpIHtcbiAgICAgICAgdGhpcy5GID0gRjtcblxuICAgICAgICBsZXQgcmVtID0gRi5zcXJ0X3Q7XG4gICAgICAgIGxldCBzID0gRi5zcXJ0X3M7XG5cbiAgICAgICAgY29uc3QgZml2ZSA9IHRoaXMuRi5hZGQodGhpcy5GLmFkZCh0aGlzLkYudHdvLCB0aGlzLkYudHdvKSwgdGhpcy5GLm9uZSk7XG5cbiAgICAgICAgdGhpcy53ID0gbmV3IEFycmF5KHMrMSk7XG4gICAgICAgIHRoaXMud2kgPSBuZXcgQXJyYXkocysxKTtcbiAgICAgICAgdGhpcy53W3NdID0gdGhpcy5GLnBvdyhmaXZlLCByZW0pO1xuICAgICAgICB0aGlzLndpW3NdID0gdGhpcy5GLmludih0aGlzLndbc10pO1xuXG4gICAgICAgIGxldCBuPXMtMTtcbiAgICAgICAgd2hpbGUgKG4+PTApIHtcbiAgICAgICAgICAgIHRoaXMud1tuXSA9IHRoaXMuRi5zcXVhcmUodGhpcy53W24rMV0pO1xuICAgICAgICAgICAgdGhpcy53aVtuXSA9IHRoaXMuRi5zcXVhcmUodGhpcy53aVtuKzFdKTtcbiAgICAgICAgICAgIG4tLTtcbiAgICAgICAgfVxuXG5cbiAgICAgICAgdGhpcy5yb290cyA9IFtdO1xuLyogICAgICAgIGZvciAobGV0IGk9MDsgaTwxNjsgaSsrKSB7XG4gICAgICAgICAgICBsZXQgciA9IHRoaXMuRi5vbmU7XG4gICAgICAgICAgICBuID0gMSA8PCBpO1xuICAgICAgICAgICAgY29uc3Qgcm9vdHNpID0gbmV3IEFycmF5KG4pO1xuICAgICAgICAgICAgZm9yIChsZXQgaj0wOyBqPG47IGorKykge1xuICAgICAgICAgICAgICAgIHJvb3RzaVtqXSA9IHI7XG4gICAgICAgICAgICAgICAgciA9IHRoaXMuRi5tdWwociwgdGhpcy53W2ldKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5yb290cy5wdXNoKHJvb3RzaSk7XG4gICAgICAgIH1cbiAgICAqL1xuICAgICAgICB0aGlzLl9zZXRSb290cygxNSk7XG4gICAgfVxuXG4gICAgX3NldFJvb3RzKG4pIHtcbiAgICAgICAgaWYgKG4gPiB0aGlzLkYuc3FydF9zKSBuID0gdGhpcy5zO1xuICAgICAgICBmb3IgKGxldCBpPW47IChpPj0wKSAmJiAoIXRoaXMucm9vdHNbaV0pOyBpLS0pIHtcbiAgICAgICAgICAgIGxldCByID0gdGhpcy5GLm9uZTtcbiAgICAgICAgICAgIGNvbnN0IG5yb290cyA9IDEgPDwgaTtcbiAgICAgICAgICAgIGNvbnN0IHJvb3RzaSA9IG5ldyBBcnJheShucm9vdHMpO1xuICAgICAgICAgICAgZm9yIChsZXQgaj0wOyBqPG5yb290czsgaisrKSB7XG4gICAgICAgICAgICAgICAgcm9vdHNpW2pdID0gcjtcbiAgICAgICAgICAgICAgICByID0gdGhpcy5GLm11bChyLCB0aGlzLndbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5yb290c1tpXSA9IHJvb3RzaTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFkZChhLCBiKSB7XG4gICAgICAgIGNvbnN0IG0gPSBNYXRoLm1heChhLmxlbmd0aCwgYi5sZW5ndGgpO1xuICAgICAgICBjb25zdCByZXMgPSBuZXcgQXJyYXkobSk7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxtOyBpKyspIHtcbiAgICAgICAgICAgIHJlc1tpXSA9IHRoaXMuRi5hZGQoYVtpXSB8fCB0aGlzLkYuemVybywgYltpXSB8fCB0aGlzLkYuemVybyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMucmVkdWNlKHJlcyk7XG4gICAgfVxuXG4gICAgZG91YmxlKGEpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWRkKGEsYSk7XG4gICAgfVxuXG4gICAgc3ViKGEsIGIpIHtcbiAgICAgICAgY29uc3QgbSA9IE1hdGgubWF4KGEubGVuZ3RoLCBiLmxlbmd0aCk7XG4gICAgICAgIGNvbnN0IHJlcyA9IG5ldyBBcnJheShtKTtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPG07IGkrKykge1xuICAgICAgICAgICAgcmVzW2ldID0gdGhpcy5GLnN1YihhW2ldIHx8IHRoaXMuRi56ZXJvLCBiW2ldIHx8IHRoaXMuRi56ZXJvKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5yZWR1Y2UocmVzKTtcbiAgICB9XG5cbiAgICBtdWxTY2FsYXIocCwgYikge1xuICAgICAgICBpZiAodGhpcy5GLmVxKGIsIHRoaXMuRi56ZXJvKSkgcmV0dXJuIFtdO1xuICAgICAgICBpZiAodGhpcy5GLmVxKGIsIHRoaXMuRi5vbmUpKSByZXR1cm4gcDtcbiAgICAgICAgY29uc3QgcmVzID0gbmV3IEFycmF5KHAubGVuZ3RoKTtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPHAubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHJlc1tpXSA9IHRoaXMuRi5tdWwocFtpXSwgYik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cblxuXG4gICAgbXVsKGEsIGIpIHtcbiAgICAgICAgaWYgKGEubGVuZ3RoID09IDApIHJldHVybiBbXTtcbiAgICAgICAgaWYgKGIubGVuZ3RoID09IDApIHJldHVybiBbXTtcbiAgICAgICAgaWYgKGEubGVuZ3RoID09IDEpIHJldHVybiB0aGlzLm11bFNjYWxhcihiLCBhWzBdKTtcbiAgICAgICAgaWYgKGIubGVuZ3RoID09IDEpIHJldHVybiB0aGlzLm11bFNjYWxhcihhLCBiWzBdKTtcblxuICAgICAgICBpZiAoYi5sZW5ndGggPiBhLmxlbmd0aCkge1xuICAgICAgICAgICAgW2IsIGFdID0gW2EsIGJdO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKChiLmxlbmd0aCA8PSAyKSB8fCAoYi5sZW5ndGggPCBsb2cyJDIoYS5sZW5ndGgpKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubXVsTm9ybWFsKGEsYik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tdWxGRlQoYSxiKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG11bE5vcm1hbChhLCBiKSB7XG4gICAgICAgIGxldCByZXMgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPGIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHJlcyA9IHRoaXMuYWRkKHJlcywgdGhpcy5zY2FsZVgodGhpcy5tdWxTY2FsYXIoYSwgYltpXSksIGkpICk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICBtdWxGRlQoYSxiKSB7XG4gICAgICAgIGNvbnN0IGxvbmdlc3ROID0gTWF0aC5tYXgoYS5sZW5ndGgsIGIubGVuZ3RoKTtcbiAgICAgICAgY29uc3QgYml0c1Jlc3VsdCA9IGxvZzIkMihsb25nZXN0Ti0xKSsyO1xuICAgICAgICB0aGlzLl9zZXRSb290cyhiaXRzUmVzdWx0KTtcblxuICAgICAgICBjb25zdCBtID0gMSA8PCBiaXRzUmVzdWx0O1xuICAgICAgICBjb25zdCBlYSA9IHRoaXMuZXh0ZW5kKGEsbSk7XG4gICAgICAgIGNvbnN0IGViID0gdGhpcy5leHRlbmQoYixtKTtcblxuICAgICAgICBjb25zdCB0YSA9IF9fZmZ0JDEodGhpcywgZWEsIGJpdHNSZXN1bHQsIDAsIDEpO1xuICAgICAgICBjb25zdCB0YiA9IF9fZmZ0JDEodGhpcywgZWIsIGJpdHNSZXN1bHQsIDAsIDEpO1xuXG4gICAgICAgIGNvbnN0IHRyZXMgPSBuZXcgQXJyYXkobSk7XG5cbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPG07IGkrKykge1xuICAgICAgICAgICAgdHJlc1tpXSA9IHRoaXMuRi5tdWwodGFbaV0sIHRiW2ldKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlcyA9IF9fZmZ0JDEodGhpcywgdHJlcywgYml0c1Jlc3VsdCwgMCwgMSk7XG5cbiAgICAgICAgY29uc3QgdHdvaW52bSA9IHRoaXMuRi5pbnYoIHRoaXMuRi5tdWxTY2FsYXIodGhpcy5GLm9uZSwgbSkgKTtcbiAgICAgICAgY29uc3QgcmVzbiA9IG5ldyBBcnJheShtKTtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPG07IGkrKykge1xuICAgICAgICAgICAgcmVzbltpXSA9IHRoaXMuRi5tdWwocmVzWyhtLWkpJW1dLCB0d29pbnZtKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLnJlZHVjZShyZXNuKTtcbiAgICB9XG5cblxuXG4gICAgc3F1YXJlKGEpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubXVsKGEsYSk7XG4gICAgfVxuXG4gICAgc2NhbGVYKHAsIG4pIHtcbiAgICAgICAgaWYgKG49PTApIHtcbiAgICAgICAgICAgIHJldHVybiBwO1xuICAgICAgICB9IGVsc2UgaWYgKG4+MCkge1xuICAgICAgICAgICAgY29uc3QgeiA9IG5ldyBBcnJheShuKS5maWxsKHRoaXMuRi56ZXJvKTtcbiAgICAgICAgICAgIHJldHVybiB6LmNvbmNhdChwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICgtbiA+PSBwLmxlbmd0aCkgcmV0dXJuIFtdO1xuICAgICAgICAgICAgcmV0dXJuIHAuc2xpY2UoLW4pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZXZhbDIocCwgeCkge1xuICAgICAgICBsZXQgdiA9IHRoaXMuRi56ZXJvO1xuICAgICAgICBsZXQgaXggPSB0aGlzLkYub25lO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8cC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdiA9IHRoaXMuRi5hZGQodiwgdGhpcy5GLm11bChwW2ldLCBpeCkpO1xuICAgICAgICAgICAgaXggPSB0aGlzLkYubXVsKGl4LCB4KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdjtcbiAgICB9XG5cbiAgICBldmFsdWF0ZShwLHgpIHtcbiAgICAgICAgY29uc3QgRiA9IHRoaXMuRjtcbiAgICAgICAgaWYgKHAubGVuZ3RoID09IDApIHJldHVybiBGLnplcm87XG4gICAgICAgIGNvbnN0IG0gPSB0aGlzLl9uZXh0MlBvd2VyKHAubGVuZ3RoKTtcbiAgICAgICAgY29uc3QgZXAgPSB0aGlzLmV4dGVuZChwLCBtKTtcblxuICAgICAgICByZXR1cm4gX2V2YWwoZXAsIHgsIDAsIDEsIG0pO1xuXG4gICAgICAgIGZ1bmN0aW9uIF9ldmFsKHAsIHgsIG9mZnNldCwgc3RlcCwgbikge1xuICAgICAgICAgICAgaWYgKG49PTEpIHJldHVybiBwW29mZnNldF07XG4gICAgICAgICAgICBjb25zdCBuZXdYID0gRi5zcXVhcmUoeCk7XG4gICAgICAgICAgICBjb25zdCByZXM9IEYuYWRkKFxuICAgICAgICAgICAgICAgIF9ldmFsKHAsIG5ld1gsIG9mZnNldCwgc3RlcCA8PCAxLCBuID4+IDEpLFxuICAgICAgICAgICAgICAgIEYubXVsKFxuICAgICAgICAgICAgICAgICAgICB4LFxuICAgICAgICAgICAgICAgICAgICBfZXZhbChwLCBuZXdYLCBvZmZzZXQrc3RlcCAsIHN0ZXAgPDwgMSwgbiA+PiAxKSkpO1xuICAgICAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGxhZ3JhbmdlKHBvaW50cykge1xuICAgICAgICBsZXQgcm9vdHMgPSBbdGhpcy5GLm9uZV07XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxwb2ludHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHJvb3RzID0gdGhpcy5tdWwocm9vdHMsIFt0aGlzLkYubmVnKHBvaW50c1tpXVswXSksIHRoaXMuRi5vbmVdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBzdW0gPSBbXTtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPHBvaW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbGV0IG1wb2wgPSB0aGlzLnJ1ZmZpbmkocm9vdHMsIHBvaW50c1tpXVswXSk7XG4gICAgICAgICAgICBjb25zdCBmYWN0b3IgPVxuICAgICAgICAgICAgICAgIHRoaXMuRi5tdWwoXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuRi5pbnYodGhpcy5ldmFsdWF0ZShtcG9sLCBwb2ludHNbaV1bMF0pKSxcbiAgICAgICAgICAgICAgICAgICAgcG9pbnRzW2ldWzFdKTtcbiAgICAgICAgICAgIG1wb2wgPSB0aGlzLm11bFNjYWxhcihtcG9sLCBmYWN0b3IpO1xuICAgICAgICAgICAgc3VtID0gdGhpcy5hZGQoc3VtLCBtcG9sKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3VtO1xuICAgIH1cblxuXG4gICAgZmZ0KHApIHtcbiAgICAgICAgaWYgKHAubGVuZ3RoIDw9IDEpIHJldHVybiBwO1xuICAgICAgICBjb25zdCBiaXRzID0gbG9nMiQyKHAubGVuZ3RoLTEpKzE7XG4gICAgICAgIHRoaXMuX3NldFJvb3RzKGJpdHMpO1xuXG4gICAgICAgIGNvbnN0IG0gPSAxIDw8IGJpdHM7XG4gICAgICAgIGNvbnN0IGVwID0gdGhpcy5leHRlbmQocCwgbSk7XG4gICAgICAgIGNvbnN0IHJlcyA9IF9fZmZ0JDEodGhpcywgZXAsIGJpdHMsIDAsIDEpO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIGZmdDIocCkge1xuICAgICAgICBpZiAocC5sZW5ndGggPD0gMSkgcmV0dXJuIHA7XG4gICAgICAgIGNvbnN0IGJpdHMgPSBsb2cyJDIocC5sZW5ndGgtMSkrMTtcbiAgICAgICAgdGhpcy5fc2V0Um9vdHMoYml0cyk7XG5cbiAgICAgICAgY29uc3QgbSA9IDEgPDwgYml0cztcbiAgICAgICAgY29uc3QgZXAgPSB0aGlzLmV4dGVuZChwLCBtKTtcbiAgICAgICAgX19iaXRSZXZlcnNlKGVwLCBiaXRzKTtcbiAgICAgICAgY29uc3QgcmVzID0gX19mZnQyKHRoaXMsIGVwLCBiaXRzKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cblxuICAgIGlmZnQocCkge1xuXG4gICAgICAgIGlmIChwLmxlbmd0aCA8PSAxKSByZXR1cm4gcDtcbiAgICAgICAgY29uc3QgYml0cyA9IGxvZzIkMihwLmxlbmd0aC0xKSsxO1xuICAgICAgICB0aGlzLl9zZXRSb290cyhiaXRzKTtcbiAgICAgICAgY29uc3QgbSA9IDEgPDwgYml0cztcbiAgICAgICAgY29uc3QgZXAgPSB0aGlzLmV4dGVuZChwLCBtKTtcbiAgICAgICAgY29uc3QgcmVzID0gIF9fZmZ0JDEodGhpcywgZXAsIGJpdHMsIDAsIDEpO1xuXG4gICAgICAgIGNvbnN0IHR3b2ludm0gPSB0aGlzLkYuaW52KCB0aGlzLkYubXVsU2NhbGFyKHRoaXMuRi5vbmUsIG0pICk7XG4gICAgICAgIGNvbnN0IHJlc24gPSBuZXcgQXJyYXkobSk7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxtOyBpKyspIHtcbiAgICAgICAgICAgIHJlc25baV0gPSB0aGlzLkYubXVsKHJlc1sobS1pKSVtXSwgdHdvaW52bSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzbjtcblxuICAgIH1cblxuXG4gICAgaWZmdDIocCkge1xuXG4gICAgICAgIGlmIChwLmxlbmd0aCA8PSAxKSByZXR1cm4gcDtcbiAgICAgICAgY29uc3QgYml0cyA9IGxvZzIkMihwLmxlbmd0aC0xKSsxO1xuICAgICAgICB0aGlzLl9zZXRSb290cyhiaXRzKTtcbiAgICAgICAgY29uc3QgbSA9IDEgPDwgYml0cztcbiAgICAgICAgY29uc3QgZXAgPSB0aGlzLmV4dGVuZChwLCBtKTtcbiAgICAgICAgX19iaXRSZXZlcnNlKGVwLCBiaXRzKTtcbiAgICAgICAgY29uc3QgcmVzID0gIF9fZmZ0Mih0aGlzLCBlcCwgYml0cyk7XG5cbiAgICAgICAgY29uc3QgdHdvaW52bSA9IHRoaXMuRi5pbnYoIHRoaXMuRi5tdWxTY2FsYXIodGhpcy5GLm9uZSwgbSkgKTtcbiAgICAgICAgY29uc3QgcmVzbiA9IG5ldyBBcnJheShtKTtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPG07IGkrKykge1xuICAgICAgICAgICAgcmVzbltpXSA9IHRoaXMuRi5tdWwocmVzWyhtLWkpJW1dLCB0d29pbnZtKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXNuO1xuXG4gICAgfVxuXG4gICAgX2ZmdChwYWxsLCBiaXRzLCBvZmZzZXQsIHN0ZXApIHtcblxuICAgICAgICBjb25zdCBuID0gMSA8PCBiaXRzO1xuICAgICAgICBpZiAobj09MSkge1xuICAgICAgICAgICAgcmV0dXJuIFsgcGFsbFtvZmZzZXRdIF07XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBuZGl2MiA9IG4gPj4gMTtcbiAgICAgICAgY29uc3QgcDEgPSB0aGlzLl9mZnQocGFsbCwgYml0cy0xLCBvZmZzZXQsIHN0ZXAqMik7XG4gICAgICAgIGNvbnN0IHAyID0gdGhpcy5fZmZ0KHBhbGwsIGJpdHMtMSwgb2Zmc2V0K3N0ZXAsIHN0ZXAqMik7XG5cbiAgICAgICAgY29uc3Qgb3V0ID0gbmV3IEFycmF5KG4pO1xuXG4gICAgICAgIGxldCBtPSB0aGlzLkYub25lO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8bmRpdjI7IGkrKykge1xuICAgICAgICAgICAgb3V0W2ldID0gdGhpcy5GLmFkZChwMVtpXSwgdGhpcy5GLm11bChtLCBwMltpXSkpO1xuICAgICAgICAgICAgb3V0W2krbmRpdjJdID0gdGhpcy5GLnN1YihwMVtpXSwgdGhpcy5GLm11bChtLCBwMltpXSkpO1xuICAgICAgICAgICAgbSA9IHRoaXMuRi5tdWwobSwgdGhpcy53W2JpdHNdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBvdXQ7XG4gICAgfVxuXG4gICAgZXh0ZW5kKHAsIGUpIHtcbiAgICAgICAgaWYgKGUgPT0gcC5sZW5ndGgpIHJldHVybiBwO1xuICAgICAgICBjb25zdCB6ID0gbmV3IEFycmF5KGUtcC5sZW5ndGgpLmZpbGwodGhpcy5GLnplcm8pO1xuXG4gICAgICAgIHJldHVybiBwLmNvbmNhdCh6KTtcbiAgICB9XG5cbiAgICByZWR1Y2UocCkge1xuICAgICAgICBpZiAocC5sZW5ndGggPT0gMCkgcmV0dXJuIHA7XG4gICAgICAgIGlmICghIHRoaXMuRi5lcShwW3AubGVuZ3RoLTFdLCB0aGlzLkYuemVybykgKSByZXR1cm4gcDtcbiAgICAgICAgbGV0IGk9cC5sZW5ndGgtMTtcbiAgICAgICAgd2hpbGUoIGk+MCAmJiB0aGlzLkYuZXEocFtpXSwgdGhpcy5GLnplcm8pICkgaS0tO1xuICAgICAgICByZXR1cm4gcC5zbGljZSgwLCBpKzEpO1xuICAgIH1cblxuICAgIGVxKGEsIGIpIHtcbiAgICAgICAgY29uc3QgcGEgPSB0aGlzLnJlZHVjZShhKTtcbiAgICAgICAgY29uc3QgcGIgPSB0aGlzLnJlZHVjZShiKTtcblxuICAgICAgICBpZiAocGEubGVuZ3RoICE9IHBiLmxlbmd0aCkgcmV0dXJuIGZhbHNlO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8cGIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5GLmVxKHBhW2ldLCBwYltpXSkpIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJ1ZmZpbmkocCwgcikge1xuICAgICAgICBjb25zdCByZXMgPSBuZXcgQXJyYXkocC5sZW5ndGgtMSk7XG4gICAgICAgIHJlc1tyZXMubGVuZ3RoLTFdID0gcFtwLmxlbmd0aC0xXTtcbiAgICAgICAgZm9yIChsZXQgaSA9IHJlcy5sZW5ndGgtMjsgaT49MDsgaS0tKSB7XG4gICAgICAgICAgICByZXNbaV0gPSB0aGlzLkYuYWRkKHRoaXMuRi5tdWwocmVzW2krMV0sIHIpLCBwW2krMV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuXG4gICAgX25leHQyUG93ZXIodikge1xuICAgICAgICB2LS07XG4gICAgICAgIHYgfD0gdiA+PiAxO1xuICAgICAgICB2IHw9IHYgPj4gMjtcbiAgICAgICAgdiB8PSB2ID4+IDQ7XG4gICAgICAgIHYgfD0gdiA+PiA4O1xuICAgICAgICB2IHw9IHYgPj4gMTY7XG4gICAgICAgIHYrKztcbiAgICAgICAgcmV0dXJuIHY7XG4gICAgfVxuXG4gICAgdG9TdHJpbmcocCkge1xuICAgICAgICBjb25zdCBhcCA9IHRoaXMubm9ybWFsaXplKHApO1xuICAgICAgICBsZXQgUyA9IFwiXCI7XG4gICAgICAgIGZvciAobGV0IGk9YXAubGVuZ3RoLTE7IGk+PTA7IGktLSkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLkYuZXEocFtpXSwgdGhpcy5GLnplcm8pKSB7XG4gICAgICAgICAgICAgICAgaWYgKFMhPVwiXCIpIFMgKz0gXCIgKyBcIjtcbiAgICAgICAgICAgICAgICBTID0gUyArIHBbaV0udG9TdHJpbmcoMTApO1xuICAgICAgICAgICAgICAgIGlmIChpPjApIHtcbiAgICAgICAgICAgICAgICAgICAgUyA9IFMgKyBcInhcIjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGk+MSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgUyA9IFMgKyBcIl5cIiAraTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUztcbiAgICB9XG5cbiAgICBub3JtYWxpemUocCkge1xuICAgICAgICBjb25zdCByZXMgID0gbmV3IEFycmF5KHAubGVuZ3RoKTtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPHAubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHJlc1tpXSA9IHRoaXMuRi5ub3JtYWxpemUocFtpXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cblxuICAgIF9yZWNpcHJvY2FsKHAsIGJpdHMpIHtcbiAgICAgICAgY29uc3QgayA9IDEgPDwgYml0cztcbiAgICAgICAgaWYgKGs9PTEpIHtcbiAgICAgICAgICAgIHJldHVybiBbIHRoaXMuRi5pbnYocFswXSkgXTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBucCA9IHRoaXMuc2NhbGVYKHAsIC1rLzIpO1xuICAgICAgICBjb25zdCBxID0gdGhpcy5fcmVjaXByb2NhbChucCwgYml0cy0xKTtcbiAgICAgICAgY29uc3QgYSA9IHRoaXMuc2NhbGVYKHRoaXMuZG91YmxlKHEpLCAzKmsvMi0yKTtcbiAgICAgICAgY29uc3QgYiA9IHRoaXMubXVsKCB0aGlzLnNxdWFyZShxKSwgcCk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuc2NhbGVYKHRoaXMuc3ViKGEsYiksICAgLShrLTIpKTtcbiAgICB9XG5cbiAgICAvLyBkaXZpZGVzIHhebSAvIHZcbiAgICBfZGl2MihtLCB2KSB7XG4gICAgICAgIGNvbnN0IGtiaXRzID0gbG9nMiQyKHYubGVuZ3RoLTEpKzE7XG4gICAgICAgIGNvbnN0IGsgPSAxIDw8IGtiaXRzO1xuXG4gICAgICAgIGNvbnN0IHNjYWxlViA9IGsgLSB2Lmxlbmd0aDtcblxuICAgICAgICAvLyByZWMgPSB4XihrIC0gMikgLyB2KiB4XnNjYWxlViA9PlxuICAgICAgICAvLyByZWMgPSB4XihrLTItc2NhbGVWKS8gdlxuICAgICAgICAvL1xuICAgICAgICAvLyByZXMgPSB4Xm0vdiA9IHheKG0gKyAoMiprLTIgLSBzY2FsZVYpIC0gKDIqay0yIC0gc2NhbGVWKSkgL3YgPT5cbiAgICAgICAgLy8gcmVzID0gcmVjICogeF4obSAtICgyKmstMiAtIHNjYWxlVikpID0+XG4gICAgICAgIC8vIHJlcyA9IHJlYyAqIHheKG0gLSAyKmsgKyAyICsgc2NhbGVWKVxuXG4gICAgICAgIGNvbnN0IHJlYyA9IHRoaXMuX3JlY2lwcm9jYWwodGhpcy5zY2FsZVgodiwgc2NhbGVWKSwga2JpdHMpO1xuICAgICAgICBjb25zdCByZXMgPSB0aGlzLnNjYWxlWChyZWMsIG0gLSAyKmsgKyAyICsgc2NhbGVWKTtcblxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIGRpdihfdSwgX3YpIHtcbiAgICAgICAgaWYgKF91Lmxlbmd0aCA8IF92Lmxlbmd0aCkgcmV0dXJuIFtdO1xuICAgICAgICBjb25zdCBrYml0cyA9IGxvZzIkMihfdi5sZW5ndGgtMSkrMTtcbiAgICAgICAgY29uc3QgayA9IDEgPDwga2JpdHM7XG5cbiAgICAgICAgY29uc3QgdSA9IHRoaXMuc2NhbGVYKF91LCBrLV92Lmxlbmd0aCk7XG4gICAgICAgIGNvbnN0IHYgPSB0aGlzLnNjYWxlWChfdiwgay1fdi5sZW5ndGgpO1xuXG4gICAgICAgIGNvbnN0IG4gPSB2Lmxlbmd0aC0xO1xuICAgICAgICBsZXQgbSA9IHUubGVuZ3RoLTE7XG5cbiAgICAgICAgY29uc3QgcyA9IHRoaXMuX3JlY2lwcm9jYWwodiwga2JpdHMpO1xuICAgICAgICBsZXQgdDtcbiAgICAgICAgaWYgKG0+MipuKSB7XG4gICAgICAgICAgICB0ID0gdGhpcy5zdWIodGhpcy5zY2FsZVgoW3RoaXMuRi5vbmVdLCAyKm4pLCB0aGlzLm11bChzLCB2KSk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcSA9IFtdO1xuICAgICAgICBsZXQgcmVtID0gdTtcbiAgICAgICAgbGV0IHVzLCB1dDtcbiAgICAgICAgbGV0IGZpbmlzaCA9IGZhbHNlO1xuXG4gICAgICAgIHdoaWxlICghZmluaXNoKSB7XG4gICAgICAgICAgICB1cyA9IHRoaXMubXVsKHJlbSwgcyk7XG4gICAgICAgICAgICBxID0gdGhpcy5hZGQocSwgdGhpcy5zY2FsZVgodXMsIC0yKm4pKTtcblxuICAgICAgICAgICAgaWYgKCBtID4gMipuICkge1xuICAgICAgICAgICAgICAgIHV0ID0gdGhpcy5tdWwocmVtLCB0KTtcbiAgICAgICAgICAgICAgICByZW0gPSB0aGlzLnNjYWxlWCh1dCwgLTIqbik7XG4gICAgICAgICAgICAgICAgbSA9IHJlbS5sZW5ndGgtMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZmluaXNoID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBxO1xuICAgIH1cblxuXG4gICAgLy8gcmV0dXJucyB0aGUgaXRoIG50aC1yb290IG9mIG9uZVxuICAgIG9uZVJvb3QobiwgaSkge1xuICAgICAgICBsZXQgbmJpdHMgPSBsb2cyJDIobi0xKSsxO1xuICAgICAgICBsZXQgcmVzID0gdGhpcy5GLm9uZTtcbiAgICAgICAgbGV0IHIgPSBpO1xuXG4gICAgICAgIGlmKGk+PW4pIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkdpdmVuICdpJyBzaG91bGQgYmUgbG93ZXIgdGhhbiAnbidcIik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoMTw8bmJpdHMgIT09IG4pIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW50ZXJuYWwgZXJybHI6ICR7bn0gc2hvdWxkIGVxdWFsICR7MTw8bmJpdHN9YCk7XG4gICAgICAgIH1cblxuICAgICAgICB3aGlsZSAocj4wKSB7XG4gICAgICAgICAgICBpZiAociAmIDEgPT0gMSkge1xuICAgICAgICAgICAgICAgIHJlcyA9IHRoaXMuRi5tdWwocmVzLCB0aGlzLndbbmJpdHNdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHIgPSByID4+IDE7XG4gICAgICAgICAgICBuYml0cyAtLTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIGNvbXB1dGVWYW5pc2hpbmdQb2xpbm9taWFsKGJpdHMsIHQpIHtcbiAgICAgICAgY29uc3QgbSA9IDEgPDwgYml0cztcbiAgICAgICAgcmV0dXJuIHRoaXMuRi5zdWIodGhpcy5GLnBvdyh0LCBtKSwgdGhpcy5GLm9uZSk7XG4gICAgfVxuXG4gICAgZXZhbHVhdGVMYWdyYW5nZVBvbHlub21pYWxzKGJpdHMsIHQpIHtcbiAgICAgICAgY29uc3QgbT0gMSA8PCBiaXRzO1xuICAgICAgICBjb25zdCB0bSA9IHRoaXMuRi5wb3codCwgbSk7XG4gICAgICAgIGNvbnN0IHU9IG5ldyBBcnJheShtKS5maWxsKHRoaXMuRi56ZXJvKTtcbiAgICAgICAgdGhpcy5fc2V0Um9vdHMoYml0cyk7XG4gICAgICAgIGNvbnN0IG9tZWdhID0gdGhpcy53W2JpdHNdO1xuXG4gICAgICAgIGlmICh0aGlzLkYuZXEodG0sIHRoaXMuRi5vbmUpKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG07IGkrKykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLkYuZXEodGhpcy5yb290c1tiaXRzXVswXSx0KSkgeyAvLyBpLmUuLCB0IGVxdWFscyBvbWVnYV5pXG4gICAgICAgICAgICAgICAgICAgIHVbaV0gPSB0aGlzLkYub25lO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB6ID0gdGhpcy5GLnN1Yih0bSwgdGhpcy5GLm9uZSk7XG4gICAgICAgIC8vICAgICAgICBsZXQgbCA9IHRoaXMuRi5tdWwoeiwgIHRoaXMuRi5wb3codGhpcy5GLnR3b2ludiwgbSkpO1xuICAgICAgICBsZXQgbCA9IHRoaXMuRi5tdWwoeiwgIHRoaXMuRi5pbnYodGhpcy5GLmUobSkpKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtOyBpKyspIHtcbiAgICAgICAgICAgIHVbaV0gPSB0aGlzLkYubXVsKGwsIHRoaXMuRi5pbnYodGhpcy5GLnN1Yih0LHRoaXMucm9vdHNbYml0c11baV0pKSk7XG4gICAgICAgICAgICBsID0gdGhpcy5GLm11bChsLCBvbWVnYSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdTtcbiAgICB9XG5cbiAgICBsb2cyKFYpIHtcbiAgICAgICAgcmV0dXJuIGxvZzIkMihWKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGxvZzIkMiggViApXG57XG4gICAgcmV0dXJuKCAoICggViAmIDB4RkZGRjAwMDAgKSAhPT0gMCA/ICggViAmPSAweEZGRkYwMDAwLCAxNiApIDogMCApIHwgKCAoIFYgJiAweEZGMDBGRjAwICkgIT09IDAgPyAoIFYgJj0gMHhGRjAwRkYwMCwgOCApIDogMCApIHwgKCAoIFYgJiAweEYwRjBGMEYwICkgIT09IDAgPyAoIFYgJj0gMHhGMEYwRjBGMCwgNCApIDogMCApIHwgKCAoIFYgJiAweENDQ0NDQ0NDICkgIT09IDAgPyAoIFYgJj0gMHhDQ0NDQ0NDQywgMiApIDogMCApIHwgKCAoIFYgJiAweEFBQUFBQUFBICkgIT09IDAgKSApO1xufVxuXG5cbmZ1bmN0aW9uIF9fZmZ0JDEoUEYsIHBhbGwsIGJpdHMsIG9mZnNldCwgc3RlcCkge1xuXG4gICAgY29uc3QgbiA9IDEgPDwgYml0cztcbiAgICBpZiAobj09MSkge1xuICAgICAgICByZXR1cm4gWyBwYWxsW29mZnNldF0gXTtcbiAgICB9IGVsc2UgaWYgKG49PTIpIHtcbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIFBGLkYuYWRkKHBhbGxbb2Zmc2V0XSwgcGFsbFtvZmZzZXQgKyBzdGVwXSksXG4gICAgICAgICAgICBQRi5GLnN1YihwYWxsW29mZnNldF0sIHBhbGxbb2Zmc2V0ICsgc3RlcF0pXTtcbiAgICB9XG5cbiAgICBjb25zdCBuZGl2MiA9IG4gPj4gMTtcbiAgICBjb25zdCBwMSA9IF9fZmZ0JDEoUEYsIHBhbGwsIGJpdHMtMSwgb2Zmc2V0LCBzdGVwKjIpO1xuICAgIGNvbnN0IHAyID0gX19mZnQkMShQRiwgcGFsbCwgYml0cy0xLCBvZmZzZXQrc3RlcCwgc3RlcCoyKTtcblxuICAgIGNvbnN0IG91dCA9IG5ldyBBcnJheShuKTtcblxuICAgIGZvciAobGV0IGk9MDsgaTxuZGl2MjsgaSsrKSB7XG4gICAgICAgIG91dFtpXSA9IFBGLkYuYWRkKHAxW2ldLCBQRi5GLm11bChQRi5yb290c1tiaXRzXVtpXSwgcDJbaV0pKTtcbiAgICAgICAgb3V0W2krbmRpdjJdID0gUEYuRi5zdWIocDFbaV0sIFBGLkYubXVsKFBGLnJvb3RzW2JpdHNdW2ldLCBwMltpXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBvdXQ7XG59XG5cblxuZnVuY3Rpb24gX19mZnQyKFBGLCBwYWxsLCBiaXRzKSB7XG5cbiAgICBjb25zdCBuID0gMSA8PCBiaXRzO1xuICAgIGlmIChuPT0xKSB7XG4gICAgICAgIHJldHVybiBbIHBhbGxbMF0gXTtcbiAgICB9XG5cbiAgICBjb25zdCBuZGl2MiA9IG4gPj4gMTtcbiAgICBjb25zdCBwMSA9IF9fZmZ0MihQRiwgcGFsbC5zbGljZSgwLCBuZGl2MiksIGJpdHMtMSk7XG4gICAgY29uc3QgcDIgPSBfX2ZmdDIoUEYsIHBhbGwuc2xpY2UobmRpdjIpLCBiaXRzLTEpO1xuXG4gICAgY29uc3Qgb3V0ID0gbmV3IEFycmF5KG4pO1xuXG4gICAgZm9yIChsZXQgaT0wOyBpPG5kaXYyOyBpKyspIHtcbiAgICAgICAgb3V0W2ldID0gUEYuRi5hZGQocDFbaV0sIFBGLkYubXVsKFBGLnJvb3RzW2JpdHNdW2ldLCBwMltpXSkpO1xuICAgICAgICBvdXRbaStuZGl2Ml0gPSBQRi5GLnN1YihwMVtpXSwgUEYuRi5tdWwoUEYucm9vdHNbYml0c11baV0sIHAyW2ldKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbn1cblxuY29uc3QgX3JldlRhYmxlJDEgPSBbXTtcbmZvciAobGV0IGk9MDsgaTwyNTY7IGkrKykge1xuICAgIF9yZXZUYWJsZSQxW2ldID0gX3JldlNsb3ckMShpLCA4KTtcbn1cblxuZnVuY3Rpb24gX3JldlNsb3ckMShpZHgsIGJpdHMpIHtcbiAgICBsZXQgcmVzID0wO1xuICAgIGxldCBhID0gaWR4O1xuICAgIGZvciAobGV0IGk9MDsgaTxiaXRzOyBpKyspIHtcbiAgICAgICAgcmVzIDw8PSAxO1xuICAgICAgICByZXMgPSByZXMgfCAoYSAmMSk7XG4gICAgICAgIGEgPj49MTtcbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbn1cblxuZnVuY3Rpb24gcmV2KGlkeCwgYml0cykge1xuICAgIHJldHVybiAoXG4gICAgICAgIF9yZXZUYWJsZSQxW2lkeCA+Pj4gMjRdIHxcbiAgICAgICAgKF9yZXZUYWJsZSQxWyhpZHggPj4+IDE2KSAmIDB4RkZdIDw8IDgpIHxcbiAgICAgICAgKF9yZXZUYWJsZSQxWyhpZHggPj4+IDgpICYgMHhGRl0gPDwgMTYpIHxcbiAgICAgICAgKF9yZXZUYWJsZSQxW2lkeCAmIDB4RkZdIDw8IDI0KVxuICAgICkgPj4+ICgzMi1iaXRzKTtcbn1cblxuZnVuY3Rpb24gX19iaXRSZXZlcnNlKHAsIGJpdHMpIHtcbiAgICBmb3IgKGxldCBrPTA7IGs8cC5sZW5ndGg7IGsrKykge1xuICAgICAgICBjb25zdCByID0gcmV2KGssIGJpdHMpO1xuICAgICAgICBpZiAocj5rKSB7XG4gICAgICAgICAgICBjb25zdCB0bXA9IHBba107XG4gICAgICAgICAgICBwW2tdID0gcFtyXTtcbiAgICAgICAgICAgIHBbcl0gPSB0bXA7XG4gICAgICAgIH1cbiAgICB9XG5cbn1cblxuLypcbiAgICBDb3B5cmlnaHQgMjAxOCAwa2ltcyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJranMuXG5cbiAgICBzbmFya2pzIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4gICAgbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZVxuICAgIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKVxuICAgIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtqcyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICAgIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvclxuICAgIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFsb25nIHdpdGhcbiAgICBzbmFya2pzLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuXG5cbmZ1bmN0aW9uIG11bFNjYWxhcihGLCBiYXNlLCBlKSB7XG4gICAgbGV0IHJlcztcblxuICAgIGlmIChpc1plcm8kMShlKSkgcmV0dXJuIEYuemVybztcblxuICAgIGNvbnN0IG4gPSBuYWYoZSk7XG5cbiAgICBpZiAobltuLmxlbmd0aC0xXSA9PSAxKSB7XG4gICAgICAgIHJlcyA9IGJhc2U7XG4gICAgfSBlbHNlIGlmIChuW24ubGVuZ3RoLTFdID09IC0xKSB7XG4gICAgICAgIHJlcyA9IEYubmVnKGJhc2UpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcImludmxhdWQgTkFGXCIpO1xuICAgIH1cblxuICAgIGZvciAobGV0IGk9bi5sZW5ndGgtMjsgaT49MDsgaS0tKSB7XG5cbiAgICAgICAgcmVzID0gRi5kb3VibGUocmVzKTtcblxuICAgICAgICBpZiAobltpXSA9PSAxKSB7XG4gICAgICAgICAgICByZXMgPSBGLmFkZChyZXMsIGJhc2UpO1xuICAgICAgICB9IGVsc2UgaWYgKG5baV0gPT0gLTEpIHtcbiAgICAgICAgICAgIHJlcyA9IEYuc3ViKHJlcywgYmFzZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzO1xufVxuXG5cbi8qXG5leHBvcnRzLm11bFNjYWxhciA9IChGLCBiYXNlLCBlKSA9PntcbiAgICBsZXQgcmVzID0gRi56ZXJvO1xuICAgIGxldCByZW0gPSBiaWdJbnQoZSk7XG4gICAgbGV0IGV4cCA9IGJhc2U7XG5cbiAgICB3aGlsZSAoISByZW0uZXEoYmlnSW50Lnplcm8pKSB7XG4gICAgICAgIGlmIChyZW0uYW5kKGJpZ0ludC5vbmUpLmVxKGJpZ0ludC5vbmUpKSB7XG4gICAgICAgICAgICByZXMgPSBGLmFkZChyZXMsIGV4cCk7XG4gICAgICAgIH1cbiAgICAgICAgZXhwID0gRi5kb3VibGUoZXhwKTtcbiAgICAgICAgcmVtID0gcmVtLnNoaWZ0UmlnaHQoMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlcztcbn07XG4qL1xuXG5cbmZ1bmN0aW9uIGV4cChGLCBiYXNlLCBlKSB7XG5cbiAgICBpZiAoaXNaZXJvJDEoZSkpIHJldHVybiBGLm9uZTtcblxuICAgIGNvbnN0IG4gPSBiaXRzKGUpO1xuXG4gICAgaWYgKG4ubGVuZ3RoPT0wKSByZXR1cm4gRi5vbmU7XG5cbiAgICBsZXQgcmVzID0gYmFzZTtcblxuICAgIGZvciAobGV0IGk9bi5sZW5ndGgtMjsgaT49MDsgaS0tKSB7XG5cbiAgICAgICAgcmVzID0gRi5zcXVhcmUocmVzKTtcblxuICAgICAgICBpZiAobltpXSkge1xuICAgICAgICAgICAgcmVzID0gRi5tdWwocmVzLCBiYXNlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXM7XG59XG5cbi8vIENoZWNrIGhlcmU6IGh0dHBzOi8vZXByaW50LmlhY3Iub3JnLzIwMTIvNjg1LnBkZlxuXG5mdW5jdGlvbiBidWlsZFNxcnQgKEYpIHtcbiAgICBpZiAoKEYubSAlIDIpID09IDEpIHtcbiAgICAgICAgaWYgKGVxKG1vZChGLnAsIDQpLCAxICkpIHtcbiAgICAgICAgICAgIGlmIChlcShtb2QoRi5wLCA4KSwgMSApKSB7XG4gICAgICAgICAgICAgICAgaWYgKGVxKG1vZChGLnAsIDE2KSwgMSApKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGFsZzdfbXVsbGVyKEYpO1xuICAgICAgICAgICAgICAgICAgICBhbGc1X3RvbmVsbGlTaGFua3MoRik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlcShtb2QoRi5wLCAxNiksIDkgKSkge1xuICAgICAgICAgICAgICAgICAgICBhbGc0X2tvbmcoRik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRmllbGQgd2l0aG90IHNxcnRcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChlcShtb2QoRi5wLCA4KSwgNSApKSB7XG4gICAgICAgICAgICAgICAgYWxnM19hdGtpbihGKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRmllbGQgd2l0aG90IHNxcnRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoZXEobW9kKEYucCwgNCksIDMgKSkge1xuICAgICAgICAgICAgYWxnMl9zaGFua3MoRik7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBwbTJtb2Q0ID0gbW9kKHBvdyhGLnAsIEYubS8yKSwgNCk7XG4gICAgICAgIGlmIChwbTJtb2Q0ID09IDEpIHtcbiAgICAgICAgICAgIGFsZzEwX2FkaihGKTtcbiAgICAgICAgfSBlbHNlIGlmIChwbTJtb2Q0ID09IDMpIHtcbiAgICAgICAgICAgIGFsZzlfYWRqKEYpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYWxnOF9jb21wbGV4KEYpO1xuICAgICAgICB9XG5cbiAgICB9XG59XG5cblxuZnVuY3Rpb24gYWxnNV90b25lbGxpU2hhbmtzKEYpIHtcbiAgICBGLnNxcnRfcSA9IHBvdyhGLnAsIEYubSk7XG5cbiAgICBGLnNxcnRfcyA9IDA7XG4gICAgRi5zcXJ0X3QgPSBzdWIoRi5zcXJ0X3EsIDEpO1xuXG4gICAgd2hpbGUgKCFpc09kZCQ1KEYuc3FydF90KSkge1xuICAgICAgICBGLnNxcnRfcyA9IEYuc3FydF9zICsgMTtcbiAgICAgICAgRi5zcXJ0X3QgPSBkaXYoRi5zcXJ0X3QsIDIpO1xuICAgIH1cblxuICAgIGxldCBjMCA9IEYub25lO1xuXG4gICAgd2hpbGUgKEYuZXEoYzAsIEYub25lKSkge1xuICAgICAgICBjb25zdCBjID0gRi5yYW5kb20oKTtcbiAgICAgICAgRi5zcXJ0X3ogPSBGLnBvdyhjLCBGLnNxcnRfdCk7XG4gICAgICAgIGMwID0gRi5wb3coRi5zcXJ0X3osIDIgKiogKEYuc3FydF9zLTEpICk7XG4gICAgfVxuXG4gICAgRi5zcXJ0X3RtMWQyID0gZGl2KHN1YihGLnNxcnRfdCwgMSksMik7XG5cbiAgICBGLnNxcnQgPSBmdW5jdGlvbihhKSB7XG4gICAgICAgIGNvbnN0IEY9dGhpcztcbiAgICAgICAgaWYgKEYuaXNaZXJvKGEpKSByZXR1cm4gRi56ZXJvO1xuICAgICAgICBsZXQgdyA9IEYucG93KGEsIEYuc3FydF90bTFkMik7XG4gICAgICAgIGNvbnN0IGEwID0gRi5wb3coIEYubXVsKEYuc3F1YXJlKHcpLCBhKSwgMiAqKiAoRi5zcXJ0X3MtMSkgKTtcbiAgICAgICAgaWYgKEYuZXEoYTAsIEYubmVnb25lKSkgcmV0dXJuIG51bGw7XG5cbiAgICAgICAgbGV0IHYgPSBGLnNxcnRfcztcbiAgICAgICAgbGV0IHggPSBGLm11bChhLCB3KTtcbiAgICAgICAgbGV0IGIgPSBGLm11bCh4LCB3KTtcbiAgICAgICAgbGV0IHogPSBGLnNxcnRfejtcbiAgICAgICAgd2hpbGUgKCFGLmVxKGIsIEYub25lKSkge1xuICAgICAgICAgICAgbGV0IGIyayA9IEYuc3F1YXJlKGIpO1xuICAgICAgICAgICAgbGV0IGs9MTtcbiAgICAgICAgICAgIHdoaWxlICghRi5lcShiMmssIEYub25lKSkge1xuICAgICAgICAgICAgICAgIGIyayA9IEYuc3F1YXJlKGIyayk7XG4gICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB3ID0gejtcbiAgICAgICAgICAgIGZvciAobGV0IGk9MDsgaTx2LWstMTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdyA9IEYuc3F1YXJlKHcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgeiA9IEYuc3F1YXJlKHcpO1xuICAgICAgICAgICAgYiA9IEYubXVsKGIsIHopO1xuICAgICAgICAgICAgeCA9IEYubXVsKHgsIHcpO1xuICAgICAgICAgICAgdiA9IGs7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIEYuZ2VxKHgsIEYuemVybykgPyB4IDogRi5uZWcoeCk7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gYWxnNF9rb25nKEYpIHtcbiAgICBGLnNxcnQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU3FydCBhbGcgNCBub3QgaW1wbGVtZW50ZWRcIik7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gYWxnM19hdGtpbihGKSB7XG4gICAgRi5zcXJ0ID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlNxcnQgYWxnIDMgbm90IGltcGxlbWVudGVkXCIpO1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIGFsZzJfc2hhbmtzKEYpIHtcblxuICAgIEYuc3FydF9xID0gcG93KEYucCwgRi5tKTtcbiAgICBGLnNxcnRfZTEgPSBkaXYoIHN1YihGLnNxcnRfcSwgMykgLCA0KTtcblxuICAgIEYuc3FydCA9IGZ1bmN0aW9uKGEpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNaZXJvKGEpKSByZXR1cm4gdGhpcy56ZXJvO1xuXG4gICAgICAgIC8vIFRlc3QgdGhhdCBoYXZlIHNvbHV0aW9uXG4gICAgICAgIGNvbnN0IGExID0gdGhpcy5wb3coYSwgdGhpcy5zcXJ0X2UxKTtcblxuICAgICAgICBjb25zdCBhMCA9IHRoaXMubXVsKHRoaXMuc3F1YXJlKGExKSwgYSk7XG5cbiAgICAgICAgaWYgKCB0aGlzLmVxKGEwLCB0aGlzLm5lZ29uZSkgKSByZXR1cm4gbnVsbDtcblxuICAgICAgICBjb25zdCB4ID0gdGhpcy5tdWwoYTEsIGEpO1xuXG4gICAgICAgIHJldHVybiBGLmdlcSh4LCBGLnplcm8pID8geCA6IEYubmVnKHgpO1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIGFsZzEwX2FkaihGKSB7XG4gICAgRi5zcXJ0ID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlNxcnQgYWxnIDEwIG5vdCBpbXBsZW1lbnRlZFwiKTtcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBhbGc5X2FkaihGKSB7XG4gICAgRi5zcXJ0X3EgPSBwb3coRi5wLCBGLm0vMik7XG4gICAgRi5zcXJ0X2UzNCA9IGRpdiggc3ViKEYuc3FydF9xLCAzKSAsIDQpO1xuICAgIEYuc3FydF9lMTIgPSBkaXYoIHN1YihGLnNxcnRfcSwgMSkgLCAyKTtcblxuICAgIEYuZnJvYmVuaXVzID0gZnVuY3Rpb24obiwgeCkge1xuICAgICAgICBpZiAoKG4lMikgPT0gMSkge1xuICAgICAgICAgICAgcmV0dXJuIEYuY29uanVnYXRlKHgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHg7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgRi5zcXJ0ID0gZnVuY3Rpb24oYSkge1xuICAgICAgICBjb25zdCBGID0gdGhpcztcbiAgICAgICAgY29uc3QgYTEgPSBGLnBvdyhhLCBGLnNxcnRfZTM0KTtcbiAgICAgICAgY29uc3QgYWxmYSA9IEYubXVsKEYuc3F1YXJlKGExKSwgYSk7XG4gICAgICAgIGNvbnN0IGEwID0gRi5tdWwoRi5mcm9iZW5pdXMoMSwgYWxmYSksIGFsZmEpO1xuICAgICAgICBpZiAoRi5lcShhMCwgRi5uZWdvbmUpKSByZXR1cm4gbnVsbDtcbiAgICAgICAgY29uc3QgeDAgPSBGLm11bChhMSwgYSk7XG4gICAgICAgIGxldCB4O1xuICAgICAgICBpZiAoRi5lcShhbGZhLCBGLm5lZ29uZSkpIHtcbiAgICAgICAgICAgIHggPSBGLm11bCh4MCwgW0YuRi56ZXJvLCBGLkYub25lXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBiID0gRi5wb3coRi5hZGQoRi5vbmUsIGFsZmEpLCBGLnNxcnRfZTEyKTtcbiAgICAgICAgICAgIHggPSBGLm11bChiLCB4MCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIEYuZ2VxKHgsIEYuemVybykgPyB4IDogRi5uZWcoeCk7XG4gICAgfTtcbn1cblxuXG5mdW5jdGlvbiBhbGc4X2NvbXBsZXgoRikge1xuICAgIEYuc3FydCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTcXJ0IGFsZyA4IG5vdCBpbXBsZW1lbnRlZFwiKTtcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBxdWFydGVyUm91bmQoc3QsIGEsIGIsIGMsIGQpIHtcblxuICAgIHN0W2FdID0gKHN0W2FdICsgc3RbYl0pID4+PiAwO1xuICAgIHN0W2RdID0gKHN0W2RdIF4gc3RbYV0pID4+PiAwO1xuICAgIHN0W2RdID0gKChzdFtkXSA8PCAxNikgfCAoKHN0W2RdPj4+MTYpICYgMHhGRkZGKSkgPj4+IDA7XG5cbiAgICBzdFtjXSA9IChzdFtjXSArIHN0W2RdKSA+Pj4gMDtcbiAgICBzdFtiXSA9IChzdFtiXSBeIHN0W2NdKSA+Pj4gMDtcbiAgICBzdFtiXSA9ICgoc3RbYl0gPDwgMTIpIHwgKChzdFtiXT4+PjIwKSAmIDB4RkZGKSkgPj4+IDA7XG5cbiAgICBzdFthXSA9IChzdFthXSArIHN0W2JdKSA+Pj4gMDtcbiAgICBzdFtkXSA9IChzdFtkXSBeIHN0W2FdKSA+Pj4gMDtcbiAgICBzdFtkXSA9ICgoc3RbZF0gPDwgOCkgfCAoKHN0W2RdPj4+MjQpICYgMHhGRikpID4+PiAwO1xuXG4gICAgc3RbY10gPSAoc3RbY10gKyBzdFtkXSkgPj4+IDA7XG4gICAgc3RbYl0gPSAoc3RbYl0gXiBzdFtjXSkgPj4+IDA7XG4gICAgc3RbYl0gPSAoKHN0W2JdIDw8IDcpIHwgKChzdFtiXT4+PjI1KSAmIDB4N0YpKSA+Pj4gMDtcbn1cblxuZnVuY3Rpb24gZG91YmxlUm91bmQoc3QpIHtcbiAgICBxdWFydGVyUm91bmQoc3QsIDAsIDQsIDgsMTIpO1xuICAgIHF1YXJ0ZXJSb3VuZChzdCwgMSwgNSwgOSwxMyk7XG4gICAgcXVhcnRlclJvdW5kKHN0LCAyLCA2LDEwLDE0KTtcbiAgICBxdWFydGVyUm91bmQoc3QsIDMsIDcsMTEsMTUpO1xuXG4gICAgcXVhcnRlclJvdW5kKHN0LCAwLCA1LDEwLDE1KTtcbiAgICBxdWFydGVyUm91bmQoc3QsIDEsIDYsMTEsMTIpO1xuICAgIHF1YXJ0ZXJSb3VuZChzdCwgMiwgNywgOCwxMyk7XG4gICAgcXVhcnRlclJvdW5kKHN0LCAzLCA0LCA5LDE0KTtcbn1cblxuY2xhc3MgQ2hhQ2hhIHtcblxuICAgIGNvbnN0cnVjdG9yKHNlZWQpIHtcbiAgICAgICAgc2VlZCA9IHNlZWQgfHwgWzAsMCwwLDAsMCwwLDAsMF07XG4gICAgICAgIHRoaXMuc3RhdGUgPSBbXG4gICAgICAgICAgICAweDYxNzA3ODY1LFxuICAgICAgICAgICAgMHgzMzIwNjQ2RSxcbiAgICAgICAgICAgIDB4Nzk2MjJEMzIsXG4gICAgICAgICAgICAweDZCMjA2NTc0LFxuICAgICAgICAgICAgc2VlZFswXSxcbiAgICAgICAgICAgIHNlZWRbMV0sXG4gICAgICAgICAgICBzZWVkWzJdLFxuICAgICAgICAgICAgc2VlZFszXSxcbiAgICAgICAgICAgIHNlZWRbNF0sXG4gICAgICAgICAgICBzZWVkWzVdLFxuICAgICAgICAgICAgc2VlZFs2XSxcbiAgICAgICAgICAgIHNlZWRbN10sXG4gICAgICAgICAgICAwLFxuICAgICAgICAgICAgMCxcbiAgICAgICAgICAgIDAsXG4gICAgICAgICAgICAwXG4gICAgICAgIF07XG4gICAgICAgIHRoaXMuaWR4ID0gMTY7XG4gICAgICAgIHRoaXMuYnVmZiA9IG5ldyBBcnJheSgxNik7XG4gICAgfVxuXG4gICAgbmV4dFUzMigpIHtcbiAgICAgICAgaWYgKHRoaXMuaWR4ID09IDE2KSB0aGlzLnVwZGF0ZSgpO1xuICAgICAgICByZXR1cm4gdGhpcy5idWZmW3RoaXMuaWR4KytdO1xuICAgIH1cblxuICAgIG5leHRVNjQoKSB7XG4gICAgICAgIHJldHVybiBhZGQobXVsKHRoaXMubmV4dFUzMigpLCAweDEwMDAwMDAwMCksIHRoaXMubmV4dFUzMigpKTtcbiAgICB9XG5cbiAgICBuZXh0Qm9vbCgpIHtcbiAgICAgICAgcmV0dXJuICh0aGlzLm5leHRVMzIoKSAmIDEpID09IDE7XG4gICAgfVxuXG4gICAgdXBkYXRlKCkge1xuICAgICAgICAvLyBDb3B5IHRoZSBzdGF0ZVxuICAgICAgICBmb3IgKGxldCBpPTA7IGk8MTY7IGkrKykgdGhpcy5idWZmW2ldID0gdGhpcy5zdGF0ZVtpXTtcblxuICAgICAgICAvLyBBcHBseSB0aGUgcm91bmRzXG4gICAgICAgIGZvciAobGV0IGk9MDsgaTwxMDsgaSsrKSBkb3VibGVSb3VuZCh0aGlzLmJ1ZmYpO1xuXG4gICAgICAgIC8vIEFkZCB0byB0aGUgaW5pdGlhbFxuICAgICAgICBmb3IgKGxldCBpPTA7IGk8MTY7IGkrKykgdGhpcy5idWZmW2ldID0gKHRoaXMuYnVmZltpXSArIHRoaXMuc3RhdGVbaV0pID4+PiAwO1xuXG4gICAgICAgIHRoaXMuaWR4ID0gMDtcblxuICAgICAgICB0aGlzLnN0YXRlWzEyXSA9ICh0aGlzLnN0YXRlWzEyXSArIDEpID4+PiAwO1xuICAgICAgICBpZiAodGhpcy5zdGF0ZVsxMl0gIT0gMCkgcmV0dXJuO1xuICAgICAgICB0aGlzLnN0YXRlWzEzXSA9ICh0aGlzLnN0YXRlWzEzXSArIDEpID4+PiAwO1xuICAgICAgICBpZiAodGhpcy5zdGF0ZVsxM10gIT0gMCkgcmV0dXJuO1xuICAgICAgICB0aGlzLnN0YXRlWzE0XSA9ICh0aGlzLnN0YXRlWzE0XSArIDEpID4+PiAwO1xuICAgICAgICBpZiAodGhpcy5zdGF0ZVsxNF0gIT0gMCkgcmV0dXJuO1xuICAgICAgICB0aGlzLnN0YXRlWzE1XSA9ICh0aGlzLnN0YXRlWzE1XSArIDEpID4+PiAwO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0UmFuZG9tQnl0ZXMobikge1xuICAgIGxldCBhcnJheSA9IG5ldyBVaW50OEFycmF5KG4pO1xuICAgIHsgLy8gQnJvd3NlclxuICAgICAgICBpZiAodHlwZW9mIGdsb2JhbFRoaXMuY3J5cHRvICE9PSBcInVuZGVmaW5lZFwiKSB7IC8vIFN1cHBvcnRlZFxuICAgICAgICAgICAgZ2xvYmFsVGhpcy5jcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKGFycmF5KTtcbiAgICAgICAgfSBlbHNlIHsgLy8gZmFsbGJhY2tcbiAgICAgICAgICAgIGZvciAobGV0IGk9MDsgaTxuOyBpKyspIHtcbiAgICAgICAgICAgICAgICBhcnJheVtpXSA9IChNYXRoLnJhbmRvbSgpKjQyOTQ5NjcyOTYpPj4+MDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYXJyYXk7XG59XG5cbmZ1bmN0aW9uIGdldFJhbmRvbVNlZWQoKSB7XG4gICAgY29uc3QgYXJyID0gZ2V0UmFuZG9tQnl0ZXMoMzIpO1xuICAgIGNvbnN0IGFyclYgPSBuZXcgVWludDMyQXJyYXkoYXJyLmJ1ZmZlcik7XG4gICAgY29uc3Qgc2VlZCA9IFtdO1xuICAgIGZvciAobGV0IGk9MDsgaTw4OyBpKyspIHtcbiAgICAgICAgc2VlZC5wdXNoKGFyclZbaV0pO1xuICAgIH1cbiAgICByZXR1cm4gc2VlZDtcbn1cblxubGV0IHRocmVhZFJuZyA9IG51bGw7XG5cbmZ1bmN0aW9uIGdldFRocmVhZFJuZygpIHtcbiAgICBpZiAodGhyZWFkUm5nKSByZXR1cm4gdGhyZWFkUm5nO1xuICAgIHRocmVhZFJuZyA9IG5ldyBDaGFDaGEoZ2V0UmFuZG9tU2VlZCgpKTtcbiAgICByZXR1cm4gdGhyZWFkUm5nO1xufVxuXG4vKlxuICAgIENvcHlyaWdodCAyMDE4IDBraW1zIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygc25hcmtqcy5cblxuICAgIHNuYXJranMgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3JcbiAgICBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlXG4gICAgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pXG4gICAgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICBzbmFya2pzIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gICAgYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yXG4gICAgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYWxvbmcgd2l0aFxuICAgIHNuYXJranMuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG4vKlxuICAgIFRoaXMgbGlicmFyeSBkb2VzIG9wZXJhdGlvbnMgb24gcG9seW5vbWlhbHMgd2l0aCBjb2VmZmljaWVudHMgaW4gYSBmaWVsZCBGLlxuXG4gICAgQSBwb2x5bm9taWFsIFAoeCkgPSBwMCArIHAxICogeCArIHAyICogeF4yICsgLi4uICsgcG4gKiB4Xm4gIGlzIHJlcHJlc2VudGVkXG4gICAgYnkgdGhlIGFycmF5IFsgcDAsIHAxLCBwMiwgLi4uICwgcG4gXS5cbiAqL1xuXG5jbGFzcyBGRlQge1xuICAgIGNvbnN0cnVjdG9yIChHLCBGLCBvcE11bEdGKSB7XG4gICAgICAgIHRoaXMuRiA9IEY7XG4gICAgICAgIHRoaXMuRyA9IEc7XG4gICAgICAgIHRoaXMub3BNdWxHRiA9IG9wTXVsR0Y7XG5cbiAgICAgICAgbGV0IHJlbSA9IEYuc3FydF90IHx8IEYudDtcbiAgICAgICAgbGV0IHMgPSBGLnNxcnRfcyB8fCBGLnM7XG5cbiAgICAgICAgbGV0IG5xciA9IEYub25lO1xuICAgICAgICB3aGlsZSAoRi5lcShGLnBvdyhucXIsIEYuaGFsZiksIEYub25lKSkgbnFyID0gRi5hZGQobnFyLCBGLm9uZSk7XG5cbiAgICAgICAgdGhpcy53ID0gbmV3IEFycmF5KHMrMSk7XG4gICAgICAgIHRoaXMud2kgPSBuZXcgQXJyYXkocysxKTtcbiAgICAgICAgdGhpcy53W3NdID0gdGhpcy5GLnBvdyhucXIsIHJlbSk7XG4gICAgICAgIHRoaXMud2lbc10gPSB0aGlzLkYuaW52KHRoaXMud1tzXSk7XG5cbiAgICAgICAgbGV0IG49cy0xO1xuICAgICAgICB3aGlsZSAobj49MCkge1xuICAgICAgICAgICAgdGhpcy53W25dID0gdGhpcy5GLnNxdWFyZSh0aGlzLndbbisxXSk7XG4gICAgICAgICAgICB0aGlzLndpW25dID0gdGhpcy5GLnNxdWFyZSh0aGlzLndpW24rMV0pO1xuICAgICAgICAgICAgbi0tO1xuICAgICAgICB9XG5cblxuICAgICAgICB0aGlzLnJvb3RzID0gW107XG4gICAgICAgIC8qXG4gICAgICAgIGZvciAobGV0IGk9MDsgaTwxNjsgaSsrKSB7XG4gICAgICAgICAgICBsZXQgciA9IHRoaXMuRi5vbmU7XG4gICAgICAgICAgICBuID0gMSA8PCBpO1xuICAgICAgICAgICAgY29uc3Qgcm9vdHNpID0gbmV3IEFycmF5KG4pO1xuICAgICAgICAgICAgZm9yIChsZXQgaj0wOyBqPG47IGorKykge1xuICAgICAgICAgICAgICAgIHJvb3RzaVtqXSA9IHI7XG4gICAgICAgICAgICAgICAgciA9IHRoaXMuRi5tdWwociwgdGhpcy53W2ldKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5yb290cy5wdXNoKHJvb3RzaSk7XG4gICAgICAgIH1cbiAgICAgICAgKi9cbiAgICAgICAgdGhpcy5fc2V0Um9vdHMoTWF0aC5taW4ocywgMTUpKTtcbiAgICB9XG5cbiAgICBfc2V0Um9vdHMobikge1xuICAgICAgICBmb3IgKGxldCBpPW47IChpPj0wKSAmJiAoIXRoaXMucm9vdHNbaV0pOyBpLS0pIHtcbiAgICAgICAgICAgIGxldCByID0gdGhpcy5GLm9uZTtcbiAgICAgICAgICAgIGNvbnN0IG5yb290cyA9IDEgPDwgaTtcbiAgICAgICAgICAgIGNvbnN0IHJvb3RzaSA9IG5ldyBBcnJheShucm9vdHMpO1xuICAgICAgICAgICAgZm9yIChsZXQgaj0wOyBqPG5yb290czsgaisrKSB7XG4gICAgICAgICAgICAgICAgcm9vdHNpW2pdID0gcjtcbiAgICAgICAgICAgICAgICByID0gdGhpcy5GLm11bChyLCB0aGlzLndbaV0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnJvb3RzW2ldID0gcm9vdHNpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZmZ0KHApIHtcbiAgICAgICAgaWYgKHAubGVuZ3RoIDw9IDEpIHJldHVybiBwO1xuICAgICAgICBjb25zdCBiaXRzID0gbG9nMiQxKHAubGVuZ3RoLTEpKzE7XG4gICAgICAgIHRoaXMuX3NldFJvb3RzKGJpdHMpO1xuXG4gICAgICAgIGNvbnN0IG0gPSAxIDw8IGJpdHM7XG4gICAgICAgIGlmIChwLmxlbmd0aCAhPSBtKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTaXplIG11c3QgYmUgbXVsdGlwbGUgb2YgMlwiKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCByZXMgPSBfX2ZmdCh0aGlzLCBwLCBiaXRzLCAwLCAxKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICBpZmZ0KHApIHtcblxuICAgICAgICBpZiAocC5sZW5ndGggPD0gMSkgcmV0dXJuIHA7XG4gICAgICAgIGNvbnN0IGJpdHMgPSBsb2cyJDEocC5sZW5ndGgtMSkrMTtcbiAgICAgICAgdGhpcy5fc2V0Um9vdHMoYml0cyk7XG4gICAgICAgIGNvbnN0IG0gPSAxIDw8IGJpdHM7XG4gICAgICAgIGlmIChwLmxlbmd0aCAhPSBtKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTaXplIG11c3QgYmUgbXVsdGlwbGUgb2YgMlwiKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCByZXMgPSAgX19mZnQodGhpcywgcCwgYml0cywgMCwgMSk7XG4gICAgICAgIGNvbnN0IHR3b2ludm0gPSB0aGlzLkYuaW52KCB0aGlzLkYubXVsU2NhbGFyKHRoaXMuRi5vbmUsIG0pICk7XG4gICAgICAgIGNvbnN0IHJlc24gPSBuZXcgQXJyYXkobSk7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxtOyBpKyspIHtcbiAgICAgICAgICAgIHJlc25baV0gPSB0aGlzLm9wTXVsR0YocmVzWyhtLWkpJW1dLCB0d29pbnZtKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXNuO1xuICAgIH1cblxuXG59XG5cbmZ1bmN0aW9uIGxvZzIkMSggViApXG57XG4gICAgcmV0dXJuKCAoICggViAmIDB4RkZGRjAwMDAgKSAhPT0gMCA/ICggViAmPSAweEZGRkYwMDAwLCAxNiApIDogMCApIHwgKCAoIFYgJiAweEZGMDBGRjAwICkgIT09IDAgPyAoIFYgJj0gMHhGRjAwRkYwMCwgOCApIDogMCApIHwgKCAoIFYgJiAweEYwRjBGMEYwICkgIT09IDAgPyAoIFYgJj0gMHhGMEYwRjBGMCwgNCApIDogMCApIHwgKCAoIFYgJiAweENDQ0NDQ0NDICkgIT09IDAgPyAoIFYgJj0gMHhDQ0NDQ0NDQywgMiApIDogMCApIHwgKCAoIFYgJiAweEFBQUFBQUFBICkgIT09IDAgKSApO1xufVxuXG5cbmZ1bmN0aW9uIF9fZmZ0KFBGLCBwYWxsLCBiaXRzLCBvZmZzZXQsIHN0ZXApIHtcblxuICAgIGNvbnN0IG4gPSAxIDw8IGJpdHM7XG4gICAgaWYgKG49PTEpIHtcbiAgICAgICAgcmV0dXJuIFsgcGFsbFtvZmZzZXRdIF07XG4gICAgfSBlbHNlIGlmIChuPT0yKSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICBQRi5HLmFkZChwYWxsW29mZnNldF0sIHBhbGxbb2Zmc2V0ICsgc3RlcF0pLFxuICAgICAgICAgICAgUEYuRy5zdWIocGFsbFtvZmZzZXRdLCBwYWxsW29mZnNldCArIHN0ZXBdKV07XG4gICAgfVxuXG4gICAgY29uc3QgbmRpdjIgPSBuID4+IDE7XG4gICAgY29uc3QgcDEgPSBfX2ZmdChQRiwgcGFsbCwgYml0cy0xLCBvZmZzZXQsIHN0ZXAqMik7XG4gICAgY29uc3QgcDIgPSBfX2ZmdChQRiwgcGFsbCwgYml0cy0xLCBvZmZzZXQrc3RlcCwgc3RlcCoyKTtcblxuICAgIGNvbnN0IG91dCA9IG5ldyBBcnJheShuKTtcblxuICAgIGZvciAobGV0IGk9MDsgaTxuZGl2MjsgaSsrKSB7XG4gICAgICAgIG91dFtpXSA9IFBGLkcuYWRkKHAxW2ldLCBQRi5vcE11bEdGKHAyW2ldLCBQRi5yb290c1tiaXRzXVtpXSkpO1xuICAgICAgICBvdXRbaStuZGl2Ml0gPSBQRi5HLnN1YihwMVtpXSwgUEYub3BNdWxHRihwMltpXSwgUEYucm9vdHNbYml0c11baV0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0O1xufVxuXG4vKiBnbG9iYWwgQmlnSW50ICovXG5cbmNsYXNzIFpxRmllbGQge1xuICAgIGNvbnN0cnVjdG9yKHApIHtcbiAgICAgICAgdGhpcy50eXBlPVwiRjFcIjtcbiAgICAgICAgdGhpcy5vbmUgPSBCaWdJbnQoMSk7XG4gICAgICAgIHRoaXMuemVybyA9IEJpZ0ludCgwKTtcbiAgICAgICAgdGhpcy5wID0gQmlnSW50KHApO1xuICAgICAgICB0aGlzLm0gPSAxO1xuICAgICAgICB0aGlzLm5lZ29uZSA9IHRoaXMucC10aGlzLm9uZTtcbiAgICAgICAgdGhpcy50d28gPSBCaWdJbnQoMik7XG4gICAgICAgIHRoaXMuaGFsZiA9IHRoaXMucCA+PiB0aGlzLm9uZTtcbiAgICAgICAgdGhpcy5iaXRMZW5ndGggPSBiaXRMZW5ndGgkNih0aGlzLnApO1xuICAgICAgICB0aGlzLm1hc2sgPSAodGhpcy5vbmUgPDwgQmlnSW50KHRoaXMuYml0TGVuZ3RoKSkgLSB0aGlzLm9uZTtcblxuICAgICAgICB0aGlzLm42NCA9IE1hdGguZmxvb3IoKHRoaXMuYml0TGVuZ3RoIC0gMSkgLyA2NCkrMTtcbiAgICAgICAgdGhpcy5uMzIgPSB0aGlzLm42NCoyO1xuICAgICAgICB0aGlzLm44ID0gdGhpcy5uNjQqODtcbiAgICAgICAgdGhpcy5SID0gdGhpcy5lKHRoaXMub25lIDw8IEJpZ0ludCh0aGlzLm42NCo2NCkpO1xuICAgICAgICB0aGlzLlJpID0gdGhpcy5pbnYodGhpcy5SKTtcblxuICAgICAgICBjb25zdCBlID0gdGhpcy5uZWdvbmUgPj4gdGhpcy5vbmU7XG4gICAgICAgIHRoaXMubnFyID0gdGhpcy50d287XG4gICAgICAgIGxldCByID0gdGhpcy5wb3codGhpcy5ucXIsIGUpO1xuICAgICAgICB3aGlsZSAoIXRoaXMuZXEociwgdGhpcy5uZWdvbmUpKSB7XG4gICAgICAgICAgICB0aGlzLm5xciA9IHRoaXMubnFyICsgdGhpcy5vbmU7XG4gICAgICAgICAgICByID0gdGhpcy5wb3codGhpcy5ucXIsIGUpO1xuICAgICAgICB9XG5cblxuICAgICAgICB0aGlzLnMgPSAwO1xuICAgICAgICB0aGlzLnQgPSB0aGlzLm5lZ29uZTtcblxuICAgICAgICB3aGlsZSAoKHRoaXMudCAmIHRoaXMub25lKSA9PSB0aGlzLnplcm8pIHtcbiAgICAgICAgICAgIHRoaXMucyA9IHRoaXMucyArIDE7XG4gICAgICAgICAgICB0aGlzLnQgPSB0aGlzLnQgPj4gdGhpcy5vbmU7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLm5xcl90b190ID0gdGhpcy5wb3codGhpcy5ucXIsIHRoaXMudCk7XG5cbiAgICAgICAgYnVpbGRTcXJ0KHRoaXMpO1xuXG4gICAgICAgIHRoaXMuRkZUID0gbmV3IEZGVCh0aGlzLCB0aGlzLCB0aGlzLm11bC5iaW5kKHRoaXMpKTtcblxuICAgICAgICB0aGlzLmZmdCA9IHRoaXMuRkZULmZmdC5iaW5kKHRoaXMuRkZUKTtcbiAgICAgICAgdGhpcy5pZmZ0ID0gdGhpcy5GRlQuaWZmdC5iaW5kKHRoaXMuRkZUKTtcbiAgICAgICAgdGhpcy53ID0gdGhpcy5GRlQudztcbiAgICAgICAgdGhpcy53aSA9IHRoaXMuRkZULndpOyBcbiAgICBcbiAgICAgICAgdGhpcy5zaGlmdCA9IHRoaXMuc3F1YXJlKHRoaXMubnFyKTtcbiAgICAgICAgdGhpcy5rID0gdGhpcy5leHAodGhpcy5ucXIsIDIqKnRoaXMucyk7XG4gICAgfVxuXG4gICAgZShhLGIpIHtcbiAgICAgICAgbGV0IHJlcztcbiAgICAgICAgaWYgKCFiKSB7XG4gICAgICAgICAgICByZXMgPSBCaWdJbnQoYSk7XG4gICAgICAgIH0gZWxzZSBpZiAoYj09MTYpIHtcbiAgICAgICAgICAgIHJlcyA9IEJpZ0ludChcIjB4XCIrYSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlcyA8IDApIHtcbiAgICAgICAgICAgIGxldCBucmVzID0gLXJlcztcbiAgICAgICAgICAgIGlmIChucmVzID49IHRoaXMucCkgbnJlcyA9IG5yZXMgJSB0aGlzLnA7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wIC0gbnJlcztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAocmVzPj0gdGhpcy5wKSA/IHJlcyV0aGlzLnAgOiByZXM7XG4gICAgICAgIH1cblxuICAgIH1cblxuICAgIGFkZChhLCBiKSB7XG4gICAgICAgIGNvbnN0IHJlcyA9IGEgKyBiO1xuICAgICAgICByZXR1cm4gcmVzID49IHRoaXMucCA/IHJlcy10aGlzLnAgOiByZXM7XG4gICAgfVxuXG4gICAgc3ViKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIChhID49IGIpID8gYS1iIDogdGhpcy5wLWIrYTtcbiAgICB9XG5cbiAgICBuZWcoYSkge1xuICAgICAgICByZXR1cm4gYSA/IHRoaXMucC1hIDogYTtcbiAgICB9XG5cbiAgICBtdWwoYSwgYikge1xuICAgICAgICByZXR1cm4gKGEqYikldGhpcy5wO1xuICAgIH1cblxuICAgIG11bFNjYWxhcihiYXNlLCBzKSB7XG4gICAgICAgIHJldHVybiAoYmFzZSAqIHRoaXMuZShzKSkgJSB0aGlzLnA7XG4gICAgfVxuXG4gICAgc3F1YXJlKGEpIHtcbiAgICAgICAgcmV0dXJuIChhKmEpICUgdGhpcy5wO1xuICAgIH1cblxuICAgIGVxKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGE9PWI7XG4gICAgfVxuXG4gICAgbmVxKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGEhPWI7XG4gICAgfVxuXG4gICAgbHQoYSwgYikge1xuICAgICAgICBjb25zdCBhYSA9IChhID4gdGhpcy5oYWxmKSA/IGEgLSB0aGlzLnAgOiBhO1xuICAgICAgICBjb25zdCBiYiA9IChiID4gdGhpcy5oYWxmKSA/IGIgLSB0aGlzLnAgOiBiO1xuICAgICAgICByZXR1cm4gYWEgPCBiYjtcbiAgICB9XG5cbiAgICBndChhLCBiKSB7XG4gICAgICAgIGNvbnN0IGFhID0gKGEgPiB0aGlzLmhhbGYpID8gYSAtIHRoaXMucCA6IGE7XG4gICAgICAgIGNvbnN0IGJiID0gKGIgPiB0aGlzLmhhbGYpID8gYiAtIHRoaXMucCA6IGI7XG4gICAgICAgIHJldHVybiBhYSA+IGJiO1xuICAgIH1cblxuICAgIGxlcShhLCBiKSB7XG4gICAgICAgIGNvbnN0IGFhID0gKGEgPiB0aGlzLmhhbGYpID8gYSAtIHRoaXMucCA6IGE7XG4gICAgICAgIGNvbnN0IGJiID0gKGIgPiB0aGlzLmhhbGYpID8gYiAtIHRoaXMucCA6IGI7XG4gICAgICAgIHJldHVybiBhYSA8PSBiYjtcbiAgICB9XG5cbiAgICBnZXEoYSwgYikge1xuICAgICAgICBjb25zdCBhYSA9IChhID4gdGhpcy5oYWxmKSA/IGEgLSB0aGlzLnAgOiBhO1xuICAgICAgICBjb25zdCBiYiA9IChiID4gdGhpcy5oYWxmKSA/IGIgLSB0aGlzLnAgOiBiO1xuICAgICAgICByZXR1cm4gYWEgPj0gYmI7XG4gICAgfVxuXG4gICAgZGl2KGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubXVsKGEsIHRoaXMuaW52KGIpKTtcbiAgICB9XG5cbiAgICBpZGl2KGEsIGIpIHtcbiAgICAgICAgaWYgKCFiKSB0aHJvdyBuZXcgRXJyb3IoXCJEaXZpc2lvbiBieSB6ZXJvXCIpO1xuICAgICAgICByZXR1cm4gYSAvIGI7XG4gICAgfVxuXG4gICAgaW52KGEpIHtcbiAgICAgICAgaWYgKCFhKSB0aHJvdyBuZXcgRXJyb3IoXCJEaXZpc2lvbiBieSB6ZXJvXCIpO1xuXG4gICAgICAgIGxldCB0ID0gdGhpcy56ZXJvO1xuICAgICAgICBsZXQgciA9IHRoaXMucDtcbiAgICAgICAgbGV0IG5ld3QgPSB0aGlzLm9uZTtcbiAgICAgICAgbGV0IG5ld3IgPSBhICUgdGhpcy5wO1xuICAgICAgICB3aGlsZSAobmV3cikge1xuICAgICAgICAgICAgbGV0IHEgPSByL25ld3I7XG4gICAgICAgICAgICBbdCwgbmV3dF0gPSBbbmV3dCwgdC1xKm5ld3RdO1xuICAgICAgICAgICAgW3IsIG5ld3JdID0gW25ld3IsIHItcSpuZXdyXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodDx0aGlzLnplcm8pIHQgKz0gdGhpcy5wO1xuICAgICAgICByZXR1cm4gdDtcbiAgICB9XG5cbiAgICBtb2QoYSwgYikge1xuICAgICAgICByZXR1cm4gYSAlIGI7XG4gICAgfVxuXG4gICAgcG93KGIsIGUpIHtcbiAgICAgICAgcmV0dXJuIGV4cCh0aGlzLCBiLCBlKTtcbiAgICB9XG5cbiAgICBleHAoYiwgZSkge1xuICAgICAgICByZXR1cm4gZXhwKHRoaXMsIGIsIGUpO1xuICAgIH1cblxuICAgIGJhbmQoYSwgYikge1xuICAgICAgICBjb25zdCByZXMgPSAgKChhICYgYikgJiB0aGlzLm1hc2spO1xuICAgICAgICByZXR1cm4gcmVzID49IHRoaXMucCA/IHJlcy10aGlzLnAgOiByZXM7XG4gICAgfVxuXG4gICAgYm9yKGEsIGIpIHtcbiAgICAgICAgY29uc3QgcmVzID0gICgoYSB8IGIpICYgdGhpcy5tYXNrKTtcbiAgICAgICAgcmV0dXJuIHJlcyA+PSB0aGlzLnAgPyByZXMtdGhpcy5wIDogcmVzO1xuICAgIH1cblxuICAgIGJ4b3IoYSwgYikge1xuICAgICAgICBjb25zdCByZXMgPSAgKChhIF4gYikgJiB0aGlzLm1hc2spO1xuICAgICAgICByZXR1cm4gcmVzID49IHRoaXMucCA/IHJlcy10aGlzLnAgOiByZXM7XG4gICAgfVxuXG4gICAgYm5vdChhKSB7XG4gICAgICAgIGNvbnN0IHJlcyA9IGEgXiB0aGlzLm1hc2s7XG4gICAgICAgIHJldHVybiByZXMgPj0gdGhpcy5wID8gcmVzLXRoaXMucCA6IHJlcztcbiAgICB9XG5cbiAgICBzaGwoYSwgYikge1xuICAgICAgICBpZiAoTnVtYmVyKGIpIDwgdGhpcy5iaXRMZW5ndGgpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlcyA9IChhIDw8IGIpICYgdGhpcy5tYXNrO1xuICAgICAgICAgICAgcmV0dXJuIHJlcyA+PSB0aGlzLnAgPyByZXMtdGhpcy5wIDogcmVzO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgbmIgPSB0aGlzLnAgLSBiO1xuICAgICAgICAgICAgaWYgKE51bWJlcihuYikgPCB0aGlzLmJpdExlbmd0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBhID4+IG5iO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy56ZXJvO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgc2hyKGEsIGIpIHtcbiAgICAgICAgaWYgKE51bWJlcihiKSA8IHRoaXMuYml0TGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gYSA+PiBiO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgbmIgPSB0aGlzLnAgLSBiO1xuICAgICAgICAgICAgaWYgKE51bWJlcihuYikgPCB0aGlzLmJpdExlbmd0aCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlcyA9IChhIDw8IG5iKSAmIHRoaXMubWFzaztcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzID49IHRoaXMucCA/IHJlcy10aGlzLnAgOiByZXM7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgbGFuZChhLCBiKSB7XG4gICAgICAgIHJldHVybiAoYSAmJiBiKSA/IHRoaXMub25lIDogdGhpcy56ZXJvO1xuICAgIH1cblxuICAgIGxvcihhLCBiKSB7XG4gICAgICAgIHJldHVybiAoYSB8fCBiKSA/IHRoaXMub25lIDogdGhpcy56ZXJvO1xuICAgIH1cblxuICAgIGxub3QoYSkge1xuICAgICAgICByZXR1cm4gKGEpID8gdGhpcy56ZXJvIDogdGhpcy5vbmU7XG4gICAgfVxuXG4gICAgc3FydF9vbGQobikge1xuXG4gICAgICAgIGlmIChuID09IHRoaXMuemVybykgcmV0dXJuIHRoaXMuemVybztcblxuICAgICAgICAvLyBUZXN0IHRoYXQgaGF2ZSBzb2x1dGlvblxuICAgICAgICBjb25zdCByZXMgPSB0aGlzLnBvdyhuLCB0aGlzLm5lZ29uZSA+PiB0aGlzLm9uZSk7XG4gICAgICAgIGlmICggcmVzICE9IHRoaXMub25lICkgcmV0dXJuIG51bGw7XG5cbiAgICAgICAgbGV0IG0gPSB0aGlzLnM7XG4gICAgICAgIGxldCBjID0gdGhpcy5ucXJfdG9fdDtcbiAgICAgICAgbGV0IHQgPSB0aGlzLnBvdyhuLCB0aGlzLnQpO1xuICAgICAgICBsZXQgciA9IHRoaXMucG93KG4sIHRoaXMuYWRkKHRoaXMudCwgdGhpcy5vbmUpID4+IHRoaXMub25lICk7XG5cbiAgICAgICAgd2hpbGUgKCB0ICE9IHRoaXMub25lICkge1xuICAgICAgICAgICAgbGV0IHNxID0gdGhpcy5zcXVhcmUodCk7XG4gICAgICAgICAgICBsZXQgaSA9IDE7XG4gICAgICAgICAgICB3aGlsZSAoc3EgIT0gdGhpcy5vbmUgKSB7XG4gICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgICAgIHNxID0gdGhpcy5zcXVhcmUoc3EpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBiID0gYyBeIG0taS0xXG4gICAgICAgICAgICBsZXQgYiA9IGM7XG4gICAgICAgICAgICBmb3IgKGxldCBqPTA7IGo8IG0taS0xOyBqICsrKSBiID0gdGhpcy5zcXVhcmUoYik7XG5cbiAgICAgICAgICAgIG0gPSBpO1xuICAgICAgICAgICAgYyA9IHRoaXMuc3F1YXJlKGIpO1xuICAgICAgICAgICAgdCA9IHRoaXMubXVsKHQsIGMpO1xuICAgICAgICAgICAgciA9IHRoaXMubXVsKHIsIGIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHIgPiAodGhpcy5wID4+IHRoaXMub25lKSkge1xuICAgICAgICAgICAgciA9IHRoaXMubmVnKHIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHI7XG4gICAgfVxuXG4gICAgbm9ybWFsaXplKGEsIGIpIHtcbiAgICAgICAgYSA9IEJpZ0ludChhLGIpO1xuICAgICAgICBpZiAoYSA8IDApIHtcbiAgICAgICAgICAgIGxldCBuYSA9IC1hO1xuICAgICAgICAgICAgaWYgKG5hID49IHRoaXMucCkgbmEgPSBuYSAlIHRoaXMucDtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnAgLSBuYTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAoYT49IHRoaXMucCkgPyBhJXRoaXMucCA6IGE7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByYW5kb20oKSB7XG4gICAgICAgIGNvbnN0IG5CeXRlcyA9ICh0aGlzLmJpdExlbmd0aCoyIC8gOCk7XG4gICAgICAgIGxldCByZXMgPXRoaXMuemVybztcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPG5CeXRlczsgaSsrKSB7XG4gICAgICAgICAgICByZXMgPSAocmVzIDw8IEJpZ0ludCg4KSkgKyBCaWdJbnQoZ2V0UmFuZG9tQnl0ZXMoMSlbMF0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXMgJSB0aGlzLnA7XG4gICAgfVxuXG4gICAgdG9TdHJpbmcoYSwgYmFzZSkge1xuICAgICAgICBiYXNlID0gYmFzZSB8fCAxMDtcbiAgICAgICAgbGV0IHZzO1xuICAgICAgICBpZiAoKGEgPiB0aGlzLmhhbGYpJiYoYmFzZSA9PSAxMCkpIHtcbiAgICAgICAgICAgIGNvbnN0IHYgPSB0aGlzLnAtYTtcbiAgICAgICAgICAgIHZzID0gXCItXCIrdi50b1N0cmluZyhiYXNlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZzID0gYS50b1N0cmluZyhiYXNlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdnM7XG4gICAgfVxuXG4gICAgaXNaZXJvKGEpIHtcbiAgICAgICAgcmV0dXJuIGEgPT0gdGhpcy56ZXJvO1xuICAgIH1cblxuICAgIGZyb21Sbmcocm5nKSB7XG4gICAgICAgIGxldCB2O1xuICAgICAgICBkbyB7XG4gICAgICAgICAgICB2PXRoaXMuemVybztcbiAgICAgICAgICAgIGZvciAobGV0IGk9MDsgaTx0aGlzLm42NDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdiArPSBybmcubmV4dFU2NCgpIDw8IEJpZ0ludCg2NCAqaSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2ICY9IHRoaXMubWFzaztcbiAgICAgICAgfSB3aGlsZSAodiA+PSB0aGlzLnApO1xuICAgICAgICB2ID0gKHYgKiB0aGlzLlJpKSAlIHRoaXMucDsgICAvLyBDb252ZXJ0IGZyb20gbW9udGdvbWVyeVxuICAgICAgICByZXR1cm4gdjtcbiAgICB9XG5cbiAgICBmZnQoYSkge1xuICAgICAgICByZXR1cm4gdGhpcy5GRlQuZmZ0KGEpO1xuICAgIH1cblxuICAgIGlmZnQoYSkge1xuICAgICAgICByZXR1cm4gdGhpcy5GRlQuaWZmdChhKTtcbiAgICB9XG5cbiAgICAvLyBSZXR1cm5zIGEgYnVmZmVyIHdpdGggTGl0dGxlIEVuZGlhbiBSZXByZXNlbnRhdGlvblxuICAgIHRvUnByTEUoYnVmZiwgbywgZSkge1xuICAgICAgICB0b1JwckxFKGJ1ZmYsIG8sIGUsIHRoaXMubjY0KjgpO1xuICAgIH1cblxuICAgIC8vIFJldHVybnMgYSBidWZmZXIgd2l0aCBCaWcgRW5kaWFuIFJlcHJlc2VudGF0aW9uXG4gICAgdG9ScHJCRShidWZmLCBvLCBlKSB7XG4gICAgICAgIHRvUnByQkUoYnVmZiwgbywgZSwgdGhpcy5uNjQqOCk7XG4gICAgfVxuXG4gICAgLy8gUmV0dXJucyBhIGJ1ZmZlciB3aXRoIEJpZyBFbmRpYW4gTW9udGdvbWVyeSBSZXByZXNlbnRhdGlvblxuICAgIHRvUnByQkVNKGJ1ZmYsIG8sIGUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudG9ScHJCRShidWZmLCBvLCB0aGlzLm11bCh0aGlzLlIsIGUpKTtcbiAgICB9XG5cbiAgICB0b1JwckxFTShidWZmLCBvLCBlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRvUnByTEUoYnVmZiwgbywgdGhpcy5tdWwodGhpcy5SLCBlKSk7XG4gICAgfVxuXG5cbiAgICAvLyBQYXNlcyBhIGJ1ZmZlciB3aXRoIExpdHRsZSBFbmRpYW4gUmVwcmVzZW50YXRpb25cbiAgICBmcm9tUnByTEUoYnVmZiwgbykge1xuICAgICAgICByZXR1cm4gZnJvbVJwckxFKGJ1ZmYsIG8sIHRoaXMubjgpO1xuICAgIH1cblxuICAgIC8vIFBhc2VzIGEgYnVmZmVyIHdpdGggQmlnIEVuZGlhbiBSZXByZXNlbnRhdGlvblxuICAgIGZyb21ScHJCRShidWZmLCBvKSB7XG4gICAgICAgIHJldHVybiBmcm9tUnByQkUoYnVmZiwgbywgdGhpcy5uOCk7XG4gICAgfVxuXG4gICAgZnJvbVJwckxFTShidWZmLCBvKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm11bCh0aGlzLmZyb21ScHJMRShidWZmLCBvKSwgdGhpcy5SaSk7XG4gICAgfVxuXG4gICAgZnJvbVJwckJFTShidWZmLCBvKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm11bCh0aGlzLmZyb21ScHJCRShidWZmLCBvKSwgdGhpcy5SaSk7XG4gICAgfVxuXG4gICAgdG9PYmplY3QoYSkge1xuICAgICAgICByZXR1cm4gYTtcbiAgICB9XG59XG5cbi8qXG4gICAgQ29weXJpZ2h0IDIwMTggMGtpbXMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya2pzLlxuXG4gICAgc25hcmtqcyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuICAgIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGVcbiAgICBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbilcbiAgICBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJranMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAgICBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3JcbiAgICBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhbG9uZyB3aXRoXG4gICAgc25hcmtqcy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cblxuY2xhc3MgRjJGaWVsZCB7XG4gICAgY29uc3RydWN0b3IoRiwgbm9uUmVzaWR1ZSkge1xuICAgICAgICB0aGlzLnR5cGU9XCJGMlwiO1xuICAgICAgICB0aGlzLkYgPSBGO1xuICAgICAgICB0aGlzLnplcm8gPSBbdGhpcy5GLnplcm8sIHRoaXMuRi56ZXJvXTtcbiAgICAgICAgdGhpcy5vbmUgPSBbdGhpcy5GLm9uZSwgdGhpcy5GLnplcm9dO1xuICAgICAgICB0aGlzLm5lZ29uZSA9IHRoaXMubmVnKHRoaXMub25lKTtcbiAgICAgICAgdGhpcy5ub25SZXNpZHVlID0gbm9uUmVzaWR1ZTtcbiAgICAgICAgdGhpcy5tID0gRi5tKjI7XG4gICAgICAgIHRoaXMucCA9IEYucDtcbiAgICAgICAgdGhpcy5uNjQgPSBGLm42NCoyO1xuICAgICAgICB0aGlzLm4zMiA9IHRoaXMubjY0KjI7XG4gICAgICAgIHRoaXMubjggPSB0aGlzLm42NCo4O1xuXG4gICAgICAgIGJ1aWxkU3FydCh0aGlzKTtcbiAgICB9XG5cbiAgICBfbXVsQnlOb25SZXNpZHVlKGEpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuRi5tdWwodGhpcy5ub25SZXNpZHVlLCBhKTtcbiAgICB9XG5cbiAgICBjb3B5KGEpIHtcbiAgICAgICAgcmV0dXJuIFt0aGlzLkYuY29weShhWzBdKSwgdGhpcy5GLmNvcHkoYVsxXSldO1xuICAgIH1cblxuICAgIGFkZChhLCBiKSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICB0aGlzLkYuYWRkKGFbMF0sIGJbMF0pLFxuICAgICAgICAgICAgdGhpcy5GLmFkZChhWzFdLCBiWzFdKVxuICAgICAgICBdO1xuICAgIH1cblxuICAgIGRvdWJsZShhKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmFkZChhLGEpO1xuICAgIH1cblxuICAgIHN1YihhLCBiKSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICB0aGlzLkYuc3ViKGFbMF0sIGJbMF0pLFxuICAgICAgICAgICAgdGhpcy5GLnN1YihhWzFdLCBiWzFdKVxuICAgICAgICBdO1xuICAgIH1cblxuICAgIG5lZyhhKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN1Yih0aGlzLnplcm8sIGEpO1xuICAgIH1cblxuICAgIGNvbmp1Z2F0ZShhKSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICBhWzBdLFxuICAgICAgICAgICAgdGhpcy5GLm5lZyhhWzFdKVxuICAgICAgICBdO1xuICAgIH1cblxuICAgIG11bChhLCBiKSB7XG4gICAgICAgIGNvbnN0IGFBID0gdGhpcy5GLm11bChhWzBdICwgYlswXSk7XG4gICAgICAgIGNvbnN0IGJCID0gdGhpcy5GLm11bChhWzFdICwgYlsxXSk7XG5cbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIHRoaXMuRi5hZGQoIGFBICwgdGhpcy5fbXVsQnlOb25SZXNpZHVlKGJCKSksXG4gICAgICAgICAgICB0aGlzLkYuc3ViKFxuICAgICAgICAgICAgICAgIHRoaXMuRi5tdWwoXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuRi5hZGQoYVswXSwgYVsxXSksXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuRi5hZGQoYlswXSwgYlsxXSkpLFxuICAgICAgICAgICAgICAgIHRoaXMuRi5hZGQoYUEsIGJCKSldO1xuICAgIH1cblxuICAgIGludihhKSB7XG4gICAgICAgIGNvbnN0IHQwID0gdGhpcy5GLnNxdWFyZShhWzBdKTtcbiAgICAgICAgY29uc3QgdDEgPSB0aGlzLkYuc3F1YXJlKGFbMV0pO1xuICAgICAgICBjb25zdCB0MiA9IHRoaXMuRi5zdWIodDAsIHRoaXMuX211bEJ5Tm9uUmVzaWR1ZSh0MSkpO1xuICAgICAgICBjb25zdCB0MyA9IHRoaXMuRi5pbnYodDIpO1xuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgdGhpcy5GLm11bChhWzBdLCB0MyksXG4gICAgICAgICAgICB0aGlzLkYubmVnKHRoaXMuRi5tdWwoIGFbMV0sIHQzKSkgXTtcbiAgICB9XG5cbiAgICBkaXYoYSwgYikge1xuICAgICAgICByZXR1cm4gdGhpcy5tdWwoYSwgdGhpcy5pbnYoYikpO1xuICAgIH1cblxuICAgIHNxdWFyZShhKSB7XG4gICAgICAgIGNvbnN0IGFiID0gdGhpcy5GLm11bChhWzBdICwgYVsxXSk7XG5cbiAgICAgICAgLypcbiAgICAgICAgW1xuICAgICAgICAgICAgKGEgKyBiKSAqIChhICsgbm9uX3Jlc2lkdWUgKiBiKSAtIGFiIC0gbm9uX3Jlc2lkdWUgKiBhYixcbiAgICAgICAgICAgIGFiICsgYWJcbiAgICAgICAgXTtcbiAgICAgICAgKi9cblxuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgdGhpcy5GLnN1YihcbiAgICAgICAgICAgICAgICB0aGlzLkYubXVsKFxuICAgICAgICAgICAgICAgICAgICB0aGlzLkYuYWRkKGFbMF0sIGFbMV0pICxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5GLmFkZChcbiAgICAgICAgICAgICAgICAgICAgICAgIGFbMF0gLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fbXVsQnlOb25SZXNpZHVlKGFbMV0pKSksXG4gICAgICAgICAgICAgICAgdGhpcy5GLmFkZChcbiAgICAgICAgICAgICAgICAgICAgYWIsXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX211bEJ5Tm9uUmVzaWR1ZShhYikpKSxcbiAgICAgICAgICAgIHRoaXMuRi5hZGQoYWIsIGFiKVxuICAgICAgICBdO1xuICAgIH1cblxuICAgIGlzWmVybyhhKSB7XG4gICAgICAgIHJldHVybiB0aGlzLkYuaXNaZXJvKGFbMF0pICYmIHRoaXMuRi5pc1plcm8oYVsxXSk7XG4gICAgfVxuXG4gICAgZXEoYSwgYikge1xuICAgICAgICByZXR1cm4gdGhpcy5GLmVxKGFbMF0sIGJbMF0pICYmIHRoaXMuRi5lcShhWzFdLCBiWzFdKTtcbiAgICB9XG5cbiAgICBtdWxTY2FsYXIoYmFzZSwgZSkge1xuICAgICAgICByZXR1cm4gbXVsU2NhbGFyKHRoaXMsIGJhc2UsIGUpO1xuICAgIH1cblxuICAgIHBvdyhiYXNlLCBlKSB7XG4gICAgICAgIHJldHVybiBleHAodGhpcywgYmFzZSwgZSk7XG4gICAgfVxuXG4gICAgZXhwKGJhc2UsIGUpIHtcbiAgICAgICAgcmV0dXJuIGV4cCh0aGlzLCBiYXNlLCBlKTtcbiAgICB9XG5cbiAgICB0b1N0cmluZyhhKSB7XG4gICAgICAgIHJldHVybiBgWyAke3RoaXMuRi50b1N0cmluZyhhWzBdKX0gLCAke3RoaXMuRi50b1N0cmluZyhhWzFdKX0gXWA7XG4gICAgfVxuXG4gICAgZnJvbVJuZyhybmcpIHtcbiAgICAgICAgY29uc3QgYzAgPSB0aGlzLkYuZnJvbVJuZyhybmcpO1xuICAgICAgICBjb25zdCBjMSA9IHRoaXMuRi5mcm9tUm5nKHJuZyk7XG4gICAgICAgIHJldHVybiBbYzAsIGMxXTtcbiAgICB9XG5cbiAgICBndChhLCBiKSB7XG4gICAgICAgIGlmICh0aGlzLkYuZ3QoYVswXSwgYlswXSkpIHJldHVybiB0cnVlO1xuICAgICAgICBpZiAodGhpcy5GLmd0KGJbMF0sIGFbMF0pKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIGlmICh0aGlzLkYuZ3QoYVsxXSwgYlsxXSkpIHJldHVybiB0cnVlO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZ2VxKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3QoYSwgYikgfHwgdGhpcy5lcShhLCBiKTtcbiAgICB9XG5cbiAgICBsdChhLCBiKSB7XG4gICAgICAgIHJldHVybiAhdGhpcy5nZXEoYSxiKTtcbiAgICB9XG5cbiAgICBsZXEoYSwgYikge1xuICAgICAgICByZXR1cm4gIXRoaXMuZ3QoYSxiKTtcbiAgICB9XG5cbiAgICBuZXEoYSwgYikge1xuICAgICAgICByZXR1cm4gIXRoaXMuZXEoYSxiKTtcbiAgICB9XG5cbiAgICByYW5kb20oKSB7XG4gICAgICAgIHJldHVybiBbdGhpcy5GLnJhbmRvbSgpLCB0aGlzLkYucmFuZG9tKCldO1xuICAgIH1cblxuXG4gICAgdG9ScHJMRShidWZmLCBvLCBlKSB7XG4gICAgICAgIHRoaXMuRi50b1JwckxFKGJ1ZmYsIG8sIGVbMF0pO1xuICAgICAgICB0aGlzLkYudG9ScHJMRShidWZmLCBvK3RoaXMuRi5uOCwgZVsxXSk7XG4gICAgfVxuXG4gICAgdG9ScHJCRShidWZmLCBvLCBlKSB7XG4gICAgICAgIHRoaXMuRi50b1JwckJFKGJ1ZmYsIG8sIGVbMV0pO1xuICAgICAgICB0aGlzLkYudG9ScHJCRShidWZmLCBvK3RoaXMuRi5uOCwgZVswXSk7XG4gICAgfVxuXG4gICAgdG9ScHJMRU0oYnVmZiwgbywgZSkge1xuICAgICAgICB0aGlzLkYudG9ScHJMRU0oYnVmZiwgbywgZVswXSk7XG4gICAgICAgIHRoaXMuRi50b1JwckxFTShidWZmLCBvK3RoaXMuRi5uOCwgZVsxXSk7XG4gICAgfVxuXG5cbiAgICB0b1JwckJFTShidWZmLCBvLCBlKSB7XG4gICAgICAgIHRoaXMuRi50b1JwckJFTShidWZmLCBvLCBlWzFdKTtcbiAgICAgICAgdGhpcy5GLnRvUnByQkVNKGJ1ZmYsIG8rdGhpcy5GLm44LCBlWzBdKTtcbiAgICB9XG5cbiAgICBmcm9tUnByTEUoYnVmZiwgbykge1xuICAgICAgICBvID0gbyB8fCAwO1xuICAgICAgICBjb25zdCBjMCA9IHRoaXMuRi5mcm9tUnByTEUoYnVmZiwgbyk7XG4gICAgICAgIGNvbnN0IGMxID0gdGhpcy5GLmZyb21ScHJMRShidWZmLCBvK3RoaXMuRi5uOCk7XG4gICAgICAgIHJldHVybiBbYzAsIGMxXTtcbiAgICB9XG5cbiAgICBmcm9tUnByQkUoYnVmZiwgbykge1xuICAgICAgICBvID0gbyB8fCAwO1xuICAgICAgICBjb25zdCBjMSA9IHRoaXMuRi5mcm9tUnByQkUoYnVmZiwgbyk7XG4gICAgICAgIGNvbnN0IGMwID0gdGhpcy5GLmZyb21ScHJCRShidWZmLCBvK3RoaXMuRi5uOCk7XG4gICAgICAgIHJldHVybiBbYzAsIGMxXTtcbiAgICB9XG5cbiAgICBmcm9tUnByTEVNKGJ1ZmYsIG8pIHtcbiAgICAgICAgbyA9IG8gfHwgMDtcbiAgICAgICAgY29uc3QgYzAgPSB0aGlzLkYuZnJvbVJwckxFTShidWZmLCBvKTtcbiAgICAgICAgY29uc3QgYzEgPSB0aGlzLkYuZnJvbVJwckxFTShidWZmLCBvK3RoaXMuRi5uOCk7XG4gICAgICAgIHJldHVybiBbYzAsIGMxXTtcbiAgICB9XG5cbiAgICBmcm9tUnByQkVNKGJ1ZmYsIG8pIHtcbiAgICAgICAgbyA9IG8gfHwgMDtcbiAgICAgICAgY29uc3QgYzEgPSB0aGlzLkYuZnJvbVJwckJFTShidWZmLCBvKTtcbiAgICAgICAgY29uc3QgYzAgPSB0aGlzLkYuZnJvbVJwckJFTShidWZmLCBvK3RoaXMuRi5uOCk7XG4gICAgICAgIHJldHVybiBbYzAsIGMxXTtcbiAgICB9XG5cbiAgICB0b09iamVjdChhKSB7XG4gICAgICAgIHJldHVybiBhO1xuICAgIH1cblxufVxuXG4vKlxuICAgIENvcHlyaWdodCAyMDE4IDBraW1zIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygc25hcmtqcy5cblxuICAgIHNuYXJranMgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3JcbiAgICBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlXG4gICAgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pXG4gICAgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICBzbmFya2pzIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gICAgYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yXG4gICAgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYWxvbmcgd2l0aFxuICAgIHNuYXJranMuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG5cbmNsYXNzIEYzRmllbGQge1xuICAgIGNvbnN0cnVjdG9yKEYsIG5vblJlc2lkdWUpIHtcbiAgICAgICAgdGhpcy50eXBlPVwiRjNcIjtcbiAgICAgICAgdGhpcy5GID0gRjtcbiAgICAgICAgdGhpcy56ZXJvID0gW3RoaXMuRi56ZXJvLCB0aGlzLkYuemVybywgdGhpcy5GLnplcm9dO1xuICAgICAgICB0aGlzLm9uZSA9IFt0aGlzLkYub25lLCB0aGlzLkYuemVybywgdGhpcy5GLnplcm9dO1xuICAgICAgICB0aGlzLm5lZ29uZSA9IHRoaXMubmVnKHRoaXMub25lKTtcbiAgICAgICAgdGhpcy5ub25SZXNpZHVlID0gbm9uUmVzaWR1ZTtcbiAgICAgICAgdGhpcy5tID0gRi5tKjM7XG4gICAgICAgIHRoaXMucCA9IEYucDtcbiAgICAgICAgdGhpcy5uNjQgPSBGLm42NCozO1xuICAgICAgICB0aGlzLm4zMiA9IHRoaXMubjY0KjI7XG4gICAgICAgIHRoaXMubjggPSB0aGlzLm42NCo4O1xuICAgIH1cblxuICAgIF9tdWxCeU5vblJlc2lkdWUoYSkge1xuICAgICAgICByZXR1cm4gdGhpcy5GLm11bCh0aGlzLm5vblJlc2lkdWUsIGEpO1xuICAgIH1cblxuICAgIGNvcHkoYSkge1xuICAgICAgICByZXR1cm4gW3RoaXMuRi5jb3B5KGFbMF0pLCB0aGlzLkYuY29weShhWzFdKSwgdGhpcy5GLmNvcHkoYVsyXSldO1xuICAgIH1cblxuICAgIGFkZChhLCBiKSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICB0aGlzLkYuYWRkKGFbMF0sIGJbMF0pLFxuICAgICAgICAgICAgdGhpcy5GLmFkZChhWzFdLCBiWzFdKSxcbiAgICAgICAgICAgIHRoaXMuRi5hZGQoYVsyXSwgYlsyXSlcbiAgICAgICAgXTtcbiAgICB9XG5cbiAgICBkb3VibGUoYSkge1xuICAgICAgICByZXR1cm4gdGhpcy5hZGQoYSxhKTtcbiAgICB9XG5cbiAgICBzdWIoYSwgYikge1xuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgdGhpcy5GLnN1YihhWzBdLCBiWzBdKSxcbiAgICAgICAgICAgIHRoaXMuRi5zdWIoYVsxXSwgYlsxXSksXG4gICAgICAgICAgICB0aGlzLkYuc3ViKGFbMl0sIGJbMl0pXG4gICAgICAgIF07XG4gICAgfVxuXG4gICAgbmVnKGEpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3ViKHRoaXMuemVybywgYSk7XG4gICAgfVxuXG4gICAgbXVsKGEsIGIpIHtcblxuICAgICAgICBjb25zdCBhQSA9IHRoaXMuRi5tdWwoYVswXSAsIGJbMF0pO1xuICAgICAgICBjb25zdCBiQiA9IHRoaXMuRi5tdWwoYVsxXSAsIGJbMV0pO1xuICAgICAgICBjb25zdCBjQyA9IHRoaXMuRi5tdWwoYVsyXSAsIGJbMl0pO1xuXG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICB0aGlzLkYuYWRkKFxuICAgICAgICAgICAgICAgIGFBLFxuICAgICAgICAgICAgICAgIHRoaXMuX211bEJ5Tm9uUmVzaWR1ZShcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5GLnN1YihcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuRi5tdWwoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5GLmFkZChhWzFdLCBhWzJdKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLkYuYWRkKGJbMV0sIGJbMl0pKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuRi5hZGQoYkIsIGNDKSkpKSwgICAgLy8gYUEgKyBub25fcmVzaWR1ZSooKGIrYykqKEIrQyktYkItY0MpLFxuXG4gICAgICAgICAgICB0aGlzLkYuYWRkKFxuICAgICAgICAgICAgICAgIHRoaXMuRi5zdWIoXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuRi5tdWwoXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLkYuYWRkKGFbMF0sIGFbMV0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5GLmFkZChiWzBdLCBiWzFdKSksXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuRi5hZGQoYUEsIGJCKSksXG4gICAgICAgICAgICAgICAgdGhpcy5fbXVsQnlOb25SZXNpZHVlKCBjQykpLCAgIC8vIChhK2IpKihBK0IpLWFBLWJCK25vbl9yZXNpZHVlKmNDXG5cbiAgICAgICAgICAgIHRoaXMuRi5hZGQoXG4gICAgICAgICAgICAgICAgdGhpcy5GLnN1YihcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5GLm11bChcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuRi5hZGQoYVswXSwgYVsyXSksXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLkYuYWRkKGJbMF0sIGJbMl0pKSxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5GLmFkZChhQSwgY0MpKSxcbiAgICAgICAgICAgICAgICBiQildOyAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIChhK2MpKihBK0MpLWFBK2JCLWNDKVxuICAgIH1cblxuICAgIGludihhKSB7XG4gICAgICAgIGNvbnN0IHQwID0gdGhpcy5GLnNxdWFyZShhWzBdKTsgICAgICAgICAgICAgLy8gdDAgPSBhXjIgO1xuICAgICAgICBjb25zdCB0MSA9IHRoaXMuRi5zcXVhcmUoYVsxXSk7ICAgICAgICAgICAgIC8vIHQxID0gYl4yIDtcbiAgICAgICAgY29uc3QgdDIgPSB0aGlzLkYuc3F1YXJlKGFbMl0pOyAgICAgICAgICAgICAvLyB0MiA9IGNeMjtcbiAgICAgICAgY29uc3QgdDMgPSB0aGlzLkYubXVsKGFbMF0sYVsxXSk7ICAgICAgICAgICAvLyB0MyA9IGFiXG4gICAgICAgIGNvbnN0IHQ0ID0gdGhpcy5GLm11bChhWzBdLGFbMl0pOyAgICAgICAgICAgLy8gdDQgPSBhY1xuICAgICAgICBjb25zdCB0NSA9IHRoaXMuRi5tdWwoYVsxXSxhWzJdKTsgICAgICAgICAgIC8vIHQ1ID0gYmM7XG4gICAgICAgIC8vIGMwID0gdDAgLSBub25fcmVzaWR1ZSAqIHQ1O1xuICAgICAgICBjb25zdCBjMCA9IHRoaXMuRi5zdWIodDAsIHRoaXMuX211bEJ5Tm9uUmVzaWR1ZSh0NSkpO1xuICAgICAgICAvLyBjMSA9IG5vbl9yZXNpZHVlICogdDIgLSB0MztcbiAgICAgICAgY29uc3QgYzEgPSB0aGlzLkYuc3ViKHRoaXMuX211bEJ5Tm9uUmVzaWR1ZSh0MiksIHQzKTtcbiAgICAgICAgY29uc3QgYzIgPSB0aGlzLkYuc3ViKHQxLCB0NCk7ICAgICAgICAgICAgICAvLyBjMiA9IHQxLXQ0XG5cbiAgICAgICAgLy8gdDYgPSAoYSAqIGMwICsgbm9uX3Jlc2lkdWUgKiAoYyAqIGMxICsgYiAqIGMyKSkuaW52KCk7XG4gICAgICAgIGNvbnN0IHQ2ID1cbiAgICAgICAgICAgIHRoaXMuRi5pbnYoXG4gICAgICAgICAgICAgICAgdGhpcy5GLmFkZChcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5GLm11bChhWzBdLCBjMCksXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX211bEJ5Tm9uUmVzaWR1ZShcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuRi5hZGQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5GLm11bChhWzJdLCBjMSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5GLm11bChhWzFdLCBjMikpKSkpO1xuXG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICB0aGlzLkYubXVsKHQ2LCBjMCksICAgICAgICAgLy8gdDYqYzBcbiAgICAgICAgICAgIHRoaXMuRi5tdWwodDYsIGMxKSwgICAgICAgICAvLyB0NipjMVxuICAgICAgICAgICAgdGhpcy5GLm11bCh0NiwgYzIpXTsgICAgICAgIC8vIHQ2KmMyXG4gICAgfVxuXG4gICAgZGl2KGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubXVsKGEsIHRoaXMuaW52KGIpKTtcbiAgICB9XG5cbiAgICBzcXVhcmUoYSkge1xuICAgICAgICBjb25zdCBzMCA9IHRoaXMuRi5zcXVhcmUoYVswXSk7ICAgICAgICAgICAgICAgICAgIC8vIHMwID0gYV4yXG4gICAgICAgIGNvbnN0IGFiID0gdGhpcy5GLm11bChhWzBdLCBhWzFdKTsgICAgICAgICAgICAgICAgLy8gYWIgPSBhKmJcbiAgICAgICAgY29uc3QgczEgPSB0aGlzLkYuYWRkKGFiLCBhYik7ICAgICAgICAgICAgICAgICAgICAvLyBzMSA9IDJhYjtcbiAgICAgICAgY29uc3QgczIgPSB0aGlzLkYuc3F1YXJlKFxuICAgICAgICAgICAgdGhpcy5GLmFkZCh0aGlzLkYuc3ViKGFbMF0sYVsxXSksIGFbMl0pKTsgICAgIC8vIHMyID0gKGEgLSBiICsgYyleMjtcbiAgICAgICAgY29uc3QgYmMgPSB0aGlzLkYubXVsKGFbMV0sYVsyXSk7ICAgICAgICAgICAgICAgICAvLyBiYyA9IGIqY1xuICAgICAgICBjb25zdCBzMyA9IHRoaXMuRi5hZGQoYmMsIGJjKTsgICAgICAgICAgICAgICAgICAgIC8vIHMzID0gMipiY1xuICAgICAgICBjb25zdCBzNCA9IHRoaXMuRi5zcXVhcmUoYVsyXSk7ICAgICAgICAgICAgICAgICAgIC8vIHM0ID0gY14yXG5cblxuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgdGhpcy5GLmFkZChcbiAgICAgICAgICAgICAgICBzMCxcbiAgICAgICAgICAgICAgICB0aGlzLl9tdWxCeU5vblJlc2lkdWUoczMpKSwgICAgICAgICAgIC8vIHMwICsgbm9uX3Jlc2lkdWUgKiBzMyxcbiAgICAgICAgICAgIHRoaXMuRi5hZGQoXG4gICAgICAgICAgICAgICAgczEsXG4gICAgICAgICAgICAgICAgdGhpcy5fbXVsQnlOb25SZXNpZHVlKHM0KSksICAgICAgICAgICAvLyBzMSArIG5vbl9yZXNpZHVlICogczQsXG4gICAgICAgICAgICB0aGlzLkYuc3ViKFxuICAgICAgICAgICAgICAgIHRoaXMuRi5hZGQoIHRoaXMuRi5hZGQoczEsIHMyKSAsIHMzICksXG4gICAgICAgICAgICAgICAgdGhpcy5GLmFkZChzMCwgczQpKV07ICAgICAgICAgICAgICAgICAgICAgIC8vIHMxICsgczIgKyBzMyAtIHMwIC0gczRcbiAgICB9XG5cbiAgICBpc1plcm8oYSkge1xuICAgICAgICByZXR1cm4gdGhpcy5GLmlzWmVybyhhWzBdKSAmJiB0aGlzLkYuaXNaZXJvKGFbMV0pICYmIHRoaXMuRi5pc1plcm8oYVsyXSk7XG4gICAgfVxuXG4gICAgZXEoYSwgYikge1xuICAgICAgICByZXR1cm4gdGhpcy5GLmVxKGFbMF0sIGJbMF0pICYmIHRoaXMuRi5lcShhWzFdLCBiWzFdKSAmJiB0aGlzLkYuZXEoYVsyXSwgYlsyXSk7XG4gICAgfVxuXG4gICAgYWZmaW5lKGEpIHtcbiAgICAgICAgcmV0dXJuIFt0aGlzLkYuYWZmaW5lKGFbMF0pLCB0aGlzLkYuYWZmaW5lKGFbMV0pLCB0aGlzLkYuYWZmaW5lKGFbMl0pXTtcbiAgICB9XG5cbiAgICBtdWxTY2FsYXIoYmFzZSwgZSkge1xuICAgICAgICByZXR1cm4gbXVsU2NhbGFyKHRoaXMsIGJhc2UsIGUpO1xuICAgIH1cblxuICAgIHBvdyhiYXNlLCBlKSB7XG4gICAgICAgIHJldHVybiBleHAodGhpcywgYmFzZSwgZSk7XG4gICAgfVxuXG4gICAgZXhwKGJhc2UsIGUpIHtcbiAgICAgICAgcmV0dXJuIGV4cCh0aGlzLCBiYXNlLCBlKTtcbiAgICB9XG5cbiAgICB0b1N0cmluZyhhKSB7XG4gICAgICAgIHJldHVybiBgWyAke3RoaXMuRi50b1N0cmluZyhhWzBdKX0gLCAke3RoaXMuRi50b1N0cmluZyhhWzFdKX0sICR7dGhpcy5GLnRvU3RyaW5nKGFbMl0pfSBdYDtcbiAgICB9XG5cbiAgICBmcm9tUm5nKHJuZykge1xuICAgICAgICBjb25zdCBjMCA9IHRoaXMuRi5mcm9tUm5nKHJuZyk7XG4gICAgICAgIGNvbnN0IGMxID0gdGhpcy5GLmZyb21Sbmcocm5nKTtcbiAgICAgICAgY29uc3QgYzIgPSB0aGlzLkYuZnJvbVJuZyhybmcpO1xuICAgICAgICByZXR1cm4gW2MwLCBjMSwgYzJdO1xuICAgIH1cblxuICAgIGd0KGEsIGIpIHtcbiAgICAgICAgaWYgKHRoaXMuRi5ndChhWzBdLCBiWzBdKSkgcmV0dXJuIHRydWU7XG4gICAgICAgIGlmICh0aGlzLkYuZ3QoYlswXSwgYVswXSkpIHJldHVybiBmYWxzZTtcbiAgICAgICAgaWYgKHRoaXMuRi5ndChhWzFdLCBiWzFdKSkgcmV0dXJuIHRydWU7XG4gICAgICAgIGlmICh0aGlzLkYuZ3QoYlsxXSwgYVsxXSkpIHJldHVybiBmYWxzZTtcbiAgICAgICAgaWYgKHRoaXMuRi5ndChhWzJdLCBiWzJdKSkgcmV0dXJuIHRydWU7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cblxuICAgIGdlcShhLCBiKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmd0KGEsIGIpIHx8IHRoaXMuZXEoYSwgYik7XG4gICAgfVxuXG4gICAgbHQoYSwgYikge1xuICAgICAgICByZXR1cm4gIXRoaXMuZ2VxKGEsYik7XG4gICAgfVxuXG4gICAgbGVxKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuICF0aGlzLmd0KGEsYik7XG4gICAgfVxuXG4gICAgbmVxKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuICF0aGlzLmVxKGEsYik7XG4gICAgfVxuXG4gICAgcmFuZG9tKCkge1xuICAgICAgICByZXR1cm4gW3RoaXMuRi5yYW5kb20oKSwgdGhpcy5GLnJhbmRvbSgpLCB0aGlzLkYucmFuZG9tKCldO1xuICAgIH1cblxuXG4gICAgdG9ScHJMRShidWZmLCBvLCBlKSB7XG4gICAgICAgIHRoaXMuRi50b1JwckxFKGJ1ZmYsIG8sIGVbMF0pO1xuICAgICAgICB0aGlzLkYudG9ScHJMRShidWZmLCBvK3RoaXMuRi5uOCwgZVsxXSk7XG4gICAgICAgIHRoaXMuRi50b1JwckxFKGJ1ZmYsIG8rdGhpcy5GLm44KjIsIGVbMl0pO1xuICAgIH1cblxuICAgIHRvUnByQkUoYnVmZiwgbywgZSkge1xuICAgICAgICB0aGlzLkYudG9ScHJCRShidWZmLCBvLCBlWzJdKTtcbiAgICAgICAgdGhpcy5GLnRvUnByQkUoYnVmZiwgbyt0aGlzLkYubjgsIGVbMV0pO1xuICAgICAgICB0aGlzLkYudG9ScHJCRShidWZmLCBvK3RoaXMuRi5uOCoyLCBlWzBdKTtcbiAgICB9XG5cbiAgICB0b1JwckxFTShidWZmLCBvLCBlKSB7XG4gICAgICAgIHRoaXMuRi50b1JwckxFTShidWZmLCBvLCBlWzBdKTtcbiAgICAgICAgdGhpcy5GLnRvUnByTEVNKGJ1ZmYsIG8rdGhpcy5GLm44LCBlWzFdKTtcbiAgICAgICAgdGhpcy5GLnRvUnByTEVNKGJ1ZmYsIG8rdGhpcy5GLm44KjIsIGVbMl0pO1xuICAgIH1cblxuXG4gICAgdG9ScHJCRU0oYnVmZiwgbywgZSkge1xuICAgICAgICB0aGlzLkYudG9ScHJCRU0oYnVmZiwgbywgZVsyXSk7XG4gICAgICAgIHRoaXMuRi50b1JwckJFTShidWZmLCBvK3RoaXMuRi5uOCwgZVsxXSk7XG4gICAgICAgIHRoaXMuRi50b1JwckJFTShidWZmLCBvK3RoaXMuRi5uOCoyLCBlWzBdKTtcbiAgICB9XG5cbiAgICBmcm9tUnByTEUoYnVmZiwgbykge1xuICAgICAgICBvID0gbyB8fCAwO1xuICAgICAgICBjb25zdCBjMCA9IHRoaXMuRi5mcm9tUnByTEUoYnVmZiwgbyk7XG4gICAgICAgIGNvbnN0IGMxID0gdGhpcy5GLmZyb21ScHJMRShidWZmLCBvK3RoaXMubjgpO1xuICAgICAgICBjb25zdCBjMiA9IHRoaXMuRi5mcm9tUnByTEUoYnVmZiwgbyt0aGlzLm44KjIpO1xuICAgICAgICByZXR1cm4gW2MwLCBjMSwgYzJdO1xuICAgIH1cblxuICAgIGZyb21ScHJCRShidWZmLCBvKSB7XG4gICAgICAgIG8gPSBvIHx8IDA7XG4gICAgICAgIGNvbnN0IGMyID0gdGhpcy5GLmZyb21ScHJCRShidWZmLCBvKTtcbiAgICAgICAgY29uc3QgYzEgPSB0aGlzLkYuZnJvbVJwckJFKGJ1ZmYsIG8rdGhpcy5uOCk7XG4gICAgICAgIGNvbnN0IGMwID0gdGhpcy5GLmZyb21ScHJCRShidWZmLCBvK3RoaXMubjgqMik7XG4gICAgICAgIHJldHVybiBbYzAsIGMxLCBjMl07XG4gICAgfVxuXG4gICAgZnJvbVJwckxFTShidWZmLCBvKSB7XG4gICAgICAgIG8gPSBvIHx8IDA7XG4gICAgICAgIGNvbnN0IGMwID0gdGhpcy5GLmZyb21ScHJMRU0oYnVmZiwgbyk7XG4gICAgICAgIGNvbnN0IGMxID0gdGhpcy5GLmZyb21ScHJMRU0oYnVmZiwgbyt0aGlzLm44KTtcbiAgICAgICAgY29uc3QgYzIgPSB0aGlzLkYuZnJvbVJwckxFTShidWZmLCBvK3RoaXMubjgqMik7XG4gICAgICAgIHJldHVybiBbYzAsIGMxLCBjMl07XG4gICAgfVxuXG4gICAgZnJvbVJwckJFTShidWZmLCBvKSB7XG4gICAgICAgIG8gPSBvIHx8IDA7XG4gICAgICAgIGNvbnN0IGMyID0gdGhpcy5GLmZyb21ScHJCRU0oYnVmZiwgbyk7XG4gICAgICAgIGNvbnN0IGMxID0gdGhpcy5GLmZyb21ScHJCRU0oYnVmZiwgbyt0aGlzLm44KTtcbiAgICAgICAgY29uc3QgYzAgPSB0aGlzLkYuZnJvbVJwckJFTShidWZmLCBvK3RoaXMubjgqMik7XG4gICAgICAgIHJldHVybiBbYzAsIGMxLCBjMl07XG4gICAgfVxuXG4gICAgdG9PYmplY3QoYSkge1xuICAgICAgICByZXR1cm4gYTtcbiAgICB9XG59XG5cbi8qXG4gICAgQ29weXJpZ2h0IDIwMTggMGtpbXMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya2pzLlxuXG4gICAgc25hcmtqcyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuICAgIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGVcbiAgICBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbilcbiAgICBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJranMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAgICBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3JcbiAgICBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhbG9uZyB3aXRoXG4gICAgc25hcmtqcy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cblxuXG5mdW5jdGlvbiBpc0dyZWF0ZXN0KEYsIGEpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShhKSkge1xuICAgICAgICBmb3IgKGxldCBpPWEubGVuZ3RoLTE7IGk+PTA7IGktLSkge1xuICAgICAgICAgICAgaWYgKCFGLkYuaXNaZXJvKGFbaV0pKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzR3JlYXRlc3QoRi5GLCBhW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMDtcbiAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBuYSA9IEYubmVnKGEpO1xuICAgICAgICByZXR1cm4gZ3QoYSwgbmEpO1xuICAgIH1cbn1cblxuXG5jbGFzcyBFQyB7XG5cbiAgICBjb25zdHJ1Y3RvcihGLCBnKSB7XG4gICAgICAgIHRoaXMuRiA9IEY7XG4gICAgICAgIHRoaXMuZyA9IGc7XG4gICAgICAgIGlmICh0aGlzLmcubGVuZ3RoID09IDIpIHRoaXMuZ1syXSA9IHRoaXMuRi5vbmU7XG4gICAgICAgIHRoaXMuemVybyA9IFt0aGlzLkYuemVybywgdGhpcy5GLm9uZSwgdGhpcy5GLnplcm9dO1xuICAgIH1cblxuICAgIGFkZChwMSwgcDIpIHtcblxuICAgICAgICBjb25zdCBGID0gdGhpcy5GO1xuXG4gICAgICAgIGlmICh0aGlzLmVxKHAxLCB0aGlzLnplcm8pKSByZXR1cm4gcDI7XG4gICAgICAgIGlmICh0aGlzLmVxKHAyLCB0aGlzLnplcm8pKSByZXR1cm4gcDE7XG5cbiAgICAgICAgY29uc3QgcmVzID0gbmV3IEFycmF5KDMpO1xuXG4gICAgICAgIGNvbnN0IFoxWjEgPSBGLnNxdWFyZSggcDFbMl0gKTtcbiAgICAgICAgY29uc3QgWjJaMiA9IEYuc3F1YXJlKCBwMlsyXSApO1xuXG4gICAgICAgIGNvbnN0IFUxID0gRi5tdWwoIHAxWzBdICwgWjJaMiApOyAgICAgLy8gVTEgPSBYMSAgKiBaMloyXG4gICAgICAgIGNvbnN0IFUyID0gRi5tdWwoIHAyWzBdICwgWjFaMSApOyAgICAgLy8gVTIgPSBYMiAgKiBaMVoxXG5cbiAgICAgICAgY29uc3QgWjFfY3ViZWQgPSBGLm11bCggcDFbMl0gLCBaMVoxKTtcbiAgICAgICAgY29uc3QgWjJfY3ViZWQgPSBGLm11bCggcDJbMl0gLCBaMloyKTtcblxuICAgICAgICBjb25zdCBTMSA9IEYubXVsKCBwMVsxXSAsIFoyX2N1YmVkKTsgIC8vIFMxID0gWTEgKiBaMiAqIFoyWjJcbiAgICAgICAgY29uc3QgUzIgPSBGLm11bCggcDJbMV0gLCBaMV9jdWJlZCk7ICAvLyBTMiA9IFkyICogWjEgKiBaMVoxXG5cbiAgICAgICAgaWYgKEYuZXEoVTEsVTIpICYmIEYuZXEoUzEsUzIpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kb3VibGUocDEpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgSCA9IEYuc3ViKCBVMiAsIFUxICk7ICAgICAgICAgICAgICAgICAgICAvLyBIID0gVTItVTFcblxuICAgICAgICBjb25zdCBTMl9taW51c19TMSA9IEYuc3ViKCBTMiAsIFMxICk7XG5cbiAgICAgICAgY29uc3QgSSA9IEYuc3F1YXJlKCBGLmFkZChILEgpICk7ICAgICAgICAgLy8gSSA9ICgyICogSCleMlxuICAgICAgICBjb25zdCBKID0gRi5tdWwoIEggLCBJICk7ICAgICAgICAgICAgICAgICAgICAgIC8vIEogPSBIICogSVxuXG4gICAgICAgIGNvbnN0IHIgPSBGLmFkZCggUzJfbWludXNfUzEgLCBTMl9taW51c19TMSApOyAgLy8gciA9IDIgKiAoUzItUzEpXG4gICAgICAgIGNvbnN0IFYgPSBGLm11bCggVTEgLCBJICk7ICAgICAgICAgICAgICAgICAgICAgLy8gViA9IFUxICogSVxuXG4gICAgICAgIHJlc1swXSA9XG4gICAgICAgICAgICBGLnN1YihcbiAgICAgICAgICAgICAgICBGLnN1YiggRi5zcXVhcmUocikgLCBKICksXG4gICAgICAgICAgICAgICAgRi5hZGQoIFYgLCBWICkpOyAgICAgICAgICAgICAgICAgICAgICAgLy8gWDMgPSByXjIgLSBKIC0gMiAqIFZcblxuICAgICAgICBjb25zdCBTMV9KID0gRi5tdWwoIFMxICwgSiApO1xuXG4gICAgICAgIHJlc1sxXSA9XG4gICAgICAgICAgICBGLnN1YihcbiAgICAgICAgICAgICAgICBGLm11bCggciAsIEYuc3ViKFYscmVzWzBdKSksXG4gICAgICAgICAgICAgICAgRi5hZGQoIFMxX0osUzFfSiApKTsgICAgICAgICAgICAgICAgICAgLy8gWTMgPSByICogKFYtWDMpLTIgUzEgSlxuXG4gICAgICAgIHJlc1syXSA9XG4gICAgICAgICAgICBGLm11bChcbiAgICAgICAgICAgICAgICBILFxuICAgICAgICAgICAgICAgIEYuc3ViKFxuICAgICAgICAgICAgICAgICAgICBGLnNxdWFyZSggRi5hZGQocDFbMl0scDJbMl0pICksXG4gICAgICAgICAgICAgICAgICAgIEYuYWRkKCBaMVoxICwgWjJaMiApKSk7ICAgICAgICAgICAgLy8gWjMgPSAoKFoxK1oyKV4yLVoxWjEtWjJaMikgKiBIXG5cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICBuZWcocCkge1xuICAgICAgICByZXR1cm4gW3BbMF0sIHRoaXMuRi5uZWcocFsxXSksIHBbMl1dO1xuICAgIH1cblxuICAgIHN1YihhLCBiKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmFkZChhLCB0aGlzLm5lZyhiKSk7XG4gICAgfVxuXG4gICAgZG91YmxlKHApIHtcbiAgICAgICAgY29uc3QgRiA9IHRoaXMuRjtcblxuICAgICAgICBjb25zdCByZXMgPSBuZXcgQXJyYXkoMyk7XG5cbiAgICAgICAgaWYgKHRoaXMuZXEocCwgdGhpcy56ZXJvKSkgcmV0dXJuIHA7XG5cbiAgICAgICAgY29uc3QgQSA9IEYuc3F1YXJlKCBwWzBdICk7ICAgICAgICAgICAgICAgICAgICAvLyBBID0gWDFeMlxuICAgICAgICBjb25zdCBCID0gRi5zcXVhcmUoIHBbMV0gKTsgICAgICAgICAgICAgICAgICAgIC8vIEIgPSBZMV4yXG4gICAgICAgIGNvbnN0IEMgPSBGLnNxdWFyZSggQiApOyAgICAgICAgICAgICAgICAgICAgICAgLy8gQyA9IEJeMlxuXG4gICAgICAgIGxldCBEID1cbiAgICAgICAgICAgIEYuc3ViKFxuICAgICAgICAgICAgICAgIEYuc3F1YXJlKCBGLmFkZChwWzBdICwgQiApKSxcbiAgICAgICAgICAgICAgICBGLmFkZCggQSAsIEMpKTtcbiAgICAgICAgRCA9IEYuYWRkKEQsRCk7ICAgICAgICAgICAgICAgICAgICAvLyBEID0gMiAqICgoWDEgKyBCKV4yIC0gQSAtIEMpXG5cbiAgICAgICAgY29uc3QgRSA9IEYuYWRkKCBGLmFkZChBLEEpLCBBKTsgICAgICAgICAgLy8gRSA9IDMgKiBBXG4gICAgICAgIGNvbnN0IEZGID1GLnNxdWFyZSggRSApOyAgICAgICAgICAgICAgICAgICAgICAgLy8gRiA9IEVeMlxuXG4gICAgICAgIHJlc1swXSA9IEYuc3ViKCBGRiAsIEYuYWRkKEQsRCkgKTsgICAgICAgICAvLyBYMyA9IEYgLSAyIERcblxuICAgICAgICBsZXQgZWlnaHRDID0gRi5hZGQoIEMgLCBDICk7XG4gICAgICAgIGVpZ2h0QyA9IEYuYWRkKCBlaWdodEMgLCBlaWdodEMgKTtcbiAgICAgICAgZWlnaHRDID0gRi5hZGQoIGVpZ2h0QyAsIGVpZ2h0QyApO1xuXG4gICAgICAgIHJlc1sxXSA9XG4gICAgICAgICAgICBGLnN1YihcbiAgICAgICAgICAgICAgICBGLm11bChcbiAgICAgICAgICAgICAgICAgICAgRSxcbiAgICAgICAgICAgICAgICAgICAgRi5zdWIoIEQsIHJlc1swXSApKSxcbiAgICAgICAgICAgICAgICBlaWdodEMpOyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFkzID0gRSAqIChEIC0gWDMpIC0gOCAqIENcblxuICAgICAgICBjb25zdCBZMVoxID0gRi5tdWwoIHBbMV0gLCBwWzJdICk7XG4gICAgICAgIHJlc1syXSA9IEYuYWRkKCBZMVoxICwgWTFaMSApOyAgICAgICAgICAgICAgICAgLy8gWjMgPSAyICogWTEgKiBaMVxuXG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuXG4gICAgdGltZXNTY2FsYXIoYmFzZSwgZSkge1xuICAgICAgICByZXR1cm4gbXVsU2NhbGFyKHRoaXMsIGJhc2UsIGUpO1xuICAgIH1cblxuICAgIG11bFNjYWxhcihiYXNlLCBlKSB7XG4gICAgICAgIHJldHVybiBtdWxTY2FsYXIodGhpcywgYmFzZSwgZSk7XG4gICAgfVxuXG4gICAgYWZmaW5lKHApIHtcbiAgICAgICAgY29uc3QgRiA9IHRoaXMuRjtcbiAgICAgICAgaWYgKHRoaXMuaXNaZXJvKHApKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy56ZXJvO1xuICAgICAgICB9IGVsc2UgaWYgKEYuZXEocFsyXSwgRi5vbmUpKSB7XG4gICAgICAgICAgICByZXR1cm4gcDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IFpfaW52ID0gRi5pbnYocFsyXSk7XG4gICAgICAgICAgICBjb25zdCBaMl9pbnYgPSBGLnNxdWFyZShaX2ludik7XG4gICAgICAgICAgICBjb25zdCBaM19pbnYgPSBGLm11bChaMl9pbnYsIFpfaW52KTtcblxuICAgICAgICAgICAgY29uc3QgcmVzID0gbmV3IEFycmF5KDMpO1xuICAgICAgICAgICAgcmVzWzBdID0gRi5tdWwocFswXSxaMl9pbnYpO1xuICAgICAgICAgICAgcmVzWzFdID0gRi5tdWwocFsxXSxaM19pbnYpO1xuICAgICAgICAgICAgcmVzWzJdID0gRi5vbmU7XG5cbiAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBtdWx0aUFmZmluZShhcnIpIHtcbiAgICAgICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKGFycik7XG4gICAgICAgIGNvbnN0IEYgPSB0aGlzLkY7XG4gICAgICAgIGNvbnN0IGFjY011bCA9IG5ldyBBcnJheShrZXlzLmxlbmd0aCsxKTtcbiAgICAgICAgYWNjTXVsWzBdID0gRi5vbmU7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoRi5lcShhcnJba2V5c1tpXV1bMl0sIEYuemVybykpIHtcbiAgICAgICAgICAgICAgICBhY2NNdWxbaSsxXSA9IGFjY011bFtpXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYWNjTXVsW2krMV0gPSBGLm11bChhY2NNdWxbaV0sIGFycltrZXlzW2ldXVsyXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBhY2NNdWxba2V5cy5sZW5ndGhdID0gRi5pbnYoYWNjTXVsW2tleXMubGVuZ3RoXSk7XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IGtleXMubGVuZ3RoLTE7IGk+PTA7IGktLSkge1xuICAgICAgICAgICAgaWYgKEYuZXEoYXJyW2tleXNbaV1dWzJdLCBGLnplcm8pKSB7XG4gICAgICAgICAgICAgICAgYWNjTXVsW2ldID0gYWNjTXVsW2krMV07XG4gICAgICAgICAgICAgICAgYXJyW2tleXNbaV1dID0gdGhpcy56ZXJvO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBaX2ludiA9IEYubXVsKGFjY011bFtpXSwgYWNjTXVsW2krMV0pO1xuICAgICAgICAgICAgICAgIGFjY011bFtpXSA9IEYubXVsKGFycltrZXlzW2ldXVsyXSwgYWNjTXVsW2krMV0pO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgWjJfaW52ID0gRi5zcXVhcmUoWl9pbnYpO1xuICAgICAgICAgICAgICAgIGNvbnN0IFozX2ludiA9IEYubXVsKFoyX2ludiwgWl9pbnYpO1xuXG4gICAgICAgICAgICAgICAgYXJyW2tleXNbaV1dWzBdID0gRi5tdWwoYXJyW2tleXNbaV1dWzBdLFoyX2ludik7XG4gICAgICAgICAgICAgICAgYXJyW2tleXNbaV1dWzFdID0gRi5tdWwoYXJyW2tleXNbaV1dWzFdLFozX2ludik7XG4gICAgICAgICAgICAgICAgYXJyW2tleXNbaV1dWzJdID0gRi5vbmU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgIH1cblxuICAgIGVxKHAxLCBwMikge1xuICAgICAgICBjb25zdCBGID0gdGhpcy5GO1xuXG4gICAgICAgIGlmICh0aGlzLkYuZXEocDFbMl0sIHRoaXMuRi56ZXJvKSkgcmV0dXJuIHRoaXMuRi5lcShwMlsyXSwgdGhpcy5GLnplcm8pO1xuICAgICAgICBpZiAodGhpcy5GLmVxKHAyWzJdLCB0aGlzLkYuemVybykpIHJldHVybiBmYWxzZTtcblxuICAgICAgICBjb25zdCBaMVoxID0gRi5zcXVhcmUoIHAxWzJdICk7XG4gICAgICAgIGNvbnN0IFoyWjIgPSBGLnNxdWFyZSggcDJbMl0gKTtcblxuICAgICAgICBjb25zdCBVMSA9IEYubXVsKCBwMVswXSAsIFoyWjIgKTtcbiAgICAgICAgY29uc3QgVTIgPSBGLm11bCggcDJbMF0gLCBaMVoxICk7XG5cbiAgICAgICAgY29uc3QgWjFfY3ViZWQgPSBGLm11bCggcDFbMl0gLCBaMVoxKTtcbiAgICAgICAgY29uc3QgWjJfY3ViZWQgPSBGLm11bCggcDJbMl0gLCBaMloyKTtcblxuICAgICAgICBjb25zdCBTMSA9IEYubXVsKCBwMVsxXSAsIFoyX2N1YmVkKTtcbiAgICAgICAgY29uc3QgUzIgPSBGLm11bCggcDJbMV0gLCBaMV9jdWJlZCk7XG5cbiAgICAgICAgcmV0dXJuIChGLmVxKFUxLFUyKSAmJiBGLmVxKFMxLFMyKSk7XG4gICAgfVxuXG4gICAgaXNaZXJvKHApIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuRi5pc1plcm8ocFsyXSk7XG4gICAgfVxuXG4gICAgdG9TdHJpbmcocCkge1xuICAgICAgICBjb25zdCBjcCA9IHRoaXMuYWZmaW5lKHApO1xuICAgICAgICByZXR1cm4gYFsgJHt0aGlzLkYudG9TdHJpbmcoY3BbMF0pfSAsICR7dGhpcy5GLnRvU3RyaW5nKGNwWzFdKX0gXWA7XG4gICAgfVxuXG4gICAgZnJvbVJuZyhybmcpIHtcbiAgICAgICAgY29uc3QgRiA9IHRoaXMuRjtcbiAgICAgICAgbGV0IFAgPSBbXTtcbiAgICAgICAgbGV0IGdyZWF0ZXN0O1xuICAgICAgICBkbyB7XG4gICAgICAgICAgICBQWzBdID0gRi5mcm9tUm5nKHJuZyk7XG4gICAgICAgICAgICBncmVhdGVzdCA9IHJuZy5uZXh0Qm9vbCgpO1xuICAgICAgICAgICAgY29uc3QgeDNiID0gRi5hZGQoRi5tdWwoRi5zcXVhcmUoUFswXSksIFBbMF0pLCB0aGlzLmIpO1xuICAgICAgICAgICAgUFsxXSA9IEYuc3FydCh4M2IpO1xuICAgICAgICB9IHdoaWxlICgoUFsxXSA9PSBudWxsKXx8KEYuaXNaZXJvW1BdKSk7XG5cbiAgICAgICAgY29uc3QgcyA9IGlzR3JlYXRlc3QoRiwgUFsxXSk7XG4gICAgICAgIGlmIChncmVhdGVzdCBeIHMpIFBbMV0gPSBGLm5lZyhQWzFdKTtcbiAgICAgICAgUFsyXSA9IEYub25lO1xuXG4gICAgICAgIGlmICh0aGlzLmNvZmFjdG9yKSB7XG4gICAgICAgICAgICBQID0gdGhpcy5tdWxTY2FsYXIoUCwgdGhpcy5jb2ZhY3Rvcik7XG4gICAgICAgIH1cblxuICAgICAgICBQID0gdGhpcy5hZmZpbmUoUCk7XG5cbiAgICAgICAgcmV0dXJuIFA7XG5cbiAgICB9XG5cbiAgICB0b1JwckxFKGJ1ZmYsIG8sIHApIHtcbiAgICAgICAgcCA9IHRoaXMuYWZmaW5lKHApO1xuICAgICAgICBpZiAodGhpcy5pc1plcm8ocCkpIHtcbiAgICAgICAgICAgIGNvbnN0IEJ1ZmZWID0gbmV3IFVpbnQ4QXJyYXkoYnVmZiwgbywgdGhpcy5GLm44KjIpO1xuICAgICAgICAgICAgQnVmZlYuZmlsbCgwKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLkYudG9ScHJMRShidWZmLCBvLCBwWzBdKTtcbiAgICAgICAgdGhpcy5GLnRvUnByTEUoYnVmZiwgbyt0aGlzLkYubjgsIHBbMV0pO1xuICAgIH1cblxuICAgIHRvUnByQkUoYnVmZiwgbywgcCkge1xuICAgICAgICBwID0gdGhpcy5hZmZpbmUocCk7XG4gICAgICAgIGlmICh0aGlzLmlzWmVybyhwKSkge1xuICAgICAgICAgICAgY29uc3QgQnVmZlYgPSBuZXcgVWludDhBcnJheShidWZmLCBvLCB0aGlzLkYubjgqMik7XG4gICAgICAgICAgICBCdWZmVi5maWxsKDApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuRi50b1JwckJFKGJ1ZmYsIG8sIHBbMF0pO1xuICAgICAgICB0aGlzLkYudG9ScHJCRShidWZmLCBvK3RoaXMuRi5uOCwgcFsxXSk7XG4gICAgfVxuXG4gICAgdG9ScHJMRU0oYnVmZiwgbywgcCkge1xuICAgICAgICBwID0gdGhpcy5hZmZpbmUocCk7XG4gICAgICAgIGlmICh0aGlzLmlzWmVybyhwKSkge1xuICAgICAgICAgICAgY29uc3QgQnVmZlYgPSBuZXcgVWludDhBcnJheShidWZmLCBvLCB0aGlzLkYubjgqMik7XG4gICAgICAgICAgICBCdWZmVi5maWxsKDApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuRi50b1JwckxFTShidWZmLCBvLCBwWzBdKTtcbiAgICAgICAgdGhpcy5GLnRvUnByTEVNKGJ1ZmYsIG8rdGhpcy5GLm44LCBwWzFdKTtcbiAgICB9XG5cbiAgICB0b1JwckxFSk0oYnVmZiwgbywgcCkge1xuICAgICAgICBwID0gdGhpcy5hZmZpbmUocCk7XG4gICAgICAgIGlmICh0aGlzLmlzWmVybyhwKSkge1xuICAgICAgICAgICAgY29uc3QgQnVmZlYgPSBuZXcgVWludDhBcnJheShidWZmLCBvLCB0aGlzLkYubjgqMik7XG4gICAgICAgICAgICBCdWZmVi5maWxsKDApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuRi50b1JwckxFTShidWZmLCBvLCBwWzBdKTtcbiAgICAgICAgdGhpcy5GLnRvUnByTEVNKGJ1ZmYsIG8rdGhpcy5GLm44LCBwWzFdKTtcbiAgICAgICAgdGhpcy5GLnRvUnByTEVNKGJ1ZmYsIG8rMip0aGlzLkYubjgsIHBbMl0pO1xuICAgIH1cblxuXG4gICAgdG9ScHJCRU0oYnVmZiwgbywgcCkge1xuICAgICAgICBwID0gdGhpcy5hZmZpbmUocCk7XG4gICAgICAgIGlmICh0aGlzLmlzWmVybyhwKSkge1xuICAgICAgICAgICAgY29uc3QgQnVmZlYgPSBuZXcgVWludDhBcnJheShidWZmLCBvLCB0aGlzLkYubjgqMik7XG4gICAgICAgICAgICBCdWZmVi5maWxsKDApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuRi50b1JwckJFTShidWZmLCBvLCBwWzBdKTtcbiAgICAgICAgdGhpcy5GLnRvUnByQkVNKGJ1ZmYsIG8rdGhpcy5GLm44LCBwWzFdKTtcbiAgICB9XG5cbiAgICBmcm9tUnByTEUoYnVmZiwgbykge1xuICAgICAgICBvID0gbyB8fCAwO1xuICAgICAgICBjb25zdCB4ID0gdGhpcy5GLmZyb21ScHJMRShidWZmLCBvKTtcbiAgICAgICAgY29uc3QgeSA9IHRoaXMuRi5mcm9tUnByTEUoYnVmZiwgbyt0aGlzLkYubjgpO1xuICAgICAgICBpZiAodGhpcy5GLmlzWmVybyh4KSAmJiB0aGlzLkYuaXNaZXJvKHkpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy56ZXJvO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBbeCwgeSwgdGhpcy5GLm9uZV07XG4gICAgfVxuXG4gICAgZnJvbVJwckJFKGJ1ZmYsIG8pIHtcbiAgICAgICAgbyA9IG8gfHwgMDtcbiAgICAgICAgY29uc3QgeCA9IHRoaXMuRi5mcm9tUnByQkUoYnVmZiwgbyk7XG4gICAgICAgIGNvbnN0IHkgPSB0aGlzLkYuZnJvbVJwckJFKGJ1ZmYsIG8rdGhpcy5GLm44KTtcbiAgICAgICAgaWYgKHRoaXMuRi5pc1plcm8oeCkgJiYgdGhpcy5GLmlzWmVybyh5KSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuemVybztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gW3gsIHksIHRoaXMuRi5vbmVdO1xuICAgIH1cblxuICAgIGZyb21ScHJMRU0oYnVmZiwgbykge1xuICAgICAgICBvID0gbyB8fCAwO1xuICAgICAgICBjb25zdCB4ID0gdGhpcy5GLmZyb21ScHJMRU0oYnVmZiwgbyk7XG4gICAgICAgIGNvbnN0IHkgPSB0aGlzLkYuZnJvbVJwckxFTShidWZmLCBvK3RoaXMuRi5uOCk7XG4gICAgICAgIGlmICh0aGlzLkYuaXNaZXJvKHgpICYmIHRoaXMuRi5pc1plcm8oeSkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnplcm87XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFt4LCB5LCB0aGlzLkYub25lXTtcbiAgICB9XG5cbiAgICBmcm9tUnByTEVKTShidWZmLCBvKSB7XG4gICAgICAgIG8gPSBvIHx8IDA7XG4gICAgICAgIGNvbnN0IHggPSB0aGlzLkYuZnJvbVJwckxFTShidWZmLCBvKTtcbiAgICAgICAgY29uc3QgeSA9IHRoaXMuRi5mcm9tUnByTEVNKGJ1ZmYsIG8rdGhpcy5GLm44KTtcbiAgICAgICAgY29uc3QgeiA9IHRoaXMuRi5mcm9tUnByTEVNKGJ1ZmYsIG8rdGhpcy5GLm44KjIpO1xuICAgICAgICBpZiAodGhpcy5GLmlzWmVybyh4KSAmJiB0aGlzLkYuaXNaZXJvKHkpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy56ZXJvO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBbeCwgeSwgel07XG4gICAgfVxuXG4gICAgZnJvbVJwckJFTShidWZmLCBvKSB7XG4gICAgICAgIG8gPSBvIHx8IDA7XG4gICAgICAgIGNvbnN0IHggPSB0aGlzLkYuZnJvbVJwckJFTShidWZmLCBvKTtcbiAgICAgICAgY29uc3QgeSA9IHRoaXMuRi5mcm9tUnByQkVNKGJ1ZmYsIG8rdGhpcy5GLm44KTtcbiAgICAgICAgaWYgKHRoaXMuRi5pc1plcm8oeCkgJiYgdGhpcy5GLmlzWmVybyh5KSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuemVybztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gW3gsIHksIHRoaXMuRi5vbmVdO1xuICAgIH1cblxuICAgIGZyb21ScHJDb21wcmVzc2VkKGJ1ZmYsIG8pIHtcbiAgICAgICAgY29uc3QgRiA9IHRoaXMuRjtcbiAgICAgICAgY29uc3QgdiA9IG5ldyBVaW50OEFycmF5KGJ1ZmYuYnVmZmVyLCBvLCBGLm44KTtcbiAgICAgICAgaWYgKHZbMF0gJiAweDQwKSByZXR1cm4gdGhpcy56ZXJvO1xuICAgICAgICBjb25zdCBQID0gbmV3IEFycmF5KDMpO1xuXG4gICAgICAgIGNvbnN0IGdyZWF0ZXN0ID0gKCh2WzBdICYgMHg4MCkgIT0gMCk7XG4gICAgICAgIHZbMF0gPSB2WzBdICYgMHg3RjtcbiAgICAgICAgUFswXSA9IEYuZnJvbVJwckJFKGJ1ZmYsIG8pO1xuICAgICAgICBpZiAoZ3JlYXRlc3QpIHZbMF0gPSB2WzBdIHwgMHg4MDsgIC8vIHNldCBiYWNrIGFnYWluIHRoZSBvbGQgdmFsdWVcblxuICAgICAgICBjb25zdCB4M2IgPSBGLmFkZChGLm11bChGLnNxdWFyZShQWzBdKSwgUFswXSksIHRoaXMuYik7XG4gICAgICAgIFBbMV0gPSBGLnNxcnQoeDNiKTtcblxuICAgICAgICBpZiAoUFsxXSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBQb2ludCFcIik7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBzID0gaXNHcmVhdGVzdChGLCBQWzFdKTtcbiAgICAgICAgaWYgKGdyZWF0ZXN0IF4gcykgUFsxXSA9IEYubmVnKFBbMV0pO1xuICAgICAgICBQWzJdID0gRi5vbmU7XG5cbiAgICAgICAgcmV0dXJuIFA7XG4gICAgfVxuXG4gICAgdG9ScHJDb21wcmVzc2VkKGJ1ZmYsIG8sIHApIHtcbiAgICAgICAgcCA9IHRoaXMuYWZmaW5lKHApO1xuICAgICAgICBjb25zdCB2ID0gbmV3IFVpbnQ4QXJyYXkoYnVmZi5idWZmZXIsIG8sIHRoaXMuRi5uOCk7XG4gICAgICAgIGlmICh0aGlzLmlzWmVybyhwKSkge1xuICAgICAgICAgICAgdi5maWxsKDApO1xuICAgICAgICAgICAgdlswXSA9IDB4NDA7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5GLnRvUnByQkUoYnVmZiwgbywgcFswXSk7XG5cbiAgICAgICAgaWYgKGlzR3JlYXRlc3QodGhpcy5GLCBwWzFdKSkge1xuICAgICAgICAgICAgdlswXSA9IHZbMF0gfCAweDgwO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICBmcm9tUnByVW5jb21wcmVzc2VkKGJ1ZmYsIG8pIHtcbiAgICAgICAgaWYgKGJ1ZmZbMF0gJiAweDQwKSByZXR1cm4gdGhpcy56ZXJvO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmZyb21ScHJCRShidWZmLCBvKTtcbiAgICB9XG5cbiAgICB0b1JwclVuY29tcHJlc3NlZChidWZmLCBvLCBwKSB7XG4gICAgICAgIHRoaXMudG9ScHJCRShidWZmLCBvLCBwKTtcblxuICAgICAgICBpZiAodGhpcy5pc1plcm8ocCkpIHtcbiAgICAgICAgICAgIGJ1ZmZbb10gPSBidWZmW29dIHwgMHg0MDtcbiAgICAgICAgfVxuICAgIH1cblxuXG59XG5cbi8qIGdsb2JhbCBCaWdJbnQgKi9cblxuZnVuY3Rpb24gc3RyaW5naWZ5QmlnSW50cyhvKSB7XG4gICAgaWYgKHR5cGVvZiBvID09IFwiYmlnaW50XCIgfHwgby5lcSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBvLnRvU3RyaW5nKDEwKTtcbiAgICB9IGVsc2UgaWYgKG8gaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7XG4gICAgICAgIHJldHVybiBmcm9tUnByTEUobywgMCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KG8pKSB7XG4gICAgICAgIHJldHVybiBvLm1hcChzdHJpbmdpZnlCaWdJbnRzKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBvID09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgY29uc3QgcmVzID0ge307XG4gICAgICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhvKTtcbiAgICAgICAga2V5cy5mb3JFYWNoKChrKSA9PiB7XG4gICAgICAgICAgICByZXNba10gPSBzdHJpbmdpZnlCaWdJbnRzKG9ba10pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbztcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHVuc3RyaW5naWZ5QmlnSW50cyhvKSB7XG4gICAgaWYgKHR5cGVvZiBvID09IFwic3RyaW5nXCIgJiYgL15bMC05XSskLy50ZXN0KG8pKSB7XG4gICAgICAgIHJldHVybiBCaWdJbnQobyk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgbyA9PSBcInN0cmluZ1wiICYmIC9eMHhbMC05YS1mQS1GXSskLy50ZXN0KG8pKSB7XG4gICAgICAgIHJldHVybiBCaWdJbnQobyk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KG8pKSB7XG4gICAgICAgIHJldHVybiBvLm1hcCh1bnN0cmluZ2lmeUJpZ0ludHMpO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIG8gPT0gXCJvYmplY3RcIikge1xuICAgICAgICBpZiAobyA9PT0gbnVsbCkgcmV0dXJuIG51bGw7XG4gICAgICAgIGNvbnN0IHJlcyA9IHt9O1xuICAgICAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMobyk7XG4gICAgICAgIGtleXMuZm9yRWFjaCgoaykgPT4ge1xuICAgICAgICAgICAgcmVzW2tdID0gdW5zdHJpbmdpZnlCaWdJbnRzKG9ba10pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbztcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGJlQnVmZjJpbnQoYnVmZikge1xuICAgIGxldCByZXMgPSBCaWdJbnQoMCk7XG4gICAgbGV0IGkgPSBidWZmLmxlbmd0aDtcbiAgICBsZXQgb2Zmc2V0ID0gMDtcbiAgICBjb25zdCBidWZmViA9IG5ldyBEYXRhVmlldyhidWZmLmJ1ZmZlciwgYnVmZi5ieXRlT2Zmc2V0LCBidWZmLmJ5dGVMZW5ndGgpO1xuICAgIHdoaWxlIChpID4gMCkge1xuICAgICAgICBpZiAoaSA+PSA0KSB7XG4gICAgICAgICAgICBpIC09IDQ7XG4gICAgICAgICAgICByZXMgKz0gQmlnSW50KGJ1ZmZWLmdldFVpbnQzMihpKSkgPDwgQmlnSW50KG9mZnNldCAqIDgpO1xuICAgICAgICAgICAgb2Zmc2V0ICs9IDQ7XG4gICAgICAgIH0gZWxzZSBpZiAoaSA+PSAyKSB7XG4gICAgICAgICAgICBpIC09IDI7XG4gICAgICAgICAgICByZXMgKz0gQmlnSW50KGJ1ZmZWLmdldFVpbnQxNihpKSkgPDwgQmlnSW50KG9mZnNldCAqIDgpO1xuICAgICAgICAgICAgb2Zmc2V0ICs9IDI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpIC09IDE7XG4gICAgICAgICAgICByZXMgKz0gQmlnSW50KGJ1ZmZWLmdldFVpbnQ4KGkpKSA8PCBCaWdJbnQob2Zmc2V0ICogOCk7XG4gICAgICAgICAgICBvZmZzZXQgKz0gMTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzO1xufVxuXG5mdW5jdGlvbiBiZUludDJCdWZmKG4sIGxlbikge1xuICAgIGxldCByID0gbjtcbiAgICBjb25zdCBidWZmID0gbmV3IFVpbnQ4QXJyYXkobGVuKTtcbiAgICBjb25zdCBidWZmViA9IG5ldyBEYXRhVmlldyhidWZmLmJ1ZmZlcik7XG4gICAgbGV0IG8gPSBsZW47XG4gICAgd2hpbGUgKG8gPiAwKSB7XG4gICAgICAgIGlmIChvIC0gNCA+PSAwKSB7XG4gICAgICAgICAgICBvIC09IDQ7XG4gICAgICAgICAgICBidWZmVi5zZXRVaW50MzIobywgTnVtYmVyKHIgJiBCaWdJbnQoMHhmZmZmZmZmZikpKTtcbiAgICAgICAgICAgIHIgPSByID4+IEJpZ0ludCgzMik7XG4gICAgICAgIH0gZWxzZSBpZiAobyAtIDIgPj0gMCkge1xuICAgICAgICAgICAgbyAtPSAyO1xuICAgICAgICAgICAgYnVmZlYuc2V0VWludDE2KG8sIE51bWJlcihyICYgQmlnSW50KDB4ZmZmZikpKTtcbiAgICAgICAgICAgIHIgPSByID4+IEJpZ0ludCgxNik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBvIC09IDE7XG4gICAgICAgICAgICBidWZmVi5zZXRVaW50OChvLCBOdW1iZXIociAmIEJpZ0ludCgweGZmKSkpO1xuICAgICAgICAgICAgciA9IHIgPj4gQmlnSW50KDgpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmIChyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk51bWJlciBkb2VzIG5vdCBmaXQgaW4gdGhpcyBsZW5ndGhcIik7XG4gICAgfVxuICAgIHJldHVybiBidWZmO1xufVxuXG5mdW5jdGlvbiBsZUJ1ZmYyaW50KGJ1ZmYpIHtcbiAgICBsZXQgcmVzID0gQmlnSW50KDApO1xuICAgIGxldCBpID0gMDtcbiAgICBjb25zdCBidWZmViA9IG5ldyBEYXRhVmlldyhidWZmLmJ1ZmZlciwgYnVmZi5ieXRlT2Zmc2V0LCBidWZmLmJ5dGVMZW5ndGgpO1xuICAgIHdoaWxlIChpIDwgYnVmZi5sZW5ndGgpIHtcbiAgICAgICAgaWYgKGkgKyA0IDw9IGJ1ZmYubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXMgKz0gQmlnSW50KGJ1ZmZWLmdldFVpbnQzMihpLCB0cnVlKSkgPDwgQmlnSW50KGkgKiA4KTtcbiAgICAgICAgICAgIGkgKz0gNDtcbiAgICAgICAgfSBlbHNlIGlmIChpICsgMiA8PSBidWZmLmxlbmd0aCkge1xuICAgICAgICAgICAgcmVzICs9IEJpZ0ludChidWZmVi5nZXRVaW50MTYoaSwgdHJ1ZSkpIDw8IEJpZ0ludChpICogOCk7XG4gICAgICAgICAgICBpICs9IDI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXMgKz0gQmlnSW50KGJ1ZmZWLmdldFVpbnQ4KGksIHRydWUpKSA8PCBCaWdJbnQoaSAqIDgpO1xuICAgICAgICAgICAgaSArPSAxO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXM7XG59XG5cbmZ1bmN0aW9uIGxlSW50MkJ1ZmYobiwgbGVuKSB7XG4gICAgbGV0IHIgPSBuO1xuICAgIGlmICh0eXBlb2YgbGVuID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgIGxlbiA9IE1hdGguZmxvb3IoKGJpdExlbmd0aCQ2KG4pIC0gMSkgLyA4KSArIDE7XG4gICAgICAgIGlmIChsZW4gPT0gMCkgbGVuID0gMTtcbiAgICB9XG4gICAgY29uc3QgYnVmZiA9IG5ldyBVaW50OEFycmF5KGxlbik7XG4gICAgY29uc3QgYnVmZlYgPSBuZXcgRGF0YVZpZXcoYnVmZi5idWZmZXIpO1xuICAgIGxldCBvID0gMDtcbiAgICB3aGlsZSAobyA8IGxlbikge1xuICAgICAgICBpZiAobyArIDQgPD0gbGVuKSB7XG4gICAgICAgICAgICBidWZmVi5zZXRVaW50MzIobywgTnVtYmVyKHIgJiBCaWdJbnQoMHhmZmZmZmZmZikpLCB0cnVlKTtcbiAgICAgICAgICAgIG8gKz0gNDtcbiAgICAgICAgICAgIHIgPSByID4+IEJpZ0ludCgzMik7XG4gICAgICAgIH0gZWxzZSBpZiAobyArIDIgPD0gbGVuKSB7XG4gICAgICAgICAgICBidWZmVi5zZXRVaW50MTYobywgTnVtYmVyKHIgJiBCaWdJbnQoMHhmZmZmKSksIHRydWUpO1xuICAgICAgICAgICAgbyArPSAyO1xuICAgICAgICAgICAgciA9IHIgPj4gQmlnSW50KDE2KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGJ1ZmZWLnNldFVpbnQ4KG8sIE51bWJlcihyICYgQmlnSW50KDB4ZmYpKSwgdHJ1ZSk7XG4gICAgICAgICAgICBvICs9IDE7XG4gICAgICAgICAgICByID0gciA+PiBCaWdJbnQoOCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKHIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTnVtYmVyIGRvZXMgbm90IGZpdCBpbiB0aGlzIGxlbmd0aFwiKTtcbiAgICB9XG4gICAgcmV0dXJuIGJ1ZmY7XG59XG5cbmZ1bmN0aW9uIHN0cmluZ2lmeUZFbGVtZW50cyhGLCBvKSB7XG4gICAgaWYgKHR5cGVvZiBvID09IFwiYmlnaW50XCIgfHwgby5lcSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBvLnRvU3RyaW5nKDEwKTtcbiAgICB9IGVsc2UgaWYgKG8gaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7XG4gICAgICAgIHJldHVybiBGLnRvU3RyaW5nKEYuZShvKSk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KG8pKSB7XG4gICAgICAgIHJldHVybiBvLm1hcChzdHJpbmdpZnlGRWxlbWVudHMuYmluZCh0aGlzLCBGKSk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgbyA9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIGNvbnN0IHJlcyA9IHt9O1xuICAgICAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMobyk7XG4gICAgICAgIGtleXMuZm9yRWFjaCgoaykgPT4ge1xuICAgICAgICAgICAgcmVzW2tdID0gc3RyaW5naWZ5RkVsZW1lbnRzKEYsIG9ba10pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbztcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHVuc3RyaW5naWZ5RkVsZW1lbnRzKEYsIG8pIHtcbiAgICBpZiAodHlwZW9mIG8gPT0gXCJzdHJpbmdcIiAmJiAvXlswLTldKyQvLnRlc3QobykpIHtcbiAgICAgICAgcmV0dXJuIEYuZShvKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBvID09IFwic3RyaW5nXCIgJiYgL14weFswLTlhLWZBLUZdKyQvLnRlc3QobykpIHtcbiAgICAgICAgcmV0dXJuIEYuZShvKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkobykpIHtcbiAgICAgICAgcmV0dXJuIG8ubWFwKHVuc3RyaW5naWZ5RkVsZW1lbnRzLmJpbmQodGhpcywgRikpO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIG8gPT0gXCJvYmplY3RcIikge1xuICAgICAgICBpZiAobyA9PT0gbnVsbCkgcmV0dXJuIG51bGw7XG4gICAgICAgIGNvbnN0IHJlcyA9IHt9O1xuICAgICAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMobyk7XG4gICAgICAgIGtleXMuZm9yRWFjaCgoaykgPT4ge1xuICAgICAgICAgICAgcmVzW2tdID0gdW5zdHJpbmdpZnlGRWxlbWVudHMoRiwgb1trXSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBvO1xuICAgIH1cbn1cblxuY29uc3QgX3JldlRhYmxlID0gW107XG5mb3IgKGxldCBpID0gMDsgaSA8IDI1NjsgaSsrKSB7XG4gICAgX3JldlRhYmxlW2ldID0gX3JldlNsb3coaSwgOCk7XG59XG5cbmZ1bmN0aW9uIF9yZXZTbG93KGlkeCwgYml0cykge1xuICAgIGxldCByZXMgPSAwO1xuICAgIGxldCBhID0gaWR4O1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYml0czsgaSsrKSB7XG4gICAgICAgIHJlcyA8PD0gMTtcbiAgICAgICAgcmVzID0gcmVzIHwgKGEgJiAxKTtcbiAgICAgICAgYSA+Pj0gMTtcbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbn1cblxuZnVuY3Rpb24gYml0UmV2ZXJzZShpZHgsIGJpdHMpIHtcbiAgICByZXR1cm4gKFxuICAgICAgICAoX3JldlRhYmxlW2lkeCA+Pj4gMjRdIHxcbiAgICAgICAgKF9yZXZUYWJsZVsoaWR4ID4+PiAxNikgJiAweGZmXSA8PCA4KSB8XG4gICAgICAgIChfcmV2VGFibGVbKGlkeCA+Pj4gOCkgJiAweGZmXSA8PCAxNikgfFxuICAgICAgICAoX3JldlRhYmxlW2lkeCAmIDB4ZmZdIDw8IDI0KSkgPj4+XG4gICAgICAgICgzMiAtIGJpdHMpXG4gICAgKTtcbn1cblxuZnVuY3Rpb24gbG9nMihWKSB7XG4gICAgcmV0dXJuIChcbiAgICAgICAgKChWICYgMHhmZmZmMDAwMCkgIT09IDAgPyAoKFYgJj0gMHhmZmZmMDAwMCksIDE2KSA6IDApIHxcbiAgICAgICAgKChWICYgMHhmZjAwZmYwMCkgIT09IDAgPyAoKFYgJj0gMHhmZjAwZmYwMCksIDgpIDogMCkgfFxuICAgICAgICAoKFYgJiAweGYwZjBmMGYwKSAhPT0gMCA/ICgoViAmPSAweGYwZjBmMGYwKSwgNCkgOiAwKSB8XG4gICAgICAgICgoViAmIDB4Y2NjY2NjY2MpICE9PSAwID8gKChWICY9IDB4Y2NjY2NjY2MpLCAyKSA6IDApIHxcbiAgICAgICAgKChWICYgMHhhYWFhYWFhYSkgIT09IDApXG4gICAgKTtcbn1cblxuZnVuY3Rpb24gYnVmZlJldmVyc2VCaXRzKGJ1ZmYsIGVTaXplKSB7XG4gICAgY29uc3QgbiA9IGJ1ZmYuYnl0ZUxlbmd0aCAvIGVTaXplO1xuICAgIGNvbnN0IGJpdHMgPSBsb2cyKG4pO1xuICAgIGlmIChuICE9IDEgPDwgYml0cykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIG51bWJlciBvZiBwb2ludGVyc1wiKTtcbiAgICB9XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuOyBpKyspIHtcbiAgICAgICAgY29uc3QgciA9IGJpdFJldmVyc2UoaSwgYml0cyk7XG4gICAgICAgIGlmIChpID4gcikge1xuICAgICAgICAgICAgY29uc3QgdG1wID0gYnVmZi5zbGljZShpICogZVNpemUsIChpICsgMSkgKiBlU2l6ZSk7XG4gICAgICAgICAgICBidWZmLnNldChidWZmLnNsaWNlKHIgKiBlU2l6ZSwgKHIgKyAxKSAqIGVTaXplKSwgaSAqIGVTaXplKTtcbiAgICAgICAgICAgIGJ1ZmYuc2V0KHRtcCwgciAqIGVTaXplKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gYXJyYXkyYnVmZmVyKGFyciwgc0cpIHtcbiAgICBjb25zdCBidWZmID0gbmV3IFVpbnQ4QXJyYXkoc0cgKiBhcnIubGVuZ3RoKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGJ1ZmYuc2V0KGFycltpXSwgaSAqIHNHKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYnVmZjtcbn1cblxuZnVuY3Rpb24gYnVmZmVyMmFycmF5KGJ1ZmYsIHNHKSB7XG4gICAgY29uc3QgbiA9IGJ1ZmYuYnl0ZUxlbmd0aCAvIHNHO1xuICAgIGNvbnN0IGFyciA9IG5ldyBBcnJheShuKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG47IGkrKykge1xuICAgICAgICBhcnJbaV0gPSBidWZmLnNsaWNlKGkgKiBzRywgaSAqIHNHICsgc0cpO1xuICAgIH1cbiAgICByZXR1cm4gYXJyO1xufVxuXG52YXIgX3V0aWxzID0gLyojX19QVVJFX18qL09iamVjdC5mcmVlemUoe1xuICAgIF9fcHJvdG9fXzogbnVsbCxcbiAgICBhcnJheTJidWZmZXI6IGFycmF5MmJ1ZmZlcixcbiAgICBiZUJ1ZmYyaW50OiBiZUJ1ZmYyaW50LFxuICAgIGJlSW50MkJ1ZmY6IGJlSW50MkJ1ZmYsXG4gICAgYml0UmV2ZXJzZTogYml0UmV2ZXJzZSxcbiAgICBidWZmUmV2ZXJzZUJpdHM6IGJ1ZmZSZXZlcnNlQml0cyxcbiAgICBidWZmZXIyYXJyYXk6IGJ1ZmZlcjJhcnJheSxcbiAgICBsZUJ1ZmYyaW50OiBsZUJ1ZmYyaW50LFxuICAgIGxlSW50MkJ1ZmY6IGxlSW50MkJ1ZmYsXG4gICAgbG9nMjogbG9nMixcbiAgICBzdHJpbmdpZnlCaWdJbnRzOiBzdHJpbmdpZnlCaWdJbnRzLFxuICAgIHN0cmluZ2lmeUZFbGVtZW50czogc3RyaW5naWZ5RkVsZW1lbnRzLFxuICAgIHVuc3RyaW5naWZ5QmlnSW50czogdW5zdHJpbmdpZnlCaWdJbnRzLFxuICAgIHVuc3RyaW5naWZ5RkVsZW1lbnRzOiB1bnN0cmluZ2lmeUZFbGVtZW50c1xufSk7XG5cbmNvbnN0IFBBR0VfU0laRSA9ICggdHlwZW9mIEJ1ZmZlciAhPT0gXCJ1bmRlZmluZWRcIiAmJiBCdWZmZXIuY29uc3RhbnRzICYmIEJ1ZmZlci5jb25zdGFudHMuTUFYX0xFTkdUSCApID8gQnVmZmVyLmNvbnN0YW50cy5NQVhfTEVOR1RIIDogKDEgPDwgMzApO1xuXG5jbGFzcyBCaWdCdWZmZXIge1xuXG4gICAgY29uc3RydWN0b3Ioc2l6ZSkge1xuICAgICAgICB0aGlzLmJ1ZmZlcnMgPSBbXTtcbiAgICAgICAgdGhpcy5ieXRlTGVuZ3RoID0gc2l6ZTtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPHNpemU7IGkrPSBQQUdFX1NJWkUpIHtcbiAgICAgICAgICAgIGNvbnN0IG4gPSBNYXRoLm1pbihzaXplLWksIFBBR0VfU0laRSk7XG4gICAgICAgICAgICB0aGlzLmJ1ZmZlcnMucHVzaChuZXcgVWludDhBcnJheShuKSk7XG4gICAgICAgICAgICAvL3RoaXMuYnVmZmVycy5wdXNoKG5ldyBVaW50OEFycmF5KG5ldyBTaGFyZWRBcnJheUJ1ZmZlcihuKSkpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmICh0aGlzLmJ1ZmZlcnMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIC8vICAgICB0aGlzLmJ1ZmZlciA9IHRoaXMuYnVmZmVyc1swXTtcbiAgICAgICAgLy8gfVxuXG4gICAgfVxuXG4gICAgc2xpY2UoZnIsIHRvKSB7XG4gICAgICAgIGlmICggdG8gPT09IHVuZGVmaW5lZCApIHRvID0gdGhpcy5ieXRlTGVuZ3RoO1xuICAgICAgICBpZiAoIGZyID09PSB1bmRlZmluZWQgKSBmciA9IDA7XG4gICAgICAgIGNvbnN0IGxlbiA9IHRvLWZyO1xuXG4gICAgICAgIGNvbnN0IGZpcnN0UGFnZSA9IE1hdGguZmxvb3IoZnIgLyBQQUdFX1NJWkUpO1xuICAgICAgICBjb25zdCBsYXN0UGFnZSA9IE1hdGguZmxvb3IoKGZyK2xlbi0xKSAvIFBBR0VfU0laRSk7XG5cbiAgICAgICAgaWYgKChmaXJzdFBhZ2UgPT0gbGFzdFBhZ2UpfHwobGVuPT0wKSlcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJ1ZmZlcnNbZmlyc3RQYWdlXS5zbGljZShmciVQQUdFX1NJWkUsIGZyJVBBR0VfU0laRSArIGxlbik7XG5cbiAgICAgICAgbGV0IGJ1ZmY7XG5cbiAgICAgICAgbGV0IHAgPSBmaXJzdFBhZ2U7XG4gICAgICAgIGxldCBvID0gZnIgJSBQQUdFX1NJWkU7XG4gICAgICAgIC8vIFJlbWFpbmluZyBieXRlcyB0byByZWFkXG4gICAgICAgIGxldCByID0gbGVuO1xuICAgICAgICB3aGlsZSAocj4wKSB7XG4gICAgICAgICAgICAvLyBieXRlcyB0byBjb3B5IGZyb20gdGhpcyBwYWdlXG4gICAgICAgICAgICBjb25zdCBsID0gKG8rciA+IFBBR0VfU0laRSkgPyAoUEFHRV9TSVpFIC1vKSA6IHI7XG4gICAgICAgICAgICBjb25zdCBzcmNWaWV3ID0gbmV3IFVpbnQ4QXJyYXkodGhpcy5idWZmZXJzW3BdLmJ1ZmZlciwgdGhpcy5idWZmZXJzW3BdLmJ5dGVPZmZzZXQrbywgbCk7XG4gICAgICAgICAgICBpZiAobCA9PSBsZW4pIHJldHVybiBzcmNWaWV3LnNsaWNlKCk7XG4gICAgICAgICAgICBpZiAoIWJ1ZmYpIHtcbiAgICAgICAgICAgICAgICBpZiAobGVuIDw9IFBBR0VfU0laRSkge1xuICAgICAgICAgICAgICAgICAgICBidWZmID0gbmV3IFVpbnQ4QXJyYXkobGVuKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBidWZmID0gbmV3IEJpZ0J1ZmZlcihsZW4pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJ1ZmYuc2V0KHNyY1ZpZXcsIGxlbi1yKTtcbiAgICAgICAgICAgIHIgPSByLWw7XG4gICAgICAgICAgICBwICsrO1xuICAgICAgICAgICAgbyA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYnVmZjtcbiAgICB9XG5cbiAgICBzZXQoYnVmZiwgb2Zmc2V0KSB7XG4gICAgICAgIGlmIChvZmZzZXQgPT09IHVuZGVmaW5lZCkgb2Zmc2V0ID0gMDtcblxuICAgICAgICBjb25zdCBsZW4gPSBidWZmLmJ5dGVMZW5ndGg7XG5cbiAgICAgICAgaWYgKGxlbj09MCkgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IGZpcnN0UGFnZSA9IE1hdGguZmxvb3Iob2Zmc2V0IC8gUEFHRV9TSVpFKTtcbiAgICAgICAgY29uc3QgbGFzdFBhZ2UgPSBNYXRoLmZsb29yKChvZmZzZXQrbGVuLTEpIC8gUEFHRV9TSVpFKTtcblxuICAgICAgICBpZiAoZmlyc3RQYWdlID09IGxhc3RQYWdlKSB7XG4gICAgICAgICAgICBpZiAoKGJ1ZmYgaW5zdGFuY2VvZiBCaWdCdWZmZXIpJiYoYnVmZi5idWZmZXJzLmxlbmd0aD09MSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5idWZmZXJzW2ZpcnN0UGFnZV0uc2V0KGJ1ZmYuYnVmZmVyc1swXSwgb2Zmc2V0ICUgUEFHRV9TSVpFKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYnVmZmVyc1tmaXJzdFBhZ2VdLnNldChidWZmLCBvZmZzZXQgJSBQQUdFX1NJWkUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH1cblxuXG4gICAgICAgIGxldCBwID0gZmlyc3RQYWdlO1xuICAgICAgICBsZXQgbyA9IG9mZnNldCAlIFBBR0VfU0laRTtcbiAgICAgICAgbGV0IHIgPSBsZW47XG4gICAgICAgIHdoaWxlIChyPjApIHtcbiAgICAgICAgICAgIGNvbnN0IGwgPSAobytyID4gUEFHRV9TSVpFKSA/IChQQUdFX1NJWkUgLW8pIDogcjtcbiAgICAgICAgICAgIGNvbnN0IHNyY1ZpZXcgPSBidWZmLnNsaWNlKCBsZW4gLXIsIGxlbiAtcitsKTtcbiAgICAgICAgICAgIGNvbnN0IGRzdFZpZXcgPSBuZXcgVWludDhBcnJheSh0aGlzLmJ1ZmZlcnNbcF0uYnVmZmVyLCB0aGlzLmJ1ZmZlcnNbcF0uYnl0ZU9mZnNldCArIG8sIGwpO1xuICAgICAgICAgICAgZHN0Vmlldy5zZXQoc3JjVmlldyk7XG4gICAgICAgICAgICByID0gci1sO1xuICAgICAgICAgICAgcCArKztcbiAgICAgICAgICAgIG8gPSAwO1xuICAgICAgICB9XG5cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGJ1aWxkQmF0Y2hDb252ZXJ0KHRtLCBmbk5hbWUsIHNJbiwgc091dCkge1xuICAgIHJldHVybiBhc3luYyBmdW5jdGlvbiBiYXRjaENvbnZlcnQoYnVmZkluKSB7XG4gICAgICAgIGNvbnN0IG5Qb2ludHMgPSBNYXRoLmZsb29yKGJ1ZmZJbi5ieXRlTGVuZ3RoIC8gc0luKTtcbiAgICAgICAgaWYgKCBuUG9pbnRzICogc0luICE9PSBidWZmSW4uYnl0ZUxlbmd0aCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBidWZmZXIgc2l6ZVwiKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwb2ludHNQZXJDaHVuayA9IE1hdGguZmxvb3IoblBvaW50cy90bS5jb25jdXJyZW5jeSk7XG4gICAgICAgIGNvbnN0IG9wUHJvbWlzZXMgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPHRtLmNvbmN1cnJlbmN5OyBpKyspIHtcbiAgICAgICAgICAgIGxldCBuO1xuICAgICAgICAgICAgaWYgKGk8IHRtLmNvbmN1cnJlbmN5LTEpIHtcbiAgICAgICAgICAgICAgICBuID0gcG9pbnRzUGVyQ2h1bms7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG4gPSBuUG9pbnRzIC0gaSpwb2ludHNQZXJDaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChuPT0wKSBjb250aW51ZTtcblxuICAgICAgICAgICAgY29uc3QgYnVmZkNodW5rID0gYnVmZkluLnNsaWNlKGkqcG9pbnRzUGVyQ2h1bmsqc0luLCBpKnBvaW50c1BlckNodW5rKnNJbiArIG4qc0luKTtcbiAgICAgICAgICAgIGNvbnN0IHRhc2sgPSBbXG4gICAgICAgICAgICAgICAge2NtZDogXCJBTExPQ1NFVFwiLCB2YXI6IDAsIGJ1ZmY6YnVmZkNodW5rfSxcbiAgICAgICAgICAgICAgICB7Y21kOiBcIkFMTE9DXCIsIHZhcjogMSwgbGVuOnNPdXQgKiBufSxcbiAgICAgICAgICAgICAgICB7Y21kOiBcIkNBTExcIiwgZm5OYW1lOiBmbk5hbWUsIHBhcmFtczogW1xuICAgICAgICAgICAgICAgICAgICB7dmFyOiAwfSxcbiAgICAgICAgICAgICAgICAgICAge3ZhbDogbn0sXG4gICAgICAgICAgICAgICAgICAgIHt2YXI6IDF9XG4gICAgICAgICAgICAgICAgXX0sXG4gICAgICAgICAgICAgICAge2NtZDogXCJHRVRcIiwgb3V0OiAwLCB2YXI6IDEsIGxlbjpzT3V0ICogbn0sXG4gICAgICAgICAgICBdO1xuICAgICAgICAgICAgb3BQcm9taXNlcy5wdXNoKFxuICAgICAgICAgICAgICAgIHRtLnF1ZXVlQWN0aW9uKHRhc2ssIFtidWZmQ2h1bmsuYnVmZmVyXSlcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBQcm9taXNlLmFsbChvcFByb21pc2VzKTtcblxuICAgICAgICBsZXQgZnVsbEJ1ZmZPdXQ7XG4gICAgICAgIGlmIChidWZmSW4gaW5zdGFuY2VvZiBCaWdCdWZmZXIpIHtcbiAgICAgICAgICAgIGZ1bGxCdWZmT3V0ID0gbmV3IEJpZ0J1ZmZlcihuUG9pbnRzKnNPdXQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZnVsbEJ1ZmZPdXQgPSBuZXcgVWludDhBcnJheShuUG9pbnRzKnNPdXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHAgPTA7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxyZXN1bHQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGZ1bGxCdWZmT3V0LnNldChyZXN1bHRbaV1bMF0sIHApO1xuICAgICAgICAgICAgcCs9cmVzdWx0W2ldWzBdLmJ5dGVMZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZnVsbEJ1ZmZPdXQ7XG4gICAgfTtcbn1cblxuY2xhc3MgV2FzbUZpZWxkMSB7XG5cbiAgICBjb25zdHJ1Y3Rvcih0bSwgcHJlZml4LCBuOCwgcCkge1xuICAgICAgICB0aGlzLnRtID0gdG07XG4gICAgICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuXG4gICAgICAgIHRoaXMucCA9IHA7XG4gICAgICAgIHRoaXMubjggPSBuODtcbiAgICAgICAgdGhpcy50eXBlID0gXCJGMVwiO1xuICAgICAgICB0aGlzLm0gPSAxO1xuXG4gICAgICAgIHRoaXMuaGFsZiA9IHNoaWZ0UmlnaHQocCwgb25lKTtcbiAgICAgICAgdGhpcy5iaXRMZW5ndGggPSBiaXRMZW5ndGgkNihwKTtcbiAgICAgICAgdGhpcy5tYXNrID0gc3ViKHNoaWZ0TGVmdChvbmUsIHRoaXMuYml0TGVuZ3RoKSwgb25lKTtcblxuICAgICAgICB0aGlzLnBPcDEgPSB0bS5hbGxvYyhuOCk7XG4gICAgICAgIHRoaXMucE9wMiA9IHRtLmFsbG9jKG44KTtcbiAgICAgICAgdGhpcy5wT3AzID0gdG0uYWxsb2MobjgpO1xuICAgICAgICB0aGlzLnRtLmluc3RhbmNlLmV4cG9ydHNbcHJlZml4ICsgXCJfemVyb1wiXSh0aGlzLnBPcDEpO1xuICAgICAgICB0aGlzLnplcm8gPSB0aGlzLnRtLmdldEJ1ZmYodGhpcy5wT3AxLCB0aGlzLm44KTtcbiAgICAgICAgdGhpcy50bS5pbnN0YW5jZS5leHBvcnRzW3ByZWZpeCArIFwiX29uZVwiXSh0aGlzLnBPcDEpO1xuICAgICAgICB0aGlzLm9uZSA9IHRoaXMudG0uZ2V0QnVmZih0aGlzLnBPcDEsIHRoaXMubjgpO1xuXG4gICAgICAgIHRoaXMubmVnb25lID0gdGhpcy5uZWcodGhpcy5vbmUpO1xuICAgICAgICB0aGlzLnR3byA9IHRoaXMuYWRkKHRoaXMub25lLCB0aGlzLm9uZSk7XG5cbiAgICAgICAgdGhpcy5uNjQgPSBNYXRoLmZsb29yKG44LzgpO1xuICAgICAgICB0aGlzLm4zMiA9IE1hdGguZmxvb3IobjgvNCk7XG5cbiAgICAgICAgaWYodGhpcy5uNjQqOCAhPSB0aGlzLm44KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJuOCBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgOFwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuaGFsZiA9IHNoaWZ0UmlnaHQodGhpcy5wLCBvbmUpO1xuICAgICAgICB0aGlzLm5xciA9IHRoaXMudHdvO1xuICAgICAgICBsZXQgciA9IHRoaXMuZXhwKHRoaXMubnFyLCB0aGlzLmhhbGYpO1xuICAgICAgICB3aGlsZSAoIXRoaXMuZXEociwgdGhpcy5uZWdvbmUpKSB7XG4gICAgICAgICAgICB0aGlzLm5xciA9IHRoaXMuYWRkKHRoaXMubnFyLCB0aGlzLm9uZSk7XG4gICAgICAgICAgICByID0gdGhpcy5leHAodGhpcy5ucXIsIHRoaXMuaGFsZik7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnNoaWZ0ID0gdGhpcy5tdWwodGhpcy5ucXIsIHRoaXMubnFyKTtcbiAgICAgICAgdGhpcy5zaGlmdEludiA9IHRoaXMuaW52KHRoaXMuc2hpZnQpO1xuXG4gICAgICAgIHRoaXMucyA9IDA7XG4gICAgICAgIGxldCB0ID0gc3ViKHRoaXMucCwgb25lKTtcblxuICAgICAgICB3aGlsZSAoICFpc09kZCQ1KHQpICkge1xuICAgICAgICAgICAgdGhpcy5zID0gdGhpcy5zICsgMTtcbiAgICAgICAgICAgIHQgPSBzaGlmdFJpZ2h0KHQsIG9uZSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLncgPSBbXTtcbiAgICAgICAgdGhpcy53W3RoaXMuc10gPSB0aGlzLmV4cCh0aGlzLm5xciwgdCk7XG5cbiAgICAgICAgZm9yIChsZXQgaT0gdGhpcy5zLTE7IGk+PTA7IGktLSkge1xuICAgICAgICAgICAgdGhpcy53W2ldID0gdGhpcy5zcXVhcmUodGhpcy53W2krMV0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0aGlzLmVxKHRoaXMud1swXSwgdGhpcy5vbmUpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJFcnJvciBjYWxjdWxhdGluZyByb290cyBvZiB1bml0eVwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuYmF0Y2hUb01vbnRnb21lcnkgPSBidWlsZEJhdGNoQ29udmVydCh0bSwgcHJlZml4ICsgXCJfYmF0Y2hUb01vbnRnb21lcnlcIiwgdGhpcy5uOCwgdGhpcy5uOCk7XG4gICAgICAgIHRoaXMuYmF0Y2hGcm9tTW9udGdvbWVyeSA9IGJ1aWxkQmF0Y2hDb252ZXJ0KHRtLCBwcmVmaXggKyBcIl9iYXRjaEZyb21Nb250Z29tZXJ5XCIsIHRoaXMubjgsIHRoaXMubjgpO1xuICAgIH1cblxuXG4gICAgb3AyKG9wTmFtZSwgYSwgYikge1xuICAgICAgICB0aGlzLnRtLnNldEJ1ZmYodGhpcy5wT3AxLCBhKTtcbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMiwgYik7XG4gICAgICAgIHRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1t0aGlzLnByZWZpeCArIG9wTmFtZV0odGhpcy5wT3AxLCB0aGlzLnBPcDIsIHRoaXMucE9wMyk7XG4gICAgICAgIHJldHVybiB0aGlzLnRtLmdldEJ1ZmYodGhpcy5wT3AzLCB0aGlzLm44KTtcbiAgICB9XG5cbiAgICBvcDJCb29sKG9wTmFtZSwgYSwgYikge1xuICAgICAgICB0aGlzLnRtLnNldEJ1ZmYodGhpcy5wT3AxLCBhKTtcbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMiwgYik7XG4gICAgICAgIHJldHVybiAhIXRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1t0aGlzLnByZWZpeCArIG9wTmFtZV0odGhpcy5wT3AxLCB0aGlzLnBPcDIpO1xuICAgIH1cblxuICAgIG9wMShvcE5hbWUsIGEpIHtcbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMSwgYSk7XG4gICAgICAgIHRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1t0aGlzLnByZWZpeCArIG9wTmFtZV0odGhpcy5wT3AxLCB0aGlzLnBPcDMpO1xuICAgICAgICByZXR1cm4gdGhpcy50bS5nZXRCdWZmKHRoaXMucE9wMywgdGhpcy5uOCk7XG4gICAgfVxuXG4gICAgb3AxQm9vbChvcE5hbWUsIGEpIHtcbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMSwgYSk7XG4gICAgICAgIHJldHVybiAhIXRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1t0aGlzLnByZWZpeCArIG9wTmFtZV0odGhpcy5wT3AxLCB0aGlzLnBPcDMpO1xuICAgIH1cblxuICAgIGFkZChhLGIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3AyKFwiX2FkZFwiLCBhLCBiKTtcbiAgICB9XG5cblxuICAgIGVxKGEsYikge1xuICAgICAgICByZXR1cm4gdGhpcy5vcDJCb29sKFwiX2VxXCIsIGEsIGIpO1xuICAgIH1cblxuICAgIGlzWmVybyhhKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9wMUJvb2woXCJfaXNaZXJvXCIsIGEpO1xuICAgIH1cblxuICAgIHN1YihhLGIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3AyKFwiX3N1YlwiLCBhLCBiKTtcbiAgICB9XG5cbiAgICBuZWcoYSkge1xuICAgICAgICByZXR1cm4gdGhpcy5vcDEoXCJfbmVnXCIsIGEpO1xuICAgIH1cblxuICAgIGludihhKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9wMShcIl9pbnZlcnNlXCIsIGEpO1xuICAgIH1cblxuICAgIHRvTW9udGdvbWVyeShhKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9wMShcIl90b01vbnRnb21lcnlcIiwgYSk7XG4gICAgfVxuXG4gICAgZnJvbU1vbnRnb21lcnkoYSkge1xuICAgICAgICByZXR1cm4gdGhpcy5vcDEoXCJfZnJvbU1vbnRnb21lcnlcIiwgYSk7XG4gICAgfVxuXG4gICAgbXVsKGEsYikge1xuICAgICAgICByZXR1cm4gdGhpcy5vcDIoXCJfbXVsXCIsIGEsIGIpO1xuICAgIH1cblxuICAgIGRpdihhLCBiKSB7XG4gICAgICAgIHRoaXMudG0uc2V0QnVmZih0aGlzLnBPcDEsIGEpO1xuICAgICAgICB0aGlzLnRtLnNldEJ1ZmYodGhpcy5wT3AyLCBiKTtcbiAgICAgICAgdGhpcy50bS5pbnN0YW5jZS5leHBvcnRzW3RoaXMucHJlZml4ICsgXCJfaW52ZXJzZVwiXSh0aGlzLnBPcDIsIHRoaXMucE9wMik7XG4gICAgICAgIHRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1t0aGlzLnByZWZpeCArIFwiX211bFwiXSh0aGlzLnBPcDEsIHRoaXMucE9wMiwgdGhpcy5wT3AzKTtcbiAgICAgICAgcmV0dXJuIHRoaXMudG0uZ2V0QnVmZih0aGlzLnBPcDMsIHRoaXMubjgpO1xuICAgIH1cblxuICAgIHNxdWFyZShhKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9wMShcIl9zcXVhcmVcIiwgYSk7XG4gICAgfVxuXG4gICAgaXNTcXVhcmUoYSkge1xuICAgICAgICByZXR1cm4gdGhpcy5vcDFCb29sKFwiX2lzU3F1YXJlXCIsIGEpO1xuICAgIH1cblxuICAgIHNxcnQoYSkge1xuICAgICAgICByZXR1cm4gdGhpcy5vcDEoXCJfc3FydFwiLCBhKTtcbiAgICB9XG5cbiAgICBleHAoYSwgYikge1xuICAgICAgICBpZiAoIShiIGluc3RhbmNlb2YgVWludDhBcnJheSkpIHtcbiAgICAgICAgICAgIGIgPSB0b0xFQnVmZihlKGIpKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRtLnNldEJ1ZmYodGhpcy5wT3AxLCBhKTtcbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMiwgYik7XG4gICAgICAgIHRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1t0aGlzLnByZWZpeCArIFwiX2V4cFwiXSh0aGlzLnBPcDEsIHRoaXMucE9wMiwgYi5ieXRlTGVuZ3RoLCB0aGlzLnBPcDMpO1xuICAgICAgICByZXR1cm4gdGhpcy50bS5nZXRCdWZmKHRoaXMucE9wMywgdGhpcy5uOCk7XG4gICAgfVxuXG4gICAgaXNOZWdhdGl2ZShhKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9wMUJvb2woXCJfaXNOZWdhdGl2ZVwiLCBhKTtcbiAgICB9XG5cbiAgICBlKGEsIGIpIHtcbiAgICAgICAgaWYgKGEgaW5zdGFuY2VvZiBVaW50OEFycmF5KSByZXR1cm4gYTtcbiAgICAgICAgbGV0IHJhID0gZShhLCBiKTtcbiAgICAgICAgaWYgKGlzTmVnYXRpdmUkNChyYSkpIHtcbiAgICAgICAgICAgIHJhID0gbmVnKHJhKTtcbiAgICAgICAgICAgIGlmIChndChyYSwgdGhpcy5wKSkge1xuICAgICAgICAgICAgICAgIHJhID0gbW9kKHJhLCB0aGlzLnApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmEgPSBzdWIodGhpcy5wLCByYSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoZ3QocmEsIHRoaXMucCkpIHtcbiAgICAgICAgICAgICAgICByYSA9IG1vZChyYSwgdGhpcy5wKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjb25zdCBidWZmID0gbGVJbnQyQnVmZihyYSwgdGhpcy5uOCk7XG4gICAgICAgIHJldHVybiB0aGlzLnRvTW9udGdvbWVyeShidWZmKTtcbiAgICB9XG5cbiAgICB0b1N0cmluZyhhLCByYWRpeCkge1xuICAgICAgICBjb25zdCBhbiA9IHRoaXMuZnJvbU1vbnRnb21lcnkoYSk7XG4gICAgICAgIGNvbnN0IHMgPSBmcm9tUnByTEUoYW4sIDApO1xuICAgICAgICByZXR1cm4gdG9TdHJpbmcocywgcmFkaXgpO1xuICAgIH1cblxuICAgIGZyb21Sbmcocm5nKSB7XG4gICAgICAgIGxldCB2O1xuICAgICAgICBjb25zdCBidWZmID0gbmV3IFVpbnQ4QXJyYXkodGhpcy5uOCk7XG4gICAgICAgIGRvIHtcbiAgICAgICAgICAgIHYgPSB6ZXJvO1xuICAgICAgICAgICAgZm9yIChsZXQgaT0wOyBpPHRoaXMubjY0OyBpKyspIHtcbiAgICAgICAgICAgICAgICB2ID0gYWRkKHYsICBzaGlmdExlZnQocm5nLm5leHRVNjQoKSwgNjQqaSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdiA9IGJhbmQodiwgdGhpcy5tYXNrKTtcbiAgICAgICAgfSB3aGlsZSAoZ2VxKHYsIHRoaXMucCkpO1xuICAgICAgICB0b1JwckxFKGJ1ZmYsIDAsIHYsIHRoaXMubjgpO1xuICAgICAgICByZXR1cm4gYnVmZjtcbiAgICB9XG5cbiAgICByYW5kb20oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZyb21SbmcoZ2V0VGhyZWFkUm5nKCkpO1xuICAgIH1cblxuICAgIHRvT2JqZWN0KGEpIHtcbiAgICAgICAgY29uc3QgYW4gPSB0aGlzLmZyb21Nb250Z29tZXJ5KGEpO1xuICAgICAgICByZXR1cm4gZnJvbVJwckxFKGFuLCAwKTtcbiAgICB9XG5cbiAgICBmcm9tT2JqZWN0KGEpIHtcbiAgICAgICAgY29uc3QgYnVmZiA9IG5ldyBVaW50OEFycmF5KHRoaXMubjgpO1xuICAgICAgICB0b1JwckxFKGJ1ZmYsIDAsIGEsIHRoaXMubjgpO1xuICAgICAgICByZXR1cm4gdGhpcy50b01vbnRnb21lcnkoYnVmZik7XG4gICAgfVxuXG4gICAgdG9ScHJMRShidWZmLCBvZmZzZXQsIGEpIHtcbiAgICAgICAgYnVmZi5zZXQodGhpcy5mcm9tTW9udGdvbWVyeShhKSwgb2Zmc2V0KTtcbiAgICB9XG5cbiAgICB0b1JwckJFKGJ1ZmYsIG9mZnNldCwgYSkge1xuICAgICAgICBjb25zdCBidWZmMiA9IHRoaXMuZnJvbU1vbnRnb21lcnkoYSk7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTx0aGlzLm44LzI7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgYXV4ID0gYnVmZjJbaV07XG4gICAgICAgICAgICBidWZmMltpXSA9IGJ1ZmYyW3RoaXMubjgtMS1pXTtcbiAgICAgICAgICAgIGJ1ZmYyW3RoaXMubjgtMS1pXSA9IGF1eDtcbiAgICAgICAgfVxuICAgICAgICBidWZmLnNldChidWZmMiwgb2Zmc2V0KTtcbiAgICB9XG5cbiAgICBmcm9tUnByTEUoYnVmZiwgb2Zmc2V0KSB7XG4gICAgICAgIG9mZnNldCA9IG9mZnNldCB8fCAwO1xuICAgICAgICBjb25zdCByZXMgPSBidWZmLnNsaWNlKG9mZnNldCwgb2Zmc2V0ICsgdGhpcy5uOCk7XG4gICAgICAgIHJldHVybiB0aGlzLnRvTW9udGdvbWVyeShyZXMpO1xuICAgIH1cblxuICAgIGFzeW5jIGJhdGNoSW52ZXJzZShidWZmSW4pIHtcbiAgICAgICAgbGV0IHJldHVybkFycmF5ID0gZmFsc2U7XG4gICAgICAgIGNvbnN0IHNJbiA9IHRoaXMubjg7XG4gICAgICAgIGNvbnN0IHNPdXQgPSB0aGlzLm44O1xuXG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KGJ1ZmZJbikpIHtcbiAgICAgICAgICAgIGJ1ZmZJbiA9IGFycmF5MmJ1ZmZlcihidWZmSW4sIHNJbiApO1xuICAgICAgICAgICAgcmV0dXJuQXJyYXkgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYnVmZkluID0gYnVmZkluLnNsaWNlKDAsIGJ1ZmZJbi5ieXRlTGVuZ3RoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IG5Qb2ludHMgPSBNYXRoLmZsb29yKGJ1ZmZJbi5ieXRlTGVuZ3RoIC8gc0luKTtcbiAgICAgICAgaWYgKCBuUG9pbnRzICogc0luICE9PSBidWZmSW4uYnl0ZUxlbmd0aCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBidWZmZXIgc2l6ZVwiKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwb2ludHNQZXJDaHVuayA9IE1hdGguZmxvb3IoblBvaW50cy90aGlzLnRtLmNvbmN1cnJlbmN5KTtcbiAgICAgICAgY29uc3Qgb3BQcm9taXNlcyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8dGhpcy50bS5jb25jdXJyZW5jeTsgaSsrKSB7XG4gICAgICAgICAgICBsZXQgbjtcbiAgICAgICAgICAgIGlmIChpPCB0aGlzLnRtLmNvbmN1cnJlbmN5LTEpIHtcbiAgICAgICAgICAgICAgICBuID0gcG9pbnRzUGVyQ2h1bms7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG4gPSBuUG9pbnRzIC0gaSpwb2ludHNQZXJDaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChuPT0wKSBjb250aW51ZTtcblxuICAgICAgICAgICAgY29uc3QgYnVmZkNodW5rID0gYnVmZkluLnNsaWNlKGkqcG9pbnRzUGVyQ2h1bmsqc0luLCBpKnBvaW50c1BlckNodW5rKnNJbiArIG4qc0luKTtcbiAgICAgICAgICAgIGNvbnN0IHRhc2sgPSBbXG4gICAgICAgICAgICAgICAge2NtZDogXCJBTExPQ1NFVFwiLCB2YXI6IDAsIGJ1ZmY6YnVmZkNodW5rfSxcbiAgICAgICAgICAgICAgICB7Y21kOiBcIkFMTE9DXCIsIHZhcjogMSwgbGVuOnNPdXQgKiBufSxcbiAgICAgICAgICAgICAgICB7Y21kOiBcIkNBTExcIiwgZm5OYW1lOiB0aGlzLnByZWZpeCArIFwiX2JhdGNoSW52ZXJzZVwiLCBwYXJhbXM6IFtcbiAgICAgICAgICAgICAgICAgICAge3ZhcjogMH0sXG4gICAgICAgICAgICAgICAgICAgIHt2YWw6IHNJbn0sXG4gICAgICAgICAgICAgICAgICAgIHt2YWw6IG59LFxuICAgICAgICAgICAgICAgICAgICB7dmFyOiAxfSxcbiAgICAgICAgICAgICAgICAgICAge3ZhbDogc091dH0sXG4gICAgICAgICAgICAgICAgXX0sXG4gICAgICAgICAgICAgICAge2NtZDogXCJHRVRcIiwgb3V0OiAwLCB2YXI6IDEsIGxlbjpzT3V0ICogbn0sXG4gICAgICAgICAgICBdO1xuICAgICAgICAgICAgb3BQcm9taXNlcy5wdXNoKFxuICAgICAgICAgICAgICAgIHRoaXMudG0ucXVldWVBY3Rpb24odGFzaywgW2J1ZmZDaHVuay5idWZmZXJdKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IFByb21pc2UuYWxsKG9wUHJvbWlzZXMpO1xuXG4gICAgICAgIGxldCBmdWxsQnVmZk91dDtcbiAgICAgICAgaWYgKGJ1ZmZJbiBpbnN0YW5jZW9mIEJpZ0J1ZmZlcikge1xuICAgICAgICAgICAgZnVsbEJ1ZmZPdXQgPSBuZXcgQmlnQnVmZmVyKG5Qb2ludHMqc091dCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmdWxsQnVmZk91dCA9IG5ldyBVaW50OEFycmF5KG5Qb2ludHMqc091dCk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcCA9MDtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPHJlc3VsdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgZnVsbEJ1ZmZPdXQuc2V0KHJlc3VsdFtpXVswXSwgcCk7XG4gICAgICAgICAgICBwKz1yZXN1bHRbaV1bMF0uYnl0ZUxlbmd0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChyZXR1cm5BcnJheSkge1xuICAgICAgICAgICAgcmV0dXJuIGJ1ZmZlcjJhcnJheShmdWxsQnVmZk91dCwgc091dCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZnVsbEJ1ZmZPdXQ7XG4gICAgICAgIH1cblxuICAgIH1cblxufVxuXG5jbGFzcyBXYXNtRmllbGQyIHtcblxuICAgIGNvbnN0cnVjdG9yKHRtLCBwcmVmaXgsIEYpIHtcbiAgICAgICAgdGhpcy50bSA9IHRtO1xuICAgICAgICB0aGlzLnByZWZpeCA9IHByZWZpeDtcblxuICAgICAgICB0aGlzLkYgPSBGO1xuICAgICAgICB0aGlzLnR5cGUgPSBcIkYyXCI7XG4gICAgICAgIHRoaXMubSA9IEYubSAqIDI7XG4gICAgICAgIHRoaXMubjggPSB0aGlzLkYubjgqMjtcbiAgICAgICAgdGhpcy5uMzIgPSB0aGlzLkYubjMyKjI7XG4gICAgICAgIHRoaXMubjY0ID0gdGhpcy5GLm42NCoyO1xuXG4gICAgICAgIHRoaXMucE9wMSA9IHRtLmFsbG9jKEYubjgqMik7XG4gICAgICAgIHRoaXMucE9wMiA9IHRtLmFsbG9jKEYubjgqMik7XG4gICAgICAgIHRoaXMucE9wMyA9IHRtLmFsbG9jKEYubjgqMik7XG4gICAgICAgIHRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1twcmVmaXggKyBcIl96ZXJvXCJdKHRoaXMucE9wMSk7XG4gICAgICAgIHRoaXMuemVybyA9IHRtLmdldEJ1ZmYodGhpcy5wT3AxLCB0aGlzLm44KTtcbiAgICAgICAgdGhpcy50bS5pbnN0YW5jZS5leHBvcnRzW3ByZWZpeCArIFwiX29uZVwiXSh0aGlzLnBPcDEpO1xuICAgICAgICB0aGlzLm9uZSA9IHRtLmdldEJ1ZmYodGhpcy5wT3AxLCB0aGlzLm44KTtcblxuICAgICAgICB0aGlzLm5lZ29uZSA9IHRoaXMubmVnKHRoaXMub25lKTtcbiAgICAgICAgdGhpcy50d28gPSB0aGlzLmFkZCh0aGlzLm9uZSwgdGhpcy5vbmUpO1xuXG4gICAgfVxuXG4gICAgb3AyKG9wTmFtZSwgYSwgYikge1xuICAgICAgICB0aGlzLnRtLnNldEJ1ZmYodGhpcy5wT3AxLCBhKTtcbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMiwgYik7XG4gICAgICAgIHRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1t0aGlzLnByZWZpeCArIG9wTmFtZV0odGhpcy5wT3AxLCB0aGlzLnBPcDIsIHRoaXMucE9wMyk7XG4gICAgICAgIHJldHVybiB0aGlzLnRtLmdldEJ1ZmYodGhpcy5wT3AzLCB0aGlzLm44KTtcbiAgICB9XG5cbiAgICBvcDJCb29sKG9wTmFtZSwgYSwgYikge1xuICAgICAgICB0aGlzLnRtLnNldEJ1ZmYodGhpcy5wT3AxLCBhKTtcbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMiwgYik7XG4gICAgICAgIHJldHVybiAhIXRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1t0aGlzLnByZWZpeCArIG9wTmFtZV0odGhpcy5wT3AxLCB0aGlzLnBPcDIpO1xuICAgIH1cblxuICAgIG9wMShvcE5hbWUsIGEpIHtcbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMSwgYSk7XG4gICAgICAgIHRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1t0aGlzLnByZWZpeCArIG9wTmFtZV0odGhpcy5wT3AxLCB0aGlzLnBPcDMpO1xuICAgICAgICByZXR1cm4gdGhpcy50bS5nZXRCdWZmKHRoaXMucE9wMywgdGhpcy5uOCk7XG4gICAgfVxuXG4gICAgb3AxQm9vbChvcE5hbWUsIGEpIHtcbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMSwgYSk7XG4gICAgICAgIHJldHVybiAhIXRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1t0aGlzLnByZWZpeCArIG9wTmFtZV0odGhpcy5wT3AxLCB0aGlzLnBPcDMpO1xuICAgIH1cblxuICAgIGFkZChhLGIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3AyKFwiX2FkZFwiLCBhLCBiKTtcbiAgICB9XG5cbiAgICBlcShhLGIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3AyQm9vbChcIl9lcVwiLCBhLCBiKTtcbiAgICB9XG5cbiAgICBpc1plcm8oYSkge1xuICAgICAgICByZXR1cm4gdGhpcy5vcDFCb29sKFwiX2lzWmVyb1wiLCBhKTtcbiAgICB9XG5cbiAgICBzdWIoYSxiKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9wMihcIl9zdWJcIiwgYSwgYik7XG4gICAgfVxuXG4gICAgbmVnKGEpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3AxKFwiX25lZ1wiLCBhKTtcbiAgICB9XG5cbiAgICBpbnYoYSkge1xuICAgICAgICByZXR1cm4gdGhpcy5vcDEoXCJfaW52ZXJzZVwiLCBhKTtcbiAgICB9XG5cbiAgICBpc05lZ2F0aXZlKGEpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3AxQm9vbChcIl9pc05lZ2F0aXZlXCIsIGEpO1xuICAgIH1cblxuICAgIHRvTW9udGdvbWVyeShhKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9wMShcIl90b01vbnRnb21lcnlcIiwgYSk7XG4gICAgfVxuXG4gICAgZnJvbU1vbnRnb21lcnkoYSkge1xuICAgICAgICByZXR1cm4gdGhpcy5vcDEoXCJfZnJvbU1vbnRnb21lcnlcIiwgYSk7XG4gICAgfVxuXG4gICAgbXVsKGEsYikge1xuICAgICAgICByZXR1cm4gdGhpcy5vcDIoXCJfbXVsXCIsIGEsIGIpO1xuICAgIH1cblxuICAgIG11bDEoYSxiKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9wMihcIl9tdWwxXCIsIGEsIGIpO1xuICAgIH1cblxuICAgIGRpdihhLCBiKSB7XG4gICAgICAgIHRoaXMudG0uc2V0QnVmZih0aGlzLnBPcDEsIGEpO1xuICAgICAgICB0aGlzLnRtLnNldEJ1ZmYodGhpcy5wT3AyLCBiKTtcbiAgICAgICAgdGhpcy50bS5pbnN0YW5jZS5leHBvcnRzW3RoaXMucHJlZml4ICsgXCJfaW52ZXJzZVwiXSh0aGlzLnBPcDIsIHRoaXMucE9wMik7XG4gICAgICAgIHRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1t0aGlzLnByZWZpeCArIFwiX211bFwiXSh0aGlzLnBPcDEsIHRoaXMucE9wMiwgdGhpcy5wT3AzKTtcbiAgICAgICAgcmV0dXJuIHRoaXMudG0uZ2V0QnVmZih0aGlzLnBPcDMsIHRoaXMubjgpO1xuICAgIH1cblxuICAgIHNxdWFyZShhKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9wMShcIl9zcXVhcmVcIiwgYSk7XG4gICAgfVxuXG4gICAgaXNTcXVhcmUoYSkge1xuICAgICAgICByZXR1cm4gdGhpcy5vcDFCb29sKFwiX2lzU3F1YXJlXCIsIGEpO1xuICAgIH1cblxuICAgIHNxcnQoYSkge1xuICAgICAgICByZXR1cm4gdGhpcy5vcDEoXCJfc3FydFwiLCBhKTtcbiAgICB9XG5cbiAgICBleHAoYSwgYikge1xuICAgICAgICBpZiAoIShiIGluc3RhbmNlb2YgVWludDhBcnJheSkpIHtcbiAgICAgICAgICAgIGIgPSB0b0xFQnVmZihlKGIpKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRtLnNldEJ1ZmYodGhpcy5wT3AxLCBhKTtcbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMiwgYik7XG4gICAgICAgIHRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1t0aGlzLnByZWZpeCArIFwiX2V4cFwiXSh0aGlzLnBPcDEsIHRoaXMucE9wMiwgYi5ieXRlTGVuZ3RoLCB0aGlzLnBPcDMpO1xuICAgICAgICByZXR1cm4gdGhpcy50bS5nZXRCdWZmKHRoaXMucE9wMywgdGhpcy5uOCk7XG4gICAgfVxuXG4gICAgZShhLCBiKSB7XG4gICAgICAgIGlmIChhIGluc3RhbmNlb2YgVWludDhBcnJheSkgcmV0dXJuIGE7XG4gICAgICAgIGlmICgoQXJyYXkuaXNBcnJheShhKSkgJiYgKGEubGVuZ3RoID09IDIpKSB7XG4gICAgICAgICAgICBjb25zdCBjMSA9IHRoaXMuRi5lKGFbMF0sIGIpO1xuICAgICAgICAgICAgY29uc3QgYzIgPSB0aGlzLkYuZShhWzFdLCBiKTtcbiAgICAgICAgICAgIGNvbnN0IHJlcyA9IG5ldyBVaW50OEFycmF5KHRoaXMuRi5uOCoyKTtcbiAgICAgICAgICAgIHJlcy5zZXQoYzEpO1xuICAgICAgICAgICAgcmVzLnNldChjMiwgdGhpcy5GLm44KjIpO1xuICAgICAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImludmFsaWQgRjJcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0b1N0cmluZyhhLCByYWRpeCkge1xuICAgICAgICBjb25zdCBzMSA9IHRoaXMuRi50b1N0cmluZyhhLnNsaWNlKDAsIHRoaXMuRi5uOCksIHJhZGl4KTtcbiAgICAgICAgY29uc3QgczIgPSB0aGlzLkYudG9TdHJpbmcoYS5zbGljZSh0aGlzLkYubjgpLCByYWRpeCk7XG4gICAgICAgIHJldHVybiBgWyR7czF9LCAke3MyfV1gO1xuICAgIH1cblxuICAgIGZyb21Sbmcocm5nKSB7XG4gICAgICAgIGNvbnN0IGMxID0gdGhpcy5GLmZyb21Sbmcocm5nKTtcbiAgICAgICAgY29uc3QgYzIgPSB0aGlzLkYuZnJvbVJuZyhybmcpO1xuICAgICAgICBjb25zdCByZXMgPSBuZXcgVWludDhBcnJheSh0aGlzLkYubjgqMik7XG4gICAgICAgIHJlcy5zZXQoYzEpO1xuICAgICAgICByZXMuc2V0KGMyLCB0aGlzLkYubjgpO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIHJhbmRvbSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZnJvbVJuZyhnZXRUaHJlYWRSbmcoKSk7XG4gICAgfVxuXG4gICAgdG9PYmplY3QoYSkge1xuICAgICAgICBjb25zdCBjMSA9IHRoaXMuRi50b09iamVjdChhLnNsaWNlKDAsIHRoaXMuRi5uOCkpO1xuICAgICAgICBjb25zdCBjMiA9IHRoaXMuRi50b09iamVjdChhLnNsaWNlKHRoaXMuRi5uOCwgdGhpcy5GLm44KjIpKTtcbiAgICAgICAgcmV0dXJuIFtjMSwgYzJdO1xuICAgIH1cblxuICAgIGZyb21PYmplY3QoYSkge1xuICAgICAgICBjb25zdCBidWZmID0gbmV3IFVpbnQ4QXJyYXkodGhpcy5GLm44KjIpO1xuICAgICAgICBjb25zdCBiMSA9IHRoaXMuRi5mcm9tT2JqZWN0KGFbMF0pO1xuICAgICAgICBjb25zdCBiMiA9IHRoaXMuRi5mcm9tT2JqZWN0KGFbMV0pO1xuICAgICAgICBidWZmLnNldChiMSk7XG4gICAgICAgIGJ1ZmYuc2V0KGIyLCB0aGlzLkYubjgpO1xuICAgICAgICByZXR1cm4gYnVmZjtcbiAgICB9XG5cbiAgICBjMShhKSB7XG4gICAgICAgIHJldHVybiBhLnNsaWNlKDAsIHRoaXMuRi5uOCk7XG4gICAgfVxuXG4gICAgYzIoYSkge1xuICAgICAgICByZXR1cm4gYS5zbGljZSh0aGlzLkYubjgpO1xuICAgIH1cblxufVxuXG5jbGFzcyBXYXNtRmllbGQzIHtcblxuICAgIGNvbnN0cnVjdG9yKHRtLCBwcmVmaXgsIEYpIHtcbiAgICAgICAgdGhpcy50bSA9IHRtO1xuICAgICAgICB0aGlzLnByZWZpeCA9IHByZWZpeDtcblxuICAgICAgICB0aGlzLkYgPSBGO1xuICAgICAgICB0aGlzLnR5cGUgPSBcIkYzXCI7XG4gICAgICAgIHRoaXMubSA9IEYubSAqIDM7XG4gICAgICAgIHRoaXMubjggPSB0aGlzLkYubjgqMztcbiAgICAgICAgdGhpcy5uMzIgPSB0aGlzLkYubjMyKjM7XG4gICAgICAgIHRoaXMubjY0ID0gdGhpcy5GLm42NCozO1xuXG4gICAgICAgIHRoaXMucE9wMSA9IHRtLmFsbG9jKEYubjgqMyk7XG4gICAgICAgIHRoaXMucE9wMiA9IHRtLmFsbG9jKEYubjgqMyk7XG4gICAgICAgIHRoaXMucE9wMyA9IHRtLmFsbG9jKEYubjgqMyk7XG4gICAgICAgIHRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1twcmVmaXggKyBcIl96ZXJvXCJdKHRoaXMucE9wMSk7XG4gICAgICAgIHRoaXMuemVybyA9IHRtLmdldEJ1ZmYodGhpcy5wT3AxLCB0aGlzLm44KTtcbiAgICAgICAgdGhpcy50bS5pbnN0YW5jZS5leHBvcnRzW3ByZWZpeCArIFwiX29uZVwiXSh0aGlzLnBPcDEpO1xuICAgICAgICB0aGlzLm9uZSA9IHRtLmdldEJ1ZmYodGhpcy5wT3AxLCB0aGlzLm44KTtcblxuICAgICAgICB0aGlzLm5lZ29uZSA9IHRoaXMubmVnKHRoaXMub25lKTtcbiAgICAgICAgdGhpcy50d28gPSB0aGlzLmFkZCh0aGlzLm9uZSwgdGhpcy5vbmUpO1xuXG4gICAgfVxuXG4gICAgb3AyKG9wTmFtZSwgYSwgYikge1xuICAgICAgICB0aGlzLnRtLnNldEJ1ZmYodGhpcy5wT3AxLCBhKTtcbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMiwgYik7XG4gICAgICAgIHRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1t0aGlzLnByZWZpeCArIG9wTmFtZV0odGhpcy5wT3AxLCB0aGlzLnBPcDIsIHRoaXMucE9wMyk7XG4gICAgICAgIHJldHVybiB0aGlzLnRtLmdldEJ1ZmYodGhpcy5wT3AzLCB0aGlzLm44KTtcbiAgICB9XG5cbiAgICBvcDJCb29sKG9wTmFtZSwgYSwgYikge1xuICAgICAgICB0aGlzLnRtLnNldEJ1ZmYodGhpcy5wT3AxLCBhKTtcbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMiwgYik7XG4gICAgICAgIHJldHVybiAhIXRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1t0aGlzLnByZWZpeCArIG9wTmFtZV0odGhpcy5wT3AxLCB0aGlzLnBPcDIpO1xuICAgIH1cblxuICAgIG9wMShvcE5hbWUsIGEpIHtcbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMSwgYSk7XG4gICAgICAgIHRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1t0aGlzLnByZWZpeCArIG9wTmFtZV0odGhpcy5wT3AxLCB0aGlzLnBPcDMpO1xuICAgICAgICByZXR1cm4gdGhpcy50bS5nZXRCdWZmKHRoaXMucE9wMywgdGhpcy5uOCk7XG4gICAgfVxuXG4gICAgb3AxQm9vbChvcE5hbWUsIGEpIHtcbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMSwgYSk7XG4gICAgICAgIHJldHVybiAhIXRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1t0aGlzLnByZWZpeCArIG9wTmFtZV0odGhpcy5wT3AxLCB0aGlzLnBPcDMpO1xuICAgIH1cblxuXG4gICAgZXEoYSxiKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9wMkJvb2woXCJfZXFcIiwgYSwgYik7XG4gICAgfVxuXG4gICAgaXNaZXJvKGEpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3AxQm9vbChcIl9pc1plcm9cIiwgYSk7XG4gICAgfVxuXG4gICAgYWRkKGEsYikge1xuICAgICAgICByZXR1cm4gdGhpcy5vcDIoXCJfYWRkXCIsIGEsIGIpO1xuICAgIH1cblxuICAgIHN1YihhLGIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3AyKFwiX3N1YlwiLCBhLCBiKTtcbiAgICB9XG5cbiAgICBuZWcoYSkge1xuICAgICAgICByZXR1cm4gdGhpcy5vcDEoXCJfbmVnXCIsIGEpO1xuICAgIH1cblxuICAgIGludihhKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9wMShcIl9pbnZlcnNlXCIsIGEpO1xuICAgIH1cblxuICAgIGlzTmVnYXRpdmUoYSkge1xuICAgICAgICByZXR1cm4gdGhpcy5vcDFCb29sKFwiX2lzTmVnYXRpdmVcIiwgYSk7XG4gICAgfVxuXG4gICAgdG9Nb250Z29tZXJ5KGEpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3AxKFwiX3RvTW9udGdvbWVyeVwiLCBhKTtcbiAgICB9XG5cbiAgICBmcm9tTW9udGdvbWVyeShhKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9wMShcIl9mcm9tTW9udGdvbWVyeVwiLCBhKTtcbiAgICB9XG5cbiAgICBtdWwoYSxiKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9wMihcIl9tdWxcIiwgYSwgYik7XG4gICAgfVxuXG4gICAgZGl2KGEsIGIpIHtcbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMSwgYSk7XG4gICAgICAgIHRoaXMudG0uc2V0QnVmZih0aGlzLnBPcDIsIGIpO1xuICAgICAgICB0aGlzLnRtLmluc3RhbmNlLmV4cG9ydHNbdGhpcy5wcmVmaXggKyBcIl9pbnZlcnNlXCJdKHRoaXMucE9wMiwgdGhpcy5wT3AyKTtcbiAgICAgICAgdGhpcy50bS5pbnN0YW5jZS5leHBvcnRzW3RoaXMucHJlZml4ICsgXCJfbXVsXCJdKHRoaXMucE9wMSwgdGhpcy5wT3AyLCB0aGlzLnBPcDMpO1xuICAgICAgICByZXR1cm4gdGhpcy50bS5nZXRCdWZmKHRoaXMucE9wMywgdGhpcy5uOCk7XG4gICAgfVxuXG4gICAgc3F1YXJlKGEpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3AxKFwiX3NxdWFyZVwiLCBhKTtcbiAgICB9XG5cbiAgICBpc1NxdWFyZShhKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9wMUJvb2woXCJfaXNTcXVhcmVcIiwgYSk7XG4gICAgfVxuXG4gICAgc3FydChhKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9wMShcIl9zcXJ0XCIsIGEpO1xuICAgIH1cblxuICAgIGV4cChhLCBiKSB7XG4gICAgICAgIGlmICghKGIgaW5zdGFuY2VvZiBVaW50OEFycmF5KSkge1xuICAgICAgICAgICAgYiA9IHRvTEVCdWZmKGUoYikpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudG0uc2V0QnVmZih0aGlzLnBPcDEsIGEpO1xuICAgICAgICB0aGlzLnRtLnNldEJ1ZmYodGhpcy5wT3AyLCBiKTtcbiAgICAgICAgdGhpcy50bS5pbnN0YW5jZS5leHBvcnRzW3RoaXMucHJlZml4ICsgXCJfZXhwXCJdKHRoaXMucE9wMSwgdGhpcy5wT3AyLCBiLmJ5dGVMZW5ndGgsIHRoaXMucE9wMyk7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEJ1ZmYodGhpcy5wT3AzLCB0aGlzLm44KTtcbiAgICB9XG5cbiAgICBlKGEsIGIpIHtcbiAgICAgICAgaWYgKGEgaW5zdGFuY2VvZiBVaW50OEFycmF5KSByZXR1cm4gYTtcbiAgICAgICAgaWYgKChBcnJheS5pc0FycmF5KGEpKSAmJiAoYS5sZW5ndGggPT0gMykpIHtcbiAgICAgICAgICAgIGNvbnN0IGMxID0gdGhpcy5GLmUoYVswXSwgYik7XG4gICAgICAgICAgICBjb25zdCBjMiA9IHRoaXMuRi5lKGFbMV0sIGIpO1xuICAgICAgICAgICAgY29uc3QgYzMgPSB0aGlzLkYuZShhWzJdLCBiKTtcbiAgICAgICAgICAgIGNvbnN0IHJlcyA9IG5ldyBVaW50OEFycmF5KHRoaXMuRi5uOCozKTtcbiAgICAgICAgICAgIHJlcy5zZXQoYzEpO1xuICAgICAgICAgICAgcmVzLnNldChjMiwgdGhpcy5GLm44KTtcbiAgICAgICAgICAgIHJlcy5zZXQoYzMsIHRoaXMuRi5uOCoyKTtcbiAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJpbnZhbGlkIEYzXCIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdG9TdHJpbmcoYSwgcmFkaXgpIHtcbiAgICAgICAgY29uc3QgczEgPSB0aGlzLkYudG9TdHJpbmcoYS5zbGljZSgwLCB0aGlzLkYubjgpLCByYWRpeCk7XG4gICAgICAgIGNvbnN0IHMyID0gdGhpcy5GLnRvU3RyaW5nKGEuc2xpY2UodGhpcy5GLm44LCB0aGlzLkYubjgqMiksIHJhZGl4KTtcbiAgICAgICAgY29uc3QgczMgPSB0aGlzLkYudG9TdHJpbmcoYS5zbGljZSh0aGlzLkYubjgqMiksIHJhZGl4KTtcbiAgICAgICAgcmV0dXJuIGBbJHtzMX0sICR7czJ9LCAke3MzfV1gO1xuICAgIH1cblxuICAgIGZyb21Sbmcocm5nKSB7XG4gICAgICAgIGNvbnN0IGMxID0gdGhpcy5GLmZyb21Sbmcocm5nKTtcbiAgICAgICAgY29uc3QgYzIgPSB0aGlzLkYuZnJvbVJuZyhybmcpO1xuICAgICAgICBjb25zdCBjMyA9IHRoaXMuRi5mcm9tUm5nKHJuZyk7XG4gICAgICAgIGNvbnN0IHJlcyA9IG5ldyBVaW50OEFycmF5KHRoaXMuRi5uOCozKTtcbiAgICAgICAgcmVzLnNldChjMSk7XG4gICAgICAgIHJlcy5zZXQoYzIsIHRoaXMuRi5uOCk7XG4gICAgICAgIHJlcy5zZXQoYzMsIHRoaXMuRi5uOCoyKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICByYW5kb20oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZyb21SbmcoZ2V0VGhyZWFkUm5nKCkpO1xuICAgIH1cblxuICAgIHRvT2JqZWN0KGEpIHtcbiAgICAgICAgY29uc3QgYzEgPSB0aGlzLkYudG9PYmplY3QoYS5zbGljZSgwLCB0aGlzLkYubjgpKTtcbiAgICAgICAgY29uc3QgYzIgPSB0aGlzLkYudG9PYmplY3QoYS5zbGljZSh0aGlzLkYubjgsIHRoaXMuRi5uOCoyKSk7XG4gICAgICAgIGNvbnN0IGMzID0gdGhpcy5GLnRvT2JqZWN0KGEuc2xpY2UodGhpcy5GLm44KjIsIHRoaXMuRi5uOCozKSk7XG4gICAgICAgIHJldHVybiBbYzEsIGMyLCBjM107XG4gICAgfVxuXG4gICAgZnJvbU9iamVjdChhKSB7XG4gICAgICAgIGNvbnN0IGJ1ZmYgPSBuZXcgVWludDhBcnJheSh0aGlzLkYubjgqMyk7XG4gICAgICAgIGNvbnN0IGIxID0gdGhpcy5GLmZyb21PYmplY3QoYVswXSk7XG4gICAgICAgIGNvbnN0IGIyID0gdGhpcy5GLmZyb21PYmplY3QoYVsxXSk7XG4gICAgICAgIGNvbnN0IGIzID0gdGhpcy5GLmZyb21PYmplY3QoYVsyXSk7XG4gICAgICAgIGJ1ZmYuc2V0KGIxKTtcbiAgICAgICAgYnVmZi5zZXQoYjIsIHRoaXMuRi5uOCk7XG4gICAgICAgIGJ1ZmYuc2V0KGIzLCB0aGlzLkYubjgqMik7XG4gICAgICAgIHJldHVybiBidWZmO1xuICAgIH1cblxuICAgIGMxKGEpIHtcbiAgICAgICAgcmV0dXJuIGEuc2xpY2UoMCwgdGhpcy5GLm44KTtcbiAgICB9XG5cbiAgICBjMihhKSB7XG4gICAgICAgIHJldHVybiBhLnNsaWNlKHRoaXMuRi5uOCwgdGhpcy5GLm44KjIpO1xuICAgIH1cblxuICAgIGMzKGEpIHtcbiAgICAgICAgcmV0dXJuIGEuc2xpY2UodGhpcy5GLm44KjIpO1xuICAgIH1cblxufVxuXG5jbGFzcyBXYXNtQ3VydmUge1xuXG4gICAgY29uc3RydWN0b3IodG0sIHByZWZpeCwgRiwgcEdlbiwgcEdiLCBjb2ZhY3Rvcikge1xuICAgICAgICB0aGlzLnRtID0gdG07XG4gICAgICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuICAgICAgICB0aGlzLkYgPSBGO1xuXG4gICAgICAgIHRoaXMucE9wMSA9IHRtLmFsbG9jKEYubjgqMyk7XG4gICAgICAgIHRoaXMucE9wMiA9IHRtLmFsbG9jKEYubjgqMyk7XG4gICAgICAgIHRoaXMucE9wMyA9IHRtLmFsbG9jKEYubjgqMyk7XG4gICAgICAgIHRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1twcmVmaXggKyBcIl96ZXJvXCJdKHRoaXMucE9wMSk7XG4gICAgICAgIHRoaXMuemVybyA9IHRoaXMudG0uZ2V0QnVmZih0aGlzLnBPcDEsIEYubjgqMyk7XG4gICAgICAgIHRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1twcmVmaXggKyBcIl96ZXJvQWZmaW5lXCJdKHRoaXMucE9wMSk7XG4gICAgICAgIHRoaXMuemVyb0FmZmluZSA9IHRoaXMudG0uZ2V0QnVmZih0aGlzLnBPcDEsIEYubjgqMik7XG4gICAgICAgIHRoaXMub25lID0gdGhpcy50bS5nZXRCdWZmKHBHZW4sIEYubjgqMyk7XG4gICAgICAgIHRoaXMuZyA9IHRoaXMub25lO1xuICAgICAgICB0aGlzLm9uZUFmZmluZSA9IHRoaXMudG0uZ2V0QnVmZihwR2VuLCBGLm44KjIpO1xuICAgICAgICB0aGlzLmdBZmZpbmUgPSB0aGlzLm9uZUFmZmluZTtcbiAgICAgICAgdGhpcy5iID0gdGhpcy50bS5nZXRCdWZmKHBHYiwgRi5uOCk7XG5cbiAgICAgICAgaWYgKGNvZmFjdG9yKSB7XG4gICAgICAgICAgICB0aGlzLmNvZmFjdG9yID0gdG9MRUJ1ZmYoY29mYWN0b3IpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5uZWdvbmUgPSB0aGlzLm5lZyh0aGlzLm9uZSk7XG4gICAgICAgIHRoaXMudHdvID0gdGhpcy5hZGQodGhpcy5vbmUsIHRoaXMub25lKTtcblxuICAgICAgICB0aGlzLmJhdGNoTEVNdG9DID0gYnVpbGRCYXRjaENvbnZlcnQodG0sIHByZWZpeCArIFwiX2JhdGNoTEVNdG9DXCIsIEYubjgqMiwgRi5uOCk7XG4gICAgICAgIHRoaXMuYmF0Y2hMRU10b1UgPSBidWlsZEJhdGNoQ29udmVydCh0bSwgcHJlZml4ICsgXCJfYmF0Y2hMRU10b1VcIiwgRi5uOCoyLCBGLm44KjIpO1xuICAgICAgICB0aGlzLmJhdGNoQ3RvTEVNID0gYnVpbGRCYXRjaENvbnZlcnQodG0sIHByZWZpeCArIFwiX2JhdGNoQ3RvTEVNXCIsIEYubjgsIEYubjgqMik7XG4gICAgICAgIHRoaXMuYmF0Y2hVdG9MRU0gPSBidWlsZEJhdGNoQ29udmVydCh0bSwgcHJlZml4ICsgXCJfYmF0Y2hVdG9MRU1cIiwgRi5uOCoyLCBGLm44KjIpO1xuICAgICAgICB0aGlzLmJhdGNoVG9KYWNvYmlhbiA9IGJ1aWxkQmF0Y2hDb252ZXJ0KHRtLCBwcmVmaXggKyBcIl9iYXRjaFRvSmFjb2JpYW5cIiwgRi5uOCoyLCBGLm44KjMpO1xuICAgICAgICB0aGlzLmJhdGNoVG9BZmZpbmUgPSBidWlsZEJhdGNoQ29udmVydCh0bSwgcHJlZml4ICsgXCJfYmF0Y2hUb0FmZmluZVwiLCBGLm44KjMsIEYubjgqMik7XG4gICAgfVxuXG4gICAgb3AyKG9wTmFtZSwgYSwgYikge1xuICAgICAgICB0aGlzLnRtLnNldEJ1ZmYodGhpcy5wT3AxLCBhKTtcbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMiwgYik7XG4gICAgICAgIHRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1t0aGlzLnByZWZpeCArIG9wTmFtZV0odGhpcy5wT3AxLCB0aGlzLnBPcDIsIHRoaXMucE9wMyk7XG4gICAgICAgIHJldHVybiB0aGlzLnRtLmdldEJ1ZmYodGhpcy5wT3AzLCB0aGlzLkYubjgqMyk7XG4gICAgfVxuXG4gICAgb3AyYm9vbChvcE5hbWUsIGEsIGIpIHtcbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMSwgYSk7XG4gICAgICAgIHRoaXMudG0uc2V0QnVmZih0aGlzLnBPcDIsIGIpO1xuICAgICAgICByZXR1cm4gISF0aGlzLnRtLmluc3RhbmNlLmV4cG9ydHNbdGhpcy5wcmVmaXggKyBvcE5hbWVdKHRoaXMucE9wMSwgdGhpcy5wT3AyLCB0aGlzLnBPcDMpO1xuICAgIH1cblxuICAgIG9wMShvcE5hbWUsIGEpIHtcbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMSwgYSk7XG4gICAgICAgIHRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1t0aGlzLnByZWZpeCArIG9wTmFtZV0odGhpcy5wT3AxLCB0aGlzLnBPcDMpO1xuICAgICAgICByZXR1cm4gdGhpcy50bS5nZXRCdWZmKHRoaXMucE9wMywgdGhpcy5GLm44KjMpO1xuICAgIH1cblxuICAgIG9wMUFmZmluZShvcE5hbWUsIGEpIHtcbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMSwgYSk7XG4gICAgICAgIHRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1t0aGlzLnByZWZpeCArIG9wTmFtZV0odGhpcy5wT3AxLCB0aGlzLnBPcDMpO1xuICAgICAgICByZXR1cm4gdGhpcy50bS5nZXRCdWZmKHRoaXMucE9wMywgdGhpcy5GLm44KjIpO1xuICAgIH1cblxuICAgIG9wMUJvb2wob3BOYW1lLCBhKSB7XG4gICAgICAgIHRoaXMudG0uc2V0QnVmZih0aGlzLnBPcDEsIGEpO1xuICAgICAgICByZXR1cm4gISF0aGlzLnRtLmluc3RhbmNlLmV4cG9ydHNbdGhpcy5wcmVmaXggKyBvcE5hbWVdKHRoaXMucE9wMSwgdGhpcy5wT3AzKTtcbiAgICB9XG5cbiAgICBhZGQoYSxiKSB7XG4gICAgICAgIGlmIChhLmJ5dGVMZW5ndGggPT0gdGhpcy5GLm44KjMpIHtcbiAgICAgICAgICAgIGlmIChiLmJ5dGVMZW5ndGggPT0gdGhpcy5GLm44KjMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5vcDIoXCJfYWRkXCIsIGEsIGIpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChiLmJ5dGVMZW5ndGggPT0gdGhpcy5GLm44KjIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5vcDIoXCJfYWRkTWl4ZWRcIiwgYSwgYik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImludmFsaWQgcG9pbnQgc2l6ZVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChhLmJ5dGVMZW5ndGggPT0gdGhpcy5GLm44KjIpIHtcbiAgICAgICAgICAgIGlmIChiLmJ5dGVMZW5ndGggPT0gdGhpcy5GLm44KjMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5vcDIoXCJfYWRkTWl4ZWRcIiwgYiwgYSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGIuYnl0ZUxlbmd0aCA9PSB0aGlzLkYubjgqMikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm9wMihcIl9hZGRBZmZpbmVcIiwgYSwgYik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImludmFsaWQgcG9pbnQgc2l6ZVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImludmFsaWQgcG9pbnQgc2l6ZVwiKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHN1YihhLGIpIHtcbiAgICAgICAgaWYgKGEuYnl0ZUxlbmd0aCA9PSB0aGlzLkYubjgqMykge1xuICAgICAgICAgICAgaWYgKGIuYnl0ZUxlbmd0aCA9PSB0aGlzLkYubjgqMykge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm9wMihcIl9zdWJcIiwgYSwgYik7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGIuYnl0ZUxlbmd0aCA9PSB0aGlzLkYubjgqMikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm9wMihcIl9zdWJNaXhlZFwiLCBhLCBiKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiaW52YWxpZCBwb2ludCBzaXplXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGEuYnl0ZUxlbmd0aCA9PSB0aGlzLkYubjgqMikge1xuICAgICAgICAgICAgaWYgKGIuYnl0ZUxlbmd0aCA9PSB0aGlzLkYubjgqMykge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm9wMihcIl9zdWJNaXhlZFwiLCBiLCBhKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoYi5ieXRlTGVuZ3RoID09IHRoaXMuRi5uOCoyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMub3AyKFwiX3N1YkFmZmluZVwiLCBhLCBiKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiaW52YWxpZCBwb2ludCBzaXplXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiaW52YWxpZCBwb2ludCBzaXplXCIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbmVnKGEpIHtcbiAgICAgICAgaWYgKGEuYnl0ZUxlbmd0aCA9PSB0aGlzLkYubjgqMykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMub3AxKFwiX25lZ1wiLCBhKTtcbiAgICAgICAgfSBlbHNlIGlmIChhLmJ5dGVMZW5ndGggPT0gdGhpcy5GLm44KjIpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm9wMUFmZmluZShcIl9uZWdBZmZpbmVcIiwgYSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJpbnZhbGlkIHBvaW50IHNpemVcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBkb3VibGUoYSkge1xuICAgICAgICBpZiAoYS5ieXRlTGVuZ3RoID09IHRoaXMuRi5uOCozKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5vcDEoXCJfZG91YmxlXCIsIGEpO1xuICAgICAgICB9IGVsc2UgaWYgKGEuYnl0ZUxlbmd0aCA9PSB0aGlzLkYubjgqMikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMub3AxKFwiX2RvdWJsZUFmZmluZVwiLCBhKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImludmFsaWQgcG9pbnQgc2l6ZVwiKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlzWmVybyhhKSB7XG4gICAgICAgIGlmIChhLmJ5dGVMZW5ndGggPT0gdGhpcy5GLm44KjMpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm9wMUJvb2woXCJfaXNaZXJvXCIsIGEpO1xuICAgICAgICB9IGVsc2UgaWYgKGEuYnl0ZUxlbmd0aCA9PSB0aGlzLkYubjgqMikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMub3AxQm9vbChcIl9pc1plcm9BZmZpbmVcIiwgYSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJpbnZhbGlkIHBvaW50IHNpemVcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0aW1lc1NjYWxhcihhLCBzKSB7XG4gICAgICAgIGlmICghKHMgaW5zdGFuY2VvZiBVaW50OEFycmF5KSkge1xuICAgICAgICAgICAgcyA9IHRvTEVCdWZmKGUocykpO1xuICAgICAgICB9XG4gICAgICAgIGxldCBmbk5hbWU7XG4gICAgICAgIGlmIChhLmJ5dGVMZW5ndGggPT0gdGhpcy5GLm44KjMpIHtcbiAgICAgICAgICAgIGZuTmFtZSA9IHRoaXMucHJlZml4ICsgXCJfdGltZXNTY2FsYXJcIjtcbiAgICAgICAgfSBlbHNlIGlmIChhLmJ5dGVMZW5ndGggPT0gdGhpcy5GLm44KjIpIHtcbiAgICAgICAgICAgIGZuTmFtZSA9IHRoaXMucHJlZml4ICsgXCJfdGltZXNTY2FsYXJBZmZpbmVcIjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImludmFsaWQgcG9pbnQgc2l6ZVwiKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRtLnNldEJ1ZmYodGhpcy5wT3AxLCBhKTtcbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMiwgcyk7XG4gICAgICAgIHRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1tmbk5hbWVdKHRoaXMucE9wMSwgdGhpcy5wT3AyLCBzLmJ5dGVMZW5ndGgsIHRoaXMucE9wMyk7XG4gICAgICAgIHJldHVybiB0aGlzLnRtLmdldEJ1ZmYodGhpcy5wT3AzLCB0aGlzLkYubjgqMyk7XG4gICAgfVxuXG4gICAgdGltZXNGcihhLCBzKSB7XG4gICAgICAgIGxldCBmbk5hbWU7XG4gICAgICAgIGlmIChhLmJ5dGVMZW5ndGggPT0gdGhpcy5GLm44KjMpIHtcbiAgICAgICAgICAgIGZuTmFtZSA9IHRoaXMucHJlZml4ICsgXCJfdGltZXNGclwiO1xuICAgICAgICB9IGVsc2UgaWYgKGEuYnl0ZUxlbmd0aCA9PSB0aGlzLkYubjgqMikge1xuICAgICAgICAgICAgZm5OYW1lID0gdGhpcy5wcmVmaXggKyBcIl90aW1lc0ZyQWZmaW5lXCI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJpbnZhbGlkIHBvaW50IHNpemVcIik7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMSwgYSk7XG4gICAgICAgIHRoaXMudG0uc2V0QnVmZih0aGlzLnBPcDIsIHMpO1xuICAgICAgICB0aGlzLnRtLmluc3RhbmNlLmV4cG9ydHNbZm5OYW1lXSh0aGlzLnBPcDEsIHRoaXMucE9wMiwgdGhpcy5wT3AzKTtcbiAgICAgICAgcmV0dXJuIHRoaXMudG0uZ2V0QnVmZih0aGlzLnBPcDMsIHRoaXMuRi5uOCozKTtcbiAgICB9XG5cbiAgICBlcShhLGIpIHtcbiAgICAgICAgaWYgKGEuYnl0ZUxlbmd0aCA9PSB0aGlzLkYubjgqMykge1xuICAgICAgICAgICAgaWYgKGIuYnl0ZUxlbmd0aCA9PSB0aGlzLkYubjgqMykge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm9wMmJvb2woXCJfZXFcIiwgYSwgYik7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGIuYnl0ZUxlbmd0aCA9PSB0aGlzLkYubjgqMikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm9wMmJvb2woXCJfZXFNaXhlZFwiLCBhLCBiKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiaW52YWxpZCBwb2ludCBzaXplXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGEuYnl0ZUxlbmd0aCA9PSB0aGlzLkYubjgqMikge1xuICAgICAgICAgICAgaWYgKGIuYnl0ZUxlbmd0aCA9PSB0aGlzLkYubjgqMykge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm9wMmJvb2woXCJfZXFNaXhlZFwiLCBiLCBhKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoYi5ieXRlTGVuZ3RoID09IHRoaXMuRi5uOCoyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMub3AyYm9vbChcIl9lcUFmZmluZVwiLCBhLCBiKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiaW52YWxpZCBwb2ludCBzaXplXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiaW52YWxpZCBwb2ludCBzaXplXCIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdG9BZmZpbmUoYSkge1xuICAgICAgICBpZiAoYS5ieXRlTGVuZ3RoID09IHRoaXMuRi5uOCozKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5vcDFBZmZpbmUoXCJfdG9BZmZpbmVcIiwgYSk7XG4gICAgICAgIH0gZWxzZSBpZiAoYS5ieXRlTGVuZ3RoID09IHRoaXMuRi5uOCoyKSB7XG4gICAgICAgICAgICByZXR1cm4gYTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImludmFsaWQgcG9pbnQgc2l6ZVwiKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHRvSmFjb2JpYW4oYSkge1xuICAgICAgICBpZiAoYS5ieXRlTGVuZ3RoID09IHRoaXMuRi5uOCozKSB7XG4gICAgICAgICAgICByZXR1cm4gYTtcbiAgICAgICAgfSBlbHNlIGlmIChhLmJ5dGVMZW5ndGggPT0gdGhpcy5GLm44KjIpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm9wMShcIl90b0phY29iaWFuXCIsIGEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiaW52YWxpZCBwb2ludCBzaXplXCIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdG9ScHJVbmNvbXByZXNzZWQoYXJyLCBvZmZzZXQsIGEpIHtcbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMSwgYSk7XG4gICAgICAgIGlmIChhLmJ5dGVMZW5ndGggPT0gdGhpcy5GLm44KjMpIHtcbiAgICAgICAgICAgIHRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1t0aGlzLnByZWZpeCArIFwiX3RvQWZmaW5lXCJdKHRoaXMucE9wMSwgdGhpcy5wT3AxKTtcbiAgICAgICAgfSBlbHNlIGlmIChhLmJ5dGVMZW5ndGggIT0gdGhpcy5GLm44KjIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImludmFsaWQgcG9pbnQgc2l6ZVwiKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRtLmluc3RhbmNlLmV4cG9ydHNbdGhpcy5wcmVmaXggKyBcIl9MRU10b1VcIl0odGhpcy5wT3AxLCB0aGlzLnBPcDEpO1xuICAgICAgICBjb25zdCByZXMgPSB0aGlzLnRtLmdldEJ1ZmYodGhpcy5wT3AxLCB0aGlzLkYubjgqMik7XG4gICAgICAgIGFyci5zZXQocmVzLCBvZmZzZXQpO1xuICAgIH1cblxuICAgIGZyb21ScHJVbmNvbXByZXNzZWQoYXJyLCBvZmZzZXQpIHtcbiAgICAgICAgY29uc3QgYnVmZiA9IGFyci5zbGljZShvZmZzZXQsIG9mZnNldCArIHRoaXMuRi5uOCoyKTtcbiAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMSwgYnVmZik7XG4gICAgICAgIHRoaXMudG0uaW5zdGFuY2UuZXhwb3J0c1t0aGlzLnByZWZpeCArIFwiX1V0b0xFTVwiXSh0aGlzLnBPcDEsIHRoaXMucE9wMSk7XG4gICAgICAgIHJldHVybiB0aGlzLnRtLmdldEJ1ZmYodGhpcy5wT3AxLCB0aGlzLkYubjgqMik7XG4gICAgfVxuXG4gICAgdG9ScHJDb21wcmVzc2VkKGFyciwgb2Zmc2V0LCBhKSB7XG4gICAgICAgIHRoaXMudG0uc2V0QnVmZih0aGlzLnBPcDEsIGEpO1xuICAgICAgICBpZiAoYS5ieXRlTGVuZ3RoID09IHRoaXMuRi5uOCozKSB7XG4gICAgICAgICAgICB0aGlzLnRtLmluc3RhbmNlLmV4cG9ydHNbdGhpcy5wcmVmaXggKyBcIl90b0FmZmluZVwiXSh0aGlzLnBPcDEsIHRoaXMucE9wMSk7XG4gICAgICAgIH0gZWxzZSBpZiAoYS5ieXRlTGVuZ3RoICE9IHRoaXMuRi5uOCoyKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJpbnZhbGlkIHBvaW50IHNpemVcIik7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy50bS5pbnN0YW5jZS5leHBvcnRzW3RoaXMucHJlZml4ICsgXCJfTEVNdG9DXCJdKHRoaXMucE9wMSwgdGhpcy5wT3AxKTtcbiAgICAgICAgY29uc3QgcmVzID0gdGhpcy50bS5nZXRCdWZmKHRoaXMucE9wMSwgdGhpcy5GLm44KTtcbiAgICAgICAgYXJyLnNldChyZXMsIG9mZnNldCk7XG4gICAgfVxuXG4gICAgZnJvbVJwckNvbXByZXNzZWQoYXJyLCBvZmZzZXQpIHtcbiAgICAgICAgY29uc3QgYnVmZiA9IGFyci5zbGljZShvZmZzZXQsIG9mZnNldCArIHRoaXMuRi5uOCk7XG4gICAgICAgIHRoaXMudG0uc2V0QnVmZih0aGlzLnBPcDEsIGJ1ZmYpO1xuICAgICAgICB0aGlzLnRtLmluc3RhbmNlLmV4cG9ydHNbdGhpcy5wcmVmaXggKyBcIl9DdG9MRU1cIl0odGhpcy5wT3AxLCB0aGlzLnBPcDIpO1xuICAgICAgICByZXR1cm4gdGhpcy50bS5nZXRCdWZmKHRoaXMucE9wMiwgdGhpcy5GLm44KjIpO1xuICAgIH1cblxuICAgIHRvVW5jb21wcmVzc2VkKGEpIHtcbiAgICAgICAgY29uc3QgYnVmZiA9IG5ldyBVaW50OEFycmF5KHRoaXMuRi5uOCoyKTtcbiAgICAgICAgdGhpcy50b1JwclVuY29tcHJlc3NlZChidWZmLCAwLCBhKTtcbiAgICAgICAgcmV0dXJuIGJ1ZmY7XG4gICAgfVxuXG4gICAgdG9ScHJMRU0oYXJyLCBvZmZzZXQsIGEpIHtcbiAgICAgICAgaWYgKGEuYnl0ZUxlbmd0aCA9PSB0aGlzLkYubjgqMikge1xuICAgICAgICAgICAgYXJyLnNldChhLCBvZmZzZXQpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2UgaWYgKGEuYnl0ZUxlbmd0aCA9PSB0aGlzLkYubjgqMykge1xuICAgICAgICAgICAgdGhpcy50bS5zZXRCdWZmKHRoaXMucE9wMSwgYSk7XG4gICAgICAgICAgICB0aGlzLnRtLmluc3RhbmNlLmV4cG9ydHNbdGhpcy5wcmVmaXggKyBcIl90b0FmZmluZVwiXSh0aGlzLnBPcDEsIHRoaXMucE9wMSk7XG4gICAgICAgICAgICBjb25zdCByZXMgPSB0aGlzLnRtLmdldEJ1ZmYodGhpcy5wT3AxLCB0aGlzLkYubjgqMik7XG4gICAgICAgICAgICBhcnIuc2V0KHJlcywgb2Zmc2V0KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImludmFsaWQgcG9pbnQgc2l6ZVwiKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZyb21ScHJMRU0oYXJyLCBvZmZzZXQpIHtcbiAgICAgICAgb2Zmc2V0ID0gb2Zmc2V0IHx8IDA7XG4gICAgICAgIHJldHVybiBhcnIuc2xpY2Uob2Zmc2V0LCBvZmZzZXQrdGhpcy5GLm44KjIpO1xuICAgIH1cblxuICAgIHRvU3RyaW5nKGEsIHJhZGl4KSB7XG4gICAgICAgIGlmIChhLmJ5dGVMZW5ndGggPT0gdGhpcy5GLm44KjMpIHtcbiAgICAgICAgICAgIGNvbnN0IHggPSB0aGlzLkYudG9TdHJpbmcoYS5zbGljZSgwLCB0aGlzLkYubjgpLCByYWRpeCk7XG4gICAgICAgICAgICBjb25zdCB5ID0gdGhpcy5GLnRvU3RyaW5nKGEuc2xpY2UodGhpcy5GLm44LCB0aGlzLkYubjgqMiksIHJhZGl4KTtcbiAgICAgICAgICAgIGNvbnN0IHogPSB0aGlzLkYudG9TdHJpbmcoYS5zbGljZSh0aGlzLkYubjgqMiksIHJhZGl4KTtcbiAgICAgICAgICAgIHJldHVybiBgWyAke3h9LCAke3l9LCAke3p9IF1gO1xuICAgICAgICB9IGVsc2UgaWYgKGEuYnl0ZUxlbmd0aCA9PSB0aGlzLkYubjgqMikge1xuICAgICAgICAgICAgY29uc3QgeCA9IHRoaXMuRi50b1N0cmluZyhhLnNsaWNlKDAsIHRoaXMuRi5uOCksIHJhZGl4KTtcbiAgICAgICAgICAgIGNvbnN0IHkgPSB0aGlzLkYudG9TdHJpbmcoYS5zbGljZSh0aGlzLkYubjgpLCByYWRpeCk7XG4gICAgICAgICAgICByZXR1cm4gYFsgJHt4fSwgJHt5fSBdYDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImludmFsaWQgcG9pbnQgc2l6ZVwiKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlzVmFsaWQoYSkge1xuICAgICAgICBpZiAodGhpcy5pc1plcm8oYSkpIHJldHVybiB0cnVlO1xuICAgICAgICBjb25zdCBGID0gdGhpcy5GO1xuICAgICAgICBjb25zdCBhYSA9IHRoaXMudG9BZmZpbmUoYSk7XG4gICAgICAgIGNvbnN0IHggPSBhYS5zbGljZSgwLCB0aGlzLkYubjgpO1xuICAgICAgICBjb25zdCB5ID0gYWEuc2xpY2UodGhpcy5GLm44LCB0aGlzLkYubjgqMik7XG4gICAgICAgIGNvbnN0IHgzYiA9IEYuYWRkKEYubXVsKEYuc3F1YXJlKHgpLHgpLCB0aGlzLmIpO1xuICAgICAgICBjb25zdCB5MiA9IEYuc3F1YXJlKHkpO1xuICAgICAgICByZXR1cm4gRi5lcSh4M2IsIHkyKTtcbiAgICB9XG5cbiAgICBmcm9tUm5nKHJuZykge1xuICAgICAgICBjb25zdCBGID0gdGhpcy5GO1xuICAgICAgICBsZXQgUCA9IFtdO1xuICAgICAgICBsZXQgZ3JlYXRlc3Q7XG4gICAgICAgIGxldCB4M2I7XG4gICAgICAgIGRvIHtcbiAgICAgICAgICAgIFBbMF0gPSBGLmZyb21Sbmcocm5nKTtcbiAgICAgICAgICAgIGdyZWF0ZXN0ID0gcm5nLm5leHRCb29sKCk7XG4gICAgICAgICAgICB4M2IgPSBGLmFkZChGLm11bChGLnNxdWFyZShQWzBdKSwgUFswXSksIHRoaXMuYik7XG4gICAgICAgIH0gd2hpbGUgKCFGLmlzU3F1YXJlKHgzYikpO1xuXG4gICAgICAgIFBbMV0gPSBGLnNxcnQoeDNiKTtcblxuICAgICAgICBjb25zdCBzID0gRi5pc05lZ2F0aXZlKFBbMV0pO1xuICAgICAgICBpZiAoZ3JlYXRlc3QgXiBzKSBQWzFdID0gRi5uZWcoUFsxXSk7XG5cbiAgICAgICAgbGV0IFBidWZmID0gbmV3IFVpbnQ4QXJyYXkodGhpcy5GLm44KjIpO1xuICAgICAgICBQYnVmZi5zZXQoUFswXSk7XG4gICAgICAgIFBidWZmLnNldChQWzFdLCB0aGlzLkYubjgpO1xuXG4gICAgICAgIGlmICh0aGlzLmNvZmFjdG9yKSB7XG4gICAgICAgICAgICBQYnVmZiA9IHRoaXMudGltZXNTY2FsYXIoUGJ1ZmYsIHRoaXMuY29mYWN0b3IpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFBidWZmO1xuICAgIH1cblxuXG5cbiAgICB0b09iamVjdChhKSB7XG4gICAgICAgIGlmICh0aGlzLmlzWmVybyhhKSkge1xuICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgICB0aGlzLkYudG9PYmplY3QodGhpcy5GLnplcm8pLFxuICAgICAgICAgICAgICAgIHRoaXMuRi50b09iamVjdCh0aGlzLkYub25lKSxcbiAgICAgICAgICAgICAgICB0aGlzLkYudG9PYmplY3QodGhpcy5GLnplcm8pLFxuICAgICAgICAgICAgXTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB4ID0gdGhpcy5GLnRvT2JqZWN0KGEuc2xpY2UoMCwgdGhpcy5GLm44KSk7XG4gICAgICAgIGNvbnN0IHkgPSB0aGlzLkYudG9PYmplY3QoYS5zbGljZSh0aGlzLkYubjgsIHRoaXMuRi5uOCoyKSk7XG4gICAgICAgIGxldCB6O1xuICAgICAgICBpZiAoYS5ieXRlTGVuZ3RoID09IHRoaXMuRi5uOCozKSB7XG4gICAgICAgICAgICB6ID0gdGhpcy5GLnRvT2JqZWN0KGEuc2xpY2UodGhpcy5GLm44KjIsIHRoaXMuRi5uOCozKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB6ID0gdGhpcy5GLnRvT2JqZWN0KHRoaXMuRi5vbmUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBbeCwgeSwgel07XG4gICAgfVxuXG4gICAgZnJvbU9iamVjdChhKSB7XG4gICAgICAgIGNvbnN0IHggPSB0aGlzLkYuZnJvbU9iamVjdChhWzBdKTtcbiAgICAgICAgY29uc3QgeSA9IHRoaXMuRi5mcm9tT2JqZWN0KGFbMV0pO1xuICAgICAgICBsZXQgejtcbiAgICAgICAgaWYgKGEubGVuZ3RoPT0zKSB7XG4gICAgICAgICAgICB6ID0gdGhpcy5GLmZyb21PYmplY3QoYVsyXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB6ID0gdGhpcy5GLm9uZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5GLmlzWmVybyh6LCB0aGlzLkYub25lKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuemVyb0FmZmluZTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLkYuZXEoeiwgdGhpcy5GLm9uZSkpIHtcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmYgPSBuZXcgVWludDhBcnJheSh0aGlzLkYubjgqMik7XG4gICAgICAgICAgICBidWZmLnNldCh4KTtcbiAgICAgICAgICAgIGJ1ZmYuc2V0KHksIHRoaXMuRi5uOCk7XG4gICAgICAgICAgICByZXR1cm4gYnVmZjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmYgPSBuZXcgVWludDhBcnJheSh0aGlzLkYubjgqMyk7XG4gICAgICAgICAgICBidWZmLnNldCh4KTtcbiAgICAgICAgICAgIGJ1ZmYuc2V0KHksIHRoaXMuRi5uOCk7XG4gICAgICAgICAgICBidWZmLnNldCh6LCB0aGlzLkYubjgqMik7XG4gICAgICAgICAgICByZXR1cm4gYnVmZjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGUoYSkge1xuICAgICAgICBpZiAoYSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHJldHVybiBhO1xuICAgICAgICByZXR1cm4gdGhpcy5mcm9tT2JqZWN0KGEpO1xuICAgIH1cblxuICAgIHgoYSkge1xuICAgICAgICBjb25zdCB0bXAgPSB0aGlzLnRvQWZmaW5lKGEpO1xuICAgICAgICByZXR1cm4gdG1wLnNsaWNlKDAsIHRoaXMuRi5uOCk7XG4gICAgfVxuXG4gICAgeShhKSB7XG4gICAgICAgIGNvbnN0IHRtcCA9IHRoaXMudG9BZmZpbmUoYSk7XG4gICAgICAgIHJldHVybiB0bXAuc2xpY2UodGhpcy5GLm44KTtcbiAgICB9XG5cbn1cblxuLyogZ2xvYmFsIFdlYkFzc2VtYmx5ICovXG5cbmZ1bmN0aW9uIHRocmVhZChzZWxmKSB7XG4gICAgY29uc3QgTUFYTUVNID0gMzI3Njc7XG4gICAgbGV0IGluc3RhbmNlO1xuICAgIGxldCBtZW1vcnk7XG4gICAgbGV0IHRlcm1pbmF0aW9uVGltZW91dCA9IDUwMDsgLy8gbWlsbGlzZWNvbmRzXG4gICAgbGV0IHRlcm1pbmF0aW9uVGltZXI7XG5cbiAgICBpZiAoc2VsZikge1xuICAgICAgICBzZWxmLm9ubWVzc2FnZSA9IGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIGxldCBkYXRhO1xuICAgICAgICAgICAgaWYgKGUuZGF0YSkge1xuICAgICAgICAgICAgICAgIGRhdGEgPSBlLmRhdGE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGRhdGEgPSBlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmIChkYXRhWzBdLmNtZCA9PT0gXCJJTklUXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgaW5pdChkYXRhWzBdKS50aGVuKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJJTklUIERPTkVcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnBvc3RNZXNzYWdlKHtzdGF0dXM6IFwiaW5pdGlhbGl6ZWRcIn0pO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRhdGFbMF0uY21kID09PSBcIlRFUk1JTkFURVwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHRlcm1pbmF0ZSgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChkYXRhW2RhdGEubGVuZ3RoLTFdLmNtZCA9PT0gXCJURVJNSU5BVEVcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vdGVybWluYXRpb25UaW1lb3V0ID0gMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb25zdCByZXMgPSBydW5UYXNrKGRhdGEpO1xuICAgICAgICAgICAgICAgICAgICAvL3NlbGYucG9zdE1lc3NhZ2UocmVzKTtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHRyYW5zZmVycyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpPTA7IGk8cmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzW2ldIGluc3RhbmNlb2YgVWludDhBcnJheSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZmVycy5wdXNoKHJlc1tpXS5idWZmZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwidHJhbnNmZXIgYnVmZmVyXCIsIHJlc1tpXS5ieXRlTGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpPTA7IGk8ZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGFbaV0uY21kID09PSBcIkNBTExcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGRhdGFbaV0uZm5OYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvL2NvbnNvbGUubG9nKFwidHJhbnNmZXJzXCIsIHRyYW5zZmVycyk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYucG9zdE1lc3NhZ2UocmVzLCB0cmFuc2ZlcnMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIC8vIENhdGNoIGFueSBlcnJvciBhbmQgc2VuZCBpdCBiYWNrIHRvIG1haW4gdGhyZWFkXG4gICAgICAgICAgICAgICAgc2VsZi5wb3N0TWVzc2FnZSh7ZXJyb3I6IGVyci5tZXNzYWdlfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gc2VsZi5vbmVycm9yID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgLy8gICAgIGNvbnNvbGUuZXJyb3IoXCJXb3JrZXIgY2F1Z2h0IGFuIGVycm9yOlwiLCBlLm1lc3NhZ2UpO1xuICAgICAgICAvLyAgICAgLy8gUHJldmVudCB0aGUgZGVmYXVsdCBiZWhhdmlvciAod2hpY2ggd291bGQgdGVybWluYXRlIHRoZSB3b3JrZXIpXG4gICAgICAgIC8vICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgLy8gfTtcbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiBpbml0KGRhdGEpIHtcbiAgICAgICAgbGV0IHdhc21Nb2R1bGU7XG4gICAgICAgIGlmIChkYXRhLmNvZGUgaW5zdGFuY2VvZiBXZWJBc3NlbWJseS5Nb2R1bGUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiVXNpbmcgcHJlY29tcGlsZWQgV2ViQXNzZW1ibHkuTW9kdWxlXCIpO1xuICAgICAgICAgICAgd2FzbU1vZHVsZSA9IGRhdGEuY29kZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiQ29tcGlsaW5nIFdlYkFzc2VtYmx5Lk1vZHVsZVwiKTtcbiAgICAgICAgICAgIGNvbnN0IGNvZGUgPSBuZXcgVWludDhBcnJheShkYXRhLmNvZGUpO1xuICAgICAgICAgICAgd2FzbU1vZHVsZSA9IGF3YWl0IFdlYkFzc2VtYmx5LmNvbXBpbGUoY29kZSk7XG4gICAgICAgIH1cbiAgICAgICAgbWVtb3J5ID0gbmV3IFdlYkFzc2VtYmx5Lk1lbW9yeSh7aW5pdGlhbDpkYXRhLmluaXQsIG1heGltdW06IE1BWE1FTX0pO1xuXG4gICAgICAgIGNvbnNvbGUubG9nKFwiSW5pdGlhbGl6ZWQgdGhyZWFkIHdpdGggbWVtb3J5XCIsIG1lbW9yeS5idWZmZXIuYnl0ZUxlbmd0aCAvIDEwMjQgLyAxMDI0LCBcIk1CXCIpO1xuXG4gICAgICAgIGluc3RhbmNlID0gYXdhaXQgV2ViQXNzZW1ibHkuaW5zdGFudGlhdGUod2FzbU1vZHVsZSwge1xuICAgICAgICAgICAgZW52OiB7XG4gICAgICAgICAgICAgICAgXCJtZW1vcnlcIjogbWVtb3J5XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChkYXRhLnRlcm1pbmF0aW9uVGltZW91dCkge1xuICAgICAgICAgICAgdGVybWluYXRpb25UaW1lb3V0ID0gZGF0YS50ZXJtaW5hdGlvblRpbWVvdXQ7XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS5sb2coXCJpbml0IGRvbmUhXCIpO1xuXG4gICAgICAgIHNjaGVkdWxlVGVybWluYXRpb24oKTtcbiAgICB9XG5cblxuXG4gICAgZnVuY3Rpb24gYWxsb2MobGVuZ3RoKSB7XG4gICAgICAgIGNvbnN0IHUzMiA9IG5ldyBVaW50MzJBcnJheShtZW1vcnkuYnVmZmVyLCAwLCAxKTtcbiAgICAgICAgd2hpbGUgKHUzMlswXSAmIDMpIHUzMlswXSsrOyAgLy8gUmV0dXJuIGFsd2F5cyBhbGlnbmVkIHBvaW50ZXJzXG4gICAgICAgIGNvbnN0IHJlcyA9IHUzMlswXTtcbiAgICAgICAgdTMyWzBdICs9IGxlbmd0aDtcbiAgICAgICAgaWYgKHUzMlswXSArIGxlbmd0aCA+IG1lbW9yeS5idWZmZXIuYnl0ZUxlbmd0aCkge1xuICAgICAgICAgICAgY29uc3QgY3VycmVudFBhZ2VzID0gbWVtb3J5LmJ1ZmZlci5ieXRlTGVuZ3RoIC8gMHgxMDAwMDtcbiAgICAgICAgICAgIGxldCByZXF1aXJlZFBhZ2VzID0gTWF0aC5mbG9vcigodTMyWzBdICsgbGVuZ3RoKSAvIDB4MTAwMDApKzE7XG4gICAgICAgICAgICBpZiAocmVxdWlyZWRQYWdlcz5NQVhNRU0pIHJlcXVpcmVkUGFnZXM9TUFYTUVNO1xuICAgICAgICAgICAgbWVtb3J5Lmdyb3cocmVxdWlyZWRQYWdlcy1jdXJyZW50UGFnZXMpO1xuICAgICAgICAgICAgY29uc29sZS5sb2coXCJHcm93aW5nIG1lbW9yeSB0b1wiLCBtZW1vcnkuYnVmZmVyLmJ5dGVMZW5ndGggLyAxMDI0IC8gMTAyNCwgXCJNQlwiKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFsbG9jQnVmZmVyKGJ1ZmZlcikge1xuICAgICAgICBjb25zdCBwID0gYWxsb2MoYnVmZmVyLmJ5dGVMZW5ndGgpO1xuICAgICAgICBzZXRCdWZmZXIocCwgYnVmZmVyKTtcbiAgICAgICAgcmV0dXJuIHA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0QnVmZmVyKHBvaW50ZXIsIGxlbmd0aCkge1xuICAgICAgICAvLyBjb25zdCB1OCA9IG5ldyBVaW50OEFycmF5KG1lbW9yeS5idWZmZXIpO1xuICAgICAgICAvLyByZXR1cm4gbmV3IFVpbnQ4QXJyYXkodTguYnVmZmVyLCB1OC5ieXRlT2Zmc2V0ICsgcG9pbnRlciwgbGVuZ3RoKTtcbiAgICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KG1lbW9yeS5idWZmZXIsIHBvaW50ZXIsIGxlbmd0aCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2V0QnVmZmVyKHBvaW50ZXIsIGJ1ZmZlcikge1xuICAgICAgICBjb25zdCB1OCA9IG5ldyBVaW50OEFycmF5KG1lbW9yeS5idWZmZXIpO1xuICAgICAgICB1OC5zZXQobmV3IFVpbnQ4QXJyYXkoYnVmZmVyKSwgcG9pbnRlcik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcnVuVGFzayh0YXNrKSB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0ZXJtaW5hdGlvblRpbWVyKTtcbiAgICAgICAgaWYgKHRhc2tbMF0uY21kID09PSBcIklOSVRcIikge1xuICAgICAgICAgICAgcmV0dXJuIGluaXQodGFza1swXSk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY3R4ID0ge1xuICAgICAgICAgICAgdmFyczogW10sXG4gICAgICAgICAgICBvdXQ6IFtdXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IHUzMmEgPSBuZXcgVWludDMyQXJyYXkobWVtb3J5LmJ1ZmZlciwgMCwgMSk7XG4gICAgICAgIGNvbnN0IG9sZEFsbG9jID0gdTMyYVswXTtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPHRhc2subGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHN3aXRjaCAodGFza1tpXS5jbWQpIHtcbiAgICAgICAgICAgIGNhc2UgXCJBTExPQ1NFVFwiOlxuICAgICAgICAgICAgICAgIGN0eC52YXJzW3Rhc2tbaV0udmFyXSA9IGFsbG9jQnVmZmVyKHRhc2tbaV0uYnVmZik7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwiQUxMT0NcIjpcbiAgICAgICAgICAgICAgICBjdHgudmFyc1t0YXNrW2ldLnZhcl0gPSBhbGxvYyh0YXNrW2ldLmxlbik7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwiU0VUXCI6XG4gICAgICAgICAgICAgICAgc2V0QnVmZmVyKGN0eC52YXJzW3Rhc2tbaV0udmFyXSwgdGFza1tpXS5idWZmKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJDQUxMXCI6IHtcbiAgICAgICAgICAgICAgICBjb25zdCBwYXJhbXMgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqPTA7IGo8dGFza1tpXS5wYXJhbXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcCA9IHRhc2tbaV0ucGFyYW1zW2pdO1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHAudmFyICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJhbXMucHVzaChjdHgudmFyc1twLnZhcl0gKyAocC5vZmZzZXQgfHwgMCkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBwLnZhbCAhPSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJhbXMucHVzaChwLnZhbCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaW5zdGFuY2UuZXhwb3J0c1t0YXNrW2ldLmZuTmFtZV0oLi4ucGFyYW1zKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhc2UgXCJHRVRcIjpcbiAgICAgICAgICAgICAgICBjdHgub3V0W3Rhc2tbaV0ub3V0XSA9IGdldEJ1ZmZlcihjdHgudmFyc1t0YXNrW2ldLnZhcl0sIHRhc2tbaV0ubGVuKS5zbGljZSgpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIGNtZFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjb25zdCB1MzJiID0gbmV3IFVpbnQzMkFycmF5KG1lbW9yeS5idWZmZXIsIDAsIDEpO1xuICAgICAgICB1MzJiWzBdID0gb2xkQWxsb2M7XG5cbiAgICAgICAgLy9jb25zb2xlLmxvZyhjdHgub3V0KTtcblxuICAgICAgICByZXR1cm4gY3R4Lm91dDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzY2hlZHVsZVRlcm1pbmF0aW9uKCkge1xuICAgICAgICBpZiAodGVybWluYXRpb25UaW1lb3V0PjApIHtcbiAgICAgICAgICAgIHRlcm1pbmF0aW9uVGltZXIgPSBzZXRUaW1lb3V0KCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJTaHV0dGluZyBkb3duIHRocmVhZCBkdWUgdG8gaW5hY3Rpdml0eVwiKTtcbiAgICAgICAgICAgICAgICB0ZXJtaW5hdGUoKTtcbiAgICAgICAgICAgIH0sIHRlcm1pbmF0aW9uVGltZW91dCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0ZXJtaW5hdGUoKSB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0ZXJtaW5hdGlvblRpbWVyKTtcbiAgICAgICAgaW5zdGFuY2UgPSBudWxsO1xuICAgICAgICBtZW1vcnkgPSBudWxsO1xuICAgICAgICBpZiAoc2VsZikge1xuICAgICAgICAgICAgY29uc29sZS5sb2coXCJURVJNSU5BVEVcIik7XG4gICAgICAgICAgICBzZWxmLnBvc3RNZXNzYWdlKHtzdGF0dXM6IFwidGVybWluYXRlZFwifSk7XG4gICAgICAgICAgICBzZWxmLmNsb3NlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcnVuVGFzaztcbn1cblxuLypcbiAgICBDb3B5cmlnaHQgMjAxOSAwS0lNUyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHdhc21zbmFyayAoV2ViIEFzc2VtYmx5IHprU25hcmsgUHJvdmVyKS5cblxuICAgIHdhc21zbmFyayBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHdhc21zbmFyayBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVFxuICAgIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpY1xuICAgIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gICAgYWxvbmcgd2l0aCB3YXNtc25hcmsuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG4vLyBjb25zdCBNRU1fU0laRSA9IDEwMDA7ICAvLyBNZW1vcnkgc2l6ZSBpbiA2NEsgUGFrZXMgKDUxMk1iKVxuY29uc3QgTUVNX1NJWkUgPSAyNTsgIC8vIE1lbW9yeSBzaXplIGluIDY0SyBQYWtlcyAoMTYwMEtiKVxuXG5jbGFzcyBEZWZlcnJlZCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMucHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpPT4ge1xuICAgICAgICAgICAgdGhpcy5yZWplY3QgPSByZWplY3Q7XG4gICAgICAgICAgICB0aGlzLnJlc29sdmUgPSByZXNvbHZlO1xuICAgICAgICB9KTtcbiAgICB9XG59XG5cbmxldCB3b3JrZXJTb3VyY2U7XG5cbmNvbnN0IHRocmVhZFN0ciA9IGAoJHtcImZ1bmN0aW9uIHRocmVhZChzZWxmKSB7XFxuICAgIGNvbnN0IE1BWE1FTSA9IDMyNzY3O1xcbiAgICBsZXQgaW5zdGFuY2U7XFxuICAgIGxldCBtZW1vcnk7XFxuICAgIGxldCB0ZXJtaW5hdGlvblRpbWVvdXQgPSA1MDA7IC8vIG1pbGxpc2Vjb25kc1xcbiAgICBsZXQgdGVybWluYXRpb25UaW1lcjtcXG5cXG4gICAgaWYgKHNlbGYpIHtcXG4gICAgICAgIHNlbGYub25tZXNzYWdlID0gZnVuY3Rpb24oZSkge1xcbiAgICAgICAgICAgIGxldCBkYXRhO1xcbiAgICAgICAgICAgIGlmIChlLmRhdGEpIHtcXG4gICAgICAgICAgICAgICAgZGF0YSA9IGUuZGF0YTtcXG4gICAgICAgICAgICB9IGVsc2Uge1xcbiAgICAgICAgICAgICAgICBkYXRhID0gZTtcXG4gICAgICAgICAgICB9XFxuXFxuICAgICAgICAgICAgdHJ5IHtcXG4gICAgICAgICAgICAgICAgaWYgKGRhdGFbMF0uY21kID09PSBcXFwiSU5JVFxcXCIpIHtcXG4gICAgICAgICAgICAgICAgICAgIGluaXQoZGF0YVswXSkudGhlbihmdW5jdGlvbigpIHtcXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcXFwiSU5JVCBET05FXFxcIik7XFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5wb3N0TWVzc2FnZSh7c3RhdHVzOiBcXFwiaW5pdGlhbGl6ZWRcXFwifSk7XFxuICAgICAgICAgICAgICAgICAgICB9KTtcXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkYXRhWzBdLmNtZCA9PT0gXFxcIlRFUk1JTkFURVxcXCIpIHtcXG4gICAgICAgICAgICAgICAgICAgIHRlcm1pbmF0ZSgpO1xcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xcbiAgICAgICAgICAgICAgICAgICAgbGV0IHRlcm1pbmF0ZUFmdGVyVGFzayA9IGZhbHNlO1xcbiAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGFbZGF0YS5sZW5ndGgtMV0uY21kID09PSBcXFwiVEVSTUlOQVRFXFxcIikge1xcbiAgICAgICAgICAgICAgICAgICAgICAgIHRlcm1pbmF0ZUFmdGVyVGFzayA9IHRydWU7XFxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5wb3AoKTtcXG4gICAgICAgICAgICAgICAgICAgICAgICAvL3Rlcm1pbmF0aW9uVGltZW91dCA9IDE7XFxuICAgICAgICAgICAgICAgICAgICB9XFxuICAgICAgICAgICAgICAgICAgICBjb25zdCByZXMgPSBydW5UYXNrKGRhdGEpO1xcbiAgICAgICAgICAgICAgICAgICAgLy9zZWxmLnBvc3RNZXNzYWdlKHJlcyk7XFxuICAgICAgICAgICAgICAgICAgICBsZXQgdHJhbnNmZXJzID0gW107XFxuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpPTA7IGk8cmVzLmxlbmd0aDsgaSsrKSB7XFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc1tpXSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHtcXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmZXJzLnB1c2gocmVzW2ldLmJ1ZmZlcik7XFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFxcXCJ0cmFuc2ZlciBidWZmZXJcXFwiLCByZXNbaV0uYnl0ZUxlbmd0aCk7XFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxcbiAgICAgICAgICAgICAgICAgICAgfVxcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaT0wOyBpPGRhdGEubGVuZ3RoOyBpKyspIHtcXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YVtpXS5jbWQgPT09IFxcXCJDQUxMXFxcIikge1xcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhkYXRhW2ldLmZuTmFtZSk7XFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxcbiAgICAgICAgICAgICAgICAgICAgfVxcbiAgICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmxvZyhcXFwidHJhbnNmZXJzXFxcIiwgdHJhbnNmZXJzKTtcXG4gICAgICAgICAgICAgICAgICAgIHNlbGYucG9zdE1lc3NhZ2UocmVzLCB0cmFuc2ZlcnMpO1xcbiAgICAgICAgICAgICAgICAgICAgLy9zZWxmLnBvc3RNZXNzYWdlKHJlcyk7XFxuICAgICAgICAgICAgICAgICAgICBpZiAodGVybWluYXRlQWZ0ZXJUYXNrKSB7XFxuICAgICAgICAgICAgICAgICAgICAgICAgLy90ZXJtaW5hdGUoKTtcXG4gICAgICAgICAgICAgICAgICAgIH1cXG4gICAgICAgICAgICAgICAgfVxcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xcbiAgICAgICAgICAgICAgICAvLyBDYXRjaCBhbnkgZXJyb3IgYW5kIHNlbmQgaXQgYmFjayB0byBtYWluIHRocmVhZFxcbiAgICAgICAgICAgICAgICBzZWxmLnBvc3RNZXNzYWdlKHtlcnJvcjogZXJyLm1lc3NhZ2V9KTtcXG4gICAgICAgICAgICB9XFxuICAgICAgICB9O1xcblxcbiAgICAgICAgLy8gc2VsZi5vbmVycm9yID0gZnVuY3Rpb24gKGUpIHtcXG4gICAgICAgIC8vICAgICBjb25zb2xlLmVycm9yKFxcXCJXb3JrZXIgY2F1Z2h0IGFuIGVycm9yOlxcXCIsIGUubWVzc2FnZSk7XFxuICAgICAgICAvLyAgICAgLy8gUHJldmVudCB0aGUgZGVmYXVsdCBiZWhhdmlvciAod2hpY2ggd291bGQgdGVybWluYXRlIHRoZSB3b3JrZXIpXFxuICAgICAgICAvLyAgICAgcmV0dXJuIHRydWU7XFxuICAgICAgICAvLyB9O1xcbiAgICB9XFxuXFxuICAgIGFzeW5jIGZ1bmN0aW9uIGluaXQoZGF0YSkge1xcbiAgICAgICAgbGV0IHdhc21Nb2R1bGU7XFxuICAgICAgICBpZiAoZGF0YS5jb2RlIGluc3RhbmNlb2YgV2ViQXNzZW1ibHkuTW9kdWxlKSB7XFxuICAgICAgICAgICAgY29uc29sZS5sb2coXFxcIlVzaW5nIHByZWNvbXBpbGVkIFdlYkFzc2VtYmx5Lk1vZHVsZVxcXCIpO1xcbiAgICAgICAgICAgIHdhc21Nb2R1bGUgPSBkYXRhLmNvZGU7XFxuICAgICAgICB9IGVsc2Uge1xcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFxcXCJDb21waWxpbmcgV2ViQXNzZW1ibHkuTW9kdWxlXFxcIik7XFxuICAgICAgICAgICAgY29uc3QgY29kZSA9IG5ldyBVaW50OEFycmF5KGRhdGEuY29kZSk7XFxuICAgICAgICAgICAgd2FzbU1vZHVsZSA9IGF3YWl0IFdlYkFzc2VtYmx5LmNvbXBpbGUoY29kZSk7XFxuICAgICAgICB9XFxuICAgICAgICBtZW1vcnkgPSBuZXcgV2ViQXNzZW1ibHkuTWVtb3J5KHtpbml0aWFsOmRhdGEuaW5pdCwgbWF4aW11bTogTUFYTUVNfSk7XFxuXFxuICAgICAgICBjb25zb2xlLmxvZyhcXFwiSW5pdGlhbGl6ZWQgdGhyZWFkIHdpdGggbWVtb3J5XFxcIiwgbWVtb3J5LmJ1ZmZlci5ieXRlTGVuZ3RoIC8gMTAyNCAvIDEwMjQsIFxcXCJNQlxcXCIpO1xcblxcbiAgICAgICAgaW5zdGFuY2UgPSBhd2FpdCBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZSh3YXNtTW9kdWxlLCB7XFxuICAgICAgICAgICAgZW52OiB7XFxuICAgICAgICAgICAgICAgIFxcXCJtZW1vcnlcXFwiOiBtZW1vcnlcXG4gICAgICAgICAgICB9XFxuICAgICAgICB9KTtcXG5cXG4gICAgICAgIGlmIChkYXRhLnRlcm1pbmF0aW9uVGltZW91dCkge1xcbiAgICAgICAgICAgIHRlcm1pbmF0aW9uVGltZW91dCA9IGRhdGEudGVybWluYXRpb25UaW1lb3V0O1xcbiAgICAgICAgfVxcbiAgICAgICAgY29uc29sZS5sb2coXFxcImluaXQgZG9uZSFcXFwiKTtcXG5cXG4gICAgICAgIHNjaGVkdWxlVGVybWluYXRpb24oKTtcXG4gICAgfVxcblxcblxcblxcbiAgICBmdW5jdGlvbiBhbGxvYyhsZW5ndGgpIHtcXG4gICAgICAgIGNvbnN0IHUzMiA9IG5ldyBVaW50MzJBcnJheShtZW1vcnkuYnVmZmVyLCAwLCAxKTtcXG4gICAgICAgIHdoaWxlICh1MzJbMF0gJiAzKSB1MzJbMF0rKzsgIC8vIFJldHVybiBhbHdheXMgYWxpZ25lZCBwb2ludGVyc1xcbiAgICAgICAgY29uc3QgcmVzID0gdTMyWzBdO1xcbiAgICAgICAgdTMyWzBdICs9IGxlbmd0aDtcXG4gICAgICAgIGlmICh1MzJbMF0gKyBsZW5ndGggPiBtZW1vcnkuYnVmZmVyLmJ5dGVMZW5ndGgpIHtcXG4gICAgICAgICAgICBjb25zdCBjdXJyZW50UGFnZXMgPSBtZW1vcnkuYnVmZmVyLmJ5dGVMZW5ndGggLyAweDEwMDAwO1xcbiAgICAgICAgICAgIGxldCByZXF1aXJlZFBhZ2VzID0gTWF0aC5mbG9vcigodTMyWzBdICsgbGVuZ3RoKSAvIDB4MTAwMDApKzE7XFxuICAgICAgICAgICAgaWYgKHJlcXVpcmVkUGFnZXM+TUFYTUVNKSByZXF1aXJlZFBhZ2VzPU1BWE1FTTtcXG4gICAgICAgICAgICBtZW1vcnkuZ3JvdyhyZXF1aXJlZFBhZ2VzLWN1cnJlbnRQYWdlcyk7XFxuICAgICAgICAgICAgY29uc29sZS5sb2coXFxcIkdyb3dpbmcgbWVtb3J5IHRvXFxcIiwgbWVtb3J5LmJ1ZmZlci5ieXRlTGVuZ3RoIC8gMTAyNCAvIDEwMjQsIFxcXCJNQlxcXCIpO1xcbiAgICAgICAgfVxcbiAgICAgICAgcmV0dXJuIHJlcztcXG4gICAgfVxcblxcbiAgICBmdW5jdGlvbiBhbGxvY0J1ZmZlcihidWZmZXIpIHtcXG4gICAgICAgIGNvbnN0IHAgPSBhbGxvYyhidWZmZXIuYnl0ZUxlbmd0aCk7XFxuICAgICAgICBzZXRCdWZmZXIocCwgYnVmZmVyKTtcXG4gICAgICAgIHJldHVybiBwO1xcbiAgICB9XFxuXFxuICAgIGZ1bmN0aW9uIGdldEJ1ZmZlcihwb2ludGVyLCBsZW5ndGgpIHtcXG4gICAgICAgIC8vIGNvbnN0IHU4ID0gbmV3IFVpbnQ4QXJyYXkobWVtb3J5LmJ1ZmZlcik7XFxuICAgICAgICAvLyByZXR1cm4gbmV3IFVpbnQ4QXJyYXkodTguYnVmZmVyLCB1OC5ieXRlT2Zmc2V0ICsgcG9pbnRlciwgbGVuZ3RoKTtcXG4gICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShtZW1vcnkuYnVmZmVyLCBwb2ludGVyLCBsZW5ndGgpO1xcbiAgICB9XFxuXFxuICAgIGZ1bmN0aW9uIHNldEJ1ZmZlcihwb2ludGVyLCBidWZmZXIpIHtcXG4gICAgICAgIGNvbnN0IHU4ID0gbmV3IFVpbnQ4QXJyYXkobWVtb3J5LmJ1ZmZlcik7XFxuICAgICAgICB1OC5zZXQobmV3IFVpbnQ4QXJyYXkoYnVmZmVyKSwgcG9pbnRlcik7XFxuICAgIH1cXG5cXG4gICAgZnVuY3Rpb24gcnVuVGFzayh0YXNrKSB7XFxuICAgICAgICBjbGVhclRpbWVvdXQodGVybWluYXRpb25UaW1lcik7XFxuICAgICAgICBpZiAodGFza1swXS5jbWQgPT09IFxcXCJJTklUXFxcIikge1xcbiAgICAgICAgICAgIHJldHVybiBpbml0KHRhc2tbMF0pO1xcbiAgICAgICAgfVxcbiAgICAgICAgY29uc3QgY3R4ID0ge1xcbiAgICAgICAgICAgIHZhcnM6IFtdLFxcbiAgICAgICAgICAgIG91dDogW11cXG4gICAgICAgIH07XFxuICAgICAgICBjb25zdCB1MzJhID0gbmV3IFVpbnQzMkFycmF5KG1lbW9yeS5idWZmZXIsIDAsIDEpO1xcbiAgICAgICAgY29uc3Qgb2xkQWxsb2MgPSB1MzJhWzBdO1xcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPHRhc2subGVuZ3RoOyBpKyspIHtcXG4gICAgICAgICAgICBzd2l0Y2ggKHRhc2tbaV0uY21kKSB7XFxuICAgICAgICAgICAgY2FzZSBcXFwiQUxMT0NTRVRcXFwiOlxcbiAgICAgICAgICAgICAgICBjdHgudmFyc1t0YXNrW2ldLnZhcl0gPSBhbGxvY0J1ZmZlcih0YXNrW2ldLmJ1ZmYpO1xcbiAgICAgICAgICAgICAgICBicmVhaztcXG4gICAgICAgICAgICBjYXNlIFxcXCJBTExPQ1xcXCI6XFxuICAgICAgICAgICAgICAgIGN0eC52YXJzW3Rhc2tbaV0udmFyXSA9IGFsbG9jKHRhc2tbaV0ubGVuKTtcXG4gICAgICAgICAgICAgICAgYnJlYWs7XFxuICAgICAgICAgICAgY2FzZSBcXFwiU0VUXFxcIjpcXG4gICAgICAgICAgICAgICAgc2V0QnVmZmVyKGN0eC52YXJzW3Rhc2tbaV0udmFyXSwgdGFza1tpXS5idWZmKTtcXG4gICAgICAgICAgICAgICAgYnJlYWs7XFxuICAgICAgICAgICAgY2FzZSBcXFwiQ0FMTFxcXCI6IHtcXG4gICAgICAgICAgICAgICAgY29uc3QgcGFyYW1zID0gW107XFxuICAgICAgICAgICAgICAgIGZvciAobGV0IGo9MDsgajx0YXNrW2ldLnBhcmFtcy5sZW5ndGg7IGorKykge1xcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcCA9IHRhc2tbaV0ucGFyYW1zW2pdO1xcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBwLnZhciAhPT0gXFxcInVuZGVmaW5lZFxcXCIpIHtcXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJhbXMucHVzaChjdHgudmFyc1twLnZhcl0gKyAocC5vZmZzZXQgfHwgMCkpO1xcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgcC52YWwgIT0gXFxcInVuZGVmaW5lZFxcXCIpIHtcXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJhbXMucHVzaChwLnZhbCk7XFxuICAgICAgICAgICAgICAgICAgICB9XFxuICAgICAgICAgICAgICAgIH1cXG4gICAgICAgICAgICAgICAgaW5zdGFuY2UuZXhwb3J0c1t0YXNrW2ldLmZuTmFtZV0oLi4ucGFyYW1zKTtcXG4gICAgICAgICAgICAgICAgYnJlYWs7XFxuICAgICAgICAgICAgfVxcbiAgICAgICAgICAgIGNhc2UgXFxcIkdFVFxcXCI6XFxuICAgICAgICAgICAgICAgIGN0eC5vdXRbdGFza1tpXS5vdXRdID0gZ2V0QnVmZmVyKGN0eC52YXJzW3Rhc2tbaV0udmFyXSwgdGFza1tpXS5sZW4pLnNsaWNlKCk7XFxuICAgICAgICAgICAgICAgIGJyZWFrO1xcbiAgICAgICAgICAgIGRlZmF1bHQ6XFxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcXFwiSW52YWxpZCBjbWRcXFwiKTtcXG4gICAgICAgICAgICB9XFxuICAgICAgICB9XFxuICAgICAgICBjb25zdCB1MzJiID0gbmV3IFVpbnQzMkFycmF5KG1lbW9yeS5idWZmZXIsIDAsIDEpO1xcbiAgICAgICAgdTMyYlswXSA9IG9sZEFsbG9jO1xcblxcbiAgICAgICAgLy9jb25zb2xlLmxvZyhjdHgub3V0KTtcXG5cXG4gICAgICAgIHJldHVybiBjdHgub3V0O1xcbiAgICB9XFxuXFxuICAgIGZ1bmN0aW9uIHNjaGVkdWxlVGVybWluYXRpb24oKSB7XFxuICAgICAgICBpZiAodGVybWluYXRpb25UaW1lb3V0PjApIHtcXG4gICAgICAgICAgICB0ZXJtaW5hdGlvblRpbWVyID0gc2V0VGltZW91dCggKCkgPT4ge1xcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcXFwiU2h1dHRpbmcgZG93biB0aHJlYWQgZHVlIHRvIGluYWN0aXZpdHlcXFwiKTtcXG4gICAgICAgICAgICAgICAgdGVybWluYXRlKCk7XFxuICAgICAgICAgICAgfSwgdGVybWluYXRpb25UaW1lb3V0KTtcXG4gICAgICAgIH1cXG4gICAgfVxcblxcbiAgICBmdW5jdGlvbiB0ZXJtaW5hdGUoKSB7XFxuICAgICAgICBjbGVhclRpbWVvdXQodGVybWluYXRpb25UaW1lcik7XFxuICAgICAgICBpbnN0YW5jZSA9IG51bGw7XFxuICAgICAgICBtZW1vcnkgPSBudWxsO1xcbiAgICAgICAgaWYgKHNlbGYpIHtcXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcXFwiVEVSTUlOQVRFXFxcIik7XFxuICAgICAgICAgICAgc2VsZi5wb3N0TWVzc2FnZSh7c3RhdHVzOiBcXFwidGVybWluYXRlZFxcXCJ9KTtcXG4gICAgICAgICAgICBzZWxmLmNsb3NlKCk7XFxuICAgICAgICB9XFxuICAgIH1cXG5cXG4gICAgcmV0dXJuIHJ1blRhc2s7XFxufVwifSkoc2VsZilgO1xue1xuICAgIGlmKGdsb2JhbFRoaXM/LkJsb2IpIHtcbiAgICAgICAgY29uc3QgdGhyZWFkQnl0ZXM9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZSh0aHJlYWRTdHIpO1xuICAgICAgICBjb25zdCB3b3JrZXJCbG9iID0gbmV3IEJsb2IoW3RocmVhZEJ5dGVzXSwgeyB0eXBlOiBcImFwcGxpY2F0aW9uL2phdmFzY3JpcHRcIiB9KSA7XG4gICAgICAgIHdvcmtlclNvdXJjZSA9IFVSTC5jcmVhdGVPYmplY3RVUkwod29ya2VyQmxvYik7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgd29ya2VyU291cmNlID0gXCJkYXRhOmFwcGxpY2F0aW9uL2phdmFzY3JpcHQ7YmFzZTY0LFwiICsgZ2xvYmFsVGhpcy5idG9hKHRocmVhZFN0cik7XG4gICAgfVxufVxuXG5cblxuYXN5bmMgZnVuY3Rpb24gYnVpbGRUaHJlYWRNYW5hZ2VyKHdhc20sIHNpbmdsZVRocmVhZCkge1xuICAgIGNvbnN0IHRtID0gbmV3IFRocmVhZE1hbmFnZXIoKTtcblxuICAgIHRtLm1lbW9yeSA9IG5ldyBXZWJBc3NlbWJseS5NZW1vcnkoe2luaXRpYWw6TUVNX1NJWkV9KTtcbiAgICB0bS51OCA9IG5ldyBVaW50OEFycmF5KHRtLm1lbW9yeS5idWZmZXIpO1xuICAgIHRtLnUzMiA9IG5ldyBVaW50MzJBcnJheSh0bS5tZW1vcnkuYnVmZmVyKTtcblxuICAgIGNvbnN0IHdhc21Nb2R1bGUgPSBhd2FpdCBXZWJBc3NlbWJseS5jb21waWxlKHdhc20uY29kZSk7XG5cbiAgICB0bS5pbnN0YW5jZSA9IGF3YWl0IFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlKHdhc21Nb2R1bGUsIHtcbiAgICAgICAgZW52OiB7XG4gICAgICAgICAgICBcIm1lbW9yeVwiOiB0bS5tZW1vcnlcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgaWYoIWdsb2JhbFRoaXM/Lldvcmtlcikge1xuICAgICAgICBzaW5nbGVUaHJlYWQgPSB0cnVlO1xuICAgIH1cbiAgICBcbiAgICB0bS5zaW5nbGVUaHJlYWQgPSBzaW5nbGVUaHJlYWQ7XG4gICAgdG0uaW5pdGFsUEZyZWUgPSB0bS51MzJbMF07ICAgLy8gU2F2ZSB0aGUgUG9pbnRlciB0byBmcmVlIHNwYWNlLlxuICAgIHRtLnBxID0gd2FzbS5wcTtcbiAgICB0bS5wciA9IHdhc20ucHI7XG4gICAgdG0ucEcxZ2VuID0gd2FzbS5wRzFnZW47XG4gICAgdG0ucEcxemVybyA9IHdhc20ucEcxemVybztcbiAgICB0bS5wRzJnZW4gPSB3YXNtLnBHMmdlbjtcbiAgICB0bS5wRzJ6ZXJvID0gd2FzbS5wRzJ6ZXJvO1xuICAgIHRtLnBPbmVUID0gd2FzbS5wT25lVDtcblxuICAgIHRtLmNvZGUgPSB3YXNtLmNvZGU7XG4gICAgdG0ud2FzbU1vZHVsZSA9IHdhc21Nb2R1bGU7XG5cbiAgICAvLyAgICB0bS5wVG1wMCA9IHRtLmFsbG9jKGN1cnZlLkcyLkYubjgqMyk7XG4gICAgLy8gICAgdG0ucFRtcDEgPSB0bS5hbGxvYyhjdXJ2ZS5HMi5GLm44KjMpO1xuXG4gICAgaWYgKHNpbmdsZVRocmVhZCkge1xuICAgICAgICB0bS50YXNrTWFuYWdlciA9IHRocmVhZCgpO1xuICAgICAgICBhd2FpdCB0bS50YXNrTWFuYWdlcihbe1xuICAgICAgICAgICAgY21kOiBcIklOSVRcIixcbiAgICAgICAgICAgIGluaXQ6IE1FTV9TSVpFLFxuICAgICAgICAgICAgY29kZTogdG0uY29kZS5zbGljZSgpXG4gICAgICAgIH1dKTtcbiAgICAgICAgdG0uY29uY3VycmVuY3kgID0gMTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0bS53b3JrZXJzID0gW107XG4gICAgICAgIHRtLnBlbmRpbmdEZWZlcnJlZHMgPSBbXTtcbiAgICAgICAgdG0ud29ya2luZyA9IFtdO1xuICAgICAgICB0bS5pbml0aWFsaXplZCA9IFtdO1xuICAgICAgICB0bS5pbml0aWFsaXppbmcgPSBbXTtcblxuICAgICAgICBsZXQgY29uY3VycmVuY3kgPSAyO1xuICAgICAgICB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG5hdmlnYXRvciA9PT0gXCJvYmplY3RcIiAmJiBuYXZpZ2F0b3IuaGFyZHdhcmVDb25jdXJyZW5jeSkge1xuICAgICAgICAgICAgICAgIGNvbmN1cnJlbmN5ID0gbmF2aWdhdG9yLmhhcmR3YXJlQ29uY3VycmVuY3k7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZihjb25jdXJyZW5jeSA9PT0gMCl7XG4gICAgICAgICAgICBjb25jdXJyZW5jeSA9IDI7XG4gICAgICAgIH1cblxuICAgICAgICAvL2NvbmN1cnJlbmN5ID0gMTA7IC8vIEZvciB0ZXN0aW5nXG5cbiAgICAgICAgLy8gTGltaXQgdG8gNjQgdGhyZWFkcyBmb3IgbWVtb3J5IHJlYXNvbnMuXG4gICAgICAgIGlmIChjb25jdXJyZW5jeT42NCkgY29uY3VycmVuY3k9NjQ7XG4gICAgICAgIHRtLmNvbmN1cnJlbmN5ID0gY29uY3VycmVuY3k7XG5cbiAgICAgICAgLy8gZm9yIChsZXQgaSA9IDA7IGk8MTsgaSsrKSB7XG4gICAgICAgIC8vXG4gICAgICAgIC8vICAgICB0bS53b3JrZXJzW2ldID0gbmV3IFdvcmtlcih3b3JrZXJTb3VyY2UpO1xuICAgICAgICAvL1xuICAgICAgICAvLyAgICAgdG0ud29ya2Vyc1tpXS5hZGRFdmVudExpc3RlbmVyKFwibWVzc2FnZVwiLCBnZXRPbk1zZyhpKSk7XG4gICAgICAgIC8vICAgICAvL3RtLndvcmtlcnNbaV0uYWRkRXZlbnRMaXN0ZW5lcihcImVycm9yXCIsIGdldE9uRXJyb3IoaSkpO1xuICAgICAgICAvL1xuICAgICAgICAvLyAgICAgdG0ud29ya2luZ1tpXT1mYWxzZTtcbiAgICAgICAgLy8gfVxuICAgICAgICAvL1xuICAgICAgICAvLyBjb25zdCBpbml0UHJvbWlzZXMgPSBbXTtcbiAgICAgICAgLy8gZm9yIChsZXQgaT0wOyBpPHRtLndvcmtlcnMubGVuZ3RoO2krKykge1xuICAgICAgICAvLyAgICAgY29uc3QgY29weUNvZGUgPSB3YXNtLmNvZGUuc2xpY2UoKTtcbiAgICAgICAgLy8gICAgIGluaXRQcm9taXNlcy5wdXNoKHRtLnBvc3RBY3Rpb24oaSwgW3tcbiAgICAgICAgLy8gICAgICAgICBjbWQ6IFwiSU5JVFwiLFxuICAgICAgICAvLyAgICAgICAgIGluaXQ6IE1FTV9TSVpFLFxuICAgICAgICAvLyAgICAgICAgIGNvZGU6IGNvcHlDb2RlXG4gICAgICAgIC8vICAgICB9XSwgW2NvcHlDb2RlLmJ1ZmZlcl0pKTtcbiAgICAgICAgLy8gfVxuICAgICAgICAvL1xuICAgICAgICAvLyAvLyBmb3IgKGxldCBpPTA7IGk8dG0ud29ya2Vycy5sZW5ndGg7aSsrKSB7XG4gICAgICAgIC8vIC8vICAgICAvL2NvbnN0IGNvcHlDb2RlID0gd2FzbS5jb2RlLnNsaWNlKCk7XG4gICAgICAgIC8vIC8vICAgICBpbml0UHJvbWlzZXMucHVzaCh0bS5wb3N0QWN0aW9uKGksIFt7XG4gICAgICAgIC8vIC8vICAgICAgICAgY21kOiBcIklOSVRcIixcbiAgICAgICAgLy8gLy8gICAgICAgICBpbml0OiBNRU1fU0laRSxcbiAgICAgICAgLy8gLy8gICAgICAgICBjb2RlOiB3YXNtTW9kdWxlXG4gICAgICAgIC8vIC8vICAgICB9XS8vLCBbY29weUNvZGUuYnVmZmVyXVxuICAgICAgICAvLyAvLyAgICAgKSk7XG4gICAgICAgIC8vIC8vIH1cbiAgICAgICAgLy9cbiAgICAgICAgLy8gYXdhaXQgUHJvbWlzZS5hbGwoaW5pdFByb21pc2VzKTtcblxuICAgICAgICAvLyBjb25zdCBpbml0UHJvbWlzZXMgPSBbXTtcbiAgICAgICAgLy8gZm9yIChsZXQgaSA9IDA7IGkgPCB0bS5jb25jdXJyZW5jeTsgaSsrKSB7XG4gICAgICAgIC8vICAgICBpbml0UHJvbWlzZXMucHVzaCh0bS5zdGFydFdvcmtlcihpKSk7XG4gICAgICAgIC8vIH1cbiAgICAgICAgLy8gYXdhaXQgUHJvbWlzZS5hbGwoaW5pdFByb21pc2VzKTtcblxuICAgIH1cbiAgICByZXR1cm4gdG07XG5cblxuXG59XG5cbmNsYXNzIFRocmVhZE1hbmFnZXIge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLmFjdGlvblF1ZXVlID0gW107XG4gICAgICAgIHRoaXMub2xkUEZyZWUgPSAwO1xuICAgIH1cblxuICAgIGdldE9uTXNnKGkpIHtcbiAgICAgICAgY29uc3QgdG0gPSB0aGlzO1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgbGV0IGRhdGE7XG4gICAgICAgICAgICBpZiAoKGUpJiYoZS5kYXRhKSkge1xuICAgICAgICAgICAgICAgIGRhdGEgPSBlLmRhdGE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGRhdGEgPSBlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBoYW5kbGUgZXJyb3JzXG4gICAgICAgICAgICBpZiAoZGF0YS5lcnJvcikge1xuICAgICAgICAgICAgICAgIHRtLndvcmtpbmdbaV09ZmFsc2U7XG4gICAgICAgICAgICAgICAgdG0ucGVuZGluZ0RlZmVycmVkc1tpXS5yZWplY3QoXCJXb3JrZXIgZXJyb3I6IFwiICsgZGF0YS5lcnJvcik7XG4gICAgICAgICAgICAgICAgaWYgKHRtLmluaXRpYWxpemluZ1tpXSkge1xuICAgICAgICAgICAgICAgICAgICB0bS5pbml0aWFsaXppbmdbaV09ZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHRtLndvcmtlcnNbaV09bnVsbDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0bS53b3JrZXJzW2ldLnBvc3RNZXNzYWdlKFt7Y21kOiBcIlRFUk1JTkFURVwifV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJXb3JrZXIgZXJyb3I6IFwiICsgZGF0YS5lcnJvcik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGhhbmRsZSBzdGF0dXMgbWVzc2FnZXNcbiAgICAgICAgICAgIGlmIChkYXRhLnN0YXR1cykge1xuICAgICAgICAgICAgICAgIGlmIChkYXRhLnN0YXR1cyA9PT0gXCJpbml0aWFsaXplZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEluaXRpYWxpemF0aW9uIHN1Y2Nlc3NmdWwgbWVzc2FnZVxuICAgICAgICAgICAgICAgICAgICB0bS5pbml0aWFsaXppbmdbaV09ZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHRtLmluaXRpYWxpemVkW2ldPXRydWU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkYXRhLnN0YXR1cyA9PT0gXCJ0ZXJtaW5hdGVkXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gVGVybWluYXRpb24gc3VjY2Vzc2Z1bCBtZXNzYWdlXG4gICAgICAgICAgICAgICAgICAgIHRtLmluaXRpYWxpemVkW2ldPWZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB0bS5pbml0aWFsaXppbmdbaV09ZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHRtLndvcmtlcnNbaV09bnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRtLndvcmtpbmdbaV09ZmFsc2U7XG4gICAgICAgICAgICB0bS5wZW5kaW5nRGVmZXJyZWRzW2ldLnJlc29sdmUoZGF0YSk7XG4gICAgICAgICAgICB0bS5wcm9jZXNzV29ya3MoKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBnZXRPbkVycm9yKGkpIHtcbiAgICAgICAgY29uc3QgdG0gPSB0aGlzO1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgdG0ud29ya2luZ1tpXT1mYWxzZTtcbiAgICAgICAgICAgIHRtLnBlbmRpbmdEZWZlcnJlZHNbaV0ucmVqZWN0KGUubWVzc2FnZSk7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJXb3JrZXIgZXJyb3I6IFwiICsgZS5tZXNzYWdlKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBzdGFydFdvcmtlcihpKXtcbiAgICAgICAgdGhpcy53b3JrZXJzW2ldID0gbmV3IFdvcmtlcih3b3JrZXJTb3VyY2UpO1xuXG4gICAgICAgIHRoaXMud29ya2Vyc1tpXS5hZGRFdmVudExpc3RlbmVyKFwibWVzc2FnZVwiLCB0aGlzLmdldE9uTXNnKGkpKTtcbiAgICAgICAgLy90bS53b3JrZXJzW2ldLmFkZEV2ZW50TGlzdGVuZXIoXCJlcnJvclwiLCB0aGlzLmdldE9uRXJyb3IoaSkpO1xuXG4gICAgICAgIC8vdGhpcy53b3JraW5nW2ldPXRydWU7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6aW5nW2ldID0gdHJ1ZTtcblxuICAgICAgICAvLyBjb25zdCBjb3B5Q29kZSA9IHRoaXMuY29kZS5zbGljZSgpO1xuICAgICAgICAvLyBhd2FpdCB0aGlzLnBvc3RBY3Rpb24oaSwgW3tcbiAgICAgICAgLy8gICAgIGNtZDogXCJJTklUXCIsXG4gICAgICAgIC8vICAgICBpbml0OiBNRU1fU0laRSxcbiAgICAgICAgLy8gICAgIGNvZGU6IGNvcHlDb2RlXG4gICAgICAgIC8vIH1dLCBbY29weUNvZGUuYnVmZmVyXSk7XG5cbiAgICAgICAgLy8gICAgIC8vY29uc3QgY29weUNvZGUgPSB3YXNtLmNvZGUuc2xpY2UoKTtcbiAgICAgICAgdGhpcy5wb3N0QWN0aW9uKGksIFt7XG4gICAgICAgICAgICBjbWQ6IFwiSU5JVFwiLFxuICAgICAgICAgICAgaW5pdDogTUVNX1NJWkUsXG4gICAgICAgICAgICBjb2RlOiB0aGlzLndhc21Nb2R1bGVcbiAgICAgICAgfV0pLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5pbml0aWFsaXplZFtpXSA9IHRydWU7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHN0YXJ0U3luY09wKCkge1xuICAgICAgICBpZiAodGhpcy5vbGRQRnJlZSAhPT0gMCkgdGhyb3cgbmV3IEVycm9yKFwiU3luYyBvcGVyYXRpb24gaW4gcHJvZ3Jlc3NcIik7XG4gICAgICAgIHRoaXMub2xkUEZyZWUgPSB0aGlzLnUzMlswXTtcbiAgICB9XG5cbiAgICBlbmRTeW5jT3AoKSB7XG4gICAgICAgIGlmICh0aGlzLm9sZFBGcmVlID09PSAwKSB0aHJvdyBuZXcgRXJyb3IoXCJObyBzeW5jIG9wZXJhdGlvbiBpbiBwcm9ncmVzc1wiKTtcbiAgICAgICAgdGhpcy51MzJbMF0gPSB0aGlzLm9sZFBGcmVlO1xuICAgICAgICB0aGlzLm9sZFBGcmVlID0gMDtcbiAgICB9XG5cbiAgICBhc3luYyBwb3N0QWN0aW9uKHdvcmtlcklkLCBlLCB0cmFuc2ZlcnMsIF9kZWZlcnJlZCkge1xuICAgICAgICBpZiAodGhpcy53b3JraW5nW3dvcmtlcklkXSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUG9zdGluZyBhIGpvYiB0byBhIHdvcmtpbmcgd29ya2VyXCIpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMud29ya2luZ1t3b3JrZXJJZF0gPSB0cnVlO1xuXG4gICAgICAgIHRoaXMucGVuZGluZ0RlZmVycmVkc1t3b3JrZXJJZF0gPSBfZGVmZXJyZWQgPyBfZGVmZXJyZWQgOiBuZXcgRGVmZXJyZWQoKTtcbiAgICAgICAgYXdhaXQgdGhpcy53b3JrZXJzW3dvcmtlcklkXS5wb3N0TWVzc2FnZShlLCB0cmFuc2ZlcnMpO1xuXG4gICAgICAgIHJldHVybiB0aGlzLnBlbmRpbmdEZWZlcnJlZHNbd29ya2VySWRdLnByb21pc2U7XG4gICAgfVxuXG4gICAgYXN5bmMgcHJvY2Vzc1dvcmtzKCkge1xuICAgICAgICBmb3IgKGxldCBpPTA7IChpPHRoaXMuY29uY3VycmVuY3kpJiYodGhpcy5hY3Rpb25RdWV1ZS5sZW5ndGggPiAwKTsgaSsrKSB7XG4gICAgICAgICAgICBpZiAodGhpcy53b3JrZXJzW2ldICYmIHRoaXMuaW5pdGlhbGl6ZWRbaV0gJiYgIXRoaXMud29ya2luZ1tpXSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHdvcmsgPSB0aGlzLmFjdGlvblF1ZXVlLnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgdGhpcy5wb3N0QWN0aW9uKGksIHdvcmsuZGF0YSwgd29yay50cmFuc2ZlcnMsIHdvcmsuZGVmZXJyZWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gSW5pdGlhbGl6ZSBtb3JlIHdvcmtlcnMgaWYgbmVlZGVkXG4gICAgICAgIGlmICh0aGlzLmFjdGlvblF1ZXVlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIC8vIEZpbmQgYSB3b3JrZXIgdGhhdCBpcyBub3QgaW5pdGlhbGl6ZWQgeWV0XG4gICAgICAgICAgICBsZXQgaW5pdGlhbGl6aW5nQ291bnQgPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgaT0wOyBpPHRoaXMuY29uY3VycmVuY3k7IGkrKykge1xuICAgICAgICAgICAgICAgIGluaXRpYWxpemluZ0NvdW50ICs9IHRoaXMuaW5pdGlhbGl6aW5nW2ldO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmluaXRpYWxpemVkW2ldKSBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pbml0aWFsaXppbmdbaV0pIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGlmIChpbml0aWFsaXppbmdDb3VudCA+PSB0aGlzLmFjdGlvblF1ZXVlLmxlbmd0aCkgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIHRoaXMgd29ya2VyXG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coYFdvcmtlciAke2l9IG5vdCBpbml0aWFsaXplZCB5ZXQuIEluaXRpYWxpemluZy4uLmApO1xuICAgICAgICAgICAgICAgIGluaXRpYWxpemluZ0NvdW50Kys7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zdGFydFdvcmtlcihpKTtcbiAgICAgICAgICAgICAgICAvL3RoaXMuc3RhcnRXb3JrZXIoaSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBxdWV1ZUFjdGlvbihhY3Rpb25EYXRhLCB0cmFuc2ZlcnMpIHtcbiAgICAgICAgY29uc3QgZCA9IG5ldyBEZWZlcnJlZCgpO1xuXG4gICAgICAgIGlmICh0aGlzLnNpbmdsZVRocmVhZCkge1xuICAgICAgICAgICAgY29uc3QgcmVzID0gdGhpcy50YXNrTWFuYWdlcihhY3Rpb25EYXRhKTtcbiAgICAgICAgICAgIGQucmVzb2x2ZShyZXMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5hY3Rpb25RdWV1ZS5wdXNoKHtcbiAgICAgICAgICAgICAgICBkYXRhOiBhY3Rpb25EYXRhLFxuICAgICAgICAgICAgICAgIHRyYW5zZmVyczogdHJhbnNmZXJzLFxuICAgICAgICAgICAgICAgIGRlZmVycmVkOiBkXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMucHJvY2Vzc1dvcmtzKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGQucHJvbWlzZTtcbiAgICB9XG5cbiAgICByZXNldE1lbW9yeSgpIHtcbiAgICAgICAgdGhpcy51MzJbMF0gPSB0aGlzLmluaXRhbFBGcmVlO1xuICAgIH1cblxuICAgIGFsbG9jQnVmZihidWZmKSB7XG4gICAgICAgIGNvbnN0IHBvaW50ZXIgPSB0aGlzLmFsbG9jKGJ1ZmYuYnl0ZUxlbmd0aCk7XG4gICAgICAgIHRoaXMuc2V0QnVmZihwb2ludGVyLCBidWZmKTtcbiAgICAgICAgcmV0dXJuIHBvaW50ZXI7XG4gICAgfVxuXG4gICAgZ2V0QnVmZihwb2ludGVyLCBsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudTguc2xpY2UocG9pbnRlciwgcG9pbnRlcisgbGVuZ3RoKTtcbiAgICB9XG5cbiAgICBzZXRCdWZmKHBvaW50ZXIsIGJ1ZmZlcikge1xuICAgICAgICB0aGlzLnU4LnNldChuZXcgVWludDhBcnJheShidWZmZXIpLCBwb2ludGVyKTtcbiAgICB9XG5cbiAgICBhbGxvYyhsZW5ndGgpIHtcbiAgICAgICAgd2hpbGUgKHRoaXMudTMyWzBdICYgMykgdGhpcy51MzJbMF0rKzsgIC8vIFJldHVybiBhbHdheXMgYWxpZ25lZCBwb2ludGVyc1xuICAgICAgICBjb25zdCByZXMgPSB0aGlzLnUzMlswXTtcbiAgICAgICAgdGhpcy51MzJbMF0gKz0gbGVuZ3RoO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIGFzeW5jIHRlcm1pbmF0ZSgpIHtcbiAgICAgICAgY29uc29sZS5sb2coXCJ0ZXJtaW5hdGUhISFcIik7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTx0aGlzLndvcmtlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRoaXMud29ya2Vyc1tpXS5wb3N0TWVzc2FnZShbe2NtZDogXCJURVJNSU5BVEVcIn1dKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBHaXZlIHNvbWUgdGltZSB0byB0aGUgd29ya2VycyB0byB0ZXJtaW5hdGVcbiAgICAgICAgLy9hd2FpdCBzbGVlcCgyMDApO1xuICAgIH1cblxufVxuXG5mdW5jdGlvbiBidWlsZEJhdGNoQXBwbHlLZXkoY3VydmUsIGdyb3VwTmFtZSkge1xuICAgIGNvbnN0IEcgPSBjdXJ2ZVtncm91cE5hbWVdO1xuICAgIGNvbnN0IEZyID0gY3VydmUuRnI7XG4gICAgY29uc3QgdG0gPSBjdXJ2ZS50bTtcblxuICAgIGN1cnZlW2dyb3VwTmFtZV0uYmF0Y2hBcHBseUtleSA9IGFzeW5jIGZ1bmN0aW9uKGJ1ZmYsIGZpcnN0LCBpbmMsIGluVHlwZSwgb3V0VHlwZSkge1xuICAgICAgICBpblR5cGUgPSBpblR5cGUgfHwgXCJhZmZpbmVcIjtcbiAgICAgICAgb3V0VHlwZSA9IG91dFR5cGUgfHwgXCJhZmZpbmVcIjtcbiAgICAgICAgbGV0IGZuTmFtZSwgZm5BZmZpbmU7XG4gICAgICAgIGxldCBzR2luLCBzR21pZCwgc0dvdXQ7XG4gICAgICAgIGlmIChncm91cE5hbWUgPT0gXCJHMVwiKSB7XG4gICAgICAgICAgICBpZiAoaW5UeXBlID09IFwiamFjb2JpYW5cIikge1xuICAgICAgICAgICAgICAgIHNHaW4gPSBHLkYubjgqMztcbiAgICAgICAgICAgICAgICBmbk5hbWUgPSBcImcxbV9iYXRjaEFwcGx5S2V5XCI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNHaW4gPSBHLkYubjgqMjtcbiAgICAgICAgICAgICAgICBmbk5hbWUgPSBcImcxbV9iYXRjaEFwcGx5S2V5TWl4ZWRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNHbWlkID0gRy5GLm44KjM7XG4gICAgICAgICAgICBpZiAob3V0VHlwZSA9PSBcImphY29iaWFuXCIpIHtcbiAgICAgICAgICAgICAgICBzR291dCA9IEcuRi5uOCozO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBmbkFmZmluZSA9IFwiZzFtX2JhdGNoVG9BZmZpbmVcIjtcbiAgICAgICAgICAgICAgICBzR291dCA9IEcuRi5uOCoyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGdyb3VwTmFtZSA9PSBcIkcyXCIpIHtcbiAgICAgICAgICAgIGlmIChpblR5cGUgPT0gXCJqYWNvYmlhblwiKSB7XG4gICAgICAgICAgICAgICAgc0dpbiA9IEcuRi5uOCozO1xuICAgICAgICAgICAgICAgIGZuTmFtZSA9IFwiZzJtX2JhdGNoQXBwbHlLZXlcIjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc0dpbiA9IEcuRi5uOCoyO1xuICAgICAgICAgICAgICAgIGZuTmFtZSA9IFwiZzJtX2JhdGNoQXBwbHlLZXlNaXhlZFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc0dtaWQgPSBHLkYubjgqMztcbiAgICAgICAgICAgIGlmIChvdXRUeXBlID09IFwiamFjb2JpYW5cIikge1xuICAgICAgICAgICAgICAgIHNHb3V0ID0gRy5GLm44KjM7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGZuQWZmaW5lID0gXCJnMm1fYmF0Y2hUb0FmZmluZVwiO1xuICAgICAgICAgICAgICAgIHNHb3V0ID0gRy5GLm44KjI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoZ3JvdXBOYW1lID09IFwiRnJcIikge1xuICAgICAgICAgICAgZm5OYW1lID0gXCJmcm1fYmF0Y2hBcHBseUtleVwiO1xuICAgICAgICAgICAgc0dpbiA9IEcubjg7XG4gICAgICAgICAgICBzR21pZCA9IEcubjg7XG4gICAgICAgICAgICBzR291dCA9IEcubjg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIGdyb3VwOiBcIiArIGdyb3VwTmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgblBvaW50cyA9IE1hdGguZmxvb3IoYnVmZi5ieXRlTGVuZ3RoIC8gc0dpbik7XG4gICAgICAgIGNvbnN0IHBvaW50c1BlckNodW5rID0gTWF0aC5mbG9vcihuUG9pbnRzL3RtLmNvbmN1cnJlbmN5KTtcbiAgICAgICAgY29uc3Qgb3BQcm9taXNlcyA9IFtdO1xuICAgICAgICBpbmMgPSBGci5lKGluYyk7XG4gICAgICAgIGxldCB0ID0gRnIuZShmaXJzdCk7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTx0bS5jb25jdXJyZW5jeTsgaSsrKSB7XG4gICAgICAgICAgICBsZXQgbjtcbiAgICAgICAgICAgIGlmIChpPCB0bS5jb25jdXJyZW5jeS0xKSB7XG4gICAgICAgICAgICAgICAgbiA9IHBvaW50c1BlckNodW5rO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBuID0gblBvaW50cyAtIGkqcG9pbnRzUGVyQ2h1bms7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobj09MCkgY29udGludWU7XG5cbiAgICAgICAgICAgIGNvbnN0IHRhc2sgPSBbXTtcblxuICAgICAgICAgICAgY29uc3QgYiA9IGJ1ZmYuc2xpY2UoaSpwb2ludHNQZXJDaHVuaypzR2luLCBpKnBvaW50c1BlckNodW5rKnNHaW4gKyBuKnNHaW4pO1xuXG4gICAgICAgICAgICB0YXNrLnB1c2goe1xuICAgICAgICAgICAgICAgIGNtZDogXCJBTExPQ1NFVFwiLFxuICAgICAgICAgICAgICAgIHZhcjogMCxcbiAgICAgICAgICAgICAgICBidWZmOiBiXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkFMTE9DU0VUXCIsIHZhcjogMSwgYnVmZjogdH0pO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQUxMT0NTRVRcIiwgdmFyOiAyLCBidWZmOiBpbmN9KTtcbiAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkFMTE9DXCIsIHZhcjogMywgbGVuOiBuKk1hdGgubWF4KHNHbWlkLCBzR291dCl9KTtcbiAgICAgICAgICAgIHRhc2sucHVzaCh7XG4gICAgICAgICAgICAgICAgY21kOiBcIkNBTExcIixcbiAgICAgICAgICAgICAgICBmbk5hbWU6IGZuTmFtZSxcbiAgICAgICAgICAgICAgICBwYXJhbXM6IFtcbiAgICAgICAgICAgICAgICAgICAge3ZhcjogMH0sXG4gICAgICAgICAgICAgICAgICAgIHt2YWw6IG59LFxuICAgICAgICAgICAgICAgICAgICB7dmFyOiAxfSxcbiAgICAgICAgICAgICAgICAgICAge3ZhcjogMn0sXG4gICAgICAgICAgICAgICAgICAgIHt2YXI6M31cbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChmbkFmZmluZSkge1xuICAgICAgICAgICAgICAgIHRhc2sucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIGNtZDogXCJDQUxMXCIsXG4gICAgICAgICAgICAgICAgICAgIGZuTmFtZTogZm5BZmZpbmUsXG4gICAgICAgICAgICAgICAgICAgIHBhcmFtczogW1xuICAgICAgICAgICAgICAgICAgICAgICAge3ZhcjogM30sXG4gICAgICAgICAgICAgICAgICAgICAgICB7dmFsOiBufSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHt2YXI6IDN9LFxuICAgICAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJHRVRcIiwgb3V0OiAwLCB2YXI6IDMsIGxlbjogbipzR291dH0pO1xuXG4gICAgICAgICAgICBvcFByb21pc2VzLnB1c2godG0ucXVldWVBY3Rpb24odGFzaywgW2IuYnVmZmVyXSkpO1xuICAgICAgICAgICAgdCA9IEZyLm11bCh0LCBGci5leHAoaW5jLCBuKSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBQcm9taXNlLmFsbChvcFByb21pc2VzKTtcblxuICAgICAgICBsZXQgb3V0QnVmZjtcbiAgICAgICAgaWYgKGJ1ZmYgaW5zdGFuY2VvZiBCaWdCdWZmZXIpIHtcbiAgICAgICAgICAgIG91dEJ1ZmYgPSBuZXcgQmlnQnVmZmVyKG5Qb2ludHMqc0dvdXQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb3V0QnVmZiA9IG5ldyBVaW50OEFycmF5KG5Qb2ludHMqc0dvdXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHA9MDtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPHJlc3VsdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgb3V0QnVmZi5zZXQocmVzdWx0W2ldWzBdLCBwKTtcbiAgICAgICAgICAgIHAgKz0gcmVzdWx0W2ldWzBdLmJ5dGVMZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gb3V0QnVmZjtcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBidWlsZFBhaXJpbmcoY3VydmUpIHtcbiAgICBjb25zdCB0bSA9IGN1cnZlLnRtO1xuICAgIGN1cnZlLnBhaXJpbmcgPSBmdW5jdGlvbiBwYWlyaW5nKGEsIGIpIHtcblxuICAgICAgICB0bS5zdGFydFN5bmNPcCgpO1xuICAgICAgICBjb25zdCBwQSA9IHRtLmFsbG9jQnVmZihjdXJ2ZS5HMS50b0phY29iaWFuKGEpKTtcbiAgICAgICAgY29uc3QgcEIgPSB0bS5hbGxvY0J1ZmYoY3VydmUuRzIudG9KYWNvYmlhbihiKSk7XG4gICAgICAgIGNvbnN0IHBSZXMgPSB0bS5hbGxvYyhjdXJ2ZS5HdC5uOCk7XG4gICAgICAgIHRtLmluc3RhbmNlLmV4cG9ydHNbY3VydmUubmFtZSArIFwiX3BhaXJpbmdcIl0ocEEsIHBCLCBwUmVzKTtcblxuICAgICAgICBjb25zdCByZXMgPSB0bS5nZXRCdWZmKHBSZXMsIGN1cnZlLkd0Lm44KTtcblxuICAgICAgICB0bS5lbmRTeW5jT3AoKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuXG4gICAgY3VydmUucGFpcmluZ0VxID0gYXN5bmMgZnVuY3Rpb24gcGFpcmluZ0VxKCkge1xuICAgICAgICBsZXQgIGJ1ZmZDdDtcbiAgICAgICAgbGV0IG5FcXM7XG4gICAgICAgIGlmICgoYXJndW1lbnRzLmxlbmd0aCAlIDIpID09IDEpIHtcbiAgICAgICAgICAgIGJ1ZmZDdCA9IGFyZ3VtZW50c1thcmd1bWVudHMubGVuZ3RoLTFdO1xuICAgICAgICAgICAgbkVxcyA9IChhcmd1bWVudHMubGVuZ3RoIC0xKSAvMjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGJ1ZmZDdCA9IGN1cnZlLkd0Lm9uZTtcbiAgICAgICAgICAgIG5FcXMgPSBhcmd1bWVudHMubGVuZ3RoIC8yO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgb3BQcm9taXNlcyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8bkVxczsgaSsrKSB7XG5cbiAgICAgICAgICAgIGNvbnN0IHRhc2sgPSBbXTtcblxuICAgICAgICAgICAgY29uc3QgZzFCdWZmID0gY3VydmUuRzEudG9KYWNvYmlhbihhcmd1bWVudHNbaSoyXSk7XG4gICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJBTExPQ1NFVFwiLCB2YXI6IDAsIGJ1ZmY6IGcxQnVmZn0pO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQUxMT0NcIiwgdmFyOiAxLCBsZW46IGN1cnZlLnByZVBTaXplfSk7XG5cbiAgICAgICAgICAgIGNvbnN0IGcyQnVmZiA9IGN1cnZlLkcyLnRvSmFjb2JpYW4oYXJndW1lbnRzW2kqMiArMV0pO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQUxMT0NTRVRcIiwgdmFyOiAyLCBidWZmOiBnMkJ1ZmZ9KTtcbiAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkFMTE9DXCIsIHZhcjogMywgbGVuOiBjdXJ2ZS5wcmVRU2l6ZX0pO1xuXG4gICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJBTExPQ1wiLCB2YXI6IDQsIGxlbjogY3VydmUuR3Qubjh9KTtcblxuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQ0FMTFwiLCBmbk5hbWU6IGN1cnZlLm5hbWUgKyBcIl9wcmVwYXJlRzFcIiwgcGFyYW1zOiBbXG4gICAgICAgICAgICAgICAge3ZhcjogMH0sXG4gICAgICAgICAgICAgICAge3ZhcjogMX1cbiAgICAgICAgICAgIF19KTtcblxuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQ0FMTFwiLCBmbk5hbWU6IGN1cnZlLm5hbWUgKyBcIl9wcmVwYXJlRzJcIiwgcGFyYW1zOiBbXG4gICAgICAgICAgICAgICAge3ZhcjogMn0sXG4gICAgICAgICAgICAgICAge3ZhcjogM31cbiAgICAgICAgICAgIF19KTtcblxuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQ0FMTFwiLCBmbk5hbWU6IGN1cnZlLm5hbWUgKyBcIl9taWxsZXJMb29wXCIsIHBhcmFtczogW1xuICAgICAgICAgICAgICAgIHt2YXI6IDF9LFxuICAgICAgICAgICAgICAgIHt2YXI6IDN9LFxuICAgICAgICAgICAgICAgIHt2YXI6IDR9XG4gICAgICAgICAgICBdfSk7XG5cbiAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkdFVFwiLCBvdXQ6IDAsIHZhcjogNCwgbGVuOiBjdXJ2ZS5HdC5uOH0pO1xuXG4gICAgICAgICAgICBvcFByb21pc2VzLnB1c2goXG4gICAgICAgICAgICAgICAgdG0ucXVldWVBY3Rpb24odGFzaywgW2cxQnVmZi5idWZmZXIsIGcyQnVmZi5idWZmZXJdKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgUHJvbWlzZS5hbGwob3BQcm9taXNlcyk7XG5cbiAgICAgICAgdG0uc3RhcnRTeW5jT3AoKTtcbiAgICAgICAgY29uc3QgcFJlcyA9IHRtLmFsbG9jKGN1cnZlLkd0Lm44KTtcbiAgICAgICAgdG0uaW5zdGFuY2UuZXhwb3J0cy5mdG1fb25lKHBSZXMpO1xuXG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxyZXN1bHQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IHBNUiA9IHRtLmFsbG9jQnVmZihyZXN1bHRbaV1bMF0pO1xuICAgICAgICAgICAgdG0uaW5zdGFuY2UuZXhwb3J0cy5mdG1fbXVsKHBSZXMsIHBNUiwgcFJlcyk7XG4gICAgICAgIH1cbiAgICAgICAgdG0uaW5zdGFuY2UuZXhwb3J0c1tjdXJ2ZS5uYW1lICsgXCJfZmluYWxFeHBvbmVudGlhdGlvblwiXShwUmVzLCBwUmVzKTtcblxuICAgICAgICBjb25zdCBwQ3QgPSB0bS5hbGxvY0J1ZmYoYnVmZkN0KTtcblxuICAgICAgICBjb25zdCByID0gISF0bS5pbnN0YW5jZS5leHBvcnRzLmZ0bV9lcShwUmVzLCBwQ3QpO1xuXG4gICAgICAgIHRtLmVuZFN5bmNPcCgpO1xuXG4gICAgICAgIHJldHVybiByO1xuICAgIH07XG5cbiAgICBjdXJ2ZS5wcmVwYXJlRzEgPSBmdW5jdGlvbihwKSB7XG4gICAgICAgIHRoaXMudG0uc3RhcnRTeW5jT3AoKTtcbiAgICAgICAgY29uc3QgcFAgPSB0aGlzLnRtLmFsbG9jQnVmZihwKTtcbiAgICAgICAgY29uc3QgcFByZXBQID0gdGhpcy50bS5hbGxvYyh0aGlzLnByZVBTaXplKTtcbiAgICAgICAgdGhpcy50bS5pbnN0YW5jZS5leHBvcnRzW3RoaXMubmFtZSArIFwiX3ByZXBhcmVHMVwiXShwUCwgcFByZXBQKTtcbiAgICAgICAgY29uc3QgcmVzID0gdGhpcy50bS5nZXRCdWZmKHBQcmVwUCwgdGhpcy5wcmVQU2l6ZSk7XG4gICAgICAgIHRoaXMudG0uZW5kU3luY09wKCk7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcblxuICAgIGN1cnZlLnByZXBhcmVHMiA9IGZ1bmN0aW9uKHEpIHtcbiAgICAgICAgdGhpcy50bS5zdGFydFN5bmNPcCgpO1xuICAgICAgICBjb25zdCBwUSA9IHRoaXMudG0uYWxsb2NCdWZmKHEpO1xuICAgICAgICBjb25zdCBwUHJlcFEgPSB0aGlzLnRtLmFsbG9jKHRoaXMucHJlUVNpemUpO1xuICAgICAgICB0aGlzLnRtLmluc3RhbmNlLmV4cG9ydHNbdGhpcy5uYW1lICsgXCJfcHJlcGFyZUcyXCJdKHBRLCBwUHJlcFEpO1xuICAgICAgICBjb25zdCByZXMgPSB0aGlzLnRtLmdldEJ1ZmYocFByZXBRLCB0aGlzLnByZVFTaXplKTtcbiAgICAgICAgdGhpcy50bS5lbmRTeW5jT3AoKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuXG4gICAgY3VydmUubWlsbGVyTG9vcCA9IGZ1bmN0aW9uKHByZVAsIHByZVEpIHtcbiAgICAgICAgdGhpcy50bS5zdGFydFN5bmNPcCgpO1xuICAgICAgICBjb25zdCBwUHJlUCA9IHRoaXMudG0uYWxsb2NCdWZmKHByZVApO1xuICAgICAgICBjb25zdCBwUHJlUSA9IHRoaXMudG0uYWxsb2NCdWZmKHByZVEpO1xuICAgICAgICBjb25zdCBwUmVzID0gdGhpcy50bS5hbGxvYyh0aGlzLkd0Lm44KTtcbiAgICAgICAgdGhpcy50bS5pbnN0YW5jZS5leHBvcnRzW3RoaXMubmFtZSArIFwiX21pbGxlckxvb3BcIl0ocFByZVAsIHBQcmVRLCBwUmVzKTtcbiAgICAgICAgY29uc3QgcmVzID0gdGhpcy50bS5nZXRCdWZmKHBSZXMsIHRoaXMuR3QubjgpO1xuICAgICAgICB0aGlzLnRtLmVuZFN5bmNPcCgpO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG5cbiAgICBjdXJ2ZS5maW5hbEV4cG9uZW50aWF0aW9uID0gZnVuY3Rpb24oYSkge1xuICAgICAgICB0aGlzLnRtLnN0YXJ0U3luY09wKCk7XG4gICAgICAgIGNvbnN0IHBBID0gdGhpcy50bS5hbGxvY0J1ZmYoYSk7XG4gICAgICAgIGNvbnN0IHBSZXMgPSB0aGlzLnRtLmFsbG9jKHRoaXMuR3QubjgpO1xuICAgICAgICB0aGlzLnRtLmluc3RhbmNlLmV4cG9ydHNbdGhpcy5uYW1lICsgXCJfZmluYWxFeHBvbmVudGlhdGlvblwiXShwQSwgcFJlcyk7XG4gICAgICAgIGNvbnN0IHJlcyA9IHRoaXMudG0uZ2V0QnVmZihwUmVzLCB0aGlzLkd0Lm44KTtcbiAgICAgICAgdGhpcy50bS5lbmRTeW5jT3AoKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuXG59XG5cbi8qIGVzbGludC1kaXNhYmxlIGluZGVudCAqL1xuXG5jb25zdCBwVFNpemVzID0gW1xuICAgIDEgLCAgMSwgIDEsICAxLCAgICAyLCAgMywgIDQsICA1LFxuICAgIDYgLCAgNywgIDcsICA4LCAgICA5LCAxMCwgMTEsIDEyLFxuICAgIDEzLCAxMywgMTQsIDE1LCAgIDE2LCAxNiwgMTcsIDE3LFxuICAgIDE3LCAxNywgMTcsIDE3LCAgIDE3LCAxNywgMTcsIDE3XG5dO1xuXG5mdW5jdGlvbiBidWlsZE11bHRpZXhwJDEoY3VydmUsIGdyb3VwTmFtZSkge1xuICAgIGNvbnN0IEcgPSBjdXJ2ZVtncm91cE5hbWVdO1xuICAgIGNvbnN0IHRtID0gRy50bTtcblxuICAgIGFzeW5jIGZ1bmN0aW9uIF9tdWx0aUV4cENodW5rKGJ1ZmZCYXNlcywgYnVmZlNjYWxhcnMsIGluVHlwZSwgbG9nZ2VyLCBsb2dUZXh0KSB7XG4gICAgICAgIGlmICggISAoYnVmZkJhc2VzIGluc3RhbmNlb2YgVWludDhBcnJheSkgKSB7XG4gICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoYCR7bG9nVGV4dH0gX211bHRpRXhwQ2h1bmsgYnVmZkJhc2VzIGlzIG5vdCBVaW50OEFycmF5YCk7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bG9nVGV4dH0gX211bHRpRXhwQ2h1bmsgYnVmZkJhc2VzIGlzIG5vdCBVaW50OEFycmF5YCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCAhIChidWZmU2NhbGFycyBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpICkge1xuICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKGAke2xvZ1RleHR9IF9tdWx0aUV4cENodW5rIGJ1ZmZTY2FsYXJzIGlzIG5vdCBVaW50OEFycmF5YCk7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bG9nVGV4dH0gX211bHRpRXhwQ2h1bmsgYnVmZlNjYWxhcnMgaXMgbm90IFVpbnQ4QXJyYXlgKTtcbiAgICAgICAgfVxuICAgICAgICBpblR5cGUgPSBpblR5cGUgfHwgXCJhZmZpbmVcIjtcblxuICAgICAgICBsZXQgc0dJbjtcbiAgICAgICAgbGV0IGZuTmFtZTtcbiAgICAgICAgaWYgKGdyb3VwTmFtZSA9PT0gXCJHMVwiKSB7XG4gICAgICAgICAgICBpZiAoaW5UeXBlID09PSBcImFmZmluZVwiKSB7XG4gICAgICAgICAgICAgICAgZm5OYW1lID0gXCJnMW1fbXVsdGlleHBBZmZpbmVcIjtcbiAgICAgICAgICAgICAgICBzR0luID0gRy5GLm44KjI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGZuTmFtZSA9IFwiZzFtX211bHRpZXhwXCI7XG4gICAgICAgICAgICAgICAgc0dJbiA9IEcuRi5uOCozO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGdyb3VwTmFtZSA9PT0gXCJHMlwiKSB7XG4gICAgICAgICAgICBpZiAoaW5UeXBlID09PSBcImFmZmluZVwiKSB7XG4gICAgICAgICAgICAgICAgZm5OYW1lID0gXCJnMm1fbXVsdGlleHBBZmZpbmVcIjtcbiAgICAgICAgICAgICAgICBzR0luID0gRy5GLm44KjI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGZuTmFtZSA9IFwiZzJtX211bHRpZXhwXCI7XG4gICAgICAgICAgICAgICAgc0dJbiA9IEcuRi5uOCozO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBncm91cFwiKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBuUG9pbnRzID0gTWF0aC5mbG9vcihidWZmQmFzZXMuYnl0ZUxlbmd0aCAvIHNHSW4pO1xuXG4gICAgICAgIGlmIChuUG9pbnRzID09PSAwKSByZXR1cm4gRy56ZXJvO1xuICAgICAgICBjb25zdCBzU2NhbGFyID0gTWF0aC5mbG9vcihidWZmU2NhbGFycy5ieXRlTGVuZ3RoIC8gblBvaW50cyk7XG4gICAgICAgIGlmKCBzU2NhbGFyICogblBvaW50cyAhPT0gYnVmZlNjYWxhcnMuYnl0ZUxlbmd0aCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU2NhbGFyIHNpemUgZG9lcyBub3QgbWF0Y2hcIik7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBiaXRDaHVua1NpemUgPSBwVFNpemVzW2xvZzIoblBvaW50cyldO1xuXG4gICAgICAgIGNvbnN0IG9wUHJvbWlzZXMgPSBbXTtcblxuICAgICAgICBjb25zdCB0YXNrID0gW1xuICAgICAgICAgICAge2NtZDogXCJBTExPQ1NFVFwiLCB2YXI6IDAsIGJ1ZmY6IGJ1ZmZCYXNlc30sXG4gICAgICAgICAgICB7Y21kOiBcIkFMTE9DU0VUXCIsIHZhcjogMSwgYnVmZjogYnVmZlNjYWxhcnN9LFxuICAgICAgICAgICAge2NtZDogXCJBTExPQ1wiLCB2YXI6IDIsIGxlbjogRy5GLm44KjN9LFxuICAgICAgICAgICAge2NtZDogXCJDQUxMXCIsIGZuTmFtZTogZm5OYW1lLCBwYXJhbXM6IFtcbiAgICAgICAgICAgICAgICB7dmFyOiAwfSwgLy9wQmFzZXNcbiAgICAgICAgICAgICAgICB7dmFyOiAxfSwgLy8gcFNjYWxhcnNcbiAgICAgICAgICAgICAgICB7dmFsOiBzU2NhbGFyfSwgLy8gc2NhbGFyU2l6ZVxuICAgICAgICAgICAgICAgIHt2YWw6IG5Qb2ludHN9LCAvLyBuUG9pbnRzXG4gICAgICAgICAgICAgICAge3ZhcjogMn0gLy8gcHJcbiAgICAgICAgICAgIF19LFxuICAgICAgICAgICAge2NtZDogXCJHRVRcIiwgb3V0OiAwLCB2YXI6IDIsIGxlbjogRy5GLm44KjN9XG4gICAgICAgIF07XG4gICAgICAgIG9wUHJvbWlzZXMucHVzaChcbiAgICAgICAgICAgIC8vIHRyYW5zZmVyIG93bmVyc2hpcCBvZiB0aGUgYnVmZmVycyB0byB0aGUgd29ya2VyIHRocmVhZFxuICAgICAgICAgICAgRy50bS5xdWV1ZUFjdGlvbih0YXNrLCBbYnVmZkJhc2VzLmJ1ZmZlciwgYnVmZlNjYWxhcnMuYnVmZmVyXSlcbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBQcm9taXNlLmFsbChvcFByb21pc2VzKTtcblxuICAgICAgICBsZXQgcmVzID0gRy56ZXJvO1xuICAgICAgICBmb3IgKGxldCBpPXJlc3VsdC5sZW5ndGgtMTsgaT49MDsgaS0tKSB7XG4gICAgICAgICAgICBpZiAoIUcuaXNaZXJvKHJlcykpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqPTA7IGo8Yml0Q2h1bmtTaXplOyBqKyspIHJlcyA9IEcuZG91YmxlKHJlcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXMgPSBHLmFkZChyZXMsIHJlc3VsdFtpXVswXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIF9tdWx0aUV4cChidWZmQmFzZXMsIGJ1ZmZTY2FsYXJzLCBpblR5cGUsIGxvZ2dlciwgbG9nVGV4dCkge1xuICAgICAgICBjb25zdCBNQVhfQ0hVTktfU0laRSA9IDEgPDwgMjI7XG4gICAgICAgIGNvbnN0IE1JTl9DSFVOS19TSVpFID0gMSA8PCAxMjtcbiAgICAgICAgbGV0IHNHSW47XG5cbiAgICAgICAgaWYgKGdyb3VwTmFtZSA9PT0gXCJHMVwiKSB7XG4gICAgICAgICAgICBpZiAoaW5UeXBlID09PSBcImFmZmluZVwiKSB7XG4gICAgICAgICAgICAgICAgc0dJbiA9IEcuRi5uOCoyO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzR0luID0gRy5GLm44KjM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoZ3JvdXBOYW1lID09PSBcIkcyXCIpIHtcbiAgICAgICAgICAgIGlmIChpblR5cGUgPT09IFwiYWZmaW5lXCIpIHtcbiAgICAgICAgICAgICAgICBzR0luID0gRy5GLm44KjI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNHSW4gPSBHLkYubjgqMztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgZ3JvdXBcIik7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBuUG9pbnRzID0gTWF0aC5mbG9vcihidWZmQmFzZXMuYnl0ZUxlbmd0aCAvIHNHSW4pO1xuICAgICAgICBpZiAoblBvaW50cyA9PT0gMCkgcmV0dXJuIEcuemVybztcbiAgICAgICAgY29uc3Qgc1NjYWxhciA9IE1hdGguZmxvb3IoYnVmZlNjYWxhcnMuYnl0ZUxlbmd0aCAvIG5Qb2ludHMpO1xuICAgICAgICBpZiggc1NjYWxhciAqIG5Qb2ludHMgIT09IGJ1ZmZTY2FsYXJzLmJ5dGVMZW5ndGgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlNjYWxhciBzaXplIGRvZXMgbm90IG1hdGNoXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy9jb25zb2xlLmxvZyhcImJ1ZmZCYXNlcy5idWZmZXIgaW5zdGFuY2VvZiBTaGFyZWRBcnJheUJ1ZmZlclwiLCBidWZmQmFzZXMuYnVmZmVyIGluc3RhbmNlb2YgU2hhcmVkQXJyYXlCdWZmZXIpO1xuICAgICAgICAvL2NvbnNvbGUubG9nKFwiYnVmZlNjYWxhcnMuYnVmZmVyIGluc3RhbmNlb2YgU2hhcmVkQXJyYXlCdWZmZXJcIiwgYnVmZlNjYWxhcnMuYnVmZmVyIGluc3RhbmNlb2YgU2hhcmVkQXJyYXlCdWZmZXIpO1xuXG4gICAgICAgIC8vbGV0IHJlc3VsdCA9IFtdO1xuICAgICAgICBjb25zdCBvcFByb21pc2VzID0gW107XG4gICAgICAgIGNvbnN0IGJpdENodW5rU2l6ZSA9IHBUU2l6ZXNbbG9nMihuUG9pbnRzKV07XG4gICAgICAgIGxldCBuQ2h1bmtzID0gTWF0aC5mbG9vcigoc1NjYWxhcio4IC0gMSkgLyBiaXRDaHVua1NpemUpICsxO1xuXG4gICAgICAgIGlmIChncm91cE5hbWUgPT09IFwiRzJcIikge1xuICAgICAgICAgICAgLy8gRzIgaGFzIGJpZ2dlciBwb2ludHMsIHNvIHdlIHJlZHVjZSBjaHVuayBzaXplIHRvIG9wdGltaXplIG1lbW9yeSB1c2FnZVxuICAgICAgICAgICAgbkNodW5rcyAqPSAyO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGNodW5rU2l6ZTtcbiAgICAgICAgLy9jaHVua1NpemUgPSBNYXRoLmZsb29yKG5Qb2ludHMgLyB0bS5jb25jdXJyZW5jeSkgKyAxO1xuXG4gICAgICAgIGNvbnNvbGUubG9nKFwibkNodW5rc18wXCIsIG5DaHVua3MpO1xuXG4gICAgICAgIC8vIG1ha2UgbkNodW5rcyBtdWx0aXBsZSBvZiB0bS5jb25jdXJyZW5jeSBmb3Igb3B0aW1hbCBsb2FkIGJhbGFuY2luZ1xuICAgICAgICBuQ2h1bmtzID0gKE1hdGguZmxvb3IoKG5DaHVua3MtMSkgLyB0bS5jb25jdXJyZW5jeSkgKyAxKSAqIHRtLmNvbmN1cnJlbmN5O1xuICAgICAgICBjaHVua1NpemUgPSBNYXRoLmZsb29yKG5Qb2ludHMgLyBuQ2h1bmtzKSArIDE7XG5cbiAgICAgICAgaWYgKGNodW5rU2l6ZT5NQVhfQ0hVTktfU0laRSkgY2h1bmtTaXplID0gTUFYX0NIVU5LX1NJWkU7XG4gICAgICAgIGlmIChjaHVua1NpemU8TUlOX0NIVU5LX1NJWkUpIGNodW5rU2l6ZSA9IE1JTl9DSFVOS19TSVpFO1xuXG4gICAgICAgIGNvbnNvbGUubG9nKFwibkNodW5rc1wiLCBuQ2h1bmtzKTtcbiAgICAgICAgY29uc29sZS5sb2coXCJlZmZlY3RpdmUgbkNodW5rc1wiLCBuUG9pbnRzIC8gY2h1bmtTaXplKTtcblxuICAgICAgICBmb3IgKGxldCBpPTA7IGk8blBvaW50czsgaSArPSBjaHVua1NpemUpIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhgTXVsdGlleHAgc3RhcnQ6ICR7bG9nVGV4dH06ICR7aX0vJHtuUG9pbnRzfWApO1xuICAgICAgICAgICAgY29uc3QgbiA9IE1hdGgubWluKG5Qb2ludHMgLSBpLCBjaHVua1NpemUpO1xuXG4gICAgICAgICAgICBjb25zdCBidWZmQmFzZXNDaHVuayA9IGJ1ZmZCYXNlcy5zbGljZShpKnNHSW4sIChpK24pKnNHSW4pO1xuICAgICAgICAgICAgY29uc3QgYnVmZlNjYWxhcnNDaHVuayA9IGJ1ZmZTY2FsYXJzLnNsaWNlKGkqc1NjYWxhciwgKGkrbikqc1NjYWxhcik7XG5cbiAgICAgICAgICAgIG9wUHJvbWlzZXMucHVzaChfbXVsdGlFeHBDaHVuayhidWZmQmFzZXNDaHVuaywgYnVmZlNjYWxhcnNDaHVuaywgaW5UeXBlLCBsb2dnZXIsIGxvZ1RleHQpLnRoZW4oKHIpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoYE11bHRpZXhwIGVuZDogJHtsb2dUZXh0fTogJHtpfS8ke25Qb2ludHN9YCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHI7XG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcmVzdWx0ID0gYXdhaXQgUHJvbWlzZS5hbGwob3BQcm9taXNlcyk7XG5cbiAgICAgICAgbGV0IHJlcyA9IEcuemVybztcbiAgICAgICAgZm9yIChsZXQgaT1yZXN1bHQubGVuZ3RoLTE7IGk+PTA7IGktLSkge1xuICAgICAgICAgICAgcmVzID0gRy5hZGQocmVzLCByZXN1bHRbaV0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICBHLm11bHRpRXhwID0gYXN5bmMgZnVuY3Rpb24gbXVsdGlFeHBBZmZpbmUoYnVmZkJhc2VzLCBidWZmU2NhbGFycywgbG9nZ2VyLCBsb2dUZXh0KSB7XG4gICAgICAgIHJldHVybiBhd2FpdCBfbXVsdGlFeHAoYnVmZkJhc2VzLCBidWZmU2NhbGFycywgXCJqYWNvYmlhblwiLCBsb2dnZXIsIGxvZ1RleHQpO1xuICAgIH07XG4gICAgRy5tdWx0aUV4cEFmZmluZSA9IGFzeW5jIGZ1bmN0aW9uIG11bHRpRXhwQWZmaW5lKGJ1ZmZCYXNlcywgYnVmZlNjYWxhcnMsIGxvZ2dlciwgbG9nVGV4dCkge1xuICAgICAgICByZXR1cm4gYXdhaXQgX211bHRpRXhwKGJ1ZmZCYXNlcywgYnVmZlNjYWxhcnMsIFwiYWZmaW5lXCIsIGxvZ2dlciwgbG9nVGV4dCk7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gYnVpbGRGRlQkMihjdXJ2ZSwgZ3JvdXBOYW1lKSB7XG4gICAgY29uc3QgRyA9IGN1cnZlW2dyb3VwTmFtZV07XG4gICAgY29uc3QgRnIgPSBjdXJ2ZS5GcjtcbiAgICBjb25zdCB0bSA9IEcudG07XG4gICAgYXN5bmMgZnVuY3Rpb24gX2ZmdChidWZmLCBpbnZlcnNlLCBpblR5cGUsIG91dFR5cGUsIGxvZ2dlciwgbG9nZ2VyVHh0KSB7XG5cbiAgICAgICAgaW5UeXBlID0gaW5UeXBlIHx8IFwiYWZmaW5lXCI7XG4gICAgICAgIG91dFR5cGUgPSBvdXRUeXBlIHx8IFwiYWZmaW5lXCI7XG4gICAgICAgIGNvbnN0IE1BWF9CSVRTX1RIUkVBRCA9IDE0O1xuXG4gICAgICAgIGxldCBzSW4sIHNNaWQsIHNPdXQsIGZuSW4yTWlkLCBmbk1pZDJPdXQsIGZuRkZUTWl4LCBmbkZGVEpvaW4sIGZuRkZURmluYWwsIGZuUmV2ZXJzZVBlcm11dGF0aW9uO1xuICAgICAgICBpZiAoZ3JvdXBOYW1lID09IFwiRzFcIikge1xuICAgICAgICAgICAgaWYgKGluVHlwZSA9PSBcImFmZmluZVwiKSB7XG4gICAgICAgICAgICAgICAgc0luID0gRy5GLm44KjI7XG4gICAgICAgICAgICAgICAgZm5JbjJNaWQgPSBcImcxbV9iYXRjaFRvSmFjb2JpYW5cIjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc0luID0gRy5GLm44KjM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzTWlkID0gRy5GLm44KjM7XG4gICAgICAgICAgICBpZiAoaW52ZXJzZSkge1xuICAgICAgICAgICAgICAgIGZuRkZURmluYWwgPSBcImcxbV9mZnRGaW5hbFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm5GRlRKb2luID0gXCJnMW1fZmZ0Sm9pblwiO1xuICAgICAgICAgICAgZm5GRlRNaXggPSBcImcxbV9mZnRNaXhcIjtcbiAgICAgICAgICAgIGZuUmV2ZXJzZVBlcm11dGF0aW9uID0gXCJnMW1fcmV2ZXJzZVBlcm11dGF0aW9uXCI7XG5cbiAgICAgICAgICAgIGlmIChvdXRUeXBlID09IFwiYWZmaW5lXCIpIHtcbiAgICAgICAgICAgICAgICBzT3V0ID0gRy5GLm44KjI7XG4gICAgICAgICAgICAgICAgZm5NaWQyT3V0ID0gXCJnMW1fYmF0Y2hUb0FmZmluZVwiO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzT3V0ID0gRy5GLm44KjM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfSBlbHNlIGlmIChncm91cE5hbWUgPT0gXCJHMlwiKSB7XG4gICAgICAgICAgICBpZiAoaW5UeXBlID09IFwiYWZmaW5lXCIpIHtcbiAgICAgICAgICAgICAgICBzSW4gPSBHLkYubjgqMjtcbiAgICAgICAgICAgICAgICBmbkluMk1pZCA9IFwiZzJtX2JhdGNoVG9KYWNvYmlhblwiO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzSW4gPSBHLkYubjgqMztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNNaWQgPSBHLkYubjgqMztcbiAgICAgICAgICAgIGlmIChpbnZlcnNlKSB7XG4gICAgICAgICAgICAgICAgZm5GRlRGaW5hbCA9IFwiZzJtX2ZmdEZpbmFsXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmbkZGVEpvaW4gPSBcImcybV9mZnRKb2luXCI7XG4gICAgICAgICAgICBmbkZGVE1peCA9IFwiZzJtX2ZmdE1peFwiO1xuICAgICAgICAgICAgZm5SZXZlcnNlUGVybXV0YXRpb24gPSBcImcybV9yZXZlcnNlUGVybXV0YXRpb25cIjtcbiAgICAgICAgICAgIGlmIChvdXRUeXBlID09IFwiYWZmaW5lXCIpIHtcbiAgICAgICAgICAgICAgICBzT3V0ID0gRy5GLm44KjI7XG4gICAgICAgICAgICAgICAgZm5NaWQyT3V0ID0gXCJnMm1fYmF0Y2hUb0FmZmluZVwiO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzT3V0ID0gRy5GLm44KjM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoZ3JvdXBOYW1lID09IFwiRnJcIikge1xuICAgICAgICAgICAgc0luID0gRy5uODtcbiAgICAgICAgICAgIHNNaWQgPSBHLm44O1xuICAgICAgICAgICAgc091dCA9IEcubjg7XG4gICAgICAgICAgICBpZiAoaW52ZXJzZSkge1xuICAgICAgICAgICAgICAgIGZuRkZURmluYWwgPSBcImZybV9mZnRGaW5hbFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm5GRlRNaXggPSBcImZybV9mZnRNaXhcIjtcbiAgICAgICAgICAgIGZuRkZUSm9pbiA9IFwiZnJtX2ZmdEpvaW5cIjtcbiAgICAgICAgICAgIGZuUmV2ZXJzZVBlcm11dGF0aW9uID0gXCJmcm1fZmZ0UmV2ZXJzZVBlcm11dGF0aW9uXCI7XG4gICAgICAgIH1cblxuXG4gICAgICAgIGxldCByZXR1cm5BcnJheSA9IGZhbHNlO1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShidWZmKSkge1xuICAgICAgICAgICAgYnVmZiA9IGFycmF5MmJ1ZmZlcihidWZmLCBzSW4pO1xuICAgICAgICAgICAgcmV0dXJuQXJyYXkgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYnVmZiA9IGJ1ZmYuc2xpY2UoMCwgYnVmZi5ieXRlTGVuZ3RoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnNvbGUubG9nKFwiRkZUIGlucHV0IHNpemU6XCIsIGJ1ZmYuYnl0ZUxlbmd0aCwgXCIgYnl0ZXNcIik7XG5cbiAgICAgICAgY29uc3QgblBvaW50cyA9IGJ1ZmYuYnl0ZUxlbmd0aCAvIHNJbjtcbiAgICAgICAgY29uc3QgYml0cyA9IGxvZzIoblBvaW50cyk7XG5cbiAgICAgICAgY29uc29sZS5sb2coXCJGRlQgcG9pbnRzOlwiLCBuUG9pbnRzLCBcIiBiaXRzOlwiLCBiaXRzKTtcblxuICAgICAgICBpZiAgKCgxIDw8IGJpdHMpICE9IG5Qb2ludHMpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImZmdCBtdXN0IGJlIG11bHRpcGxlIG9mIDJcIiApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGJpdHMgPT0gRnIucyArMSkge1xuICAgICAgICAgICAgbGV0IGJ1ZmZPdXQ7XG5cbiAgICAgICAgICAgIGlmIChpbnZlcnNlKSB7XG4gICAgICAgICAgICAgICAgYnVmZk91dCA9ICBhd2FpdCBfZmZ0RXh0SW52KGJ1ZmYsIGluVHlwZSwgb3V0VHlwZSwgbG9nZ2VyLCBsb2dnZXJUeHQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBidWZmT3V0ID0gIGF3YWl0IF9mZnRFeHQoYnVmZiwgaW5UeXBlLCBvdXRUeXBlLCBsb2dnZXIsIGxvZ2dlclR4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChyZXR1cm5BcnJheSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBidWZmZXIyYXJyYXkoYnVmZk91dCwgc091dCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBidWZmT3V0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGludjtcbiAgICAgICAgaWYgKGludmVyc2UpIHtcbiAgICAgICAgICAgIGludiA9IEZyLmludihGci5lKG5Qb2ludHMpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBidWZmT3V0O1xuXG4gICAgICAgIC8vIFRPRE86IG9wdGltaXplLiBNb3ZlIHRvIHdhc20/XG4gICAgICAgIC8vYnVmZlJldmVyc2VCaXRzKGJ1ZmYsIHNJbik7XG5cbiAgICAgICAgY29uc29sZS5sb2coXCJmblJldmVyc2VQZXJtdXRhdGlvbjpcIiwgZm5SZXZlcnNlUGVybXV0YXRpb24pO1xuXG4gICAgICAgIGNvbnN0IHRhc2sgPSBbXTtcbiAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQUxMT0NcIiwgdmFyOiAwLCBsZW46IGJ1ZmYuYnl0ZUxlbmd0aH0pO1xuICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJTRVRcIiwgdmFyOiAwLCBidWZmOiBidWZmfSk7XG4gICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkNBTExcIiwgZm5OYW1lOiBmblJldmVyc2VQZXJtdXRhdGlvbiwgcGFyYW1zOiBbe3ZhcjowfSwge3ZhbDogYml0c30sIHt2YXI6IDB9XX0pO1xuICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJHRVRcIiwgb3V0OjAsIHZhcjogMCwgbGVuOiBidWZmLmJ5dGVMZW5ndGh9KTtcbiAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgdG0ucXVldWVBY3Rpb24odGFzaywgW2J1ZmYuYnVmZmVyXSk7XG5cbiAgICAgICAgYnVmZi5zZXQocmVzWzBdKTtcblxuICAgICAgICBsZXQgY2h1bmtzO1xuICAgICAgICBsZXQgcG9pbnRzSW5DaHVuayA9IE1hdGgubWluKDEgPDwgTUFYX0JJVFNfVEhSRUFELCBuUG9pbnRzKTtcbiAgICAgICAgbGV0IG5DaHVua3MgPSBuUG9pbnRzIC8gcG9pbnRzSW5DaHVuaztcblxuICAgICAgICB3aGlsZSAoKG5DaHVua3MgPCB0bS5jb25jdXJyZW5jeSkmJihwb2ludHNJbkNodW5rPj0xNikpIHtcbiAgICAgICAgICAgIG5DaHVua3MgKj0gMjtcbiAgICAgICAgICAgIHBvaW50c0luQ2h1bmsgLz0gMjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGwyQ2h1bmsgPSBsb2cyKHBvaW50c0luQ2h1bmspO1xuXG4gICAgICAgIGNvbnN0IHByb21pc2VzID0gW107XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpPCBuQ2h1bmtzOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhgJHtsb2dnZXJUeHR9OiBmZnQgJHtiaXRzfSBtaXggc3RhcnQ6ICR7aX0vJHtuQ2h1bmtzfWApO1xuICAgICAgICAgICAgY29uc3QgdGFzayA9IFtdO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQUxMT0NcIiwgdmFyOiAwLCBsZW46IHNNaWQqcG9pbnRzSW5DaHVua30pO1xuICAgICAgICAgICAgY29uc3QgYnVmZkNodW5rID0gYnVmZi5zbGljZSggKHBvaW50c0luQ2h1bmsgKiBpKSpzSW4sIChwb2ludHNJbkNodW5rICogKGkrMSkpKnNJbik7XG4gICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJTRVRcIiwgdmFyOiAwLCBidWZmOiBidWZmQ2h1bmt9KTtcbiAgICAgICAgICAgIGlmIChmbkluMk1pZCkge1xuICAgICAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkNBTExcIiwgZm5OYW1lOmZuSW4yTWlkLCBwYXJhbXM6IFt7dmFyOjB9LCB7dmFsOiBwb2ludHNJbkNodW5rfSwge3ZhcjogMH1dfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBqPTE7IGo8PWwyQ2h1bms7aisrKSB7XG4gICAgICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQ0FMTFwiLCBmbk5hbWU6Zm5GRlRNaXgsIHBhcmFtczogW3t2YXI6MH0sIHt2YWw6IHBvaW50c0luQ2h1bmt9LCB7dmFsOiBqfV19KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGwyQ2h1bms9PWJpdHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZm5GRlRGaW5hbCkge1xuICAgICAgICAgICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJBTExPQ1NFVFwiLCB2YXI6IDEsIGJ1ZmY6IGludn0pO1xuICAgICAgICAgICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJDQUxMXCIsIGZuTmFtZTogZm5GRlRGaW5hbCwgIHBhcmFtczpbXG4gICAgICAgICAgICAgICAgICAgICAgICB7dmFyOiAwfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHt2YWw6IHBvaW50c0luQ2h1bmt9LFxuICAgICAgICAgICAgICAgICAgICAgICAge3ZhcjogMX0sXG4gICAgICAgICAgICAgICAgICAgIF19KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGZuTWlkMk91dCkge1xuICAgICAgICAgICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJDQUxMXCIsIGZuTmFtZTpmbk1pZDJPdXQsIHBhcmFtczogW3t2YXI6MH0sIHt2YWw6IHBvaW50c0luQ2h1bmt9LCB7dmFyOiAwfV19KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiR0VUXCIsIG91dDogMCwgdmFyOiAwLCBsZW46IHBvaW50c0luQ2h1bmsqc091dH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJHRVRcIiwgb3V0OjAsIHZhcjogMCwgbGVuOiBzTWlkKnBvaW50c0luQ2h1bmt9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHByb21pc2VzLnB1c2godG0ucXVldWVBY3Rpb24odGFzaywgW2J1ZmZDaHVuay5idWZmZXJdKS50aGVuKCAocikgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhgJHtsb2dnZXJUeHR9OiBmZnQgJHtiaXRzfSBtaXggZW5kOiAke2l9LyR7bkNodW5rc31gKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcjtcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNodW5rcyA9IGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VzKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGk8IG5DaHVua3M7IGkrKykgY2h1bmtzW2ldID0gY2h1bmtzW2ldWzBdO1xuXG4gICAgICAgIGZvciAobGV0IGkgPSBsMkNodW5rKzE7ICAgaTw9Yml0czsgaSsrKSB7XG4gICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoYCR7bG9nZ2VyVHh0fTogZmZ0ICAke2JpdHN9ICBqb2luOiAke2l9LyR7Yml0c31gKTtcbiAgICAgICAgICAgIGNvbnN0IG5Hcm91cHMgPSAxIDw8IChiaXRzIC0gaSk7XG4gICAgICAgICAgICBjb25zdCBuQ2h1bmtzUGVyR3JvdXAgPSBuQ2h1bmtzIC8gbkdyb3VwcztcbiAgICAgICAgICAgIGNvbnN0IG9wUHJvbWlzZXMgPSBbXTtcbiAgICAgICAgICAgIGZvciAobGV0IGo9MDsgajxuR3JvdXBzOyBqKyspIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBrPTA7IGsgPG5DaHVua3NQZXJHcm91cC8yOyBrKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZmlyc3QgPSBGci5leHAoIEZyLndbaV0sIGsqcG9pbnRzSW5DaHVuayk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGluYyA9IEZyLndbaV07XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG8xID0gaipuQ2h1bmtzUGVyR3JvdXAgKyBrO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBvMiA9IGoqbkNodW5rc1Blckdyb3VwICsgayArIG5DaHVua3NQZXJHcm91cC8yO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRhc2sgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQUxMT0NTRVRcIiwgdmFyOiAwLCBidWZmOiBjaHVua3NbbzFdfSk7XG4gICAgICAgICAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkFMTE9DU0VUXCIsIHZhcjogMSwgYnVmZjogY2h1bmtzW28yXX0pO1xuICAgICAgICAgICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJBTExPQ1NFVFwiLCB2YXI6IDIsIGJ1ZmY6IGZpcnN0fSk7XG4gICAgICAgICAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkFMTE9DU0VUXCIsIHZhcjogMywgYnVmZjogaW5jfSk7XG4gICAgICAgICAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkNBTExcIiwgZm5OYW1lOiBmbkZGVEpvaW4sICBwYXJhbXM6W1xuICAgICAgICAgICAgICAgICAgICAgICAge3ZhcjogMH0sXG4gICAgICAgICAgICAgICAgICAgICAgICB7dmFyOiAxfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHt2YWw6IHBvaW50c0luQ2h1bmt9LFxuICAgICAgICAgICAgICAgICAgICAgICAge3ZhcjogMn0sXG4gICAgICAgICAgICAgICAgICAgICAgICB7dmFyOiAzfVxuICAgICAgICAgICAgICAgICAgICBdfSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpPT1iaXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZm5GRlRGaW5hbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkFMTE9DU0VUXCIsIHZhcjogNCwgYnVmZjogaW52fSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQ0FMTFwiLCBmbk5hbWU6IGZuRkZURmluYWwsICBwYXJhbXM6W1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7dmFyOiAwfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3ZhbDogcG9pbnRzSW5DaHVua30sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt2YXI6IDR9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF19KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJDQUxMXCIsIGZuTmFtZTogZm5GRlRGaW5hbCwgIHBhcmFtczpbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt2YXI6IDF9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7dmFsOiBwb2ludHNJbkNodW5rfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3ZhcjogNH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXX0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZuTWlkMk91dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkNBTExcIiwgZm5OYW1lOmZuTWlkMk91dCwgcGFyYW1zOiBbe3ZhcjowfSwge3ZhbDogcG9pbnRzSW5DaHVua30sIHt2YXI6IDB9XX0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkNBTExcIiwgZm5OYW1lOmZuTWlkMk91dCwgcGFyYW1zOiBbe3ZhcjoxfSwge3ZhbDogcG9pbnRzSW5DaHVua30sIHt2YXI6IDF9XX0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiR0VUXCIsIG91dDogMCwgdmFyOiAwLCBsZW46IHBvaW50c0luQ2h1bmsqc091dH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiR0VUXCIsIG91dDogMSwgdmFyOiAxLCBsZW46IHBvaW50c0luQ2h1bmsqc091dH0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiR0VUXCIsIG91dDogMCwgdmFyOiAwLCBsZW46IHBvaW50c0luQ2h1bmsqc01pZH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiR0VUXCIsIG91dDogMSwgdmFyOiAxLCBsZW46IHBvaW50c0luQ2h1bmsqc01pZH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIG9wUHJvbWlzZXMucHVzaCh0bS5xdWV1ZUFjdGlvbih0YXNrLCBbY2h1bmtzW28xXS5idWZmZXIsIGNodW5rc1tvMl0uYnVmZmVyLCBmaXJzdC5idWZmZXIgXSkudGhlbiggKHIpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhgJHtsb2dnZXJUeHR9OiBmZnQgJHtiaXRzfSBqb2luICAke2l9LyR7Yml0c30gICR7aisxfS8ke25Hcm91cHN9ICR7a30vJHtuQ2h1bmtzUGVyR3JvdXAvMn1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByO1xuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCByZXMgPSBhd2FpdCBQcm9taXNlLmFsbChvcFByb21pc2VzKTtcbiAgICAgICAgICAgIGZvciAobGV0IGo9MDsgajxuR3JvdXBzOyBqKyspIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBrPTA7IGsgPG5DaHVua3NQZXJHcm91cC8yOyBrKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbzEgPSBqKm5DaHVua3NQZXJHcm91cCArIGs7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG8yID0gaipuQ2h1bmtzUGVyR3JvdXAgKyBrICsgbkNodW5rc1Blckdyb3VwLzI7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc0NodW5rID0gcmVzLnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgICAgIGNodW5rc1tvMV0gPSByZXNDaHVua1swXTtcbiAgICAgICAgICAgICAgICAgICAgY2h1bmtzW28yXSA9IHJlc0NodW5rWzFdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChidWZmIGluc3RhbmNlb2YgQmlnQnVmZmVyKSB7XG4gICAgICAgICAgICBidWZmT3V0ID0gbmV3IEJpZ0J1ZmZlcihuUG9pbnRzKnNPdXQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYnVmZk91dCA9IG5ldyBVaW50OEFycmF5KG5Qb2ludHMqc091dCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGludmVyc2UpIHtcbiAgICAgICAgICAgIGJ1ZmZPdXQuc2V0KGNodW5rc1swXS5zbGljZSgocG9pbnRzSW5DaHVuay0xKSpzT3V0KSk7XG4gICAgICAgICAgICBsZXQgcD0gc091dDtcbiAgICAgICAgICAgIGZvciAobGV0IGk9bkNodW5rcy0xOyBpPjA7IGktLSkge1xuICAgICAgICAgICAgICAgIGJ1ZmZPdXQuc2V0KGNodW5rc1tpXSwgcCk7XG4gICAgICAgICAgICAgICAgcCArPSBwb2ludHNJbkNodW5rKnNPdXQ7XG4gICAgICAgICAgICAgICAgZGVsZXRlIGNodW5rc1tpXTsgIC8vIExpYmVyYXRlIG1lbVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnVmZk91dC5zZXQoY2h1bmtzWzBdLnNsaWNlKDAsIChwb2ludHNJbkNodW5rLTEpKnNPdXQpLCBwKTtcbiAgICAgICAgICAgIGRlbGV0ZSBjaHVua3NbMF07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmb3IgKGxldCBpPTA7IGk8bkNodW5rczsgaSsrKSB7XG4gICAgICAgICAgICAgICAgYnVmZk91dC5zZXQoY2h1bmtzW2ldLCBwb2ludHNJbkNodW5rKnNPdXQqaSk7XG4gICAgICAgICAgICAgICAgZGVsZXRlIGNodW5rc1tpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChyZXR1cm5BcnJheSkge1xuICAgICAgICAgICAgcmV0dXJuIGJ1ZmZlcjJhcnJheShidWZmT3V0LCBzT3V0KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBidWZmT3V0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMgZnVuY3Rpb24gX2ZmdEV4dChidWZmLCBpblR5cGUsIG91dFR5cGUsIGxvZ2dlciwgbG9nZ2VyVHh0KSB7XG4gICAgICAgIGxldCBiMSwgYjI7XG4gICAgICAgIGIxID0gYnVmZi5zbGljZSggMCAsIGJ1ZmYuYnl0ZUxlbmd0aC8yKTtcbiAgICAgICAgYjIgPSBidWZmLnNsaWNlKCBidWZmLmJ5dGVMZW5ndGgvMiwgYnVmZi5ieXRlTGVuZ3RoKTtcblxuICAgICAgICBjb25zdCBwcm9taXNlcyA9IFtdO1xuXG4gICAgICAgIFtiMSwgYjJdID0gYXdhaXQgX2ZmdEpvaW5FeHQoYjEsIGIyLCBcImZmdEpvaW5FeHRcIiwgRnIub25lLCBGci5zaGlmdCwgaW5UeXBlLCBcImphY29iaWFuXCIsIGxvZ2dlciwgbG9nZ2VyVHh0KTtcblxuICAgICAgICBwcm9taXNlcy5wdXNoKCBfZmZ0KGIxLCBmYWxzZSwgXCJqYWNvYmlhblwiLCBvdXRUeXBlLCBsb2dnZXIsIGxvZ2dlclR4dCkpO1xuICAgICAgICBwcm9taXNlcy5wdXNoKCBfZmZ0KGIyLCBmYWxzZSwgXCJqYWNvYmlhblwiLCBvdXRUeXBlLCBsb2dnZXIsIGxvZ2dlclR4dCkpO1xuXG4gICAgICAgIGNvbnN0IHJlczEgPSBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7XG5cbiAgICAgICAgbGV0IGJ1ZmZPdXQ7XG4gICAgICAgIGlmIChyZXMxWzBdLmJ5dGVMZW5ndGggPiAoMTw8MjgpKSB7XG4gICAgICAgICAgICBidWZmT3V0ID0gbmV3IEJpZ0J1ZmZlcihyZXMxWzBdLmJ5dGVMZW5ndGgqMik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBidWZmT3V0ID0gbmV3IFVpbnQ4QXJyYXkocmVzMVswXS5ieXRlTGVuZ3RoKjIpO1xuICAgICAgICB9XG5cbiAgICAgICAgYnVmZk91dC5zZXQocmVzMVswXSk7XG4gICAgICAgIGJ1ZmZPdXQuc2V0KHJlczFbMV0sIHJlczFbMF0uYnl0ZUxlbmd0aCk7XG5cbiAgICAgICAgcmV0dXJuIGJ1ZmZPdXQ7XG4gICAgfVxuXG4gICAgYXN5bmMgZnVuY3Rpb24gX2ZmdEV4dEludihidWZmLCBpblR5cGUsIG91dFR5cGUsIGxvZ2dlciwgbG9nZ2VyVHh0KSB7XG4gICAgICAgIGxldCBiMSwgYjI7XG4gICAgICAgIGIxID0gYnVmZi5zbGljZSggMCAsIGJ1ZmYuYnl0ZUxlbmd0aC8yKTtcbiAgICAgICAgYjIgPSBidWZmLnNsaWNlKCBidWZmLmJ5dGVMZW5ndGgvMiwgYnVmZi5ieXRlTGVuZ3RoKTtcblxuICAgICAgICBjb25zdCBwcm9taXNlcyA9IFtdO1xuXG4gICAgICAgIHByb21pc2VzLnB1c2goIF9mZnQoYjEsIHRydWUsIGluVHlwZSwgXCJqYWNvYmlhblwiLCBsb2dnZXIsIGxvZ2dlclR4dCkpO1xuICAgICAgICBwcm9taXNlcy5wdXNoKCBfZmZ0KGIyLCB0cnVlLCBpblR5cGUsIFwiamFjb2JpYW5cIiwgbG9nZ2VyLCBsb2dnZXJUeHQpKTtcblxuICAgICAgICBbYjEsIGIyXSA9IGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VzKTtcblxuICAgICAgICBjb25zdCByZXMxID0gYXdhaXQgX2ZmdEpvaW5FeHQoYjEsIGIyLCBcImZmdEpvaW5FeHRJbnZcIiwgRnIub25lLCBGci5zaGlmdEludiwgXCJqYWNvYmlhblwiLCBvdXRUeXBlLCBsb2dnZXIsIGxvZ2dlclR4dCk7XG5cbiAgICAgICAgbGV0IGJ1ZmZPdXQ7XG4gICAgICAgIGlmIChyZXMxWzBdLmJ5dGVMZW5ndGggPiAoMTw8MjgpKSB7XG4gICAgICAgICAgICBidWZmT3V0ID0gbmV3IEJpZ0J1ZmZlcihyZXMxWzBdLmJ5dGVMZW5ndGgqMik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBidWZmT3V0ID0gbmV3IFVpbnQ4QXJyYXkocmVzMVswXS5ieXRlTGVuZ3RoKjIpO1xuICAgICAgICB9XG5cbiAgICAgICAgYnVmZk91dC5zZXQocmVzMVswXSk7XG4gICAgICAgIGJ1ZmZPdXQuc2V0KHJlczFbMV0sIHJlczFbMF0uYnl0ZUxlbmd0aCk7XG5cbiAgICAgICAgcmV0dXJuIGJ1ZmZPdXQ7XG4gICAgfVxuXG5cbiAgICBhc3luYyBmdW5jdGlvbiBfZmZ0Sm9pbkV4dChidWZmMSwgYnVmZjIsIGZuLCBmaXJzdCwgaW5jLCBpblR5cGUsIG91dFR5cGUsIGxvZ2dlciwgbG9nZ2VyVHh0KSB7XG4gICAgICAgIGNvbnN0IE1BWF9DSFVOS19TSVpFID0gMTw8MTY7XG4gICAgICAgIGNvbnN0IE1JTl9DSFVOS19TSVpFID0gMTw8NDtcblxuICAgICAgICBsZXQgZm5OYW1lO1xuICAgICAgICBsZXQgZm5JbjJNaWQsIGZuTWlkMk91dDtcbiAgICAgICAgbGV0IHNPdXQsIHNJbiwgc01pZDtcblxuICAgICAgICBpZiAoZ3JvdXBOYW1lID09IFwiRzFcIikge1xuICAgICAgICAgICAgaWYgKGluVHlwZSA9PSBcImFmZmluZVwiKSB7XG4gICAgICAgICAgICAgICAgc0luID0gRy5GLm44KjI7XG4gICAgICAgICAgICAgICAgZm5JbjJNaWQgPSBcImcxbV9iYXRjaFRvSmFjb2JpYW5cIjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc0luID0gRy5GLm44KjM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzTWlkID0gRy5GLm44KjM7XG4gICAgICAgICAgICBmbk5hbWUgPSBcImcxbV9cIitmbjtcbiAgICAgICAgICAgIGlmIChvdXRUeXBlID09IFwiYWZmaW5lXCIpIHtcbiAgICAgICAgICAgICAgICBmbk1pZDJPdXQgPSBcImcxbV9iYXRjaFRvQWZmaW5lXCI7XG4gICAgICAgICAgICAgICAgc091dCA9IEcuRi5uOCoyO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzT3V0ID0gRy5GLm44KjM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoZ3JvdXBOYW1lID09IFwiRzJcIikge1xuICAgICAgICAgICAgaWYgKGluVHlwZSA9PSBcImFmZmluZVwiKSB7XG4gICAgICAgICAgICAgICAgc0luID0gRy5GLm44KjI7XG4gICAgICAgICAgICAgICAgZm5JbjJNaWQgPSBcImcybV9iYXRjaFRvSmFjb2JpYW5cIjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc0luID0gRy5GLm44KjM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmbk5hbWUgPSBcImcybV9cIitmbjtcbiAgICAgICAgICAgIHNNaWQgPSBHLkYubjgqMztcbiAgICAgICAgICAgIGlmIChvdXRUeXBlID09IFwiYWZmaW5lXCIpIHtcbiAgICAgICAgICAgICAgICBmbk1pZDJPdXQgPSBcImcybV9iYXRjaFRvQWZmaW5lXCI7XG4gICAgICAgICAgICAgICAgc091dCA9IEcuRi5uOCoyO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzT3V0ID0gRy5GLm44KjM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoZ3JvdXBOYW1lID09IFwiRnJcIikge1xuICAgICAgICAgICAgc0luID0gRnIubjg7XG4gICAgICAgICAgICBzT3V0ID0gRnIubjg7XG4gICAgICAgICAgICBzTWlkID0gRnIubjg7XG4gICAgICAgICAgICBmbk5hbWUgPSBcImZybV9cIiArIGZuO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBncm91cFwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChidWZmMS5ieXRlTGVuZ3RoICE9IGJ1ZmYyLmJ5dGVMZW5ndGgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgYnVmZmVyIHNpemVcIik7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgblBvaW50cyA9IE1hdGguZmxvb3IoYnVmZjEuYnl0ZUxlbmd0aCAvIHNJbik7XG4gICAgICAgIGlmIChuUG9pbnRzICE9IDEgPDwgbG9nMihuUG9pbnRzKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBudW1iZXIgb2YgcG9pbnRzXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGNodW5rU2l6ZSA9IE1hdGguZmxvb3IoblBvaW50cyAvdG0uY29uY3VycmVuY3kpO1xuICAgICAgICBpZiAoY2h1bmtTaXplIDwgTUlOX0NIVU5LX1NJWkUpIGNodW5rU2l6ZSA9IE1JTl9DSFVOS19TSVpFO1xuICAgICAgICBpZiAoY2h1bmtTaXplID4gTUFYX0NIVU5LX1NJWkUpIGNodW5rU2l6ZSA9IE1BWF9DSFVOS19TSVpFO1xuXG4gICAgICAgIGNvbnN0IG9wUHJvbWlzZXMgPSBbXTtcblxuICAgICAgICBmb3IgKGxldCBpPTA7IGk8blBvaW50czsgaSArPSBjaHVua1NpemUpIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhgJHtsb2dnZXJUeHR9OiBmZnRKb2luRXh0IFN0YXJ0OiAke2l9LyR7blBvaW50c31gKTtcbiAgICAgICAgICAgIGNvbnN0IG49IE1hdGgubWluKG5Qb2ludHMgLSBpLCBjaHVua1NpemUpO1xuXG4gICAgICAgICAgICBjb25zdCBmaXJzdENodW5rID0gRnIubXVsKGZpcnN0LCBGci5leHAoIGluYywgaSkpO1xuICAgICAgICAgICAgY29uc3QgdGFzayA9IFtdO1xuXG4gICAgICAgICAgICBjb25zdCBiMSA9IGJ1ZmYxLnNsaWNlKGkqc0luLCAoaStuKSpzSW4pO1xuICAgICAgICAgICAgY29uc3QgYjIgPSBidWZmMi5zbGljZShpKnNJbiwgKGkrbikqc0luKTtcblxuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQUxMT0NcIiwgdmFyOiAwLCBsZW46IHNNaWQqbn0pO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiU0VUXCIsIHZhcjogMCwgYnVmZjogYjF9KTtcbiAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkFMTE9DXCIsIHZhcjogMSwgbGVuOiBzTWlkKm59KTtcbiAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIlNFVFwiLCB2YXI6IDEsIGJ1ZmY6IGIyfSk7XG4gICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJBTExPQ1NFVFwiLCB2YXI6IDIsIGJ1ZmY6IGZpcnN0Q2h1bmt9KTtcbiAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkFMTE9DU0VUXCIsIHZhcjogMywgYnVmZjogaW5jfSk7XG4gICAgICAgICAgICBpZiAoZm5JbjJNaWQpIHtcbiAgICAgICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJDQUxMXCIsIGZuTmFtZTpmbkluMk1pZCwgcGFyYW1zOiBbe3ZhcjowfSwge3ZhbDogbn0sIHt2YXI6IDB9XX0pO1xuICAgICAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkNBTExcIiwgZm5OYW1lOmZuSW4yTWlkLCBwYXJhbXM6IFt7dmFyOjF9LCB7dmFsOiBufSwge3ZhcjogMX1dfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJDQUxMXCIsIGZuTmFtZTogZm5OYW1lLCBwYXJhbXM6IFtcbiAgICAgICAgICAgICAgICB7dmFyOiAwfSxcbiAgICAgICAgICAgICAgICB7dmFyOiAxfSxcbiAgICAgICAgICAgICAgICB7dmFsOiBufSxcbiAgICAgICAgICAgICAgICB7dmFyOiAyfSxcbiAgICAgICAgICAgICAgICB7dmFyOiAzfSxcbiAgICAgICAgICAgICAgICB7dmFsOiBGci5zfSxcbiAgICAgICAgICAgIF19KTtcbiAgICAgICAgICAgIGlmIChmbk1pZDJPdXQpIHtcbiAgICAgICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJDQUxMXCIsIGZuTmFtZTpmbk1pZDJPdXQsIHBhcmFtczogW3t2YXI6MH0sIHt2YWw6IG59LCB7dmFyOiAwfV19KTtcbiAgICAgICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJDQUxMXCIsIGZuTmFtZTpmbk1pZDJPdXQsIHBhcmFtczogW3t2YXI6MX0sIHt2YWw6IG59LCB7dmFyOiAxfV19KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkdFVFwiLCBvdXQ6IDAsIHZhcjogMCwgbGVuOiBuKnNPdXR9KTtcbiAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkdFVFwiLCBvdXQ6IDEsIHZhcjogMSwgbGVuOiBuKnNPdXR9KTtcbiAgICAgICAgICAgIG9wUHJvbWlzZXMucHVzaChcbiAgICAgICAgICAgICAgICB0bS5xdWV1ZUFjdGlvbih0YXNrLCBbYjEuYnVmZmVyLCBiMi5idWZmZXIsIGZpcnN0Q2h1bmsuYnVmZmVyXSkudGhlbigocikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoYCR7bG9nZ2VyVHh0fTogZmZ0Sm9pbkV4dCBFbmQ6ICR7aX0vJHtuUG9pbnRzfWApO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcjtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IFByb21pc2UuYWxsKG9wUHJvbWlzZXMpO1xuXG4gICAgICAgIGxldCBmdWxsQnVmZk91dDE7XG4gICAgICAgIGxldCBmdWxsQnVmZk91dDI7XG4gICAgICAgIGlmIChuUG9pbnRzICogc091dCA+IDE8PDI4KSB7XG4gICAgICAgICAgICBmdWxsQnVmZk91dDEgPSBuZXcgQmlnQnVmZmVyKG5Qb2ludHMqc091dCk7XG4gICAgICAgICAgICBmdWxsQnVmZk91dDIgPSBuZXcgQmlnQnVmZmVyKG5Qb2ludHMqc091dCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmdWxsQnVmZk91dDEgPSBuZXcgVWludDhBcnJheShuUG9pbnRzKnNPdXQpO1xuICAgICAgICAgICAgZnVsbEJ1ZmZPdXQyID0gbmV3IFVpbnQ4QXJyYXkoblBvaW50cypzT3V0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBwID0wO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8cmVzdWx0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBmdWxsQnVmZk91dDEuc2V0KHJlc3VsdFtpXVswXSwgcCk7XG4gICAgICAgICAgICBmdWxsQnVmZk91dDIuc2V0KHJlc3VsdFtpXVsxXSwgcCk7XG4gICAgICAgICAgICBwKz1yZXN1bHRbaV1bMF0uYnl0ZUxlbmd0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBbZnVsbEJ1ZmZPdXQxLCBmdWxsQnVmZk91dDJdO1xuICAgIH1cblxuXG4gICAgRy5mZnQgPSBhc3luYyBmdW5jdGlvbihidWZmLCBpblR5cGUsIG91dFR5cGUsIGxvZ2dlciwgbG9nZ2VyVHh0KSB7XG4gICAgICAgIHJldHVybiBhd2FpdCBfZmZ0KGJ1ZmYsIGZhbHNlLCBpblR5cGUsIG91dFR5cGUsIGxvZ2dlciwgbG9nZ2VyVHh0KTtcbiAgICB9O1xuXG4gICAgRy5pZmZ0ID0gYXN5bmMgZnVuY3Rpb24oYnVmZiwgaW5UeXBlLCBvdXRUeXBlLCBsb2dnZXIsIGxvZ2dlclR4dCkge1xuICAgICAgICByZXR1cm4gYXdhaXQgX2ZmdChidWZmLCB0cnVlLCBpblR5cGUsIG91dFR5cGUsIGxvZ2dlciwgbG9nZ2VyVHh0KTtcbiAgICB9O1xuXG4gICAgRy5sYWdyYW5nZUV2YWx1YXRpb25zID0gYXN5bmMgZnVuY3Rpb24gKGJ1ZmYsIGluVHlwZSwgb3V0VHlwZSwgbG9nZ2VyLCBsb2dnZXJUeHQpIHtcbiAgICAgICAgaW5UeXBlID0gaW5UeXBlIHx8IFwiYWZmaW5lXCI7XG4gICAgICAgIG91dFR5cGUgPSBvdXRUeXBlIHx8IFwiYWZmaW5lXCI7XG5cbiAgICAgICAgbGV0IHNJbjtcbiAgICAgICAgaWYgKGdyb3VwTmFtZSA9PSBcIkcxXCIpIHtcbiAgICAgICAgICAgIGlmIChpblR5cGUgPT0gXCJhZmZpbmVcIikge1xuICAgICAgICAgICAgICAgIHNJbiA9IEcuRi5uOCoyO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzSW4gPSBHLkYubjgqMztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChncm91cE5hbWUgPT0gXCJHMlwiKSB7XG4gICAgICAgICAgICBpZiAoaW5UeXBlID09IFwiYWZmaW5lXCIpIHtcbiAgICAgICAgICAgICAgICBzSW4gPSBHLkYubjgqMjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc0luID0gRy5GLm44KjM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoZ3JvdXBOYW1lID09IFwiRnJcIikge1xuICAgICAgICAgICAgc0luID0gRnIubjg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIGdyb3VwXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgblBvaW50cyA9IGJ1ZmYuYnl0ZUxlbmd0aCAvc0luO1xuICAgICAgICBjb25zdCBiaXRzID0gbG9nMihuUG9pbnRzKTtcblxuICAgICAgICBpZiAoKDIgKiogYml0cykqc0luICE9IGJ1ZmYuYnl0ZUxlbmd0aCkge1xuICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwibGFncmFuZ2VFdmFsdWF0aW9ucyBpaW52YWxpZCBpbnB1dCBzaXplXCIpO1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwibGFncmFuZ2VFdmFsdWF0aW9ucyBpbnZhbGlkIElucHV0IHNpemVcIik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYml0cyA8PSBGci5zKSB7XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgRy5pZmZ0KGJ1ZmYsIGluVHlwZSwgb3V0VHlwZSwgbG9nZ2VyLCBsb2dnZXJUeHQpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGJpdHMgPiBGci5zKzEpIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihcImxhZ3JhbmdlRXZhbHVhdGlvbnMgaW5wdXQgdG9vIGJpZ1wiKTtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImxhZ3JhbmdlRXZhbHVhdGlvbnMgaW5wdXQgdG9vIGJpZ1wiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCB0MCA9IGJ1ZmYuc2xpY2UoMCwgYnVmZi5ieXRlTGVuZ3RoLzIpO1xuICAgICAgICBsZXQgdDEgPSBidWZmLnNsaWNlKGJ1ZmYuYnl0ZUxlbmd0aC8yLCBidWZmLmJ5dGVMZW5ndGgpO1xuXG5cbiAgICAgICAgY29uc3Qgc2hpZnRUb1NtYWxsTSA9IEZyLmV4cChGci5zaGlmdCwgblBvaW50cy8yKTtcbiAgICAgICAgY29uc3Qgc0NvbnN0ID0gRnIuaW52KCBGci5zdWIoRnIub25lLCBzaGlmdFRvU21hbGxNKSk7XG5cbiAgICAgICAgW3QwLCB0MV0gPSBhd2FpdCBfZmZ0Sm9pbkV4dCh0MCwgdDEsIFwicHJlcGFyZUxhZ3JhbmdlRXZhbHVhdGlvblwiLCBzQ29uc3QsIEZyLnNoaWZ0SW52LCBpblR5cGUsIFwiamFjb2JpYW5cIiwgbG9nZ2VyLCBsb2dnZXJUeHQgKyBcIiBwcmVwXCIpO1xuXG4gICAgICAgIGNvbnN0IHByb21pc2VzID0gW107XG5cbiAgICAgICAgcHJvbWlzZXMucHVzaCggX2ZmdCh0MCwgdHJ1ZSwgXCJqYWNvYmlhblwiLCBvdXRUeXBlLCBsb2dnZXIsIGxvZ2dlclR4dCArIFwiIHQwXCIpKTtcbiAgICAgICAgcHJvbWlzZXMucHVzaCggX2ZmdCh0MSwgdHJ1ZSwgXCJqYWNvYmlhblwiLCBvdXRUeXBlLCBsb2dnZXIsIGxvZ2dlclR4dCArIFwiIHQxXCIpKTtcblxuICAgICAgICBbdDAsIHQxXSA9IGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VzKTtcblxuICAgICAgICBsZXQgYnVmZk91dDtcbiAgICAgICAgaWYgKHQwLmJ5dGVMZW5ndGggPiAoMTw8MjgpKSB7XG4gICAgICAgICAgICBidWZmT3V0ID0gbmV3IEJpZ0J1ZmZlcih0MC5ieXRlTGVuZ3RoKjIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYnVmZk91dCA9IG5ldyBVaW50OEFycmF5KHQwLmJ5dGVMZW5ndGgqMik7XG4gICAgICAgIH1cblxuICAgICAgICBidWZmT3V0LnNldCh0MCk7XG4gICAgICAgIGJ1ZmZPdXQuc2V0KHQxLCB0MC5ieXRlTGVuZ3RoKTtcblxuICAgICAgICByZXR1cm4gYnVmZk91dDtcbiAgICB9O1xuXG4gICAgRy5mZnRNaXggPSBhc3luYyBmdW5jdGlvbiBmZnRNaXgoYnVmZikge1xuICAgICAgICBjb25zdCBzRyA9IEcuRi5uOCozO1xuICAgICAgICBsZXQgZm5OYW1lLCBmbkZGVEpvaW47XG4gICAgICAgIGlmIChncm91cE5hbWUgPT0gXCJHMVwiKSB7XG4gICAgICAgICAgICBmbk5hbWUgPSBcImcxbV9mZnRNaXhcIjtcbiAgICAgICAgICAgIGZuRkZUSm9pbiA9IFwiZzFtX2ZmdEpvaW5cIjtcbiAgICAgICAgfSBlbHNlIGlmIChncm91cE5hbWUgPT0gXCJHMlwiKSB7XG4gICAgICAgICAgICBmbk5hbWUgPSBcImcybV9mZnRNaXhcIjtcbiAgICAgICAgICAgIGZuRkZUSm9pbiA9IFwiZzJtX2ZmdEpvaW5cIjtcbiAgICAgICAgfSBlbHNlIGlmIChncm91cE5hbWUgPT0gXCJGclwiKSB7XG4gICAgICAgICAgICBmbk5hbWUgPSBcImZybV9mZnRNaXhcIjtcbiAgICAgICAgICAgIGZuRkZUSm9pbiA9IFwiZnJtX2ZmdEpvaW5cIjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgZ3JvdXBcIik7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBuUG9pbnRzID0gTWF0aC5mbG9vcihidWZmLmJ5dGVMZW5ndGggLyBzRyk7XG4gICAgICAgIGNvbnN0IHBvd2VyID0gbG9nMihuUG9pbnRzKTtcblxuICAgICAgICBsZXQgbkNodW5rcyA9IDEgPDwgbG9nMih0bS5jb25jdXJyZW5jeSk7XG5cbiAgICAgICAgaWYgKG5Qb2ludHMgPD0gbkNodW5rcyoyKSBuQ2h1bmtzID0gMTtcblxuICAgICAgICBjb25zdCBwb2ludHNQZXJDaHVuayA9IG5Qb2ludHMgLyBuQ2h1bmtzO1xuXG4gICAgICAgIGNvbnN0IHBvd2VyQ2h1bmsgPSBsb2cyKHBvaW50c1BlckNodW5rKTtcblxuICAgICAgICBjb25zdCBvcFByb21pc2VzID0gW107XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxuQ2h1bmtzOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IHRhc2sgPSBbXTtcbiAgICAgICAgICAgIGNvbnN0IGIgPSBidWZmLnNsaWNlKChpKiBwb2ludHNQZXJDaHVuaykqc0csICgoaSsxKSogcG9pbnRzUGVyQ2h1bmspKnNHKTtcbiAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkFMTE9DU0VUXCIsIHZhcjogMCwgYnVmZjogYn0pO1xuICAgICAgICAgICAgZm9yIChsZXQgaj0xOyBqPD1wb3dlckNodW5rOyBqKyspIHtcbiAgICAgICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJDQUxMXCIsIGZuTmFtZTogZm5OYW1lLCBwYXJhbXM6IFtcbiAgICAgICAgICAgICAgICAgICAge3ZhcjogMH0sXG4gICAgICAgICAgICAgICAgICAgIHt2YWw6IHBvaW50c1BlckNodW5rfSxcbiAgICAgICAgICAgICAgICAgICAge3ZhbDogan1cbiAgICAgICAgICAgICAgICBdfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJHRVRcIiwgb3V0OiAwLCB2YXI6IDAsIGxlbjogcG9pbnRzUGVyQ2h1bmsqc0d9KTtcbiAgICAgICAgICAgIG9wUHJvbWlzZXMucHVzaChcbiAgICAgICAgICAgICAgICB0bS5xdWV1ZUFjdGlvbih0YXNrLCBbYi5idWZmZXJdKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IFByb21pc2UuYWxsKG9wUHJvbWlzZXMpO1xuXG4gICAgICAgIGNvbnN0IGNodW5rcyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8cmVzdWx0Lmxlbmd0aDsgaSsrKSBjaHVua3NbaV0gPSByZXN1bHRbaV1bMF07XG5cblxuICAgICAgICBmb3IgKGxldCBpID0gcG93ZXJDaHVuaysxOyBpPD1wb3dlcjsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBuR3JvdXBzID0gMSA8PCAocG93ZXIgLSBpKTtcbiAgICAgICAgICAgIGNvbnN0IG5DaHVua3NQZXJHcm91cCA9IG5DaHVua3MgLyBuR3JvdXBzO1xuICAgICAgICAgICAgY29uc3Qgb3BQcm9taXNlcyA9IFtdO1xuICAgICAgICAgICAgZm9yIChsZXQgaj0wOyBqPG5Hcm91cHM7IGorKykge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGs9MDsgayA8bkNodW5rc1Blckdyb3VwLzI7IGsrKykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBmaXJzdCA9IEZyLmV4cCggRnIud1tpXSwgaypwb2ludHNQZXJDaHVuayk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGluYyA9IEZyLndbaV07XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG8xID0gaipuQ2h1bmtzUGVyR3JvdXAgKyBrO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBvMiA9IGoqbkNodW5rc1Blckdyb3VwICsgayArIG5DaHVua3NQZXJHcm91cC8yO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRhc2sgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQUxMT0NTRVRcIiwgdmFyOiAwLCBidWZmOiBjaHVua3NbbzFdfSk7XG4gICAgICAgICAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkFMTE9DU0VUXCIsIHZhcjogMSwgYnVmZjogY2h1bmtzW28yXX0pO1xuICAgICAgICAgICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJBTExPQ1NFVFwiLCB2YXI6IDIsIGJ1ZmY6IGZpcnN0fSk7XG4gICAgICAgICAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkFMTE9DU0VUXCIsIHZhcjogMywgYnVmZjogaW5jfSk7XG4gICAgICAgICAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkNBTExcIiwgZm5OYW1lOiBmbkZGVEpvaW4sICBwYXJhbXM6W1xuICAgICAgICAgICAgICAgICAgICAgICAge3ZhcjogMH0sXG4gICAgICAgICAgICAgICAgICAgICAgICB7dmFyOiAxfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHt2YWw6IHBvaW50c1BlckNodW5rfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHt2YXI6IDJ9LFxuICAgICAgICAgICAgICAgICAgICAgICAge3ZhcjogM31cbiAgICAgICAgICAgICAgICAgICAgXX0pO1xuICAgICAgICAgICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJHRVRcIiwgb3V0OiAwLCB2YXI6IDAsIGxlbjogcG9pbnRzUGVyQ2h1bmsqc0d9KTtcbiAgICAgICAgICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiR0VUXCIsIG91dDogMSwgdmFyOiAxLCBsZW46IHBvaW50c1BlckNodW5rKnNHfSk7XG4gICAgICAgICAgICAgICAgICAgIG9wUHJvbWlzZXMucHVzaCh0bS5xdWV1ZUFjdGlvbih0YXNrLCBbY2h1bmtzW28xXS5idWZmZXIsIGNodW5rc1tvMl0uYnVmZmVyLCBmaXJzdC5idWZmZXJdKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCByZXMgPSBhd2FpdCBQcm9taXNlLmFsbChvcFByb21pc2VzKTtcbiAgICAgICAgICAgIGZvciAobGV0IGo9MDsgajxuR3JvdXBzOyBqKyspIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBrPTA7IGsgPG5DaHVua3NQZXJHcm91cC8yOyBrKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbzEgPSBqKm5DaHVua3NQZXJHcm91cCArIGs7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG8yID0gaipuQ2h1bmtzUGVyR3JvdXAgKyBrICsgbkNodW5rc1Blckdyb3VwLzI7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc0NodW5rID0gcmVzLnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgICAgIGNodW5rc1tvMV0gPSByZXNDaHVua1swXTtcbiAgICAgICAgICAgICAgICAgICAgY2h1bmtzW28yXSA9IHJlc0NodW5rWzFdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBmdWxsQnVmZk91dDtcbiAgICAgICAgaWYgKGJ1ZmYgaW5zdGFuY2VvZiBCaWdCdWZmZXIpIHtcbiAgICAgICAgICAgIGZ1bGxCdWZmT3V0ID0gbmV3IEJpZ0J1ZmZlcihuUG9pbnRzKnNHKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZ1bGxCdWZmT3V0ID0gbmV3IFVpbnQ4QXJyYXkoblBvaW50cypzRyk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHAgPTA7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxuQ2h1bmtzOyBpKyspIHtcbiAgICAgICAgICAgIGZ1bGxCdWZmT3V0LnNldChjaHVua3NbaV0sIHApO1xuICAgICAgICAgICAgcCs9Y2h1bmtzW2ldLmJ5dGVMZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZnVsbEJ1ZmZPdXQ7XG4gICAgfTtcblxuICAgIEcuZmZ0Sm9pbiA9IGFzeW5jIGZ1bmN0aW9uIGZmdEpvaW4oYnVmZjEsIGJ1ZmYyLCBmaXJzdCwgaW5jKSB7XG4gICAgICAgIGNvbnN0IHNHID0gRy5GLm44KjM7XG4gICAgICAgIGxldCBmbk5hbWU7XG4gICAgICAgIGlmIChncm91cE5hbWUgPT0gXCJHMVwiKSB7XG4gICAgICAgICAgICBmbk5hbWUgPSBcImcxbV9mZnRKb2luXCI7XG4gICAgICAgIH0gZWxzZSBpZiAoZ3JvdXBOYW1lID09IFwiRzJcIikge1xuICAgICAgICAgICAgZm5OYW1lID0gXCJnMm1fZmZ0Sm9pblwiO1xuICAgICAgICB9IGVsc2UgaWYgKGdyb3VwTmFtZSA9PSBcIkZyXCIpIHtcbiAgICAgICAgICAgIGZuTmFtZSA9IFwiZnJtX2ZmdEpvaW5cIjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgZ3JvdXBcIik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYnVmZjEuYnl0ZUxlbmd0aCAhPSBidWZmMi5ieXRlTGVuZ3RoKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIGJ1ZmZlciBzaXplXCIpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG5Qb2ludHMgPSBNYXRoLmZsb29yKGJ1ZmYxLmJ5dGVMZW5ndGggLyBzRyk7XG4gICAgICAgIGlmIChuUG9pbnRzICE9IDEgPDwgbG9nMihuUG9pbnRzKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBudW1iZXIgb2YgcG9pbnRzXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IG5DaHVua3MgPSAxIDw8IGxvZzIodG0uY29uY3VycmVuY3kpO1xuICAgICAgICBpZiAoblBvaW50cyA8PSBuQ2h1bmtzKjIpIG5DaHVua3MgPSAxO1xuXG4gICAgICAgIGNvbnN0IHBvaW50c1BlckNodW5rID0gblBvaW50cyAvIG5DaHVua3M7XG5cblxuICAgICAgICBjb25zdCBvcFByb21pc2VzID0gW107XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxuQ2h1bmtzOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IHRhc2sgPSBbXTtcblxuICAgICAgICAgICAgY29uc3QgZmlyc3RDaHVuayA9IEZyLm11bChmaXJzdCwgRnIuZXhwKGluYywgaSpwb2ludHNQZXJDaHVuaykpO1xuICAgICAgICAgICAgY29uc3QgYjEgPSBidWZmMS5zbGljZSgoaSogcG9pbnRzUGVyQ2h1bmspKnNHLCAoKGkrMSkqIHBvaW50c1BlckNodW5rKSpzRyk7XG4gICAgICAgICAgICBjb25zdCBiMiA9IGJ1ZmYyLnNsaWNlKChpKiBwb2ludHNQZXJDaHVuaykqc0csICgoaSsxKSogcG9pbnRzUGVyQ2h1bmspKnNHKTtcbiAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkFMTE9DU0VUXCIsIHZhcjogMCwgYnVmZjogYjF9KTtcbiAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkFMTE9DU0VUXCIsIHZhcjogMSwgYnVmZjogYjJ9KTtcbiAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkFMTE9DU0VUXCIsIHZhcjogMiwgYnVmZjogZmlyc3RDaHVua30pO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQUxMT0NTRVRcIiwgdmFyOiAzLCBidWZmOiBpbmN9KTtcbiAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkNBTExcIiwgZm5OYW1lOiBmbk5hbWUsIHBhcmFtczogW1xuICAgICAgICAgICAgICAgIHt2YXI6IDB9LFxuICAgICAgICAgICAgICAgIHt2YXI6IDF9LFxuICAgICAgICAgICAgICAgIHt2YWw6IHBvaW50c1BlckNodW5rfSxcbiAgICAgICAgICAgICAgICB7dmFyOiAyfSxcbiAgICAgICAgICAgICAgICB7dmFyOiAzfVxuICAgICAgICAgICAgXX0pO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiR0VUXCIsIG91dDogMCwgdmFyOiAwLCBsZW46IHBvaW50c1BlckNodW5rKnNHfSk7XG4gICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJHRVRcIiwgb3V0OiAxLCB2YXI6IDEsIGxlbjogcG9pbnRzUGVyQ2h1bmsqc0d9KTtcbiAgICAgICAgICAgIG9wUHJvbWlzZXMucHVzaChcbiAgICAgICAgICAgICAgICB0bS5xdWV1ZUFjdGlvbih0YXNrLCBbYjEuYnVmZmVyLCBiMi5idWZmZXIsIGZpcnN0Q2h1bmsuYnVmZmVyXSlcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgfVxuXG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgUHJvbWlzZS5hbGwob3BQcm9taXNlcyk7XG5cbiAgICAgICAgbGV0IGZ1bGxCdWZmT3V0MTtcbiAgICAgICAgbGV0IGZ1bGxCdWZmT3V0MjtcbiAgICAgICAgaWYgKGJ1ZmYxIGluc3RhbmNlb2YgQmlnQnVmZmVyKSB7XG4gICAgICAgICAgICBmdWxsQnVmZk91dDEgPSBuZXcgQmlnQnVmZmVyKG5Qb2ludHMqc0cpO1xuICAgICAgICAgICAgZnVsbEJ1ZmZPdXQyID0gbmV3IEJpZ0J1ZmZlcihuUG9pbnRzKnNHKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZ1bGxCdWZmT3V0MSA9IG5ldyBVaW50OEFycmF5KG5Qb2ludHMqc0cpO1xuICAgICAgICAgICAgZnVsbEJ1ZmZPdXQyID0gbmV3IFVpbnQ4QXJyYXkoblBvaW50cypzRyk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcCA9MDtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPHJlc3VsdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgZnVsbEJ1ZmZPdXQxLnNldChyZXN1bHRbaV1bMF0sIHApO1xuICAgICAgICAgICAgZnVsbEJ1ZmZPdXQyLnNldChyZXN1bHRbaV1bMV0sIHApO1xuICAgICAgICAgICAgcCs9cmVzdWx0W2ldWzBdLmJ5dGVMZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gW2Z1bGxCdWZmT3V0MSwgZnVsbEJ1ZmZPdXQyXTtcbiAgICB9O1xuXG5cblxuICAgIEcuZmZ0RmluYWwgPSAgYXN5bmMgZnVuY3Rpb24gZmZ0RmluYWwoYnVmZiwgZmFjdG9yKSB7XG4gICAgICAgIGNvbnN0IHNHID0gRy5GLm44KjM7XG4gICAgICAgIGNvbnN0IHNHb3V0ID0gRy5GLm44KjI7XG4gICAgICAgIGxldCBmbk5hbWUsIGZuVG9BZmZpbmU7XG4gICAgICAgIGlmIChncm91cE5hbWUgPT0gXCJHMVwiKSB7XG4gICAgICAgICAgICBmbk5hbWUgPSBcImcxbV9mZnRGaW5hbFwiO1xuICAgICAgICAgICAgZm5Ub0FmZmluZSA9IFwiZzFtX2JhdGNoVG9BZmZpbmVcIjtcbiAgICAgICAgfSBlbHNlIGlmIChncm91cE5hbWUgPT0gXCJHMlwiKSB7XG4gICAgICAgICAgICBmbk5hbWUgPSBcImcybV9mZnRGaW5hbFwiO1xuICAgICAgICAgICAgZm5Ub0FmZmluZSA9IFwiZzJtX2JhdGNoVG9BZmZpbmVcIjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgZ3JvdXBcIik7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBuUG9pbnRzID0gTWF0aC5mbG9vcihidWZmLmJ5dGVMZW5ndGggLyBzRyk7XG4gICAgICAgIGlmIChuUG9pbnRzICE9IDEgPDwgbG9nMihuUG9pbnRzKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBudW1iZXIgb2YgcG9pbnRzXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcG9pbnRzUGVyQ2h1bmsgPSBNYXRoLmZsb29yKG5Qb2ludHMgLyB0bS5jb25jdXJyZW5jeSk7XG5cbiAgICAgICAgY29uc3Qgb3BQcm9taXNlcyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8dG0uY29uY3VycmVuY3k7IGkrKykge1xuICAgICAgICAgICAgbGV0IG47XG4gICAgICAgICAgICBpZiAoaTwgdG0uY29uY3VycmVuY3ktMSkge1xuICAgICAgICAgICAgICAgIG4gPSBwb2ludHNQZXJDaHVuaztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbiA9IG5Qb2ludHMgLSBpKnBvaW50c1BlckNodW5rO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG49PTApIGNvbnRpbnVlO1xuICAgICAgICAgICAgY29uc3QgdGFzayA9IFtdO1xuICAgICAgICAgICAgY29uc3QgYiA9IGJ1ZmYuc2xpY2UoKGkqIHBvaW50c1BlckNodW5rKSpzRywgKGkqcG9pbnRzUGVyQ2h1bmsrbikqc0cpO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQUxMT0NTRVRcIiwgdmFyOiAwLCBidWZmOiBifSk7XG4gICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJBTExPQ1NFVFwiLCB2YXI6IDEsIGJ1ZmY6IGZhY3Rvcn0pO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQ0FMTFwiLCBmbk5hbWU6IGZuTmFtZSwgcGFyYW1zOiBbXG4gICAgICAgICAgICAgICAge3ZhcjogMH0sXG4gICAgICAgICAgICAgICAge3ZhbDogbn0sXG4gICAgICAgICAgICAgICAge3ZhcjogMX0sXG4gICAgICAgICAgICBdfSk7XG4gICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJDQUxMXCIsIGZuTmFtZTogZm5Ub0FmZmluZSwgcGFyYW1zOiBbXG4gICAgICAgICAgICAgICAge3ZhcjogMH0sXG4gICAgICAgICAgICAgICAge3ZhbDogbn0sXG4gICAgICAgICAgICAgICAge3ZhcjogMH0sXG4gICAgICAgICAgICBdfSk7XG4gICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJHRVRcIiwgb3V0OiAwLCB2YXI6IDAsIGxlbjogbipzR291dH0pO1xuICAgICAgICAgICAgb3BQcm9taXNlcy5wdXNoKFxuICAgICAgICAgICAgICAgIHRtLnF1ZXVlQWN0aW9uKHRhc2ssIFtiLmJ1ZmZlcl0pXG4gICAgICAgICAgICApO1xuXG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBQcm9taXNlLmFsbChvcFByb21pc2VzKTtcblxuICAgICAgICBsZXQgZnVsbEJ1ZmZPdXQ7XG4gICAgICAgIGlmIChidWZmIGluc3RhbmNlb2YgQmlnQnVmZmVyKSB7XG4gICAgICAgICAgICBmdWxsQnVmZk91dCA9IG5ldyBCaWdCdWZmZXIoblBvaW50cypzR291dCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmdWxsQnVmZk91dCA9IG5ldyBVaW50OEFycmF5KG5Qb2ludHMqc0dvdXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHAgPTA7XG4gICAgICAgIGZvciAobGV0IGk9cmVzdWx0Lmxlbmd0aC0xOyBpPj0wOyBpLS0pIHtcbiAgICAgICAgICAgIGZ1bGxCdWZmT3V0LnNldChyZXN1bHRbaV1bMF0sIHApO1xuICAgICAgICAgICAgcCs9cmVzdWx0W2ldWzBdLmJ5dGVMZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZnVsbEJ1ZmZPdXQ7XG4gICAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gYnVpbGRFbmdpbmUocGFyYW1zKSB7XG5cbiAgICBjb25zdCB0bSA9IGF3YWl0IGJ1aWxkVGhyZWFkTWFuYWdlcihwYXJhbXMud2FzbSwgcGFyYW1zLnNpbmdsZVRocmVhZCk7XG5cblxuICAgIGNvbnN0IGN1cnZlID0ge307XG5cbiAgICBjdXJ2ZS5xID0gZShwYXJhbXMud2FzbS5xLnRvU3RyaW5nKCkpO1xuICAgIGN1cnZlLnIgPSBlKHBhcmFtcy53YXNtLnIudG9TdHJpbmcoKSk7XG4gICAgY3VydmUubmFtZSA9IHBhcmFtcy5uYW1lO1xuICAgIGN1cnZlLnRtID0gdG07XG4gICAgY3VydmUucHJlUFNpemUgPSBwYXJhbXMud2FzbS5wcmVQU2l6ZTtcbiAgICBjdXJ2ZS5wcmVRU2l6ZSA9IHBhcmFtcy53YXNtLnByZVFTaXplO1xuICAgIGN1cnZlLkZyID0gbmV3IFdhc21GaWVsZDEodG0sIFwiZnJtXCIsIHBhcmFtcy5uOHIsIHBhcmFtcy5yKTtcbiAgICBjdXJ2ZS5GMSA9IG5ldyBXYXNtRmllbGQxKHRtLCBcImYxbVwiLCBwYXJhbXMubjhxLCBwYXJhbXMucSk7XG4gICAgY3VydmUuRjIgPSBuZXcgV2FzbUZpZWxkMih0bSwgXCJmMm1cIiwgY3VydmUuRjEpO1xuICAgIGN1cnZlLkcxID0gbmV3IFdhc21DdXJ2ZSh0bSwgXCJnMW1cIiwgY3VydmUuRjEsIHBhcmFtcy53YXNtLnBHMWdlbiwgcGFyYW1zLndhc20ucEcxYiwgcGFyYW1zLmNvZmFjdG9yRzEpO1xuICAgIGN1cnZlLkcyID0gbmV3IFdhc21DdXJ2ZSh0bSwgXCJnMm1cIiwgY3VydmUuRjIsIHBhcmFtcy53YXNtLnBHMmdlbiwgcGFyYW1zLndhc20ucEcyYiwgcGFyYW1zLmNvZmFjdG9yRzIpO1xuICAgIGN1cnZlLkY2ID0gbmV3IFdhc21GaWVsZDModG0sIFwiZjZtXCIsIGN1cnZlLkYyKTtcbiAgICBjdXJ2ZS5GMTIgPSBuZXcgV2FzbUZpZWxkMih0bSwgXCJmdG1cIiwgY3VydmUuRjYpO1xuXG4gICAgY3VydmUuR3QgPSBjdXJ2ZS5GMTI7XG5cbiAgICBidWlsZEJhdGNoQXBwbHlLZXkoY3VydmUsIFwiRzFcIik7XG4gICAgYnVpbGRCYXRjaEFwcGx5S2V5KGN1cnZlLCBcIkcyXCIpO1xuICAgIGJ1aWxkQmF0Y2hBcHBseUtleShjdXJ2ZSwgXCJGclwiKTtcblxuICAgIGJ1aWxkTXVsdGlleHAkMShjdXJ2ZSwgXCJHMVwiKTtcbiAgICBidWlsZE11bHRpZXhwJDEoY3VydmUsIFwiRzJcIik7XG5cbiAgICBidWlsZEZGVCQyKGN1cnZlLCBcIkcxXCIpO1xuICAgIGJ1aWxkRkZUJDIoY3VydmUsIFwiRzJcIik7XG4gICAgYnVpbGRGRlQkMihjdXJ2ZSwgXCJGclwiKTtcblxuICAgIGJ1aWxkUGFpcmluZyhjdXJ2ZSk7XG5cbiAgICBjdXJ2ZS5hcnJheTJidWZmZXIgPSBmdW5jdGlvbihhcnIsIHNHKSB7XG4gICAgICAgIGNvbnN0IGJ1ZmYgPSBuZXcgVWludDhBcnJheShzRyphcnIubGVuZ3RoKTtcblxuICAgICAgICBmb3IgKGxldCBpPTA7IGk8YXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBidWZmLnNldChhcnJbaV0sIGkqc0cpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGJ1ZmY7XG4gICAgfTtcblxuICAgIGN1cnZlLmJ1ZmZlcjJhcnJheSA9IGZ1bmN0aW9uKGJ1ZmYgLCBzRykge1xuICAgICAgICBjb25zdCBuPSBidWZmLmJ5dGVMZW5ndGggLyBzRztcbiAgICAgICAgY29uc3QgYXJyID0gbmV3IEFycmF5KG4pO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8bjsgaSsrKSB7XG4gICAgICAgICAgICBhcnJbaV0gPSBidWZmLnNsaWNlKGkqc0csIGkqc0crc0cpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhcnI7XG4gICAgfTtcblxuICAgIHJldHVybiBjdXJ2ZTtcbn1cblxuLy9pbXBvcnQgeyBibjEyOF93YXNtX2d6aXAgYXMgYm4xMjh3YXNtUHJlYnVpbHQgfSBmcm9tIFwid2FzbWN1cnZlc1wiO1xuXG5nbG9iYWxUaGlzLmN1cnZlX2JuMTI4ID0gbnVsbDtcblxuYXN5bmMgZnVuY3Rpb24gYnVpbGRCbjEyOCQxKHNpbmdsZVRocmVhZCwgcGx1Z2lucykge1xuICAgIGlmICgoIXNpbmdsZVRocmVhZCkgJiYgKGdsb2JhbFRoaXMuY3VydmVfYm4xMjgpKSByZXR1cm4gZ2xvYmFsVGhpcy5jdXJ2ZV9ibjEyODtcblxuICAgIGxldCBibjEyOHdhc20gPSB7fTtcblxuICAgIGlmICghcGx1Z2lucykge1xuXG4gICAgICAgIGNvbnNvbGUubG9nKFwiVXNpbmcgcHJlYnVpbHQgYm4xMjggd2FzbVwiKTtcblxuICAgICAgICAvL2ltcG9ydCB7IGJuMTI4X3dhc21fZ3ppcCBhcyBibjEyOHdhc21QcmVidWlsdCB9IGZyb20gXCJ3YXNtY3VydmVzXCI7XG4gICAgICAgIGNvbnN0IHsgYm4xMjhfd2FzbV9nemlwOiBibjEyOHdhc21QcmVidWlsdCB9ID0gYXdhaXQgUHJvbWlzZS5yZXNvbHZlKCkudGhlbihmdW5jdGlvbiAoKSB7IHJldHVybiBpbmRleDsgfSk7XG4gICAgICAgIC8vY29uc3QgeyBkZWZhdWx0OiBibjEyOHdhc21QcmVidWlsdCB9ID0gYXdhaXQgaW1wb3J0KFwid2FzbWN1cnZlcy9idWlsZC9ibjEyOF93YXNtX2d6aXAuanNcIik7XG5cbiAgICAgICAgLy9jb25zb2xlLmxvZyhibjEyOHdhc21QcmVidWlsdCk7XG4gICAgICAgIGJuMTI4d2FzbS5wcSA9IGJuMTI4d2FzbVByZWJ1aWx0LnBxO1xuICAgICAgICBibjEyOHdhc20ucHIgPSBibjEyOHdhc21QcmVidWlsdC5wcTtcbiAgICAgICAgYm4xMjh3YXNtLnBHMWdlbiA9IGJuMTI4d2FzbVByZWJ1aWx0LnBHMWdlbjtcbiAgICAgICAgYm4xMjh3YXNtLnBHMXplcm8gPSBibjEyOHdhc21QcmVidWlsdC5wRzF6ZXJvO1xuICAgICAgICBibjEyOHdhc20ucEcxYiA9IGJuMTI4d2FzbVByZWJ1aWx0LnBHMWI7XG4gICAgICAgIGJuMTI4d2FzbS5wRzJnZW4gPSBibjEyOHdhc21QcmVidWlsdC5wRzJnZW47XG4gICAgICAgIGJuMTI4d2FzbS5wRzJ6ZXJvID0gYm4xMjh3YXNtUHJlYnVpbHQucEcyemVybztcbiAgICAgICAgYm4xMjh3YXNtLnBHMmIgPSBibjEyOHdhc21QcmVidWlsdC5wRzJiO1xuICAgICAgICBibjEyOHdhc20ucE9uZVQgPSBibjEyOHdhc21QcmVidWlsdC5wT25lVDtcbiAgICAgICAgYm4xMjh3YXNtLnByZVBTaXplID0gYm4xMjh3YXNtUHJlYnVpbHQucHJlUFNpemU7XG4gICAgICAgIGJuMTI4d2FzbS5wcmVRU2l6ZSA9IGJuMTI4d2FzbVByZWJ1aWx0LnByZVFTaXplO1xuICAgICAgICBibjEyOHdhc20ubjhxID0gMzI7XG4gICAgICAgIGJuMTI4d2FzbS5uOHIgPSAzMjtcbiAgICAgICAgYm4xMjh3YXNtLnEgPSBibjEyOHdhc21QcmVidWlsdC5xO1xuICAgICAgICBibjEyOHdhc20uciA9IGJuMTI4d2FzbVByZWJ1aWx0LnI7XG5cbiAgICAgICAgY29uc3QgY29tcHJlc3NlZENvZGUgPSBuZXcgVWludDhBcnJheShCdWZmZXIuZnJvbShibjEyOHdhc21QcmVidWlsdC5nemlwQ29kZSwgXCJiYXNlNjRcIikpO1xuICAgICAgICBjb25zdCBibG9iID0gbmV3IEJsb2IoW2NvbXByZXNzZWRDb2RlXSk7XG5cbiAgICAgICAgY29uc3QgZHMgPSBuZXcgRGVjb21wcmVzc2lvblN0cmVhbShcImd6aXBcIik7XG4gICAgICAgIGNvbnN0IGRlY29tcHJlc3NlZFN0cmVhbSA9IGJsb2Iuc3RyZWFtKCkucGlwZVRocm91Z2goZHMpO1xuXG4gICAgICAgIGJuMTI4d2FzbS5jb2RlID0gYXdhaXQgbmV3IFJlc3BvbnNlKGRlY29tcHJlc3NlZFN0cmVhbSkuYnl0ZXMoKTtcbiAgICB9IGVsc2Uge1xuXG4gICAgICAgIC8vaW1wb3J0IHsgTW9kdWxlQnVpbGRlciB9IGZyb20gXCJ3YXNtYnVpbGRlclwiO1xuICAgICAgICAvL2ltcG9ydCB7IGJ1aWxkQm4xMjggYXMgYnVpbGRCbjEyOHdhc20gfSBmcm9tIFwid2FzbWN1cnZlc1wiO1xuICAgICAgICBjb25zdCB7IE1vZHVsZUJ1aWxkZXIgfSA9IGF3YWl0IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oZnVuY3Rpb24gKCkgeyByZXR1cm4gbWFpbjsgfSk7XG4gICAgICAgIGNvbnN0IHsgYnVpbGRCbjEyODogYnVpbGRCbjEyOHdhc20gfSA9IGF3YWl0IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oZnVuY3Rpb24gKCkgeyByZXR1cm4gaW5kZXg7IH0pO1xuXG4gICAgICAgIGNvbnN0IG1vZHVsZUJ1aWxkZXIgPSBuZXcgTW9kdWxlQnVpbGRlcigpO1xuICAgICAgICBtb2R1bGVCdWlsZGVyLnNldE1lbW9yeSgyNSk7XG4gICAgICAgIGJ1aWxkQm4xMjh3YXNtKG1vZHVsZUJ1aWxkZXIpO1xuXG4gICAgICAgIGlmIChwbHVnaW5zKSBwbHVnaW5zKG1vZHVsZUJ1aWxkZXIpO1xuXG4gICAgICAgIGJuMTI4d2FzbS5jb2RlID0gbW9kdWxlQnVpbGRlci5idWlsZCgpO1xuICAgICAgICBibjEyOHdhc20ucHEgPSBtb2R1bGVCdWlsZGVyLm1vZHVsZXMuZjFtLnBxO1xuICAgICAgICBibjEyOHdhc20ucHIgPSBtb2R1bGVCdWlsZGVyLm1vZHVsZXMuZnJtLnBxO1xuICAgICAgICBibjEyOHdhc20ucEcxZ2VuID0gbW9kdWxlQnVpbGRlci5tb2R1bGVzLmJuMTI4LnBHMWdlbjtcbiAgICAgICAgYm4xMjh3YXNtLnBHMXplcm8gPSBtb2R1bGVCdWlsZGVyLm1vZHVsZXMuYm4xMjgucEcxemVybztcbiAgICAgICAgYm4xMjh3YXNtLnBHMWIgPSBtb2R1bGVCdWlsZGVyLm1vZHVsZXMuYm4xMjgucEcxYjtcbiAgICAgICAgYm4xMjh3YXNtLnBHMmdlbiA9IG1vZHVsZUJ1aWxkZXIubW9kdWxlcy5ibjEyOC5wRzJnZW47XG4gICAgICAgIGJuMTI4d2FzbS5wRzJ6ZXJvID0gbW9kdWxlQnVpbGRlci5tb2R1bGVzLmJuMTI4LnBHMnplcm87XG4gICAgICAgIGJuMTI4d2FzbS5wRzJiID0gbW9kdWxlQnVpbGRlci5tb2R1bGVzLmJuMTI4LnBHMmI7XG4gICAgICAgIGJuMTI4d2FzbS5wT25lVCA9IG1vZHVsZUJ1aWxkZXIubW9kdWxlcy5ibjEyOC5wT25lVDtcbiAgICAgICAgYm4xMjh3YXNtLnByZVBTaXplID0gbW9kdWxlQnVpbGRlci5tb2R1bGVzLmJuMTI4LnByZVBTaXplO1xuICAgICAgICBibjEyOHdhc20ucHJlUVNpemUgPSBtb2R1bGVCdWlsZGVyLm1vZHVsZXMuYm4xMjgucHJlUVNpemU7XG4gICAgICAgIGJuMTI4d2FzbS5uOHEgPSAzMjtcbiAgICAgICAgYm4xMjh3YXNtLm44ciA9IDMyO1xuICAgICAgICBibjEyOHdhc20ucSA9IG1vZHVsZUJ1aWxkZXIubW9kdWxlcy5ibjEyOC5xO1xuICAgICAgICBibjEyOHdhc20uciA9IG1vZHVsZUJ1aWxkZXIubW9kdWxlcy5ibjEyOC5yO1xuICAgIH1cblxuICAgIC8vY29uc29sZS5sb2coXCJibjEyOHdhc206XCIsIGJuMTI4d2FzbSk7XG5cbiAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgIG5hbWU6IFwiYm4xMjhcIixcbiAgICAgICAgd2FzbTogYm4xMjh3YXNtLFxuICAgICAgICBxOiBlKFwiMjE4ODgyNDI4NzE4MzkyNzUyMjIyNDY0MDU3NDUyNTcyNzUwODg2OTYzMTExNTcyOTc4MjM2NjI2ODkwMzc4OTQ2NDUyMjYyMDg1ODNcIiksXG4gICAgICAgIHI6IGUoXCIyMTg4ODI0Mjg3MTgzOTI3NTIyMjI0NjQwNTc0NTI1NzI3NTA4ODU0ODM2NDQwMDQxNjAzNDM0MzY5ODIwNDE4NjU3NTgwODQ5NTYxN1wiKSxcbiAgICAgICAgbjhxOiAzMixcbiAgICAgICAgbjhyOiAzMixcbiAgICAgICAgY29mYWN0b3JHMjogZShcIjMwNjQ0ZTcyZTEzMWEwMjliODUwNDViNjgxODE1ODVlMDZjZWVjZGE1NzJhMjQ4OTM0NWYyMjk5YzBmOWZhOGRcIiwgMTYpLFxuICAgICAgICBzaW5nbGVUaHJlYWQ6IHNpbmdsZVRocmVhZCA/IHRydWUgOiBmYWxzZVxuICAgIH07XG5cbiAgICBjb25zdCBjdXJ2ZSA9IGF3YWl0IGJ1aWxkRW5naW5lKHBhcmFtcyk7XG4gICAgY3VydmUudGVybWluYXRlID0gYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXBhcmFtcy5zaW5nbGVUaHJlYWQpIHtcbiAgICAgICAgICAgIGdsb2JhbFRoaXMuY3VydmVfYm4xMjggPSBudWxsO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy50bS50ZXJtaW5hdGUoKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBpZiAoIXNpbmdsZVRocmVhZCkge1xuICAgICAgICBnbG9iYWxUaGlzLmN1cnZlX2JuMTI4ID0gY3VydmU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGN1cnZlO1xufVxuXG5nbG9iYWxUaGlzLmN1cnZlX2JsczEyMzgxID0gbnVsbDtcblxuYXN5bmMgZnVuY3Rpb24gYnVpbGRCbHMxMjM4MSQxKHNpbmdsZVRocmVhZCwgcGx1Z2lucykge1xuICAgIGlmICgoIXNpbmdsZVRocmVhZCkgJiYgKGdsb2JhbFRoaXMuY3VydmVfYmxzMTIzODEpKSByZXR1cm4gZ2xvYmFsVGhpcy5jdXJ2ZV9ibHMxMjM4MTtcblxuICAgIGNvbnN0IHsgTW9kdWxlQnVpbGRlciB9ID0gYXdhaXQgUHJvbWlzZS5yZXNvbHZlKCkudGhlbihmdW5jdGlvbiAoKSB7IHJldHVybiBtYWluOyB9KTtcbiAgICBjb25zdCB7IGJ1aWxkQmxzMTIzODE6IGJ1aWxkQmxzMTIzODF3YXNtIH0gPSBhd2FpdCBQcm9taXNlLnJlc29sdmUoKS50aGVuKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGluZGV4OyB9KTtcblxuICAgIGNvbnN0IG1vZHVsZUJ1aWxkZXIgPSBuZXcgTW9kdWxlQnVpbGRlcigpO1xuICAgIG1vZHVsZUJ1aWxkZXIuc2V0TWVtb3J5KDI1KTtcbiAgICBidWlsZEJsczEyMzgxd2FzbShtb2R1bGVCdWlsZGVyKTtcblxuICAgIGlmIChwbHVnaW5zKSBwbHVnaW5zKG1vZHVsZUJ1aWxkZXIpO1xuXG4gICAgY29uc3QgYmxzMTIzODF3YXNtID0ge307XG5cbiAgICBibHMxMjM4MXdhc20uY29kZSA9IG1vZHVsZUJ1aWxkZXIuYnVpbGQoKTtcbiAgICBibHMxMjM4MXdhc20ucHEgPSBtb2R1bGVCdWlsZGVyLm1vZHVsZXMuZjFtLnBxO1xuICAgIGJsczEyMzgxd2FzbS5wciA9IG1vZHVsZUJ1aWxkZXIubW9kdWxlcy5mcm0ucHE7XG4gICAgYmxzMTIzODF3YXNtLnBHMWdlbiA9IG1vZHVsZUJ1aWxkZXIubW9kdWxlcy5ibHMxMjM4MS5wRzFnZW47XG4gICAgYmxzMTIzODF3YXNtLnBHMXplcm8gPSBtb2R1bGVCdWlsZGVyLm1vZHVsZXMuYmxzMTIzODEucEcxemVybztcbiAgICBibHMxMjM4MXdhc20ucEcxYiA9IG1vZHVsZUJ1aWxkZXIubW9kdWxlcy5ibHMxMjM4MS5wRzFiO1xuICAgIGJsczEyMzgxd2FzbS5wRzJnZW4gPSBtb2R1bGVCdWlsZGVyLm1vZHVsZXMuYmxzMTIzODEucEcyZ2VuO1xuICAgIGJsczEyMzgxd2FzbS5wRzJ6ZXJvID0gbW9kdWxlQnVpbGRlci5tb2R1bGVzLmJsczEyMzgxLnBHMnplcm87XG4gICAgYmxzMTIzODF3YXNtLnBHMmIgPSBtb2R1bGVCdWlsZGVyLm1vZHVsZXMuYmxzMTIzODEucEcyYjtcbiAgICBibHMxMjM4MXdhc20ucE9uZVQgPSBtb2R1bGVCdWlsZGVyLm1vZHVsZXMuYmxzMTIzODEucE9uZVQ7XG4gICAgYmxzMTIzODF3YXNtLnByZVBTaXplID0gbW9kdWxlQnVpbGRlci5tb2R1bGVzLmJsczEyMzgxLnByZVBTaXplO1xuICAgIGJsczEyMzgxd2FzbS5wcmVRU2l6ZSA9IG1vZHVsZUJ1aWxkZXIubW9kdWxlcy5ibHMxMjM4MS5wcmVRU2l6ZTtcbiAgICBibHMxMjM4MXdhc20ubjhxID0gNDg7XG4gICAgYmxzMTIzODF3YXNtLm44ciA9IDMyO1xuICAgIGJsczEyMzgxd2FzbS5xID0gbW9kdWxlQnVpbGRlci5tb2R1bGVzLmJsczEyMzgxLnE7XG4gICAgYmxzMTIzODF3YXNtLnIgPSBtb2R1bGVCdWlsZGVyLm1vZHVsZXMuYmxzMTIzODEucjtcblxuXG4gICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgICBuYW1lOiBcImJsczEyMzgxXCIsXG4gICAgICAgIHdhc206IGJsczEyMzgxd2FzbSxcbiAgICAgICAgcTogZShcIjFhMDExMWVhMzk3ZmU2OWE0YjFiYTdiNjQzNGJhY2Q3NjQ3NzRiODRmMzg1MTJiZjY3MzBkMmEwZjZiMGY2MjQxZWFiZmZmZWIxNTNmZmZmYjlmZWZmZmZmZmZmYWFhYlwiLCAxNiksXG4gICAgICAgIHI6IGUoXCI3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxXCIsIDE2KSxcbiAgICAgICAgbjhxOiA0OCxcbiAgICAgICAgbjhyOiAzMixcbiAgICAgICAgY29mYWN0b3JHMTogZShcIjB4Mzk2YzhjMDA1NTU1ZTE1NjhjMDBhYWFiMDAwMGFhYWJcIiwgMTYpLFxuICAgICAgICBjb2ZhY3RvckcyOiBlKFwiMHg1ZDU0M2E5NTQxNGU3ZjEwOTFkNTA3OTI4NzZhMjAyY2Q5MWRlNDU0NzA4NWFiYWE2OGEyMDViMmU1YTdkZGZhNjI4ZjFjYjRkOWU4MmVmMjE1MzdlMjkzYTY2OTFhZTE2MTZlYzZlNzg2ZjBjNzBjZjFjMzhlMzFjNzIzOGU1XCIsIDE2KSxcbiAgICAgICAgc2luZ2xlVGhyZWFkOiBzaW5nbGVUaHJlYWQgPyB0cnVlIDogZmFsc2VcbiAgICB9O1xuXG4gICAgY29uc3QgY3VydmUgPSBhd2FpdCBidWlsZEVuZ2luZShwYXJhbXMpO1xuICAgIGN1cnZlLnRlcm1pbmF0ZSA9IGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCFwYXJhbXMuc2luZ2xlVGhyZWFkKSB7XG4gICAgICAgICAgICBnbG9iYWxUaGlzLmN1cnZlX2JsczEyMzgxID0gbnVsbDtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMudG0udGVybWluYXRlKCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgaWYgKCFzaW5nbGVUaHJlYWQpIHtcbiAgICAgICAgZ2xvYmFsVGhpcy5jdXJ2ZV9ibHMxMjM4MSA9IGN1cnZlO1xuICAgIH1cblxuICAgIHJldHVybiBjdXJ2ZTtcbn1cblxuY29uc3QgYmxzMTIzODFyID0gZShcIjczZWRhNzUzMjk5ZDdkNDgzMzM5ZDgwODA5YTFkODA1NTNiZGE0MDJmZmZlNWJmZWZmZmZmZmZmMDAwMDAwMDFcIiwgMTYpO1xuY29uc3QgYm4xMjhyID0gZShcIjIxODg4MjQyODcxODM5Mjc1MjIyMjQ2NDA1NzQ1MjU3Mjc1MDg4NTQ4MzY0NDAwNDE2MDM0MzQzNjk4MjA0MTg2NTc1ODA4NDk1NjE3XCIpO1xuXG5jb25zdCBibHMxMjM4MXEgPSBlKFwiMWEwMTExZWEzOTdmZTY5YTRiMWJhN2I2NDM0YmFjZDc2NDc3NGI4NGYzODUxMmJmNjczMGQyYTBmNmIwZjYyNDFlYWJmZmZlYjE1M2ZmZmZiOWZlZmZmZmZmZmZhYWFiXCIsIDE2KTtcbmNvbnN0IGJuMTI4cSA9IGUoXCIyMTg4ODI0Mjg3MTgzOTI3NTIyMjI0NjQwNTc0NTI1NzI3NTA4ODY5NjMxMTE1NzI5NzgyMzY2MjY4OTAzNzg5NDY0NTIyNjIwODU4M1wiKTtcblxuYXN5bmMgZnVuY3Rpb24gZ2V0Q3VydmVGcm9tUihyLCBzaW5nbGVUaHJlYWQsIHBsdWdpbnMpIHtcbiAgICBsZXQgY3VydmU7XG4gICAgaWYgKGVxKHIsIGJuMTI4cikpIHtcbiAgICAgICAgY3VydmUgPSBhd2FpdCBidWlsZEJuMTI4JDEoc2luZ2xlVGhyZWFkLCBwbHVnaW5zKTtcbiAgICB9IGVsc2UgaWYgKGVxKHIsIGJsczEyMzgxcikpIHtcbiAgICAgICAgY3VydmUgPSBhd2FpdCBidWlsZEJsczEyMzgxJDEoc2luZ2xlVGhyZWFkLCBwbHVnaW5zKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEN1cnZlIG5vdCBzdXBwb3J0ZWQ6ICR7dG9TdHJpbmcocil9YCk7XG4gICAgfVxuICAgIHJldHVybiBjdXJ2ZTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0Q3VydmVGcm9tUShxLCBzaW5nbGVUaHJlYWQsIHBsdWdpbnMpIHtcbiAgICBsZXQgY3VydmU7XG4gICAgaWYgKGVxKHEsIGJuMTI4cSkpIHtcbiAgICAgICAgY3VydmUgPSBhd2FpdCBidWlsZEJuMTI4JDEoc2luZ2xlVGhyZWFkLCBwbHVnaW5zKTtcbiAgICB9IGVsc2UgaWYgKGVxKHEsIGJsczEyMzgxcSkpIHtcbiAgICAgICAgY3VydmUgPSBhd2FpdCBidWlsZEJsczEyMzgxJDEoc2luZ2xlVGhyZWFkLCBwbHVnaW5zKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEN1cnZlIG5vdCBzdXBwb3J0ZWQ6ICR7dG9TdHJpbmcocSwgMTYpfWApO1xuICAgIH1cbiAgICByZXR1cm4gY3VydmU7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldEN1cnZlRnJvbU5hbWUobmFtZSwgc2luZ2xlVGhyZWFkLCBwbHVnaW5zKSB7XG4gICAgbGV0IGN1cnZlO1xuICAgIGNvbnN0IG5vcm1OYW1lID0gbm9ybWFsaXplTmFtZShuYW1lKTtcbiAgICBpZiAoW1wiQk4xMjhcIiwgXCJCTjI1NFwiLCBcIkFMVEJOMTI4XCJdLmluZGV4T2Yobm9ybU5hbWUpID49IDApIHtcbiAgICAgICAgY3VydmUgPSBhd2FpdCBidWlsZEJuMTI4JDEoc2luZ2xlVGhyZWFkLCBwbHVnaW5zKTtcbiAgICB9IGVsc2UgaWYgKFtcIkJMUzEyMzgxXCJdLmluZGV4T2Yobm9ybU5hbWUpID49IDApIHtcbiAgICAgICAgY3VydmUgPSBhd2FpdCBidWlsZEJsczEyMzgxJDEoc2luZ2xlVGhyZWFkLCBwbHVnaW5zKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEN1cnZlIG5vdCBzdXBwb3J0ZWQ6ICR7bmFtZX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIGN1cnZlO1xuXG4gICAgZnVuY3Rpb24gbm9ybWFsaXplTmFtZShuKSB7XG4gICAgICAgIHJldHVybiBuLnRvVXBwZXJDYXNlKCkubWF0Y2goL1tBLVphLXowLTldKy9nKS5qb2luKFwiXCIpO1xuICAgIH1cblxufVxuXG5jb25zdCBTY2FsYXI9X1NjYWxhcjtcbmNvbnN0IHV0aWxzJDYgPSBfdXRpbHM7XG5cbnZhciBibjEyOF93YXNtX2d6aXAkMSA9IHt9O1xuXG5ibjEyOF93YXNtX2d6aXAkMS5nemlwQ29kZSA9IFwiSDRzSUFBQUFBQUFBQSt4OUIzd1VSZnYvek41ZWNzbmVKWnVRQm9Td0YxcG9vWU5neTRBZ1ZSREVnbzBXSUFFQ2hGNGtvUjgxb1FrQ0FsSlBRWnFnSUFqWVQ0cEdRRVNsaXNKSmtkQTcrWCtlbWRtN3ZiS1g0TXZ2OTN2Zjk1K1FzRFBQdE9mNXpqTXpPN1BmdlVOZEJ2YkZDQ0U4QjBkMkZyS3lVR2RNLzNBV3hIQldaME9XNjRJNkc3SkdaNkhPUXRabzFGbk1vaEpqRnJ2U0tNN3FISnlWeFNWQmFpQTB5L1dqNXRka3hGbWRRMXpwT0t1ejVNNmRoYk9FY0d4SXpSZ1MxRGUxYjcvTTRRSXFhZmhjMkNVZ0xHQ0RRUlNOQ0FVRm00eUMwWWlRRVNHRUJBRmhveW5FYURTYVRDWVRFdlJUakNBU01KaHVNQmdRTXRLY1Jwb1h5ckZTUnZnSlJWSUkvSmxNQm1ReUNRaUZtTTFHb3htWkxDRW1Xb1hSaUZoQkF6SUpRb2pwSDlSczlLamFLMllNZ1IvRTJvS21CTllVYmNsdit6Um1NckUyTlQ5aVdMZ2NZUXordXNJYXdaU1dNZWpOYnYzNkQwZUlCa2VrWnZaRE9CaUMvVEpTa1NFVVFta0RPNEZZQ0lKSTZnQWswdlNlZzFLUmtZYTZkTytPZ21obzRPQ3VLSmlHK2c3dWcweTA5TUFCZzd0a3BxSVFpenZTdGs5M0ZFcXpkVThiZ2l4aHRKR01JYW1aQTFQYjlPdU93a3c5YXZWVnRZSWcweW9VZ2k1ZElFSjFnUUJvSU5NUWFCQkJReG1wUFZGa0dDdnpYR3JQTG9QU2hxU2lraUZNMERZakZZWFR1Z2VtOWN4QXBTUUk5bTJmMm4xd3QwR29CQzBQRmtUUk5ya0YwUlozQkN5SWlZUjRqOHgrZmR2MHl4alVzMS9mMU16aEtFNEc0YUIrR2xFc3JaemJoMHJUeWdIY2VOcCtuMzVkdXFNeTRiUlVXdC9VZ1IyNmRlblRKUk1sMEd5cHcvcWppclRHcmwwR2RldlZndGRSbG1rK0lITVFxbVJtQm5WZ09pWkZ1eksvb05WQmlYWEptM2txYkRYMXlIU0RuZWtHTzFNTGRxWUtkaVlEdXdvTkFkaFZhUWpBcmhiR3lyakFyaFBDQkFCMlpWbzNCYnV1QkVFVjdPcTBQSUNkVE52a1lOZXd1Q01BZHMxSWlIdUJYVnNHb1FmWXRXamxLdGoxYU9VQWRuM2FQZ1c3UVRndHBRSDdNWm9Od0U2aE5YcUEzWkJwRG1BVE16T0lnOTA0MnBYWkEreEdzUzY1RjlpUEIvWElaUGhCZ01JSEFZb2VCQUNHSmlHUXhGcDRKclJIcHN1WXBoYUl1T0Z0RnR3amszY2NoRmkvUVMzVTNoQ2FtZldmc1VjbTdUNXpUK2JYZzlMQTFnR1IydWliM1hvTnp1aU4rbnNJU1k4ZWFSbXBhSENjcjVEbkh4VGEwejBxbTh2dUNDLzZiRkJQTmxEYlNTelFKbTFZYW5mVTFzeGlQTmR6cHA3cWlHOGRwZ1o1V2l1YVJxMXJHYVlHZVZvTDJucjNmb083OWtsRjdXVjNoS2MvSDl5VHp3NGR6VHpFMm4vQndxTThZd2VhRWZyaEpRc1A4WlFYYVFwMFZTY3pEN0VxWHJId0tNLzRNa1hPeTBOZmkvTVY4dnl2VW5VOW5QZU5HRzhSei90NmVFK3YrV0ZJdEplRTV4eksxTytYMmJkTG43UVJxYWdiUmFoMTB6YUQrblZFcWU1SUU5U0RSam9PNnRlNmFSdlVrMGFhc0VndjJocjFYMTR3elV2U0JLVzdKYnlLM200SnI2ZVBtWm5EVlhzempFVmJkdW5XcjJ0YWx3elVKcUtuZTdMaW1icVcwTWhjT2Z0UzUwbkxhREk0YzBncTZoS2hpZkZ5bmVtWWV6TXpsWTZWZHFtWmZRY1A2aklvclY4R0drNEhkNDhlZzlCYmRDU25RWEEwbldzeXV3eUZ5RWlKNTJqWkx5MERaWVZwWWsySERVTFpPTUpUMGlKakNCckRac2dlUFFhMVNSdUd4bUl6anpWTHkralNCNDNEWlNEZVB6TzFmNWZNMU5aZGVtWjJ5ZWlaMm5SSWx6NkRtVkxqc2FsL3Z6N01xeWZnY0FoMzY1Y3hjRkRtNEc2RFdqZEJFN0Y1UUpmK2IzWWRuTmFuTzJuY0JFM0NFc1RUKzZWbFFOVEdrd0VsMHIwN21veERlOVIyamNJcE9JVEZZTjZkaWswUW9RMU53OEVRaHVsaE9oUFRFVGVEaVdIdXlXSGl2b1A3MUVLNXJGSStFODFrbVdBb3pXSkJHQkt6V1JER3pSeFdsTTd3QzdHRjFaNlJQcmhubDBHcGFDNk9CSUhYNEppSFpaQjZESUczY1JESVVnZWcrVmlpWnZEWjd4M1dGRXhjaTNFNExhY1pEZ3RZVlI0VDk3dGNJNWk1bDJBenc0UlAzVXR4R0l1N1p0TkYyTnl6dG1aMjNJc2p0WEUrM2UzeGxITG4rd0hIK1VwNWllOXhhRTkzM3l6RHNqdkdTNytIZzNveWt6L0FFZ3V4R2VaOXBwSnJsclJqVTArMTAxYmhNRFhNVTFleVZOclRLMWlxWnFaY3p0VGdVK1ZhcG9iSFhMa0dCL2ZrUGJ5ZU5leWFMZGRoQzQvenZCK3l2TkR2RzFtYWU4TGN3TkxBUFRhemVseFQ1a2NzcjN2TzNNVGc5UEtManhtY2ZtZk5MVXh6RDUvWmltTzhaVHozSnppOHA1ZW41T0ZvTHhIUCt5TTN4RFYxZnNZZzQxUGdMazJzQ2RyTlluenErNXpGK0xUM0JXdFVPMzkrNlMxcWdyN1NpSGcxWDJ0RXZLNXZHSUt1T1hRYjYxak5KTG9hUjdnS3VXYlJIYmlFUnVqSyt5M3pMM1VlM2M2S2VrNmtuMkxKdGJJMHkwUUhjQ3hFL1Uyc2h6QmRHbUVHUFlMcElrMm4xbDh3WFV2NDNIcVlWYWRPcnIvaU1FMFVadGZmY0lTbkJHYlhvNndPUHJzZXcyWWVZN1ByY1Z3RzR2cXo2d2xtcDJyRFNSd0xVWDgyL002Y0ZUUTl3OFlQdGVFczYxQnV3eCtzT3RVR0orc0RqUTEvTVNBOWJUakg2dUEybkdjZDZiTGhBaTREY1gwYkxqSmN1QTI4Yy81bURYa0tMN0gxaWEwRy9mdjNHZDRxZFRqS3grN0YxU1c4akdOOGhHeGtYdEY0a1N2N1ZUYXUvR1MvaGtONzFIZE5hamR3Q0l2QmduTVRteUJDcDZGYk9CakNzT0RjWm1JNmQ5MWhZbGh3N3JLSytDSnpqeVhBRkhTZkJXRVdlY0NDTU5rVXNGcm9JcE10UkVMWWErNFlLOGdnOVpnZnhnaEJJRXNkZ01ZSkV0V1VyeERqQlZvelRQYzJJWnlXMDh3VUUxaFZIbXZLSkNHTW1lcGFOeVlLb1QwR3VkZGVJWVRGNk5vcm1DREMxbDRoR01KMDdXVml0dll5TVYxN21aaXR2YXhTZGUxbG1lamF5NEowN1dWQnV2YXlvbXp0RlN5c2R0ZmFLMFNDd0h2dEZXU1FlcTY5UWhESVlPMFZKR3FHdXZheXB1amFLNFRUY3RxMWwxWGx1Zlp5amVqYUs1Z1pKdXJhSzRTeHVIdnRGYUs2WnRTcS9kaWJvR1hYMUl5MHdRUGJkT2xmRTczdlYxNExmZUJYWGh1dDhTdXZnOWI2bGRkRkgvcVYxMFByL01ycm8vVis1UTNRQnIveXg5Qkd2L0tHYUpNZ00zbi9MbW1aYVJrOW13Nm9oYmI1eUdxalQzMWtkZEIySDFsZHRNTkhWZzk5SmxnOFpHaW5FTTRGYk01NXRoWmE3aTJxalZhcVZmVk42OU1uTmJOMXYzNzlrVjBveVdROVlPcHFPcXgvdjR6VWpFRnBiSjdhS3NUckpzTEcvU08xRGZEc3hzTnIxcTZMVmdtUlhpTEl1RnFJNWRKdXc3djE2VGVvWDkrMGJ0eGp0dmhKYWpxcy81dERhNktQaGREN0p3eTdoQ3BJd1FxcWJFQU5ERHhrYW1Bd3NaRGN3Q0N6VUZ3RFE1eVVnQlRVbU9hakZ4Tzd5T3dTSjlWQk5HYzdNWVdXNVZjVHY2SjI0VWFDd2lYM2YvQkhxOFM2VlQ3THFsUndaVVBjODd4ZWlNZzhZb0tJaVVjUVJORHovcHA1UzFQUEMySUtRZUZHdCtCRk1ZVmdKbUNWYTNJd2dTWUhhMUdUZ3drME9aZ2FuY0lsK2dPdEg4SVlqMVpRUFFFcHVKNkFSbGtOaXFBWW5oSVF5RVNRaWFNVVEyUEY1a29SSWNVRUtTYXZGQk9rbUNIRjdKVmloaFFaVW1TdkZCbFNvaUFseWlzbENsTGlJQ1hPS3lVT1V1SWhKZDRySlo1R1YwdlRCQStyM21McGpRc0tDZ3JDeDNrWTl4YVVtRFRLSzRQR1J2OFpOS2I2ejZDeDJIOEdqZUgrTTJqczk1OUJBNFAvREJTTlNhdWxIRGtTank3OG42c2tCUzdSU0tGTERCb04xWW9jWjFIMURyR3hZZ081V29UbUZoTk5veUdQZ1NhUDBxWUQ0SW5CU3BCWHVxQ0lnRFpVRG5LUDJreUpvVjV0dTlLREZaTmVFblJjWW9qaVYyMlRmN1hOaVdZOXRZT1ZVTDJrRUNXUXNlWkV5Yit4WnYvR3lvbGgrc2FhOVpKQ0ZGMklwSUFReVlrVy94REovaUdLU3BUMUlRclRoMGdYV0VrZldFdEFZS01Tdy8wREcrVWYyTGpFU0gxZ1pYMWdkYnREMHU4T2kzNTNoQWZzanJqRUNQL2RFZWUvTytJVG8vUzdJMUsvTzNRN1VkTHZSSXQrSjRicmQySkV3RTZNVHl6aHZ4UGpmVG94V0luUzd5VGRycFgwdTlhaTM3WGgrbDBib2QrMUpYeTZsbmFkNHROMUlZcHVyMG42dldiUjc3VncvVjZMME8rMUVqNjlScUV2N3dPOXBBKzlSUi82Y0gzb0kvU2hMK0VEUFFVeHlRZEVpejZJNGZvZ1J1aURXTUlIUkFwSE5SODR3dlhoaU5DSG80UVBITlN3bWo2R1JlZ2JWc0xITUtwaVhSOFZTL2lvU0J0N1RHMk1GbnRDbWhacDFyc0phSXlzUW1NRVdYbWRqZkZFSzl4VTRJbUtvRGJ1Y1o4UVJFZXlvQmhjNlZnUjRCYkJZQlZadTBhZlNwVWdma1BnVmJJb2phcW9hRW9xUmxlell1SE5tdWhkeXNNMkc2em9LVnVJUnFiQ05USW5odWpWemU1MEhpMUc1c0kxa3VtOWw0NUdlc29HMHNpa2EwY2h5c3FGS3h1VktPa3JxMnVINlIvWkVWalpxTUtWamFNM216cks2dHBoMHJVamtMSWh1aVlXWWtkYzRYYkVKMXIwN2RBMTBhUnZZc2cvTWpHd0hmRUI3UWhXZEUwdzZac1FvbXRDSUQxRDlSMHhzQWxLUUJOTStpYUU2SnNRK285TUNLeG4rWUI2aHVqckdhcXJaeUJsSkgxSENxeG5Va0E5US9YMWxQNlJub0dWcVJaUUdVbFhtVUF0bXZYN1BiQXlOUU1xWS81SHlnUnVzVzZnRmdOVmE5SHZwc0F0UHFacFVjSHNiaWdVS2ZBUHl5YnBZMzRhaHBDQ1IvTkRKUVNuUlVoVTZBR0orNndKd1JrUk12bUk0V1FJbVgzRWNCNkVaQjh4bkFLaEtCOHhuUDJnT0I4eG5QaWdlQjl4dlBTY2dFZmpMQVhnTTFEbHVmV2dQRUJnRllRVVE0b2l0TE5neFVERWREV2Y0SlBQakNSSldpTUVBMDJVL2h0TmF4YkVGRVd3R28zRWdheEdTVEdJS1FDa2tUaVJWWlFVcElneVVqQkprcEZpbERHeFlSbVRzdFlnVXRZYURBMlRKQ1U0dlRwQ1NqQXhOTXUwWUNXWTRON1dZR2lMSmhGRDczb0lOY2FqckNiRjFCZy9MNlkwUm8xUmRpa0pDbFBOUlNXSVZoQkVnbWtGUVZCQkVGUkFrMGh3NzhvSVdVUGdVQ2JiR3FJRUtjRzlpZGpiR2tvTGh6VE96czdPN2ordW5SSkswSE1ETEZnSmFXeXlXVU9VVUlMVHJhRzBsaEE0Q2haSmtteHNhaEVhWTJzSVFkWlEwQzZFMkxFc0tTS3hZeVcwdHlMS3dhVVVveEthcm9USVpncldGa0Z5Z2VYeGp6aXcxVUFjZ0FXeVNzU0p3ZVdJRTh1STJBU3JTR3lDYkNESWFpWjJ3V3BTRUxFTE1pSU93UnBFbklJMW1EZ01YSDJUTEZpd1lsUk1ZSlpzVVlJVWtkZ01za21SeEJURkxLWVFtMEV4eUVZZVVFTGw0RklFV1MxR3hRQUNHc1ZXaTJSVWs0TjQzRldXeVZ4Rm9DcE5XWkJyYW9haWtxUVlyQ0dLYURVb29WWlJDYkdHS21hcnBGaXNac1ZvRFZGTVZxTVNiRFVwSWF5THFaNFkzRXdPTG1Xa1Z5VFJVVWZzb2l5R1M5WG84Rk1FT1FpOGpEalZuQkNreXJoa2tpVEZxcG1EM1FsQmtJQ0lRNlRET0VKYUZHSGd1NW5KMzc2eklveFBMUFE0V0JqTjV3ZXJ5QVIwSkJHbkFjSWkzVHdoemZtM08xWFVwdkx6WVhlcVNadktENGZkcVdadEtqOFpkcWZLMmxSK0xPeE9qZEttOGpOaGQycWNOcFVmQ0x0VDQ3V3A4Y1FXUk5PZUVwQ0toK2lOaDZpSGg0L0ZZa0NMVFFFdE5nZTBXQTVvY1ZSQWl6M3dpSWRVUlE4UHhZMkhxT0poOHNiRHBJZUhqOFZpUUl0TkFTMDJCN1JZRG1oeFZFQ0xQZkJRSUxXOEhoN2wzWGlZVkR6TTNuaVk5ZkR3c1ZnTWFMRXBvTVhtZ0JiTEFTMk9DbWl4Qng3bElUVkpENDhrTng1bUZRL1pHdzlaRHc4Zmk4V0FGcHNDV213T2FMRWMwT0tvZ0JaNzRKRUVxZFgwOEtqbXhrTlc4WWp5eGlOS0R3OGZpOFdBRnBzQ1dtd09hTEVjME9Lb2dCWjc0RkVOVW12cTRWSFRqVWVVaWtlY054NXhlbmo0V0N3R3ROZ1UwR0p6UUl2bGdCWkhCYlRZQTQrYWtGcFhENCs2Ymp6aVZEeml2ZkdJMThQRHgySXhvTVdtZ0JhYkExb3NCN1E0S3FERkhualVoZFRIOVBCNHpJMEhYWG9SVWRJVkxNdlN6ckxsaXZJNHR2Qi8vTzdHNlBYZ05vZzl1QTNXTzVFMnVyckU1QklTVkU5d0doSkRmQjVsZUo5U0I3SG52RkxBNTd5aDlLelVYenEwYzhHUUdPQVJuMXM3YzZBSGlkNG4zMEhzaVhHNG50SHN5RVAvaVhHWW9vdVhSZmVwRUZpVGIwaU0wSCsyNTdaRzFqNjM4bjRrNEJkbGMySUpQWkJDbFhDOXBEQWxVTitZRXlOMSt5YlFreWI5eDBtQXdUVkRZblJSZWpRcTBMTXd2ejBxSjhicTkyZ0p2YVF3UmRjUElnUDZnWndZRThnUEFqei8wWDNtRlIzUWUyNFpFa3NXeFh2aXRONFRWeFR2aVVvc3JlODlzZnJlbyt0emtmbytGeFBRNTZJU1N3WHl1VGg5bjlOOUlCYXQ3NmtsQTNycVBVTmltYUo0YXJ6V1UrT0w0cWx4aVdYMVBiVzB2cWZxK25la3ZuL0g2UHQzcVlEK0haZVlFTWkvNC9YOTI5dm5OUDZ0T3lwSzZvK0tNZ0ZIUmJhWWFDM0txRkMwbzBJcHlxaUlUeXluUHlySzZvOEszYkVVcVQrV1l2VEhVaW45c1pRUWNDekZKeVlHR2t1Sy9sanlkbUxOV05JZGdTWDFSMkFaL1JGb0RUZ0N4NHVKRllveUFzdHJSMkQ1UWtaZ3FGSk9mNFRwanN0SS9YRVpvejh1UyttUHl3VDljWm1vUHk0dDFEeWRjZWZ0MVpweHB6dGFTK3FQMWpMNm85V3FQMW9yK0NkbitMSUF3eFRkNFJXcFA3eGk5SWRYS2YzaGxhQS92QkwxaDFlRWp5OXBCb0x1OENtcFAzeks2QThmcS83d3FlQXpmSFNZa0pINm5oMmo3OW1sOUQwN1FkK3pFL1U5TzFyZlIwdnErMmdaZlIrMTZ2dG9CZjhrRmwveVpveSt0NVhTOTdZRWZXOUwxUGUya3ZwK1UwYmZiNno2ZmxQQngyOTA2S0dsOUQwZ1FkOERFdlU5b0l4K1gxcjErN0tDVDEvcThFVVQ5SHNsVWI5WHJQcjRWdkRCVjRmdm1haVBWQVVmbXozcGxTcjVjSFVSbmtCc3Q1YjVsL2ZzUVEvUHN3cEFRQXJTN09oVm9jZU9YbHNxTUNPQzdkOGY1Wk5lclVJWERJbG1mU0tRMnd3cEVOMmlVQU5NdXRTVVI4M1EwRHdkMTZNajhET0M4S0tZSGFZMU8reGh6VFpUanJZT3grS1JQcnpYbU8ydHBTc3BQQ0FpMXd5SmtVVkJKRUtMU01URElpTFRFeFFkUlBUQWV0UzhBdzFZM2dab3dOTEZNVElnanJmVWs1ZENjSXpTNGhqMXNEaEdKY2JvNDZnTHNlVWZRVndVSEwwTjBPQ29DM0drUHNUUkFTRytaMGlNS3dyRXNWcUlZeDhXNHJqRWt2b1E2Nkp2MFVVL0VNU3lic2NVQ1gxdjJ6VG82M1pNcEg3SFJPdDNURnpBanNrV0Uwc1hwV05LYVR1bTFNTjJUSHhpdkg3SDZQYVpSYi9QNUgvVVowWHBHRy9iTkIyajIyZVIrbjBXcmQ5bmNmcDlWanBnbjQwWEV4T0swbWRsdEgxVzVpSDZMRlRSN1M2TGZuZkp1dDBWcUU5SzZNOTlSZWt1YjdNMDNhWGJrNUg2UFJtdDM1TngrajFaV3I4bkUzeDZzZ2pFZm9zKy9ySSsvaVgrRWY2Rmd4eXVEM0trUHNqUitpREg2WU5jV2gva0JCK1FpL0N1Z3F5UFpBbGRKQVBCRmFNL0p4V09aS1Era3RINlNNYnBJMWxhSDhrRUh5U0w4Q0pGQ1gyNFl2NFJYSVZqRXEyUFNadytKcVgxTVVud3dhUUk3MnZFNkJvZXlMcVMrb094Y01QajlBMHZyVzk0Z28vaFJYakJvK1Evc3E1d0UwcnJtNURnWTBMaDczWUVVaVplM3pNTDF6UEJSMCtmRnpRWWp6bGVNY0xoQllhRENrd1BMN0I2ZU9HU1NaS2I3QndsU2NEQXRJazBIRTNEb1RJaTlsQWc4SVlxV0M0aFJZRFVFU3JIRVVjb3NSbGxvMVFlS1VnVzZDY01TQW9pVGtoenNqUXhoV1NGU3dTSGM0cW1IS2MySEtaZ0JjdXhVZ2dRUGhVa0kya3ZGbFdXckNMSW1DaFdJNUNYQmFDN0doWGNDdml1UkdrRy9GUkpqamNTbTBSc0lvU2pKR0NtU3NRdXlWR0tRT3lTSXNpeVlpQUtVSnFOY0RGU3lpa21TbjhBcUttWUVrNXpBd2MzaU5ZZnBJak5nRUdzR0tvajFBalpvVVlNeFlQZ3dqakZlbzBUdStUVHVoUlArYWpFSWNsbGlFT0NheXpBSmlrR09VcTY1YmFVb0NRQldZMEVLWEN3aE5PSjBpZTl2Z0NNNlhnRldZTzQrZ1JaVFZSUGt5SlFQUUZ1U091dEdHVmtWSUxVY0pRRWo3VFNYUVVWRStodm92b0hLVUNQcGptdGxIRkxjRzlGN0pOdURWYU1pbEV1elJwbzZxNmVacFdSRWl4akZpWk9DY2pjdkRrNVNqRVNwNlFFODFhaDhtQkY3QTMxc1RaTVFNaW1qWU45OVFVa1BXWGdIWXpndEkwYXhqcllvR0F3VEZTTWNxd2lndTZpYWdMckNVcXJMa3J4dUgrdGVLUis4VFp1LzBRd3dxeEJpc0VhVEpCVkZCZ2RuZmFOa1RLeVpiVjhFRnlDbEdDNEJDc2kxQ1krZEcwUmo3UzJxRUpyMnlRSWJCZzJCZGEzSEUvSHRjMHNJNGdvZ2xvcGRLOElNdzNROEtsUEdlUm94VWl5Y1Z2cW50bVllaHF4bWFuYnU5SjNJNWErRy9sUFY5cHk3L2FiS3JOVTJYK3FpYVdhL0tlS0xGWDBueXF3Vk1GL0tqZkt5eWF4cVFWVHpJNWpsM2ZSNFlObERET2ZWU0FPSTdFRGRvallqVVFoRHJOY0VhWkpDRHZOY2tYQWtqak1sUGR1d1JDeVdlUm9ncGx2RXB0RlRiRlphSXJHSlluZFRPd1dHY0hCZFcvYUc2eGptbG93c1ZzZ0tacjNFcDBCREZhQmlzMXlORzNRRExwRUVTZFVBcXBFMFRxZFpybWttRUtjWmdYTGtVWjJoZExxTEkvWkxDK0NLUmE1SW5Fd0JUbDVQOHdmZWQvaVBqcTNxRWZuRmozeXZrVkQzZytqaTBaVkRYa2Zsc0Fpa2ZjdEFjbjdsb0RrZlV0QThyNGxJSG5mRXBDOGJ3bEkzcmNFSk85YmZNbjdNaWNURm9HODc0MkhqOFVCeVB2ZWVQaFlISUM4NzQySGo4VUJ5UHZlZUhnU1FyM3hVTng0RklHODc0MkhqOFVCeVB2ZWVQaFlISUM4NzQySGo4VUJ5UHZlZUhoU1lMM3hLTy9Hb3dqa2ZXODhmQ3dPUU43M3hzUEg0Z0RrZlc4OGZDd09RTjczeHNPVDlPdU5SNUlianlLUTk3M3g4TEU0QUhuZkd3OGZpd09ROTczeDhMRTRBSG5mR3c5UG1yTTNIdFhjZUJTQnZPK05oNC9GQWNqNzNuajRXQnlBdk8rTmg0L0ZBY2o3M25oNEVydTk4YWpweHFNSTVIMXZQSHdzRGtEZTk4YkR4K0lBNUgxdlBId3NEa0RlOThiRGs4cnVqVWRkTng1RklPOTc0K0ZqY1FEeXZqY2VQaFlISU85NzQrRmpjUUR5dmpjZW51UjliendlYytOQmwxNU8zcS95Q01uNzdPN21rWkgzTGY5TDVIM0xmeFY1MzFKTTNyOW1LU2J2LzBQeXZxV1l2UCsvU3Q2M0ZKUDMvd1BJKzJIRjVQMy9XdkorV0RGNXY1aTg3elZRaXNuN3hlVDlZdkorTVhuLzM0VzhIL0FKeEw5RzNpK2dlL2IvSmZLKzVkK052Ry81LzVPOGJ5a203M3NpY3MxU1RONzNBT3Vma3ZjdHhlUjlEeHovQjhqN2xtTHl2Z2Y2L3piay9iQmk4cjVIeC93bmtQZkRpc243YW5jVmsvYzFTQmFUOTR2SisyNjRpc243V3NPTHlmdkY1SDB2WlFLUjl5MXU4cjVGSmU5YmZNajd5Wnk4SDBiRGpMd2ZCZVQ5S0NEdlJ5bFlyczdKKzFGeWJlS0lJclp3UCtSOVNIT3lOQi95Zm0yMVlVYmVyMFhKKzJFUFM5NlBsdXNiaVMyYTJNSWduRXpKKzlIRUhpMG5BMzArV2hIa0tvV1Q5Nk1Ea1BlakE1RDN2UnNuOW1pZjFsM2svV2k1QVhGRXc3VVd3QmF0R09Ua29wSDM2LzhUOG43eVB5ZnYxeE9LUU42UDFwTDNrNEc4SDYwRTgxWWZGWG0vMXIvR3ZxLzlyeFd2OW1qSSsxVWVLZDIrNmlPdExmbGh5ZnYxR1hrL2hwTDM2d2NtNzlmd1I5NlBvVzd2U3ZjaDczdWxlNUgzdlZLOXlQdGVxVjdrZmE5VUwvSytWNm9YZWQ4cjFZdTh6MU1MSWUvSEEzay9uTmhqR0hrL0hCanZNWElLVEpNUWRzYkk5SXNJaUNPRzh0NkJ2QjlEYkxGeURUZDVQMVpOc2NYU0ZBL3lmZ3l4eCtxUTkyTWhxWVlQZVQ4V2xLbEJHNHdCWFpLSkV5b0JWWklaZVQ5R3JnUGsvUmdGeTlXTTdPcUh2QjhHcHNUS0tjVEJGS1RMQmN6dXNWQmxMQ3dpZ3B6c1hsdWFzTFdGVGY1U0NGMWJZUFVJby9WU0pwd3NER0N2QU94RzZiSWdXU0FGc3hSTXExZGo4VHdQbHRvWCthdDhXVWhwWUZCWUtLbUJJWW1GYWpZdzFHU2h4eG9ZSHBOR1BQSXFXU2lsZ1NHRmhabzNNRFJub1hZTkRPMVk2T1VHaHBlbEpMRHhXZW84TFdHdEJodmpPVWtRN0daSUlrbUt3K0JuQ3BaRlRhbzRJRndhVEJPZ29GVlFrTnljMXZWc3VBVC84eFZha01QaHk0TVZMRDhITVdLUGs2TVZUT3h4eEJISDNqK0xJMDRJUWFYRUdVZHNKZVVvV0x6aVpCRUtndFJXRXNMZ0N2VGJmamRqTmwrb0RWUE5nZlBJRldoT0ZXanVvUUJXa053MkhONW1VOVZweTlRcFNkOVBjY0FGRVVkSjRpeEpkYkdYSkxaU1RMK1N4QTRoeUVRY3BhaHlTanB4bENMT1VxcmE5bExFVmhwZVRLR2xRRmNubFdpMWRtSVZibWk5RFhWcmUybmFMRlJYR2w1eEtVMmNUT0lvVFd6eHNreHM4WENOaHF1ZGlpSWc2SFFIV1FZWlV1R1hCdVBWSU9zdDNtWFF1NUNvWU5vQk5naEV1QUpRcDdNMGNVQUZqbmoyNnhtRWZLem5JN2pSOFN6S01YRHdhSVEwR1Y1ZG9YMEJscmFtbGtMckt2TFBoN014SGE4YWJ5c0RKcFloOWpKVVlpdERIR1dnY1hxTmhxc3pIb0lSRUxTWGNRVWRQS016bnY3U1lCbHQwSmJBbTJBYUVIdUNITVZLd1dkWUUxc0N2UzJNZ0RxaDJnUm9OSUg5ZWdYTGVCbnZMT05wZkFKUEpmWUVZazlRNFphV0MrNFJZbEJIbXlMSXJSU0JEVGQxckNqSVMwcUhHeDhBZk1EeHNzK0h3OTBsQUpqQXRXRW8yc3RDTnlZUVcxbEFzeXo4T3NxQzdtWFpMMENTQUVGbldUbUsyTXZDcjAyaFhnTHBpaHhGYkFxeEs0QzRBcjlPQlJ4R0ljNnlpaUJId0FOSWhRWm9hODZ5eEdhRklsYjJDdzBwaXFBSURDU0I5cXZDb2xFOGF1V3BvSWN6Z1JzclM5a0dUNUNhQndTcHRYWVVLNExjQWVMRWJtWFRpcFU0ckhTdzJxM0VhWFZOSzFaaVMyVFRpbFV6clNSNllFb2NWaGlTaVRDd0VybVJFTEVuRWtjaWdBSlhZaXNIamxPTy9RSStJQ0wyY2pENkUrSFhVWTVDQ3VubHdkdktFV2M1NkpEeThHc3ZENzBBK1Rtazl2SnVTTzNsaUlNV0tjOStvYUh5WHBBNnlubEE2aWl2cGhxSVBWRkZsRjE1TEpwZGlkM0tCUkZjNEZEelIwZzdETm9aMWNCblZGSFRGNjNWT2RXckR6Q052eEF1S2FLbVQxNmdmZUlzVDkvbXMxVmdvN29Dc1ZlZ0hlSXNUeHdWYUNjNXl4TW5oQ0FUc1ZWVTUxWmJSV0t2Nk9xN0NzUlJFUnkyQXBTQ0dkVmVFU1FpMTZVOTdUcW9uRGdyd3J3QWhZbXRFcmhaUmZpMVY0SnVxZ1RYYUJZbmprcmd1WlhnMTBsVEs5QU1TZENKbFlndFNZNG05aVQ0ZFNSQkp5UVJSeVhlWDQ0a0NGQVZLaEVuTFpERWZxR2FKSy9lY2xieTZDMW5rcXUzNEI0NVFHYzV5M3QxbHEyQ2w4QlprUXVpcENpK1VHdm1pa2dwMFkrUTlTK2ZuSkFVQ1RkUXRzcnlpOUE3bFdFb01aR1RpWndnZW9HSkhGWGtsMkQwVkZFRXVhUGFZSnltN2ppMVFRK2hSNE54YXJsWVRaWll0WnlIMEtOY3JOUUt1ZFoyUGd0am96cWpWNVZMRTN0VjRxZ0tmUVpYNHF6S1JucFYrRXdBUG82cjh0bGFrbW9oN21QVnFGZmExUXVFb3VCcWk0T2dUR3hVSklaTDRmUUlvcHI4SnZ6WE9WeGFoNDJhcjhlaU8yb0RRYkNyVTdmVFRMV1RNQllNUkpITDBoMmd3V3BVNEd1eEVQczJNU1dZN1FLTjlQWTlTTVowZjBUM3ZuUlBTR3pWNGIxbnhRaXY4c0xYZzlHM29HM1ZXVFo0ajVlY3BHTTBpSTVWMXhZOEdHN1hnL2t1MkFDNzROWnU5RnE2WUtzT3NGVW5qdW9BRzF5SnN6cURyYm9HdHVydVJZNU94SkwwT04rcUtUZ2Q3dlFOaXJybk15aENjL2hlTmtXa1p4b0k5ZzJRcnRublZYSGZiN1pnZTd4aytWVmlTeWFLZ3VYdXhFNEQwRjUzMEYzTmltbmpqUkE3N25Fa3crYzQ4Q0xzOXJ3VXlXcEdaeUpjSFNHU2pUTWJJU1JKTlpDQ0lMNGJEZEMwcUJCbk1pOUhGR0tySVhjbnptUUZ5NjlMbTlTYlN0aGNDblJzdVFzS0pCc1BBR09Kb3daOHZWa05SU0JQRDJpRUlFZ1VZb2Q2N0RXb0YyUElFazB2RUlxQ3F5ME9naklYVllLcnZZWWNDUkd1dkVGTWdWclpiYmZSRll5VWpCNUprZTRrQURTbENDY01xWXJJSjNNanZYcWNNVHhkaEFwNmFDcndQcU1vaWdJOUF5blEzbFdCZ2dudURRT0lFcU5vWkRmcWsrNi96bDR3UkhyektudDdWdm1DVjVXMEZsZWRKM1hyYkVQMVpKV2U5SzZVTU9mQXhOUkhFWG96SmxoTHVMbFh4RUYwajI0a1dER3dJTnk3Q2NRd0pEMEp2bytRQkE4WW9oZ0hTSE0xNTQyWTRHYjBWQkJUcFFiQjVvbStzeVV3L1VRNnVIdGJqVnhIWXpNMnNoU0QzSkZPQmthNW8yS2c0OStnemdObXRtbUcrdVIrOUdMRnREaHVTbzlpakhKN0x1VTVqUXFTTzByN2NLaS9iLzFUREUzcHJOU1NLbWtjWkxXd2lTNk1JQ1ZNc1ZBMTZ3c0l2dmlQTm1KV0xLQmptR0ttU1hKTHhRemdtVmxiMWxBRlcwM3MyL1A2cEZ0RCtPRmlDQlF4QWZGTk1jb1oxbkFGYmlEQ2xIQlhQOG1LREN3WnVhTUUyZEt0SmlXVUdzdSs3REJNTWNyOWxEQWxTRzROV3NGVXR4U2IvWCtMSWM1U1JMa2x0UXB1VFhwV1I0NmFNQjhUMm1lS01ZTWV2Tkl2WkZTTWZmaFhGb1lTQkZPYUtEZHZDbnRKbDZsRzVqS2kzRjVqcGNSdWZlQUxCdUdnc29iY1h4R0pzNFlpeWgxQjBwc3AvUi9tU0FQL0F4MHBNNEFqdmFCeHBOMGVqalR3bnp0U3JmOVJSNm9wRHdKSHF1bnRTR3ZFWUMrOStQRnBTN3BlR1FiQkxBZElpNHBvRFNXSTNsUW94blF5YkFEZ0RVZTJtQ0JpR0VKR0RVaFBnaDRnWlFjTUlYZ0FQY2NONGM4cHFJWndhK0xLcHdTcCtVd0tmUDZGU1V4UlFxaFZ3UVN6YnlPRjFaOTlLYWxSSXk3UXlDV2pWNWtDbjBMSXV5NUpNdnBwREduTFlWYzU1Tk9XM3pSdFU5b2k4UHpDL1NnbW1MWHFwYVpuRVMrN3ZWUTM4dks2QlNRSkFyMnRvWERmWFV0dURmM0l4NnhCYnErRXdrMkppWnB2b2tNZTlrNjFZQlFiMVZBbitpV3lvZEJmckNaK0N5aUNPeGM3eTMrcnN6aHF5NjJLNEN5TzJvcEJmc0dvaGw0SjVDeU5ZUU5UZ0FkVVI3WjJKRzZRZ29ocGlDc3VENExUSnRrdE1FR0dPRmM4UFYzQlE2V2UyaDBTVnZBZ3E2QzU1YUlQaDJDREFIZDc4QndIeThQZ3NBRzhyZy9NbmdaRmJFR2ZmdGdPSUJtQlo4RzNEUjlBU3BDTUpPMXQyYS9ZMTY4VmcxeDVnTG9vRHFKTElEd1hoRDZGNEJDK0dBWXJ4clpValdEYWFBZzBEOSszREpGUStrM1JCcmt5OUNXeFV5VkNsUkI0TkgwQUthSHdETlF0TmlnaGNqSk5nTzhXVG9ZN2RpaG9WRUpZRXMwQ0NaSm1iNmJtZ1VKSVRvWlZsTGZzeW4wV2gvaFpmR0NyUEp4WkZrS3c2M2tiUEsrbTl4RFdZR0tydzRFTUpZZ2JhMVJDMnNMRG5nTklyZzlhRExHYU5BK2pUUXdJSTN3Rk5aU1RGRWt4MFpCWk1VTWg0andBU2tyRWRoQkJUeHlrRWtXU3E3akNacmtxNUZSQ2FTUEpIayt5bFdEMW1iaDdNNmd1Y3ZJSXFZbDY5b1NIVURkaGR4c0MzRzBJVkFhM0crbnE3UWExL1ZreEJjRVQ5dmhXTENERnd3a2lsa2ZCSTZlRFlDVGNBaUVhSGlsWitUMFhTMjRFWnpCOTB2bHRFbFlNOGtocGlMcG5NQkFITmRHOVNlZk9Hc3lkRmZNUUxQRU9zUDBnb2s4NGJZY29Nb2VvUkRFQ01qd2NCTWdjQk9kMjBMeHVKNURHYTU3TU96NVhmU0FFenZJT01TMDhuc01qM2l0QkN1YWhZSGpDU2h5SGtGeEZDVlpDNk5OV2VDd09UNFNEb1JLUVFEcU1IQm9YYWRYSm1pZjEwbUtQOHd5TkhzVHBjUHVsZ1RpTHFsTXdaQ1cybjVnZjJINUM5Smx5c0JMSzlRdFJndVJrS2c4Q2RKUWdKWlJLbkZRL3A3ZCtYL2tiQ0FRckFoL2NRMmkzQ0VNWS9hS1BOUWhHQU90anliVTZoU2lHWnZDWThpY2sxNGN2UldmM1pXekpRa3FJSXZaUlF0TlYvWlVndUVVMFFXN2krSWwxbXZNbnNON0pKQUN3SzJ5U3EwSk9SYUsxSjN0OEh6c0VRNmdWSXozdTJvZlFGUlVQb0dlWVFkQ3VJcWdoSUhtNEIyNFFINXd1bjhYMDFsTGRLc014b3Uwd05FdmZJQUpjRDhOemN5aUIrYkNUNWhleGgrMkhpK3gxSWNSeG1BSGpPSXhvdUNyM3ZLb1FZejBLUG5pWStTQmNSZHFBUjk4bTg3SFBMWVBhQmUwcVlaQXhwOWJRN0ROd2tJY1R3QTBMOEZZd0g2NmNlQkFFdHpJaFNoQVIwK21CbTJzU1pOc2ZTS1pObVhnVzZISGlCTjNnZjhXa21PUXFLbDNCRGFNZjVvSkRNUGx1ZUt5U0lsck5pb0hQRkJiYXVNVDJOWktNRmJPTUZRbXFraFF6WE54N0c0Q2dtcXRJS0NzU21pU1k2QWJHMUFMK1UwTFMyMmJTKzROcTRHVllnZ3pJR3FhRUVVVFhlbXVFVVFsajY3NElZVmRHbWxPRTNaRVMxQUwrVTRLOXE0b0FNWE90Q0VXQTVtaEVDU1htZEdMN0dUb3ZBcTVLaEZ4RkxjWWU5VE9iamVCR2Z1MVd6TENxZWRxdGhNS0ZiV2RTTlI3cTRwUUlnTGJWNUxwWENOSDJJeEJLN0tBUy9LOEV3ekQwenpReHdZVzVXMnN0YjBWVU1OeDlXSVBvUWtBZG16dFJNRDhUVW9Ma0tsNEVIVlkxcmN5TFNnREh4SEs0R2czMzRoUFFXTHdhODNOaWo2VEJqTkhnK0JueDgxZisvSVBGK2FuMUVTVEwvRkVrc1VNRVJCQ2lTVkdRV3hIZ2FCR3U4TUd1RUdKU2FJVm1wMEgrSkVLS1V6L01VRzJUUDdHUStpTzFVY2NSalFaT3FnRlQ1aGRFbnluWWZxRi8wQmJvQWxMNDN4V1RvUkRrb0NmTEdHVDBxU3VrTzQ0Z1pyOHNsVlkxa2QzV2M2M2RhUkhlYVJFcW1KRWVqei84UGhQeCsvekI3OE1NeGk3eDRqdElyOU1uQWI4ZzlibTFFNEx3UDdIOUNrWTdXSWpHSW1qSS9pdVNTeXYwNmo1V3B4SDN3Mk5WdTNqa3VpbEtjUFVGbmYza0JLa1VlMFFLeDkxV3JHQTRtWVlEYmJsVXVGUVNjYWVEeFVRdXljNjUweUdRSStnei8zWWpsZm8zSFhQdUh6MmQ5U1gvVGNFcWZVb3h5ak13SStTeFdBN1dNQURaNGE0L0NpQS9vL1htQUw2RHRTUkExZ3pMTGMvQVNyQThEZk1vY2Z5S1FPUnFXczRCZHFialYxaGJ1QTRlZkVEV29DOGg4SHRQcHRsMFJpNnkvVVpyaDNoZ3R0bE03STl1OWh1c3Q2Q0ZLNHNQNDh3M2l4ZnB6RGVERisvTU40TVg5Y3czZ3hmN3pEZURGd0hOTjRNWEI4MlZ3Y1ZDMjQ4UmNSeEQ4blFNRnhxY0ExT2U0emQ0MUdJN2l1VEZHQzdFY1JSQmxUUkFJem1ZQm0zSGtEd1h3OFVWemVIUlkwaWVqK0gySGlxQVhqcnVLcVdtMFFBbXptTklqcWNLMkk3RE1NdkJSdUk0enJRNnpwczhqdVJaTE9xa3VvRmdNUk9vaFNRcERSSG5TVnJPZVpJRnFUVzJFMURDZm9LV3NKOUF4SG1DVytQa2tSeE1nL2FUMUJyN1NlU0s1dkRvU2E0eFl2eGtvRFhMVXpBbnhrekJBeGhkTFJ0REJENnpHc25UMU5ScG1BNXh0d0FHTE0wNkRVdkw4UDhaZjR5Rk9qY3dkR2FoWGcwTXZWaW9md05EZnhZYTFzQXdUQm9yL052cnlFTFp1SUVoRzdPd0RUY3cySGc0RnpjdzVQTHdmTnpBTUorSGwrSUdocVU4Yk1jTkRIWWUzb0FiR0RidzhGYmN3TEFWMDhlUjhudDAzcFpYWUdEYlFRZE94eDVQdW1kZ3V1ck13QkxiMEVKa3ZtZVcrWGhBdURRVnM5VWdHelBlM1RKVzczdVlralRld3k3bTIxVE1LVmQyVEEvNm5LZW80MklJRVB2djRKNU1TcHdzZ2htMzRIZEU3S2VwZ0dXYlQrdGhUNDVQYzA5V2VXMi91Tmg0VEIxcUdlWHhjTFdXTWJXV2Vha0ZqTHozTVNXU3VOUjhuNnQ1bXFwcElQWS8rRUN6LzRHSTh3K3Vvdk0wSXZZL1ZlVlBJK0prRVpxZjJNOXd4YW0yWnhCeG50R2E5aWNpOXJOc3hQN0JxcUhXT004d3VZZHBhd1ZYcjRGMnF6a1g5U3hYaWpiZ2hBaGNpTk9wS3V0RXhQNFhuWERzZjdIZ1RCWjBubVhSMlR6cTlJaXFtV2RobXBIKzhlaGYyaWgzQ05VdHdKRllIZ1d6M3JYVDRHeHRrTFpGMnp2SEZEdUgxRDkvVVNqRlBXNjJDem9RVXBFTFRmczU1TW9sSGFKb0xWUFJXc1hRQXUxYy9ic0djK3JmT1MyRTV4ays1eEZ4bmxjaFBJK0kvUUxUNVFJTHptUkI1emtXbmMyajV6MmlhbWJBNHh6TDdPVFJDejVSKzBXM0ZreFQ0cnpJcG14V2pZS3BBaGNwR0JURTg3ekZ2NWxxZnlQMXoxLzBnajhRTC9pQytMY2JSRkFBL2x6ZEtsMFEzR1BkNEpwREZFRmVpU2t0SVozZHhXRFZUYjBUMkJ5aURsL1hMTUlyV1lOZFpNSy9rVXRMM2pIT1N4UlhKNWgwaVhYQUpjVCs4cG1GK1VqOW81ait6YUxPZkRhK0xpSDZaNy9NblpabXZjSUF2b3lJOHpLcjh3cVZFdWNWVnNsbFdvRWlnRFlDU0ZtUXF3UlZYR1ZWWEVYcUg5WGxDdDN3cUdoenp0dGx4RVU1THRGVjVNcEZOWGIralRoZXM3QjAxT0NKOXJKQzBWN2xPWVVwZ3Z3aFp1eTNxK3BjQzBwZTR6TVVSSnpYdEJQU05VVHMxOVc1OXByblhIc2RlWFVWNUlET3VzNDgvcnJLTlhMZVlGMTFIUkg3RFFickRjVCtiako0YmlMMWo2SjhuVVdkTjFsWDNVRDB6MzVMN1NySWVwdmhmQXNSNXkxVzUyMHFKYzdickpKYnRBSlhWOTMyN0NxbzRnNnI0ZzVTLzZndXQvMTExUzNmcnJyajdpcUE3cnE3bzFpQVIyZnlLSURMUmJOVmtmMkdXeVN0RkxWTGxZRXZWYUsybjFlNUZ5dWY3bVZjeDNXWWtoMDFIYjZPZC9nZDJ1RWlzZDlWWjdHN2lEanZxcXNXQUhCUGRZTTdpRGhaaE9Zbjl2dmFWZXMrSXM3N1dpZTVoNGo5QWV1cXU2d2F0bXJkWi9MNXFycHJtWlBjbyswUzV3UG1KZzhReTFuQW5PUUJZbjhGckJjTFdIQW1WcVhFbm8xcHR4WFFNc1NaVGVkQldpTkV4OUJVWnpZbTlqR1lsaHZEL3V4ajJZUUp3V3lzK29WOUxBc3lIYkl4Y1k1bEZZeDEvZEhxeDJCZnIzQm1ZMit2Y0k3RkdxK2dCNkFCZmVLT3IwL2M5UkU1SDZpaUhNeVBST2pkbUdiT25JT2xTam9KektING5EMERTekV3Zjl2SFlYa0Q5WUp4YkZaZ1l1ZDRMbmFPWjc3RGMwL0U4a2FhZXlLSTE3dTBtT2ZaMkR5WEZqNEpIbHJNYzFYd3RtZSt0MTBWK0NSNFZQQTJsdDVBN3B1NGFlcEtObzFTTHlsbWs3RDhEb1lMc2R1WUg3QWdjZG93bjgvZ0R0cnQxMDRiZGkxK2twU2lUbDcyeVpodnB6UUJHc21oRjJJL3hkTEF0M2pLZkJ3dWxhQXZPVTNCOGpaTUw1L2ljR21uUGpsVFBmRmcydS9HbEoyNUc4bnY0c0Q4VEhvd0VRUUlCTGtRTURKU0c3RlBwZWJCYVFic21DbFBrNTVOMktlcTJlbUdtZXpHakt1WjdYRlk0a3ZXMUdLK3dnMzFWQWIxVkV6czB4alVMRWljMDFTb3AzbENQUTFyN3pQWXl2V3YwVGZyYWJZd3k5bk5uWDA2bHJkZ3VKRGQ0Rkk3TVhIeU1HMTdKNVphYWtwTjgrUnkybWVBRjhORkxjMDN1QXV4WDBwblF5OUtKMWRpTnlMT0dlN1NFTGZuTUYxbUFDYWZZUGNleFp2Y3VSeDdzRHZ0dVRDNjRlSWllTnB6TVcyQjF3aG93bENobWZqZGRpNkw1UERnS1ZiUExIZktFaGFFT3VZd2lXb2hrRHVoTlhYL1o5VEU1bURPL3RTS2pCN1pnVkJXQkFybUxsaGwyRkpucEZkUGJtTVJhdGl0cmNHSHhWbVVHajRQcUVQSGdLVE5iS3hIMnZ3Q2ExaWI2b21jYnEyMEhqZTlWTGZXMVV4WFRqRDFydlZmcC9BdEtCcUZiemZtRkQ2cWdpK0ZiejNtSEw3MWRDYkRqTVMzRzN1UitMN0RmbGw4YTdFdmpXODlsZzRFNXZHdHdEcEVQbEJXaDhnSFNmSUsvTkJNUGdmMnBQSlJQRlFxMzNxczVmSmhMWmZ2TzB6SmZLdXd5dWF6QjJUenJjQmFPcDk5Rmk0Nm4yOFoxaUgwcmNYNmpMNWNMTzhCQjNQbVFoWHI4YU9saC83dit0YisvMVRmMmhmSXQ5WnBmU3ZidzdmMi95dStaWnZ6UCt4YmpsbFkvaDU4eXpITDE3YzI2NUVBVitCaUZ1Qi9OZ3ZRUGdmTzIyaFh1b2lBYTdGZkpxQjlEcWJEMitnS2I4YUIySURGWHZOZjZ6WE91UmpPdFlyaU5jNjVrRzhkOVJvVy9paWcxN0N0N3R2d0NUd0lyZ1RlSEI0aU5YTlRTemRqTDI3cFp1eE5MdDJNdmRpbG16R2psNllYalY3SzN2V2gvTktEbUJOTXFVekxNUDBZeTYwcHc3UTFoT0VkQUErRzZlbEh3akNscmJvb3BqVG15VEYxVWpXQVk5b2F3a3FvM05xb0VRT1I5QUNtS2NBT1BZQzlXYVlITUNlT0hzQUJlS1lIR0pPTXQrOHVjRkdYYW5vSUY4STFuWWQxeWFhZjRNTElwbFFSeGphbFFVbzMvUVFUNXljWWRKV0lZeXVXVzhQL0lGSWt1YU1yYkpZN1FWYmdtMzZDSDRaditoTitKSVRUQkVZNC9SbStMdFcrRGJzWnA5dXdmQmhMNVZYS0tjdXdHUHVRVGc5amFiaUdkYm9OKzJlZGNoL0dhcER5VHJkaDR0eEdJVElTeDZjVW9rK3BDTjduY1lXREFLSnQ5RzVnRy9Za250cTB4Tk9WV0VzODNZNzlVd0I1NjFnTmN1cnBkaXgzNU5UVEE1Z3pBRHNDNzI4N3BpTElRVitzQVlGSXEvY2dBSzd3cENhNmRTSE90VmhMVGR4UlpMMkNJVE54N0tBQUJVRkFDWlk3Y2Y0cFZSSUlxQWRvRnNwQTdjUVpxQWN3bEFRdGQzaHA2WGdZQ3VwSlJEbW84N0F1Q2ZVekhJaUVxcHJoWXFGK2hvbmpNMnBOTUxIdmhPNjI3NlFpd05vVk5zbWRJQ3ZRVUQvRHVqVFVzVGdRRHhXYTVrUlUrdmJWQWV5WGlrbzExSEpSMVpmTmdJeTZpMnJLMktnSE1NUVZnOXhhUzBkOXQ0aDk3dHoxRUw0WVFteTdPVWEyM1poR09uRi83QVF4M3NQQTVOM0ZYZE5KejBXZ0ZZL09qcVZyMTI2K2R1MW1hMWNlMWk1ZXg3MFhyK00raTlkeDc4WHJPRis4K2hadDhXS25FM1R4T3FVdVhsU21YYnhPMHRzK1dMMVdZWWpSblluSCtuWDJrYXhmdEdIWCtrVmpudXVYNHhUVkJCYXdWUmhpU3FpOENodTFLYkJNbldScHNPNmM5Rm5EVHFwcjJNbEFhOWhKNW9KY0IzZUJmTjAxN1BmQzFyRFBkZGN3MitsQzF6Q3FDRnZEYUJEV01OdHBUT3luTWVncUVlY2ZBQUJjUUtaSThucDN4Q3h2cG8wb29iU3BoMWpHVGovU1pleFB1a3FkMFN4alo3RDhoMllaWXhrY3ZzdllIMWdhcFZuR3p1Z3NZOXlic1Jxa3k5Z1pUSnhuS0VwR1luZFNsT3hPS3FQbkRxNUlFS0RrT0VOWHNqTmVLOWxVN1VyMmczWWxjLzZsTTN0d0JiQWFaQ3VaN1J5Ry9USmJ5azZxUzlsNk9tSDhoYWtNOHJDOVAwaEUyb0xIekxIS2MyTDdRVE94SGRaT2JJN3pSVll0R0RJVDUza0tVeEFFbEdCNU0rYXIyVWwxTlR0Sjg5RFZiRFBteXhrTXR2TVV0UE5lZXU1OW1PVnNONmJMMmVmNnk5bkZnTXVaYW9ock9idUlpZU1pdFNlWTJDN1JicmRkb2pJS3VDdGlnbTYzWDZRcjJrWDlGVzFjd0JVTld1Y3JHajBxT3VsL1JhTkthbGMwOVh3TVB2SWxueXJMVmpRQU5SOGNmeFhXTG1sTGl0anp0aXNQNFpRaHhINkY0MlMvZ21sa3MrcVltMm1jOXpNQWVVWDEwU3ZRNWRDT1I1ZXpEZGxWdnFoZFpZdmFVTGJXMmE0eHNlMGFFLytJcFplMVJIbEd3aGVJL1JwVFhwMEc2WGw1TUlnVkV4MlZHcm85bFJwb0VlMnNKcjNxcjJLSC80b2R0T0lEN042WFZRMVhFMDB3MEZLRjErMzBYN2VUMXYwM25aQTg2bmJTdXAxRnF0dDIzVy9kdHV0UTkwazIyYkc2NFdxaUNRWmFxdkM2N2Y3cnR0TzZMMEV3MjZOdU82M2I3bDIzQlJIYmZVWXJ6TUdVUnU5Qk8zVnhUZ2RRK3JrODFXOWF1QmNCZFpxR2dFcFRwdnRMOGYrMGZJYlAwL0kvQmY3aXd3UDM4MHZPZTdBVmNKR3JBSEZ3RVgvWVo4c1c0TkcvU3BSd3NLajZrTmMyeHBWS3k3S29sdkJsRzh0eXVMbDB4RUZGb0E2MFQyempYRkZIQVNZT0ZvVVVpTnJHcytoWUFjb3BBdU1wMk1ZTG5QMmdDUEoxV3BnR0lXZTJBRnA2c3hwczQ5emNCOWJPZUNpcGZsVFhlRFVWYWhnamdDVXV2Z0tuTURqR0NkNnNCbHNCZGxPYnh0QkgzN1lKQW4zRXp1RnpUQkFvcVhxQ1FQOXNFMTN3MGRTSmxMZmhtQ2h3dEJ3VEdSWVRCUnIwSXMvWkp0SEtiSk1FK3VlWXhOR21hVGJJRGpJRkF5SzJDUUlsMVlFOU52NFJqbFErVVhCMWhtb3ZLR1lUM0V4SFdvbkdoN2lLV3RFc3RTYXRpRDdCcG95ZFdSNXU1b0pXNjJodTRGeWxadnNyTmR0ZnFka3U3NThUa0NzeUIwczFYWVF6ZVNIV3Z0ckJuNFI3dk8yeEVJY1htYjFSVkpwSVphVERNL2JJT0I4UGtOWlFEM0xZM0IxUGJKTjVoSHJIWkEvZnNrMFIxSkZLVTNsVTZ6QlRtY05NRlloaktoc29OaHFrVWVqV3lRS3hUYU1wdG1rQzFFaWpzekUwRERVU3h6VEIxUVVzejNSM001QktITk5aSTlOcGtLYlBZbEVJWHFjdkpVeDFaZU5adkxPOXd5dVlLdENKbE1tbkNTNktCVXVkcGpwcERwYnF1Ti9tV2VDQ2xyN1BBeVVXdUxxQmlxRE1BdVpwZk01Vk9ZQThLQy9DNGZ5enV5QW9xY3hhQ0FkOHl3ZXJiL25jZHIzbGcvMis1WE9EditVRHR6L3lIZlV0SHhxNzYvR1dEOVo5eXdmN2ZjdG52S0I5eStlRzZ5MGYzRnUrQS9jc3R6Q1BFdHNNQVVTdXB1VzdjT3RrbXlFb3dhb09ubS81NENLOTVYT2JEU2RIRHEwZDRvSGY4cm5uN3kwZlJ3NzA1RjMrZHN3OWYyLzUrTW5pK1phUG53eWViL240eWVENWxvK2ZESjV2K2ZqSjRQbVdqNThNbm0vNXVETzQzdktweXU4aG1NT3lNYTFaek4wczlCbVl2ZGh5ZzRweHVud0RENERQRDBUeVRZMGtuTDNmY2tzVjNlSXZ2TnpXQ0RoMzdRNFhRWE00WGI2RHBRbVkzU3pZWmdyZ0hwcFU0cGpGUkV4SWJITUUrVDYvTTREVXVSQUZLUVJwNmwwTVpSUkJobGxtcGtCWDZQdTBhaWFuYmJJeUxNSkZEN0RyWFQyTkRqenhMcGJlUW00bDVubm81SmhQZGVKcEM2QmxXSk1YQ0RRQ1RjMFRpR01oMWNpeFVIQkY3Mk1vQ3BrVURQVmhrQ3BZZnNCSzJPWUpIS0g3V0ZKVTFlNTd3T015eDUzaGdiOE1EMXpnRjNpQ1g2RFhLKzZFTVlKSHdoaEJUUmpybVRCV29MZU5DcGJIZVNhTUV3Wkk2ZlEyNVYwQm5KT2p0aGdpY0NHMnBheTMzcVZCR2dVTWxnckU4WjRnajRmYUhPOXhrSGpoOTFSczduSlhjS3V0dU9mb0NZSzdIeG5oUVo0Z1NHWDRCOVBpZERsYjhGaUpzNFZ3S1FHNW5Kck8wUk1GdG03amRCb01OQzluRzF4dlh3cDhYczQyK0gvN2tuMzNRcmFCdm4wcHNNbVJ4WElFemJ4TWkvdWRsN01OL3QrKzlKaVhwNmpmd1pCdDZDM1RHWGVhd0tQRXRsd0FrYXRwT1VlQWVYazU1T0k2ZU16THJNSEMzNzVrY05sVzBkb2hYc2pibDRLL3R5OVhRVkhRd3BYRjUrMUwzeXhlYjEvNlp2QjYrOUkzZzlmYmw3NFp2TjYrOU0zZzlmYWxid2F2dHk5ZEdWeno4bzhZRWRzV1FZWjdrUzMwVDU1RDU1UDNZU2dUMjFwQmhpR3pWaUMyOVFMVWlTQkFJemtDQzI0UzVMbjA0b3JtOE9nV1FaNHZzTmN2MTlLU1c5MmxlQm9OM01MRThiRWczOFpNaDYzMEJra3dFdHQycHRoMlhtYTdJTTlpVWNjSFRMM3RUTDN0N2xLU2xJNkl3MEVMT2h6MGoxdTBreFp4N0tKRkhMc0U0dmlDVytUNGdrVnlCQmI4bWxyaytOb2R6ZUZSQjllYXY0SjVtbTg3MlYyN3lwVDErRFRlMlI3TEc4bDFHdHlVL0Z5bmdRcGNWUFU4Sjd3MXkrUi9HUmdCbmN0SjNsKzhKRVJ5ejBFRUx1enZ2SUh0UUdrVGZ4bElIa3ZQWTBFYW5ZVnBNUGM4aTdyYlBHZGc5Nk41ZnhrOHRrMjhmbDRJYnBpcFh1ZFpGRkxQZXhhWXJXckFhbkx0TE4xdkE2a0ZuZlR3bDZWQ0xaemxEM2NJZ3BwQlVIYzNhd3l1dmVSOVRQSm9GUXFDZ0R0Q0s3OWdjTzhqOG1nRUx2UXY5eUlGSVBlaVI5VDJnSXN1TXJSWWtPVCt6ZEJpUVRXYWU0RkY4M2pxM3dhbXo5L01KTFdoeXdidjQ0SGNTNno4SlFNTnp1VEJ5eXc2bXpjRTVXbFVRU1EzbnlrUCtyQ2cyamhVUDV1Q0FFR0Z2czJSbDArejhhYlZvQ3Y2dDRIZjg3czJYTFNrZWs1QWE3NWs0SHNCMklXQVVaZTRUMENLdXVzRXRlRFB2VDEyUmR6Yll4TmJrN3RKVFZsZ0xpWjVsdzJLbGxmT0s1eUxTZTRWYjQvejJDL094ZEorbFhRTi9KOTArVE5NcnlUdmlnSHVHL2tvdWdvUmtuZVZ2bnhQRjJhclFKN21YMGFTZHdYY2F4bS8rNEt2b0txR0hIdnAxNTN3bWhSQmZzK1ZMQ2tHV013WWM1MS9CeE8wY2MwZ3J4RGdRdkt1cytBTkEveFJYRURxVlE5azg2MThnNUUrZ0NLNWR3enNIUjQyY2VTNW9nTFlubnVYUlptQTVONmlMbVZnMlVuZVRSYWx1Tkc3REpKM2kzWDFMY2l6VzFBRlBJOUE4dTR5Lzc1cmdMcEo3bTNtL2ZjeEJFbmViWlo2MndCNktXcEpwc3B0ZDBuSWVwZTVNZ1R2NkZURVcwVTZaV2t6dHcxOEQwc1BpZ1NTZTVPbDNUUkFVQzJaZTRjM2M4L1ZhdTQ5bGpxYk0wb1Y3RkwvTGxXQU44T2g1UURlZEd0OW04TkkzL1ZSTUVmVHUyWGE2bDJkbHYzWWk0dGtMMnVWUVN2b1pQZXFHL3hlVmYrV0R6ajZLcnBielJhOFVjNjlhWERYbXVkVks5T0VLUWxIVUUvQzNKdDNqNDZ3M1BzR09Kd1ZTTjU5Rm45Z1lLOWo1RDFnOFFLSVEyNTZBNUlqU0l2VXV6VzRNV01qMDBDZTVqZG9zRldhS2JqY1JVa25lUVVHT1ZmdE8wUnlzMFVXelNzd1FBUmVwUlBjVEdKMUhQL0RDdGhOa01lWERmMURUZjZwQW4wb3R0bWk5cDJiM0RHaTEyUkk4cWlJcjZac1E1STdWdVE3RUpZTGhqd1ZRVyt6WE9EMzQyZ3VLcEttQ1A0K3pCK1R2SEdpNzl3TW1VN1MyRW5Fc2xIZHhudnJ4dldDN0V0cGJDbG0yYW5lNDczMTVqclQybW5zSk05T2JacmdiUk8zaDlaT1kwc0ZYanZZTzhIYlhtNHJyWjNHVHZMc0ZJdUpHaXdZOEJNOWdaL2tDL3drWCtCdHZzRGJmSUdmWEJUZ0p4Y2QrQ2tQQi95VWh3Tis2c01CUC9YaGdKL21BL3cwVCtDbit3SS8zUmY0R2I3QXovQUZQcWNvd09jVUhmamNod00rOStHQW4vbHd3TTk4T09CbitRQS95eFA0MmI3QXovWUZmbzR2OEhOOGdaOWJGT0RuRmgzNHR4OE8rTGNmRHZoNUR3Zjh2SWNEZnI0UDhQTTlnWC9IRi9oM2ZJRmY0QXY4QWwvZ0Z4WUYrSVZGQjM3Und3Ry82T0dBZi9maGdILzM0WUJmck1HQzVzbGJMSktUY0M2d1dKQ2FnMkREZTZMcjZKSGtMeFBaQWVXR0ZhTDhqZ0NKRUNRYlZvdXc0ZCt3V2lRYlBoRGxOYTRnTzJBWUg4VE9aa0hERFJ0RWQvZkF2ZHVHRDdsZ3c0Y2lqYWhQa29WMGtyOEJvbkJ4cGZMOTFvWU5JazNOY1FYVnpKQ1JGNEQ3T2tpbE9Yak4vTllUdXNLdEN1YXFyQlBkM3JSaG5VZ0ZYb1cwS3ZFY2hhdTBUbFFMZUtqa3FwMXQ5N1hvN0ZiUldTKzZoOEdHOVNJVmVCWFNxc1J6Rks3U2VsRXQ0S0hTZWhWRFJmMHdHL1dCTWNoNE1CK1NOYjdJRGxMVXFFdEk4M21MMW90VU02NVYvZ2JSWXhETThqZ3RkZ2xwUGkvUmh2V2l4M0JUejFLOG4waERQbS9ST3RGallNOTJVeEU4bm9GRFBpOVJQaXZxR2xkTVlUWHFFdEo4bmlKcGd1c2ptL0kzaXZKY0dHVFRCZkpVTmJSaG81Z0l0K1VDZSsrRDgwWUUrTGlxL0kxOENFbmtTYzVXaFQ3WVFqZmxSU3JudlR1WHR0RG55Zm1iUmZsakFTNDBPSmNIUHhIbExRSmNTUDZuTFBpcHlLS2YwUkdlLzVsSThuZXpvcnRaY0M0UGZzbnlmeW1TL0c5WWhtOVljQzR2OWgwTGduUWZDKzRUV2RFZldOMC8wRXdrL3dDTEh1QXQvK1NPUXVZakxIb0UraUgvTnhiNVNTVDV4MFg1QXdFdUlDWDVwOXlsL3FBelV2NGZWRXJ5ejBJS0ZEN0h0RGduc2dvdXNoSVhSWktmTDhwckJiaEFiZ1prRkVYdHFpaHZGdUFDYjdnTFVodEU4bStJOUdrQ3lkMG55TXZwQm5tL0lLOFVJQTVCa245YmxPMEM1SU1nelovRG96ZEVlU3NOS25CSUtyMkZTUDY5d21vcllMWGRFeUZJOCtmQWFRblBieWhTZmhhOXgxcS9CMjgzemhla0R6RWkrV09OaFRRL3dVaXJHMnVFSU0wZnVIbS8rVVUxdjdGSStWbDBySkdxT3hZK0gzYStJQjBEZFcyRnFUdVZWV2N6UXBEbUQ2eXUzL3dCMVBXYlAwak5IMXlrL0N4cVkrYlpqSW9KekpzdUlKSS9vekR6WnJMcVpoZ2hTUE1ITnM5di9nRG0rYzBmd0R5LytVMXEvcEFpNVdmUkdReU9HVVlsRk9Db2hnTEJNSWRWTThlb0NQSldRWkpzQy9Fd1JKQWs1cmZDQ0JHVHBHQ0U4bWRmUDlWa1p2OXR3NXM3NnlTOS92S1lNUjgzYmJlMTh0SmFwektmNjE0VEVhZEJVcDY5UCtwSXpEVGxpZWw3QnZTYW1UNW1ubTh1bXlncGsrOU02ZkRxdldwWDcrS21oeUpLbnQxeUk0dUVGaVNzZWJac3ZhMTdCaXc1RW9TSVhaU1VkeTA1WDA5djh2ckJKNlZ2cnllZEh4WmFyZG53WWYyV1ovU29jU0o0d2VkRFE4TVFjWWlTZ2dyN0lVNVJVcGFQZnFxUDFFeGUzT3pQeHpZMzM3SjdiL0xhM1NtL0pTWWRqY3FiMzc5aHBkcHhpTmlNa3JLaTBGeDJZMUhxY2hnbDVZTkxGeU1uTi8reVY5dGRIMlQyeWpKTnJ4VnBDbmwyMmFubjcreXUvT3pHdzY4a0l1STBTa3I3cDh0K2JDeG5hcnM4TTc3VGlrNG5VMk5mN0x5MGIwUlVSbWl2MWxzWGxTaHBobStDTGdyMnRqQkpXZDNYdXE3cG1hMmxUNy95MnVtTmpSNTBtSkM5dmNPVDQxcE1XL25NYzFrYjgySUVST3hoa25LM29LQnRmTjIzMTFiZTMzbkozQ0gzNmlmN29ocFdKRlJacmx2ZjNjbC9yL25XbzArVXYxWnlqaDlVdzZuMmhlU3loMHZLMDYrVWZTb3FaTjdDU2VPZkduZGdRblJjcjFmRkNRdUZVaVdTeno0VFpLQXRPc0lsWmRHVFAyWjNISmpSN1hCQjAvS0RybFpkZHNTd0tXRjNsYVl2bnIzZHJmS2NTNTNqNEF2REpXWHAydkN5VThidjNkK2s4Ukx5MXhlaDVzM1Z4MzdSQms4UG1UY3djUnltZGRuaUpPWG5wQS9idmI4bmRzUTJhOGRUSXo1UEx6ditRTyswNTg2MXFqUGozZGp2bitsWnRnb2lqcHFTRXVINmtlWHdNSXZGTElXR21JS0RnNHlpUWNBWXd3ZkoxaXBLTGxzZGFXbHdZZUFISWJSMDZPZXQ1dlZjL3ZLdm13WTB1SnpzNVRSVEx4MWRQTy9Kd1ZuS3pHYzNWb3Q5K3MyTVBpR0RobmZkT1AwSDArY042NDFzVVBYcFVSOXUrYjNsaDdkMlR0ZzdydUNienRWdlZwN3pldFg3UTM1NS81Y0ZUNThkbFZMZWtGTmowS2kzUHI2MnIxZGV0NlBWUy9kS2YrbHU2VXM3L3B6MjRJbVBEenhmZVZSTTk5WXY3ZHA0TXlyeHlsdTFidFlvZHp0cC8rQVBOOWpIRC83VDBEZjI2Q3QzeDFUZDFTVm56SitHM0JsZlBMaTFzTzZ1aGRPZTY0Q2Yzdi8zMFE1UGZGRDV6OTV2NTFiY09ISk14WnBmRFEvTmY2dkRPNlAyYlJwNS9Bd1JmcXEwNStQVytiWHJQLzNSQ0xTdjViSnhUMjlkdnl5ancrdnRmK2w0WlZiSll4TUZVNC9CYjdTb1VQM3JWUnRIeGgwdnR5THg3T01kRmxreVRveUtmTGRLZCtQdUJTbk5CdSt3akczMzVLYnByZlBSK0FoejB1YVByaVZVcS9MR3VpOE9qZmdoTG5YNTEzMGVEOW82YmZlSjFHMWZOUyszNlllMjZ5WmJ6ellQN25ScitoTjNEYUdoeVF2UDFadlNwbUJvbVVYN2s2ZTluM1R3dHdzZjFXaC9xTXlIVnp2bXphNlMyTXZaOGFlUGVyeTFhR2V6VzNPNmJMMHhxL1RoNTVZTzMzbTA5ZVJKd1FlZlNUL2VaKzZibi8vMmM5V1AzM3ZsdVg3WkMrUS96a2R1UFdkczgrM1NFcC9HMUZvVDBlMTFuTnhwNmNwcDFXWVp0dnc2NS9TRG42TjNCcjJ3OWY2cnhwdlBaVjg1OTMzS2dONnJSK3lkL0dCVHIwN2YzZnMyNkt2TDllS2JsYWt6cUdIRFY4NSs5T3lQNWVNdHN4bzE2dHZrelp1RG5vK3MrOTZMUDZYL2pjdU9MVDNxcUJoNVpLdnhWeks5WnRDWktyV2JWNXU4ZUh5bEdmWHF6ZnFwK3VHN2U4TEY4Vkwva0JyZjlLalFlZUt1cFVNYXhkVzUvSEs3bDE3SmFmaEwzZjAvTnZ3K3VhK3gvb2hsWno1WnZsamM4ZHRUUnNPWjg1Y09MZjYrVWFmTjVjZS9NZHkyS25mY3FLUlNzNmQva0hxbzlxK0xjcks3VExpUlZuSENCc2NmemRhTUxGOUtPRHhtVW8vSExVL1VxSDE5bHZWY3BkVi81YVQrTlQ1dVk5cnVEa3QzbEp2WWFGWERVeFh5citaRVhpbDFhVWRHNG95Rm5YdW5uRmh6dWVuaUo3ZXYvdW1sQTlNNzdGZytkcGhoOW1PaGFPYmkzV0w1NWhtYktxQlh2cDA1MkJLeDg0MUd3eXNKSyt5dDMvLzh5MVhkY2MyOHRrZlNQa3Y4dGxwTSt4OHF0Z3pyL05mcXEwMS9IcDE1OTdWS2Q5TTJyVzRmODN2d2F5OFYzQWxMK1hwQlRxc1dBOHQxYlBEaDJURVgxd3ovb0dGeUc5UFdQNzhwOVVDWjhsM2luR1ZMMzMxdGR1cWVyb2NHM2h6YjlGQkd5MDlQZlR5MmtYbDMxTDJrbnNMazdLanVyMHhxWWRqOXg1WmhqVnFPM3JpcS9iRzJxRVhrdVRPcHgyS2JKaFUrZmRnYkZXR1lQaWdvS0hzazZvbGh4eEttbS92Vm1MKythZHY3OTJZTmVqTm43YTVGVDVicTFxQnNRVUZCZUovUWhCMFpPYzBtZmhLNzcrZGxxMGVQYnZIcCttY1B2L2w5d3ZTTkM4TUxtVnNMbTMzbFF0Sk5oYVNMaGFRTGhhVGp3TW5aaFJSUEtTUzkyUHlBUDhYbXc3M0E1MGhhR2p5cW9PRHByVysrVlJCM3Zjc1Q3elY2b3VuTmZzODEvTk95Nk1hbzlMVGZ2NXoyckRubWFzR1NpZk91dkJyUytqSEozUHlESDI4Y1hacFRldHVyWHpaY2FmMnBuM09aZkhMb3lRSzhxdk9POU1sOWwvKzR0V1BUaitjdlROMjI4dENKQ2xuMjJJSS9UbFRPbXYxNndyQWJkMGFjdjFqOXQ0MVRMMjFlVnZOUXpYYUxudDQrSXZkRSs0SGZwUWwvM2tlTm9uSW43UnMzZFVObSt0cnFkK3QzUHhmeVlGdXpScjh0Zm4zMUsxMCtpeEp5ZDZ4L01lalk5UW8vaU9VcUwvcXpiRmFQYm9kU2ZuMWo4dDdweWFHSGdpWWxoeC9wOS9PMDRVOU9sTTlVT0hkaFQ4dGRIY09PTk83Y3J0ZkdEajIvZTNGdmNHdmxVb2ZZTWxYWGY0aXV4MzU5WW1XM1ovWW43S2pUNnZmYzEzZGRLdFZsOWNXalo2MGR4WUo5QjlyOXZMN3IzZFVOOHU3Mi8wcEpqcmk1TE82ejVNTzFVdWQ5RmpTaDlNamZrMWZkUE5hcDJyY2QvNnh4ZnNYTklWa1hyeHo4b3VmNDdjUEdqNjhsN2RzWWNuM1kyTDJsUy9hNEdyVTRaT0NSZWgxMkhEWCtNclRUMkhIZjlaN1E5Y1NtUGkyRXFkOWViSkl0Zm4xMnhaYWp5aHpqayt2ZldGL0o4VUwrM0ZkT2RmNTFmLzBmS29YRnA4d3BtUHp5emVPeDI1L1lGdkhtcDZUaUg5Ym0xenArZHVXcjB2WDJEaHQvdjhyTkRxKzErT0xvbXdkZlM3M2Y5UEZSVjlZdW5FcSsrK0pwbkhadGdyMjZLWDJtK0h1RDMvYnVtVGp2Y3RWWFNmbVJKeFkycU5Xc1Z0SVByNloyaXZzMVp2YVNsQ3J4dDlkWmZ2N29zeXR6RmpTOU1yNWF6L3diSWRYV2xLKzdPV3hrNnVDcERjNThlOWQ2ZGQrM0dURWoyL2I3TlgwWUt2SGgvUjBybjkyMDZzaWVqR0dicjJYOWtKa3IxOXg4Y3ZGQjRiUGhCbHZlc0xuSGE5M2NPenJ5OFJiMUwrN2MwbTNGdFNhbmV0Z3FoNHg5NDdRMUt1ZmxhbkhOTisyOTB1Ukk2TnRYVzUrT3lkOSsrc3NOYjY2L2ZEdzhKUExYaWFzK3NyUlBiaG5jN0xXUFMreHFHRUsrRDZ2NTZReW5lZE9RMTU0ZlZxM2IrNDdvNTZMdnhoZU1iTlQyaTA3OWxuYTd0bnZ0MjkxcnRQcDBhTlNVMytmUHFUZ2tvMFBOODB0M3RWMzk1d1J6bDU4YjNKV2loNWJMcjlkc2FNbWxmWHMvL2tHOXNLNVZyVFc3R3hiWmwzOFpOMng5NHJXa1N5OS9jUHVYYitZMzNMT21ZZjMzbDU2b09yUjk5cXNUUmo1enR1ayt4dytEVmswOHRXajYwUlQ1N0VCaFJQclRWZmZnK2lIVkpqakt2TGI2alhydjlpbHo5Y0xXOWcvS0pKYzNieS94NDZhL0tqVzh0ZkdWbFlhaEJWZEhORHQ1WitpV1gwbGEyOWVxUEhVb2ZrK0pqUzIvTzF4ZCttdis5UndTKzJEY21sRTlaODdwc0w4SjJiMW0vSE1QYWc0eERpb1hyWlRZTGw4Y3Q2REJPTlQ1ZU5peEg2cVUyTmo0bVFyNHA2cXR0dGNhVWY3VGt1OTAvR2hhMEViSDd5ZEdsUHFxNWdKYmoxMHZkKzgzYi9DcjMrMWFuVnMyZjJ6Q25DK2xGbzJtci9qeWhaZEtsMGZ3UFUzUzB1QVhPM2E4L3NueXQ4ZEtyU28rWHpOLzZOZk9SaSsrV1A2WEtSVUdSRnZmYmwxM2Z2UzhmcmNyZnRIcmVOZ3JxYzJHLzlybDROYVhublNramhsOU4rRmc5cVk5MDVZY1F1M0NQMDNDTHd0SEtrN2Fkc25SNVkvRnIvOVEvZFhtNGVlR0xwK2FzS1RSam1aSjMzL3laL0RlR21jK3J4N1RkV2lYeWR0Ny9GM08rY2JaTDhxMGJwNWY5c25JcEJQQ2xpdmZaeFRVNnQzczBGZHZsSis3djErSnRobXpWMXo0NmQzWUJzMWFMNWduYnlvVjl0YnRsSGRNMzFYNnBtOUUxdHIzTFF1WGhEWXoxcHYrOXZmUHZKdndaNnQ3SCtLbks1UmJzdVdGc3VzU1Y2NyswNzR2ZWtEcGNoMEtabi9lcVhQSm0wUHFkR2lmaXpkbmxjcjkwTnd1WTEzTjZIRlhoaTI2dnJ4anFSTjFQKzNiTG4vUmM3L1loN2FxL2tUVy9iK2tMWStQcmpXcVRkRHNmakgzdjUyYmV1L1Y0VTl2ZG16S1RPcjJXNHVrRjRMZmVhWGZwSzN5MEg0WHU0NDROL241SDJwdW1GRnAyYmozcyt0OVczdlpHdy9pOWxWcVZlRmNuZTlHUGIwOC9ORDQ5enIxWGRRdStOM1Bub3N5VGxqN1ZMWUZTV1crK2ZQTzZDK3ViYnRYTjJyLy9WZGUrUDBWY2ZyT1NydmZucnpxL3BxOVg5VmV1Ni9VK3FnZUwzOVJVS3J4VSsyU0YzMXN3WU1OdTAzVEhvK3EzMnBycGNzUDdPYkRzWk9yZDN1M2dhbkZwaEhySTA0TTdOMisxQUw3YTRaR2RUY2UvVHR6WksvM1dtdzBETHo3YmJuRjMzNHl2YjlsOFlOcXkvZFBEU245em9qVW4zS2ZzRzM4TnVYd0xTVG1uaDJHOTV4NGFtRFF2dGhMSnpkSVlmdE8zL2pocy8zTFJxWkg3Qjd5MXVCKzFkTkdWZHBWcjRSbC9hS0lnanZscjlTNm5kWHV3TUdXZVd1N3JuODNyZWxsdkJEM21yd3VvY3lUTXdjWXhMaWIxaG94aHFSRXEyblpaN2UrWDFnOWFPZkp6WTNsdnQrMTNaVlZiOEd1ZHJzck5oNTlvOXozU2U4c3hyOEduN2FzbVYvMjRLK2xualhzTDVlNWJlTGthNE82VjZyWWJmVE5zU3VlV3J1ajRlb3greThrL0RJdnJjM29XalYvelRZdlB2akdxZWpWMWVlZm5kenJ3cENUZDF0ZmJINmcxZk5ONU01VFgzaG1SZkRmNlc4KzhlbmhvVitXWENZTlhYbHI1NTZ0ay9kdlh0SXQvNjNGMlh2aWY0aHNhaHg5bzB5R25OWDA0S2FzRWk5ZTdySHg0NGw3cCtaMHF0T2s4dmlkNXZNdEtnOHBWUmVmL3FyNXhhVkRJNGRFVmEwNDlxTTV6My8rYmRDeCtiTy92YnFtZEkxVm94ckVIejVTQnJkUnFyYXVlUHI1VzN2NnIrL1F2MktWSlMyZnZuLzNWSGk0TXI3QlpmUHFXV3ZlTy96MXhVL0tiTUVQVnRkdk9LVmJzeS9HMzNBYzYxdWo5dFRRMUdkYlJTNjUzR0hCeGprTERVczJSZXk2MWZGdTJJV0NIWU43ZmxYaW85RGhjOWVrWHIxZitlRDVCOWFaR3lKbjFwcys1UDAvVnh4N1lkVHdYck9mNzkzM1ZQK0NzbU5lRFMxWDlxZUxZNWY4dUtISDRuYWZyeG9VWHR0OE1hVGV4cDhPZnRnOXJ1dWloTktubitvWmpZZ3REMG5aQXNwTzJhMHM3WHhTem0yWFYzTkQvM3lUcmJranlkN0xHVGYvNVNPUGJSMTJTeHovekZmbFYzVC9JMnJPQzRmcWJoNTB6VHl0OWI1cWEvdGNpRi8wMnRFbmRveTZKNHh0L0VYaXNxNi9SODVxZjZEMnBzd3JvVk5hN3FueVFmcTVVZ3M2L2RybzB4RjNnaVkyKzZiaXFoNW5ZdDUrOFhEOWo0ZmNDSnZ4M1BmSjZ6TCtUbGo4eHZHbmRvNStnTWVRejYzdmRUa1ZNZlA1SDJ0dEhIQTVaSEtMN3lxL24vWlh5WGRlK2FYaHR1RzNqUk9hZmwxaFplcWYwWE03L2xSdnkrRHJsdWx0OWxmL3NPL0ZNdSsrZnV6Sno5NjZieGpYNU10eXk3dWRMakc3dzhFNkh3MjhLazF0dGJmcW10N25TeTk4OWJmSHQ0KzhHenpwMlc4cnJlNTVObmJlU3o4MytHVG96ZkNjdGovVVdOL3ZVdGtsYjU1NGVsZFdBZjBDR0VsNXZ2QkRHY2hXaERPbEUwV3F6WDRLU1NsMllldlEwNC9kZnZ6MURuWHFWeW90Q1ozYkQyNlJmL0dUaW4zdDQ1dlUvaWFxUXMrQ296L3V1M0Qyc2FjczM4OSs2NlA4MUEvUTJzUmplUzErYmpPOVY4dnZ0eEdNaUgwV0x0SkJ4SnlpWlp1SGl3OHNpZzhzaWc4cy90MFBMQllYWlp3V24xZ0UraW5lc2dmOEtUWS80RThSVHl4VzR1SVRpK0lUaStJVGkzLzNFNHUxdVBqRW92akVvdmpFNHQvOXhHSXpMajZ4S0VEd0FYZkYrL1RpZlhyeFB2M2ZmWi91S042bi8wZnMxQUw4RkpzZjhPZS93WHo0RE5UaWZYcnhQcjE0bi83dnZrOC9YTHhQTDk2bkYrL1QvKzMzNmNlTDkrbVVXWEFkUzUwTGU2V2xVZW1FcWFVbmZicHFaTXlNODg4ZnZoejE4clFyK2NlYkhkdjN4czd3dXVNdVJjVVgva3FNL1FhV09oZHlvNE1LcmFhd0gySzdpYVhkdUtLeVEvaHh5N2dabVhoa2kzb2x6eDg5VVdyTXZHY3JicjM3ZUx1MzE1UEhYaXFaMHFXMS9hMkJtOWQvZFVSNHVkT3hKcDBuMWxqYS9sNjd2MEo2anp6WGFGeitnNmdiZi9XMnZYdm4zUzdERmk2K1B1OUExb01IYjVVdTE3WFU0b0tneG92WG5SOTlQK252RitPK2ZmSFZrTzdibjNpcmR1THRsNDRPa2V2VjJWbnZkc2V4M2UvUFByTjBoZVZmdDhOeEMrd29OTi8vTko3LzZnK3gzY0ZTdHVIL1hJLy8zMy9neFd3cDVXYVdoWHovYk5DTmlMelNCOXYwZTdMR2o5K2tOQnhkcDBubGwrYWZYdTJjUDdkTUVWNXNnMm95alVGdEQ1emRPZW5QOVBnYXg2cmN6M3ZHNnl5Z0NObzh3SStDV0dSN1gzZ0VnK1QvL0FjK3dQRy93ZzdienY4T094eDdCWW5RZlQ5R3dEbURQNFRVQU1aTWhyZ2NzUUJQUWE1Y0NEN3NUMHFwdWFaYlUvbnhvVnRlNlA3Qis0NlpXWFZuaGlTWHJ6UUFqYmdRTlRiaXlJNFhTNzcwN0FkTEU1YU16eUF6YjAzdU96TCtnMFo3VHQ3WlgrTHN4MStlSC92YzlyWnBGUkY4TXFDVVV2bmorcFhOeDdiL3NmZlRPcWU2WHE2NXZVZUg3cmMvL3ZIOVdzZHVvWlU3KzllcjhPM1FCMi8rTWVybjkzNzdzZUt3aVB2cmczc2ZIYjI5MG1jeGZmYzlPRDVCVUNaVm94K3VKYVg4Nnl0VDdwaEhVazNlbzZrbWQreWowZWJSVkpNNzd0Rm84MmlxeVIwdlBncjN5NE5xWnUxc05EN3I1eTRENzBiVXJYU3c2dmFWNzVSN3FsV3Rzbk1XWFRpNFpQdXhSU2VpVzN4M3BGWDAvV092ZDM3MW1SVXJLKy90dXUzQVcrYlFTVHNhM004ZlVPdmQwSEhsRVh5a21aUVMzQ0txenR1ckZxNmY4c242U1FQTDlONHpTWm1TLzhiRnp5SkdOU3BiYW5DYnEwSm05UmF0eTYxTFhQYnFxZGRmWENHRTUxWDg3a1NIWlZkckhIMSs3dVNQWWw1YUxTUDRxTE5ITVJoeUo0cFN5dG53TkZJanJmOTNVcXUwU3RhNktiODdYL2xxWE84ek8yc1QyNGJRaXpzK2lIeC8xN3FVY3E4M3Q3eTByOGFhdUxvbGpkZmxGbE9rRlJzT2RwcDFvTjZXODlZYTlIUFRIa2xQVFJLbGxFV1NzOFFNUjdzNjIxNTg0N2RSSGI5L3ErV0wwUjl2M1l3N240d1ZoTmd6WXlzV3dXK2dtbzZueHY0Y1laNDlvRnlkblFXajVteGY5VXpVb0VQUDFLbjVRWk1XcjFTMFBQMTR0U0pvWXhPbGxDdWw3eUJqOXZROWFmTSs2aFYxK092OHVHY3NIdzZJVk1MT3ZIamswOVR3eW9VZHFZSTJVRTJoYjVzWHJzMWtVVXBaYzNuT1Y3WXZmekFkR2xoaWVsVDBSeVZMQ0gzMjNzOTk3dVVXdGhvblh1MTFLcVFJMmt4K05EMDFSWlJTUHV6OVljek54UFhmYmVxNnFtV1ZZUkVmWGZ1MitlL2QxLzlkY3V5U0pxZUhQbFZKV1R2Nys1dWRrM2F2YmQxNzljZ3hQOVZwMkhOOG4yZW14cDFKNjdndjlwbStobWFoQ0Q2VlRrbzUwYlhueUpXenB6eHo0dHo5cE92VkQrOGFjV2hoV043MWw0KzhmR0ZJM1RaUGJnajZzZjUzTzY3OVdyTHFrc3JYWGh6eDNNcjNMcTg3M3VuazMzVzJiRnA2Ykh6Vk1lWllCSjlXSjZXODlVdXo1K0ppT3RSZjB2ZTdRNHNqYjRadUNaSDMxRmo5Ym1vNXk3SnhrL3RHbUJxV1hQVGx6WlluTm1idEdqaGxrckRreVpPaDY2Zk5VaElYcm5vaC8xSjAwMTR3d3FHYWhHZWJyUTlkMy8ybHo4T2ZtcFE4dk4zUkcySVpXOEhBVlJOYnI2NzV4T1pqeVZMMmhOSERhb2UzV0xEeFZzdjhyTDQvNWx3WktYd3p3OWF3MWV2dnRYKzFmL0l4QTRKUHQ1TlNsblQ4WVhCaXF4MG53OCs4OEhuVGJZOTk4Y1piQzJhdEhOc3dlL1QvMitJbjMzVlp6NGt1bjJtK2YrOTdEZDFpOW10U05uV2NzNk9EdmRZTE8rck9TRTVnZlR5eDg2RUsrRWc4cXNSVUwxVXl3NFZlcW1UTkNYM1V5ZUY5MUFtYmZ1cUVUVDkxWERPQmhkdGg0K01YSVdxN3BINEtuWnQwUi85MG9idnAvZTQvRDdJMjNublNQZmZzMUlWZTZ0M3lqUkxyQXY3RTlNeHdQbTNjc3NsYk1tbnJZZUg0eS81V0hTZjA5M3BLR2pDQURoemtkcmgyKzlhTmp3b21MWnZPMmt1Y0ZQaGc2Sm13WEgyclFiTHprL3RTSDkxTHJnaVgvQXBmb2V6ZytWNUtZUFZWcHRoSldnTDZ5MlkzaVc1b1hyeE9tRWRXMEZLVkFYUVFJYmREMlFRajZhYjg3VzBpMnlSOXRiOTJPK2krYkwxNVllZjk0T1dYbWpKRkZPUllqNzhPS3I4eVp3Ky95ajFSazhmLyszTjNPcDYzK0tEemFWL0kvalNiLzI4UGlES0FEaWlrU2owMWlZWGJZWWRybXNubmg5N2lMTE5mejFScC9YRy9WUGthbjlXY0tsOWJhWk8zRGg3S3pLN1hXY00zeWpIR3JHU1Z1TEZsUzZIdWtWbE55L1k5T2xOamxKZlM1LzlHV1ExODJpRlZZbW95ZGRvMzFERm13aFNxVkRBWHFHUE1oS25VY2MxVTZvVE5OT3EwL2FaUnArMDNuWVhid1dGTHh0S0dweTA5VE1LSEhzajZpcDI5YXY1OVFuakVwR1ZyVTRXTy8yVW8xTDE2M3Jqbjg5Mi9NdzFmQ2d1OVRTODZidGEvVUZja1NPSE9kYTRWdWpIZjk4Z3pnTTZlcEVvOU5ZT0YyeUhocmZEMDUwb2JpaHJyT1J3THpCeTNsdnpiODljcmZtTHJDL0hHYTYwVGQ4ck9zejAzL2JQZURUMnpmNDU3Szh3eUptVzRXM3hmdFhEK2szTzg4YXYzSmpreGdnK3lwRXBNemFST3pUQ1RPbTIvV2RTcEdXWlJKMnhtVXlkc1psUEhOWE9vMC9hYlE1MjIzMXdXYm9kVHltWmQvMHJQc3I2TFdUSDVVM2hYendxL3d1MXQ4ellGc1UzdWozMzVJRWlENzhrREVYbEh4eTVlN245M09UTWVSZGI2WHZxaXJLb24yK3p0K0RHRzh3OG5BK2hZVWFyVVUvTll1QjFXTEYrYjlNVWhKYnIyaWN4eTc0MGVWLy9kZXZaTzRMQ1l4ZW8vUGk5ZFBLZEpMVWgybFl5Yzg1MVA2dkJzMzlBMzVYOFlXYzB2TFdKUlZqaG1yL1B2d1pFbWJ2QVpwZHdQbUJRK3RwMUs4WjdXdGtUWjllbjI5MHNjZG51OW1GYXhzcjVaWXVlbW5kdVlCTTF1VFFyN2ZLL3gzb0dFNDRlWHZUak9zcTkrZDhIVmt6L1RyanRLaERYN1RqYzR0RGh6MytFTXNWM1JVNUtDQkk0SVd0VExMTDk3cS9iZExrMkdsYkVpdmRhTiszVm0yVHZkM3lXZEVuZm1sY3VyTGR3cmFoNy9GZkZJU3oxN2FTSlR4TTRVWnErN0g5UTROdDZmL0U3RlBmQm83MjJuN0ZaemZtN244d0s3eFp3YThoMzhQQjErci9xOGh2M2grZEQyZGE4Zk5MenBVRmhndmxqd2dsMVd5OVJBS3ptdnFDVWVZbnhINzJlNHBqMTlmWVRIUjlNeGEvV3Q0eG1YbUs1ZGFPbzZZdk4ybGt0RzJwOVl4azM4WjVNQ0xtNit1M0dGZzJhOVI0cVNsdFcycitYcm5KOGtDbGQ4K0hmaTJOVU92dmJ5bjZ1eTArV1hwVEJYTHI2MzlwemU4L2FJQXVsWkM1S2ZsZ3R2T254RCt0MzdFSjd2TjFTdVJsMDhiQmRyWmJFcExlVGpyUVAvcHV3dTVucjg4RkcxZlR4am9VelcvNDJaeWZ1ZGRWdjJLTlFLM0wvMVY2SGdaSzYzUGpncGI5akl3bTBQR3J6Nnp3QWQ1NElzYzJGaytBOFo5WUlzZWdGeC8wT0ZvTlIvbUhKR0FONlpiaDlKVWdFQVwiO1xuICAgICAgICAgICAgYm4xMjhfd2FzbV9nemlwJDEucHEgPSA0ODg7XG4gICAgICAgICAgICBibjEyOF93YXNtX2d6aXAkMS5wciA9IDE3Njg7XG4gICAgICAgICAgICBibjEyOF93YXNtX2d6aXAkMS5wRzFnZW4gPSAzMTQzMjtcbiAgICAgICAgICAgIGJuMTI4X3dhc21fZ3ppcCQxLnBHMXplcm8gPSAzMTUyODtcbiAgICAgICAgICAgIGJuMTI4X3dhc21fZ3ppcCQxLnBHMWIgPSAzMDgwO1xuICAgICAgICAgICAgYm4xMjhfd2FzbV9nemlwJDEucEcyZ2VuID0gMzE2MjQ7XG4gICAgICAgICAgICBibjEyOF93YXNtX2d6aXAkMS5wRzJ6ZXJvID0gMzE4MTY7XG4gICAgICAgICAgICBibjEyOF93YXNtX2d6aXAkMS5wRzJiID0gMTI0NTY7XG4gICAgICAgICAgICBibjEyOF93YXNtX2d6aXAkMS5wT25lVCA9IDMyMDA4O1xuICAgICAgICAgICAgYm4xMjhfd2FzbV9nemlwJDEucHJlUFNpemUgPSAxOTI7XG4gICAgICAgICAgICBibjEyOF93YXNtX2d6aXAkMS5wcmVRU2l6ZSA9IDE5Nzc2O1xuICAgICAgICAgICAgYm4xMjhfd2FzbV9nemlwJDEubjhxID0gMzI7XG4gICAgICAgICAgICBibjEyOF93YXNtX2d6aXAkMS5uOHIgPSAzMjtcbiAgICAgICAgICAgIGJuMTI4X3dhc21fZ3ppcCQxLnEgPSBcIjIxODg4MjQyODcxODM5Mjc1MjIyMjQ2NDA1NzQ1MjU3Mjc1MDg4Njk2MzExMTU3Mjk3ODIzNjYyNjg5MDM3ODk0NjQ1MjI2MjA4NTgzXCI7XG4gICAgICAgICAgICBibjEyOF93YXNtX2d6aXAkMS5yID0gXCIyMTg4ODI0Mjg3MTgzOTI3NTIyMjI0NjQwNTc0NTI1NzI3NTA4ODU0ODM2NDQwMDQxNjAzNDM0MzY5ODIwNDE4NjU3NTgwODQ5NTYxN1wiO1xuXG52YXIgdXRpbHMkNSA9IHt9O1xuXG4vKlxuICAgIENvcHlyaWdodCAyMDE5IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygd2FzbXNuYXJrIChXZWIgQXNzZW1ibHkgemtTbmFyayBQcm92ZXIpLlxuXG4gICAgd2FzbXNuYXJrIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICAgIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gICAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAgICAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgd2FzbXNuYXJrIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHdhc21zbmFyay4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbnV0aWxzJDUuYmlnSW50MkJ5dGVzTEUgPSBmdW5jdGlvbiBiaWdJbnQyQnl0ZXNMRShfYSwgbGVuKSB7XG4gICAgY29uc3QgYiA9IEFycmF5KGxlbik7XG4gICAgbGV0IHYgPSBCaWdJbnQoX2EpO1xuICAgIGZvciAobGV0IGk9MDsgaTxsZW47IGkrKykge1xuICAgICAgICBiW2ldID0gTnVtYmVyKHYgJiAweEZGbik7XG4gICAgICAgIHYgPSB2ID4+IDhuO1xuICAgIH1cbiAgICByZXR1cm4gYjtcbn07XG5cbnV0aWxzJDUuYmlnSW50MlUzMkxFID0gZnVuY3Rpb24gYmlnSW50MkJ5dGVzTEUoX2EsIGxlbikge1xuICAgIGNvbnN0IGIgPSBBcnJheShsZW4pO1xuICAgIGxldCB2ID0gQmlnSW50KF9hKTtcbiAgICBmb3IgKGxldCBpPTA7IGk8bGVuOyBpKyspIHtcbiAgICAgICAgYltpXSA9IE51bWJlcih2ICYgMHhGRkZGRkZGRm4pO1xuICAgICAgICB2ID0gdiA+PiAzMm47XG4gICAgfVxuICAgIHJldHVybiBiO1xufTtcblxudXRpbHMkNS5pc09jYW1OdW0gPSBmdW5jdGlvbihhKSB7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KGEpKSByZXR1cm4gZmFsc2U7XG4gICAgaWYgKGEubGVuZ3RoICE9IDMpIHJldHVybiBmYWxzZTtcbiAgICBpZiAodHlwZW9mIGFbMF0gIT09IFwibnVtYmVyXCIpIHJldHVybiBmYWxzZTtcbiAgICBpZiAodHlwZW9mIGFbMV0gIT09IFwibnVtYmVyXCIpIHJldHVybiBmYWxzZTtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoYVsyXSkpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gdHJ1ZTtcbn07XG5cbi8qXG4gICAgQ29weXJpZ2h0IDIwMTkgMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiB3YXNtc25hcmsgKFdlYiBBc3NlbWJseSB6a1NuYXJrIFByb3ZlcikuXG5cbiAgICB3YXNtc25hcmsgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gICAgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAgICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICAgIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICB3YXNtc25hcmsgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggd2FzbXNuYXJrLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxudmFyIGJ1aWxkX2ludCA9IGZ1bmN0aW9uIGJ1aWxkSW50KG1vZHVsZSwgbjY0LCBfcHJlZml4KSB7XG5cbiAgICBjb25zdCBwcmVmaXggPSBfcHJlZml4IHx8IFwiaW50XCI7XG4gICAgaWYgKG1vZHVsZS5tb2R1bGVzW3ByZWZpeF0pIHJldHVybiBwcmVmaXg7ICAvLyBhbHJlYWR5IGJ1aWxkZWRcbiAgICBtb2R1bGUubW9kdWxlc1twcmVmaXhdID0ge307XG5cbiAgICBjb25zdCBuMzIgPSBuNjQqMjtcbiAgICBjb25zdCBuOCA9IG42NCo4O1xuXG4gICAgZnVuY3Rpb24gYnVpbGRDb3B5KCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9jb3B5XCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicHhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwclwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxuNjQ7IGkrKykge1xuICAgICAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgICAgIGMuaTY0X3N0b3JlKFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicHJcIiksXG4gICAgICAgICAgICAgICAgICAgIGkqOCxcbiAgICAgICAgICAgICAgICAgICAgYy5pNjRfbG9hZChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJweFwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGkqOFxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkWmVybygpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfemVyb1wiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInByXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPG42NDsgaSsrKSB7XG4gICAgICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICAgICAgYy5pNjRfc3RvcmUoXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwclwiKSxcbiAgICAgICAgICAgICAgICAgICAgaSo4LFxuICAgICAgICAgICAgICAgICAgICBjLmk2NF9jb25zdCgwKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZE9uZSgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfb25lXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicHJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmk2NF9zdG9yZShcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicHJcIiksXG4gICAgICAgICAgICAgICAgMCxcbiAgICAgICAgICAgICAgICBjLmk2NF9jb25zdCgxKVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgICBmb3IgKGxldCBpPTE7IGk8bjY0OyBpKyspIHtcbiAgICAgICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgICAgICBjLmk2NF9zdG9yZShcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInByXCIpLFxuICAgICAgICAgICAgICAgICAgICBpKjgsXG4gICAgICAgICAgICAgICAgICAgIGMuaTY0X2NvbnN0KDApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkSXNaZXJvKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9pc1plcm9cIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJweFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5zZXRSZXR1cm5UeXBlKFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgZnVuY3Rpb24gZ2V0Q29tcENvZGUobikge1xuICAgICAgICAgICAgaWYgKG49PTApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gIGMucmV0KGMuaTY0X2VxeihcbiAgICAgICAgICAgICAgICAgICAgYy5pNjRfbG9hZChjLmdldExvY2FsKFwicHhcIikpXG4gICAgICAgICAgICAgICAgKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gYy5pZihcbiAgICAgICAgICAgICAgICBjLmk2NF9lcXooXG4gICAgICAgICAgICAgICAgICAgIGMuaTY0X2xvYWQoYy5nZXRMb2NhbChcInB4XCIpLCBuKjggKVxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgZ2V0Q29tcENvZGUobi0xKSxcbiAgICAgICAgICAgICAgICBjLnJldChjLmkzMl9jb25zdCgwKSlcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBmLmFkZENvZGUoZ2V0Q29tcENvZGUobjY0LTEpKTtcbiAgICAgICAgZi5hZGRDb2RlKGMucmV0KGMuaTMyX2NvbnN0KDApKSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRFcSgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfZXFcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJweFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInB5XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLnNldFJldHVyblR5cGUoXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBmdW5jdGlvbiBnZXRDb21wQ29kZShuKSB7XG4gICAgICAgICAgICBpZiAobj09MCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAgYy5yZXQoYy5pNjRfZXEoXG4gICAgICAgICAgICAgICAgICAgIGMuaTY0X2xvYWQoYy5nZXRMb2NhbChcInB4XCIpKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pNjRfbG9hZChjLmdldExvY2FsKFwicHlcIikpXG4gICAgICAgICAgICAgICAgKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gYy5pZihcbiAgICAgICAgICAgICAgICBjLmk2NF9lcShcbiAgICAgICAgICAgICAgICAgICAgYy5pNjRfbG9hZChjLmdldExvY2FsKFwicHhcIiksIG4qOCApLFxuICAgICAgICAgICAgICAgICAgICBjLmk2NF9sb2FkKGMuZ2V0TG9jYWwoXCJweVwiKSwgbio4IClcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGdldENvbXBDb2RlKG4tMSksXG4gICAgICAgICAgICAgICAgYy5yZXQoYy5pMzJfY29uc3QoMCkpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgZi5hZGRDb2RlKGdldENvbXBDb2RlKG42NC0xKSk7XG4gICAgICAgIGYuYWRkQ29kZShjLnJldChjLmkzMl9jb25zdCgwKSkpO1xuICAgIH1cblxuXG5cbiAgICBmdW5jdGlvbiBidWlsZEd0ZSgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfZ3RlXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicHhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJweVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5zZXRSZXR1cm5UeXBlKFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgZnVuY3Rpb24gZ2V0Q29tcENvZGUobikge1xuICAgICAgICAgICAgaWYgKG49PTApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gIGMucmV0KGMuaTY0X2dlX3UoXG4gICAgICAgICAgICAgICAgICAgIGMuaTY0X2xvYWQoYy5nZXRMb2NhbChcInB4XCIpKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pNjRfbG9hZChjLmdldExvY2FsKFwicHlcIikpXG4gICAgICAgICAgICAgICAgKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gYy5pZihcbiAgICAgICAgICAgICAgICBjLmk2NF9sdF91KFxuICAgICAgICAgICAgICAgICAgICBjLmk2NF9sb2FkKGMuZ2V0TG9jYWwoXCJweFwiKSwgbio4ICksXG4gICAgICAgICAgICAgICAgICAgIGMuaTY0X2xvYWQoYy5nZXRMb2NhbChcInB5XCIpLCBuKjggKVxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgYy5yZXQoYy5pMzJfY29uc3QoMCkpLFxuICAgICAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgICAgIGMuaTY0X2d0X3UoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9sb2FkKGMuZ2V0TG9jYWwoXCJweFwiKSwgbio4ICksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9sb2FkKGMuZ2V0TG9jYWwoXCJweVwiKSwgbio4IClcbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgYy5yZXQoYy5pMzJfY29uc3QoMSkpLFxuICAgICAgICAgICAgICAgICAgICBnZXRDb21wQ29kZShuLTEpXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGYuYWRkQ29kZShnZXRDb21wQ29kZShuNjQtMSkpO1xuICAgICAgICBmLmFkZENvZGUoYy5yZXQoYy5pMzJfY29uc3QoMCkpKTtcbiAgICB9XG5cblxuXG4gICAgZnVuY3Rpb24gYnVpbGRBZGQoKSB7XG5cbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfYWRkXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInlcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLnNldFJldHVyblR5cGUoXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJjXCIsIFwiaTY0XCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgZi5hZGRDb2RlKGMuc2V0TG9jYWwoXG4gICAgICAgICAgICBcImNcIixcbiAgICAgICAgICAgIGMuaTY0X2FkZChcbiAgICAgICAgICAgICAgICBjLmk2NF9sb2FkMzJfdShjLmdldExvY2FsKFwieFwiKSksXG4gICAgICAgICAgICAgICAgYy5pNjRfbG9hZDMyX3UoYy5nZXRMb2NhbChcInlcIikpXG4gICAgICAgICAgICApXG4gICAgICAgICkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShjLmk2NF9zdG9yZTMyKFxuICAgICAgICAgICAgYy5nZXRMb2NhbChcInJcIiksXG4gICAgICAgICAgICBjLmdldExvY2FsKFwiY1wiKSxcbiAgICAgICAgKSk7XG5cbiAgICAgICAgZm9yIChsZXQgaT0xOyBpPG4zMjsgaSsrKSB7XG4gICAgICAgICAgICBmLmFkZENvZGUoYy5zZXRMb2NhbCggXCJjXCIsXG4gICAgICAgICAgICAgICAgYy5pNjRfYWRkKFxuICAgICAgICAgICAgICAgICAgICBjLmk2NF9hZGQoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9sb2FkMzJfdShjLmdldExvY2FsKFwieFwiKSwgNCppKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2xvYWQzMl91KGMuZ2V0TG9jYWwoXCJ5XCIpLCA0KmkpXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgIGMuaTY0X3Nocl91IChjLmdldExvY2FsKFwiY1wiKSwgYy5pNjRfY29uc3QoMzIpKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICkpO1xuXG4gICAgICAgICAgICBmLmFkZENvZGUoYy5pNjRfc3RvcmUzMihcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiclwiKSxcbiAgICAgICAgICAgICAgICBpKjQsXG4gICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImNcIilcbiAgICAgICAgICAgICkpO1xuICAgICAgICB9XG5cbiAgICAgICAgZi5hZGRDb2RlKGMuaTMyX3dyYXBfaTY0KGMuaTY0X3Nocl91IChjLmdldExvY2FsKFwiY1wiKSwgYy5pNjRfY29uc3QoMzIpKSkpO1xuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gYnVpbGRTdWIoKSB7XG5cbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfc3ViXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInlcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLnNldFJldHVyblR5cGUoXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJjXCIsIFwiaTY0XCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgZi5hZGRDb2RlKGMuc2V0TG9jYWwoXG4gICAgICAgICAgICBcImNcIixcbiAgICAgICAgICAgIGMuaTY0X3N1YihcbiAgICAgICAgICAgICAgICBjLmk2NF9sb2FkMzJfdShjLmdldExvY2FsKFwieFwiKSksXG4gICAgICAgICAgICAgICAgYy5pNjRfbG9hZDMyX3UoYy5nZXRMb2NhbChcInlcIikpXG4gICAgICAgICAgICApXG4gICAgICAgICkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShjLmk2NF9zdG9yZTMyKFxuICAgICAgICAgICAgYy5nZXRMb2NhbChcInJcIiksXG4gICAgICAgICAgICBjLmk2NF9hbmQoXG4gICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImNcIiksXG4gICAgICAgICAgICAgICAgYy5pNjRfY29uc3QoXCIweEZGRkZGRkZGXCIpXG4gICAgICAgICAgICApXG4gICAgICAgICkpO1xuXG4gICAgICAgIGZvciAobGV0IGk9MTsgaTxuMzI7IGkrKykge1xuICAgICAgICAgICAgZi5hZGRDb2RlKGMuc2V0TG9jYWwoIFwiY1wiLFxuICAgICAgICAgICAgICAgIGMuaTY0X2FkZChcbiAgICAgICAgICAgICAgICAgICAgYy5pNjRfc3ViKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfbG9hZDMyX3UoYy5nZXRMb2NhbChcInhcIiksIDQqaSksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9sb2FkMzJfdShjLmdldExvY2FsKFwieVwiKSwgNCppKVxuICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICBjLmk2NF9zaHJfcyAoYy5nZXRMb2NhbChcImNcIiksIGMuaTY0X2NvbnN0KDMyKSlcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApKTtcblxuICAgICAgICAgICAgZi5hZGRDb2RlKGMuaTY0X3N0b3JlMzIoXG4gICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInJcIiksXG4gICAgICAgICAgICAgICAgaSo0LFxuICAgICAgICAgICAgICAgIGMuaTY0X2FuZCggYy5nZXRMb2NhbChcImNcIiksIGMuaTY0X2NvbnN0KFwiMHhGRkZGRkZGRlwiKSlcbiAgICAgICAgICAgICkpO1xuICAgICAgICB9XG5cbiAgICAgICAgZi5hZGRDb2RlKGMuaTMyX3dyYXBfaTY0ICggYy5pNjRfc2hyX3MgKGMuZ2V0TG9jYWwoXCJjXCIpLCBjLmk2NF9jb25zdCgzMikpKSk7XG4gICAgfVxuXG5cbiAgICBmdW5jdGlvbiBidWlsZE11bCgpIHtcblxuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9tdWxcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ4XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJjMFwiLCBcImk2NFwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImMxXCIsIFwiaTY0XCIpO1xuXG5cbiAgICAgICAgZm9yIChsZXQgaT0wO2k8bjMyOyBpKyspIHtcbiAgICAgICAgICAgIGYuYWRkTG9jYWwoXCJ4XCIraSwgXCJpNjRcIik7XG4gICAgICAgICAgICBmLmFkZExvY2FsKFwieVwiK2ksIFwiaTY0XCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCBsb2FkWCA9IFtdO1xuICAgICAgICBjb25zdCBsb2FkWSA9IFtdO1xuICAgICAgICBmdW5jdGlvbiBtdWxpaihpLCBqKSB7XG4gICAgICAgICAgICBsZXQgWCxZO1xuICAgICAgICAgICAgaWYgKCFsb2FkWFtpXSkge1xuICAgICAgICAgICAgICAgIFggPSBjLnRlZUxvY2FsKFwieFwiK2ksIGMuaTY0X2xvYWQzMl91KCBjLmdldExvY2FsKFwieFwiKSwgaSo0KSk7XG4gICAgICAgICAgICAgICAgbG9hZFhbaV0gPSB0cnVlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBYID0gYy5nZXRMb2NhbChcInhcIitpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghbG9hZFlbal0pIHtcbiAgICAgICAgICAgICAgICBZID0gYy50ZWVMb2NhbChcInlcIitqLCBjLmk2NF9sb2FkMzJfdSggYy5nZXRMb2NhbChcInlcIiksIGoqNCkpO1xuICAgICAgICAgICAgICAgIGxvYWRZW2pdID0gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgWSA9IGMuZ2V0TG9jYWwoXCJ5XCIraik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBjLmk2NF9tdWwoIFgsIFkgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBjMCA9IFwiYzBcIjtcbiAgICAgICAgbGV0IGMxID0gXCJjMVwiO1xuXG4gICAgICAgIGZvciAobGV0IGs9MDsgazxuMzIqMi0xOyBrKyspIHtcbiAgICAgICAgICAgIGZvciAobGV0IGk9TWF0aC5tYXgoMCwgay1uMzIrMSk7IChpPD1rKSYmKGk8bjMyKTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgaj0gay1pO1xuXG4gICAgICAgICAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgICAgICAgICBjLnNldExvY2FsKGMwLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2FuZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChjMCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2NvbnN0KDB4RkZGRkZGRkYpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdWxpaihpLGopXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgICAgICAgICBjLnNldExvY2FsKGMxLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoYzEpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X3Nocl91KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKGMwKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfY29uc3QoMzIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICAgICAgYy5pNjRfc3RvcmUzMihcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInJcIiksXG4gICAgICAgICAgICAgICAgICAgIGsqNCxcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChjMClcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgW2MwLCBjMV0gPSBbYzEsIGMwXTtcbiAgICAgICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKGMxLFxuICAgICAgICAgICAgICAgICAgICBjLmk2NF9zaHJfdShcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoYzApLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfY29uc3QoMzIpXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuaTY0X3N0b3JlMzIoXG4gICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInJcIiksXG4gICAgICAgICAgICAgICAgbjMyKjQqMi00LFxuICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoYzApXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG5cbiAgICB9XG5cblxuXG4gICAgZnVuY3Rpb24gYnVpbGRTcXVhcmUoKSB7XG5cbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfc3F1YXJlXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJjMFwiLCBcImk2NFwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImMxXCIsIFwiaTY0XCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiYzBfb2xkXCIsIFwiaTY0XCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiYzFfb2xkXCIsIFwiaTY0XCIpO1xuXG5cbiAgICAgICAgZm9yIChsZXQgaT0wO2k8bjMyOyBpKyspIHtcbiAgICAgICAgICAgIGYuYWRkTG9jYWwoXCJ4XCIraSwgXCJpNjRcIik7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IGxvYWRYID0gW107XG4gICAgICAgIGZ1bmN0aW9uIG11bGlqKGksIGopIHtcbiAgICAgICAgICAgIGxldCBYLFk7XG4gICAgICAgICAgICBpZiAoIWxvYWRYW2ldKSB7XG4gICAgICAgICAgICAgICAgWCA9IGMudGVlTG9jYWwoXCJ4XCIraSwgYy5pNjRfbG9hZDMyX3UoIGMuZ2V0TG9jYWwoXCJ4XCIpLCBpKjQpKTtcbiAgICAgICAgICAgICAgICBsb2FkWFtpXSA9IHRydWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIFggPSBjLmdldExvY2FsKFwieFwiK2kpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFsb2FkWFtqXSkge1xuICAgICAgICAgICAgICAgIFkgPSBjLnRlZUxvY2FsKFwieFwiK2osIGMuaTY0X2xvYWQzMl91KCBjLmdldExvY2FsKFwieFwiKSwgaio0KSk7XG4gICAgICAgICAgICAgICAgbG9hZFhbal0gPSB0cnVlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBZID0gYy5nZXRMb2NhbChcInhcIitqKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIGMuaTY0X211bCggWCwgWSApO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGMwID0gXCJjMFwiO1xuICAgICAgICBsZXQgYzEgPSBcImMxXCI7XG4gICAgICAgIGxldCBjMF9vbGQgPSBcImMwX29sZFwiO1xuICAgICAgICBsZXQgYzFfb2xkID0gXCJjMV9vbGRcIjtcblxuICAgICAgICBmb3IgKGxldCBrPTA7IGs8bjMyKjItMTsgaysrKSB7XG4gICAgICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChjMCwgYy5pNjRfY29uc3QoMCkpLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoYzEsIGMuaTY0X2NvbnN0KDApKSxcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGZvciAobGV0IGk9TWF0aC5tYXgoMCwgay1uMzIrMSk7IChpPCgoaysxKT4+MSkgKSYmKGk8bjMyKTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgaj0gay1pO1xuXG4gICAgICAgICAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgICAgICAgICBjLnNldExvY2FsKGMwLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2FuZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChjMCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2NvbnN0KDB4RkZGRkZGRkYpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdWxpaihpLGopXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgICAgICAgICBjLnNldExvY2FsKGMxLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoYzEpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X3Nocl91KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKGMwKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfY29uc3QoMzIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTXVsdGlwbHkgYnkgMlxuICAgICAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoYzAsXG4gICAgICAgICAgICAgICAgICAgIGMuaTY0X3NobChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2FuZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKGMwKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9jb25zdCgweEZGRkZGRkZGKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2NvbnN0KDEpXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChjMSxcbiAgICAgICAgICAgICAgICAgICAgYy5pNjRfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfc2hsKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoYzEpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2NvbnN0KDEpXG4gICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfc2hyX3UoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChjMCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfY29uc3QoMzIpXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICBpZiAoayUyID09IDApIHtcbiAgICAgICAgICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoYzAsXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9hZGQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfYW5kKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKGMwKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfY29uc3QoMHhGRkZGRkZGRilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11bGlqKGs+PjEsIGs+PjEpXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgICAgICAgICBjLnNldExvY2FsKGMxLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoYzEpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X3Nocl91KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKGMwKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfY29uc3QoMzIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQWRkIHRoZSBvbGQgY2FycnlcblxuICAgICAgICAgICAgaWYgKGs+MCkge1xuICAgICAgICAgICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgICAgICAgICAgYy5zZXRMb2NhbChjMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9hbmQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoYzApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9jb25zdCgweEZGRkZGRkZGKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfYW5kKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKGMwX29sZCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2NvbnN0KDB4RkZGRkZGRkYpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoYzEsXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9hZGQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKGMxKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfc2hyX3UoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKGMwKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2NvbnN0KDMyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKGMxX29sZClcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgICAgICBjLmk2NF9zdG9yZTMyKFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiclwiKSxcbiAgICAgICAgICAgICAgICAgICAgayo0LFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKGMwKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgICAgICBjMF9vbGQsXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoYzEpXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgICAgICBjMV9vbGQsXG4gICAgICAgICAgICAgICAgICAgIGMuaTY0X3Nocl91KFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChjMF9vbGQpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfY29uc3QoMzIpXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuXG4gICAgICAgIH1cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5pNjRfc3RvcmUzMihcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiclwiKSxcbiAgICAgICAgICAgICAgICBuMzIqNCoyLTQsXG4gICAgICAgICAgICAgICAgYy5nZXRMb2NhbChjMF9vbGQpXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG5cbiAgICB9XG5cblxuICAgIGZ1bmN0aW9uIGJ1aWxkU3F1YXJlT2xkKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9zcXVhcmVPbGRcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ4XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiclwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGYuYWRkQ29kZShjLmNhbGwocHJlZml4ICsgXCJfbXVsXCIsIGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmdldExvY2FsKFwieFwiKSwgYy5nZXRMb2NhbChcInJcIikpKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBfYnVpbGRNdWwxKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9fbXVsMVwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInB4XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieVwiLCBcImk2NFwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInByXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiY1wiLCBcImk2NFwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGYuYWRkQ29kZShjLnNldExvY2FsKFxuICAgICAgICAgICAgXCJjXCIsXG4gICAgICAgICAgICBjLmk2NF9tdWwoXG4gICAgICAgICAgICAgICAgYy5pNjRfbG9hZDMyX3UoYy5nZXRMb2NhbChcInB4XCIpLCAwLCAwKSxcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwieVwiKVxuICAgICAgICAgICAgKVxuICAgICAgICApKTtcblxuICAgICAgICBmLmFkZENvZGUoYy5pNjRfc3RvcmUzMihcbiAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwclwiKSxcbiAgICAgICAgICAgIDAsXG4gICAgICAgICAgICAwLFxuICAgICAgICAgICAgYy5nZXRMb2NhbChcImNcIiksXG4gICAgICAgICkpO1xuXG4gICAgICAgIGZvciAobGV0IGk9MTsgaTxuMzI7IGkrKykge1xuICAgICAgICAgICAgZi5hZGRDb2RlKGMuc2V0TG9jYWwoIFwiY1wiLFxuICAgICAgICAgICAgICAgIGMuaTY0X2FkZChcbiAgICAgICAgICAgICAgICAgICAgYy5pNjRfbXVsKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfbG9hZDMyX3UoYy5nZXRMb2NhbChcInB4XCIpLCA0KmksIDApLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInlcIilcbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pNjRfc2hyX3UgKGMuZ2V0TG9jYWwoXCJjXCIpLCBjLmk2NF9jb25zdCgzMikpXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSk7XG5cbiAgICAgICAgICAgIGYuYWRkQ29kZShjLmk2NF9zdG9yZTMyKFxuICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwclwiKSxcbiAgICAgICAgICAgICAgICBpKjQsXG4gICAgICAgICAgICAgICAgMCxcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiY1wiKVxuICAgICAgICAgICAgKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBfYnVpbGRBZGQxKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9fYWRkMVwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ5XCIsIFwiaTY0XCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiY1wiLCBcImk2NFwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcInB4XCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgZi5hZGRDb2RlKGMuc2V0TG9jYWwoXCJweFwiLCBjLmdldExvY2FsKFwieFwiKSkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShjLnNldExvY2FsKFxuICAgICAgICAgICAgXCJjXCIsXG4gICAgICAgICAgICBjLmk2NF9hZGQoXG4gICAgICAgICAgICAgICAgYy5pNjRfbG9hZDMyX3UoYy5nZXRMb2NhbChcInB4XCIpLCAwLCAwKSxcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwieVwiKVxuICAgICAgICAgICAgKVxuICAgICAgICApKTtcblxuICAgICAgICBmLmFkZENvZGUoYy5pNjRfc3RvcmUzMihcbiAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJweFwiKSxcbiAgICAgICAgICAgIDAsXG4gICAgICAgICAgICAwLFxuICAgICAgICAgICAgYy5nZXRMb2NhbChcImNcIiksXG4gICAgICAgICkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShjLnNldExvY2FsKFxuICAgICAgICAgICAgXCJjXCIsXG4gICAgICAgICAgICBjLmk2NF9zaHJfdShcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiY1wiKSxcbiAgICAgICAgICAgICAgICBjLmk2NF9jb25zdCgzMilcbiAgICAgICAgICAgIClcbiAgICAgICAgKSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKGMuYmxvY2soYy5sb29wKFxuICAgICAgICAgICAgYy5icl9pZihcbiAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgIGMuaTY0X2VxeihjLmdldExvY2FsKFwiY1wiKSlcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgIFwicHhcIixcbiAgICAgICAgICAgICAgICBjLmkzMl9hZGQoXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJweFwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoNClcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApLFxuXG4gICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgIFwiY1wiLFxuICAgICAgICAgICAgICAgIGMuaTY0X2FkZChcbiAgICAgICAgICAgICAgICAgICAgYy5pNjRfbG9hZDMyX3UoYy5nZXRMb2NhbChcInB4XCIpLCAwLCAwKSxcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImNcIilcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApLFxuXG4gICAgICAgICAgICBjLmk2NF9zdG9yZTMyKFxuICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJweFwiKSxcbiAgICAgICAgICAgICAgICAwLFxuICAgICAgICAgICAgICAgIDAsXG4gICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImNcIiksXG4gICAgICAgICAgICApLFxuXG4gICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgIFwiY1wiLFxuICAgICAgICAgICAgICAgIGMuaTY0X3Nocl91KFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiY1wiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pNjRfY29uc3QoMzIpXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgYy5icigwKVxuICAgICAgICApKSk7XG4gICAgfVxuXG5cbiAgICBmdW5jdGlvbiBidWlsZERpdigpIHtcbiAgICAgICAgX2J1aWxkTXVsMSgpO1xuICAgICAgICBfYnVpbGRBZGQxKCk7XG5cbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfZGl2XCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInlcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJjXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiclwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcInJyXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiY2NcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJlWFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImVZXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwic3lcIiwgXCJpNjRcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJzeFwiLCBcImk2NFwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImVjXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgWSA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuICAgICAgICBjb25zdCBDYXV4ID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IFJhdXggPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgQyA9IGMuZ2V0TG9jYWwoXCJjY1wiKTtcbiAgICAgICAgY29uc3QgUiA9IGMuZ2V0TG9jYWwoXCJyclwiKTtcbiAgICAgICAgY29uc3QgcHIxID0gbW9kdWxlLmFsbG9jKG44KjIpO1xuICAgICAgICBjb25zdCBSMSA9IGMuaTMyX2NvbnN0KHByMSk7XG4gICAgICAgIGNvbnN0IFIyID0gYy5pMzJfY29uc3QocHIxK244KTtcblxuICAgICAgICAvLyBJYyBjIGlzIDAgdGhlbiBzdG9yZSBpdCBpbiBhbiBhdXhpbGlhcnkgYnVmZmVyXG4gICAgICAgIGYuYWRkQ29kZShjLmlmKFxuICAgICAgICAgICAgYy5nZXRMb2NhbChcImNcIiksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiY2NcIiwgYy5nZXRMb2NhbChcImNcIikpLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcImNjXCIsIENhdXgpXG4gICAgICAgICkpO1xuXG4gICAgICAgIC8vIEljIHIgaXMgMCB0aGVuIHN0b3JlIGl0IGluIGFuIGF1eGlsaWFyeSBidWZmZXJcbiAgICAgICAgZi5hZGRDb2RlKGMuaWYoXG4gICAgICAgICAgICBjLmdldExvY2FsKFwiclwiKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJyclwiLCBjLmdldExvY2FsKFwiclwiKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwicnJcIiwgUmF1eClcbiAgICAgICAgKSk7XG5cbiAgICAgICAgLy8gQ29weVxuICAgICAgICBmLmFkZENvZGUoYy5jYWxsKHByZWZpeCArIFwiX2NvcHlcIiwgYy5nZXRMb2NhbChcInhcIiksIFIpKTtcbiAgICAgICAgZi5hZGRDb2RlKGMuY2FsbChwcmVmaXggKyBcIl9jb3B5XCIsIGMuZ2V0TG9jYWwoXCJ5XCIpLCBZKSk7XG4gICAgICAgIGYuYWRkQ29kZShjLmNhbGwocHJlZml4ICsgXCJfemVyb1wiLCBDKSk7XG4gICAgICAgIGYuYWRkQ29kZShjLmNhbGwocHJlZml4ICsgXCJfemVyb1wiLCBSMSkpO1xuXG5cbiAgICAgICAgZi5hZGRDb2RlKGMuc2V0TG9jYWwoXCJlWFwiLCBjLmkzMl9jb25zdChuOC0xKSkpO1xuICAgICAgICBmLmFkZENvZGUoYy5zZXRMb2NhbChcImVZXCIsIGMuaTMyX2NvbnN0KG44LTEpKSk7XG5cbiAgICAgICAgLy8gd2hpbGUgKGVZPjMpJiYoWVtlWV09PTApIGV5LS07XG4gICAgICAgIGYuYWRkQ29kZShjLmJsb2NrKGMubG9vcChcbiAgICAgICAgICAgIGMuYnJfaWYoXG4gICAgICAgICAgICAgICAgMSxcbiAgICAgICAgICAgICAgICBjLmkzMl9vcihcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfbG9hZDhfdShcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2FkZChZICwgYy5nZXRMb2NhbChcImVZXCIpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIDAsXG4gICAgICAgICAgICAgICAgICAgICAgICAwXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2VxKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImVZXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMylcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiZVlcIiwgYy5pMzJfc3ViKGMuZ2V0TG9jYWwoXCJlWVwiKSwgYy5pMzJfY29uc3QoMSkpKSxcbiAgICAgICAgICAgIGMuYnIoMClcbiAgICAgICAgKSkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgXCJzeVwiLFxuICAgICAgICAgICAgICAgIGMuaTY0X2FkZChcbiAgICAgICAgICAgICAgICAgICAgYy5pNjRfbG9hZDMyX3UoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9zdWIoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfYWRkKCBZLCBjLmdldExvY2FsKFwiZVlcIikpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDMpXG4gICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIDBcbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pNjRfY29uc3QoMSlcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gRm9yY2UgYSBkaXZpZGUgYnkgMCBpZiBxdW90aWVuIGlzIDBcbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmk2NF9lcShcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInN5XCIpLFxuICAgICAgICAgICAgICAgICAgICBjLmk2NF9jb25zdCgxKVxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgYy5kcm9wKGMuaTY0X2Rpdl91KGMuaTY0X2NvbnN0KDApLCBjLmk2NF9jb25zdCgwKSkpXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG5cbiAgICAgICAgZi5hZGRDb2RlKGMuYmxvY2soYy5sb29wKFxuXG4gICAgICAgICAgICAvLyB3aGlsZSAoZVg+NykmJihZW2VYXT09MCkgZXgtLTtcbiAgICAgICAgICAgIGMuYmxvY2soYy5sb29wKFxuICAgICAgICAgICAgICAgIGMuYnJfaWYoXG4gICAgICAgICAgICAgICAgICAgIDEsXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX29yKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfbG9hZDhfdShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9hZGQoUiAsIGMuZ2V0TG9jYWwoXCJlWFwiKSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAwXG4gICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfZXEoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImVYXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDcpXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJlWFwiLCBjLmkzMl9zdWIoYy5nZXRMb2NhbChcImVYXCIpLCBjLmkzMl9jb25zdCgxKSkpLFxuICAgICAgICAgICAgICAgIGMuYnIoMClcbiAgICAgICAgICAgICkpLFxuXG4gICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgIFwic3hcIixcbiAgICAgICAgICAgICAgICBjLmk2NF9sb2FkKFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9zdWIoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9hZGQoIFIsIGMuZ2V0TG9jYWwoXCJlWFwiKSksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdCg3KVxuICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAwLFxuICAgICAgICAgICAgICAgICAgICAwXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgYy5zZXRMb2NhbChcbiAgICAgICAgICAgICAgICBcInN4XCIsXG4gICAgICAgICAgICAgICAgYy5pNjRfZGl2X3UoXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJzeFwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInN5XCIpXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgXCJlY1wiLFxuICAgICAgICAgICAgICAgIGMuaTMyX3N1YihcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfc3ViKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImVYXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImVZXCIpXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDQpXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgLy8gV2hpbGUgZ3JlYXRlciB0aGFuIDMyIGJpdHMgb3IgZWMgaXMgbmVnLCBzaHIgYW5kIGluYyBleHBcbiAgICAgICAgICAgIGMuYmxvY2soYy5sb29wKFxuICAgICAgICAgICAgICAgIGMuYnJfaWYoXG4gICAgICAgICAgICAgICAgICAgIDEsXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2FuZChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2VxeihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9hbmQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJzeFwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfY29uc3QoXCIweEZGRkZGRkZGMDAwMDAwMDBcIilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfZ2VfcyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiZWNcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMClcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgICAgICBcInN4XCIsXG4gICAgICAgICAgICAgICAgICAgIGMuaTY0X3Nocl91KFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInN4XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfY29uc3QoOClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgICAgICBcImVjXCIsXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJlY1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDEpXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGMuYnIoMClcbiAgICAgICAgICAgICkpLFxuXG4gICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgIGMuaTY0X2VxeihjLmdldExvY2FsKFwic3hcIikpLFxuICAgICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5icl9pZihcbiAgICAgICAgICAgICAgICAgICAgICAgIDIsXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9lcXooYy5jYWxsKHByZWZpeCArIFwiX2d0ZVwiLCBSLCBZKSlcbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5zZXRMb2NhbChcInN4XCIsIGMuaTY0X2NvbnN0KDEpKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5zZXRMb2NhbChcImVjXCIsIGMuaTMyX2NvbnN0KDApKVxuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9fbXVsMVwiLCBZLCBjLmdldExvY2FsKFwic3hcIiksIFIyKSxcbiAgICAgICAgICAgIGMuZHJvcChjLmNhbGwoXG4gICAgICAgICAgICAgICAgcHJlZml4ICsgXCJfc3ViXCIsXG4gICAgICAgICAgICAgICAgUixcbiAgICAgICAgICAgICAgICBjLmkzMl9zdWIoUjIsIGMuZ2V0TG9jYWwoXCJlY1wiKSksXG4gICAgICAgICAgICAgICAgUlxuICAgICAgICAgICAgKSksXG4gICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgcHJlZml4ICsgXCJfX2FkZDFcIixcbiAgICAgICAgICAgICAgICBjLmkzMl9hZGQoQywgYy5nZXRMb2NhbChcImVjXCIpKSxcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwic3hcIilcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLmJyKDApXG4gICAgICAgICkpKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZEludmVyc2VNb2QoKSB7XG5cbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfaW52ZXJzZU1vZFwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInB4XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicG1cIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwclwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcInRcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJuZXd0XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiclwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcInFxXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwicXJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJuZXdyXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwic3dwXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcInNpZ250XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwic2lnbm5ld3RcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJzaWdueFwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IGF1eDEgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgYXV4MiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuICAgICAgICBjb25zdCBhdXgzID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IGF1eDQgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgYXV4NSA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuICAgICAgICBjb25zdCBhdXg2ID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IG11bEJ1ZmYgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgqMikpO1xuICAgICAgICBjb25zdCBhdXg3ID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcInRcIiwgYXV4MSksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfemVyb1wiLCBhdXgxKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJzaWdudFwiLCBjLmkzMl9jb25zdCgwKSksXG4gICAgICAgICk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcInJcIiwgYXV4MiksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfY29weVwiLCBjLmdldExvY2FsKFwicG1cIiksIGF1eDIpXG4gICAgICAgICk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcIm5ld3RcIiwgYXV4MyksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfb25lXCIsIGF1eDMpLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcInNpZ25uZXd0XCIsIGMuaTMyX2NvbnN0KDApKSxcbiAgICAgICAgKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLnNldExvY2FsKFwibmV3clwiLCBhdXg0KSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9jb3B5XCIsIGMuZ2V0TG9jYWwoXCJweFwiKSwgYXV4NClcbiAgICAgICAgKTtcblxuXG5cblxuICAgICAgICBmLmFkZENvZGUoYy5zZXRMb2NhbChcInFxXCIsIGF1eDUpKTtcbiAgICAgICAgZi5hZGRDb2RlKGMuc2V0TG9jYWwoXCJxclwiLCBhdXg2KSk7XG4gICAgICAgIGYuYWRkQ29kZShjLnNldExvY2FsKFwieFwiLCBhdXg3KSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKGMuYmxvY2soYy5sb29wKFxuICAgICAgICAgICAgYy5icl9pZihcbiAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9pc1plcm9cIiwgYy5nZXRMb2NhbChcIm5ld3JcIikgKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9kaXZcIiwgYy5nZXRMb2NhbChcInJcIiksIGMuZ2V0TG9jYWwoXCJuZXdyXCIpLCBjLmdldExvY2FsKFwicXFcIiksIGMuZ2V0TG9jYWwoXCJxclwiKSksXG5cbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9tdWxcIiwgYy5nZXRMb2NhbChcInFxXCIpLCBjLmdldExvY2FsKFwibmV3dFwiKSwgbXVsQnVmZiksXG5cbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInNpZ250XCIpLFxuICAgICAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJzaWdubmV3dFwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfZ3RlXCIsIG11bEJ1ZmYsIGMuZ2V0TG9jYWwoXCJ0XCIpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5jLmRyb3AoYy5jYWxsKHByZWZpeCArIFwiX3N1YlwiLCBtdWxCdWZmLCBjLmdldExvY2FsKFwidFwiKSwgYy5nZXRMb2NhbChcInhcIikpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5jLnNldExvY2FsKFwic2lnbnhcIiwgYy5pMzJfY29uc3QoMCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuZHJvcChjLmNhbGwocHJlZml4ICsgXCJfc3ViXCIsIGMuZ2V0TG9jYWwoXCJ0XCIpLCBtdWxCdWZmLCBjLmdldExvY2FsKFwieFwiKSkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuc2V0TG9jYWwoXCJzaWdueFwiLCBjLmkzMl9jb25zdCgxKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuZHJvcChjLmNhbGwocHJlZml4ICsgXCJfYWRkXCIsIG11bEJ1ZmYsIGMuZ2V0TG9jYWwoXCJ0XCIpLCBjLmdldExvY2FsKFwieFwiKSkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgLi4uYy5zZXRMb2NhbChcInNpZ254XCIsIGMuaTMyX2NvbnN0KDEpKVxuICAgICAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwic2lnbm5ld3RcIiksXG4gICAgICAgICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuZHJvcChjLmNhbGwocHJlZml4ICsgXCJfYWRkXCIsIG11bEJ1ZmYsIGMuZ2V0TG9jYWwoXCJ0XCIpLCBjLmdldExvY2FsKFwieFwiKSkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgLi4uYy5zZXRMb2NhbChcInNpZ254XCIsIGMuaTMyX2NvbnN0KDApKVxuICAgICAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICAgICAgICBjLmlmIChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9ndGVcIiwgYy5nZXRMb2NhbChcInRcIiksIG11bEJ1ZmYpLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuZHJvcChjLmNhbGwocHJlZml4ICsgXCJfc3ViXCIsIGMuZ2V0TG9jYWwoXCJ0XCIpLCBtdWxCdWZmLCBjLmdldExvY2FsKFwieFwiKSkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuc2V0TG9jYWwoXCJzaWdueFwiLCBjLmkzMl9jb25zdCgwKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uYy5kcm9wKGMuY2FsbChwcmVmaXggKyBcIl9zdWJcIiwgbXVsQnVmZiwgYy5nZXRMb2NhbChcInRcIiksIGMuZ2V0TG9jYWwoXCJ4XCIpKSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uYy5zZXRMb2NhbChcInNpZ254XCIsIGMuaTMyX2NvbnN0KDEpKVxuICAgICAgICAgICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgYy5zZXRMb2NhbChcInN3cFwiLCBjLmdldExvY2FsKFwidFwiKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwidFwiLCBjLmdldExvY2FsKFwibmV3dFwiKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwibmV3dFwiLCBjLmdldExvY2FsKFwieFwiKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwieFwiLCBjLmdldExvY2FsKFwic3dwXCIpKSxcblxuICAgICAgICAgICAgYy5zZXRMb2NhbChcInNpZ250XCIsIGMuZ2V0TG9jYWwoXCJzaWdubmV3dFwiKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwic2lnbm5ld3RcIiwgYy5nZXRMb2NhbChcInNpZ254XCIpKSxcblxuICAgICAgICAgICAgYy5zZXRMb2NhbChcInN3cFwiLCBjLmdldExvY2FsKFwiclwiKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiclwiLCBjLmdldExvY2FsKFwibmV3clwiKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwibmV3clwiLCBjLmdldExvY2FsKFwicXJcIikpLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcInFyXCIsIGMuZ2V0TG9jYWwoXCJzd3BcIikpLFxuXG4gICAgICAgICAgICBjLmJyKDApXG4gICAgICAgICkpKTtcblxuICAgICAgICBmLmFkZENvZGUoYy5pZihcbiAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJzaWdudFwiKSxcbiAgICAgICAgICAgIGMuZHJvcChjLmNhbGwocHJlZml4ICsgXCJfc3ViXCIsIGMuZ2V0TG9jYWwoXCJwbVwiKSwgYy5nZXRMb2NhbChcInRcIiksIGMuZ2V0TG9jYWwoXCJwclwiKSkpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX2NvcHlcIiwgYy5nZXRMb2NhbChcInRcIiksIGMuZ2V0TG9jYWwoXCJwclwiKSlcbiAgICAgICAgKSk7XG4gICAgfVxuXG5cbiAgICBidWlsZENvcHkoKTtcbiAgICBidWlsZFplcm8oKTtcbiAgICBidWlsZElzWmVybygpO1xuICAgIGJ1aWxkT25lKCk7XG4gICAgYnVpbGRFcSgpO1xuICAgIGJ1aWxkR3RlKCk7XG4gICAgYnVpbGRBZGQoKTtcbiAgICBidWlsZFN1YigpO1xuICAgIGJ1aWxkTXVsKCk7XG4gICAgYnVpbGRTcXVhcmUoKTtcbiAgICBidWlsZFNxdWFyZU9sZCgpO1xuICAgIGJ1aWxkRGl2KCk7XG4gICAgYnVpbGRJbnZlcnNlTW9kKCk7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCtcIl9jb3B5XCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXgrXCJfemVyb1wiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4K1wiX29uZVwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4K1wiX2lzWmVyb1wiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4K1wiX2VxXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXgrXCJfZ3RlXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXgrXCJfYWRkXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXgrXCJfc3ViXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXgrXCJfbXVsXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXgrXCJfc3F1YXJlXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXgrXCJfc3F1YXJlT2xkXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXgrXCJfZGl2XCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXgrXCJfaW52ZXJzZU1vZFwiKTtcblxuICAgIHJldHVybiBwcmVmaXg7XG59O1xuXG4vKlxuICAgIENvcHlyaWdodCAyMDE5IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygd2FzbXNuYXJrIChXZWIgQXNzZW1ibHkgemtTbmFyayBQcm92ZXIpLlxuXG4gICAgd2FzbXNuYXJrIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICAgIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gICAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAgICAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgd2FzbXNuYXJrIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHdhc21zbmFyay4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbnZhciBidWlsZF90aW1lc3NjYWxhciA9IGZ1bmN0aW9uIGJ1aWxkVGltZXNTY2FsYXIobW9kdWxlLCBmbk5hbWUsIGVsZW1lbnRMZW4sIG9wQUIsIG9wQUEsIG9wQ29weSwgb3BJbml0KSB7XG5cbiAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKGZuTmFtZSk7XG4gICAgZi5hZGRQYXJhbShcImJhc2VcIiwgXCJpMzJcIik7XG4gICAgZi5hZGRQYXJhbShcInNjYWxhclwiLCBcImkzMlwiKTtcbiAgICBmLmFkZFBhcmFtKFwic2NhbGFyTGVuZ3RoXCIsIFwiaTMyXCIpO1xuICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuICAgIGYuYWRkTG9jYWwoXCJpXCIsIFwiaTMyXCIpO1xuICAgIGYuYWRkTG9jYWwoXCJiXCIsIFwiaTMyXCIpO1xuXG4gICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgIGNvbnN0IGF1eCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhlbGVtZW50TGVuKSk7XG5cbiAgICBmLmFkZENvZGUoXG4gICAgICAgIGMuaWYoXG4gICAgICAgICAgICBjLmkzMl9lcXooYy5nZXRMb2NhbChcInNjYWxhckxlbmd0aFwiKSksXG4gICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgLi4uYy5jYWxsKG9wSW5pdCwgYy5nZXRMb2NhbChcInJcIikpLFxuICAgICAgICAgICAgICAgIC4uLmMucmV0KFtdKVxuICAgICAgICAgICAgXVxuICAgICAgICApXG4gICAgKTtcbiAgICBmLmFkZENvZGUoYy5jYWxsKG9wQ29weSwgYy5nZXRMb2NhbChcImJhc2VcIiksIGF1eCkpO1xuICAgIGYuYWRkQ29kZShjLmNhbGwob3BJbml0LCBjLmdldExvY2FsKFwiclwiKSkpO1xuICAgIGYuYWRkQ29kZShjLnNldExvY2FsKFwiaVwiLCBjLmdldExvY2FsKFwic2NhbGFyTGVuZ3RoXCIpKSk7XG4gICAgZi5hZGRDb2RlKGMuYmxvY2soYy5sb29wKFxuICAgICAgICBjLnNldExvY2FsKFwiaVwiLCBjLmkzMl9zdWIoYy5nZXRMb2NhbChcImlcIiksIGMuaTMyX2NvbnN0KDEpKSksXG5cbiAgICAgICAgYy5zZXRMb2NhbChcbiAgICAgICAgICAgIFwiYlwiLFxuICAgICAgICAgICAgYy5pMzJfbG9hZDhfdShcbiAgICAgICAgICAgICAgICBjLmkzMl9hZGQoXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJzY2FsYXJcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpXCIpXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKVxuICAgICAgICApLFxuICAgICAgICAuLi5pbm5lckxvb3AoKSxcbiAgICAgICAgYy5icl9pZigxLCBjLmkzMl9lcXogKCBjLmdldExvY2FsKFwiaVwiKSApKSxcbiAgICAgICAgYy5icigwKVxuICAgICkpKTtcblxuXG4gICAgZnVuY3Rpb24gaW5uZXJMb29wKCkge1xuICAgICAgICBjb25zdCBjb2RlID0gW107XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTw4OyBpKyspIHtcbiAgICAgICAgICAgIGNvZGUucHVzaChcbiAgICAgICAgICAgICAgICAuLi5jLmNhbGwob3BBQSwgYy5nZXRMb2NhbChcInJcIiksIGMuZ2V0TG9jYWwoXCJyXCIpKSxcbiAgICAgICAgICAgICAgICAuLi5jLmlmKFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9nZV91KCBjLmdldExvY2FsKFwiYlwiKSwgYy5pMzJfY29uc3QoMHg4MCA+PiBpKSksXG4gICAgICAgICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJiXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfc3ViKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiYlwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMHg4MCA+PiBpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwob3BBQiwgYy5nZXRMb2NhbChcInJcIiksYXV4LCBjLmdldExvY2FsKFwiclwiKSlcbiAgICAgICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNvZGU7XG4gICAgfVxuXG59O1xuXG52YXIgYnVpbGRfYmF0Y2hpbnZlcnNlID0gYnVpbGRCYXRjaEludmVyc2UkMztcblxuZnVuY3Rpb24gYnVpbGRCYXRjaEludmVyc2UkMyhtb2R1bGUsIHByZWZpeCkge1xuXG5cbiAgICBjb25zdCBuOCA9IG1vZHVsZS5tb2R1bGVzW3ByZWZpeF0ubjY0Kjg7XG5cbiAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9iYXRjaEludmVyc2VcIik7XG4gICAgZi5hZGRQYXJhbShcInBJblwiLCBcImkzMlwiKTtcbiAgICBmLmFkZFBhcmFtKFwiaW5TdGVwXCIsIFwiaTMyXCIpO1xuICAgIGYuYWRkUGFyYW0oXCJuXCIsIFwiaTMyXCIpO1xuICAgIGYuYWRkUGFyYW0oXCJwT3V0XCIsIFwiaTMyXCIpO1xuICAgIGYuYWRkUGFyYW0oXCJvdXRTdGVwXCIsIFwiaTMyXCIpO1xuICAgIGYuYWRkTG9jYWwoXCJpdEF1eFwiLCBcImkzMlwiKTtcbiAgICBmLmFkZExvY2FsKFwiaXRJblwiLCBcImkzMlwiKTtcbiAgICBmLmFkZExvY2FsKFwiaXRPdXRcIixcImkzMlwiKTtcbiAgICBmLmFkZExvY2FsKFwiaVwiLFwiaTMyXCIpO1xuXG4gICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgIGNvbnN0IEFVWCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuXG5cbiAgICAvLyBBbGxvYyBXb3JraW5nIHNwYWNlIGZvciBhY2N1bXVsYXRlZCB1bWx0aXBsaWNhdGlvbnNcbiAgICBmLmFkZENvZGUoXG4gICAgICAgIGMuc2V0TG9jYWwoXCJpdEF1eFwiLCBjLmkzMl9sb2FkKCBjLmkzMl9jb25zdCgwKSApKSxcbiAgICAgICAgYy5pMzJfc3RvcmUoXG4gICAgICAgICAgICBjLmkzMl9jb25zdCgwKSxcbiAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaXRBdXhcIiksXG4gICAgICAgICAgICAgICAgYy5pMzJfbXVsKFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9hZGQoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiblwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDEpXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KG44KVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgIClcbiAgICAgICAgKVxuICAgICk7XG5cbiAgICBmLmFkZENvZGUoXG5cbiAgICAgICAgLy8gYXV4WzBdID0gYTtcbiAgICAgICAgYy5jYWxsKHByZWZpeCtcIl9vbmVcIiwgYy5nZXRMb2NhbChcIml0QXV4XCIpKSxcbiAgICAgICAgLy8gZm9yIChpPTA7aTxuO2krKykgYXV4W2ldID0gYXV4W2ktMV0qaW5baV1cbiAgICAgICAgYy5zZXRMb2NhbChcIml0SW5cIiwgYy5nZXRMb2NhbChcInBJblwiKSksXG4gICAgICAgIGMuc2V0TG9jYWwoXCJpdEF1eFwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcIml0QXV4XCIpLCBjLmkzMl9jb25zdChuOCkpKSxcbiAgICAgICAgYy5zZXRMb2NhbChcImlcIiwgYy5pMzJfY29uc3QoMCkpLFxuXG4gICAgICAgIGMuYmxvY2soYy5sb29wKFxuICAgICAgICAgICAgYy5icl9pZigxLCBjLmkzMl9lcSAoIGMuZ2V0TG9jYWwoXCJpXCIpLCBjLmdldExvY2FsKFwiblwiKSApKSxcbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeCtcIl9pc1plcm9cIiwgYy5nZXRMb2NhbChcIml0SW5cIikpLFxuICAgICAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgcHJlZml4ICsgXCJfY29weVwiLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9zdWIoYy5nZXRMb2NhbChcIml0QXV4XCIpLCBjLmkzMl9jb25zdChuOCkpLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaXRBdXhcIilcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgcHJlZml4K1wiX211bFwiLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaXRJblwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfc3ViKGMuZ2V0TG9jYWwoXCJpdEF1eFwiKSwgYy5pMzJfY29uc3QobjgpKSxcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIml0QXV4XCIpXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpdEluXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwiaXRJblwiKSwgYy5nZXRMb2NhbChcImluU3RlcFwiKSkpLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcIml0QXV4XCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwiaXRBdXhcIiksIGMuaTMyX2NvbnN0KG44KSkpLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcImlcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJpXCIpLCBjLmkzMl9jb25zdCgxKSkpLFxuICAgICAgICAgICAgYy5icigwKVxuICAgICAgICApKSxcblxuICAgICAgICAvLyBwb2ludCB0byB0aGUgbGFzdFxuICAgICAgICBjLnNldExvY2FsKFwiaXRJblwiLCBjLmkzMl9zdWIoYy5nZXRMb2NhbChcIml0SW5cIiksIGMuZ2V0TG9jYWwoXCJpblN0ZXBcIikpKSxcbiAgICAgICAgYy5zZXRMb2NhbChcIml0QXV4XCIsIGMuaTMyX3N1YihjLmdldExvY2FsKFwiaXRBdXhcIiksIGMuaTMyX2NvbnN0KG44KSkpLFxuICAgICAgICAvLyBpdE91dCA9IHBPdXQgKyAobi0xKSpzdGVwT3V0ICAgLy8gUG9pbnQgdG8gdGhlIGxhc3RcbiAgICAgICAgYy5zZXRMb2NhbChcbiAgICAgICAgICAgIFwiaXRPdXRcIixcbiAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicE91dFwiKSxcbiAgICAgICAgICAgICAgICBjLmkzMl9tdWwoXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX3N1YihjLmdldExvY2FsKFwiblwiKSwgYy5pMzJfY29uc3QoMSkpLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwib3V0U3RlcFwiKSxcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApXG4gICAgICAgICksXG5cbiAgICAgICAgLy8gYXV4W24tMV0gPSAxL2F1eFtuLTFdXG4gICAgICAgIGMuY2FsbChwcmVmaXgrXCJfaW52ZXJzZVwiLCBjLmdldExvY2FsKFwiaXRBdXhcIiksIGMuZ2V0TG9jYWwoXCJpdEF1eFwiKSApLFxuXG4gICAgICAgIGMuYmxvY2soYy5sb29wKFxuICAgICAgICAgICAgYy5icl9pZigxLCBjLmkzMl9lcXooIGMuZ2V0TG9jYWwoXCJpXCIpKSksXG4gICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXgrXCJfaXNaZXJvXCIsIGMuZ2V0TG9jYWwoXCJpdEluXCIpKSxcbiAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZWZpeCArIFwiX2NvcHlcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpdEF1eFwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX3N1YihjLmdldExvY2FsKFwiaXRBdXhcIiksIGMuaTMyX2NvbnN0KG44KSksXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZWZpeCArIFwiX3plcm9cIixcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpdE91dFwiKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgXSxbXG4gICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChwcmVmaXggKyBcIl9jb3B5XCIsIGMuaTMyX3N1YihjLmdldExvY2FsKFwiaXRBdXhcIiksIGMuaTMyX2NvbnN0KG44KSksIEFVWCksXG4gICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZWZpeCtcIl9tdWxcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpdEF1eFwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpdEluXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfc3ViKGMuZ2V0TG9jYWwoXCJpdEF1eFwiKSwgYy5pMzJfY29uc3QobjgpKSxcbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5jYWxsKFxuICAgICAgICAgICAgICAgICAgICAgICAgcHJlZml4K1wiX211bFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIml0QXV4XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgQVVYLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIml0T3V0XCIpXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcIml0SW5cIiwgYy5pMzJfc3ViKGMuZ2V0TG9jYWwoXCJpdEluXCIpLCBjLmdldExvY2FsKFwiaW5TdGVwXCIpKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiaXRPdXRcIiwgYy5pMzJfc3ViKGMuZ2V0TG9jYWwoXCJpdE91dFwiKSwgYy5nZXRMb2NhbChcIm91dFN0ZXBcIikpKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpdEF1eFwiLCBjLmkzMl9zdWIoYy5nZXRMb2NhbChcIml0QXV4XCIpLCBjLmkzMl9jb25zdChuOCkpKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpXCIsIGMuaTMyX3N1YihjLmdldExvY2FsKFwiaVwiKSwgYy5pMzJfY29uc3QoMSkpKSxcbiAgICAgICAgICAgIGMuYnIoMClcbiAgICAgICAgKSlcblxuICAgICk7XG5cblxuICAgIC8vIFJlY292ZXIgT2xkIG1lbW9yeVxuICAgIGYuYWRkQ29kZShcbiAgICAgICAgYy5pMzJfc3RvcmUoXG4gICAgICAgICAgICBjLmkzMl9jb25zdCgwKSxcbiAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpdEF1eFwiKVxuICAgICAgICApXG4gICAgKTtcblxufVxuXG52YXIgYnVpbGRfYmF0Y2hjb252ZXJ0aW9uID0gYnVpbGRCYXRjaENvbnZlcnRpb24kMztcblxuZnVuY3Rpb24gYnVpbGRCYXRjaENvbnZlcnRpb24kMyhtb2R1bGUsIGZuTmFtZSwgaW50ZXJuYWxGbk5hbWUsIHNpemVJbiwgc2l6ZU91dCwgcmV2ZXJzZSkge1xuICAgIGlmICh0eXBlb2YgcmV2ZXJzZSA9PT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAvLyBTZXQgdGhlIHJldmVyc2UgaW4gYSB3YXkgdGhhdCBhbGxvd3MgdG8gdXNlIHRoZSBzYW1lIGJ1ZmZlciBhcyBpbi9vdXQuXG4gICAgICAgIGlmIChzaXplSW4gPCBzaXplT3V0KSB7XG4gICAgICAgICAgICByZXZlcnNlID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldmVyc2UgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24oZm5OYW1lKTtcbiAgICBmLmFkZFBhcmFtKFwicEluXCIsIFwiaTMyXCIpO1xuICAgIGYuYWRkUGFyYW0oXCJuXCIsIFwiaTMyXCIpO1xuICAgIGYuYWRkUGFyYW0oXCJwT3V0XCIsIFwiaTMyXCIpO1xuICAgIGYuYWRkTG9jYWwoXCJpXCIsIFwiaTMyXCIpO1xuICAgIGYuYWRkTG9jYWwoXCJpdEluXCIsIFwiaTMyXCIpO1xuICAgIGYuYWRkTG9jYWwoXCJpdE91dFwiLCBcImkzMlwiKTtcblxuICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICBpZiAocmV2ZXJzZSkge1xuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiaXRJblwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBJblwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfbXVsKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfc3ViKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJuXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDEpXG4gICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3Qoc2l6ZUluKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpdE91dFwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBPdXRcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX211bChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX3N1YihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiblwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdCgxKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KHNpemVPdXQpXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcImlcIiwgYy5pMzJfY29uc3QoMCkpLFxuICAgICAgICAgICAgYy5ibG9jayhjLmxvb3AoXG4gICAgICAgICAgICAgICAgYy5icl9pZigxLCBjLmkzMl9lcSAoIGMuZ2V0TG9jYWwoXCJpXCIpLCBjLmdldExvY2FsKFwiblwiKSApKSxcblxuICAgICAgICAgICAgICAgIGMuY2FsbChpbnRlcm5hbEZuTmFtZSwgYy5nZXRMb2NhbChcIml0SW5cIiksIGMuZ2V0TG9jYWwoXCJpdE91dFwiKSksXG5cbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaXRJblwiLCBjLmkzMl9zdWIoYy5nZXRMb2NhbChcIml0SW5cIiksIGMuaTMyX2NvbnN0KHNpemVJbikpKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaXRPdXRcIiwgYy5pMzJfc3ViKGMuZ2V0TG9jYWwoXCJpdE91dFwiKSwgYy5pMzJfY29uc3Qoc2l6ZU91dCkpKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaVwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcImlcIiksIGMuaTMyX2NvbnN0KDEpKSksXG4gICAgICAgICAgICAgICAgYy5icigwKVxuICAgICAgICAgICAgKSksXG4gICAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcIml0SW5cIiwgYy5nZXRMb2NhbChcInBJblwiKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiaXRPdXRcIiwgYy5nZXRMb2NhbChcInBPdXRcIikpLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcImlcIiwgYy5pMzJfY29uc3QoMCkpLFxuICAgICAgICAgICAgYy5ibG9jayhjLmxvb3AoXG4gICAgICAgICAgICAgICAgYy5icl9pZigxLCBjLmkzMl9lcSAoIGMuZ2V0TG9jYWwoXCJpXCIpLCBjLmdldExvY2FsKFwiblwiKSApKSxcblxuICAgICAgICAgICAgICAgIGMuY2FsbChpbnRlcm5hbEZuTmFtZSwgYy5nZXRMb2NhbChcIml0SW5cIiksIGMuZ2V0TG9jYWwoXCJpdE91dFwiKSksXG5cbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaXRJblwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcIml0SW5cIiksIGMuaTMyX2NvbnN0KHNpemVJbikpKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaXRPdXRcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJpdE91dFwiKSwgYy5pMzJfY29uc3Qoc2l6ZU91dCkpKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaVwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcImlcIiksIGMuaTMyX2NvbnN0KDEpKSksXG4gICAgICAgICAgICAgICAgYy5icigwKVxuICAgICAgICAgICAgKSksXG4gICAgICAgICk7XG4gICAgfVxufVxuXG52YXIgYnVpbGRfYmF0Y2hvcCA9IGJ1aWxkQmF0Y2hDb252ZXJ0aW9uJDI7XG5cbmZ1bmN0aW9uIGJ1aWxkQmF0Y2hDb252ZXJ0aW9uJDIobW9kdWxlLCBmbk5hbWUsIGludGVybmFsRm5OYW1lLCBzaXplSW4sIHNpemVPdXQsIHJldmVyc2UpIHtcbiAgICBpZiAodHlwZW9mIHJldmVyc2UgPT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgLy8gU2V0IHRoZSByZXZlcnNlIGluIGEgd2F5IHRoYXQgYWxsb3dzIHRvIHVzZSB0aGUgc2FtZSBidWZmZXIgYXMgaW4vb3V0LlxuICAgICAgICBpZiAoc2l6ZUluIDwgc2l6ZU91dCkge1xuICAgICAgICAgICAgcmV2ZXJzZSA9IHRydWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXZlcnNlID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKGZuTmFtZSk7XG4gICAgZi5hZGRQYXJhbShcInBJbjFcIiwgXCJpMzJcIik7XG4gICAgZi5hZGRQYXJhbShcInBJbjJcIiwgXCJpMzJcIik7XG4gICAgZi5hZGRQYXJhbShcIm5cIiwgXCJpMzJcIik7XG4gICAgZi5hZGRQYXJhbShcInBPdXRcIiwgXCJpMzJcIik7XG4gICAgZi5hZGRMb2NhbChcImlcIiwgXCJpMzJcIik7XG4gICAgZi5hZGRMb2NhbChcIml0SW4xXCIsIFwiaTMyXCIpO1xuICAgIGYuYWRkTG9jYWwoXCJpdEluMlwiLCBcImkzMlwiKTtcbiAgICBmLmFkZExvY2FsKFwiaXRPdXRcIiwgXCJpMzJcIik7XG5cbiAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgaWYgKHJldmVyc2UpIHtcbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcIml0SW4xXCIsXG4gICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicEluMVwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfbXVsKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfc3ViKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJuXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDEpXG4gICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3Qoc2l6ZUluKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpdEluMlwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBJbjJcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX211bChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX3N1YihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiblwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdCgxKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KHNpemVJbilcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiaXRPdXRcIixcbiAgICAgICAgICAgICAgICBjLmkzMl9hZGQoXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwT3V0XCIpLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9tdWwoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9zdWIoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIm5cIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMSlcbiAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdChzaXplT3V0KVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpXCIsIGMuaTMyX2NvbnN0KDApKSxcbiAgICAgICAgICAgIGMuYmxvY2soYy5sb29wKFxuICAgICAgICAgICAgICAgIGMuYnJfaWYoMSwgYy5pMzJfZXEgKCBjLmdldExvY2FsKFwiaVwiKSwgYy5nZXRMb2NhbChcIm5cIikgKSksXG5cbiAgICAgICAgICAgICAgICBjLmNhbGwoaW50ZXJuYWxGbk5hbWUsIGMuZ2V0TG9jYWwoXCJpdEluMVwiKSwgYy5nZXRMb2NhbChcIml0SW4yXCIpLCBjLmdldExvY2FsKFwiaXRPdXRcIikpLFxuXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcIml0SW4xXCIsIGMuaTMyX3N1YihjLmdldExvY2FsKFwiaXRJbjFcIiksIGMuaTMyX2NvbnN0KHNpemVJbikpKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaXRJbjJcIiwgYy5pMzJfc3ViKGMuZ2V0TG9jYWwoXCJpdEluMlwiKSwgYy5pMzJfY29uc3Qoc2l6ZUluKSkpLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpdE91dFwiLCBjLmkzMl9zdWIoYy5nZXRMb2NhbChcIml0T3V0XCIpLCBjLmkzMl9jb25zdChzaXplT3V0KSkpLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwiaVwiKSwgYy5pMzJfY29uc3QoMSkpKSxcbiAgICAgICAgICAgICAgICBjLmJyKDApXG4gICAgICAgICAgICApKSxcbiAgICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiaXRJbjFcIiwgYy5nZXRMb2NhbChcInBJbjFcIikpLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcIml0SW4yXCIsIGMuZ2V0TG9jYWwoXCJwSW4yXCIpKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpdE91dFwiLCBjLmdldExvY2FsKFwicE91dFwiKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiaVwiLCBjLmkzMl9jb25zdCgwKSksXG4gICAgICAgICAgICBjLmJsb2NrKGMubG9vcChcbiAgICAgICAgICAgICAgICBjLmJyX2lmKDEsIGMuaTMyX2VxICggYy5nZXRMb2NhbChcImlcIiksIGMuZ2V0TG9jYWwoXCJuXCIpICkpLFxuXG4gICAgICAgICAgICAgICAgYy5jYWxsKGludGVybmFsRm5OYW1lLCBjLmdldExvY2FsKFwiaXRJbjFcIiksIGMuZ2V0TG9jYWwoXCJpdEluMlwiKSwgYy5nZXRMb2NhbChcIml0T3V0XCIpKSxcblxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpdEluMVwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcIml0SW4xXCIpLCBjLmkzMl9jb25zdChzaXplSW4pKSksXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcIml0SW4yXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwiaXRJbjJcIiksIGMuaTMyX2NvbnN0KHNpemVJbikpKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaXRPdXRcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJpdE91dFwiKSwgYy5pMzJfY29uc3Qoc2l6ZU91dCkpKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaVwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcImlcIiksIGMuaTMyX2NvbnN0KDEpKSksXG4gICAgICAgICAgICAgICAgYy5icigwKVxuICAgICAgICAgICAgKSksXG4gICAgICAgICk7XG4gICAgfVxufVxuXG52YXIgYmlnaW50ID0ge307XG5cbi8vIE1hbnkgb2YgdGhlc2UgdXRpbGl0aWVzIGFyZSBmcm9tIHRoZSBgYmlnLWludGVnZXJgIGxpYnJhcnksXG4vLyBidXQgYWRqdXN0ZWQgdG8gb25seSB3b3JrIHdpdGggbmF0aXZlIEJpZ0ludCB0eXBlXG4vLyBSZWYgaHR0cHM6Ly9naXRodWIuY29tL3BldGVyb2xzb24vQmlnSW50ZWdlci5qcy9ibG9iL2U1ZDIxNTRkM2M0MTcwNjljNTFlNzExNmJhZmMzYjkxZDBiOWZlNDEvQmlnSW50ZWdlci5qc1xuLy8gT3JpZ2luYWxseSBsaWNlbnNlZCBUaGUgVW5saWNlbnNlXG5cbmZ1bmN0aW9uIGNvbXBhcmUoYSwgYikge1xuICAgIHJldHVybiBhID09PSBiID8gMCA6IGEgPiBiID8gMSA6IC0xO1xufVxuXG5mdW5jdGlvbiBzcXVhcmUkMShuKSB7XG4gICAgcmV0dXJuIG4gKiBuO1xufVxuXG5mdW5jdGlvbiBpc09kZCQ0KG4pIHtcbiAgICByZXR1cm4gbiAlIDJuICE9PSAwbjtcbn1cblxuZnVuY3Rpb24gaXNFdmVuKG4pIHtcbiAgICByZXR1cm4gbiAlIDJuID09PSAwbjtcbn1cblxuZnVuY3Rpb24gaXNOZWdhdGl2ZSQzKG4pIHtcbiAgICByZXR1cm4gbiA8IDBuO1xufVxuXG5mdW5jdGlvbiBpc1Bvc2l0aXZlKG4pIHtcbiAgICByZXR1cm4gbiA+IDBuO1xufVxuXG5mdW5jdGlvbiBiaXRMZW5ndGgkNShuKSB7XG4gICAgaWYgKGlzTmVnYXRpdmUkMyhuKSkge1xuICAgICAgICByZXR1cm4gbi50b1N0cmluZygyKS5sZW5ndGggLSAxOyAvLyBkaXNjYXJkIHRoZSAtIHNpZ25cbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbi50b1N0cmluZygyKS5sZW5ndGg7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBhYnMobikge1xuICAgIHJldHVybiBuIDwgMG4gPyAtbiA6IG47XG59XG5cbmZ1bmN0aW9uIGlzVW5pdChuKSB7XG4gICAgcmV0dXJuIGFicyhuKSA9PT0gMW47XG59XG5cbmZ1bmN0aW9uIG1vZEludiQzKGEsIG4pIHtcbiAgICB2YXIgdCA9IDBuLCBuZXdUID0gMW4sIHIgPSBuLCBuZXdSID0gYWJzKGEpLCBxLCBsYXN0VCwgbGFzdFI7XG4gICAgd2hpbGUgKG5ld1IgIT09IDBuKSB7XG4gICAgICAgIHEgPSByIC8gbmV3UjtcbiAgICAgICAgbGFzdFQgPSB0O1xuICAgICAgICBsYXN0UiA9IHI7XG4gICAgICAgIHQgPSBuZXdUO1xuICAgICAgICByID0gbmV3UjtcbiAgICAgICAgbmV3VCA9IGxhc3RUIC0gKHEgKiBuZXdUKTtcbiAgICAgICAgbmV3UiA9IGxhc3RSIC0gKHEgKiBuZXdSKTtcbiAgICB9XG4gICAgaWYgKCFpc1VuaXQocikpIHRocm93IG5ldyBFcnJvcihhLnRvU3RyaW5nKCkgKyBcIiBhbmQgXCIgKyBuLnRvU3RyaW5nKCkgKyBcIiBhcmUgbm90IGNvLXByaW1lXCIpO1xuICAgIGlmIChjb21wYXJlKHQsIDBuKSA9PT0gLTEpIHtcbiAgICAgICAgdCA9IHQgKyBuO1xuICAgIH1cbiAgICBpZiAoaXNOZWdhdGl2ZSQzKGEpKSB7XG4gICAgICAgIHJldHVybiAtdDtcbiAgICB9XG4gICAgcmV0dXJuIHQ7XG59XG5cbmZ1bmN0aW9uIG1vZFBvdyQyKG4sIGV4cCwgbW9kKSB7XG4gICAgaWYgKG1vZCA9PT0gMG4pIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCB0YWtlIG1vZFBvdyB3aXRoIG1vZHVsdXMgMFwiKTtcbiAgICB2YXIgciA9IDFuLFxuICAgICAgICBiYXNlID0gbiAlIG1vZDtcbiAgICBpZiAoaXNOZWdhdGl2ZSQzKGV4cCkpIHtcbiAgICAgICAgZXhwID0gZXhwICogLTFuO1xuICAgICAgICBiYXNlID0gbW9kSW52JDMoYmFzZSwgbW9kKTtcbiAgICB9XG4gICAgd2hpbGUgKGlzUG9zaXRpdmUoZXhwKSkge1xuICAgICAgICBpZiAoYmFzZSA9PT0gMG4pIHJldHVybiAwbjtcbiAgICAgICAgaWYgKGlzT2RkJDQoZXhwKSkgciA9IHIgKiBiYXNlICUgbW9kO1xuICAgICAgICBleHAgPSBleHAgLyAybjtcbiAgICAgICAgYmFzZSA9IHNxdWFyZSQxKGJhc2UpICUgbW9kO1xuICAgIH1cbiAgICByZXR1cm4gcjtcbn1cblxuZnVuY3Rpb24gY29tcGFyZUFicyhhLCBiKSB7XG4gICAgYSA9IGEgPj0gMG4gPyBhIDogLWE7XG4gICAgYiA9IGIgPj0gMG4gPyBiIDogLWI7XG4gICAgcmV0dXJuIGEgPT09IGIgPyAwIDogYSA+IGIgPyAxIDogLTE7XG59XG5cbmZ1bmN0aW9uIGlzRGl2aXNpYmxlQnkoYSwgbikge1xuICAgIGlmIChuID09PSAwbikgcmV0dXJuIGZhbHNlO1xuICAgIGlmIChpc1VuaXQobikpIHJldHVybiB0cnVlO1xuICAgIGlmIChjb21wYXJlQWJzKG4sIDJuKSA9PT0gMCkgcmV0dXJuIGlzRXZlbihhKTtcbiAgICByZXR1cm4gYSAlIG4gPT09IDBuO1xufVxuXG5mdW5jdGlvbiBpc0Jhc2ljUHJpbWUodikge1xuICAgIHZhciBuID0gYWJzKHYpO1xuICAgIGlmIChpc1VuaXQobikpIHJldHVybiBmYWxzZTtcbiAgICBpZiAobiA9PT0gMm4gfHwgbiA9PT0gM24gfHwgbiA9PT0gNW4pIHJldHVybiB0cnVlO1xuICAgIGlmIChpc0V2ZW4obikgfHwgaXNEaXZpc2libGVCeShuLCAzbikgfHwgaXNEaXZpc2libGVCeShuLCA1bikpIHJldHVybiBmYWxzZTtcbiAgICBpZiAobiA8IDQ5bikgcmV0dXJuIHRydWU7XG4gICAgLy8gd2UgZG9uJ3Qga25vdyBpZiBpdCdzIHByaW1lOiBsZXQgdGhlIG90aGVyIGZ1bmN0aW9ucyBmaWd1cmUgaXQgb3V0XG59XG5cbmZ1bmN0aW9uIHByZXYobikge1xuICAgIHJldHVybiBuIC0gMW47XG59XG5cbmZ1bmN0aW9uIG1pbGxlclJhYmluVGVzdChuLCBhKSB7XG4gICAgdmFyIG5QcmV2ID0gcHJldihuKSxcbiAgICAgICAgYiA9IG5QcmV2LFxuICAgICAgICByID0gMCxcbiAgICAgICAgZCwgaSwgeDtcbiAgICB3aGlsZSAoaXNFdmVuKGIpKSBiID0gYiAvIDJuLCByKys7XG4gICAgbmV4dDogZm9yIChpID0gMDsgaSA8IGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKG4gPCBhW2ldKSBjb250aW51ZTtcbiAgICAgICAgeCA9IG1vZFBvdyQyKEJpZ0ludChhW2ldKSwgYiwgbik7XG4gICAgICAgIGlmIChpc1VuaXQoeCkgfHwgeCA9PT0gblByZXYpIGNvbnRpbnVlO1xuICAgICAgICBmb3IgKGQgPSByIC0gMTsgZCAhPSAwOyBkLS0pIHtcbiAgICAgICAgICAgIHggPSBzcXVhcmUkMSh4KSAlIG47XG4gICAgICAgICAgICBpZiAoaXNVbml0KHgpKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICBpZiAoeCA9PT0gblByZXYpIGNvbnRpbnVlIG5leHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gaXNQcmltZSQxKHApIHtcbiAgICB2YXIgaXNQcmltZSA9IGlzQmFzaWNQcmltZShwKTtcbiAgICBpZiAoaXNQcmltZSAhPT0gdW5kZWZpbmVkKSByZXR1cm4gaXNQcmltZTtcbiAgICB2YXIgbiA9IGFicyhwKTtcbiAgICB2YXIgYml0cyA9IGJpdExlbmd0aCQ1KG4pO1xuICAgIGlmIChiaXRzIDw9IDY0KVxuICAgICAgICByZXR1cm4gbWlsbGVyUmFiaW5UZXN0KG4sIFsyLCAzLCA1LCA3LCAxMSwgMTMsIDE3LCAxOSwgMjMsIDI5LCAzMSwgMzddKTtcbiAgICB2YXIgbG9nTiA9IE1hdGgubG9nKDIpICogTnVtYmVyKGJpdHMpO1xuICAgIHZhciB0ID0gTWF0aC5jZWlsKGxvZ04pO1xuICAgIGZvciAodmFyIGEgPSBbXSwgaSA9IDA7IGkgPCB0OyBpKyspIHtcbiAgICAgICAgYS5wdXNoKEJpZ0ludChpICsgMikpO1xuICAgIH1cbiAgICByZXR1cm4gbWlsbGVyUmFiaW5UZXN0KG4sIGEpO1xufVxuXG5iaWdpbnQuYml0TGVuZ3RoID0gYml0TGVuZ3RoJDU7XG5iaWdpbnQuaXNPZGQgPSBpc09kZCQ0O1xuYmlnaW50LmlzTmVnYXRpdmUgPSBpc05lZ2F0aXZlJDM7XG5iaWdpbnQuYWJzID0gYWJzO1xuYmlnaW50LmlzVW5pdCA9IGlzVW5pdDtcbmJpZ2ludC5jb21wYXJlID0gY29tcGFyZTtcbmJpZ2ludC5tb2RJbnYgPSBtb2RJbnYkMztcbmJpZ2ludC5tb2RQb3cgPSBtb2RQb3ckMjtcbmJpZ2ludC5pc1ByaW1lID0gaXNQcmltZSQxO1xuYmlnaW50LnNxdWFyZSA9IHNxdWFyZSQxO1xuXG4vKlxuICAgIENvcHlyaWdodCAyMDE5IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygd2FzbXNuYXJrIChXZWIgQXNzZW1ibHkgemtTbmFyayBQcm92ZXIpLlxuXG4gICAgd2FzbXNuYXJrIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICAgIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gICAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAgICAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgd2FzbXNuYXJrIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHdhc21zbmFyay4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbmNvbnN0IGJ1aWxkSW50ID0gYnVpbGRfaW50O1xuY29uc3QgdXRpbHMkNCA9IHV0aWxzJDU7XG5jb25zdCBidWlsZEV4cCQyID0gYnVpbGRfdGltZXNzY2FsYXI7XG5jb25zdCBidWlsZEJhdGNoSW52ZXJzZSQyID0gYnVpbGRfYmF0Y2hpbnZlcnNlO1xuY29uc3QgYnVpbGRCYXRjaENvbnZlcnRpb24kMSA9IGJ1aWxkX2JhdGNoY29udmVydGlvbjtcbmNvbnN0IGJ1aWxkQmF0Y2hPcCA9IGJ1aWxkX2JhdGNob3A7XG5jb25zdCB7IGJpdExlbmd0aDogYml0TGVuZ3RoJDQsIG1vZEludjogbW9kSW52JDIsIG1vZFBvdzogbW9kUG93JDEsIGlzUHJpbWUsIGlzT2RkOiBpc09kZCQzLCBzcXVhcmUgfSA9IGJpZ2ludDtcblxudmFyIGJ1aWxkX2YxbSA9IGZ1bmN0aW9uIGJ1aWxkRjFtKG1vZHVsZSwgX3EsIF9wcmVmaXgsIF9pbnRQcmVmaXgpIHtcbiAgICBjb25zdCBxID0gQmlnSW50KF9xKTtcbiAgICBjb25zdCBuNjQgPSBNYXRoLmZsb29yKChiaXRMZW5ndGgkNChxIC0gMW4pIC0gMSkvNjQpICsxO1xuICAgIGNvbnN0IG4zMiA9IG42NCoyO1xuICAgIGNvbnN0IG44ID0gbjY0Kjg7XG5cbiAgICBjb25zdCBwcmVmaXggPSBfcHJlZml4IHx8IFwiZjFtXCI7XG4gICAgaWYgKG1vZHVsZS5tb2R1bGVzW3ByZWZpeF0pIHJldHVybiBwcmVmaXg7ICAvLyBhbHJlYWR5IGJ1aWxkZWRcblxuICAgIGNvbnN0IGludFByZWZpeCA9IGJ1aWxkSW50KG1vZHVsZSwgbjY0LCBfaW50UHJlZml4KTtcbiAgICBjb25zdCBwcSA9IG1vZHVsZS5hbGxvYyhuOCwgdXRpbHMkNC5iaWdJbnQyQnl0ZXNMRShxLCBuOCkpO1xuXG4gICAgY29uc3QgcFIyID0gbW9kdWxlLmFsbG9jKHV0aWxzJDQuYmlnSW50MkJ5dGVzTEUoc3F1YXJlKDFuIDw8IEJpZ0ludChuNjQqNjQpKSAlIHEsIG44KSk7XG4gICAgY29uc3QgcE9uZSA9IG1vZHVsZS5hbGxvYyh1dGlscyQ0LmJpZ0ludDJCeXRlc0xFKCgxbiA8PCBCaWdJbnQobjY0KjY0KSkgJSBxLCBuOCkpO1xuICAgIGNvbnN0IHBaZXJvID0gbW9kdWxlLmFsbG9jKHV0aWxzJDQuYmlnSW50MkJ5dGVzTEUoMG4sIG44KSk7XG4gICAgY29uc3QgX21pbnVzT25lID0gcSAtIDFuO1xuICAgIGNvbnN0IF9lID0gX21pbnVzT25lID4+IDFuOyAvLyBlID0gKHAtMSkvMlxuICAgIGNvbnN0IHBlID0gbW9kdWxlLmFsbG9jKG44LCB1dGlscyQ0LmJpZ0ludDJCeXRlc0xFKF9lLCBuOCkpO1xuXG4gICAgY29uc3QgX2VQbHVzT25lID0gX2UgKyAxbjsgLy8gZSA9IChwLTEpLzJcbiAgICBjb25zdCBwZVBsdXNPbmUgPSBtb2R1bGUuYWxsb2MobjgsIHV0aWxzJDQuYmlnSW50MkJ5dGVzTEUoX2VQbHVzT25lLCBuOCkpO1xuXG4gICAgbW9kdWxlLm1vZHVsZXNbcHJlZml4XSA9IHtcbiAgICAgICAgcHE6IHBxLFxuICAgICAgICBwUjI6IHBSMixcbiAgICAgICAgbjY0OiBuNjQsXG4gICAgICAgIHE6IHEsXG4gICAgICAgIHBPbmU6IHBPbmUsXG4gICAgICAgIHBaZXJvOiBwWmVybyxcbiAgICAgICAgcGVQbHVzT25lOiBwZVBsdXNPbmVcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gYnVpbGRPbmUoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX29uZVwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInByXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgZi5hZGRDb2RlKGMuY2FsbChpbnRQcmVmaXggKyBcIl9jb3B5XCIsIGMuaTMyX2NvbnN0KHBPbmUpLCBjLmdldExvY2FsKFwicHJcIikpKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZEFkZCgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfYWRkXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInlcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmNhbGwoaW50UHJlZml4K1wiX2FkZFwiLCBjLmdldExvY2FsKFwieFwiKSwgIGMuZ2V0TG9jYWwoXCJ5XCIpLCBjLmdldExvY2FsKFwiclwiKSksXG4gICAgICAgICAgICAgICAgYy5kcm9wKGMuY2FsbChpbnRQcmVmaXgrXCJfc3ViXCIsIGMuZ2V0TG9jYWwoXCJyXCIpLCBjLmkzMl9jb25zdChwcSksIGMuZ2V0TG9jYWwoXCJyXCIpKSksXG4gICAgICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICAgICAgYy5jYWxsKGludFByZWZpeCtcIl9ndGVcIiwgYy5nZXRMb2NhbChcInJcIiksIGMuaTMyX2NvbnN0KHBxKSAgKSxcbiAgICAgICAgICAgICAgICAgICAgYy5kcm9wKGMuY2FsbChpbnRQcmVmaXgrXCJfc3ViXCIsIGMuZ2V0TG9jYWwoXCJyXCIpLCBjLmkzMl9jb25zdChwcSksIGMuZ2V0TG9jYWwoXCJyXCIpKSksXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkU3ViKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9zdWJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ4XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgIGMuY2FsbChpbnRQcmVmaXgrXCJfc3ViXCIsIGMuZ2V0TG9jYWwoXCJ4XCIpLCAgYy5nZXRMb2NhbChcInlcIiksIGMuZ2V0TG9jYWwoXCJyXCIpKSxcbiAgICAgICAgICAgICAgICBjLmRyb3AoYy5jYWxsKGludFByZWZpeCtcIl9hZGRcIiwgYy5nZXRMb2NhbChcInJcIiksICBjLmkzMl9jb25zdChwcSksIGMuZ2V0TG9jYWwoXCJyXCIpKSlcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZE5lZygpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfbmVnXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfc3ViXCIsIGMuaTMyX2NvbnN0KHBaZXJvKSwgYy5nZXRMb2NhbChcInhcIiksIGMuZ2V0TG9jYWwoXCJyXCIpKVxuICAgICAgICApO1xuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gYnVpbGRJc05lZ2F0aXZlKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9pc05lZ2F0aXZlXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5zZXRSZXR1cm5UeXBlKFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgQVVYID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX2Zyb21Nb250Z29tZXJ5XCIsIGMuZ2V0TG9jYWwoXCJ4XCIpLCBBVVgpLFxuICAgICAgICAgICAgYy5jYWxsKGludFByZWZpeCArIFwiX2d0ZVwiLCBBVVgsIGMuaTMyX2NvbnN0KHBlUGx1c09uZSkgKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkU2lnbigpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfc2lnblwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuc2V0UmV0dXJuVHlwZShcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IEFVWCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuaWYgKFxuICAgICAgICAgICAgICAgIGMuY2FsbChpbnRQcmVmaXggKyBcIl9pc1plcm9cIiwgYy5nZXRMb2NhbChcInhcIikpLFxuICAgICAgICAgICAgICAgIGMucmV0KGMuaTMyX2NvbnN0KDApKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9mcm9tTW9udGdvbWVyeVwiLCBjLmdldExvY2FsKFwieFwiKSwgQVVYKSxcbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5jYWxsKGludFByZWZpeCArIFwiX2d0ZVwiLCBBVVgsIGMuaTMyX2NvbnN0KHBlUGx1c09uZSkpLFxuICAgICAgICAgICAgICAgIGMucmV0KGMuaTMyX2NvbnN0KC0xKSlcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLnJldChjLmkzMl9jb25zdCgxKSlcbiAgICAgICAgKTtcbiAgICB9XG5cblxuICAgIGZ1bmN0aW9uIGJ1aWxkTVJlZHVjdCgpIHtcbiAgICAgICAgY29uc3QgY2FycmllcyA9IG1vZHVsZS5hbGxvYyhuMzIqbjMyKjgpO1xuXG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX21SZWR1Y3RcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ0XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiclwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcIm5wMzJcIiwgXCJpNjRcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJjXCIsIFwiaTY0XCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwibVwiLCBcImk2NFwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IG5wMzIgPSBOdW1iZXIoMHgxMDAwMDAwMDBuIC0gbW9kSW52JDIocSwgMHgxMDAwMDAwMDBuKSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKGMuc2V0TG9jYWwoXCJucDMyXCIsIGMuaTY0X2NvbnN0KG5wMzIpKSk7XG5cbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPG4zMjsgaSsrKSB7XG4gICAgICAgICAgICBmLmFkZENvZGUoYy5zZXRMb2NhbChcImNcIiwgYy5pNjRfY29uc3QoMCkpKTtcblxuICAgICAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgICAgIFwibVwiLFxuICAgICAgICAgICAgICAgICAgICBjLmk2NF9hbmQoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9tdWwoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfbG9hZDMyX3UoYy5nZXRMb2NhbChcInRcIiksIGkqNCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIm5wMzJcIilcbiAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9jb25zdChcIjB4RkZGRkZGRkZcIilcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGZvciAobGV0IGo9MDsgajxuMzI7IGorKykge1xuXG4gICAgICAgICAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiY1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfbG9hZDMyX3UoYy5nZXRMb2NhbChcInRcIiksIChpK2opKjQpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9zaHJfdShjLmdldExvY2FsKFwiY1wiKSwgYy5pNjRfY29uc3QoMzIpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfbXVsKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9sb2FkMzJfdShjLmkzMl9jb25zdChwcSksIGoqNCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJtXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgICAgICAgICAgYy5pNjRfc3RvcmUzMihcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJ0XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgKGkraikqNCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJjXCIpXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICAgICAgYy5pNjRfc3RvcmUzMihcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoY2FycmllcyksXG4gICAgICAgICAgICAgICAgICAgIGkqNCxcbiAgICAgICAgICAgICAgICAgICAgYy5pNjRfc2hyX3UoYy5nZXRMb2NhbChcImNcIiksIGMuaTY0X2NvbnN0KDMyKSlcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgIHByZWZpeCtcIl9hZGRcIixcbiAgICAgICAgICAgICAgICBjLmkzMl9jb25zdChjYXJyaWVzKSxcbiAgICAgICAgICAgICAgICBjLmkzMl9hZGQoXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJ0XCIpLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdChuMzIqNClcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJyXCIpXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxuXG5cblxuICAgIGZ1bmN0aW9uIGJ1aWxkTXVsKCkge1xuXG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX211bFwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ5XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiclwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImMwXCIsIFwiaTY0XCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiYzFcIiwgXCJpNjRcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJucDMyXCIsIFwiaTY0XCIpO1xuXG5cbiAgICAgICAgZm9yIChsZXQgaT0wO2k8bjMyOyBpKyspIHtcbiAgICAgICAgICAgIGYuYWRkTG9jYWwoXCJ4XCIraSwgXCJpNjRcIik7XG4gICAgICAgICAgICBmLmFkZExvY2FsKFwieVwiK2ksIFwiaTY0XCIpO1xuICAgICAgICAgICAgZi5hZGRMb2NhbChcIm1cIitpLCBcImk2NFwiKTtcbiAgICAgICAgICAgIGYuYWRkTG9jYWwoXCJxXCIraSwgXCJpNjRcIik7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IG5wMzIgPSBOdW1iZXIoMHgxMDAwMDAwMDBuIC0gbW9kSW52JDIocSwgMHgxMDAwMDAwMDBuKSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKGMuc2V0TG9jYWwoXCJucDMyXCIsIGMuaTY0X2NvbnN0KG5wMzIpKSk7XG5cblxuICAgICAgICBjb25zdCBsb2FkWCA9IFtdO1xuICAgICAgICBjb25zdCBsb2FkWSA9IFtdO1xuICAgICAgICBjb25zdCBsb2FkUSA9IFtdO1xuICAgICAgICBmdW5jdGlvbiBtdWxpaihpLCBqKSB7XG4gICAgICAgICAgICBsZXQgWCxZO1xuICAgICAgICAgICAgaWYgKCFsb2FkWFtpXSkge1xuICAgICAgICAgICAgICAgIFggPSBjLnRlZUxvY2FsKFwieFwiK2ksIGMuaTY0X2xvYWQzMl91KCBjLmdldExvY2FsKFwieFwiKSwgaSo0KSk7XG4gICAgICAgICAgICAgICAgbG9hZFhbaV0gPSB0cnVlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBYID0gYy5nZXRMb2NhbChcInhcIitpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghbG9hZFlbal0pIHtcbiAgICAgICAgICAgICAgICBZID0gYy50ZWVMb2NhbChcInlcIitqLCBjLmk2NF9sb2FkMzJfdSggYy5nZXRMb2NhbChcInlcIiksIGoqNCkpO1xuICAgICAgICAgICAgICAgIGxvYWRZW2pdID0gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgWSA9IGMuZ2V0TG9jYWwoXCJ5XCIraik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBjLmk2NF9tdWwoIFgsIFkgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIG11bHFtKGksIGopIHtcbiAgICAgICAgICAgIGxldCBRLE07XG4gICAgICAgICAgICBpZiAoIWxvYWRRW2ldKSB7XG4gICAgICAgICAgICAgICAgUSA9IGMudGVlTG9jYWwoXCJxXCIraSwgYy5pNjRfbG9hZDMyX3UoYy5pMzJfY29uc3QoMCksIHBxK2kqNCApKTtcbiAgICAgICAgICAgICAgICBsb2FkUVtpXSA9IHRydWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIFEgPSBjLmdldExvY2FsKFwicVwiK2kpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgTSA9IGMuZ2V0TG9jYWwoXCJtXCIraik7XG5cbiAgICAgICAgICAgIHJldHVybiBjLmk2NF9tdWwoIFEsIE0gKTtcbiAgICAgICAgfVxuXG5cbiAgICAgICAgbGV0IGMwID0gXCJjMFwiO1xuICAgICAgICBsZXQgYzEgPSBcImMxXCI7XG5cbiAgICAgICAgZm9yIChsZXQgaz0wOyBrPG4zMioyLTE7IGsrKykge1xuICAgICAgICAgICAgZm9yIChsZXQgaT1NYXRoLm1heCgwLCBrLW4zMisxKTsgKGk8PWspJiYoaTxuMzIpOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBqPSBrLWk7XG5cbiAgICAgICAgICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoYzAsXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9hZGQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfYW5kKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKGMwKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfY29uc3QoMHhGRkZGRkZGRilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11bGlqKGksailcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoYzEsXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9hZGQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChjMSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfc2hyX3UoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoYzApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9jb25zdCgzMilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuXG5cbiAgICAgICAgICAgIGZvciAobGV0IGk9TWF0aC5tYXgoMSwgay1uMzIrMSk7IChpPD1rKSYmKGk8bjMyKTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgaj0gay1pO1xuXG4gICAgICAgICAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgICAgICAgICBjLnNldExvY2FsKGMwLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2FuZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChjMCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2NvbnN0KDB4RkZGRkZGRkYpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdWxxbShpLGopXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgICAgICAgICBjLnNldExvY2FsKGMxLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoYzEpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X3Nocl91KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKGMwKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfY29uc3QoMzIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChrPG4zMikge1xuICAgICAgICAgICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcbiAgICAgICAgICAgICAgICAgICAgICAgIFwibVwiK2ssXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9hbmQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfbXVsKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9hbmQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKGMwKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2NvbnN0KDB4RkZGRkZGRkYpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJucDMyXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9jb25zdChcIjB4RkZGRkZGRkZcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICk7XG5cblxuICAgICAgICAgICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgICAgICAgICAgYy5zZXRMb2NhbChjMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9hbmQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoYzApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9jb25zdCgweEZGRkZGRkZGKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXVscW0oMCxrKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgICAgICAgICAgYy5zZXRMb2NhbChjMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKGMxKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9zaHJfdShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChjMCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2NvbnN0KDMyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG5cblxuICAgICAgICAgICAgaWYgKGs+PW4zMikge1xuICAgICAgICAgICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgICAgICAgICAgYy5pNjRfc3RvcmUzMihcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJyXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgKGstbjMyKSo0LFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChjMClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBbYzAsIGMxXSA9IFtjMSwgYzBdO1xuICAgICAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoYzEsXG4gICAgICAgICAgICAgICAgICAgIGMuaTY0X3Nocl91KFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChjMCksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9jb25zdCgzMilcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5pNjRfc3RvcmUzMihcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiclwiKSxcbiAgICAgICAgICAgICAgICBuMzIqNC00LFxuICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoYzApXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmkzMl93cmFwX2k2NChjLmdldExvY2FsKGMxKSksXG4gICAgICAgICAgICAgICAgYy5kcm9wKGMuY2FsbChpbnRQcmVmaXgrXCJfc3ViXCIsIGMuZ2V0TG9jYWwoXCJyXCIpLCBjLmkzMl9jb25zdChwcSksIGMuZ2V0TG9jYWwoXCJyXCIpKSksXG4gICAgICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICAgICAgYy5jYWxsKGludFByZWZpeCtcIl9ndGVcIiwgYy5nZXRMb2NhbChcInJcIiksIGMuaTMyX2NvbnN0KHBxKSAgKSxcbiAgICAgICAgICAgICAgICAgICAgYy5kcm9wKGMuY2FsbChpbnRQcmVmaXgrXCJfc3ViXCIsIGMuZ2V0TG9jYWwoXCJyXCIpLCBjLmkzMl9jb25zdChwcSksIGMuZ2V0TG9jYWwoXCJyXCIpKSksXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gYnVpbGRTcXVhcmUoKSB7XG5cbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfc3F1YXJlXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJjMFwiLCBcImk2NFwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImMxXCIsIFwiaTY0XCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiYzBfb2xkXCIsIFwiaTY0XCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiYzFfb2xkXCIsIFwiaTY0XCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwibnAzMlwiLCBcImk2NFwiKTtcblxuXG4gICAgICAgIGZvciAobGV0IGk9MDtpPG4zMjsgaSsrKSB7XG4gICAgICAgICAgICBmLmFkZExvY2FsKFwieFwiK2ksIFwiaTY0XCIpO1xuICAgICAgICAgICAgZi5hZGRMb2NhbChcIm1cIitpLCBcImk2NFwiKTtcbiAgICAgICAgICAgIGYuYWRkTG9jYWwoXCJxXCIraSwgXCJpNjRcIik7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IG5wMzIgPSBOdW1iZXIoMHgxMDAwMDAwMDBuIC0gbW9kSW52JDIocSwgMHgxMDAwMDAwMDBuKSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKGMuc2V0TG9jYWwoXCJucDMyXCIsIGMuaTY0X2NvbnN0KG5wMzIpKSk7XG5cblxuICAgICAgICBjb25zdCBsb2FkWCA9IFtdO1xuICAgICAgICBjb25zdCBsb2FkUSA9IFtdO1xuICAgICAgICBmdW5jdGlvbiBtdWxpaihpLCBqKSB7XG4gICAgICAgICAgICBsZXQgWCxZO1xuICAgICAgICAgICAgaWYgKCFsb2FkWFtpXSkge1xuICAgICAgICAgICAgICAgIFggPSBjLnRlZUxvY2FsKFwieFwiK2ksIGMuaTY0X2xvYWQzMl91KCBjLmdldExvY2FsKFwieFwiKSwgaSo0KSk7XG4gICAgICAgICAgICAgICAgbG9hZFhbaV0gPSB0cnVlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBYID0gYy5nZXRMb2NhbChcInhcIitpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghbG9hZFhbal0pIHtcbiAgICAgICAgICAgICAgICBZID0gYy50ZWVMb2NhbChcInhcIitqLCBjLmk2NF9sb2FkMzJfdSggYy5nZXRMb2NhbChcInhcIiksIGoqNCkpO1xuICAgICAgICAgICAgICAgIGxvYWRYW2pdID0gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgWSA9IGMuZ2V0TG9jYWwoXCJ4XCIraik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBjLmk2NF9tdWwoIFgsIFkgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIG11bHFtKGksIGopIHtcbiAgICAgICAgICAgIGxldCBRLE07XG4gICAgICAgICAgICBpZiAoIWxvYWRRW2ldKSB7XG4gICAgICAgICAgICAgICAgUSA9IGMudGVlTG9jYWwoXCJxXCIraSwgYy5pNjRfbG9hZDMyX3UoYy5pMzJfY29uc3QoMCksIHBxK2kqNCApKTtcbiAgICAgICAgICAgICAgICBsb2FkUVtpXSA9IHRydWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIFEgPSBjLmdldExvY2FsKFwicVwiK2kpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgTSA9IGMuZ2V0TG9jYWwoXCJtXCIraik7XG5cbiAgICAgICAgICAgIHJldHVybiBjLmk2NF9tdWwoIFEsIE0gKTtcbiAgICAgICAgfVxuXG5cbiAgICAgICAgbGV0IGMwID0gXCJjMFwiO1xuICAgICAgICBsZXQgYzEgPSBcImMxXCI7XG4gICAgICAgIGxldCBjMF9vbGQgPSBcImMwX29sZFwiO1xuICAgICAgICBsZXQgYzFfb2xkID0gXCJjMV9vbGRcIjtcblxuICAgICAgICBmb3IgKGxldCBrPTA7IGs8bjMyKjItMTsgaysrKSB7XG4gICAgICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChjMCwgYy5pNjRfY29uc3QoMCkpLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoYzEsIGMuaTY0X2NvbnN0KDApKSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBmb3IgKGxldCBpPU1hdGgubWF4KDAsIGstbjMyKzEpOyAoaTwoKGsrMSk+PjEpICkmJihpPG4zMik7IGkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGo9IGstaTtcblxuICAgICAgICAgICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgICAgICAgICAgYy5zZXRMb2NhbChjMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9hbmQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoYzApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9jb25zdCgweEZGRkZGRkZGKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXVsaWooaSxqKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgICAgICAgICAgYy5zZXRMb2NhbChjMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKGMxKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9zaHJfdShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChjMCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2NvbnN0KDMyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIE11bHRpcGx5IGJ5IDJcbiAgICAgICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKGMwLFxuICAgICAgICAgICAgICAgICAgICBjLmk2NF9zaGwoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9hbmQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChjMCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfY29uc3QoMHhGRkZGRkZGRilcbiAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9jb25zdCgxKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoYzEsXG4gICAgICAgICAgICAgICAgICAgIGMuaTY0X2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X3NobChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKGMxKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9jb25zdCgxKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X3Nocl91KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoYzApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2NvbnN0KDMyKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgaWYgKGslMiA9PSAwKSB7XG4gICAgICAgICAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgICAgICAgICBjLnNldExvY2FsKGMwLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2FuZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChjMCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2NvbnN0KDB4RkZGRkZGRkYpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdWxpaihrPj4xLCBrPj4xKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgICAgICAgICAgYy5zZXRMb2NhbChjMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKGMxKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9zaHJfdShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChjMCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2NvbnN0KDMyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEFkZCB0aGUgb2xkIGNhcnJ5XG5cbiAgICAgICAgICAgIGlmIChrPjApIHtcbiAgICAgICAgICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoYzAsXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9hZGQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfYW5kKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKGMwKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfY29uc3QoMHhGRkZGRkZGRilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2FuZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChjMF9vbGQpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9jb25zdCgweEZGRkZGRkZGKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgICAgICAgICBjLnNldExvY2FsKGMxLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChjMSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X3Nocl91KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChjMCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9jb25zdCgzMilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChjMV9vbGQpXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuXG5cbiAgICAgICAgICAgIGZvciAobGV0IGk9TWF0aC5tYXgoMSwgay1uMzIrMSk7IChpPD1rKSYmKGk8bjMyKTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgaj0gay1pO1xuXG4gICAgICAgICAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgICAgICAgICBjLnNldExvY2FsKGMwLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2FuZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChjMCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2NvbnN0KDB4RkZGRkZGRkYpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdWxxbShpLGopXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgICAgICAgICBjLnNldExvY2FsKGMxLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoYzEpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X3Nocl91KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKGMwKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfY29uc3QoMzIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChrPG4zMikge1xuICAgICAgICAgICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcbiAgICAgICAgICAgICAgICAgICAgICAgIFwibVwiK2ssXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9hbmQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pNjRfbXVsKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9hbmQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKGMwKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2NvbnN0KDB4RkZGRkZGRkYpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJucDMyXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9jb25zdChcIjB4RkZGRkZGRkZcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICk7XG5cblxuICAgICAgICAgICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgICAgICAgICAgYy5zZXRMb2NhbChjMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9hbmQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoYzApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9jb25zdCgweEZGRkZGRkZGKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXVscW0oMCxrKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgICAgICAgICAgYy5zZXRMb2NhbChjMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKGMxKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9zaHJfdShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChjMCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTY0X2NvbnN0KDMyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChrPj1uMzIpIHtcbiAgICAgICAgICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICAgICAgICAgIGMuaTY0X3N0b3JlMzIoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiclwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIChrLW4zMikqNCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoYzApXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgICAgIGMwX29sZCxcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChjMSlcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgICAgIGMxX29sZCxcbiAgICAgICAgICAgICAgICAgICAgYy5pNjRfc2hyX3UoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKGMwX29sZCksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmk2NF9jb25zdCgzMilcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5pNjRfc3RvcmUzMihcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiclwiKSxcbiAgICAgICAgICAgICAgICBuMzIqNC00LFxuICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoYzBfb2xkKVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5pMzJfd3JhcF9pNjQoYy5nZXRMb2NhbChjMV9vbGQpKSxcbiAgICAgICAgICAgICAgICBjLmRyb3AoYy5jYWxsKGludFByZWZpeCtcIl9zdWJcIiwgYy5nZXRMb2NhbChcInJcIiksIGMuaTMyX2NvbnN0KHBxKSwgYy5nZXRMb2NhbChcInJcIikpKSxcbiAgICAgICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgICAgICBjLmNhbGwoaW50UHJlZml4K1wiX2d0ZVwiLCBjLmdldExvY2FsKFwiclwiKSwgYy5pMzJfY29uc3QocHEpICApLFxuICAgICAgICAgICAgICAgICAgICBjLmRyb3AoYy5jYWxsKGludFByZWZpeCtcIl9zdWJcIiwgYy5nZXRMb2NhbChcInJcIiksIGMuaTMyX2NvbnN0KHBxKSwgYy5nZXRMb2NhbChcInJcIikpKSxcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxuXG5cbiAgICBmdW5jdGlvbiBidWlsZFNxdWFyZU9sZCgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfc3F1YXJlT2xkXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBmLmFkZENvZGUoYy5jYWxsKHByZWZpeCArIFwiX211bFwiLCBjLmdldExvY2FsKFwieFwiKSwgYy5nZXRMb2NhbChcInhcIiksIGMuZ2V0TG9jYWwoXCJyXCIpKSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRUb01vbnRnb21lcnkoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX3RvTW9udGdvbWVyeVwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG4gICAgICAgIGYuYWRkQ29kZShjLmNhbGwocHJlZml4K1wiX211bFwiLCBjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QocFIyKSwgYy5nZXRMb2NhbChcInJcIikpKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZEZyb21Nb250Z29tZXJ5KCkge1xuXG4gICAgICAgIGNvbnN0IHBBdXgyID0gbW9kdWxlLmFsbG9jKG44KjIpO1xuXG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX2Zyb21Nb250Z29tZXJ5XCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcbiAgICAgICAgZi5hZGRDb2RlKGMuY2FsbChpbnRQcmVmaXggKyBcIl9jb3B5XCIsIGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdChwQXV4MikgKSk7XG4gICAgICAgIGYuYWRkQ29kZShjLmNhbGwoaW50UHJlZml4ICsgXCJfemVyb1wiLCBjLmkzMl9jb25zdChwQXV4MiArIG44KSApKTtcbiAgICAgICAgZi5hZGRDb2RlKGMuY2FsbChwcmVmaXgrXCJfbVJlZHVjdFwiLCBjLmkzMl9jb25zdChwQXV4MiksIGMuZ2V0TG9jYWwoXCJyXCIpKSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRJbnZlcnNlKCkge1xuXG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4KyBcIl9pbnZlcnNlXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcbiAgICAgICAgZi5hZGRDb2RlKGMuY2FsbChwcmVmaXggKyBcIl9mcm9tTW9udGdvbWVyeVwiLCBjLmdldExvY2FsKFwieFwiKSwgYy5nZXRMb2NhbChcInJcIikpKTtcbiAgICAgICAgZi5hZGRDb2RlKGMuY2FsbChpbnRQcmVmaXggKyBcIl9pbnZlcnNlTW9kXCIsIGMuZ2V0TG9jYWwoXCJyXCIpLCBjLmkzMl9jb25zdChwcSksIGMuZ2V0TG9jYWwoXCJyXCIpKSk7XG4gICAgICAgIGYuYWRkQ29kZShjLmNhbGwocHJlZml4ICsgXCJfdG9Nb250Z29tZXJ5XCIsIGMuZ2V0TG9jYWwoXCJyXCIpLCBjLmdldExvY2FsKFwiclwiKSkpO1xuICAgIH1cblxuICAgIC8vIENhbGN1bGF0ZSB2YXJpb3VzIHZhbHVzZSBuZWVkZWQgZm9yIHNxcnRcblxuXG4gICAgbGV0IF9ucXIgPSAybjtcbiAgICBpZiAoaXNQcmltZShxKSkge1xuICAgICAgICB3aGlsZSAobW9kUG93JDEoX25xciwgX2UsIHEpICE9PSBfbWludXNPbmUpIF9ucXIgPSBfbnFyICsgMW47XG4gICAgfVxuXG4gICAgbGV0IHMyID0gMDtcbiAgICBsZXQgX3QgPSBfbWludXNPbmU7XG5cbiAgICB3aGlsZSAoKCFpc09kZCQzKF90KSkmJihfdCAhPT0gMG4pKSB7XG4gICAgICAgIHMyKys7XG4gICAgICAgIF90ID0gX3QgPj4gMW47XG4gICAgfVxuICAgIGNvbnN0IHB0ID0gbW9kdWxlLmFsbG9jKG44LCB1dGlscyQ0LmJpZ0ludDJCeXRlc0xFKF90LCBuOCkpO1xuXG4gICAgY29uc3QgX25xclRvVCA9IG1vZFBvdyQxKF9ucXIsIF90LCBxKTtcbiAgICBjb25zdCBwTnFyVG9UID0gbW9kdWxlLmFsbG9jKHV0aWxzJDQuYmlnSW50MkJ5dGVzTEUoKF9ucXJUb1QgPDwgQmlnSW50KG42NCo2NCkpICUgcSwgbjgpKTtcblxuICAgIGNvbnN0IF90UGx1c09uZU92ZXIyID0gKF90ICsgMW4pID4+IDFuO1xuICAgIGNvbnN0IHB0UGx1c09uZU92ZXIyID0gbW9kdWxlLmFsbG9jKG44LCB1dGlscyQ0LmJpZ0ludDJCeXRlc0xFKF90UGx1c09uZU92ZXIyLCBuOCkpO1xuXG4gICAgZnVuY3Rpb24gYnVpbGRTcXJ0KCkge1xuXG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4KyBcIl9zcXJ0XCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiblwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJtXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiaVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImpcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCBPTkUgPSBjLmkzMl9jb25zdChwT25lKTtcbiAgICAgICAgY29uc3QgQyA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuICAgICAgICBjb25zdCBUID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IFIgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgU1EgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgQiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcblxuICAgICAgICAgICAgLy8gSWYgKG49PTApIHJldHVybiAwXG4gICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9pc1plcm9cIiwgYy5nZXRMb2NhbChcIm5cIikpLFxuICAgICAgICAgICAgICAgIGMucmV0KFxuICAgICAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfemVyb1wiLCBjLmdldExvY2FsKFwiclwiKSlcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApLFxuXG4gICAgICAgICAgICBjLnNldExvY2FsKFwibVwiLCBjLmkzMl9jb25zdChzMikpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX2NvcHlcIiwgYy5pMzJfY29uc3QocE5xclRvVCksIEMpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX2V4cFwiLCBjLmdldExvY2FsKFwiblwiKSwgYy5pMzJfY29uc3QocHQpLCBjLmkzMl9jb25zdChuOCksIFQpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX2V4cFwiLCBjLmdldExvY2FsKFwiblwiKSwgYy5pMzJfY29uc3QocHRQbHVzT25lT3ZlcjIpLCBjLmkzMl9jb25zdChuOCksIFIpLFxuXG4gICAgICAgICAgICBjLmJsb2NrKGMubG9vcChcbiAgICAgICAgICAgICAgICBjLmJyX2lmKDEsIGMuY2FsbChwcmVmaXggKyBcIl9lcVwiLCBULCBPTkUpKSxcblxuICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9zcXVhcmVcIiwgVCwgU1EpLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpXCIsIGMuaTMyX2NvbnN0KDEpKSxcbiAgICAgICAgICAgICAgICBjLmJsb2NrKGMubG9vcChcbiAgICAgICAgICAgICAgICAgICAgYy5icl9pZigxLCBjLmNhbGwocHJlZml4ICsgXCJfZXFcIiwgU1EsIE9ORSkpLFxuICAgICAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfc3F1YXJlXCIsIFNRLCBTUSksXG4gICAgICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwiaVwiKSwgYy5pMzJfY29uc3QoMSkpKSxcbiAgICAgICAgICAgICAgICAgICAgYy5icigwKVxuICAgICAgICAgICAgICAgICkpLFxuXG4gICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX2NvcHlcIiwgQywgQiksXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcImpcIiwgYy5pMzJfc3ViKGMuaTMyX3N1YiggYy5nZXRMb2NhbChcIm1cIiksIGMuZ2V0TG9jYWwoXCJpXCIpKSwgYy5pMzJfY29uc3QoMSkpICksXG4gICAgICAgICAgICAgICAgYy5ibG9jayhjLmxvb3AoXG4gICAgICAgICAgICAgICAgICAgIGMuYnJfaWYoMSwgYy5pMzJfZXF6KGMuZ2V0TG9jYWwoXCJqXCIpKSksXG4gICAgICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9zcXVhcmVcIiwgQiwgQiksXG4gICAgICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJqXCIsIGMuaTMyX3N1YihjLmdldExvY2FsKFwialwiKSwgYy5pMzJfY29uc3QoMSkpKSxcbiAgICAgICAgICAgICAgICAgICAgYy5icigwKVxuICAgICAgICAgICAgICAgICkpLFxuXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcIm1cIiwgYy5nZXRMb2NhbChcImlcIikpLFxuICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9zcXVhcmVcIiwgQiwgQyksXG4gICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX211bFwiLCBULCBDLCBUKSxcbiAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfbXVsXCIsIFIsIEIsIFIpLFxuXG4gICAgICAgICAgICAgICAgYy5icigwKVxuICAgICAgICAgICAgKSksXG5cbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX2lzTmVnYXRpdmVcIiwgUiksXG4gICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX25lZ1wiLCBSLCBjLmdldExvY2FsKFwiclwiKSksXG4gICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX2NvcHlcIiwgUiwgYy5nZXRMb2NhbChcInJcIikpLFxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkSXNTcXVhcmUoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX2lzU3F1YXJlXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiblwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5zZXRSZXR1cm5UeXBlKFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgT05FID0gYy5pMzJfY29uc3QocE9uZSk7XG4gICAgICAgIGNvbnN0IEFVWCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX2lzWmVyb1wiLCBjLmdldExvY2FsKFwiblwiKSksXG4gICAgICAgICAgICAgICAgYy5yZXQoYy5pMzJfY29uc3QoMSkpXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX2V4cFwiLCBjLmdldExvY2FsKFwiblwiKSwgYy5pMzJfY29uc3QocGUpLCBjLmkzMl9jb25zdChuOCksIEFVWCksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfZXFcIiwgQVVYLCBPTkUpXG4gICAgICAgICk7XG4gICAgfVxuXG5cbiAgICBmdW5jdGlvbiBidWlsZExvYWQoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX2xvYWRcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJzY2FsYXJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJzY2FsYXJMZW5cIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwicFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImxcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJpXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwialwiLCBcImkzMlwiKTtcbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCBSID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IHBBdXggPSBtb2R1bGUuYWxsb2MobjgpO1xuICAgICAgICBjb25zdCBBVVggPSBjLmkzMl9jb25zdChwQXV4KTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwoaW50UHJlZml4ICsgXCJfemVyb1wiLCBjLmdldExvY2FsKFwiclwiKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiaVwiLCBjLmkzMl9jb25zdChuOCkpLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcInBcIiwgYy5nZXRMb2NhbChcInNjYWxhclwiKSksXG4gICAgICAgICAgICBjLmJsb2NrKGMubG9vcChcbiAgICAgICAgICAgICAgICBjLmJyX2lmKDEsIGMuaTMyX2d0X3UoYy5nZXRMb2NhbChcImlcIiksIGMuZ2V0TG9jYWwoXCJzY2FsYXJMZW5cIikpKSxcblxuICAgICAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2VxKGMuZ2V0TG9jYWwoXCJpXCIpLCBjLmkzMl9jb25zdChuOCkpLFxuICAgICAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfb25lXCIsIFIpLFxuICAgICAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfbXVsXCIsIFIsIGMuaTMyX2NvbnN0KHBSMiksIFIpXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfbXVsXCIsIGMuZ2V0TG9jYWwoXCJwXCIpLCBSLCBBVVgpLFxuICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9hZGRcIiwgYy5nZXRMb2NhbChcInJcIiksIEFVWCwgYy5nZXRMb2NhbChcInJcIikpLFxuXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcInBcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwXCIpLCBjLmkzMl9jb25zdChuOCkpKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaVwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcImlcIiksIGMuaTMyX2NvbnN0KG44KSkpLFxuICAgICAgICAgICAgICAgIGMuYnIoMClcbiAgICAgICAgICAgICkpLFxuXG4gICAgICAgICAgICBjLnNldExvY2FsKFwibFwiLCBjLmkzMl9yZW1fdSggYy5nZXRMb2NhbChcInNjYWxhckxlblwiKSwgYy5pMzJfY29uc3QobjgpKSksXG4gICAgICAgICAgICBjLmlmKGMuaTMyX2VxeihjLmdldExvY2FsKFwibFwiKSksIGMucmV0KFtdKSksXG4gICAgICAgICAgICBjLmNhbGwoaW50UHJlZml4ICsgXCJfemVyb1wiLCBBVVgpLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcImpcIiwgYy5pMzJfY29uc3QoMCkpLFxuICAgICAgICAgICAgYy5ibG9jayhjLmxvb3AoXG4gICAgICAgICAgICAgICAgYy5icl9pZigxLCBjLmkzMl9lcShjLmdldExvY2FsKFwialwiKSwgYy5nZXRMb2NhbChcImxcIikpKSxcblxuICAgICAgICAgICAgICAgIGMuaTMyX3N0b3JlOChcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImpcIiksXG4gICAgICAgICAgICAgICAgICAgIHBBdXgsXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2xvYWQ4X3UoYy5nZXRMb2NhbChcInBcIikpLFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcInBcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwXCIpLCBjLmkzMl9jb25zdCgxKSkpLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJqXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwialwiKSwgYy5pMzJfY29uc3QoMSkpKSxcbiAgICAgICAgICAgICAgICBjLmJyKDApXG4gICAgICAgICAgICApKSxcblxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmkzMl9lcShjLmdldExvY2FsKFwiaVwiKSwgYy5pMzJfY29uc3QobjgpKSxcbiAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfb25lXCIsIFIpLFxuICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9tdWxcIiwgUiwgYy5pMzJfY29uc3QocFIyKSwgUilcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfbXVsXCIsIEFVWCwgUiwgQVVYKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9hZGRcIiwgYy5nZXRMb2NhbChcInJcIiksIEFVWCwgYy5nZXRMb2NhbChcInJcIikpLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkVGltZXNTY2FsYXIoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX3RpbWVzU2NhbGFyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInNjYWxhclwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInNjYWxhckxlblwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCBBVVggPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfbG9hZFwiLCBjLmdldExvY2FsKFwic2NhbGFyXCIpLCBjLmdldExvY2FsKFwic2NhbGFyTGVuXCIpLCBBVVgpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX3RvTW9udGdvbWVyeVwiLCBBVVgsIEFVWCksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfbXVsXCIsIGMuZ2V0TG9jYWwoXCJ4XCIpLCBBVVgsIGMuZ2V0TG9jYWwoXCJyXCIpKSxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZElzT25lKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9pc09uZVwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuc2V0UmV0dXJuVHlwZShcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLnJldChjLmNhbGwoaW50UHJlZml4ICsgXCJfZXFcIiwgYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KHBPbmUpKSlcbiAgICAgICAgKTtcbiAgICB9XG5cblxuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihpbnRQcmVmaXggKyBcIl9jb3B5XCIsIHByZWZpeCtcIl9jb3B5XCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihpbnRQcmVmaXggKyBcIl96ZXJvXCIsIHByZWZpeCtcIl96ZXJvXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihpbnRQcmVmaXggKyBcIl9pc1plcm9cIiwgcHJlZml4K1wiX2lzWmVyb1wiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24oaW50UHJlZml4ICsgXCJfZXFcIiwgcHJlZml4K1wiX2VxXCIpO1xuXG4gICAgYnVpbGRJc09uZSgpO1xuICAgIGJ1aWxkQWRkKCk7XG4gICAgYnVpbGRTdWIoKTtcbiAgICBidWlsZE5lZygpO1xuICAgIGJ1aWxkTVJlZHVjdCgpO1xuICAgIGJ1aWxkTXVsKCk7XG4gICAgYnVpbGRTcXVhcmUoKTtcbiAgICBidWlsZFNxdWFyZU9sZCgpO1xuICAgIGJ1aWxkVG9Nb250Z29tZXJ5KCk7XG4gICAgYnVpbGRGcm9tTW9udGdvbWVyeSgpO1xuICAgIGJ1aWxkSXNOZWdhdGl2ZSgpO1xuICAgIGJ1aWxkU2lnbigpO1xuICAgIGJ1aWxkSW52ZXJzZSgpO1xuICAgIGJ1aWxkT25lKCk7XG4gICAgYnVpbGRMb2FkKCk7XG4gICAgYnVpbGRUaW1lc1NjYWxhcigpO1xuICAgIGJ1aWxkQmF0Y2hJbnZlcnNlJDIobW9kdWxlLCBwcmVmaXgpO1xuICAgIGJ1aWxkQmF0Y2hDb252ZXJ0aW9uJDEobW9kdWxlLCBwcmVmaXggKyBcIl9iYXRjaFRvTW9udGdvbWVyeVwiLCBwcmVmaXggKyBcIl90b01vbnRnb21lcnlcIiwgbjgsIG44KTtcbiAgICBidWlsZEJhdGNoQ29udmVydGlvbiQxKG1vZHVsZSwgcHJlZml4ICsgXCJfYmF0Y2hGcm9tTW9udGdvbWVyeVwiLCBwcmVmaXggKyBcIl9mcm9tTW9udGdvbWVyeVwiLCBuOCwgbjgpO1xuICAgIGJ1aWxkQmF0Y2hDb252ZXJ0aW9uJDEobW9kdWxlLCBwcmVmaXggKyBcIl9iYXRjaE5lZ1wiLCBwcmVmaXggKyBcIl9uZWdcIiwgbjgsIG44KTtcbiAgICBidWlsZEJhdGNoT3AobW9kdWxlLCBwcmVmaXggKyBcIl9iYXRjaEFkZFwiLCBwcmVmaXggKyBcIl9hZGRcIiwgbjgsIG44KTtcbiAgICBidWlsZEJhdGNoT3AobW9kdWxlLCBwcmVmaXggKyBcIl9iYXRjaFN1YlwiLCBwcmVmaXggKyBcIl9zdWJcIiwgbjgsIG44KTtcbiAgICBidWlsZEJhdGNoT3AobW9kdWxlLCBwcmVmaXggKyBcIl9iYXRjaE11bFwiLCBwcmVmaXggKyBcIl9tdWxcIiwgbjgsIG44KTtcblxuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9hZGRcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX3N1YlwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfbmVnXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9pc05lZ2F0aXZlXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9pc09uZVwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfc2lnblwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfbVJlZHVjdFwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfbXVsXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9zcXVhcmVcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX3NxdWFyZU9sZFwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfZnJvbU1vbnRnb21lcnlcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX3RvTW9udGdvbWVyeVwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfaW52ZXJzZVwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfb25lXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9sb2FkXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl90aW1lc1NjYWxhclwiKTtcbiAgICBidWlsZEV4cCQyKFxuICAgICAgICBtb2R1bGUsXG4gICAgICAgIHByZWZpeCArIFwiX2V4cFwiLFxuICAgICAgICBuOCxcbiAgICAgICAgcHJlZml4ICsgXCJfbXVsXCIsXG4gICAgICAgIHByZWZpeCArIFwiX3NxdWFyZVwiLFxuICAgICAgICBpbnRQcmVmaXggKyBcIl9jb3B5XCIsXG4gICAgICAgIHByZWZpeCArIFwiX29uZVwiLFxuICAgICk7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2V4cFwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfYmF0Y2hJbnZlcnNlXCIpO1xuICAgIGlmIChpc1ByaW1lKHEpKSB7XG4gICAgICAgIGJ1aWxkU3FydCgpO1xuICAgICAgICBidWlsZElzU3F1YXJlKCk7XG4gICAgICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9zcXJ0XCIpO1xuICAgICAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfaXNTcXVhcmVcIik7XG4gICAgfVxuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9iYXRjaFRvTW9udGdvbWVyeVwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfYmF0Y2hGcm9tTW9udGdvbWVyeVwiKTtcbiAgICAvLyBjb25zb2xlLmxvZyhtb2R1bGUuZnVuY3Rpb25JZHhCeU5hbWUpO1xuXG4gICAgcmV0dXJuIHByZWZpeDtcbn07XG5cbi8qXG4gICAgQ29weXJpZ2h0IDIwMTkgMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiB3YXNtc25hcmsgKFdlYiBBc3NlbWJseSB6a1NuYXJrIFByb3ZlcikuXG5cbiAgICB3YXNtc25hcmsgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gICAgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAgICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICAgIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICB3YXNtc25hcmsgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggd2FzbXNuYXJrLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuY29uc3QgYnVpbGRGMW0kMiA9YnVpbGRfZjFtO1xuY29uc3QgeyBiaXRMZW5ndGg6IGJpdExlbmd0aCQzIH0gPSBiaWdpbnQ7XG5cbnZhciBidWlsZF9mMSA9IGZ1bmN0aW9uIGJ1aWxkRjEobW9kdWxlLCBfcSwgX3ByZWZpeCwgX2YxbVByZWZpeCwgX2ludFByZWZpeCkge1xuXG4gICAgY29uc3QgcSA9IEJpZ0ludChfcSk7XG4gICAgY29uc3QgbjY0ID0gTWF0aC5mbG9vcigoYml0TGVuZ3RoJDMocSAtIDFuKSAtIDEpLzY0KSArMTtcbiAgICBjb25zdCBuOCA9IG42NCo4O1xuXG4gICAgY29uc3QgcHJlZml4ID0gX3ByZWZpeCB8fCBcImYxXCI7XG4gICAgaWYgKG1vZHVsZS5tb2R1bGVzW3ByZWZpeF0pIHJldHVybiBwcmVmaXg7ICAvLyBhbHJlYWR5IGJ1aWxkZWRcbiAgICBtb2R1bGUubW9kdWxlc1twcmVmaXhdID0ge1xuICAgICAgICBuNjQ6IG42NFxuICAgIH07XG5cbiAgICBjb25zdCBpbnRQcmVmaXggPSBfaW50UHJlZml4IHx8IFwiaW50XCI7XG4gICAgY29uc3QgZjFtUHJlZml4ID0gYnVpbGRGMW0kMihtb2R1bGUsIHEsIF9mMW1QcmVmaXgsIGludFByZWZpeCk7XG5cblxuICAgIGNvbnN0IHBSMiA9ICAgICBtb2R1bGUubW9kdWxlc1tmMW1QcmVmaXhdLnBSMjtcbiAgICBjb25zdCBwcSA9ICAgICBtb2R1bGUubW9kdWxlc1tmMW1QcmVmaXhdLnBxO1xuICAgIGNvbnN0IHBlUGx1c09uZSA9IG1vZHVsZS5tb2R1bGVzW2YxbVByZWZpeF0ucGVQbHVzT25lO1xuXG4gICAgZnVuY3Rpb24gYnVpbGRNdWwoKSB7XG4gICAgICAgIGNvbnN0IHBBdXgxID0gbW9kdWxlLmFsbG9jKG44KTtcblxuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCsgXCJfbXVsXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInlcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG4gICAgICAgIGYuYWRkQ29kZShjLmNhbGwoZjFtUHJlZml4ICsgXCJfbXVsXCIsIGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmdldExvY2FsKFwieVwiKSwgYy5pMzJfY29uc3QocEF1eDEpKSk7XG4gICAgICAgIGYuYWRkQ29kZShjLmNhbGwoZjFtUHJlZml4ICsgXCJfbXVsXCIsIGMuaTMyX2NvbnN0KHBBdXgxKSwgYy5pMzJfY29uc3QocFIyKSwgYy5nZXRMb2NhbChcInJcIikpKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZFNxdWFyZSgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfc3F1YXJlXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBmLmFkZENvZGUoYy5jYWxsKHByZWZpeCArIFwiX211bFwiLCBjLmdldExvY2FsKFwieFwiKSwgYy5nZXRMb2NhbChcInhcIiksIGMuZ2V0TG9jYWwoXCJyXCIpKSk7XG4gICAgfVxuXG5cbiAgICBmdW5jdGlvbiBidWlsZEludmVyc2UoKSB7XG5cbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrIFwiX2ludmVyc2VcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ4XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiclwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuICAgICAgICBmLmFkZENvZGUoYy5jYWxsKGludFByZWZpeCArIFwiX2ludmVyc2VNb2RcIiwgYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KHBxKSwgYy5nZXRMb2NhbChcInJcIikpKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZElzTmVnYXRpdmUoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX2lzTmVnYXRpdmVcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ4XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLnNldFJldHVyblR5cGUoXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwoaW50UHJlZml4ICsgXCJfZ3RlXCIsIGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdChwZVBsdXNPbmUpIClcbiAgICAgICAgKTtcbiAgICB9XG5cblxuICAgIGJ1aWxkTXVsKCk7XG4gICAgYnVpbGRTcXVhcmUoKTtcbiAgICBidWlsZEludmVyc2UoKTtcbiAgICBidWlsZElzTmVnYXRpdmUoKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24oZjFtUHJlZml4ICsgXCJfYWRkXCIsIHByZWZpeCArIFwiX2FkZFwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24oZjFtUHJlZml4ICsgXCJfc3ViXCIsIHByZWZpeCArIFwiX3N1YlwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24oZjFtUHJlZml4ICsgXCJfbmVnXCIsIHByZWZpeCArIFwiX25lZ1wiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfbXVsXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9zcXVhcmVcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2ludmVyc2VcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2lzTmVnYXRpdmVcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKGYxbVByZWZpeCArIFwiX2NvcHlcIiwgcHJlZml4K1wiX2NvcHlcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKGYxbVByZWZpeCArIFwiX3plcm9cIiwgcHJlZml4K1wiX3plcm9cIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKGYxbVByZWZpeCArIFwiX29uZVwiLCBwcmVmaXgrXCJfb25lXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihmMW1QcmVmaXggKyBcIl9pc1plcm9cIiwgcHJlZml4K1wiX2lzWmVyb1wiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24oZjFtUHJlZml4ICsgXCJfZXFcIiwgcHJlZml4K1wiX2VxXCIpO1xuXG4gICAgcmV0dXJuIHByZWZpeDtcbn07XG5cbi8qXG4gICAgQ29weXJpZ2h0IDIwMTkgMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiB3YXNtc25hcmsgKFdlYiBBc3NlbWJseSB6a1NuYXJrIFByb3ZlcikuXG5cbiAgICB3YXNtc25hcmsgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gICAgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAgICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICAgIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICB3YXNtc25hcmsgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggd2FzbXNuYXJrLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuY29uc3QgYnVpbGRFeHAkMSA9IGJ1aWxkX3RpbWVzc2NhbGFyO1xuY29uc3QgYnVpbGRCYXRjaEludmVyc2UkMSA9IGJ1aWxkX2JhdGNoaW52ZXJzZTtcbmNvbnN0IHV0aWxzJDMgPSB1dGlscyQ1O1xuXG52YXIgYnVpbGRfZjJtID0gZnVuY3Rpb24gYnVpbGRGMm0obW9kdWxlLCBtdWxOb25SZXNpZHVlRm4sIHByZWZpeCwgZjFtUHJlZml4KSB7XG5cbiAgICBpZiAobW9kdWxlLm1vZHVsZXNbcHJlZml4XSkgcmV0dXJuIHByZWZpeDsgIC8vIGFscmVhZHkgYnVpbGRlZFxuXG4gICAgY29uc3QgZjFuOCA9IG1vZHVsZS5tb2R1bGVzW2YxbVByZWZpeF0ubjY0Kjg7XG4gICAgY29uc3QgcSA9IG1vZHVsZS5tb2R1bGVzW2YxbVByZWZpeF0ucTtcblxuICAgIG1vZHVsZS5tb2R1bGVzW3ByZWZpeF0gPSB7XG4gICAgICAgIG42NDogbW9kdWxlLm1vZHVsZXNbZjFtUHJlZml4XS5uNjQqMlxuICAgIH07XG5cbiAgICBmdW5jdGlvbiBidWlsZEFkZCgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfYWRkXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInlcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgeDAgPSBjLmdldExvY2FsKFwieFwiKTtcbiAgICAgICAgY29uc3QgeDEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcbiAgICAgICAgY29uc3QgeTAgPSBjLmdldExvY2FsKFwieVwiKTtcbiAgICAgICAgY29uc3QgeTEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInlcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcbiAgICAgICAgY29uc3QgcjAgPSBjLmdldExvY2FsKFwiclwiKTtcbiAgICAgICAgY29uc3QgcjEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInJcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX2FkZFwiLCB4MCwgeTAsIHIwKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfYWRkXCIsIHgxLCB5MSwgcjEpLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkVGltZXNTY2FsYXIoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX3RpbWVzU2NhbGFyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInNjYWxhclwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInNjYWxhckxlblwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCB4MCA9IGMuZ2V0TG9jYWwoXCJ4XCIpO1xuICAgICAgICBjb25zdCB4MSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QoZjFuOCkpO1xuICAgICAgICBjb25zdCByMCA9IGMuZ2V0TG9jYWwoXCJyXCIpO1xuICAgICAgICBjb25zdCByMSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwiclwiKSwgYy5pMzJfY29uc3QoZjFuOCkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfdGltZXNTY2FsYXJcIiwgeDAsIGMuZ2V0TG9jYWwoXCJzY2FsYXJcIiksIGMuZ2V0TG9jYWwoXCJzY2FsYXJMZW5cIiksIHIwKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfdGltZXNTY2FsYXJcIiwgeDEsIGMuZ2V0TG9jYWwoXCJzY2FsYXJcIiksIGMuZ2V0TG9jYWwoXCJzY2FsYXJMZW5cIiksIHIxKSxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZFN1YigpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfc3ViXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInlcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgeDAgPSBjLmdldExvY2FsKFwieFwiKTtcbiAgICAgICAgY29uc3QgeDEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcbiAgICAgICAgY29uc3QgeTAgPSBjLmdldExvY2FsKFwieVwiKTtcbiAgICAgICAgY29uc3QgeTEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInlcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcbiAgICAgICAgY29uc3QgcjAgPSBjLmdldExvY2FsKFwiclwiKTtcbiAgICAgICAgY29uc3QgcjEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInJcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX3N1YlwiLCB4MCwgeTAsIHIwKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfc3ViXCIsIHgxLCB5MSwgcjEpLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkTmVnKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9uZWdcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ4XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiclwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IHgwID0gYy5nZXRMb2NhbChcInhcIik7XG4gICAgICAgIGNvbnN0IHgxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdChmMW44KSk7XG4gICAgICAgIGNvbnN0IHIwID0gYy5nZXRMb2NhbChcInJcIik7XG4gICAgICAgIGNvbnN0IHIxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJyXCIpLCBjLmkzMl9jb25zdChmMW44KSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9uZWdcIiwgeDAsIHIwKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfbmVnXCIsIHgxLCByMSksXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRDb25qdWdhdGUoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX2Nvbmp1Z2F0ZVwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgeDAgPSBjLmdldExvY2FsKFwieFwiKTtcbiAgICAgICAgY29uc3QgeDEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcbiAgICAgICAgY29uc3QgcjAgPSBjLmdldExvY2FsKFwiclwiKTtcbiAgICAgICAgY29uc3QgcjEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInJcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX2NvcHlcIiwgeDAsIHIwKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfbmVnXCIsIHgxLCByMSksXG4gICAgICAgICk7XG4gICAgfVxuXG5cbiAgICBmdW5jdGlvbiBidWlsZElzTmVnYXRpdmUoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX2lzTmVnYXRpdmVcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ4XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLnNldFJldHVyblR5cGUoXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCB4MCA9IGMuZ2V0TG9jYWwoXCJ4XCIpO1xuICAgICAgICBjb25zdCB4MSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QoZjFuOCkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9pc1plcm9cIiwgeDEpLFxuICAgICAgICAgICAgICAgIGMucmV0KGMuY2FsbChmMW1QcmVmaXgrXCJfaXNOZWdhdGl2ZVwiLCB4MCkpXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5yZXQoYy5jYWxsKGYxbVByZWZpeCtcIl9pc05lZ2F0aXZlXCIsIHgxKSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZE11bCgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfbXVsXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInlcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgeDAgPSBjLmdldExvY2FsKFwieFwiKTtcbiAgICAgICAgY29uc3QgeDEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcbiAgICAgICAgY29uc3QgeTAgPSBjLmdldExvY2FsKFwieVwiKTtcbiAgICAgICAgY29uc3QgeTEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInlcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcbiAgICAgICAgY29uc3QgcjAgPSBjLmdldExvY2FsKFwiclwiKTtcbiAgICAgICAgY29uc3QgcjEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInJcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcblxuICAgICAgICBjb25zdCBBID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxbjgpKTtcbiAgICAgICAgY29uc3QgQiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMW44KSk7XG4gICAgICAgIGNvbnN0IEMgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjFuOCkpO1xuICAgICAgICBjb25zdCBEID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxbjgpKTtcblxuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXggKyBcIl9tdWxcIiwgeDAsIHkwLCBBKSwgICAgICAgICAgICAgLy8gQSA9IHgwKnkwXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4ICsgXCJfbXVsXCIsIHgxLCB5MSwgQiksICAgICAgICAgICAgIC8vIEIgPSB4MSp5MVxuXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4ICsgXCJfYWRkXCIsIHgwLCB4MSwgQyksICAgICAgICAgICAgIC8vIEMgPSB4MCArIHgxXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4ICsgXCJfYWRkXCIsIHkwLCB5MSwgRCksICAgICAgICAgICAgIC8vIEQgPSB5MCArIHkxXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4ICsgXCJfbXVsXCIsIEMsIEQsIEMpLCAgICAgICAgICAgICAgIC8vIEMgPSAoeDAgKyB4MSkqKHkwICsgeTEpID0geDAqeTAreDAqeTEreDEqeTAreDEqeTFcblxuICAgICAgICAgICAgLy8gIGMuY2FsbChmMW1QcmVmaXggKyBcIl9tdWxcIiwgQiwgYy5pMzJfY29uc3QocE5vblJlc2lkdWUpLCByMCksICAvLyByMCA9IG5yKih4MSp5MSlcbiAgICAgICAgICAgIGMuY2FsbChtdWxOb25SZXNpZHVlRm4sIEIsIHIwKSwgIC8vIHIwID0gbnIqKHgxKnkxKVxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCArIFwiX2FkZFwiLCBBLCByMCwgcjApLCAgICAgICAgICAgICAvLyByMCA9IHgwKnkwICsgbnIqKHgxKnkxKVxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCArIFwiX2FkZFwiLCBBLCBCLCByMSksICAgICAgICAgICAgIC8vIHIxID0geDAqeTAreDEqeTFcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXggKyBcIl9zdWJcIiwgQywgcjEsIHIxKSAgICAgICAgICAgICAgLy8gcjEgPSB4MCp5MCt4MCp5MSt4MSp5MCt4MSp5MSAtIHgwKnkwK3gxKnkxID0geDAqeTEreDEqeTBcbiAgICAgICAgKTtcblxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkTXVsMSgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfbXVsMVwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ5XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiclwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IHgwID0gYy5nZXRMb2NhbChcInhcIik7XG4gICAgICAgIGNvbnN0IHgxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdChmMW44KSk7XG4gICAgICAgIGNvbnN0IHkgPSBjLmdldExvY2FsKFwieVwiKTtcbiAgICAgICAgY29uc3QgcjAgPSBjLmdldExvY2FsKFwiclwiKTtcbiAgICAgICAgY29uc3QgcjEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInJcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcblxuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXggKyBcIl9tdWxcIiwgeDAsIHksIHIwKSwgICAgICAgICAgICAgLy8gQSA9IHgwKnlcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXggKyBcIl9tdWxcIiwgeDEsIHksIHIxKSwgICAgICAgICAgICAgLy8gQiA9IHgxKnlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZFNxdWFyZSgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfc3F1YXJlXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCB4MCA9IGMuZ2V0TG9jYWwoXCJ4XCIpO1xuICAgICAgICBjb25zdCB4MSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QoZjFuOCkpO1xuICAgICAgICBjb25zdCByMCA9IGMuZ2V0TG9jYWwoXCJyXCIpO1xuICAgICAgICBjb25zdCByMSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwiclwiKSwgYy5pMzJfY29uc3QoZjFuOCkpO1xuXG4gICAgICAgIGNvbnN0IEFCID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxbjgpKTtcbiAgICAgICAgY29uc3QgQVBCID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxbjgpKTtcbiAgICAgICAgY29uc3QgQVBOQiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMW44KSk7XG4gICAgICAgIGNvbnN0IEFCUE5BQiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMW44KSk7XG5cblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICAvLyBBQiA9IHgwKnkxXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4ICsgXCJfbXVsXCIsIHgwLCB4MSwgQUIpLFxuXG4gICAgICAgICAgICAvLyBBUEIgPSB4MCt5MVxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCArIFwiX2FkZFwiLCB4MCwgeDEsIEFQQiksXG5cbiAgICAgICAgICAgIC8vIEFQQk4wID0geDAgKyBucip4MVxuICAgICAgICAgICAgYy5jYWxsKG11bE5vblJlc2lkdWVGbiwgeDEsIEFQTkIpLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCArIFwiX2FkZFwiLCB4MCwgQVBOQiwgQVBOQiksXG5cbiAgICAgICAgICAgIC8vIEFCUE5BQiA9IGFiICsgbnIqYWJcbiAgICAgICAgICAgIGMuY2FsbChtdWxOb25SZXNpZHVlRm4sIEFCLCBBQlBOQUIpLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCArIFwiX2FkZFwiLCBBQlBOQUIsIEFCLCBBQlBOQUIpLFxuXG4gICAgICAgICAgICAvLyByMCA9IEFQQiAqIEFQTkIgLSBBQlBOQUJcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXggKyBcIl9tdWxcIiwgQVBCLCBBUE5CLCByMCksXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4ICsgXCJfc3ViXCIsIHIwLCBBQlBOQUIsIHIwKSxcblxuICAgICAgICAgICAgLy8gcjEgPSBBQiArIEFCXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4ICsgXCJfYWRkXCIsIEFCLCBBQiwgcjEpLFxuICAgICAgICApO1xuXG4gICAgfVxuXG5cbiAgICBmdW5jdGlvbiBidWlsZFRvTW9udGdvbWVyeSgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfdG9Nb250Z29tZXJ5XCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCB4MCA9IGMuZ2V0TG9jYWwoXCJ4XCIpO1xuICAgICAgICBjb25zdCB4MSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QoZjFuOCkpO1xuICAgICAgICBjb25zdCByMCA9IGMuZ2V0TG9jYWwoXCJyXCIpO1xuICAgICAgICBjb25zdCByMSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwiclwiKSwgYy5pMzJfY29uc3QoZjFuOCkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfdG9Nb250Z29tZXJ5XCIsIHgwLCByMCksXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX3RvTW9udGdvbWVyeVwiLCB4MSwgcjEpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRGcm9tTW9udGdvbWVyeSgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfZnJvbU1vbnRnb21lcnlcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ4XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiclwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IHgwID0gYy5nZXRMb2NhbChcInhcIik7XG4gICAgICAgIGNvbnN0IHgxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdChmMW44KSk7XG4gICAgICAgIGNvbnN0IHIwID0gYy5nZXRMb2NhbChcInJcIik7XG4gICAgICAgIGNvbnN0IHIxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJyXCIpLCBjLmkzMl9jb25zdChmMW44KSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9mcm9tTW9udGdvbWVyeVwiLCB4MCwgcjApLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9mcm9tTW9udGdvbWVyeVwiLCB4MSwgcjEpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRDb3B5KCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9jb3B5XCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCB4MCA9IGMuZ2V0TG9jYWwoXCJ4XCIpO1xuICAgICAgICBjb25zdCB4MSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QoZjFuOCkpO1xuICAgICAgICBjb25zdCByMCA9IGMuZ2V0TG9jYWwoXCJyXCIpO1xuICAgICAgICBjb25zdCByMSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwiclwiKSwgYy5pMzJfY29uc3QoZjFuOCkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfY29weVwiLCB4MCwgcjApLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9jb3B5XCIsIHgxLCByMSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZFplcm8oKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX3plcm9cIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ4XCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgeDAgPSBjLmdldExvY2FsKFwieFwiKTtcbiAgICAgICAgY29uc3QgeDEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX3plcm9cIiwgeDApLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl96ZXJvXCIsIHgxKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkT25lKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9vbmVcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ4XCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgeDAgPSBjLmdldExvY2FsKFwieFwiKTtcbiAgICAgICAgY29uc3QgeDEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX29uZVwiLCB4MCksXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX3plcm9cIiwgeDEpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRFcSgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfZXFcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ4XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5zZXRSZXR1cm5UeXBlKFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgeDAgPSBjLmdldExvY2FsKFwieFwiKTtcbiAgICAgICAgY29uc3QgeDEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcbiAgICAgICAgY29uc3QgeTAgPSBjLmdldExvY2FsKFwieVwiKTtcbiAgICAgICAgY29uc3QgeTEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInlcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmkzMl9hbmQoXG4gICAgICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9lcVwiLCB4MCwgeTApLFxuICAgICAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfZXFcIiwgeDEsIHkxKVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkSXNaZXJvKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9pc1plcm9cIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ4XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLnNldFJldHVyblR5cGUoXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCB4MCA9IGMuZ2V0TG9jYWwoXCJ4XCIpO1xuICAgICAgICBjb25zdCB4MSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QoZjFuOCkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuaTMyX2FuZChcbiAgICAgICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX2lzWmVyb1wiLCB4MCksXG4gICAgICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9pc1plcm9cIiwgeDEpXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRJbnZlcnNlKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9pbnZlcnNlXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCB4MCA9IGMuZ2V0TG9jYWwoXCJ4XCIpO1xuICAgICAgICBjb25zdCB4MSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QoZjFuOCkpO1xuICAgICAgICBjb25zdCByMCA9IGMuZ2V0TG9jYWwoXCJyXCIpO1xuICAgICAgICBjb25zdCByMSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwiclwiKSwgYy5pMzJfY29uc3QoZjFuOCkpO1xuXG4gICAgICAgIGNvbnN0IHQwID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxbjgpKTtcbiAgICAgICAgY29uc3QgdDEgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjFuOCkpO1xuICAgICAgICBjb25zdCB0MiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMW44KSk7XG4gICAgICAgIGNvbnN0IHQzID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxbjgpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX3NxdWFyZVwiLCB4MCwgdDApLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9zcXVhcmVcIiwgeDEsIHQxKSxcbiAgICAgICAgICAgIC8vIGMuY2FsbChmMW1QcmVmaXgrXCJfbXVsXCIsIHQxLCBjLmkzMl9jb25zdChwTm9uUmVzaWR1ZSksIHQyKSxcbiAgICAgICAgICAgIGMuY2FsbChtdWxOb25SZXNpZHVlRm4sIHQxLCB0MiksXG5cbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfc3ViXCIsIHQwLCB0MiwgdDIpLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9pbnZlcnNlXCIsIHQyLCB0MyksXG5cbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfbXVsXCIsIHgwLCB0MywgcjApLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9tdWxcIiwgeDEsIHQzLCByMSksXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX25lZ1wiLCByMSwgcjEpLFxuICAgICAgICApO1xuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gYnVpbGRTaWduKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9zaWduXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcInNcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuc2V0UmV0dXJuVHlwZShcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IHgwID0gYy5nZXRMb2NhbChcInhcIik7XG4gICAgICAgIGNvbnN0IHgxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdChmMW44KSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcInNcIiAsIGMuY2FsbCggZjFtUHJlZml4ICsgXCJfc2lnblwiLCB4MSkpLFxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwic1wiKSxcbiAgICAgICAgICAgICAgICBjLnJldChjLmdldExvY2FsKFwic1wiKSlcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLnJldChjLmNhbGwoIGYxbVByZWZpeCArIFwiX3NpZ25cIiwgeDApKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkSXNPbmUoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX2lzT25lXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5zZXRSZXR1cm5UeXBlKFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgeDAgPSBjLmdldExvY2FsKFwieFwiKTtcbiAgICAgICAgY29uc3QgeDEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLnJldChjLmkzMl9hbmQoXG4gICAgICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCArIFwiX2lzT25lXCIsIHgwKSxcbiAgICAgICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4ICsgXCJfaXNaZXJvXCIsIHgxKSxcbiAgICAgICAgICAgICkpXG4gICAgICAgICk7XG4gICAgfVxuXG5cbiAgICAvLyBDaGVjayBoZXJlOiBodHRwczovL2VwcmludC5pYWNyLm9yZy8yMDEyLzY4NS5wZGZcbiAgICAvLyBBbGcgOWFkalxuICAgIGZ1bmN0aW9uIGJ1aWxkU3FydCgpIHtcblxuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9zcXJ0XCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiYVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInByXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgLy8gQmlnSW50IGNhbid0IHRha2UgYHVuZGVmaW5lZGAgc28gd2UgdXNlIGB8fCAwYFxuICAgICAgICBjb25zdCBlMzQgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2ModXRpbHMkMy5iaWdJbnQyQnl0ZXNMRSgoQmlnSW50KHEgfHwgMCkgLSAzbikgLyA0biwgZjFuOCApKSk7XG4gICAgICAgIC8vIEJpZ0ludCBjYW4ndCB0YWtlIGB1bmRlZmluZWRgIHNvIHdlIHVzZSBgfHwgMGBcbiAgICAgICAgY29uc3QgZTEyID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKHV0aWxzJDMuYmlnSW50MkJ5dGVzTEUoKEJpZ0ludChxIHx8IDApIC0gMW4pIC8gMm4sIGYxbjggKSkpO1xuXG4gICAgICAgIGNvbnN0IGEgPSBjLmdldExvY2FsKFwiYVwiKTtcbiAgICAgICAgY29uc3QgYTEgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjFuOCoyKSk7XG4gICAgICAgIGNvbnN0IGFscGhhID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxbjgqMikpO1xuICAgICAgICBjb25zdCBhMCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMW44KjIpKTtcbiAgICAgICAgY29uc3QgcG4xID0gbW9kdWxlLmFsbG9jKGYxbjgqMik7XG4gICAgICAgIGNvbnN0IG4xID0gYy5pMzJfY29uc3QocG4xKTtcbiAgICAgICAgY29uc3QgbjFhID0gYy5pMzJfY29uc3QocG4xKTtcbiAgICAgICAgY29uc3QgbjFiID0gYy5pMzJfY29uc3QocG4xK2YxbjgpO1xuICAgICAgICBjb25zdCB4MCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMW44KjIpKTtcbiAgICAgICAgY29uc3QgYiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMW44KjIpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG5cbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9vbmVcIiwgbjEpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX25lZ1wiLCBuMSwgbjEpLFxuXG4gICAgICAgICAgICAvLyBjb25zdCBhMSA9IEYucG93KGEsIEYuc3FydF9lMzQpO1xuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX2V4cFwiLCBhLCBlMzQsIGMuaTMyX2NvbnN0KGYxbjgpLCBhMSksXG5cbiAgICAgICAgICAgIC8vIGNvbnN0IGExID0gRi5wb3coYSwgRi5zcXJ0X2UzNCk7XG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfc3F1YXJlXCIsIGExLCBhbHBoYSksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfbXVsXCIsIGEsIGFscGhhLCBhbHBoYSksXG5cbiAgICAgICAgICAgIC8vIGNvbnN0IGEwID0gRi5tdWwoRi5mcm9iZW5pdXMoMSwgYWxmYSksIGFsZmEpO1xuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX2Nvbmp1Z2F0ZVwiLCBhbHBoYSwgYTApLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX211bFwiLCBhMCwgYWxwaGEsIGEwKSxcblxuICAgICAgICAgICAgLy8gaWYgKEYuZXEoYTAsIEYubmVnb25lKSkgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICBjLmlmKGMuY2FsbChwcmVmaXggKyBcIl9lcVwiLGEwLG4xKSwgYy51bnJlYWNoYWJsZSgpICksXG5cbiAgICAgICAgICAgIC8vIGNvbnN0IHgwID0gRi5tdWwoYTEsIGEpO1xuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX211bFwiLCBhMSwgYSwgeDApLFxuXG4gICAgICAgICAgICAvLyBpZiAoRi5lcShhbGZhLCBGLm5lZ29uZSkpIHtcbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX2VxXCIsIGFscGhhLCBuMSksXG4gICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAvLyB4ID0gRi5tdWwoeDAsIFtGLkYuemVybywgRi5GLm9uZV0pO1xuICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwoZjFtUHJlZml4ICsgXCJfemVyb1wiLCBuMWEpLFxuICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwoZjFtUHJlZml4ICsgXCJfb25lXCIsIG4xYiksXG4gICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChwcmVmaXggKyBcIl9tdWxcIiwgbjEsIHgwLCBjLmdldExvY2FsKFwicHJcIikpLFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAvLyBjb25zdCBiID0gRi5wb3coRi5hZGQoRi5vbmUsIGFsZmEpLCBGLnNxcnRfZTEyKTtcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5jYWxsKHByZWZpeCArIFwiX29uZVwiLCBiKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5jYWxsKHByZWZpeCArIFwiX2FkZFwiLCBiLCBhbHBoYSwgYiksXG4gICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChwcmVmaXggKyBcIl9leHBcIiwgYiwgZTEyLCBjLmkzMl9jb25zdChmMW44KSwgYiksXG5cbiAgICAgICAgICAgICAgICAgICAgLy8geCA9IEYubXVsKGIsIHgwKTtcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5jYWxsKHByZWZpeCArIFwiX211bFwiLCBiLCB4MCwgYy5nZXRMb2NhbChcInByXCIpKSxcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG5cbiAgICB9XG5cblxuICAgIGZ1bmN0aW9uIGJ1aWxkSXNTcXVhcmUoKSB7XG5cbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfaXNTcXVhcmVcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJhXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLnNldFJldHVyblR5cGUoXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICAvLyBCaWdJbnQgY2FuJ3QgdGFrZSBgdW5kZWZpbmVkYCBzbyB3ZSB1c2UgYHx8IDBgXG4gICAgICAgIGNvbnN0IGUzNCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyh1dGlscyQzLmJpZ0ludDJCeXRlc0xFKChCaWdJbnQocSB8fCAwKSAtIDNuKSAvIDRuLCBmMW44ICkpKTtcblxuICAgICAgICBjb25zdCBhID0gYy5nZXRMb2NhbChcImFcIik7XG4gICAgICAgIGNvbnN0IGExID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxbjgqMikpO1xuICAgICAgICBjb25zdCBhbHBoYSA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMW44KjIpKTtcbiAgICAgICAgY29uc3QgYTAgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjFuOCoyKSk7XG4gICAgICAgIGNvbnN0IHBuMSA9IG1vZHVsZS5hbGxvYyhmMW44KjIpO1xuICAgICAgICBjb25zdCBuMSA9IGMuaTMyX2NvbnN0KHBuMSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfb25lXCIsIG4xKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9uZWdcIiwgbjEsIG4xKSxcblxuICAgICAgICAgICAgLy8gY29uc3QgYTEgPSBGLnBvdyhhLCBGLnNxcnRfZTM0KTtcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9leHBcIiwgYSwgZTM0LCBjLmkzMl9jb25zdChmMW44KSwgYTEpLFxuXG4gICAgICAgICAgICAvLyBjb25zdCBhMSA9IEYucG93KGEsIEYuc3FydF9lMzQpO1xuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX3NxdWFyZVwiLCBhMSwgYWxwaGEpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX211bFwiLCBhLCBhbHBoYSwgYWxwaGEpLFxuXG4gICAgICAgICAgICAvLyBjb25zdCBhMCA9IEYubXVsKEYuZnJvYmVuaXVzKDEsIGFsZmEpLCBhbGZhKTtcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9jb25qdWdhdGVcIiwgYWxwaGEsIGEwKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9tdWxcIiwgYTAsIGFscGhhLCBhMCksXG5cbiAgICAgICAgICAgIC8vIGlmIChGLmVxKGEwLCBGLm5lZ29uZSkpIHJldHVybiBudWxsO1xuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgICAgIHByZWZpeCArIFwiX2VxXCIsXG4gICAgICAgICAgICAgICAgICAgIGEwLFxuICAgICAgICAgICAgICAgICAgICBuMVxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgYy5yZXQoYy5pMzJfY29uc3QoMCkpXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5yZXQoYy5pMzJfY29uc3QoMSkpXG4gICAgICAgICk7XG5cbiAgICB9XG5cblxuICAgIGJ1aWxkSXNaZXJvKCk7XG4gICAgYnVpbGRJc09uZSgpO1xuICAgIGJ1aWxkWmVybygpO1xuICAgIGJ1aWxkT25lKCk7XG4gICAgYnVpbGRDb3B5KCk7XG4gICAgYnVpbGRNdWwoKTtcbiAgICBidWlsZE11bDEoKTtcbiAgICBidWlsZFNxdWFyZSgpO1xuICAgIGJ1aWxkQWRkKCk7XG4gICAgYnVpbGRTdWIoKTtcbiAgICBidWlsZE5lZygpO1xuICAgIGJ1aWxkQ29uanVnYXRlKCk7XG4gICAgYnVpbGRUb01vbnRnb21lcnkoKTtcbiAgICBidWlsZEZyb21Nb250Z29tZXJ5KCk7XG4gICAgYnVpbGRFcSgpO1xuICAgIGJ1aWxkSW52ZXJzZSgpO1xuICAgIGJ1aWxkVGltZXNTY2FsYXIoKTtcbiAgICBidWlsZFNpZ24oKTtcbiAgICBidWlsZElzTmVnYXRpdmUoKTtcblxuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9pc1plcm9cIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2lzT25lXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl96ZXJvXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9vbmVcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2NvcHlcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX211bFwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfbXVsMVwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfc3F1YXJlXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9hZGRcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX3N1YlwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfbmVnXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9zaWduXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9jb25qdWdhdGVcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2Zyb21Nb250Z29tZXJ5XCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl90b01vbnRnb21lcnlcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2VxXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9pbnZlcnNlXCIpO1xuICAgIGJ1aWxkQmF0Y2hJbnZlcnNlJDEobW9kdWxlLCBwcmVmaXgpO1xuICAgIGJ1aWxkRXhwJDEoXG4gICAgICAgIG1vZHVsZSxcbiAgICAgICAgcHJlZml4ICsgXCJfZXhwXCIsXG4gICAgICAgIGYxbjgqMixcbiAgICAgICAgcHJlZml4ICsgXCJfbXVsXCIsXG4gICAgICAgIHByZWZpeCArIFwiX3NxdWFyZVwiLFxuICAgICAgICBwcmVmaXggKyBcIl9jb3B5XCIsXG4gICAgICAgIHByZWZpeCArIFwiX29uZVwiLFxuICAgICk7XG4gICAgYnVpbGRTcXJ0KCk7XG4gICAgYnVpbGRJc1NxdWFyZSgpO1xuXG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2V4cFwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfdGltZXNTY2FsYXJcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2JhdGNoSW52ZXJzZVwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfc3FydFwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfaXNTcXVhcmVcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2lzTmVnYXRpdmVcIik7XG5cblxuICAgIHJldHVybiBwcmVmaXg7XG59O1xuXG4vKlxuICAgIENvcHlyaWdodCAyMDE5IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygd2FzbXNuYXJrIChXZWIgQXNzZW1ibHkgemtTbmFyayBQcm92ZXIpLlxuXG4gICAgd2FzbXNuYXJrIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICAgIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gICAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAgICAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgd2FzbXNuYXJrIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHdhc21zbmFyay4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbmNvbnN0IGJ1aWxkRXhwID0gYnVpbGRfdGltZXNzY2FsYXI7XG5jb25zdCBidWlsZEJhdGNoSW52ZXJzZSA9IGJ1aWxkX2JhdGNoaW52ZXJzZTtcblxudmFyIGJ1aWxkX2YzbSA9IGZ1bmN0aW9uIGJ1aWxkRjNtKG1vZHVsZSwgbXVsTm9uUmVzaWR1ZUZuLCBwcmVmaXgsIGYxbVByZWZpeCkge1xuXG4gICAgaWYgKG1vZHVsZS5tb2R1bGVzW3ByZWZpeF0pIHJldHVybiBwcmVmaXg7ICAvLyBhbHJlYWR5IGJ1aWxkZWRcblxuICAgIGNvbnN0IGYxbjggPSBtb2R1bGUubW9kdWxlc1tmMW1QcmVmaXhdLm42NCo4O1xuICAgIG1vZHVsZS5tb2R1bGVzW3ByZWZpeF0gPSB7XG4gICAgICAgIG42NDogbW9kdWxlLm1vZHVsZXNbZjFtUHJlZml4XS5uNjQqM1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBidWlsZEFkZCgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfYWRkXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInlcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgeDAgPSBjLmdldExvY2FsKFwieFwiKTtcbiAgICAgICAgY29uc3QgeDEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcbiAgICAgICAgY29uc3QgeDIgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KDIqZjFuOCkpO1xuICAgICAgICBjb25zdCB5MCA9IGMuZ2V0TG9jYWwoXCJ5XCIpO1xuICAgICAgICBjb25zdCB5MSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwieVwiKSwgYy5pMzJfY29uc3QoZjFuOCkpO1xuICAgICAgICBjb25zdCB5MiA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwieVwiKSwgYy5pMzJfY29uc3QoMipmMW44KSk7XG4gICAgICAgIGNvbnN0IHIwID0gYy5nZXRMb2NhbChcInJcIik7XG4gICAgICAgIGNvbnN0IHIxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJyXCIpLCBjLmkzMl9jb25zdChmMW44KSk7XG4gICAgICAgIGNvbnN0IHIyID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJyXCIpLCBjLmkzMl9jb25zdCgyKmYxbjgpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX2FkZFwiLCB4MCwgeTAsIHIwKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfYWRkXCIsIHgxLCB5MSwgcjEpLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9hZGRcIiwgeDIsIHkyLCByMiksXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRUaW1lc1NjYWxhcigpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfdGltZXNTY2FsYXJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ4XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwic2NhbGFyXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwic2NhbGFyTGVuXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiclwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IHgwID0gYy5nZXRMb2NhbChcInhcIik7XG4gICAgICAgIGNvbnN0IHgxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdChmMW44KSk7XG4gICAgICAgIGNvbnN0IHgyID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdCgyKmYxbjgpKTtcbiAgICAgICAgY29uc3QgcjAgPSBjLmdldExvY2FsKFwiclwiKTtcbiAgICAgICAgY29uc3QgcjEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInJcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcbiAgICAgICAgY29uc3QgcjIgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInJcIiksIGMuaTMyX2NvbnN0KDIqZjFuOCkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfdGltZXNTY2FsYXJcIiwgeDAsIGMuZ2V0TG9jYWwoXCJzY2FsYXJcIiksIGMuZ2V0TG9jYWwoXCJzY2FsYXJMZW5cIiksIHIwKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfdGltZXNTY2FsYXJcIiwgeDEsIGMuZ2V0TG9jYWwoXCJzY2FsYXJcIiksIGMuZ2V0TG9jYWwoXCJzY2FsYXJMZW5cIiksIHIxKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfdGltZXNTY2FsYXJcIiwgeDIsIGMuZ2V0TG9jYWwoXCJzY2FsYXJcIiksIGMuZ2V0TG9jYWwoXCJzY2FsYXJMZW5cIiksIHIyKSxcbiAgICAgICAgKTtcbiAgICB9XG5cblxuICAgIGZ1bmN0aW9uIGJ1aWxkU3ViKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9zdWJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ4XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCB4MCA9IGMuZ2V0TG9jYWwoXCJ4XCIpO1xuICAgICAgICBjb25zdCB4MSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QoZjFuOCkpO1xuICAgICAgICBjb25zdCB4MiA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QoMipmMW44KSk7XG4gICAgICAgIGNvbnN0IHkwID0gYy5nZXRMb2NhbChcInlcIik7XG4gICAgICAgIGNvbnN0IHkxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ5XCIpLCBjLmkzMl9jb25zdChmMW44KSk7XG4gICAgICAgIGNvbnN0IHkyID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ5XCIpLCBjLmkzMl9jb25zdCgyKmYxbjgpKTtcbiAgICAgICAgY29uc3QgcjAgPSBjLmdldExvY2FsKFwiclwiKTtcbiAgICAgICAgY29uc3QgcjEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInJcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcbiAgICAgICAgY29uc3QgcjIgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInJcIiksIGMuaTMyX2NvbnN0KDIqZjFuOCkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfc3ViXCIsIHgwLCB5MCwgcjApLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9zdWJcIiwgeDEsIHkxLCByMSksXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX3N1YlwiLCB4MiwgeTIsIHIyKSxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZE5lZygpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfbmVnXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCB4MCA9IGMuZ2V0TG9jYWwoXCJ4XCIpO1xuICAgICAgICBjb25zdCB4MSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QoZjFuOCkpO1xuICAgICAgICBjb25zdCB4MiA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QoMipmMW44KSk7XG4gICAgICAgIGNvbnN0IHIwID0gYy5nZXRMb2NhbChcInJcIik7XG4gICAgICAgIGNvbnN0IHIxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJyXCIpLCBjLmkzMl9jb25zdChmMW44KSk7XG4gICAgICAgIGNvbnN0IHIyID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJyXCIpLCBjLmkzMl9jb25zdCgyKmYxbjgpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX25lZ1wiLCB4MCwgcjApLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9uZWdcIiwgeDEsIHIxKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfbmVnXCIsIHgyLCByMiksXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRJc05lZ2F0aXZlKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9pc05lZ2F0aXZlXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5zZXRSZXR1cm5UeXBlKFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgeDAgPSBjLmdldExvY2FsKFwieFwiKTtcbiAgICAgICAgY29uc3QgeDEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcbiAgICAgICAgY29uc3QgeDIgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KDIqZjFuOCkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9pc1plcm9cIiwgeDIpLFxuICAgICAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfaXNaZXJvXCIsIHgxKSxcbiAgICAgICAgICAgICAgICAgICAgYy5yZXQoYy5jYWxsKGYxbVByZWZpeCtcIl9pc05lZ2F0aXZlXCIsIHgwKSksXG4gICAgICAgICAgICAgICAgICAgIGMucmV0KGMuY2FsbChmMW1QcmVmaXgrXCJfaXNOZWdhdGl2ZVwiLCB4MSkpXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMucmV0KGMuY2FsbChmMW1QcmVmaXgrXCJfaXNOZWdhdGl2ZVwiLCB4MikpXG4gICAgICAgICk7XG4gICAgfVxuXG5cbiAgICBmdW5jdGlvbiBidWlsZE11bCgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfbXVsXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInlcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGNkID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IGEgPSBjZC5nZXRMb2NhbChcInhcIik7XG4gICAgICAgIGNvbnN0IGIgPSBjZC5pMzJfYWRkKGNkLmdldExvY2FsKFwieFwiKSwgY2QuaTMyX2NvbnN0KGYxbjgpKTtcbiAgICAgICAgY29uc3QgYyA9IGNkLmkzMl9hZGQoY2QuZ2V0TG9jYWwoXCJ4XCIpLCBjZC5pMzJfY29uc3QoMipmMW44KSk7XG4gICAgICAgIGNvbnN0IEEgPSBjZC5nZXRMb2NhbChcInlcIik7XG4gICAgICAgIGNvbnN0IEIgPSBjZC5pMzJfYWRkKGNkLmdldExvY2FsKFwieVwiKSwgY2QuaTMyX2NvbnN0KGYxbjgpKTtcbiAgICAgICAgY29uc3QgQyA9IGNkLmkzMl9hZGQoY2QuZ2V0TG9jYWwoXCJ5XCIpLCBjZC5pMzJfY29uc3QoMipmMW44KSk7XG4gICAgICAgIGNvbnN0IHIwID0gY2QuZ2V0TG9jYWwoXCJyXCIpO1xuICAgICAgICBjb25zdCByMSA9IGNkLmkzMl9hZGQoY2QuZ2V0TG9jYWwoXCJyXCIpLCBjZC5pMzJfY29uc3QoZjFuOCkpO1xuICAgICAgICBjb25zdCByMiA9IGNkLmkzMl9hZGQoY2QuZ2V0TG9jYWwoXCJyXCIpLCBjZC5pMzJfY29uc3QoMipmMW44KSk7XG5cbiAgICAgICAgY29uc3QgYUEgPSBjZC5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxbjgpKTtcbiAgICAgICAgY29uc3QgYkIgPSBjZC5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxbjgpKTtcbiAgICAgICAgY29uc3QgY0MgPSBjZC5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxbjgpKTtcbiAgICAgICAgY29uc3QgYV9iID0gY2QuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMW44KSk7XG4gICAgICAgIGNvbnN0IEFfQiA9IGNkLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjFuOCkpO1xuICAgICAgICBjb25zdCBhX2MgPSBjZC5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxbjgpKTtcbiAgICAgICAgY29uc3QgQV9DID0gY2QuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMW44KSk7XG4gICAgICAgIGNvbnN0IGJfYyA9IGNkLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjFuOCkpO1xuICAgICAgICBjb25zdCBCX0MgPSBjZC5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxbjgpKTtcbiAgICAgICAgY29uc3QgYUFfYkIgPSBjZC5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxbjgpKTtcbiAgICAgICAgY29uc3QgYUFfY0MgPSBjZC5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxbjgpKTtcbiAgICAgICAgY29uc3QgYkJfY0MgPSBjZC5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxbjgpKTtcbiAgICAgICAgY29uc3QgQVVYID0gY2QuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMW44KSk7XG5cblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjZC5jYWxsKGYxbVByZWZpeCArIFwiX211bFwiLCBhLCBBLCBhQSksXG4gICAgICAgICAgICBjZC5jYWxsKGYxbVByZWZpeCArIFwiX211bFwiLCBiLCBCLCBiQiksXG4gICAgICAgICAgICBjZC5jYWxsKGYxbVByZWZpeCArIFwiX211bFwiLCBjLCBDLCBjQyksXG5cbiAgICAgICAgICAgIGNkLmNhbGwoZjFtUHJlZml4ICsgXCJfYWRkXCIsIGEsIGIsIGFfYiksXG4gICAgICAgICAgICBjZC5jYWxsKGYxbVByZWZpeCArIFwiX2FkZFwiLCBBLCBCLCBBX0IpLFxuICAgICAgICAgICAgY2QuY2FsbChmMW1QcmVmaXggKyBcIl9hZGRcIiwgYSwgYywgYV9jKSxcbiAgICAgICAgICAgIGNkLmNhbGwoZjFtUHJlZml4ICsgXCJfYWRkXCIsIEEsIEMsIEFfQyksXG4gICAgICAgICAgICBjZC5jYWxsKGYxbVByZWZpeCArIFwiX2FkZFwiLCBiLCBjLCBiX2MpLFxuICAgICAgICAgICAgY2QuY2FsbChmMW1QcmVmaXggKyBcIl9hZGRcIiwgQiwgQywgQl9DKSxcblxuICAgICAgICAgICAgY2QuY2FsbChmMW1QcmVmaXggKyBcIl9hZGRcIiwgYUEsIGJCLCBhQV9iQiksXG4gICAgICAgICAgICBjZC5jYWxsKGYxbVByZWZpeCArIFwiX2FkZFwiLCBhQSwgY0MsIGFBX2NDKSxcbiAgICAgICAgICAgIGNkLmNhbGwoZjFtUHJlZml4ICsgXCJfYWRkXCIsIGJCLCBjQywgYkJfY0MpLFxuXG4gICAgICAgICAgICBjZC5jYWxsKGYxbVByZWZpeCArIFwiX211bFwiLCBiX2MsIEJfQywgcjApLFxuICAgICAgICAgICAgY2QuY2FsbChmMW1QcmVmaXggKyBcIl9zdWJcIiwgcjAsIGJCX2NDLCByMCksXG4gICAgICAgICAgICBjZC5jYWxsKG11bE5vblJlc2lkdWVGbiwgcjAsIHIwKSxcbiAgICAgICAgICAgIGNkLmNhbGwoZjFtUHJlZml4ICsgXCJfYWRkXCIsIGFBLCByMCwgcjApLFxuXG4gICAgICAgICAgICBjZC5jYWxsKGYxbVByZWZpeCArIFwiX211bFwiLCBhX2IsIEFfQiwgcjEpLFxuICAgICAgICAgICAgY2QuY2FsbChmMW1QcmVmaXggKyBcIl9zdWJcIiwgcjEsIGFBX2JCLCByMSksXG4gICAgICAgICAgICBjZC5jYWxsKG11bE5vblJlc2lkdWVGbiwgY0MsIEFVWCksXG4gICAgICAgICAgICBjZC5jYWxsKGYxbVByZWZpeCArIFwiX2FkZFwiLCByMSwgQVVYLCByMSksXG5cbiAgICAgICAgICAgIGNkLmNhbGwoZjFtUHJlZml4ICsgXCJfbXVsXCIsIGFfYywgQV9DLCByMiksXG4gICAgICAgICAgICBjZC5jYWxsKGYxbVByZWZpeCArIFwiX3N1YlwiLCByMiwgYUFfY0MsIHIyKSxcbiAgICAgICAgICAgIGNkLmNhbGwoZjFtUHJlZml4ICsgXCJfYWRkXCIsIHIyLCBiQiwgcjIpLFxuICAgICAgICApO1xuXG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRTcXVhcmUoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX3NxdWFyZVwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgQSA9IGMuZ2V0TG9jYWwoXCJ4XCIpO1xuICAgICAgICBjb25zdCBCID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdChmMW44KSk7XG4gICAgICAgIGNvbnN0IEMgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KDIqZjFuOCkpO1xuICAgICAgICBjb25zdCByMCA9IGMuZ2V0TG9jYWwoXCJyXCIpO1xuICAgICAgICBjb25zdCByMSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwiclwiKSwgYy5pMzJfY29uc3QoZjFuOCkpO1xuICAgICAgICBjb25zdCByMiA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwiclwiKSwgYy5pMzJfY29uc3QoMipmMW44KSk7XG5cbiAgICAgICAgY29uc3QgczAgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjFuOCkpO1xuICAgICAgICBjb25zdCBhYiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMW44KSk7XG4gICAgICAgIGNvbnN0IHMxID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxbjgpKTtcbiAgICAgICAgY29uc3QgczIgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjFuOCkpO1xuICAgICAgICBjb25zdCBiYyA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMW44KSk7XG4gICAgICAgIGNvbnN0IHMzID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxbjgpKTtcbiAgICAgICAgY29uc3QgczQgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjFuOCkpO1xuXG5cbiAgICAgICAgZi5hZGRDb2RlKFxuXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4ICsgXCJfc3F1YXJlXCIsIEEsIHMwKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXggKyBcIl9tdWxcIiwgQSwgQiwgYWIpLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCArIFwiX2FkZFwiLCBhYiwgYWIsIHMxKSxcblxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCArIFwiX3N1YlwiLCBBLCBCLCBzMiksXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4ICsgXCJfYWRkXCIsIHMyLCBDLCBzMiksXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4ICsgXCJfc3F1YXJlXCIsIHMyLCBzMiksXG5cbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXggKyBcIl9tdWxcIiwgQiwgQywgYmMpLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCArIFwiX2FkZFwiLCBiYywgYmMsIHMzKSxcblxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCArIFwiX3NxdWFyZVwiLCBDLCBzNCksXG5cbiAgICAgICAgICAgIGMuY2FsbChtdWxOb25SZXNpZHVlRm4sIHMzLCByMCksXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4ICsgXCJfYWRkXCIsIHMwLCByMCwgcjApLFxuXG4gICAgICAgICAgICBjLmNhbGwobXVsTm9uUmVzaWR1ZUZuLCBzNCwgcjEpLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCArIFwiX2FkZFwiLCBzMSwgcjEsIHIxKSxcblxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCArIFwiX2FkZFwiLCBzMCwgczQsIHIyKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXggKyBcIl9zdWJcIiwgczMsIHIyLCByMiksXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4ICsgXCJfYWRkXCIsIHMyLCByMiwgcjIpLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCArIFwiX2FkZFwiLCBzMSwgcjIsIHIyKSxcbiAgICAgICAgKTtcblxuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gYnVpbGRUb01vbnRnb21lcnkoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX3RvTW9udGdvbWVyeVwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgeDAgPSBjLmdldExvY2FsKFwieFwiKTtcbiAgICAgICAgY29uc3QgeDEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcbiAgICAgICAgY29uc3QgeDIgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KDIqZjFuOCkpO1xuICAgICAgICBjb25zdCByMCA9IGMuZ2V0TG9jYWwoXCJyXCIpO1xuICAgICAgICBjb25zdCByMSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwiclwiKSwgYy5pMzJfY29uc3QoZjFuOCkpO1xuICAgICAgICBjb25zdCByMiA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwiclwiKSwgYy5pMzJfY29uc3QoMipmMW44KSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl90b01vbnRnb21lcnlcIiwgeDAsIHIwKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfdG9Nb250Z29tZXJ5XCIsIHgxLCByMSksXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX3RvTW9udGdvbWVyeVwiLCB4MiwgcjIpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRGcm9tTW9udGdvbWVyeSgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfZnJvbU1vbnRnb21lcnlcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ4XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiclwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IHgwID0gYy5nZXRMb2NhbChcInhcIik7XG4gICAgICAgIGNvbnN0IHgxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdChmMW44KSk7XG4gICAgICAgIGNvbnN0IHgyID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdCgyKmYxbjgpKTtcbiAgICAgICAgY29uc3QgcjAgPSBjLmdldExvY2FsKFwiclwiKTtcbiAgICAgICAgY29uc3QgcjEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInJcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcbiAgICAgICAgY29uc3QgcjIgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInJcIiksIGMuaTMyX2NvbnN0KDIqZjFuOCkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfZnJvbU1vbnRnb21lcnlcIiwgeDAsIHIwKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfZnJvbU1vbnRnb21lcnlcIiwgeDEsIHIxKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfZnJvbU1vbnRnb21lcnlcIiwgeDIsIHIyKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkQ29weSgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfY29weVwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgeDAgPSBjLmdldExvY2FsKFwieFwiKTtcbiAgICAgICAgY29uc3QgeDEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcbiAgICAgICAgY29uc3QgeDIgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KDIqZjFuOCkpO1xuICAgICAgICBjb25zdCByMCA9IGMuZ2V0TG9jYWwoXCJyXCIpO1xuICAgICAgICBjb25zdCByMSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwiclwiKSwgYy5pMzJfY29uc3QoZjFuOCkpO1xuICAgICAgICBjb25zdCByMiA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwiclwiKSwgYy5pMzJfY29uc3QoMipmMW44KSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9jb3B5XCIsIHgwLCByMCksXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX2NvcHlcIiwgeDEsIHIxKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfY29weVwiLCB4MiwgcjIpLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkWmVybygpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfemVyb1wiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInhcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCB4MCA9IGMuZ2V0TG9jYWwoXCJ4XCIpO1xuICAgICAgICBjb25zdCB4MSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QoZjFuOCkpO1xuICAgICAgICBjb25zdCB4MiA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QoMipmMW44KSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl96ZXJvXCIsIHgwKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfemVyb1wiLCB4MSksXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX3plcm9cIiwgeDIpLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkT25lKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9vbmVcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ4XCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgeDAgPSBjLmdldExvY2FsKFwieFwiKTtcbiAgICAgICAgY29uc3QgeDEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcbiAgICAgICAgY29uc3QgeDIgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KDIqZjFuOCkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfb25lXCIsIHgwKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfemVyb1wiLCB4MSksXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX3plcm9cIiwgeDIpLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkRXEoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX2VxXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInlcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuc2V0UmV0dXJuVHlwZShcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IHgwID0gYy5nZXRMb2NhbChcInhcIik7XG4gICAgICAgIGNvbnN0IHgxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdChmMW44KSk7XG4gICAgICAgIGNvbnN0IHgyID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdCgyKmYxbjgpKTtcbiAgICAgICAgY29uc3QgeTAgPSBjLmdldExvY2FsKFwieVwiKTtcbiAgICAgICAgY29uc3QgeTEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInlcIiksIGMuaTMyX2NvbnN0KGYxbjgpKTtcbiAgICAgICAgY29uc3QgeTIgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInlcIiksIGMuaTMyX2NvbnN0KDIqZjFuOCkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuaTMyX2FuZChcbiAgICAgICAgICAgICAgICBjLmkzMl9hbmQoXG4gICAgICAgICAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfZXFcIiwgeDAsIHkwKSxcbiAgICAgICAgICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9lcVwiLCB4MSwgeTEpLFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9lcVwiLCB4MiwgeTIpXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRJc1plcm8oKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX2lzWmVyb1wiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuc2V0UmV0dXJuVHlwZShcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IHgwID0gYy5nZXRMb2NhbChcInhcIik7XG4gICAgICAgIGNvbnN0IHgxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdChmMW44KSk7XG4gICAgICAgIGNvbnN0IHgyID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdCgyKmYxbjgpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmkzMl9hbmQoXG4gICAgICAgICAgICAgICAgYy5pMzJfYW5kKFxuICAgICAgICAgICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX2lzWmVyb1wiLCB4MCksXG4gICAgICAgICAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfaXNaZXJvXCIsIHgxKVxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9pc1plcm9cIiwgeDIpXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRJbnZlcnNlKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9pbnZlcnNlXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCB4MCA9IGMuZ2V0TG9jYWwoXCJ4XCIpO1xuICAgICAgICBjb25zdCB4MSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QoZjFuOCkpO1xuICAgICAgICBjb25zdCB4MiA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QoMipmMW44KSk7XG4gICAgICAgIGNvbnN0IHIwID0gYy5nZXRMb2NhbChcInJcIik7XG4gICAgICAgIGNvbnN0IHIxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJyXCIpLCBjLmkzMl9jb25zdChmMW44KSk7XG4gICAgICAgIGNvbnN0IHIyID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJyXCIpLCBjLmkzMl9jb25zdCgyKmYxbjgpKTtcblxuICAgICAgICBjb25zdCB0MCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMW44KSk7XG4gICAgICAgIGNvbnN0IHQxID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxbjgpKTtcbiAgICAgICAgY29uc3QgdDIgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjFuOCkpO1xuICAgICAgICBjb25zdCB0MyA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMW44KSk7XG4gICAgICAgIGNvbnN0IHQ0ID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxbjgpKTtcbiAgICAgICAgY29uc3QgdDUgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjFuOCkpO1xuICAgICAgICBjb25zdCBjMCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMW44KSk7XG4gICAgICAgIGNvbnN0IGMxID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxbjgpKTtcbiAgICAgICAgY29uc3QgYzIgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjFuOCkpO1xuICAgICAgICBjb25zdCB0NiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMW44KSk7XG4gICAgICAgIGNvbnN0IEFVWCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMW44KSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9zcXVhcmVcIiwgeDAsIHQwKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfc3F1YXJlXCIsIHgxLCB0MSksXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX3NxdWFyZVwiLCB4MiwgdDIpLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9tdWxcIiwgeDAsIHgxLCB0MyksXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX211bFwiLCB4MCwgeDIsIHQ0KSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfbXVsXCIsIHgxLCB4MiwgdDUpLFxuXG4gICAgICAgICAgICBjLmNhbGwobXVsTm9uUmVzaWR1ZUZuLCB0NSwgYzApLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9zdWJcIiwgdDAsIGMwLCBjMCksXG5cbiAgICAgICAgICAgIGMuY2FsbChtdWxOb25SZXNpZHVlRm4sIHQyLCBjMSksXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX3N1YlwiLCBjMSwgdDMsIGMxKSxcblxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9zdWJcIiwgdDEsIHQ0LCBjMiksXG5cbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfbXVsXCIsIHgyLCBjMSwgdDYpLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9tdWxcIiwgeDEsIGMyLCBBVVgpLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9hZGRcIiwgdDYsIEFVWCwgdDYpLFxuICAgICAgICAgICAgYy5jYWxsKG11bE5vblJlc2lkdWVGbiwgdDYsIHQ2KSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfbXVsXCIsIHgwLCBjMCwgQVVYKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfYWRkXCIsIEFVWCwgdDYsIHQ2KSxcblxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9pbnZlcnNlXCIsIHQ2LCB0NiksXG5cbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXgrXCJfbXVsXCIsIHQ2LCBjMCwgcjApLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9tdWxcIiwgdDYsIGMxLCByMSksXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX211bFwiLCB0NiwgYzIsIHIyKVxuICAgICAgICApO1xuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gYnVpbGRTaWduKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9zaWduXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcInNcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuc2V0UmV0dXJuVHlwZShcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IHgwID0gYy5nZXRMb2NhbChcInhcIik7XG4gICAgICAgIGNvbnN0IHgxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdChmMW44KSk7XG4gICAgICAgIGNvbnN0IHgyID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdCgyKmYxbjgpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLnNldExvY2FsKFwic1wiICwgYy5jYWxsKCBmMW1QcmVmaXggKyBcIl9zaWduXCIsIHgyKSksXG4gICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJzXCIpLFxuICAgICAgICAgICAgICAgIGMucmV0KGMuZ2V0TG9jYWwoXCJzXCIpKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJzXCIgLCBjLmNhbGwoIGYxbVByZWZpeCArIFwiX3NpZ25cIiwgeDEpKSxcbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInNcIiksXG4gICAgICAgICAgICAgICAgYy5yZXQoYy5nZXRMb2NhbChcInNcIikpXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5yZXQoYy5jYWxsKCBmMW1QcmVmaXggKyBcIl9zaWduXCIsIHgwKSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZElzT25lKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9pc09uZVwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuc2V0UmV0dXJuVHlwZShcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IHgwID0gYy5nZXRMb2NhbChcInhcIik7XG4gICAgICAgIGNvbnN0IHgxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdChmMW44KSk7XG4gICAgICAgIGNvbnN0IHgyID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdChmMW44KjIpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLnJldChcbiAgICAgICAgICAgICAgICBjLmkzMl9hbmQoXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2FuZChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXggKyBcIl9pc09uZVwiLCB4MCksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4ICsgXCJfaXNaZXJvXCIsIHgxKVxuICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4ICsgXCJfaXNaZXJvXCIsIHgyKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBidWlsZElzWmVybygpO1xuICAgIGJ1aWxkSXNPbmUoKTtcbiAgICBidWlsZFplcm8oKTtcbiAgICBidWlsZE9uZSgpO1xuICAgIGJ1aWxkQ29weSgpO1xuICAgIGJ1aWxkTXVsKCk7XG4gICAgYnVpbGRTcXVhcmUoKTtcbiAgICBidWlsZEFkZCgpO1xuICAgIGJ1aWxkU3ViKCk7XG4gICAgYnVpbGROZWcoKTtcbiAgICBidWlsZFNpZ24oKTtcbiAgICBidWlsZFRvTW9udGdvbWVyeSgpO1xuICAgIGJ1aWxkRnJvbU1vbnRnb21lcnkoKTtcbiAgICBidWlsZEVxKCk7XG4gICAgYnVpbGRJbnZlcnNlKCk7XG4gICAgYnVpbGRUaW1lc1NjYWxhcigpO1xuICAgIGJ1aWxkSXNOZWdhdGl2ZSgpO1xuXG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2lzWmVyb1wiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfaXNPbmVcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX3plcm9cIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX29uZVwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfY29weVwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfbXVsXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9zcXVhcmVcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2FkZFwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfc3ViXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9uZWdcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX3NpZ25cIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2Zyb21Nb250Z29tZXJ5XCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl90b01vbnRnb21lcnlcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2VxXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9pbnZlcnNlXCIpO1xuICAgIGJ1aWxkQmF0Y2hJbnZlcnNlKG1vZHVsZSwgcHJlZml4KTtcbiAgICBidWlsZEV4cChcbiAgICAgICAgbW9kdWxlLFxuICAgICAgICBwcmVmaXggKyBcIl9leHBcIixcbiAgICAgICAgZjFuOCozLFxuICAgICAgICBwcmVmaXggKyBcIl9tdWxcIixcbiAgICAgICAgcHJlZml4ICsgXCJfc3F1YXJlXCIsXG4gICAgICAgIHByZWZpeCArIFwiX2NvcHlcIixcbiAgICAgICAgcHJlZml4ICsgXCJfb25lXCJcbiAgICApO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9leHBcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX3RpbWVzU2NhbGFyXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9iYXRjaEludmVyc2VcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2lzTmVnYXRpdmVcIik7XG5cbiAgICByZXR1cm4gcHJlZml4O1xufTtcblxuLypcbiAgICBDb3B5cmlnaHQgMjAxOSAwS0lNUyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHdhc21zbmFyayAoV2ViIEFzc2VtYmx5IHprU25hcmsgUHJvdmVyKS5cblxuICAgIHdhc21zbmFyayBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHdhc21zbmFyayBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVFxuICAgIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpY1xuICAgIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gICAgYWxvbmcgd2l0aCB3YXNtc25hcmsuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG52YXIgYnVpbGRfdGltZXNzY2FsYXJuYWYgPSBmdW5jdGlvbiBidWlsZFRpbWVzU2NhbGFyTkFGKG1vZHVsZSwgZm5OYW1lLCBlbGVtZW50TGVuLCBvcEFCLCBvcEFBLCBvcEFtQiwgb3BDb3B5LCBvcEluaXQpIHtcblxuICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24oZm5OYW1lKTtcbiAgICBmLmFkZFBhcmFtKFwiYmFzZVwiLCBcImkzMlwiKTtcbiAgICBmLmFkZFBhcmFtKFwic2NhbGFyXCIsIFwiaTMyXCIpO1xuICAgIGYuYWRkUGFyYW0oXCJzY2FsYXJMZW5ndGhcIiwgXCJpMzJcIik7XG4gICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG4gICAgZi5hZGRMb2NhbChcIm9sZDBcIiwgXCJpMzJcIik7XG4gICAgZi5hZGRMb2NhbChcIm5iaXRzXCIsIFwiaTMyXCIpO1xuICAgIGYuYWRkTG9jYWwoXCJpXCIsIFwiaTMyXCIpO1xuICAgIGYuYWRkTG9jYWwoXCJsYXN0XCIsIFwiaTMyXCIpO1xuICAgIGYuYWRkTG9jYWwoXCJjdXJcIiwgXCJpMzJcIik7XG4gICAgZi5hZGRMb2NhbChcImNhcnJ5XCIsIFwiaTMyXCIpO1xuICAgIGYuYWRkTG9jYWwoXCJwXCIsIFwiaTMyXCIpO1xuXG4gICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgIGNvbnN0IGF1eCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhlbGVtZW50TGVuKSk7XG5cbiAgICBmdW5jdGlvbiBnZXRCaXQoSURYKSB7XG4gICAgICAgIHJldHVybiBjLmkzMl9hbmQoXG4gICAgICAgICAgICBjLmkzMl9zaHJfdShcbiAgICAgICAgICAgICAgICBjLmkzMl9sb2FkKFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9hZGQoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwic2NhbGFyXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfYW5kKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX3Nocl91KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJRFgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDMpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdCgweEZGRkZGRkZDKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLmkzMl9hbmQoXG4gICAgICAgICAgICAgICAgICAgIElEWCxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMHgxRilcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5pMzJfY29uc3QoMSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwdXNoQml0KGIpIHtcbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIC4uLmMuaTMyX3N0b3JlOChcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicFwiKSxcbiAgICAgICAgICAgICAgICBjLmkzMl9jb25zdChiKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIC4uLmMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgXCJwXCIsXG4gICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicFwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMSlcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApXG4gICAgICAgIF07XG4gICAgfVxuXG4gICAgZi5hZGRDb2RlKFxuICAgICAgICBjLmlmKFxuICAgICAgICAgICAgYy5pMzJfZXF6KGMuZ2V0TG9jYWwoXCJzY2FsYXJMZW5ndGhcIikpLFxuICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgIC4uLmMuY2FsbChvcEluaXQsIGMuZ2V0TG9jYWwoXCJyXCIpKSxcbiAgICAgICAgICAgICAgICAuLi5jLnJldChbXSlcbiAgICAgICAgICAgIF1cbiAgICAgICAgKSxcbiAgICAgICAgYy5zZXRMb2NhbChcIm5iaXRzXCIsIGMuaTMyX3NobChjLmdldExvY2FsKFwic2NhbGFyTGVuZ3RoXCIpLCBjLmkzMl9jb25zdCgzKSkpLFxuICAgICAgICBjLnNldExvY2FsKFwib2xkMFwiLCBjLmkzMl9sb2FkKGMuaTMyX2NvbnN0KDApKSksXG4gICAgICAgIGMuc2V0TG9jYWwoXCJwXCIsIGMuZ2V0TG9jYWwoXCJvbGQwXCIpKSxcbiAgICAgICAgYy5pMzJfc3RvcmUoXG4gICAgICAgICAgICBjLmkzMl9jb25zdCgwKSxcbiAgICAgICAgICAgIGMuaTMyX2FuZChcbiAgICAgICAgICAgICAgICBjLmkzMl9hZGQoXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJvbGQwXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMzIpXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJuYml0c1wiKVxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMHhGRkZGRkZGOClcbiAgICAgICAgICAgIClcbiAgICAgICAgKSxcbiAgICAgICAgYy5zZXRMb2NhbChcImlcIiwgYy5pMzJfY29uc3QoMSkpLFxuXG4gICAgICAgIGMuc2V0TG9jYWwoXCJsYXN0XCIsZ2V0Qml0KGMuaTMyX2NvbnN0KDApKSksXG4gICAgICAgIGMuc2V0TG9jYWwoXCJjYXJyeVwiLGMuaTMyX2NvbnN0KDApKSxcblxuICAgICAgICBjLmJsb2NrKGMubG9vcChcbiAgICAgICAgICAgIGMuYnJfaWYoMSwgYy5pMzJfZXEoIGMuZ2V0TG9jYWwoXCJpXCIpLCBjLmdldExvY2FsKFwibmJpdHNcIikpKSxcblxuICAgICAgICAgICAgYy5zZXRMb2NhbChcImN1clwiLCBnZXRCaXQoYy5nZXRMb2NhbChcImlcIikpKSxcbiAgICAgICAgICAgIGMuaWYoIGMuZ2V0TG9jYWwoXCJsYXN0XCIpLFxuICAgICAgICAgICAgICAgIGMuaWYoIGMuZ2V0TG9jYWwoXCJjdXJcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuaWYoYy5nZXRMb2NhbChcImNhcnJ5XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuc2V0TG9jYWwoXCJsYXN0XCIsIGMuaTMyX2NvbnN0KDApKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5jLnNldExvY2FsKFwiY2FycnlcIiwgYy5pMzJfY29uc3QoMSkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLnB1c2hCaXQoMSlcbiAgICAgICAgICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICAgICAgICAgICAgICxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5jLnNldExvY2FsKFwibGFzdFwiLCBjLmkzMl9jb25zdCgwKSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uYy5zZXRMb2NhbChcImNhcnJ5XCIsIGMuaTMyX2NvbnN0KDEpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5wdXNoQml0KDI1NSlcbiAgICAgICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgIGMuaWYoYy5nZXRMb2NhbChcImNhcnJ5XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuc2V0TG9jYWwoXCJsYXN0XCIsIGMuaTMyX2NvbnN0KDApKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5jLnNldExvY2FsKFwiY2FycnlcIiwgYy5pMzJfY29uc3QoMSkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLnB1c2hCaXQoMjU1KVxuICAgICAgICAgICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgICAgICAgICAgICAgLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuc2V0TG9jYWwoXCJsYXN0XCIsIGMuaTMyX2NvbnN0KDApKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5jLnNldExvY2FsKFwiY2FycnlcIiwgYy5pMzJfY29uc3QoMCkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLnB1c2hCaXQoMSlcbiAgICAgICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLmlmKCBjLmdldExvY2FsKFwiY3VyXCIpLFxuICAgICAgICAgICAgICAgICAgICBjLmlmKGMuZ2V0TG9jYWwoXCJjYXJyeVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5jLnNldExvY2FsKFwibGFzdFwiLCBjLmkzMl9jb25zdCgwKSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uYy5zZXRMb2NhbChcImNhcnJ5XCIsIGMuaTMyX2NvbnN0KDEpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5wdXNoQml0KDApXG4gICAgICAgICAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICAgICAgICAgICAgICAsXG4gICAgICAgICAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uYy5zZXRMb2NhbChcImxhc3RcIiwgYy5pMzJfY29uc3QoMSkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuc2V0TG9jYWwoXCJjYXJyeVwiLCBjLmkzMl9jb25zdCgwKSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4ucHVzaEJpdCgwKVxuICAgICAgICAgICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pZihjLmdldExvY2FsKFwiY2FycnlcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uYy5zZXRMb2NhbChcImxhc3RcIiwgYy5pMzJfY29uc3QoMSkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuc2V0TG9jYWwoXCJjYXJyeVwiLCBjLmkzMl9jb25zdCgwKSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4ucHVzaEJpdCgwKVxuICAgICAgICAgICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgICAgICAgICAgICAgLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuc2V0TG9jYWwoXCJsYXN0XCIsIGMuaTMyX2NvbnN0KDApKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5jLnNldExvY2FsKFwiY2FycnlcIiwgYy5pMzJfY29uc3QoMCkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLnB1c2hCaXQoMClcbiAgICAgICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwiaVwiKSwgYy5pMzJfY29uc3QoMSkpKSxcbiAgICAgICAgICAgIGMuYnIoMClcbiAgICAgICAgKSksXG5cbiAgICAgICAgYy5pZiggYy5nZXRMb2NhbChcImxhc3RcIiksXG4gICAgICAgICAgICBjLmlmKGMuZ2V0TG9jYWwoXCJjYXJyeVwiKSxcbiAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIC4uLnB1c2hCaXQoMjU1KSxcbiAgICAgICAgICAgICAgICAgICAgLi4ucHVzaEJpdCgwKSxcbiAgICAgICAgICAgICAgICAgICAgLi4ucHVzaEJpdCgxKVxuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICAgICAsXG4gICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAuLi5wdXNoQml0KDEpXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLmlmKGMuZ2V0TG9jYWwoXCJjYXJyeVwiKSxcbiAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIC4uLnB1c2hCaXQoMCksXG4gICAgICAgICAgICAgICAgICAgIC4uLnB1c2hCaXQoMSlcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICApLFxuICAgICAgICApLFxuXG4gICAgICAgIGMuc2V0TG9jYWwoXCJwXCIsIGMuaTMyX3N1YihjLmdldExvY2FsKFwicFwiKSwgYy5pMzJfY29uc3QoMSkpKSxcblxuICAgICAgICAvLyBwIGFscmVhZHkgcG9pbnRzIHRvIHRoZSBsYXN0IGJpdFxuXG4gICAgICAgIGMuY2FsbChvcENvcHksIGMuZ2V0TG9jYWwoXCJiYXNlXCIpLCBhdXgpLFxuXG4gICAgICAgIGMuY2FsbChvcEluaXQsIGMuZ2V0TG9jYWwoXCJyXCIpKSxcblxuICAgICAgICBjLmJsb2NrKGMubG9vcChcblxuXG4gICAgICAgICAgICBjLmNhbGwob3BBQSwgYy5nZXRMb2NhbChcInJcIiksIGMuZ2V0TG9jYWwoXCJyXCIpKSxcblxuXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiY3VyXCIsXG4gICAgICAgICAgICAgICAgYy5pMzJfbG9hZDhfdShcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBcIilcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApLFxuXG4gICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJjdXJcIiksXG4gICAgICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfZXEoYy5nZXRMb2NhbChcImN1clwiKSwgYy5pMzJfY29uc3QoMSkpLFxuICAgICAgICAgICAgICAgICAgICBjLmNhbGwob3BBQiwgIGMuZ2V0TG9jYWwoXCJyXCIpLCBhdXgsIGMuZ2V0TG9jYWwoXCJyXCIpKSxcbiAgICAgICAgICAgICAgICAgICAgYy5jYWxsKG9wQW1CLCBjLmdldExvY2FsKFwiclwiKSwgYXV4LCBjLmdldExvY2FsKFwiclwiKSksXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgYy5icl9pZigxLCBjLmkzMl9lcSggYy5nZXRMb2NhbChcIm9sZDBcIiksIGMuZ2V0TG9jYWwoXCJwXCIpKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwicFwiLCBjLmkzMl9zdWIoYy5nZXRMb2NhbChcInBcIiksIGMuaTMyX2NvbnN0KDEpKSksXG4gICAgICAgICAgICBjLmJyKDApXG5cbiAgICAgICAgKSksXG5cbiAgICAgICAgYy5pMzJfc3RvcmUoIGMuaTMyX2NvbnN0KDApLCBjLmdldExvY2FsKFwib2xkMFwiKSlcblxuICAgICk7XG5cbn07XG5cbi8qXG4gICAgQ29weXJpZ2h0IDIwMTkgMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiB3YXNtc25hcmsgKFdlYiBBc3NlbWJseSB6a1NuYXJrIFByb3ZlcikuXG5cbiAgICB3YXNtc25hcmsgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gICAgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAgICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICAgIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICB3YXNtc25hcmsgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggd2FzbXNuYXJrLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxudmFyIGJ1aWxkX211bHRpZXhwID0gZnVuY3Rpb24gYnVpbGRNdWx0aWV4cChtb2R1bGUsIHByZWZpeCwgZm5OYW1lLCBvcEFkZCwgbjhiKSB7XG5cbiAgICBjb25zdCBuNjRnID0gbW9kdWxlLm1vZHVsZXNbcHJlZml4XS5uNjQ7XG4gICAgY29uc3QgbjhnID0gbjY0Zyo4O1xuXG4gICAgZnVuY3Rpb24gYnVpbGRHZXRDaHVuaygpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihmbk5hbWUgKyBcIl9nZXRDaHVua1wiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInBTY2FsYXJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJzY2FsYXJTaXplXCIsIFwiaTMyXCIpOyAgLy8gTnVtYmVyIG9mIGJ5dGVzIG9mIHRoZSBzY2FsYXJcbiAgICAgICAgZi5hZGRQYXJhbShcInN0YXJ0Qml0XCIsIFwiaTMyXCIpOyAgLy8gQml0IHRvIHN0YXJ0IGV4dHJhY3RcbiAgICAgICAgZi5hZGRQYXJhbShcImNodW5rU2l6ZVwiLCBcImkzMlwiKTsgIC8vIENodW5rIHNpemUgaW4gYml0c1xuICAgICAgICBmLmFkZExvY2FsKFwiYml0c1RvRW5kXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwibWFza1wiLCBcImkzMlwiKTtcbiAgICAgICAgZi5zZXRSZXR1cm5UeXBlKFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcImJpdHNUb0VuZFwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX3N1YihcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfbXVsKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInNjYWxhclNpemVcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdCg4KVxuICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwic3RhcnRCaXRcIilcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmkzMl9ndF9zKFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiY2h1bmtTaXplXCIpLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiYml0c1RvRW5kXCIpXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgICAgICBcIm1hc2tcIixcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfc3ViKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfc2hsKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDEpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJiaXRzVG9FbmRcIilcbiAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdCgxKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgICAgICBcIm1hc2tcIixcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfc3ViKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfc2hsKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDEpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJjaHVua1NpemVcIilcbiAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdCgxKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuaTMyX2FuZChcbiAgICAgICAgICAgICAgICBjLmkzMl9zaHJfdShcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfbG9hZChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicFNjYWxhclwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9zaHJfdShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInN0YXJ0Qml0XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdCgzKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAwLCAgLy8gb2Zmc2V0XG4gICAgICAgICAgICAgICAgICAgICAgICAwICAgLy8gYWxpZ24gdG8gYnl0ZS5cbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfYW5kKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInN0YXJ0Qml0XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMHg3KVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwibWFza1wiKVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkTXV0aWV4cENodW5rKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKGZuTmFtZSArIFwiX2NodW5rXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicEJhc2VzXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicFNjYWxhcnNcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJzY2FsYXJTaXplXCIsIFwiaTMyXCIpOyAgLy8gTnVtYmVyIG9mIHBvaW50c1xuICAgICAgICBmLmFkZFBhcmFtKFwiblwiLCBcImkzMlwiKTsgIC8vIE51bWJlciBvZiBwb2ludHNcbiAgICAgICAgZi5hZGRQYXJhbShcInN0YXJ0Qml0XCIsIFwiaTMyXCIpOyAgLy8gYml0IHdoZXJlIGl0IHN0YXJ0cyB0aGUgY2h1bmtcbiAgICAgICAgZi5hZGRQYXJhbShcImNodW5rU2l6ZVwiLCBcImkzMlwiKTsgIC8vIGJpdCB3aGVyZSBpdCBzdGFydHMgdGhlIGNodW5rXG4gICAgICAgIGYuYWRkUGFyYW0oXCJwclwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcIm5DaHVua3NcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJpdFNjYWxhclwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImVuZFNjYWxhclwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcIml0QmFzZVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImlcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJqXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiblRhYmxlXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwicFRhYmxlXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiaWR4XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwicElkeFRhYmxlXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmkzMl9lcXooYy5nZXRMb2NhbChcIm5cIikpLFxuICAgICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5jYWxsKHByZWZpeCArIFwiX3plcm9cIiwgYy5nZXRMb2NhbChcInByXCIpKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5yZXQoW10pXG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgLy8gQWxsb2NhdGUgbWVtb3J5XG5cbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgXCJuVGFibGVcIixcbiAgICAgICAgICAgICAgICBjLmkzMl9zaGwoXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDEpLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiY2h1bmtTaXplXCIpXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJwVGFibGVcIiwgYy5pMzJfbG9hZCggYy5pMzJfY29uc3QoMCkgKSksXG4gICAgICAgICAgICBjLmkzMl9zdG9yZShcbiAgICAgICAgICAgICAgICBjLmkzMl9jb25zdCgwKSxcbiAgICAgICAgICAgICAgICBjLmkzMl9hZGQoXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwVGFibGVcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX211bChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJuVGFibGVcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdChuOGcpXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAvLyBSZXNldCBUYWJsZVxuICAgICAgICAgICAgYy5zZXRMb2NhbChcImpcIiwgYy5pMzJfY29uc3QoMCkpLFxuICAgICAgICAgICAgYy5ibG9jayhjLmxvb3AoXG4gICAgICAgICAgICAgICAgYy5icl9pZihcbiAgICAgICAgICAgICAgICAgICAgMSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfZXEoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwialwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJuVGFibGVcIilcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgICAgIHByZWZpeCArIFwiX3plcm9cIixcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBUYWJsZVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX211bChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwialwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdChuOGcpXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcImpcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJqXCIpLCBjLmkzMl9jb25zdCgxKSkpLFxuICAgICAgICAgICAgICAgIGMuYnIoMClcbiAgICAgICAgICAgICkpLFxuXG4gICAgICAgICAgICAvLyBEaXN0cmlidXRlIGVsZW1lbnRzXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiaXRCYXNlXCIsIGMuZ2V0TG9jYWwoXCJwQmFzZXNcIikpLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcIml0U2NhbGFyXCIsIGMuZ2V0TG9jYWwoXCJwU2NhbGFyc1wiKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiZW5kU2NhbGFyXCIsXG4gICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicFNjYWxhcnNcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX211bChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJuXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInNjYWxhclNpemVcIilcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLmJsb2NrKGMubG9vcChcbiAgICAgICAgICAgICAgICBjLmJyX2lmKFxuICAgICAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9lcShcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpdFNjYWxhclwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJlbmRTY2FsYXJcIilcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgICAgICBcImlkeFwiLFxuICAgICAgICAgICAgICAgICAgICBjLmNhbGwoZm5OYW1lICsgXCJfZ2V0Q2h1bmtcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpdFNjYWxhclwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJzY2FsYXJTaXplXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInN0YXJ0Qml0XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImNodW5rU2l6ZVwiKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpZHhcIiksXG4gICAgICAgICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJwSWR4VGFibGVcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9hZGQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwVGFibGVcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX211bChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX3N1YihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaWR4XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDEpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QobjhnKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcEFkZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicElkeFRhYmxlXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpdEJhc2VcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBJZHhUYWJsZVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaXRTY2FsYXJcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJpdFNjYWxhclwiKSwgYy5nZXRMb2NhbChcInNjYWxhclNpemVcIikpKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaXRCYXNlXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwiaXRCYXNlXCIpLCBjLmkzMl9jb25zdChuOGIpKSksXG4gICAgICAgICAgICAgICAgYy5icigwKVxuICAgICAgICAgICAgKSksXG5cbiAgICAgICAgICAgIGMuY2FsbChmbk5hbWUgKyBcIl9yZWR1Y2VUYWJsZVwiLCBjLmdldExvY2FsKFwicFRhYmxlXCIpLCBjLmdldExvY2FsKFwiY2h1bmtTaXplXCIpKSxcbiAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICBwcmVmaXggKyBcIl9jb3B5XCIsXG4gICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBUYWJsZVwiKSxcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicHJcIilcbiAgICAgICAgICAgICksXG5cblxuICAgICAgICAgICAgYy5pMzJfc3RvcmUoXG4gICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMCksXG4gICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBUYWJsZVwiKVxuICAgICAgICAgICAgKVxuXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRNdWx0aWV4cCgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihmbk5hbWUpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicEJhc2VzXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicFNjYWxhcnNcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJzY2FsYXJTaXplXCIsIFwiaTMyXCIpOyAgLy8gTnVtYmVyIG9mIHBvaW50c1xuICAgICAgICBmLmFkZFBhcmFtKFwiblwiLCBcImkzMlwiKTsgIC8vIE51bWJlciBvZiBwb2ludHNcbiAgICAgICAgZi5hZGRQYXJhbShcInByXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiY2h1bmtTaXplXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwibkNodW5rc1wiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcIml0U2NhbGFyXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiZW5kU2NhbGFyXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiaXRCYXNlXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiaXRCaXRcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJpXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwialwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcIm5UYWJsZVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcInBUYWJsZVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImlkeFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcInBJZHhUYWJsZVwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IGF1eCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOGcpKTtcblxuICAgICAgICBjb25zdCBwVFNpemVzID0gbW9kdWxlLmFsbG9jKFtcbiAgICAgICAgICAgIDE3LCAxNywgMTcsIDE3LCAgIDE3LCAxNywgMTcsIDE3LFxuICAgICAgICAgICAgMTcsIDE3LCAxNiwgMTYsICAgMTUsIDE0LCAxMywgMTMsXG4gICAgICAgICAgICAxMiwgMTEsIDEwLCAgOSwgICAgOCwgIDcsICA3LCAgNixcbiAgICAgICAgICAgIDUgLCAgNCwgIDMsICAyLCAgICAxLCAgMSwgIDEsICAxXG4gICAgICAgIF0pO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl96ZXJvXCIsIGMuZ2V0TG9jYWwoXCJwclwiKSksXG4gICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgIGMuaTMyX2VxeihjLmdldExvY2FsKFwiblwiKSksXG4gICAgICAgICAgICAgICAgYy5yZXQoW10pXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcImNodW5rU2l6ZVwiLCBjLmkzMl9sb2FkOF91KCBjLmkzMl9jbHooYy5nZXRMb2NhbChcIm5cIikpLCAgcFRTaXplcyApKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgXCJuQ2h1bmtzXCIsXG4gICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9kaXZfdShcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX3N1YihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9zaGwoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJzY2FsYXJTaXplXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdCgzKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMSlcbiAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiY2h1bmtTaXplXCIpXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDEpXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcblxuXG4gICAgICAgICAgICAvLyBBbGxvY2F0ZSBtZW1vcnlcblxuICAgICAgICAgICAgYy5zZXRMb2NhbChcbiAgICAgICAgICAgICAgICBcIml0Qml0XCIsXG4gICAgICAgICAgICAgICAgYy5pMzJfbXVsKFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9zdWIoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwibkNodW5rc1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDEpXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJjaHVua1NpemVcIilcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5ibG9jayhjLmxvb3AoXG4gICAgICAgICAgICAgICAgYy5icl9pZihcbiAgICAgICAgICAgICAgICAgICAgMSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfbHRfcyhcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpdEJpdFwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDApXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgLy8gRG91YmxlIG5DaHVuayB0aW1lc1xuICAgICAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2VxeihjLmNhbGwocHJlZml4ICsgXCJfaXNaZXJvXCIsIGMuZ2V0TG9jYWwoXCJwclwiKSkpLFxuICAgICAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgICAgICAuLi5jLnNldExvY2FsKFwialwiLCBjLmkzMl9jb25zdCgwKSksXG4gICAgICAgICAgICAgICAgICAgICAgICAuLi5jLmJsb2NrKGMubG9vcChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmJyX2lmKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9lcShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJqXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImNodW5rU2l6ZVwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9kb3VibGVcIiwgYy5nZXRMb2NhbChcInByXCIpLCBjLmdldExvY2FsKFwicHJcIikpLFxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcImpcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJqXCIpLCBjLmkzMl9jb25zdCgxKSkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuYnIoMClcbiAgICAgICAgICAgICAgICAgICAgICAgICkpXG4gICAgICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgICAgICBmbk5hbWUgKyBcIl9jaHVua1wiLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicEJhc2VzXCIpLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicFNjYWxhcnNcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJzY2FsYXJTaXplXCIpLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiblwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIml0Qml0XCIpLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiY2h1bmtTaXplXCIpLFxuICAgICAgICAgICAgICAgICAgICBhdXhcbiAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgICAgICBwcmVmaXggKyBcIl9hZGRcIixcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInByXCIpLFxuICAgICAgICAgICAgICAgICAgICBhdXgsXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwclwiKVxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcIml0Qml0XCIsIGMuaTMyX3N1YihjLmdldExvY2FsKFwiaXRCaXRcIiksIGMuZ2V0TG9jYWwoXCJjaHVua1NpemVcIikpKSxcbiAgICAgICAgICAgICAgICBjLmJyKDApXG4gICAgICAgICAgICApKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkUmVkdWNlVGFibGUoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24oZm5OYW1lICsgXCJfcmVkdWNlVGFibGVcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwVGFibGVcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwXCIsIFwiaTMyXCIpOyAgLy8gTnVtYmVyIG9mIGJpdHMgb2YgdGhlIHRhYmxlXG4gICAgICAgIGYuYWRkTG9jYWwoXCJoYWxmXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiaXQxXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiaXQyXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwicEFjY1wiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5pMzJfZXEoYy5nZXRMb2NhbChcInBcIiksIGMuaTMyX2NvbnN0KDEpKSxcbiAgICAgICAgICAgICAgICBjLnJldChbXSlcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgIFwiaGFsZlwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX3NobChcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMSksXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX3N1YihcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMSlcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpdDFcIiwgYy5nZXRMb2NhbChcInBUYWJsZVwiKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgIFwiaXQyXCIsXG4gICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicFRhYmxlXCIpLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9tdWwoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaGFsZlwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KG44ZylcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwicEFjY1wiLFxuICAgICAgICAgICAgICAgIGMuaTMyX3N1YihcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIml0MlwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QobjhnKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLmJsb2NrKGMubG9vcChcbiAgICAgICAgICAgICAgICBjLmJyX2lmKFxuICAgICAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9lcShcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpdDFcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicEFjY1wiKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgICAgIHByZWZpeCArIFwiX2FkZFwiLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaXQxXCIpLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaXQyXCIpLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaXQxXCIpXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgICAgIHByZWZpeCArIFwiX2FkZFwiLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicEFjY1wiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIml0MlwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBBY2NcIilcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpdDFcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJpdDFcIiksIGMuaTMyX2NvbnN0KG44ZykpKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaXQyXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwiaXQyXCIpLCBjLmkzMl9jb25zdChuOGcpKSksXG4gICAgICAgICAgICAgICAgYy5icigwKVxuICAgICAgICAgICAgKSksXG5cbiAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICBmbk5hbWUgKyBcIl9yZWR1Y2VUYWJsZVwiLFxuICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwVGFibGVcIiksXG4gICAgICAgICAgICAgICAgYy5pMzJfc3ViKFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicFwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMSlcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApLFxuXG4gICAgICAgICAgICBjLnNldExvY2FsKFwicFwiLCBjLmkzMl9zdWIoYy5nZXRMb2NhbChcInBcIiksIGMuaTMyX2NvbnN0KDEpKSksXG4gICAgICAgICAgICBjLmJsb2NrKGMubG9vcChcbiAgICAgICAgICAgICAgICBjLmJyX2lmKDEsIGMuaTMyX2VxeihjLmdldExvY2FsKFwicFwiKSkpLFxuICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9kb3VibGVcIiwgYy5nZXRMb2NhbChcInBBY2NcIiksIGMuZ2V0TG9jYWwoXCJwQWNjXCIpKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwicFwiLCBjLmkzMl9zdWIoYy5nZXRMb2NhbChcInBcIiksIGMuaTMyX2NvbnN0KDEpKSksXG4gICAgICAgICAgICAgICAgYy5icigwKVxuICAgICAgICAgICAgKSksXG5cbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9hZGRcIiwgYy5nZXRMb2NhbChcInBUYWJsZVwiKSwgYy5nZXRMb2NhbChcInBBY2NcIiksIGMuZ2V0TG9jYWwoXCJwVGFibGVcIikpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgYnVpbGRHZXRDaHVuaygpO1xuICAgIGJ1aWxkUmVkdWNlVGFibGUoKTtcbiAgICBidWlsZE11dGlleHBDaHVuaygpO1xuICAgIGJ1aWxkTXVsdGlleHAoKTtcblxuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihmbk5hbWUpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihmbk5hbWUgK1wiX2NodW5rXCIpO1xuXG5cbn07XG5cbi8qXG4gICAgQ29weXJpZ2h0IDIwMTkgMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiB3YXNtc25hcmsgKFdlYiBBc3NlbWJseSB6a1NuYXJrIFByb3ZlcikuXG5cbiAgICB3YXNtc25hcmsgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gICAgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAgICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICAgIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICB3YXNtc25hcmsgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggd2FzbXNuYXJrLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuY29uc3QgYnVpbGRUaW1lc1NjYWxhck5BRiA9IGJ1aWxkX3RpbWVzc2NhbGFybmFmO1xuLy9jb25zdCBidWlsZFRpbWVzU2NhbGFyID0gcmVxdWlyZShcIi4vYnVpbGRfdGltZXNzY2FsYXJcIik7XG5jb25zdCBidWlsZEJhdGNoQ29udmVydGlvbiA9IGJ1aWxkX2JhdGNoY29udmVydGlvbjtcbmNvbnN0IGJ1aWxkTXVsdGlleHAgPSBidWlsZF9tdWx0aWV4cDtcblxudmFyIGJ1aWxkX2N1cnZlX2phY29iaWFuX2EwID0gZnVuY3Rpb24gYnVpbGRDdXJ2ZShtb2R1bGUsIHByZWZpeCwgcHJlZml4RmllbGQsIHBCKSB7XG5cblxuICAgIGNvbnN0IG42NCA9IG1vZHVsZS5tb2R1bGVzW3ByZWZpeEZpZWxkXS5uNjQ7XG4gICAgY29uc3QgbjggPSBuNjQqODtcblxuICAgIGlmIChtb2R1bGUubW9kdWxlc1twcmVmaXhdKSByZXR1cm4gcHJlZml4OyAgLy8gYWxyZWFkeSBidWlsZGVkXG4gICAgbW9kdWxlLm1vZHVsZXNbcHJlZml4XSA9IHtcbiAgICAgICAgbjY0OiBuNjQqM1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBidWlsZElzWmVybygpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXggKyBcIl9pc1plcm9cIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwMVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5zZXRSZXR1cm5UeXBlKFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgZi5hZGRDb2RlKGMuY2FsbChcbiAgICAgICAgICAgIHByZWZpeEZpZWxkICsgXCJfaXNaZXJvXCIsXG4gICAgICAgICAgICBjLmkzMl9hZGQoXG4gICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInAxXCIpLFxuICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KG44KjIpXG4gICAgICAgICAgICApXG4gICAgICAgICkpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBidWlsZElzWmVyb0FmZmluZSgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXggKyBcIl9pc1plcm9BZmZpbmVcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwMVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5zZXRSZXR1cm5UeXBlKFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5pMzJfYW5kKFxuICAgICAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgcHJlZml4RmllbGQgKyBcIl9pc1plcm9cIixcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInAxXCIpXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgICAgIHByZWZpeEZpZWxkICsgXCJfaXNaZXJvXCIsXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwMVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KG44KVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkQ29weSgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXggKyBcIl9jb3B5XCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicHNcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwZFwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxuNjQqMzsgaSsrKSB7XG4gICAgICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICAgICAgYy5pNjRfc3RvcmUoXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwZFwiKSxcbiAgICAgICAgICAgICAgICAgICAgaSo4LFxuICAgICAgICAgICAgICAgICAgICBjLmk2NF9sb2FkKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBzXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgaSo4XG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICBmdW5jdGlvbiBidWlsZENvcHlBZmZpbmUoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4ICsgXCJfY29weUFmZmluZVwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInBzXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicGRcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBmb3IgKGxldCBpPTA7IGk8bjY0KjI7IGkrKykge1xuICAgICAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgICAgIGMuaTY0X3N0b3JlKFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicGRcIiksXG4gICAgICAgICAgICAgICAgICAgIGkqOCxcbiAgICAgICAgICAgICAgICAgICAgYy5pNjRfbG9hZChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwc1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGkqOFxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgfVxuXG5cbiAgICBmdW5jdGlvbiBidWlsZFplcm8oKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4ICsgXCJfemVyb1wiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInByXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgZi5hZGRDb2RlKGMuY2FsbChcbiAgICAgICAgICAgIHByZWZpeEZpZWxkICsgXCJfemVyb1wiLFxuICAgICAgICAgICAgYy5nZXRMb2NhbChcInByXCIpXG4gICAgICAgICkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShjLmNhbGwoXG4gICAgICAgICAgICBwcmVmaXhGaWVsZCArIFwiX29uZVwiLFxuICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwclwiKSxcbiAgICAgICAgICAgICAgICBjLmkzMl9jb25zdChuOClcbiAgICAgICAgICAgIClcbiAgICAgICAgKSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKGMuY2FsbChcbiAgICAgICAgICAgIHByZWZpeEZpZWxkICsgXCJfemVyb1wiLFxuICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwclwiKSxcbiAgICAgICAgICAgICAgICBjLmkzMl9jb25zdChuOCoyKVxuICAgICAgICAgICAgKVxuICAgICAgICApKTtcbiAgICB9XG5cblxuICAgIGZ1bmN0aW9uIGJ1aWxkWmVyb0FmZmluZSgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXggKyBcIl96ZXJvQWZmaW5lXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicHJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBmLmFkZENvZGUoYy5jYWxsKFxuICAgICAgICAgICAgcHJlZml4RmllbGQgKyBcIl96ZXJvXCIsXG4gICAgICAgICAgICBjLmdldExvY2FsKFwicHJcIilcbiAgICAgICAgKSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKGMuY2FsbChcbiAgICAgICAgICAgIHByZWZpeEZpZWxkICsgXCJfemVyb1wiLFxuICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwclwiKSxcbiAgICAgICAgICAgICAgICBjLmkzMl9jb25zdChuOClcbiAgICAgICAgICAgIClcbiAgICAgICAgKSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRFcSgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXggKyBcIl9lcVwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInAxXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicDJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuc2V0UmV0dXJuVHlwZShcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcInoxXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiejJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCB4MSA9IGMuZ2V0TG9jYWwoXCJwMVwiKTtcbiAgICAgICAgY29uc3QgeTEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInAxXCIpLCBjLmkzMl9jb25zdChuOCkpO1xuICAgICAgICBmLmFkZENvZGUoYy5zZXRMb2NhbChcInoxXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwicDFcIiksIGMuaTMyX2NvbnN0KG44KjIpKSkpO1xuICAgICAgICBjb25zdCB6MSA9IGMuZ2V0TG9jYWwoXCJ6MVwiKTtcbiAgICAgICAgY29uc3QgeDIgPSBjLmdldExvY2FsKFwicDJcIik7XG4gICAgICAgIGNvbnN0IHkyID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwMlwiKSwgYy5pMzJfY29uc3QobjgpKTtcbiAgICAgICAgZi5hZGRDb2RlKGMuc2V0TG9jYWwoXCJ6MlwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInAyXCIpLCBjLmkzMl9jb25zdChuOCoyKSkpKTtcbiAgICAgICAgY29uc3QgejIgPSBjLmdldExvY2FsKFwiejJcIik7XG5cbiAgICAgICAgY29uc3QgWjFaMSA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuICAgICAgICBjb25zdCBaMloyID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IFUxID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IFUyID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IFoxX2N1YmVkID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IFoyX2N1YmVkID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IFMxID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IFMyID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG5cblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9pc1plcm9cIiwgYy5nZXRMb2NhbChcInAxXCIpKSxcbiAgICAgICAgICAgICAgICBjLnJldCggYy5jYWxsKHByZWZpeCArIFwiX2lzWmVyb1wiLCBjLmdldExvY2FsKFwicDJcIikpKSxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9pc1plcm9cIiwgYy5nZXRMb2NhbChcInAyXCIpKSxcbiAgICAgICAgICAgICAgICBjLnJldChjLmkzMl9jb25zdCgwKSlcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2lzT25lXCIsIHoxKSxcbiAgICAgICAgICAgICAgICBjLnJldChjLmNhbGwocHJlZml4ICsgXCJfZXFNaXhlZFwiLCBjLmdldExvY2FsKFwicDJcIiksIGMuZ2V0TG9jYWwoXCJwMVwiKSkpXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9pc09uZVwiLCB6MiksXG4gICAgICAgICAgICAgICAgYy5yZXQoYy5jYWxsKHByZWZpeCArIFwiX2VxTWl4ZWRcIiwgYy5nZXRMb2NhbChcInAxXCIpLCBjLmdldExvY2FsKFwicDJcIikpKVxuICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfc3F1YXJlXCIsIHoxLCBaMVoxKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3NxdWFyZVwiLCB6MiwgWjJaMiksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9tdWxcIiwgeDEsIFoyWjIsIFUxKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX211bFwiLCB4MiwgWjFaMSwgVTIpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfbXVsXCIsIHoxLCBaMVoxLCBaMV9jdWJlZCksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9tdWxcIiwgejIsIFoyWjIsIFoyX2N1YmVkKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX211bFwiLCB5MSwgWjJfY3ViZWQsIFMxKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX211bFwiLCB5MiwgWjFfY3ViZWQsIFMyKSxcblxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9lcVwiLCBVMSwgVTIpLFxuICAgICAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2VxXCIsIFMxLCBTMiksXG4gICAgICAgICAgICAgICAgICAgIGMucmV0KGMuaTMyX2NvbnN0KDEpKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLnJldChjLmkzMl9jb25zdCgwKSlcbiAgICAgICAgKTtcbiAgICB9XG5cblxuICAgIGZ1bmN0aW9uIGJ1aWxkRXFNaXhlZCgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXggKyBcIl9lcU1peGVkXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicDFcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwMlwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5zZXRSZXR1cm5UeXBlKFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiejFcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCB4MSA9IGMuZ2V0TG9jYWwoXCJwMVwiKTtcbiAgICAgICAgY29uc3QgeTEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInAxXCIpLCBjLmkzMl9jb25zdChuOCkpO1xuICAgICAgICBmLmFkZENvZGUoYy5zZXRMb2NhbChcInoxXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwicDFcIiksIGMuaTMyX2NvbnN0KG44KjIpKSkpO1xuICAgICAgICBjb25zdCB6MSA9IGMuZ2V0TG9jYWwoXCJ6MVwiKTtcbiAgICAgICAgY29uc3QgeDIgPSBjLmdldExvY2FsKFwicDJcIik7XG4gICAgICAgIGNvbnN0IHkyID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwMlwiKSwgYy5pMzJfY29uc3QobjgpKTtcblxuICAgICAgICBjb25zdCBaMVoxID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IFUyID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IFoxX2N1YmVkID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IFMyID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfaXNaZXJvXCIsIGMuZ2V0TG9jYWwoXCJwMVwiKSksXG4gICAgICAgICAgICAgICAgYy5yZXQoIGMuY2FsbChwcmVmaXggKyBcIl9pc1plcm9BZmZpbmVcIiwgYy5nZXRMb2NhbChcInAyXCIpKSksXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfaXNaZXJvQWZmaW5lXCIsIGMuZ2V0TG9jYWwoXCJwMlwiKSksXG4gICAgICAgICAgICAgICAgYy5yZXQoYy5pMzJfY29uc3QoMCkpXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9pc09uZVwiLCB6MSksXG4gICAgICAgICAgICAgICAgYy5yZXQoYy5jYWxsKHByZWZpeCArIFwiX2VxQWZmaW5lXCIsIGMuZ2V0TG9jYWwoXCJwMVwiKSwgYy5nZXRMb2NhbChcInAyXCIpKSlcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9zcXVhcmVcIiwgejEsIFoxWjEpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfbXVsXCIsIHgyLCBaMVoxLCBVMiksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9tdWxcIiwgejEsIFoxWjEsIFoxX2N1YmVkKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX211bFwiLCB5MiwgWjFfY3ViZWQsIFMyKSxcblxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9lcVwiLCB4MSwgVTIpLFxuICAgICAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2VxXCIsIHkxLCBTMiksXG4gICAgICAgICAgICAgICAgICAgIGMucmV0KGMuaTMyX2NvbnN0KDEpKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLnJldChjLmkzMl9jb25zdCgwKSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZERvdWJsZSgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXggKyBcIl9kb3VibGVcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwMVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInByXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgeCA9IGMuZ2V0TG9jYWwoXCJwMVwiKTtcbiAgICAgICAgY29uc3QgeSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicDFcIiksIGMuaTMyX2NvbnN0KG44KSk7XG4gICAgICAgIGNvbnN0IHogPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInAxXCIpLCBjLmkzMl9jb25zdChuOCoyKSk7XG4gICAgICAgIGNvbnN0IHgzID0gYy5nZXRMb2NhbChcInByXCIpO1xuICAgICAgICBjb25zdCB5MyA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicHJcIiksIGMuaTMyX2NvbnN0KG44KSk7XG4gICAgICAgIGNvbnN0IHozID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwclwiKSwgYy5pMzJfY29uc3QobjgqMikpO1xuXG4gICAgICAgIGNvbnN0IEEgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgQiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuICAgICAgICBjb25zdCBDID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IEQgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgRSA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuICAgICAgICBjb25zdCBGID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IEcgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgZWlnaHRDID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfaXNaZXJvXCIsIGMuZ2V0TG9jYWwoXCJwMVwiKSksXG4gICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwocHJlZml4ICsgXCJfY29weVwiLCBjLmdldExvY2FsKFwicDFcIiksIGMuZ2V0TG9jYWwoXCJwclwiKSksXG4gICAgICAgICAgICAgICAgICAgIC4uLmMucmV0KFtdKVxuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2lzT25lXCIsIHopLFxuICAgICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5yZXQoYy5jYWxsKHByZWZpeCArIFwiX2RvdWJsZUFmZmluZVwiLCBjLmdldExvY2FsKFwicDFcIiksIGMuZ2V0TG9jYWwoXCJwclwiKSkpLFxuICAgICAgICAgICAgICAgICAgICAuLi5jLnJldChbXSlcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICApLFxuXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9zcXVhcmVcIiwgeCwgQSksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9zcXVhcmVcIiwgeSwgQiksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9zcXVhcmVcIiwgQiwgQyksXG5cbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2FkZFwiLCB4LCBCLCBEKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3NxdWFyZVwiLCBELCBEKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3N1YlwiLCBELCBBLCBEKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3N1YlwiLCBELCBDLCBEKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2FkZFwiLCBELCBELCBEKSxcblxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfYWRkXCIsIEEsIEEsIEUpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfYWRkXCIsIEUsIEEsIEUpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfc3F1YXJlXCIsIEUsIEYpLFxuXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9tdWxcIiwgeSwgeiwgRyksXG5cbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2FkZFwiLCBELCBELCB4MyksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9zdWJcIiwgRiwgeDMsIHgzKSxcblxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfYWRkXCIsIEMsIEMsIGVpZ2h0QyksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9hZGRcIiwgZWlnaHRDLCBlaWdodEMsIGVpZ2h0QyksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9hZGRcIiwgZWlnaHRDLCBlaWdodEMsIGVpZ2h0QyksXG5cbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3N1YlwiLCBELCB4MywgeTMpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfbXVsXCIsIHkzLCBFLCB5MyksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9zdWJcIiwgeTMsIGVpZ2h0QywgeTMpLFxuXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9hZGRcIiwgRywgRywgejMpLFxuICAgICAgICApO1xuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gYnVpbGREb3VibGVBZmZpbmUoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4ICsgXCJfZG91YmxlQWZmaW5lXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicDFcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwclwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IHggPSBjLmdldExvY2FsKFwicDFcIik7XG4gICAgICAgIGNvbnN0IHkgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInAxXCIpLCBjLmkzMl9jb25zdChuOCkpO1xuICAgICAgICBjb25zdCB4MyA9IGMuZ2V0TG9jYWwoXCJwclwiKTtcbiAgICAgICAgY29uc3QgeTMgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInByXCIpLCBjLmkzMl9jb25zdChuOCkpO1xuICAgICAgICBjb25zdCB6MyA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicHJcIiksIGMuaTMyX2NvbnN0KG44KjIpKTtcblxuICAgICAgICBjb25zdCBYWCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuICAgICAgICBjb25zdCBZWSA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuICAgICAgICBjb25zdCBZWVlZID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IFMgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgTSA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuICAgICAgICBjb25zdCBlaWdodFlZWVkgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9pc1plcm9BZmZpbmVcIiwgYy5nZXRMb2NhbChcInAxXCIpKSxcbiAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChwcmVmaXggKyBcIl90b0phY29iaWFuXCIsIGMuZ2V0TG9jYWwoXCJwMVwiKSwgYy5nZXRMb2NhbChcInByXCIpKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5yZXQoW10pXG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgLy8gWFggPSBYMV4yXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9zcXVhcmVcIiwgeCwgWFgpLFxuXG4gICAgICAgICAgICAvLyBZWSA9IFkxXjJcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3NxdWFyZVwiLCB5LCBZWSksXG5cbiAgICAgICAgICAgIC8vIFlZWVkgPSBZWV4yXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9zcXVhcmVcIiwgWVksIFlZWVkpLFxuXG4gICAgICAgICAgICAvLyBTID0gMiooKFgxK1lZKV4yLVhYLVlZWVkpXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9hZGRcIiwgeCwgWVksIFMpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfc3F1YXJlXCIsIFMsIFMpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfc3ViXCIsIFMsIFhYLCBTKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3N1YlwiLCBTLCBZWVlZLCBTKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2FkZFwiLCBTLCBTLCBTKSxcblxuICAgICAgICAgICAgLy8gTSA9IDMqWFgrYSAgKEhlcmEgYT0wKVxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfYWRkXCIsIFhYLCBYWCwgTSksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9hZGRcIiwgTSwgWFgsIE0pLFxuXG4gICAgICAgICAgICAvLyBaMyA9IDIqWTFcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2FkZFwiLCB5LCB5LCB6MyksXG5cbiAgICAgICAgICAgIC8vIFQgPSBNXjItMipTXG4gICAgICAgICAgICAvLyBYMyA9IFRcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3NxdWFyZVwiLCBNLCB4MyksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9zdWJcIiwgeDMsIFMsIHgzKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3N1YlwiLCB4MywgUywgeDMpLFxuXG4gICAgICAgICAgICAvLyBZMyA9IE0qKFMtVCktOCpZWVlZXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9hZGRcIiwgWVlZWSwgWVlZWSwgZWlnaHRZWVlZKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2FkZFwiLCBlaWdodFlZWVksIGVpZ2h0WVlZWSwgZWlnaHRZWVlZKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2FkZFwiLCBlaWdodFlZWVksIGVpZ2h0WVlZWSwgZWlnaHRZWVlZKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3N1YlwiLCBTLCB4MywgeTMpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfbXVsXCIsIHkzLCBNLCB5MyksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9zdWJcIiwgeTMsIGVpZ2h0WVlZWSwgeTMpLFxuICAgICAgICApO1xuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gYnVpbGRFcUFmZmluZSgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXggKyBcIl9lcUFmZmluZVwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInAxXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicDJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuc2V0UmV0dXJuVHlwZShcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcInoxXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5yZXQoYy5pMzJfYW5kKFxuICAgICAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgcHJlZml4RmllbGQgKyBcIl9lcVwiLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicDFcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwMlwiKVxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgICAgICBwcmVmaXhGaWVsZCArIFwiX2VxXCIsXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2FkZChjLmdldExvY2FsKFwicDFcIiksIGMuaTMyX2NvbnN0KG44KSksXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2FkZChjLmdldExvY2FsKFwicDJcIiksIGMuaTMyX2NvbnN0KG44KSlcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkVG9Nb250Z29tZXJ5KCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCArIFwiX3RvTW9udGdvbWVyeVwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInAxXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicHJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBmLmFkZENvZGUoYy5jYWxsKFxuICAgICAgICAgICAgcHJlZml4RmllbGQgKyBcIl90b01vbnRnb21lcnlcIixcbiAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwMVwiKSxcbiAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwclwiKVxuICAgICAgICApKTtcbiAgICAgICAgZm9yIChsZXQgaT0xOyBpPDM7IGkrKykge1xuICAgICAgICAgICAgZi5hZGRDb2RlKGMuY2FsbChcbiAgICAgICAgICAgICAgICBwcmVmaXhGaWVsZCArIFwiX3RvTW9udGdvbWVyeVwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChjLmdldExvY2FsKFwicDFcIiksIGMuaTMyX2NvbnN0KGkqbjgpKSxcbiAgICAgICAgICAgICAgICBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInByXCIpLCBjLmkzMl9jb25zdChpKm44KSlcbiAgICAgICAgICAgICkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRUb01vbnRnb21lcnlBZmZpbmUoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4ICsgXCJfdG9Nb250Z29tZXJ5QWZmaW5lXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicDFcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwclwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGYuYWRkQ29kZShjLmNhbGwoXG4gICAgICAgICAgICBwcmVmaXhGaWVsZCArIFwiX3RvTW9udGdvbWVyeVwiLFxuICAgICAgICAgICAgYy5nZXRMb2NhbChcInAxXCIpLFxuICAgICAgICAgICAgYy5nZXRMb2NhbChcInByXCIpXG4gICAgICAgICkpO1xuICAgICAgICBmb3IgKGxldCBpPTE7IGk8MjsgaSsrKSB7XG4gICAgICAgICAgICBmLmFkZENvZGUoYy5jYWxsKFxuICAgICAgICAgICAgICAgIHByZWZpeEZpZWxkICsgXCJfdG9Nb250Z29tZXJ5XCIsXG4gICAgICAgICAgICAgICAgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwMVwiKSwgYy5pMzJfY29uc3QoaSpuOCkpLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChjLmdldExvY2FsKFwicHJcIiksIGMuaTMyX2NvbnN0KGkqbjgpKVxuICAgICAgICAgICAgKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZEZyb21Nb250Z29tZXJ5KCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCArIFwiX2Zyb21Nb250Z29tZXJ5XCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicDFcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwclwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGYuYWRkQ29kZShjLmNhbGwoXG4gICAgICAgICAgICBwcmVmaXhGaWVsZCArIFwiX2Zyb21Nb250Z29tZXJ5XCIsXG4gICAgICAgICAgICBjLmdldExvY2FsKFwicDFcIiksXG4gICAgICAgICAgICBjLmdldExvY2FsKFwicHJcIilcbiAgICAgICAgKSk7XG4gICAgICAgIGZvciAobGV0IGk9MTsgaTwzOyBpKyspIHtcbiAgICAgICAgICAgIGYuYWRkQ29kZShjLmNhbGwoXG4gICAgICAgICAgICAgICAgcHJlZml4RmllbGQgKyBcIl9mcm9tTW9udGdvbWVyeVwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChjLmdldExvY2FsKFwicDFcIiksIGMuaTMyX2NvbnN0KGkqbjgpKSxcbiAgICAgICAgICAgICAgICBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInByXCIpLCBjLmkzMl9jb25zdChpKm44KSlcbiAgICAgICAgICAgICkpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICBmdW5jdGlvbiBidWlsZEZyb21Nb250Z29tZXJ5QWZmaW5lKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCArIFwiX2Zyb21Nb250Z29tZXJ5QWZmaW5lXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicDFcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwclwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGYuYWRkQ29kZShjLmNhbGwoXG4gICAgICAgICAgICBwcmVmaXhGaWVsZCArIFwiX2Zyb21Nb250Z29tZXJ5XCIsXG4gICAgICAgICAgICBjLmdldExvY2FsKFwicDFcIiksXG4gICAgICAgICAgICBjLmdldExvY2FsKFwicHJcIilcbiAgICAgICAgKSk7XG4gICAgICAgIGZvciAobGV0IGk9MTsgaTwyOyBpKyspIHtcbiAgICAgICAgICAgIGYuYWRkQ29kZShjLmNhbGwoXG4gICAgICAgICAgICAgICAgcHJlZml4RmllbGQgKyBcIl9mcm9tTW9udGdvbWVyeVwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChjLmdldExvY2FsKFwicDFcIiksIGMuaTMyX2NvbnN0KGkqbjgpKSxcbiAgICAgICAgICAgICAgICBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInByXCIpLCBjLmkzMl9jb25zdChpKm44KSlcbiAgICAgICAgICAgICkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRBZGQoKSB7XG5cbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXggKyBcIl9hZGRcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwMVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInAyXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicHJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJ6MVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcInoyXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgeDEgPSBjLmdldExvY2FsKFwicDFcIik7XG4gICAgICAgIGNvbnN0IHkxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwMVwiKSwgYy5pMzJfY29uc3QobjgpKTtcbiAgICAgICAgZi5hZGRDb2RlKGMuc2V0TG9jYWwoXCJ6MVwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInAxXCIpLCBjLmkzMl9jb25zdChuOCoyKSkpKTtcbiAgICAgICAgY29uc3QgejEgPSBjLmdldExvY2FsKFwiejFcIik7XG4gICAgICAgIGNvbnN0IHgyID0gYy5nZXRMb2NhbChcInAyXCIpO1xuICAgICAgICBjb25zdCB5MiA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicDJcIiksIGMuaTMyX2NvbnN0KG44KSk7XG4gICAgICAgIGYuYWRkQ29kZShjLnNldExvY2FsKFwiejJcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwMlwiKSwgYy5pMzJfY29uc3QobjgqMikpKSk7XG4gICAgICAgIGNvbnN0IHoyID0gYy5nZXRMb2NhbChcInoyXCIpO1xuICAgICAgICBjb25zdCB4MyA9IGMuZ2V0TG9jYWwoXCJwclwiKTtcbiAgICAgICAgY29uc3QgeTMgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInByXCIpLCBjLmkzMl9jb25zdChuOCkpO1xuICAgICAgICBjb25zdCB6MyA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicHJcIiksIGMuaTMyX2NvbnN0KG44KjIpKTtcblxuICAgICAgICBjb25zdCBaMVoxID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IFoyWjIgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgVTEgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgVTIgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgWjFfY3ViZWQgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgWjJfY3ViZWQgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgUzEgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgUzIgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgSCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuICAgICAgICBjb25zdCBTMl9taW51c19TMSA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuICAgICAgICBjb25zdCBJID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IEogPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgciA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuICAgICAgICBjb25zdCByMiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuICAgICAgICBjb25zdCBWID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IFYyID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IFMxX0oyID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfaXNaZXJvXCIsIGMuZ2V0TG9jYWwoXCJwMVwiKSksXG4gICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwocHJlZml4ICsgXCJfY29weVwiLCBjLmdldExvY2FsKFwicDJcIiksIGMuZ2V0TG9jYWwoXCJwclwiKSksXG4gICAgICAgICAgICAgICAgICAgIC4uLmMucmV0KFtdKVxuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9pc1plcm9cIiwgYy5nZXRMb2NhbChcInAyXCIpKSxcbiAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChwcmVmaXggKyBcIl9jb3B5XCIsIGMuZ2V0TG9jYWwoXCJwMVwiKSwgYy5nZXRMb2NhbChcInByXCIpKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5yZXQoW10pXG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfaXNPbmVcIiwgejEpLFxuICAgICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5jYWxsKHByZWZpeCArIFwiX2FkZE1peGVkXCIsIHgyLCB4MSwgeDMpLFxuICAgICAgICAgICAgICAgICAgICAuLi5jLnJldChbXSlcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9pc09uZVwiLCB6MiksXG4gICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwocHJlZml4ICsgXCJfYWRkTWl4ZWRcIiwgeDEsIHgyLCB4MyksXG4gICAgICAgICAgICAgICAgICAgIC4uLmMucmV0KFtdKVxuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9zcXVhcmVcIiwgejEsIFoxWjEpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfc3F1YXJlXCIsIHoyLCBaMloyKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX211bFwiLCB4MSwgWjJaMiwgVTEpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfbXVsXCIsIHgyLCBaMVoxLCBVMiksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9tdWxcIiwgejEsIFoxWjEsIFoxX2N1YmVkKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX211bFwiLCB6MiwgWjJaMiwgWjJfY3ViZWQpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfbXVsXCIsIHkxLCBaMl9jdWJlZCwgUzEpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfbXVsXCIsIHkyLCBaMV9jdWJlZCwgUzIpLFxuXG4gICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2VxXCIsIFUxLCBVMiksXG4gICAgICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfZXFcIiwgUzEsIFMyKSxcbiAgICAgICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAgICAgLi4uYy5jYWxsKHByZWZpeCArIFwiX2RvdWJsZVwiLCBjLmdldExvY2FsKFwicDFcIiksIGMuZ2V0TG9jYWwoXCJwclwiKSksXG4gICAgICAgICAgICAgICAgICAgICAgICAuLi5jLnJldChbXSlcbiAgICAgICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3N1YlwiLCBVMiwgVTEsIEgpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfc3ViXCIsIFMyLCBTMSwgUzJfbWludXNfUzEpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfYWRkXCIsIEgsIEgsIEkpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfc3F1YXJlXCIsIEksIEkpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfbXVsXCIsIEgsIEksIEopLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfYWRkXCIsIFMyX21pbnVzX1MxLCBTMl9taW51c19TMSwgciksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9tdWxcIiwgVTEsIEksIFYpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfc3F1YXJlXCIsIHIsIHIyKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2FkZFwiLCBWLCBWLCBWMiksXG5cbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3N1YlwiLCByMiwgSiwgeDMpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfc3ViXCIsIHgzLCBWMiwgeDMpLFxuXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9tdWxcIiwgUzEsIEosIFMxX0oyKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2FkZFwiLCBTMV9KMiwgUzFfSjIsIFMxX0oyKSxcblxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfc3ViXCIsIFYsIHgzLCB5MyksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9tdWxcIiwgeTMsIHIsIHkzKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3N1YlwiLCB5MywgUzFfSjIsIHkzKSxcblxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfYWRkXCIsIHoxLCB6MiwgejMpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfc3F1YXJlXCIsIHozLCB6MyksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9zdWJcIiwgejMsIFoxWjEsIHozKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3N1YlwiLCB6MywgWjJaMiwgejMpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfbXVsXCIsIHozLCBILCB6MyksXG4gICAgICAgICk7XG5cbiAgICB9XG5cblxuICAgIGZ1bmN0aW9uIGJ1aWxkQWRkTWl4ZWQoKSB7XG5cbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXggKyBcIl9hZGRNaXhlZFwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInAxXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicDJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwclwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcInoxXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgeDEgPSBjLmdldExvY2FsKFwicDFcIik7XG4gICAgICAgIGNvbnN0IHkxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwMVwiKSwgYy5pMzJfY29uc3QobjgpKTtcbiAgICAgICAgZi5hZGRDb2RlKGMuc2V0TG9jYWwoXCJ6MVwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInAxXCIpLCBjLmkzMl9jb25zdChuOCoyKSkpKTtcbiAgICAgICAgY29uc3QgejEgPSBjLmdldExvY2FsKFwiejFcIik7XG4gICAgICAgIGNvbnN0IHgyID0gYy5nZXRMb2NhbChcInAyXCIpO1xuICAgICAgICBjb25zdCB5MiA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicDJcIiksIGMuaTMyX2NvbnN0KG44KSk7XG4gICAgICAgIGNvbnN0IHgzID0gYy5nZXRMb2NhbChcInByXCIpO1xuICAgICAgICBjb25zdCB5MyA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicHJcIiksIGMuaTMyX2NvbnN0KG44KSk7XG4gICAgICAgIGNvbnN0IHozID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwclwiKSwgYy5pMzJfY29uc3QobjgqMikpO1xuXG4gICAgICAgIGNvbnN0IFoxWjEgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgVTIgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgWjFfY3ViZWQgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgUzIgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgSCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuICAgICAgICBjb25zdCBISCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuICAgICAgICBjb25zdCBTMl9taW51c195MSA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuICAgICAgICBjb25zdCBJID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IEogPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgciA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuICAgICAgICBjb25zdCByMiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuICAgICAgICBjb25zdCBWID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IFYyID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IHkxX0oyID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfaXNaZXJvXCIsIGMuZ2V0TG9jYWwoXCJwMVwiKSksXG4gICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwocHJlZml4ICsgXCJfY29weUFmZmluZVwiLCBjLmdldExvY2FsKFwicDJcIiksIGMuZ2V0TG9jYWwoXCJwclwiKSksXG4gICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChwcmVmaXhGaWVsZCArIFwiX29uZVwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInByXCIpICwgYy5pMzJfY29uc3QobjgqMikpKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5yZXQoW10pXG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX2lzWmVyb0FmZmluZVwiLCBjLmdldExvY2FsKFwicDJcIikpLFxuICAgICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5jYWxsKHByZWZpeCArIFwiX2NvcHlcIiwgYy5nZXRMb2NhbChcInAxXCIpLCBjLmdldExvY2FsKFwicHJcIikpLFxuICAgICAgICAgICAgICAgICAgICAuLi5jLnJldChbXSlcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9pc09uZVwiLCB6MSksXG4gICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwocHJlZml4ICsgXCJfYWRkQWZmaW5lXCIsIHgxLCB4MiwgeDMpLFxuICAgICAgICAgICAgICAgICAgICAuLi5jLnJldChbXSlcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfc3F1YXJlXCIsIHoxLCBaMVoxKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX211bFwiLCB4MiwgWjFaMSwgVTIpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfbXVsXCIsIHoxLCBaMVoxLCBaMV9jdWJlZCksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9tdWxcIiwgeTIsIFoxX2N1YmVkLCBTMiksXG5cbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfZXFcIiwgeDEsIFUyKSxcbiAgICAgICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9lcVwiLCB5MSwgUzIpLFxuICAgICAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwocHJlZml4ICsgXCJfZG91YmxlQWZmaW5lXCIsIGMuZ2V0TG9jYWwoXCJwMlwiKSwgYy5nZXRMb2NhbChcInByXCIpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMucmV0KFtdKVxuICAgICAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfc3ViXCIsIFUyLCB4MSwgSCksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9zdWJcIiwgUzIsIHkxLCBTMl9taW51c195MSksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9zcXVhcmVcIiwgSCwgSEgpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfYWRkXCIsIEhIICwgSEgsIEkpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfYWRkXCIsIEkgLCBJLCBJKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX211bFwiLCBILCBJLCBKKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2FkZFwiLCBTMl9taW51c195MSwgUzJfbWludXNfeTEsIHIpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfbXVsXCIsIHgxLCBJLCBWKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3NxdWFyZVwiLCByLCByMiksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9hZGRcIiwgViwgViwgVjIpLFxuXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9zdWJcIiwgcjIsIEosIHgzKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3N1YlwiLCB4MywgVjIsIHgzKSxcblxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfbXVsXCIsIHkxLCBKLCB5MV9KMiksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9hZGRcIiwgeTFfSjIsIHkxX0oyLCB5MV9KMiksXG5cbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3N1YlwiLCBWLCB4MywgeTMpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfbXVsXCIsIHkzLCByLCB5MyksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9zdWJcIiwgeTMsIHkxX0oyLCB5MyksXG5cbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2FkZFwiLCB6MSwgSCwgejMpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfc3F1YXJlXCIsIHozLCB6MyksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9zdWJcIiwgejMsIFoxWjEsIHozKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3N1YlwiLCB6MywgSEgsIHozKSxcbiAgICAgICAgKTtcbiAgICB9XG5cblxuICAgIGZ1bmN0aW9uIGJ1aWxkQWRkQWZmaW5lKCkge1xuXG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4ICsgXCJfYWRkQWZmaW5lXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicDFcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwMlwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInByXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiejFcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCB4MSA9IGMuZ2V0TG9jYWwoXCJwMVwiKTtcbiAgICAgICAgY29uc3QgeTEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInAxXCIpLCBjLmkzMl9jb25zdChuOCkpO1xuICAgICAgICBmLmFkZENvZGUoYy5zZXRMb2NhbChcInoxXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwicDFcIiksIGMuaTMyX2NvbnN0KG44KjIpKSkpO1xuICAgICAgICBjb25zdCB4MiA9IGMuZ2V0TG9jYWwoXCJwMlwiKTtcbiAgICAgICAgY29uc3QgeTIgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInAyXCIpLCBjLmkzMl9jb25zdChuOCkpO1xuICAgICAgICBjb25zdCB4MyA9IGMuZ2V0TG9jYWwoXCJwclwiKTtcbiAgICAgICAgY29uc3QgeTMgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInByXCIpLCBjLmkzMl9jb25zdChuOCkpO1xuICAgICAgICBjb25zdCB6MyA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicHJcIiksIGMuaTMyX2NvbnN0KG44KjIpKTtcblxuICAgICAgICBjb25zdCBIID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IEhIID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IHkyX21pbnVzX3kxID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IEkgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgSiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuICAgICAgICBjb25zdCByID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IHIyID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IFYgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgVjIgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgeTFfSjIgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9pc1plcm9BZmZpbmVcIiwgYy5nZXRMb2NhbChcInAxXCIpKSxcbiAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChwcmVmaXggKyBcIl9jb3B5QWZmaW5lXCIsIGMuZ2V0TG9jYWwoXCJwMlwiKSwgYy5nZXRMb2NhbChcInByXCIpKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfb25lXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwicHJcIikgLCBjLmkzMl9jb25zdChuOCoyKSkpLFxuICAgICAgICAgICAgICAgICAgICAuLi5jLnJldChbXSlcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfaXNaZXJvQWZmaW5lXCIsIGMuZ2V0TG9jYWwoXCJwMlwiKSksXG4gICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwocHJlZml4ICsgXCJfY29weUFmZmluZVwiLCBjLmdldExvY2FsKFwicDFcIiksIGMuZ2V0TG9jYWwoXCJwclwiKSksXG4gICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChwcmVmaXhGaWVsZCArIFwiX29uZVwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInByXCIpICwgYy5pMzJfY29uc3QobjgqMikpKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5yZXQoW10pXG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgKSxcblxuXG4gICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2VxXCIsIHgxLCB4MiksXG4gICAgICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfZXFcIiwgeTEsIHkyKSxcbiAgICAgICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAgICAgLi4uYy5jYWxsKHByZWZpeCArIFwiX2RvdWJsZUFmZmluZVwiLCBjLmdldExvY2FsKFwicDJcIiksIGMuZ2V0TG9jYWwoXCJwclwiKSksXG4gICAgICAgICAgICAgICAgICAgICAgICAuLi5jLnJldChbXSlcbiAgICAgICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3N1YlwiLCB4MiwgeDEsIEgpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfc3ViXCIsIHkyLCB5MSwgeTJfbWludXNfeTEpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfc3F1YXJlXCIsIEgsIEhIKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2FkZFwiLCBISCAsIEhILCBJKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2FkZFwiLCBJICwgSSwgSSksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9tdWxcIiwgSCwgSSwgSiksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9hZGRcIiwgeTJfbWludXNfeTEsIHkyX21pbnVzX3kxLCByKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX211bFwiLCB4MSwgSSwgViksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9zcXVhcmVcIiwgciwgcjIpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfYWRkXCIsIFYsIFYsIFYyKSxcblxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfc3ViXCIsIHIyLCBKLCB4MyksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9zdWJcIiwgeDMsIFYyLCB4MyksXG5cbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX211bFwiLCB5MSwgSiwgeTFfSjIpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfYWRkXCIsIHkxX0oyLCB5MV9KMiwgeTFfSjIpLFxuXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9zdWJcIiwgViwgeDMsIHkzKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX211bFwiLCB5MywgciwgeTMpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfc3ViXCIsIHkzLCB5MV9KMiwgeTMpLFxuXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9hZGRcIiwgSCwgSCwgejMpLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkTmVnKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCArIFwiX25lZ1wiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInAxXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicHJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCB4ID0gYy5nZXRMb2NhbChcInAxXCIpO1xuICAgICAgICBjb25zdCB5ID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwMVwiKSwgYy5pMzJfY29uc3QobjgpKTtcbiAgICAgICAgY29uc3QgeiA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicDFcIiksIGMuaTMyX2NvbnN0KG44KjIpKTtcbiAgICAgICAgY29uc3QgeDMgPSBjLmdldExvY2FsKFwicHJcIik7XG4gICAgICAgIGNvbnN0IHkzID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwclwiKSwgYy5pMzJfY29uc3QobjgpKTtcbiAgICAgICAgY29uc3QgejMgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInByXCIpLCBjLmkzMl9jb25zdChuOCoyKSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfY29weVwiLCB4LCB4MyksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9uZWdcIiwgeSwgeTMpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfY29weVwiLCB6LCB6MylcbiAgICAgICAgKTtcbiAgICB9XG5cblxuICAgIGZ1bmN0aW9uIGJ1aWxkTmVnQWZmaW5lKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCArIFwiX25lZ0FmZmluZVwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInAxXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicHJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCB4ID0gYy5nZXRMb2NhbChcInAxXCIpO1xuICAgICAgICBjb25zdCB5ID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwMVwiKSwgYy5pMzJfY29uc3QobjgpKTtcbiAgICAgICAgY29uc3QgeDMgPSBjLmdldExvY2FsKFwicHJcIik7XG4gICAgICAgIGNvbnN0IHkzID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwclwiKSwgYy5pMzJfY29uc3QobjgpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9jb3B5XCIsIHgsIHgzKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX25lZ1wiLCB5LCB5MyksXG4gICAgICAgICk7XG4gICAgfVxuXG5cbiAgICBmdW5jdGlvbiBidWlsZFN1YigpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXggKyBcIl9zdWJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwMVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInAyXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicHJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCBBVVggPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgqMykpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9uZWdcIiwgYy5nZXRMb2NhbChcInAyXCIpLCBBVVgpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX2FkZFwiLCBjLmdldExvY2FsKFwicDFcIiksIEFVWCwgYy5nZXRMb2NhbChcInByXCIpKSxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZFN1Yk1peGVkKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCArIFwiX3N1Yk1peGVkXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicDFcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwMlwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInByXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgQVVYID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KjMpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfbmVnQWZmaW5lXCIsIGMuZ2V0TG9jYWwoXCJwMlwiKSwgQVVYKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9hZGRNaXhlZFwiLCBjLmdldExvY2FsKFwicDFcIiksIEFVWCwgYy5nZXRMb2NhbChcInByXCIpKSxcbiAgICAgICAgKTtcbiAgICB9XG5cblxuICAgIGZ1bmN0aW9uIGJ1aWxkU3ViQWZmaW5lKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCArIFwiX3N1YkFmZmluZVwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInAxXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicDJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwclwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IEFVWCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCozKSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX25lZ0FmZmluZVwiLCBjLmdldExvY2FsKFwicDJcIiksIEFVWCksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfYWRkQWZmaW5lXCIsIGMuZ2V0TG9jYWwoXCJwMVwiKSwgQVVYLCBjLmdldExvY2FsKFwicHJcIikpLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIC8vIFRoaXMgc2V0cyBaIHRvIE9uZVxuICAgIGZ1bmN0aW9uIGJ1aWxkTm9ybWFsaXplKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCArIFwiX25vcm1hbGl6ZVwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInAxXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicHJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCB4ID0gYy5nZXRMb2NhbChcInAxXCIpO1xuICAgICAgICBjb25zdCB5ID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwMVwiKSwgYy5pMzJfY29uc3QobjgpKTtcbiAgICAgICAgY29uc3QgeiA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicDFcIiksIGMuaTMyX2NvbnN0KG44KjIpKTtcbiAgICAgICAgY29uc3QgeDMgPSBjLmdldExvY2FsKFwicHJcIik7XG4gICAgICAgIGNvbnN0IHkzID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwclwiKSwgYy5pMzJfY29uc3QobjgpKTtcbiAgICAgICAgY29uc3QgejMgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInByXCIpLCBjLmkzMl9jb25zdChuOCoyKSk7XG5cblxuICAgICAgICBjb25zdCBaX2ludiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuICAgICAgICBjb25zdCBaMl9pbnYgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgWjNfaW52ID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfaXNaZXJvXCIsIGMuZ2V0TG9jYWwoXCJwMVwiKSksXG4gICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX3plcm9cIiwgYy5nZXRMb2NhbChcInByXCIpKSxcbiAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2ludmVyc2VcIiwgeiwgWl9pbnYpLFxuICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwocHJlZml4RmllbGQgKyBcIl9zcXVhcmVcIiwgWl9pbnYsIFoyX2ludiksXG4gICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChwcmVmaXhGaWVsZCArIFwiX211bFwiLCBaX2ludiwgWjJfaW52LCBaM19pbnYpLFxuICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwocHJlZml4RmllbGQgKyBcIl9tdWxcIiwgeCwgWjJfaW52LCB4MyksXG4gICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChwcmVmaXhGaWVsZCArIFwiX211bFwiLCB5LCBaM19pbnYsIHkzKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfb25lXCIsIHozKSxcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxuXG5cbiAgICAvLyBEb2VzIG5vdCBzZXQgWi5cbiAgICBmdW5jdGlvbiBidWlsZFRvQWZmaW5lKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCArIFwiX3RvQWZmaW5lXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicDFcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwclwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IHggPSBjLmdldExvY2FsKFwicDFcIik7XG4gICAgICAgIGNvbnN0IHkgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInAxXCIpLCBjLmkzMl9jb25zdChuOCkpO1xuICAgICAgICBjb25zdCB6ID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwMVwiKSwgYy5pMzJfY29uc3QobjgqMikpO1xuICAgICAgICBjb25zdCB4MyA9IGMuZ2V0TG9jYWwoXCJwclwiKTtcbiAgICAgICAgY29uc3QgeTMgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInByXCIpLCBjLmkzMl9jb25zdChuOCkpO1xuXG5cbiAgICAgICAgY29uc3QgWl9pbnYgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcbiAgICAgICAgY29uc3QgWjJfaW52ID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG4gICAgICAgIGNvbnN0IFozX2ludiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX2lzWmVyb1wiLCBjLmdldExvY2FsKFwicDFcIikpLFxuICAgICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfemVyb1wiLCB4MyksXG4gICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3plcm9cIiwgeTMpLFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwocHJlZml4RmllbGQgKyBcIl9pbnZlcnNlXCIsIHosIFpfaW52KSxcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfc3F1YXJlXCIsIFpfaW52LCBaMl9pbnYpLFxuICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwocHJlZml4RmllbGQgKyBcIl9tdWxcIiwgWl9pbnYsIFoyX2ludiwgWjNfaW52KSxcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfbXVsXCIsIHgsIFoyX2ludiwgeDMpLFxuICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwocHJlZml4RmllbGQgKyBcIl9tdWxcIiwgeSwgWjNfaW52LCB5MyksXG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gYnVpbGRUb0phY29iaWFuKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCArIFwiX3RvSmFjb2JpYW5cIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwMVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInByXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgeCA9IGMuZ2V0TG9jYWwoXCJwMVwiKTtcbiAgICAgICAgY29uc3QgeSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicDFcIiksIGMuaTMyX2NvbnN0KG44KSk7XG4gICAgICAgIGNvbnN0IHgzID0gYy5nZXRMb2NhbChcInByXCIpO1xuICAgICAgICBjb25zdCB5MyA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicHJcIiksIGMuaTMyX2NvbnN0KG44KSk7XG4gICAgICAgIGNvbnN0IHozID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwclwiKSwgYy5pMzJfY29uc3QobjgqMikpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX2lzWmVyb0FmZmluZVwiLCBjLmdldExvY2FsKFwicDFcIikpLFxuICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl96ZXJvXCIsIGMuZ2V0TG9jYWwoXCJwclwiKSksXG4gICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwocHJlZml4RmllbGQgKyBcIl9vbmVcIiwgejMpLFxuICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwocHJlZml4RmllbGQgKyBcIl9jb3B5XCIsIHksIHkzKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfY29weVwiLCB4LCB4MylcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRCYXRjaFRvQWZmaW5lKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCArIFwiX2JhdGNoVG9BZmZpbmVcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwSW5cIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJuXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicE91dFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcInBBdXhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJpdEluXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiaXRBdXhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJpdE91dFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImlcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCB0bXAgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLnNldExvY2FsKFwicEF1eFwiLCBjLmkzMl9sb2FkKCBjLmkzMl9jb25zdCgwKSApKSxcbiAgICAgICAgICAgIGMuaTMyX3N0b3JlKFxuICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDApLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBBdXhcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX211bChjLmdldExvY2FsKFwiblwiKSwgYy5pMzJfY29uc3QobjgpKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICBwcmVmaXhGaWVsZCArIFwiX2JhdGNoSW52ZXJzZVwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChjLmdldExvY2FsKFwicEluXCIpLCBjLmkzMl9jb25zdChuOCoyKSksXG4gICAgICAgICAgICAgICAgYy5pMzJfY29uc3QobjgqMyksXG4gICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIm5cIiksXG4gICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBBdXhcIiksXG4gICAgICAgICAgICAgICAgYy5pMzJfY29uc3QobjgpXG4gICAgICAgICAgICApLFxuXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiaXRJblwiLCBjLmdldExvY2FsKFwicEluXCIpKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpdEF1eFwiLCBjLmdldExvY2FsKFwicEF1eFwiKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiaXRPdXRcIiwgYy5nZXRMb2NhbChcInBPdXRcIikpLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcImlcIiwgYy5pMzJfY29uc3QoMCkpLFxuICAgICAgICAgICAgYy5ibG9jayhjLmxvb3AoXG4gICAgICAgICAgICAgICAgYy5icl9pZigxLCBjLmkzMl9lcSAoIGMuZ2V0TG9jYWwoXCJpXCIpLCBjLmdldExvY2FsKFwiblwiKSApKSxcblxuICAgICAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2lzWmVyb1wiLCBjLmdldExvY2FsKFwiaXRBdXhcIikpLFxuICAgICAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwocHJlZml4RmllbGQgKyBcIl96ZXJvXCIsIGMuZ2V0TG9jYWwoXCJpdE91dFwiKSksXG4gICAgICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwocHJlZml4RmllbGQgKyBcIl96ZXJvXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwiaXRPdXRcIiksIGMuaTMyX2NvbnN0KG44KSkpXG4gICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVmaXhGaWVsZCtcIl9tdWxcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaXRBdXhcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJpdEluXCIpLCBjLmkzMl9jb25zdChuOCkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtcCxcbiAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlZml4RmllbGQrXCJfc3F1YXJlXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIml0QXV4XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpdEF1eFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVmaXhGaWVsZCtcIl9tdWxcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaXRBdXhcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIml0SW5cIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIml0T3V0XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVmaXhGaWVsZCtcIl9tdWxcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaXRBdXhcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1wLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2FkZChjLmdldExvY2FsKFwiaXRPdXRcIiksIGMuaTMyX2NvbnN0KG44KSksXG4gICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpdEluXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwiaXRJblwiKSwgYy5pMzJfY29uc3QobjgqMykpKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaXRPdXRcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJpdE91dFwiKSwgYy5pMzJfY29uc3QobjgqMikpKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaXRBdXhcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJpdEF1eFwiKSwgYy5pMzJfY29uc3QobjgpKSksXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcImlcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJpXCIpLCBjLmkzMl9jb25zdCgxKSkpLFxuICAgICAgICAgICAgICAgIGMuYnIoMClcbiAgICAgICAgICAgICkpLFxuICAgICAgICAgICAgYy5pMzJfc3RvcmUoXG4gICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMCksXG4gICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBBdXhcIilcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9XG5cblxuICAgIC8vIFRoaXMgZnVuY3Rpb24gaXMgcHJpdmF0ZSBhbmQgZG9lcyBub3QgYWxsb3cgdG8gT1ZFUkxBUCBidWZmZXJzLlxuICAgIGZ1bmN0aW9uIGJ1aWxkUmV2ZXJzZUJ5dGVzKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCArIFwiX19yZXZlcnNlQnl0ZXNcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwSW5cIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJuXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicE91dFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcIml0T3V0XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiaXRJblwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgXCJpdE91dFwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX3N1YihcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBPdXRcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiblwiKVxuICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdCgxKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgIFwiaXRJblwiLFxuICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwSW5cIilcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLmJsb2NrKGMubG9vcChcbiAgICAgICAgICAgICAgICBjLmJyX2lmKDEsIGMuaTMyX2x0X3MoIGMuZ2V0TG9jYWwoXCJpdE91dFwiKSwgYy5nZXRMb2NhbChcInBPdXRcIikgKSksXG4gICAgICAgICAgICAgICAgYy5pMzJfc3RvcmU4KFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaXRPdXRcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2xvYWQ4X3UoYy5nZXRMb2NhbChcIml0SW5cIikpLFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcIml0T3V0XCIsIGMuaTMyX3N1YihjLmdldExvY2FsKFwiaXRPdXRcIiksIGMuaTMyX2NvbnN0KDEpKSksXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcIml0SW5cIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJpdEluXCIpLCBjLmkzMl9jb25zdCgxKSkpLFxuICAgICAgICAgICAgICAgIGMuYnIoMClcbiAgICAgICAgICAgICkpLFxuICAgICAgICApO1xuXG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRMRU10b0MoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4ICsgXCJfTEVNdG9DXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicEluXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicE91dFwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IHRtcCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX2lzWmVyb0FmZmluZVwiLCBjLmdldExvY2FsKFwicEluXCIpKSxcbiAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3plcm9cIiwgYy5nZXRMb2NhbChcInBPdXRcIikpLFxuICAgICAgICAgICAgICAgICAgICAuLi5jLmkzMl9zdG9yZTgoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicE91dFwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDB4NDApXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgIC4uLmMucmV0KFtdKVxuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9mcm9tTW9udGdvbWVyeVwiLCBjLmdldExvY2FsKFwicEluXCIpLCB0bXApLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX19yZXZlcnNlQnl0ZXNcIiwgdG1wLCBjLmkzMl9jb25zdChuOCksIGMuZ2V0TG9jYWwoXCJwT3V0XCIpKSxcbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5pMzJfZXEoXG4gICAgICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3NpZ25cIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwSW5cIiksIGMuaTMyX2NvbnN0KG44KSkpLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdCgtMSlcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGMuaTMyX3N0b3JlOChcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBPdXRcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX29yKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfbG9hZDhfdShjLmdldExvY2FsKFwicE91dFwiKSksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdCgweDgwKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZExFTXRvVSgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXggKyBcIl9MRU10b1VcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwSW5cIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwT3V0XCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgcFRtcCA9IG1vZHVsZS5hbGxvYyhuOCoyKTtcbiAgICAgICAgY29uc3QgdG1wID0gYy5pMzJfY29uc3QocFRtcCk7XG4gICAgICAgIGNvbnN0IHRtcFggPSBjLmkzMl9jb25zdChwVG1wKTtcbiAgICAgICAgY29uc3QgdG1wWSA9IGMuaTMyX2NvbnN0KHBUbXAgKyBuOCk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfaXNaZXJvQWZmaW5lXCIsIGMuZ2V0TG9jYWwoXCJwSW5cIikpLFxuICAgICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5jYWxsKHByZWZpeCArIFwiX3plcm9BZmZpbmVcIiwgYy5nZXRMb2NhbChcInBPdXRcIikpLFxuICAgICAgICAgICAgICAgICAgICAuLi5jLnJldChbXSlcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICApLFxuXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfZnJvbU1vbnRnb21lcnlBZmZpbmVcIiwgYy5nZXRMb2NhbChcInBJblwiKSwgdG1wKSxcblxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX19yZXZlcnNlQnl0ZXNcIiwgdG1wWCwgYy5pMzJfY29uc3QobjgpLCBjLmdldExvY2FsKFwicE91dFwiKSksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfX3JldmVyc2VCeXRlc1wiLCB0bXBZLCBjLmkzMl9jb25zdChuOCksIGMuaTMyX2FkZChjLmdldExvY2FsKFwicE91dFwiKSwgYy5pMzJfY29uc3QobjgpKSksXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRVdG9MRU0oKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4ICsgXCJfVXRvTEVNXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicEluXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicE91dFwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IHBUbXAgPSBtb2R1bGUuYWxsb2MobjgqMik7XG4gICAgICAgIGNvbnN0IHRtcCA9IGMuaTMyX2NvbnN0KHBUbXApO1xuICAgICAgICBjb25zdCB0bXBYID0gYy5pMzJfY29uc3QocFRtcCk7XG4gICAgICAgIGNvbnN0IHRtcFkgPSBjLmkzMl9jb25zdChwVG1wICsgbjgpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5pMzJfYW5kKGMuaTMyX2xvYWQ4X3UoYy5nZXRMb2NhbChcInBJblwiKSksIGMuaTMyX2NvbnN0KDB4NDApKSxcbiAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChwcmVmaXggKyBcIl96ZXJvQWZmaW5lXCIsIGMuZ2V0TG9jYWwoXCJwT3V0XCIpKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5yZXQoW10pXG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9fcmV2ZXJzZUJ5dGVzXCIsIGMuZ2V0TG9jYWwoXCJwSW5cIiksIGMuaTMyX2NvbnN0KG44KSwgdG1wWCksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfX3JldmVyc2VCeXRlc1wiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInBJblwiKSwgYy5pMzJfY29uc3QobjgpKSwgYy5pMzJfY29uc3QobjgpLCB0bXBZKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl90b01vbnRnb21lcnlBZmZpbmVcIiwgdG1wLCAgYy5nZXRMb2NhbChcInBPdXRcIikpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRDdG9MRU0oKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4ICsgXCJfQ3RvTEVNXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicEluXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicE91dFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImZpcnN0Qnl0ZVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImdyZWF0ZXN0XCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgcFRtcCA9IG1vZHVsZS5hbGxvYyhuOCoyKTtcbiAgICAgICAgY29uc3QgdG1wWCA9IGMuaTMyX2NvbnN0KHBUbXApO1xuICAgICAgICBjb25zdCB0bXBZID0gYy5pMzJfY29uc3QocFRtcCArIG44KTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiZmlyc3RCeXRlXCIsIGMuaTMyX2xvYWQ4X3UoYy5nZXRMb2NhbChcInBJblwiKSkpLFxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmkzMl9hbmQoXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJmaXJzdEJ5dGVcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDB4NDApXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChwcmVmaXggKyBcIl96ZXJvQWZmaW5lXCIsIGMuZ2V0TG9jYWwoXCJwT3V0XCIpKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uYy5yZXQoW10pXG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgXCJncmVhdGVzdFwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FuZChcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImZpcnN0Qnl0ZVwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMHg4MClcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApLFxuXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9jb3B5XCIsIGMuZ2V0TG9jYWwoXCJwSW5cIiksIHRtcFkpLFxuICAgICAgICAgICAgYy5pMzJfc3RvcmU4KHRtcFksIGMuaTMyX2FuZChjLmdldExvY2FsKFwiZmlyc3RCeXRlXCIpLCBjLmkzMl9jb25zdCgweDNGKSkpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX19yZXZlcnNlQnl0ZXNcIiwgdG1wWSwgYy5pMzJfY29uc3QobjgpLCB0bXBYKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3RvTW9udGdvbWVyeVwiLCB0bXBYLCBjLmdldExvY2FsKFwicE91dFwiKSksXG5cbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX3NxdWFyZVwiLCBjLmdldExvY2FsKFwicE91dFwiKSwgdG1wWSksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9tdWxcIiwgYy5nZXRMb2NhbChcInBPdXRcIiksIHRtcFksICB0bXBZKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2FkZFwiLCB0bXBZLCBjLmkzMl9jb25zdChwQiksICB0bXBZKSxcblxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfc3FydFwiLCB0bXBZLCB0bXBZKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX25lZ1wiLCB0bXBZLCB0bXBYKSxcblxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmkzMl9lcShcbiAgICAgICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfc2lnblwiLCB0bXBZKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoLTEpXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiZ3JlYXRlc3RcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2NvcHlcIiwgdG1wWSwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwT3V0XCIpLCBjLmkzMl9jb25zdChuOCkpKSxcbiAgICAgICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfbmVnXCIsIHRtcFksIGMuaTMyX2FkZChjLmdldExvY2FsKFwicE91dFwiKSwgYy5pMzJfY29uc3QobjgpKSlcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJncmVhdGVzdFwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfbmVnXCIsIHRtcFksIGMuaTMyX2FkZChjLmdldExvY2FsKFwicE91dFwiKSwgYy5pMzJfY29uc3QobjgpKSksXG4gICAgICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXhGaWVsZCArIFwiX2NvcHlcIiwgdG1wWSwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwT3V0XCIpLCBjLmkzMl9jb25zdChuOCkpKVxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICApXG5cbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZEluQ3VydmVBZmZpbmUoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4ICsgXCJfaW5DdXJ2ZUFmZmluZVwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInBJblwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5zZXRSZXR1cm5UeXBlKFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgeCA9IGMuZ2V0TG9jYWwoXCJwSW5cIik7XG4gICAgICAgIGNvbnN0IHkgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInBJblwiKSwgYy5pMzJfY29uc3QobjgpKTtcblxuICAgICAgICBjb25zdCB5MiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuICAgICAgICBjb25zdCB4M2IgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9zcXVhcmVcIiwgeSwgeTIpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfc3F1YXJlXCIsIHgsIHgzYiksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9tdWxcIiwgeCwgeDNiLCB4M2IpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfYWRkXCIsIHgzYiwgYy5pMzJfY29uc3QocEIpLCB4M2IpLFxuXG4gICAgICAgICAgICBjLnJldChcbiAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl9lcVwiLCB5MiwgeDNiKVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkSW5DdXJ2ZSgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXggKyBcIl9pbkN1cnZlXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicEluXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLnNldFJldHVyblR5cGUoXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCBhdXggPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjgqMikpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl90b0FmZmluZVwiLCBjLmdldExvY2FsKFwicEluXCIpLCBhdXgpLFxuXG4gICAgICAgICAgICBjLnJldChcbiAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfaW5DdXJ2ZUFmZmluZVwiLCBhdXgpLFxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGJ1aWxkSXNaZXJvQWZmaW5lKCk7XG4gICAgYnVpbGRJc1plcm8oKTtcbiAgICBidWlsZFplcm9BZmZpbmUoKTtcbiAgICBidWlsZFplcm8oKTtcbiAgICBidWlsZENvcHlBZmZpbmUoKTtcbiAgICBidWlsZENvcHkoKTtcbiAgICBidWlsZFRvSmFjb2JpYW4oKTtcbiAgICBidWlsZEVxQWZmaW5lKCk7XG4gICAgYnVpbGRFcU1peGVkKCk7XG4gICAgYnVpbGRFcSgpO1xuICAgIGJ1aWxkRG91YmxlQWZmaW5lKCk7XG4gICAgYnVpbGREb3VibGUoKTtcbiAgICBidWlsZEFkZEFmZmluZSgpO1xuICAgIGJ1aWxkQWRkTWl4ZWQoKTtcbiAgICBidWlsZEFkZCgpO1xuICAgIGJ1aWxkTmVnQWZmaW5lKCk7XG4gICAgYnVpbGROZWcoKTtcbiAgICBidWlsZFN1YkFmZmluZSgpO1xuICAgIGJ1aWxkU3ViTWl4ZWQoKTtcbiAgICBidWlsZFN1YigpO1xuICAgIGJ1aWxkRnJvbU1vbnRnb21lcnlBZmZpbmUoKTtcbiAgICBidWlsZEZyb21Nb250Z29tZXJ5KCk7XG4gICAgYnVpbGRUb01vbnRnb21lcnlBZmZpbmUoKTtcbiAgICBidWlsZFRvTW9udGdvbWVyeSgpO1xuICAgIGJ1aWxkVG9BZmZpbmUoKTtcbiAgICBidWlsZEluQ3VydmVBZmZpbmUoKTtcbiAgICBidWlsZEluQ3VydmUoKTtcblxuICAgIGJ1aWxkQmF0Y2hUb0FmZmluZSgpO1xuXG4gICAgYnVpbGROb3JtYWxpemUoKTtcblxuXG4gICAgYnVpbGRSZXZlcnNlQnl0ZXMoKTtcblxuICAgIGJ1aWxkTEVNdG9VKCk7XG4gICAgYnVpbGRMRU10b0MoKTtcbiAgICBidWlsZFV0b0xFTSgpO1xuICAgIGJ1aWxkQ3RvTEVNKCk7XG5cbiAgICBidWlsZEJhdGNoQ29udmVydGlvbihtb2R1bGUsIHByZWZpeCArIFwiX2JhdGNoTEVNdG9VXCIsIHByZWZpeCArIFwiX0xFTXRvVVwiLCBuOCoyLCBuOCoyKTtcbiAgICBidWlsZEJhdGNoQ29udmVydGlvbihtb2R1bGUsIHByZWZpeCArIFwiX2JhdGNoTEVNdG9DXCIsIHByZWZpeCArIFwiX0xFTXRvQ1wiLCBuOCoyLCBuOCk7XG4gICAgYnVpbGRCYXRjaENvbnZlcnRpb24obW9kdWxlLCBwcmVmaXggKyBcIl9iYXRjaFV0b0xFTVwiLCBwcmVmaXggKyBcIl9VdG9MRU1cIiwgbjgqMiwgbjgqMik7XG4gICAgYnVpbGRCYXRjaENvbnZlcnRpb24obW9kdWxlLCBwcmVmaXggKyBcIl9iYXRjaEN0b0xFTVwiLCBwcmVmaXggKyBcIl9DdG9MRU1cIiwgbjgsIG44KjIsIHRydWUpO1xuXG4gICAgYnVpbGRCYXRjaENvbnZlcnRpb24obW9kdWxlLCBwcmVmaXggKyBcIl9iYXRjaFRvSmFjb2JpYW5cIiwgcHJlZml4ICsgXCJfdG9KYWNvYmlhblwiLCBuOCoyLCBuOCozLCB0cnVlKTtcblxuICAgIGJ1aWxkTXVsdGlleHAobW9kdWxlLCBwcmVmaXgsIHByZWZpeCArIFwiX211bHRpZXhwXCIsIHByZWZpeCArIFwiX2FkZFwiLCBuOCozKTtcbiAgICBidWlsZE11bHRpZXhwKG1vZHVsZSwgcHJlZml4LCBwcmVmaXggKyBcIl9tdWx0aWV4cEFmZmluZVwiLCBwcmVmaXggKyBcIl9hZGRNaXhlZFwiLCBuOCoyKTtcblxuICAgIC8qXG4gICAgYnVpbGRUaW1lc1NjYWxhcihcbiAgICAgICAgbW9kdWxlLFxuICAgICAgICBwcmVmaXggKyBcIl90aW1lc1NjYWxhck9sZFwiLFxuICAgICAgICBuOCozLFxuICAgICAgICBwcmVmaXggKyBcIl9hZGRcIixcbiAgICAgICAgcHJlZml4ICsgXCJfZG91YmxlXCIsXG4gICAgICAgIHByZWZpeCArIFwiX2NvcHlcIixcbiAgICAgICAgcHJlZml4ICsgXCJfemVyb1wiLFxuICAgICk7XG4gICAgKi9cbiAgICBidWlsZFRpbWVzU2NhbGFyTkFGKFxuICAgICAgICBtb2R1bGUsXG4gICAgICAgIHByZWZpeCArIFwiX3RpbWVzU2NhbGFyXCIsXG4gICAgICAgIG44KjMsXG4gICAgICAgIHByZWZpeCArIFwiX2FkZFwiLFxuICAgICAgICBwcmVmaXggKyBcIl9kb3VibGVcIixcbiAgICAgICAgcHJlZml4ICsgXCJfc3ViXCIsXG4gICAgICAgIHByZWZpeCArIFwiX2NvcHlcIixcbiAgICAgICAgcHJlZml4ICsgXCJfemVyb1wiXG4gICAgKTtcblxuICAgIGJ1aWxkVGltZXNTY2FsYXJOQUYoXG4gICAgICAgIG1vZHVsZSxcbiAgICAgICAgcHJlZml4ICsgXCJfdGltZXNTY2FsYXJBZmZpbmVcIixcbiAgICAgICAgbjgqMixcbiAgICAgICAgcHJlZml4ICsgXCJfYWRkTWl4ZWRcIixcbiAgICAgICAgcHJlZml4ICsgXCJfZG91YmxlXCIsXG4gICAgICAgIHByZWZpeCArIFwiX3N1Yk1peGVkXCIsXG4gICAgICAgIHByZWZpeCArIFwiX2NvcHlBZmZpbmVcIixcbiAgICAgICAgcHJlZml4ICsgXCJfemVyb1wiXG4gICAgKTtcblxuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9pc1plcm9cIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2lzWmVyb0FmZmluZVwiKTtcblxuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9lcVwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfZXFNaXhlZFwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfZXFBZmZpbmVcIik7XG5cbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfY29weVwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfY29weUFmZmluZVwiKTtcblxuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl96ZXJvXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl96ZXJvQWZmaW5lXCIpO1xuXG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2RvdWJsZVwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfZG91YmxlQWZmaW5lXCIpO1xuXG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2FkZFwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfYWRkTWl4ZWRcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2FkZEFmZmluZVwiKTtcblxuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9uZWdcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX25lZ0FmZmluZVwiKTtcblxuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9zdWJcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX3N1Yk1peGVkXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9zdWJBZmZpbmVcIik7XG5cbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfZnJvbU1vbnRnb21lcnlcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2Zyb21Nb250Z29tZXJ5QWZmaW5lXCIpO1xuXG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX3RvTW9udGdvbWVyeVwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfdG9Nb250Z29tZXJ5QWZmaW5lXCIpO1xuXG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX3RpbWVzU2NhbGFyXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl90aW1lc1NjYWxhckFmZmluZVwiKTtcblxuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9ub3JtYWxpemVcIik7XG5cbiAgICAvLyBDb252ZXJ0aW9uIGZ1bmN0aW9uc1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9MRU10b1VcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX0xFTXRvQ1wiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfVXRvTEVNXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9DdG9MRU1cIik7XG5cbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfYmF0Y2hMRU10b1VcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2JhdGNoTEVNdG9DXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9iYXRjaFV0b0xFTVwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfYmF0Y2hDdG9MRU1cIik7XG5cbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfdG9BZmZpbmVcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX3RvSmFjb2JpYW5cIik7XG5cbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfYmF0Y2hUb0FmZmluZVwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfYmF0Y2hUb0phY29iaWFuXCIpO1xuXG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2luQ3VydmVcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2luQ3VydmVBZmZpbmVcIik7XG5cbiAgICAvKlxuICAgIGJ1aWxkRzFNdWxTY2FsYXIobW9kdWxlLCB6cSk7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKFwiZzFNdWxTY2FsYXJcIik7XG4gICAgKi9cblxuICAgIHJldHVybiBwcmVmaXg7XG59O1xuXG4vKlxuICAgIENvcHlyaWdodCAyMDE5IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygd2FzbXNuYXJrIChXZWIgQXNzZW1ibHkgemtTbmFyayBQcm92ZXIpLlxuXG4gICAgd2FzbXNuYXJrIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICAgIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gICAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAgICAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgd2FzbXNuYXJrIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHdhc21zbmFyay4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbmNvbnN0IHsgaXNPZGQ6IGlzT2RkJDIsIG1vZEludjogbW9kSW52JDEsIG1vZFBvdyB9ID0gYmlnaW50O1xuY29uc3QgdXRpbHMkMiA9IHV0aWxzJDU7XG5cbnZhciBidWlsZF9mZnQgPSBmdW5jdGlvbiBidWlsZEZGVChtb2R1bGUsIHByZWZpeCwgZ1ByZWZpeCwgZlByZWZpeCwgb3BHdGltZXNGKSB7XG5cbiAgICBjb25zdCBuNjRmID0gbW9kdWxlLm1vZHVsZXNbZlByZWZpeF0ubjY0O1xuICAgIGNvbnN0IG44ZiA9IG42NGYqODtcblxuICAgIGNvbnN0IG42NGcgPSBtb2R1bGUubW9kdWxlc1tnUHJlZml4XS5uNjQ7XG4gICAgY29uc3QgbjhnID0gbjY0Zyo4O1xuXG4gICAgY29uc3QgcSA9IG1vZHVsZS5tb2R1bGVzW2ZQcmVmaXhdLnE7XG5cbiAgICBsZXQgcmVtID0gcSAtIDFuO1xuICAgIGxldCBtYXhCaXRzID0gMDtcbiAgICB3aGlsZSAoIWlzT2RkJDIocmVtKSkge1xuICAgICAgICBtYXhCaXRzICsrO1xuICAgICAgICByZW0gPSByZW0gPj4gMW47XG4gICAgfVxuXG4gICAgbGV0IG5yID0gMm47XG5cbiAgICB3aGlsZSAoIG1vZFBvdyhuciwgcSA+PiAxbiwgcSkgPT09IDFuICkgbnIgPSBuciArIDFuO1xuXG4gICAgLy8gY29uc29sZS5sb2cobnIpO1xuXG4gICAgY29uc3QgdyA9IG5ldyBBcnJheShtYXhCaXRzKzEpO1xuICAgIHdbbWF4Qml0c10gPSBtb2RQb3cobnIsIHJlbSwgcSk7XG5cbiAgICBsZXQgbj1tYXhCaXRzLTE7XG4gICAgd2hpbGUgKG4+PTApIHtcbiAgICAgICAgd1tuXSA9IG1vZFBvdyh3W24rMV0sIDJuLCBxKTtcbiAgICAgICAgbi0tO1xuICAgIH1cblxuICAgIGNvbnN0IGJ5dGVzID0gW107XG4gICAgY29uc3QgUiA9ICgxbiA8PCBCaWdJbnQobjhmKjgpKSAlIHE7XG5cbiAgICBmb3IgKGxldCBpPTA7IGk8dy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBtID0gd1tpXSAqIFIgJSBxO1xuICAgICAgICBieXRlcy5wdXNoKC4uLnV0aWxzJDIuYmlnSW50MkJ5dGVzTEUobSwgbjhmKSk7XG4gICAgfVxuXG4gICAgY29uc3QgUk9PVHMgPSBtb2R1bGUuYWxsb2MoYnl0ZXMpO1xuXG4gICAgY29uc3QgaTIgPSBuZXcgQXJyYXkobWF4Qml0cysxKTtcbiAgICBpMlswXSA9IDFuO1xuXG4gICAgZm9yIChsZXQgaT0xOyBpPD1tYXhCaXRzOyBpKyspIHtcbiAgICAgICAgaTJbaV0gPSBpMltpLTFdICogMm47XG4gICAgfVxuXG4gICAgY29uc3QgYnl0ZXNpMiA9W107XG4gICAgZm9yIChsZXQgaT0wOyBpPD1tYXhCaXRzOyBpKyspIHtcbiAgICAgICAgY29uc3QgbSA9IG1vZEludiQxKGkyW2ldLCBxKSAqIFIgJSBxO1xuICAgICAgICBieXRlc2kyLnB1c2goLi4udXRpbHMkMi5iaWdJbnQyQnl0ZXNMRShtLCBuOGYpKTtcbiAgICB9XG5cbiAgICBjb25zdCBJTlYyID0gbW9kdWxlLmFsbG9jKGJ5dGVzaTIpO1xuXG4gICAgY29uc3Qgc2hpZnQgPSBtb2RQb3cobnIsIDJuLCBxKTtcbiAgICBjb25zdCBieXRlc1NoaWZ0VG9TbWFsbE0gPVtdO1xuICAgIGNvbnN0IGJ5dGVzU0NvbnN0ID1bXTtcbiAgICBmb3IgKGxldCBpPTA7IGk8PW1heEJpdHM7IGkrKykge1xuICAgICAgICBjb25zdCBzaGlmdFRvU21hbGxNID0gbW9kUG93KHNoaWZ0LCAybiAqKiBCaWdJbnQoaSksIHEpO1xuICAgICAgICBjb25zdCBzQ29uc3QgPSBtb2RJbnYkMShxICsgMW4gLSBzaGlmdFRvU21hbGxNLCBxKTtcbiAgICAgICAgYnl0ZXNTaGlmdFRvU21hbGxNLnB1c2goLi4udXRpbHMkMi5iaWdJbnQyQnl0ZXNMRShzaGlmdFRvU21hbGxNICogUiAlIHEsIG44ZikpO1xuICAgICAgICBieXRlc1NDb25zdC5wdXNoKC4uLnV0aWxzJDIuYmlnSW50MkJ5dGVzTEUoc0NvbnN0ICogUiAlIHEsIG44ZikpO1xuICAgIH1cblxuICAgIGNvbnN0IFNISUZUX1RPX00gPSBtb2R1bGUuYWxsb2MoIGJ5dGVzU2hpZnRUb1NtYWxsTSAgKTtcbiAgICBjb25zdCBTQ09OU1QgPSBtb2R1bGUuYWxsb2MoIGJ5dGVzU0NvbnN0ICApO1xuXG4gICAgZnVuY3Rpb24gcmV2KHgpIHtcbiAgICAgICAgbGV0IHI9MDtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPDg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHggJiAoMSA8PCBpKSkge1xuICAgICAgICAgICAgICAgIHIgPSByIHwgKDB4ODAgPj4gaSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHI7XG4gICAgfVxuXG4gICAgY29uc3QgcnRhYmxlID0gQXJyYXkoMjU2KTtcbiAgICBmb3IgKGxldCBpPTA7IGk8MjU2OyBpKyspIHtcbiAgICAgICAgcnRhYmxlW2ldID0gcmV2KGkpO1xuICAgIH1cblxuICAgIGNvbnN0IFJFVlRBQkxFID0gbW9kdWxlLmFsbG9jKHJ0YWJsZSk7XG5cblxuICAgIGZ1bmN0aW9uIGJ1aWxkTG9nMigpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrXCJfX2xvZzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJuXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLnNldFJldHVyblR5cGUoXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJiaXRzXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiYXV4XCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcbiAgICAgICAgICAgICAgICBcImF1eFwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX3Nocl91KFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiblwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMSlcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICAgIGYuYWRkQ29kZShjLnNldExvY2FsKFwiYml0c1wiLCBjLmkzMl9jb25zdCgwKSkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShjLmJsb2NrKGMubG9vcChcbiAgICAgICAgICAgIGMuYnJfaWYoXG4gICAgICAgICAgICAgICAgMSxcbiAgICAgICAgICAgICAgICBjLmkzMl9lcXooYy5nZXRMb2NhbChcImF1eFwiKSlcbiAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgXCJhdXhcIixcbiAgICAgICAgICAgICAgICBjLmkzMl9zaHJfdShcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImF1eFwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMSlcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApLFxuXG4gICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgIFwiYml0c1wiLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImJpdHNcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDEpXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgYy5icigwKVxuICAgICAgICApKSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKGMuaWYoXG4gICAgICAgICAgICBjLmkzMl9uZShcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiblwiKSxcbiAgICAgICAgICAgICAgICBjLmkzMl9zaGwoXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDEpLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiYml0c1wiKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLnVucmVhY2hhYmxlKClcbiAgICAgICAgKSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKGMuaWYoXG4gICAgICAgICAgICBjLmkzMl9ndF91KFxuICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJiaXRzXCIpLFxuICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KG1heEJpdHMpXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy51bnJlYWNoYWJsZSgpXG4gICAgICAgICkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShjLmdldExvY2FsKFwiYml0c1wiKSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRGRlQoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX2ZmdFwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInB4XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiblwiLCBcImkzMlwiKTtcblxuICAgICAgICBmLmFkZExvY2FsKFwiYml0c1wiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IE9uZSA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOGYpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgIFwiYml0c1wiLFxuICAgICAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgcHJlZml4ICsgXCJfX2xvZzJcIixcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIm5cIilcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5jYWxsKGZQcmVmaXggKyBcIl9vbmVcIiwgT25lKSxcbiAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICBwcmVmaXgrXCJfcmF3ZmZ0XCIsXG4gICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInB4XCIpLFxuICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJiaXRzXCIpLFxuICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDApLFxuICAgICAgICAgICAgICAgIE9uZVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuXG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRJRkZUKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9pZmZ0XCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicHhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJuXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiYml0c1wiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcInBJbnYyXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcbiAgICAgICAgICAgICAgICBcImJpdHNcIixcbiAgICAgICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgICAgIHByZWZpeCArIFwiX19sb2cyXCIsXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJuXCIpXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgXCJwSW52MlwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoSU5WMiksXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX211bChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJiaXRzXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QobjhmKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgIHByZWZpeCtcIl9yYXdmZnRcIixcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicHhcIiksXG4gICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImJpdHNcIiksXG4gICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMSksXG4gICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBJbnYyXCIpXG4gICAgICAgICAgICApLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkUmF3RkZUKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9yYXdmZnRcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJweFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcImJpdHNcIiwgXCJpMzJcIik7IC8vIDIgcG93ZXJcbiAgICAgICAgZi5hZGRQYXJhbShcInJldmVyc2VcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJtdWxGYWN0b3JcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgZi5hZGRMb2NhbChcInNcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJrXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwialwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcIm1cIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJtZGl2MlwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcIm5cIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJwd21cIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJpZHgxXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiaWR4MlwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IFcgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjhmKSk7XG4gICAgICAgIGNvbnN0IFQgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjhnKSk7XG4gICAgICAgIGNvbnN0IFUgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjhnKSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX19yZXZlcnNlUGVybXV0YXRpb25cIiwgYy5nZXRMb2NhbChcInB4XCIpLCBjLmdldExvY2FsKFwiYml0c1wiKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiblwiLCBjLmkzMl9zaGwoYy5pMzJfY29uc3QoMSksIGMuZ2V0TG9jYWwoXCJiaXRzXCIpKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwic1wiLCBjLmkzMl9jb25zdCgxKSksXG4gICAgICAgICAgICBjLmJsb2NrKGMubG9vcChcbiAgICAgICAgICAgICAgICBjLmJyX2lmKFxuICAgICAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9ndF91KFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInNcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiYml0c1wiKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwibVwiLCBjLmkzMl9zaGwoYy5pMzJfY29uc3QoMSksIGMuZ2V0TG9jYWwoXCJzXCIpKSksXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcInB3bVwiLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9hZGQoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdChST09UcyksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9tdWwoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInNcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QobjhmKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwia1wiLCBjLmkzMl9jb25zdCgwKSksXG4gICAgICAgICAgICAgICAgYy5ibG9jayhjLmxvb3AoXG4gICAgICAgICAgICAgICAgICAgIGMuYnJfaWYoXG4gICAgICAgICAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfZ2VfdShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwia1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiblwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgICAgIGMuY2FsbChmUHJlZml4ICsgXCJfb25lXCIsIFcpLFxuXG4gICAgICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJtZGl2MlwiLCBjLmkzMl9zaHJfdShjLmdldExvY2FsKFwibVwiKSwgYy5pMzJfY29uc3QoMSkpICksXG4gICAgICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJqXCIsIGMuaTMyX2NvbnN0KDApKSxcbiAgICAgICAgICAgICAgICAgICAgYy5ibG9jayhjLmxvb3AoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmJyX2lmKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfZ2VfdShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImpcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJtZGl2MlwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJpZHgxXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicHhcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX211bChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwia1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwialwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KG44ZylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJpZHgyXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaWR4MVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfbXVsKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIm1kaXYyXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QobjhnKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wR3RpbWVzRixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaWR4MlwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBXLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRcbiAgICAgICAgICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnUHJlZml4ICsgXCJfY29weVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpZHgxXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVcbiAgICAgICAgICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnUHJlZml4ICsgXCJfYWRkXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgVSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBULFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpZHgxXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdQcmVmaXggKyBcIl9zdWJcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBVLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImlkeDJcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZlByZWZpeCArIFwiX211bFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInB3bVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBXLFxuICAgICAgICAgICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcImpcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJqXCIpLCBjLmkzMl9jb25zdCgxKSkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5icigwKVxuICAgICAgICAgICAgICAgICAgICApKSxcblxuICAgICAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwia1wiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcImtcIiksIGMuZ2V0TG9jYWwoXCJtXCIpKSksXG4gICAgICAgICAgICAgICAgICAgIGMuYnIoMClcbiAgICAgICAgICAgICAgICApKSxcblxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJzXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwic1wiKSwgYy5pMzJfY29uc3QoMSkpKSxcbiAgICAgICAgICAgICAgICBjLmJyKDApXG4gICAgICAgICAgICApKSxcbiAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICBwcmVmaXggKyBcIl9fZmZ0RmluYWxcIixcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicHhcIiksXG4gICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImJpdHNcIiksXG4gICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInJldmVyc2VcIiksXG4gICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIm11bEZhY3RvclwiKVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gYnVpbGRGaW5hbEludmVyc2UoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX19mZnRGaW5hbFwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInB4XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiYml0c1wiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJldmVyc2VcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJtdWxGYWN0b3JcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJuXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwibmRpdjJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJwSW52MlwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImlcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJtYXNrXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiaWR4MVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImlkeDJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCBUID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44ZykpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5pMzJfYW5kKFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9lcXooYy5nZXRMb2NhbChcInJldmVyc2VcIikpLFxuICAgICAgICAgICAgICAgICAgICBjLmNhbGwoZlByZWZpeCArIFwiX2lzT25lXCIsIGMuZ2V0TG9jYWwoXCJtdWxGYWN0b3JcIikpXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLnJldChbXSlcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiblwiLCBjLmkzMl9zaGwoIGMuaTMyX2NvbnN0KDEpLCBjLmdldExvY2FsKFwiYml0c1wiKSkpLFxuXG4gICAgICAgICAgICBjLnNldExvY2FsKFwibWFza1wiLCBjLmkzMl9zdWIoIGMuZ2V0TG9jYWwoXCJuXCIpICwgYy5pMzJfY29uc3QoMSkpKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpXCIsIGMuaTMyX2NvbnN0KDEpKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgXCJuZGl2MlwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX3Nocl91KFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiblwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMSlcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5ibG9jayhjLmxvb3AoXG4gICAgICAgICAgICAgICAgYy5icl9pZihcbiAgICAgICAgICAgICAgICAgICAgMSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfZ2VfdShcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIm5kaXYyXCIpXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcImlkeDFcIixcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInB4XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfbXVsKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KG44ZylcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaWR4MlwiLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9hZGQoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicHhcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9tdWwoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfc3ViKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiblwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImlcIilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KG44ZylcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicmV2ZXJzZVwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FsbChmUHJlZml4ICsgXCJfaXNPbmVcIiwgYy5nZXRMb2NhbChcIm11bEZhY3RvclwiKSksXG4gICAgICAgICAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uYy5jYWxsKGdQcmVmaXggKyBcIl9jb3B5XCIsIGMuZ2V0TG9jYWwoXCJpZHgxXCIpLCBUKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwoZ1ByZWZpeCArIFwiX2NvcHlcIiwgYy5nZXRMb2NhbChcImlkeDJcIikgLCBjLmdldExvY2FsKFwiaWR4MVwiKSApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChnUHJlZml4ICsgXCJfY29weVwiLCBUICwgYy5nZXRMb2NhbChcImlkeDJcIikpLFxuICAgICAgICAgICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwoZ1ByZWZpeCArIFwiX2NvcHlcIiwgYy5nZXRMb2NhbChcImlkeDFcIiksIFQpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChvcEd0aW1lc0YgLCBjLmdldExvY2FsKFwiaWR4MlwiKSAsIGMuZ2V0TG9jYWwoXCJtdWxGYWN0b3JcIiksIGMuZ2V0TG9jYWwoXCJpZHgxXCIpICksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uYy5jYWxsKG9wR3RpbWVzRiAsIFQgLCBjLmdldExvY2FsKFwibXVsRmFjdG9yXCIpLCBjLmdldExvY2FsKFwiaWR4MlwiKSksXG4gICAgICAgICAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmNhbGwoZlByZWZpeCArIFwiX2lzT25lXCIsIGMuZ2V0TG9jYWwoXCJtdWxGYWN0b3JcIikpLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIERvIG5vdGhpbmcgKEl0IHNob3VsZCBub3QgYmUgaGVyZSlcbiAgICAgICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uYy5jYWxsKG9wR3RpbWVzRiAsIGMuZ2V0TG9jYWwoXCJpZHgxXCIpICwgYy5nZXRMb2NhbChcIm11bEZhY3RvclwiKSwgYy5nZXRMb2NhbChcImlkeDFcIikgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwob3BHdGltZXNGICwgYy5nZXRMb2NhbChcImlkeDJcIikgLCBjLmdldExvY2FsKFwibXVsRmFjdG9yXCIpLCBjLmdldExvY2FsKFwiaWR4MlwiKSksXG4gICAgICAgICAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwiaVwiKSwgYy5pMzJfY29uc3QoMSkpKSxcblxuICAgICAgICAgICAgICAgIGMuYnIoMClcbiAgICAgICAgICAgICkpLFxuXG4gICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgIGMuY2FsbChmUHJlZml4ICsgXCJfaXNPbmVcIiwgYy5nZXRMb2NhbChcIm11bEZhY3RvclwiKSksXG4gICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAvLyBEbyBub3RoaW5nIChJdCBzaG91bGQgbm90IGJlIGhlcmUpXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChvcEd0aW1lc0YsIGMuZ2V0TG9jYWwoXCJweFwiKSAsIGMuZ2V0TG9jYWwoXCJtdWxGYWN0b3JcIiksIGMuZ2V0TG9jYWwoXCJweFwiKSksXG4gICAgICAgICAgICAgICAgICAgIC4uLmMuc2V0TG9jYWwoXCJpZHgyXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9hZGQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInB4XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX211bChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIm5kaXYyXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdChuOGcpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwob3BHdGltZXNGLCBjLmdldExvY2FsKFwiaWR4MlwiKSxjLmdldExvY2FsKFwibXVsRmFjdG9yXCIpLCBjLmdldExvY2FsKFwiaWR4MlwiKSlcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRSZXZlcnNlUGVybXV0YXRpb24oKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX19yZXZlcnNlUGVybXV0YXRpb25cIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJweFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcImJpdHNcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJuXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiaVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcInJpXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiaWR4MVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImlkeDJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCBUID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44ZykpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJuXCIsIGMuaTMyX3NobCggYy5pMzJfY29uc3QoMSksIGMuZ2V0TG9jYWwoXCJiaXRzXCIpKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiaVwiLCBjLmkzMl9jb25zdCgwKSksXG4gICAgICAgICAgICBjLmJsb2NrKGMubG9vcChcbiAgICAgICAgICAgICAgICBjLmJyX2lmKFxuICAgICAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9lcShcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIm5cIilcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaWR4MVwiLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9hZGQoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicHhcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9tdWwoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImlcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QobjhnKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJyaVwiLCBjLmNhbGwocHJlZml4ICsgXCJfX3JldlwiLCBjLmdldExvY2FsKFwiaVwiKSwgYy5nZXRMb2NhbChcImJpdHNcIikpKSxcblxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpZHgyXCIsXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJweFwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX211bChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicmlcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QobjhnKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2x0X3UoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJyaVwiKVxuICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwoZ1ByZWZpeCArIFwiX2NvcHlcIiwgYy5nZXRMb2NhbChcImlkeDFcIiksIFQpLFxuICAgICAgICAgICAgICAgICAgICAgICAgLi4uYy5jYWxsKGdQcmVmaXggKyBcIl9jb3B5XCIsIGMuZ2V0TG9jYWwoXCJpZHgyXCIpICwgYy5nZXRMb2NhbChcImlkeDFcIikpLFxuICAgICAgICAgICAgICAgICAgICAgICAgLi4uYy5jYWxsKGdQcmVmaXggKyBcIl9jb3B5XCIsIFQgLCBjLmdldExvY2FsKFwiaWR4MlwiKSlcbiAgICAgICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaVwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcImlcIiksIGMuaTMyX2NvbnN0KDEpKSksXG5cbiAgICAgICAgICAgICAgICBjLmJyKDApXG4gICAgICAgICAgICApKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkUmV2KCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9fcmV2XCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcImJpdHNcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuc2V0UmV0dXJuVHlwZShcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuaTMyX3JvdGwoXG4gICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9hZGQoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9zaGwoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfbG9hZDhfdShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfYW5kKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInhcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdCgweEZGKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRVZUQUJMRSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMjQpXG4gICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfc2hsKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2xvYWQ4X3UoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2FuZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX3Nocl91KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJ4XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMHhGRilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUkVWVEFCTEUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDE2KVxuICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfc2hsKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2xvYWQ4X3UoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2FuZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX3Nocl91KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJ4XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDE2KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDB4RkYpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFVlRBQkxFLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdCg4KVxuICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2xvYWQ4X3UoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfYW5kKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9zaHJfdShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJ4XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMjQpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KDB4RkYpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRVZUQUJMRSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAwXG4gICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiYml0c1wiKVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gYnVpbGRGRlRKb2luKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9mZnRKb2luXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicEJ1ZmYxXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicEJ1ZmYyXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiblwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcImZpcnN0XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiaW5jXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiaWR4MVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImlkeDJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJpXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgVyA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOGYpKTtcbiAgICAgICAgY29uc3QgVCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOGcpKTtcbiAgICAgICAgY29uc3QgVSA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOGcpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwoIGZQcmVmaXggKyBcIl9jb3B5XCIsIGMuZ2V0TG9jYWwoXCJmaXJzdFwiKSwgVyksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiaVwiLCBjLmkzMl9jb25zdCgwKSksXG4gICAgICAgICAgICBjLmJsb2NrKGMubG9vcChcbiAgICAgICAgICAgICAgICBjLmJyX2lmKFxuICAgICAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9lcShcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIm5cIilcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgICAgICBcImlkeDFcIixcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBCdWZmMVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX211bChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdChuOGcpXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcbiAgICAgICAgICAgICAgICAgICAgXCJpZHgyXCIsXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwQnVmZjJcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9tdWwoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImlcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QobjhnKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgb3BHdGltZXNGLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaWR4MlwiKSxcbiAgICAgICAgICAgICAgICAgICAgVyxcbiAgICAgICAgICAgICAgICAgICAgVFxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgICAgIGdQcmVmaXggKyBcIl9jb3B5XCIsXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpZHgxXCIpLFxuICAgICAgICAgICAgICAgICAgICBVXG4gICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgZ1ByZWZpeCArIFwiX2FkZFwiLFxuICAgICAgICAgICAgICAgICAgICBVLFxuICAgICAgICAgICAgICAgICAgICBULFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaWR4MVwiKSxcbiAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgICAgICBnUHJlZml4ICsgXCJfc3ViXCIsXG4gICAgICAgICAgICAgICAgICAgIFUsXG4gICAgICAgICAgICAgICAgICAgIFQsXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpZHgyXCIpLFxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgICAgIGZQcmVmaXggKyBcIl9tdWxcIixcbiAgICAgICAgICAgICAgICAgICAgVyxcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImluY1wiKSxcbiAgICAgICAgICAgICAgICAgICAgVyxcbiAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcImlcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJpXCIpLCBjLmkzMl9jb25zdCgxKSkpLFxuICAgICAgICAgICAgICAgIGMuYnIoMClcbiAgICAgICAgICAgICkpXG4gICAgICAgICk7XG4gICAgfVxuXG5cbiAgICBmdW5jdGlvbiBidWlsZEZGVEpvaW5FeHQoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX2ZmdEpvaW5FeHRcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwQnVmZjFcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwQnVmZjJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJuXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiZmlyc3RcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJpbmNcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ0b3RhbEJpdHNcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJpZHgxXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiaWR4MlwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImlcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJwU2hpZnRUb01cIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCBXID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44ZikpO1xuICAgICAgICBjb25zdCBVID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44ZykpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcblxuICAgICAgICAgICAgYy5zZXRMb2NhbChcInBTaGlmdFRvTVwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoU0hJRlRfVE9fTSksXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX211bChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJ0b3RhbEJpdHNcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdChuOGYpXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApLFxuXG5cbiAgICAgICAgICAgIGMuY2FsbCggZlByZWZpeCArIFwiX2NvcHlcIiwgYy5nZXRMb2NhbChcImZpcnN0XCIpLCBXKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpXCIsIGMuaTMyX2NvbnN0KDApKSxcbiAgICAgICAgICAgIGMuYmxvY2soYy5sb29wKFxuICAgICAgICAgICAgICAgIGMuYnJfaWYoXG4gICAgICAgICAgICAgICAgICAgIDEsXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2VxKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImlcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiblwiKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgICAgIFwiaWR4MVwiLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9hZGQoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicEJ1ZmYxXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfbXVsKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KG44ZylcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgICAgICBcImlkeDJcIixcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBCdWZmMlwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX211bChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdChuOGcpXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgICAgICBnUHJlZml4ICsgXCJfYWRkXCIsXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpZHgxXCIpLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaWR4MlwiKSxcbiAgICAgICAgICAgICAgICAgICAgVVxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgICAgIG9wR3RpbWVzRixcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImlkeDJcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwU2hpZnRUb01cIiksXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpZHgyXCIpXG4gICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgZ1ByZWZpeCArIFwiX2FkZFwiLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaWR4MVwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImlkeDJcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpZHgyXCIpXG4gICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgb3BHdGltZXNGLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaWR4MlwiKSxcbiAgICAgICAgICAgICAgICAgICAgVyxcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImlkeDJcIiksXG4gICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgZ1ByZWZpeCArIFwiX2NvcHlcIixcbiAgICAgICAgICAgICAgICAgICAgVSxcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImlkeDFcIilcbiAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgICAgICBmUHJlZml4ICsgXCJfbXVsXCIsXG4gICAgICAgICAgICAgICAgICAgIFcsXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpbmNcIiksXG4gICAgICAgICAgICAgICAgICAgIFdcbiAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcImlcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJpXCIpLCBjLmkzMl9jb25zdCgxKSkpLFxuICAgICAgICAgICAgICAgIGMuYnIoMClcbiAgICAgICAgICAgICkpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRGRlRKb2luRXh0SW52KCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl9mZnRKb2luRXh0SW52XCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicEJ1ZmYxXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicEJ1ZmYyXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiblwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcImZpcnN0XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiaW5jXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwidG90YWxCaXRzXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiaWR4MVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImlkeDJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJpXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwicFNoaWZ0VG9NXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwicFNDb25zdFwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IFcgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjhmKSk7XG4gICAgICAgIGNvbnN0IFUgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MobjhnKSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuXG4gICAgICAgICAgICBjLnNldExvY2FsKFwicFNoaWZ0VG9NXCIsXG4gICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdChTSElGVF9UT19NKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfbXVsKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInRvdGFsQml0c1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KG44ZilcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwicFNDb25zdFwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoU0NPTlNUKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfbXVsKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInRvdGFsQml0c1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KG44ZilcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICksXG5cblxuICAgICAgICAgICAgYy5jYWxsKCBmUHJlZml4ICsgXCJfY29weVwiLCBjLmdldExvY2FsKFwiZmlyc3RcIiksIFcpLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcImlcIiwgYy5pMzJfY29uc3QoMCkpLFxuICAgICAgICAgICAgYy5ibG9jayhjLmxvb3AoXG4gICAgICAgICAgICAgICAgYy5icl9pZihcbiAgICAgICAgICAgICAgICAgICAgMSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfZXEoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJuXCIpXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcbiAgICAgICAgICAgICAgICAgICAgXCJpZHgxXCIsXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwQnVmZjFcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9tdWwoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImlcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QobjhnKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgICAgIFwiaWR4MlwiLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9hZGQoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicEJ1ZmYyXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfbXVsKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KG44ZylcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgICAgIG9wR3RpbWVzRixcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImlkeDJcIiksXG4gICAgICAgICAgICAgICAgICAgIFcsXG4gICAgICAgICAgICAgICAgICAgIFVcbiAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgICAgICBnUHJlZml4ICsgXCJfc3ViXCIsXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpZHgxXCIpLFxuICAgICAgICAgICAgICAgICAgICBVLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaWR4MlwiKSxcbiAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgICAgICBvcEd0aW1lc0YsXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpZHgyXCIpLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicFNDb25zdFwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImlkeDJcIilcbiAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgICAgICBvcEd0aW1lc0YsXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpZHgxXCIpLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicFNoaWZ0VG9NXCIpLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaWR4MVwiKVxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgICAgIGdQcmVmaXggKyBcIl9zdWJcIixcbiAgICAgICAgICAgICAgICAgICAgVSxcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImlkeDFcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpZHgxXCIpXG4gICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgb3BHdGltZXNGLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaWR4MVwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBTQ29uc3RcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpZHgxXCIpXG4gICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgZlByZWZpeCArIFwiX211bFwiLFxuICAgICAgICAgICAgICAgICAgICBXLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaW5jXCIpLFxuICAgICAgICAgICAgICAgICAgICBXXG4gICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwiaVwiKSwgYy5pMzJfY29uc3QoMSkpKSxcbiAgICAgICAgICAgICAgICBjLmJyKDApXG4gICAgICAgICAgICApKVxuICAgICAgICApO1xuICAgIH1cblxuXG5cbiAgICBmdW5jdGlvbiBidWlsZFByZXBhcmVMYWdyYW5nZUV2YWx1YXRpb24oKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX3ByZXBhcmVMYWdyYW5nZUV2YWx1YXRpb25cIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwQnVmZjFcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwQnVmZjJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJuXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiZmlyc3RcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJpbmNcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ0b3RhbEJpdHNcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJpZHgxXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiaWR4MlwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImlcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJwU2hpZnRUb01cIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJwU0NvbnN0XCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgVyA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOGYpKTtcbiAgICAgICAgY29uc3QgVSA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOGcpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG5cbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJwU2hpZnRUb01cIixcbiAgICAgICAgICAgICAgICBjLmkzMl9hZGQoXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KFNISUZUX1RPX00pLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9tdWwoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwidG90YWxCaXRzXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QobjhmKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJwU0NvbnN0XCIsXG4gICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdChTQ09OU1QpLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9tdWwoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwidG90YWxCaXRzXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QobjhmKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcblxuXG4gICAgICAgICAgICBjLmNhbGwoIGZQcmVmaXggKyBcIl9jb3B5XCIsIGMuZ2V0TG9jYWwoXCJmaXJzdFwiKSwgVyksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiaVwiLCBjLmkzMl9jb25zdCgwKSksXG4gICAgICAgICAgICBjLmJsb2NrKGMubG9vcChcbiAgICAgICAgICAgICAgICBjLmJyX2lmKFxuICAgICAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9lcShcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIm5cIilcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgICAgICBcImlkeDFcIixcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBCdWZmMVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX211bChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdChuOGcpXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcbiAgICAgICAgICAgICAgICAgICAgXCJpZHgyXCIsXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwQnVmZjJcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9tdWwoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImlcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QobjhnKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKSxcblxuXG4gICAgICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgICAgICBvcEd0aW1lc0YsXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpZHgxXCIpLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicFNoaWZ0VG9NXCIpLFxuICAgICAgICAgICAgICAgICAgICBVXG4gICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgZ1ByZWZpeCArIFwiX3N1YlwiLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaWR4MlwiKSxcbiAgICAgICAgICAgICAgICAgICAgVSxcbiAgICAgICAgICAgICAgICAgICAgVVxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgICAgIGdQcmVmaXggKyBcIl9zdWJcIixcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImlkeDFcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpZHgyXCIpLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaWR4MlwiKSxcbiAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgICAgICBvcEd0aW1lc0YsXG4gICAgICAgICAgICAgICAgICAgIFUsXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwU0NvbnN0XCIpLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaWR4MVwiKSxcbiAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgICAgICBvcEd0aW1lc0YsXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpZHgyXCIpLFxuICAgICAgICAgICAgICAgICAgICBXLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaWR4MlwiKSxcbiAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgICAgICBmUHJlZml4ICsgXCJfbXVsXCIsXG4gICAgICAgICAgICAgICAgICAgIFcsXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpbmNcIiksXG4gICAgICAgICAgICAgICAgICAgIFdcbiAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcImlcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJpXCIpLCBjLmkzMl9jb25zdCgxKSkpLFxuICAgICAgICAgICAgICAgIGMuYnIoMClcbiAgICAgICAgICAgICkpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRGRlRNaXgoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX2ZmdE1peFwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInBCdWZmXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiblwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcImV4cFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcIm5Hcm91cHNcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJuUGVyR3JvdXBcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJuUGVyR3JvdXBEaXYyXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwicGFpck9mZnNldFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImlkeDFcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJpZHgyXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiaVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImpcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJwd21cIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCBXID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44ZikpO1xuICAgICAgICBjb25zdCBUID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44ZykpO1xuICAgICAgICBjb25zdCBVID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44ZykpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJuUGVyR3JvdXBcIiwgYy5pMzJfc2hsKGMuaTMyX2NvbnN0KDEpLCBjLmdldExvY2FsKFwiZXhwXCIpKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiblBlckdyb3VwRGl2MlwiLCBjLmkzMl9zaHJfdShjLmdldExvY2FsKFwiblBlckdyb3VwXCIpLCBjLmkzMl9jb25zdCgxKSkpLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcIm5Hcm91cHNcIiwgYy5pMzJfc2hyX3UoYy5nZXRMb2NhbChcIm5cIiksIGMuZ2V0TG9jYWwoXCJleHBcIikpKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJwYWlyT2Zmc2V0XCIsIGMuaTMyX211bChjLmdldExvY2FsKFwiblBlckdyb3VwRGl2MlwiKSwgYy5pMzJfY29uc3QobjhnKSkpLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcInB3bVwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoUk9PVHMpLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9tdWwoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiZXhwXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QobjhmKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpXCIsIGMuaTMyX2NvbnN0KDApKSxcbiAgICAgICAgICAgIGMuYmxvY2soYy5sb29wKFxuICAgICAgICAgICAgICAgIGMuYnJfaWYoXG4gICAgICAgICAgICAgICAgICAgIDEsXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2VxKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImlcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwibkdyb3Vwc1wiKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLmNhbGwoIGZQcmVmaXggKyBcIl9vbmVcIiwgVyksXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcImpcIiwgYy5pMzJfY29uc3QoMCkpLFxuICAgICAgICAgICAgICAgIGMuYmxvY2soYy5sb29wKFxuICAgICAgICAgICAgICAgICAgICBjLmJyX2lmKFxuICAgICAgICAgICAgICAgICAgICAgICAgMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2VxKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJqXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJuUGVyR3JvdXBEaXYyXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiaWR4MVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwQnVmZlwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9tdWwoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX211bChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiblBlckdyb3VwXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImpcIilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QobjhnKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgICAgICAgICAgXCJpZHgyXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9hZGQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImlkeDFcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBhaXJPZmZzZXRcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgICAgICAgICBvcEd0aW1lc0YsXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaWR4MlwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFcsXG4gICAgICAgICAgICAgICAgICAgICAgICBUXG4gICAgICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgICAgICAgICAgZ1ByZWZpeCArIFwiX2NvcHlcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpZHgxXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgVVxuICAgICAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgICAgIGdQcmVmaXggKyBcIl9hZGRcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIFUsXG4gICAgICAgICAgICAgICAgICAgICAgICBULFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImlkeDFcIiksXG4gICAgICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgICAgICAgICAgZ1ByZWZpeCArIFwiX3N1YlwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgVSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFQsXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaWR4MlwiKSxcbiAgICAgICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgICAgICAgICBmUHJlZml4ICsgXCJfbXVsXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBXLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInB3bVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFcsXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJqXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwialwiKSwgYy5pMzJfY29uc3QoMSkpKSxcbiAgICAgICAgICAgICAgICAgICAgYy5icigwKVxuICAgICAgICAgICAgICAgICkpLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwiaVwiKSwgYy5pMzJfY29uc3QoMSkpKSxcbiAgICAgICAgICAgICAgICBjLmJyKDApXG4gICAgICAgICAgICApKVxuICAgICAgICApO1xuICAgIH1cblxuXG4gICAgLy8gUmV2ZXJzZSBhbGwgYW5kIG11bHRpcGx5IGJ5IGZhY3RvclxuICAgIGZ1bmN0aW9uIGJ1aWxkRkZURmluYWwoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX2ZmdEZpbmFsXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicEJ1ZmZcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJuXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiZmFjdG9yXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiaWR4MVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImlkeDJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJpXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwibmRpdjJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCBUID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44ZykpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJuZGl2MlwiLCBjLmkzMl9zaHJfdShjLmdldExvY2FsKFwiblwiKSwgYy5pMzJfY29uc3QoMSkpKSxcbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5pMzJfYW5kKFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiblwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMSlcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgb3BHdGltZXNGLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9hZGQoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicEJ1ZmZcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9tdWwoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIm5kaXYyXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KG44ZylcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImZhY3RvclwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBCdWZmXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfbXVsKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJuZGl2MlwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdChuOGcpXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiaVwiLCBjLmkzMl9jb25zdCgwKSksXG4gICAgICAgICAgICBjLmJsb2NrKGMubG9vcChcbiAgICAgICAgICAgICAgICBjLmJyX2lmKFxuICAgICAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9nZV91KFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImlcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwibmRpdjJcIilcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgICAgICBcImlkeDFcIixcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBCdWZmXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfbXVsKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KG44ZylcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgICAgICBcImlkeDJcIixcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBCdWZmXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfbXVsKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX3N1YihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfc3ViKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIm5cIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdCgxKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaVwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QobjhnKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgb3BHdGltZXNGLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaWR4MlwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImZhY3RvclwiKSxcbiAgICAgICAgICAgICAgICAgICAgVFxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgICAgIG9wR3RpbWVzRixcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImlkeDFcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJmYWN0b3JcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpZHgyXCIpLFxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgICAgIGdQcmVmaXggKyBcIl9jb3B5XCIsXG4gICAgICAgICAgICAgICAgICAgIFQsXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpZHgxXCIpLFxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaVwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcImlcIiksIGMuaTMyX2NvbnN0KDEpKSksXG4gICAgICAgICAgICAgICAgYy5icigwKVxuICAgICAgICAgICAgKSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBidWlsZFJldigpO1xuICAgIGJ1aWxkUmV2ZXJzZVBlcm11dGF0aW9uKCk7XG4gICAgYnVpbGRGaW5hbEludmVyc2UoKTtcbiAgICBidWlsZFJhd0ZGVCgpO1xuICAgIGJ1aWxkTG9nMigpO1xuICAgIGJ1aWxkRkZUKCk7XG4gICAgYnVpbGRJRkZUKCk7XG4gICAgYnVpbGRGRlRKb2luKCk7XG4gICAgYnVpbGRGRlRKb2luRXh0KCk7XG4gICAgYnVpbGRGRlRKb2luRXh0SW52KCk7XG4gICAgYnVpbGRGRlRNaXgoKTtcbiAgICBidWlsZEZGVEZpbmFsKCk7XG4gICAgYnVpbGRQcmVwYXJlTGFncmFuZ2VFdmFsdWF0aW9uKCk7XG5cbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4K1wiX19yZXZlcnNlUGVybXV0YXRpb25cIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCtcIl9mZnRcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCtcIl9pZmZ0XCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXgrXCJfcmF3ZmZ0XCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXgrXCJfZmZ0Sm9pblwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4K1wiX2ZmdEpvaW5FeHRcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCtcIl9mZnRKb2luRXh0SW52XCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXgrXCJfZmZ0TWl4XCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXgrXCJfZmZ0RmluYWxcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCtcIl9wcmVwYXJlTGFncmFuZ2VFdmFsdWF0aW9uXCIpO1xuXG59O1xuXG4vKlxuICAgIENvcHlyaWdodCAyMDE5IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygd2FzbXNuYXJrIChXZWIgQXNzZW1ibHkgemtTbmFyayBQcm92ZXIpLlxuXG4gICAgd2FzbXNuYXJrIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICAgIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gICAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAgICAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgd2FzbXNuYXJrIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHdhc21zbmFyay4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbnZhciBidWlsZF9wb2wgPSBmdW5jdGlvbiBidWlsZFBvbChtb2R1bGUsIHByZWZpeCwgcHJlZml4RmllbGQpIHtcblxuICAgIGNvbnN0IG42NCA9IG1vZHVsZS5tb2R1bGVzW3ByZWZpeEZpZWxkXS5uNjQ7XG4gICAgY29uc3QgbjggPSBuNjQqODtcblxuXG4gICAgZnVuY3Rpb24gYnVpbGRaZXJvKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCtcIl96ZXJvXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicHhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJuXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwibGFzdHBcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJwXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcInBcIiwgYy5nZXRMb2NhbChcInB4XCIpKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgXCJsYXN0cFwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInB4XCIpLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9tdWwoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiblwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KG44KVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuYmxvY2soYy5sb29wKFxuICAgICAgICAgICAgICAgIGMuYnJfaWYoXG4gICAgICAgICAgICAgICAgICAgIDEsXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2VxKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwibGFzdHBcIilcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfemVyb1wiLCBjLmdldExvY2FsKFwicFwiKSksXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcInBcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwXCIpLCBjLmkzMl9jb25zdChuOCkpKSxcbiAgICAgICAgICAgICAgICBjLmJyKDApXG4gICAgICAgICAgICApKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkQ29uc3RydWN0TEMoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX2NvbnN0cnVjdExDXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicHBvbHlub21pYWxzXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicHNpZ25hbHNcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJuU2lnbmFsc1wiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInByZXNcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJpXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwialwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcInBwXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwicHNcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJwZFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcIm5jb2Vmc1wiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IGF1eCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpXCIsIGMuaTMyX2NvbnN0KDApKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJwcFwiLCBjLmdldExvY2FsKFwicHBvbHlub21pYWxzXCIpKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJwc1wiLCBjLmdldExvY2FsKFwicHNpZ25hbHNcIikpLFxuICAgICAgICAgICAgYy5ibG9jayhjLmxvb3AoXG4gICAgICAgICAgICAgICAgYy5icl9pZihcbiAgICAgICAgICAgICAgICAgICAgMSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfZXEoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJuU2lnbmFsc1wiKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJuY29lZnNcIiwgYy5pMzJfbG9hZChjLmdldExvY2FsKFwicHBcIikpKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwicHBcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwcFwiKSwgYy5pMzJfY29uc3QoNCkpKSxcblxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJqXCIsIGMuaTMyX2NvbnN0KDApKSxcbiAgICAgICAgICAgICAgICBjLmJsb2NrKGMubG9vcChcbiAgICAgICAgICAgICAgICAgICAgYy5icl9pZihcbiAgICAgICAgICAgICAgICAgICAgICAgIDEsXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9lcShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwialwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwibmNvZWZzXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcbiAgICAgICAgICAgICAgICAgICAgICAgIFwicGRcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicHJlc1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9tdWwoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2xvYWQoYy5nZXRMb2NhbChcInBwXCIpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QobjgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJwcFwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInBwXCIpLCBjLmkzMl9jb25zdCg0KSkpLFxuXG5cbiAgICAgICAgICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgICAgICAgICAgcHJlZml4RmllbGQgKyBcIl9tdWxcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwc1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwcFwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGF1eFxuICAgICAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZWZpeEZpZWxkICsgXCJfYWRkXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBhdXgsXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicGRcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicGRcIilcbiAgICAgICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwicHBcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwcFwiKSwgYy5pMzJfY29uc3QobjgpKSksXG4gICAgICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJqXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwialwiKSwgYy5pMzJfY29uc3QoMSkpKSxcbiAgICAgICAgICAgICAgICAgICAgYy5icigwKVxuICAgICAgICAgICAgICAgICkpLFxuXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcInBzXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwicHNcIiksIGMuaTMyX2NvbnN0KG44KSkpLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwiaVwiKSwgYy5pMzJfY29uc3QoMSkpKSxcbiAgICAgICAgICAgICAgICBjLmJyKDApXG4gICAgICAgICAgICApKVxuICAgICAgICApO1xuXG4gICAgfVxuXG4gICAgYnVpbGRaZXJvKCk7XG4gICAgYnVpbGRDb25zdHJ1Y3RMQygpO1xuXG5cbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfemVyb1wiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfY29uc3RydWN0TENcIik7XG5cbiAgICByZXR1cm4gcHJlZml4O1xuXG5cblxuXG59O1xuXG52YXIgYnVpbGRfcWFwID0gZnVuY3Rpb24gYnVpbGRRQVAobW9kdWxlLCBwcmVmaXgsIHByZWZpeEZpZWxkKSB7XG5cbiAgICBjb25zdCBuNjQgPSBtb2R1bGUubW9kdWxlc1twcmVmaXhGaWVsZF0ubjY0O1xuICAgIGNvbnN0IG44ID0gbjY0Kjg7XG5cblxuICAgIGZ1bmN0aW9uIGJ1aWxkQnVpbGRBQkMoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX2J1aWxkQUJDXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicENvZWZzXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwibkNvZWZzXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicFdpdG5lc3NcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwQVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInBCXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicENcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJvZmZzZXRPdXRcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJuT3V0XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwib2Zmc2V0V2l0bmVzc1wiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcIm5XaXRuZXNzXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiaXRcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJpdGFcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJpdGJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJsYXN0XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwibVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImNcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJzXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwicE91dFwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IGF1eCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcblxuICAgICAgICAgICAgLy8gU2V0IG91dHB1dCBhIGFuZCBiIHRvIDBcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpdGFcIiwgYy5nZXRMb2NhbChcInBBXCIpKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpdGJcIiwgYy5nZXRMb2NhbChcInBCXCIpKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgXCJsYXN0XCIsXG4gICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicEFcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX211bChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJuT3V0XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QobjgpXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5ibG9jayhjLmxvb3AoXG4gICAgICAgICAgICAgICAgYy5icl9pZihcbiAgICAgICAgICAgICAgICAgICAgMSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfZXEoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaXRhXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImxhc3RcIilcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeEZpZWxkICsgXCJfemVyb1wiLCBjLmdldExvY2FsKFwiaXRhXCIpKSxcbiAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4RmllbGQgKyBcIl96ZXJvXCIsIGMuZ2V0TG9jYWwoXCJpdGJcIikpLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpdGFcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJpdGFcIiksIGMuaTMyX2NvbnN0KG44KSkpLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpdGJcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJpdGJcIiksIGMuaTMyX2NvbnN0KG44KSkpLFxuICAgICAgICAgICAgICAgIGMuYnIoMClcbiAgICAgICAgICAgICkpLFxuXG5cbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpdFwiLCBjLmdldExvY2FsKFwicENvZWZzXCIpKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgXCJsYXN0XCIsXG4gICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicENvZWZzXCIpLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9tdWwoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwibkNvZWZzXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QobjgrMTIpXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5ibG9jayhjLmxvb3AoXG4gICAgICAgICAgICAgICAgYy5icl9pZihcbiAgICAgICAgICAgICAgICAgICAgMSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfZXEoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiaXRcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwibGFzdFwiKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgICAgICBcInNcIixcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfbG9hZChjLmdldExvY2FsKFwiaXRcIiksIDgpXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9vcihcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2x0X3UoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInNcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIm9mZnNldFdpdG5lc3NcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfZ2VfdShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwic1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9hZGQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJvZmZzZXRXaXRuZXNzXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwibldpdG5lc3NcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgICAgICAuLi5jLnNldExvY2FsKFwiaXRcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJpdFwiKSwgYy5pMzJfY29uc3QobjgrMTIpKSksXG4gICAgICAgICAgICAgICAgICAgICAgICAuLi5jLmJyKDEpXG4gICAgICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICAgICApLFxuXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcbiAgICAgICAgICAgICAgICAgICAgXCJtXCIsXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2xvYWQoYy5nZXRMb2NhbChcIml0XCIpKVxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfZXEoYy5nZXRMb2NhbChcIm1cIiksIGMuaTMyX2NvbnN0KDApKSxcbiAgICAgICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcInBPdXRcIiwgYy5nZXRMb2NhbChcInBBXCIpKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2VxKGMuZ2V0TG9jYWwoXCJtXCIpLCBjLmkzMl9jb25zdCgxKSksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwicE91dFwiLCBjLmdldExvY2FsKFwicEJcIikpLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuc2V0TG9jYWwoXCJpdFwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcIml0XCIpLCBjLmkzMl9jb25zdChuOCsxMikpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5jLmJyKDEpXG4gICAgICAgICAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXG4gICAgICAgICAgICAgICAgICAgIFwiY1wiLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9sb2FkKGMuZ2V0TG9jYWwoXCJpdFwiKSwgNClcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX29yKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfbHRfdShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiY1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwib2Zmc2V0T3V0XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2dlX3UoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImNcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfYWRkKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwib2Zmc2V0T3V0XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwibk91dFwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuc2V0TG9jYWwoXCJpdFwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcIml0XCIpLCBjLmkzMl9jb25zdChuOCsxMikpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuYnIoMSlcbiAgICAgICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcbiAgICAgICAgICAgICAgICAgICAgXCJwT3V0XCIsXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwT3V0XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfbXVsKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX3N1YihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImNcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJvZmZzZXRPdXRcIilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KG44KVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgICAgIHByZWZpeEZpZWxkICsgXCJfbXVsXCIsXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwV2l0bmVzc1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX211bChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9zdWIoYy5nZXRMb2NhbChcInNcIiksIGMuZ2V0TG9jYWwoXCJvZmZzZXRXaXRuZXNzXCIpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdChuOClcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfYWRkKCBjLmdldExvY2FsKFwiaXRcIiksIGMuaTMyX2NvbnN0KDEyKSksXG4gICAgICAgICAgICAgICAgICAgIGF1eFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgICAgICBwcmVmaXhGaWVsZCArIFwiX2FkZFwiLFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicE91dFwiKSxcbiAgICAgICAgICAgICAgICAgICAgYXV4LFxuICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicE91dFwiKSxcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpdFwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcIml0XCIpLCBjLmkzMl9jb25zdChuOCsxMikpKSxcbiAgICAgICAgICAgICAgICBjLmJyKDApXG4gICAgICAgICAgICApKSxcblxuICAgICAgICAgICAgYy5zZXRMb2NhbChcIml0YVwiLCBjLmdldExvY2FsKFwicEFcIikpLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcIml0YlwiLCBjLmdldExvY2FsKFwicEJcIikpLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcIml0XCIsIGMuZ2V0TG9jYWwoXCJwQ1wiKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgIFwibGFzdFwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBBXCIpLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9tdWwoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwibk91dFwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KG44KVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuYmxvY2soYy5sb29wKFxuICAgICAgICAgICAgICAgIGMuYnJfaWYoXG4gICAgICAgICAgICAgICAgICAgIDEsXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2VxKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIml0YVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJsYXN0XCIpXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgcHJlZml4RmllbGQgKyBcIl9tdWxcIixcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIml0YVwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIml0YlwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIml0XCIpXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaXRhXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwiaXRhXCIpLCBjLmkzMl9jb25zdChuOCkpKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaXRiXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwiaXRiXCIpLCBjLmkzMl9jb25zdChuOCkpKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaXRcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJpdFwiKSwgYy5pMzJfY29uc3QobjgpKSksXG4gICAgICAgICAgICAgICAgYy5icigwKVxuICAgICAgICAgICAgKSksXG5cbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZEpvaW5BQkMoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX2pvaW5BQkNcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwQVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInBCXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicENcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJuXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicFBcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJpdGFcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJpdGJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJpdGNcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJpdHBcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJsYXN0XCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgYXV4ID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKG44KSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcIml0YVwiLCBjLmdldExvY2FsKFwicEFcIikpLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcIml0YlwiLCBjLmdldExvY2FsKFwicEJcIikpLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcIml0Y1wiLCBjLmdldExvY2FsKFwicENcIikpLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcIml0cFwiLCBjLmdldExvY2FsKFwicFBcIikpLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcbiAgICAgICAgICAgICAgICBcImxhc3RcIixcbiAgICAgICAgICAgICAgICBjLmkzMl9hZGQoXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwQVwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfbXVsKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIm5cIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdChuOClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLmJsb2NrKGMubG9vcChcbiAgICAgICAgICAgICAgICBjLmJyX2lmKFxuICAgICAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9lcShcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpdGFcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwibGFzdFwiKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgICAgIHByZWZpeEZpZWxkICsgXCJfbXVsXCIsXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpdGFcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpdGJcIiksXG4gICAgICAgICAgICAgICAgICAgIGF1eFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgICAgICBwcmVmaXhGaWVsZCArIFwiX3N1YlwiLFxuICAgICAgICAgICAgICAgICAgICBhdXgsXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpdGNcIiksXG4gICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJpdHBcIiksXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaXRhXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwiaXRhXCIpLCBjLmkzMl9jb25zdChuOCkpKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaXRiXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwiaXRiXCIpLCBjLmkzMl9jb25zdChuOCkpKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaXRjXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwiaXRjXCIpLCBjLmkzMl9jb25zdChuOCkpKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaXRwXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwiaXRwXCIpLCBjLmkzMl9jb25zdChuOCkpKSxcbiAgICAgICAgICAgICAgICBjLmJyKDApXG4gICAgICAgICAgICApKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkQmF0Y2hBZGQoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4K1wiX2JhdGNoQWRkXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicGFcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwYlwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcIm5cIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwclwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcIml0YVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcIml0YlwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcIml0clwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImxhc3RcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiaXRhXCIsIGMuZ2V0TG9jYWwoXCJwYVwiKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiaXRiXCIsIGMuZ2V0TG9jYWwoXCJwYlwiKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiaXRyXCIsIGMuZ2V0TG9jYWwoXCJwclwiKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFxuICAgICAgICAgICAgICAgIFwibGFzdFwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInBhXCIpLFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9tdWwoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiblwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KG44KVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuYmxvY2soYy5sb29wKFxuICAgICAgICAgICAgICAgIGMuYnJfaWYoXG4gICAgICAgICAgICAgICAgICAgIDEsXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2VxKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIml0YVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJsYXN0XCIpXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgcHJlZml4RmllbGQgKyBcIl9hZGRcIixcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIml0YVwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIml0YlwiKSxcbiAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcIml0clwiKSxcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpdGFcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJpdGFcIiksIGMuaTMyX2NvbnN0KG44KSkpLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpdGJcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJpdGJcIiksIGMuaTMyX2NvbnN0KG44KSkpLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpdHJcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJpdHJcIiksIGMuaTMyX2NvbnN0KG44KSkpLFxuICAgICAgICAgICAgICAgIGMuYnIoMClcbiAgICAgICAgICAgICkpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgYnVpbGRCdWlsZEFCQygpO1xuICAgIGJ1aWxkSm9pbkFCQygpO1xuICAgIGJ1aWxkQmF0Y2hBZGQoKTtcblxuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9idWlsZEFCQ1wiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfam9pbkFCQ1wiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfYmF0Y2hBZGRcIik7XG5cbiAgICByZXR1cm4gcHJlZml4O1xuXG59O1xuXG4vKlxuICAgIENvcHlyaWdodCAyMDE5IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygd2FzbXNuYXJrIChXZWIgQXNzZW1ibHkgemtTbmFyayBQcm92ZXIpLlxuXG4gICAgd2FzbXNuYXJrIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICAgIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gICAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAgICAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgd2FzbXNuYXJrIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHdhc21zbmFyay4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbnZhciBidWlsZF9hcHBseWtleSA9IGZ1bmN0aW9uIGJ1aWxkQXBwbHlLZXkobW9kdWxlLCBmbk5hbWUsIGdQcmVmaXgsIGZyUHJlZml4LCBzaXplR0luLCBzaXplR091dCwgc2l6ZUYsIG9wR3RpbWVzRikge1xuXG4gICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihmbk5hbWUpO1xuICAgIGYuYWRkUGFyYW0oXCJwSW5cIiwgXCJpMzJcIik7XG4gICAgZi5hZGRQYXJhbShcIm5cIiwgXCJpMzJcIik7XG4gICAgZi5hZGRQYXJhbShcInBGaXJzdFwiLCBcImkzMlwiKTtcbiAgICBmLmFkZFBhcmFtKFwicEluY1wiLCBcImkzMlwiKTtcbiAgICBmLmFkZFBhcmFtKFwicE91dFwiLCBcImkzMlwiKTtcbiAgICBmLmFkZExvY2FsKFwicE9sZEZyZWVcIiwgXCJpMzJcIik7XG4gICAgZi5hZGRMb2NhbChcImlcIiwgXCJpMzJcIik7XG4gICAgZi5hZGRMb2NhbChcInBGcm9tXCIsIFwiaTMyXCIpO1xuICAgIGYuYWRkTG9jYWwoXCJwVG9cIiwgXCJpMzJcIik7XG5cbiAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgY29uc3QgdCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhzaXplRikpO1xuXG4gICAgZi5hZGRDb2RlKFxuICAgICAgICBjLnNldExvY2FsKFwicEZyb21cIiwgYy5nZXRMb2NhbChcInBJblwiKSksXG4gICAgICAgIGMuc2V0TG9jYWwoXCJwVG9cIiwgYy5nZXRMb2NhbChcInBPdXRcIikpLFxuICAgICk7XG5cbiAgICAvLyB0ID0gZmlyc3RcbiAgICBmLmFkZENvZGUoXG4gICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgIGZyUHJlZml4ICsgXCJfY29weVwiLFxuICAgICAgICAgICAgYy5nZXRMb2NhbChcInBGaXJzdFwiKSxcbiAgICAgICAgICAgIHRcbiAgICAgICAgKVxuICAgICk7XG4gICAgZi5hZGRDb2RlKFxuICAgICAgICBjLnNldExvY2FsKFwiaVwiLCBjLmkzMl9jb25zdCgwKSksXG4gICAgICAgIGMuYmxvY2soYy5sb29wKFxuICAgICAgICAgICAgYy5icl9pZigxLCBjLmkzMl9lcSAoIGMuZ2V0TG9jYWwoXCJpXCIpLCBjLmdldExvY2FsKFwiblwiKSApKSxcblxuICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgIG9wR3RpbWVzRixcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicEZyb21cIiksXG4gICAgICAgICAgICAgICAgdCxcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicFRvXCIpXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcInBGcm9tXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwicEZyb21cIiksIGMuaTMyX2NvbnN0KHNpemVHSW4pKSksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwicFRvXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwicFRvXCIpLCBjLmkzMl9jb25zdChzaXplR091dCkpKSxcblxuICAgICAgICAgICAgLy8gdCA9IHQqIGluY1xuICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgIGZyUHJlZml4ICsgXCJfbXVsXCIsXG4gICAgICAgICAgICAgICAgdCxcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicEluY1wiKSxcbiAgICAgICAgICAgICAgICB0XG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcImlcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJpXCIpLCBjLmkzMl9jb25zdCgxKSkpLFxuICAgICAgICAgICAgYy5icigwKVxuICAgICAgICApKVxuICAgICk7XG5cbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24oZm5OYW1lKTtcblxufTtcblxuY29uc3QgdXRpbHMkMSA9IHV0aWxzJDU7XG5cbmNvbnN0IGJ1aWxkRjFtJDEgPWJ1aWxkX2YxbTtcbmNvbnN0IGJ1aWxkRjEkMSA9YnVpbGRfZjE7XG5jb25zdCBidWlsZEYybSQxID1idWlsZF9mMm07XG5jb25zdCBidWlsZEYzbSQxID1idWlsZF9mM207XG5jb25zdCBidWlsZEN1cnZlJDEgPWJ1aWxkX2N1cnZlX2phY29iaWFuX2EwO1xuY29uc3QgYnVpbGRGRlQkMSA9IGJ1aWxkX2ZmdDtcbmNvbnN0IGJ1aWxkUG9sJDEgPSBidWlsZF9wb2w7XG5jb25zdCBidWlsZFFBUCQxID0gYnVpbGRfcWFwO1xuY29uc3QgYnVpbGRBcHBseUtleSQxID0gYnVpbGRfYXBwbHlrZXk7XG5jb25zdCB7IGJpdExlbmd0aDogYml0TGVuZ3RoJDIsIG1vZEludiwgaXNPZGQ6IGlzT2RkJDEsIGlzTmVnYXRpdmU6IGlzTmVnYXRpdmUkMiB9ID0gYmlnaW50O1xuXG52YXIgYnVpbGRfYm4xMjggPSBmdW5jdGlvbiBidWlsZEJOMTI4KG1vZHVsZSwgX3ByZWZpeCkge1xuXG4gICAgY29uc3QgcHJlZml4ID0gX3ByZWZpeCB8fCBcImJuMTI4XCI7XG5cbiAgICBpZiAobW9kdWxlLm1vZHVsZXNbcHJlZml4XSkgcmV0dXJuIHByZWZpeDsgIC8vIGFscmVhZHkgYnVpbGRlZFxuXG4gICAgY29uc3QgcSA9IDIxODg4MjQyODcxODM5Mjc1MjIyMjQ2NDA1NzQ1MjU3Mjc1MDg4Njk2MzExMTU3Mjk3ODIzNjYyNjg5MDM3ODk0NjQ1MjI2MjA4NTgzbjtcbiAgICBjb25zdCByID0gMjE4ODgyNDI4NzE4MzkyNzUyMjIyNDY0MDU3NDUyNTcyNzUwODg1NDgzNjQ0MDA0MTYwMzQzNDM2OTgyMDQxODY1NzU4MDg0OTU2MTduO1xuXG5cbiAgICBjb25zdCBuNjQgPSBNYXRoLmZsb29yKChiaXRMZW5ndGgkMihxIC0gMW4pIC0gMSkvNjQpICsxO1xuICAgIGNvbnN0IG44ID0gbjY0Kjg7XG4gICAgY29uc3QgZnJzaXplID0gbjg7XG4gICAgY29uc3QgZjFzaXplID0gbjg7XG4gICAgY29uc3QgZjJzaXplID0gZjFzaXplICogMjtcbiAgICBjb25zdCBmdHNpemUgPSBmMXNpemUgKiAxMjtcblxuICAgIGNvbnN0IHByID0gbW9kdWxlLmFsbG9jKHV0aWxzJDEuYmlnSW50MkJ5dGVzTEUoIHIsIGZyc2l6ZSApKTtcblxuICAgIGNvbnN0IGYxbVByZWZpeCA9IGJ1aWxkRjFtJDEobW9kdWxlLCBxLCBcImYxbVwiKTtcbiAgICBidWlsZEYxJDEobW9kdWxlLCByLCBcImZyXCIsIFwiZnJtXCIpO1xuXG4gICAgY29uc3QgcEcxYiA9IG1vZHVsZS5hbGxvYyh1dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoM24pLCBmMXNpemUgKSk7XG4gICAgY29uc3QgZzFtUHJlZml4ID0gYnVpbGRDdXJ2ZSQxKG1vZHVsZSwgXCJnMW1cIiwgXCJmMW1cIiwgcEcxYik7XG5cbiAgICBidWlsZEZGVCQxKG1vZHVsZSwgXCJmcm1cIiwgXCJmcm1cIiwgXCJmcm1cIiwgXCJmcm1fbXVsXCIpO1xuXG4gICAgYnVpbGRQb2wkMShtb2R1bGUsIFwicG9sXCIsIFwiZnJtXCIpO1xuICAgIGJ1aWxkUUFQJDEobW9kdWxlLCBcInFhcFwiLCBcImZybVwiKTtcblxuICAgIGNvbnN0IGYybVByZWZpeCA9IGJ1aWxkRjJtJDEobW9kdWxlLCBcImYxbV9uZWdcIiwgXCJmMm1cIiwgXCJmMW1cIik7XG4gICAgY29uc3QgcEcyYiA9IG1vZHVsZS5hbGxvYyhbXG4gICAgICAgIC4uLnV0aWxzJDEuYmlnSW50MkJ5dGVzTEUoIHRvTW9udGdvbWVyeSgxOTQ4NTg3NDc1MTc1OTM1NDc3MTAyNDIzOTI2MTAyMTcyMDUwNTc5MDYxODQ2OTMwMTcyMTA2NTU2NDYzMTI5NjQ1MjQ1NzQ3ODM3M24pLCBmMXNpemUgKSxcbiAgICAgICAgLi4udXRpbHMkMS5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KDI2NjkyOTc5MTExOTk5MTE2MTI0NjkwNzM4NzEzNzI4Mzg0MjU0NTA3Njk2NTMzMjkwMDI4ODU2OTM3ODUxMDkxMDMwNzYzNjY5MG4pLCBmMXNpemUgKVxuICAgIF0pO1xuICAgIGNvbnN0IGcybVByZWZpeCA9IGJ1aWxkQ3VydmUkMShtb2R1bGUsIFwiZzJtXCIsIFwiZjJtXCIsIHBHMmIpO1xuXG5cbiAgICBmdW5jdGlvbiBidWlsZEdUaW1lc0ZyKGZuTmFtZSwgb3BNdWwpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihmbk5hbWUpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicEdcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwRnJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwclwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IEFVWCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOCkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuY2FsbChcImZybV9mcm9tTW9udGdvbWVyeVwiLCBjLmdldExvY2FsKFwicEZyXCIpLCBBVVgpLFxuICAgICAgICAgICAgYy5jYWxsKFxuICAgICAgICAgICAgICAgIG9wTXVsLFxuICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwR1wiKSxcbiAgICAgICAgICAgICAgICBBVVgsXG4gICAgICAgICAgICAgICAgYy5pMzJfY29uc3QobjgpLFxuICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJwclwiKVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuXG4gICAgICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihmbk5hbWUpO1xuICAgIH1cbiAgICBidWlsZEdUaW1lc0ZyKFwiZzFtX3RpbWVzRnJcIiwgXCJnMW1fdGltZXNTY2FsYXJcIik7XG4gICAgYnVpbGRGRlQkMShtb2R1bGUsIFwiZzFtXCIsIFwiZzFtXCIsIFwiZnJtXCIsIFwiZzFtX3RpbWVzRnJcIik7XG5cbiAgICBidWlsZEdUaW1lc0ZyKFwiZzJtX3RpbWVzRnJcIiwgXCJnMm1fdGltZXNTY2FsYXJcIik7XG4gICAgYnVpbGRGRlQkMShtb2R1bGUsIFwiZzJtXCIsIFwiZzJtXCIsIFwiZnJtXCIsIFwiZzJtX3RpbWVzRnJcIik7XG5cbiAgICBidWlsZEdUaW1lc0ZyKFwiZzFtX3RpbWVzRnJBZmZpbmVcIiwgXCJnMW1fdGltZXNTY2FsYXJBZmZpbmVcIik7XG4gICAgYnVpbGRHVGltZXNGcihcImcybV90aW1lc0ZyQWZmaW5lXCIsIFwiZzJtX3RpbWVzU2NhbGFyQWZmaW5lXCIpO1xuXG4gICAgYnVpbGRBcHBseUtleSQxKG1vZHVsZSwgXCJmcm1fYmF0Y2hBcHBseUtleVwiLCBcImZtclwiLCBcImZybVwiLCBuOCwgbjgsIG44LCBcImZybV9tdWxcIik7XG4gICAgYnVpbGRBcHBseUtleSQxKG1vZHVsZSwgXCJnMW1fYmF0Y2hBcHBseUtleVwiLCBcImcxbVwiLCBcImZybVwiLCBuOCozLCBuOCozLCBuOCwgXCJnMW1fdGltZXNGclwiKTtcbiAgICBidWlsZEFwcGx5S2V5JDEobW9kdWxlLCBcImcxbV9iYXRjaEFwcGx5S2V5TWl4ZWRcIiwgXCJnMW1cIiwgXCJmcm1cIiwgbjgqMiwgbjgqMywgbjgsIFwiZzFtX3RpbWVzRnJBZmZpbmVcIik7XG4gICAgYnVpbGRBcHBseUtleSQxKG1vZHVsZSwgXCJnMm1fYmF0Y2hBcHBseUtleVwiLCBcImcybVwiLCBcImZybVwiLCBuOCoyKjMsIG44KjMqMiwgbjgsIFwiZzJtX3RpbWVzRnJcIik7XG4gICAgYnVpbGRBcHBseUtleSQxKG1vZHVsZSwgXCJnMm1fYmF0Y2hBcHBseUtleU1peGVkXCIsIFwiZzJtXCIsIFwiZnJtXCIsIG44KjIqMiwgbjgqMyoyLCBuOCwgXCJnMm1fdGltZXNGckFmZmluZVwiKTtcblxuICAgIGZ1bmN0aW9uIHRvTW9udGdvbWVyeShhKSB7XG4gICAgICAgIHJldHVybiBCaWdJbnQoYSkgKiAoIDFuIDw8IEJpZ0ludChmMXNpemUqOCkpICUgcTtcbiAgICB9XG5cbiAgICBjb25zdCBHMWdlbiA9IFtcbiAgICAgICAgMW4sXG4gICAgICAgIDJuLFxuICAgICAgICAxblxuICAgIF07XG5cbiAgICBjb25zdCBwRzFnZW4gPSBtb2R1bGUuYWxsb2MoXG4gICAgICAgIFtcbiAgICAgICAgICAgIC4uLnV0aWxzJDEuYmlnSW50MkJ5dGVzTEUoIHRvTW9udGdvbWVyeShHMWdlblswXSksIGYxc2l6ZSApLFxuICAgICAgICAgICAgLi4udXRpbHMkMS5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KEcxZ2VuWzFdKSwgZjFzaXplICksXG4gICAgICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoRzFnZW5bMl0pLCBmMXNpemUgKSxcbiAgICAgICAgXVxuICAgICk7XG5cbiAgICBjb25zdCBHMXplcm8gPSBbXG4gICAgICAgIDBuLFxuICAgICAgICAxbixcbiAgICAgICAgMG5cbiAgICBdO1xuXG4gICAgY29uc3QgcEcxemVybyA9IG1vZHVsZS5hbGxvYyhcbiAgICAgICAgW1xuICAgICAgICAgICAgLi4udXRpbHMkMS5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KEcxemVyb1swXSksIGYxc2l6ZSApLFxuICAgICAgICAgICAgLi4udXRpbHMkMS5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KEcxemVyb1sxXSksIGYxc2l6ZSApLFxuICAgICAgICAgICAgLi4udXRpbHMkMS5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KEcxemVyb1syXSksIGYxc2l6ZSApXG4gICAgICAgIF1cbiAgICApO1xuXG4gICAgY29uc3QgRzJnZW4gPSBbXG4gICAgICAgIFtcbiAgICAgICAgICAgIDEwODU3MDQ2OTk5MDIzMDU3MTM1OTQ0NTcwNzYyMjMyODI5NDgxMzcwNzU2MzU5NTc4NTE4MDg2OTkwNTE5OTkzMjg1NjU1ODUyNzgxbixcbiAgICAgICAgICAgIDExNTU5NzMyMDMyOTg2Mzg3MTA3OTkxMDA0MDIxMzkyMjg1NzgzOTI1ODEyODYxODIxMTkyNTMwOTE3NDAzMTUxNDUyMzkxODA1NjM0bixcbiAgICAgICAgXSxbXG4gICAgICAgICAgICA4NDk1NjUzOTIzMTIzNDMxNDE3NjA0OTczMjQ3NDg5MjcyNDM4NDE4MTkwNTg3MjYzNjAwMTQ4NzcwMjgwNjQ5MzA2OTU4MTAxOTMwbixcbiAgICAgICAgICAgIDQwODIzNjc4NzU4NjM0MzM2ODEzMzIyMDM0MDMxNDU0MzU1NjgzMTY4NTEzMjc1OTM0MDEyMDgxMDU3NDEwNzYyMTQxMjAwOTM1MzFuLFxuICAgICAgICBdLFtcbiAgICAgICAgICAgIDFuLFxuICAgICAgICAgICAgMG4sXG4gICAgICAgIF1cbiAgICBdO1xuXG4gICAgY29uc3QgcEcyZ2VuID0gbW9kdWxlLmFsbG9jKFxuICAgICAgICBbXG4gICAgICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoRzJnZW5bMF1bMF0pLCBmMXNpemUgKSxcbiAgICAgICAgICAgIC4uLnV0aWxzJDEuYmlnSW50MkJ5dGVzTEUoIHRvTW9udGdvbWVyeShHMmdlblswXVsxXSksIGYxc2l6ZSApLFxuICAgICAgICAgICAgLi4udXRpbHMkMS5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KEcyZ2VuWzFdWzBdKSwgZjFzaXplICksXG4gICAgICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoRzJnZW5bMV1bMV0pLCBmMXNpemUgKSxcbiAgICAgICAgICAgIC4uLnV0aWxzJDEuYmlnSW50MkJ5dGVzTEUoIHRvTW9udGdvbWVyeShHMmdlblsyXVswXSksIGYxc2l6ZSApLFxuICAgICAgICAgICAgLi4udXRpbHMkMS5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KEcyZ2VuWzJdWzFdKSwgZjFzaXplICksXG4gICAgICAgIF1cbiAgICApO1xuXG4gICAgY29uc3QgRzJ6ZXJvID0gW1xuICAgICAgICBbXG4gICAgICAgICAgICAwbixcbiAgICAgICAgICAgIDBuLFxuICAgICAgICBdLFtcbiAgICAgICAgICAgIDFuLFxuICAgICAgICAgICAgMG4sXG4gICAgICAgIF0sW1xuICAgICAgICAgICAgMG4sXG4gICAgICAgICAgICAwbixcbiAgICAgICAgXVxuICAgIF07XG5cbiAgICBjb25zdCBwRzJ6ZXJvID0gbW9kdWxlLmFsbG9jKFxuICAgICAgICBbXG4gICAgICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoRzJ6ZXJvWzBdWzBdKSwgZjFzaXplICksXG4gICAgICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoRzJ6ZXJvWzBdWzFdKSwgZjFzaXplICksXG4gICAgICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoRzJ6ZXJvWzFdWzBdKSwgZjFzaXplICksXG4gICAgICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoRzJ6ZXJvWzFdWzFdKSwgZjFzaXplICksXG4gICAgICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoRzJ6ZXJvWzJdWzBdKSwgZjFzaXplICksXG4gICAgICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoRzJ6ZXJvWzJdWzFdKSwgZjFzaXplICksXG4gICAgICAgIF1cbiAgICApO1xuXG4gICAgY29uc3QgcE9uZVQgPSBtb2R1bGUuYWxsb2MoW1xuICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoMSksIGYxc2l6ZSApLFxuICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoMCksIGYxc2l6ZSApLFxuICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoMCksIGYxc2l6ZSApLFxuICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoMCksIGYxc2l6ZSApLFxuICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoMCksIGYxc2l6ZSApLFxuICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoMCksIGYxc2l6ZSApLFxuICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoMCksIGYxc2l6ZSApLFxuICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoMCksIGYxc2l6ZSApLFxuICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoMCksIGYxc2l6ZSApLFxuICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoMCksIGYxc2l6ZSApLFxuICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoMCksIGYxc2l6ZSApLFxuICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoMCksIGYxc2l6ZSApLFxuICAgIF0pO1xuXG4gICAgY29uc3QgcE5vblJlc2lkdWVGNiA9IG1vZHVsZS5hbGxvYyhbXG4gICAgICAgIC4uLnV0aWxzJDEuYmlnSW50MkJ5dGVzTEUoIHRvTW9udGdvbWVyeSg5KSwgZjFzaXplICksXG4gICAgICAgIC4uLnV0aWxzJDEuYmlnSW50MkJ5dGVzTEUoIHRvTW9udGdvbWVyeSgxKSwgZjFzaXplICksXG4gICAgXSk7XG5cbiAgICBjb25zdCBwVHdvSW52ID0gbW9kdWxlLmFsbG9jKFtcbiAgICAgICAgLi4udXRpbHMkMS5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KCAgbW9kSW52KDJuLCBxKSksIGYxc2l6ZSApLFxuICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCAwbiwgZjFzaXplIClcbiAgICBdKTtcblxuICAgIGNvbnN0IHBBbHRCbjEyOFR3aXN0ID0gcE5vblJlc2lkdWVGNjtcblxuICAgIGNvbnN0IHBUd2lzdENvZWZCID0gbW9kdWxlLmFsbG9jKFtcbiAgICAgICAgLi4udXRpbHMkMS5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KDE5NDg1ODc0NzUxNzU5MzU0NzcxMDI0MjM5MjYxMDIxNzIwNTA1NzkwNjE4NDY5MzAxNzIxMDY1NTY0NjMxMjk2NDUyNDU3NDc4MzczbiksIGYxc2l6ZSApLFxuICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoMjY2OTI5NzkxMTE5OTkxMTYxMjQ2OTA3Mzg3MTM3MjgzODQyNTQ1MDc2OTY1MzMyOTAwMjg4NTY5Mzc4NTEwOTEwMzA3NjM2NjkwbiksIGYxc2l6ZSApLFxuICAgIF0pO1xuXG4gICAgZnVuY3Rpb24gYnVpbGRfbXVsTlI2KCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCArIFwiX211bE5SNlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwclwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICBmMm1QcmVmaXggKyBcIl9tdWxcIixcbiAgICAgICAgICAgICAgICBjLmkzMl9jb25zdChwTm9uUmVzaWR1ZUY2KSxcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwieFwiKSxcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicHJcIilcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9XG4gICAgYnVpbGRfbXVsTlI2KCk7XG5cbiAgICBjb25zdCBmNm1QcmVmaXggPSBidWlsZEYzbSQxKG1vZHVsZSwgcHJlZml4K1wiX211bE5SNlwiLCBcImY2bVwiLCBcImYybVwiKTtcblxuICAgIGZ1bmN0aW9uIGJ1aWxkX211bE5SMTIoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4ICsgXCJfbXVsTlIxMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwclwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICBmMm1QcmVmaXggKyBcIl9tdWxcIixcbiAgICAgICAgICAgICAgICBjLmkzMl9jb25zdChwTm9uUmVzaWR1ZUY2KSxcbiAgICAgICAgICAgICAgICBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KG44KjQpKSxcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicHJcIilcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgZjJtUHJlZml4ICsgXCJfY29weVwiLFxuICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJ4XCIpLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChjLmdldExvY2FsKFwicHJcIiksIGMuaTMyX2NvbnN0KG44KjIpKSxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgZjJtUHJlZml4ICsgXCJfY29weVwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QobjgqMikpLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChjLmdldExvY2FsKFwicHJcIiksIGMuaTMyX2NvbnN0KG44KjQpKSxcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9XG4gICAgYnVpbGRfbXVsTlIxMigpO1xuXG4gICAgY29uc3QgZnRtUHJlZml4ID0gYnVpbGRGMm0kMShtb2R1bGUsIHByZWZpeCtcIl9tdWxOUjEyXCIsIFwiZnRtXCIsIGY2bVByZWZpeCk7XG5cblxuICAgIGNvbnN0IGF0ZUxvb3BDb3VudCA9IDI5NzkzOTY4MjAzMTU3MDkzMjg4bjtcbiAgICBjb25zdCBhdGVMb29wQml0Qnl0ZXMgPSBiaXRzKGF0ZUxvb3BDb3VudCk7XG4gICAgY29uc3QgcEF0ZUxvb3BCaXRCeXRlcyA9IG1vZHVsZS5hbGxvYyhhdGVMb29wQml0Qnl0ZXMpO1xuXG4gICAgY29uc3QgYXRlQ29lZlNpemUgPSAzICogZjJzaXplO1xuICAgIGNvbnN0IGF0ZU5EYmxDb2VmcyA9IGF0ZUxvb3BCaXRCeXRlcy5sZW5ndGgtMTtcbiAgICBjb25zdCBhdGVOQWRkQ29lZnMgPSBhdGVMb29wQml0Qnl0ZXMucmVkdWNlKChhY2MsIGIpID0+ICBhY2MgKyAoIGIhPTAgPyAxIDogMCkgICAsMCk7XG4gICAgY29uc3QgYXRlTkNvZWZzID0gYXRlTkFkZENvZWZzICsgYXRlTkRibENvZWZzICsgMTtcbiAgICBjb25zdCBwcmVQU2l6ZSA9IDMqMipuODtcbiAgICBjb25zdCBwcmVRU2l6ZSA9IDMqbjgqMiArIGF0ZU5Db2VmcyphdGVDb2VmU2l6ZTtcblxuXG4gICAgbW9kdWxlLm1vZHVsZXNbcHJlZml4XSA9IHtcbiAgICAgICAgbjY0OiBuNjQsXG4gICAgICAgIHBHMWdlbjogcEcxZ2VuLFxuICAgICAgICBwRzF6ZXJvOiBwRzF6ZXJvLFxuICAgICAgICBwRzFiOiBwRzFiLFxuICAgICAgICBwRzJnZW46IHBHMmdlbixcbiAgICAgICAgcEcyemVybzogcEcyemVybyxcbiAgICAgICAgcEcyYjogcEcyYixcbiAgICAgICAgcHE6IG1vZHVsZS5tb2R1bGVzW1wiZjFtXCJdLnBxLFxuICAgICAgICBwcjogcHIsXG4gICAgICAgIHBPbmVUOiBwT25lVCxcbiAgICAgICAgcHJlUFNpemU6IHByZVBTaXplLFxuICAgICAgICBwcmVRU2l6ZTogcHJlUVNpemUsXG4gICAgICAgIHI6IHIudG9TdHJpbmcoKSxcbiAgICAgICAgcTogcS50b1N0cmluZygpXG4gICAgfTtcblxuICAgIC8vIGNvbnNvbGUubG9nKFwiUHJlUFNpemU6IFwiICtwcmVQU2l6ZSk7XG4gICAgLy8gY29uc29sZS5sb2coXCJQcmVRU2l6ZTogXCIgK3ByZVFTaXplKTtcblxuICAgIGNvbnN0IGZpbmFsRXhwWiA9IDQ5NjU2NjEzNjcxOTI4NDg4ODFuO1xuXG4gICAgZnVuY3Rpb24gbmFmKG4pIHtcbiAgICAgICAgbGV0IEUgPSBuO1xuICAgICAgICBjb25zdCByZXMgPSBbXTtcbiAgICAgICAgd2hpbGUgKEUgPiAwbikge1xuICAgICAgICAgICAgaWYgKGlzT2RkJDEoRSkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB6ID0gMiAtIE51bWJlcihFICUgNG4pO1xuICAgICAgICAgICAgICAgIHJlcy5wdXNoKCB6ICk7XG4gICAgICAgICAgICAgICAgRSA9IEUgLSBCaWdJbnQoeik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlcy5wdXNoKCAwICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBFID0gRSA+PiAxbjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJpdHMobikge1xuICAgICAgICBsZXQgRSA9IG47XG4gICAgICAgIGNvbnN0IHJlcyA9IFtdO1xuICAgICAgICB3aGlsZSAoRSA+IDBuKSB7XG4gICAgICAgICAgICBpZiAoaXNPZGQkMShFKSkge1xuICAgICAgICAgICAgICAgIHJlcy5wdXNoKCAxICk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlcy5wdXNoKCAwICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBFID0gRSA+PiAxbjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkUHJlcGFyZUcxKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCsgXCJfcHJlcGFyZUcxXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicFBcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwcHJlUFwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuY2FsbChnMW1QcmVmaXggKyBcIl9ub3JtYWxpemVcIiwgYy5nZXRMb2NhbChcInBQXCIpLCBjLmdldExvY2FsKFwicHByZVBcIikpLCAgLy8gVE9ETyBSZW1vdmUgaWYgYWxyZWFkeSBpbiBhZmZpbmVcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZFByZXBBZGRTdGVwKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCsgXCJfcHJlcEFkZFN0ZXBcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwUVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInBSXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicENvZWZcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCBYMiAgPSBjLmdldExvY2FsKFwicFFcIik7XG4gICAgICAgIGNvbnN0IFkyICA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicFFcIiksIGMuaTMyX2NvbnN0KGYyc2l6ZSkpO1xuXG4gICAgICAgIGNvbnN0IFgxICA9IGMuZ2V0TG9jYWwoXCJwUlwiKTtcbiAgICAgICAgY29uc3QgWTEgID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwUlwiKSwgYy5pMzJfY29uc3QoZjJzaXplKSk7XG4gICAgICAgIGNvbnN0IFoxICA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicFJcIiksIGMuaTMyX2NvbnN0KDIqZjJzaXplKSk7XG5cbiAgICAgICAgY29uc3QgRUxMXzAgID0gYy5nZXRMb2NhbChcInBDb2VmXCIpO1xuICAgICAgICBjb25zdCBFTExfVlcgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInBDb2VmXCIpLCBjLmkzMl9jb25zdChmMnNpemUpKTtcbiAgICAgICAgY29uc3QgRUxMX1ZWICA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicENvZWZcIiksIGMuaTMyX2NvbnN0KDIqZjJzaXplKSk7XG5cbiAgICAgICAgY29uc3QgRCA9IEVMTF9WVztcbiAgICAgICAgY29uc3QgRSA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcbiAgICAgICAgY29uc3QgRiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcbiAgICAgICAgY29uc3QgRyA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcbiAgICAgICAgY29uc3QgSCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcbiAgICAgICAgY29uc3QgSSA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcbiAgICAgICAgY29uc3QgSiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcbiAgICAgICAgY29uc3QgQVVYID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIC8vIEQgPSBYMSAtIFgyKloxXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIFgyLCBaMSwgRCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3ViXCIsIFgxLCBELCBEKSxcblxuICAgICAgICAgICAgLy8gRSA9IFkxIC0gWTIqWjFcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgWTIsIFoxLCBFKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zdWJcIiwgWTEsIEUsIEUpLFxuXG4gICAgICAgICAgICAvLyBGID0gRF4yXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3F1YXJlXCIsIEQsIEYpLFxuXG4gICAgICAgICAgICAvLyBHID0gRV4yXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3F1YXJlXCIsIEUsIEcpLFxuXG4gICAgICAgICAgICAvLyBIID0gRCpGXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIEQsIEYsIEgpLFxuXG4gICAgICAgICAgICAvLyBJID0gWDEgKiBGXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIFgxLCBGLCBJKSxcblxuICAgICAgICAgICAgLy8gSiA9IEggKyBaMSpHIC0gKEkrSSlcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgSSwgSSwgQVVYKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgWjEsIEcsIEopLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCBILCBKLCBKKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zdWJcIiwgSiwgQVVYLCBKKSxcblxuXG4gICAgICAgICAgICAvLyBYMyAoWDEpID0gRCpKXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIEQsIEosIFgxKSxcblxuICAgICAgICAgICAgLy8gWTMgKFkxKSA9IEUqKEktSiktKEgqWTEpXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIEgsIFkxLCBZMSksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3ViXCIsIEksIEosIEFVWCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIEUsIEFVWCwgQVVYKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zdWJcIiwgQVVYLCBZMSwgWTEpLFxuXG4gICAgICAgICAgICAvLyBaMyAoWjEpID0gWjEqSFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCBaMSwgSCwgWjEpLFxuXG4gICAgICAgICAgICAvLyBlbGxfMCA9IHhpICogKEUgKiBYMiAtIEQgKiBZMilcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgRCwgWTIsIEFVWCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIEUsIFgyLCBFTExfMCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3ViXCIsIEVMTF8wLCBBVVgsIEVMTF8wKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgRUxMXzAsIGMuaTMyX2NvbnN0KHBBbHRCbjEyOFR3aXN0KSwgRUxMXzApLFxuXG5cbiAgICAgICAgICAgIC8vIGVsbF9WViA9IC0gRSAobGF0ZXI6ICogeFApXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbmVnXCIsIEUsIEVMTF9WViksXG5cbiAgICAgICAgICAgIC8vIGVsbF9WVyA9IEQgKGxhdGVyOiAqIHlQICAgIClcbiAgICAgICAgICAgIC8vIEFscmVhZHkgYXNzaWduZWRcblxuICAgICAgICApO1xuICAgIH1cblxuXG5cbiAgICBmdW5jdGlvbiBidWlsZFByZXBEb3VibGVTdGVwKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCsgXCJfcHJlcERibFN0ZXBcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwUlwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInBDb2VmXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgWDEgID0gYy5nZXRMb2NhbChcInBSXCIpO1xuICAgICAgICBjb25zdCBZMSAgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInBSXCIpLCBjLmkzMl9jb25zdChmMnNpemUpKTtcbiAgICAgICAgY29uc3QgWjEgID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwUlwiKSwgYy5pMzJfY29uc3QoMipmMnNpemUpKTtcblxuICAgICAgICBjb25zdCBFTExfMCAgPSBjLmdldExvY2FsKFwicENvZWZcIik7XG4gICAgICAgIGNvbnN0IEVMTF9WVyA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicENvZWZcIiksIGMuaTMyX2NvbnN0KGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCBFTExfVlYgID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwQ29lZlwiKSwgYy5pMzJfY29uc3QoMipmMnNpemUpKTtcblxuICAgICAgICBjb25zdCBBID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCBCID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCBDID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCBEID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCBFID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCBGID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCBHID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCBIID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCBJID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCBKID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCBFMiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcbiAgICAgICAgY29uc3QgQVVYID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcblxuICAgICAgICAgICAgLy8gQSA9IFgxICogWTEgLyAyXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIFkxLCBjLmkzMl9jb25zdChwVHdvSW52KSwgQSksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIFgxLCBBLCBBKSxcblxuICAgICAgICAgICAgLy8gQiA9IFkxXjJcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zcXVhcmVcIiwgWTEsIEIpLFxuXG4gICAgICAgICAgICAvLyBDID0gWjFeMlxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3NxdWFyZVwiLCBaMSwgQyksXG5cbiAgICAgICAgICAgIC8vIEQgPSAzICogQ1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCBDLCBDLCBEKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgRCwgQywgRCksXG5cbiAgICAgICAgICAgIC8vIEUgPSB0d2lzdF9iICogRFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCBjLmkzMl9jb25zdChwVHdpc3RDb2VmQiksIEQsIEUpLFxuXG4gICAgICAgICAgICAvLyBGID0gMyAqIEVcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgRSwgRSwgRiksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIEUsIEYsIEYpLFxuXG4gICAgICAgICAgICAvLyBHID0gKEIrRikvMlxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCBCLCBGLCBHKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgRywgYy5pMzJfY29uc3QocFR3b0ludiksIEcpLFxuXG4gICAgICAgICAgICAvLyBIID0gKFkxK1oxKV4yLShCK0MpXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIEIsIEMsIEFVWCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIFkxLCBaMSwgSCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3F1YXJlXCIsIEgsIEgpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3N1YlwiLCBILCBBVVgsIEgpLFxuXG4gICAgICAgICAgICAvLyBJID0gRS1CXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3ViXCIsIEUsIEIsIEkpLFxuXG4gICAgICAgICAgICAvLyBKID0gWDFeMlxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3NxdWFyZVwiLCBYMSwgSiksXG5cbiAgICAgICAgICAgIC8vIEVfc3F1YXJlZCA9IEVeMlxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3NxdWFyZVwiLCBFLCBFMiksXG5cbiAgICAgICAgICAgIC8vIFgzIChYMSkgPSBBICogKEItRilcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zdWJcIiwgQiwgRiwgQVVYKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgQSwgQVVYLCBYMSksXG5cbiAgICAgICAgICAgIC8vIFkzIChZMSkgPSBHXjIgLSAzKkVeMlxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCBFMiwgRTIsIEFVWCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIEUyLCBBVVgsIEFVWCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3F1YXJlXCIsIEcsIFkxKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zdWJcIiwgWTEsIEFVWCwgWTEpLFxuXG4gICAgICAgICAgICAvLyBaMyAoWjEpID0gQiAqIEhcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgQiwgSCwgWjEpLFxuXG4gICAgICAgICAgICAvLyBlbGxfMCA9IHhpICogSVxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCBjLmkzMl9jb25zdChwQWx0Qm4xMjhUd2lzdCksIEksIEVMTF8wKSxcblxuICAgICAgICAgICAgLy8gZWxsX1ZXID0gLSBIIChsYXRlcjogKiB5UClcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9uZWdcIiwgSCwgRUxMX1ZXKSxcblxuICAgICAgICAgICAgLy8gZWxsX1ZWID0gMypKIChsYXRlcjogKiB4UClcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgSiwgSiwgRUxMX1ZWKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgSiwgRUxMX1ZWLCBFTExfVlYpLFxuXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRNdWxCeVEoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4ICsgXCJfbXVsQnlRXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicDFcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwclwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IHggPSBjLmdldExvY2FsKFwicDFcIik7XG4gICAgICAgIGNvbnN0IHkgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInAxXCIpLCBjLmkzMl9jb25zdChmMnNpemUpKTtcbiAgICAgICAgY29uc3QgeiA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicDFcIiksIGMuaTMyX2NvbnN0KGYyc2l6ZSoyKSk7XG4gICAgICAgIGNvbnN0IHgzID0gYy5nZXRMb2NhbChcInByXCIpO1xuICAgICAgICBjb25zdCB5MyA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicHJcIiksIGMuaTMyX2NvbnN0KGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCB6MyA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicHJcIiksIGMuaTMyX2NvbnN0KGYyc2l6ZSoyKSk7XG5cbiAgICAgICAgY29uc3QgTXVsQnlRWCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhbXG4gICAgICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoXCIyMTU3NTQ2MzYzODI4MDg0MzAxMDM5ODMyNDI2OTQzMDgyNjA5OTI2OTA0NDI3NDM0NzIxNjgyNzIxMjYxMzg2NzgzNjQzNTAyNzI2MVwiKSwgZjFzaXplICksXG4gICAgICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoXCIxMDMwNzYwMTU5NTg3MzcwOTcwMDE1MjI4NDI3MzgxNjExMjI2NDA2OTIzMDEzMDYxNjQzNjc1NTYyNTE5NDg1NDgxNTg3NTcxMzk1NFwiKSwgZjFzaXplICksXG4gICAgICAgIF0pKTtcblxuICAgICAgICBjb25zdCBNdWxCeVFZID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKFtcbiAgICAgICAgICAgIC4uLnV0aWxzJDEuYmlnSW50MkJ5dGVzTEUoIHRvTW9udGdvbWVyeShcIjI4MjE1NjUxODIxOTQ1MzY4NDQ1NDgxNTk1NjE2OTM1MDI2NTkzNTk2MTcxODUyNDQxMjAzNjcwNzgwNzk1NTQxODY0ODQxMjY1NTRcIiksIGYxc2l6ZSApLFxuICAgICAgICAgICAgLi4udXRpbHMkMS5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KFwiMzUwNTg0Mzc2NzkxMTU1NjM3ODY4NzAzMDMwOTk4NDI0ODg0NTU0MDI0MzUwOTg5OTI1OTY0MTAxMzY3ODA5MzAzMzEzMDkzMDQwM1wiKSwgZjFzaXplICksXG4gICAgICAgIF0pKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICAvLyBUaGUgZnJvYmVuaXVzTWFwKDEpIGluIHRoaXMgZmllbGQsIGlzIHRoZSBjb25qdWdhdGVcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9jb25qdWdhdGVcIiwgeCwgeDMpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCBNdWxCeVFYLCB4MywgeDMpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2Nvbmp1Z2F0ZVwiLCB5LCB5MyksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIE11bEJ5UVksIHkzLCB5MyksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfY29uanVnYXRlXCIsIHosIHozKSxcbiAgICAgICAgKTtcbiAgICB9XG5cblxuICAgIGZ1bmN0aW9uIGJ1aWxkUHJlcGFyZUcyKCkge1xuICAgICAgICBidWlsZE11bEJ5USgpO1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCsgXCJfcHJlcGFyZUcyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicFFcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwcHJlUVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcInBDb2VmXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiaVwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IFFYID0gYy5nZXRMb2NhbChcInBRXCIpO1xuXG4gICAgICAgIGNvbnN0IHBSID0gbW9kdWxlLmFsbG9jKGYyc2l6ZSozKTtcbiAgICAgICAgY29uc3QgUiA9IGMuaTMyX2NvbnN0KHBSKTtcbiAgICAgICAgY29uc3QgUlggPSBjLmkzMl9jb25zdChwUik7XG4gICAgICAgIGNvbnN0IFJZID0gYy5pMzJfY29uc3QocFIrZjJzaXplKTtcbiAgICAgICAgY29uc3QgUlogPSBjLmkzMl9jb25zdChwUisyKmYyc2l6ZSk7XG5cbiAgICAgICAgY29uc3QgY1FYID0gYy5pMzJfYWRkKCBjLmdldExvY2FsKFwicHByZVFcIiksIGMuaTMyX2NvbnN0KDApKTtcbiAgICAgICAgY29uc3QgY1FZID0gYy5pMzJfYWRkKCBjLmdldExvY2FsKFwicHByZVFcIiksIGMuaTMyX2NvbnN0KGYyc2l6ZSkpO1xuXG4gICAgICAgIGNvbnN0IHBRMSA9IG1vZHVsZS5hbGxvYyhmMnNpemUqMyk7XG4gICAgICAgIGNvbnN0IFExID0gYy5pMzJfY29uc3QocFExKTtcblxuICAgICAgICBjb25zdCBwUTIgPSBtb2R1bGUuYWxsb2MoZjJzaXplKjMpO1xuICAgICAgICBjb25zdCBRMiA9IGMuaTMyX2NvbnN0KHBRMik7XG4gICAgICAgIGNvbnN0IFEyWSA9IGMuaTMyX2NvbnN0KHBRMiArIGYyc2l6ZSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5jYWxsKGcybVByZWZpeCArIFwiX25vcm1hbGl6ZVwiLCBRWCwgY1FYKSwgIC8vIFRPRE8gUmVtb3ZlIGlmIGFscmVhZHkgaW4gYWZmaW5lXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfY29weVwiLCBjUVgsIFJYKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9jb3B5XCIsIGNRWSwgUlkpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX29uZVwiLCBSWiksXG4gICAgICAgICk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcInBDb2VmXCIsIGMuaTMyX2FkZCggYy5nZXRMb2NhbChcInBwcmVRXCIpLCBjLmkzMl9jb25zdChmMnNpemUqMykpKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpXCIsIGMuaTMyX2NvbnN0KGF0ZUxvb3BCaXRCeXRlcy5sZW5ndGgtMikpLFxuICAgICAgICAgICAgYy5ibG9jayhjLmxvb3AoXG5cbiAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfcHJlcERibFN0ZXBcIiwgUiwgYy5nZXRMb2NhbChcInBDb2VmXCIpKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwicENvZWZcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwQ29lZlwiKSwgYy5pMzJfY29uc3QoYXRlQ29lZlNpemUpKSksXG5cbiAgICAgICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9sb2FkOF9zKGMuZ2V0TG9jYWwoXCJpXCIpLCBwQXRlTG9vcEJpdEJ5dGVzKSxcbiAgICAgICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAgICAgLi4uYy5jYWxsKHByZWZpeCArIFwiX3ByZXBBZGRTdGVwXCIsIGNRWCwgUiwgYy5nZXRMb2NhbChcInBDb2VmXCIpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuc2V0TG9jYWwoXCJwQ29lZlwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInBDb2VmXCIpLCBjLmkzMl9jb25zdChhdGVDb2VmU2l6ZSkpKSxcbiAgICAgICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgYy5icl9pZigxLCBjLmkzMl9lcXogKCBjLmdldExvY2FsKFwiaVwiKSApKSxcbiAgICAgICAgICAgICAgICBjLnNldExvY2FsKFwiaVwiLCBjLmkzMl9zdWIoYy5nZXRMb2NhbChcImlcIiksIGMuaTMyX2NvbnN0KDEpKSksXG4gICAgICAgICAgICAgICAgYy5icigwKVxuICAgICAgICAgICAgKSlcbiAgICAgICAgKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfbXVsQnlRXCIsIGNRWCwgUTEpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX211bEJ5UVwiLCBRMSwgUTIpXG4gICAgICAgICk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX25lZ1wiLCBRMlksIFEyWSksXG5cbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9wcmVwQWRkU3RlcFwiLCBRMSwgUiwgYy5nZXRMb2NhbChcInBDb2VmXCIpKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJwQ29lZlwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInBDb2VmXCIpLCBjLmkzMl9jb25zdChhdGVDb2VmU2l6ZSkpKSxcblxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX3ByZXBBZGRTdGVwXCIsIFEyLCBSLCBjLmdldExvY2FsKFwicENvZWZcIikpLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcInBDb2VmXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwicENvZWZcIiksIGMuaTMyX2NvbnN0KGF0ZUNvZWZTaXplKSkpLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkTXVsQnkwMjRPbGQoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4KyBcIl9fbXVsQnkwMjRPbGRcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwRWxsMFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInBFbGxWV1wiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInBFbGxWVlwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInBSXCIsIFwiaTMyXCIpOyAgICAgICAgICAgIC8vIFJlc3VsdCBpbiBGMTJcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IHgwICA9IGMuZ2V0TG9jYWwoXCJwRWxsMFwiKTtcbiAgICAgICAgY29uc3QgeDIgID0gYy5nZXRMb2NhbChcInBFbGxWVlwiKTtcbiAgICAgICAgY29uc3QgeDQgID0gYy5nZXRMb2NhbChcInBFbGxWV1wiKTtcblxuICAgICAgICBjb25zdCB6MCAgPSBjLmdldExvY2FsKFwicFJcIik7XG5cbiAgICAgICAgY29uc3QgcEFVWDEyID0gbW9kdWxlLmFsbG9jKGZ0c2l6ZSk7XG4gICAgICAgIGNvbnN0IEFVWDEyID0gYy5pMzJfY29uc3QocEFVWDEyKTtcbiAgICAgICAgY29uc3QgQVVYMTJfMCA9IGMuaTMyX2NvbnN0KHBBVVgxMik7XG4gICAgICAgIGNvbnN0IEFVWDEyXzIgPSBjLmkzMl9jb25zdChwQVVYMTIrZjJzaXplKTtcbiAgICAgICAgY29uc3QgQVVYMTJfNCA9IGMuaTMyX2NvbnN0KHBBVVgxMitmMnNpemUqMik7XG4gICAgICAgIGNvbnN0IEFVWDEyXzYgPSBjLmkzMl9jb25zdChwQVVYMTIrZjJzaXplKjMpO1xuICAgICAgICBjb25zdCBBVVgxMl84ID0gYy5pMzJfY29uc3QocEFVWDEyK2Yyc2l6ZSo0KTtcbiAgICAgICAgY29uc3QgQVVYMTJfMTAgPSBjLmkzMl9jb25zdChwQVVYMTIrZjJzaXplKjUpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcblxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2NvcHlcIiwgeDAsIEFVWDEyXzApLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3plcm9cIiwgQVVYMTJfMiksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfY29weVwiLCB4MiwgQVVYMTJfNCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfemVyb1wiLCBBVVgxMl82KSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9jb3B5XCIsIHg0LCBBVVgxMl84KSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl96ZXJvXCIsIEFVWDEyXzEwKSxcbiAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9tdWxcIiwgQVVYMTIsIHowLCB6MCksXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRNdWxCeTAyNCgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrIFwiX19tdWxCeTAyNFwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInBFbGwwXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicEVsbFZXXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicEVsbFZWXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicFJcIiwgXCJpMzJcIik7ICAgICAgICAgICAgLy8gUmVzdWx0IGluIEYxMlxuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgeDAgID0gYy5nZXRMb2NhbChcInBFbGwwXCIpO1xuICAgICAgICBjb25zdCB4MiAgPSBjLmdldExvY2FsKFwicEVsbFZWXCIpO1xuICAgICAgICBjb25zdCB4NCAgPSBjLmdldExvY2FsKFwicEVsbFZXXCIpO1xuXG4gICAgICAgIGNvbnN0IHowICA9IGMuZ2V0TG9jYWwoXCJwUlwiKTtcbiAgICAgICAgY29uc3QgejEgID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwUlwiKSwgYy5pMzJfY29uc3QoMipuOCkpO1xuICAgICAgICBjb25zdCB6MiAgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInBSXCIpLCBjLmkzMl9jb25zdCg0Km44KSk7XG4gICAgICAgIGNvbnN0IHozICA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicFJcIiksIGMuaTMyX2NvbnN0KDYqbjgpKTtcbiAgICAgICAgY29uc3QgejQgID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwUlwiKSwgYy5pMzJfY29uc3QoOCpuOCkpO1xuICAgICAgICBjb25zdCB6NSAgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInBSXCIpLCBjLmkzMl9jb25zdCgxMCpuOCkpO1xuXG4gICAgICAgIGNvbnN0IHQwID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCB0MSA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcbiAgICAgICAgY29uc3QgdDIgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjJzaXplKSk7XG4gICAgICAgIGNvbnN0IHMwID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCBUMyA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcbiAgICAgICAgY29uc3QgVDQgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjJzaXplKSk7XG4gICAgICAgIGNvbnN0IEQwID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCBEMiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcbiAgICAgICAgY29uc3QgRDQgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjJzaXplKSk7XG4gICAgICAgIGNvbnN0IFMxID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCBBVVggPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjJzaXplKSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuXG4gICAgICAgICAgICAvLyBEMCA9IHowICogeDA7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIHowLCB4MCwgRDApLFxuICAgICAgICAgICAgLy8gRDIgPSB6MiAqIHgyO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCB6MiwgeDIsIEQyKSxcbiAgICAgICAgICAgIC8vIEQ0ID0gejQgKiB4NDtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgejQsIHg0LCBENCksXG4gICAgICAgICAgICAvLyB0MiA9IHowICsgejQ7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIHowLCB6NCwgdDIpLFxuICAgICAgICAgICAgLy8gdDEgPSB6MCArIHoyO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB6MCwgejIsIHQxKSxcbiAgICAgICAgICAgIC8vIHMwID0gejEgKyB6MyArIHo1O1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB6MSwgejMsIHMwKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgczAsIHo1LCBzMCksXG5cblxuICAgICAgICAgICAgLy8gRm9yIHouYV8uYV8gPSB6MC5cbiAgICAgICAgICAgIC8vIFMxID0gejEgKiB4MjtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgejEsIHgyLCBTMSksXG4gICAgICAgICAgICAvLyBUMyA9IFMxICsgRDQ7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIFMxLCBENCwgVDMpLFxuICAgICAgICAgICAgLy8gVDQgPSBteV9GcDY6Om5vbl9yZXNpZHVlICogVDMgKyBEMDtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgYy5pMzJfY29uc3QocE5vblJlc2lkdWVGNiksIFQzLCBUNCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIFQ0LCBEMCwgejApLFxuICAgICAgICAgICAgLy8gejAgPSBUNDtcblxuICAgICAgICAgICAgLy8gRm9yIHouYV8uYl8gPSB6MVxuICAgICAgICAgICAgLy8gVDMgPSB6NSAqIHg0O1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCB6NSwgeDQsIFQzKSxcbiAgICAgICAgICAgIC8vIFMxID0gUzEgKyBUMztcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgUzEsIFQzLCBTMSksXG4gICAgICAgICAgICAvLyBUMyA9IFQzICsgRDI7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIFQzLCBEMiwgVDMpLFxuICAgICAgICAgICAgLy8gVDQgPSBteV9GcDY6Om5vbl9yZXNpZHVlICogVDM7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIGMuaTMyX2NvbnN0KHBOb25SZXNpZHVlRjYpLCBUMywgVDQpLFxuICAgICAgICAgICAgLy8gVDMgPSB6MSAqIHgwO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCB6MSwgeDAsIFQzKSxcbiAgICAgICAgICAgIC8vIFMxID0gUzEgKyBUMztcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgUzEsIFQzLCBTMSksXG4gICAgICAgICAgICAvLyBUNCA9IFQ0ICsgVDM7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIFQ0LCBUMywgejEpLFxuICAgICAgICAgICAgLy8gejEgPSBUNDtcblxuXG5cbiAgICAgICAgICAgIC8vIEZvciB6LmFfLmNfID0gejJcbiAgICAgICAgICAgIC8vIHQwID0geDAgKyB4MjtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgeDAsIHgyLCB0MCksXG4gICAgICAgICAgICAvLyBUMyA9IHQxICogdDAgLSBEMCAtIEQyO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCB0MSwgdDAsIFQzKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgRDAsIEQyLCBBVVgpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3N1YlwiLCBUMywgQVVYLCBUMyksXG4gICAgICAgICAgICAvLyBUNCA9IHozICogeDQ7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIHozLCB4NCwgVDQpLFxuICAgICAgICAgICAgLy8gUzEgPSBTMSArIFQ0O1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCBTMSwgVDQsIFMxKSxcblxuXG4gICAgICAgICAgICAvLyBGb3Igei5iXy5hXyA9IHozICh6MyBuZWVkcyB6MilcbiAgICAgICAgICAgIC8vIHQwID0gejIgKyB6NDtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgejIsIHo0LCB0MCksXG4gICAgICAgICAgICAvLyBUMyA9IFQzICsgVDQ7XG4gICAgICAgICAgICAvLyB6MiA9IFQzO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCBUMywgVDQsIHoyKSxcbiAgICAgICAgICAgIC8vIHQxID0geDIgKyB4NDtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgeDIsIHg0LCB0MSksXG4gICAgICAgICAgICAvLyBUMyA9IHQwICogdDEgLSBEMiAtIEQ0O1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCB0MSwgdDAsIFQzKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgRDIsIEQ0LCBBVVgpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3N1YlwiLCBUMywgQVVYLCBUMyksXG4gICAgICAgICAgICAvLyBUNCA9IG15X0ZwNjo6bm9uX3Jlc2lkdWUgKiBUMztcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgYy5pMzJfY29uc3QocE5vblJlc2lkdWVGNiksIFQzLCBUNCksXG4gICAgICAgICAgICAvLyBUMyA9IHozICogeDA7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIHozLCB4MCwgVDMpLFxuICAgICAgICAgICAgLy8gUzEgPSBTMSArIFQzO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCBTMSwgVDMsIFMxKSxcbiAgICAgICAgICAgIC8vIFQ0ID0gVDQgKyBUMztcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgVDQsIFQzLCB6MyksXG4gICAgICAgICAgICAvLyB6MyA9IFQ0O1xuXG4gICAgICAgICAgICAvLyBGb3Igei5iXy5iXyA9IHo0XG4gICAgICAgICAgICAvLyBUMyA9IHo1ICogeDI7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIHo1LCB4MiwgVDMpLFxuICAgICAgICAgICAgLy8gUzEgPSBTMSArIFQzO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCBTMSwgVDMsIFMxKSxcbiAgICAgICAgICAgIC8vIFQ0ID0gbXlfRnA2Ojpub25fcmVzaWR1ZSAqIFQzO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCBjLmkzMl9jb25zdChwTm9uUmVzaWR1ZUY2KSwgVDMsIFQ0KSxcbiAgICAgICAgICAgIC8vIHQwID0geDAgKyB4NDtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgeDAsIHg0LCB0MCksXG4gICAgICAgICAgICAvLyBUMyA9IHQyICogdDAgLSBEMCAtIEQ0O1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCB0MiwgdDAsIFQzKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgRDAsIEQ0LCBBVVgpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3N1YlwiLCBUMywgQVVYLCBUMyksXG4gICAgICAgICAgICAvLyBUNCA9IFQ0ICsgVDM7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIFQ0LCBUMywgejQpLFxuICAgICAgICAgICAgLy8gejQgPSBUNDtcblxuICAgICAgICAgICAgLy8gRm9yIHouYl8uY18gPSB6NS5cbiAgICAgICAgICAgIC8vIHQwID0geDAgKyB4MiArIHg0O1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB4MCwgeDIsIHQwKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgdDAsIHg0LCB0MCksXG4gICAgICAgICAgICAvLyBUMyA9IHMwICogdDAgLSBTMTtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgczAsIHQwLCBUMyksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3ViXCIsIFQzLCBTMSwgejUpLFxuICAgICAgICAgICAgLy8gejUgPSBUMztcblxuICAgICAgICApO1xuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gYnVpbGRNaWxsZXJMb29wKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCsgXCJfbWlsbGVyTG9vcFwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInBwcmVQXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicHByZVFcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwicENvZWZcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJpXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgcHJlUF9QWCA9IGMuZ2V0TG9jYWwoXCJwcHJlUFwiKTtcbiAgICAgICAgY29uc3QgcHJlUF9QWSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicHByZVBcIiksIGMuaTMyX2NvbnN0KGYxc2l6ZSkpO1xuXG4gICAgICAgIGNvbnN0IEVMTF8wICA9IGMuZ2V0TG9jYWwoXCJwQ29lZlwiKTtcbiAgICAgICAgY29uc3QgRUxMX1ZXID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwQ29lZlwiKSwgYy5pMzJfY29uc3QoZjJzaXplKSk7XG4gICAgICAgIGNvbnN0IEVMTF9WViAgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInBDb2VmXCIpLCBjLmkzMl9jb25zdCgyKmYyc2l6ZSkpO1xuXG5cbiAgICAgICAgY29uc3QgcFZXID0gbW9kdWxlLmFsbG9jKGYyc2l6ZSk7XG4gICAgICAgIGNvbnN0IFZXID0gYy5pMzJfY29uc3QocFZXKTtcbiAgICAgICAgY29uc3QgcFZWID0gbW9kdWxlLmFsbG9jKGYyc2l6ZSk7XG4gICAgICAgIGNvbnN0IFZWID0gYy5pMzJfY29uc3QocFZWKTtcblxuICAgICAgICBjb25zdCBGID0gYy5nZXRMb2NhbChcInJcIik7XG5cblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfb25lXCIsIEYpLFxuXG4gICAgICAgICAgICBjLnNldExvY2FsKFwicENvZWZcIiwgYy5pMzJfYWRkKCBjLmdldExvY2FsKFwicHByZVFcIiksIGMuaTMyX2NvbnN0KGYyc2l6ZSozKSkpLFxuXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiaVwiLCBjLmkzMl9jb25zdChhdGVMb29wQml0Qnl0ZXMubGVuZ3RoLTIpKSxcbiAgICAgICAgICAgIGMuYmxvY2soYy5sb29wKFxuXG5cbiAgICAgICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfc3F1YXJlXCIsIEYsIEYpLFxuXG4gICAgICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bDFcIiwgRUxMX1ZXLHByZVBfUFksIFZXKSxcbiAgICAgICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsMVwiLCBFTExfVlYsIHByZVBfUFgsIFZWKSxcbiAgICAgICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfX211bEJ5MDI0XCIsIEVMTF8wLCBWVywgVlYsIEYpLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJwQ29lZlwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInBDb2VmXCIpLCBjLmkzMl9jb25zdChhdGVDb2VmU2l6ZSkpKSxcblxuICAgICAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2xvYWQ4X3MoYy5nZXRMb2NhbChcImlcIiksIHBBdGVMb29wQml0Qnl0ZXMpLFxuICAgICAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsMVwiLCBFTExfVlcsIHByZVBfUFksIFZXKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWwxXCIsIEVMTF9WViwgcHJlUF9QWCwgVlYpLFxuXG4gICAgICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwocHJlZml4ICsgXCJfX211bEJ5MDI0XCIsIEVMTF8wLCBWVywgVlYsIEYpLFxuICAgICAgICAgICAgICAgICAgICAgICAgLi4uYy5zZXRMb2NhbChcInBDb2VmXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwicENvZWZcIiksIGMuaTMyX2NvbnN0KGF0ZUNvZWZTaXplKSkpLFxuXG4gICAgICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGMuYnJfaWYoMSwgYy5pMzJfZXF6ICggYy5nZXRMb2NhbChcImlcIikgKSksXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcImlcIiwgYy5pMzJfc3ViKGMuZ2V0TG9jYWwoXCJpXCIpLCBjLmkzMl9jb25zdCgxKSkpLFxuICAgICAgICAgICAgICAgIGMuYnIoMClcbiAgICAgICAgICAgICkpXG5cbiAgICAgICAgKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsMVwiLCBFTExfVlcsIHByZVBfUFksIFZXKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWwxXCIsIEVMTF9WViwgcHJlUF9QWCwgVlYpLFxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX19tdWxCeTAyNFwiLCBFTExfMCwgVlcsIFZWLCBGKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJwQ29lZlwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInBDb2VmXCIpLCBjLmkzMl9jb25zdChhdGVDb2VmU2l6ZSkpKSxcblxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bDFcIiwgRUxMX1ZXLCBwcmVQX1BZLCBWVyksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsMVwiLCBFTExfVlYsIHByZVBfUFgsIFZWKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9fbXVsQnkwMjRcIiwgRUxMXzAsIFZXLCBWViwgRiksXG4gICAgICAgICAgICBjLnNldExvY2FsKFwicENvZWZcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwQ29lZlwiKSwgYy5pMzJfY29uc3QoYXRlQ29lZlNpemUpKSksXG5cbiAgICAgICAgKTtcblxuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gYnVpbGRGcm9iZW5pdXNNYXAobikge1xuICAgICAgICBjb25zdCBGMTIgPSBbXG4gICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgWzFuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzFuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzFuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzFuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzFuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzFuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzFuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzFuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzFuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzFuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzFuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzFuLCAwbl0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgIFsxbiwgMG5dLFxuICAgICAgICAgICAgICAgIFs4Mzc2MTE4ODY1NzYzODIxNDk2NTgzOTczODY3NjI2MzY0MDkyNTg5OTA2MDY1ODY4Mjk4Nzc2OTA5NjE3OTE2MDE4NzY4MzQwMDgwbiwgMTY0Njk4MjMzMjMwNzc4MDgyMjM4ODkxMzcyNDExNzY1MzY3OTkwMDkyODY2NDYxMDgxNjk5MzU2NTkzMDE2MTM5NjE3MTIxOTgzMTZuXSxcbiAgICAgICAgICAgICAgICBbMjE4ODgyNDI4NzE4MzkyNzUyMjAwNDI0NDUyNjAxMDkxNTMxNjcyNzc3MDc0MTQ0NzIwNjE2NDE3MTQ3NTg2MzU3NjUwMjA1NTY2MTduLCAwbl0sXG4gICAgICAgICAgICAgICAgWzExNjk3NDIzNDk2MzU4MTU0MzA0ODI1NzgyOTIyNTg0NzI1MzEyOTEyMzgzNDQxMTU5NTA1MDM4Nzk0MDI3MTA1Nzc4OTU0MTg0MzE5biwgMzAzODQ3Mzg5MTM1MDY1ODg3NDIyNzgzNDU0ODc3NjA5OTQxNDU2MzQ5MTg4OTE5NzE5MjcyMzQ1MDgzOTU0NDM3ODYwNDA5NjAxbl0sXG4gICAgICAgICAgICAgICAgWzIxODg4MjQyODcxODM5Mjc1MjIwMDQyNDQ1MjYwMTA5MTUzMTY3Mjc3NzA3NDE0NDcyMDYxNjQxNzE0NzU4NjM1NzY1MDIwNTU2NjE2biwgMG5dLFxuICAgICAgICAgICAgICAgIFszMzIxMzA0NjMwNTk0MzMyODA4MjQxODA5MDU0OTU4MzYxMjIwMzIyNDc3Mzc1MjkxMjA2MjYxODg0NDA5MTg5NzYwMTg1ODQ0MjM5biwgNTcyMjI2NjkzNzg5NjUzMjg4NTc4MDA1MTk1ODk1ODM0ODIzMTE0MzM3MzcwMDEwOTM3Mjk5OTM3NDgyMDIzNTEyMTM3NDQxOTg2OG5dLFxuICAgICAgICAgICAgICAgIFsyMTg4ODI0Mjg3MTgzOTI3NTIyMjI0NjQwNTc0NTI1NzI3NTA4ODY5NjMxMTE1NzI5NzgyMzY2MjY4OTAzNzg5NDY0NTIyNjIwODU4Mm4sIDBuXSxcbiAgICAgICAgICAgICAgICBbMTM1MTIxMjQwMDYwNzU0NTM3MjU2NjI0MzE4Nzc2MzA5MTA5OTYxMDY0MDUwOTE0Mjk1MjQ4ODU3Nzk0MTk5Nzg2MjY0NTc4Njg1MDNuLCA1NDE4NDE5NTQ4NzYxNDY2OTk4MzU3MjY4NTA0MDgwNzM4Mjg5Njg3MDI0NTExMTg5NjUzNzI3MDI5NzM2MjgwNjgzNTE0MDEwMjY3bl0sXG4gICAgICAgICAgICAgICAgWzIyMDM5NjA0ODUxNDgxMjE5MjE0MTg2MDM3NDI4MjU3NjIwMjA5NzQyNzkyNTg4ODAyMDU2NTE5NjZuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzEwMTkwODE5Mzc1NDgxMTIwOTE3NDIwNjIyODIyNjcyNTQ5Nzc1NzgzOTI3NzE2MTM4MzE4NjIzODk1MDEwNzg4ODY2MjcyMDI0MjY0biwgMjE1ODQzOTU0ODI3MDQyMDkzMzQ4MjM2MjIyOTAzNzk2NjUxNDcyMzk5NjE5NjgzNzgxMDQzOTAzNDM5NTM5NDAyMDczNjU3OTg5ODJuXSxcbiAgICAgICAgICAgICAgICBbMjIwMzk2MDQ4NTE0ODEyMTkyMTQxODYwMzc0MjgyNTc2MjAyMDk3NDI3OTI1ODg4MDIwNTY1MTk2N24sIDBuXSxcbiAgICAgICAgICAgICAgICBbMTg1NjY5MzgyNDEyNDQ5NDI0MTQwMDQ1OTY2OTAyOTg5MTM4NjgzNzM4MzM3ODIwMDY2MTc0MDA4MDQ2Mjg3MDQ4ODUwNDAzNjQzNDRuLCAxNjE2NTk3NTkzMzk0Mjc0MjMzNjQ2NjM1Mzc4NjI5ODkyNjg1NzU1MjkzNzQ1NzE4ODQ1MDY2MzMxNDIxNzY1OTUyMzg1MTc4ODcxNW5dLFxuICAgICAgICAgICAgXVxuICAgICAgICBdO1xuXG4gICAgICAgIGNvbnN0IEY2ID0gW1xuICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgIFsxbiwgMG5dLFxuICAgICAgICAgICAgICAgIFsxbiwgMG5dLFxuICAgICAgICAgICAgICAgIFsxbiwgMG5dLFxuICAgICAgICAgICAgICAgIFsxbiwgMG5dLFxuICAgICAgICAgICAgICAgIFsxbiwgMG5dLFxuICAgICAgICAgICAgICAgIFsxbiwgMG5dLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICBbMW4sIDBuXSxcbiAgICAgICAgICAgICAgICBbMjE1NzU0NjM2MzgyODA4NDMwMTAzOTgzMjQyNjk0MzA4MjYwOTkyNjkwNDQyNzQzNDcyMTY4MjcyMTI2MTM4Njc4MzY0MzUwMjcyNjFuLCAxMDMwNzYwMTU5NTg3MzcwOTcwMDE1MjI4NDI3MzgxNjExMjI2NDA2OTIzMDEzMDYxNjQzNjc1NTYyNTE5NDg1NDgxNTg3NTcxMzk1NG5dLFxuICAgICAgICAgICAgICAgIFsyMTg4ODI0Mjg3MTgzOTI3NTIyMDA0MjQ0NTI2MDEwOTE1MzE2NzI3NzcwNzQxNDQ3MjA2MTY0MTcxNDc1ODYzNTc2NTAyMDU1NjYxNm4sIDBuXSxcbiAgICAgICAgICAgICAgICBbMzc3MjAwMDg4MTkxOTg1Mzc3NjQzMzY5NTE4NjcxMzg1ODIzOTAwOTA3MzU5MzgxNzE5NTc3MTc3MzM4MTkxOTMxNjQxOTM0NTI2MW4sIDIyMzY1OTU0OTU5NjcyNDUxODgyODE3MDEyNDgyMDMxODE3OTUxMjEwNjg5MDI2MDU4NjEyMjc4NTUyNjExMzc4MjA5NDQwMDg5MjZuXSxcbiAgICAgICAgICAgICAgICBbMjIwMzk2MDQ4NTE0ODEyMTkyMTQxODYwMzc0MjgyNTc2MjAyMDk3NDI3OTI1ODg4MDIwNTY1MTk2Nm4sIDBuXSxcbiAgICAgICAgICAgICAgICBbMTg0MjkwMjEyMjM0Nzc4NTM2NTc2NjA3OTIwMzQzNjk4NjU4MzkxMTQ1MDQ0NDY0MzEyMzQ3MjYzOTIwODAwMDIxMzc1OTgwNDQ2NDRuLCA5MzQ0MDQ1Nzc5OTk4MzIwMzMzODEyNDIwMjIzMjM3OTgxMDI5NTA2MDEyMTI0MDc1NTI1Njc5MjA4NTgxOTAyMDA4NDA2NDg1NzAzbl0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgIFsxbiwgMG5dLFxuICAgICAgICAgICAgICAgIFsyNTgxOTExMzQ0NDY3MDA5MzM1MjY3MzExMTE1NDY4ODAzMDk5NTUxNjY1NjA1MDc2MTk2NzQwODY3ODA1MjU4NTY4MjM0MzQ2MzM4biwgMTk5Mzc3NTY5NzE3NzU2NDc5ODc5OTU5MzIxNjk5MjkzNDE5OTQzMTQ2NDA2NTI5NjQ5NDk0NDgzMTMzNzQ0NzI0MDA3MTY2NjEwMzBuXSxcbiAgICAgICAgICAgICAgICBbMjIwMzk2MDQ4NTE0ODEyMTkyMTQxODYwMzc0MjgyNTc2MjAyMDk3NDI3OTI1ODg4MDIwNTY1MTk2Nm4sIDBuXSxcbiAgICAgICAgICAgICAgICBbNTMyNDQ3OTIwMjQ0OTkwMzU0MjcyNjc4MzM5NTUwNjIxNDQ4MTkyODI1Nzc2MjQwMDY0MzI3OTc4MDM0MzM2ODU1NzI5NzEzNTcxOG4sIDE2MjA4OTAwMzgwNzM3NjkzMDg0OTE5NDk1MTI3MzM0Mzg3OTgxMzkzNzI2NDE5ODU2ODg4Nzk5OTE3OTE0MTgwOTg4ODQ0MTIzMDM5bl0sXG4gICAgICAgICAgICAgICAgWzIxODg4MjQyODcxODM5Mjc1MjIwMDQyNDQ1MjYwMTA5MTUzMTY3Mjc3NzA3NDE0NDcyMDYxNjQxNzE0NzU4NjM1NzY1MDIwNTU2NjE2biwgMG5dLFxuICAgICAgICAgICAgICAgIFsxMzk4MTg1MjMyNDkyMjM2MjM0NDI1MjMxMTIzNDI4MjI1NzUwNzIxNjM4Nzc4OTgyMDk4MzY0MjA0MDg4OTI2NzUxOTY5NDcyNjUyN24sIDc2Mjk4MjgzOTExNjUyMDkzNzE1NzczODQxOTMyNTA4MjAyMDE2ODQyNTUyNDE3NzM4MDkwNzcxNDY3ODcxMzU5MDA4OTE2MzMwOTduXSxcbiAgICAgICAgICAgIF1cbiAgICAgICAgXTtcblxuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCsgXCJfX2Zyb2Jlbml1c01hcFwiK24pO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBmb3IgKGxldCBpPTA7IGk8NjsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBYID0gKGk9PTApID8gYy5nZXRMb2NhbChcInhcIikgOiBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KGkqZjJzaXplKSk7XG4gICAgICAgICAgICBjb25zdCBYYzAgPSBYO1xuICAgICAgICAgICAgY29uc3QgWGMxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdChpKmYyc2l6ZSArIGYxc2l6ZSkpO1xuICAgICAgICAgICAgY29uc3QgUiA9IChpPT0wKSA/IGMuZ2V0TG9jYWwoXCJyXCIpIDogYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJyXCIpLCBjLmkzMl9jb25zdChpKmYyc2l6ZSkpO1xuICAgICAgICAgICAgY29uc3QgUmMwID0gUjtcbiAgICAgICAgICAgIGNvbnN0IFJjMSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwiclwiKSwgYy5pMzJfY29uc3QoaSpmMnNpemUgKyBmMXNpemUpKTtcbiAgICAgICAgICAgIGNvbnN0IGNvZWYgPSBtdWwyKEYxMltNYXRoLmZsb29yKGkvMyldW24lMTJdICwgRjZbaSUzXVtuJTZdKTtcbiAgICAgICAgICAgIGNvbnN0IHBDb2VmID0gbW9kdWxlLmFsbG9jKFtcbiAgICAgICAgICAgICAgICAuLi51dGlscyQxLmJpZ0ludDJCeXRlc0xFKHRvTW9udGdvbWVyeShjb2VmWzBdKSwgMzIpLFxuICAgICAgICAgICAgICAgIC4uLnV0aWxzJDEuYmlnSW50MkJ5dGVzTEUodG9Nb250Z29tZXJ5KGNvZWZbMV0pLCAzMiksXG4gICAgICAgICAgICBdKTtcbiAgICAgICAgICAgIGlmIChuJTIgPT0gMSkge1xuICAgICAgICAgICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCArIFwiX2NvcHlcIiwgWGMwLCBSYzApLFxuICAgICAgICAgICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4ICsgXCJfbmVnXCIsIFhjMSwgUmMxKSxcbiAgICAgICAgICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCBSLCBjLmkzMl9jb25zdChwQ29lZiksIFIpLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGYuYWRkQ29kZShjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIFgsIGMuaTMyX2NvbnN0KHBDb2VmKSwgUikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gbXVsMihhLCBiKSB7XG4gICAgICAgICAgICBjb25zdCBhYzAgPSBCaWdJbnQoYVswXSk7XG4gICAgICAgICAgICBjb25zdCBhYzEgPSBCaWdJbnQoYVsxXSk7XG4gICAgICAgICAgICBjb25zdCBiYzAgPSBCaWdJbnQoYlswXSk7XG4gICAgICAgICAgICBjb25zdCBiYzEgPSBCaWdJbnQoYlsxXSk7XG4gICAgICAgICAgICBjb25zdCByZXMgPSBbXG4gICAgICAgICAgICAgICAgKGFjMCAqIGJjMCAtICggIGFjMSAqIGJjMSkgICkgJSBxLFxuICAgICAgICAgICAgICAgIChhYzAgKiBiYzEgKyAoICBhYzEgKiBiYzApICApICUgcSxcbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBpZiAoaXNOZWdhdGl2ZSQyKHJlc1swXSkpIHJlc1swXSA9IHJlc1swXSArIHE7XG4gICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9XG5cbiAgICB9XG5cblxuXG4gICAgZnVuY3Rpb24gYnVpbGRGaW5hbEV4cG9uZW50aWF0aW9uRmlyc3RDaHVuaygpIHtcblxuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCsgXCJfX2ZpbmFsRXhwb25lbnRpYXRpb25GaXJzdENodW5rXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCBlbHQgPSBjLmdldExvY2FsKFwieFwiKTtcbiAgICAgICAgY29uc3QgZWx0QzAgPSBlbHQ7XG4gICAgICAgIGNvbnN0IGVsdEMxID0gYy5pMzJfYWRkKGVsdCwgYy5pMzJfY29uc3QobjgqNikpO1xuICAgICAgICBjb25zdCByID0gYy5nZXRMb2NhbChcInJcIik7XG4gICAgICAgIGNvbnN0IHBBID0gbW9kdWxlLmFsbG9jKGZ0c2l6ZSk7XG4gICAgICAgIGNvbnN0IEEgPSBjLmkzMl9jb25zdChwQSk7XG4gICAgICAgIGNvbnN0IEFjMCA9IEE7XG4gICAgICAgIGNvbnN0IEFjMSA9IGMuaTMyX2NvbnN0KHBBICsgbjgqNik7XG4gICAgICAgIGNvbnN0IEIgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IEMgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IEQgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgLy8gY29uc3QgYWx0X2JuMTI4X0ZxMTIgQSA9IGFsdF9ibjEyOF9GcTEyKGVsdC5jMCwtZWx0LmMxKTtcbiAgICAgICAgICAgIGMuY2FsbChmNm1QcmVmaXggKyBcIl9jb3B5XCIsIGVsdEMwLCBBYzApLFxuICAgICAgICAgICAgYy5jYWxsKGY2bVByZWZpeCArIFwiX25lZ1wiLCBlbHRDMSwgQWMxKSxcblxuICAgICAgICAgICAgLy8gY29uc3QgYWx0X2JuMTI4X0ZxMTIgQiA9IGVsdC5pbnZlcnNlKCk7XG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfaW52ZXJzZVwiLCBlbHQsIEIpLFxuXG4gICAgICAgICAgICAvLyBjb25zdCBhbHRfYm4xMjhfRnExMiBDID0gQSAqIEI7XG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfbXVsXCIsIEEsIEIsIEMpLFxuICAgICAgICAgICAgLy8gY29uc3QgYWx0X2JuMTI4X0ZxMTIgRCA9IEMuRnJvYmVuaXVzX21hcCgyKTtcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9fZnJvYmVuaXVzTWFwMlwiLCBDLCBEKSxcbiAgICAgICAgICAgIC8vIGNvbnN0IGFsdF9ibjEyOF9GcTEyIHJlc3VsdCA9IEQgKiBDO1xuICAgICAgICAgICAgYy5jYWxsKGZ0bVByZWZpeCArIFwiX211bFwiLCBDLCBELCByKSxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZEN5Y2xvdG9taWNTcXVhcmUoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4KyBcIl9fY3ljbG90b21pY1NxdWFyZVwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgeDAgPSBjLmdldExvY2FsKFwieFwiKTtcbiAgICAgICAgY29uc3QgeDQgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCB4MyA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QoMipmMnNpemUpKTtcbiAgICAgICAgY29uc3QgeDIgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KDMqZjJzaXplKSk7XG4gICAgICAgIGNvbnN0IHgxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdCg0KmYyc2l6ZSkpO1xuICAgICAgICBjb25zdCB4NSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QoNSpmMnNpemUpKTtcblxuICAgICAgICBjb25zdCByMCA9IGMuZ2V0TG9jYWwoXCJyXCIpO1xuICAgICAgICBjb25zdCByNCA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwiclwiKSwgYy5pMzJfY29uc3QoZjJzaXplKSk7XG4gICAgICAgIGNvbnN0IHIzID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJyXCIpLCBjLmkzMl9jb25zdCgyKmYyc2l6ZSkpO1xuICAgICAgICBjb25zdCByMiA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwiclwiKSwgYy5pMzJfY29uc3QoMypmMnNpemUpKTtcbiAgICAgICAgY29uc3QgcjEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInJcIiksIGMuaTMyX2NvbnN0KDQqZjJzaXplKSk7XG4gICAgICAgIGNvbnN0IHI1ID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJyXCIpLCBjLmkzMl9jb25zdCg1KmYyc2l6ZSkpO1xuXG4gICAgICAgIGNvbnN0IHQwID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCB0MSA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcbiAgICAgICAgY29uc3QgdDIgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjJzaXplKSk7XG4gICAgICAgIGNvbnN0IHQzID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCB0NCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcbiAgICAgICAgY29uc3QgdDUgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjJzaXplKSk7XG4gICAgICAgIGNvbnN0IHRtcCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcbiAgICAgICAgY29uc3QgQVVYID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuXG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgLy8gICAgLy8gdDAgKyB0MSp5ID0gKHowICsgejEqeSleMiA9IGFeMlxuICAgICAgICAgICAgLy8gICAgdG1wID0gejAgKiB6MTtcbiAgICAgICAgICAgIC8vICAgIHQwID0gKHowICsgejEpICogKHowICsgbXlfRnA2Ojpub25fcmVzaWR1ZSAqIHoxKSAtIHRtcCAtIG15X0ZwNjo6bm9uX3Jlc2lkdWUgKiB0bXA7XG4gICAgICAgICAgICAvLyAgICB0MSA9IHRtcCArIHRtcDtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgeDAsIHgxLCB0bXApLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCB4MSwgYy5pMzJfY29uc3QocE5vblJlc2lkdWVGNiksIHQwKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgeDAsIHQwLCB0MCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIHgwLCB4MSwgQVVYKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgQVVYLCB0MCwgdDApLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCBjLmkzMl9jb25zdChwTm9uUmVzaWR1ZUY2KSwgdG1wLCBBVVgpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0bXAsIEFVWCwgQVVYKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zdWJcIiwgdDAsIEFVWCwgdDApLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0bXAsIHRtcCwgdDEpLFxuXG4gICAgICAgICAgICAvLyAgLy8gdDIgKyB0Myp5ID0gKHoyICsgejMqeSleMiA9IGJeMlxuICAgICAgICAgICAgLy8gIHRtcCA9IHoyICogejM7XG4gICAgICAgICAgICAvLyAgdDIgPSAoejIgKyB6MykgKiAoejIgKyBteV9GcDY6Om5vbl9yZXNpZHVlICogejMpIC0gdG1wIC0gbXlfRnA2Ojpub25fcmVzaWR1ZSAqIHRtcDtcbiAgICAgICAgICAgIC8vICB0MyA9IHRtcCArIHRtcDtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgeDIsIHgzLCB0bXApLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCB4MywgYy5pMzJfY29uc3QocE5vblJlc2lkdWVGNiksIHQyKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgeDIsIHQyLCB0MiksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIHgyLCB4MywgQVVYKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgQVVYLCB0MiwgdDIpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCBjLmkzMl9jb25zdChwTm9uUmVzaWR1ZUY2KSwgdG1wLCBBVVgpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0bXAsIEFVWCwgQVVYKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zdWJcIiwgdDIsIEFVWCwgdDIpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0bXAsIHRtcCwgdDMpLFxuXG4gICAgICAgICAgICAvLyAgLy8gdDQgKyB0NSp5ID0gKHo0ICsgejUqeSleMiA9IGNeMlxuICAgICAgICAgICAgLy8gIHRtcCA9IHo0ICogejU7XG4gICAgICAgICAgICAvLyAgdDQgPSAoejQgKyB6NSkgKiAoejQgKyBteV9GcDY6Om5vbl9yZXNpZHVlICogejUpIC0gdG1wIC0gbXlfRnA2Ojpub25fcmVzaWR1ZSAqIHRtcDtcbiAgICAgICAgICAgIC8vICB0NSA9IHRtcCArIHRtcDtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgeDQsIHg1LCB0bXApLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCB4NSwgYy5pMzJfY29uc3QocE5vblJlc2lkdWVGNiksIHQ0KSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgeDQsIHQ0LCB0NCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIHg0LCB4NSwgQVVYKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgQVVYLCB0NCwgdDQpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCBjLmkzMl9jb25zdChwTm9uUmVzaWR1ZUY2KSwgdG1wLCBBVVgpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0bXAsIEFVWCwgQVVYKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zdWJcIiwgdDQsIEFVWCwgdDQpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0bXAsIHRtcCwgdDUpLFxuXG4gICAgICAgICAgICAvLyBGb3IgQVxuICAgICAgICAgICAgLy8gejAgPSAzICogdDAgLSAyICogejBcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zdWJcIiwgdDAsIHgwLCByMCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIHIwLCByMCwgcjApLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0MCwgcjAsIHIwKSxcbiAgICAgICAgICAgIC8vIHoxID0gMyAqIHQxICsgMiAqIHoxXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIHQxLCB4MSwgcjEpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCByMSwgcjEsIHIxKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgdDEsIHIxLCByMSksXG5cbiAgICAgICAgICAgIC8vIEZvciBCXG4gICAgICAgICAgICAvLyB6MiA9IDMgKiAoeGkgKiB0NSkgKyAyICogejJcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgdDUsIGMuaTMyX2NvbnN0KHBBbHRCbjEyOFR3aXN0KSwgQVVYKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgQVVYLCB4MiwgcjIpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCByMiwgcjIsIHIyKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgQVVYLCByMiwgcjIpLFxuICAgICAgICAgICAgLy8gejMgPSAzICogdDQgLSAyICogejNcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zdWJcIiwgdDQsIHgzLCByMyksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIHIzLCByMywgcjMpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0NCwgcjMsIHIzKSxcblxuICAgICAgICAgICAgLy8gRm9yIENcbiAgICAgICAgICAgIC8vIHo0ID0gMyAqIHQyIC0gMiAqIHo0XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3ViXCIsIHQyLCB4NCwgcjQpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCByNCwgcjQsIHI0KSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgdDIsIHI0LCByNCksXG4gICAgICAgICAgICAvLyB6NSA9IDMgKiB0MyArIDIgKiB6NVxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0MywgeDUsIHI1KSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgcjUsIHI1LCByNSksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIHQzLCByNSwgcjUpLFxuXG4gICAgICAgICk7XG4gICAgfVxuXG5cbiAgICBmdW5jdGlvbiBidWlsZEN5Y2xvdG9taWNFeHAoZXhwb25lbnQsIGZuTmFtZSkge1xuICAgICAgICBjb25zdCBleHBvbmVudE5hZkJ5dGVzID0gbmFmKGV4cG9uZW50KS5tYXAoIChiKSA9PiAoYj09LTEgPyAweEZGOiBiKSApO1xuICAgICAgICBjb25zdCBwRXhwb25lbnROYWZCeXRlcyA9IG1vZHVsZS5hbGxvYyhleHBvbmVudE5hZkJ5dGVzKTtcblxuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCsgXCJfX2N5Y2xvdG9taWNFeHBfXCIrZm5OYW1lKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiYml0XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiaVwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IHggPSBjLmdldExvY2FsKFwieFwiKTtcblxuICAgICAgICBjb25zdCByZXMgPSBjLmdldExvY2FsKFwiclwiKTtcblxuICAgICAgICBjb25zdCBpbnZlcnNlID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGZ0c2l6ZSkpO1xuXG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5jYWxsKGZ0bVByZWZpeCArIFwiX2Nvbmp1Z2F0ZVwiLCB4LCBpbnZlcnNlKSxcbiAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9vbmVcIiwgcmVzKSxcblxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLnRlZUxvY2FsKFwiYml0XCIsIGMuaTMyX2xvYWQ4X3MoYy5pMzJfY29uc3QoZXhwb25lbnROYWZCeXRlcy5sZW5ndGgtMSksIHBFeHBvbmVudE5hZkJ5dGVzKSksXG4gICAgICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfZXEoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiYml0XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMSlcbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgYy5jYWxsKGZ0bVByZWZpeCArIFwiX211bFwiLCByZXMsIHgsIHJlcyksXG4gICAgICAgICAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9tdWxcIiwgcmVzLCBpbnZlcnNlLCByZXMpLFxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpXCIsIGMuaTMyX2NvbnN0KGV4cG9uZW50TmFmQnl0ZXMubGVuZ3RoLTIpKSxcbiAgICAgICAgICAgIGMuYmxvY2soYy5sb29wKFxuICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9fY3ljbG90b21pY1NxdWFyZVwiLCByZXMsIHJlcyksXG4gICAgICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICAgICAgYy50ZWVMb2NhbChcImJpdFwiLCBjLmkzMl9sb2FkOF9zKGMuZ2V0TG9jYWwoXCJpXCIpLCBwRXhwb25lbnROYWZCeXRlcykpLFxuICAgICAgICAgICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfZXEoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImJpdFwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdCgxKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9tdWxcIiwgcmVzLCB4LCByZXMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5jYWxsKGZ0bVByZWZpeCArIFwiX211bFwiLCByZXMsIGludmVyc2UsIHJlcyksXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGMuYnJfaWYoMSwgYy5pMzJfZXF6ICggYy5nZXRMb2NhbChcImlcIikgKSksXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcImlcIiwgYy5pMzJfc3ViKGMuZ2V0TG9jYWwoXCJpXCIpLCBjLmkzMl9jb25zdCgxKSkpLFxuICAgICAgICAgICAgICAgIGMuYnIoMClcbiAgICAgICAgICAgICkpXG4gICAgICAgICk7XG4gICAgfVxuXG5cblxuICAgIGZ1bmN0aW9uIGJ1aWxkRmluYWxFeHBvbmVudGlhdGlvbkxhc3RDaHVuaygpIHtcbiAgICAgICAgYnVpbGRDeWNsb3RvbWljU3F1YXJlKCk7XG4gICAgICAgIGJ1aWxkQ3ljbG90b21pY0V4cChmaW5hbEV4cFosIFwidzBcIik7XG5cbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrIFwiX19maW5hbEV4cG9uZW50aWF0aW9uTGFzdENodW5rXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCBlbHQgPSBjLmdldExvY2FsKFwieFwiKTtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYy5nZXRMb2NhbChcInJcIik7XG4gICAgICAgIGNvbnN0IEEgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IEIgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IEMgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IEQgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IEUgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IEYgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IEcgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IEggPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IEkgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IEogPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IEsgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IEwgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IE0gPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IE4gPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IE8gPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IFAgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IFEgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IFIgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IFMgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IFQgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IFUgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuXG5cbiAgICAgICAgICAgIC8vIEEgPSBleHBfYnlfbmVnX3ooZWx0KSAgLy8gPSBlbHReKC16KVxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX19jeWNsb3RvbWljRXhwX3cwXCIsIGVsdCwgQSksXG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfY29uanVnYXRlXCIsIEEsIEEpLFxuICAgICAgICAgICAgLy8gQiA9IEFeMiAgICAgICAgICAgICAgICAvLyA9IGVsdF4oLTIqeilcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9fY3ljbG90b21pY1NxdWFyZVwiLCBBLCBCKSxcbiAgICAgICAgICAgIC8vIEMgPSBCXjIgICAgICAgICAgICAgICAgLy8gPSBlbHReKC00KnopXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfX2N5Y2xvdG9taWNTcXVhcmVcIiwgQiwgQyksXG4gICAgICAgICAgICAvLyBEID0gQyAqIEIgICAgICAgICAgICAgIC8vID0gZWx0XigtNip6KVxuICAgICAgICAgICAgYy5jYWxsKGZ0bVByZWZpeCArIFwiX211bFwiLCBDLCBCLCBEKSxcbiAgICAgICAgICAgIC8vIEUgPSBleHBfYnlfbmVnX3ooRCkgICAgLy8gPSBlbHReKDYqel4yKVxuICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX19jeWNsb3RvbWljRXhwX3cwXCIsIEQsIEUpLFxuICAgICAgICAgICAgYy5jYWxsKGZ0bVByZWZpeCArIFwiX2Nvbmp1Z2F0ZVwiLCBFLCBFKSxcbiAgICAgICAgICAgIC8vIEYgPSBFXjIgICAgICAgICAgICAgICAgLy8gPSBlbHReKDEyKnpeMilcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9fY3ljbG90b21pY1NxdWFyZVwiLCBFLCBGKSxcbiAgICAgICAgICAgIC8vIEcgPSBlcHhfYnlfbmVnX3ooRikgICAgLy8gPSBlbHReKC0xMip6XjMpXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfX2N5Y2xvdG9taWNFeHBfdzBcIiwgRiwgRyksXG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfY29uanVnYXRlXCIsIEcsIEcpLFxuICAgICAgICAgICAgLy8gSCA9IGNvbmooRCkgICAgICAgICAgICAvLyA9IGVsdF4oNip6KVxuICAgICAgICAgICAgYy5jYWxsKGZ0bVByZWZpeCArIFwiX2Nvbmp1Z2F0ZVwiLCBELCBIKSxcbiAgICAgICAgICAgIC8vIEkgPSBjb25qKEcpICAgICAgICAgICAgLy8gPSBlbHReKDEyKnpeMylcbiAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9jb25qdWdhdGVcIiwgRywgSSksXG4gICAgICAgICAgICAvLyBKID0gSSAqIEUgICAgICAgICAgICAgIC8vID0gZWx0XigxMip6XjMgKyA2KnpeMilcbiAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9tdWxcIiwgSSwgRSwgSiksXG4gICAgICAgICAgICAvLyBLID0gSiAqIEggICAgICAgICAgICAgIC8vID0gZWx0XigxMip6XjMgKyA2KnpeMiArIDYqeilcbiAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9tdWxcIiwgSiwgSCwgSyksXG4gICAgICAgICAgICAvLyBMID0gSyAqIEIgICAgICAgICAgICAgIC8vID0gZWx0XigxMip6XjMgKyA2KnpeMiArIDQqeilcbiAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9tdWxcIiwgSywgQiwgTCksXG4gICAgICAgICAgICAvLyBNID0gSyAqIEUgICAgICAgICAgICAgIC8vID0gZWx0XigxMip6XjMgKyAxMip6XjIgKyA2KnopXG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfbXVsXCIsIEssIEUsIE0pLFxuXG4gICAgICAgICAgICAvLyBOID0gTSAqIGVsdCAgICAgICAgICAgIC8vID0gZWx0XigxMip6XjMgKyAxMip6XjIgKyA2KnogKyAxKVxuICAgICAgICAgICAgYy5jYWxsKGZ0bVByZWZpeCArIFwiX211bFwiLCBNLCBlbHQsIE4pLFxuXG4gICAgICAgICAgICAvLyBPID0gTC5Gcm9iZW5pdXNfbWFwKDEpIC8vID0gZWx0XihxKigxMip6XjMgKyA2KnpeMiArIDQqeikpXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfX2Zyb2Jlbml1c01hcDFcIiwgTCwgTyksXG4gICAgICAgICAgICAvLyBQID0gTyAqIE4gICAgICAgICAgICAgIC8vID0gZWx0XihxKigxMip6XjMgKyA2KnpeMiArIDQqeikgKiAoMTIqel4zICsgMTIqel4yICsgNip6ICsgMSkpXG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfbXVsXCIsIE8sIE4sIFApLFxuICAgICAgICAgICAgLy8gUSA9IEsuRnJvYmVuaXVzX21hcCgyKSAvLyA9IGVsdF4ocV4yICogKDEyKnpeMyArIDYqel4yICsgNip6KSlcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9fZnJvYmVuaXVzTWFwMlwiLCBLLCBRKSxcbiAgICAgICAgICAgIC8vIFIgPSBRICogUCAgICAgICAgICAgICAgLy8gPSBlbHReKHFeMiAqICgxMip6XjMgKyA2KnpeMiArIDYqeikgKyBxKigxMip6XjMgKyA2KnpeMiArIDQqeikgKiAoMTIqel4zICsgMTIqel4yICsgNip6ICsgMSkpXG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfbXVsXCIsIFEsIFAsIFIpLFxuICAgICAgICAgICAgLy8gUyA9IGNvbmooZWx0KSAgICAgICAgICAvLyA9IGVsdF4oLTEpXG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfY29uanVnYXRlXCIsIGVsdCwgUyksXG4gICAgICAgICAgICAvLyBUID0gUyAqIEwgICAgICAgICAgICAgIC8vID0gZWx0XigxMip6XjMgKyA2KnpeMiArIDQqeiAtIDEpXG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfbXVsXCIsIFMsIEwsIFQpLFxuICAgICAgICAgICAgLy8gVSA9IFQuRnJvYmVuaXVzX21hcCgzKSAvLyA9IGVsdF4ocV4zKDEyKnpeMyArIDYqel4yICsgNCp6IC0gMSkpXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfX2Zyb2Jlbml1c01hcDNcIiwgVCwgVSksXG4gICAgICAgICAgICAvLyBWID0gVSAqIFIgICAgICAgICAgICAgIC8vID0gZWx0XihxXjMoMTIqel4zICsgNip6XjIgKyA0KnogLSAxKSArIHFeMiAqICgxMip6XjMgKyA2KnpeMiArIDYqeikgKyBxKigxMip6XjMgKyA2KnpeMiArIDQqeikgKiAoMTIqel4zICsgMTIqel4yICsgNip6ICsgMSkpXG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfbXVsXCIsIFUsIFIsIHJlc3VsdCksXG4gICAgICAgICAgICAvLyByZXN1bHQgPSBWXG4gICAgICAgICk7XG4gICAgfVxuXG5cbiAgICBmdW5jdGlvbiBidWlsZEZpbmFsRXhwb25lbnRpYXRpb24oKSB7XG4gICAgICAgIGJ1aWxkRmluYWxFeHBvbmVudGlhdGlvbkZpcnN0Q2h1bmsoKTtcbiAgICAgICAgYnVpbGRGaW5hbEV4cG9uZW50aWF0aW9uTGFzdENodW5rKCk7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4KyBcIl9maW5hbEV4cG9uZW50aWF0aW9uXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwieFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCBlbHQgPSBjLmdldExvY2FsKFwieFwiKTtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYy5nZXRMb2NhbChcInJcIik7XG4gICAgICAgIGNvbnN0IGVsdFRvRmlyc3RDaHVuayA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmdHNpemUpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfX2ZpbmFsRXhwb25lbnRpYXRpb25GaXJzdENodW5rXCIsIGVsdCwgZWx0VG9GaXJzdENodW5rICksXG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfX2ZpbmFsRXhwb25lbnRpYXRpb25MYXN0Q2h1bmtcIiwgZWx0VG9GaXJzdENodW5rLCByZXN1bHQgKVxuICAgICAgICApO1xuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gYnVpbGRGaW5hbEV4cG9uZW50aWF0aW9uT2xkKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCsgXCJfZmluYWxFeHBvbmVudGlhdGlvbk9sZFwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGV4cG9uZW50ID0gNTUyNDg0MjMzNjEzMjI0MDk2MzEyNjE3MTI2NzgzMTczMTQ3MDk3MzgyMTAzNzYyOTU3NjU0MTg4ODgyNzM0MzE0MTk2OTEwODM5OTA3NTQxMjEzOTc0NTAyNzYxNTQwNjI5ODE3MDA5NjA4NTQ4NjU0NjgwMzQzNjI3NzAxMTUzODI5NDQ2NzQ3ODEwOTA3MzczMjU2ODQxNTUxMDA2MjAxNjM5Njc3NzI2MTM5OTQ2MDI5MTk5OTY4NDEyNTk4ODA0ODgyMzkxNzAyMjczMDE5MDgzNjUzMjcyMDQ3NTY2MzE2NTg0MzY1NTU5Nzc2NDkzMDI3NDk1NDU4MjM4MzczOTAyODc1OTM3NjU5OTQzNTA0ODczMjIwNTU0MTYxNTUwNTI1OTI2MzAyMzAzMzMxNzQ3NDYzNTE1NjQ0NzExODc2NjUzMTc3MTI5NTc4MzAzMTkxMDk1OTAwOTA5MTkxNjI0ODE3ODI2NTY2Njg4MjQxODA0NDA4MDgxODkyNzg1NzI1OTY3OTMxNzE0MDk3NzE2NzA5NTI2MDkyMjYxMjc4MDcxOTUyNTYwMTcxMTExNDQ0MDcyMDQ5MjI5MTIzNTY1MDU3NDgzNzUwMTYxNDYwMDI0MzUzMzQ2Mjg0MTY3MjgyNDUyNzU2MjE3NjYyMzM1NTI4ODEzNTE5MTM5ODA4MjkxMTcwNTM5MDcyMTI1MzgxMjMwODE1NzI5MDcxNTQ0ODYxNjAyNzUwOTM2OTY0ODI5MzEzNjA4MTM3MzI1NDI2MzgzNzM1MTIyMTc1MjI5NTQxMTU1Mzc2MzQ2NDM2MDkzOTMwMjg3NDAyMDg5NTE3NDI2OTczMTc4OTE3NTY5NzEzMzg0NzQ4MDgxODI3MjU1NDcyNTc2OTM3NDcxNDk2MTk1NzUyNzI3MTg4MjYxNDM1NjMzMjcxMjM4NzEwMTMxNzM2MDk2Mjk5Nzk4MTY4ODUyOTI1NTQwNTQ5MzQyMzMwNzc1Mjc5ODc3MDA2Nzg0MzU0ODAxNDIyMjQ5NzIyNTczNzgzNTYxNjg1MTc5NjE4ODE2NDgwMDM3Njk1MDA1NTE1NDI2MTYyMzYyNDMxMDcyMjQ1NjM4MzI0NzQ0NDgwbjtcblxuICAgICAgICBjb25zdCBwRXhwb25lbnQgPSBtb2R1bGUuYWxsb2ModXRpbHMkMS5iaWdJbnQyQnl0ZXNMRSggZXhwb25lbnQsIDM1MiApKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9leHBcIiwgYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KHBFeHBvbmVudCksIGMuaTMyX2NvbnN0KDM1MiksIGMuZ2V0TG9jYWwoXCJyXCIpKSxcbiAgICAgICAgKTtcbiAgICB9XG5cblxuXG5cbiAgICBjb25zdCBwUHJlUCA9IG1vZHVsZS5hbGxvYyhwcmVQU2l6ZSk7XG4gICAgY29uc3QgcFByZVEgPSBtb2R1bGUuYWxsb2MocHJlUVNpemUpO1xuXG4gICAgZnVuY3Rpb24gYnVpbGRQYWlyaW5nRXF1YXRpb24oblBhaXJpbmdzKSB7XG5cbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrIFwiX3BhaXJpbmdFcVwiK25QYWlyaW5ncyk7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxuUGFpcmluZ3M7IGkrKykge1xuICAgICAgICAgICAgZi5hZGRQYXJhbShcInBfXCIraSwgXCJpMzJcIik7XG4gICAgICAgICAgICBmLmFkZFBhcmFtKFwicV9cIitpLCBcImkzMlwiKTtcbiAgICAgICAgfVxuICAgICAgICBmLmFkZFBhcmFtKFwiY1wiLCBcImkzMlwiKTtcbiAgICAgICAgZi5zZXRSZXR1cm5UeXBlKFwiaTMyXCIpO1xuXG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCByZXNUID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGZ0c2l6ZSkpO1xuICAgICAgICBjb25zdCBhdXhUID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGZ0c2l6ZSkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShjLmNhbGwoZnRtUHJlZml4ICsgXCJfb25lXCIsIHJlc1QgKSk7XG5cbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPG5QYWlyaW5nczsgaSsrKSB7XG5cbiAgICAgICAgICAgIGYuYWRkQ29kZShjLmNhbGwocHJlZml4ICsgXCJfcHJlcGFyZUcxXCIsIGMuZ2V0TG9jYWwoXCJwX1wiK2kpLCBjLmkzMl9jb25zdChwUHJlUCkgKSk7XG4gICAgICAgICAgICBmLmFkZENvZGUoYy5jYWxsKHByZWZpeCArIFwiX3ByZXBhcmVHMlwiLCBjLmdldExvY2FsKFwicV9cIitpKSwgYy5pMzJfY29uc3QocFByZVEpICkpO1xuICAgICAgICAgICAgZi5hZGRDb2RlKGMuY2FsbChwcmVmaXggKyBcIl9taWxsZXJMb29wXCIsIGMuaTMyX2NvbnN0KHBQcmVQKSwgYy5pMzJfY29uc3QocFByZVEpLCBhdXhUICkpO1xuXG4gICAgICAgICAgICBmLmFkZENvZGUoYy5jYWxsKGZ0bVByZWZpeCArIFwiX211bFwiLCByZXNULCBhdXhULCByZXNUICkpO1xuICAgICAgICB9XG5cbiAgICAgICAgZi5hZGRDb2RlKGMuY2FsbChwcmVmaXggKyBcIl9maW5hbEV4cG9uZW50aWF0aW9uXCIsIHJlc1QsIHJlc1QgKSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKGMuY2FsbChmdG1QcmVmaXggKyBcIl9lcVwiLCByZXNULCBjLmdldExvY2FsKFwiY1wiKSkpO1xuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gYnVpbGRQYWlyaW5nKCkge1xuXG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4KyBcIl9wYWlyaW5nXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInFcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgcmVzVCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmdHNpemUpKTtcblxuICAgICAgICBmLmFkZENvZGUoYy5jYWxsKHByZWZpeCArIFwiX3ByZXBhcmVHMVwiLCBjLmdldExvY2FsKFwicFwiKSwgYy5pMzJfY29uc3QocFByZVApICkpO1xuICAgICAgICBmLmFkZENvZGUoYy5jYWxsKHByZWZpeCArIFwiX3ByZXBhcmVHMlwiLCBjLmdldExvY2FsKFwicVwiKSwgYy5pMzJfY29uc3QocFByZVEpICkpO1xuICAgICAgICBmLmFkZENvZGUoYy5jYWxsKHByZWZpeCArIFwiX21pbGxlckxvb3BcIiwgYy5pMzJfY29uc3QocFByZVApLCBjLmkzMl9jb25zdChwUHJlUSksIHJlc1QgKSk7XG4gICAgICAgIGYuYWRkQ29kZShjLmNhbGwocHJlZml4ICsgXCJfZmluYWxFeHBvbmVudGlhdGlvblwiLCByZXNULCBjLmdldExvY2FsKFwiclwiKSApKTtcbiAgICB9XG5cblxuICAgIGJ1aWxkUHJlcEFkZFN0ZXAoKTtcbiAgICBidWlsZFByZXBEb3VibGVTdGVwKCk7XG5cbiAgICBidWlsZFByZXBhcmVHMSgpO1xuICAgIGJ1aWxkUHJlcGFyZUcyKCk7XG5cbiAgICBidWlsZE11bEJ5MDI0KCk7XG4gICAgYnVpbGRNdWxCeTAyNE9sZCgpO1xuICAgIGJ1aWxkTWlsbGVyTG9vcCgpO1xuXG5cbiAgICBmb3IgKGxldCBpPTA7IGk8MTA7IGkrKykge1xuICAgICAgICBidWlsZEZyb2Jlbml1c01hcChpKTtcbiAgICAgICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX19mcm9iZW5pdXNNYXBcIitpKTtcbiAgICB9XG5cbiAgICBidWlsZEZpbmFsRXhwb25lbnRpYXRpb25PbGQoKTtcbiAgICBidWlsZEZpbmFsRXhwb25lbnRpYXRpb24oKTtcblxuICAgIGZvciAobGV0IGk9MTsgaTw9NTsgaSsrKSB7XG4gICAgICAgIGJ1aWxkUGFpcmluZ0VxdWF0aW9uKGkpO1xuICAgICAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfcGFpcmluZ0VxXCIraSk7XG4gICAgfVxuXG4gICAgYnVpbGRQYWlyaW5nKCk7XG5cbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfcGFpcmluZ1wiKTtcblxuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9wcmVwYXJlRzFcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX3ByZXBhcmVHMlwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfbWlsbGVyTG9vcFwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfZmluYWxFeHBvbmVudGlhdGlvblwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfZmluYWxFeHBvbmVudGlhdGlvbk9sZFwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfX211bEJ5MDI0XCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9fbXVsQnkwMjRPbGRcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX19jeWNsb3RvbWljU3F1YXJlXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9fY3ljbG90b21pY0V4cF93MFwiKTtcblxuICAgIC8vIGNvbnNvbGUubG9nKG1vZHVsZS5mdW5jdGlvbklkeEJ5TmFtZSk7XG5cbn07XG5cbmNvbnN0IHV0aWxzID0gdXRpbHMkNTtcblxuY29uc3QgYnVpbGRGMW0gPWJ1aWxkX2YxbTtcbmNvbnN0IGJ1aWxkRjEgPWJ1aWxkX2YxO1xuY29uc3QgYnVpbGRGMm0gPWJ1aWxkX2YybTtcbmNvbnN0IGJ1aWxkRjNtID1idWlsZF9mM207XG5jb25zdCBidWlsZEN1cnZlID1idWlsZF9jdXJ2ZV9qYWNvYmlhbl9hMDtcbmNvbnN0IGJ1aWxkRkZUID0gYnVpbGRfZmZ0O1xuY29uc3QgYnVpbGRQb2wgPSBidWlsZF9wb2w7XG5jb25zdCBidWlsZFFBUCA9IGJ1aWxkX3FhcDtcbmNvbnN0IGJ1aWxkQXBwbHlLZXkgPSBidWlsZF9hcHBseWtleTtcbmNvbnN0IHsgYml0TGVuZ3RoOiBiaXRMZW5ndGgkMSwgaXNPZGQsIGlzTmVnYXRpdmU6IGlzTmVnYXRpdmUkMSB9ID0gYmlnaW50O1xuXG4vLyBEZWZpbml0aW9uIGhlcmU6IGh0dHBzOi8vZWxlY3RyaWNjb2luLmNvL2Jsb2cvbmV3LXNuYXJrLWN1cnZlL1xuXG52YXIgYnVpbGRfYmxzMTIzODEgPSBmdW5jdGlvbiBidWlsZEJMUzEyMzgxKG1vZHVsZSwgX3ByZWZpeCkge1xuXG4gICAgY29uc3QgcHJlZml4ID0gX3ByZWZpeCB8fCBcImJsczEyMzgxXCI7XG5cbiAgICBpZiAobW9kdWxlLm1vZHVsZXNbcHJlZml4XSkgcmV0dXJuIHByZWZpeDsgIC8vIGFscmVhZHkgYnVpbGRlZFxuXG4gICAgY29uc3QgcSA9IDB4MWEwMTExZWEzOTdmZTY5YTRiMWJhN2I2NDM0YmFjZDc2NDc3NGI4NGYzODUxMmJmNjczMGQyYTBmNmIwZjYyNDFlYWJmZmZlYjE1M2ZmZmZiOWZlZmZmZmZmZmZhYWFibjtcbiAgICBjb25zdCByID0gMHg3M2VkYTc1MzI5OWQ3ZDQ4MzMzOWQ4MDgwOWExZDgwNTUzYmRhNDAyZmZmZTViZmVmZmZmZmZmZjAwMDAwMDAxbjtcblxuICAgIGNvbnN0IG42NHEgPSBNYXRoLmZsb29yKChiaXRMZW5ndGgkMShxIC0gMW4pIC0gMSkvNjQpICsxO1xuICAgIGNvbnN0IG44cSA9IG42NHEqODtcbiAgICBjb25zdCBmMXNpemUgPSBuOHE7XG4gICAgY29uc3QgZjJzaXplID0gZjFzaXplICogMjtcbiAgICBjb25zdCBmdHNpemUgPSBmMXNpemUgKiAxMjtcblxuICAgIGNvbnN0IG42NHIgPSBNYXRoLmZsb29yKChiaXRMZW5ndGgkMShyIC0gMW4pIC0gMSkvNjQpICsxO1xuICAgIGNvbnN0IG44ciA9IG42NHIqODtcbiAgICBjb25zdCBmcnNpemUgPSBuOHI7XG5cblxuICAgIGNvbnN0IHByID0gbW9kdWxlLmFsbG9jKHV0aWxzLmJpZ0ludDJCeXRlc0xFKCByLCBmcnNpemUgKSk7XG5cbiAgICBjb25zdCBmMW1QcmVmaXggPSBidWlsZEYxbShtb2R1bGUsIHEsIFwiZjFtXCIsIFwiaW50cVwiKTtcbiAgICBidWlsZEYxKG1vZHVsZSwgciwgXCJmclwiLCBcImZybVwiLCBcImludHJcIik7XG4gICAgY29uc3QgcEcxYiA9IG1vZHVsZS5hbGxvYyh1dGlscy5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KDRuKSwgZjFzaXplICkpO1xuICAgIGNvbnN0IGcxbVByZWZpeCA9IGJ1aWxkQ3VydmUobW9kdWxlLCBcImcxbVwiLCBcImYxbVwiLCBwRzFiKTtcblxuICAgIGJ1aWxkRkZUKG1vZHVsZSwgXCJmcm1cIiwgXCJmcm1cIiwgXCJmcm1cIiwgXCJmcm1fbXVsXCIpO1xuXG4gICAgYnVpbGRQb2wobW9kdWxlLCBcInBvbFwiLCBcImZybVwiKTtcbiAgICBidWlsZFFBUChtb2R1bGUsIFwicWFwXCIsIFwiZnJtXCIpO1xuXG4gICAgY29uc3QgZjJtUHJlZml4ID0gYnVpbGRGMm0obW9kdWxlLCBcImYxbV9uZWdcIiwgXCJmMm1cIiwgXCJmMW1cIik7XG4gICAgY29uc3QgcEcyYiA9IG1vZHVsZS5hbGxvYyhbXG4gICAgICAgIC4uLnV0aWxzLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoNG4pLCBmMXNpemUgKSxcbiAgICAgICAgLi4udXRpbHMuYmlnSW50MkJ5dGVzTEUoIHRvTW9udGdvbWVyeSg0biksIGYxc2l6ZSApXG4gICAgXSk7XG4gICAgY29uc3QgZzJtUHJlZml4ID0gYnVpbGRDdXJ2ZShtb2R1bGUsIFwiZzJtXCIsIFwiZjJtXCIsIHBHMmIpO1xuXG5cbiAgICBmdW5jdGlvbiBidWlsZEdUaW1lc0ZyKGZuTmFtZSwgb3BNdWwpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihmbk5hbWUpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicEdcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwRnJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwclwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IEFVWCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhuOHIpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwoXCJmcm1fZnJvbU1vbnRnb21lcnlcIiwgYy5nZXRMb2NhbChcInBGclwiKSwgQVVYKSxcbiAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICBvcE11bCxcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicEdcIiksXG4gICAgICAgICAgICAgICAgQVVYLFxuICAgICAgICAgICAgICAgIGMuaTMyX2NvbnN0KG44ciksXG4gICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcInByXCIpXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG5cbiAgICAgICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKGZuTmFtZSk7XG4gICAgfVxuICAgIGJ1aWxkR1RpbWVzRnIoXCJnMW1fdGltZXNGclwiLCBcImcxbV90aW1lc1NjYWxhclwiKTtcbiAgICBidWlsZEZGVChtb2R1bGUsIFwiZzFtXCIsIFwiZzFtXCIsIFwiZnJtXCIsIFwiZzFtX3RpbWVzRnJcIik7XG5cbiAgICBidWlsZEdUaW1lc0ZyKFwiZzJtX3RpbWVzRnJcIiwgXCJnMm1fdGltZXNTY2FsYXJcIik7XG4gICAgYnVpbGRGRlQobW9kdWxlLCBcImcybVwiLCBcImcybVwiLCBcImZybVwiLCBcImcybV90aW1lc0ZyXCIpO1xuXG4gICAgYnVpbGRHVGltZXNGcihcImcxbV90aW1lc0ZyQWZmaW5lXCIsIFwiZzFtX3RpbWVzU2NhbGFyQWZmaW5lXCIpO1xuICAgIGJ1aWxkR1RpbWVzRnIoXCJnMm1fdGltZXNGckFmZmluZVwiLCBcImcybV90aW1lc1NjYWxhckFmZmluZVwiKTtcblxuICAgIGJ1aWxkQXBwbHlLZXkobW9kdWxlLCBcImZybV9iYXRjaEFwcGx5S2V5XCIsIFwiZm1yXCIsIFwiZnJtXCIsIG44ciwgbjhyLCBuOHIsIFwiZnJtX211bFwiKTtcbiAgICBidWlsZEFwcGx5S2V5KG1vZHVsZSwgXCJnMW1fYmF0Y2hBcHBseUtleVwiLCBcImcxbVwiLCBcImZybVwiLCBuOHEqMywgbjhxKjMsIG44ciwgXCJnMW1fdGltZXNGclwiKTtcbiAgICBidWlsZEFwcGx5S2V5KG1vZHVsZSwgXCJnMW1fYmF0Y2hBcHBseUtleU1peGVkXCIsIFwiZzFtXCIsIFwiZnJtXCIsIG44cSoyLCBuOHEqMywgbjhyLCBcImcxbV90aW1lc0ZyQWZmaW5lXCIpO1xuICAgIGJ1aWxkQXBwbHlLZXkobW9kdWxlLCBcImcybV9iYXRjaEFwcGx5S2V5XCIsIFwiZzJtXCIsIFwiZnJtXCIsIG44cSoyKjMsIG44cSozKjIsIG44ciwgXCJnMm1fdGltZXNGclwiKTtcbiAgICBidWlsZEFwcGx5S2V5KG1vZHVsZSwgXCJnMm1fYmF0Y2hBcHBseUtleU1peGVkXCIsIFwiZzJtXCIsIFwiZnJtXCIsIG44cSoyKjIsIG44cSozKjIsIG44ciwgXCJnMm1fdGltZXNGckFmZmluZVwiKTtcblxuXG4gICAgZnVuY3Rpb24gdG9Nb250Z29tZXJ5KGEpIHtcbiAgICAgICAgcmV0dXJuIEJpZ0ludChhKSAqICgxbiA8PCBCaWdJbnQoZjFzaXplKjgpKSAlIHE7XG4gICAgfVxuXG4gICAgY29uc3QgRzFnZW4gPSBbXG4gICAgICAgIDM2ODU0MTY3NTM3MTMzODcwMTY3ODEwODgzMTUxODMwNzc3NTc5NjE2MjA3OTU3ODI1NDY0MDk4OTQ1NzgzNzg2ODg2MDc1OTIzNzgzNzYzMTg4MzYwNTQ5NDc2NzYzNDU4MjE1NDgxMDQxODU0NjQ1MDduLFxuICAgICAgICAxMzM5NTA2NTQ0OTQ0NDc2NDczMDIwNDcxMzc5OTQxOTIxMjIxNTg0OTMzODc1OTM4MzQ5NjIwNDI2NTQzNzM2NDE2NTExNDIzOTU2MzMzNTA2NDcyNzI0NjU1MzUzMzY2NTM0OTkyMzkxNzU2NDQxNTY5bixcbiAgICAgICAgMW5cbiAgICBdO1xuXG4gICAgY29uc3QgcEcxZ2VuID0gbW9kdWxlLmFsbG9jKFxuICAgICAgICBbXG4gICAgICAgICAgICAuLi51dGlscy5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KEcxZ2VuWzBdKSwgZjFzaXplICksXG4gICAgICAgICAgICAuLi51dGlscy5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KEcxZ2VuWzFdKSwgZjFzaXplICksXG4gICAgICAgICAgICAuLi51dGlscy5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KEcxZ2VuWzJdKSwgZjFzaXplICksXG4gICAgICAgIF1cbiAgICApO1xuXG4gICAgY29uc3QgRzF6ZXJvID0gW1xuICAgICAgICAwbixcbiAgICAgICAgMW4sXG4gICAgICAgIDBuXG4gICAgXTtcblxuICAgIGNvbnN0IHBHMXplcm8gPSBtb2R1bGUuYWxsb2MoXG4gICAgICAgIFtcbiAgICAgICAgICAgIC4uLnV0aWxzLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoRzF6ZXJvWzBdKSwgZjFzaXplICksXG4gICAgICAgICAgICAuLi51dGlscy5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KEcxemVyb1sxXSksIGYxc2l6ZSApLFxuICAgICAgICAgICAgLi4udXRpbHMuYmlnSW50MkJ5dGVzTEUoIHRvTW9udGdvbWVyeShHMXplcm9bMl0pLCBmMXNpemUgKVxuICAgICAgICBdXG4gICAgKTtcblxuICAgIGNvbnN0IEcyZ2VuID0gW1xuICAgICAgICBbXG4gICAgICAgICAgICAzNTI3MDEwNjk1ODc0NjY2MTgxODcxMzkxMTYwMTEwNjAxNDQ4OTAwMjk5NTI3OTI3NzUyNDAyMTk5MDg2NDQyMzk3OTM3ODU3MzU3MTUwMjY4NzMzNDc2MDAzNDM4NjUxNzU5NTI3NjE5MjYzMDMxNjBuLFxuICAgICAgICAgICAgMzA1OTE0NDM0NDI0NDIxMzcwOTk3MTI1OTgxNDc1Mzc4MTYzNjk4NjQ3MDMyNTQ3NjY0NzU1ODY1OTM3MzIwNjI5MTYzNTMyNDc2ODk1ODQzMjQzMzUwOTU2MzEwNDM0NzAxNzgzNzg4NTc2MzM2NTc1OG4sXG4gICAgICAgIF0sW1xuICAgICAgICAgICAgMTk4NTE1MDYwMjI4NzI5MTkzNTU2ODA1NDUyMTE3NzE3MTYzODMwMDg2ODk3ODIxNTY1NTczMDg1OTM3ODY2NTA2NjM0NDcyNjM3MzgyMzcxODQyMzg2OTEwNDI2MzMzMzk4NDY0MTQ5NDM0MDM0NzkwNW4sXG4gICAgICAgICAgICA5Mjc1NTM2NjU0OTIzMzI0NTU3NDcyMDE5NjU3NzYwMzc4ODA3NTc3NDAxOTM0NTM1OTI5NzAwMjUwMjc5Nzg3OTM5NzY4NzcwMDI2NzU1NjQ5ODA5NDkyODk3Mjc5NTc1NjU1NzU0MzMzNDQyMTk1ODJuLFxuICAgICAgICBdLFtcbiAgICAgICAgICAgIDFuLFxuICAgICAgICAgICAgMG4sXG4gICAgICAgIF1cbiAgICBdO1xuXG4gICAgY29uc3QgcEcyZ2VuID0gbW9kdWxlLmFsbG9jKFxuICAgICAgICBbXG4gICAgICAgICAgICAuLi51dGlscy5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KEcyZ2VuWzBdWzBdKSwgZjFzaXplICksXG4gICAgICAgICAgICAuLi51dGlscy5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KEcyZ2VuWzBdWzFdKSwgZjFzaXplICksXG4gICAgICAgICAgICAuLi51dGlscy5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KEcyZ2VuWzFdWzBdKSwgZjFzaXplICksXG4gICAgICAgICAgICAuLi51dGlscy5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KEcyZ2VuWzFdWzFdKSwgZjFzaXplICksXG4gICAgICAgICAgICAuLi51dGlscy5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KEcyZ2VuWzJdWzBdKSwgZjFzaXplICksXG4gICAgICAgICAgICAuLi51dGlscy5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KEcyZ2VuWzJdWzFdKSwgZjFzaXplICksXG4gICAgICAgIF1cbiAgICApO1xuXG4gICAgY29uc3QgRzJ6ZXJvID0gW1xuICAgICAgICBbXG4gICAgICAgICAgICAwbixcbiAgICAgICAgICAgIDBuLFxuICAgICAgICBdLFtcbiAgICAgICAgICAgIDFuLFxuICAgICAgICAgICAgMG4sXG4gICAgICAgIF0sW1xuICAgICAgICAgICAgMG4sXG4gICAgICAgICAgICAwbixcbiAgICAgICAgXVxuICAgIF07XG5cbiAgICBjb25zdCBwRzJ6ZXJvID0gbW9kdWxlLmFsbG9jKFxuICAgICAgICBbXG4gICAgICAgICAgICAuLi51dGlscy5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KEcyemVyb1swXVswXSksIGYxc2l6ZSApLFxuICAgICAgICAgICAgLi4udXRpbHMuYmlnSW50MkJ5dGVzTEUoIHRvTW9udGdvbWVyeShHMnplcm9bMF1bMV0pLCBmMXNpemUgKSxcbiAgICAgICAgICAgIC4uLnV0aWxzLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoRzJ6ZXJvWzFdWzBdKSwgZjFzaXplICksXG4gICAgICAgICAgICAuLi51dGlscy5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KEcyemVyb1sxXVsxXSksIGYxc2l6ZSApLFxuICAgICAgICAgICAgLi4udXRpbHMuYmlnSW50MkJ5dGVzTEUoIHRvTW9udGdvbWVyeShHMnplcm9bMl1bMF0pLCBmMXNpemUgKSxcbiAgICAgICAgICAgIC4uLnV0aWxzLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoRzJ6ZXJvWzJdWzFdKSwgZjFzaXplICksXG4gICAgICAgIF1cbiAgICApO1xuXG4gICAgY29uc3QgcE9uZVQgPSBtb2R1bGUuYWxsb2MoW1xuICAgICAgICAuLi51dGlscy5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KDFuKSwgZjFzaXplICksXG4gICAgICAgIC4uLnV0aWxzLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoMG4pLCBmMXNpemUgKSxcbiAgICAgICAgLi4udXRpbHMuYmlnSW50MkJ5dGVzTEUoIHRvTW9udGdvbWVyeSgwbiksIGYxc2l6ZSApLFxuICAgICAgICAuLi51dGlscy5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KDBuKSwgZjFzaXplICksXG4gICAgICAgIC4uLnV0aWxzLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoMG4pLCBmMXNpemUgKSxcbiAgICAgICAgLi4udXRpbHMuYmlnSW50MkJ5dGVzTEUoIHRvTW9udGdvbWVyeSgwbiksIGYxc2l6ZSApLFxuICAgICAgICAuLi51dGlscy5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KDBuKSwgZjFzaXplICksXG4gICAgICAgIC4uLnV0aWxzLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoMG4pLCBmMXNpemUgKSxcbiAgICAgICAgLi4udXRpbHMuYmlnSW50MkJ5dGVzTEUoIHRvTW9udGdvbWVyeSgwbiksIGYxc2l6ZSApLFxuICAgICAgICAuLi51dGlscy5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KDBuKSwgZjFzaXplICksXG4gICAgICAgIC4uLnV0aWxzLmJpZ0ludDJCeXRlc0xFKCB0b01vbnRnb21lcnkoMG4pLCBmMXNpemUgKSxcbiAgICAgICAgLi4udXRpbHMuYmlnSW50MkJ5dGVzTEUoIHRvTW9udGdvbWVyeSgwbiksIGYxc2l6ZSApLFxuICAgIF0pO1xuXG4gICAgY29uc3QgcEJsczEyMzgxVHdpc3QgPSAgbW9kdWxlLmFsbG9jKFtcbiAgICAgICAgLi4udXRpbHMuYmlnSW50MkJ5dGVzTEUoIHRvTW9udGdvbWVyeSgxbiksIGYxc2l6ZSApLFxuICAgICAgICAuLi51dGlscy5iaWdJbnQyQnl0ZXNMRSggdG9Nb250Z29tZXJ5KDFuKSwgZjFzaXplICksXG4gICAgXSk7XG5cbiAgICBmdW5jdGlvbiBidWlsZF9tdWxOUjIoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24oZjJtUHJlZml4ICsgXCJfbXVsTlJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ4XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicHJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCB4MGMgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjFzaXplKSk7XG4gICAgICAgIGNvbnN0IHgwID0gYy5nZXRMb2NhbChcInhcIik7XG4gICAgICAgIGNvbnN0IHgxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdChmMXNpemUpKTtcbiAgICAgICAgY29uc3QgcjAgPSBjLmdldExvY2FsKFwicHJcIik7XG4gICAgICAgIGNvbnN0IHIxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwclwiKSwgYy5pMzJfY29uc3QoZjFzaXplKSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9jb3B5XCIsIHgwLCB4MGMpLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCtcIl9zdWJcIiwgeDAsIHgxLCByMCksXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4K1wiX2FkZFwiLCB4MGMsIHgxLCByMSksXG4gICAgICAgICk7XG4gICAgfVxuICAgIGJ1aWxkX211bE5SMigpO1xuXG4gICAgY29uc3QgZjZtUHJlZml4ID0gYnVpbGRGM20obW9kdWxlLCBmMm1QcmVmaXgrXCJfbXVsTlJcIiwgXCJmNm1cIiwgXCJmMm1cIik7XG5cbiAgICBmdW5jdGlvbiBidWlsZF9tdWxOUjYoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24oZjZtUHJlZml4ICsgXCJfbXVsTlJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ4XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicHJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCBjMGNvcHkgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjFzaXplKjIpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgZjJtUHJlZml4ICsgXCJfY29weVwiLFxuICAgICAgICAgICAgICAgIGMuZ2V0TG9jYWwoXCJ4XCIpLFxuICAgICAgICAgICAgICAgIGMwY29weVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICBmMm1QcmVmaXggKyBcIl9tdWxOUlwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QobjhxKjQpKSxcbiAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwicHJcIilcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLmNhbGwoXG4gICAgICAgICAgICAgICAgZjJtUHJlZml4ICsgXCJfY29weVwiLFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QobjhxKjIpKSxcbiAgICAgICAgICAgICAgICBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInByXCIpLCBjLmkzMl9jb25zdChuOHEqNCkpLFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuY2FsbChcbiAgICAgICAgICAgICAgICBmMm1QcmVmaXggKyBcIl9jb3B5XCIsXG4gICAgICAgICAgICAgICAgYzBjb3B5LFxuICAgICAgICAgICAgICAgIGMuaTMyX2FkZChjLmdldExvY2FsKFwicHJcIiksIGMuaTMyX2NvbnN0KG44cSoyKSksXG4gICAgICAgICAgICApLFxuICAgICAgICApO1xuICAgIH1cbiAgICBidWlsZF9tdWxOUjYoKTtcblxuICAgIGNvbnN0IGZ0bVByZWZpeCA9IGJ1aWxkRjJtKG1vZHVsZSwgZjZtUHJlZml4K1wiX211bE5SXCIsIFwiZnRtXCIsIGY2bVByZWZpeCk7XG5cbiAgICBjb25zdCBhdGVMb29wQ291bnQgPSAweGQyMDEwMDAwMDAwMTAwMDBuO1xuICAgIGNvbnN0IGF0ZUxvb3BCaXRCeXRlcyA9IGJpdHMoYXRlTG9vcENvdW50KTtcbiAgICBjb25zdCBwQXRlTG9vcEJpdEJ5dGVzID0gbW9kdWxlLmFsbG9jKGF0ZUxvb3BCaXRCeXRlcyk7XG5cbiAgICBjb25zdCBhdGVDb2VmU2l6ZSA9IDMgKiBmMnNpemU7XG4gICAgY29uc3QgYXRlTkRibENvZWZzID0gYXRlTG9vcEJpdEJ5dGVzLmxlbmd0aC0xO1xuICAgIGNvbnN0IGF0ZU5BZGRDb2VmcyA9IGF0ZUxvb3BCaXRCeXRlcy5yZWR1Y2UoKGFjYywgYikgPT4gIGFjYyArICggYiE9MCA/IDEgOiAwKSAgICwwKTtcbiAgICBjb25zdCBhdGVOQ29lZnMgPSBhdGVOQWRkQ29lZnMgKyBhdGVORGJsQ29lZnMgKyAxO1xuICAgIGNvbnN0IHByZVBTaXplID0gMyoyKm44cTtcbiAgICBjb25zdCBwcmVRU2l6ZSA9IDMqbjhxKjIgKyBhdGVOQ29lZnMqYXRlQ29lZlNpemU7XG4gICAgY29uc3QgZmluYWxFeHBJc05lZ2F0aXZlID0gdHJ1ZTtcblxuICAgIGNvbnN0IGZpbmFsRXhwWiA9IDE1MTMyMzc2MjIyOTQxNjQyNzUybjtcblxuXG4gICAgbW9kdWxlLm1vZHVsZXNbcHJlZml4XSA9IHtcbiAgICAgICAgbjY0cTogbjY0cSxcbiAgICAgICAgbjY0cjogbjY0cixcbiAgICAgICAgbjhxOiBuOHEsXG4gICAgICAgIG44cjogbjhyLFxuICAgICAgICBwRzFnZW46IHBHMWdlbixcbiAgICAgICAgcEcxemVybzogcEcxemVybyxcbiAgICAgICAgcEcxYjogcEcxYixcbiAgICAgICAgcEcyZ2VuOiBwRzJnZW4sXG4gICAgICAgIHBHMnplcm86IHBHMnplcm8sXG4gICAgICAgIHBHMmI6IHBHMmIsXG4gICAgICAgIHBxOiBtb2R1bGUubW9kdWxlc1tcImYxbVwiXS5wcSxcbiAgICAgICAgcHI6IHByLFxuICAgICAgICBwT25lVDogcE9uZVQsXG4gICAgICAgIHI6IHIsXG4gICAgICAgIHE6IHEsXG4gICAgICAgIHByZVBTaXplOiBwcmVQU2l6ZSxcbiAgICAgICAgcHJlUVNpemU6IHByZVFTaXplXG4gICAgfTtcblxuXG4gICAgZnVuY3Rpb24gbmFmKG4pIHtcbiAgICAgICAgbGV0IEUgPSBuO1xuICAgICAgICBjb25zdCByZXMgPSBbXTtcbiAgICAgICAgd2hpbGUgKEUgPiAwbikge1xuICAgICAgICAgICAgaWYgKGlzT2RkKEUpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgeiA9IDIgLSBOdW1iZXIoRSAlIDRuKTtcbiAgICAgICAgICAgICAgICByZXMucHVzaCggeiApO1xuICAgICAgICAgICAgICAgIEUgPSBFIC0gQmlnSW50KHopO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXMucHVzaCggMCApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgRSA9IEUgPj4gMW47XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBiaXRzKG4pIHtcbiAgICAgICAgbGV0IEUgPSBuO1xuICAgICAgICBjb25zdCByZXMgPSBbXTtcbiAgICAgICAgd2hpbGUgKEUgPiAwbikge1xuICAgICAgICAgICAgaWYgKGlzT2RkKEUpKSB7XG4gICAgICAgICAgICAgICAgcmVzLnB1c2goIDEgKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzLnB1c2goIDAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIEUgPSBFID4+IDFuO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRQcmVwYXJlRzEoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4KyBcIl9wcmVwYXJlRzFcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwUFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInBwcmVQXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5jYWxsKGcxbVByZWZpeCArIFwiX25vcm1hbGl6ZVwiLCBjLmdldExvY2FsKFwicFBcIiksIGMuZ2V0TG9jYWwoXCJwcHJlUFwiKSksICAvLyBUT0RPIFJlbW92ZSBpZiBhbHJlYWR5IGluIGFmZmluZVxuICAgICAgICApO1xuICAgIH1cblxuXG5cbiAgICBmdW5jdGlvbiBidWlsZFByZXBEb3VibGVTdGVwKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCsgXCJfcHJlcERibFN0ZXBcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJSXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiclwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IFJ4ICA9IGMuZ2V0TG9jYWwoXCJSXCIpO1xuICAgICAgICBjb25zdCBSeSAgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcIlJcIiksIGMuaTMyX2NvbnN0KDIqbjhxKSk7XG4gICAgICAgIGNvbnN0IFJ6ICA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwiUlwiKSwgYy5pMzJfY29uc3QoNCpuOHEpKTtcblxuICAgICAgICBjb25zdCB0MCAgPSBjLmdldExvY2FsKFwiclwiKTtcbiAgICAgICAgY29uc3QgdDMgID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJyXCIpLCBjLmkzMl9jb25zdCgyKm44cSkpO1xuICAgICAgICBjb25zdCB0NiAgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInJcIiksIGMuaTMyX2NvbnN0KDQqbjhxKSk7XG5cblxuICAgICAgICBjb25zdCB6c3F1YXJlZCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcbiAgICAgICAgY29uc3QgdDEgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjJzaXplKSk7XG4gICAgICAgIGNvbnN0IHQyID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCB0NCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcbiAgICAgICAgY29uc3QgdDUgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjJzaXplKSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuXG4gICAgICAgICAgICAvLyB0bXAwID0gci54LnNxdWFyZSgpO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3NxdWFyZVwiLCBSeCwgdDApLFxuXG4gICAgICAgICAgICAvLyB0bXAxID0gci55LnNxdWFyZSgpO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3NxdWFyZVwiLCBSeSwgdDEpLFxuXG4gICAgICAgICAgICAvLyB0bXAyID0gdG1wMS5zcXVhcmUoKTtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zcXVhcmVcIiwgdDEsIHQyKSxcblxuICAgICAgICAgICAgLy8gdG1wMyA9ICh0bXAxICsgci54KS5zcXVhcmUoKSAtIHRtcDAgLSB0bXAyO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0MSwgUngsIHQzKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zcXVhcmVcIiwgdDMsIHQzKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zdWJcIiwgdDMsIHQwLCB0MyksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3ViXCIsIHQzLCB0MiwgdDMpLFxuXG4gICAgICAgICAgICAvLyB0bXAzID0gdG1wMyArIHRtcDM7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIHQzLCB0MywgdDMpLFxuXG4gICAgICAgICAgICAvLyB0bXA0ID0gdG1wMCArIHRtcDAgKyB0bXAwO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0MCwgdDAsIHQ0KSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgdDQsIHQwLCB0NCksXG5cbiAgICAgICAgICAgIC8vIHRtcDYgPSByLnggKyB0bXA0O1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCBSeCwgdDQsIHQ2KSxcblxuICAgICAgICAgICAgLy8gdG1wNSA9IHRtcDQuc3F1YXJlKCk7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3F1YXJlXCIsIHQ0LCB0NSksXG5cbiAgICAgICAgICAgIC8vIHpzcXVhcmVkID0gci56LnNxdWFyZSgpO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3NxdWFyZVwiLCBSeiwgenNxdWFyZWQpLFxuXG4gICAgICAgICAgICAvLyByLnggPSB0bXA1IC0gdG1wMyAtIHRtcDM7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3ViXCIsIHQ1LCB0MywgUngpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3N1YlwiLCBSeCwgdDMsIFJ4KSxcblxuICAgICAgICAgICAgLy8gci56ID0gKHIueiArIHIueSkuc3F1YXJlKCkgLSB0bXAxIC0genNxdWFyZWQ7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIFJ6LCBSeSwgUnopLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3NxdWFyZVwiLCBSeiwgUnopLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3N1YlwiLCBSeiwgdDEsIFJ6KSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zdWJcIiwgUnosIHpzcXVhcmVkLCBSeiksXG5cbiAgICAgICAgICAgIC8vIHIueSA9ICh0bXAzIC0gci54KSAqIHRtcDQ7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3ViXCIsIHQzLCBSeCwgUnkpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCBSeSwgdDQsIFJ5KSxcblxuICAgICAgICAgICAgLy8gdG1wMiA9IHRtcDIgKyB0bXAyO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0MiwgdDIsIHQyKSxcblxuICAgICAgICAgICAgLy8gdG1wMiA9IHRtcDIgKyB0bXAyO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0MiwgdDIsIHQyKSxcblxuICAgICAgICAgICAgLy8gdG1wMiA9IHRtcDIgKyB0bXAyO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0MiwgdDIsIHQyKSxcblxuICAgICAgICAgICAgLy8gci55IC09IHRtcDI7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3ViXCIsIFJ5LCB0MiwgUnkpLFxuXG4gICAgICAgICAgICAvLyB0bXAzID0gdG1wNCAqIHpzcXVhcmVkO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCB0NCwgenNxdWFyZWQsIHQzKSxcblxuICAgICAgICAgICAgLy8gdG1wMyA9IHRtcDMgKyB0bXAzO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0MywgdDMsIHQzKSxcblxuICAgICAgICAgICAgLy8gdG1wMyA9IC10bXAzO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX25lZ1wiLCB0MywgdDMpLFxuXG4gICAgICAgICAgICAvLyB0bXA2ID0gdG1wNi5zcXVhcmUoKSAtIHRtcDAgLSB0bXA1O1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3NxdWFyZVwiLCB0NiwgdDYpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3N1YlwiLCB0NiwgdDAsIHQ2KSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zdWJcIiwgdDYsIHQ1LCB0NiksXG5cbiAgICAgICAgICAgIC8vIHRtcDEgPSB0bXAxICsgdG1wMTtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgdDEsIHQxLCB0MSksXG5cbiAgICAgICAgICAgIC8vIHRtcDEgPSB0bXAxICsgdG1wMTtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgdDEsIHQxLCB0MSksXG5cbiAgICAgICAgICAgIC8vIHRtcDYgPSB0bXA2IC0gdG1wMTtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zdWJcIiwgdDYsIHQxLCB0NiksXG5cbiAgICAgICAgICAgIC8vIHRtcDAgPSByLnogKiB6c3F1YXJlZDtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgUnosIHpzcXVhcmVkLCB0MCksXG5cbiAgICAgICAgICAgIC8vIHRtcDAgPSB0bXAwICsgdG1wMDtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgdDAsIHQwLCB0MCksXG5cbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZFByZXBBZGRTdGVwKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCsgXCJfcHJlcEFkZFN0ZXBcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJSXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiUVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCBSeCAgPSBjLmdldExvY2FsKFwiUlwiKTtcbiAgICAgICAgY29uc3QgUnkgID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJSXCIpLCBjLmkzMl9jb25zdCgyKm44cSkpO1xuICAgICAgICBjb25zdCBSeiAgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcIlJcIiksIGMuaTMyX2NvbnN0KDQqbjhxKSk7XG5cbiAgICAgICAgY29uc3QgUXggID0gYy5nZXRMb2NhbChcIlFcIik7XG4gICAgICAgIGNvbnN0IFF5ICA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwiUVwiKSwgYy5pMzJfY29uc3QoMipuOHEpKTtcblxuICAgICAgICBjb25zdCB0MTAgID0gYy5nZXRMb2NhbChcInJcIik7XG4gICAgICAgIGNvbnN0IHQxICA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwiclwiKSwgYy5pMzJfY29uc3QoMipuOHEpKTtcbiAgICAgICAgY29uc3QgdDkgID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJyXCIpLCBjLmkzMl9jb25zdCg0Km44cSkpO1xuXG4gICAgICAgIGNvbnN0IHpzcXVhcmVkID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCB5c3F1YXJlZCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcbiAgICAgICAgY29uc3QgenRzcXVhcmVkID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCB0MCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcbiAgICAgICAgY29uc3QgdDIgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjJzaXplKSk7XG4gICAgICAgIGNvbnN0IHQzID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCB0NCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcbiAgICAgICAgY29uc3QgdDUgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjJzaXplKSk7XG4gICAgICAgIGNvbnN0IHQ2ID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCB0NyA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcbiAgICAgICAgY29uc3QgdDggPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjJzaXplKSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuXG4gICAgICAgICAgICAvLyB6c3F1YXJlZCA9IHIuei5zcXVhcmUoKTtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zcXVhcmVcIiwgUnosIHpzcXVhcmVkKSxcblxuICAgICAgICAgICAgLy8geXNxdWFyZWQgPSBxLnkuc3F1YXJlKCk7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3F1YXJlXCIsIFF5LCB5c3F1YXJlZCksXG5cbiAgICAgICAgICAgIC8vIHQwID0genNxdWFyZWQgKiBxLng7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIHpzcXVhcmVkLCBReCwgdDApLFxuXG4gICAgICAgICAgICAvLyB0MSA9ICgocS55ICsgci56KS5zcXVhcmUoKSAtIHlzcXVhcmVkIC0genNxdWFyZWQpICogenNxdWFyZWQ7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIFF5LCBSeiwgdDEpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3NxdWFyZVwiLCB0MSwgdDEpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3N1YlwiLCB0MSwgeXNxdWFyZWQsIHQxKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zdWJcIiwgdDEsIHpzcXVhcmVkLCB0MSksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIHQxLCB6c3F1YXJlZCwgdDEpLFxuXG4gICAgICAgICAgICAvLyB0MiA9IHQwIC0gci54O1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3N1YlwiLCB0MCwgUngsIHQyKSxcblxuICAgICAgICAgICAgLy8gdDMgPSB0Mi5zcXVhcmUoKTtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zcXVhcmVcIiwgdDIsIHQzKSxcblxuICAgICAgICAgICAgLy8gdDQgPSB0MyArIHQzO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0MywgdDMsIHQ0KSxcblxuICAgICAgICAgICAgLy8gdDQgPSB0NCArIHQ0O1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0NCwgdDQsIHQ0KSxcblxuICAgICAgICAgICAgLy8gdDUgPSB0NCAqIHQyO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCB0NCwgdDIsIHQ1KSxcblxuICAgICAgICAgICAgLy8gdDYgPSB0MSAtIHIueSAtIHIueTtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zdWJcIiwgdDEsIFJ5LCB0NiksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3ViXCIsIHQ2LCBSeSwgdDYpLFxuXG4gICAgICAgICAgICAvLyB0OSA9IHQ2ICogcS54O1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCB0NiwgUXgsIHQ5KSxcblxuICAgICAgICAgICAgLy8gdDcgPSB0NCAqIHIueDtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgdDQsIFJ4LCB0NyksXG5cbiAgICAgICAgICAgIC8vIHIueCA9IHQ2LnNxdWFyZSgpIC0gdDUgLSB0NyAtIHQ3O1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3NxdWFyZVwiLCB0NiwgUngpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3N1YlwiLCBSeCwgdDUsIFJ4KSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zdWJcIiwgUngsIHQ3LCBSeCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3ViXCIsIFJ4LCB0NywgUngpLFxuXG4gICAgICAgICAgICAvLyByLnogPSAoci56ICsgdDIpLnNxdWFyZSgpIC0genNxdWFyZWQgLSB0MztcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgUnosIHQyLCBSeiksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3F1YXJlXCIsIFJ6LCBSeiksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3ViXCIsIFJ6LCB6c3F1YXJlZCwgUnopLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3N1YlwiLCBSeiwgdDMsIFJ6KSxcblxuICAgICAgICAgICAgLy8gdDEwID0gcS55ICsgci56O1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCBReSwgUnosIHQxMCksXG5cbiAgICAgICAgICAgIC8vIHQ4ID0gKHQ3IC0gci54KSAqIHQ2O1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3N1YlwiLCB0NywgUngsIHQ4KSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgdDgsIHQ2LCB0OCksXG5cbiAgICAgICAgICAgIC8vIHQwID0gci55ICogdDU7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIFJ5LCB0NSwgdDApLFxuXG4gICAgICAgICAgICAvLyB0MCA9IHQwICsgdDA7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIHQwLCB0MCwgdDApLFxuXG4gICAgICAgICAgICAvLyByLnkgPSB0OCAtIHQwO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3N1YlwiLCB0OCwgdDAsIFJ5KSxcblxuICAgICAgICAgICAgLy8gdDEwID0gdDEwLnNxdWFyZSgpIC0geXNxdWFyZWQ7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3F1YXJlXCIsIHQxMCwgdDEwKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zdWJcIiwgdDEwLCB5c3F1YXJlZCwgdDEwKSxcblxuICAgICAgICAgICAgLy8genRzcXVhcmVkID0gci56LnNxdWFyZSgpO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3NxdWFyZVwiLCBSeiwgenRzcXVhcmVkKSxcblxuICAgICAgICAgICAgLy8gdDEwID0gdDEwIC0genRzcXVhcmVkO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3N1YlwiLCB0MTAsIHp0c3F1YXJlZCwgdDEwKSxcblxuICAgICAgICAgICAgLy8gdDkgPSB0OSArIHQ5IC0gdDEwO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0OSwgdDksIHQ5KSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zdWJcIiwgdDksIHQxMCwgdDkpLFxuXG4gICAgICAgICAgICAvLyB0MTAgPSByLnogKyByLno7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIFJ6LCBSeiwgdDEwKSxcblxuICAgICAgICAgICAgLy8gdDYgPSAtdDY7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbmVnXCIsIHQ2LCB0NiksXG5cbiAgICAgICAgICAgIC8vIHQxID0gdDYgKyB0NjtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgdDYsIHQ2LCB0MSksXG4gICAgICAgICk7XG4gICAgfVxuXG5cbiAgICBmdW5jdGlvbiBidWlsZFByZXBhcmVHMigpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrIFwiX3ByZXBhcmVHMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInBRXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicHByZVFcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJwQ29lZlwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImlcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuXG4gICAgICAgIGNvbnN0IFEgPSBjLmdldExvY2FsKFwicFFcIik7XG5cbiAgICAgICAgY29uc3QgcFIgPSBtb2R1bGUuYWxsb2MoZjJzaXplKjMpO1xuICAgICAgICBjb25zdCBSID0gYy5pMzJfY29uc3QocFIpO1xuXG4gICAgICAgIGNvbnN0IGJhc2UgPSBjLmdldExvY2FsKFwicHByZVFcIik7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5jYWxsKGcybVByZWZpeCArIFwiX25vcm1hbGl6ZVwiLCBRLCBiYXNlKSxcbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5jYWxsKGcybVByZWZpeCArIFwiX2lzWmVyb1wiLCBiYXNlKSxcbiAgICAgICAgICAgICAgICBjLnJldChbXSlcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLmNhbGwoZzJtUHJlZml4ICsgXCJfY29weVwiLCBiYXNlLCBSKSxcbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJwQ29lZlwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInBwcmVRXCIpLCBjLmkzMl9jb25zdChmMnNpemUqMykpKSxcbiAgICAgICAgKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLnNldExvY2FsKFwiaVwiLCBjLmkzMl9jb25zdChhdGVMb29wQml0Qnl0ZXMubGVuZ3RoLTIpKSxcbiAgICAgICAgICAgIGMuYmxvY2soYy5sb29wKFxuXG4gICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX3ByZXBEYmxTdGVwXCIsIFIsIGMuZ2V0TG9jYWwoXCJwQ29lZlwiKSksXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcInBDb2VmXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwicENvZWZcIiksIGMuaTMyX2NvbnN0KGF0ZUNvZWZTaXplKSkpLFxuXG4gICAgICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfbG9hZDhfcyhjLmdldExvY2FsKFwiaVwiKSwgcEF0ZUxvb3BCaXRCeXRlcyksXG4gICAgICAgICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLmMuY2FsbChwcmVmaXggKyBcIl9wcmVwQWRkU3RlcFwiLCBSLCBiYXNlLCBjLmdldExvY2FsKFwicENvZWZcIikpLFxuICAgICAgICAgICAgICAgICAgICAgICAgLi4uYy5zZXRMb2NhbChcInBDb2VmXCIsIGMuaTMyX2FkZChjLmdldExvY2FsKFwicENvZWZcIiksIGMuaTMyX2NvbnN0KGF0ZUNvZWZTaXplKSkpLFxuICAgICAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjLmJyX2lmKDEsIGMuaTMyX2VxeiAoIGMuZ2V0TG9jYWwoXCJpXCIpICkpLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpXCIsIGMuaTMyX3N1YihjLmdldExvY2FsKFwiaVwiKSwgYy5pMzJfY29uc3QoMSkpKSxcbiAgICAgICAgICAgICAgICBjLmJyKDApXG4gICAgICAgICAgICApKVxuICAgICAgICApO1xuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gYnVpbGRGNk11bDEoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24oZjZtUHJlZml4KyBcIl9tdWwxXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicEFcIiwgXCJpMzJcIik7ICAgIC8vIEY2XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwQzFcIiwgXCJpMzJcIik7ICAgLy8gRjJcbiAgICAgICAgZi5hZGRQYXJhbShcInBSXCIsIFwiaTMyXCIpOyAgICAvLyBGNlxuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgQV9jMCA9IGMuZ2V0TG9jYWwoXCJwQVwiKTtcbiAgICAgICAgY29uc3QgQV9jMSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicEFcIiksIGMuaTMyX2NvbnN0KGYxc2l6ZSoyKSk7XG4gICAgICAgIGNvbnN0IEFfYzIgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInBBXCIpLCBjLmkzMl9jb25zdChmMXNpemUqNCkpO1xuXG4gICAgICAgIGNvbnN0IGMxICA9IGMuZ2V0TG9jYWwoXCJwQzFcIik7XG5cbiAgICAgICAgY29uc3QgdDEgPSBjLmdldExvY2FsKFwicFJcIik7XG4gICAgICAgIGNvbnN0IHQyID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwUlwiKSwgYy5pMzJfY29uc3QoZjFzaXplKjIpKTtcbiAgICAgICAgY29uc3QgYl9iID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwUlwiKSwgYy5pMzJfY29uc3QoZjFzaXplKjQpKTtcblxuICAgICAgICBjb25zdCBBYzBfQWMxID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxc2l6ZSoyKSk7XG4gICAgICAgIGNvbnN0IEFjMV9BYzIgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjFzaXplKjIpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG5cbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgQV9jMCwgQV9jMSwgQWMwX0FjMSksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIEFfYzEsIEFfYzIsIEFjMV9BYzIpLFxuXG4gICAgICAgICAgICAvLyBsZXQgYl9iID0gc2VsZi5jMSAqIGMxO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCBBX2MxLCBjMSwgYl9iKSxcblxuICAgICAgICAgICAgLy8gbGV0IHQxID0gKHNlbGYuYzEgKyBzZWxmLmMyKSAqIGMxIC0gYl9iO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCBBYzFfQWMyLCBjMSwgdDEpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3N1YlwiLCB0MSwgYl9iLCB0MSksXG5cbiAgICAgICAgICAgIC8vIGxldCB0MSA9IHQxLm11bF9ieV9ub25yZXNpZHVlKCk7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsTlJcIiwgdDEsIHQxKSxcblxuICAgICAgICAgICAgLy8gbGV0IHQyID0gKHNlbGYuYzAgKyBzZWxmLmMxKSAqIGMxIC0gYl9iO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCBBYzBfQWMxLCBjMSwgdDIpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3N1YlwiLCB0MiwgYl9iLCB0MiksXG4gICAgICAgICk7XG4gICAgfVxuICAgIGJ1aWxkRjZNdWwxKCk7XG5cbiAgICBmdW5jdGlvbiBidWlsZEY2TXVsMDEoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24oZjZtUHJlZml4KyBcIl9tdWwwMVwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInBBXCIsIFwiaTMyXCIpOyAgICAvLyBGNlxuICAgICAgICBmLmFkZFBhcmFtKFwicEMwXCIsIFwiaTMyXCIpOyAgIC8vIEYyXG4gICAgICAgIGYuYWRkUGFyYW0oXCJwQzFcIiwgXCJpMzJcIik7ICAgLy8gRjJcbiAgICAgICAgZi5hZGRQYXJhbShcInBSXCIsIFwiaTMyXCIpOyAgICAvLyBGNlxuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgQV9jMCA9IGMuZ2V0TG9jYWwoXCJwQVwiKTtcbiAgICAgICAgY29uc3QgQV9jMSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicEFcIiksIGMuaTMyX2NvbnN0KGYxc2l6ZSoyKSk7XG4gICAgICAgIGNvbnN0IEFfYzIgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInBBXCIpLCBjLmkzMl9jb25zdChmMXNpemUqNCkpO1xuXG4gICAgICAgIGNvbnN0IGMwICA9IGMuZ2V0TG9jYWwoXCJwQzBcIik7XG4gICAgICAgIGNvbnN0IGMxICA9IGMuZ2V0TG9jYWwoXCJwQzFcIik7XG5cbiAgICAgICAgY29uc3QgdDEgPSBjLmdldExvY2FsKFwicFJcIik7XG4gICAgICAgIGNvbnN0IHQyID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwUlwiKSwgYy5pMzJfY29uc3QoZjFzaXplKjIpKTtcbiAgICAgICAgY29uc3QgdDMgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInBSXCIpLCBjLmkzMl9jb25zdChmMXNpemUqNCkpO1xuXG4gICAgICAgIGNvbnN0IGFfYSA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMXNpemUqMikpO1xuICAgICAgICBjb25zdCBiX2IgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjFzaXplKjIpKTtcbiAgICAgICAgY29uc3QgQWMwX0FjMSA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMXNpemUqMikpO1xuICAgICAgICBjb25zdCBBYzBfQWMyID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxc2l6ZSoyKSk7XG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgLy8gbGV0IGFfYSA9IHNlbGYuYzAgKiBjMDtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgQV9jMCwgYzAsIGFfYSksXG5cbiAgICAgICAgICAgIC8vIGxldCBiX2IgPSBzZWxmLmMxICogYzE7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIEFfYzEsIGMxLCBiX2IpLFxuXG5cbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgQV9jMCwgQV9jMSwgQWMwX0FjMSksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIEFfYzAsIEFfYzIsIEFjMF9BYzIpLFxuXG4gICAgICAgICAgICAvLyBsZXQgdDEgPSAoc2VsZi5jMSArIHNlbGYuYzIpICogYzEgLSBiX2I7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIEFfYzEsIEFfYzIsIHQxKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgdDEsIGMxLCB0MSksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3ViXCIsIHQxLCBiX2IsIHQxKSxcblxuICAgICAgICAgICAgLy8gbGV0IHQxID0gdDEubXVsX2J5X25vbnJlc2lkdWUoKSArIGFfYTtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxOUlwiLCB0MSwgdDEpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0MSwgYV9hLCB0MSksXG5cbiAgICAgICAgICAgIC8vIGxldCB0MiA9IChjMCArIGMxKSAqIChzZWxmLmMwICsgc2VsZi5jMSkgLSBhX2EgLSBiX2I7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIGMwLCBjMSwgdDIpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCB0MiwgQWMwX0FjMSwgdDIpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3N1YlwiLCB0MiwgYV9hLCB0MiksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3ViXCIsIHQyLCBiX2IsIHQyKSxcblxuICAgICAgICAgICAgLy8gbGV0IHQzID0gKHNlbGYuYzAgKyBzZWxmLmMyKSAqIGMwIC0gYV9hICsgYl9iO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCBBYzBfQWMyLCBjMCwgdDMpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3N1YlwiLCB0MywgYV9hLCB0MyksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIHQzLCBiX2IsIHQzKSxcblxuXG4gICAgICAgICk7XG4gICAgfVxuICAgIGJ1aWxkRjZNdWwwMSgpO1xuXG5cbiAgICBmdW5jdGlvbiBidWlsZEYxMk11bDAxNCgpIHtcblxuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKGZ0bVByZWZpeCsgXCJfbXVsMDE0XCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicEFcIiwgXCJpMzJcIik7ICAgIC8vIEYxMlxuICAgICAgICBmLmFkZFBhcmFtKFwicEMwXCIsIFwiaTMyXCIpOyAgIC8vIEYyXG4gICAgICAgIGYuYWRkUGFyYW0oXCJwQzFcIiwgXCJpMzJcIik7ICAgLy8gRjJcbiAgICAgICAgZi5hZGRQYXJhbShcInBDNFwiLCBcImkzMlwiKTsgICAvLyBGMlxuICAgICAgICBmLmFkZFBhcmFtKFwicFJcIiwgXCJpMzJcIik7ICAgIC8vIEYxMlxuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cblxuICAgICAgICBjb25zdCBBX2MwID0gYy5nZXRMb2NhbChcInBBXCIpO1xuICAgICAgICBjb25zdCBBX2MxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwQVwiKSwgYy5pMzJfY29uc3QoZjFzaXplKjYpKTtcblxuICAgICAgICBjb25zdCBjMCAgPSBjLmdldExvY2FsKFwicEMwXCIpO1xuICAgICAgICBjb25zdCBjMSAgPSBjLmdldExvY2FsKFwicEMxXCIpO1xuICAgICAgICBjb25zdCBjNCAgPSBjLmdldExvY2FsKFwicEM0XCIpO1xuXG4gICAgICAgIGNvbnN0IGFhID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxc2l6ZSo2KSk7XG4gICAgICAgIGNvbnN0IGJiID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYxc2l6ZSo2KSk7XG4gICAgICAgIGNvbnN0IG8gPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjFzaXplKjIpKTtcblxuICAgICAgICBjb25zdCBSX2MwID0gYy5nZXRMb2NhbChcInBSXCIpO1xuICAgICAgICBjb25zdCBSX2MxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwUlwiKSwgYy5pMzJfY29uc3QoZjFzaXplKjYpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICAvLyBsZXQgYWEgPSBzZWxmLmMwLm11bF9ieV8wMShjMCwgYzEpO1xuICAgICAgICAgICAgYy5jYWxsKGY2bVByZWZpeCArIFwiX211bDAxXCIsIEFfYzAsIGMwLCBjMSwgYWEpLFxuXG4gICAgICAgICAgICAvLyBsZXQgYmIgPSBzZWxmLmMxLm11bF9ieV8xKGM0KTtcbiAgICAgICAgICAgIGMuY2FsbChmNm1QcmVmaXggKyBcIl9tdWwxXCIsIEFfYzEsIGM0LCBiYiksXG5cbiAgICAgICAgICAgIC8vIGxldCBvID0gYzEgKyBjNDtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgYzEsIGM0LCBvKSxcblxuICAgICAgICAgICAgLy8gbGV0IGMxID0gc2VsZi5jMSArIHNlbGYuYzA7XG4gICAgICAgICAgICBjLmNhbGwoZjZtUHJlZml4ICsgXCJfYWRkXCIsIEFfYzEsIEFfYzAsIFJfYzEpLFxuXG4gICAgICAgICAgICAvLyBsZXQgYzEgPSBjMS5tdWxfYnlfMDEoYzAsICZvKTtcbiAgICAgICAgICAgIGMuY2FsbChmNm1QcmVmaXggKyBcIl9tdWwwMVwiLCBSX2MxLCBjMCwgbywgUl9jMSksXG5cbiAgICAgICAgICAgIC8vIGxldCBjMSA9IGMxIC0gYWEgLSBiYjtcbiAgICAgICAgICAgIGMuY2FsbChmNm1QcmVmaXggKyBcIl9zdWJcIiwgUl9jMSwgYWEsIFJfYzEpLFxuICAgICAgICAgICAgYy5jYWxsKGY2bVByZWZpeCArIFwiX3N1YlwiLCBSX2MxLCBiYiwgUl9jMSksXG5cbiAgICAgICAgICAgIC8vIGxldCBjMCA9IGJiO1xuICAgICAgICAgICAgYy5jYWxsKGY2bVByZWZpeCArIFwiX2NvcHlcIiwgYmIsIFJfYzApLFxuXG4gICAgICAgICAgICAvLyBsZXQgYzAgPSBjMC5tdWxfYnlfbm9ucmVzaWR1ZSgpO1xuICAgICAgICAgICAgYy5jYWxsKGY2bVByZWZpeCArIFwiX211bE5SXCIsIFJfYzAsIFJfYzApLFxuXG4gICAgICAgICAgICAvLyBsZXQgYzAgPSBjMCArIGFhO1xuICAgICAgICAgICAgYy5jYWxsKGY2bVByZWZpeCArIFwiX2FkZFwiLCBSX2MwLCBhYSwgUl9jMCksXG4gICAgICAgICk7XG4gICAgfVxuICAgIGJ1aWxkRjEyTXVsMDE0KCk7XG5cblxuICAgIGZ1bmN0aW9uIGJ1aWxkRUxMKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCsgXCJfZWxsXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicFBcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwQ29lZnNcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwRlwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IFB4ICA9IGMuZ2V0TG9jYWwoXCJwUFwiKTtcbiAgICAgICAgY29uc3QgUHkgID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwUFwiKSwgYy5pMzJfY29uc3QobjhxKSk7XG5cbiAgICAgICAgY29uc3QgRiAgPSBjLmdldExvY2FsKFwicEZcIik7XG5cbiAgICAgICAgY29uc3QgY29lZjBfMCAgPSBjLmdldExvY2FsKFwicENvZWZzXCIpO1xuICAgICAgICBjb25zdCBjb2VmMF8xICA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwicENvZWZzXCIpLCBjLmkzMl9jb25zdChmMXNpemUpKTtcbiAgICAgICAgY29uc3QgY29lZjFfMCAgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInBDb2Vmc1wiKSwgYy5pMzJfY29uc3QoZjFzaXplKjIpKTtcbiAgICAgICAgY29uc3QgY29lZjFfMSAgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInBDb2Vmc1wiKSwgYy5pMzJfY29uc3QoZjFzaXplKjMpKTtcbiAgICAgICAgY29uc3QgY29lZjIgID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwQ29lZnNcIiksIGMuaTMyX2NvbnN0KGYxc2l6ZSo0KSk7XG5cbiAgICAgICAgY29uc3QgcGMwID0gbW9kdWxlLmFsbG9jKGYxc2l6ZSoyKTtcbiAgICAgICAgY29uc3QgYzAgID0gYy5pMzJfY29uc3QocGMwKTtcbiAgICAgICAgY29uc3QgYzBfYzAgPSBjLmkzMl9jb25zdChwYzApO1xuICAgICAgICBjb25zdCBjMF9jMSA9IGMuaTMyX2NvbnN0KHBjMCtmMXNpemUpO1xuXG4gICAgICAgIGNvbnN0IHBjMSA9IG1vZHVsZS5hbGxvYyhmMXNpemUqMik7XG4gICAgICAgIGNvbnN0IGMxICA9IGMuaTMyX2NvbnN0KHBjMSk7XG4gICAgICAgIGNvbnN0IGMxX2MwID0gYy5pMzJfY29uc3QocGMxKTtcbiAgICAgICAgY29uc3QgYzFfYzEgPSBjLmkzMl9jb25zdChwYzErZjFzaXplKTtcbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgLy8gICAgIGxldCBtdXQgYzAgPSBjb2VmZnMuMDtcbiAgICAgICAgICAgIC8vICAgICBsZXQgbXV0IGMxID0gY29lZmZzLjE7XG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgLy8gICAgYzAuYzAgKj0gcC55O1xuICAgICAgICAgICAgLy8gICAgYzAuYzEgKj0gcC55O1xuICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIC8vICAgIGMxLmMwICo9IHAueDtcbiAgICAgICAgICAgIC8vICAgIGMxLmMxICo9IHAueDtcbiAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAvLyAgICAgZi5tdWxfYnlfMDE0KCZjb2VmZnMuMiwgJmMxLCAmYzApXG5cbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXggKyBcIl9tdWxcIiwgY29lZjBfMCwgUHksIGMwX2MwKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXggKyBcIl9tdWxcIiwgY29lZjBfMSwgUHksIGMwX2MxKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXggKyBcIl9tdWxcIiwgY29lZjFfMCwgUHgsIGMxX2MwKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXggKyBcIl9tdWxcIiwgY29lZjFfMSwgUHgsIGMxX2MxKSxcblxuICAgICAgICAgICAgYy5jYWxsKGZ0bVByZWZpeCArIFwiX211bDAxNFwiLCBGLCBjb2VmMiwgYzEsIGMwLCBGKSxcblxuICAgICAgICApO1xuXG4gICAgfVxuICAgIGJ1aWxkRUxMKCk7XG5cbiAgICBmdW5jdGlvbiBidWlsZE1pbGxlckxvb3AoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24ocHJlZml4KyBcIl9taWxsZXJMb29wXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicHByZVBcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwcHJlUVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkTG9jYWwoXCJwQ29lZlwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRMb2NhbChcImlcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCBwcmVQID0gYy5nZXRMb2NhbChcInBwcmVQXCIpO1xuXG4gICAgICAgIGNvbnN0IGNvZWZzICA9IGMuZ2V0TG9jYWwoXCJwQ29lZlwiKTtcblxuICAgICAgICBjb25zdCBGID0gYy5nZXRMb2NhbChcInJcIik7XG5cblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfb25lXCIsIEYpLFxuXG4gICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgIGMuY2FsbChnMW1QcmVmaXggKyBcIl9pc1plcm9cIiwgcHJlUCksXG4gICAgICAgICAgICAgICAgYy5yZXQoW10pXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmNhbGwoZzFtUHJlZml4ICsgXCJfaXNaZXJvXCIsIGMuZ2V0TG9jYWwoXCJwcHJlUVwiKSksXG4gICAgICAgICAgICAgICAgYy5yZXQoW10pXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYy5zZXRMb2NhbChcInBDb2VmXCIsIGMuaTMyX2FkZCggYy5nZXRMb2NhbChcInBwcmVRXCIpLCBjLmkzMl9jb25zdChmMnNpemUqMykpKSxcblxuICAgICAgICAgICAgYy5zZXRMb2NhbChcImlcIiwgYy5pMzJfY29uc3QoYXRlTG9vcEJpdEJ5dGVzLmxlbmd0aC0yKSksXG4gICAgICAgICAgICBjLmJsb2NrKGMubG9vcChcblxuXG4gICAgICAgICAgICAgICAgYy5jYWxsKHByZWZpeCArIFwiX2VsbFwiLCBwcmVQLCBjb2VmcywgIEYpLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJwQ29lZlwiLCBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInBDb2VmXCIpLCBjLmkzMl9jb25zdChhdGVDb2VmU2l6ZSkpKSxcblxuICAgICAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgICAgIGMuaTMyX2xvYWQ4X3MoYy5nZXRMb2NhbChcImlcIiksIHBBdGVMb29wQml0Qnl0ZXMpLFxuICAgICAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgICAgICAuLi5jLmNhbGwocHJlZml4ICsgXCJfZWxsXCIsIHByZVAsIGNvZWZzLCAgRiksXG4gICAgICAgICAgICAgICAgICAgICAgICAuLi5jLnNldExvY2FsKFwicENvZWZcIiwgYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwQ29lZlwiKSwgYy5pMzJfY29uc3QoYXRlQ29lZlNpemUpKSksXG4gICAgICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9zcXVhcmVcIiwgRiwgRiksXG5cbiAgICAgICAgICAgICAgICBjLmJyX2lmKDEsIGMuaTMyX2VxICggYy5nZXRMb2NhbChcImlcIiksIGMuaTMyX2NvbnN0KDEpICkpLFxuICAgICAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpXCIsIGMuaTMyX3N1YihjLmdldExvY2FsKFwiaVwiKSwgYy5pMzJfY29uc3QoMSkpKSxcbiAgICAgICAgICAgICAgICBjLmJyKDApXG4gICAgICAgICAgICApKSxcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9lbGxcIiwgcHJlUCwgY29lZnMsICBGKSxcblxuICAgICAgICApO1xuXG5cbiAgICAgICAge1xuICAgICAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9jb25qdWdhdGVcIiwgRiwgRiksXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICBmdW5jdGlvbiBidWlsZEZyb2Jlbml1c01hcChuKSB7XG4gICAgICAgIGNvbnN0IEYxMiA9IFtcbiAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICBbMW4sIDBuXSxcbiAgICAgICAgICAgICAgICBbMW4sIDBuXSxcbiAgICAgICAgICAgICAgICBbMW4sIDBuXSxcbiAgICAgICAgICAgICAgICBbMW4sIDBuXSxcbiAgICAgICAgICAgICAgICBbMW4sIDBuXSxcbiAgICAgICAgICAgICAgICBbMW4sIDBuXSxcbiAgICAgICAgICAgICAgICBbMW4sIDBuXSxcbiAgICAgICAgICAgICAgICBbMW4sIDBuXSxcbiAgICAgICAgICAgICAgICBbMW4sIDBuXSxcbiAgICAgICAgICAgICAgICBbMW4sIDBuXSxcbiAgICAgICAgICAgICAgICBbMW4sIDBuXSxcbiAgICAgICAgICAgICAgICBbMW4sIDBuXSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgWzFuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzM4NTA3NTQzNzAwMzcxNjkwMTE5NTIxNDcwNzYwNTEzNjQwNTcxNTg4MDc0MjA5NzA2ODI0Mzg2NzYwNTA1MjI2MTM2Mjg0MjMyMTk2Mzc3MjUwNzIxODI2OTcxMTMwNjI3Nzc4OTE1ODk1MDY0MjQ3NjBuLCAxNTE2NTUxODUxODQ0OTgzODE0NjU2NDI3NDk2ODQ1NDAwOTkzOTgwNzUzOTg5NjgzMjU0NDY2NTYwMDc2MTM1MTA0MDMyMjcyNzEyMDAxMzkzNzA1MDQ5MzIwMTU5NTI4ODYxNDYzMDQ3NjYxMzUwMjduXSxcbiAgICAgICAgICAgICAgICBbNzkzNDc5MzkwNzI5MjE1NTEyNjIxMzc5NzAxNjMzNDIxNDQ3MDYwODg2NzQwMjgxMDYwNDkzMDEwNDU2NDg3NDI3MjgxNjQ5MDc1NDc2MzA1NjIwNzU4NzMxNjIwMzUxbiwgMG5dLFxuICAgICAgICAgICAgICAgIFsyOTczNjc3NDA4OTg2NTYxMDQzNDQyNDY1MzQ2NTIwMTA4ODc5MTcyMDQyODgzMDA5MjQ5OTg5MTc2NDE1MDE4MDkxNDIwODA3MTkyMTgyNjM4NTY3MTE2MzE4NTc2NDcyNjQ5MzQ3MDE1OTE3NjkwNTMwbiwgMTAyODczMjE0NjIzNTEwNjM0OTk3NTMyNDQ3OTIxNTc5NTI3NzM4NDgzOTkzNjkyOTc1Nzg5NjE1NTY0MzExODAzMjYxMDg0MzI5ODY1NTIyNTg3NTU3MTMxMDU1MjU0MzAxNDY5MDg3ODM1NDg2OTI1N25dLFxuICAgICAgICAgICAgICAgIFs3OTM0NzkzOTA3MjkyMTU1MTI2MjEzNzk3MDE2MzM0MjE0NDcwNjA4ODY3NDAyODEwNjA0OTMwMTA0NTY0ODc0MjcyODE2NDkwNzU0NzYzMDU2MjA3NTg3MzE2MjAzNTBuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzMxMjUzMzI1OTQxNzEwNTk0MjQ5MDgxMDgwOTYyMDQ2NDg5Nzg1NzAxMTgyODE5Nzc1NzU0MzU4MzI0MjI2MzE2MDE4MjQwMzQ0NjMzODI3Nzc5Mzc2MjEyNTA1OTI0MjU1MzU0OTMzMjA2ODM4MjU1NTduLCA4NzcwNzY5NjEwNTA2MDc5Njg1MDk2ODE3Mjk1MzEyNTUxNzc5ODY3NjQ1Mzc5NjE0MzI0NDk0OTk2MzU1MDQ1MjIyMDc2MTYwMjc0NTUwODY1MDUwNjYzNzg1MzY1OTAxMjg1NDQ1NzM1ODg3MzQyMzBuXSxcbiAgICAgICAgICAgICAgICBbNDAwMjQwOTU1NTIyMTY2NzM5MzQxNzc4OTgyNTczNTkwNDE1NjU1Njg4MjgxOTkzOTAwNzg4NTMzMjA1ODEzNjEyNDAzMTY1MDQ5MDgzNzg2NDQ0MjY4NzYyOTEyOTAxNTY2NDAzNzg5NDI3MjU1OTc4Nm4sIDBuXSxcbiAgICAgICAgICAgICAgICBbMTUxNjU1MTg1MTg0NDk4MzgxNDY1NjQyNzQ5Njg0NTQwMDk5Mzk4MDc1Mzk4OTY4MzI1NDQ2NjU2MDA3NjEzNTEwNDAzMjI3MjcxMjAwMTM5MzcwNTA0OTMyMDE1OTUyODg2MTQ2MzA0NzY2MTM1MDI3biwgMzg1MDc1NDM3MDAzNzE2OTAxMTk1MjE0NzA3NjA1MTM2NDA1NzE1ODgwNzQyMDk3MDY4MjQzODY3NjA1MDUyMjYxMzYyODQyMzIxOTYzNzcyNTA3MjE4MjY5NzExMzA2Mjc3Nzg5MTU4OTUwNjQyNDc2MG5dLFxuICAgICAgICAgICAgICAgIFs0MDAyNDA5NTU1MjIxNjY3MzkyNjI0MzEwNDM1MDA2Njg4NjQzOTM1NTAzMTE4MzA1NTg2NDM4MjcxMTcxMzk1ODQyOTcxMTU3NDgwMzgxMzc3MDE1NDA1OTgwMDUzNTM5MzU4NDE3MTM1NTQwOTM5NDM2biwgMG5dLFxuICAgICAgICAgICAgICAgIFsxMDI4NzMyMTQ2MjM1MTA2MzQ5OTc1MzI0NDc5MjE1Nzk1Mjc3Mzg0ODM5OTM2OTI5NzU3ODk2MTU1NjQzMTE4MDMyNjEwODQzMjk4NjU1MjI1ODc1NTcxMzEwNTUyNTQzMDE0NjkwODc4MzU0ODY5MjU3biwgMjk3MzY3NzQwODk4NjU2MTA0MzQ0MjQ2NTM0NjUyMDEwODg3OTE3MjA0Mjg4MzAwOTI0OTk4OTE3NjQxNTAxODA5MTQyMDgwNzE5MjE4MjYzODU2NzExNjMxODU3NjQ3MjY0OTM0NzAxNTkxNzY5MDUzMG5dLFxuICAgICAgICAgICAgICAgIFs0MDAyNDA5NTU1MjIxNjY3MzkyNjI0MzEwNDM1MDA2Njg4NjQzOTM1NTAzMTE4MzA1NTg2NDM4MjcxMTcxMzk1ODQyOTcxMTU3NDgwMzgxMzc3MDE1NDA1OTgwMDUzNTM5MzU4NDE3MTM1NTQwOTM5NDM3biwgMG5dLFxuICAgICAgICAgICAgICAgIFs4NzcwNzY5NjEwNTA2MDc5Njg1MDk2ODE3Mjk1MzEyNTUxNzc5ODY3NjQ1Mzc5NjE0MzI0NDk0OTk2MzU1MDQ1MjIyMDc2MTYwMjc0NTUwODY1MDUwNjYzNzg1MzY1OTAxMjg1NDQ1NzM1ODg3MzQyMzBuLCAzMTI1MzMyNTk0MTcxMDU5NDI0OTA4MTA4MDk2MjA0NjQ4OTc4NTcwMTE4MjgxOTc3NTc1NDM1ODMyNDIyNjMxNjAxODI0MDM0NDYzMzgyNzc3OTM3NjIxMjUwNTkyNDI1NTM1NDkzMzIwNjgzODI1NTU3bl0sXG4gICAgICAgICAgICBdXG4gICAgICAgIF07XG5cbiAgICAgICAgY29uc3QgRjYgPSBbXG4gICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgWzFuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzFuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzFuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzFuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzFuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzFuLCAwbl0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgIFsxbiwgMG5dLFxuICAgICAgICAgICAgICAgIFswbiwgNDAwMjQwOTU1NTIyMTY2NzM5MjYyNDMxMDQzNTAwNjY4ODY0MzkzNTUwMzExODMwNTU4NjQzODI3MTE3MTM5NTg0Mjk3MTE1NzQ4MDM4MTM3NzAxNTQwNTk4MDA1MzUzOTM1ODQxNzEzNTU0MDkzOTQzNm5dLFxuICAgICAgICAgICAgICAgIFs3OTM0NzkzOTA3MjkyMTU1MTI2MjEzNzk3MDE2MzM0MjE0NDcwNjA4ODY3NDAyODEwNjA0OTMwMTA0NTY0ODc0MjcyODE2NDkwNzU0NzYzMDU2MjA3NTg3MzE2MjAzNTBuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzBuLCAxbl0sXG4gICAgICAgICAgICAgICAgWzQwMDI0MDk1NTUyMjE2NjczOTI2MjQzMTA0MzUwMDY2ODg2NDM5MzU1MDMxMTgzMDU1ODY0MzgyNzExNzEzOTU4NDI5NzExNTc0ODAzODEzNzcwMTU0MDU5ODAwNTM1MzkzNTg0MTcxMzU1NDA5Mzk0MzZuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzBuLCA3OTM0NzkzOTA3MjkyMTU1MTI2MjEzNzk3MDE2MzM0MjE0NDcwNjA4ODY3NDAyODEwNjA0OTMwMTA0NTY0ODc0MjcyODE2NDkwNzU0NzYzMDU2MjA3NTg3MzE2MjAzNTBuXSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgWzFuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzQwMDI0MDk1NTUyMjE2NjczOTI2MjQzMTA0MzUwMDY2ODg2NDM5MzU1MDMxMTgzMDU1ODY0MzgyNzExNzEzOTU4NDI5NzExNTc0ODAzODEzNzcwMTU0MDU5ODAwNTM1MzkzNTg0MTcxMzU1NDA5Mzk0MzduLCAwbl0sXG4gICAgICAgICAgICAgICAgWzQwMDI0MDk1NTUyMjE2NjczOTI2MjQzMTA0MzUwMDY2ODg2NDM5MzU1MDMxMTgzMDU1ODY0MzgyNzExNzEzOTU4NDI5NzExNTc0ODAzODEzNzcwMTU0MDU5ODAwNTM1MzkzNTg0MTcxMzU1NDA5Mzk0MzZuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzQwMDI0MDk1NTUyMjE2NjczOTM0MTc3ODk4MjU3MzU5MDQxNTY1NTY4ODI4MTk5MzkwMDc4ODUzMzIwNTgxMzYxMjQwMzE2NTA0OTA4Mzc4NjQ0NDI2ODc2MjkxMjkwMTU2NjQwMzc4OTQyNzI1NTk3ODZuLCAwbl0sXG4gICAgICAgICAgICAgICAgWzc5MzQ3OTM5MDcyOTIxNTUxMjYyMTM3OTcwMTYzMzQyMTQ0NzA2MDg4Njc0MDI4MTA2MDQ5MzAxMDQ1NjQ4NzQyNzI4MTY0OTA3NTQ3NjMwNTYyMDc1ODczMTYyMDM1MG4sIDBuXSxcbiAgICAgICAgICAgICAgICBbNzkzNDc5MzkwNzI5MjE1NTEyNjIxMzc5NzAxNjMzNDIxNDQ3MDYwODg2NzQwMjgxMDYwNDkzMDEwNDU2NDg3NDI3MjgxNjQ5MDc1NDc2MzA1NjIwNzU4NzMxNjIwMzUxbiwgMG5dLFxuICAgICAgICAgICAgXVxuICAgICAgICBdO1xuXG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24oZnRtUHJlZml4ICsgXCJfZnJvYmVuaXVzTWFwXCIrbik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ4XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiclwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGZvciAobGV0IGk9MDsgaTw2OyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IFggPSAoaT09MCkgPyBjLmdldExvY2FsKFwieFwiKSA6IGMuaTMyX2FkZChjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QoaSpmMnNpemUpKTtcbiAgICAgICAgICAgIGNvbnN0IFhjMCA9IFg7XG4gICAgICAgICAgICBjb25zdCBYYzEgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KGkqZjJzaXplICsgZjFzaXplKSk7XG4gICAgICAgICAgICBjb25zdCBSID0gKGk9PTApID8gYy5nZXRMb2NhbChcInJcIikgOiBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInJcIiksIGMuaTMyX2NvbnN0KGkqZjJzaXplKSk7XG4gICAgICAgICAgICBjb25zdCBSYzAgPSBSO1xuICAgICAgICAgICAgY29uc3QgUmMxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJyXCIpLCBjLmkzMl9jb25zdChpKmYyc2l6ZSArIGYxc2l6ZSkpO1xuICAgICAgICAgICAgY29uc3QgY29lZiA9IG11bDIoRjEyW01hdGguZmxvb3IoaS8zKV1bbiUxMl0gLCBGNltpJTNdW24lNl0pO1xuICAgICAgICAgICAgY29uc3QgcENvZWYgPSBtb2R1bGUuYWxsb2MoW1xuICAgICAgICAgICAgICAgIC4uLnV0aWxzLmJpZ0ludDJCeXRlc0xFKHRvTW9udGdvbWVyeShjb2VmWzBdKSwgbjhxKSxcbiAgICAgICAgICAgICAgICAuLi51dGlscy5iaWdJbnQyQnl0ZXNMRSh0b01vbnRnb21lcnkoY29lZlsxXSksIG44cSksXG4gICAgICAgICAgICBdKTtcbiAgICAgICAgICAgIGlmIChuJTIgPT0gMSkge1xuICAgICAgICAgICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCArIFwiX2NvcHlcIiwgWGMwLCBSYzApLFxuICAgICAgICAgICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4ICsgXCJfbmVnXCIsIFhjMSwgUmMxKSxcbiAgICAgICAgICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCBSLCBjLmkzMl9jb25zdChwQ29lZiksIFIpLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGYuYWRkQ29kZShjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIFgsIGMuaTMyX2NvbnN0KHBDb2VmKSwgUikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gbXVsMihhLCBiKSB7XG4gICAgICAgICAgICBjb25zdCBhYzAgPSBhWzBdO1xuICAgICAgICAgICAgY29uc3QgYWMxID0gYVsxXTtcbiAgICAgICAgICAgIGNvbnN0IGJjMCA9IGJbMF07XG4gICAgICAgICAgICBjb25zdCBiYzEgPSBiWzFdO1xuICAgICAgICAgICAgY29uc3QgcmVzID0gW1xuICAgICAgICAgICAgICAgIChhYzAgKiBiYzAgLSAoYWMxICogYmMxKSkgJSBxLFxuICAgICAgICAgICAgICAgIChhYzAgKiBiYzEgKyAoYWMxICogYmMwKSkgJSBxLFxuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIGlmIChpc05lZ2F0aXZlJDEocmVzWzBdKSkgcmVzWzBdID0gcmVzWzBdICsgcTtcbiAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH1cblxuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gYnVpbGRDeWNsb3RvbWljU3F1YXJlKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCsgXCJfX2N5Y2xvdG9taWNTcXVhcmVcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJ4XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwiclwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IHgwID0gYy5nZXRMb2NhbChcInhcIik7XG4gICAgICAgIGNvbnN0IHg0ID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdChmMnNpemUpKTtcbiAgICAgICAgY29uc3QgeDMgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KDIqZjJzaXplKSk7XG4gICAgICAgIGNvbnN0IHgyID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdCgzKmYyc2l6ZSkpO1xuICAgICAgICBjb25zdCB4MSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwieFwiKSwgYy5pMzJfY29uc3QoNCpmMnNpemUpKTtcbiAgICAgICAgY29uc3QgeDUgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInhcIiksIGMuaTMyX2NvbnN0KDUqZjJzaXplKSk7XG5cbiAgICAgICAgY29uc3QgcjAgPSBjLmdldExvY2FsKFwiclwiKTtcbiAgICAgICAgY29uc3QgcjQgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInJcIiksIGMuaTMyX2NvbnN0KGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCByMyA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwiclwiKSwgYy5pMzJfY29uc3QoMipmMnNpemUpKTtcbiAgICAgICAgY29uc3QgcjIgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInJcIiksIGMuaTMyX2NvbnN0KDMqZjJzaXplKSk7XG4gICAgICAgIGNvbnN0IHIxID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJyXCIpLCBjLmkzMl9jb25zdCg0KmYyc2l6ZSkpO1xuICAgICAgICBjb25zdCByNSA9IGMuaTMyX2FkZChjLmdldExvY2FsKFwiclwiKSwgYy5pMzJfY29uc3QoNSpmMnNpemUpKTtcblxuICAgICAgICBjb25zdCB0MCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcbiAgICAgICAgY29uc3QgdDEgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjJzaXplKSk7XG4gICAgICAgIGNvbnN0IHQyID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCB0MyA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcbiAgICAgICAgY29uc3QgdDQgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjJzaXplKSk7XG4gICAgICAgIGNvbnN0IHQ1ID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGYyc2l6ZSkpO1xuICAgICAgICBjb25zdCB0bXAgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjJzaXplKSk7XG4gICAgICAgIGNvbnN0IEFVWCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcblxuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIC8vICAgIC8vIHQwICsgdDEqeSA9ICh6MCArIHoxKnkpXjIgPSBhXjJcbiAgICAgICAgICAgIC8vICAgIHRtcCA9IHowICogejE7XG4gICAgICAgICAgICAvLyAgICB0MCA9ICh6MCArIHoxKSAqICh6MCArIG15X0ZwNjo6bm9uX3Jlc2lkdWUgKiB6MSkgLSB0bXAgLSBteV9GcDY6Om5vbl9yZXNpZHVlICogdG1wO1xuICAgICAgICAgICAgLy8gICAgdDEgPSB0bXAgKyB0bXA7XG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIHgwLCB4MSwgdG1wKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxOUlwiLCB4MSwgdDApLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB4MCwgdDAsIHQwKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgeDAsIHgxLCBBVVgpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCBBVVgsIHQwLCB0MCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsTlJcIiwgdG1wLCBBVVgpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0bXAsIEFVWCwgQVVYKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9zdWJcIiwgdDAsIEFVWCwgdDApLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0bXAsIHRtcCwgdDEpLFxuXG4gICAgICAgICAgICAvLyAgLy8gdDIgKyB0Myp5ID0gKHoyICsgejMqeSleMiA9IGJeMlxuICAgICAgICAgICAgLy8gIHRtcCA9IHoyICogejM7XG4gICAgICAgICAgICAvLyAgdDIgPSAoejIgKyB6MykgKiAoejIgKyBteV9GcDY6Om5vbl9yZXNpZHVlICogejMpIC0gdG1wIC0gbXlfRnA2Ojpub25fcmVzaWR1ZSAqIHRtcDtcbiAgICAgICAgICAgIC8vICB0MyA9IHRtcCArIHRtcDtcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgeDIsIHgzLCB0bXApLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bE5SXCIsIHgzLCB0MiksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIHgyLCB0MiwgdDIpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB4MiwgeDMsIEFVWCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIEFVWCwgdDIsIHQyKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxOUlwiLCB0bXAsIEFVWCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIHRtcCwgQVVYLCBBVVgpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3N1YlwiLCB0MiwgQVVYLCB0MiksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIHRtcCwgdG1wLCB0MyksXG5cbiAgICAgICAgICAgIC8vICAvLyB0NCArIHQ1KnkgPSAoejQgKyB6NSp5KV4yID0gY14yXG4gICAgICAgICAgICAvLyAgdG1wID0gejQgKiB6NTtcbiAgICAgICAgICAgIC8vICB0NCA9ICh6NCArIHo1KSAqICh6NCArIG15X0ZwNjo6bm9uX3Jlc2lkdWUgKiB6NSkgLSB0bXAgLSBteV9GcDY6Om5vbl9yZXNpZHVlICogdG1wO1xuICAgICAgICAgICAgLy8gIHQ1ID0gdG1wICsgdG1wO1xuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCB4NCwgeDUsIHRtcCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsTlJcIiwgeDUsIHQ0KSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgeDQsIHQ0LCB0NCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIHg0LCB4NSwgQVVYKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9tdWxcIiwgQVVYLCB0NCwgdDQpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bE5SXCIsIHRtcCwgQVVYKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgdG1wLCBBVVgsIEFVWCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3ViXCIsIHQ0LCBBVVgsIHQ0KSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgdG1wLCB0bXAsIHQ1KSxcblxuICAgICAgICAgICAgLy8gRm9yIEFcbiAgICAgICAgICAgIC8vIHowID0gMyAqIHQwIC0gMiAqIHowXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3ViXCIsIHQwLCB4MCwgcjApLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCByMCwgcjAsIHIwKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgdDAsIHIwLCByMCksXG4gICAgICAgICAgICAvLyB6MSA9IDMgKiB0MSArIDIgKiB6MVxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0MSwgeDEsIHIxKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgcjEsIHIxLCByMSksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIHQxLCByMSwgcjEpLFxuXG4gICAgICAgICAgICAvLyBGb3IgQlxuICAgICAgICAgICAgLy8gejIgPSAzICogKHhpICogdDUpICsgMiAqIHoyXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIHQ1LCBjLmkzMl9jb25zdChwQmxzMTIzODFUd2lzdCksIEFVWCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIEFVWCwgeDIsIHIyKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgcjIsIHIyLCByMiksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIEFVWCwgcjIsIHIyKSxcbiAgICAgICAgICAgIC8vIHozID0gMyAqIHQ0IC0gMiAqIHozXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfc3ViXCIsIHQ0LCB4MywgcjMpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCByMywgcjMsIHIzKSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgdDQsIHIzLCByMyksXG5cbiAgICAgICAgICAgIC8vIEZvciBDXG4gICAgICAgICAgICAvLyB6NCA9IDMgKiB0MiAtIDIgKiB6NFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX3N1YlwiLCB0MiwgeDQsIHI0KSxcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgcjQsIHI0LCByNCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIHQyLCByNCwgcjQpLFxuICAgICAgICAgICAgLy8gejUgPSAzICogdDMgKyAyICogejVcbiAgICAgICAgICAgIGMuY2FsbChmMm1QcmVmaXggKyBcIl9hZGRcIiwgdDMsIHg1LCByNSksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfYWRkXCIsIHI1LCByNSwgcjUpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX2FkZFwiLCB0MywgcjUsIHI1KSxcblxuICAgICAgICApO1xuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gYnVpbGRDeWNsb3RvbWljRXhwKGV4cG9uZW50LCBpc0V4cE5lZ2F0aXZlLCBmbk5hbWUpIHtcbiAgICAgICAgY29uc3QgZXhwb25lbnROYWZCeXRlcyA9IG5hZihleHBvbmVudCkubWFwKCAoYikgPT4gKGI9PS0xID8gMHhGRjogYikgKTtcbiAgICAgICAgY29uc3QgcEV4cG9uZW50TmFmQnl0ZXMgPSBtb2R1bGUuYWxsb2MoZXhwb25lbnROYWZCeXRlcyk7XG4gICAgICAgIC8vIGNvbnN0IHBFeHBvbmVudCA9IG1vZHVsZS5hbGxvYyh1dGlscy5iaWdJbnQyQnl0ZXNMRShleHBvbmVudCwgbjgpKTtcblxuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCsgXCJfX2N5Y2xvdG9taWNFeHBfXCIrZm5OYW1lKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiYml0XCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZExvY2FsKFwiaVwiLCBcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjID0gZi5nZXRDb2RlQnVpbGRlcigpO1xuXG4gICAgICAgIGNvbnN0IHggPSBjLmdldExvY2FsKFwieFwiKTtcblxuICAgICAgICBjb25zdCByZXMgPSBjLmdldExvY2FsKFwiclwiKTtcblxuICAgICAgICBjb25zdCBpbnZlcnNlID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGZ0c2l6ZSkpO1xuXG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5jYWxsKGZ0bVByZWZpeCArIFwiX2Nvbmp1Z2F0ZVwiLCB4LCBpbnZlcnNlKSxcbiAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9vbmVcIiwgcmVzKSxcblxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLnRlZUxvY2FsKFwiYml0XCIsIGMuaTMyX2xvYWQ4X3MoYy5pMzJfY29uc3QoZXhwb25lbnROYWZCeXRlcy5sZW5ndGgtMSksIHBFeHBvbmVudE5hZkJ5dGVzKSksXG4gICAgICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfZXEoXG4gICAgICAgICAgICAgICAgICAgICAgICBjLmdldExvY2FsKFwiYml0XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfY29uc3QoMSlcbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgYy5jYWxsKGZ0bVByZWZpeCArIFwiX211bFwiLCByZXMsIHgsIHJlcyksXG4gICAgICAgICAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9tdWxcIiwgcmVzLCBpbnZlcnNlLCByZXMpLFxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgIGMuc2V0TG9jYWwoXCJpXCIsIGMuaTMyX2NvbnN0KGV4cG9uZW50TmFmQnl0ZXMubGVuZ3RoLTIpKSxcbiAgICAgICAgICAgIGMuYmxvY2soYy5sb29wKFxuICAgICAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9fY3ljbG90b21pY1NxdWFyZVwiLCByZXMsIHJlcyksXG4gICAgICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICAgICAgYy50ZWVMb2NhbChcImJpdFwiLCBjLmkzMl9sb2FkOF9zKGMuZ2V0TG9jYWwoXCJpXCIpLCBwRXhwb25lbnROYWZCeXRlcykpLFxuICAgICAgICAgICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5pMzJfZXEoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5nZXRMb2NhbChcImJpdFwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmkzMl9jb25zdCgxKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9tdWxcIiwgcmVzLCB4LCByZXMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYy5jYWxsKGZ0bVByZWZpeCArIFwiX211bFwiLCByZXMsIGludmVyc2UsIHJlcyksXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGMuYnJfaWYoMSwgYy5pMzJfZXF6ICggYy5nZXRMb2NhbChcImlcIikgKSksXG4gICAgICAgICAgICAgICAgYy5zZXRMb2NhbChcImlcIiwgYy5pMzJfc3ViKGMuZ2V0TG9jYWwoXCJpXCIpLCBjLmkzMl9jb25zdCgxKSkpLFxuICAgICAgICAgICAgICAgIGMuYnIoMClcbiAgICAgICAgICAgICkpXG4gICAgICAgICk7XG5cbiAgICAgICAgaWYgKGlzRXhwTmVnYXRpdmUpIHtcbiAgICAgICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfY29uanVnYXRlXCIsIHJlcywgcmVzKSxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1aWxkRmluYWxFeHBvbmVudGlhdGlvbigpIHtcbiAgICAgICAgYnVpbGRDeWNsb3RvbWljU3F1YXJlKCk7XG4gICAgICAgIGJ1aWxkQ3ljbG90b21pY0V4cChmaW5hbEV4cFosIGZpbmFsRXhwSXNOZWdhdGl2ZSwgXCJ3MFwiKTtcblxuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCsgXCJfZmluYWxFeHBvbmVudGlhdGlvblwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgZWx0ID0gYy5nZXRMb2NhbChcInhcIik7XG4gICAgICAgIGNvbnN0IHJlcyA9IGMuZ2V0TG9jYWwoXCJyXCIpO1xuICAgICAgICBjb25zdCB0MCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmdHNpemUpKTtcbiAgICAgICAgY29uc3QgdDEgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IHQyID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGZ0c2l6ZSkpO1xuICAgICAgICBjb25zdCB0MyA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmdHNpemUpKTtcbiAgICAgICAgY29uc3QgdDQgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZnRzaXplKSk7XG4gICAgICAgIGNvbnN0IHQ1ID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGZ0c2l6ZSkpO1xuICAgICAgICBjb25zdCB0NiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmdHNpemUpKTtcblxuICAgICAgICBmLmFkZENvZGUoXG5cbiAgICAgICAgICAgIC8vIGxldCBtdXQgdDAgPSBmLmZyb2Jlbml1c19tYXAoNilcbiAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9mcm9iZW5pdXNNYXA2XCIsIGVsdCwgdDApLFxuXG4gICAgICAgICAgICAvLyBsZXQgdDEgPSBmLmludmVydCgpXG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfaW52ZXJzZVwiLCBlbHQsIHQxKSxcblxuICAgICAgICAgICAgLy8gbGV0IG11dCB0MiA9IHQwICogdDE7XG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfbXVsXCIsIHQwLCB0MSwgdDIpLFxuXG4gICAgICAgICAgICAvLyB0MSA9IHQyLmNsb25lKCk7XG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfY29weVwiLCB0MiwgdDEpLFxuXG4gICAgICAgICAgICAvLyB0MiA9IHQyLmZyb2Jlbml1c19tYXAoKS5mcm9iZW5pdXNfbWFwKCk7XG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfZnJvYmVuaXVzTWFwMlwiLCB0MiwgdDIpLFxuXG4gICAgICAgICAgICAvLyB0MiAqPSB0MTtcbiAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9tdWxcIiwgdDIsIHQxLCB0MiksXG5cblxuICAgICAgICAgICAgLy8gdDEgPSBjeWNsb3RvbWljX3NxdWFyZSh0MikuY29uanVnYXRlKCk7XG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfX2N5Y2xvdG9taWNTcXVhcmVcIiwgdDIsIHQxKSxcbiAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9jb25qdWdhdGVcIiwgdDEsIHQxKSxcblxuICAgICAgICAgICAgLy8gbGV0IG11dCB0MyA9IGN5Y29sb3RvbWljX2V4cCh0Mik7XG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfX2N5Y2xvdG9taWNFeHBfdzBcIiwgdDIsIHQzKSxcblxuICAgICAgICAgICAgLy8gbGV0IG11dCB0NCA9IGN5Y2xvdG9taWNfc3F1YXJlKHQzKTtcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9fY3ljbG90b21pY1NxdWFyZVwiLCB0MywgdDQpLFxuXG4gICAgICAgICAgICAvLyBsZXQgbXV0IHQ1ID0gdDEgKiB0MztcbiAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9tdWxcIiwgdDEsIHQzLCB0NSksXG5cbiAgICAgICAgICAgIC8vIHQxID0gY3ljb2xvdG9taWNfZXhwKHQ1KTtcbiAgICAgICAgICAgIGMuY2FsbChwcmVmaXggKyBcIl9fY3ljbG90b21pY0V4cF93MFwiLCB0NSwgdDEpLFxuXG4gICAgICAgICAgICAvLyB0MCA9IGN5Y29sb3RvbWljX2V4cCh0MSk7XG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfX2N5Y2xvdG9taWNFeHBfdzBcIiwgdDEsIHQwKSxcblxuICAgICAgICAgICAgLy8gbGV0IG11dCB0NiA9IGN5Y29sb3RvbWljX2V4cCh0MCk7XG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfX2N5Y2xvdG9taWNFeHBfdzBcIiwgdDAsIHQ2KSxcblxuICAgICAgICAgICAgLy8gdDYgKj0gdDQ7XG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfbXVsXCIsIHQ2LCB0NCwgdDYpLFxuXG4gICAgICAgICAgICAvLyB0NCA9IGN5Y29sb3RvbWljX2V4cCh0Nik7XG4gICAgICAgICAgICBjLmNhbGwocHJlZml4ICsgXCJfX2N5Y2xvdG9taWNFeHBfdzBcIiwgdDYsIHQ0KSxcblxuICAgICAgICAgICAgLy8gdDUgPSB0NS5jb25qdWdhdGUoKTtcbiAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9jb25qdWdhdGVcIiwgdDUsIHQ1KSxcblxuICAgICAgICAgICAgLy8gdDQgKj0gdDUgKiB0MjtcbiAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9tdWxcIiwgdDQsIHQ1LCB0NCksXG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfbXVsXCIsIHQ0LCB0MiwgdDQpLFxuXG4gICAgICAgICAgICAvLyB0NSA9IHQyLmNvbmp1Z2F0ZSgpO1xuICAgICAgICAgICAgYy5jYWxsKGZ0bVByZWZpeCArIFwiX2Nvbmp1Z2F0ZVwiLCB0MiwgdDUpLFxuXG4gICAgICAgICAgICAvLyB0MSAqPSB0MjtcbiAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9tdWxcIiwgdDEsIHQyLCB0MSksXG5cbiAgICAgICAgICAgIC8vIHQxID0gdDEuZnJvYmVuaXVzX21hcCgpLmZyb2Jlbml1c19tYXAoKS5mcm9iZW5pdXNfbWFwKCk7XG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfZnJvYmVuaXVzTWFwM1wiLCB0MSwgdDEpLFxuXG4gICAgICAgICAgICAvLyB0NiAqPSB0NTtcbiAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9tdWxcIiwgdDYsIHQ1LCB0NiksXG5cbiAgICAgICAgICAgIC8vIHQ2ID0gdDYuZnJvYmVuaXVzX21hcCgpO1xuICAgICAgICAgICAgYy5jYWxsKGZ0bVByZWZpeCArIFwiX2Zyb2Jlbml1c01hcDFcIiwgdDYsIHQ2KSxcblxuICAgICAgICAgICAgLy8gdDMgKj0gdDA7XG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfbXVsXCIsIHQzLCB0MCwgdDMpLFxuXG4gICAgICAgICAgICAvLyB0MyA9IHQzLmZyb2Jlbml1c19tYXAoKS5mcm9iZW5pdXNfbWFwKCk7XG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfZnJvYmVuaXVzTWFwMlwiLCB0MywgdDMpLFxuXG4gICAgICAgICAgICAvLyB0MyAqPSB0MTtcbiAgICAgICAgICAgIGMuY2FsbChmdG1QcmVmaXggKyBcIl9tdWxcIiwgdDMsIHQxLCB0MyksXG5cbiAgICAgICAgICAgIC8vIHQzICo9IHQ2O1xuICAgICAgICAgICAgYy5jYWxsKGZ0bVByZWZpeCArIFwiX211bFwiLCB0MywgdDYsIHQzKSxcblxuICAgICAgICAgICAgLy8gZiA9IHQzICogdDQ7XG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfbXVsXCIsIHQzLCB0NCwgcmVzKSxcblxuICAgICAgICApO1xuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gYnVpbGRGaW5hbEV4cG9uZW50aWF0aW9uT2xkKCkge1xuICAgICAgICBjb25zdCBmID0gbW9kdWxlLmFkZEZ1bmN0aW9uKHByZWZpeCsgXCJfZmluYWxFeHBvbmVudGlhdGlvbk9sZFwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInhcIiwgXCJpMzJcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJyXCIsIFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGV4cG9uZW50ID0gMzIyMjc3MzYxNTE2OTM0MTQwNDYyODkxNTY0NTg2NTEwMTM5OTA4Mzc5OTY5NTE0ODI4NDk0MjE4MzY2Njg4MDI1Mjg4NjYxMDQxMTA0NjgyNzk0OTk4NjgwNDk3NTgwMDA4ODk5OTczMjQ5ODE0MTA0NDQ3NjkyNzc4OTg4MjA4Mzc2Nzc5NTczODE5NDg1MjYzMDI2MTU5NTg4NTEwNTEzODM0ODc2MzAzMDE0MDE2Nzk4ODA5OTE5MzQzNTMyODk5MTY0ODQ4NzMwMjgwOTQyNjA5OTU2NjcwOTE3NTY1NjE4MTE1ODY3Mjg3Mzk5NjIzMjg2ODEzMjcwMzU3OTAxNzMxNTEwMTg4MTQ5OTM0MzYzMzYwMzgxNjE0NTAxMzM0MDg2ODI1NDQyMjcxOTIwMDc5MzYzMjg5OTU0NTEwNTY1Mzc1Mzc4NDQzNzA0MzcyOTk0ODgxNDA2Nzk3ODgyNjc2OTcxMDgyMjAwNjI2NTQxOTE2NDEzMTg0NjQyNTIwMjY5Njc4ODk3NTU5NTMyMjYwOTQ5MzM0NzYwNjA0OTYyMDg2MzQ4ODk4MTE4OTgyMjQ4ODQyNjM0Mzc5NjM3NTk4NjY1NDY4ODE3NzY5MDc1ODc4NTU1NDkzNzUyMjE0NDkyNzkwMTIyNzg1ODUwMjAyOTU3NTc1MjAwMTc2MDg0MjA0NDIyNzUxNDg1OTU3MzM2NDY1NDcyMzI0ODEwOTgyODMzNjM4NDkwOTA0Mjc5MjgyNjk2MTM0MzIzMDcyNTE1MjIwMDQ0NDUxNTkyNjQ2ODg1NDEwNTcyMjM0NDUxNzMyNzkwNTkwMDEzNDc5MzU4MzQzODQxMjIwMDc0MTc0ODQ4MjIxNzIyMDE3MDgzNTk3ODcyMDE3NjM4NTE0MTAzMTc0MTIyNzg0ODQzOTI1NTc4MzcwNDMwODQzNTIyOTU5NjAwMDk1Njc2Mjg1NzIzNzM3MDQ5NDM4MzQ2NTQ0NzUzMTY4OTEyOTc0OTc2NzkxNTI4NTM1Mjc2MzE3MjU2OTA0MzM2NTIwMTc5MjgxMTQ1Mzk0Njg2NTY1MDUwNDE5MjUwNjE0MTA3ODAzMjMzMzE0NjU4ODI1NDYzMTE3OTAwMjUwNzAxMTk5MTgxNTI5MjA1OTQyMzYzMTU5MzI1NzY1OTkxODE5NDMzOTE0MzAzOTA4ODYwNDYwNzIwNTgxNDA4MjAxMzczMTY0MDQ3NzczNzk0ODI1NDExMDExOTIyMzA1ODIwMDY1NjExMTIxNTQ0NTYxODA4NDE0MDU1MzAyMjEyMDU3NDcxMzk1NzE5NDMyMDcyMjA5MjQ1NjAwMjU4MTM0MzY0NTg0NjM2ODEwMDkzNTIwMjg1NzExMDcyNTc4NzIxNDM1NTE3ODg0MTAzNTI2NDgzODMyNzMzMjg5ODAyNDI2MTU3MzAxNTQyNzQ0NDc2NzQwMDA4NDk0NzgwMzYzMzU0MzA1MTE2OTc4ODA1NjIwNjcxNDY3MDcxNDAwNzExMzU4ODM5NTUzMzc1MzQwNzI0ODk5NzM1NDYwNDgwMTQ0NTk5NzgyMDE0OTA2NTg2NTQzODEzMjkyMTU3OTIyMjIwNjQ1MDg5MTkyMTMwMjA5MzM0OTI2NjYxNTg4NzM3MDA3NzY4NTY1ODM4NTE5NDU2NjAxNTYwODA0OTU3OTg1NjY3ODgwMzk1MjIxMDQ5MjQ5ODAzNzUzNTgyNjM3NzA4NTYwbjtcblxuICAgICAgICBjb25zdCBwRXhwb25lbnQgPSBtb2R1bGUuYWxsb2ModXRpbHMuYmlnSW50MkJ5dGVzTEUoIGV4cG9uZW50LCA1NDQgKSk7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBmLmFkZENvZGUoXG4gICAgICAgICAgICBjLmNhbGwoZnRtUHJlZml4ICsgXCJfZXhwXCIsIGMuZ2V0TG9jYWwoXCJ4XCIpLCBjLmkzMl9jb25zdChwRXhwb25lbnQpLCBjLmkzMl9jb25zdCg1NDQpLCBjLmdldExvY2FsKFwiclwiKSksXG4gICAgICAgICk7XG4gICAgfVxuXG5cbiAgICBjb25zdCBwUHJlUCA9IG1vZHVsZS5hbGxvYyhwcmVQU2l6ZSk7XG4gICAgY29uc3QgcFByZVEgPSBtb2R1bGUuYWxsb2MocHJlUVNpemUpO1xuXG4gICAgZnVuY3Rpb24gYnVpbGRQYWlyaW5nRXF1YXRpb24oblBhaXJpbmdzKSB7XG5cbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrIFwiX3BhaXJpbmdFcVwiK25QYWlyaW5ncyk7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxuUGFpcmluZ3M7IGkrKykge1xuICAgICAgICAgICAgZi5hZGRQYXJhbShcInBfXCIraSwgXCJpMzJcIik7XG4gICAgICAgICAgICBmLmFkZFBhcmFtKFwicV9cIitpLCBcImkzMlwiKTtcbiAgICAgICAgfVxuICAgICAgICBmLmFkZFBhcmFtKFwiY1wiLCBcImkzMlwiKTtcbiAgICAgICAgZi5zZXRSZXR1cm5UeXBlKFwiaTMyXCIpO1xuXG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCByZXNUID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGZ0c2l6ZSkpO1xuICAgICAgICBjb25zdCBhdXhUID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGZ0c2l6ZSkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShjLmNhbGwoZnRtUHJlZml4ICsgXCJfb25lXCIsIHJlc1QgKSk7XG5cbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPG5QYWlyaW5nczsgaSsrKSB7XG5cbiAgICAgICAgICAgIGYuYWRkQ29kZShjLmNhbGwocHJlZml4ICsgXCJfcHJlcGFyZUcxXCIsIGMuZ2V0TG9jYWwoXCJwX1wiK2kpLCBjLmkzMl9jb25zdChwUHJlUCkgKSk7XG4gICAgICAgICAgICBmLmFkZENvZGUoYy5jYWxsKHByZWZpeCArIFwiX3ByZXBhcmVHMlwiLCBjLmdldExvY2FsKFwicV9cIitpKSwgYy5pMzJfY29uc3QocFByZVEpICkpO1xuXG4gICAgICAgICAgICAvLyBDaGVja3NcbiAgICAgICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgICAgICBjLmkzMl9lcXooYy5jYWxsKGcxbVByZWZpeCArIFwiX2luR3JvdXBBZmZpbmVcIiwgYy5pMzJfY29uc3QocFByZVApKSksXG4gICAgICAgICAgICAgICAgICAgIGMucmV0KGMuaTMyX2NvbnN0KDApKVxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICAgICAgYy5pMzJfZXF6KGMuY2FsbChnMm1QcmVmaXggKyBcIl9pbkdyb3VwQWZmaW5lXCIsIGMuaTMyX2NvbnN0KHBQcmVRKSkpLFxuICAgICAgICAgICAgICAgICAgICBjLnJldChjLmkzMl9jb25zdCgwKSlcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICBmLmFkZENvZGUoYy5jYWxsKHByZWZpeCArIFwiX21pbGxlckxvb3BcIiwgYy5pMzJfY29uc3QocFByZVApLCBjLmkzMl9jb25zdChwUHJlUSksIGF1eFQgKSk7XG5cbiAgICAgICAgICAgIGYuYWRkQ29kZShjLmNhbGwoZnRtUHJlZml4ICsgXCJfbXVsXCIsIHJlc1QsIGF1eFQsIHJlc1QgKSk7XG4gICAgICAgIH1cblxuICAgICAgICBmLmFkZENvZGUoYy5jYWxsKHByZWZpeCArIFwiX2ZpbmFsRXhwb25lbnRpYXRpb25cIiwgcmVzVCwgcmVzVCApKTtcblxuICAgICAgICBmLmFkZENvZGUoYy5jYWxsKGZ0bVByZWZpeCArIFwiX2VxXCIsIHJlc1QsIGMuZ2V0TG9jYWwoXCJjXCIpKSk7XG4gICAgfVxuXG5cbiAgICBmdW5jdGlvbiBidWlsZFBhaXJpbmcoKSB7XG5cbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihwcmVmaXgrIFwiX3BhaXJpbmdcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicVwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5hZGRQYXJhbShcInJcIiwgXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCByZXNUID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKGZ0c2l6ZSkpO1xuXG4gICAgICAgIGYuYWRkQ29kZShjLmNhbGwocHJlZml4ICsgXCJfcHJlcGFyZUcxXCIsIGMuZ2V0TG9jYWwoXCJwXCIpLCBjLmkzMl9jb25zdChwUHJlUCkgKSk7XG4gICAgICAgIGYuYWRkQ29kZShjLmNhbGwocHJlZml4ICsgXCJfcHJlcGFyZUcyXCIsIGMuZ2V0TG9jYWwoXCJxXCIpLCBjLmkzMl9jb25zdChwUHJlUSkgKSk7XG4gICAgICAgIGYuYWRkQ29kZShjLmNhbGwocHJlZml4ICsgXCJfbWlsbGVyTG9vcFwiLCBjLmkzMl9jb25zdChwUHJlUCksIGMuaTMyX2NvbnN0KHBQcmVRKSwgcmVzVCApKTtcbiAgICAgICAgZi5hZGRDb2RlKGMuY2FsbChwcmVmaXggKyBcIl9maW5hbEV4cG9uZW50aWF0aW9uXCIsIHJlc1QsIGMuZ2V0TG9jYWwoXCJyXCIpICkpO1xuICAgIH1cblxuXG4gICAgZnVuY3Rpb24gYnVpbGRJbkdyb3VwRzIoKSB7XG4gICAgICAgIGNvbnN0IGYgPSBtb2R1bGUuYWRkRnVuY3Rpb24oZzJtUHJlZml4KyBcIl9pbkdyb3VwQWZmaW5lXCIpO1xuICAgICAgICBmLmFkZFBhcmFtKFwicFwiLCBcImkzMlwiKTtcbiAgICAgICAgZi5zZXRSZXR1cm5UeXBlKFwiaTMyXCIpO1xuXG4gICAgICAgIGNvbnN0IGMgPSBmLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgV0lOViA9IFtcbiAgICAgICAgICAgIDIwMDEyMDQ3Nzc2MTA4MzM2OTY3MDg4OTQ5MTI4Njc5NTIwNzgyNzg0NDE0MDk5Njk1MDM5NDI2NjYwMjkwNjgwNjIwMTU4MjUyNDU0MTg5MzIyMjEzNDM4MTQ1NjQ1MDc4MzIwMTg5NDcxMzYyNzk4OTRuLFxuICAgICAgICAgICAgMjAwMTIwNDc3NzYxMDgzMzY5NjcwODg5NDkxMjg2Nzk1MjA3ODI3ODQ0MTQwOTk2OTUwMzk0MjY2NjAyOTA2ODA2MjAxNTgyNTI0NTQxODkzMjIyMTM0MzgxNDU2NDUwNzgzMjAxODk0NzEzNjI3OTg5M25cbiAgICAgICAgXTtcblxuICAgICAgICBjb25zdCBGUk9CMlggPSA0MDAyNDA5NTU1MjIxNjY3MzkyNjI0MzEwNDM1MDA2Njg4NjQzOTM1NTAzMTE4MzA1NTg2NDM4MjcxMTcxMzk1ODQyOTcxMTU3NDgwMzgxMzc3MDE1NDA1OTgwMDUzNTM5MzU4NDE3MTM1NTQwOTM5NDM2bjtcbiAgICAgICAgY29uc3QgRlJPQjNZID0gW1xuICAgICAgICAgICAgMjk3MzY3NzQwODk4NjU2MTA0MzQ0MjQ2NTM0NjUyMDEwODg3OTE3MjA0Mjg4MzAwOTI0OTk4OTE3NjQxNTAxODA5MTQyMDgwNzE5MjE4MjYzODU2NzExNjMxODU3NjQ3MjY0OTM0NzAxNTkxNzY5MDUzMG4sXG4gICAgICAgICAgICAyOTczNjc3NDA4OTg2NTYxMDQzNDQyNDY1MzQ2NTIwMTA4ODc5MTcyMDQyODgzMDA5MjQ5OTg5MTc2NDE1MDE4MDkxNDIwODA3MTkyMTgyNjM4NTY3MTE2MzE4NTc2NDcyNjQ5MzQ3MDE1OTE3NjkwNTMwblxuICAgICAgICBdO1xuXG4gICAgICAgIGNvbnN0IHdJbnYgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoW1xuICAgICAgICAgICAgLi4udXRpbHMuYmlnSW50MkJ5dGVzTEUodG9Nb250Z29tZXJ5KFdJTlZbMF0pLCBuOHEpLFxuICAgICAgICAgICAgLi4udXRpbHMuYmlnSW50MkJ5dGVzTEUodG9Nb250Z29tZXJ5KFdJTlZbMV0pLCBuOHEpLFxuICAgICAgICBdKSk7XG5cbiAgICAgICAgY29uc3QgZnJvYjJYID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKHV0aWxzLmJpZ0ludDJCeXRlc0xFKHRvTW9udGdvbWVyeShGUk9CMlgpLCBuOHEpKSk7XG4gICAgICAgIGNvbnN0IGZyb2IzWSA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhbXG4gICAgICAgICAgICAuLi51dGlscy5iaWdJbnQyQnl0ZXNMRSh0b01vbnRnb21lcnkoRlJPQjNZWzBdKSwgbjhxKSxcbiAgICAgICAgICAgIC4uLnV0aWxzLmJpZ0ludDJCeXRlc0xFKHRvTW9udGdvbWVyeShGUk9CM1lbMV0pLCBuOHEpLFxuICAgICAgICBdKSk7XG5cbiAgICAgICAgY29uc3QgeiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyh1dGlscy5iaWdJbnQyQnl0ZXNMRShmaW5hbEV4cFosIDgpKSk7XG5cbiAgICAgICAgY29uc3QgcHggPSBjLmdldExvY2FsKFwicFwiKTtcbiAgICAgICAgY29uc3QgcHkgPSBjLmkzMl9hZGQoYy5nZXRMb2NhbChcInBcIiksIGMuaTMyX2NvbnN0KGYyc2l6ZSkpO1xuXG4gICAgICAgIGNvbnN0IGF1eCA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMXNpemUpKTtcblxuICAgICAgICBjb25zdCB4X3dpbnYgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjJzaXplKSk7XG4gICAgICAgIGNvbnN0IHlfd2ludiA9IGMuaTMyX2NvbnN0KG1vZHVsZS5hbGxvYyhmMnNpemUpKTtcbiAgICAgICAgY29uc3QgcGYyID0gbW9kdWxlLmFsbG9jKGYyc2l6ZSoyKTtcbiAgICAgICAgY29uc3QgZjIgPSBjLmkzMl9jb25zdChwZjIpO1xuICAgICAgICBjb25zdCBmMnggPSBjLmkzMl9jb25zdChwZjIpO1xuICAgICAgICBjb25zdCBmMnhfYzEgPSBjLmkzMl9jb25zdChwZjIpO1xuICAgICAgICBjb25zdCBmMnhfYzIgPSBjLmkzMl9jb25zdChwZjIrZjFzaXplKTtcbiAgICAgICAgY29uc3QgZjJ5ID0gYy5pMzJfY29uc3QocGYyK2Yyc2l6ZSk7XG4gICAgICAgIGNvbnN0IGYyeV9jMSA9IGMuaTMyX2NvbnN0KHBmMitmMnNpemUpO1xuICAgICAgICBjb25zdCBmMnlfYzIgPSBjLmkzMl9jb25zdChwZjIrZjJzaXplK2Yxc2l6ZSk7XG4gICAgICAgIGNvbnN0IHBmMyA9IG1vZHVsZS5hbGxvYyhmMnNpemUqMyk7XG4gICAgICAgIGNvbnN0IGYzID0gYy5pMzJfY29uc3QocGYzKTtcbiAgICAgICAgY29uc3QgZjN4ID0gYy5pMzJfY29uc3QocGYzKTtcbiAgICAgICAgY29uc3QgZjN4X2MxID0gYy5pMzJfY29uc3QocGYzKTtcbiAgICAgICAgY29uc3QgZjN4X2MyID0gYy5pMzJfY29uc3QocGYzK2Yxc2l6ZSk7XG4gICAgICAgIGNvbnN0IGYzeSA9IGMuaTMyX2NvbnN0KHBmMytmMnNpemUpO1xuICAgICAgICBjb25zdCBmM3lfYzEgPSBjLmkzMl9jb25zdChwZjMrZjJzaXplKTtcbiAgICAgICAgY29uc3QgZjN5X2MyID0gYy5pMzJfY29uc3QocGYzK2Yyc2l6ZStmMXNpemUpO1xuICAgICAgICBjb25zdCBmM3ogPSBjLmkzMl9jb25zdChwZjMrZjJzaXplKjIpO1xuXG5cbiAgICAgICAgZi5hZGRDb2RlKFxuICAgICAgICAgICAgYy5pZihcbiAgICAgICAgICAgICAgICBjLmNhbGwoZzJtUHJlZml4ICsgXCJfaXNaZXJvQWZmaW5lXCIsIGMuZ2V0TG9jYWwoXCJwXCIpKSxcbiAgICAgICAgICAgICAgICBjLnJldCggYy5pMzJfY29uc3QoMSkpLFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5pMzJfZXF6KGMuY2FsbChnMm1QcmVmaXggKyBcIl9pbkN1cnZlQWZmaW5lXCIsIGMuZ2V0TG9jYWwoXCJwXCIpKSksXG4gICAgICAgICAgICAgICAgYy5yZXQoIGMuaTMyX2NvbnN0KDApKSxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIHB4LCB3SW52LCB4X3dpbnYpLFxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bFwiLCBweSwgd0ludiwgeV93aW52KSxcblxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX211bDFcIiwgeF93aW52LCBmcm9iMlgsIGYyeCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbmVnXCIsIHlfd2ludiwgZjJ5KSxcblxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX25lZ1wiLCB4X3dpbnYsIGYzeCksXG4gICAgICAgICAgICBjLmNhbGwoZjJtUHJlZml4ICsgXCJfbXVsXCIsIHlfd2ludiwgZnJvYjNZLCBmM3kpLFxuXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4ICsgXCJfc3ViXCIsIGYyeF9jMSwgZjJ4X2MyLCBhdXgpLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCArIFwiX2FkZFwiLCBmMnhfYzEsIGYyeF9jMiwgZjJ4X2MyKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXggKyBcIl9jb3B5XCIsIGF1eCwgZjJ4X2MxKSxcblxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCArIFwiX3N1YlwiLCBmMnlfYzEsIGYyeV9jMiwgYXV4KSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXggKyBcIl9hZGRcIiwgZjJ5X2MxLCBmMnlfYzIsIGYyeV9jMiksXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4ICsgXCJfY29weVwiLCBhdXgsIGYyeV9jMSksXG5cbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXggKyBcIl9hZGRcIiwgZjN4X2MxLCBmM3hfYzIsIGF1eCksXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4ICsgXCJfc3ViXCIsIGYzeF9jMSwgZjN4X2MyLCBmM3hfYzIpLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCArIFwiX2NvcHlcIiwgYXV4LCBmM3hfYzEpLFxuXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4ICsgXCJfc3ViXCIsIGYzeV9jMiwgZjN5X2MxLCBhdXgpLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCArIFwiX2FkZFwiLCBmM3lfYzEsIGYzeV9jMiwgZjN5X2MyKSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXggKyBcIl9jb3B5XCIsIGF1eCwgZjN5X2MxKSxcblxuICAgICAgICAgICAgYy5jYWxsKGYybVByZWZpeCArIFwiX29uZVwiLCBmM3opLFxuXG4gICAgICAgICAgICBjLmNhbGwoZzJtUHJlZml4ICsgXCJfdGltZXNTY2FsYXJcIiwgZjMsIHosIGMuaTMyX2NvbnN0KDgpLCBmMyksXG4gICAgICAgICAgICBjLmNhbGwoZzJtUHJlZml4ICsgXCJfYWRkTWl4ZWRcIiwgZjMsIGYyLCBmMyksXG5cbiAgICAgICAgICAgIGMucmV0KFxuICAgICAgICAgICAgICAgIGMuY2FsbChnMm1QcmVmaXggKyBcIl9lcU1peGVkXCIsIGYzLCBjLmdldExvY2FsKFwicFwiKSlcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCBmSW5Hcm91cCA9IG1vZHVsZS5hZGRGdW5jdGlvbihnMm1QcmVmaXggKyBcIl9pbkdyb3VwXCIpO1xuICAgICAgICBmSW5Hcm91cC5hZGRQYXJhbShcInBJblwiLCBcImkzMlwiKTtcbiAgICAgICAgZkluR3JvdXAuc2V0UmV0dXJuVHlwZShcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjMiA9IGZJbkdyb3VwLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgYXV4MiA9IGMyLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjJzaXplKjIpKTtcblxuICAgICAgICBmSW5Hcm91cC5hZGRDb2RlKFxuICAgICAgICAgICAgYzIuY2FsbChnMm1QcmVmaXggKyBcIl90b0FmZmluZVwiLCBjMi5nZXRMb2NhbChcInBJblwiKSwgYXV4MiksXG5cbiAgICAgICAgICAgIGMyLnJldChcbiAgICAgICAgICAgICAgICBjMi5jYWxsKGcybVByZWZpeCArIFwiX2luR3JvdXBBZmZpbmVcIiwgYXV4MiksXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG5cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBidWlsZEluR3JvdXBHMSgpIHtcbiAgICAgICAgY29uc3QgZiA9IG1vZHVsZS5hZGRGdW5jdGlvbihnMW1QcmVmaXgrIFwiX2luR3JvdXBBZmZpbmVcIik7XG4gICAgICAgIGYuYWRkUGFyYW0oXCJwXCIsIFwiaTMyXCIpO1xuICAgICAgICBmLnNldFJldHVyblR5cGUoXCJpMzJcIik7XG5cbiAgICAgICAgY29uc3QgYyA9IGYuZ2V0Q29kZUJ1aWxkZXIoKTtcblxuICAgICAgICBjb25zdCBCRVRBID0gNDAwMjQwOTU1NTIyMTY2NzM5MjYyNDMxMDQzNTAwNjY4ODY0MzkzNTUwMzExODMwNTU4NjQzODI3MTE3MTM5NTg0Mjk3MTE1NzQ4MDM4MTM3NzAxNTQwNTk4MDA1MzUzOTM1ODQxNzEzNTU0MDkzOTQzNm47XG4gICAgICAgIGNvbnN0IEJFVEEyID0gNzkzNDc5MzkwNzI5MjE1NTEyNjIxMzc5NzAxNjMzNDIxNDQ3MDYwODg2NzQwMjgxMDYwNDkzMDEwNDU2NDg3NDI3MjgxNjQ5MDc1NDc2MzA1NjIwNzU4NzMxNjIwMzUwbjtcbiAgICAgICAgY29uc3QgWjJNMUQzID0gKGZpbmFsRXhwWiAqIGZpbmFsRXhwWiAtIDFuKSAvIDNuO1xuXG4gICAgICAgIGNvbnN0IGJldGEgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2ModXRpbHMuYmlnSW50MkJ5dGVzTEUodG9Nb250Z29tZXJ5KEJFVEEpLCBuOHEpKSk7XG4gICAgICAgIGNvbnN0IGJldGEyID0gYy5pMzJfY29uc3QobW9kdWxlLmFsbG9jKHV0aWxzLmJpZ0ludDJCeXRlc0xFKHRvTW9udGdvbWVyeShCRVRBMiksIG44cSkpKTtcblxuICAgICAgICBjb25zdCB6Mm0xZDMgPSBjLmkzMl9jb25zdChtb2R1bGUuYWxsb2ModXRpbHMuYmlnSW50MkJ5dGVzTEUoWjJNMUQzLCAxNikpKTtcblxuXG4gICAgICAgIGNvbnN0IHB4ID0gYy5nZXRMb2NhbChcInBcIik7XG4gICAgICAgIGNvbnN0IHB5ID0gYy5pMzJfYWRkKGMuZ2V0TG9jYWwoXCJwXCIpLCBjLmkzMl9jb25zdChmMXNpemUpKTtcblxuICAgICAgICBjb25zdCBwc3AgPSBtb2R1bGUuYWxsb2MoZjFzaXplKjMpO1xuICAgICAgICBjb25zdCBzcCA9IGMuaTMyX2NvbnN0KHBzcCk7XG4gICAgICAgIGNvbnN0IHNweCA9IGMuaTMyX2NvbnN0KHBzcCk7XG4gICAgICAgIGNvbnN0IHNweSA9IGMuaTMyX2NvbnN0KHBzcCtmMXNpemUpO1xuXG4gICAgICAgIGNvbnN0IHBzMnAgPSBtb2R1bGUuYWxsb2MoZjFzaXplKjIpO1xuICAgICAgICBjb25zdCBzMnAgPSBjLmkzMl9jb25zdChwczJwKTtcbiAgICAgICAgY29uc3QgczJweCA9IGMuaTMyX2NvbnN0KHBzMnApO1xuICAgICAgICBjb25zdCBzMnB5ID0gYy5pMzJfY29uc3QocHMycCtmMXNpemUpO1xuXG4gICAgICAgIGYuYWRkQ29kZShcbiAgICAgICAgICAgIGMuaWYoXG4gICAgICAgICAgICAgICAgYy5jYWxsKGcxbVByZWZpeCArIFwiX2lzWmVyb0FmZmluZVwiLCBjLmdldExvY2FsKFwicFwiKSksXG4gICAgICAgICAgICAgICAgYy5yZXQoIGMuaTMyX2NvbnN0KDEpKSxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjLmlmKFxuICAgICAgICAgICAgICAgIGMuaTMyX2VxeihjLmNhbGwoZzFtUHJlZml4ICsgXCJfaW5DdXJ2ZUFmZmluZVwiLCBjLmdldExvY2FsKFwicFwiKSkpLFxuICAgICAgICAgICAgICAgIGMucmV0KCBjLmkzMl9jb25zdCgwKSksXG4gICAgICAgICAgICApLFxuXG4gICAgICAgICAgICBjLmNhbGwoZjFtUHJlZml4ICsgXCJfbXVsXCIsIHB4LCBiZXRhLCBzcHgpLFxuICAgICAgICAgICAgYy5jYWxsKGYxbVByZWZpeCArIFwiX2NvcHlcIiwgcHksIHNweSksXG5cbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXggKyBcIl9tdWxcIiwgcHgsIGJldGEyLCBzMnB4KSxcbiAgICAgICAgICAgIGMuY2FsbChmMW1QcmVmaXggKyBcIl9jb3B5XCIsIHB5LCBzMnB5KSxcblxuXG4gICAgICAgICAgICBjLmNhbGwoZzFtUHJlZml4ICsgXCJfZG91YmxlQWZmaW5lXCIsIHNwLCBzcCksXG4gICAgICAgICAgICBjLmNhbGwoZzFtUHJlZml4ICsgXCJfc3ViTWl4ZWRcIiwgc3AsIGMuZ2V0TG9jYWwoXCJwXCIpLCBzcCksXG4gICAgICAgICAgICBjLmNhbGwoZzFtUHJlZml4ICsgXCJfc3ViTWl4ZWRcIiwgc3AsIHMycCwgc3ApLFxuXG4gICAgICAgICAgICBjLmNhbGwoZzFtUHJlZml4ICsgXCJfdGltZXNTY2FsYXJcIiwgc3AsIHoybTFkMywgYy5pMzJfY29uc3QoMTYpLCBzcCksXG5cbiAgICAgICAgICAgIGMucmV0KFxuICAgICAgICAgICAgICAgIGMuY2FsbChnMW1QcmVmaXggKyBcIl9lcU1peGVkXCIsIHNwLCBzMnApXG4gICAgICAgICAgICApXG5cbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCBmSW5Hcm91cCA9IG1vZHVsZS5hZGRGdW5jdGlvbihnMW1QcmVmaXggKyBcIl9pbkdyb3VwXCIpO1xuICAgICAgICBmSW5Hcm91cC5hZGRQYXJhbShcInBJblwiLCBcImkzMlwiKTtcbiAgICAgICAgZkluR3JvdXAuc2V0UmV0dXJuVHlwZShcImkzMlwiKTtcblxuICAgICAgICBjb25zdCBjMiA9IGZJbkdyb3VwLmdldENvZGVCdWlsZGVyKCk7XG5cbiAgICAgICAgY29uc3QgYXV4MiA9IGMyLmkzMl9jb25zdChtb2R1bGUuYWxsb2MoZjFzaXplKjIpKTtcblxuICAgICAgICBmSW5Hcm91cC5hZGRDb2RlKFxuICAgICAgICAgICAgYzIuY2FsbChnMW1QcmVmaXggKyBcIl90b0FmZmluZVwiLCBjMi5nZXRMb2NhbChcInBJblwiKSwgYXV4MiksXG5cbiAgICAgICAgICAgIGMyLnJldChcbiAgICAgICAgICAgICAgICBjMi5jYWxsKGcxbVByZWZpeCArIFwiX2luR3JvdXBBZmZpbmVcIiwgYXV4MiksXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZm9yIChsZXQgaT0wOyBpPDEwOyBpKyspIHtcbiAgICAgICAgYnVpbGRGcm9iZW5pdXNNYXAoaSk7XG4gICAgICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihmdG1QcmVmaXggKyBcIl9mcm9iZW5pdXNNYXBcIitpKTtcbiAgICB9XG5cblxuICAgIGJ1aWxkSW5Hcm91cEcxKCk7XG4gICAgYnVpbGRJbkdyb3VwRzIoKTtcblxuICAgIGJ1aWxkUHJlcEFkZFN0ZXAoKTtcbiAgICBidWlsZFByZXBEb3VibGVTdGVwKCk7XG5cbiAgICBidWlsZFByZXBhcmVHMSgpO1xuICAgIGJ1aWxkUHJlcGFyZUcyKCk7XG5cbiAgICBidWlsZE1pbGxlckxvb3AoKTtcblxuICAgIGJ1aWxkRmluYWxFeHBvbmVudGlhdGlvbk9sZCgpO1xuICAgIGJ1aWxkRmluYWxFeHBvbmVudGlhdGlvbigpO1xuXG4gICAgZm9yIChsZXQgaT0xOyBpPD01OyBpKyspIHtcbiAgICAgICAgYnVpbGRQYWlyaW5nRXF1YXRpb24oaSk7XG4gICAgICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9wYWlyaW5nRXFcIitpKTtcbiAgICB9XG5cbiAgICBidWlsZFBhaXJpbmcoKTtcblxuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9wYWlyaW5nXCIpO1xuXG5cbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24ocHJlZml4ICsgXCJfcHJlcGFyZUcxXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9wcmVwYXJlRzJcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX21pbGxlckxvb3BcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2ZpbmFsRXhwb25lbnRpYXRpb25cIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX2ZpbmFsRXhwb25lbnRpYXRpb25PbGRcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKHByZWZpeCArIFwiX19jeWNsb3RvbWljU3F1YXJlXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihwcmVmaXggKyBcIl9fY3ljbG90b21pY0V4cF93MFwiKTtcblxuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihmNm1QcmVmaXggKyBcIl9tdWwxXCIpO1xuICAgIG1vZHVsZS5leHBvcnRGdW5jdGlvbihmNm1QcmVmaXggKyBcIl9tdWwwMVwiKTtcbiAgICBtb2R1bGUuZXhwb3J0RnVuY3Rpb24oZnRtUHJlZml4ICsgXCJfbXVsMDE0XCIpO1xuXG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKGcxbVByZWZpeCArIFwiX2luR3JvdXBBZmZpbmVcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKGcxbVByZWZpeCArIFwiX2luR3JvdXBcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKGcybVByZWZpeCArIFwiX2luR3JvdXBBZmZpbmVcIik7XG4gICAgbW9kdWxlLmV4cG9ydEZ1bmN0aW9uKGcybVByZWZpeCArIFwiX2luR3JvdXBcIik7XG5cbiAgICAvLyBjb25zb2xlLmxvZyhtb2R1bGUuZnVuY3Rpb25JZHhCeU5hbWUpO1xufTtcblxuLypcbiAgICBDb3B5cmlnaHQgMjAxOSAwS0lNUyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHdhc21zbmFyayAoV2ViIEFzc2VtYmx5IHprU25hcmsgUHJvdmVyKS5cblxuICAgIHdhc21zbmFyayBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHdhc21zbmFyayBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVFxuICAgIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpY1xuICAgIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gICAgYWxvbmcgd2l0aCB3YXNtc25hcmsuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG4vLyBtb2R1bGUuZXhwb3J0cy5ibjEyOF93YXNtID0gcmVxdWlyZShcIi4vYnVpbGQvYm4xMjhfd2FzbS5qc1wiKTtcbnZhciBibjEyOF93YXNtX2d6aXAgPSBibjEyOF93YXNtX2d6aXAkMTtcbi8vIG1vZHVsZS5leHBvcnRzLmJsczEyMzgxX3dhc20gPSByZXF1aXJlKFwiLi9idWlsZC9ibHMxMjM4MV93YXNtLmpzXCIpO1xuLy8gbW9kdWxlLmV4cG9ydHMubW50Njc1M193YXNtID0gcmVxdWlyZShcIi4vYnVpbGQvbW50Njc1M193YXNtLmpzXCIpO1xuXG52YXIgYnVpbGRCbjEyOCA9IGJ1aWxkX2JuMTI4O1xudmFyIGJ1aWxkQmxzMTIzODEgPSBidWlsZF9ibHMxMjM4MTtcblxudmFyIGluZGV4ID0gLyojX19QVVJFX18qL09iamVjdC5mcmVlemUoe1xuICAgIF9fcHJvdG9fXzogbnVsbCxcbiAgICBibjEyOF93YXNtX2d6aXA6IGJuMTI4X3dhc21fZ3ppcCxcbiAgICBidWlsZEJsczEyMzgxOiBidWlsZEJsczEyMzgxLFxuICAgIGJ1aWxkQm4xMjg6IGJ1aWxkQm4xMjhcbn0pO1xuXG4vKlxuICAgIENvcHlyaWdodCAyMDE5IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygd2FzbWJ1aWxkZXJcblxuICAgIHdhc21idWlsZGVyIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICAgIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gICAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAgICAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgd2FzbWJ1aWxkZXIgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggd2FzbWJ1aWxkZXIuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG5mdW5jdGlvbiB0b051bWJlcihuKSB7XG4gICAgcmV0dXJuIEJpZ0ludChuKTtcbn1cblxuZnVuY3Rpb24gaXNOZWdhdGl2ZShuKSB7XG4gICAgcmV0dXJuIG4gPCAwbjtcbn1cblxuZnVuY3Rpb24gaXNaZXJvKG4pIHtcbiAgICByZXR1cm4gbiA9PT0gMG47XG59XG5cbmZ1bmN0aW9uIGJpdExlbmd0aChuKSB7XG4gICAgaWYgKGlzTmVnYXRpdmUobikpIHtcbiAgICAgICAgcmV0dXJuIG4udG9TdHJpbmcoMikubGVuZ3RoIC0gMTsgLy8gZGlzY2FyZCB0aGUgLSBzaWduXG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG4udG9TdHJpbmcoMikubGVuZ3RoO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gdTMyKG4pIHtcbiAgICBjb25zdCBiID0gW107XG4gICAgY29uc3QgdiA9IHRvTnVtYmVyKG4pO1xuICAgIGIucHVzaChOdW1iZXIodiAmIDB4RkZuKSk7XG4gICAgYi5wdXNoKE51bWJlcih2ID4+IDhuICYgMHhGRm4pKTtcbiAgICBiLnB1c2goTnVtYmVyKHYgPj4gMTZuICYgMHhGRm4pKTtcbiAgICBiLnB1c2goTnVtYmVyKHYgPj4gMjRuICYgMHhGRm4pKTtcbiAgICByZXR1cm4gYjtcbn1cblxuZnVuY3Rpb24gdG9VVEY4QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjggPSBbXTtcbiAgICBmb3IgKHZhciBpPTA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNoYXJjb2RlID0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgICAgIGlmIChjaGFyY29kZSA8IDB4ODApIHV0ZjgucHVzaChjaGFyY29kZSk7XG4gICAgICAgIGVsc2UgaWYgKGNoYXJjb2RlIDwgMHg4MDApIHtcbiAgICAgICAgICAgIHV0ZjgucHVzaCgweGMwIHwgKGNoYXJjb2RlID4+IDYpLFxuICAgICAgICAgICAgICAgIDB4ODAgfCAoY2hhcmNvZGUgJiAweDNmKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoY2hhcmNvZGUgPCAweGQ4MDAgfHwgY2hhcmNvZGUgPj0gMHhlMDAwKSB7XG4gICAgICAgICAgICB1dGY4LnB1c2goMHhlMCB8IChjaGFyY29kZSA+PiAxMiksXG4gICAgICAgICAgICAgICAgMHg4MCB8ICgoY2hhcmNvZGU+PjYpICYgMHgzZiksXG4gICAgICAgICAgICAgICAgMHg4MCB8IChjaGFyY29kZSAmIDB4M2YpKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBzdXJyb2dhdGUgcGFpclxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgIC8vIFVURi0xNiBlbmNvZGVzIDB4MTAwMDAtMHgxMEZGRkYgYnlcbiAgICAgICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgICAgIC8vIDIwIGJpdHMgb2YgMHgwLTB4RkZGRkYgaW50byB0d28gaGFsdmVzXG4gICAgICAgICAgICBjaGFyY29kZSA9IDB4MTAwMDAgKyAoKChjaGFyY29kZSAmIDB4M2ZmKTw8MTApXG4gICAgICAgICAgICAgICAgICAgICAgfCAoc3RyLmNoYXJDb2RlQXQoaSkgJiAweDNmZikpO1xuICAgICAgICAgICAgdXRmOC5wdXNoKDB4ZjAgfCAoY2hhcmNvZGUgPj4xOCksXG4gICAgICAgICAgICAgICAgMHg4MCB8ICgoY2hhcmNvZGU+PjEyKSAmIDB4M2YpLFxuICAgICAgICAgICAgICAgIDB4ODAgfCAoKGNoYXJjb2RlPj42KSAmIDB4M2YpLFxuICAgICAgICAgICAgICAgIDB4ODAgfCAoY2hhcmNvZGUgJiAweDNmKSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG59XG5cbmZ1bmN0aW9uIHN0cmluZyhzdHIpIHtcbiAgICBjb25zdCBieXRlcyA9IHRvVVRGOEFycmF5KHN0cik7XG4gICAgcmV0dXJuIFsgLi4udmFydWludDMyKGJ5dGVzLmxlbmd0aCksIC4uLmJ5dGVzIF07XG59XG5cbmZ1bmN0aW9uIHZhcnVpbnQobikge1xuICAgIGNvbnN0IGNvZGUgPSBbXTtcbiAgICBsZXQgdiA9IHRvTnVtYmVyKG4pO1xuICAgIGlmIChpc05lZ2F0aXZlKHYpKSB0aHJvdyBuZXcgRXJyb3IoXCJOdW1iZXIgY2Fubm90IGJlIG5lZ2F0aXZlXCIpO1xuICAgIHdoaWxlICghaXNaZXJvKHYpKSB7XG4gICAgICAgIGNvZGUucHVzaChOdW1iZXIodiAmIDB4N0ZuKSk7XG4gICAgICAgIHYgPSB2ID4+IDduO1xuICAgIH1cbiAgICBpZiAoY29kZS5sZW5ndGg9PTApIGNvZGUucHVzaCgwKTtcbiAgICBmb3IgKGxldCBpPTA7IGk8Y29kZS5sZW5ndGgtMTsgaSsrKSB7XG4gICAgICAgIGNvZGVbaV0gPSBjb2RlW2ldIHwgMHg4MDtcbiAgICB9XG4gICAgcmV0dXJuIGNvZGU7XG59XG5cbmZ1bmN0aW9uIHZhcmludChfbikge1xuICAgIGxldCBuLCBzaWduO1xuICAgIGNvbnN0IGJpdHMgPSBiaXRMZW5ndGgoX24pO1xuICAgIGlmIChfbjwwKSB7XG4gICAgICAgIHNpZ24gPSB0cnVlO1xuICAgICAgICBuID0gKDFuIDw8IEJpZ0ludChiaXRzKSkgKyBfbjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzaWduID0gZmFsc2U7XG4gICAgICAgIG4gPSB0b051bWJlcihfbik7XG4gICAgfVxuICAgIGNvbnN0IHBhZGRpbmdCaXRzID0gNyAtIChiaXRzICUgNyk7XG5cbiAgICBjb25zdCBwYWRkaW5nID0gKCgxbiA8PCBCaWdJbnQocGFkZGluZ0JpdHMpKSAtIDFuKSA8PCBCaWdJbnQoYml0cyk7XG4gICAgY29uc3QgcGFkZGluZ01hc2sgPSAoKDEgPDwgKDcgLSBwYWRkaW5nQml0cykpLTEpIHwgMHg4MDtcblxuICAgIGNvbnN0IGNvZGUgPSB2YXJ1aW50KG4gKyBwYWRkaW5nKTtcblxuICAgIGlmICghc2lnbikge1xuICAgICAgICBjb2RlW2NvZGUubGVuZ3RoLTFdID0gY29kZVtjb2RlLmxlbmd0aC0xXSAmIHBhZGRpbmdNYXNrO1xuICAgIH1cblxuICAgIHJldHVybiBjb2RlO1xufVxuXG5mdW5jdGlvbiB2YXJpbnQzMihuKSB7XG4gICAgbGV0IHYgPSB0b051bWJlcihuKTtcbiAgICBpZiAodiA+IDB4RkZGRkZGRkZuKSB0aHJvdyBuZXcgRXJyb3IoXCJOdW1iZXIgdG9vIGJpZ1wiKTtcbiAgICBpZiAodiA+IDB4N0ZGRkZGRkZuKSB2ID0gdiAtIDB4MTAwMDAwMDAwbjtcbiAgICAvLyBiaWdJbnQoXCItODAwMDAwMDBcIiwgMTYpIGFzIGJhc2UxMFxuICAgIGlmICh2IDwgLTIxNDc0ODM2NDhuKSB0aHJvdyBuZXcgRXJyb3IoXCJOdW1iZXIgdG9vIHNtYWxsXCIpO1xuICAgIHJldHVybiB2YXJpbnQodik7XG59XG5cbmZ1bmN0aW9uIHZhcmludDY0KG4pIHtcbiAgICBsZXQgdiA9IHRvTnVtYmVyKG4pO1xuICAgIGlmICh2ID4gMHhGRkZGRkZGRkZGRkZGRkZGbikgdGhyb3cgbmV3IEVycm9yKFwiTnVtYmVyIHRvbyBiaWdcIik7XG4gICAgaWYgKHYgPiAweDdGRkZGRkZGRkZGRkZGRkZuKSB2ID0gdiAtIDB4MTAwMDAwMDAwMDAwMDAwMDBuO1xuICAgIC8vIGJpZ0ludChcIi04MDAwMDAwMDAwMDAwMDAwXCIsIDE2KSBhcyBiYXNlMTBcbiAgICBpZiAodiA8IC05MjIzMzcyMDM2ODU0Nzc1ODA4bikgdGhyb3cgbmV3IEVycm9yKFwiTnVtYmVyIHRvbyBzbWFsbFwiKTtcbiAgICByZXR1cm4gdmFyaW50KHYpO1xufVxuXG5mdW5jdGlvbiB2YXJ1aW50MzIobikge1xuICAgIGxldCB2ID0gdG9OdW1iZXIobik7XG4gICAgaWYgKHYgPiAweEZGRkZGRkZGbikgdGhyb3cgbmV3IEVycm9yKFwiTnVtYmVyIHRvbyBiaWdcIik7XG4gICAgcmV0dXJuIHZhcnVpbnQodik7XG59XG5cbmZ1bmN0aW9uIHRvSGV4U3RyaW5nKGJ5dGVBcnJheSkge1xuICAgIHJldHVybiBBcnJheS5mcm9tKGJ5dGVBcnJheSwgZnVuY3Rpb24oYnl0ZSkge1xuICAgICAgICByZXR1cm4gKFwiMFwiICsgKGJ5dGUgJiAweEZGKS50b1N0cmluZygxNikpLnNsaWNlKC0yKTtcbiAgICB9KS5qb2luKFwiXCIpO1xufVxuXG4vKlxuICAgIENvcHlyaWdodCAyMDE5IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygd2FzbWJ1aWxkZXJcblxuICAgIHdhc21idWlsZGVyIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICAgIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gICAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAgICAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgd2FzbWJ1aWxkZXIgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggd2FzbWJ1aWxkZXIuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG5cbmNsYXNzIENvZGVCdWlsZGVyIHtcbiAgICBjb25zdHJ1Y3RvcihmdW5jKSB7XG4gICAgICAgIHRoaXMuZnVuYyA9IGZ1bmM7XG4gICAgICAgIHRoaXMuZnVuY3Rpb25OYW1lID0gZnVuYy5mdW5jdGlvbk5hbWU7XG4gICAgICAgIHRoaXMubW9kdWxlID0gZnVuYy5tb2R1bGU7XG4gICAgfVxuXG4gICAgc2V0TG9jYWwobG9jYWxOYW1lLCB2YWxDb2RlKSB7XG4gICAgICAgIGNvbnN0IGlkeCA9IHRoaXMuZnVuYy5sb2NhbElkeEJ5TmFtZVtsb2NhbE5hbWVdO1xuICAgICAgICBpZiAoaWR4ID09PSB1bmRlZmluZWQpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYExvY2FsIFZhcmlhYmxlIG5vdCBkZWZpbmVkOiBGdW5jdGlvbjogJHt0aGlzLmZ1bmN0aW9uTmFtZX0gbG9jYWw6ICR7bG9jYWxOYW1lfSBgKTtcbiAgICAgICAgcmV0dXJuIFsuLi52YWxDb2RlLCAweDIxLCAuLi52YXJ1aW50MzIoIGlkeCApXTtcbiAgICB9XG5cbiAgICB0ZWVMb2NhbChsb2NhbE5hbWUsIHZhbENvZGUpIHtcbiAgICAgICAgY29uc3QgaWR4ID0gdGhpcy5mdW5jLmxvY2FsSWR4QnlOYW1lW2xvY2FsTmFtZV07XG4gICAgICAgIGlmIChpZHggPT09IHVuZGVmaW5lZClcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgTG9jYWwgVmFyaWFibGUgbm90IGRlZmluZWQ6IEZ1bmN0aW9uOiAke3RoaXMuZnVuY3Rpb25OYW1lfSBsb2NhbDogJHtsb2NhbE5hbWV9IGApO1xuICAgICAgICByZXR1cm4gWy4uLnZhbENvZGUsIDB4MjIsIC4uLnZhcnVpbnQzMiggaWR4ICldO1xuICAgIH1cblxuICAgIGdldExvY2FsKGxvY2FsTmFtZSkge1xuICAgICAgICBjb25zdCBpZHggPSB0aGlzLmZ1bmMubG9jYWxJZHhCeU5hbWVbbG9jYWxOYW1lXTtcbiAgICAgICAgaWYgKGlkeCA9PT0gdW5kZWZpbmVkKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBMb2NhbCBWYXJpYWJsZSBub3QgZGVmaW5lZDogRnVuY3Rpb246ICR7dGhpcy5mdW5jdGlvbk5hbWV9IGxvY2FsOiAke2xvY2FsTmFtZX0gYCk7XG4gICAgICAgIHJldHVybiBbMHgyMCwgLi4udmFydWludDMyKCBpZHggKV07XG4gICAgfVxuXG4gICAgaTY0X2xvYWQ4X3MoaWR4Q29kZSwgX29mZnNldCwgX2FsaWduKSB7XG4gICAgICAgIGNvbnN0IG9mZnNldCA9IF9vZmZzZXQgfHwgMDtcbiAgICAgICAgY29uc3QgYWxpZ24gPSAoX2FsaWduID09PSB1bmRlZmluZWQpID8gMCA6IF9hbGlnbjsgIC8vIDggYml0cyBhbGlnbm1lbnQgYnkgZGVmYXVsdFxuICAgICAgICByZXR1cm4gWy4uLmlkeENvZGUsIDB4MzAsIGFsaWduLCAuLi52YXJ1aW50MzIob2Zmc2V0KV07XG4gICAgfVxuXG4gICAgaTY0X2xvYWQ4X3UoaWR4Q29kZSwgX29mZnNldCwgX2FsaWduKSB7XG4gICAgICAgIGNvbnN0IG9mZnNldCA9IF9vZmZzZXQgfHwgMDtcbiAgICAgICAgY29uc3QgYWxpZ24gPSAoX2FsaWduID09PSB1bmRlZmluZWQpID8gMCA6IF9hbGlnbjsgIC8vIDggYml0cyBhbGlnbm1lbnQgYnkgZGVmYXVsdFxuICAgICAgICByZXR1cm4gWy4uLmlkeENvZGUsIDB4MzEsIGFsaWduLCAuLi52YXJ1aW50MzIob2Zmc2V0KV07XG4gICAgfVxuXG4gICAgaTY0X2xvYWQxNl9zKGlkeENvZGUsIF9vZmZzZXQsIF9hbGlnbikge1xuICAgICAgICBjb25zdCBvZmZzZXQgPSBfb2Zmc2V0IHx8IDA7XG4gICAgICAgIGNvbnN0IGFsaWduID0gKF9hbGlnbiA9PT0gdW5kZWZpbmVkKSA/IDEgOiBfYWxpZ247ICAvLyAxNiBiaXRzIGFsaWdubWVudCBieSBkZWZhdWx0XG4gICAgICAgIHJldHVybiBbLi4uaWR4Q29kZSwgMHgzMiwgYWxpZ24sIC4uLnZhcnVpbnQzMihvZmZzZXQpXTtcbiAgICB9XG5cbiAgICBpNjRfbG9hZDE2X3UoaWR4Q29kZSwgX29mZnNldCwgX2FsaWduKSB7XG4gICAgICAgIGNvbnN0IG9mZnNldCA9IF9vZmZzZXQgfHwgMDtcbiAgICAgICAgY29uc3QgYWxpZ24gPSAoX2FsaWduID09PSB1bmRlZmluZWQpID8gMSA6IF9hbGlnbjsgIC8vIDE2IGJpdHMgYWxpZ25tZW50IGJ5IGRlZmF1bHRcbiAgICAgICAgcmV0dXJuIFsuLi5pZHhDb2RlLCAweDMzLCBhbGlnbiwgLi4udmFydWludDMyKG9mZnNldCldO1xuICAgIH1cblxuICAgIGk2NF9sb2FkMzJfcyhpZHhDb2RlLCBfb2Zmc2V0LCBfYWxpZ24pIHtcbiAgICAgICAgY29uc3Qgb2Zmc2V0ID0gX29mZnNldCB8fCAwO1xuICAgICAgICBjb25zdCBhbGlnbiA9IChfYWxpZ24gPT09IHVuZGVmaW5lZCkgPyAyIDogX2FsaWduOyAgLy8gMzIgYml0cyBhbGlnbm1lbnQgYnkgZGVmYXVsdFxuICAgICAgICByZXR1cm4gWy4uLmlkeENvZGUsIDB4MzQsIGFsaWduLCAuLi52YXJ1aW50MzIob2Zmc2V0KV07XG4gICAgfVxuXG4gICAgaTY0X2xvYWQzMl91KGlkeENvZGUsIF9vZmZzZXQsIF9hbGlnbikge1xuICAgICAgICBjb25zdCBvZmZzZXQgPSBfb2Zmc2V0IHx8IDA7XG4gICAgICAgIGNvbnN0IGFsaWduID0gKF9hbGlnbiA9PT0gdW5kZWZpbmVkKSA/IDIgOiBfYWxpZ247ICAvLyAzMiBiaXRzIGFsaWdubWVudCBieSBkZWZhdWx0XG4gICAgICAgIHJldHVybiBbLi4uaWR4Q29kZSwgMHgzNSwgYWxpZ24sIC4uLnZhcnVpbnQzMihvZmZzZXQpXTtcbiAgICB9XG5cbiAgICBpNjRfbG9hZChpZHhDb2RlLCBfb2Zmc2V0LCBfYWxpZ24pIHtcbiAgICAgICAgY29uc3Qgb2Zmc2V0ID0gX29mZnNldCB8fCAwO1xuICAgICAgICBjb25zdCBhbGlnbiA9IChfYWxpZ24gPT09IHVuZGVmaW5lZCkgPyAzIDogX2FsaWduOyAgLy8gNjQgYml0cyBhbGlnbm1lbnQgYnkgZGVmYXVsdFxuICAgICAgICByZXR1cm4gWy4uLmlkeENvZGUsIDB4MjksIGFsaWduLCAuLi52YXJ1aW50MzIob2Zmc2V0KV07XG4gICAgfVxuXG5cbiAgICBpNjRfc3RvcmUoaWR4Q29kZSwgX29mZnNldCwgX2FsaWduLCBfY29kZVZhbCkge1xuICAgICAgICBsZXQgb2Zmc2V0LCBhbGlnbiwgY29kZVZhbDtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoX29mZnNldCkpIHtcbiAgICAgICAgICAgIG9mZnNldCA9IDA7XG4gICAgICAgICAgICBhbGlnbiA9IDM7XG4gICAgICAgICAgICBjb2RlVmFsID0gX29mZnNldDtcbiAgICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KF9hbGlnbikpIHtcbiAgICAgICAgICAgIG9mZnNldCA9IF9vZmZzZXQ7XG4gICAgICAgICAgICBhbGlnbiA9IDM7XG4gICAgICAgICAgICBjb2RlVmFsID0gX2FsaWduO1xuICAgICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoX2NvZGVWYWwpKSB7XG4gICAgICAgICAgICBvZmZzZXQgPSBfb2Zmc2V0O1xuICAgICAgICAgICAgYWxpZ24gPSBfYWxpZ247XG4gICAgICAgICAgICBjb2RlVmFsID0gX2NvZGVWYWw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFsuLi5pZHhDb2RlLCAuLi5jb2RlVmFsLCAweDM3LCBhbGlnbiwgLi4udmFydWludDMyKG9mZnNldCldO1xuICAgIH1cblxuICAgIGk2NF9zdG9yZTMyKGlkeENvZGUsIF9vZmZzZXQsIF9hbGlnbiwgX2NvZGVWYWwpIHtcbiAgICAgICAgbGV0IG9mZnNldCwgYWxpZ24sIGNvZGVWYWw7XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KF9vZmZzZXQpKSB7XG4gICAgICAgICAgICBvZmZzZXQgPSAwO1xuICAgICAgICAgICAgYWxpZ24gPSAyO1xuICAgICAgICAgICAgY29kZVZhbCA9IF9vZmZzZXQ7XG4gICAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShfYWxpZ24pKSB7XG4gICAgICAgICAgICBvZmZzZXQgPSBfb2Zmc2V0O1xuICAgICAgICAgICAgYWxpZ24gPSAyO1xuICAgICAgICAgICAgY29kZVZhbCA9IF9hbGlnbjtcbiAgICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KF9jb2RlVmFsKSkge1xuICAgICAgICAgICAgb2Zmc2V0ID0gX29mZnNldDtcbiAgICAgICAgICAgIGFsaWduID0gX2FsaWduO1xuICAgICAgICAgICAgY29kZVZhbCA9IF9jb2RlVmFsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBbLi4uaWR4Q29kZSwgLi4uY29kZVZhbCwgMHgzZSwgYWxpZ24sIC4uLnZhcnVpbnQzMihvZmZzZXQpXTtcbiAgICB9XG5cblxuICAgIGk2NF9zdG9yZTE2KGlkeENvZGUsIF9vZmZzZXQsIF9hbGlnbiwgX2NvZGVWYWwpIHtcbiAgICAgICAgbGV0IG9mZnNldCwgYWxpZ24sIGNvZGVWYWw7XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KF9vZmZzZXQpKSB7XG4gICAgICAgICAgICBvZmZzZXQgPSAwO1xuICAgICAgICAgICAgYWxpZ24gPSAxO1xuICAgICAgICAgICAgY29kZVZhbCA9IF9vZmZzZXQ7XG4gICAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShfYWxpZ24pKSB7XG4gICAgICAgICAgICBvZmZzZXQgPSBfb2Zmc2V0O1xuICAgICAgICAgICAgYWxpZ24gPSAxO1xuICAgICAgICAgICAgY29kZVZhbCA9IF9hbGlnbjtcbiAgICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KF9jb2RlVmFsKSkge1xuICAgICAgICAgICAgb2Zmc2V0ID0gX29mZnNldDtcbiAgICAgICAgICAgIGFsaWduID0gX2FsaWduO1xuICAgICAgICAgICAgY29kZVZhbCA9IF9jb2RlVmFsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBbLi4uaWR4Q29kZSwgLi4uY29kZVZhbCwgMHgzZCwgYWxpZ24sIC4uLnZhcnVpbnQzMihvZmZzZXQpXTtcbiAgICB9XG5cblxuICAgIGk2NF9zdG9yZTgoaWR4Q29kZSwgX29mZnNldCwgX2FsaWduLCBfY29kZVZhbCkge1xuICAgICAgICBsZXQgb2Zmc2V0LCBhbGlnbiwgY29kZVZhbDtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoX29mZnNldCkpIHtcbiAgICAgICAgICAgIG9mZnNldCA9IDA7XG4gICAgICAgICAgICBhbGlnbiA9IDA7XG4gICAgICAgICAgICBjb2RlVmFsID0gX29mZnNldDtcbiAgICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KF9hbGlnbikpIHtcbiAgICAgICAgICAgIG9mZnNldCA9IF9vZmZzZXQ7XG4gICAgICAgICAgICBhbGlnbiA9IDA7XG4gICAgICAgICAgICBjb2RlVmFsID0gX2FsaWduO1xuICAgICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoX2NvZGVWYWwpKSB7XG4gICAgICAgICAgICBvZmZzZXQgPSBfb2Zmc2V0O1xuICAgICAgICAgICAgYWxpZ24gPSBfYWxpZ247XG4gICAgICAgICAgICBjb2RlVmFsID0gX2NvZGVWYWw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFsuLi5pZHhDb2RlLCAuLi5jb2RlVmFsLCAweDNjLCBhbGlnbiwgLi4udmFydWludDMyKG9mZnNldCldO1xuICAgIH1cblxuICAgIGkzMl9sb2FkOF9zKGlkeENvZGUsIF9vZmZzZXQsIF9hbGlnbikge1xuICAgICAgICBjb25zdCBvZmZzZXQgPSBfb2Zmc2V0IHx8IDA7XG4gICAgICAgIGNvbnN0IGFsaWduID0gKF9hbGlnbiA9PT0gdW5kZWZpbmVkKSA/IDAgOiBfYWxpZ247ICAvLyAzMiBiaXRzIGFsaWdubWVudCBieSBkZWZhdWx0XG4gICAgICAgIHJldHVybiBbLi4uaWR4Q29kZSwgMHgyYywgYWxpZ24sIC4uLnZhcnVpbnQzMihvZmZzZXQpXTtcbiAgICB9XG5cbiAgICBpMzJfbG9hZDhfdShpZHhDb2RlLCBfb2Zmc2V0LCBfYWxpZ24pIHtcbiAgICAgICAgY29uc3Qgb2Zmc2V0ID0gX29mZnNldCB8fCAwO1xuICAgICAgICBjb25zdCBhbGlnbiA9IChfYWxpZ24gPT09IHVuZGVmaW5lZCkgPyAwIDogX2FsaWduOyAgLy8gMzIgYml0cyBhbGlnbm1lbnQgYnkgZGVmYXVsdFxuICAgICAgICByZXR1cm4gWy4uLmlkeENvZGUsIDB4MmQsIGFsaWduLCAuLi52YXJ1aW50MzIob2Zmc2V0KV07XG4gICAgfVxuXG4gICAgaTMyX2xvYWQxNl9zKGlkeENvZGUsIF9vZmZzZXQsIF9hbGlnbikge1xuICAgICAgICBjb25zdCBvZmZzZXQgPSBfb2Zmc2V0IHx8IDA7XG4gICAgICAgIGNvbnN0IGFsaWduID0gKF9hbGlnbiA9PT0gdW5kZWZpbmVkKSA/IDEgOiBfYWxpZ247ICAvLyAzMiBiaXRzIGFsaWdubWVudCBieSBkZWZhdWx0XG4gICAgICAgIHJldHVybiBbLi4uaWR4Q29kZSwgMHgyZSwgYWxpZ24sIC4uLnZhcnVpbnQzMihvZmZzZXQpXTtcbiAgICB9XG5cbiAgICBpMzJfbG9hZDE2X3UoaWR4Q29kZSwgX29mZnNldCwgX2FsaWduKSB7XG4gICAgICAgIGNvbnN0IG9mZnNldCA9IF9vZmZzZXQgfHwgMDtcbiAgICAgICAgY29uc3QgYWxpZ24gPSAoX2FsaWduID09PSB1bmRlZmluZWQpID8gMSA6IF9hbGlnbjsgIC8vIDMyIGJpdHMgYWxpZ25tZW50IGJ5IGRlZmF1bHRcbiAgICAgICAgcmV0dXJuIFsuLi5pZHhDb2RlLCAweDJmLCBhbGlnbiwgLi4udmFydWludDMyKG9mZnNldCldO1xuICAgIH1cblxuICAgIGkzMl9sb2FkKGlkeENvZGUsIF9vZmZzZXQsIF9hbGlnbikge1xuICAgICAgICBjb25zdCBvZmZzZXQgPSBfb2Zmc2V0IHx8IDA7XG4gICAgICAgIGNvbnN0IGFsaWduID0gKF9hbGlnbiA9PT0gdW5kZWZpbmVkKSA/IDIgOiBfYWxpZ247ICAvLyAzMiBiaXRzIGFsaWdubWVudCBieSBkZWZhdWx0XG4gICAgICAgIHJldHVybiBbLi4uaWR4Q29kZSwgMHgyOCwgYWxpZ24sIC4uLnZhcnVpbnQzMihvZmZzZXQpXTtcbiAgICB9XG5cbiAgICBpMzJfc3RvcmUoaWR4Q29kZSwgX29mZnNldCwgX2FsaWduLCBfY29kZVZhbCkge1xuICAgICAgICBsZXQgb2Zmc2V0LCBhbGlnbiwgY29kZVZhbDtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoX29mZnNldCkpIHtcbiAgICAgICAgICAgIG9mZnNldCA9IDA7XG4gICAgICAgICAgICBhbGlnbiA9IDI7XG4gICAgICAgICAgICBjb2RlVmFsID0gX29mZnNldDtcbiAgICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KF9hbGlnbikpIHtcbiAgICAgICAgICAgIG9mZnNldCA9IF9vZmZzZXQ7XG4gICAgICAgICAgICBhbGlnbiA9IDI7XG4gICAgICAgICAgICBjb2RlVmFsID0gX2FsaWduO1xuICAgICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoX2NvZGVWYWwpKSB7XG4gICAgICAgICAgICBvZmZzZXQgPSBfb2Zmc2V0O1xuICAgICAgICAgICAgYWxpZ24gPSBfYWxpZ247XG4gICAgICAgICAgICBjb2RlVmFsID0gX2NvZGVWYWw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFsuLi5pZHhDb2RlLCAuLi5jb2RlVmFsLCAweDM2LCBhbGlnbiwgLi4udmFydWludDMyKG9mZnNldCldO1xuICAgIH1cblxuXG4gICAgaTMyX3N0b3JlMTYoaWR4Q29kZSwgX29mZnNldCwgX2FsaWduLCBfY29kZVZhbCkge1xuICAgICAgICBsZXQgb2Zmc2V0LCBhbGlnbiwgY29kZVZhbDtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoX29mZnNldCkpIHtcbiAgICAgICAgICAgIG9mZnNldCA9IDA7XG4gICAgICAgICAgICBhbGlnbiA9IDE7XG4gICAgICAgICAgICBjb2RlVmFsID0gX29mZnNldDtcbiAgICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KF9hbGlnbikpIHtcbiAgICAgICAgICAgIG9mZnNldCA9IF9vZmZzZXQ7XG4gICAgICAgICAgICBhbGlnbiA9IDE7XG4gICAgICAgICAgICBjb2RlVmFsID0gX2FsaWduO1xuICAgICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoX2NvZGVWYWwpKSB7XG4gICAgICAgICAgICBvZmZzZXQgPSBfb2Zmc2V0O1xuICAgICAgICAgICAgYWxpZ24gPSBfYWxpZ247XG4gICAgICAgICAgICBjb2RlVmFsID0gX2NvZGVWYWw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFsuLi5pZHhDb2RlLCAuLi5jb2RlVmFsLCAweDNiLCBhbGlnbiwgLi4udmFydWludDMyKG9mZnNldCldO1xuICAgIH1cblxuICAgIGkzMl9zdG9yZTgoaWR4Q29kZSwgX29mZnNldCwgX2FsaWduLCBfY29kZVZhbCkge1xuICAgICAgICBsZXQgb2Zmc2V0LCBhbGlnbiwgY29kZVZhbDtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoX29mZnNldCkpIHtcbiAgICAgICAgICAgIG9mZnNldCA9IDA7XG4gICAgICAgICAgICBhbGlnbiA9IDA7XG4gICAgICAgICAgICBjb2RlVmFsID0gX29mZnNldDtcbiAgICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KF9hbGlnbikpIHtcbiAgICAgICAgICAgIG9mZnNldCA9IF9vZmZzZXQ7XG4gICAgICAgICAgICBhbGlnbiA9IDA7XG4gICAgICAgICAgICBjb2RlVmFsID0gX2FsaWduO1xuICAgICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoX2NvZGVWYWwpKSB7XG4gICAgICAgICAgICBvZmZzZXQgPSBfb2Zmc2V0O1xuICAgICAgICAgICAgYWxpZ24gPSBfYWxpZ247XG4gICAgICAgICAgICBjb2RlVmFsID0gX2NvZGVWYWw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFsuLi5pZHhDb2RlLCAuLi5jb2RlVmFsLCAweDNhLCBhbGlnbiwgLi4udmFydWludDMyKG9mZnNldCldO1xuICAgIH1cblxuICAgIGNhbGwoZm5OYW1lLCAuLi5hcmdzKSB7XG4gICAgICAgIGNvbnN0IGlkeCA9IHRoaXMubW9kdWxlLmZ1bmN0aW9uSWR4QnlOYW1lW2ZuTmFtZV07XG4gICAgICAgIGlmIChpZHggPT09IHVuZGVmaW5lZClcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRnVuY3Rpb24gbm90IGRlZmluZWQ6IEZ1bmN0aW9uOiAke2ZuTmFtZX1gKTtcbiAgICAgICAgcmV0dXJuIFsuLi5bXS5jb25jYXQoLi4uYXJncyksIDB4MTAsIC4uLnZhcnVpbnQzMihpZHgpXTtcbiAgICB9XG5cbiAgICBjYWxsX2luZGlyZWN0KGZuSWR4LCAuLi5hcmdzKSB7XG4gICAgICAgIHJldHVybiBbLi4uW10uY29uY2F0KC4uLmFyZ3MpLCAuLi5mbklkeCwgMHgxMSwgMCwgMF07XG4gICAgfVxuXG4gICAgaWYoY29uZENvZGUsIHRoZW5Db2RlLCBlbHNlQ29kZSkge1xuICAgICAgICBpZiAoZWxzZUNvZGUpIHtcbiAgICAgICAgICAgIHJldHVybiBbLi4uY29uZENvZGUsIDB4MDQsIDB4NDAsIC4uLnRoZW5Db2RlLCAweDA1LCAuLi5lbHNlQ29kZSwgMHgwYl07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gWy4uLmNvbmRDb2RlLCAweDA0LCAweDQwLCAuLi50aGVuQ29kZSwgMHgwYl07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBibG9jayhiQ29kZSkgeyByZXR1cm4gWzB4MDIsIDB4NDAsIC4uLmJDb2RlLCAweDBiXTsgfVxuICAgIGxvb3AoLi4uYXJncykge1xuICAgICAgICByZXR1cm4gWzB4MDMsIDB4NDAsIC4uLltdLmNvbmNhdCguLi5bLi4uYXJnc10pLCAweDBiXTtcbiAgICB9XG4gICAgYnJfaWYocmVsUGF0aCwgY29uZENvZGUpIHsgcmV0dXJuIFsuLi5jb25kQ29kZSwgMHgwZCwgLi4udmFydWludDMyKHJlbFBhdGgpXTsgfVxuICAgIGJyKHJlbFBhdGgpIHsgcmV0dXJuIFsweDBjLCAuLi52YXJ1aW50MzIocmVsUGF0aCldOyB9XG4gICAgcmV0KHJDb2RlKSB7IHJldHVybiBbLi4uckNvZGUsIDB4MGZdOyB9XG4gICAgZHJvcChkQ29kZSkgeyByZXR1cm4gWy4uLmRDb2RlLCAgMHgxYV07IH1cblxuICAgIGk2NF9jb25zdChudW0pIHsgcmV0dXJuIFsweDQyLCAuLi52YXJpbnQ2NChudW0pXTsgfVxuICAgIGkzMl9jb25zdChudW0pIHsgcmV0dXJuIFsweDQxLCAuLi52YXJpbnQzMihudW0pXTsgfVxuXG5cbiAgICBpNjRfZXF6KG9wY29kZSkgeyByZXR1cm4gWy4uLm9wY29kZSwgMHg1MF07IH1cbiAgICBpNjRfZXEob3AxY29kZSwgb3AyY29kZSkgeyByZXR1cm4gWy4uLm9wMWNvZGUsIC4uLm9wMmNvZGUsIDB4NTFdOyB9XG4gICAgaTY0X25lKG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDUyXTsgfVxuICAgIGk2NF9sdF9zKG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDUzXTsgfVxuICAgIGk2NF9sdF91KG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDU0XTsgfVxuICAgIGk2NF9ndF9zKG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDU1XTsgfVxuICAgIGk2NF9ndF91KG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDU2XTsgfVxuICAgIGk2NF9sZV9zKG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDU3XTsgfVxuICAgIGk2NF9sZV91KG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDU4XTsgfVxuICAgIGk2NF9nZV9zKG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDU5XTsgfVxuICAgIGk2NF9nZV91KG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDVhXTsgfVxuICAgIGk2NF9hZGQob3AxY29kZSwgb3AyY29kZSkgeyByZXR1cm4gWy4uLm9wMWNvZGUsIC4uLm9wMmNvZGUsIDB4N2NdOyB9XG4gICAgaTY0X3N1YihvcDFjb2RlLCBvcDJjb2RlKSB7IHJldHVybiBbLi4ub3AxY29kZSwgLi4ub3AyY29kZSwgMHg3ZF07IH1cbiAgICBpNjRfbXVsKG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDdlXTsgfVxuICAgIGk2NF9kaXZfcyhvcDFjb2RlLCBvcDJjb2RlKSB7IHJldHVybiBbLi4ub3AxY29kZSwgLi4ub3AyY29kZSwgMHg3Zl07IH1cbiAgICBpNjRfZGl2X3Uob3AxY29kZSwgb3AyY29kZSkgeyByZXR1cm4gWy4uLm9wMWNvZGUsIC4uLm9wMmNvZGUsIDB4ODBdOyB9XG4gICAgaTY0X3JlbV9zKG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDgxXTsgfVxuICAgIGk2NF9yZW1fdShvcDFjb2RlLCBvcDJjb2RlKSB7IHJldHVybiBbLi4ub3AxY29kZSwgLi4ub3AyY29kZSwgMHg4Ml07IH1cbiAgICBpNjRfYW5kKG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDgzXTsgfVxuICAgIGk2NF9vcihvcDFjb2RlLCBvcDJjb2RlKSB7IHJldHVybiBbLi4ub3AxY29kZSwgLi4ub3AyY29kZSwgMHg4NF07IH1cbiAgICBpNjRfeG9yKG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDg1XTsgfVxuICAgIGk2NF9zaGwob3AxY29kZSwgb3AyY29kZSkgeyByZXR1cm4gWy4uLm9wMWNvZGUsIC4uLm9wMmNvZGUsIDB4ODZdOyB9XG4gICAgaTY0X3Nocl9zKG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDg3XTsgfVxuICAgIGk2NF9zaHJfdShvcDFjb2RlLCBvcDJjb2RlKSB7IHJldHVybiBbLi4ub3AxY29kZSwgLi4ub3AyY29kZSwgMHg4OF07IH1cbiAgICBpNjRfZXh0ZW5kX2kzMl9zKG9wMWNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAweGFjXTsgfVxuICAgIGk2NF9leHRlbmRfaTMyX3Uob3AxY29kZSkgeyByZXR1cm4gWy4uLm9wMWNvZGUsIDB4YWRdOyB9XG4gICAgaTY0X2NseihvcDFjb2RlKSB7IHJldHVybiBbLi4ub3AxY29kZSwgMHg3OV07IH1cbiAgICBpNjRfY3R6KG9wMWNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAweDdhXTsgfVxuXG4gICAgaTMyX2VxeihvcDFjb2RlKSB7IHJldHVybiBbLi4ub3AxY29kZSwgMHg0NV07IH1cbiAgICBpMzJfZXEob3AxY29kZSwgb3AyY29kZSkgeyByZXR1cm4gWy4uLm9wMWNvZGUsIC4uLm9wMmNvZGUsIDB4NDZdOyB9XG4gICAgaTMyX25lKG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDQ3XTsgfVxuICAgIGkzMl9sdF9zKG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDQ4XTsgfVxuICAgIGkzMl9sdF91KG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDQ5XTsgfVxuICAgIGkzMl9ndF9zKG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDRhXTsgfVxuICAgIGkzMl9ndF91KG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDRiXTsgfVxuICAgIGkzMl9sZV9zKG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDRjXTsgfVxuICAgIGkzMl9sZV91KG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDRkXTsgfVxuICAgIGkzMl9nZV9zKG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDRlXTsgfVxuICAgIGkzMl9nZV91KG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDRmXTsgfVxuICAgIGkzMl9hZGQob3AxY29kZSwgb3AyY29kZSkgeyByZXR1cm4gWy4uLm9wMWNvZGUsIC4uLm9wMmNvZGUsIDB4NmFdOyB9XG4gICAgaTMyX3N1YihvcDFjb2RlLCBvcDJjb2RlKSB7IHJldHVybiBbLi4ub3AxY29kZSwgLi4ub3AyY29kZSwgMHg2Yl07IH1cbiAgICBpMzJfbXVsKG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDZjXTsgfVxuICAgIGkzMl9kaXZfcyhvcDFjb2RlLCBvcDJjb2RlKSB7IHJldHVybiBbLi4ub3AxY29kZSwgLi4ub3AyY29kZSwgMHg2ZF07IH1cbiAgICBpMzJfZGl2X3Uob3AxY29kZSwgb3AyY29kZSkgeyByZXR1cm4gWy4uLm9wMWNvZGUsIC4uLm9wMmNvZGUsIDB4NmVdOyB9XG4gICAgaTMyX3JlbV9zKG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDZmXTsgfVxuICAgIGkzMl9yZW1fdShvcDFjb2RlLCBvcDJjb2RlKSB7IHJldHVybiBbLi4ub3AxY29kZSwgLi4ub3AyY29kZSwgMHg3MF07IH1cbiAgICBpMzJfYW5kKG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDcxXTsgfVxuICAgIGkzMl9vcihvcDFjb2RlLCBvcDJjb2RlKSB7IHJldHVybiBbLi4ub3AxY29kZSwgLi4ub3AyY29kZSwgMHg3Ml07IH1cbiAgICBpMzJfeG9yKG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDczXTsgfVxuICAgIGkzMl9zaGwob3AxY29kZSwgb3AyY29kZSkgeyByZXR1cm4gWy4uLm9wMWNvZGUsIC4uLm9wMmNvZGUsIDB4NzRdOyB9XG4gICAgaTMyX3Nocl9zKG9wMWNvZGUsIG9wMmNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAuLi5vcDJjb2RlLCAweDc1XTsgfVxuICAgIGkzMl9zaHJfdShvcDFjb2RlLCBvcDJjb2RlKSB7IHJldHVybiBbLi4ub3AxY29kZSwgLi4ub3AyY29kZSwgMHg3Nl07IH1cbiAgICBpMzJfcm90bChvcDFjb2RlLCBvcDJjb2RlKSB7IHJldHVybiBbLi4ub3AxY29kZSwgLi4ub3AyY29kZSwgMHg3N107IH1cbiAgICBpMzJfcm90cihvcDFjb2RlLCBvcDJjb2RlKSB7IHJldHVybiBbLi4ub3AxY29kZSwgLi4ub3AyY29kZSwgMHg3OF07IH1cbiAgICBpMzJfd3JhcF9pNjQob3AxY29kZSkgeyByZXR1cm4gWy4uLm9wMWNvZGUsIDB4YTddOyB9XG4gICAgaTMyX2NseihvcDFjb2RlKSB7IHJldHVybiBbLi4ub3AxY29kZSwgMHg2N107IH1cbiAgICBpMzJfY3R6KG9wMWNvZGUpIHsgcmV0dXJuIFsuLi5vcDFjb2RlLCAweDY4XTsgfVxuXG4gICAgdW5yZWFjaGFibGUoKSB7IHJldHVybiBbIDB4MCBdOyB9XG5cbiAgICBjdXJyZW50X21lbW9yeSgpIHsgcmV0dXJuIFsgMHgzZiwgMF07IH1cblxuICAgIGNvbW1lbnQoKSB7IHJldHVybiBbXTsgfVxufVxuXG4vKlxuICAgIENvcHlyaWdodCAyMDE5IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygd2FzbWJ1aWxkZXJcblxuICAgIHdhc21idWlsZGVyIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICAgIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gICAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAgICAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgd2FzbWJ1aWxkZXIgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggd2FzbWJ1aWxkZXIuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG5cbmNvbnN0IHR5cGVDb2RlcyA9IHtcbiAgICBcImkzMlwiOiAweDdmLFxuICAgIFwiaTY0XCI6IDB4N2UsXG4gICAgXCJmMzJcIjogMHg3ZCxcbiAgICBcImY2NFwiOiAweDdjLFxuICAgIFwiYW55ZnVuY1wiOiAweDcwLFxuICAgIFwiZnVuY1wiOiAweDYwLFxuICAgIFwiZW1wdHlibG9ja1wiOiAweDQwXG59O1xuXG5cbmNsYXNzIEZ1bmN0aW9uQnVpbGRlciB7XG5cbiAgICBjb25zdHJ1Y3RvciAobW9kdWxlLCBmbk5hbWUsIGZuVHlwZSwgbW9kdWxlTmFtZSwgZmllbGROYW1lKSB7XG4gICAgICAgIGlmIChmblR5cGUgPT0gXCJpbXBvcnRcIikge1xuICAgICAgICAgICAgdGhpcy5mblR5cGUgPSBcImltcG9ydFwiO1xuICAgICAgICAgICAgdGhpcy5tb2R1bGVOYW1lID0gbW9kdWxlTmFtZTtcbiAgICAgICAgICAgIHRoaXMuZmllbGROYW1lID0gZmllbGROYW1lO1xuICAgICAgICB9IGVsc2UgaWYgKGZuVHlwZSA9PSBcImludGVybmFsXCIpIHtcbiAgICAgICAgICAgIHRoaXMuZm5UeXBlID0gXCJpbnRlcm5hbFwiO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBmdW5jdGlvbiBmblR5cGU6IFwiICsgZm5UeXBlKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm1vZHVsZSA9IG1vZHVsZTtcbiAgICAgICAgdGhpcy5mbk5hbWUgPSBmbk5hbWU7XG4gICAgICAgIHRoaXMucGFyYW1zID0gW107XG4gICAgICAgIHRoaXMubG9jYWxzID0gW107XG4gICAgICAgIHRoaXMubG9jYWxJZHhCeU5hbWUgPSB7fTtcbiAgICAgICAgdGhpcy5jb2RlID0gW107XG4gICAgICAgIHRoaXMucmV0dXJuVHlwZSA9IG51bGw7XG4gICAgICAgIHRoaXMubmV4dExvY2FsID0wO1xuICAgIH1cblxuICAgIGFkZFBhcmFtKHBhcmFtTmFtZSwgcGFyYW1UeXBlKSB7XG4gICAgICAgIGlmICh0aGlzLmxvY2FsSWR4QnlOYW1lW3BhcmFtTmFtZV0pXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHBhcmFtIGFscmVhZHkgZXhpc3RzLiBGdW5jdGlvbjogJHt0aGlzLmZuTmFtZX0sIFBhcmFtOiAke3BhcmFtTmFtZX0gYCk7XG4gICAgICAgIGNvbnN0IGlkeCA9IHRoaXMubmV4dExvY2FsKys7XG4gICAgICAgIHRoaXMubG9jYWxJZHhCeU5hbWVbcGFyYW1OYW1lXSA9IGlkeDtcbiAgICAgICAgdGhpcy5wYXJhbXMucHVzaCh7XG4gICAgICAgICAgICB0eXBlOiBwYXJhbVR5cGVcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgYWRkTG9jYWwobG9jYWxOYW1lLCBsb2NhbFR5cGUsIF9sZW5ndGgpIHtcbiAgICAgICAgY29uc3QgbGVuZ3RoID0gX2xlbmd0aCB8fCAxO1xuICAgICAgICBpZiAodGhpcy5sb2NhbElkeEJ5TmFtZVtsb2NhbE5hbWVdKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBsb2NhbCBhbHJlYWR5IGV4aXN0cy4gRnVuY3Rpb246ICR7dGhpcy5mbk5hbWV9LCBQYXJhbTogJHtsb2NhbE5hbWV9IGApO1xuICAgICAgICBjb25zdCBpZHggPSB0aGlzLm5leHRMb2NhbCsrO1xuICAgICAgICB0aGlzLmxvY2FsSWR4QnlOYW1lW2xvY2FsTmFtZV0gPSBpZHg7XG4gICAgICAgIHRoaXMubG9jYWxzLnB1c2goe1xuICAgICAgICAgICAgdHlwZTogbG9jYWxUeXBlLFxuICAgICAgICAgICAgbGVuZ3RoOiBsZW5ndGhcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgc2V0UmV0dXJuVHlwZShyZXR1cm5UeXBlKSB7XG4gICAgICAgIGlmICh0aGlzLnJldHVyblR5cGUpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHJldHVyblR5cGUgYWxyZWFkeSBkZWZpbmVkLiBGdW5jdGlvbjogJHt0aGlzLmZuTmFtZX1gKTtcbiAgICAgICAgdGhpcy5yZXR1cm5UeXBlID0gcmV0dXJuVHlwZTtcbiAgICB9XG5cbiAgICBnZXRTaWduYXR1cmUoKSB7XG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IFsuLi52YXJ1aW50MzIodGhpcy5wYXJhbXMubGVuZ3RoKSwgLi4udGhpcy5wYXJhbXMubWFwKChwKSA9PiB0eXBlQ29kZXNbcC50eXBlXSldO1xuICAgICAgICBjb25zdCByZXR1cm5zID0gdGhpcy5yZXR1cm5UeXBlID8gWzB4MDEsIHR5cGVDb2Rlc1t0aGlzLnJldHVyblR5cGVdXSA6IFswXTtcbiAgICAgICAgcmV0dXJuIFsweDYwLCAuLi5wYXJhbXMsIC4uLnJldHVybnNdO1xuICAgIH1cblxuICAgIGdldEJvZHkoKSB7XG4gICAgICAgIGNvbnN0IGxvY2FscyA9IHRoaXMubG9jYWxzLm1hcCgobCkgPT4gW1xuICAgICAgICAgICAgLi4udmFydWludDMyKGwubGVuZ3RoKSxcbiAgICAgICAgICAgIHR5cGVDb2Rlc1tsLnR5cGVdXG4gICAgICAgIF0pO1xuXG4gICAgICAgIGNvbnN0IGJvZHkgPSBbXG4gICAgICAgICAgICAuLi52YXJ1aW50MzIodGhpcy5sb2NhbHMubGVuZ3RoKSxcbiAgICAgICAgICAgIC4uLltdLmNvbmNhdCguLi5sb2NhbHMpLFxuICAgICAgICAgICAgLi4udGhpcy5jb2RlLFxuICAgICAgICAgICAgMHgwYlxuICAgICAgICBdO1xuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgLi4udmFydWludDMyKGJvZHkubGVuZ3RoKSxcbiAgICAgICAgICAgIC4uLmJvZHlcbiAgICAgICAgXTtcbiAgICB9XG5cbiAgICBhZGRDb2RlKC4uLmNvZGUpIHtcbiAgICAgICAgdGhpcy5jb2RlLnB1c2goLi4uW10uY29uY2F0KC4uLlsuLi5jb2RlXSkpO1xuICAgIH1cblxuICAgIGdldENvZGVCdWlsZGVyKCkge1xuICAgICAgICByZXR1cm4gbmV3IENvZGVCdWlsZGVyKHRoaXMpO1xuICAgIH1cbn1cblxuLypcbiAgICBDb3B5cmlnaHQgMjAxOSAwS0lNUyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHdhc21idWlsZGVyXG5cbiAgICB3YXNtYnVpbGRlciBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHdhc21idWlsZGVyIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHdhc21idWlsZGVyLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuXG5jbGFzcyBNb2R1bGVCdWlsZGVyIHtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLmZ1bmN0aW9ucyA9IFtdO1xuICAgICAgICB0aGlzLmZ1bmN0aW9uSWR4QnlOYW1lID0ge307XG4gICAgICAgIHRoaXMubkltcG9ydEZ1bmN0aW9ucyA9IDA7XG4gICAgICAgIHRoaXMubkludGVybmFsRnVuY3Rpb25zID0wO1xuICAgICAgICB0aGlzLm1lbW9yeSA9IHtcbiAgICAgICAgICAgIHBhZ2VzU2l6ZTogMSxcbiAgICAgICAgICAgIG1vZHVsZU5hbWU6IFwiZW52XCIsXG4gICAgICAgICAgICBmaWVsZE5hbWU6IFwibWVtb3J5XCJcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5mcmVlID0gODtcbiAgICAgICAgdGhpcy5kYXRhcyA9IFtdO1xuICAgICAgICB0aGlzLm1vZHVsZXMgPSB7fTtcbiAgICAgICAgdGhpcy5leHBvcnRzID0gW107XG4gICAgICAgIHRoaXMuZnVuY3Rpb25zVGFibGUgPSBbXTtcbiAgICB9XG5cbiAgICBidWlsZCgpIHtcbiAgICAgICAgdGhpcy5fc2V0U2lnbmF0dXJlcygpO1xuICAgICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoW1xuICAgICAgICAgICAgLi4udTMyKDB4NmQ3MzYxMDApLFxuICAgICAgICAgICAgLi4udTMyKDEpLFxuICAgICAgICAgICAgLi4udGhpcy5fYnVpbGRUeXBlKCksXG4gICAgICAgICAgICAuLi50aGlzLl9idWlsZEltcG9ydCgpLFxuICAgICAgICAgICAgLi4udGhpcy5fYnVpbGRGdW5jdGlvbkRlY2xhcmF0aW9ucygpLFxuICAgICAgICAgICAgLi4udGhpcy5fYnVpbGRGdW5jdGlvbnNUYWJsZSgpLFxuICAgICAgICAgICAgLi4udGhpcy5fYnVpbGRFeHBvcnRzKCksXG4gICAgICAgICAgICAuLi50aGlzLl9idWlsZEVsZW1lbnRzKCksXG4gICAgICAgICAgICAuLi50aGlzLl9idWlsZENvZGUoKSxcbiAgICAgICAgICAgIC4uLnRoaXMuX2J1aWxkRGF0YSgpXG4gICAgICAgIF0pO1xuICAgIH1cblxuICAgIGFkZEZ1bmN0aW9uKGZuTmFtZSkge1xuICAgICAgICBpZiAodHlwZW9mKHRoaXMuZnVuY3Rpb25JZHhCeU5hbWVbZm5OYW1lXSkgIT09IFwidW5kZWZpbmVkXCIpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEZ1bmN0aW9uIGFscmVhZHkgZGVmaW5lZDogJHtmbk5hbWV9YCk7XG5cbiAgICAgICAgY29uc3QgaWR4ID0gdGhpcy5mdW5jdGlvbnMubGVuZ3RoO1xuICAgICAgICB0aGlzLmZ1bmN0aW9uSWR4QnlOYW1lW2ZuTmFtZV0gPSBpZHg7XG5cbiAgICAgICAgdGhpcy5mdW5jdGlvbnMucHVzaChuZXcgRnVuY3Rpb25CdWlsZGVyKHRoaXMsIGZuTmFtZSwgXCJpbnRlcm5hbFwiKSk7XG5cbiAgICAgICAgdGhpcy5uSW50ZXJuYWxGdW5jdGlvbnMrKztcbiAgICAgICAgcmV0dXJuIHRoaXMuZnVuY3Rpb25zW2lkeF07XG4gICAgfVxuXG4gICAgYWRkSWltcG9ydEZ1bmN0aW9uKGZuTmFtZSwgbW9kdWxlTmFtZSwgX2ZpZWxkTmFtZSkge1xuICAgICAgICBpZiAodHlwZW9mKHRoaXMuZnVuY3Rpb25JZHhCeU5hbWVbZm5OYW1lXSkgIT09IFwidW5kZWZpbmVkXCIpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEZ1bmN0aW9uIGFscmVhZHkgZGVmaW5lZDogJHtmbk5hbWV9YCk7XG5cbiAgICAgICAgaWYgKCAgKHRoaXMuZnVuY3Rpb25zLmxlbmd0aD4wKVxuICAgICAgICAgICAgJiYodGhpcy5mdW5jdGlvbnNbdGhpcy5mdW5jdGlvbnMubGVuZ3RoLTFdLnR5cGUgPT0gXCJpbnRlcm5hbFwiKSlcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW1wb3J0IGZ1bmN0aW9ucyBtdXN0IGJlIGRlY2xhcmVkIGJlZm9yZSBpbnRlcm5hbDogJHtmbk5hbWV9YCk7XG5cbiAgICAgICAgbGV0IGZpZWxkTmFtZSA9IF9maWVsZE5hbWUgfHwgZm5OYW1lO1xuXG4gICAgICAgIGNvbnN0IGlkeCA9IHRoaXMuZnVuY3Rpb25zLmxlbmd0aDtcbiAgICAgICAgdGhpcy5mdW5jdGlvbklkeEJ5TmFtZVtmbk5hbWVdID0gaWR4O1xuXG4gICAgICAgIHRoaXMuZnVuY3Rpb25zLnB1c2gobmV3IEZ1bmN0aW9uQnVpbGRlcih0aGlzLCBmbk5hbWUsIFwiaW1wb3J0XCIsIG1vZHVsZU5hbWUsIGZpZWxkTmFtZSkpO1xuXG4gICAgICAgIHRoaXMubkltcG9ydEZ1bmN0aW9ucyArKztcbiAgICAgICAgcmV0dXJuIHRoaXMuZnVuY3Rpb25zW2lkeF07XG4gICAgfVxuXG4gICAgc2V0TWVtb3J5KHBhZ2VzU2l6ZSwgbW9kdWxlTmFtZSwgZmllbGROYW1lKSB7XG4gICAgICAgIHRoaXMubWVtb3J5ID0ge1xuICAgICAgICAgICAgcGFnZXNTaXplOiBwYWdlc1NpemUsXG4gICAgICAgICAgICBtb2R1bGVOYW1lOiBtb2R1bGVOYW1lIHx8IFwiZW52XCIsXG4gICAgICAgICAgICBmaWVsZE5hbWU6IGZpZWxkTmFtZSB8fCBcIm1lbW9yeVwiXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZXhwb3J0RnVuY3Rpb24oZm5OYW1lLCBfZXhwb3J0TmFtZSkge1xuICAgICAgICBjb25zdCBleHBvcnROYW1lID0gX2V4cG9ydE5hbWUgfHwgZm5OYW1lO1xuICAgICAgICBpZiAodHlwZW9mKHRoaXMuZnVuY3Rpb25JZHhCeU5hbWVbZm5OYW1lXSkgPT09IFwidW5kZWZpbmVkXCIpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEZ1bmN0aW9uIG5vdCBkZWZpbmVkOiAke2ZuTmFtZX1gKTtcbiAgICAgICAgY29uc3QgaWR4ID0gdGhpcy5mdW5jdGlvbklkeEJ5TmFtZVtmbk5hbWVdO1xuICAgICAgICBpZiAoZXhwb3J0TmFtZSAhPSBmbk5hbWUpIHtcbiAgICAgICAgICAgIHRoaXMuZnVuY3Rpb25JZHhCeU5hbWVbZXhwb3J0TmFtZV0gPSBpZHg7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5leHBvcnRzLnB1c2goe1xuICAgICAgICAgICAgZXhwb3J0TmFtZTogZXhwb3J0TmFtZSxcbiAgICAgICAgICAgIGlkeDogaWR4XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGFkZEZ1bmN0aW9uVG9UYWJsZShmbk5hbWUpIHtcbiAgICAgICAgY29uc3QgaWR4ID0gdGhpcy5mdW5jdGlvbklkeEJ5TmFtZVtmbk5hbWVdO1xuICAgICAgICB0aGlzLmZ1bmN0aW9uc1RhYmxlLnB1c2goaWR4KTtcbiAgICB9XG5cbiAgICBhZGREYXRhKG9mZnNldCwgYnl0ZXMpIHtcbiAgICAgICAgdGhpcy5kYXRhcy5wdXNoKHtcbiAgICAgICAgICAgIG9mZnNldDogb2Zmc2V0LFxuICAgICAgICAgICAgYnl0ZXM6IGJ5dGVzXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGFsbG9jKGEsIGIpIHtcbiAgICAgICAgbGV0IHNpemU7XG4gICAgICAgIGxldCBieXRlcztcbiAgICAgICAgaWYgKChBcnJheS5pc0FycmF5KGEpIHx8IEFycmF5QnVmZmVyLmlzVmlldyhhKSkgJiYgKHR5cGVvZihiKSA9PT0gXCJ1bmRlZmluZWRcIikpIHtcbiAgICAgICAgICAgIHNpemUgPSBhLmxlbmd0aDtcbiAgICAgICAgICAgIGJ5dGVzID0gYTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNpemUgPSBhO1xuICAgICAgICAgICAgYnl0ZXMgPSBiO1xuICAgICAgICB9XG4gICAgICAgIHNpemUgPSAoKChzaXplLTEpPj4zKSArMSk8PDM7ICAgICAgIC8vIEFsaWduIHRvIDY0IGJpdHMuXG4gICAgICAgIGNvbnN0IHAgPSB0aGlzLmZyZWU7XG4gICAgICAgIHRoaXMuZnJlZSArPSBzaXplO1xuICAgICAgICBpZiAoYnl0ZXMpIHtcbiAgICAgICAgICAgIHRoaXMuYWRkRGF0YShwLCBieXRlcyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHA7XG4gICAgfVxuXG4gICAgYWxsb2NTdHJpbmcocykge1xuICAgICAgICBjb25zdCBlbmNvZGVyID0gbmV3IGdsb2JhbFRoaXMuVGV4dEVuY29kZXIoKTtcbiAgICAgICAgY29uc3QgdWludDhhcnJheSA9IGVuY29kZXIuZW5jb2RlKHMpO1xuICAgICAgICByZXR1cm4gdGhpcy5hbGxvYyhbLi4udWludDhhcnJheSwgMF0pO1xuICAgIH1cblxuICAgIF9zZXRTaWduYXR1cmVzKCkge1xuICAgICAgICB0aGlzLnNpZ25hdHVyZXMgPSBbXTtcbiAgICAgICAgY29uc3Qgc2lnbmF0dXJlSWR4QnlOYW1lID0ge307XG4gICAgICAgIGlmICh0aGlzLmZ1bmN0aW9uc1RhYmxlLmxlbmd0aD4wKSB7XG4gICAgICAgICAgICBjb25zdCBzaWduYXR1cmUgPSB0aGlzLmZ1bmN0aW9uc1t0aGlzLmZ1bmN0aW9uc1RhYmxlWzBdXS5nZXRTaWduYXR1cmUoKTtcbiAgICAgICAgICAgIGNvbnN0IHNpZ25hdHVyZU5hbWUgPSBcInNfXCIrdG9IZXhTdHJpbmcoc2lnbmF0dXJlKTtcbiAgICAgICAgICAgIHNpZ25hdHVyZUlkeEJ5TmFtZVtzaWduYXR1cmVOYW1lXSA9IDA7XG4gICAgICAgICAgICB0aGlzLnNpZ25hdHVyZXMucHVzaChzaWduYXR1cmUpO1xuICAgICAgICB9XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTx0aGlzLmZ1bmN0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29uc3Qgc2lnbmF0dXJlID0gdGhpcy5mdW5jdGlvbnNbaV0uZ2V0U2lnbmF0dXJlKCk7XG4gICAgICAgICAgICBjb25zdCBzaWduYXR1cmVOYW1lID0gXCJzX1wiK3RvSGV4U3RyaW5nKHNpZ25hdHVyZSk7XG4gICAgICAgICAgICBpZiAodHlwZW9mKHNpZ25hdHVyZUlkeEJ5TmFtZVtzaWduYXR1cmVOYW1lXSkgPT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICBzaWduYXR1cmVJZHhCeU5hbWVbc2lnbmF0dXJlTmFtZV0gPSB0aGlzLnNpZ25hdHVyZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHRoaXMuc2lnbmF0dXJlcy5wdXNoKHNpZ25hdHVyZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuZnVuY3Rpb25zW2ldLnNpZ25hdHVyZUlkeCA9IHNpZ25hdHVyZUlkeEJ5TmFtZVtzaWduYXR1cmVOYW1lXTtcbiAgICAgICAgfVxuXG4gICAgfVxuXG4gICAgX2J1aWxkU2VjdGlvbihzZWN0aW9uVHlwZSwgc2VjdGlvbikge1xuICAgICAgICByZXR1cm4gW3NlY3Rpb25UeXBlLCAuLi52YXJ1aW50MzIoc2VjdGlvbi5sZW5ndGgpLCAuLi5zZWN0aW9uXTtcbiAgICB9XG5cbiAgICBfYnVpbGRUeXBlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYnVpbGRTZWN0aW9uKFxuICAgICAgICAgICAgMHgwMSxcbiAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAuLi52YXJ1aW50MzIodGhpcy5zaWduYXR1cmVzLmxlbmd0aCksXG4gICAgICAgICAgICAgICAgLi4uW10uY29uY2F0KC4uLnRoaXMuc2lnbmF0dXJlcylcbiAgICAgICAgICAgIF1cbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBfYnVpbGRJbXBvcnQoKSB7XG4gICAgICAgIGNvbnN0IGVudHJpZXMgPSBbXTtcbiAgICAgICAgZW50cmllcy5wdXNoKFtcbiAgICAgICAgICAgIC4uLnN0cmluZyh0aGlzLm1lbW9yeS5tb2R1bGVOYW1lKSxcbiAgICAgICAgICAgIC4uLnN0cmluZyh0aGlzLm1lbW9yeS5maWVsZE5hbWUpLFxuICAgICAgICAgICAgMHgwMixcbiAgICAgICAgICAgIDB4MDAsICAgLy9GbGFncyBubyBpbml0IHZhbHVhXG4gICAgICAgICAgICAuLi52YXJ1aW50MzIodGhpcy5tZW1vcnkucGFnZXNTaXplKVxuICAgICAgICBdKTtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPCB0aGlzLm5JbXBvcnRGdW5jdGlvbnM7IGkrKykge1xuICAgICAgICAgICAgZW50cmllcy5wdXNoKFtcbiAgICAgICAgICAgICAgICAuLi5zdHJpbmcodGhpcy5mdW5jdGlvbnNbaV0ubW9kdWxlTmFtZSksXG4gICAgICAgICAgICAgICAgLi4uc3RyaW5nKHRoaXMuZnVuY3Rpb25zW2ldLmZpZWxkTmFtZSksXG4gICAgICAgICAgICAgICAgMHgwMCxcbiAgICAgICAgICAgICAgICAuLi52YXJ1aW50MzIodGhpcy5mdW5jdGlvbnNbaV0uc2lnbmF0dXJlSWR4KVxuICAgICAgICAgICAgXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX2J1aWxkU2VjdGlvbihcbiAgICAgICAgICAgIDB4MDIsXG4gICAgICAgICAgICB2YXJ1aW50MzIoZW50cmllcy5sZW5ndGgpLmNvbmNhdCguLi5lbnRyaWVzKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIF9idWlsZEZ1bmN0aW9uRGVjbGFyYXRpb25zKCkge1xuICAgICAgICBjb25zdCBlbnRyaWVzID0gW107XG4gICAgICAgIGZvciAobGV0IGk9dGhpcy5uSW1wb3J0RnVuY3Rpb25zOyBpPCB0aGlzLm5JbXBvcnRGdW5jdGlvbnMgKyB0aGlzLm5JbnRlcm5hbEZ1bmN0aW9uczsgaSsrKSB7XG4gICAgICAgICAgICBlbnRyaWVzLnB1c2goLi4udmFydWludDMyKHRoaXMuZnVuY3Rpb25zW2ldLnNpZ25hdHVyZUlkeCkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9idWlsZFNlY3Rpb24oXG4gICAgICAgICAgICAweDAzLFxuICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgIC4uLnZhcnVpbnQzMihlbnRyaWVzLmxlbmd0aCksXG4gICAgICAgICAgICAgICAgLi4uWy4uLmVudHJpZXNdXG4gICAgICAgICAgICBdXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgX2J1aWxkRnVuY3Rpb25zVGFibGUoKSB7XG4gICAgICAgIGlmICh0aGlzLmZ1bmN0aW9uc1RhYmxlLmxlbmd0aCA9PSAwKSByZXR1cm4gW107XG4gICAgICAgIHJldHVybiB0aGlzLl9idWlsZFNlY3Rpb24oXG4gICAgICAgICAgICAweDA0LFxuICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgIC4uLnZhcnVpbnQzMigxKSxcbiAgICAgICAgICAgICAgICAweDcwLCAwLCAuLi52YXJ1aW50MzIodGhpcy5mdW5jdGlvbnNUYWJsZS5sZW5ndGgpXG4gICAgICAgICAgICBdXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgX2J1aWxkRWxlbWVudHMoKSB7XG4gICAgICAgIGlmICh0aGlzLmZ1bmN0aW9uc1RhYmxlLmxlbmd0aCA9PSAwKSByZXR1cm4gW107XG4gICAgICAgIGNvbnN0IGVudHJpZXMgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPHRoaXMuZnVuY3Rpb25zVGFibGUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGVudHJpZXMucHVzaCguLi52YXJ1aW50MzIodGhpcy5mdW5jdGlvbnNUYWJsZVtpXSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9idWlsZFNlY3Rpb24oXG4gICAgICAgICAgICAweDA5LFxuICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgIC4uLnZhcnVpbnQzMigxKSwgICAgICAvLyAxIGVudHJ5XG4gICAgICAgICAgICAgICAgLi4udmFydWludDMyKDApLCAgICAgIC8vIFRhYmxlICgwIGluIE1WUClcbiAgICAgICAgICAgICAgICAweDQxLCAgICAgICAgICAgICAgICAgICAgICAgLy8gb2Zmc2V0IDBcbiAgICAgICAgICAgICAgICAuLi52YXJpbnQzMigwKSxcbiAgICAgICAgICAgICAgICAweDBiLFxuICAgICAgICAgICAgICAgIC4uLnZhcnVpbnQzMih0aGlzLmZ1bmN0aW9uc1RhYmxlLmxlbmd0aCksIC8vIE51bWJlciBvZiBlbGVtZW50c1xuICAgICAgICAgICAgICAgIC4uLlsuLi5lbnRyaWVzXVxuICAgICAgICAgICAgXVxuICAgICAgICApO1xuICAgIH1cblxuICAgIF9idWlsZEV4cG9ydHMoKSB7XG4gICAgICAgIGNvbnN0IGVudHJpZXMgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPCB0aGlzLmV4cG9ydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGVudHJpZXMucHVzaChbXG4gICAgICAgICAgICAgICAgLi4uc3RyaW5nKHRoaXMuZXhwb3J0c1tpXS5leHBvcnROYW1lKSxcbiAgICAgICAgICAgICAgICAweDAwLFxuICAgICAgICAgICAgICAgIC4uLnZhcnVpbnQzMih0aGlzLmV4cG9ydHNbaV0uaWR4KVxuICAgICAgICAgICAgXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX2J1aWxkU2VjdGlvbihcbiAgICAgICAgICAgIDB4MDcsXG4gICAgICAgICAgICB2YXJ1aW50MzIoZW50cmllcy5sZW5ndGgpLmNvbmNhdCguLi5lbnRyaWVzKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIF9idWlsZENvZGUoKSB7XG4gICAgICAgIGNvbnN0IGVudHJpZXMgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgaT10aGlzLm5JbXBvcnRGdW5jdGlvbnM7IGk8IHRoaXMubkltcG9ydEZ1bmN0aW9ucyArIHRoaXMubkludGVybmFsRnVuY3Rpb25zOyBpKyspIHtcbiAgICAgICAgICAgIGVudHJpZXMucHVzaCh0aGlzLmZ1bmN0aW9uc1tpXS5nZXRCb2R5KCkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9idWlsZFNlY3Rpb24oXG4gICAgICAgICAgICAweDBhLFxuICAgICAgICAgICAgdmFydWludDMyKGVudHJpZXMubGVuZ3RoKS5jb25jYXQoLi4uZW50cmllcylcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBfYnVpbGREYXRhKCkge1xuICAgICAgICBjb25zdCBlbnRyaWVzID0gW107XG4gICAgICAgIGVudHJpZXMucHVzaChbXG4gICAgICAgICAgICAweDAwLFxuICAgICAgICAgICAgMHg0MSxcbiAgICAgICAgICAgIDB4MDAsXG4gICAgICAgICAgICAweDBiLFxuICAgICAgICAgICAgMHgwNCxcbiAgICAgICAgICAgIC4uLnUzMih0aGlzLmZyZWUpXG4gICAgICAgIF0pO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8IHRoaXMuZGF0YXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGVudHJpZXMucHVzaChbXG4gICAgICAgICAgICAgICAgMHgwMCxcbiAgICAgICAgICAgICAgICAweDQxLFxuICAgICAgICAgICAgICAgIC4uLnZhcmludDMyKHRoaXMuZGF0YXNbaV0ub2Zmc2V0KSxcbiAgICAgICAgICAgICAgICAweDBiLFxuICAgICAgICAgICAgICAgIC4uLnZhcnVpbnQzMih0aGlzLmRhdGFzW2ldLmJ5dGVzLmxlbmd0aCksXG4gICAgICAgICAgICAgICAgLi4udGhpcy5kYXRhc1tpXS5ieXRlcyxcbiAgICAgICAgICAgIF0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9idWlsZFNlY3Rpb24oXG4gICAgICAgICAgICAweDBiLFxuICAgICAgICAgICAgdmFydWludDMyKGVudHJpZXMubGVuZ3RoKS5jb25jYXQoLi4uZW50cmllcylcbiAgICAgICAgKTtcbiAgICB9XG5cbn1cblxuLypcbiAgICBDb3B5cmlnaHQgMjAxOSAwS0lNUyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHdhc21idWlsZGVyXG5cbiAgICB3YXNtYnVpbGRlciBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHdhc21idWlsZGVyIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHdhc21idWlsZGVyLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxudmFyIG1haW4gPSAvKiNfX1BVUkVfXyovT2JqZWN0LmZyZWV6ZSh7XG4gICAgX19wcm90b19fOiBudWxsLFxuICAgIE1vZHVsZUJ1aWxkZXI6IE1vZHVsZUJ1aWxkZXJcbn0pO1xuXG5leHBvcnQgeyBCaWdCdWZmZXIsIENoYUNoYSwgRUMsIFpxRmllbGQgYXMgRjFGaWVsZCwgRjJGaWVsZCwgRjNGaWVsZCwgUG9sRmllbGQsIFNjYWxhciwgWnFGaWVsZCwgYnVpbGRCbHMxMjM4MSQxIGFzIGJ1aWxkQmxzMTIzODEsIGJ1aWxkQm4xMjgkMSBhcyBidWlsZEJuMTI4LCBnZXRDdXJ2ZUZyb21OYW1lLCBnZXRDdXJ2ZUZyb21RLCBnZXRDdXJ2ZUZyb21SLCB1dGlscyQ2IGFzIHV0aWxzIH07XG4iLCJcbmltcG9ydCBmcyBmcm9tXCJmc1wiO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gb3BlbihmaWxlTmFtZSwgb3BlbkZsYWdzLCBjYWNoZVNpemUsIHBhZ2VTaXplKSB7XG4gICAgY2FjaGVTaXplID0gY2FjaGVTaXplIHx8IDQwOTYqNjQ7XG4gICAgaWYgKHR5cGVvZiBvcGVuRmxhZ3MgIT09IFwibnVtYmVyXCIgJiYgW1widytcIiwgXCJ3eCtcIiwgXCJyXCIsIFwiYXgrXCIsIFwiYStcIl0uaW5kZXhPZihvcGVuRmxhZ3MpIDwwKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIG9wZW4gb3B0aW9uXCIpO1xuICAgIGNvbnN0IGZkID1hd2FpdCBmcy5wcm9taXNlcy5vcGVuKGZpbGVOYW1lLCBvcGVuRmxhZ3MpO1xuXG4gICAgY29uc3Qgc3RhdHMgPSBhd2FpdCBmZC5zdGF0KCk7XG5cbiAgICByZXR1cm4gIG5ldyBGYXN0RmlsZShmZCwgc3RhdHMsIGNhY2hlU2l6ZSwgcGFnZVNpemUsIGZpbGVOYW1lKTtcbn1cblxuXG5jbGFzcyBGYXN0RmlsZSB7XG5cbiAgICBjb25zdHJ1Y3RvcihmZCwgc3RhdHMsIGNhY2hlU2l6ZSwgcGFnZVNpemUsIGZpbGVOYW1lKSB7XG4gICAgICAgIHRoaXMuZmlsZU5hbWUgPSBmaWxlTmFtZTtcbiAgICAgICAgdGhpcy5mZCA9IGZkO1xuICAgICAgICB0aGlzLnBvcyA9IDA7XG4gICAgICAgIHRoaXMucGFnZVNpemUgPSBwYWdlU2l6ZSB8fCAoMSA8PCA4KTtcbiAgICAgICAgd2hpbGUgKHRoaXMucGFnZVNpemUgPCBzdGF0cy5ibGtzaXplKSB7XG4gICAgICAgICAgICB0aGlzLnBhZ2VTaXplICo9IDI7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy50b3RhbFNpemUgPSBzdGF0cy5zaXplO1xuICAgICAgICB0aGlzLnRvdGFsUGFnZXMgPSBNYXRoLmZsb29yKChzdGF0cy5zaXplIC0xKSAvIHRoaXMucGFnZVNpemUpKzE7XG4gICAgICAgIHRoaXMubWF4UGFnZXNMb2FkZWQgPSBNYXRoLmZsb29yKCBjYWNoZVNpemUgLyB0aGlzLnBhZ2VTaXplKSsxO1xuICAgICAgICB0aGlzLnBhZ2VzID0ge307XG4gICAgICAgIHRoaXMucGVuZGluZ0xvYWRzID0gW107XG4gICAgICAgIHRoaXMud3JpdGluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLnJlYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5hdkJ1ZmZzID0gW107XG4gICAgICAgIHRoaXMuaGlzdG9yeSA9IHt9O1xuICAgIH1cblxuICAgIF9sb2FkUGFnZShwKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBjb25zdCBQID0gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCk9PiB7XG4gICAgICAgICAgICBzZWxmLnBlbmRpbmdMb2Fkcy5wdXNoKHtcbiAgICAgICAgICAgICAgICBwYWdlOiBwLFxuICAgICAgICAgICAgICAgIHJlc29sdmU6IHJlc29sdmUsXG4gICAgICAgICAgICAgICAgcmVqZWN0OiByZWplY3RcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgc2VsZi5fX3N0YXR1c1BhZ2UoXCJBZnRlciBMb2FkIHJlcXVlc3Q6IFwiLCBwKTtcbiAgICAgICAgcmV0dXJuIFA7XG4gICAgfVxuXG4gICAgX19zdGF0dXNQYWdlKHMsIHApIHtcbiAgICAgICAgY29uc3QgbG9nRW50cnkgPSBbXTtcbiAgICAgICAgY29uc3Qgc2VsZj10aGlzO1xuICAgICAgICBpZiAoIXNlbGYubG9nSGlzdG9yeSkgcmV0dXJuO1xuICAgICAgICBsb2dFbnRyeS5wdXNoKFwiPT1cIiArIHMrIFwiIFwiICtwKTtcbiAgICAgICAgbGV0IFMgPSBcIlwiO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8c2VsZi5wZW5kaW5nTG9hZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChzZWxmLnBlbmRpbmdMb2Fkc1tpXS5wYWdlID09IHApIFMgPSBTICsgXCIgXCIgKyBpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChTKSBsb2dFbnRyeS5wdXNoKFwiUGVuZGluZyBsb2FkczpcIitTKTtcbiAgICAgICAgaWYgKHR5cGVvZiBzZWxmLnBhZ2VzW3BdICE9IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgIGNvbnN0IHBhZ2UgPSBzZWxmLnBhZ2VzW3BdO1xuICAgICAgICAgICAgbG9nRW50cnkucHVzaChcIkxvYWRlZFwiKTtcbiAgICAgICAgICAgIGxvZ0VudHJ5LnB1c2goXCJwZW5kaW5nT3BzOiBcIitwYWdlLnBlbmRpbmdPcHMpO1xuICAgICAgICAgICAgaWYgKHBhZ2UubG9hZGluZykgbG9nRW50cnkucHVzaChcImxvYWRpbmc6IFwiK3BhZ2UubG9hZGluZyk7XG4gICAgICAgICAgICBpZiAocGFnZS53cml0aW5nKSBsb2dFbnRyeS5wdXNoKFwid3JpdGluZ1wiKTtcbiAgICAgICAgICAgIGlmIChwYWdlLmRpcnR5KSBsb2dFbnRyeS5wdXNoKFwiZGlydHlcIik7XG4gICAgICAgIH1cbiAgICAgICAgbG9nRW50cnkucHVzaChcIj09XCIpO1xuXG4gICAgICAgIGlmICghc2VsZi5oaXN0b3J5W3BdKSBzZWxmLmhpc3RvcnlbcF0gPSBbXTtcbiAgICAgICAgc2VsZi5oaXN0b3J5W3BdLnB1c2gobG9nRW50cnkpO1xuICAgIH1cblxuICAgIF9fcHJpbnRIaXN0b3J5KHApIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGlmICghc2VsZi5oaXN0b3J5W3BdKSBjb25zb2xlLmxvZyhcIkVtcHR5IEhpc3RvcnkgXCIsIHApO1xuICAgICAgICBjb25zb2xlLmxvZyhcIkhpc3RvcnkgXCIrcCk7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxzZWxmLmhpc3RvcnlbcF0ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGZvciAobGV0IGo9MDsgajxzZWxmLmhpc3RvcnlbcF1baV0ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIi0+IFwiICsgc2VsZi5oaXN0b3J5W3BdW2ldW2pdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuXG5cbiAgICBfdHJpZ2dlckxvYWQoKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gICAgICAgIGlmIChzZWxmLnJlYWRpbmcpIHJldHVybjtcbiAgICAgICAgaWYgKHNlbGYucGVuZGluZ0xvYWRzLmxlbmd0aD09MCkgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IHBhZ2VJZHhzID0gT2JqZWN0LmtleXMoc2VsZi5wYWdlcyk7XG5cbiAgICAgICAgY29uc3QgZGVsZXRhYmxlUGFnZXMgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPHBhZ2VJZHhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBwYWdlID0gc2VsZi5wYWdlc1twYXJzZUludChwYWdlSWR4c1tpXSldO1xuICAgICAgICAgICAgaWYgKChwYWdlLmRpcnR5ID09IGZhbHNlKSYmKHBhZ2UucGVuZGluZ09wcz09MCkmJighcGFnZS53cml0aW5nKSYmKCFwYWdlLmxvYWRpbmcpKSBkZWxldGFibGVQYWdlcy5wdXNoKHBhcnNlSW50KHBhZ2VJZHhzW2ldKSk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgZnJlZVBhZ2VzID0gc2VsZi5tYXhQYWdlc0xvYWRlZCAtIHBhZ2VJZHhzLmxlbmd0aDtcblxuICAgICAgICBjb25zdCBvcHMgPSBbXTtcblxuICAgICAgICAvLyB3aGlsZSBwZW5kaW5nIGxvYWRzIGFuZFxuICAgICAgICAvLyAgICAgdGhlIHBhZ2UgaXMgbG9hZGVkIG9yIEkgY2FuIHJlY292ZXIgb25lLlxuICAgICAgICB3aGlsZSAoXG4gICAgICAgICAgICAoc2VsZi5wZW5kaW5nTG9hZHMubGVuZ3RoPjApICYmXG4gICAgICAgICAgICAoICAgKHR5cGVvZiBzZWxmLnBhZ2VzW3NlbGYucGVuZGluZ0xvYWRzWzBdLnBhZ2VdICE9IFwidW5kZWZpbmVkXCIgKVxuICAgICAgICAgICAgICB8fCggIChmcmVlUGFnZXM+MClcbiAgICAgICAgICAgICAgICAgfHwoZGVsZXRhYmxlUGFnZXMubGVuZ3RoPjApKSkpIHtcbiAgICAgICAgICAgIGNvbnN0IGxvYWQgPSBzZWxmLnBlbmRpbmdMb2Fkcy5zaGlmdCgpO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBzZWxmLnBhZ2VzW2xvYWQucGFnZV0gIT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgICAgIHNlbGYucGFnZXNbbG9hZC5wYWdlXS5wZW5kaW5nT3BzICsrO1xuICAgICAgICAgICAgICAgIGNvbnN0IGlkeCA9IGRlbGV0YWJsZVBhZ2VzLmluZGV4T2YobG9hZC5wYWdlKTtcbiAgICAgICAgICAgICAgICBpZiAoaWR4Pj0wKSBkZWxldGFibGVQYWdlcy5zcGxpY2UoaWR4LCAxKTtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZi5wYWdlc1tsb2FkLnBhZ2VdLmxvYWRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5wYWdlc1tsb2FkLnBhZ2VdLmxvYWRpbmcucHVzaChsb2FkKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBsb2FkLnJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2VsZi5fX3N0YXR1c1BhZ2UoXCJBZnRlciBMb2FkIChjYWNoZWQpOiBcIiwgbG9hZC5wYWdlKTtcblxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoZnJlZVBhZ2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGZyZWVQYWdlcy0tO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGZwID0gZGVsZXRhYmxlUGFnZXMuc2hpZnQoKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fX3N0YXR1c1BhZ2UoXCJCZWZvcmUgVW5sb2FkOiBcIiwgZnApO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLmF2QnVmZnMudW5zaGlmdChzZWxmLnBhZ2VzW2ZwXSk7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBzZWxmLnBhZ2VzW2ZwXTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fX3N0YXR1c1BhZ2UoXCJBZnRlciBVbmxvYWQ6IFwiLCBmcCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGxvYWQucGFnZT49c2VsZi50b3RhbFBhZ2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYucGFnZXNbbG9hZC5wYWdlXSA9IGdldE5ld1BhZ2UoKTtcbiAgICAgICAgICAgICAgICAgICAgbG9hZC5yZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX19zdGF0dXNQYWdlKFwiQWZ0ZXIgTG9hZCAobmV3KTogXCIsIGxvYWQucGFnZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5yZWFkaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5wYWdlc1tsb2FkLnBhZ2VdID0gZ2V0TmV3UGFnZSgpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnBhZ2VzW2xvYWQucGFnZV0ubG9hZGluZyA9IFtsb2FkXTtcbiAgICAgICAgICAgICAgICAgICAgb3BzLnB1c2goc2VsZi5mZC5yZWFkKHNlbGYucGFnZXNbbG9hZC5wYWdlXS5idWZmLCAwLCBzZWxmLnBhZ2VTaXplLCBsb2FkLnBhZ2Uqc2VsZi5wYWdlU2l6ZSkudGhlbigocmVzKT0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYucGFnZXNbbG9hZC5wYWdlXS5zaXplID0gcmVzLmJ5dGVzUmVhZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxvYWRpbmcgPSBzZWxmLnBhZ2VzW2xvYWQucGFnZV0ubG9hZGluZztcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBzZWxmLnBhZ2VzW2xvYWQucGFnZV0ubG9hZGluZztcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGk9MDsgaTxsb2FkaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9hZGluZ1tpXS5yZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9fc3RhdHVzUGFnZShcIkFmdGVyIExvYWQgKGxvYWRlZCk6IFwiLCBsb2FkLnBhZ2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgICAgICAgICAgICAgICAgfSwgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9hZC5yZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9fc3RhdHVzUGFnZShcIkFmdGVyIExvYWQgKGxvYWRpbmcpOiBcIiwgbG9hZC5wYWdlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgKG9wcy5sZW5ndGg+MSkgY29uc29sZS5sb2cob3BzLmxlbmd0aCk7XG5cbiAgICAgICAgUHJvbWlzZS5hbGwob3BzKS50aGVuKCAoKSA9PiB7XG4gICAgICAgICAgICBzZWxmLnJlYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmIChzZWxmLnBlbmRpbmdMb2Fkcy5sZW5ndGg+MCkgc2V0SW1tZWRpYXRlKHNlbGYuX3RyaWdnZXJMb2FkLmJpbmQoc2VsZikpO1xuICAgICAgICAgICAgc2VsZi5fdHJ5Q2xvc2UoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgZnVuY3Rpb24gZ2V0TmV3UGFnZSgpIHtcbiAgICAgICAgICAgIGlmIChzZWxmLmF2QnVmZnMubGVuZ3RoPjApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwID0gc2VsZi5hdkJ1ZmZzLnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgcC5kaXJ0eSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHAucGVuZGluZ09wcyA9IDE7XG4gICAgICAgICAgICAgICAgcC5zaXplID0wO1xuICAgICAgICAgICAgICAgIHJldHVybiBwO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBkaXJ0eTogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIGJ1ZmY6IG5ldyBVaW50OEFycmF5KHNlbGYucGFnZVNpemUpLFxuICAgICAgICAgICAgICAgICAgICBwZW5kaW5nT3BzOiAxLFxuICAgICAgICAgICAgICAgICAgICBzaXplOiAwXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgfVxuXG5cbiAgICBfdHJpZ2dlcldyaXRlKCkge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgaWYgKHNlbGYud3JpdGluZykgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IHBhZ2VJZHhzID0gT2JqZWN0LmtleXMoc2VsZi5wYWdlcyk7XG5cbiAgICAgICAgY29uc3Qgb3BzID0gW107XG5cbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPHBhZ2VJZHhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBwYWdlID0gc2VsZi5wYWdlc1twYXJzZUludChwYWdlSWR4c1tpXSldO1xuICAgICAgICAgICAgaWYgKHBhZ2UuZGlydHkpIHtcbiAgICAgICAgICAgICAgICBwYWdlLmRpcnR5ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcGFnZS53cml0aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBzZWxmLndyaXRpbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIG9wcy5wdXNoKCBzZWxmLmZkLndyaXRlKHBhZ2UuYnVmZiwgMCwgcGFnZS5zaXplLCBwYXJzZUludChwYWdlSWR4c1tpXSkqc2VsZi5wYWdlU2l6ZSkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHBhZ2Uud3JpdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSwgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIkVSUk9SIFdyaXRpbmc6IFwiK2Vycik7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuZXJyb3IgPSBlcnI7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3RyeUNsb3NlKCk7XG4gICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNlbGYud3JpdGluZykge1xuICAgICAgICAgICAgUHJvbWlzZS5hbGwob3BzKS50aGVuKCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgc2VsZi53cml0aW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgc2V0SW1tZWRpYXRlKHNlbGYuX3RyaWdnZXJXcml0ZS5iaW5kKHNlbGYpKTtcbiAgICAgICAgICAgICAgICBzZWxmLl90cnlDbG9zZSgpO1xuICAgICAgICAgICAgICAgIGlmIChzZWxmLnBlbmRpbmdMb2Fkcy5sZW5ndGg+MCkgc2V0SW1tZWRpYXRlKHNlbGYuX3RyaWdnZXJMb2FkLmJpbmQoc2VsZikpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBfZ2V0RGlydHlQYWdlKCkge1xuICAgICAgICBmb3IgKGxldCBwIGluIHRoaXMucGFnZXMpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnBhZ2VzW3BdLmRpcnR5KSByZXR1cm4gcDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgYXN5bmMgd3JpdGUoYnVmZiwgcG9zKSB7XG4gICAgICAgIGlmIChidWZmLmJ5dGVMZW5ndGggPT0gMCkgcmV0dXJuO1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgLypcbiAgICAgICAgaWYgKGJ1ZmYuYnl0ZUxlbmd0aCA+IHNlbGYucGFnZVNpemUqc2VsZi5tYXhQYWdlc0xvYWRlZCowLjgpIHtcbiAgICAgICAgICAgIGNvbnN0IGNhY2hlU2l6ZSA9IE1hdGguZmxvb3IoYnVmZi5ieXRlTGVuZ3RoICogMS4xKTtcbiAgICAgICAgICAgIHRoaXMubWF4UGFnZXNMb2FkZWQgPSBNYXRoLmZsb29yKCBjYWNoZVNpemUgLyBzZWxmLnBhZ2VTaXplKSsxO1xuICAgICAgICB9XG4gICAgICAgICovXG4gICAgICAgIGlmICh0eXBlb2YgcG9zID09IFwidW5kZWZpbmVkXCIpIHBvcyA9IHNlbGYucG9zO1xuICAgICAgICBzZWxmLnBvcyA9IHBvcytidWZmLmJ5dGVMZW5ndGg7XG4gICAgICAgIGlmIChzZWxmLnRvdGFsU2l6ZSA8IHBvcyArIGJ1ZmYuYnl0ZUxlbmd0aCkgc2VsZi50b3RhbFNpemUgPSBwb3MgKyBidWZmLmJ5dGVMZW5ndGg7XG4gICAgICAgIGlmIChzZWxmLnBlbmRpbmdDbG9zZSlcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIldyaXRpbmcgYSBjbG9zaW5nIGZpbGVcIik7XG4gICAgICAgIGNvbnN0IGZpcnN0UGFnZSA9IE1hdGguZmxvb3IocG9zIC8gc2VsZi5wYWdlU2l6ZSk7XG4gICAgICAgIGNvbnN0IGxhc3RQYWdlID0gTWF0aC5mbG9vcigocG9zICsgYnVmZi5ieXRlTGVuZ3RoIC0xKSAvIHNlbGYucGFnZVNpemUpO1xuXG4gICAgICAgIGNvbnN0IHBhZ2VQcm9taXNlcyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBpPWZpcnN0UGFnZTsgaTw9bGFzdFBhZ2U7IGkrKykgcGFnZVByb21pc2VzLnB1c2goc2VsZi5fbG9hZFBhZ2UoaSkpO1xuICAgICAgICBzZWxmLl90cmlnZ2VyTG9hZCgpO1xuXG4gICAgICAgIGxldCBwID0gZmlyc3RQYWdlO1xuICAgICAgICBsZXQgbyA9IHBvcyAlIHNlbGYucGFnZVNpemU7XG4gICAgICAgIGxldCByID0gYnVmZi5ieXRlTGVuZ3RoO1xuICAgICAgICB3aGlsZSAocj4wKSB7XG4gICAgICAgICAgICBhd2FpdCBwYWdlUHJvbWlzZXNbcC1maXJzdFBhZ2VdO1xuICAgICAgICAgICAgY29uc3QgbCA9IChvK3IgPiBzZWxmLnBhZ2VTaXplKSA/IChzZWxmLnBhZ2VTaXplIC1vKSA6IHI7XG4gICAgICAgICAgICBjb25zdCBzcmNWaWV3ID0gYnVmZi5zbGljZSggYnVmZi5ieXRlTGVuZ3RoIC0gciwgYnVmZi5ieXRlTGVuZ3RoIC0gciArIGwpO1xuICAgICAgICAgICAgY29uc3QgZHN0VmlldyA9IG5ldyBVaW50OEFycmF5KHNlbGYucGFnZXNbcF0uYnVmZi5idWZmZXIsIG8sIGwpO1xuICAgICAgICAgICAgZHN0Vmlldy5zZXQoc3JjVmlldyk7XG4gICAgICAgICAgICBzZWxmLnBhZ2VzW3BdLmRpcnR5ID0gdHJ1ZTtcbiAgICAgICAgICAgIHNlbGYucGFnZXNbcF0ucGVuZGluZ09wcyAtLTtcbiAgICAgICAgICAgIHNlbGYucGFnZXNbcF0uc2l6ZSA9IE1hdGgubWF4KG8rbCwgc2VsZi5wYWdlc1twXS5zaXplKTtcbiAgICAgICAgICAgIGlmIChwPj1zZWxmLnRvdGFsUGFnZXMpIHtcbiAgICAgICAgICAgICAgICBzZWxmLnRvdGFsUGFnZXMgPSBwKzE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByID0gci1sO1xuICAgICAgICAgICAgcCArKztcbiAgICAgICAgICAgIG8gPSAwO1xuICAgICAgICAgICAgaWYgKCFzZWxmLndyaXRpbmcpIHNldEltbWVkaWF0ZShzZWxmLl90cmlnZ2VyV3JpdGUuYmluZChzZWxmKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhc3luYyByZWFkKGxlbiwgcG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBsZXQgYnVmZiA9IG5ldyBVaW50OEFycmF5KGxlbik7XG4gICAgICAgIGF3YWl0IHNlbGYucmVhZFRvQnVmZmVyKGJ1ZmYsIDAsIGxlbiwgcG9zKTtcblxuICAgICAgICByZXR1cm4gYnVmZjtcbiAgICB9XG5cbiAgICBhc3luYyByZWFkVG9CdWZmZXIoYnVmZkRzdCwgb2Zmc2V0LCBsZW4sIHBvcykge1xuICAgICAgICBpZiAobGVuID09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgaWYgKGxlbiA+IHNlbGYucGFnZVNpemUqc2VsZi5tYXhQYWdlc0xvYWRlZCowLjgpIHtcbiAgICAgICAgICAgIGNvbnN0IGNhY2hlU2l6ZSA9IE1hdGguZmxvb3IobGVuICogMS4xKTtcbiAgICAgICAgICAgIHRoaXMubWF4UGFnZXNMb2FkZWQgPSBNYXRoLmZsb29yKCBjYWNoZVNpemUgLyBzZWxmLnBhZ2VTaXplKSsxO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2YgcG9zID09IFwidW5kZWZpbmVkXCIpIHBvcyA9IHNlbGYucG9zO1xuICAgICAgICBzZWxmLnBvcyA9IHBvcytsZW47XG4gICAgICAgIGlmIChzZWxmLnBlbmRpbmdDbG9zZSlcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlJlYWRpbmcgYSBjbG9zaW5nIGZpbGVcIik7XG4gICAgICAgIGNvbnN0IGZpcnN0UGFnZSA9IE1hdGguZmxvb3IocG9zIC8gc2VsZi5wYWdlU2l6ZSk7XG4gICAgICAgIGNvbnN0IGxhc3RQYWdlID0gTWF0aC5mbG9vcigocG9zICsgbGVuIC0xKSAvIHNlbGYucGFnZVNpemUpO1xuXG4gICAgICAgIGNvbnN0IHBhZ2VQcm9taXNlcyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBpPWZpcnN0UGFnZTsgaTw9bGFzdFBhZ2U7IGkrKykgcGFnZVByb21pc2VzLnB1c2goc2VsZi5fbG9hZFBhZ2UoaSkpO1xuXG4gICAgICAgIHNlbGYuX3RyaWdnZXJMb2FkKCk7XG5cbiAgICAgICAgbGV0IHAgPSBmaXJzdFBhZ2U7XG4gICAgICAgIGxldCBvID0gcG9zICUgc2VsZi5wYWdlU2l6ZTtcbiAgICAgICAgLy8gUmVtYWluaW5nIGJ5dGVzIHRvIHJlYWRcbiAgICAgICAgbGV0IHIgPSBwb3MgKyBsZW4gPiBzZWxmLnRvdGFsU2l6ZSA/IGxlbiAtIChwb3MgKyBsZW4gLSBzZWxmLnRvdGFsU2l6ZSk6IGxlbjtcbiAgICAgICAgd2hpbGUgKHI+MCkge1xuICAgICAgICAgICAgYXdhaXQgcGFnZVByb21pc2VzW3AgLSBmaXJzdFBhZ2VdO1xuICAgICAgICAgICAgc2VsZi5fX3N0YXR1c1BhZ2UoXCJBZnRlciBBd2FpdCAocmVhZCk6IFwiLCBwKTtcblxuICAgICAgICAgICAgLy8gYnl0ZXMgdG8gY29weSBmcm9tIHRoaXMgcGFnZVxuICAgICAgICAgICAgY29uc3QgbCA9IChvK3IgPiBzZWxmLnBhZ2VTaXplKSA/IChzZWxmLnBhZ2VTaXplIC1vKSA6IHI7XG4gICAgICAgICAgICBjb25zdCBzcmNWaWV3ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5wYWdlc1twXS5idWZmLmJ1ZmZlciwgc2VsZi5wYWdlc1twXS5idWZmLmJ5dGVPZmZzZXQgKyBvLCBsKTtcbiAgICAgICAgICAgIGJ1ZmZEc3Quc2V0KHNyY1ZpZXcsIG9mZnNldCtsZW4tcik7XG4gICAgICAgICAgICBzZWxmLnBhZ2VzW3BdLnBlbmRpbmdPcHMgLS07XG5cbiAgICAgICAgICAgIHNlbGYuX19zdGF0dXNQYWdlKFwiQWZ0ZXIgT3AgZG9uZTogXCIsIHApO1xuXG4gICAgICAgICAgICByID0gci1sO1xuICAgICAgICAgICAgcCArKztcbiAgICAgICAgICAgIG8gPSAwO1xuICAgICAgICAgICAgaWYgKHNlbGYucGVuZGluZ0xvYWRzLmxlbmd0aD4wKSBzZXRJbW1lZGlhdGUoc2VsZi5fdHJpZ2dlckxvYWQuYmluZChzZWxmKSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnBvcyA9IHBvcyArIGxlbjtcblxuICAgIH1cblxuXG4gICAgX3RyeUNsb3NlKCkge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgaWYgKCFzZWxmLnBlbmRpbmdDbG9zZSkgcmV0dXJuO1xuICAgICAgICBpZiAoc2VsZi5lcnJvcikge1xuICAgICAgICAgICAgc2VsZi5wZW5kaW5nQ2xvc2VSZWplY3Qoc2VsZi5lcnJvcik7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcCA9IHNlbGYuX2dldERpcnR5UGFnZSgpO1xuICAgICAgICBpZiAoKHA+PTApIHx8IChzZWxmLndyaXRpbmcpIHx8IChzZWxmLnJlYWRpbmcpIHx8IChzZWxmLnBlbmRpbmdMb2Fkcy5sZW5ndGg+MCkpIHJldHVybjtcbiAgICAgICAgc2VsZi5wZW5kaW5nQ2xvc2UoKTtcbiAgICB9XG5cbiAgICBjbG9zZSgpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGlmIChzZWxmLnBlbmRpbmdDbG9zZSlcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNsb3NpbmcgdGhlIGZpbGUgdHdpY2VcIik7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBzZWxmLnBlbmRpbmdDbG9zZSA9IHJlc29sdmU7XG4gICAgICAgICAgICBzZWxmLnBlbmRpbmdDbG9zZVJlamVjdCA9IHJlamVjdDtcbiAgICAgICAgICAgIHNlbGYuX3RyeUNsb3NlKCk7XG4gICAgICAgIH0pLnRoZW4oKCk9PiB7XG4gICAgICAgICAgICBzZWxmLmZkLmNsb3NlKCk7XG4gICAgICAgIH0sIChlcnIpID0+IHtcbiAgICAgICAgICAgIHNlbGYuZmQuY2xvc2UoKTtcbiAgICAgICAgICAgIHRocm93IChlcnIpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBhc3luYyBkaXNjYXJkKCkge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgYXdhaXQgc2VsZi5jbG9zZSgpO1xuICAgICAgICBhd2FpdCBmcy5wcm9taXNlcy51bmxpbmsodGhpcy5maWxlTmFtZSk7XG4gICAgfVxuXG4gICAgYXN5bmMgd3JpdGVVTEUzMih2LCBwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGNvbnN0IHRtcEJ1ZmYzMiA9IG5ldyBVaW50OEFycmF5KDQpO1xuICAgICAgICBjb25zdCB0bXBCdWZmMzJ2ID0gbmV3IERhdGFWaWV3KHRtcEJ1ZmYzMi5idWZmZXIpO1xuXG4gICAgICAgIHRtcEJ1ZmYzMnYuc2V0VWludDMyKDAsIHYsIHRydWUpO1xuXG4gICAgICAgIGF3YWl0IHNlbGYud3JpdGUodG1wQnVmZjMyLCBwb3MpO1xuICAgIH1cblxuICAgIGFzeW5jIHdyaXRlVUJFMzIodiwgcG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gICAgICAgIGNvbnN0IHRtcEJ1ZmYzMiA9IG5ldyBVaW50OEFycmF5KDQpO1xuICAgICAgICBjb25zdCB0bXBCdWZmMzJ2ID0gbmV3IERhdGFWaWV3KHRtcEJ1ZmYzMi5idWZmZXIpO1xuXG4gICAgICAgIHRtcEJ1ZmYzMnYuc2V0VWludDMyKDAsIHYsIGZhbHNlKTtcblxuICAgICAgICBhd2FpdCBzZWxmLndyaXRlKHRtcEJ1ZmYzMiwgcG9zKTtcbiAgICB9XG5cblxuICAgIGFzeW5jIHdyaXRlVUxFNjQodiwgcG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gICAgICAgIGNvbnN0IHRtcEJ1ZmY2NCA9IG5ldyBVaW50OEFycmF5KDgpO1xuICAgICAgICBjb25zdCB0bXBCdWZmNjR2ID0gbmV3IERhdGFWaWV3KHRtcEJ1ZmY2NC5idWZmZXIpO1xuXG4gICAgICAgIHRtcEJ1ZmY2NHYuc2V0VWludDMyKDAsIHYgJiAweEZGRkZGRkZGLCB0cnVlKTtcbiAgICAgICAgdG1wQnVmZjY0di5zZXRVaW50MzIoNCwgTWF0aC5mbG9vcih2IC8gMHgxMDAwMDAwMDApICwgdHJ1ZSk7XG5cbiAgICAgICAgYXdhaXQgc2VsZi53cml0ZSh0bXBCdWZmNjQsIHBvcyk7XG4gICAgfVxuXG4gICAgYXN5bmMgcmVhZFVMRTMyKHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgY29uc3QgYiA9IGF3YWl0IHNlbGYucmVhZCg0LCBwb3MpO1xuXG4gICAgICAgIGNvbnN0IHZpZXcgPSBuZXcgVWludDMyQXJyYXkoYi5idWZmZXIpO1xuXG4gICAgICAgIHJldHVybiB2aWV3WzBdO1xuICAgIH1cblxuICAgIGFzeW5jIHJlYWRVQkUzMihwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGNvbnN0IGIgPSBhd2FpdCBzZWxmLnJlYWQoNCwgcG9zKTtcblxuICAgICAgICBjb25zdCB2aWV3ID0gbmV3IERhdGFWaWV3KGIuYnVmZmVyKTtcblxuICAgICAgICByZXR1cm4gdmlldy5nZXRVaW50MzIoMCwgZmFsc2UpO1xuICAgIH1cblxuICAgIGFzeW5jIHJlYWRVTEU2NChwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGNvbnN0IGIgPSBhd2FpdCBzZWxmLnJlYWQoOCwgcG9zKTtcblxuICAgICAgICBjb25zdCB2aWV3ID0gbmV3IFVpbnQzMkFycmF5KGIuYnVmZmVyKTtcblxuICAgICAgICByZXR1cm4gdmlld1sxXSAqIDB4MTAwMDAwMDAwICsgdmlld1swXTtcbiAgICB9XG5cbiAgICBhc3luYyByZWFkU3RyaW5nKHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcblxuICAgICAgICBpZiAoc2VsZi5wZW5kaW5nQ2xvc2UpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlJlYWRpbmcgYSBjbG9zaW5nIGZpbGVcIik7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgY3VycmVudFBvc2l0aW9uID0gdHlwZW9mIHBvcyA9PSBcInVuZGVmaW5lZFwiID8gc2VsZi5wb3MgOiBwb3M7XG4gICAgICAgIGxldCBjdXJyZW50UGFnZSA9IE1hdGguZmxvb3IoY3VycmVudFBvc2l0aW9uIC8gc2VsZi5wYWdlU2l6ZSk7XG5cbiAgICAgICAgbGV0IGVuZE9mU3RyaW5nRm91bmQgPSBmYWxzZTtcbiAgICAgICAgbGV0IHN0ciA9IFwiXCI7XG5cbiAgICAgICAgd2hpbGUgKCFlbmRPZlN0cmluZ0ZvdW5kKSB7XG4gICAgICAgICAgICAvL1JlYWQgcGFnZVxuICAgICAgICAgICAgbGV0IHBhZ2VQcm9taXNlID0gc2VsZi5fbG9hZFBhZ2UoY3VycmVudFBhZ2UpO1xuICAgICAgICAgICAgc2VsZi5fdHJpZ2dlckxvYWQoKTtcbiAgICAgICAgICAgIGF3YWl0IHBhZ2VQcm9taXNlO1xuICAgICAgICAgICAgc2VsZi5fX3N0YXR1c1BhZ2UoXCJBZnRlciBBd2FpdCAocmVhZCk6IFwiLCBjdXJyZW50UGFnZSk7XG5cbiAgICAgICAgICAgIGxldCBvZmZzZXRPblBhZ2UgPSBjdXJyZW50UG9zaXRpb24gJSBzZWxmLnBhZ2VTaXplO1xuXG4gICAgICAgICAgICBjb25zdCBkYXRhQXJyYXkgPSBuZXcgVWludDhBcnJheShcbiAgICAgICAgICAgICAgICBzZWxmLnBhZ2VzW2N1cnJlbnRQYWdlXS5idWZmLmJ1ZmZlcixcbiAgICAgICAgICAgICAgICBzZWxmLnBhZ2VzW2N1cnJlbnRQYWdlXS5idWZmLmJ5dGVPZmZzZXQgKyBvZmZzZXRPblBhZ2UsXG4gICAgICAgICAgICAgICAgc2VsZi5wYWdlU2l6ZSAtIG9mZnNldE9uUGFnZVxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgbGV0IGluZGV4RW5kT2ZTdHJpbmcgPSBkYXRhQXJyYXkuZmluZEluZGV4KGVsZW1lbnQgPT4gZWxlbWVudCA9PT0gMCk7XG4gICAgICAgICAgICBlbmRPZlN0cmluZ0ZvdW5kID0gaW5kZXhFbmRPZlN0cmluZyAhPT0gLTE7XG5cbiAgICAgICAgICAgIGlmIChlbmRPZlN0cmluZ0ZvdW5kKSB7XG4gICAgICAgICAgICAgICAgc3RyICs9IG5ldyBUZXh0RGVjb2RlcigpLmRlY29kZShkYXRhQXJyYXkuc2xpY2UoMCwgaW5kZXhFbmRPZlN0cmluZykpO1xuICAgICAgICAgICAgICAgIHNlbGYucG9zID0gY3VycmVudFBhZ2UgKiB0aGlzLnBhZ2VTaXplICsgb2Zmc2V0T25QYWdlICsgaW5kZXhFbmRPZlN0cmluZyArIDE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN0ciArPSBuZXcgVGV4dERlY29kZXIoKS5kZWNvZGUoZGF0YUFycmF5KTtcbiAgICAgICAgICAgICAgICBzZWxmLnBvcyA9IGN1cnJlbnRQYWdlICogdGhpcy5wYWdlU2l6ZSArIG9mZnNldE9uUGFnZSArIGRhdGFBcnJheS5sZW5ndGg7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHNlbGYucGFnZXNbY3VycmVudFBhZ2VdLnBlbmRpbmdPcHMtLTtcbiAgICAgICAgICAgIHNlbGYuX19zdGF0dXNQYWdlKFwiQWZ0ZXIgT3AgZG9uZTogXCIsIGN1cnJlbnRQYWdlKTtcblxuICAgICAgICAgICAgY3VycmVudFBvc2l0aW9uID0gc2VsZi5wb3M7XG4gICAgICAgICAgICBjdXJyZW50UGFnZSsrO1xuXG4gICAgICAgICAgICBpZiAoc2VsZi5wZW5kaW5nTG9hZHMubGVuZ3RoID4gMCkgc2V0SW1tZWRpYXRlKHNlbGYuX3RyaWdnZXJMb2FkLmJpbmQoc2VsZikpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHN0cjtcbiAgICB9XG59XG4iLCJleHBvcnQgZnVuY3Rpb24gY3JlYXRlTmV3KG8pIHtcbiAgICBjb25zdCBpbml0aWFsU2l6ZSA9IG8uaW5pdGlhbFNpemUgfHwgMTw8MjA7XG4gICAgY29uc3QgZmQgPSBuZXcgTWVtRmlsZSgpO1xuICAgIGZkLm8gPSBvO1xuICAgIGZkLm8uZGF0YSA9IG5ldyBVaW50OEFycmF5KGluaXRpYWxTaXplKTtcbiAgICBmZC5hbGxvY1NpemUgPSBpbml0aWFsU2l6ZTtcbiAgICBmZC50b3RhbFNpemUgPSAwO1xuICAgIGZkLnJlYWRPbmx5ID0gZmFsc2U7XG4gICAgZmQucG9zID0gMDtcbiAgICByZXR1cm4gZmQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWFkRXhpc3Rpbmcobykge1xuICAgIGNvbnN0IGZkID0gbmV3IE1lbUZpbGUoKTtcbiAgICBmZC5vID0gbztcbiAgICBmZC5hbGxvY1NpemUgPSBvLmRhdGEuYnl0ZUxlbmd0aDtcbiAgICBmZC50b3RhbFNpemUgPSBvLmRhdGEuYnl0ZUxlbmd0aDtcbiAgICBmZC5yZWFkT25seSA9IHRydWU7XG4gICAgZmQucG9zID0gMDtcbiAgICByZXR1cm4gZmQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWFkV3JpdGVFeGlzdGluZyhvKSB7XG4gICAgY29uc3QgZmQgPSBuZXcgTWVtRmlsZSgpO1xuICAgIGZkLm8gPSBvO1xuICAgIGZkLmFsbG9jU2l6ZSA9IG8uZGF0YS5ieXRlTGVuZ3RoO1xuICAgIGZkLnRvdGFsU2l6ZSA9IG8uZGF0YS5ieXRlTGVuZ3RoO1xuICAgIGZkLnJlYWRPbmx5ID0gZmFsc2U7XG4gICAgZmQucG9zID0gMDtcbiAgICByZXR1cm4gZmQ7XG59XG5cbmNvbnN0IHRtcEJ1ZmYzMiA9IG5ldyBVaW50OEFycmF5KDQpO1xuY29uc3QgdG1wQnVmZjMydiA9IG5ldyBEYXRhVmlldyh0bXBCdWZmMzIuYnVmZmVyKTtcbmNvbnN0IHRtcEJ1ZmY2NCA9IG5ldyBVaW50OEFycmF5KDgpO1xuY29uc3QgdG1wQnVmZjY0diA9IG5ldyBEYXRhVmlldyh0bXBCdWZmNjQuYnVmZmVyKTtcblxuY2xhc3MgTWVtRmlsZSB7XG5cbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5wYWdlU2l6ZSA9IDEgPDwgMTQ7ICAvLyBmb3IgY29tcGF0aWJpbGl0eVxuICAgIH1cblxuICAgIF9yZXNpemVJZk5lZWRlZChuZXdMZW4pIHtcbiAgICAgICAgaWYgKG5ld0xlbiA+IHRoaXMuYWxsb2NTaXplKSB7XG4gICAgICAgICAgICBjb25zdCBuZXdBbGxvY1NpemUgPSBNYXRoLm1heChcbiAgICAgICAgICAgICAgICB0aGlzLmFsbG9jU2l6ZSArICgxIDw8IDIwKSxcbiAgICAgICAgICAgICAgICBNYXRoLmZsb29yKHRoaXMuYWxsb2NTaXplICogMS4xKSxcbiAgICAgICAgICAgICAgICBuZXdMZW5cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjb25zdCBuZXdEYXRhID0gbmV3IFVpbnQ4QXJyYXkobmV3QWxsb2NTaXplKTtcbiAgICAgICAgICAgIG5ld0RhdGEuc2V0KHRoaXMuby5kYXRhKTtcbiAgICAgICAgICAgIHRoaXMuby5kYXRhID0gbmV3RGF0YTtcbiAgICAgICAgICAgIHRoaXMuYWxsb2NTaXplID0gbmV3QWxsb2NTaXplO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMgd3JpdGUoYnVmZiwgcG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPXRoaXM7XG4gICAgICAgIGlmICh0eXBlb2YgcG9zID09IFwidW5kZWZpbmVkXCIpIHBvcyA9IHNlbGYucG9zO1xuICAgICAgICBpZiAodGhpcy5yZWFkT25seSkgdGhyb3cgbmV3IEVycm9yKFwiV3JpdGluZyBhIHJlYWQgb25seSBmaWxlXCIpO1xuXG4gICAgICAgIHRoaXMuX3Jlc2l6ZUlmTmVlZGVkKHBvcyArIGJ1ZmYuYnl0ZUxlbmd0aCk7XG5cbiAgICAgICAgdGhpcy5vLmRhdGEuc2V0KGJ1ZmYuc2xpY2UoKSwgcG9zKTtcblxuICAgICAgICBpZiAocG9zICsgYnVmZi5ieXRlTGVuZ3RoID4gdGhpcy50b3RhbFNpemUpIHRoaXMudG90YWxTaXplID0gcG9zICsgYnVmZi5ieXRlTGVuZ3RoO1xuXG4gICAgICAgIHRoaXMucG9zID0gcG9zICsgYnVmZi5ieXRlTGVuZ3RoO1xuICAgIH1cblxuICAgIGFzeW5jIHJlYWRUb0J1ZmZlcihidWZmRGVzdCwgb2Zmc2V0LCBsZW4sIHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgaWYgKHR5cGVvZiBwb3MgPT0gXCJ1bmRlZmluZWRcIikgcG9zID0gc2VsZi5wb3M7XG4gICAgICAgIGlmICh0aGlzLnJlYWRPbmx5KSB7XG4gICAgICAgICAgICBpZiAocG9zICsgbGVuID4gdGhpcy50b3RhbFNpemUpIHRocm93IG5ldyBFcnJvcihcIlJlYWRpbmcgb3V0IG9mIGJvdW5kc1wiKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9yZXNpemVJZk5lZWRlZChwb3MgKyBsZW4pO1xuXG4gICAgICAgIGNvbnN0IGJ1ZmZTcmMgPSBuZXcgVWludDhBcnJheSh0aGlzLm8uZGF0YS5idWZmZXIsIHRoaXMuby5kYXRhLmJ5dGVPZmZzZXQgKyBwb3MsIGxlbik7XG5cbiAgICAgICAgYnVmZkRlc3Quc2V0KGJ1ZmZTcmMsIG9mZnNldCk7XG5cbiAgICAgICAgdGhpcy5wb3MgPSBwb3MgKyBsZW47XG4gICAgfVxuXG4gICAgYXN5bmMgcmVhZChsZW4sIHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcblxuICAgICAgICBjb25zdCBidWZmID0gbmV3IFVpbnQ4QXJyYXkobGVuKTtcbiAgICAgICAgYXdhaXQgc2VsZi5yZWFkVG9CdWZmZXIoYnVmZiwgMCwgbGVuLCBwb3MpO1xuXG4gICAgICAgIHJldHVybiBidWZmO1xuICAgIH1cblxuICAgIGNsb3NlKCkge1xuICAgICAgICBpZiAodGhpcy5vLmRhdGEuYnl0ZUxlbmd0aCAhPSB0aGlzLnRvdGFsU2l6ZSkge1xuICAgICAgICAgICAgdGhpcy5vLmRhdGEgPSB0aGlzLm8uZGF0YS5zbGljZSgwLCB0aGlzLnRvdGFsU2l6ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhc3luYyBkaXNjYXJkKCkge1xuICAgIH1cblxuXG4gICAgYXN5bmMgd3JpdGVVTEUzMih2LCBwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICAgICAgdG1wQnVmZjMydi5zZXRVaW50MzIoMCwgdiwgdHJ1ZSk7XG5cbiAgICAgICAgYXdhaXQgc2VsZi53cml0ZSh0bXBCdWZmMzIsIHBvcyk7XG4gICAgfVxuXG4gICAgYXN5bmMgd3JpdGVVQkUzMih2LCBwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICAgICAgdG1wQnVmZjMydi5zZXRVaW50MzIoMCwgdiwgZmFsc2UpO1xuXG4gICAgICAgIGF3YWl0IHNlbGYud3JpdGUodG1wQnVmZjMyLCBwb3MpO1xuICAgIH1cblxuXG4gICAgYXN5bmMgd3JpdGVVTEU2NCh2LCBwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICAgICAgdG1wQnVmZjY0di5zZXRVaW50MzIoMCwgdiAmIDB4RkZGRkZGRkYsIHRydWUpO1xuICAgICAgICB0bXBCdWZmNjR2LnNldFVpbnQzMig0LCBNYXRoLmZsb29yKHYgLyAweDEwMDAwMDAwMCkgLCB0cnVlKTtcblxuICAgICAgICBhd2FpdCBzZWxmLndyaXRlKHRtcEJ1ZmY2NCwgcG9zKTtcbiAgICB9XG5cblxuICAgIGFzeW5jIHJlYWRVTEUzMihwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGNvbnN0IGIgPSBhd2FpdCBzZWxmLnJlYWQoNCwgcG9zKTtcblxuICAgICAgICBjb25zdCB2aWV3ID0gbmV3IFVpbnQzMkFycmF5KGIuYnVmZmVyKTtcblxuICAgICAgICByZXR1cm4gdmlld1swXTtcbiAgICB9XG5cbiAgICBhc3luYyByZWFkVUJFMzIocG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBjb25zdCBiID0gYXdhaXQgc2VsZi5yZWFkKDQsIHBvcyk7XG5cbiAgICAgICAgY29uc3QgdmlldyA9IG5ldyBEYXRhVmlldyhiLmJ1ZmZlcik7XG5cbiAgICAgICAgcmV0dXJuIHZpZXcuZ2V0VWludDMyKDAsIGZhbHNlKTtcbiAgICB9XG5cbiAgICBhc3luYyByZWFkVUxFNjQocG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBjb25zdCBiID0gYXdhaXQgc2VsZi5yZWFkKDgsIHBvcyk7XG5cbiAgICAgICAgY29uc3QgdmlldyA9IG5ldyBVaW50MzJBcnJheShiLmJ1ZmZlcik7XG5cbiAgICAgICAgcmV0dXJuIHZpZXdbMV0gKiAweDEwMDAwMDAwMCArIHZpZXdbMF07XG4gICAgfVxuXG4gICAgYXN5bmMgcmVhZFN0cmluZyhwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICAgICAgbGV0IGN1cnJlbnRQb3NpdGlvbiA9IHR5cGVvZiBwb3MgPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYucG9zIDogcG9zO1xuXG4gICAgICAgIGlmIChjdXJyZW50UG9zaXRpb24gPiB0aGlzLnRvdGFsU2l6ZSkge1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE9ubHkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJSZWFkaW5nIG91dCBvZiBib3VuZHNcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9yZXNpemVJZk5lZWRlZChwb3MpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGRhdGFBcnJheSA9IG5ldyBVaW50OEFycmF5KFxuICAgICAgICAgICAgc2VsZi5vLmRhdGEuYnVmZmVyLFxuICAgICAgICAgICAgY3VycmVudFBvc2l0aW9uLFxuICAgICAgICAgICAgdGhpcy50b3RhbFNpemUgLSBjdXJyZW50UG9zaXRpb25cbiAgICAgICAgKTtcblxuICAgICAgICBsZXQgaW5kZXhFbmRPZlN0cmluZyA9IGRhdGFBcnJheS5maW5kSW5kZXgoZWxlbWVudCA9PiBlbGVtZW50ID09PSAwKTtcbiAgICAgICAgbGV0IGVuZE9mU3RyaW5nRm91bmQgPSBpbmRleEVuZE9mU3RyaW5nICE9PSAtMTtcblxuICAgICAgICBsZXQgc3RyID0gXCJcIjtcbiAgICAgICAgaWYgKGVuZE9mU3RyaW5nRm91bmQpIHtcbiAgICAgICAgICAgIHN0ciA9IG5ldyBUZXh0RGVjb2RlcigpLmRlY29kZShkYXRhQXJyYXkuc2xpY2UoMCwgaW5kZXhFbmRPZlN0cmluZykpO1xuICAgICAgICAgICAgc2VsZi5wb3MgPSBjdXJyZW50UG9zaXRpb24gKyBpbmRleEVuZE9mU3RyaW5nICsgMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNlbGYucG9zID0gY3VycmVudFBvc2l0aW9uO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdHI7XG4gICAgfVxufVxuIiwiY29uc3QgUEFHRV9TSVpFID0gMTw8MjI7XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVOZXcobykge1xuICAgIGNvbnN0IGluaXRpYWxTaXplID0gby5pbml0aWFsU2l6ZSB8fCAwO1xuICAgIGNvbnN0IGZkID0gbmV3IEJpZ01lbUZpbGUoKTtcbiAgICBmZC5vID0gbztcbiAgICBjb25zdCBuUGFnZXMgPSBpbml0aWFsU2l6ZSA/IE1hdGguZmxvb3IoKGluaXRpYWxTaXplIC0gMSkgLyBQQUdFX1NJWkUpKzEgOiAwO1xuICAgIGZkLm8uZGF0YSA9IFtdO1xuICAgIGZvciAobGV0IGk9MDsgaTxuUGFnZXMtMTsgaSsrKSB7XG4gICAgICAgIGZkLm8uZGF0YS5wdXNoKCBuZXcgVWludDhBcnJheShQQUdFX1NJWkUpKTtcbiAgICB9XG4gICAgaWYgKG5QYWdlcykgZmQuby5kYXRhLnB1c2goIG5ldyBVaW50OEFycmF5KGluaXRpYWxTaXplIC0gUEFHRV9TSVpFKihuUGFnZXMtMSkpKTtcbiAgICBmZC50b3RhbFNpemUgPSAwO1xuICAgIGZkLnJlYWRPbmx5ID0gZmFsc2U7XG4gICAgZmQucG9zID0gMDtcbiAgICByZXR1cm4gZmQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWFkRXhpc3Rpbmcobykge1xuICAgIGNvbnN0IGZkID0gbmV3IEJpZ01lbUZpbGUoKTtcbiAgICBmZC5vID0gbztcbiAgICBmZC50b3RhbFNpemUgPSAoby5kYXRhLmxlbmd0aC0xKSogUEFHRV9TSVpFICsgby5kYXRhW28uZGF0YS5sZW5ndGgtMV0uYnl0ZUxlbmd0aDtcbiAgICBmZC5yZWFkT25seSA9IHRydWU7XG4gICAgZmQucG9zID0gMDtcbiAgICByZXR1cm4gZmQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWFkV3JpdGVFeGlzdGluZyhvKSB7XG4gICAgY29uc3QgZmQgPSBuZXcgQmlnTWVtRmlsZSgpO1xuICAgIGZkLm8gPSBvO1xuICAgIGZkLnRvdGFsU2l6ZSA9IChvLmRhdGEubGVuZ3RoLTEpKiBQQUdFX1NJWkUgKyBvLmRhdGFbby5kYXRhLmxlbmd0aC0xXS5ieXRlTGVuZ3RoO1xuICAgIGZkLnJlYWRPbmx5ID0gZmFsc2U7XG4gICAgZmQucG9zID0gMDtcbiAgICByZXR1cm4gZmQ7XG59XG5cbmNvbnN0IHRtcEJ1ZmYzMiA9IG5ldyBVaW50OEFycmF5KDQpO1xuY29uc3QgdG1wQnVmZjMydiA9IG5ldyBEYXRhVmlldyh0bXBCdWZmMzIuYnVmZmVyKTtcbmNvbnN0IHRtcEJ1ZmY2NCA9IG5ldyBVaW50OEFycmF5KDgpO1xuY29uc3QgdG1wQnVmZjY0diA9IG5ldyBEYXRhVmlldyh0bXBCdWZmNjQuYnVmZmVyKTtcblxuY2xhc3MgQmlnTWVtRmlsZSB7XG5cbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5wYWdlU2l6ZSA9IDEgPDwgMTQ7ICAvLyBmb3IgY29tcGF0aWJpbGl0eVxuICAgIH1cblxuICAgIF9yZXNpemVJZk5lZWRlZChuZXdMZW4pIHtcblxuICAgICAgICBpZiAobmV3TGVuIDw9IHRoaXMudG90YWxTaXplKSByZXR1cm47XG5cbiAgICAgICAgaWYgKHRoaXMucmVhZE9ubHkpIHRocm93IG5ldyBFcnJvcihcIlJlYWRpbmcgb3V0IG9mIGZpbGUgYm91bmRzXCIpO1xuXG4gICAgICAgIGNvbnN0IG5QYWdlcyA9IE1hdGguZmxvb3IoKG5ld0xlbiAtIDEpIC8gUEFHRV9TSVpFKSsxO1xuICAgICAgICBmb3IgKGxldCBpPSBNYXRoLm1heCh0aGlzLm8uZGF0YS5sZW5ndGgtMSwgMCk7IGk8blBhZ2VzOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IG5ld1NpemUgPSBpPG5QYWdlcy0xID8gUEFHRV9TSVpFIDogbmV3TGVuIC0gKG5QYWdlcy0xKSpQQUdFX1NJWkU7XG4gICAgICAgICAgICBjb25zdCBwID0gbmV3IFVpbnQ4QXJyYXkobmV3U2l6ZSk7XG4gICAgICAgICAgICBpZiAoaSA9PSB0aGlzLm8uZGF0YS5sZW5ndGgtMSkgcC5zZXQodGhpcy5vLmRhdGFbaV0pO1xuICAgICAgICAgICAgdGhpcy5vLmRhdGFbaV0gPSBwO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudG90YWxTaXplID0gbmV3TGVuO1xuICAgIH1cblxuICAgIGFzeW5jIHdyaXRlKGJ1ZmYsIHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID10aGlzO1xuICAgICAgICBpZiAodHlwZW9mIHBvcyA9PSBcInVuZGVmaW5lZFwiKSBwb3MgPSBzZWxmLnBvcztcbiAgICAgICAgaWYgKHRoaXMucmVhZE9ubHkpIHRocm93IG5ldyBFcnJvcihcIldyaXRpbmcgYSByZWFkIG9ubHkgZmlsZVwiKTtcblxuICAgICAgICB0aGlzLl9yZXNpemVJZk5lZWRlZChwb3MgKyBidWZmLmJ5dGVMZW5ndGgpO1xuXG4gICAgICAgIGNvbnN0IGZpcnN0UGFnZSA9IE1hdGguZmxvb3IocG9zIC8gUEFHRV9TSVpFKTtcblxuICAgICAgICBsZXQgcCA9IGZpcnN0UGFnZTtcbiAgICAgICAgbGV0IG8gPSBwb3MgJSBQQUdFX1NJWkU7XG4gICAgICAgIGxldCByID0gYnVmZi5ieXRlTGVuZ3RoO1xuICAgICAgICB3aGlsZSAocj4wKSB7XG4gICAgICAgICAgICBjb25zdCBsID0gKG8rciA+IFBBR0VfU0laRSkgPyAoUEFHRV9TSVpFIC1vKSA6IHI7XG4gICAgICAgICAgICBjb25zdCBzcmNWaWV3ID0gYnVmZi5zbGljZShidWZmLmJ5dGVMZW5ndGggLSByLCBidWZmLmJ5dGVMZW5ndGggLSByICsgbCk7XG4gICAgICAgICAgICBjb25zdCBkc3RWaWV3ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5vLmRhdGFbcF0uYnVmZmVyLCBvLCBsKTtcbiAgICAgICAgICAgIGRzdFZpZXcuc2V0KHNyY1ZpZXcpO1xuICAgICAgICAgICAgciA9IHItbDtcbiAgICAgICAgICAgIHAgKys7XG4gICAgICAgICAgICBvID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucG9zID0gcG9zICsgYnVmZi5ieXRlTGVuZ3RoO1xuICAgIH1cblxuICAgIGFzeW5jIHJlYWRUb0J1ZmZlcihidWZmRHN0LCBvZmZzZXQsIGxlbiwgcG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBpZiAodHlwZW9mIHBvcyA9PSBcInVuZGVmaW5lZFwiKSBwb3MgPSBzZWxmLnBvcztcbiAgICAgICAgaWYgKHRoaXMucmVhZE9ubHkpIHtcbiAgICAgICAgICAgIGlmIChwb3MgKyBsZW4gPiB0aGlzLnRvdGFsU2l6ZSkgdGhyb3cgbmV3IEVycm9yKFwiUmVhZGluZyBvdXQgb2YgYm91bmRzXCIpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3Jlc2l6ZUlmTmVlZGVkKHBvcyArIGxlbik7XG5cbiAgICAgICAgY29uc3QgZmlyc3RQYWdlID0gTWF0aC5mbG9vcihwb3MgLyBQQUdFX1NJWkUpO1xuXG4gICAgICAgIGxldCBwID0gZmlyc3RQYWdlO1xuICAgICAgICBsZXQgbyA9IHBvcyAlIFBBR0VfU0laRTtcbiAgICAgICAgLy8gUmVtYWluaW5nIGJ5dGVzIHRvIHJlYWRcbiAgICAgICAgbGV0IHIgPSBsZW47XG4gICAgICAgIHdoaWxlIChyPjApIHtcbiAgICAgICAgICAgIC8vIGJ5dGVzIHRvIGNvcHkgZnJvbSB0aGlzIHBhZ2VcbiAgICAgICAgICAgIGNvbnN0IGwgPSAobytyID4gUEFHRV9TSVpFKSA/IChQQUdFX1NJWkUgLW8pIDogcjtcbiAgICAgICAgICAgIGNvbnN0IHNyY1ZpZXcgPSBuZXcgVWludDhBcnJheShzZWxmLm8uZGF0YVtwXS5idWZmZXIsIG8sIGwpO1xuICAgICAgICAgICAgYnVmZkRzdC5zZXQoc3JjVmlldywgb2Zmc2V0K2xlbi1yKTtcbiAgICAgICAgICAgIHIgPSByLWw7XG4gICAgICAgICAgICBwICsrO1xuICAgICAgICAgICAgbyA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnBvcyA9IHBvcyArIGxlbjtcbiAgICB9XG5cbiAgICBhc3luYyByZWFkKGxlbiwgcG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBjb25zdCBidWZmID0gbmV3IFVpbnQ4QXJyYXkobGVuKTtcblxuICAgICAgICBhd2FpdCBzZWxmLnJlYWRUb0J1ZmZlcihidWZmLCAwLCBsZW4sIHBvcyk7XG5cbiAgICAgICAgcmV0dXJuIGJ1ZmY7XG4gICAgfVxuXG4gICAgY2xvc2UoKSB7XG4gICAgfVxuXG4gICAgYXN5bmMgZGlzY2FyZCgpIHtcbiAgICB9XG5cblxuICAgIGFzeW5jIHdyaXRlVUxFMzIodiwgcG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gICAgICAgIHRtcEJ1ZmYzMnYuc2V0VWludDMyKDAsIHYsIHRydWUpO1xuXG4gICAgICAgIGF3YWl0IHNlbGYud3JpdGUodG1wQnVmZjMyLCBwb3MpO1xuICAgIH1cblxuICAgIGFzeW5jIHdyaXRlVUJFMzIodiwgcG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gICAgICAgIHRtcEJ1ZmYzMnYuc2V0VWludDMyKDAsIHYsIGZhbHNlKTtcblxuICAgICAgICBhd2FpdCBzZWxmLndyaXRlKHRtcEJ1ZmYzMiwgcG9zKTtcbiAgICB9XG5cblxuICAgIGFzeW5jIHdyaXRlVUxFNjQodiwgcG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gICAgICAgIHRtcEJ1ZmY2NHYuc2V0VWludDMyKDAsIHYgJiAweEZGRkZGRkZGLCB0cnVlKTtcbiAgICAgICAgdG1wQnVmZjY0di5zZXRVaW50MzIoNCwgTWF0aC5mbG9vcih2IC8gMHgxMDAwMDAwMDApICwgdHJ1ZSk7XG5cbiAgICAgICAgYXdhaXQgc2VsZi53cml0ZSh0bXBCdWZmNjQsIHBvcyk7XG4gICAgfVxuXG5cbiAgICBhc3luYyByZWFkVUxFMzIocG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBjb25zdCBiID0gYXdhaXQgc2VsZi5yZWFkKDQsIHBvcyk7XG5cbiAgICAgICAgY29uc3QgdmlldyA9IG5ldyBVaW50MzJBcnJheShiLmJ1ZmZlcik7XG5cbiAgICAgICAgcmV0dXJuIHZpZXdbMF07XG4gICAgfVxuXG4gICAgYXN5bmMgcmVhZFVCRTMyKHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgY29uc3QgYiA9IGF3YWl0IHNlbGYucmVhZCg0LCBwb3MpO1xuXG4gICAgICAgIGNvbnN0IHZpZXcgPSBuZXcgRGF0YVZpZXcoYi5idWZmZXIpO1xuXG4gICAgICAgIHJldHVybiB2aWV3LmdldFVpbnQzMigwLCBmYWxzZSk7XG4gICAgfVxuXG4gICAgYXN5bmMgcmVhZFVMRTY0KHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgY29uc3QgYiA9IGF3YWl0IHNlbGYucmVhZCg4LCBwb3MpO1xuXG4gICAgICAgIGNvbnN0IHZpZXcgPSBuZXcgVWludDMyQXJyYXkoYi5idWZmZXIpO1xuXG4gICAgICAgIHJldHVybiB2aWV3WzFdICogMHgxMDAwMDAwMDAgKyB2aWV3WzBdO1xuICAgIH1cblxuICAgIGFzeW5jIHJlYWRTdHJpbmcocG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBjb25zdCBmaXhlZFNpemUgPSAyMDQ4O1xuXG4gICAgICAgIGxldCBjdXJyZW50UG9zaXRpb24gPSB0eXBlb2YgcG9zID09IFwidW5kZWZpbmVkXCIgPyBzZWxmLnBvcyA6IHBvcztcblxuICAgICAgICBpZiAoY3VycmVudFBvc2l0aW9uID4gdGhpcy50b3RhbFNpemUpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlYWRPbmx5KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUmVhZGluZyBvdXQgb2YgYm91bmRzXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fcmVzaXplSWZOZWVkZWQocG9zKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBlbmRPZlN0cmluZ0ZvdW5kID0gZmFsc2U7XG4gICAgICAgIGxldCBzdHIgPSBcIlwiO1xuXG4gICAgICAgIHdoaWxlICghZW5kT2ZTdHJpbmdGb3VuZCkge1xuICAgICAgICAgICAgbGV0IGN1cnJlbnRQYWdlID0gTWF0aC5mbG9vcihjdXJyZW50UG9zaXRpb24gLyBQQUdFX1NJWkUpO1xuICAgICAgICAgICAgbGV0IG9mZnNldE9uUGFnZSA9IGN1cnJlbnRQb3NpdGlvbiAlIFBBR0VfU0laRTtcblxuICAgICAgICAgICAgaWYgKHNlbGYuby5kYXRhW2N1cnJlbnRQYWdlXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRVJST1JcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCByZWFkTGVuZ3RoID0gTWF0aC5taW4oZml4ZWRTaXplLCBzZWxmLm8uZGF0YVtjdXJyZW50UGFnZV0ubGVuZ3RoIC0gb2Zmc2V0T25QYWdlKTtcbiAgICAgICAgICAgIGNvbnN0IGRhdGFBcnJheSA9IG5ldyBVaW50OEFycmF5KHNlbGYuby5kYXRhW2N1cnJlbnRQYWdlXS5idWZmZXIsIG9mZnNldE9uUGFnZSwgcmVhZExlbmd0aCk7XG5cbiAgICAgICAgICAgIGxldCBpbmRleEVuZE9mU3RyaW5nID0gZGF0YUFycmF5LmZpbmRJbmRleChlbGVtZW50ID0+IGVsZW1lbnQgPT09IDApO1xuICAgICAgICAgICAgZW5kT2ZTdHJpbmdGb3VuZCA9IGluZGV4RW5kT2ZTdHJpbmcgIT09IC0xO1xuXG4gICAgICAgICAgICBpZiAoZW5kT2ZTdHJpbmdGb3VuZCkge1xuICAgICAgICAgICAgICAgIHN0ciArPSBuZXcgVGV4dERlY29kZXIoKS5kZWNvZGUoZGF0YUFycmF5LnNsaWNlKDAsIGluZGV4RW5kT2ZTdHJpbmcpKTtcbiAgICAgICAgICAgICAgICBzZWxmLnBvcyA9IGN1cnJlbnRQYWdlICogUEFHRV9TSVpFICsgb2Zmc2V0T25QYWdlICsgaW5kZXhFbmRPZlN0cmluZyArIDE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN0ciArPSBuZXcgVGV4dERlY29kZXIoKS5kZWNvZGUoZGF0YUFycmF5KTtcbiAgICAgICAgICAgICAgICBzZWxmLnBvcyA9IGN1cnJlbnRQYWdlICogUEFHRV9TSVpFICsgb2Zmc2V0T25QYWdlICsgZGF0YUFycmF5Lmxlbmd0aDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY3VycmVudFBvc2l0aW9uID0gc2VsZi5wb3M7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0cjtcbiAgICB9XG59XG4iLCJpbXBvcnQgeyBvcGVuIH0gZnJvbSBcIi4vb3NmaWxlLmpzXCI7XG4vL2ltcG9ydCB7IGRpcmVjdE9wZW4gYXMgb3BlbiB9IGZyb20gXCIuL2RpcmVjdGZpbGUuanNcIjtcbmltcG9ydCAqIGFzIG1lbUZpbGUgZnJvbSBcIi4vbWVtZmlsZS5qc1wiO1xuaW1wb3J0ICogYXMgYmlnTWVtRmlsZSBmcm9tIFwiLi9iaWdtZW1maWxlLmpzXCI7XG5pbXBvcnQgeyBjb25zdGFudHMgfSBmcm9tIFwibm9kZTpmc1wiO1xuXG5jb25zdCB7IE9fVFJVTkMsIE9fQ1JFQVQsIE9fUkRXUiwgT19FWENMLCBPX1JET05MWSB9ID0gY29uc3RhbnRzO1xuXG5jb25zdCBERUZBVUxUX0NBQ0hFX1NJWkUgPSAoMSA8PCAxNik7XG5jb25zdCBERUZBVUxUX1BBR0VfU0laRSA9ICgxIDw8IDEzKTtcblxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlT3ZlcnJpZGUobywgYiwgYykge1xuICAgIGlmICh0eXBlb2YgbyA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICBvID0ge1xuICAgICAgICAgICAgdHlwZTogXCJmaWxlXCIsXG4gICAgICAgICAgICBmaWxlTmFtZTogbyxcbiAgICAgICAgICAgIGNhY2hlU2l6ZTogYiB8fCBERUZBVUxUX0NBQ0hFX1NJWkUsXG4gICAgICAgICAgICBwYWdlU2l6ZTogYyB8fCBERUZBVUxUX1BBR0VfU0laRVxuICAgICAgICB9O1xuICAgIH1cbiAgICBpZiAoby50eXBlID09IFwiZmlsZVwiKSB7XG4gICAgICAgIHJldHVybiBhd2FpdCBvcGVuKG8uZmlsZU5hbWUsIE9fVFJVTkMgfCBPX0NSRUFUIHwgT19SRFdSLCBvLmNhY2hlU2l6ZSwgby5wYWdlU2l6ZSk7XG4gICAgfSBlbHNlIGlmIChvLnR5cGUgPT0gXCJtZW1cIikge1xuICAgICAgICByZXR1cm4gbWVtRmlsZS5jcmVhdGVOZXcobyk7XG4gICAgfSBlbHNlIGlmIChvLnR5cGUgPT0gXCJiaWdNZW1cIikge1xuICAgICAgICByZXR1cm4gYmlnTWVtRmlsZS5jcmVhdGVOZXcobyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBGYXN0RmlsZSB0eXBlOiBcIitvLnR5cGUpO1xuICAgIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZU5vT3ZlcnJpZGUobywgYiwgYykge1xuICAgIGlmICh0eXBlb2YgbyA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICBvID0ge1xuICAgICAgICAgICAgdHlwZTogXCJmaWxlXCIsXG4gICAgICAgICAgICBmaWxlTmFtZTogbyxcbiAgICAgICAgICAgIGNhY2hlU2l6ZTogYiB8fCBERUZBVUxUX0NBQ0hFX1NJWkUsXG4gICAgICAgICAgICBwYWdlU2l6ZTogYyB8fCBERUZBVUxUX1BBR0VfU0laRVxuICAgICAgICB9O1xuICAgIH1cbiAgICBpZiAoby50eXBlID09IFwiZmlsZVwiKSB7XG4gICAgICAgIHJldHVybiBvcGVuKG8uZmlsZU5hbWUsIE9fVFJVTkMgfCBPX0NSRUFUIHwgT19SRFdSIHwgT19FWENMLCBvLmNhY2hlU2l6ZSwgby5wYWdlU2l6ZSk7XG4gICAgfSBlbHNlIGlmIChvLnR5cGUgPT0gXCJtZW1cIikge1xuICAgICAgICByZXR1cm4gbWVtRmlsZS5jcmVhdGVOZXcobyk7XG4gICAgfSBlbHNlIGlmIChvLnR5cGUgPT0gXCJiaWdNZW1cIikge1xuICAgICAgICByZXR1cm4gYmlnTWVtRmlsZS5jcmVhdGVOZXcobyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBGYXN0RmlsZSB0eXBlOiBcIitvLnR5cGUpO1xuICAgIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRFeGlzdGluZyhvLCBiLCBjKSB7XG4gICAgaWYgKG8gaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7XG4gICAgICAgIG8gPSB7XG4gICAgICAgICAgICB0eXBlOiBcIm1lbVwiLFxuICAgICAgICAgICAgZGF0YTogb1xuICAgICAgICB9O1xuICAgIH1cbiAgICBpZiAocHJvY2Vzcy5icm93c2VyKSB7XG4gICAgICAgIGlmICh0eXBlb2YgbyA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgY29uc3QgYnVmZiA9IGF3YWl0IGZldGNoKG8pLnRoZW4oIGZ1bmN0aW9uKHJlcykge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXMuYXJyYXlCdWZmZXIoKTtcbiAgICAgICAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKGFiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGFiKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgbyA9IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBcIm1lbVwiLFxuICAgICAgICAgICAgICAgIGRhdGE6IGJ1ZmZcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBpZiAodHlwZW9mIG8gPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgIG8gPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJmaWxlXCIsXG4gICAgICAgICAgICAgICAgZmlsZU5hbWU6IG8sXG4gICAgICAgICAgICAgICAgY2FjaGVTaXplOiBiIHx8IERFRkFVTFRfQ0FDSEVfU0laRSxcbiAgICAgICAgICAgICAgICBwYWdlU2l6ZTogYyB8fCBERUZBVUxUX1BBR0VfU0laRVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoby50eXBlID09IFwiZmlsZVwiKSB7XG4gICAgICAgIHJldHVybiBhd2FpdCBvcGVuKG8uZmlsZU5hbWUsIE9fUkRPTkxZLCBvLmNhY2hlU2l6ZSwgby5wYWdlU2l6ZSk7XG4gICAgfSBlbHNlIGlmIChvLnR5cGUgPT0gXCJtZW1cIikge1xuICAgICAgICByZXR1cm4gYXdhaXQgbWVtRmlsZS5yZWFkRXhpc3Rpbmcobyk7XG4gICAgfSBlbHNlIGlmIChvLnR5cGUgPT0gXCJiaWdNZW1cIikge1xuICAgICAgICByZXR1cm4gYXdhaXQgYmlnTWVtRmlsZS5yZWFkRXhpc3Rpbmcobyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBGYXN0RmlsZSB0eXBlOiBcIitvLnR5cGUpO1xuICAgIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlYWRXcml0ZUV4aXN0aW5nKG8sIGIsIGMpIHtcbiAgICBpZiAodHlwZW9mIG8gPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgbyA9IHtcbiAgICAgICAgICAgIHR5cGU6IFwiZmlsZVwiLFxuICAgICAgICAgICAgZmlsZU5hbWU6IG8sXG4gICAgICAgICAgICBjYWNoZVNpemU6IGIgfHwgREVGQVVMVF9DQUNIRV9TSVpFLFxuICAgICAgICAgICAgcGFnZVNpemU6IGMgfHwgREVGQVVMVF9QQUdFX1NJWkVcbiAgICAgICAgfTtcbiAgICB9XG4gICAgaWYgKG8udHlwZSA9PSBcImZpbGVcIikge1xuICAgICAgICByZXR1cm4gb3BlbihvLmZpbGVOYW1lLCBPX0NSRUFUIHwgT19SRFdSLCBvLmNhY2hlU2l6ZSwgby5wYWdlU2l6ZSk7XG4gICAgfSBlbHNlIGlmIChvLnR5cGUgPT0gXCJtZW1cIikge1xuICAgICAgICByZXR1cm4gbWVtRmlsZS5yZWFkV3JpdGVFeGlzdGluZyhvKTtcbiAgICB9IGVsc2UgaWYgKG8udHlwZSA9PSBcImJpZ01lbVwiKSB7XG4gICAgICAgIHJldHVybiBiaWdNZW1GaWxlLnJlYWRXcml0ZUV4aXN0aW5nKG8pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgRmFzdEZpbGUgdHlwZTogXCIrby50eXBlKTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWFkV3JpdGVFeGlzdGluZ09yQ3JlYXRlKG8sIGIsIGMpIHtcbiAgICBpZiAodHlwZW9mIG8gPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgbyA9IHtcbiAgICAgICAgICAgIHR5cGU6IFwiZmlsZVwiLFxuICAgICAgICAgICAgZmlsZU5hbWU6IG8sXG4gICAgICAgICAgICBjYWNoZVNpemU6IGIgfHwgREVGQVVMVF9DQUNIRV9TSVpFLFxuICAgICAgICAgICAgcGFnZVNpemU6IGMgfHwgREVGQVVMVF9QQUdFX1NJWkVcbiAgICAgICAgfTtcbiAgICB9XG4gICAgaWYgKG8udHlwZSA9PSBcImZpbGVcIikge1xuICAgICAgICByZXR1cm4gb3BlbihvLmZpbGVOYW1lLCBPX0NSRUFUIHwgT19SRFdSIHwgT19FWENMLCBvLmNhY2hlU2l6ZSk7XG4gICAgfSBlbHNlIGlmIChvLnR5cGUgPT0gXCJtZW1cIikge1xuICAgICAgICByZXR1cm4gbWVtRmlsZS5yZWFkV3JpdGVFeGlzdGluZyhvKTtcbiAgICB9IGVsc2UgaWYgKG8udHlwZSA9PSBcImJpZ01lbVwiKSB7XG4gICAgICAgIHJldHVybiBiaWdNZW1GaWxlLnJlYWRXcml0ZUV4aXN0aW5nKG8pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgRmFzdEZpbGUgdHlwZTogXCIrby50eXBlKTtcbiAgICB9XG59XG4iLCJcbmltcG9ydCAgeyBTY2FsYXIsIEJpZ0J1ZmZlciB9IGZyb20gXCJmZmphdmFzY3JpcHRcIjtcbmltcG9ydCAqIGFzIGZhc3RGaWxlIGZyb20gXCJmYXN0ZmlsZVwiO1xuXG5jb25zdCBNQVhfQlVGRkVSX1NJWkUgPSAoIHR5cGVvZiBCdWZmZXIgIT09IFwidW5kZWZpbmVkXCIgJiYgQnVmZmVyLmNvbnN0YW50cyAmJiBCdWZmZXIuY29uc3RhbnRzLk1BWF9MRU5HVEggKSA/IEJ1ZmZlci5jb25zdGFudHMuTUFYX0xFTkdUSCA6ICgxIDw8IDMwKTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRCaW5GaWxlKGZpbGVOYW1lLCB0eXBlLCBtYXhWZXJzaW9uLCBjYWNoZVNpemUsIHBhZ2VTaXplKSB7XG5cbiAgICBjb25zdCBmZCA9IGF3YWl0IGZhc3RGaWxlLnJlYWRFeGlzdGluZyhmaWxlTmFtZSwgY2FjaGVTaXplLCBwYWdlU2l6ZSk7XG5cbiAgICBjb25zdCBiID0gYXdhaXQgZmQucmVhZCg0KTtcbiAgICBsZXQgcmVhZGVkVHlwZSA9IFwiXCI7XG4gICAgZm9yIChsZXQgaT0wOyBpPDQ7IGkrKykgcmVhZGVkVHlwZSArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJbaV0pO1xuXG4gICAgaWYgKHJlYWRlZFR5cGUgIT0gdHlwZSkgdGhyb3cgbmV3IEVycm9yKGZpbGVOYW1lICsgXCI6IEludmFsaWQgRmlsZSBmb3JtYXRcIik7XG5cbiAgICBsZXQgdiA9IGF3YWl0IGZkLnJlYWRVTEUzMigpO1xuXG4gICAgaWYgKHY+bWF4VmVyc2lvbikgdGhyb3cgbmV3IEVycm9yKFwiVmVyc2lvbiBub3Qgc3VwcG9ydGVkXCIpO1xuXG4gICAgY29uc3QgblNlY3Rpb25zID0gYXdhaXQgZmQucmVhZFVMRTMyKCk7XG5cbiAgICAvLyBTY2FuIHNlY3Rpb25zXG4gICAgbGV0IHNlY3Rpb25zID0gW107XG4gICAgZm9yIChsZXQgaT0wOyBpPG5TZWN0aW9uczsgaSsrKSB7XG4gICAgICAgIGxldCBodCA9IGF3YWl0IGZkLnJlYWRVTEUzMigpO1xuICAgICAgICBsZXQgaGwgPSBhd2FpdCBmZC5yZWFkVUxFNjQoKTtcbiAgICAgICAgaWYgKHR5cGVvZiBzZWN0aW9uc1todF0gPT0gXCJ1bmRlZmluZWRcIikgc2VjdGlvbnNbaHRdID0gW107XG4gICAgICAgIHNlY3Rpb25zW2h0XS5wdXNoKHtcbiAgICAgICAgICAgIHA6IGZkLnBvcyxcbiAgICAgICAgICAgIHNpemU6IGhsXG4gICAgICAgIH0pO1xuICAgICAgICBmZC5wb3MgKz0gaGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtmZCwgc2VjdGlvbnN9O1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlQmluRmlsZShmaWxlTmFtZSwgdHlwZSwgdmVyc2lvbiwgblNlY3Rpb25zLCBjYWNoZVNpemUsIHBhZ2VTaXplKSB7XG5cbiAgICBjb25zdCBmZCA9IGF3YWl0IGZhc3RGaWxlLmNyZWF0ZU92ZXJyaWRlKGZpbGVOYW1lLCBjYWNoZVNpemUsIHBhZ2VTaXplKTtcblxuICAgIGNvbnN0IGJ1ZmYgPSBuZXcgVWludDhBcnJheSg0KTtcbiAgICBmb3IgKGxldCBpPTA7IGk8NDsgaSsrKSBidWZmW2ldID0gdHlwZS5jaGFyQ29kZUF0KGkpO1xuICAgIGF3YWl0IGZkLndyaXRlKGJ1ZmYsIDApOyAvLyBNYWdpYyBcInIxY3NcIlxuXG4gICAgYXdhaXQgZmQud3JpdGVVTEUzMih2ZXJzaW9uKTsgLy8gVmVyc2lvblxuICAgIGF3YWl0IGZkLndyaXRlVUxFMzIoblNlY3Rpb25zKTsgLy8gTnVtYmVyIG9mIFNlY3Rpb25zXG5cbiAgICByZXR1cm4gZmQ7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdGFydFdyaXRlU2VjdGlvbihmZCwgaWRTZWN0aW9uKSB7XG4gICAgaWYgKHR5cGVvZiBmZC53cml0aW5nU2VjdGlvbiAhPT0gXCJ1bmRlZmluZWRcIikgdGhyb3cgbmV3IEVycm9yKFwiQWxyZWFkeSB3cml0aW5nIGEgc2VjdGlvblwiKTtcbiAgICBhd2FpdCBmZC53cml0ZVVMRTMyKGlkU2VjdGlvbik7IC8vIEhlYWRlciB0eXBlXG4gICAgZmQud3JpdGluZ1NlY3Rpb24gPSB7XG4gICAgICAgIHBTZWN0aW9uU2l6ZTogZmQucG9zXG4gICAgfTtcbiAgICBhd2FpdCBmZC53cml0ZVVMRTY0KDApOyAvLyBUZW1wb3JhbGx5IHNldCB0byAwIGxlbmd0aFxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZW5kV3JpdGVTZWN0aW9uKGZkKSB7XG4gICAgaWYgKHR5cGVvZiBmZC53cml0aW5nU2VjdGlvbiA9PT0gXCJ1bmRlZmluZWRcIikgdGhyb3cgbmV3IEVycm9yKFwiTm90IHdyaXRpbmcgYSBzZWN0aW9uXCIpO1xuXG4gICAgY29uc3Qgc2VjdGlvblNpemUgPSBmZC5wb3MgLSBmZC53cml0aW5nU2VjdGlvbi5wU2VjdGlvblNpemUgLSA4O1xuICAgIGNvbnN0IG9sZFBvcyA9IGZkLnBvcztcbiAgICBmZC5wb3MgPSBmZC53cml0aW5nU2VjdGlvbi5wU2VjdGlvblNpemU7XG4gICAgYXdhaXQgZmQud3JpdGVVTEU2NChzZWN0aW9uU2l6ZSk7XG4gICAgZmQucG9zID0gb2xkUG9zO1xuICAgIGRlbGV0ZSBmZC53cml0aW5nU2VjdGlvbjtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHN0YXJ0UmVhZFVuaXF1ZVNlY3Rpb24oZmQsIHNlY3Rpb25zLCBpZFNlY3Rpb24pIHtcbiAgICBpZiAodHlwZW9mIGZkLnJlYWRpbmdTZWN0aW9uICE9PSBcInVuZGVmaW5lZFwiKSB0aHJvdyBuZXcgRXJyb3IoXCJBbHJlYWR5IHJlYWRpbmcgYSBzZWN0aW9uXCIpO1xuICAgIGlmICghc2VjdGlvbnNbaWRTZWN0aW9uXSkgIHRocm93IG5ldyBFcnJvcihmZC5maWxlTmFtZSArIFwiOiBNaXNzaW5nIHNlY3Rpb24gXCIrIGlkU2VjdGlvbiApO1xuICAgIGlmIChzZWN0aW9uc1tpZFNlY3Rpb25dLmxlbmd0aD4xKSB0aHJvdyBuZXcgRXJyb3IoZmQuZmlsZU5hbWUgK1wiOiBTZWN0aW9uIER1cGxpY2F0ZWQgXCIgK2lkU2VjdGlvbik7XG5cbiAgICBmZC5wb3MgPSBzZWN0aW9uc1tpZFNlY3Rpb25dWzBdLnA7XG5cbiAgICBmZC5yZWFkaW5nU2VjdGlvbiA9IHNlY3Rpb25zW2lkU2VjdGlvbl1bMF07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBlbmRSZWFkU2VjdGlvbihmZCwgbm9DaGVjaykge1xuICAgIGlmICh0eXBlb2YgZmQucmVhZGluZ1NlY3Rpb24gPT09IFwidW5kZWZpbmVkXCIpIHRocm93IG5ldyBFcnJvcihcIk5vdCByZWFkaW5nIGEgc2VjdGlvblwiKTtcbiAgICBpZiAoIW5vQ2hlY2spIHtcbiAgICAgICAgaWYgKGZkLnBvcy1mZC5yZWFkaW5nU2VjdGlvbi5wICE9ICBmZC5yZWFkaW5nU2VjdGlvbi5zaXplKSB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNlY3Rpb24gc2l6ZSByZWFkaW5nXCIpO1xuICAgIH1cbiAgICBkZWxldGUgZmQucmVhZGluZ1NlY3Rpb247XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3cml0ZUJpZ0ludChmZCwgbiwgbjgsIHBvcykge1xuICAgIGNvbnN0IGJ1ZmYgPSBuZXcgVWludDhBcnJheShuOCk7XG4gICAgU2NhbGFyLnRvUnByTEUoYnVmZiwgMCwgbiwgbjgpO1xuICAgIGF3YWl0IGZkLndyaXRlKGJ1ZmYsIHBvcyk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWFkQmlnSW50KGZkLCBuOCwgcG9zKSB7XG4gICAgY29uc3QgYnVmZiA9IGF3YWl0IGZkLnJlYWQobjgsIHBvcyk7XG4gICAgcmV0dXJuIFNjYWxhci5mcm9tUnByTEUoYnVmZiwgMCwgbjgpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY29weVNlY3Rpb24oZmRGcm9tLCBzZWN0aW9ucywgZmRUbywgc2VjdGlvbklkLCBzaXplKSB7XG4gICAgaWYgKHR5cGVvZiBzaXplID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgIHNpemUgPSBzZWN0aW9uc1tzZWN0aW9uSWRdWzBdLnNpemU7XG4gICAgfVxuICAgIGNvbnN0IGNodW5rU2l6ZSA9IGZkRnJvbS5wYWdlU2l6ZTtcbiAgICBhd2FpdCBzdGFydFJlYWRVbmlxdWVTZWN0aW9uKGZkRnJvbSwgc2VjdGlvbnMsIHNlY3Rpb25JZCk7XG4gICAgYXdhaXQgc3RhcnRXcml0ZVNlY3Rpb24oZmRUbywgc2VjdGlvbklkKTtcbiAgICBmb3IgKGxldCBwPTA7IHA8c2l6ZTsgcCs9Y2h1bmtTaXplKSB7XG4gICAgICAgIGNvbnN0IGwgPSBNYXRoLm1pbihzaXplIC1wLCBjaHVua1NpemUpO1xuICAgICAgICBjb25zdCBidWZmID0gYXdhaXQgZmRGcm9tLnJlYWQobCk7XG4gICAgICAgIGF3YWl0IGZkVG8ud3JpdGUoYnVmZik7XG4gICAgfVxuICAgIGF3YWl0IGVuZFdyaXRlU2VjdGlvbihmZFRvKTtcbiAgICBhd2FpdCBlbmRSZWFkU2VjdGlvbihmZEZyb20sIHNpemUgIT0gc2VjdGlvbnNbc2VjdGlvbklkXVswXS5zaXplKTtcblxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZFNlY3Rpb24oZmQsIHNlY3Rpb25zLCBpZFNlY3Rpb24sIG9mZnNldCwgbGVuZ3RoKSB7XG5cbiAgICBvZmZzZXQgPSAodHlwZW9mIG9mZnNldCA9PT0gXCJ1bmRlZmluZWRcIikgPyAwIDogb2Zmc2V0O1xuICAgIGxlbmd0aCA9ICh0eXBlb2YgbGVuZ3RoID09PSBcInVuZGVmaW5lZFwiKSA/IHNlY3Rpb25zW2lkU2VjdGlvbl1bMF0uc2l6ZSAtIG9mZnNldCA6IGxlbmd0aDtcblxuICAgIGNvbnNvbGUudGltZShcInJlYWRTZWN0aW9uIGlkU2VjdGlvbj1cIisgaWRTZWN0aW9uKyBcIiBvZmZzZXQ9XCIrIG9mZnNldCsgXCIgbGVuZ3RoPVwiKyBsZW5ndGgpO1xuXG4gICAgaWYgKG9mZnNldCArIGxlbmd0aCA+IHNlY3Rpb25zW2lkU2VjdGlvbl1bMF0uc2l6ZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJSZWFkaW5nIG91dCBvZiB0aGUgcmFuZ2Ugb2YgdGhlIHNlY3Rpb25cIik7XG4gICAgfVxuXG4gICAgbGV0IGJ1ZmY7XG4gICAgaWYgKGxlbmd0aCA8IE1BWF9CVUZGRVJfU0laRSkge1xuICAgICAgICBidWZmID0gbmV3IFVpbnQ4QXJyYXkobGVuZ3RoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBidWZmID0gbmV3IEJpZ0J1ZmZlcihsZW5ndGgpO1xuICAgIH1cblxuICAgIGF3YWl0IGZkLnJlYWRUb0J1ZmZlcihidWZmLCAwLCBsZW5ndGgsIHNlY3Rpb25zW2lkU2VjdGlvbl1bMF0ucCArIG9mZnNldCk7XG5cbiAgICBjb25zb2xlLnRpbWVFbmQoXCJyZWFkU2VjdGlvbiBpZFNlY3Rpb249XCIrIGlkU2VjdGlvbisgXCIgb2Zmc2V0PVwiKyBvZmZzZXQrIFwiIGxlbmd0aD1cIisgbGVuZ3RoKTtcblxuICAgIHJldHVybiBidWZmO1xufVxuXG5cbi8vIHJlYWRTZWN0aW9uVG9TdHJlYW1cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWFkU2VjdGlvblRvU3RyZWFtKGZkLCBzZWN0aW9ucywgaWRTZWN0aW9uLCBvZmZzZXQsIGxlbmd0aCkge1xuXG4gICAgb2Zmc2V0ID0gKHR5cGVvZiBvZmZzZXQgPT09IFwidW5kZWZpbmVkXCIpID8gMCA6IG9mZnNldDtcbiAgICBsZW5ndGggPSAodHlwZW9mIGxlbmd0aCA9PT0gXCJ1bmRlZmluZWRcIikgPyBzZWN0aW9uc1tpZFNlY3Rpb25dWzBdLnNpemUgLSBvZmZzZXQgOiBsZW5ndGg7XG5cbiAgICBpZiAob2Zmc2V0ICsgbGVuZ3RoID4gc2VjdGlvbnNbaWRTZWN0aW9uXVswXS5zaXplKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlJlYWRpbmcgb3V0IG9mIHRoZSByYW5nZSBvZiB0aGUgc2VjdGlvblwiKTtcbiAgICB9XG5cbiAgICBjb25zdCBjaHVua1NpemUgPSBmZC5wYWdlU2l6ZSAqIDE2O1xuICAgIGxldCByZW1haW5pbmcgPSBsZW5ndGg7XG4gICAgbGV0IHBvcyA9IHNlY3Rpb25zW2lkU2VjdGlvbl1bMF0ucCArIG9mZnNldDtcblxuICAgIC8vbGV0IHN0cmVhbSA9XG4gICAgd2hpbGUgKHJlbWFpbmluZyA+IDApIHtcbiAgICAgICAgY29uc3QgdG9SZWFkID0gTWF0aC5taW4ocmVtYWluaW5nLCBjaHVua1NpemUpO1xuICAgICAgICBjb25zdCBidWZmID0gYXdhaXQgZmQucmVhZCh0b1JlYWQsIHBvcyk7XG4gICAgICAgIGF3YWl0IHdyaXRlU3RyZWFtLndyaXRlKGJ1ZmYpO1xuICAgICAgICBwb3MgKz0gdG9SZWFkO1xuICAgICAgICByZW1haW5pbmcgLT0gdG9SZWFkO1xuICAgIH1cbn1cblxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2VjdGlvbklzRXF1YWwoZmQxLCBzZWN0aW9uczEsIGZkMiwgc2VjdGlvbnMyLCBpZFNlY3Rpb24pIHtcbiAgICBjb25zdCBNQVhfQlVGRl9TSVpFID0gZmQxLnBhZ2VTaXplICogMTY7XG4gICAgYXdhaXQgc3RhcnRSZWFkVW5pcXVlU2VjdGlvbihmZDEsIHNlY3Rpb25zMSwgaWRTZWN0aW9uKTtcbiAgICBhd2FpdCBzdGFydFJlYWRVbmlxdWVTZWN0aW9uKGZkMiwgc2VjdGlvbnMyLCBpZFNlY3Rpb24pO1xuICAgIGlmIChzZWN0aW9uczFbaWRTZWN0aW9uXVswXS5zaXplICE9IHNlY3Rpb25zMltpZFNlY3Rpb25dWzBdLnNpemUpIHJldHVybiBmYWxzZTtcbiAgICBjb25zdCB0b3RhbEJ5dGVzPXNlY3Rpb25zMVtpZFNlY3Rpb25dWzBdLnNpemU7XG4gICAgZm9yIChsZXQgaT0wOyBpPHRvdGFsQnl0ZXM7IGkrPSBNQVhfQlVGRl9TSVpFKSB7XG4gICAgICAgIGNvbnN0IG4gPSBNYXRoLm1pbih0b3RhbEJ5dGVzLWksIE1BWF9CVUZGX1NJWkUpO1xuICAgICAgICBjb25zdCBidWZmMSA9IGF3YWl0IGZkMS5yZWFkKG4pO1xuICAgICAgICBjb25zdCBidWZmMiA9IGF3YWl0IGZkMi5yZWFkKG4pO1xuICAgICAgICBmb3IgKGxldCBqPTA7IGo8bjsgaisrKSBpZiAoYnVmZjFbal0gIT0gYnVmZjJbal0pIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgYXdhaXQgZW5kUmVhZFNlY3Rpb24oZmQxKTtcbiAgICBhd2FpdCBlbmRSZWFkU2VjdGlvbihmZDIpO1xuICAgIHJldHVybiB0cnVlO1xufVxuIiwiaW1wb3J0IHsgU2NhbGFyLCBidWlsZEJuMTI4LCBidWlsZEJsczEyMzgxfSBmcm9tIFwiZmZqYXZhc2NyaXB0XCI7XG5cbmNvbnN0IGJsczEyMzgxciA9IFNjYWxhci5lKFwiNzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMVwiLCAxNik7XG5jb25zdCBibjEyOHIgPSBTY2FsYXIuZShcIjIxODg4MjQyODcxODM5Mjc1MjIyMjQ2NDA1NzQ1MjU3Mjc1MDg4NTQ4MzY0NDAwNDE2MDM0MzQzNjk4MjA0MTg2NTc1ODA4NDk1NjE3XCIpO1xuXG5jb25zdCBibHMxMjM4MXEgPSBTY2FsYXIuZShcIjFhMDExMWVhMzk3ZmU2OWE0YjFiYTdiNjQzNGJhY2Q3NjQ3NzRiODRmMzg1MTJiZjY3MzBkMmEwZjZiMGY2MjQxZWFiZmZmZWIxNTNmZmZmYjlmZWZmZmZmZmZmYWFhYlwiLCAxNik7XG5jb25zdCBibjEyOHEgPSBTY2FsYXIuZShcIjIxODg4MjQyODcxODM5Mjc1MjIyMjQ2NDA1NzQ1MjU3Mjc1MDg4Njk2MzExMTU3Mjk3ODIzNjYyNjg5MDM3ODk0NjQ1MjI2MjA4NTgzXCIpO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0Q3VydmVGcm9tUihyLCBvcHRpb25zKSB7XG4gICAgbGV0IGN1cnZlO1xuICAgIC8vIGNoZWNrIHRoYXQgb3B0aW9ucyBwYXJhbSBpcyBkZWZpbmVkIGFuZCB0aGF0IG9wdGlvbnMuc2luZ2xlVGhyZWFkIGlzIGRlZmluZWRcbiAgICBsZXQgc2luZ2xlVGhyZWFkID0gb3B0aW9ucyAmJiBvcHRpb25zLnNpbmdsZVRocmVhZDtcbiAgICBpZiAoU2NhbGFyLmVxKHIsIGJuMTI4cikpIHtcbiAgICAgICAgY3VydmUgPSBhd2FpdCBidWlsZEJuMTI4KHNpbmdsZVRocmVhZCk7XG4gICAgfSBlbHNlIGlmIChTY2FsYXIuZXEociwgYmxzMTIzODFyKSkge1xuICAgICAgICBjdXJ2ZSA9IGF3YWl0IGJ1aWxkQmxzMTIzODEoc2luZ2xlVGhyZWFkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEN1cnZlIG5vdCBzdXBwb3J0ZWQ6ICR7U2NhbGFyLnRvU3RyaW5nKHIpfWApO1xuICAgIH1cbiAgICByZXR1cm4gY3VydmU7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRDdXJ2ZUZyb21RKHEsIG9wdGlvbnMpIHtcbiAgICBsZXQgY3VydmU7XG4gICAgbGV0IHNpbmdsZVRocmVhZCA9IG9wdGlvbnMgJiYgb3B0aW9ucy5zaW5nbGVUaHJlYWQ7XG4gICAgaWYgKFNjYWxhci5lcShxLCBibjEyOHEpKSB7XG4gICAgICAgIGN1cnZlID0gYXdhaXQgYnVpbGRCbjEyOChzaW5nbGVUaHJlYWQpO1xuICAgIH0gZWxzZSBpZiAoU2NhbGFyLmVxKHEsIGJsczEyMzgxcSkpIHtcbiAgICAgICAgY3VydmUgPSBhd2FpdCBidWlsZEJsczEyMzgxKHNpbmdsZVRocmVhZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDdXJ2ZSBub3Qgc3VwcG9ydGVkOiAke1NjYWxhci50b1N0cmluZyhxKX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIGN1cnZlO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0Q3VydmVGcm9tTmFtZShuYW1lLCBvcHRpb25zKSB7XG4gICAgbGV0IGN1cnZlO1xuICAgIGxldCBzaW5nbGVUaHJlYWQgPSBvcHRpb25zICYmIG9wdGlvbnMuc2luZ2xlVGhyZWFkO1xuICAgIGNvbnN0IG5vcm1OYW1lID0gbm9ybWFsaXplTmFtZShuYW1lKTtcbiAgICBpZiAoW1wiQk4xMjhcIiwgXCJCTjI1NFwiLCBcIkFMVEJOMTI4XCJdLmluZGV4T2Yobm9ybU5hbWUpID49IDApIHtcbiAgICAgICAgY3VydmUgPSBhd2FpdCBidWlsZEJuMTI4KHNpbmdsZVRocmVhZCk7XG4gICAgfSBlbHNlIGlmIChbXCJCTFMxMjM4MVwiXS5pbmRleE9mKG5vcm1OYW1lKSA+PSAwKSB7XG4gICAgICAgIGN1cnZlID0gYXdhaXQgYnVpbGRCbHMxMjM4MShzaW5nbGVUaHJlYWQpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ3VydmUgbm90IHN1cHBvcnRlZDogJHtuYW1lfWApO1xuICAgIH1cbiAgICByZXR1cm4gY3VydmU7XG5cbiAgICBmdW5jdGlvbiBub3JtYWxpemVOYW1lKG4pIHtcbiAgICAgICAgcmV0dXJuIG4udG9VcHBlckNhc2UoKS5tYXRjaCgvW0EtWmEtejAtOV0rL2cpLmpvaW4oXCJcIik7XG4gICAgfVxuXG59XG5cbiIsIi8qKlxuICogSW50ZXJuYWwgYXNzZXJ0aW9uIGhlbHBlcnMuXG4gKiBAbW9kdWxlXG4gKi9cbi8qKiBBc3NlcnRzIHNvbWV0aGluZyBpcyBwb3NpdGl2ZSBpbnRlZ2VyLiAqL1xuZnVuY3Rpb24gYW51bWJlcihuKSB7XG4gICAgaWYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcihuKSB8fCBuIDwgMClcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdwb3NpdGl2ZSBpbnRlZ2VyIGV4cGVjdGVkLCBnb3QgJyArIG4pO1xufVxuLyoqIElzIG51bWJlciBhbiBVaW50OEFycmF5PyBDb3BpZWQgZnJvbSB1dGlscyBmb3IgcGVyZi4gKi9cbmZ1bmN0aW9uIGlzQnl0ZXMoYSkge1xuICAgIHJldHVybiBhIGluc3RhbmNlb2YgVWludDhBcnJheSB8fCAoQXJyYXlCdWZmZXIuaXNWaWV3KGEpICYmIGEuY29uc3RydWN0b3IubmFtZSA9PT0gJ1VpbnQ4QXJyYXknKTtcbn1cbi8qKiBBc3NlcnRzIHNvbWV0aGluZyBpcyBVaW50OEFycmF5LiAqL1xuZnVuY3Rpb24gYWJ5dGVzKGIsIC4uLmxlbmd0aHMpIHtcbiAgICBpZiAoIWlzQnl0ZXMoYikpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVWludDhBcnJheSBleHBlY3RlZCcpO1xuICAgIGlmIChsZW5ndGhzLmxlbmd0aCA+IDAgJiYgIWxlbmd0aHMuaW5jbHVkZXMoYi5sZW5ndGgpKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VpbnQ4QXJyYXkgZXhwZWN0ZWQgb2YgbGVuZ3RoICcgKyBsZW5ndGhzICsgJywgZ290IGxlbmd0aD0nICsgYi5sZW5ndGgpO1xufVxuLyoqIEFzc2VydHMgc29tZXRoaW5nIGlzIGhhc2ggKi9cbmZ1bmN0aW9uIGFoYXNoKGgpIHtcbiAgICBpZiAodHlwZW9mIGggIT09ICdmdW5jdGlvbicgfHwgdHlwZW9mIGguY3JlYXRlICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0hhc2ggc2hvdWxkIGJlIHdyYXBwZWQgYnkgdXRpbHMud3JhcENvbnN0cnVjdG9yJyk7XG4gICAgYW51bWJlcihoLm91dHB1dExlbik7XG4gICAgYW51bWJlcihoLmJsb2NrTGVuKTtcbn1cbi8qKiBBc3NlcnRzIGEgaGFzaCBpbnN0YW5jZSBoYXMgbm90IGJlZW4gZGVzdHJveWVkIC8gZmluaXNoZWQgKi9cbmZ1bmN0aW9uIGFleGlzdHMoaW5zdGFuY2UsIGNoZWNrRmluaXNoZWQgPSB0cnVlKSB7XG4gICAgaWYgKGluc3RhbmNlLmRlc3Ryb3llZClcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdIYXNoIGluc3RhbmNlIGhhcyBiZWVuIGRlc3Ryb3llZCcpO1xuICAgIGlmIChjaGVja0ZpbmlzaGVkICYmIGluc3RhbmNlLmZpbmlzaGVkKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0hhc2gjZGlnZXN0KCkgaGFzIGFscmVhZHkgYmVlbiBjYWxsZWQnKTtcbn1cbi8qKiBBc3NlcnRzIG91dHB1dCBpcyBwcm9wZXJseS1zaXplZCBieXRlIGFycmF5ICovXG5mdW5jdGlvbiBhb3V0cHV0KG91dCwgaW5zdGFuY2UpIHtcbiAgICBhYnl0ZXMob3V0KTtcbiAgICBjb25zdCBtaW4gPSBpbnN0YW5jZS5vdXRwdXRMZW47XG4gICAgaWYgKG91dC5sZW5ndGggPCBtaW4pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdkaWdlc3RJbnRvKCkgZXhwZWN0cyBvdXRwdXQgYnVmZmVyIG9mIGxlbmd0aCBhdCBsZWFzdCAnICsgbWluKTtcbiAgICB9XG59XG5leHBvcnQgeyBhbnVtYmVyLCBhYnl0ZXMsIGFoYXNoLCBhZXhpc3RzLCBhb3V0cHV0IH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1fYXNzZXJ0LmpzLm1hcCIsIi8qKlxuICogVXRpbGl0aWVzIGZvciBoZXgsIGJ5dGVzLCBDU1BSTkcuXG4gKiBAbW9kdWxlXG4gKi9cbi8qISBub2JsZS1oYXNoZXMgLSBNSVQgTGljZW5zZSAoYykgMjAyMiBQYXVsIE1pbGxlciAocGF1bG1pbGxyLmNvbSkgKi9cbi8vIFdlIHVzZSBXZWJDcnlwdG8gYWthIGdsb2JhbFRoaXMuY3J5cHRvLCB3aGljaCBleGlzdHMgaW4gYnJvd3NlcnMgYW5kIG5vZGUuanMgMTYrLlxuLy8gbm9kZS5qcyB2ZXJzaW9ucyBlYXJsaWVyIHRoYW4gdjE5IGRvbid0IGRlY2xhcmUgaXQgaW4gZ2xvYmFsIHNjb3BlLlxuLy8gRm9yIG5vZGUuanMsIHBhY2thZ2UuanNvbiNleHBvcnRzIGZpZWxkIG1hcHBpbmcgcmV3cml0ZXMgaW1wb3J0XG4vLyBmcm9tIGBjcnlwdG9gIHRvIGBjcnlwdG9Ob2RlYCwgd2hpY2ggaW1wb3J0cyBuYXRpdmUgbW9kdWxlLlxuLy8gTWFrZXMgdGhlIHV0aWxzIHVuLWltcG9ydGFibGUgaW4gYnJvd3NlcnMgd2l0aG91dCBhIGJ1bmRsZXIuXG4vLyBPbmNlIG5vZGUuanMgMTggaXMgZGVwcmVjYXRlZCAoMjAyNS0wNC0zMCksIHdlIGNhbiBqdXN0IGRyb3AgdGhlIGltcG9ydC5cbmltcG9ydCB7IGNyeXB0byB9IGZyb20gJ0Bub2JsZS9oYXNoZXMvY3J5cHRvJztcbmltcG9ydCB7IGFieXRlcyB9IGZyb20gJy4vX2Fzc2VydC5qcyc7XG4vLyBleHBvcnQgeyBpc0J5dGVzIH0gZnJvbSAnLi9fYXNzZXJ0LmpzJztcbi8vIFdlIGNhbid0IHJldXNlIGlzQnl0ZXMgZnJvbSBfYXNzZXJ0LCBiZWNhdXNlIHNvbWVob3cgdGhpcyBjYXVzZXMgaHVnZSBwZXJmIGlzc3Vlc1xuZXhwb3J0IGZ1bmN0aW9uIGlzQnl0ZXMoYSkge1xuICAgIHJldHVybiBhIGluc3RhbmNlb2YgVWludDhBcnJheSB8fCAoQXJyYXlCdWZmZXIuaXNWaWV3KGEpICYmIGEuY29uc3RydWN0b3IubmFtZSA9PT0gJ1VpbnQ4QXJyYXknKTtcbn1cbi8vIENhc3QgYXJyYXkgdG8gZGlmZmVyZW50IHR5cGVcbmV4cG9ydCBmdW5jdGlvbiB1OChhcnIpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoYXJyLmJ1ZmZlciwgYXJyLmJ5dGVPZmZzZXQsIGFyci5ieXRlTGVuZ3RoKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiB1MzIoYXJyKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50MzJBcnJheShhcnIuYnVmZmVyLCBhcnIuYnl0ZU9mZnNldCwgTWF0aC5mbG9vcihhcnIuYnl0ZUxlbmd0aCAvIDQpKTtcbn1cbi8vIENhc3QgYXJyYXkgdG8gdmlld1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVZpZXcoYXJyKSB7XG4gICAgcmV0dXJuIG5ldyBEYXRhVmlldyhhcnIuYnVmZmVyLCBhcnIuYnl0ZU9mZnNldCwgYXJyLmJ5dGVMZW5ndGgpO1xufVxuLyoqIFRoZSByb3RhdGUgcmlnaHQgKGNpcmN1bGFyIHJpZ2h0IHNoaWZ0KSBvcGVyYXRpb24gZm9yIHVpbnQzMiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJvdHIod29yZCwgc2hpZnQpIHtcbiAgICByZXR1cm4gKHdvcmQgPDwgKDMyIC0gc2hpZnQpKSB8ICh3b3JkID4+PiBzaGlmdCk7XG59XG4vKiogVGhlIHJvdGF0ZSBsZWZ0IChjaXJjdWxhciBsZWZ0IHNoaWZ0KSBvcGVyYXRpb24gZm9yIHVpbnQzMiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJvdGwod29yZCwgc2hpZnQpIHtcbiAgICByZXR1cm4gKHdvcmQgPDwgc2hpZnQpIHwgKCh3b3JkID4+PiAoMzIgLSBzaGlmdCkpID4+PiAwKTtcbn1cbi8qKiBJcyBjdXJyZW50IHBsYXRmb3JtIGxpdHRsZS1lbmRpYW4/IE1vc3QgYXJlLiBCaWctRW5kaWFuIHBsYXRmb3JtOiBJQk0gKi9cbmV4cG9ydCBjb25zdCBpc0xFID0gLyogQF9fUFVSRV9fICovICgoKSA9PiBuZXcgVWludDhBcnJheShuZXcgVWludDMyQXJyYXkoWzB4MTEyMjMzNDRdKS5idWZmZXIpWzBdID09PSAweDQ0KSgpO1xuLy8gVGhlIGJ5dGUgc3dhcCBvcGVyYXRpb24gZm9yIHVpbnQzMlxuZXhwb3J0IGZ1bmN0aW9uIGJ5dGVTd2FwKHdvcmQpIHtcbiAgICByZXR1cm4gKCgod29yZCA8PCAyNCkgJiAweGZmMDAwMDAwKSB8XG4gICAgICAgICgod29yZCA8PCA4KSAmIDB4ZmYwMDAwKSB8XG4gICAgICAgICgod29yZCA+Pj4gOCkgJiAweGZmMDApIHxcbiAgICAgICAgKCh3b3JkID4+PiAyNCkgJiAweGZmKSk7XG59XG4vKiogQ29uZGl0aW9uYWxseSBieXRlIHN3YXAgaWYgb24gYSBiaWctZW5kaWFuIHBsYXRmb3JtICovXG5leHBvcnQgY29uc3QgYnl0ZVN3YXBJZkJFID0gaXNMRVxuICAgID8gKG4pID0+IG5cbiAgICA6IChuKSA9PiBieXRlU3dhcChuKTtcbi8qKiBJbiBwbGFjZSBieXRlIHN3YXAgZm9yIFVpbnQzMkFycmF5ICovXG5leHBvcnQgZnVuY3Rpb24gYnl0ZVN3YXAzMihhcnIpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuICAgICAgICBhcnJbaV0gPSBieXRlU3dhcChhcnJbaV0pO1xuICAgIH1cbn1cbi8vIEFycmF5IHdoZXJlIGluZGV4IDB4ZjAgKDI0MCkgaXMgbWFwcGVkIHRvIHN0cmluZyAnZjAnXG5jb25zdCBoZXhlcyA9IC8qIEBfX1BVUkVfXyAqLyBBcnJheS5mcm9tKHsgbGVuZ3RoOiAyNTYgfSwgKF8sIGkpID0+IGkudG9TdHJpbmcoMTYpLnBhZFN0YXJ0KDIsICcwJykpO1xuLyoqXG4gKiBDb252ZXJ0IGJ5dGUgYXJyYXkgdG8gaGV4IHN0cmluZy5cbiAqIEBleGFtcGxlIGJ5dGVzVG9IZXgoVWludDhBcnJheS5mcm9tKFsweGNhLCAweGZlLCAweDAxLCAweDIzXSkpIC8vICdjYWZlMDEyMydcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ5dGVzVG9IZXgoYnl0ZXMpIHtcbiAgICBhYnl0ZXMoYnl0ZXMpO1xuICAgIC8vIHByZS1jYWNoaW5nIGltcHJvdmVzIHRoZSBzcGVlZCA2eFxuICAgIGxldCBoZXggPSAnJztcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJ5dGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGhleCArPSBoZXhlc1tieXRlc1tpXV07XG4gICAgfVxuICAgIHJldHVybiBoZXg7XG59XG4vLyBXZSB1c2Ugb3B0aW1pemVkIHRlY2huaXF1ZSB0byBjb252ZXJ0IGhleCBzdHJpbmcgdG8gYnl0ZSBhcnJheVxuY29uc3QgYXNjaWlzID0geyBfMDogNDgsIF85OiA1NywgQTogNjUsIEY6IDcwLCBhOiA5NywgZjogMTAyIH07XG5mdW5jdGlvbiBhc2NpaVRvQmFzZTE2KGNoKSB7XG4gICAgaWYgKGNoID49IGFzY2lpcy5fMCAmJiBjaCA8PSBhc2NpaXMuXzkpXG4gICAgICAgIHJldHVybiBjaCAtIGFzY2lpcy5fMDsgLy8gJzInID0+IDUwLTQ4XG4gICAgaWYgKGNoID49IGFzY2lpcy5BICYmIGNoIDw9IGFzY2lpcy5GKVxuICAgICAgICByZXR1cm4gY2ggLSAoYXNjaWlzLkEgLSAxMCk7IC8vICdCJyA9PiA2Ni0oNjUtMTApXG4gICAgaWYgKGNoID49IGFzY2lpcy5hICYmIGNoIDw9IGFzY2lpcy5mKVxuICAgICAgICByZXR1cm4gY2ggLSAoYXNjaWlzLmEgLSAxMCk7IC8vICdiJyA9PiA5OC0oOTctMTApXG4gICAgcmV0dXJuO1xufVxuLyoqXG4gKiBDb252ZXJ0IGhleCBzdHJpbmcgdG8gYnl0ZSBhcnJheS5cbiAqIEBleGFtcGxlIGhleFRvQnl0ZXMoJ2NhZmUwMTIzJykgLy8gVWludDhBcnJheS5mcm9tKFsweGNhLCAweGZlLCAweDAxLCAweDIzXSlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhleFRvQnl0ZXMoaGV4KSB7XG4gICAgaWYgKHR5cGVvZiBoZXggIT09ICdzdHJpbmcnKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2hleCBzdHJpbmcgZXhwZWN0ZWQsIGdvdCAnICsgdHlwZW9mIGhleCk7XG4gICAgY29uc3QgaGwgPSBoZXgubGVuZ3RoO1xuICAgIGNvbnN0IGFsID0gaGwgLyAyO1xuICAgIGlmIChobCAlIDIpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignaGV4IHN0cmluZyBleHBlY3RlZCwgZ290IHVucGFkZGVkIGhleCBvZiBsZW5ndGggJyArIGhsKTtcbiAgICBjb25zdCBhcnJheSA9IG5ldyBVaW50OEFycmF5KGFsKTtcbiAgICBmb3IgKGxldCBhaSA9IDAsIGhpID0gMDsgYWkgPCBhbDsgYWkrKywgaGkgKz0gMikge1xuICAgICAgICBjb25zdCBuMSA9IGFzY2lpVG9CYXNlMTYoaGV4LmNoYXJDb2RlQXQoaGkpKTtcbiAgICAgICAgY29uc3QgbjIgPSBhc2NpaVRvQmFzZTE2KGhleC5jaGFyQ29kZUF0KGhpICsgMSkpO1xuICAgICAgICBpZiAobjEgPT09IHVuZGVmaW5lZCB8fCBuMiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBjb25zdCBjaGFyID0gaGV4W2hpXSArIGhleFtoaSArIDFdO1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdoZXggc3RyaW5nIGV4cGVjdGVkLCBnb3Qgbm9uLWhleCBjaGFyYWN0ZXIgXCInICsgY2hhciArICdcIiBhdCBpbmRleCAnICsgaGkpO1xuICAgICAgICB9XG4gICAgICAgIGFycmF5W2FpXSA9IG4xICogMTYgKyBuMjsgLy8gbXVsdGlwbHkgZmlyc3Qgb2N0ZXQsIGUuZy4gJ2EzJyA9PiAxMCoxNiszID0+IDE2MCArIDMgPT4gMTYzXG4gICAgfVxuICAgIHJldHVybiBhcnJheTtcbn1cbi8qKlxuICogVGhlcmUgaXMgbm8gc2V0SW1tZWRpYXRlIGluIGJyb3dzZXIgYW5kIHNldFRpbWVvdXQgaXMgc2xvdy5cbiAqIENhbGwgb2YgYXN5bmMgZm4gd2lsbCByZXR1cm4gUHJvbWlzZSwgd2hpY2ggd2lsbCBiZSBmdWxsZmlsZWQgb25seSBvblxuICogbmV4dCBzY2hlZHVsZXIgcXVldWUgcHJvY2Vzc2luZyBzdGVwIGFuZCB0aGlzIGlzIGV4YWN0bHkgd2hhdCB3ZSBuZWVkLlxuICovXG5leHBvcnQgY29uc3QgbmV4dFRpY2sgPSBhc3luYyAoKSA9PiB7IH07XG4vKiogUmV0dXJucyBjb250cm9sIHRvIHRocmVhZCBlYWNoICd0aWNrJyBtcyB0byBhdm9pZCBibG9ja2luZy4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhc3luY0xvb3AoaXRlcnMsIHRpY2ssIGNiKSB7XG4gICAgbGV0IHRzID0gRGF0ZS5ub3coKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGl0ZXJzOyBpKyspIHtcbiAgICAgICAgY2IoaSk7XG4gICAgICAgIC8vIERhdGUubm93KCkgaXMgbm90IG1vbm90b25pYywgc28gaW4gY2FzZSBpZiBjbG9jayBnb2VzIGJhY2t3YXJkcyB3ZSByZXR1cm4gcmV0dXJuIGNvbnRyb2wgdG9vXG4gICAgICAgIGNvbnN0IGRpZmYgPSBEYXRlLm5vdygpIC0gdHM7XG4gICAgICAgIGlmIChkaWZmID49IDAgJiYgZGlmZiA8IHRpY2spXG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgYXdhaXQgbmV4dFRpY2soKTtcbiAgICAgICAgdHMgKz0gZGlmZjtcbiAgICB9XG59XG4vKipcbiAqIENvbnZlcnQgSlMgc3RyaW5nIHRvIGJ5dGUgYXJyYXkuXG4gKiBAZXhhbXBsZSB1dGY4VG9CeXRlcygnYWJjJykgLy8gbmV3IFVpbnQ4QXJyYXkoWzk3LCA5OCwgOTldKVxuICovXG5leHBvcnQgZnVuY3Rpb24gdXRmOFRvQnl0ZXMoc3RyKSB7XG4gICAgaWYgKHR5cGVvZiBzdHIgIT09ICdzdHJpbmcnKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3V0ZjhUb0J5dGVzIGV4cGVjdGVkIHN0cmluZywgZ290ICcgKyB0eXBlb2Ygc3RyKTtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkobmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKHN0cikpOyAvLyBodHRwczovL2J1Z3ppbC5sYS8xNjgxODA5XG59XG4vKipcbiAqIE5vcm1hbGl6ZXMgKG5vbi1oZXgpIHN0cmluZyBvciBVaW50OEFycmF5IHRvIFVpbnQ4QXJyYXkuXG4gKiBXYXJuaW5nOiB3aGVuIFVpbnQ4QXJyYXkgaXMgcGFzc2VkLCBpdCB3b3VsZCBOT1QgZ2V0IGNvcGllZC5cbiAqIEtlZXAgaW4gbWluZCBmb3IgZnV0dXJlIG11dGFibGUgb3BlcmF0aW9ucy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvQnl0ZXMoZGF0YSkge1xuICAgIGlmICh0eXBlb2YgZGF0YSA9PT0gJ3N0cmluZycpXG4gICAgICAgIGRhdGEgPSB1dGY4VG9CeXRlcyhkYXRhKTtcbiAgICBhYnl0ZXMoZGF0YSk7XG4gICAgcmV0dXJuIGRhdGE7XG59XG4vKipcbiAqIENvcGllcyBzZXZlcmFsIFVpbnQ4QXJyYXlzIGludG8gb25lLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY29uY2F0Qnl0ZXMoLi4uYXJyYXlzKSB7XG4gICAgbGV0IHN1bSA9IDA7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcnJheXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgYSA9IGFycmF5c1tpXTtcbiAgICAgICAgYWJ5dGVzKGEpO1xuICAgICAgICBzdW0gKz0gYS5sZW5ndGg7XG4gICAgfVxuICAgIGNvbnN0IHJlcyA9IG5ldyBVaW50OEFycmF5KHN1bSk7XG4gICAgZm9yIChsZXQgaSA9IDAsIHBhZCA9IDA7IGkgPCBhcnJheXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgYSA9IGFycmF5c1tpXTtcbiAgICAgICAgcmVzLnNldChhLCBwYWQpO1xuICAgICAgICBwYWQgKz0gYS5sZW5ndGg7XG4gICAgfVxuICAgIHJldHVybiByZXM7XG59XG4vKiogRm9yIHJ1bnRpbWUgY2hlY2sgaWYgY2xhc3MgaW1wbGVtZW50cyBpbnRlcmZhY2UgKi9cbmV4cG9ydCBjbGFzcyBIYXNoIHtcbiAgICAvLyBTYWZlIHZlcnNpb24gdGhhdCBjbG9uZXMgaW50ZXJuYWwgc3RhdGVcbiAgICBjbG9uZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2Nsb25lSW50bygpO1xuICAgIH1cbn1cbmV4cG9ydCBmdW5jdGlvbiBjaGVja09wdHMoZGVmYXVsdHMsIG9wdHMpIHtcbiAgICBpZiAob3B0cyAhPT0gdW5kZWZpbmVkICYmIHt9LnRvU3RyaW5nLmNhbGwob3B0cykgIT09ICdbb2JqZWN0IE9iamVjdF0nKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ09wdGlvbnMgc2hvdWxkIGJlIG9iamVjdCBvciB1bmRlZmluZWQnKTtcbiAgICBjb25zdCBtZXJnZWQgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCBvcHRzKTtcbiAgICByZXR1cm4gbWVyZ2VkO1xufVxuLyoqIFdyYXBzIGhhc2ggZnVuY3Rpb24sIGNyZWF0aW5nIGFuIGludGVyZmFjZSBvbiB0b3Agb2YgaXQgKi9cbmV4cG9ydCBmdW5jdGlvbiB3cmFwQ29uc3RydWN0b3IoaGFzaENvbnMpIHtcbiAgICBjb25zdCBoYXNoQyA9IChtc2cpID0+IGhhc2hDb25zKCkudXBkYXRlKHRvQnl0ZXMobXNnKSkuZGlnZXN0KCk7XG4gICAgY29uc3QgdG1wID0gaGFzaENvbnMoKTtcbiAgICBoYXNoQy5vdXRwdXRMZW4gPSB0bXAub3V0cHV0TGVuO1xuICAgIGhhc2hDLmJsb2NrTGVuID0gdG1wLmJsb2NrTGVuO1xuICAgIGhhc2hDLmNyZWF0ZSA9ICgpID0+IGhhc2hDb25zKCk7XG4gICAgcmV0dXJuIGhhc2hDO1xufVxuZXhwb3J0IGZ1bmN0aW9uIHdyYXBDb25zdHJ1Y3RvcldpdGhPcHRzKGhhc2hDb25zKSB7XG4gICAgY29uc3QgaGFzaEMgPSAobXNnLCBvcHRzKSA9PiBoYXNoQ29ucyhvcHRzKS51cGRhdGUodG9CeXRlcyhtc2cpKS5kaWdlc3QoKTtcbiAgICBjb25zdCB0bXAgPSBoYXNoQ29ucyh7fSk7XG4gICAgaGFzaEMub3V0cHV0TGVuID0gdG1wLm91dHB1dExlbjtcbiAgICBoYXNoQy5ibG9ja0xlbiA9IHRtcC5ibG9ja0xlbjtcbiAgICBoYXNoQy5jcmVhdGUgPSAob3B0cykgPT4gaGFzaENvbnMob3B0cyk7XG4gICAgcmV0dXJuIGhhc2hDO1xufVxuZXhwb3J0IGZ1bmN0aW9uIHdyYXBYT0ZDb25zdHJ1Y3RvcldpdGhPcHRzKGhhc2hDb25zKSB7XG4gICAgY29uc3QgaGFzaEMgPSAobXNnLCBvcHRzKSA9PiBoYXNoQ29ucyhvcHRzKS51cGRhdGUodG9CeXRlcyhtc2cpKS5kaWdlc3QoKTtcbiAgICBjb25zdCB0bXAgPSBoYXNoQ29ucyh7fSk7XG4gICAgaGFzaEMub3V0cHV0TGVuID0gdG1wLm91dHB1dExlbjtcbiAgICBoYXNoQy5ibG9ja0xlbiA9IHRtcC5ibG9ja0xlbjtcbiAgICBoYXNoQy5jcmVhdGUgPSAob3B0cykgPT4gaGFzaENvbnMob3B0cyk7XG4gICAgcmV0dXJuIGhhc2hDO1xufVxuLyoqIENyeXB0b2dyYXBoaWNhbGx5IHNlY3VyZSBQUk5HLiBVc2VzIGludGVybmFsIE9TLWxldmVsIGBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzYC4gKi9cbmV4cG9ydCBmdW5jdGlvbiByYW5kb21CeXRlcyhieXRlc0xlbmd0aCA9IDMyKSB7XG4gICAgaWYgKGNyeXB0byAmJiB0eXBlb2YgY3J5cHRvLmdldFJhbmRvbVZhbHVlcyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXR1cm4gY3J5cHRvLmdldFJhbmRvbVZhbHVlcyhuZXcgVWludDhBcnJheShieXRlc0xlbmd0aCkpO1xuICAgIH1cbiAgICAvLyBMZWdhY3kgTm9kZS5qcyBjb21wYXRpYmlsaXR5XG4gICAgaWYgKGNyeXB0byAmJiB0eXBlb2YgY3J5cHRvLnJhbmRvbUJ5dGVzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiBjcnlwdG8ucmFuZG9tQnl0ZXMoYnl0ZXNMZW5ndGgpO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2NyeXB0by5nZXRSYW5kb21WYWx1ZXMgbXVzdCBiZSBkZWZpbmVkJyk7XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD11dGlscy5qcy5tYXAiLCIvKipcbiAqIEludGVybmFsIGhlbHBlcnMgZm9yIGJsYWtlIGhhc2guXG4gKiBAbW9kdWxlXG4gKi9cbmltcG9ydCB7IGFleGlzdHMsIGFudW1iZXIsIGFvdXRwdXQgfSBmcm9tICcuL19hc3NlcnQuanMnO1xuaW1wb3J0IHsgYnl0ZVN3YXAzMiwgYnl0ZVN3YXBJZkJFLCBIYXNoLCBpc0xFLCB0b0J5dGVzLCB1MzIgfSBmcm9tICcuL3V0aWxzLmpzJztcbi8qKlxuICogSW50ZXJuYWwgYmxha2UgdmFyaWFibGUuXG4gKiBGb3IgQkxBS0UyYiwgdGhlIHR3byBleHRyYSBwZXJtdXRhdGlvbnMgZm9yIHJvdW5kcyAxMCBhbmQgMTEgYXJlIFNJR01BWzEwLi4xMV0gPSBTSUdNQVswLi4xXS5cbiAqL1xuLy8gcHJldHRpZXItaWdub3JlXG5leHBvcnQgY29uc3QgU0lHTUEgPSAvKiBAX19QVVJFX18gKi8gbmV3IFVpbnQ4QXJyYXkoW1xuICAgIDAsIDEsIDIsIDMsIDQsIDUsIDYsIDcsIDgsIDksIDEwLCAxMSwgMTIsIDEzLCAxNCwgMTUsXG4gICAgMTQsIDEwLCA0LCA4LCA5LCAxNSwgMTMsIDYsIDEsIDEyLCAwLCAyLCAxMSwgNywgNSwgMyxcbiAgICAxMSwgOCwgMTIsIDAsIDUsIDIsIDE1LCAxMywgMTAsIDE0LCAzLCA2LCA3LCAxLCA5LCA0LFxuICAgIDcsIDksIDMsIDEsIDEzLCAxMiwgMTEsIDE0LCAyLCA2LCA1LCAxMCwgNCwgMCwgMTUsIDgsXG4gICAgOSwgMCwgNSwgNywgMiwgNCwgMTAsIDE1LCAxNCwgMSwgMTEsIDEyLCA2LCA4LCAzLCAxMyxcbiAgICAyLCAxMiwgNiwgMTAsIDAsIDExLCA4LCAzLCA0LCAxMywgNywgNSwgMTUsIDE0LCAxLCA5LFxuICAgIDEyLCA1LCAxLCAxNSwgMTQsIDEzLCA0LCAxMCwgMCwgNywgNiwgMywgOSwgMiwgOCwgMTEsXG4gICAgMTMsIDExLCA3LCAxNCwgMTIsIDEsIDMsIDksIDUsIDAsIDE1LCA0LCA4LCA2LCAyLCAxMCxcbiAgICA2LCAxNSwgMTQsIDksIDExLCAzLCAwLCA4LCAxMiwgMiwgMTMsIDcsIDEsIDQsIDEwLCA1LFxuICAgIDEwLCAyLCA4LCA0LCA3LCA2LCAxLCA1LCAxNSwgMTEsIDksIDE0LCAzLCAxMiwgMTMsIDAsXG4gICAgMCwgMSwgMiwgMywgNCwgNSwgNiwgNywgOCwgOSwgMTAsIDExLCAxMiwgMTMsIDE0LCAxNSxcbiAgICAxNCwgMTAsIDQsIDgsIDksIDE1LCAxMywgNiwgMSwgMTIsIDAsIDIsIDExLCA3LCA1LCAzLFxuICAgIC8vIEJsYWtlMSwgdW51c2VkIGluIG90aGVyc1xuICAgIDExLCA4LCAxMiwgMCwgNSwgMiwgMTUsIDEzLCAxMCwgMTQsIDMsIDYsIDcsIDEsIDksIDQsXG4gICAgNywgOSwgMywgMSwgMTMsIDEyLCAxMSwgMTQsIDIsIDYsIDUsIDEwLCA0LCAwLCAxNSwgOCxcbiAgICA5LCAwLCA1LCA3LCAyLCA0LCAxMCwgMTUsIDE0LCAxLCAxMSwgMTIsIDYsIDgsIDMsIDEzLFxuICAgIDIsIDEyLCA2LCAxMCwgMCwgMTEsIDgsIDMsIDQsIDEzLCA3LCA1LCAxNSwgMTQsIDEsIDksXG5dKTtcbi8qKiBDbGFzcywgZnJvbSB3aGljaCBvdGhlcnMgYXJlIHN1YmNsYXNzZWQuICovXG5leHBvcnQgY2xhc3MgQkxBS0UgZXh0ZW5kcyBIYXNoIHtcbiAgICBjb25zdHJ1Y3RvcihibG9ja0xlbiwgb3V0cHV0TGVuLCBvcHRzID0ge30sIGtleUxlbiwgc2FsdExlbiwgcGVyc0xlbikge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLmJsb2NrTGVuID0gYmxvY2tMZW47XG4gICAgICAgIHRoaXMub3V0cHV0TGVuID0gb3V0cHV0TGVuO1xuICAgICAgICB0aGlzLmxlbmd0aCA9IDA7XG4gICAgICAgIHRoaXMucG9zID0gMDtcbiAgICAgICAgdGhpcy5maW5pc2hlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmRlc3Ryb3llZCA9IGZhbHNlO1xuICAgICAgICBhbnVtYmVyKGJsb2NrTGVuKTtcbiAgICAgICAgYW51bWJlcihvdXRwdXRMZW4pO1xuICAgICAgICBhbnVtYmVyKGtleUxlbik7XG4gICAgICAgIGlmIChvdXRwdXRMZW4gPCAwIHx8IG91dHB1dExlbiA+IGtleUxlbilcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignb3V0cHV0TGVuIGJpZ2dlciB0aGFuIGtleUxlbicpO1xuICAgICAgICBpZiAob3B0cy5rZXkgIT09IHVuZGVmaW5lZCAmJiAob3B0cy5rZXkubGVuZ3RoIDwgMSB8fCBvcHRzLmtleS5sZW5ndGggPiBrZXlMZW4pKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdrZXkgbGVuZ3RoIG11c3QgYmUgdW5kZWZpbmVkIG9yIDEuLicgKyBrZXlMZW4pO1xuICAgICAgICBpZiAob3B0cy5zYWx0ICE9PSB1bmRlZmluZWQgJiYgb3B0cy5zYWx0Lmxlbmd0aCAhPT0gc2FsdExlbilcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignc2FsdCBtdXN0IGJlIHVuZGVmaW5lZCBvciAnICsgc2FsdExlbik7XG4gICAgICAgIGlmIChvcHRzLnBlcnNvbmFsaXphdGlvbiAhPT0gdW5kZWZpbmVkICYmIG9wdHMucGVyc29uYWxpemF0aW9uLmxlbmd0aCAhPT0gcGVyc0xlbilcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigncGVyc29uYWxpemF0aW9uIG11c3QgYmUgdW5kZWZpbmVkIG9yICcgKyBwZXJzTGVuKTtcbiAgICAgICAgdGhpcy5idWZmZXIgPSBuZXcgVWludDhBcnJheShibG9ja0xlbik7XG4gICAgICAgIHRoaXMuYnVmZmVyMzIgPSB1MzIodGhpcy5idWZmZXIpO1xuICAgIH1cbiAgICB1cGRhdGUoZGF0YSkge1xuICAgICAgICBhZXhpc3RzKHRoaXMpO1xuICAgICAgICAvLyBNYWluIGRpZmZlcmVuY2Ugd2l0aCBvdGhlciBoYXNoZXM6IHRoZXJlIGlzIGZsYWcgZm9yIGxhc3QgYmxvY2ssXG4gICAgICAgIC8vIHNvIHdlIGNhbm5vdCBwcm9jZXNzIGN1cnJlbnQgYmxvY2sgYmVmb3JlIHdlIGtub3cgdGhhdCB0aGVyZVxuICAgICAgICAvLyBpcyB0aGUgbmV4dCBvbmUuIFRoaXMgc2lnbmlmaWNhbnRseSBjb21wbGljYXRlcyBsb2dpYyBhbmQgcmVkdWNlcyBhYmlsaXR5XG4gICAgICAgIC8vIHRvIGRvIHplcm8tY29weSBwcm9jZXNzaW5nXG4gICAgICAgIGNvbnN0IHsgYmxvY2tMZW4sIGJ1ZmZlciwgYnVmZmVyMzIgfSA9IHRoaXM7XG4gICAgICAgIGRhdGEgPSB0b0J5dGVzKGRhdGEpO1xuICAgICAgICBjb25zdCBsZW4gPSBkYXRhLmxlbmd0aDtcbiAgICAgICAgY29uc3Qgb2Zmc2V0ID0gZGF0YS5ieXRlT2Zmc2V0O1xuICAgICAgICBjb25zdCBidWYgPSBkYXRhLmJ1ZmZlcjtcbiAgICAgICAgZm9yIChsZXQgcG9zID0gMDsgcG9zIDwgbGVuOykge1xuICAgICAgICAgICAgLy8gSWYgYnVmZmVyIGlzIGZ1bGwgYW5kIHdlIHN0aWxsIGhhdmUgaW5wdXQgKGRvbid0IHByb2Nlc3MgbGFzdCBibG9jaywgc2FtZSBhcyBibGFrZTJzKVxuICAgICAgICAgICAgaWYgKHRoaXMucG9zID09PSBibG9ja0xlbikge1xuICAgICAgICAgICAgICAgIGlmICghaXNMRSlcbiAgICAgICAgICAgICAgICAgICAgYnl0ZVN3YXAzMihidWZmZXIzMik7XG4gICAgICAgICAgICAgICAgdGhpcy5jb21wcmVzcyhidWZmZXIzMiwgMCwgZmFsc2UpO1xuICAgICAgICAgICAgICAgIGlmICghaXNMRSlcbiAgICAgICAgICAgICAgICAgICAgYnl0ZVN3YXAzMihidWZmZXIzMik7XG4gICAgICAgICAgICAgICAgdGhpcy5wb3MgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgdGFrZSA9IE1hdGgubWluKGJsb2NrTGVuIC0gdGhpcy5wb3MsIGxlbiAtIHBvcyk7XG4gICAgICAgICAgICBjb25zdCBkYXRhT2Zmc2V0ID0gb2Zmc2V0ICsgcG9zO1xuICAgICAgICAgICAgLy8gZnVsbCBibG9jayAmJiBhbGlnbmVkIHRvIDQgYnl0ZXMgJiYgbm90IGxhc3QgaW4gaW5wdXRcbiAgICAgICAgICAgIGlmICh0YWtlID09PSBibG9ja0xlbiAmJiAhKGRhdGFPZmZzZXQgJSA0KSAmJiBwb3MgKyB0YWtlIDwgbGVuKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGF0YTMyID0gbmV3IFVpbnQzMkFycmF5KGJ1ZiwgZGF0YU9mZnNldCwgTWF0aC5mbG9vcigobGVuIC0gcG9zKSAvIDQpKTtcbiAgICAgICAgICAgICAgICBpZiAoIWlzTEUpXG4gICAgICAgICAgICAgICAgICAgIGJ5dGVTd2FwMzIoZGF0YTMyKTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBwb3MzMiA9IDA7IHBvcyArIGJsb2NrTGVuIDwgbGVuOyBwb3MzMiArPSBidWZmZXIzMi5sZW5ndGgsIHBvcyArPSBibG9ja0xlbikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxlbmd0aCArPSBibG9ja0xlbjtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wcmVzcyhkYXRhMzIsIHBvczMyLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghaXNMRSlcbiAgICAgICAgICAgICAgICAgICAgYnl0ZVN3YXAzMihkYXRhMzIpO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnVmZmVyLnNldChkYXRhLnN1YmFycmF5KHBvcywgcG9zICsgdGFrZSksIHRoaXMucG9zKTtcbiAgICAgICAgICAgIHRoaXMucG9zICs9IHRha2U7XG4gICAgICAgICAgICB0aGlzLmxlbmd0aCArPSB0YWtlO1xuICAgICAgICAgICAgcG9zICs9IHRha2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIGRpZ2VzdEludG8ob3V0KSB7XG4gICAgICAgIGFleGlzdHModGhpcyk7XG4gICAgICAgIGFvdXRwdXQob3V0LCB0aGlzKTtcbiAgICAgICAgY29uc3QgeyBwb3MsIGJ1ZmZlcjMyIH0gPSB0aGlzO1xuICAgICAgICB0aGlzLmZpbmlzaGVkID0gdHJ1ZTtcbiAgICAgICAgLy8gUGFkZGluZ1xuICAgICAgICB0aGlzLmJ1ZmZlci5zdWJhcnJheShwb3MpLmZpbGwoMCk7XG4gICAgICAgIGlmICghaXNMRSlcbiAgICAgICAgICAgIGJ5dGVTd2FwMzIoYnVmZmVyMzIpO1xuICAgICAgICB0aGlzLmNvbXByZXNzKGJ1ZmZlcjMyLCAwLCB0cnVlKTtcbiAgICAgICAgaWYgKCFpc0xFKVxuICAgICAgICAgICAgYnl0ZVN3YXAzMihidWZmZXIzMik7XG4gICAgICAgIGNvbnN0IG91dDMyID0gdTMyKG91dCk7XG4gICAgICAgIHRoaXMuZ2V0KCkuZm9yRWFjaCgodiwgaSkgPT4gKG91dDMyW2ldID0gYnl0ZVN3YXBJZkJFKHYpKSk7XG4gICAgfVxuICAgIGRpZ2VzdCgpIHtcbiAgICAgICAgY29uc3QgeyBidWZmZXIsIG91dHB1dExlbiB9ID0gdGhpcztcbiAgICAgICAgdGhpcy5kaWdlc3RJbnRvKGJ1ZmZlcik7XG4gICAgICAgIGNvbnN0IHJlcyA9IGJ1ZmZlci5zbGljZSgwLCBvdXRwdXRMZW4pO1xuICAgICAgICB0aGlzLmRlc3Ryb3koKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG4gICAgX2Nsb25lSW50byh0bykge1xuICAgICAgICBjb25zdCB7IGJ1ZmZlciwgbGVuZ3RoLCBmaW5pc2hlZCwgZGVzdHJveWVkLCBvdXRwdXRMZW4sIHBvcyB9ID0gdGhpcztcbiAgICAgICAgdG8gfHwgKHRvID0gbmV3IHRoaXMuY29uc3RydWN0b3IoeyBka0xlbjogb3V0cHV0TGVuIH0pKTtcbiAgICAgICAgdG8uc2V0KC4uLnRoaXMuZ2V0KCkpO1xuICAgICAgICB0by5sZW5ndGggPSBsZW5ndGg7XG4gICAgICAgIHRvLmZpbmlzaGVkID0gZmluaXNoZWQ7XG4gICAgICAgIHRvLmRlc3Ryb3llZCA9IGRlc3Ryb3llZDtcbiAgICAgICAgdG8ub3V0cHV0TGVuID0gb3V0cHV0TGVuO1xuICAgICAgICB0by5idWZmZXIuc2V0KGJ1ZmZlcik7XG4gICAgICAgIHRvLnBvcyA9IHBvcztcbiAgICAgICAgcmV0dXJuIHRvO1xuICAgIH1cbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPV9ibGFrZS5qcy5tYXAiLCIvKipcbiAqIEludGVybmFsIGhlbHBlcnMgZm9yIHU2NC4gQmlnVWludDY0QXJyYXkgaXMgdG9vIHNsb3cgYXMgcGVyIDIwMjUsIHNvIHdlIGltcGxlbWVudCBpdCB1c2luZyBVaW50MzJBcnJheS5cbiAqIEB0b2RvIHJlLWNoZWNrIGh0dHBzOi8vaXNzdWVzLmNocm9taXVtLm9yZy9pc3N1ZXMvNDIyMTI1ODhcbiAqIEBtb2R1bGVcbiAqL1xuY29uc3QgVTMyX01BU0s2NCA9IC8qIEBfX1BVUkVfXyAqLyBCaWdJbnQoMiAqKiAzMiAtIDEpO1xuY29uc3QgXzMybiA9IC8qIEBfX1BVUkVfXyAqLyBCaWdJbnQoMzIpO1xuZnVuY3Rpb24gZnJvbUJpZyhuLCBsZSA9IGZhbHNlKSB7XG4gICAgaWYgKGxlKVxuICAgICAgICByZXR1cm4geyBoOiBOdW1iZXIobiAmIFUzMl9NQVNLNjQpLCBsOiBOdW1iZXIoKG4gPj4gXzMybikgJiBVMzJfTUFTSzY0KSB9O1xuICAgIHJldHVybiB7IGg6IE51bWJlcigobiA+PiBfMzJuKSAmIFUzMl9NQVNLNjQpIHwgMCwgbDogTnVtYmVyKG4gJiBVMzJfTUFTSzY0KSB8IDAgfTtcbn1cbmZ1bmN0aW9uIHNwbGl0KGxzdCwgbGUgPSBmYWxzZSkge1xuICAgIGxldCBBaCA9IG5ldyBVaW50MzJBcnJheShsc3QubGVuZ3RoKTtcbiAgICBsZXQgQWwgPSBuZXcgVWludDMyQXJyYXkobHN0Lmxlbmd0aCk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgeyBoLCBsIH0gPSBmcm9tQmlnKGxzdFtpXSwgbGUpO1xuICAgICAgICBbQWhbaV0sIEFsW2ldXSA9IFtoLCBsXTtcbiAgICB9XG4gICAgcmV0dXJuIFtBaCwgQWxdO1xufVxuY29uc3QgdG9CaWcgPSAoaCwgbCkgPT4gKEJpZ0ludChoID4+PiAwKSA8PCBfMzJuKSB8IEJpZ0ludChsID4+PiAwKTtcbi8vIGZvciBTaGlmdCBpbiBbMCwgMzIpXG5jb25zdCBzaHJTSCA9IChoLCBfbCwgcykgPT4gaCA+Pj4gcztcbmNvbnN0IHNoclNMID0gKGgsIGwsIHMpID0+IChoIDw8ICgzMiAtIHMpKSB8IChsID4+PiBzKTtcbi8vIFJpZ2h0IHJvdGF0ZSBmb3IgU2hpZnQgaW4gWzEsIDMyKVxuY29uc3Qgcm90clNIID0gKGgsIGwsIHMpID0+IChoID4+PiBzKSB8IChsIDw8ICgzMiAtIHMpKTtcbmNvbnN0IHJvdHJTTCA9IChoLCBsLCBzKSA9PiAoaCA8PCAoMzIgLSBzKSkgfCAobCA+Pj4gcyk7XG4vLyBSaWdodCByb3RhdGUgZm9yIFNoaWZ0IGluICgzMiwgNjQpLCBOT1RFOiAzMiBpcyBzcGVjaWFsIGNhc2UuXG5jb25zdCByb3RyQkggPSAoaCwgbCwgcykgPT4gKGggPDwgKDY0IC0gcykpIHwgKGwgPj4+IChzIC0gMzIpKTtcbmNvbnN0IHJvdHJCTCA9IChoLCBsLCBzKSA9PiAoaCA+Pj4gKHMgLSAzMikpIHwgKGwgPDwgKDY0IC0gcykpO1xuLy8gUmlnaHQgcm90YXRlIGZvciBzaGlmdD09PTMyIChqdXN0IHN3YXBzIGwmaClcbmNvbnN0IHJvdHIzMkggPSAoX2gsIGwpID0+IGw7XG5jb25zdCByb3RyMzJMID0gKGgsIF9sKSA9PiBoO1xuLy8gTGVmdCByb3RhdGUgZm9yIFNoaWZ0IGluIFsxLCAzMilcbmNvbnN0IHJvdGxTSCA9IChoLCBsLCBzKSA9PiAoaCA8PCBzKSB8IChsID4+PiAoMzIgLSBzKSk7XG5jb25zdCByb3RsU0wgPSAoaCwgbCwgcykgPT4gKGwgPDwgcykgfCAoaCA+Pj4gKDMyIC0gcykpO1xuLy8gTGVmdCByb3RhdGUgZm9yIFNoaWZ0IGluICgzMiwgNjQpLCBOT1RFOiAzMiBpcyBzcGVjaWFsIGNhc2UuXG5jb25zdCByb3RsQkggPSAoaCwgbCwgcykgPT4gKGwgPDwgKHMgLSAzMikpIHwgKGggPj4+ICg2NCAtIHMpKTtcbmNvbnN0IHJvdGxCTCA9IChoLCBsLCBzKSA9PiAoaCA8PCAocyAtIDMyKSkgfCAobCA+Pj4gKDY0IC0gcykpO1xuLy8gSlMgdXNlcyAzMi1iaXQgc2lnbmVkIGludGVnZXJzIGZvciBiaXR3aXNlIG9wZXJhdGlvbnMgd2hpY2ggbWVhbnMgd2UgY2Fubm90XG4vLyBzaW1wbGUgdGFrZSBjYXJyeSBvdXQgb2YgbG93IGJpdCBzdW0gYnkgc2hpZnQsIHdlIG5lZWQgdG8gdXNlIGRpdmlzaW9uLlxuZnVuY3Rpb24gYWRkKEFoLCBBbCwgQmgsIEJsKSB7XG4gICAgY29uc3QgbCA9IChBbCA+Pj4gMCkgKyAoQmwgPj4+IDApO1xuICAgIHJldHVybiB7IGg6IChBaCArIEJoICsgKChsIC8gMiAqKiAzMikgfCAwKSkgfCAwLCBsOiBsIHwgMCB9O1xufVxuLy8gQWRkaXRpb24gd2l0aCBtb3JlIHRoYW4gMiBlbGVtZW50c1xuY29uc3QgYWRkM0wgPSAoQWwsIEJsLCBDbCkgPT4gKEFsID4+PiAwKSArIChCbCA+Pj4gMCkgKyAoQ2wgPj4+IDApO1xuY29uc3QgYWRkM0ggPSAobG93LCBBaCwgQmgsIENoKSA9PiAoQWggKyBCaCArIENoICsgKChsb3cgLyAyICoqIDMyKSB8IDApKSB8IDA7XG5jb25zdCBhZGQ0TCA9IChBbCwgQmwsIENsLCBEbCkgPT4gKEFsID4+PiAwKSArIChCbCA+Pj4gMCkgKyAoQ2wgPj4+IDApICsgKERsID4+PiAwKTtcbmNvbnN0IGFkZDRIID0gKGxvdywgQWgsIEJoLCBDaCwgRGgpID0+IChBaCArIEJoICsgQ2ggKyBEaCArICgobG93IC8gMiAqKiAzMikgfCAwKSkgfCAwO1xuY29uc3QgYWRkNUwgPSAoQWwsIEJsLCBDbCwgRGwsIEVsKSA9PiAoQWwgPj4+IDApICsgKEJsID4+PiAwKSArIChDbCA+Pj4gMCkgKyAoRGwgPj4+IDApICsgKEVsID4+PiAwKTtcbmNvbnN0IGFkZDVIID0gKGxvdywgQWgsIEJoLCBDaCwgRGgsIEVoKSA9PiAoQWggKyBCaCArIENoICsgRGggKyBFaCArICgobG93IC8gMiAqKiAzMikgfCAwKSkgfCAwO1xuLy8gcHJldHRpZXItaWdub3JlXG5leHBvcnQgeyBmcm9tQmlnLCBzcGxpdCwgdG9CaWcsIHNoclNILCBzaHJTTCwgcm90clNILCByb3RyU0wsIHJvdHJCSCwgcm90ckJMLCByb3RyMzJILCByb3RyMzJMLCByb3RsU0gsIHJvdGxTTCwgcm90bEJILCByb3RsQkwsIGFkZCwgYWRkM0wsIGFkZDNILCBhZGQ0TCwgYWRkNEgsIGFkZDVILCBhZGQ1TCwgfTtcbi8vIHByZXR0aWVyLWlnbm9yZVxuY29uc3QgdTY0ID0ge1xuICAgIGZyb21CaWcsIHNwbGl0LCB0b0JpZyxcbiAgICBzaHJTSCwgc2hyU0wsXG4gICAgcm90clNILCByb3RyU0wsIHJvdHJCSCwgcm90ckJMLFxuICAgIHJvdHIzMkgsIHJvdHIzMkwsXG4gICAgcm90bFNILCByb3RsU0wsIHJvdGxCSCwgcm90bEJMLFxuICAgIGFkZCwgYWRkM0wsIGFkZDNILCBhZGQ0TCwgYWRkNEgsIGFkZDVILCBhZGQ1TCxcbn07XG5leHBvcnQgZGVmYXVsdCB1NjQ7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1fdTY0LmpzLm1hcCIsIi8qKlxuICogQmxha2UyYiBoYXNoIGZ1bmN0aW9uLiBGb2N1c2VzIG9uIDY0LWJpdCBwbGF0Zm9ybXMsIGJ1dCBpbiBKUyBzcGVlZCBkaWZmZXJlbnQgZnJvbSBCbGFrZTJzIGlzIG5lZ2xpZ2libGUuXG4gKiBAbW9kdWxlXG4gKi9cbmltcG9ydCB7IEJMQUtFLCBTSUdNQSB9IGZyb20gJy4vX2JsYWtlLmpzJztcbmltcG9ydCB1NjQgZnJvbSAnLi9fdTY0LmpzJztcbmltcG9ydCB7IGJ5dGVTd2FwSWZCRSwgdG9CeXRlcywgdTMyLCB3cmFwQ29uc3RydWN0b3JXaXRoT3B0cyB9IGZyb20gJy4vdXRpbHMuanMnO1xuLy8gU2FtZSBhcyBTSEEtNTEyIGJ1dCBMRVxuLy8gcHJldHRpZXItaWdub3JlXG5jb25zdCBCMkJfSVYgPSAvKiBAX19QVVJFX18gKi8gbmV3IFVpbnQzMkFycmF5KFtcbiAgICAweGYzYmNjOTA4LCAweDZhMDllNjY3LCAweDg0Y2FhNzNiLCAweGJiNjdhZTg1LCAweGZlOTRmODJiLCAweDNjNmVmMzcyLCAweDVmMWQzNmYxLCAweGE1NGZmNTNhLFxuICAgIDB4YWRlNjgyZDEsIDB4NTEwZTUyN2YsIDB4MmIzZTZjMWYsIDB4OWIwNTY4OGMsIDB4ZmI0MWJkNmIsIDB4MWY4M2Q5YWIsIDB4MTM3ZTIxNzksIDB4NWJlMGNkMTlcbl0pO1xuLy8gVGVtcG9yYXJ5IGJ1ZmZlclxuY29uc3QgQkJVRiA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgVWludDMyQXJyYXkoMzIpO1xuLy8gTWl4aW5nIGZ1bmN0aW9uIEcgc3BsaXR0ZWQgaW4gdHdvIGhhbGZzXG5mdW5jdGlvbiBHMWIoYSwgYiwgYywgZCwgbXNnLCB4KSB7XG4gICAgLy8gTk9URTogViBpcyBMRSBoZXJlXG4gICAgY29uc3QgWGwgPSBtc2dbeF0sIFhoID0gbXNnW3ggKyAxXTsgLy8gcHJldHRpZXItaWdub3JlXG4gICAgbGV0IEFsID0gQkJVRlsyICogYV0sIEFoID0gQkJVRlsyICogYSArIDFdOyAvLyBwcmV0dGllci1pZ25vcmVcbiAgICBsZXQgQmwgPSBCQlVGWzIgKiBiXSwgQmggPSBCQlVGWzIgKiBiICsgMV07IC8vIHByZXR0aWVyLWlnbm9yZVxuICAgIGxldCBDbCA9IEJCVUZbMiAqIGNdLCBDaCA9IEJCVUZbMiAqIGMgKyAxXTsgLy8gcHJldHRpZXItaWdub3JlXG4gICAgbGV0IERsID0gQkJVRlsyICogZF0sIERoID0gQkJVRlsyICogZCArIDFdOyAvLyBwcmV0dGllci1pZ25vcmVcbiAgICAvLyB2W2FdID0gKHZbYV0gKyB2W2JdICsgeCkgfCAwO1xuICAgIGxldCBsbCA9IHU2NC5hZGQzTChBbCwgQmwsIFhsKTtcbiAgICBBaCA9IHU2NC5hZGQzSChsbCwgQWgsIEJoLCBYaCk7XG4gICAgQWwgPSBsbCB8IDA7XG4gICAgLy8gdltkXSA9IHJvdHIodltkXSBeIHZbYV0sIDMyKVxuICAgICh7IERoLCBEbCB9ID0geyBEaDogRGggXiBBaCwgRGw6IERsIF4gQWwgfSk7XG4gICAgKHsgRGgsIERsIH0gPSB7IERoOiB1NjQucm90cjMySChEaCwgRGwpLCBEbDogdTY0LnJvdHIzMkwoRGgsIERsKSB9KTtcbiAgICAvLyB2W2NdID0gKHZbY10gKyB2W2RdKSB8IDA7XG4gICAgKHsgaDogQ2gsIGw6IENsIH0gPSB1NjQuYWRkKENoLCBDbCwgRGgsIERsKSk7XG4gICAgLy8gdltiXSA9IHJvdHIodltiXSBeIHZbY10sIDI0KVxuICAgICh7IEJoLCBCbCB9ID0geyBCaDogQmggXiBDaCwgQmw6IEJsIF4gQ2wgfSk7XG4gICAgKHsgQmgsIEJsIH0gPSB7IEJoOiB1NjQucm90clNIKEJoLCBCbCwgMjQpLCBCbDogdTY0LnJvdHJTTChCaCwgQmwsIDI0KSB9KTtcbiAgICAoQkJVRlsyICogYV0gPSBBbCksIChCQlVGWzIgKiBhICsgMV0gPSBBaCk7XG4gICAgKEJCVUZbMiAqIGJdID0gQmwpLCAoQkJVRlsyICogYiArIDFdID0gQmgpO1xuICAgIChCQlVGWzIgKiBjXSA9IENsKSwgKEJCVUZbMiAqIGMgKyAxXSA9IENoKTtcbiAgICAoQkJVRlsyICogZF0gPSBEbCksIChCQlVGWzIgKiBkICsgMV0gPSBEaCk7XG59XG5mdW5jdGlvbiBHMmIoYSwgYiwgYywgZCwgbXNnLCB4KSB7XG4gICAgLy8gTk9URTogViBpcyBMRSBoZXJlXG4gICAgY29uc3QgWGwgPSBtc2dbeF0sIFhoID0gbXNnW3ggKyAxXTsgLy8gcHJldHRpZXItaWdub3JlXG4gICAgbGV0IEFsID0gQkJVRlsyICogYV0sIEFoID0gQkJVRlsyICogYSArIDFdOyAvLyBwcmV0dGllci1pZ25vcmVcbiAgICBsZXQgQmwgPSBCQlVGWzIgKiBiXSwgQmggPSBCQlVGWzIgKiBiICsgMV07IC8vIHByZXR0aWVyLWlnbm9yZVxuICAgIGxldCBDbCA9IEJCVUZbMiAqIGNdLCBDaCA9IEJCVUZbMiAqIGMgKyAxXTsgLy8gcHJldHRpZXItaWdub3JlXG4gICAgbGV0IERsID0gQkJVRlsyICogZF0sIERoID0gQkJVRlsyICogZCArIDFdOyAvLyBwcmV0dGllci1pZ25vcmVcbiAgICAvLyB2W2FdID0gKHZbYV0gKyB2W2JdICsgeCkgfCAwO1xuICAgIGxldCBsbCA9IHU2NC5hZGQzTChBbCwgQmwsIFhsKTtcbiAgICBBaCA9IHU2NC5hZGQzSChsbCwgQWgsIEJoLCBYaCk7XG4gICAgQWwgPSBsbCB8IDA7XG4gICAgLy8gdltkXSA9IHJvdHIodltkXSBeIHZbYV0sIDE2KVxuICAgICh7IERoLCBEbCB9ID0geyBEaDogRGggXiBBaCwgRGw6IERsIF4gQWwgfSk7XG4gICAgKHsgRGgsIERsIH0gPSB7IERoOiB1NjQucm90clNIKERoLCBEbCwgMTYpLCBEbDogdTY0LnJvdHJTTChEaCwgRGwsIDE2KSB9KTtcbiAgICAvLyB2W2NdID0gKHZbY10gKyB2W2RdKSB8IDA7XG4gICAgKHsgaDogQ2gsIGw6IENsIH0gPSB1NjQuYWRkKENoLCBDbCwgRGgsIERsKSk7XG4gICAgLy8gdltiXSA9IHJvdHIodltiXSBeIHZbY10sIDYzKVxuICAgICh7IEJoLCBCbCB9ID0geyBCaDogQmggXiBDaCwgQmw6IEJsIF4gQ2wgfSk7XG4gICAgKHsgQmgsIEJsIH0gPSB7IEJoOiB1NjQucm90ckJIKEJoLCBCbCwgNjMpLCBCbDogdTY0LnJvdHJCTChCaCwgQmwsIDYzKSB9KTtcbiAgICAoQkJVRlsyICogYV0gPSBBbCksIChCQlVGWzIgKiBhICsgMV0gPSBBaCk7XG4gICAgKEJCVUZbMiAqIGJdID0gQmwpLCAoQkJVRlsyICogYiArIDFdID0gQmgpO1xuICAgIChCQlVGWzIgKiBjXSA9IENsKSwgKEJCVUZbMiAqIGMgKyAxXSA9IENoKTtcbiAgICAoQkJVRlsyICogZF0gPSBEbCksIChCQlVGWzIgKiBkICsgMV0gPSBEaCk7XG59XG5leHBvcnQgY2xhc3MgQkxBS0UyYiBleHRlbmRzIEJMQUtFIHtcbiAgICBjb25zdHJ1Y3RvcihvcHRzID0ge30pIHtcbiAgICAgICAgc3VwZXIoMTI4LCBvcHRzLmRrTGVuID09PSB1bmRlZmluZWQgPyA2NCA6IG9wdHMuZGtMZW4sIG9wdHMsIDY0LCAxNiwgMTYpO1xuICAgICAgICAvLyBTYW1lIGFzIFNIQS01MTIsIGJ1dCBMRVxuICAgICAgICB0aGlzLnYwbCA9IEIyQl9JVlswXSB8IDA7XG4gICAgICAgIHRoaXMudjBoID0gQjJCX0lWWzFdIHwgMDtcbiAgICAgICAgdGhpcy52MWwgPSBCMkJfSVZbMl0gfCAwO1xuICAgICAgICB0aGlzLnYxaCA9IEIyQl9JVlszXSB8IDA7XG4gICAgICAgIHRoaXMudjJsID0gQjJCX0lWWzRdIHwgMDtcbiAgICAgICAgdGhpcy52MmggPSBCMkJfSVZbNV0gfCAwO1xuICAgICAgICB0aGlzLnYzbCA9IEIyQl9JVls2XSB8IDA7XG4gICAgICAgIHRoaXMudjNoID0gQjJCX0lWWzddIHwgMDtcbiAgICAgICAgdGhpcy52NGwgPSBCMkJfSVZbOF0gfCAwO1xuICAgICAgICB0aGlzLnY0aCA9IEIyQl9JVls5XSB8IDA7XG4gICAgICAgIHRoaXMudjVsID0gQjJCX0lWWzEwXSB8IDA7XG4gICAgICAgIHRoaXMudjVoID0gQjJCX0lWWzExXSB8IDA7XG4gICAgICAgIHRoaXMudjZsID0gQjJCX0lWWzEyXSB8IDA7XG4gICAgICAgIHRoaXMudjZoID0gQjJCX0lWWzEzXSB8IDA7XG4gICAgICAgIHRoaXMudjdsID0gQjJCX0lWWzE0XSB8IDA7XG4gICAgICAgIHRoaXMudjdoID0gQjJCX0lWWzE1XSB8IDA7XG4gICAgICAgIGNvbnN0IGtleUxlbmd0aCA9IG9wdHMua2V5ID8gb3B0cy5rZXkubGVuZ3RoIDogMDtcbiAgICAgICAgdGhpcy52MGwgXj0gdGhpcy5vdXRwdXRMZW4gfCAoa2V5TGVuZ3RoIDw8IDgpIHwgKDB4MDEgPDwgMTYpIHwgKDB4MDEgPDwgMjQpO1xuICAgICAgICBpZiAob3B0cy5zYWx0KSB7XG4gICAgICAgICAgICBjb25zdCBzYWx0ID0gdTMyKHRvQnl0ZXMob3B0cy5zYWx0KSk7XG4gICAgICAgICAgICB0aGlzLnY0bCBePSBieXRlU3dhcElmQkUoc2FsdFswXSk7XG4gICAgICAgICAgICB0aGlzLnY0aCBePSBieXRlU3dhcElmQkUoc2FsdFsxXSk7XG4gICAgICAgICAgICB0aGlzLnY1bCBePSBieXRlU3dhcElmQkUoc2FsdFsyXSk7XG4gICAgICAgICAgICB0aGlzLnY1aCBePSBieXRlU3dhcElmQkUoc2FsdFszXSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdHMucGVyc29uYWxpemF0aW9uKSB7XG4gICAgICAgICAgICBjb25zdCBwZXJzID0gdTMyKHRvQnl0ZXMob3B0cy5wZXJzb25hbGl6YXRpb24pKTtcbiAgICAgICAgICAgIHRoaXMudjZsIF49IGJ5dGVTd2FwSWZCRShwZXJzWzBdKTtcbiAgICAgICAgICAgIHRoaXMudjZoIF49IGJ5dGVTd2FwSWZCRShwZXJzWzFdKTtcbiAgICAgICAgICAgIHRoaXMudjdsIF49IGJ5dGVTd2FwSWZCRShwZXJzWzJdKTtcbiAgICAgICAgICAgIHRoaXMudjdoIF49IGJ5dGVTd2FwSWZCRShwZXJzWzNdKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0cy5rZXkpIHtcbiAgICAgICAgICAgIC8vIFBhZCB0byBibG9ja0xlbiBhbmQgdXBkYXRlXG4gICAgICAgICAgICBjb25zdCB0bXAgPSBuZXcgVWludDhBcnJheSh0aGlzLmJsb2NrTGVuKTtcbiAgICAgICAgICAgIHRtcC5zZXQodG9CeXRlcyhvcHRzLmtleSkpO1xuICAgICAgICAgICAgdGhpcy51cGRhdGUodG1wKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBwcmV0dGllci1pZ25vcmVcbiAgICBnZXQoKSB7XG4gICAgICAgIGxldCB7IHYwbCwgdjBoLCB2MWwsIHYxaCwgdjJsLCB2MmgsIHYzbCwgdjNoLCB2NGwsIHY0aCwgdjVsLCB2NWgsIHY2bCwgdjZoLCB2N2wsIHY3aCB9ID0gdGhpcztcbiAgICAgICAgcmV0dXJuIFt2MGwsIHYwaCwgdjFsLCB2MWgsIHYybCwgdjJoLCB2M2wsIHYzaCwgdjRsLCB2NGgsIHY1bCwgdjVoLCB2NmwsIHY2aCwgdjdsLCB2N2hdO1xuICAgIH1cbiAgICAvLyBwcmV0dGllci1pZ25vcmVcbiAgICBzZXQodjBsLCB2MGgsIHYxbCwgdjFoLCB2MmwsIHYyaCwgdjNsLCB2M2gsIHY0bCwgdjRoLCB2NWwsIHY1aCwgdjZsLCB2NmgsIHY3bCwgdjdoKSB7XG4gICAgICAgIHRoaXMudjBsID0gdjBsIHwgMDtcbiAgICAgICAgdGhpcy52MGggPSB2MGggfCAwO1xuICAgICAgICB0aGlzLnYxbCA9IHYxbCB8IDA7XG4gICAgICAgIHRoaXMudjFoID0gdjFoIHwgMDtcbiAgICAgICAgdGhpcy52MmwgPSB2MmwgfCAwO1xuICAgICAgICB0aGlzLnYyaCA9IHYyaCB8IDA7XG4gICAgICAgIHRoaXMudjNsID0gdjNsIHwgMDtcbiAgICAgICAgdGhpcy52M2ggPSB2M2ggfCAwO1xuICAgICAgICB0aGlzLnY0bCA9IHY0bCB8IDA7XG4gICAgICAgIHRoaXMudjRoID0gdjRoIHwgMDtcbiAgICAgICAgdGhpcy52NWwgPSB2NWwgfCAwO1xuICAgICAgICB0aGlzLnY1aCA9IHY1aCB8IDA7XG4gICAgICAgIHRoaXMudjZsID0gdjZsIHwgMDtcbiAgICAgICAgdGhpcy52NmggPSB2NmggfCAwO1xuICAgICAgICB0aGlzLnY3bCA9IHY3bCB8IDA7XG4gICAgICAgIHRoaXMudjdoID0gdjdoIHwgMDtcbiAgICB9XG4gICAgY29tcHJlc3MobXNnLCBvZmZzZXQsIGlzTGFzdCkge1xuICAgICAgICB0aGlzLmdldCgpLmZvckVhY2goKHYsIGkpID0+IChCQlVGW2ldID0gdikpOyAvLyBGaXJzdCBoYWxmIGZyb20gc3RhdGUuXG4gICAgICAgIEJCVUYuc2V0KEIyQl9JViwgMTYpOyAvLyBTZWNvbmQgaGFsZiBmcm9tIElWLlxuICAgICAgICBsZXQgeyBoLCBsIH0gPSB1NjQuZnJvbUJpZyhCaWdJbnQodGhpcy5sZW5ndGgpKTtcbiAgICAgICAgQkJVRlsyNF0gPSBCMkJfSVZbOF0gXiBsOyAvLyBMb3cgd29yZCBvZiB0aGUgb2Zmc2V0LlxuICAgICAgICBCQlVGWzI1XSA9IEIyQl9JVls5XSBeIGg7IC8vIEhpZ2ggd29yZC5cbiAgICAgICAgLy8gSW52ZXJ0IGFsbCBiaXRzIGZvciBsYXN0IGJsb2NrXG4gICAgICAgIGlmIChpc0xhc3QpIHtcbiAgICAgICAgICAgIEJCVUZbMjhdID0gfkJCVUZbMjhdO1xuICAgICAgICAgICAgQkJVRlsyOV0gPSB+QkJVRlsyOV07XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGogPSAwO1xuICAgICAgICBjb25zdCBzID0gU0lHTUE7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMTI7IGkrKykge1xuICAgICAgICAgICAgRzFiKDAsIDQsIDgsIDEyLCBtc2csIG9mZnNldCArIDIgKiBzW2orK10pO1xuICAgICAgICAgICAgRzJiKDAsIDQsIDgsIDEyLCBtc2csIG9mZnNldCArIDIgKiBzW2orK10pO1xuICAgICAgICAgICAgRzFiKDEsIDUsIDksIDEzLCBtc2csIG9mZnNldCArIDIgKiBzW2orK10pO1xuICAgICAgICAgICAgRzJiKDEsIDUsIDksIDEzLCBtc2csIG9mZnNldCArIDIgKiBzW2orK10pO1xuICAgICAgICAgICAgRzFiKDIsIDYsIDEwLCAxNCwgbXNnLCBvZmZzZXQgKyAyICogc1tqKytdKTtcbiAgICAgICAgICAgIEcyYigyLCA2LCAxMCwgMTQsIG1zZywgb2Zmc2V0ICsgMiAqIHNbaisrXSk7XG4gICAgICAgICAgICBHMWIoMywgNywgMTEsIDE1LCBtc2csIG9mZnNldCArIDIgKiBzW2orK10pO1xuICAgICAgICAgICAgRzJiKDMsIDcsIDExLCAxNSwgbXNnLCBvZmZzZXQgKyAyICogc1tqKytdKTtcbiAgICAgICAgICAgIEcxYigwLCA1LCAxMCwgMTUsIG1zZywgb2Zmc2V0ICsgMiAqIHNbaisrXSk7XG4gICAgICAgICAgICBHMmIoMCwgNSwgMTAsIDE1LCBtc2csIG9mZnNldCArIDIgKiBzW2orK10pO1xuICAgICAgICAgICAgRzFiKDEsIDYsIDExLCAxMiwgbXNnLCBvZmZzZXQgKyAyICogc1tqKytdKTtcbiAgICAgICAgICAgIEcyYigxLCA2LCAxMSwgMTIsIG1zZywgb2Zmc2V0ICsgMiAqIHNbaisrXSk7XG4gICAgICAgICAgICBHMWIoMiwgNywgOCwgMTMsIG1zZywgb2Zmc2V0ICsgMiAqIHNbaisrXSk7XG4gICAgICAgICAgICBHMmIoMiwgNywgOCwgMTMsIG1zZywgb2Zmc2V0ICsgMiAqIHNbaisrXSk7XG4gICAgICAgICAgICBHMWIoMywgNCwgOSwgMTQsIG1zZywgb2Zmc2V0ICsgMiAqIHNbaisrXSk7XG4gICAgICAgICAgICBHMmIoMywgNCwgOSwgMTQsIG1zZywgb2Zmc2V0ICsgMiAqIHNbaisrXSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy52MGwgXj0gQkJVRlswXSBeIEJCVUZbMTZdO1xuICAgICAgICB0aGlzLnYwaCBePSBCQlVGWzFdIF4gQkJVRlsxN107XG4gICAgICAgIHRoaXMudjFsIF49IEJCVUZbMl0gXiBCQlVGWzE4XTtcbiAgICAgICAgdGhpcy52MWggXj0gQkJVRlszXSBeIEJCVUZbMTldO1xuICAgICAgICB0aGlzLnYybCBePSBCQlVGWzRdIF4gQkJVRlsyMF07XG4gICAgICAgIHRoaXMudjJoIF49IEJCVUZbNV0gXiBCQlVGWzIxXTtcbiAgICAgICAgdGhpcy52M2wgXj0gQkJVRls2XSBeIEJCVUZbMjJdO1xuICAgICAgICB0aGlzLnYzaCBePSBCQlVGWzddIF4gQkJVRlsyM107XG4gICAgICAgIHRoaXMudjRsIF49IEJCVUZbOF0gXiBCQlVGWzI0XTtcbiAgICAgICAgdGhpcy52NGggXj0gQkJVRls5XSBeIEJCVUZbMjVdO1xuICAgICAgICB0aGlzLnY1bCBePSBCQlVGWzEwXSBeIEJCVUZbMjZdO1xuICAgICAgICB0aGlzLnY1aCBePSBCQlVGWzExXSBeIEJCVUZbMjddO1xuICAgICAgICB0aGlzLnY2bCBePSBCQlVGWzEyXSBeIEJCVUZbMjhdO1xuICAgICAgICB0aGlzLnY2aCBePSBCQlVGWzEzXSBeIEJCVUZbMjldO1xuICAgICAgICB0aGlzLnY3bCBePSBCQlVGWzE0XSBeIEJCVUZbMzBdO1xuICAgICAgICB0aGlzLnY3aCBePSBCQlVGWzE1XSBeIEJCVUZbMzFdO1xuICAgICAgICBCQlVGLmZpbGwoMCk7XG4gICAgfVxuICAgIGRlc3Ryb3koKSB7XG4gICAgICAgIHRoaXMuZGVzdHJveWVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5idWZmZXIzMi5maWxsKDApO1xuICAgICAgICB0aGlzLnNldCgwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwKTtcbiAgICB9XG59XG4vKipcbiAqIEJsYWtlMmIgaGFzaCBmdW5jdGlvbi4gRm9jdXNlcyBvbiA2NC1iaXQgcGxhdGZvcm1zLCBidXQgaW4gSlMgc3BlZWQgZGlmZmVyZW50IGZyb20gQmxha2UycyBpcyBuZWdsaWdpYmxlLlxuICogQHBhcmFtIG1zZyAtIG1lc3NhZ2UgdGhhdCB3b3VsZCBiZSBoYXNoZWRcbiAqIEBwYXJhbSBvcHRzIC0gZGtMZW4gb3V0cHV0IGxlbmd0aCwga2V5IGZvciBNQUMgbW9kZSwgc2FsdCwgcGVyc29uYWxpemF0aW9uXG4gKi9cbmV4cG9ydCBjb25zdCBibGFrZTJiID0gLyogQF9fUFVSRV9fICovIHdyYXBDb25zdHJ1Y3RvcldpdGhPcHRzKChvcHRzKSA9PiBuZXcgQkxBS0UyYihvcHRzKSk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1ibGFrZTJiLmpzLm1hcCIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMTggMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya0pTLlxuXG4gICAgc25hcmtKUyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJrSlMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggc25hcmtKUy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbi8qIGdsb2JhbCB3aW5kb3cgKi9cbmltcG9ydCB7IGJsYWtlMmIgfSBmcm9tIFwiQG5vYmxlL2hhc2hlcy9ibGFrZTJiXCI7XG5pbXBvcnQgeyB1MzIgfSBmcm9tIFwiQG5vYmxlL2hhc2hlcy91dGlsc1wiO1xuaW1wb3J0IHJlYWRsaW5lIGZyb20gXCJyZWFkbGluZVwiO1xuaW1wb3J0IHsgQ2hhQ2hhIH0gZnJvbSBcImZmamF2YXNjcmlwdFwiO1xuaW1wb3J0IGNyeXB0byBmcm9tIFwiY3J5cHRvXCI7XG5cbmNvbnN0IF9yZXZUYWJsZSA9IFtdO1xuZm9yIChsZXQgaT0wOyBpPDI1NjsgaSsrKSB7XG4gICAgX3JldlRhYmxlW2ldID0gX3JldlNsb3coaSwgOCk7XG59XG5cbmZ1bmN0aW9uIF9yZXZTbG93KGlkeCwgYml0cykge1xuICAgIGxldCByZXMgPTA7XG4gICAgbGV0IGEgPSBpZHg7XG4gICAgZm9yIChsZXQgaT0wOyBpPGJpdHM7IGkrKykge1xuICAgICAgICByZXMgPDw9IDE7XG4gICAgICAgIHJlcyA9IHJlcyB8IChhICYxKTtcbiAgICAgICAgYSA+Pj0xO1xuICAgIH1cbiAgICByZXR1cm4gcmVzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYml0UmV2ZXJzZShpZHgsIGJpdHMpIHtcbiAgICByZXR1cm4gKFxuICAgICAgICBfcmV2VGFibGVbaWR4ID4+PiAyNF0gfFxuICAgICAgICAoX3JldlRhYmxlWyhpZHggPj4+IDE2KSAmIDB4RkZdIDw8IDgpIHxcbiAgICAgICAgKF9yZXZUYWJsZVsoaWR4ID4+PiA4KSAmIDB4RkZdIDw8IDE2KSB8XG4gICAgICAgIChfcmV2VGFibGVbaWR4ICYgMHhGRl0gPDwgMjQpXG4gICAgKSA+Pj4gKDMyLWJpdHMpO1xufVxuXG5cbmV4cG9ydCBmdW5jdGlvbiBsb2cyKCBWIClcbntcbiAgICByZXR1cm4oICggKCBWICYgMHhGRkZGMDAwMCApICE9PSAwID8gKCBWICY9IDB4RkZGRjAwMDAsIDE2ICkgOiAwICkgfCAoICggViAmIDB4RkYwMEZGMDAgKSAhPT0gMCA/ICggViAmPSAweEZGMDBGRjAwLCA4ICkgOiAwICkgfCAoICggViAmIDB4RjBGMEYwRjAgKSAhPT0gMCA/ICggViAmPSAweEYwRjBGMEYwLCA0ICkgOiAwICkgfCAoICggViAmIDB4Q0NDQ0NDQ0MgKSAhPT0gMCA/ICggViAmPSAweENDQ0NDQ0NDLCAyICkgOiAwICkgfCAoICggViAmIDB4QUFBQUFBQUEgKSAhPT0gMCApICk7XG59XG5cblxuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdEhhc2goYiwgdGl0bGUpIHtcbiAgICBjb25zdCBhID0gbmV3IERhdGFWaWV3KGIuYnVmZmVyLCBiLmJ5dGVPZmZzZXQsIGIuYnl0ZUxlbmd0aCk7XG4gICAgbGV0IFMgPSBcIlwiO1xuICAgIGZvciAobGV0IGk9MDsgaTw0OyBpKyspIHtcbiAgICAgICAgaWYgKGk+MCkgUyArPSBcIlxcblwiO1xuICAgICAgICBTICs9IFwiXFx0XFx0XCI7XG4gICAgICAgIGZvciAobGV0IGo9MDsgajw0OyBqKyspIHtcbiAgICAgICAgICAgIGlmIChqPjApIFMgKz0gXCIgXCI7XG4gICAgICAgICAgICBTICs9IGEuZ2V0VWludDMyKGkqMTYraio0KS50b1N0cmluZygxNikucGFkU3RhcnQoOCwgXCIwXCIpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmICh0aXRsZSkgUyA9IHRpdGxlICsgXCJcXG5cIiArIFM7XG4gICAgcmV0dXJuIFM7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBoYXNoSXNFcXVhbChoMSwgaDIpIHtcbiAgICBpZiAoaDEuYnl0ZUxlbmd0aCAhPSBoMi5ieXRlTGVuZ3RoKSByZXR1cm4gZmFsc2U7XG4gICAgdmFyIGR2MSA9IG5ldyBJbnQ4QXJyYXkoaDEpO1xuICAgIHZhciBkdjIgPSBuZXcgSW50OEFycmF5KGgyKTtcbiAgICBmb3IgKHZhciBpID0gMCA7IGkgIT0gaDEuYnl0ZUxlbmd0aCA7IGkrKylcbiAgICB7XG4gICAgICAgIGlmIChkdjFbaV0gIT0gZHYyW2ldKSByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY2xvbmVIYXNoZXIoaCkge1xuICAgIHJldHVybiBoLmNsb25lKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmcm9tUGFydGlhbEhhc2gocGFydGlhbCkge1xuICAgIC8vIE5PVEU6IHRoaXMgaXMgdW5zYWZlIGFuZCB1c2VzIGludGVybmFsIEFQSVxuICAgIGNvbnN0IGJ1ZiA9IHBhcnRpYWwuc3ViYXJyYXkoMCwgMTI4KTtcbiAgICBjb25zdCByZXN0ID0gdTMyKHBhcnRpYWwuc3ViYXJyYXkoMTI4KSk7XG4gICAgY29uc3QgcmVzID0gYmxha2UyYi5jcmVhdGUoeyBka0xlbjogNjQgfSk7XG4gICAgcmVzLmJ1ZmZlci5zZXQoYnVmKTtcbiAgICAocmVzLnYwbCA9IHJlc3RbMF0gfCAwKSwgKHJlcy52MGggPSByZXN0WzFdIHwgMCk7XG4gICAgKHJlcy52MWwgPSByZXN0WzJdIHwgMCksIChyZXMudjFoID0gcmVzdFszXSB8IDApO1xuICAgIChyZXMudjJsID0gcmVzdFs0XSB8IDApLCAocmVzLnYyaCA9IHJlc3RbNV0gfCAwKTtcbiAgICAocmVzLnYzbCA9IHJlc3RbNl0gfCAwKSwgKHJlcy52M2ggPSByZXN0WzddIHwgMCk7XG4gICAgKHJlcy52NGwgPSByZXN0WzhdIHwgMCksIChyZXMudjRoID0gcmVzdFs5XSB8IDApO1xuICAgIChyZXMudjVsID0gcmVzdFsxMF0gfCAwKSwgKHJlcy52NWggPSByZXN0WzExXSB8IDApO1xuICAgIChyZXMudjZsID0gcmVzdFsxMl0gfCAwKSwgKHJlcy52NmggPSByZXN0WzEzXSB8IDApO1xuICAgIChyZXMudjdsID0gcmVzdFsxNF0gfCAwKSwgKHJlcy52N2ggPSByZXN0WzE1XSB8IDApO1xuICAgIGNvbnN0IHNoaWZ0ID0gMiAqKiAzMjtcbiAgICBjb25zdCBsZW4gPSByZXN0WzE2XSArIHJlc3RbMTddICogc2hpZnQ7XG4gICAgY29uc3QgcG9zID0gcmVzdFsxOF0gKyByZXN0WzE5XSAqIHNoaWZ0O1xuICAgIHJlcy5sZW5ndGggPSBsZW4gKyBwb3M7XG4gICAgcmVzLnBvcyA9IHBvcztcbiAgICByZXR1cm4gcmVzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdG9QYXJ0aWFsSGFzaChoYXNoKXtcbiAgICAvLyBOT1RFOiB0aGlzIGlzIHVuc2FmZSBhbmQgdXNlcyBpbnRlcm5hbCBBUElcbiAgICBjb25zdCByZXMgPSBuZXcgVWludDhBcnJheSgyMTYpO1xuICAgIGNvbnN0IHJlczMyID0gdTMyKHJlcy5zdWJhcnJheSgxMjgpKTtcbiAgICByZXMuc2V0KGhhc2guYnVmZmVyKTtcbiAgICAocmVzMzJbMF0gPSBoYXNoLnYwbCksIChyZXMzMlsxXSA9IGhhc2gudjBoKTtcbiAgICAocmVzMzJbMl0gPSBoYXNoLnYxbCksIChyZXMzMlszXSA9IGhhc2gudjFoKTtcbiAgICAocmVzMzJbNF0gPSBoYXNoLnYybCksIChyZXMzMls1XSA9IGhhc2gudjJoKTtcbiAgICAocmVzMzJbNl0gPSBoYXNoLnYzbCksIChyZXMzMls3XSA9IGhhc2gudjNoKTtcbiAgICAocmVzMzJbOF0gPSBoYXNoLnY0bCksIChyZXMzMls5XSA9IGhhc2gudjRoKTtcbiAgICAocmVzMzJbMTBdID0gaGFzaC52NWwpLCAocmVzMzJbMTFdID0gaGFzaC52NWgpO1xuICAgIChyZXMzMlsxMl0gPSBoYXNoLnY2bCksIChyZXMzMlsxM10gPSBoYXNoLnY2aCk7XG4gICAgKHJlczMyWzE0XSA9IGhhc2gudjdsKSwgKHJlczMyWzE1XSA9IGhhc2gudjdoKTtcbiAgICByZXMzMlsxOF0gPSBoYXNoLnBvcztcbiAgICByZXMzMlsxNl0gPSBoYXNoLmxlbmd0aC1oYXNoLnBvcztcbiAgICByZXR1cm4gcmVzO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2FtZVJhdGlvKGN1cnZlLCBnMXMsIGcxc3gsIGcycywgZzJzeCkge1xuICAgIGlmIChjdXJ2ZS5HMS5pc1plcm8oZzFzKSkgcmV0dXJuIGZhbHNlO1xuICAgIGlmIChjdXJ2ZS5HMS5pc1plcm8oZzFzeCkpIHJldHVybiBmYWxzZTtcbiAgICBpZiAoY3VydmUuRzIuaXNaZXJvKGcycykpIHJldHVybiBmYWxzZTtcbiAgICBpZiAoY3VydmUuRzIuaXNaZXJvKGcyc3gpKSByZXR1cm4gZmFsc2U7XG4gICAgLy8gcmV0dXJuIGN1cnZlLkYxMi5lcShjdXJ2ZS5wYWlyaW5nKGcxcywgZzJzeCksIGN1cnZlLnBhaXJpbmcoZzFzeCwgZzJzKSk7XG4gICAgY29uc3QgcmVzID0gYXdhaXQgY3VydmUucGFpcmluZ0VxKGcxcywgZzJzeCwgY3VydmUuRzEubmVnKGcxc3gpLCBnMnMpO1xuICAgIHJldHVybiByZXM7XG59XG5cblxuZXhwb3J0IGZ1bmN0aW9uIGFza0VudHJvcHkoKSB7XG4gICAgaWYgKHByb2Nlc3MuYnJvd3Nlcikge1xuICAgICAgICByZXR1cm4gd2luZG93LnByb21wdChcIkVudGVyIGEgcmFuZG9tIHRleHQuIChFbnRyb3B5KTogXCIsIFwiXCIpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IHJsID0gcmVhZGxpbmUuY3JlYXRlSW50ZXJmYWNlKHtcbiAgICAgICAgICAgIGlucHV0OiBwcm9jZXNzLnN0ZGluLFxuICAgICAgICAgICAgb3V0cHV0OiBwcm9jZXNzLnN0ZG91dFxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgICAgICAgIHJsLnF1ZXN0aW9uKFwiRW50ZXIgYSByYW5kb20gdGV4dC4gKEVudHJvcHkpOiBcIiwgKGlucHV0KSA9PiByZXNvbHZlKGlucHV0KSApO1xuICAgICAgICB9KTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRSYW5kb21CeXRlcyhuKSB7XG4gICAgbGV0IGFycmF5ID0gbmV3IFVpbnQ4QXJyYXkobik7XG4gICAgaWYgKHByb2Nlc3MuYnJvd3NlcikgeyAvLyBTdXBwb3J0ZWRcbiAgICAgICAgZ2xvYmFsVGhpcy5jcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKGFycmF5KTtcbiAgICB9IGVsc2UgeyAvLyBOb2RlSlNcbiAgICAgICAgY3J5cHRvLnJhbmRvbUZpbGxTeW5jKGFycmF5KTtcbiAgICB9XG4gICAgcmV0dXJuIGFycmF5O1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2hhMjU2ZGlnZXN0KGRhdGEpIHtcbiAgICBpZiAocHJvY2Vzcy5icm93c2VyKSB7IC8vIFN1cHBvcnRlZFxuICAgICAgICBjb25zdCBidWZmZXIgPSBhd2FpdCBnbG9iYWxUaGlzLmNyeXB0by5zdWJ0bGUuZGlnZXN0KFwiU0hBLTI1NlwiLCBkYXRhLmJ1ZmZlcik7XG4gICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShidWZmZXIpO1xuICAgIH0gZWxzZSB7IC8vIE5vZGVKU1xuICAgICAgICByZXR1cm4gY3J5cHRvLmNyZWF0ZUhhc2goXCJzaGEyNTZcIikudXBkYXRlKGRhdGEpLmRpZ2VzdCgpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBAcGFyYW0ge1VpbnQ4QXJyYXl9IGRhdGFcbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlYWRVSW50MzJCRShkYXRhLCBvZmZzZXQpIHtcbiAgICByZXR1cm4gbmV3IERhdGFWaWV3KGRhdGEuYnVmZmVyKS5nZXRVaW50MzIob2Zmc2V0LCBmYWxzZSk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRSYW5kb21SbmcoZW50cm9weSkge1xuICAgIC8vIEdlbmVyYXRlIGEgcmFuZG9tIFJuZ1xuICAgIHdoaWxlICghZW50cm9weSkge1xuICAgICAgICBlbnRyb3B5ID0gYXdhaXQgYXNrRW50cm9weSgpO1xuICAgIH1cbiAgICBjb25zdCBoYXNoZXIgPSBibGFrZTJiLmNyZWF0ZSg2NCk7XG4gICAgaGFzaGVyLnVwZGF0ZShnZXRSYW5kb21CeXRlcyg2NCkpO1xuICAgIGNvbnN0IGVuYyA9IG5ldyBUZXh0RW5jb2RlcigpOyAvLyBhbHdheXMgdXRmLThcbiAgICBoYXNoZXIudXBkYXRlKGVuYy5lbmNvZGUoZW50cm9weSkpO1xuICAgIGNvbnN0IGhhc2ggPSBoYXNoZXIuZGlnZXN0KCk7XG5cbiAgICBjb25zdCBzZWVkID0gW107XG4gICAgZm9yIChsZXQgaT0wO2k8ODtpKyspIHtcbiAgICAgICAgc2VlZFtpXSA9IHJlYWRVSW50MzJCRShoYXNoLCBpKjQpO1xuICAgIH1cbiAgICBjb25zdCBybmcgPSBuZXcgQ2hhQ2hhKHNlZWQpO1xuICAgIHJldHVybiBybmc7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBybmdGcm9tQmVhY29uUGFyYW1zKGJlYWNvbkhhc2gsIG51bUl0ZXJhdGlvbnNFeHApIHtcbiAgICBsZXQgbkl0ZXJhdGlvbnNJbm5lcjtcbiAgICBsZXQgbkl0ZXJhdGlvbnNPdXRlcjtcbiAgICBpZiAobnVtSXRlcmF0aW9uc0V4cDwzMikge1xuICAgICAgICBuSXRlcmF0aW9uc0lubmVyID0gKDEgPDwgbnVtSXRlcmF0aW9uc0V4cCkgPj4+IDA7XG4gICAgICAgIG5JdGVyYXRpb25zT3V0ZXIgPSAxO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG5JdGVyYXRpb25zSW5uZXIgPSAweDEwMDAwMDAwMDtcbiAgICAgICAgbkl0ZXJhdGlvbnNPdXRlciA9ICgxIDw8IChudW1JdGVyYXRpb25zRXhwLTMyKSkgPj4+IDA7XG4gICAgfVxuXG4gICAgbGV0IGN1ckhhc2ggPSBiZWFjb25IYXNoO1xuICAgIGZvciAobGV0IGk9MDsgaTxuSXRlcmF0aW9uc091dGVyOyBpKyspIHtcbiAgICAgICAgZm9yIChsZXQgaj0wOyBqPG5JdGVyYXRpb25zSW5uZXI7IGorKykge1xuICAgICAgICAgICAgY3VySGFzaCA9IGF3YWl0IHNoYTI1NmRpZ2VzdChjdXJIYXNoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGN1ckhhc2hWID0gbmV3IERhdGFWaWV3KGN1ckhhc2guYnVmZmVyLCBjdXJIYXNoLmJ5dGVPZmZzZXQsIGN1ckhhc2guYnl0ZUxlbmd0aCk7XG4gICAgY29uc3Qgc2VlZCA9IFtdO1xuICAgIGZvciAobGV0IGk9MDsgaTw4OyBpKyspIHtcbiAgICAgICAgc2VlZFtpXSA9IGN1ckhhc2hWLmdldFVpbnQzMihpKjQsIGZhbHNlKTtcbiAgICB9XG5cbiAgICBjb25zdCBybmcgPSBuZXcgQ2hhQ2hhKHNlZWQpO1xuXG4gICAgcmV0dXJuIHJuZztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGhleDJCeXRlQXJyYXkocykge1xuICAgIGlmIChzIGluc3RhbmNlb2YgVWludDhBcnJheSkgcmV0dXJuIHM7XG4gICAgaWYgKHMuc2xpY2UoMCwyKSA9PSBcIjB4XCIpIHM9IHMuc2xpY2UoMik7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KHMubWF0Y2goL1tcXGRhLWZdezJ9L2dpKS5tYXAoZnVuY3Rpb24gKGgpIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlSW50KGgsIDE2KTtcbiAgICB9KSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBieXRlQXJyYXkyaGV4KGJ5dGVBcnJheSkge1xuICAgIHJldHVybiBBcnJheS5wcm90b3R5cGUubWFwLmNhbGwoYnl0ZUFycmF5LCBmdW5jdGlvbihieXRlKSB7XG4gICAgICAgIHJldHVybiAoXCIwXCIgKyAoYnl0ZSAmIDB4RkYpLnRvU3RyaW5nKDE2KSkuc2xpY2UoLTIpO1xuICAgIH0pLmpvaW4oXCJcIik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdHJpbmdpZnlCaWdJbnRzV2l0aEZpZWxkKEZyLCBvKSB7XG4gICAgaWYgKG8gaW5zdGFuY2VvZiBVaW50OEFycmF5KSAge1xuICAgICAgICByZXR1cm4gRnIudG9TdHJpbmcobyk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KG8pKSB7XG4gICAgICAgIHJldHVybiBvLm1hcChzdHJpbmdpZnlCaWdJbnRzV2l0aEZpZWxkLmJpbmQobnVsbCwgRnIpKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBvID09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgY29uc3QgcmVzID0ge307XG4gICAgICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhvKTtcbiAgICAgICAga2V5cy5mb3JFYWNoKCAoaykgPT4ge1xuICAgICAgICAgICAgcmVzW2tdID0gc3RyaW5naWZ5QmlnSW50c1dpdGhGaWVsZChGciwgb1trXSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH0gZWxzZSBpZiAoKHR5cGVvZihvKSA9PSBcImJpZ2ludFwiKSB8fCBvLmVxICE9PSB1bmRlZmluZWQpICB7XG4gICAgICAgIHJldHVybiBvLnRvU3RyaW5nKDEwKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbztcbiAgICB9XG59XG4iLCJleHBvcnQgY29uc3QgSEVBREVSX1pLRVlfU0VDVElPTiA9IDE7XG5cbmV4cG9ydCBjb25zdCBHUk9USDE2X1BST1RPQ09MX0lEID0gMTtcbmV4cG9ydCBjb25zdCBQTE9OS19QUk9UT0NPTF9JRCA9IDI7XG5leHBvcnQgY29uc3QgRkZMT05LX1BST1RPQ09MX0lEID0gMTA7XG4iLCIvKlxuICAgIENvcHlyaWdodCAyMDIyIGlkZW4zIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygc25hcmtqcy5cblxuICAgIHNuYXJranMgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3JcbiAgICBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlXG4gICAgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pXG4gICAgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICBzbmFya2pzIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gICAgYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yXG4gICAgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYWxvbmcgd2l0aFxuICAgIHNuYXJranMuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG4vLyBGRmxvbmsgY29uc3RhbnRzXG5leHBvcnQgY29uc3QgRkZfVF9QT0xfREVHX01JTiA9IDM7XG5cbi8vIEZGbG9uayBBXG5leHBvcnQgY29uc3QgQSA9IDEyO1xuXG4vLyBaS0VZIGNvbnN0YW50c1xuZXhwb3J0IGNvbnN0IFpLRVlfRkZfTlNFQ1RJT05TID0gMTc7XG5cbmV4cG9ydCBjb25zdCBaS0VZX0ZGX0hFQURFUl9TRUNUSU9OID0gMjtcbmV4cG9ydCBjb25zdCBaS0VZX0ZGX0FERElUSU9OU19TRUNUSU9OID0gMztcbmV4cG9ydCBjb25zdCBaS0VZX0ZGX0FfTUFQX1NFQ1RJT04gPSA0O1xuZXhwb3J0IGNvbnN0IFpLRVlfRkZfQl9NQVBfU0VDVElPTiA9IDU7XG5leHBvcnQgY29uc3QgWktFWV9GRl9DX01BUF9TRUNUSU9OID0gNjtcbmV4cG9ydCBjb25zdCBaS0VZX0ZGX1FMX1NFQ1RJT04gPSA3O1xuZXhwb3J0IGNvbnN0IFpLRVlfRkZfUVJfU0VDVElPTiA9IDg7XG5leHBvcnQgY29uc3QgWktFWV9GRl9RTV9TRUNUSU9OID0gOTtcbmV4cG9ydCBjb25zdCBaS0VZX0ZGX1FPX1NFQ1RJT04gPSAxMDtcbmV4cG9ydCBjb25zdCBaS0VZX0ZGX1FDX1NFQ1RJT04gPSAxMTtcbmV4cG9ydCBjb25zdCBaS0VZX0ZGX1NJR01BMV9TRUNUSU9OID0gMTI7XG5leHBvcnQgY29uc3QgWktFWV9GRl9TSUdNQTJfU0VDVElPTiA9IDEzO1xuZXhwb3J0IGNvbnN0IFpLRVlfRkZfU0lHTUEzX1NFQ1RJT04gPSAxNDtcbmV4cG9ydCBjb25zdCBaS0VZX0ZGX0xBR1JBTkdFX1NFQ1RJT04gPSAxNTtcbmV4cG9ydCBjb25zdCBaS0VZX0ZGX1BUQVVfU0VDVElPTiA9IDE2O1xuZXhwb3J0IGNvbnN0IFpLRVlfRkZfQzBfU0VDVElPTiA9IDE3O1xuIiwiLypcbiAgICBDb3B5cmlnaHQgMjAxOCAwS0lNUyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJrSlMuXG5cbiAgICBzbmFya0pTIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICAgIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gICAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAgICAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtKUyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVFxuICAgIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpY1xuICAgIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gICAgYWxvbmcgd2l0aCBzbmFya0pTLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuLy8gRm9ybWF0XG4vLyA9PT09PT1cbi8vIEhlYWRlcigxKVxuLy8gICAgICBQcm92ZXIgVHlwZSAxIEdyb3RoXG4vLyBIZWFkZXJHcm90aCgyKVxuLy8gICAgICBuOHFcbi8vICAgICAgcVxuLy8gICAgICBuOHJcbi8vICAgICAgclxuLy8gICAgICBOVmFyc1xuLy8gICAgICBOUHViXG4vLyAgICAgIERvbWFpblNpemUgIChtdWx0aXBsZSBvZiAyXG4vLyAgICAgIGFscGhhMVxuLy8gICAgICBiZXRhMVxuLy8gICAgICBkZWx0YTFcbi8vICAgICAgYmV0YTJcbi8vICAgICAgZ2FtbWEyXG4vLyAgICAgIGRlbHRhMlxuLy8gSUMoMylcbi8vIENvZWZzKDQpXG4vLyBQb2ludHNBKDUpXG4vLyBQb2ludHNCMSg2KVxuLy8gUG9pbnRzQjIoNylcbi8vIFBvaW50c0MoOClcbi8vIFBvaW50c0goOSlcbi8vIENvbnRyaWJ1dGlvbnMoMTApXG5cbmltcG9ydCB7IFNjYWxhciwgRjFGaWVsZCB9IGZyb20gXCJmZmphdmFzY3JpcHRcIjtcbmltcG9ydCAqIGFzIGJpbkZpbGVVdGlscyBmcm9tIFwiQGlkZW4zL2JpbmZpbGV1dGlsc1wiO1xuXG5pbXBvcnQgeyBnZXRDdXJ2ZUZyb21RIGFzIGdldEN1cnZlIH0gZnJvbSBcIi4vY3VydmVzLmpzXCI7XG5pbXBvcnQgeyBsb2cyIH0gZnJvbSBcIi4vbWlzYy5qc1wiO1xuaW1wb3J0IHtGRkxPTktfUFJPVE9DT0xfSUQsIEdST1RIMTZfUFJPVE9DT0xfSUQsIFBMT05LX1BST1RPQ09MX0lEfSBmcm9tIFwiLi96a2V5X2NvbnN0YW50cy5qc1wiO1xuaW1wb3J0IHtaS0VZX0ZGX0hFQURFUl9TRUNUSU9OfSBmcm9tIFwiLi9mZmxvbmtfY29uc3RhbnRzLmpzXCI7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3cml0ZUhlYWRlcihmZCwgemtleSkge1xuXG4gICAgLy8gV3JpdGUgdGhlIGhlYWRlclxuICAgIC8vLy8vLy8vLy8vXG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLnN0YXJ0V3JpdGVTZWN0aW9uKGZkLCAxKTtcbiAgICBhd2FpdCBmZC53cml0ZVVMRTMyKDEpOyAvLyBHcm90aFxuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5lbmRXcml0ZVNlY3Rpb24oZmQpO1xuXG4gICAgLy8gV3JpdGUgdGhlIEdyb3RoIGhlYWRlciBzZWN0aW9uXG4gICAgLy8vLy8vLy8vLy9cblxuICAgIGNvbnN0IGN1cnZlID0gYXdhaXQgZ2V0Q3VydmUoemtleS5xKTtcblxuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFdyaXRlU2VjdGlvbihmZCwgMik7XG4gICAgY29uc3QgcHJpbWVRID0gY3VydmUucTtcbiAgICBjb25zdCBuOHEgPSAoTWF0aC5mbG9vciggKFNjYWxhci5iaXRMZW5ndGgocHJpbWVRKSAtIDEpIC8gNjQpICsxKSo4O1xuXG4gICAgY29uc3QgcHJpbWVSID0gY3VydmUucjtcbiAgICBjb25zdCBuOHIgPSAoTWF0aC5mbG9vciggKFNjYWxhci5iaXRMZW5ndGgocHJpbWVSKSAtIDEpIC8gNjQpICsxKSo4O1xuXG4gICAgYXdhaXQgZmQud3JpdGVVTEUzMihuOHEpO1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy53cml0ZUJpZ0ludChmZCwgcHJpbWVRLCBuOHEpO1xuICAgIGF3YWl0IGZkLndyaXRlVUxFMzIobjhyKTtcbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMud3JpdGVCaWdJbnQoZmQsIHByaW1lUiwgbjhyKTtcbiAgICBhd2FpdCBmZC53cml0ZVVMRTMyKHprZXkublZhcnMpOyAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUb3RhbCBudW1iZXIgb2YgYmFyc1xuICAgIGF3YWl0IGZkLndyaXRlVUxFMzIoemtleS5uUHVibGljKTsgICAgICAgICAgICAgICAgICAgICAgIC8vIFRvdGFsIG51bWJlciBvZiBwdWJsaWMgdmFycyAobm90IGluY2x1ZGluZyBPTkUpXG4gICAgYXdhaXQgZmQud3JpdGVVTEUzMih6a2V5LmRvbWFpblNpemUpOyAgICAgICAgICAgICAgICAgIC8vIGRvbWFpblNpemVcbiAgICBhd2FpdCB3cml0ZUcxKGZkLCBjdXJ2ZSwgemtleS52a19hbHBoYV8xKTtcbiAgICBhd2FpdCB3cml0ZUcxKGZkLCBjdXJ2ZSwgemtleS52a19iZXRhXzEpO1xuICAgIGF3YWl0IHdyaXRlRzIoZmQsIGN1cnZlLCB6a2V5LnZrX2JldGFfMik7XG4gICAgYXdhaXQgd3JpdGVHMihmZCwgY3VydmUsIHprZXkudmtfZ2FtbWFfMik7XG4gICAgYXdhaXQgd3JpdGVHMShmZCwgY3VydmUsIHprZXkudmtfZGVsdGFfMSk7XG4gICAgYXdhaXQgd3JpdGVHMihmZCwgY3VydmUsIHprZXkudmtfZGVsdGFfMik7XG5cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kV3JpdGVTZWN0aW9uKGZkKTtcblxuXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3cml0ZVpLZXkoZmlsZU5hbWUsIHprZXkpIHtcblxuICAgIGxldCBjdXJ2ZSA9IGdldEN1cnZlKHprZXkucSk7XG5cbiAgICBjb25zdCBmZCA9IGF3YWl0IGJpbkZpbGVVdGlscy5jcmVhdGVCaW5GaWxlKGZpbGVOYW1lLFwiemtleVwiLCAxLCA5KTtcblxuICAgIGF3YWl0IHdyaXRlSGVhZGVyKGZkLCB6a2V5KTtcbiAgICBjb25zdCBuOHIgPSAoTWF0aC5mbG9vciggKFNjYWxhci5iaXRMZW5ndGgoemtleS5yKSAtIDEpIC8gNjQpICsxKSo4O1xuICAgIGNvbnN0IFJyID0gU2NhbGFyLm1vZChTY2FsYXIuc2hsKDEsIG44cio4KSwgemtleS5yKTtcbiAgICBjb25zdCBSMnIgPSBTY2FsYXIubW9kKFNjYWxhci5tdWwoUnIsUnIpLCB6a2V5LnIpO1xuXG4gICAgLy8gV3JpdGUgUG9scyAoQSBhbmQgQiAoQyBjYW4gYmUgb21pdHRlZCkpXG4gICAgLy8vLy8vLy8vLy9cblxuICAgIHprZXkuY2NvZWZzID0gemtleS5jY29lZnMuZmlsdGVyKGMgPT4gYy5tYXRyaXg8Mik7XG4gICAgemtleS5jY29lZnMuc29ydCggKGEsYikgPT4gYS5jb25zdHJhaW50IC0gYi5jb25zdHJhaW50ICk7XG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLnN0YXJ0V3JpdGVTZWN0aW9uKGZkLCA0KTtcbiAgICBhd2FpdCBmZC53cml0ZVVMRTMyKHprZXkuY2NvZWZzLmxlbmd0aCk7XG4gICAgZm9yIChsZXQgaT0wOyBpPHprZXkuY2NvZWZzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGNvZWYgPSB6a2V5LmNjb2Vmc1tpXTtcbiAgICAgICAgYXdhaXQgZmQud3JpdGVVTEUzMihjb2VmLm1hdHJpeCk7XG4gICAgICAgIGF3YWl0IGZkLndyaXRlVUxFMzIoY29lZi5jb25zdHJhaW50KTtcbiAgICAgICAgYXdhaXQgZmQud3JpdGVVTEUzMihjb2VmLnNpZ25hbCk7XG4gICAgICAgIGF3YWl0IHdyaXRlRnIyKGNvZWYudmFsdWUpO1xuICAgIH1cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kV3JpdGVTZWN0aW9uKGZkKTtcblxuXG4gICAgLy8gV3JpdGUgSUMgU2VjdGlvblxuICAgIC8vLy8vLy8vLy8vXG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLnN0YXJ0V3JpdGVTZWN0aW9uKGZkLCAzKTtcbiAgICBmb3IgKGxldCBpPTA7IGk8PSB6a2V5Lm5QdWJsaWM7IGkrKykge1xuICAgICAgICBhd2FpdCB3cml0ZUcxKGZkLCBjdXJ2ZSwgemtleS5JQ1tpXSApO1xuICAgIH1cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kV3JpdGVTZWN0aW9uKGZkKTtcblxuXG4gICAgLy8gV3JpdGUgQVxuICAgIC8vLy8vLy8vLy8vXG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLnN0YXJ0V3JpdGVTZWN0aW9uKGZkLCA1KTtcbiAgICBmb3IgKGxldCBpPTA7IGk8emtleS5uVmFyczsgaSsrKSB7XG4gICAgICAgIGF3YWl0IHdyaXRlRzEoZmQsIGN1cnZlLCB6a2V5LkFbaV0pO1xuICAgIH1cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kV3JpdGVTZWN0aW9uKGZkKTtcblxuICAgIC8vIFdyaXRlIEIxXG4gICAgLy8vLy8vLy8vLy9cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuc3RhcnRXcml0ZVNlY3Rpb24oZmQsIDYpO1xuICAgIGZvciAobGV0IGk9MDsgaTx6a2V5Lm5WYXJzOyBpKyspIHtcbiAgICAgICAgYXdhaXQgd3JpdGVHMShmZCwgY3VydmUsIHprZXkuQjFbaV0pO1xuICAgIH1cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kV3JpdGVTZWN0aW9uKGZkKTtcblxuICAgIC8vIFdyaXRlIEIyXG4gICAgLy8vLy8vLy8vLy9cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuc3RhcnRXcml0ZVNlY3Rpb24oZmQsIDcpO1xuICAgIGZvciAobGV0IGk9MDsgaTx6a2V5Lm5WYXJzOyBpKyspIHtcbiAgICAgICAgYXdhaXQgd3JpdGVHMihmZCwgY3VydmUsIHprZXkuQjJbaV0pO1xuICAgIH1cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kV3JpdGVTZWN0aW9uKGZkKTtcblxuICAgIC8vIFdyaXRlIENcbiAgICAvLy8vLy8vLy8vL1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFdyaXRlU2VjdGlvbihmZCwgOCk7XG4gICAgZm9yIChsZXQgaT16a2V5Lm5QdWJsaWMrMTsgaTx6a2V5Lm5WYXJzOyBpKyspIHtcbiAgICAgICAgYXdhaXQgd3JpdGVHMShmZCwgY3VydmUsIHprZXkuQ1tpXSk7XG4gICAgfVxuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5lbmRXcml0ZVNlY3Rpb24oZmQpO1xuXG5cbiAgICAvLyBXcml0ZSBIIHBvaW50c1xuICAgIC8vLy8vLy8vLy8vXG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLnN0YXJ0V3JpdGVTZWN0aW9uKGZkLCA5KTtcbiAgICBmb3IgKGxldCBpPTA7IGk8emtleS5kb21haW5TaXplOyBpKyspIHtcbiAgICAgICAgYXdhaXQgd3JpdGVHMShmZCwgY3VydmUsIHprZXkuaEV4cHNbaV0pO1xuICAgIH1cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kV3JpdGVTZWN0aW9uKGZkKTtcblxuICAgIGF3YWl0IGZkLmNsb3NlKCk7XG5cbiAgICBhc3luYyBmdW5jdGlvbiB3cml0ZUZyMihuKSB7XG4gICAgICAgIC8vIENvbnZlcnQgdG8gbW9udGdvbWVyeVxuICAgICAgICBuID0gU2NhbGFyLm1vZCggU2NhbGFyLm11bChuLCBSMnIpLCB6a2V5LnIpO1xuXG4gICAgICAgIGF3YWl0IGJpbkZpbGVVdGlscy53cml0ZUJpZ0ludChmZCwgbiwgbjhyKTtcbiAgICB9XG5cbn1cblxuYXN5bmMgZnVuY3Rpb24gd3JpdGVHMShmZCwgY3VydmUsIHApIHtcbiAgICBjb25zdCBidWZmID0gbmV3IFVpbnQ4QXJyYXkoY3VydmUuRzEuRi5uOCoyKTtcbiAgICBjdXJ2ZS5HMS50b1JwckxFTShidWZmLCAwLCBwKTtcbiAgICBhd2FpdCBmZC53cml0ZShidWZmKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gd3JpdGVHMihmZCwgY3VydmUsIHApIHtcbiAgICBjb25zdCBidWZmID0gbmV3IFVpbnQ4QXJyYXkoY3VydmUuRzIuRi5uOCoyKTtcbiAgICBjdXJ2ZS5HMi50b1JwckxFTShidWZmLCAwLCBwKTtcbiAgICBhd2FpdCBmZC53cml0ZShidWZmKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcmVhZEcxKGZkLCBjdXJ2ZSwgdG9PYmplY3QpIHtcbiAgICBjb25zdCBidWZmID0gYXdhaXQgZmQucmVhZChjdXJ2ZS5HMS5GLm44KjIpO1xuICAgIGNvbnN0IHJlcyA9IGN1cnZlLkcxLmZyb21ScHJMRU0oYnVmZiwgMCk7XG4gICAgcmV0dXJuIHRvT2JqZWN0ID8gY3VydmUuRzEudG9PYmplY3QocmVzKSA6IHJlcztcbn1cblxuYXN5bmMgZnVuY3Rpb24gcmVhZEcyKGZkLCBjdXJ2ZSwgdG9PYmplY3QpIHtcbiAgICBjb25zdCBidWZmID0gYXdhaXQgZmQucmVhZChjdXJ2ZS5HMi5GLm44KjIpO1xuICAgIGNvbnN0IHJlcyA9IGN1cnZlLkcyLmZyb21ScHJMRU0oYnVmZiwgMCk7XG4gICAgcmV0dXJuIHRvT2JqZWN0ID8gY3VydmUuRzIudG9PYmplY3QocmVzKSA6IHJlcztcbn1cblxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZEhlYWRlcihmZCwgc2VjdGlvbnMsIHRvT2JqZWN0LCBvcHRpb25zKSB7XG4gICAgLy8gUmVhZCBIZWFkZXJcbiAgICAvLy8vLy8vLy8vLy8vLy8vLy8vLy9cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuc3RhcnRSZWFkVW5pcXVlU2VjdGlvbihmZCwgc2VjdGlvbnMsIDEpO1xuICAgIGNvbnN0IHByb3RvY29sSWQgPSBhd2FpdCBmZC5yZWFkVUxFMzIoKTtcbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kUmVhZFNlY3Rpb24oZmQpO1xuXG4gICAgaWYgKHByb3RvY29sSWQgPT09IEdST1RIMTZfUFJPVE9DT0xfSUQpIHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHJlYWRIZWFkZXJHcm90aDE2KGZkLCBzZWN0aW9ucywgdG9PYmplY3QsIG9wdGlvbnMpO1xuICAgIH0gZWxzZSBpZiAocHJvdG9jb2xJZCA9PT0gUExPTktfUFJPVE9DT0xfSUQpIHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHJlYWRIZWFkZXJQbG9uayhmZCwgc2VjdGlvbnMsIHRvT2JqZWN0LCBvcHRpb25zKTtcbiAgICB9IGVsc2UgaWYgKHByb3RvY29sSWQgPT09IEZGTE9OS19QUk9UT0NPTF9JRCkge1xuICAgICAgICByZXR1cm4gYXdhaXQgcmVhZEhlYWRlckZGbG9uayhmZCwgc2VjdGlvbnMsIHRvT2JqZWN0LCBvcHRpb25zKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJQcm90b2NvbCBub3Qgc3VwcG9ydGVkOiBcIik7XG4gICAgfVxufVxuXG5cblxuXG5hc3luYyBmdW5jdGlvbiByZWFkSGVhZGVyR3JvdGgxNihmZCwgc2VjdGlvbnMsIHRvT2JqZWN0LCBvcHRpb25zKSB7XG4gICAgY29uc3QgemtleSA9IHt9O1xuXG4gICAgemtleS5wcm90b2NvbCA9IFwiZ3JvdGgxNlwiO1xuXG4gICAgLy8gUmVhZCBHcm90aCBIZWFkZXJcbiAgICAvLy8vLy8vLy8vLy8vLy8vLy8vLy9cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuc3RhcnRSZWFkVW5pcXVlU2VjdGlvbihmZCwgc2VjdGlvbnMsIDIpO1xuICAgIGNvbnN0IG44cSA9IGF3YWl0IGZkLnJlYWRVTEUzMigpO1xuICAgIHprZXkubjhxID0gbjhxO1xuICAgIHprZXkucSA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkQmlnSW50KGZkLCBuOHEpO1xuXG4gICAgY29uc3QgbjhyID0gYXdhaXQgZmQucmVhZFVMRTMyKCk7XG4gICAgemtleS5uOHIgPSBuOHI7XG4gICAgemtleS5yID0gYXdhaXQgYmluRmlsZVV0aWxzLnJlYWRCaWdJbnQoZmQsIG44cik7XG4gICAgemtleS5jdXJ2ZSA9IGF3YWl0IGdldEN1cnZlKHprZXkucSwgb3B0aW9ucyk7XG4gICAgemtleS5uVmFycyA9IGF3YWl0IGZkLnJlYWRVTEUzMigpO1xuICAgIHprZXkublB1YmxpYyA9IGF3YWl0IGZkLnJlYWRVTEUzMigpO1xuICAgIHprZXkuZG9tYWluU2l6ZSA9IGF3YWl0IGZkLnJlYWRVTEUzMigpO1xuICAgIHprZXkucG93ZXIgPSBsb2cyKHprZXkuZG9tYWluU2l6ZSk7XG4gICAgemtleS52a19hbHBoYV8xID0gYXdhaXQgcmVhZEcxKGZkLCB6a2V5LmN1cnZlLCB0b09iamVjdCk7XG4gICAgemtleS52a19iZXRhXzEgPSBhd2FpdCByZWFkRzEoZmQsIHprZXkuY3VydmUsIHRvT2JqZWN0KTtcbiAgICB6a2V5LnZrX2JldGFfMiA9IGF3YWl0IHJlYWRHMihmZCwgemtleS5jdXJ2ZSwgdG9PYmplY3QpO1xuICAgIHprZXkudmtfZ2FtbWFfMiA9IGF3YWl0IHJlYWRHMihmZCwgemtleS5jdXJ2ZSwgdG9PYmplY3QpO1xuICAgIHprZXkudmtfZGVsdGFfMSA9IGF3YWl0IHJlYWRHMShmZCwgemtleS5jdXJ2ZSwgdG9PYmplY3QpO1xuICAgIHprZXkudmtfZGVsdGFfMiA9IGF3YWl0IHJlYWRHMihmZCwgemtleS5jdXJ2ZSwgdG9PYmplY3QpO1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5lbmRSZWFkU2VjdGlvbihmZCk7XG5cbiAgICByZXR1cm4gemtleTtcblxufVxuXG5hc3luYyBmdW5jdGlvbiByZWFkSGVhZGVyUGxvbmsoZmQsIHNlY3Rpb25zLCB0b09iamVjdCwgb3B0aW9ucykge1xuICAgIGNvbnN0IHprZXkgPSB7fTtcblxuICAgIHprZXkucHJvdG9jb2wgPSBcInBsb25rXCI7XG5cbiAgICAvLyBSZWFkIFBsb25rIEhlYWRlclxuICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFJlYWRVbmlxdWVTZWN0aW9uKGZkLCBzZWN0aW9ucywgMik7XG4gICAgY29uc3QgbjhxID0gYXdhaXQgZmQucmVhZFVMRTMyKCk7XG4gICAgemtleS5uOHEgPSBuOHE7XG4gICAgemtleS5xID0gYXdhaXQgYmluRmlsZVV0aWxzLnJlYWRCaWdJbnQoZmQsIG44cSk7XG5cbiAgICBjb25zdCBuOHIgPSBhd2FpdCBmZC5yZWFkVUxFMzIoKTtcbiAgICB6a2V5Lm44ciA9IG44cjtcbiAgICB6a2V5LnIgPSBhd2FpdCBiaW5GaWxlVXRpbHMucmVhZEJpZ0ludChmZCwgbjhyKTtcbiAgICB6a2V5LmN1cnZlID0gYXdhaXQgZ2V0Q3VydmUoemtleS5xLCBvcHRpb25zKTtcbiAgICB6a2V5Lm5WYXJzID0gYXdhaXQgZmQucmVhZFVMRTMyKCk7XG4gICAgemtleS5uUHVibGljID0gYXdhaXQgZmQucmVhZFVMRTMyKCk7XG4gICAgemtleS5kb21haW5TaXplID0gYXdhaXQgZmQucmVhZFVMRTMyKCk7XG4gICAgemtleS5wb3dlciA9IGxvZzIoemtleS5kb21haW5TaXplKTtcbiAgICB6a2V5Lm5BZGRpdGlvbnMgPSBhd2FpdCBmZC5yZWFkVUxFMzIoKTtcbiAgICB6a2V5Lm5Db25zdHJhaW50cyA9IGF3YWl0IGZkLnJlYWRVTEUzMigpO1xuICAgIHprZXkuazEgPSBhd2FpdCBmZC5yZWFkKG44cik7XG4gICAgemtleS5rMiA9IGF3YWl0IGZkLnJlYWQobjhyKTtcblxuICAgIHprZXkuUW0gPSBhd2FpdCByZWFkRzEoZmQsIHprZXkuY3VydmUsIHRvT2JqZWN0KTtcbiAgICB6a2V5LlFsID0gYXdhaXQgcmVhZEcxKGZkLCB6a2V5LmN1cnZlLCB0b09iamVjdCk7XG4gICAgemtleS5RciA9IGF3YWl0IHJlYWRHMShmZCwgemtleS5jdXJ2ZSwgdG9PYmplY3QpO1xuICAgIHprZXkuUW8gPSBhd2FpdCByZWFkRzEoZmQsIHprZXkuY3VydmUsIHRvT2JqZWN0KTtcbiAgICB6a2V5LlFjID0gYXdhaXQgcmVhZEcxKGZkLCB6a2V5LmN1cnZlLCB0b09iamVjdCk7XG4gICAgemtleS5TMSA9IGF3YWl0IHJlYWRHMShmZCwgemtleS5jdXJ2ZSwgdG9PYmplY3QpO1xuICAgIHprZXkuUzIgPSBhd2FpdCByZWFkRzEoZmQsIHprZXkuY3VydmUsIHRvT2JqZWN0KTtcbiAgICB6a2V5LlMzID0gYXdhaXQgcmVhZEcxKGZkLCB6a2V5LmN1cnZlLCB0b09iamVjdCk7XG4gICAgemtleS5YXzIgPSBhd2FpdCByZWFkRzIoZmQsIHprZXkuY3VydmUsIHRvT2JqZWN0KTtcblxuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5lbmRSZWFkU2VjdGlvbihmZCk7XG5cbiAgICByZXR1cm4gemtleTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcmVhZEhlYWRlckZGbG9uayhmZCwgc2VjdGlvbnMsIHRvT2JqZWN0LCBvcHRpb25zKSB7XG4gICAgY29uc3QgemtleSA9IHt9O1xuXG4gICAgemtleS5wcm90b2NvbCA9IFwiZmZsb25rXCI7XG4gICAgemtleS5wcm90b2NvbElkID0gRkZMT05LX1BST1RPQ09MX0lEO1xuXG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLnN0YXJ0UmVhZFVuaXF1ZVNlY3Rpb24oZmQsIHNlY3Rpb25zLCBaS0VZX0ZGX0hFQURFUl9TRUNUSU9OKTtcbiAgICBjb25zdCBuOHEgPSBhd2FpdCBmZC5yZWFkVUxFMzIoKTtcbiAgICB6a2V5Lm44cSA9IG44cTtcbiAgICB6a2V5LnEgPSBhd2FpdCBiaW5GaWxlVXRpbHMucmVhZEJpZ0ludChmZCwgbjhxKTtcbiAgICB6a2V5LmN1cnZlID0gYXdhaXQgZ2V0Q3VydmUoemtleS5xLCBvcHRpb25zKTtcblxuICAgIGNvbnN0IG44ciA9IGF3YWl0IGZkLnJlYWRVTEUzMigpO1xuICAgIHprZXkubjhyID0gbjhyO1xuICAgIHprZXkuciA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkQmlnSW50KGZkLCBuOHIpO1xuXG4gICAgemtleS5uVmFycyA9IGF3YWl0IGZkLnJlYWRVTEUzMigpO1xuICAgIHprZXkublB1YmxpYyA9IGF3YWl0IGZkLnJlYWRVTEUzMigpO1xuICAgIHprZXkuZG9tYWluU2l6ZSA9IGF3YWl0IGZkLnJlYWRVTEUzMigpO1xuICAgIHprZXkucG93ZXIgPSBsb2cyKHprZXkuZG9tYWluU2l6ZSk7XG4gICAgemtleS5uQWRkaXRpb25zID0gYXdhaXQgZmQucmVhZFVMRTMyKCk7XG4gICAgemtleS5uQ29uc3RyYWludHMgPSBhd2FpdCBmZC5yZWFkVUxFMzIoKTtcblxuICAgIHprZXkuazEgPSBhd2FpdCBmZC5yZWFkKG44cik7XG4gICAgemtleS5rMiA9IGF3YWl0IGZkLnJlYWQobjhyKTtcblxuICAgIHprZXkudzMgPSBhd2FpdCBmZC5yZWFkKG44cik7XG4gICAgemtleS53NCA9IGF3YWl0IGZkLnJlYWQobjhyKTtcbiAgICB6a2V5Lnc4ID0gYXdhaXQgZmQucmVhZChuOHIpO1xuICAgIHprZXkud3IgPSBhd2FpdCBmZC5yZWFkKG44cik7XG5cbiAgICB6a2V5LlhfMiA9IGF3YWl0IHJlYWRHMihmZCwgemtleS5jdXJ2ZSwgdG9PYmplY3QpO1xuXG4gICAgemtleS5DMCA9IGF3YWl0IHJlYWRHMShmZCwgemtleS5jdXJ2ZSwgdG9PYmplY3QpO1xuXG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmVuZFJlYWRTZWN0aW9uKGZkKTtcblxuICAgIHJldHVybiB6a2V5O1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZFpLZXkoZmlsZU5hbWUsIHRvT2JqZWN0KSB7XG4gICAgY29uc3Qge2ZkLCBzZWN0aW9uc30gPSBhd2FpdCBiaW5GaWxlVXRpbHMucmVhZEJpbkZpbGUoZmlsZU5hbWUsIFwiemtleVwiLCAxKTtcblxuICAgIGNvbnN0IHprZXkgPSBhd2FpdCByZWFkSGVhZGVyKGZkLCBzZWN0aW9ucywgdG9PYmplY3QpO1xuXG4gICAgY29uc3QgRnIgPSBuZXcgRjFGaWVsZCh6a2V5LnIpO1xuICAgIGNvbnN0IFJyID0gU2NhbGFyLm1vZChTY2FsYXIuc2hsKDEsIHprZXkubjhyKjgpLCB6a2V5LnIpO1xuICAgIGNvbnN0IFJyaSA9IEZyLmludihScik7XG4gICAgY29uc3QgUnJpMiA9IEZyLm11bChScmksIFJyaSk7XG5cbiAgICBsZXQgY3VydmUgPSBhd2FpdCBnZXRDdXJ2ZSh6a2V5LnEpO1xuXG4gICAgLy8gUmVhZCBJQyBTZWN0aW9uXG4gICAgLy8vLy8vLy8vLy9cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuc3RhcnRSZWFkVW5pcXVlU2VjdGlvbihmZCwgc2VjdGlvbnMsIDMpO1xuICAgIHprZXkuSUMgPSBbXTtcbiAgICBmb3IgKGxldCBpPTA7IGk8PSB6a2V5Lm5QdWJsaWM7IGkrKykge1xuICAgICAgICBjb25zdCBQID0gYXdhaXQgcmVhZEcxKGZkLCBjdXJ2ZSwgdG9PYmplY3QpO1xuICAgICAgICB6a2V5LklDLnB1c2goUCk7XG4gICAgfVxuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5lbmRSZWFkU2VjdGlvbihmZCk7XG5cblxuICAgIC8vIFJlYWQgQ29lZnNcbiAgICAvLy8vLy8vLy8vL1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFJlYWRVbmlxdWVTZWN0aW9uKGZkLCBzZWN0aW9ucywgNCk7XG4gICAgY29uc3QgbkNDb2VmcyA9IGF3YWl0IGZkLnJlYWRVTEUzMigpO1xuICAgIHprZXkuY2NvZWZzID0gW107XG4gICAgZm9yIChsZXQgaT0wOyBpPG5DQ29lZnM7IGkrKykge1xuICAgICAgICBjb25zdCBtID0gYXdhaXQgZmQucmVhZFVMRTMyKCk7XG4gICAgICAgIGNvbnN0IGMgPSBhd2FpdCBmZC5yZWFkVUxFMzIoKTtcbiAgICAgICAgY29uc3QgcyA9IGF3YWl0IGZkLnJlYWRVTEUzMigpO1xuICAgICAgICBjb25zdCB2ID0gYXdhaXQgcmVhZEZyMih0b09iamVjdCk7XG4gICAgICAgIHprZXkuY2NvZWZzLnB1c2goe1xuICAgICAgICAgICAgbWF0cml4OiBtLFxuICAgICAgICAgICAgY29uc3RyYWludDogYyxcbiAgICAgICAgICAgIHNpZ25hbDogcyxcbiAgICAgICAgICAgIHZhbHVlOiB2XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kUmVhZFNlY3Rpb24oZmQpO1xuXG4gICAgLy8gUmVhZCBBIHBvaW50c1xuICAgIC8vLy8vLy8vLy8vXG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLnN0YXJ0UmVhZFVuaXF1ZVNlY3Rpb24oZmQsIHNlY3Rpb25zLCA1KTtcbiAgICB6a2V5LkEgPSBbXTtcbiAgICBmb3IgKGxldCBpPTA7IGk8emtleS5uVmFyczsgaSsrKSB7XG4gICAgICAgIGNvbnN0IEEgPSBhd2FpdCByZWFkRzEoZmQsIGN1cnZlLCB0b09iamVjdCk7XG4gICAgICAgIHprZXkuQVtpXSA9IEE7XG4gICAgfVxuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5lbmRSZWFkU2VjdGlvbihmZCk7XG5cblxuICAgIC8vIFJlYWQgQjFcbiAgICAvLy8vLy8vLy8vL1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFJlYWRVbmlxdWVTZWN0aW9uKGZkLCBzZWN0aW9ucywgNik7XG4gICAgemtleS5CMSA9IFtdO1xuICAgIGZvciAobGV0IGk9MDsgaTx6a2V5Lm5WYXJzOyBpKyspIHtcbiAgICAgICAgY29uc3QgQjEgPSBhd2FpdCByZWFkRzEoZmQsIGN1cnZlLCB0b09iamVjdCk7XG5cbiAgICAgICAgemtleS5CMVtpXSA9IEIxO1xuICAgIH1cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kUmVhZFNlY3Rpb24oZmQpO1xuXG5cbiAgICAvLyBSZWFkIEIyIHBvaW50c1xuICAgIC8vLy8vLy8vLy8vXG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLnN0YXJ0UmVhZFVuaXF1ZVNlY3Rpb24oZmQsIHNlY3Rpb25zLCA3KTtcbiAgICB6a2V5LkIyID0gW107XG4gICAgZm9yIChsZXQgaT0wOyBpPHprZXkublZhcnM7IGkrKykge1xuICAgICAgICBjb25zdCBCMiA9IGF3YWl0IHJlYWRHMihmZCwgY3VydmUsIHRvT2JqZWN0KTtcbiAgICAgICAgemtleS5CMltpXSA9IEIyO1xuICAgIH1cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kUmVhZFNlY3Rpb24oZmQpO1xuXG5cbiAgICAvLyBSZWFkIEMgcG9pbnRzXG4gICAgLy8vLy8vLy8vLy9cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuc3RhcnRSZWFkVW5pcXVlU2VjdGlvbihmZCwgc2VjdGlvbnMsIDgpO1xuICAgIHprZXkuQyA9IFtdO1xuICAgIGZvciAobGV0IGk9emtleS5uUHVibGljKzE7IGk8emtleS5uVmFyczsgaSsrKSB7XG4gICAgICAgIGNvbnN0IEMgPSBhd2FpdCByZWFkRzEoZmQsIGN1cnZlLCB0b09iamVjdCk7XG5cbiAgICAgICAgemtleS5DW2ldID0gQztcbiAgICB9XG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmVuZFJlYWRTZWN0aW9uKGZkKTtcblxuXG4gICAgLy8gUmVhZCBIIHBvaW50c1xuICAgIC8vLy8vLy8vLy8vXG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLnN0YXJ0UmVhZFVuaXF1ZVNlY3Rpb24oZmQsIHNlY3Rpb25zLCA5KTtcbiAgICB6a2V5LmhFeHBzID0gW107XG4gICAgZm9yIChsZXQgaT0wOyBpPHprZXkuZG9tYWluU2l6ZTsgaSsrKSB7XG4gICAgICAgIGNvbnN0IEggPSBhd2FpdCByZWFkRzEoZmQsIGN1cnZlLCB0b09iamVjdCk7XG4gICAgICAgIHprZXkuaEV4cHMucHVzaChIKTtcbiAgICB9XG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmVuZFJlYWRTZWN0aW9uKGZkKTtcblxuICAgIGF3YWl0IGZkLmNsb3NlKCk7XG5cbiAgICByZXR1cm4gemtleTtcblxuICAgIGFzeW5jIGZ1bmN0aW9uIHJlYWRGcjIoLyogdG9PYmplY3QgKi8pIHtcbiAgICAgICAgY29uc3QgbiA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkQmlnSW50KGZkLCB6a2V5Lm44cik7XG4gICAgICAgIHJldHVybiBGci5tdWwobiwgUnJpMik7XG4gICAgfVxuXG59XG5cblxuYXN5bmMgZnVuY3Rpb24gcmVhZENvbnRyaWJ1dGlvbihmZCwgY3VydmUsIHRvT2JqZWN0KSB7XG4gICAgY29uc3QgYyA9IHtkZWx0YTp7fX07XG4gICAgYy5kZWx0YUFmdGVyID0gYXdhaXQgcmVhZEcxKGZkLCBjdXJ2ZSwgdG9PYmplY3QpO1xuICAgIGMuZGVsdGEuZzFfcyA9IGF3YWl0IHJlYWRHMShmZCwgY3VydmUsIHRvT2JqZWN0KTtcbiAgICBjLmRlbHRhLmcxX3N4ID0gYXdhaXQgcmVhZEcxKGZkLCBjdXJ2ZSwgdG9PYmplY3QpO1xuICAgIGMuZGVsdGEuZzJfc3B4ID0gYXdhaXQgcmVhZEcyKGZkLCBjdXJ2ZSwgdG9PYmplY3QpO1xuICAgIGMudHJhbnNjcmlwdCA9IGF3YWl0IGZkLnJlYWQoNjQpO1xuICAgIGMudHlwZSA9IGF3YWl0IGZkLnJlYWRVTEUzMigpO1xuXG4gICAgY29uc3QgcGFyYW1MZW5ndGggPSBhd2FpdCBmZC5yZWFkVUxFMzIoKTtcbiAgICBjb25zdCBjdXJQb3MgPSBmZC5wb3M7XG4gICAgbGV0IGxhc3RUeXBlID0wO1xuICAgIHdoaWxlIChmZC5wb3MtY3VyUG9zIDwgcGFyYW1MZW5ndGgpIHtcbiAgICAgICAgY29uc3QgYnVmZlR5cGUgPSBhd2FpdCBmZC5yZWFkKDEpO1xuICAgICAgICBpZiAoYnVmZlR5cGVbMF08PSBsYXN0VHlwZSkgdGhyb3cgbmV3IEVycm9yKFwiUGFyYW1ldGVycyBpbiB0aGUgY29udHJpYnV0aW9uIG11c3QgYmUgc29ydGVkXCIpO1xuICAgICAgICBsYXN0VHlwZSA9IGJ1ZmZUeXBlWzBdO1xuICAgICAgICBpZiAoYnVmZlR5cGVbMF09PTEpIHsgICAgIC8vIE5hbWVcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmZMZW4gPSBhd2FpdCBmZC5yZWFkKDEpO1xuICAgICAgICAgICAgY29uc3QgYnVmZlN0ciA9IGF3YWl0IGZkLnJlYWQoYnVmZkxlblswXSk7XG4gICAgICAgICAgICBjLm5hbWUgPSBuZXcgVGV4dERlY29kZXIoKS5kZWNvZGUoYnVmZlN0cik7XG4gICAgICAgIH0gZWxzZSBpZiAoYnVmZlR5cGVbMF09PTIpIHtcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmZFeHAgPSBhd2FpdCBmZC5yZWFkKDEpO1xuICAgICAgICAgICAgYy5udW1JdGVyYXRpb25zRXhwID0gYnVmZkV4cFswXTtcbiAgICAgICAgfSBlbHNlIGlmIChidWZmVHlwZVswXT09Mykge1xuICAgICAgICAgICAgY29uc3QgYnVmZkxlbiA9IGF3YWl0IGZkLnJlYWQoMSk7XG4gICAgICAgICAgICBjLmJlYWNvbkhhc2ggPSBhd2FpdCBmZC5yZWFkKGJ1ZmZMZW5bMF0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUGFyYW1ldGVyIG5vdCByZWNvZ25pemVkXCIpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmIChmZC5wb3MgIT0gY3VyUG9zICsgcGFyYW1MZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUGFyYW1ldGVycyBkbyBub3QgbWF0Y2hcIik7XG4gICAgfVxuXG4gICAgcmV0dXJuIGM7XG59XG5cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRNUENQYXJhbXMoZmQsIGN1cnZlLCBzZWN0aW9ucykge1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFJlYWRVbmlxdWVTZWN0aW9uKGZkLCBzZWN0aW9ucywgMTApO1xuICAgIGNvbnN0IHJlcyA9IHsgY29udHJpYnV0aW9uczogW119O1xuICAgIHJlcy5jc0hhc2ggPSBhd2FpdCBmZC5yZWFkKDY0KTtcbiAgICBjb25zdCBuID0gYXdhaXQgZmQucmVhZFVMRTMyKCk7XG4gICAgZm9yIChsZXQgaT0wOyBpPG47IGkrKykge1xuICAgICAgICBjb25zdCBjID0gYXdhaXQgcmVhZENvbnRyaWJ1dGlvbihmZCwgY3VydmUpO1xuICAgICAgICByZXMuY29udHJpYnV0aW9ucy5wdXNoKGMpO1xuICAgIH1cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kUmVhZFNlY3Rpb24oZmQpO1xuXG4gICAgcmV0dXJuIHJlcztcbn1cblxuYXN5bmMgZnVuY3Rpb24gd3JpdGVDb250cmlidXRpb24oZmQsIGN1cnZlLCBjKSB7XG4gICAgYXdhaXQgd3JpdGVHMShmZCwgY3VydmUsIGMuZGVsdGFBZnRlcik7XG4gICAgYXdhaXQgd3JpdGVHMShmZCwgY3VydmUsIGMuZGVsdGEuZzFfcyk7XG4gICAgYXdhaXQgd3JpdGVHMShmZCwgY3VydmUsIGMuZGVsdGEuZzFfc3gpO1xuICAgIGF3YWl0IHdyaXRlRzIoZmQsIGN1cnZlLCBjLmRlbHRhLmcyX3NweCk7XG4gICAgYXdhaXQgZmQud3JpdGUoYy50cmFuc2NyaXB0KTtcbiAgICBhd2FpdCBmZC53cml0ZVVMRTMyKGMudHlwZSB8fCAwKTtcblxuICAgIGNvbnN0IHBhcmFtcyA9IFtdO1xuICAgIGlmIChjLm5hbWUpIHtcbiAgICAgICAgcGFyYW1zLnB1c2goMSk7ICAgICAgLy8gUGFyYW0gTmFtZVxuICAgICAgICBjb25zdCBuYW1lRGF0YSA9IG5ldyBUZXh0RW5jb2RlcihcInV0Zi04XCIpLmVuY29kZShjLm5hbWUuc3Vic3RyaW5nKDAsNjQpKTtcbiAgICAgICAgcGFyYW1zLnB1c2gobmFtZURhdGEuYnl0ZUxlbmd0aCk7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxuYW1lRGF0YS5ieXRlTGVuZ3RoOyBpKyspIHBhcmFtcy5wdXNoKG5hbWVEYXRhW2ldKTtcbiAgICB9XG4gICAgaWYgKGMudHlwZSA9PSAxKSB7XG4gICAgICAgIHBhcmFtcy5wdXNoKDIpOyAgICAgIC8vIFBhcmFtIG51bUl0ZXJhdGlvbnNFeHBcbiAgICAgICAgcGFyYW1zLnB1c2goYy5udW1JdGVyYXRpb25zRXhwKTtcblxuICAgICAgICBwYXJhbXMucHVzaCgzKTsgICAgICAvLyBCZWFjb24gSGFzaFxuICAgICAgICBwYXJhbXMucHVzaChjLmJlYWNvbkhhc2guYnl0ZUxlbmd0aCk7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxjLmJlYWNvbkhhc2guYnl0ZUxlbmd0aDsgaSsrKSBwYXJhbXMucHVzaChjLmJlYWNvbkhhc2hbaV0pO1xuICAgIH1cbiAgICBpZiAocGFyYW1zLmxlbmd0aD4wKSB7XG4gICAgICAgIGNvbnN0IHBhcmFtc0J1ZmYgPSBuZXcgVWludDhBcnJheShwYXJhbXMpO1xuICAgICAgICBhd2FpdCBmZC53cml0ZVVMRTMyKHBhcmFtc0J1ZmYuYnl0ZUxlbmd0aCk7XG4gICAgICAgIGF3YWl0IGZkLndyaXRlKHBhcmFtc0J1ZmYpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGF3YWl0IGZkLndyaXRlVUxFMzIoMCk7XG4gICAgfVxuXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3cml0ZU1QQ1BhcmFtcyhmZCwgY3VydmUsIG1wY1BhcmFtcykge1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFdyaXRlU2VjdGlvbihmZCwgMTApO1xuICAgIGF3YWl0IGZkLndyaXRlKG1wY1BhcmFtcy5jc0hhc2gpO1xuICAgIGF3YWl0IGZkLndyaXRlVUxFMzIobXBjUGFyYW1zLmNvbnRyaWJ1dGlvbnMubGVuZ3RoKTtcbiAgICBmb3IgKGxldCBpPTA7IGk8bXBjUGFyYW1zLmNvbnRyaWJ1dGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYXdhaXQgd3JpdGVDb250cmlidXRpb24oZmQsIGN1cnZlLG1wY1BhcmFtcy5jb250cmlidXRpb25zW2ldKTtcbiAgICB9XG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmVuZFdyaXRlU2VjdGlvbihmZCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBoYXNoRzEoaGFzaGVyLCBjdXJ2ZSwgcCkge1xuICAgIGNvbnN0IGJ1ZmYgPSBuZXcgVWludDhBcnJheShjdXJ2ZS5HMS5GLm44KjIpO1xuICAgIGN1cnZlLkcxLnRvUnByVW5jb21wcmVzc2VkKGJ1ZmYsIDAsIHApO1xuICAgIGhhc2hlci51cGRhdGUoYnVmZik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBoYXNoRzIoaGFzaGVyLGN1cnZlLCBwKSB7XG4gICAgY29uc3QgYnVmZiA9IG5ldyBVaW50OEFycmF5KGN1cnZlLkcyLkYubjgqMik7XG4gICAgY3VydmUuRzIudG9ScHJVbmNvbXByZXNzZWQoYnVmZiwgMCwgcCk7XG4gICAgaGFzaGVyLnVwZGF0ZShidWZmKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGhhc2hQdWJLZXkoaGFzaGVyLCBjdXJ2ZSwgYykge1xuICAgIGhhc2hHMShoYXNoZXIsIGN1cnZlLCBjLmRlbHRhQWZ0ZXIpO1xuICAgIGhhc2hHMShoYXNoZXIsIGN1cnZlLCBjLmRlbHRhLmcxX3MpO1xuICAgIGhhc2hHMShoYXNoZXIsIGN1cnZlLCBjLmRlbHRhLmcxX3N4KTtcbiAgICBoYXNoRzIoaGFzaGVyLCBjdXJ2ZSwgYy5kZWx0YS5nMl9zcHgpO1xuICAgIGhhc2hlci51cGRhdGUoYy50cmFuc2NyaXB0KTtcbn1cblxuIiwiLypcbiAgICBDb3B5cmlnaHQgMjAxOCAwS0lNUyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJrSlMuXG5cbiAgICBzbmFya0pTIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICAgIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gICAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAgICAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtKUyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVFxuICAgIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpY1xuICAgIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gICAgYWxvbmcgd2l0aCBzbmFya0pTLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuaW1wb3J0IHsgU2NhbGFyIH0gZnJvbSBcImZmamF2YXNjcmlwdFwiO1xuXG5pbXBvcnQgKiBhcyBiaW5GaWxlVXRpbHMgZnJvbSBcIkBpZGVuMy9iaW5maWxldXRpbHNcIjtcblxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd3JpdGUoZmQsIHdpdG5lc3MsIHByaW1lKSB7XG5cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuc3RhcnRXcml0ZVNlY3Rpb24oZmQsIDEpO1xuICAgIGNvbnN0IG44ID0gKE1hdGguZmxvb3IoIChTY2FsYXIuYml0TGVuZ3RoKHByaW1lKSAtIDEpIC8gNjQpICsxKSo4O1xuICAgIGF3YWl0IGZkLndyaXRlVUxFMzIobjgpO1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy53cml0ZUJpZ0ludChmZCwgcHJpbWUsIG44KTtcbiAgICBhd2FpdCBmZC53cml0ZVVMRTMyKHdpdG5lc3MubGVuZ3RoKTtcbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kV3JpdGVTZWN0aW9uKGZkKTtcblxuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFdyaXRlU2VjdGlvbihmZCwgMik7XG4gICAgZm9yIChsZXQgaT0wOyBpPHdpdG5lc3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYXdhaXQgYmluRmlsZVV0aWxzLndyaXRlQmlnSW50KGZkLCB3aXRuZXNzW2ldLCBuOCk7XG4gICAgfVxuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5lbmRXcml0ZVNlY3Rpb24oZmQsIDIpO1xuXG5cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdyaXRlQmluKGZkLCB3aXRuZXNzQmluLCBwcmltZSkge1xuXG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLnN0YXJ0V3JpdGVTZWN0aW9uKGZkLCAxKTtcbiAgICBjb25zdCBuOCA9IChNYXRoLmZsb29yKCAoU2NhbGFyLmJpdExlbmd0aChwcmltZSkgLSAxKSAvIDY0KSArMSkqODtcbiAgICBhd2FpdCBmZC53cml0ZVVMRTMyKG44KTtcbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMud3JpdGVCaWdJbnQoZmQsIHByaW1lLCBuOCk7XG4gICAgaWYgKHdpdG5lc3NCaW4uYnl0ZUxlbmd0aCAlIG44ICE9IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCB3aXRuZXNzIGxlbmd0aFwiKTtcbiAgICB9XG4gICAgYXdhaXQgZmQud3JpdGVVTEUzMih3aXRuZXNzQmluLmJ5dGVMZW5ndGggLyBuOCk7XG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmVuZFdyaXRlU2VjdGlvbihmZCk7XG5cblxuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFdyaXRlU2VjdGlvbihmZCwgMik7XG4gICAgYXdhaXQgZmQud3JpdGUod2l0bmVzc0Jpbik7XG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmVuZFdyaXRlU2VjdGlvbihmZCk7XG5cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRIZWFkZXIoZmQsIHNlY3Rpb25zKSB7XG5cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuc3RhcnRSZWFkVW5pcXVlU2VjdGlvbihmZCwgc2VjdGlvbnMsIDEpO1xuICAgIGNvbnN0IG44ID0gYXdhaXQgZmQucmVhZFVMRTMyKCk7XG4gICAgY29uc3QgcSA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkQmlnSW50KGZkLCBuOCk7XG4gICAgY29uc3QgbldpdG5lc3MgPSBhd2FpdCBmZC5yZWFkVUxFMzIoKTtcbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kUmVhZFNlY3Rpb24oZmQpO1xuXG4gICAgcmV0dXJuIHtuOCwgcSwgbldpdG5lc3N9O1xuXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWFkKGZpbGVOYW1lKSB7XG5cbiAgICBjb25zdCB7ZmQsIHNlY3Rpb25zfSA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkQmluRmlsZShmaWxlTmFtZSwgXCJ3dG5zXCIsIDIpO1xuXG4gICAgY29uc3Qge244LCBuV2l0bmVzc30gPSBhd2FpdCByZWFkSGVhZGVyKGZkLCBzZWN0aW9ucyk7XG5cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuc3RhcnRSZWFkVW5pcXVlU2VjdGlvbihmZCwgc2VjdGlvbnMsIDIpO1xuICAgIGNvbnN0IHJlcyA9IFtdO1xuICAgIGZvciAobGV0IGk9MDsgaTxuV2l0bmVzczsgaSsrKSB7XG4gICAgICAgIGNvbnN0IHYgPSBhd2FpdCBiaW5GaWxlVXRpbHMucmVhZEJpZ0ludChmZCwgbjgpO1xuICAgICAgICByZXMucHVzaCh2KTtcbiAgICB9XG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmVuZFJlYWRTZWN0aW9uKGZkKTtcblxuICAgIGF3YWl0IGZkLmNsb3NlKCk7XG5cbiAgICByZXR1cm4gcmVzO1xufVxuXG4iLCIvKlxuICAgIENvcHlyaWdodCAyMDE4IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygc25hcmtKUy5cblxuICAgIHNuYXJrSlMgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gICAgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAgICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICAgIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICBzbmFya0pTIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHNuYXJrSlMuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG5pbXBvcnQgKiBhcyBiaW5GaWxlVXRpbHMgZnJvbSBcIkBpZGVuMy9iaW5maWxldXRpbHNcIjtcbmltcG9ydCAqIGFzIHprZXlVdGlscyBmcm9tIFwiLi96a2V5X3V0aWxzLmpzXCI7XG5pbXBvcnQgKiBhcyB3dG5zVXRpbHMgZnJvbSBcIi4vd3Ruc191dGlscy5qc1wiO1xuaW1wb3J0IHsgbG9nMiB9IGZyb20gXCIuL21pc2MuanNcIjtcbmltcG9ydCB7IFNjYWxhciwgdXRpbHMsIEJpZ0J1ZmZlciB9IGZyb20gXCJmZmphdmFzY3JpcHRcIjtcbmNvbnN0IHtzdHJpbmdpZnlCaWdJbnRzfSA9IHV0aWxzO1xuXG5leHBvcnQgZGVmYXVsdCBhc3luYyBmdW5jdGlvbiBncm90aDE2UHJvdmUoemtleUZpbGVOYW1lLCB3aXRuZXNzRmlsZU5hbWUsIGxvZ2dlciwgb3B0aW9ucykge1xuXG4gICAgaWYgKGxvZ2dlcikgbW9uaXRvck1lbW9yeVVzYWdlKGxvZ2dlciwgNTApO1xuICAgIGNvbnN0IHtmZDogZmRXdG5zLCBzZWN0aW9uczogc2VjdGlvbnNXdG5zfSA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkQmluRmlsZSh3aXRuZXNzRmlsZU5hbWUsIFwid3Ruc1wiLCAyLCAxPDwyNSwgMTw8MjMpO1xuXG4gICAgY29uc3Qgd3RucyA9IGF3YWl0IHd0bnNVdGlscy5yZWFkSGVhZGVyKGZkV3Rucywgc2VjdGlvbnNXdG5zKTtcblxuICAgIGNvbnN0IHtmZDogZmRaS2V5LCBzZWN0aW9uczogc2VjdGlvbnNaS2V5fSA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkQmluRmlsZSh6a2V5RmlsZU5hbWUsIFwiemtleVwiLCAyLCAxPDwyNSwgMTw8MjMpO1xuXG4gICAgY29uc3QgemtleSA9IGF3YWl0IHprZXlVdGlscy5yZWFkSGVhZGVyKGZkWktleSwgc2VjdGlvbnNaS2V5LCB1bmRlZmluZWQsIG9wdGlvbnMpO1xuXG4gICAgaWYgKHprZXkucHJvdG9jb2wgIT0gXCJncm90aDE2XCIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiemtleSBmaWxlIGlzIG5vdCBncm90aDE2XCIpO1xuICAgIH1cblxuICAgIGlmICghU2NhbGFyLmVxKHprZXkuciwgIHd0bnMucSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ3VydmUgb2YgdGhlIHdpdG5lc3MgZG9lcyBub3QgbWF0Y2ggdGhlIGN1cnZlIG9mIHRoZSBwcm92aW5nIGtleVwiKTtcbiAgICB9XG5cbiAgICBpZiAod3Rucy5uV2l0bmVzcyAhPSB6a2V5Lm5WYXJzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCB3aXRuZXNzIGxlbmd0aC4gQ2lyY3VpdDogJHt6a2V5Lm5WYXJzfSwgd2l0bmVzczogJHt3dG5zLm5XaXRuZXNzfWApO1xuICAgIH1cblxuICAgIGNvbnN0IGN1cnZlID0gemtleS5jdXJ2ZTtcbiAgICBjb25zdCBGciA9IGN1cnZlLkZyO1xuICAgIGNvbnN0IEcxID0gY3VydmUuRzE7XG4gICAgY29uc3QgRzIgPSBjdXJ2ZS5HMjtcblxuICAgIGNvbnN0IHBvd2VyID0gbG9nMih6a2V5LmRvbWFpblNpemUpO1xuXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKFwiUmVhZGluZyBXdG5zXCIpO1xuICAgIGNvbnN0IGJ1ZmZXaXRuZXNzID0gYXdhaXQgYmluRmlsZVV0aWxzLnJlYWRTZWN0aW9uKGZkV3Rucywgc2VjdGlvbnNXdG5zLCAyKTtcblxuICAgIGxldCByZXNIO1xuICAgIGxldCByZXNIUHJvbWlzZTtcbiAgICBsZXQgYnVmZlBvZGRfVDtcblxuICAgIGxldCBhYmNQcm9taXNlID0gKGFzeW5jIGZ1bmN0aW9uICgpe1xuICAgICAgICBsZXQgYnVmZkFfVCwgYnVmZkJfVCwgYnVmZkNfVDtcblxuICAgICAgICBhd2FpdCAoYXN5bmMgZnVuY3Rpb24gKCl7XG4gICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCJSZWFkaW5nIENvZWZmc1wiKTtcbiAgICAgICAgICAgIGNvbnNvbGUudGltZShcImJ1aWxkQUJDX291dGVyXCIpO1xuICAgICAgICAgICAgY29uc3QgYnVmZkNvZWZmcyA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkU2VjdGlvbihmZFpLZXksIHNlY3Rpb25zWktleSwgNCk7XG5cbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIkJ1aWxkaW5nIEFCQ1wiKTtcblxuICAgICAgICAgICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gICAgICAgICAgICAvL29wdGlvbnMuYnVpbGRBQkM9XCJ3YXNtMVwiOyAvLyBmb3IgdGVzdGluZ1xuXG4gICAgICAgICAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLmJ1aWxkQUJDPT09XCJ3YXNtXCIpIHtcbiAgICAgICAgICAgICAgICAvLyBidWlsZCBBQkMgaW4gV0FTTVxuICAgICAgICAgICAgICAgIFtidWZmQV9ULCBidWZmQl9ULCBidWZmQ19UXSA9IGF3YWl0IGJ1aWxkQUJDKGN1cnZlLCB6a2V5LCBidWZmV2l0bmVzcywgYnVmZkNvZWZmcywgbG9nZ2VyKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAob3B0aW9ucyAmJiBvcHRpb25zLmJ1aWxkQUJDPT09XCJ3YXNtMVwiKSB7XG4gICAgICAgICAgICAgICAgLy8gYnVpbGQgQUJDIGluIFdBU01cbiAgICAgICAgICAgICAgICBbYnVmZkFfVCwgYnVmZkJfVCwgYnVmZkNfVF0gPSBhd2FpdCBidWlsZEFCQ1dBU00xKGN1cnZlLCB6a2V5LCBidWZmV2l0bmVzcywgYnVmZkNvZWZmcywgbG9nZ2VyKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gZGVmYXVsdCwgYnVpbGQgQUJDIGluIEpTXG4gICAgICAgICAgICAgICAgW2J1ZmZBX1QsIGJ1ZmZCX1QsIGJ1ZmZDX1RdID0gYXdhaXQgYnVpbGRBQkMxKGN1cnZlLCB6a2V5LCBidWZmV2l0bmVzcywgYnVmZkNvZWZmcywgbG9nZ2VyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnNvbGUudGltZUVuZChcImJ1aWxkQUJDX291dGVyXCIpO1xuICAgICAgICB9KSgpO1xuXG4gICAgICAgIGNvbnNvbGUudGltZShcImFiY1Byb21pc2VcIik7XG5cbiAgICAgICAgaWYgKGdsb2JhbFRoaXMuZ2MpIHtnbG9iYWxUaGlzLmdjKCk7fVxuXG4gICAgICAgIGNvbnN0IGluYyA9IHBvd2VyID09PSBGci5zID8gY3VydmUuRnIuc2hpZnQgOiBjdXJ2ZS5Gci53W3Bvd2VyKzFdO1xuXG4gICAgICAgIGxldCBidWZmQW9kZF9UO1xuICAgICAgICBhd2FpdCAoYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgbGV0IGJ1ZmZBID0gYXdhaXQgRnIuaWZmdChidWZmQV9ULCBcIlwiLCBcIlwiLCBsb2dnZXIsIFwiSUZGVF9BXCIpO1xuICAgICAgICAgICAgYnVmZkFfVCA9IG51bGw7XG4gICAgICAgICAgICBjb25zdCBidWZmQW9kZCA9IGF3YWl0IEZyLmJhdGNoQXBwbHlLZXkoYnVmZkEsIEZyLmUoMSksIGluYyk7XG4gICAgICAgICAgICBidWZmQW9kZF9UID0gYXdhaXQgRnIuZmZ0KGJ1ZmZBb2RkLCBcIlwiLCBcIlwiLCBsb2dnZXIsIFwiRkZUX0FcIik7XG4gICAgICAgIH0pKCk7XG5cbiAgICAgICAgbGV0IGJ1ZmZCb2RkX1Q7XG4gICAgICAgIGF3YWl0IChhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBjb25zdCBidWZmQiA9IGF3YWl0IEZyLmlmZnQoYnVmZkJfVCwgXCJcIiwgXCJcIiwgbG9nZ2VyLCBcIklGRlRfQlwiKTtcbiAgICAgICAgICAgIGJ1ZmZCX1QgPSBudWxsO1xuICAgICAgICAgICAgY29uc3QgYnVmZkJvZGQgPSBhd2FpdCBGci5iYXRjaEFwcGx5S2V5KGJ1ZmZCLCBGci5lKDEpLCBpbmMpO1xuICAgICAgICAgICAgYnVmZkJvZGRfVCA9IGF3YWl0IEZyLmZmdChidWZmQm9kZCwgXCJcIiwgXCJcIiwgbG9nZ2VyLCBcIkZGVF9CXCIpO1xuICAgICAgICB9KSgpO1xuXG4gICAgICAgIGxldCBidWZmQ29kZF9UO1xuICAgICAgICBhd2FpdCAoYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgY29uc3QgYnVmZkMgPSBhd2FpdCBGci5pZmZ0KGJ1ZmZDX1QsIFwiXCIsIFwiXCIsIGxvZ2dlciwgXCJJRkZUX0NcIik7XG4gICAgICAgICAgICBidWZmQ19UID0gbnVsbDtcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmZDb2RkID0gYXdhaXQgRnIuYmF0Y2hBcHBseUtleShidWZmQywgRnIuZSgxKSwgaW5jKTtcbiAgICAgICAgICAgIGJ1ZmZDb2RkX1QgPSBhd2FpdCBGci5mZnQoYnVmZkNvZGQsIFwiXCIsIFwiXCIsIGxvZ2dlciwgXCJGRlRfQ1wiKTtcbiAgICAgICAgfSkoKTtcblxuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCJKb2luIEFCQ1wiKTtcbiAgICAgICAgYnVmZlBvZGRfVCA9IGF3YWl0IGpvaW5BQkMoY3VydmUsIHprZXksIGJ1ZmZBb2RkX1QsIGJ1ZmZCb2RkX1QsIGJ1ZmZDb2RkX1QsIGxvZ2dlcik7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIkpvaW4gQUJDIGZpbmlzaGVkXCIpO1xuICAgICAgICBidWZmQW9kZF9UID0gbnVsbDtcbiAgICAgICAgYnVmZkJvZGRfVCA9IG51bGw7XG4gICAgICAgIGJ1ZmZDb2RkX1QgPSBudWxsO1xuXG4gICAgICAgIGlmIChnbG9iYWxUaGlzLmdjKSB7Z2xvYmFsVGhpcy5nYygpO31cbiAgICAgICAgY29uc29sZS50aW1lRW5kKFwiYWJjUHJvbWlzZVwiKTtcbiAgICB9KSgpO1xuICAgIC8vYXdhaXQgYWJjUHJvbWlzZTtcblxuICAgIGxldCBwcm9vZiA9IHt9O1xuXG4gICAgYXN5bmMgZnVuY3Rpb24gY2FsY1BpQSgpe1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCJSZWFkaW5nIEEgUG9pbnRzXCIpO1xuICAgICAgICBjb25zdCBidWZmQmFzZXNBID0gYXdhaXQgYmluRmlsZVV0aWxzLnJlYWRTZWN0aW9uKGZkWktleSwgc2VjdGlvbnNaS2V5LCA1KTtcbiAgICAgICAgY29uc29sZS50aW1lKFwiQ2FsY3VsYXRlIFBpQVwiKTtcbiAgICAgICAgcHJvb2YucGlfYSA9IGF3YWl0IGN1cnZlLkcxLm11bHRpRXhwQWZmaW5lKGJ1ZmZCYXNlc0EsIGJ1ZmZXaXRuZXNzLCBsb2dnZXIsIFwibXVsdGlleHAgQVwiKTtcbiAgICAgICAgY29uc29sZS50aW1lRW5kKFwiQ2FsY3VsYXRlIFBpQVwiKTtcbiAgICB9XG5cbiAgICBsZXQgcGlhUHJvbWlzZSA9IGNhbGNQaUEoKTtcbiAgICAvL2F3YWl0IHBpYVByb21pc2U7XG5cbiAgICBsZXQgcGliMTtcblxuICAgIGFzeW5jIGZ1bmN0aW9uIGNhbGNQaUIxKCkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCJSZWFkaW5nIEIxIFBvaW50c1wiKTtcbiAgICAgICAgY29uc3QgYnVmZkJhc2VzQjEgPSBhd2FpdCBiaW5GaWxlVXRpbHMucmVhZFNlY3Rpb24oZmRaS2V5LCBzZWN0aW9uc1pLZXksIDYpO1xuICAgICAgICBjb25zb2xlLnRpbWUoXCJDYWxjdWxhdGUgUGlCMVwiKTtcbiAgICAgICAgcGliMSA9IGF3YWl0IGN1cnZlLkcxLm11bHRpRXhwQWZmaW5lKGJ1ZmZCYXNlc0IxLCBidWZmV2l0bmVzcywgbG9nZ2VyLCBcIm11bHRpZXhwIEIxXCIpO1xuICAgICAgICBjb25zb2xlLnRpbWVFbmQoXCJDYWxjdWxhdGUgUGlCMVwiKTtcbiAgICB9XG5cbiAgICBsZXQgcGliMVByb21pc2UgPSBjYWxjUGlCMSgpO1xuICAgIC8vYXdhaXQgcGliMVByb21pc2U7XG5cbiAgICBhc3luYyBmdW5jdGlvbiBjYWxjUGlCKCkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCJSZWFkaW5nIEIyIFBvaW50c1wiKTtcbiAgICAgICAgY29uc3QgYnVmZkJhc2VzQjIgPSBhd2FpdCBiaW5GaWxlVXRpbHMucmVhZFNlY3Rpb24oZmRaS2V5LCBzZWN0aW9uc1pLZXksIDcpO1xuICAgICAgICBjb25zb2xlLnRpbWUoXCJDYWxjdWxhdGUgUGlCXCIpO1xuICAgICAgICBwcm9vZi5waV9iID0gYXdhaXQgY3VydmUuRzIubXVsdGlFeHBBZmZpbmUoYnVmZkJhc2VzQjIsIGJ1ZmZXaXRuZXNzLCBsb2dnZXIsIFwibXVsdGlleHAgQjJcIik7XG4gICAgICAgIGNvbnNvbGUudGltZUVuZChcIkNhbGN1bGF0ZSBQaUJcIik7XG4gICAgfVxuXG4gICAgbGV0IHBpYlByb21pc2UgPSBjYWxjUGlCKCk7XG4gICAgLy9hd2FpdCBwaWJQcm9taXNlO1xuXG4gICAgbGV0IHBpY1Byb21pc2UgPSAoYXN5bmMgZnVuY3Rpb24gKCl7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIlJlYWRpbmcgQyBQb2ludHNcIik7XG4gICAgICAgIGNvbnN0IGJ1ZmZCYXNlc0MgPSBhd2FpdCBiaW5GaWxlVXRpbHMucmVhZFNlY3Rpb24oZmRaS2V5LCBzZWN0aW9uc1pLZXksIDgpO1xuICAgICAgICBjb25zb2xlLnRpbWUoXCJDYWxjdWxhdGUgUGlDXCIpO1xuICAgICAgICBwcm9vZi5waV9jID0gYXdhaXQgY3VydmUuRzEubXVsdGlFeHBBZmZpbmUoYnVmZkJhc2VzQywgYnVmZldpdG5lc3Muc2xpY2UoKHprZXkublB1YmxpYysxKSpjdXJ2ZS5Gci5uOCksIGxvZ2dlciwgXCJtdWx0aWV4cCBDXCIpO1xuICAgICAgICBjb25zb2xlLnRpbWVFbmQoXCJDYWxjdWxhdGUgUGlDXCIpO1xuICAgIH0pKCk7XG4gICAgLy9hd2FpdCBwaWNQcm9taXNlO1xuXG5cbiAgICByZXNIUHJvbWlzZSA9IChhc3luYyBmdW5jdGlvbiAoKXtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKFwiUmVhZGluZyBIIFBvaW50c1wiKTtcbiAgICAgICAgYXdhaXQgYWJjUHJvbWlzZTtcbiAgICAgICAgY29uc29sZS50aW1lKFwicmVzSFByb21pc2VcIik7XG4gICAgICAgIGNvbnN0IGJ1ZmZCYXNlc0ggPSBhd2FpdCBiaW5GaWxlVXRpbHMucmVhZFNlY3Rpb24oZmRaS2V5LCBzZWN0aW9uc1pLZXksIDkpO1xuICAgICAgICAvL2F3YWl0IFByb21pc2UuYWxsKFthYmNQcm9taXNlLCBwaWFQcm9taXNlLCBwaWIxUHJvbWlzZSwgcGliUHJvbWlzZSwgcGljUHJvbWlzZV0pO1xuICAgICAgICByZXNIID0gYXdhaXQgY3VydmUuRzEubXVsdGlFeHBBZmZpbmUoYnVmZkJhc2VzSCwgYnVmZlBvZGRfVCwgbG9nZ2VyLCBcIm11bHRpZXhwIEhcIik7XG4gICAgICAgIC8vYnVmZlBvZGRfVCA9IG51bGw7XG4gICAgICAgIGNvbnNvbGUudGltZUVuZChcInJlc0hQcm9taXNlXCIpO1xuICAgIH0pKCk7XG4gICAgLy9hd2FpdCByZXNIUHJvbWlzZTtcblxuXG4gICAgY29uc3QgciA9IGN1cnZlLkZyLnJhbmRvbSgpO1xuICAgIGNvbnN0IHMgPSBjdXJ2ZS5Gci5yYW5kb20oKTtcblxuICAgIGF3YWl0IHBpYVByb21pc2U7XG4gICAgcHJvb2YucGlfYSAgPSBHMS5hZGQoIHByb29mLnBpX2EsIHprZXkudmtfYWxwaGFfMSApO1xuICAgIHByb29mLnBpX2EgID0gRzEuYWRkKCBwcm9vZi5waV9hLCBHMS50aW1lc0ZyKCB6a2V5LnZrX2RlbHRhXzEsIHIgKSk7XG5cbiAgICBhd2FpdCBwaWJQcm9taXNlO1xuICAgIHByb29mLnBpX2IgID0gRzIuYWRkKCBwcm9vZi5waV9iLCB6a2V5LnZrX2JldGFfMiApO1xuICAgIHByb29mLnBpX2IgID0gRzIuYWRkKCBwcm9vZi5waV9iLCBHMi50aW1lc0ZyKCB6a2V5LnZrX2RlbHRhXzIsIHMgKSk7XG5cbiAgICBhd2FpdCBwaWIxUHJvbWlzZTtcbiAgICBwaWIxID0gRzEuYWRkKCBwaWIxLCB6a2V5LnZrX2JldGFfMSApO1xuICAgIHBpYjEgPSBHMS5hZGQoIHBpYjEsIEcxLnRpbWVzRnIoIHprZXkudmtfZGVsdGFfMSwgcyApKTtcblxuICAgIGF3YWl0IFByb21pc2UuYWxsKFtwaWNQcm9taXNlLCByZXNIUHJvbWlzZV0pO1xuICAgIHByb29mLnBpX2MgPSBHMS5hZGQocHJvb2YucGlfYywgcmVzSCk7XG5cblxuICAgIHByb29mLnBpX2MgID0gRzEuYWRkKCBwcm9vZi5waV9jLCBHMS50aW1lc0ZyKCBwcm9vZi5waV9hLCBzICkpO1xuICAgIHByb29mLnBpX2MgID0gRzEuYWRkKCBwcm9vZi5waV9jLCBHMS50aW1lc0ZyKCBwaWIxLCByICkpO1xuICAgIHByb29mLnBpX2MgID0gRzEuYWRkKCBwcm9vZi5waV9jLCBHMS50aW1lc0ZyKCB6a2V5LnZrX2RlbHRhXzEsIEZyLm5lZyhGci5tdWwocixzKSApKSk7XG5cblxuICAgIGxldCBwdWJsaWNTaWduYWxzID0gW107XG5cbiAgICBmb3IgKGxldCBpPTE7IGk8PSB6a2V5Lm5QdWJsaWM7IGkrKykge1xuICAgICAgICBjb25zdCBiID0gYnVmZldpdG5lc3Muc2xpY2UoaSpGci5uOCwgaSpGci5uOCtGci5uOCk7XG4gICAgICAgIHB1YmxpY1NpZ25hbHMucHVzaChTY2FsYXIuZnJvbVJwckxFKGIpKTtcbiAgICB9XG5cbiAgICBwcm9vZi5waV9hID0gRzEudG9PYmplY3QoRzEudG9BZmZpbmUocHJvb2YucGlfYSkpO1xuICAgIHByb29mLnBpX2IgPSBHMi50b09iamVjdChHMi50b0FmZmluZShwcm9vZi5waV9iKSk7XG4gICAgcHJvb2YucGlfYyA9IEcxLnRvT2JqZWN0KEcxLnRvQWZmaW5lKHByb29mLnBpX2MpKTtcblxuICAgIHByb29mLnByb3RvY29sID0gXCJncm90aDE2XCI7XG4gICAgcHJvb2YuY3VydmUgPSBjdXJ2ZS5uYW1lO1xuXG4gICAgYXdhaXQgZmRaS2V5LmNsb3NlKCk7XG4gICAgYXdhaXQgZmRXdG5zLmNsb3NlKCk7XG5cbiAgICBwcm9vZiA9IHN0cmluZ2lmeUJpZ0ludHMocHJvb2YpO1xuICAgIHB1YmxpY1NpZ25hbHMgPSBzdHJpbmdpZnlCaWdJbnRzKHB1YmxpY1NpZ25hbHMpO1xuXG4gICAgcmV0dXJuIHtwcm9vZiwgcHVibGljU2lnbmFsc307XG59XG5cblxuYXN5bmMgZnVuY3Rpb24gYnVpbGRBQkMxKGN1cnZlLCB6a2V5LCB3aXRuZXNzLCBjb2VmZnMsIGxvZ2dlcikge1xuICAgIGNvbnN0IG44ID0gY3VydmUuRnIubjg7XG4gICAgY29uc3Qgc0NvZWYgPSA0KjMgKyB6a2V5Lm44cjtcbiAgICBjb25zdCBuQ29lZiA9IChjb2VmZnMuYnl0ZUxlbmd0aC00KSAvIHNDb2VmO1xuXG4gICAgY29uc3Qgb3V0QnVmZkEgPSBuZXcgQmlnQnVmZmVyKHprZXkuZG9tYWluU2l6ZSAqIG44KTtcbiAgICBjb25zdCBvdXRCdWZmQiA9IG5ldyBCaWdCdWZmZXIoemtleS5kb21haW5TaXplICogbjgpO1xuICAgIGNvbnN0IG91dEJ1ZmZDID0gbmV3IEJpZ0J1ZmZlcih6a2V5LmRvbWFpblNpemUgKiBuOCk7XG5cbiAgICBjb25zdCBvdXRCdWYgPSBbIG91dEJ1ZmZBLCBvdXRCdWZmQiBdO1xuICAgIGZvciAobGV0IGk9MDsgaTxuQ29lZjsgaSsrKSB7XG4gICAgICAgIGlmICgobG9nZ2VyKSYmKGklMTAwMDAwMCA9PSAwKSkgbG9nZ2VyLmRlYnVnKGBRQVAgQUI6ICR7aX0vJHtuQ29lZn1gKTtcblxuICAgICAgICBsZXQgYnVmZkNvZWZWLCBjb2VmO1xuICAgICAgICBpZiAoY29lZmZzLmJ1ZmZlcikge1xuICAgICAgICAgICAgLy8gaWYgd2UgaGF2ZSBkaXJlY3QgYWNjZXNzIHRvIGFycmF5IGJ1ZmZlciwgdGhlbiB3ZSBjYW4gY3JlYXRlIHplcm8tY29weSB2aWV3c1xuICAgICAgICAgICAgY29uc3QgY29lZmZPZmZzZXQgPSA0ICsgaSAqIHNDb2VmO1xuICAgICAgICAgICAgYnVmZkNvZWZWID0gbmV3IERhdGFWaWV3KGNvZWZmcy5idWZmZXIsIGNvZWZmcy5ieXRlT2Zmc2V0ICsgY29lZmZPZmZzZXQsIHNDb2VmKTtcbiAgICAgICAgICAgIGNvZWYgPSBuZXcgVWludDhBcnJheShjb2VmZnMuYnVmZmVyLCBjb2VmZnMuYnl0ZU9mZnNldCArIGNvZWZmT2Zmc2V0ICsgMTIsIG44KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGNvZWZmcyBpcyBhIEJpZ0J1ZmZlciBhbmQgd2UgbmVlZCB0byBjb3B5IHRoZSBzbGljZVxuICAgICAgICAgICAgY29uc3QgYnVmZkNvZWYgPSBjb2VmZnMuc2xpY2UoNCtpKnNDb2VmLCA0K2kqc0NvZWYrc0NvZWYpO1xuICAgICAgICAgICAgYnVmZkNvZWZWID0gbmV3IERhdGFWaWV3KGJ1ZmZDb2VmLmJ1ZmZlcik7XG4gICAgICAgICAgICBjb2VmID0gYnVmZkNvZWYuc2xpY2UoMTIsIDEyK244KTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBtID0gYnVmZkNvZWZWLmdldFVpbnQzMigwLCB0cnVlKTtcbiAgICAgICAgY29uc3QgYyA9IGJ1ZmZDb2VmVi5nZXRVaW50MzIoNCwgdHJ1ZSk7XG4gICAgICAgIGNvbnN0IHMgPSBidWZmQ29lZlYuZ2V0VWludDMyKDgsIHRydWUpO1xuXG4gICAgICAgIG91dEJ1ZlttXS5zZXQoXG4gICAgICAgICAgICBjdXJ2ZS5Gci5hZGQoXG4gICAgICAgICAgICAgICAgb3V0QnVmW21dLnNsaWNlKGMqbjgsIGMqbjgrbjgpLFxuICAgICAgICAgICAgICAgIGN1cnZlLkZyLm11bChjb2VmLCB3aXRuZXNzLnNsaWNlKHMqbjgsIHMqbjgrbjgpKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGMqbjhcbiAgICAgICAgKTtcblxuICAgICAgICBpZiAoaSUxMDAwMDAwID09IDAgJiYgbG9nZ2VyKSBtZW1Vc2FnZShsb2dnZXIpO1xuICAgIH1cblxuICAgIGZvciAobGV0IGk9MDsgaTx6a2V5LmRvbWFpblNpemU7IGkrKykge1xuICAgICAgICBpZiAoKGxvZ2dlcikmJihpJTEwMDAwMDAgPT0gMCkpIGxvZ2dlci5kZWJ1ZyhgUUFQIEM6ICR7aX0vJHt6a2V5LmRvbWFpblNpemV9YCk7XG4gICAgICAgIG91dEJ1ZmZDLnNldChcbiAgICAgICAgICAgIGN1cnZlLkZyLm11bChcbiAgICAgICAgICAgICAgICBvdXRCdWZmQS5zbGljZShpKm44LCBpKm44K244KSxcbiAgICAgICAgICAgICAgICBvdXRCdWZmQi5zbGljZShpKm44LCBpKm44K244KSxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBpKm44XG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFtvdXRCdWZmQSwgb3V0QnVmZkIsIG91dEJ1ZmZDXTtcblxufVxuXG5cbmFzeW5jIGZ1bmN0aW9uIGJ1aWxkQUJDKGN1cnZlLCB6a2V5LCB3aXRuZXNzLCBjb2VmZnMsIGxvZ2dlcikge1xuICAgIGxldCBjb25jdXJyZW5jeSA9IGN1cnZlLnRtLmNvbmN1cnJlbmN5O1xuICAgIGNvbnN0IHNDb2VmID0gNCozICsgemtleS5uOHI7XG5cbiAgICBsZXQgZ2V0VWludDMyO1xuXG4gICAgaWYgKGNvZWZmcyBpbnN0YW5jZW9mIEJpZ0J1ZmZlcikge1xuICAgICAgICBjb25zdCBjb2VmZnNEViA9IFtdO1xuICAgICAgICBjb25zdCBQQUdFX0xFTiA9IGNvZWZmcy5idWZmZXJzWzBdLmxlbmd0aDtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPCBjb2VmZnMuYnVmZmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29lZmZzRFYucHVzaChuZXcgRGF0YVZpZXcoY29lZmZzLmJ1ZmZlcnNbaV0uYnVmZmVyKSk7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0VWludDMyID0gZnVuY3Rpb24gKHBvcykge1xuICAgICAgICAgICAgcmV0dXJuIGNvZWZmc0RWW01hdGguZmxvb3IocG9zL1BBR0VfTEVOKV0uZ2V0VWludDMyKHBvcyAlIFBBR0VfTEVOLCB0cnVlKTtcbiAgICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBjb2VmZnNEViA9IG5ldyBEYXRhVmlldyhjb2VmZnMuYnVmZmVyLCBjb2VmZnMuYnl0ZU9mZnNldCwgY29lZmZzLmJ5dGVMZW5ndGgpO1xuICAgICAgICBnZXRVaW50MzIgPSBmdW5jdGlvbiAocG9zKSB7XG4gICAgICAgICAgICByZXR1cm4gY29lZmZzRFYuZ2V0VWludDMyKHBvcywgdHJ1ZSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgbGV0IGVsZW1lbnRzUGVyQ2h1bmsgPSBNYXRoLmZsb29yKHprZXkuZG9tYWluU2l6ZS9jb25jdXJyZW5jeSk7XG4gICAgY29uc29sZS5sb2coXCJAQEAgZWxlbWVudHNQZXJDaHVua1wiLCBlbGVtZW50c1BlckNodW5rKTtcbiAgICB3aGlsZSAoZWxlbWVudHNQZXJDaHVuayA+IDIqKjE2KSB7XG4gICAgICAgIGNvbmN1cnJlbmN5Kj0yO1xuICAgICAgICBlbGVtZW50c1BlckNodW5rID0gTWF0aC5mbG9vcih6a2V5LmRvbWFpblNpemUvY29uY3VycmVuY3kpO1xuICAgIH1cbiAgICBjb25zb2xlLmxvZyhcIkBAQCBuZXcgZWxlbWVudHNQZXJDaHVua1wiLCBlbGVtZW50c1BlckNodW5rKTtcblxuXG4gICAgY29uc3QgcHJvbWlzZXMgPSBbXTtcblxuICAgIGNvbnN0IGN1dFBvaW50cyA9IFtdO1xuICAgIGZvciAobGV0IGk9MDsgaTxjb25jdXJyZW5jeTsgaSsrKSB7XG4gICAgICAgIGN1dFBvaW50cy5wdXNoKCBnZXRDdXRQb2ludCggTWF0aC5mbG9vcihpKmVsZW1lbnRzUGVyQ2h1bmspICkpO1xuICAgIH1cbiAgICBjdXRQb2ludHMucHVzaChjb2VmZnMuYnl0ZUxlbmd0aCk7XG5cbiAgICBjb25zdCBjaHVua1NpemUgPSAyKioyNjtcbiAgICBmb3IgKGxldCBzPTAgOyBzPHprZXkublZhcnMgOyBzKz0gY2h1bmtTaXplKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhgUUFQICR7c306ICR7c30vJHt6a2V5Lm5WYXJzfWApO1xuICAgICAgICBjb25zdCBucz0gTWF0aC5taW4oemtleS5uVmFycy1zLCBjaHVua1NpemUgKTtcblxuICAgICAgICBmb3IgKGxldCBpPTA7IGk8Y29uY3VycmVuY3k7IGkrKykge1xuICAgICAgICAgICAgbGV0IG47XG4gICAgICAgICAgICBpZiAoaTwgY29uY3VycmVuY3ktMSkge1xuICAgICAgICAgICAgICAgIG4gPSBlbGVtZW50c1BlckNodW5rO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBuID0gemtleS5kb21haW5TaXplIC0gaSplbGVtZW50c1BlckNodW5rO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG49PTApIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICBjb25zdCB0YXNrID0gW107XG5cbiAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkFMTE9DU0VUXCIsIHZhcjogMCwgYnVmZjogY29lZmZzLnNsaWNlKGN1dFBvaW50c1tpXSwgY3V0UG9pbnRzW2krMV0pfSk7XG4gICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJBTExPQ1NFVFwiLCB2YXI6IDEsIGJ1ZmY6IHdpdG5lc3Muc2xpY2UocypjdXJ2ZS5Gci5uOCwgKHMrbnMpKmN1cnZlLkZyLm44KX0pO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQUxMT0NcIiwgdmFyOiAyLCBsZW46IG4qY3VydmUuRnIubjh9KTtcbiAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkFMTE9DXCIsIHZhcjogMywgbGVuOiBuKmN1cnZlLkZyLm44fSk7XG4gICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJBTExPQ1wiLCB2YXI6IDQsIGxlbjogbipjdXJ2ZS5Gci5uOH0pO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQ0FMTFwiLCBmbk5hbWU6IFwicWFwX2J1aWxkQUJDXCIsIHBhcmFtczpbXG4gICAgICAgICAgICAgICAge3ZhcjogMH0sXG4gICAgICAgICAgICAgICAge3ZhbDogKGN1dFBvaW50c1tpKzFdIC0gY3V0UG9pbnRzW2ldKS9zQ29lZn0sXG4gICAgICAgICAgICAgICAge3ZhcjogMX0sXG4gICAgICAgICAgICAgICAge3ZhcjogMn0sXG4gICAgICAgICAgICAgICAge3ZhcjogM30sXG4gICAgICAgICAgICAgICAge3ZhcjogNH0sXG4gICAgICAgICAgICAgICAge3ZhbDogaSplbGVtZW50c1BlckNodW5rfSxcbiAgICAgICAgICAgICAgICB7dmFsOiBufSxcbiAgICAgICAgICAgICAgICB7dmFsOiBzfSxcbiAgICAgICAgICAgICAgICB7dmFsOiBuc31cbiAgICAgICAgICAgIF19KTtcbiAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkdFVFwiLCBvdXQ6IDAsIHZhcjogMiwgbGVuOiBuKmN1cnZlLkZyLm44fSk7XG4gICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJHRVRcIiwgb3V0OiAxLCB2YXI6IDMsIGxlbjogbipjdXJ2ZS5Gci5uOH0pO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiR0VUXCIsIG91dDogMiwgdmFyOiA0LCBsZW46IG4qY3VydmUuRnIubjh9KTtcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2goY3VydmUudG0ucXVldWVBY3Rpb24odGFzaykpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbGV0IHJlc3VsdCA9IGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VzKTtcblxuICAgIGNvbnN0IG5Hcm91cHMgPSByZXN1bHQubGVuZ3RoIC8gY29uY3VycmVuY3k7XG4gICAgaWYgKG5Hcm91cHM+MSkge1xuICAgICAgICBjb25zdCBwcm9taXNlczIgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPGNvbmN1cnJlbmN5OyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IHRhc2s9W107XG4gICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJBTExPQ1wiLCB2YXI6IDAsIGxlbjogcmVzdWx0W2ldWzBdLmJ5dGVMZW5ndGh9KTtcbiAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkFMTE9DXCIsIHZhcjogMSwgbGVuOiByZXN1bHRbaV1bMF0uYnl0ZUxlbmd0aH0pO1xuICAgICAgICAgICAgZm9yIChsZXQgbT0wOyBtPDM7IG0rKykge1xuICAgICAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIlNFVFwiLCB2YXI6IDAsIGJ1ZmY6IHJlc3VsdFtpXVttXX0pO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHM9MTsgczxuR3JvdXBzOyBzKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiU0VUXCIsIHZhcjogMSwgYnVmZjogcmVzdWx0W3MqY29uY3VycmVuY3kgKyBpXVttXX0pO1xuICAgICAgICAgICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJDQUxMXCIsIGZuTmFtZTogXCJxYXBfYmF0Y2hBZGRcIiwgcGFyYW1zOltcbiAgICAgICAgICAgICAgICAgICAgICAgIHt2YXI6IDB9LFxuICAgICAgICAgICAgICAgICAgICAgICAge3ZhcjogMX0sXG4gICAgICAgICAgICAgICAgICAgICAgICB7dmFsOiByZXN1bHRbaV1bbV0ubGVuZ3RoL2N1cnZlLkZyLm44fSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHt2YXI6IDB9XG4gICAgICAgICAgICAgICAgICAgIF19KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiR0VUXCIsIG91dDogbSwgdmFyOiAwLCBsZW46IHJlc3VsdFtpXVttXS5sZW5ndGh9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHByb21pc2VzMi5wdXNoKGN1cnZlLnRtLnF1ZXVlQWN0aW9uKHRhc2spKTtcbiAgICAgICAgfVxuICAgICAgICByZXN1bHQgPSBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlczIpO1xuICAgIH1cblxuICAgIGNvbnN0IG91dEJ1ZmZBID0gbmV3IEJpZ0J1ZmZlcih6a2V5LmRvbWFpblNpemUgKiBjdXJ2ZS5Gci5uOCk7XG4gICAgY29uc3Qgb3V0QnVmZkIgPSBuZXcgQmlnQnVmZmVyKHprZXkuZG9tYWluU2l6ZSAqIGN1cnZlLkZyLm44KTtcbiAgICBjb25zdCBvdXRCdWZmQyA9IG5ldyBCaWdCdWZmZXIoemtleS5kb21haW5TaXplICogY3VydmUuRnIubjgpO1xuICAgIGxldCBwPTA7XG4gICAgZm9yIChsZXQgaT0wOyBpPHJlc3VsdC5sZW5ndGg7IGkrKykge1xuICAgICAgICBvdXRCdWZmQS5zZXQocmVzdWx0W2ldWzBdLCBwKTtcbiAgICAgICAgb3V0QnVmZkIuc2V0KHJlc3VsdFtpXVsxXSwgcCk7XG4gICAgICAgIG91dEJ1ZmZDLnNldChyZXN1bHRbaV1bMl0sIHApO1xuICAgICAgICBwICs9IHJlc3VsdFtpXVswXS5ieXRlTGVuZ3RoO1xuICAgIH1cblxuICAgIHJldHVybiBbb3V0QnVmZkEsIG91dEJ1ZmZCLCBvdXRCdWZmQ107XG5cbiAgICBmdW5jdGlvbiBnZXRDdXRQb2ludCh2KSB7XG4gICAgICAgIGxldCBtID0gMDtcbiAgICAgICAgbGV0IG4gPSBnZXRVaW50MzIoMCk7XG4gICAgICAgIHdoaWxlIChtIDwgbikge1xuICAgICAgICAgICAgdmFyIGsgPSBNYXRoLmZsb29yKChuICsgbSkgLyAyKTtcbiAgICAgICAgICAgIGNvbnN0IHZhID0gZ2V0VWludDMyKDQgKyBrKnNDb2VmICsgNCk7XG4gICAgICAgICAgICBpZiAodmEgPiB2KSB7XG4gICAgICAgICAgICAgICAgbiA9IGsgLSAxO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh2YSA8IHYpIHtcbiAgICAgICAgICAgICAgICBtID0gayArIDE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG4gPSBrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiA0ICsgbSpzQ29lZjtcbiAgICB9XG59XG5cblxuLy8gYnVpbGRBQkNXQVNNMSBpcyBzaW5nbGUtdGhyZWFkZWQgaW1wbGVtZW50YXRpb24gb2YgYnVpbGRBQlMgdXNpbmcgd2FzbVxuLy8gSXQgaGFzIG11Y2ggYmV0dGVyIG1lbW9yeSB1c2FnZSB0aGFuIG11bHRpdGhyZWFkZWQgd2FzbSBpbXBsZW1lbnRhdGlvbi5cbi8vIEl0J3MgbXVjaCBmYXN0ZXIgdGhhbiBwdXJlIGpzIG9uZSwgYnV0IHVzZXMgbXVjaCBtb3JlIG1lbW9yeS5cbmFzeW5jIGZ1bmN0aW9uIGJ1aWxkQUJDV0FTTTEoY3VydmUsIHprZXksIHdpdG5lc3MsIGNvZWZmcywgbG9nZ2VyKSB7XG4gICAgY29uc29sZS50aW1lKFwiYnVpbGRBQkNcIik7XG4gICAgY29uc3QgY29uY3VycmVuY3kgPSAxOy8vY3VydmUudG0uY29uY3VycmVuY3k7XG4gICAgY29uc3Qgc0NvZWYgPSA0ICogMyArIHprZXkubjhyO1xuXG4gICAgbGV0IGdldFVpbnQzMjtcblxuICAgIGlmIChjb2VmZnMgaW5zdGFuY2VvZiBCaWdCdWZmZXIpIHtcbiAgICAgICAgY29uc3QgY29lZmZzRFYgPSBbXTtcbiAgICAgICAgY29uc3QgUEFHRV9MRU4gPSBjb2VmZnMuYnVmZmVyc1swXS5sZW5ndGg7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29lZmZzLmJ1ZmZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvZWZmc0RWLnB1c2gobmV3IERhdGFWaWV3KGNvZWZmcy5idWZmZXJzW2ldLmJ1ZmZlcikpO1xuICAgICAgICB9XG4gICAgICAgIGdldFVpbnQzMiA9IGZ1bmN0aW9uIChwb3MpIHtcbiAgICAgICAgICAgIHJldHVybiBjb2VmZnNEVltNYXRoLmZsb29yKHBvcyAvIFBBR0VfTEVOKV0uZ2V0VWludDMyKHBvcyAlIFBBR0VfTEVOLCB0cnVlKTtcbiAgICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBjb2VmZnNEViA9IG5ldyBEYXRhVmlldyhjb2VmZnMuYnVmZmVyLCBjb2VmZnMuYnl0ZU9mZnNldCwgY29lZmZzLmJ5dGVMZW5ndGgpO1xuICAgICAgICBnZXRVaW50MzIgPSBmdW5jdGlvbiAocG9zKSB7XG4gICAgICAgICAgICByZXR1cm4gY29lZmZzRFYuZ2V0VWludDMyKHBvcywgdHJ1ZSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3QgZWxlbWVudHNQZXJDaHVuayA9IE1hdGguZmxvb3IoKHprZXkuZG9tYWluU2l6ZSAtIDEpIC8gY29uY3VycmVuY3kpICsgMTtcbiAgICBjb25zdCBwcm9taXNlcyA9IFtdO1xuXG4gICAgY29uc3QgY3V0UG9pbnRzID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb25jdXJyZW5jeTsgaSsrKSB7XG4gICAgICAgIGN1dFBvaW50cy5wdXNoKGdldEN1dFBvaW50KE1hdGguZmxvb3IoaSAqIGVsZW1lbnRzUGVyQ2h1bmspKSk7XG4gICAgfVxuICAgIGN1dFBvaW50cy5wdXNoKGNvZWZmcy5ieXRlTGVuZ3RoKTtcblxuICAgIC8vY29uc3QgY2h1bmtTaXplID0gMioqMTg7XG4gICAgY29uc3QgY2h1bmtTaXplID0gZWxlbWVudHNQZXJDaHVuaztcblxuICAgIGNvbnNvbGUubG9nKFwiemtleS5kb21haW5TaXplXCIsIHprZXkuZG9tYWluU2l6ZSk7XG4gICAgY29uc29sZS5sb2coXCJjb25jdXJyZW5jeVwiLCBjb25jdXJyZW5jeSk7XG4gICAgY29uc29sZS5sb2coXCJlbGVtZW50c1BlckNodW5rXCIsIGVsZW1lbnRzUGVyQ2h1bmspO1xuICAgIGNvbnNvbGUubG9nKFwiY2h1bmtTaXplXCIsIGNodW5rU2l6ZSk7XG5cbiAgICBmb3IgKGxldCBzID0gMDsgcyA8IHprZXkublZhcnM7IHMgKz0gY2h1bmtTaXplKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhgUUFQOiAke3N9LyR7emtleS5uVmFyc31gKTtcbiAgICAgICAgY29uc3QgbnMgPSBNYXRoLm1pbih6a2V5Lm5WYXJzIC0gcywgY2h1bmtTaXplKTtcblxuICAgICAgICBjb25zb2xlLmxvZyhcIm5zXCIsIG5zKTtcblxuICAgICAgICAvL2xldCBpPTA7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29uY3VycmVuY3k7IGkrKykge1xuICAgICAgICAgICAgbGV0IG47XG4gICAgICAgICAgICBpZiAoaSA8IGNvbmN1cnJlbmN5IC0gMSkge1xuICAgICAgICAgICAgICAgIG4gPSBlbGVtZW50c1BlckNodW5rO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBuID0gemtleS5kb21haW5TaXplIC0gaSAqIGVsZW1lbnRzUGVyQ2h1bms7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobiA9PT0gMCkgY29udGludWU7XG5cbiAgICAgICAgICAgIGNvbnN0IHRhc2sgPSBbXTtcblxuICAgICAgICAgICAgY29uc3QgY29lZmZzQnVmZiA9IGNvZWZmcy5zbGljZShjdXRQb2ludHNbaV0sIGN1dFBvaW50c1tpICsgMV0pO1xuICAgICAgICAgICAgY29uc3Qgd2l0bmVzc0J1ZmYgPSB3aXRuZXNzLnNsaWNlKHMgKiBjdXJ2ZS5Gci5uOCwgKHMgKyBucykgKiBjdXJ2ZS5Gci5uOCk7XG5cbiAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkFMTE9DU0VUXCIsIHZhcjogMCwgYnVmZjogY29lZmZzQnVmZn0pO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQUxMT0NTRVRcIiwgdmFyOiAxLCBidWZmOiB3aXRuZXNzQnVmZn0pO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQUxMT0NcIiwgdmFyOiAyLCBsZW46IG4gKiBjdXJ2ZS5Gci5uOH0pO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQUxMT0NcIiwgdmFyOiAzLCBsZW46IG4gKiBjdXJ2ZS5Gci5uOH0pO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQUxMT0NcIiwgdmFyOiA0LCBsZW46IG4gKiBjdXJ2ZS5Gci5uOH0pO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtcbiAgICAgICAgICAgICAgICBjbWQ6IFwiQ0FMTFwiLCBmbk5hbWU6IFwicWFwX2J1aWxkQUJDXCIsIHBhcmFtczogW1xuICAgICAgICAgICAgICAgICAgICB7dmFyOiAwfSxcbiAgICAgICAgICAgICAgICAgICAge3ZhbDogKGN1dFBvaW50c1tpICsgMV0gLSBjdXRQb2ludHNbaV0pIC8gc0NvZWZ9LFxuICAgICAgICAgICAgICAgICAgICB7dmFyOiAxfSxcbiAgICAgICAgICAgICAgICAgICAge3ZhcjogMn0sXG4gICAgICAgICAgICAgICAgICAgIHt2YXI6IDN9LFxuICAgICAgICAgICAgICAgICAgICB7dmFyOiA0fSxcbiAgICAgICAgICAgICAgICAgICAge3ZhbDogaSAqIGVsZW1lbnRzUGVyQ2h1bmt9LFxuICAgICAgICAgICAgICAgICAgICB7dmFsOiBufSxcbiAgICAgICAgICAgICAgICAgICAge3ZhbDogc30sXG4gICAgICAgICAgICAgICAgICAgIHt2YWw6IG5zfVxuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiR0VUXCIsIG91dDogMCwgdmFyOiAyLCBsZW46IG4gKiBjdXJ2ZS5Gci5uOH0pO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiR0VUXCIsIG91dDogMSwgdmFyOiAzLCBsZW46IG4gKiBjdXJ2ZS5Gci5uOH0pO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiR0VUXCIsIG91dDogMiwgdmFyOiA0LCBsZW46IG4gKiBjdXJ2ZS5Gci5uOH0pO1xuICAgICAgICAgICAgLy90YXNrLnB1c2goe2NtZDogXCJURVJNSU5BVEVcIn0pOyAvLyB0byBmcmVlIG1lbW9yeSBpbW1lZGlhdGVseVxuICAgICAgICAgICAgLy9wcm9taXNlcy5wdXNoKGN1cnZlLnRtLnF1ZXVlQWN0aW9uKHRhc2spKTtcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2goY3VydmUudG0ucXVldWVBY3Rpb24odGFzaywgW2NvZWZmc0J1ZmYuYnVmZmVyLCB3aXRuZXNzQnVmZi5idWZmZXJdKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgcmVzdWx0ID0gYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuXG5cbiAgICBjb25zb2xlLmxvZyhcInJlc3VsdC5sZW5ndGhcIiwgcmVzdWx0Lmxlbmd0aCk7XG4gICAgY29uc29sZS5sb2coXCJyZXN1bHRcIiwgcmVzdWx0KTtcblxuICAgIGNvbnN0IG5Hcm91cHMgPSByZXN1bHQubGVuZ3RoIC8gY29uY3VycmVuY3k7XG5cbiAgICBjb25zb2xlLmxvZyhcIm5Hcm91cHNcIiwgbkdyb3Vwcyk7XG5cbiAgICBjb25zdCB0cmFuc2ZlcnMgPSBbXTtcbiAgICBsZXQgcmVzdWx0MjtcbiAgICBpZiAobkdyb3VwcyA+IDEpIHtcbiAgICAgICAgY29uc3QgcHJvbWlzZXMyID0gW107XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29uY3VycmVuY3k7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgdGFzayA9IFtdO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQUxMT0NcIiwgdmFyOiAwLCBsZW46IHJlc3VsdFtpXVswXS5ieXRlTGVuZ3RofSk7XG4gICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJBTExPQ1wiLCB2YXI6IDEsIGxlbjogcmVzdWx0W2ldWzBdLmJ5dGVMZW5ndGh9KTtcbiAgICAgICAgICAgIGZvciAobGV0IG0gPSAwOyBtIDwgMzsgbSsrKSB7XG4gICAgICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiU0VUXCIsIHZhcjogMCwgYnVmZjogcmVzdWx0W2ldW21dfSk7XG4gICAgICAgICAgICAgICAgLy90cmFuc2ZlcnMucHVzaChyZXN1bHRbaV1bbV0uYnVmZmVyKTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBzID0gMTsgcyA8IG5Hcm91cHM7IHMrKykge1xuICAgICAgICAgICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJTRVRcIiwgdmFyOiAxLCBidWZmOiByZXN1bHRbcyAqIGNvbmN1cnJlbmN5ICsgaV1bbV19KTtcbiAgICAgICAgICAgICAgICAgICAgLy90cmFuc2ZlcnMucHVzaChyZXN1bHRbcypjb25jdXJyZW5jeSArIGldW21dLmJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgICAgIHRhc2sucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbWQ6IFwiQ0FMTFwiLCBmbk5hbWU6IFwicWFwX2JhdGNoQWRkXCIsIHBhcmFtczogW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt2YXI6IDB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt2YXI6IDF9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt2YWw6IHJlc3VsdFtpXVttXS5sZW5ndGggLyBjdXJ2ZS5Gci5uOH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge3ZhcjogMH1cbiAgICAgICAgICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkdFVFwiLCBvdXQ6IG0sIHZhcjogMCwgbGVuOiByZXN1bHRbaV1bbV0ubGVuZ3RofSk7XG4gICAgICAgICAgICAgICAgLy90YXNrLnB1c2goe2NtZDogXCJURVJNSU5BVEVcIn0pOyAvLyB0byBmcmVlIG1lbW9yeSBpbW1lZGlhdGVseVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc29sZS5sb2coXCJ0YXNrLmxlbmd0aFwiLCB0YXNrLmxlbmd0aCk7XG4gICAgICAgICAgICAvL3Byb21pc2VzMi5wdXNoKGN1cnZlLnRtLnF1ZXVlQWN0aW9uKHRhc2spKTtcbiAgICAgICAgICAgIHByb21pc2VzMi5wdXNoKGN1cnZlLnRtLnF1ZXVlQWN0aW9uKHRhc2ssIHJlc3VsdC5idWZmZXIpKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zb2xlLmxvZyhcInByb21pc2VzMi5sZW5ndGhcIiwgcHJvbWlzZXMyLmxlbmd0aCk7XG4gICAgICAgIHJlc3VsdDIgPSBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlczIpO1xuICAgICAgICByZXN1bHQgPSByZXN1bHQyO1xuICAgIH1cblxuICAgIC8vY29uc29sZS5sb2coXCJyZXN1bHRcIiwgcmVzdWx0KTtcbiAgICAvL2NvbnNvbGUubG9nKFwicmVzdWx0MlwiLCByZXN1bHQyKTtcbiAgICAvL3Jlc3VsdCA9IHJlc3VsdDIgfHwgcmVzdWx0O1xuXG4gICAgY29uc3Qgb3V0QnVmZkEgPSBuZXcgQmlnQnVmZmVyKHprZXkuZG9tYWluU2l6ZSAqIGN1cnZlLkZyLm44KTtcbiAgICBjb25zdCBvdXRCdWZmQiA9IG5ldyBCaWdCdWZmZXIoemtleS5kb21haW5TaXplICogY3VydmUuRnIubjgpO1xuICAgIGNvbnN0IG91dEJ1ZmZDID0gbmV3IEJpZ0J1ZmZlcih6a2V5LmRvbWFpblNpemUgKiBjdXJ2ZS5Gci5uOCk7XG4gICAgbGV0IHAgPSAwO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVzdWx0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIG91dEJ1ZmZBLnNldChyZXN1bHRbaV1bMF0sIHApO1xuICAgICAgICBvdXRCdWZmQi5zZXQocmVzdWx0W2ldWzFdLCBwKTtcbiAgICAgICAgb3V0QnVmZkMuc2V0KHJlc3VsdFtpXVsyXSwgcCk7XG4gICAgICAgIHAgKz0gcmVzdWx0W2ldWzBdLmJ5dGVMZW5ndGg7XG4gICAgfVxuXG4gICAgY29uc29sZS50aW1lRW5kKFwiYnVpbGRBQkNcIik7XG5cbiAgICByZXR1cm4gW291dEJ1ZmZBLCBvdXRCdWZmQiwgb3V0QnVmZkNdO1xuXG4gICAgZnVuY3Rpb24gZ2V0Q3V0UG9pbnQodikge1xuICAgICAgICBsZXQgbSA9IDA7XG4gICAgICAgIGxldCBuID0gZ2V0VWludDMyKDApO1xuICAgICAgICB3aGlsZSAobSA8IG4pIHtcbiAgICAgICAgICAgIGxldCBrID0gTWF0aC5mbG9vcigobiArIG0pIC8gMik7XG4gICAgICAgICAgICBjb25zdCB2YSA9IGdldFVpbnQzMig0ICsgayAqIHNDb2VmICsgNCk7XG4gICAgICAgICAgICBpZiAodmEgPiB2KSB7XG4gICAgICAgICAgICAgICAgbiA9IGsgLSAxO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh2YSA8IHYpIHtcbiAgICAgICAgICAgICAgICBtID0gayArIDE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG4gPSBrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiA0ICsgbSAqIHNDb2VmO1xuICAgIH1cbn1cblxuXG5hc3luYyBmdW5jdGlvbiBqb2luQUJDKGN1cnZlLCB6a2V5LCBhLCBiLCBjLCBsb2dnZXIpIHtcbiAgICBjb25zb2xlLnRpbWUoXCJqb2luQUJDXCIpO1xuICAgIGNvbnN0IE1BWF9DSFVOS19TSVpFID0gMSA8PCAxNjtcblxuICAgIGNvbnN0IG44ID0gY3VydmUuRnIubjg7XG4gICAgY29uc3QgbkVsZW1lbnRzID0gTWF0aC5mbG9vcihhLmJ5dGVMZW5ndGggLyBjdXJ2ZS5Gci5uOCk7XG5cbiAgICBjb25zdCBwcm9taXNlcyA9IFtdO1xuXG4gICAgZm9yIChsZXQgaT0wOyBpPG5FbGVtZW50czsgaSArPSBNQVhfQ0hVTktfU0laRSkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoYEpvaW5BQkM6ICR7aX0vJHtuRWxlbWVudHN9YCk7XG4gICAgICAgIGNvbnN0IG49IE1hdGgubWluKG5FbGVtZW50cyAtIGksIE1BWF9DSFVOS19TSVpFKTtcblxuICAgICAgICBjb25zdCB0YXNrID0gW107XG5cbiAgICAgICAgY29uc3QgYUNodW5rID0gYS5zbGljZShpKm44LCAoaSArIG4pKm44ICk7XG4gICAgICAgIGNvbnN0IGJDaHVuayA9IGIuc2xpY2UoaSpuOCwgKGkgKyBuKSpuOCApO1xuICAgICAgICBjb25zdCBjQ2h1bmsgPSBjLnNsaWNlKGkqbjgsIChpICsgbikqbjggKTtcblxuICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJBTExPQ1NFVFwiLCB2YXI6IDAsIGJ1ZmY6IGFDaHVua30pO1xuICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJBTExPQ1NFVFwiLCB2YXI6IDEsIGJ1ZmY6IGJDaHVua30pO1xuICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJBTExPQ1NFVFwiLCB2YXI6IDIsIGJ1ZmY6IGNDaHVua30pO1xuICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJBTExPQ1wiLCB2YXI6IDMsIGxlbjogbipuOH0pO1xuICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJDQUxMXCIsIGZuTmFtZTogXCJxYXBfam9pbkFCQ1wiLCBwYXJhbXM6W1xuICAgICAgICAgICAge3ZhcjogMH0sXG4gICAgICAgICAgICB7dmFyOiAxfSxcbiAgICAgICAgICAgIHt2YXI6IDJ9LFxuICAgICAgICAgICAge3ZhbDogbn0sXG4gICAgICAgICAgICB7dmFyOiAzfSxcbiAgICAgICAgXX0pO1xuICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJDQUxMXCIsIGZuTmFtZTogXCJmcm1fYmF0Y2hGcm9tTW9udGdvbWVyeVwiLCBwYXJhbXM6W1xuICAgICAgICAgICAge3ZhcjogM30sXG4gICAgICAgICAgICB7dmFsOiBufSxcbiAgICAgICAgICAgIHt2YXI6IDN9XG4gICAgICAgIF19KTtcbiAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiR0VUXCIsIG91dDogMCwgdmFyOiAzLCBsZW46IG4qbjh9KTtcbiAgICAgICAgcHJvbWlzZXMucHVzaChjdXJ2ZS50bS5xdWV1ZUFjdGlvbih0YXNrLCBbYUNodW5rLmJ1ZmZlciwgYkNodW5rLmJ1ZmZlciwgY0NodW5rLmJ1ZmZlcl0pICk7XG4gICAgfVxuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuXG4gICAgbGV0IG91dEJ1ZmY7XG4gICAgaWYgKGEgaW5zdGFuY2VvZiBCaWdCdWZmZXIpIHtcbiAgICAgICAgb3V0QnVmZiA9IG5ldyBCaWdCdWZmZXIoYS5ieXRlTGVuZ3RoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBvdXRCdWZmID0gbmV3IFVpbnQ4QXJyYXkoYS5ieXRlTGVuZ3RoKTtcbiAgICB9XG5cbiAgICBsZXQgcD0wO1xuICAgIGZvciAobGV0IGk9MDsgaTxyZXN1bHQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgb3V0QnVmZi5zZXQocmVzdWx0W2ldWzBdLCBwKTtcbiAgICAgICAgcCArPSByZXN1bHRbaV1bMF0uYnl0ZUxlbmd0aDtcbiAgICB9XG5cbiAgICBjb25zb2xlLnRpbWVFbmQoXCJqb2luQUJDXCIpO1xuICAgIHJldHVybiBvdXRCdWZmO1xufVxuXG5mdW5jdGlvbiBtZW1Vc2FnZShsb2dnZXIpIHtcbiAgICBpZiAoIWxvZ2dlcikgcmV0dXJuO1xuICAgIGNvbnN0IHVzZWQgPSBwcm9jZXNzLm1lbW9yeVVzYWdlKCk7XG4gICAgbG9nZ2VyLmRlYnVnKFxuICAgICAgICBcIiAgICAgICAgIFwiLFxuICAgICAgICBcIlxceDFiWzBtIEhlYXA6XFx4MWJbMzJtXCIsIGAke01hdGgucm91bmQodXNlZC5oZWFwVXNlZCAvIDEwMjQgLyAxMDI0ICogMTAwKSAvIDEwMH0gTUJgLnBhZEVuZCgxMiksXG4gICAgICAgIFwiXFx4MWJbMG0gLyBcXHgxYlszMm1cIiwgYCR7TWF0aC5yb3VuZCh1c2VkLmhlYXBUb3RhbCAvIDEwMjQgLyAxMDI0ICogMTAwKSAvIDEwMH0gTUJgLnBhZEVuZCgxMiksXG4gICAgICAgIFwiXFx4MWJbMG0gUlNTOlxceDFiWzMybVwiLCBgJHtNYXRoLnJvdW5kKHVzZWQucnNzIC8gMTAyNCAvIDEwMjQgKiAxMDApIC8gMTAwfSBNQmAucGFkRW5kKDEyKSxcbiAgICAgICAgXCJcXHgxYlswbSBFeHRlcm5hbDpcXHgxYlszMm1cIiwgYCR7TWF0aC5yb3VuZCh1c2VkLmV4dGVybmFsIC8gMTAyNCAvIDEwMjQgKiAxMDApIC8gMTAwfSBNQmAucGFkRW5kKDEyKSxcbiAgICAgICAgXCJcXHgxYlswbSBBcnJCdWZmZXJzOlxceDFiWzMybVwiLCBgJHtNYXRoLnJvdW5kKHVzZWQuYXJyYXlCdWZmZXJzIC8gMTAyNCAvIDEwMjQgKiAxMDApIC8gMTAwfSBNQmAucGFkRW5kKDEyKSxcbiAgICAgICAgXCJcXHgxYlswbVwiXG4gICAgKTtcbn1cblxuZnVuY3Rpb24gbW9uaXRvck1lbW9yeVVzYWdlKGxvZ2dlciwgaW50ZXJ2YWwgPSA1MDAwKSB7XG4gICAgcmV0dXJuIHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgbWVtVXNhZ2UobG9nZ2VyKTtcbiAgICB9LCBpbnRlcnZhbCk7XG59XG4iLCJcbmltcG9ydCBmcyBmcm9tXCJmc1wiO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gb3BlbihmaWxlTmFtZSwgb3BlbkZsYWdzLCBjYWNoZVNpemUsIHBhZ2VTaXplKSB7XG4gICAgY2FjaGVTaXplID0gY2FjaGVTaXplIHx8IDQwOTYqNjQ7XG4gICAgaWYgKHR5cGVvZiBvcGVuRmxhZ3MgIT09IFwibnVtYmVyXCIgJiYgW1widytcIiwgXCJ3eCtcIiwgXCJyXCIsIFwiYXgrXCIsIFwiYStcIl0uaW5kZXhPZihvcGVuRmxhZ3MpIDwwKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIG9wZW4gb3B0aW9uXCIpO1xuICAgIGNvbnN0IGZkID1hd2FpdCBmcy5wcm9taXNlcy5vcGVuKGZpbGVOYW1lLCBvcGVuRmxhZ3MpO1xuXG4gICAgY29uc3Qgc3RhdHMgPSBhd2FpdCBmZC5zdGF0KCk7XG5cbiAgICByZXR1cm4gIG5ldyBGYXN0RmlsZShmZCwgc3RhdHMsIGNhY2hlU2l6ZSwgcGFnZVNpemUsIGZpbGVOYW1lKTtcbn1cblxuXG5jbGFzcyBGYXN0RmlsZSB7XG5cbiAgICBjb25zdHJ1Y3RvcihmZCwgc3RhdHMsIGNhY2hlU2l6ZSwgcGFnZVNpemUsIGZpbGVOYW1lKSB7XG4gICAgICAgIHRoaXMuZmlsZU5hbWUgPSBmaWxlTmFtZTtcbiAgICAgICAgdGhpcy5mZCA9IGZkO1xuICAgICAgICB0aGlzLnBvcyA9IDA7XG4gICAgICAgIHRoaXMucGFnZVNpemUgPSBwYWdlU2l6ZSB8fCAoMSA8PCA4KTtcbiAgICAgICAgd2hpbGUgKHRoaXMucGFnZVNpemUgPCBzdGF0cy5ibGtzaXplKSB7XG4gICAgICAgICAgICB0aGlzLnBhZ2VTaXplICo9IDI7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy50b3RhbFNpemUgPSBzdGF0cy5zaXplO1xuICAgICAgICB0aGlzLnRvdGFsUGFnZXMgPSBNYXRoLmZsb29yKChzdGF0cy5zaXplIC0xKSAvIHRoaXMucGFnZVNpemUpKzE7XG4gICAgICAgIHRoaXMubWF4UGFnZXNMb2FkZWQgPSBNYXRoLmZsb29yKCBjYWNoZVNpemUgLyB0aGlzLnBhZ2VTaXplKSsxO1xuICAgICAgICB0aGlzLnBhZ2VzID0ge307XG4gICAgICAgIHRoaXMucGVuZGluZ0xvYWRzID0gW107XG4gICAgICAgIHRoaXMud3JpdGluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLnJlYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5hdkJ1ZmZzID0gW107XG4gICAgICAgIHRoaXMuaGlzdG9yeSA9IHt9O1xuICAgIH1cblxuICAgIF9sb2FkUGFnZShwKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBjb25zdCBQID0gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCk9PiB7XG4gICAgICAgICAgICBzZWxmLnBlbmRpbmdMb2Fkcy5wdXNoKHtcbiAgICAgICAgICAgICAgICBwYWdlOiBwLFxuICAgICAgICAgICAgICAgIHJlc29sdmU6IHJlc29sdmUsXG4gICAgICAgICAgICAgICAgcmVqZWN0OiByZWplY3RcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgc2VsZi5fX3N0YXR1c1BhZ2UoXCJBZnRlciBMb2FkIHJlcXVlc3Q6IFwiLCBwKTtcbiAgICAgICAgcmV0dXJuIFA7XG4gICAgfVxuXG4gICAgX19zdGF0dXNQYWdlKHMsIHApIHtcbiAgICAgICAgY29uc3QgbG9nRW50cnkgPSBbXTtcbiAgICAgICAgY29uc3Qgc2VsZj10aGlzO1xuICAgICAgICBpZiAoIXNlbGYubG9nSGlzdG9yeSkgcmV0dXJuO1xuICAgICAgICBsb2dFbnRyeS5wdXNoKFwiPT1cIiArIHMrIFwiIFwiICtwKTtcbiAgICAgICAgbGV0IFMgPSBcIlwiO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8c2VsZi5wZW5kaW5nTG9hZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChzZWxmLnBlbmRpbmdMb2Fkc1tpXS5wYWdlID09IHApIFMgPSBTICsgXCIgXCIgKyBpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChTKSBsb2dFbnRyeS5wdXNoKFwiUGVuZGluZyBsb2FkczpcIitTKTtcbiAgICAgICAgaWYgKHR5cGVvZiBzZWxmLnBhZ2VzW3BdICE9IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgIGNvbnN0IHBhZ2UgPSBzZWxmLnBhZ2VzW3BdO1xuICAgICAgICAgICAgbG9nRW50cnkucHVzaChcIkxvYWRlZFwiKTtcbiAgICAgICAgICAgIGxvZ0VudHJ5LnB1c2goXCJwZW5kaW5nT3BzOiBcIitwYWdlLnBlbmRpbmdPcHMpO1xuICAgICAgICAgICAgaWYgKHBhZ2UubG9hZGluZykgbG9nRW50cnkucHVzaChcImxvYWRpbmc6IFwiK3BhZ2UubG9hZGluZyk7XG4gICAgICAgICAgICBpZiAocGFnZS53cml0aW5nKSBsb2dFbnRyeS5wdXNoKFwid3JpdGluZ1wiKTtcbiAgICAgICAgICAgIGlmIChwYWdlLmRpcnR5KSBsb2dFbnRyeS5wdXNoKFwiZGlydHlcIik7XG4gICAgICAgIH1cbiAgICAgICAgbG9nRW50cnkucHVzaChcIj09XCIpO1xuXG4gICAgICAgIGlmICghc2VsZi5oaXN0b3J5W3BdKSBzZWxmLmhpc3RvcnlbcF0gPSBbXTtcbiAgICAgICAgc2VsZi5oaXN0b3J5W3BdLnB1c2gobG9nRW50cnkpO1xuICAgIH1cblxuICAgIF9fcHJpbnRIaXN0b3J5KHApIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGlmICghc2VsZi5oaXN0b3J5W3BdKSBjb25zb2xlLmxvZyhcIkVtcHR5IEhpc3RvcnkgXCIsIHApO1xuICAgICAgICBjb25zb2xlLmxvZyhcIkhpc3RvcnkgXCIrcCk7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxzZWxmLmhpc3RvcnlbcF0ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGZvciAobGV0IGo9MDsgajxzZWxmLmhpc3RvcnlbcF1baV0ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIi0+IFwiICsgc2VsZi5oaXN0b3J5W3BdW2ldW2pdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuXG5cbiAgICBfdHJpZ2dlckxvYWQoKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gICAgICAgIGlmIChzZWxmLnJlYWRpbmcpIHJldHVybjtcbiAgICAgICAgaWYgKHNlbGYucGVuZGluZ0xvYWRzLmxlbmd0aD09MCkgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IHBhZ2VJZHhzID0gT2JqZWN0LmtleXMoc2VsZi5wYWdlcyk7XG5cbiAgICAgICAgY29uc3QgZGVsZXRhYmxlUGFnZXMgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPHBhZ2VJZHhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBwYWdlID0gc2VsZi5wYWdlc1twYXJzZUludChwYWdlSWR4c1tpXSldO1xuICAgICAgICAgICAgaWYgKChwYWdlLmRpcnR5ID09IGZhbHNlKSYmKHBhZ2UucGVuZGluZ09wcz09MCkmJighcGFnZS53cml0aW5nKSYmKCFwYWdlLmxvYWRpbmcpKSBkZWxldGFibGVQYWdlcy5wdXNoKHBhcnNlSW50KHBhZ2VJZHhzW2ldKSk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgZnJlZVBhZ2VzID0gc2VsZi5tYXhQYWdlc0xvYWRlZCAtIHBhZ2VJZHhzLmxlbmd0aDtcblxuICAgICAgICBjb25zdCBvcHMgPSBbXTtcblxuICAgICAgICAvLyB3aGlsZSBwZW5kaW5nIGxvYWRzIGFuZFxuICAgICAgICAvLyAgICAgdGhlIHBhZ2UgaXMgbG9hZGVkIG9yIEkgY2FuIHJlY292ZXIgb25lLlxuICAgICAgICB3aGlsZSAoXG4gICAgICAgICAgICAoc2VsZi5wZW5kaW5nTG9hZHMubGVuZ3RoPjApICYmXG4gICAgICAgICAgICAoICAgKHR5cGVvZiBzZWxmLnBhZ2VzW3NlbGYucGVuZGluZ0xvYWRzWzBdLnBhZ2VdICE9IFwidW5kZWZpbmVkXCIgKVxuICAgICAgICAgICAgICB8fCggIChmcmVlUGFnZXM+MClcbiAgICAgICAgICAgICAgICAgfHwoZGVsZXRhYmxlUGFnZXMubGVuZ3RoPjApKSkpIHtcbiAgICAgICAgICAgIGNvbnN0IGxvYWQgPSBzZWxmLnBlbmRpbmdMb2Fkcy5zaGlmdCgpO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBzZWxmLnBhZ2VzW2xvYWQucGFnZV0gIT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgICAgIHNlbGYucGFnZXNbbG9hZC5wYWdlXS5wZW5kaW5nT3BzICsrO1xuICAgICAgICAgICAgICAgIGNvbnN0IGlkeCA9IGRlbGV0YWJsZVBhZ2VzLmluZGV4T2YobG9hZC5wYWdlKTtcbiAgICAgICAgICAgICAgICBpZiAoaWR4Pj0wKSBkZWxldGFibGVQYWdlcy5zcGxpY2UoaWR4LCAxKTtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZi5wYWdlc1tsb2FkLnBhZ2VdLmxvYWRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5wYWdlc1tsb2FkLnBhZ2VdLmxvYWRpbmcucHVzaChsb2FkKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBsb2FkLnJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2VsZi5fX3N0YXR1c1BhZ2UoXCJBZnRlciBMb2FkIChjYWNoZWQpOiBcIiwgbG9hZC5wYWdlKTtcblxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoZnJlZVBhZ2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGZyZWVQYWdlcy0tO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGZwID0gZGVsZXRhYmxlUGFnZXMuc2hpZnQoKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fX3N0YXR1c1BhZ2UoXCJCZWZvcmUgVW5sb2FkOiBcIiwgZnApO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLmF2QnVmZnMudW5zaGlmdChzZWxmLnBhZ2VzW2ZwXSk7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBzZWxmLnBhZ2VzW2ZwXTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fX3N0YXR1c1BhZ2UoXCJBZnRlciBVbmxvYWQ6IFwiLCBmcCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGxvYWQucGFnZT49c2VsZi50b3RhbFBhZ2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYucGFnZXNbbG9hZC5wYWdlXSA9IGdldE5ld1BhZ2UoKTtcbiAgICAgICAgICAgICAgICAgICAgbG9hZC5yZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX19zdGF0dXNQYWdlKFwiQWZ0ZXIgTG9hZCAobmV3KTogXCIsIGxvYWQucGFnZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5yZWFkaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5wYWdlc1tsb2FkLnBhZ2VdID0gZ2V0TmV3UGFnZSgpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnBhZ2VzW2xvYWQucGFnZV0ubG9hZGluZyA9IFtsb2FkXTtcbiAgICAgICAgICAgICAgICAgICAgb3BzLnB1c2goc2VsZi5mZC5yZWFkKHNlbGYucGFnZXNbbG9hZC5wYWdlXS5idWZmLCAwLCBzZWxmLnBhZ2VTaXplLCBsb2FkLnBhZ2Uqc2VsZi5wYWdlU2l6ZSkudGhlbigocmVzKT0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYucGFnZXNbbG9hZC5wYWdlXS5zaXplID0gcmVzLmJ5dGVzUmVhZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxvYWRpbmcgPSBzZWxmLnBhZ2VzW2xvYWQucGFnZV0ubG9hZGluZztcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBzZWxmLnBhZ2VzW2xvYWQucGFnZV0ubG9hZGluZztcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGk9MDsgaTxsb2FkaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9hZGluZ1tpXS5yZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9fc3RhdHVzUGFnZShcIkFmdGVyIExvYWQgKGxvYWRlZCk6IFwiLCBsb2FkLnBhZ2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgICAgICAgICAgICAgICAgfSwgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9hZC5yZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9fc3RhdHVzUGFnZShcIkFmdGVyIExvYWQgKGxvYWRpbmcpOiBcIiwgbG9hZC5wYWdlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgKG9wcy5sZW5ndGg+MSkgY29uc29sZS5sb2cob3BzLmxlbmd0aCk7XG5cbiAgICAgICAgUHJvbWlzZS5hbGwob3BzKS50aGVuKCAoKSA9PiB7XG4gICAgICAgICAgICBzZWxmLnJlYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmIChzZWxmLnBlbmRpbmdMb2Fkcy5sZW5ndGg+MCkgc2V0SW1tZWRpYXRlKHNlbGYuX3RyaWdnZXJMb2FkLmJpbmQoc2VsZikpO1xuICAgICAgICAgICAgc2VsZi5fdHJ5Q2xvc2UoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgZnVuY3Rpb24gZ2V0TmV3UGFnZSgpIHtcbiAgICAgICAgICAgIGlmIChzZWxmLmF2QnVmZnMubGVuZ3RoPjApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwID0gc2VsZi5hdkJ1ZmZzLnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgcC5kaXJ0eSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHAucGVuZGluZ09wcyA9IDE7XG4gICAgICAgICAgICAgICAgcC5zaXplID0wO1xuICAgICAgICAgICAgICAgIHJldHVybiBwO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBkaXJ0eTogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIGJ1ZmY6IG5ldyBVaW50OEFycmF5KHNlbGYucGFnZVNpemUpLFxuICAgICAgICAgICAgICAgICAgICBwZW5kaW5nT3BzOiAxLFxuICAgICAgICAgICAgICAgICAgICBzaXplOiAwXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgfVxuXG5cbiAgICBfdHJpZ2dlcldyaXRlKCkge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgaWYgKHNlbGYud3JpdGluZykgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IHBhZ2VJZHhzID0gT2JqZWN0LmtleXMoc2VsZi5wYWdlcyk7XG5cbiAgICAgICAgY29uc3Qgb3BzID0gW107XG5cbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPHBhZ2VJZHhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBwYWdlID0gc2VsZi5wYWdlc1twYXJzZUludChwYWdlSWR4c1tpXSldO1xuICAgICAgICAgICAgaWYgKHBhZ2UuZGlydHkpIHtcbiAgICAgICAgICAgICAgICBwYWdlLmRpcnR5ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcGFnZS53cml0aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBzZWxmLndyaXRpbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIG9wcy5wdXNoKCBzZWxmLmZkLndyaXRlKHBhZ2UuYnVmZiwgMCwgcGFnZS5zaXplLCBwYXJzZUludChwYWdlSWR4c1tpXSkqc2VsZi5wYWdlU2l6ZSkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHBhZ2Uud3JpdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSwgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIkVSUk9SIFdyaXRpbmc6IFwiK2Vycik7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuZXJyb3IgPSBlcnI7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3RyeUNsb3NlKCk7XG4gICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNlbGYud3JpdGluZykge1xuICAgICAgICAgICAgUHJvbWlzZS5hbGwob3BzKS50aGVuKCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgc2VsZi53cml0aW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgc2V0SW1tZWRpYXRlKHNlbGYuX3RyaWdnZXJXcml0ZS5iaW5kKHNlbGYpKTtcbiAgICAgICAgICAgICAgICBzZWxmLl90cnlDbG9zZSgpO1xuICAgICAgICAgICAgICAgIGlmIChzZWxmLnBlbmRpbmdMb2Fkcy5sZW5ndGg+MCkgc2V0SW1tZWRpYXRlKHNlbGYuX3RyaWdnZXJMb2FkLmJpbmQoc2VsZikpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBfZ2V0RGlydHlQYWdlKCkge1xuICAgICAgICBmb3IgKGxldCBwIGluIHRoaXMucGFnZXMpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnBhZ2VzW3BdLmRpcnR5KSByZXR1cm4gcDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgYXN5bmMgd3JpdGUoYnVmZiwgcG9zKSB7XG4gICAgICAgIGlmIChidWZmLmJ5dGVMZW5ndGggPT0gMCkgcmV0dXJuO1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbi8qXG4gICAgICAgIGlmIChidWZmLmJ5dGVMZW5ndGggPiBzZWxmLnBhZ2VTaXplKnNlbGYubWF4UGFnZXNMb2FkZWQqMC44KSB7XG4gICAgICAgICAgICBjb25zdCBjYWNoZVNpemUgPSBNYXRoLmZsb29yKGJ1ZmYuYnl0ZUxlbmd0aCAqIDEuMSk7XG4gICAgICAgICAgICB0aGlzLm1heFBhZ2VzTG9hZGVkID0gTWF0aC5mbG9vciggY2FjaGVTaXplIC8gc2VsZi5wYWdlU2l6ZSkrMTtcbiAgICAgICAgfVxuKi9cbiAgICAgICAgaWYgKHR5cGVvZiBwb3MgPT0gXCJ1bmRlZmluZWRcIikgcG9zID0gc2VsZi5wb3M7XG4gICAgICAgIHNlbGYucG9zID0gcG9zK2J1ZmYuYnl0ZUxlbmd0aDtcbiAgICAgICAgaWYgKHNlbGYudG90YWxTaXplIDwgcG9zICsgYnVmZi5ieXRlTGVuZ3RoKSBzZWxmLnRvdGFsU2l6ZSA9IHBvcyArIGJ1ZmYuYnl0ZUxlbmd0aDtcbiAgICAgICAgaWYgKHNlbGYucGVuZGluZ0Nsb3NlKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiV3JpdGluZyBhIGNsb3NpbmcgZmlsZVwiKTtcbiAgICAgICAgY29uc3QgZmlyc3RQYWdlID0gTWF0aC5mbG9vcihwb3MgLyBzZWxmLnBhZ2VTaXplKTtcbiAgICAgICAgY29uc3QgbGFzdFBhZ2UgPSBNYXRoLmZsb29yKChwb3MgKyBidWZmLmJ5dGVMZW5ndGggLTEpIC8gc2VsZi5wYWdlU2l6ZSk7XG5cbiAgICAgICAgY29uc3QgcGFnZVByb21pc2VzID0gW107XG4gICAgICAgIGZvciAobGV0IGk9Zmlyc3RQYWdlOyBpPD1sYXN0UGFnZTsgaSsrKSBwYWdlUHJvbWlzZXMucHVzaChzZWxmLl9sb2FkUGFnZShpKSk7XG4gICAgICAgIHNlbGYuX3RyaWdnZXJMb2FkKCk7XG5cbiAgICAgICAgbGV0IHAgPSBmaXJzdFBhZ2U7XG4gICAgICAgIGxldCBvID0gcG9zICUgc2VsZi5wYWdlU2l6ZTtcbiAgICAgICAgbGV0IHIgPSBidWZmLmJ5dGVMZW5ndGg7XG4gICAgICAgIHdoaWxlIChyPjApIHtcbiAgICAgICAgICAgIGF3YWl0IHBhZ2VQcm9taXNlc1twLWZpcnN0UGFnZV07XG4gICAgICAgICAgICBjb25zdCBsID0gKG8rciA+IHNlbGYucGFnZVNpemUpID8gKHNlbGYucGFnZVNpemUgLW8pIDogcjtcbiAgICAgICAgICAgIGNvbnN0IHNyY1ZpZXcgPSBidWZmLnNsaWNlKCBidWZmLmJ5dGVMZW5ndGggLSByLCBidWZmLmJ5dGVMZW5ndGggLSByICsgbCk7XG4gICAgICAgICAgICBjb25zdCBkc3RWaWV3ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5wYWdlc1twXS5idWZmLmJ1ZmZlciwgbywgbCk7XG4gICAgICAgICAgICBkc3RWaWV3LnNldChzcmNWaWV3KTtcbiAgICAgICAgICAgIHNlbGYucGFnZXNbcF0uZGlydHkgPSB0cnVlO1xuICAgICAgICAgICAgc2VsZi5wYWdlc1twXS5wZW5kaW5nT3BzIC0tO1xuICAgICAgICAgICAgc2VsZi5wYWdlc1twXS5zaXplID0gTWF0aC5tYXgobytsLCBzZWxmLnBhZ2VzW3BdLnNpemUpO1xuICAgICAgICAgICAgaWYgKHA+PXNlbGYudG90YWxQYWdlcykge1xuICAgICAgICAgICAgICAgIHNlbGYudG90YWxQYWdlcyA9IHArMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHIgPSByLWw7XG4gICAgICAgICAgICBwICsrO1xuICAgICAgICAgICAgbyA9IDA7XG4gICAgICAgICAgICBpZiAoIXNlbGYud3JpdGluZykgc2V0SW1tZWRpYXRlKHNlbGYuX3RyaWdnZXJXcml0ZS5iaW5kKHNlbGYpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIHJlYWQobGVuLCBwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGxldCBidWZmID0gbmV3IFVpbnQ4QXJyYXkobGVuKTtcbiAgICAgICAgYXdhaXQgc2VsZi5yZWFkVG9CdWZmZXIoYnVmZiwgMCwgbGVuLCBwb3MpO1xuXG4gICAgICAgIHJldHVybiBidWZmO1xuICAgIH1cblxuICAgIGFzeW5jIHJlYWRUb0J1ZmZlcihidWZmRHN0LCBvZmZzZXQsIGxlbiwgcG9zKSB7XG4gICAgICAgIGlmIChsZW4gPT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBpZiAobGVuID4gc2VsZi5wYWdlU2l6ZSpzZWxmLm1heFBhZ2VzTG9hZGVkKjAuOCkge1xuICAgICAgICAgICAgY29uc3QgY2FjaGVTaXplID0gTWF0aC5mbG9vcihsZW4gKiAxLjEpO1xuICAgICAgICAgICAgdGhpcy5tYXhQYWdlc0xvYWRlZCA9IE1hdGguZmxvb3IoIGNhY2hlU2l6ZSAvIHNlbGYucGFnZVNpemUpKzE7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiBwb3MgPT0gXCJ1bmRlZmluZWRcIikgcG9zID0gc2VsZi5wb3M7XG4gICAgICAgIHNlbGYucG9zID0gcG9zK2xlbjtcbiAgICAgICAgaWYgKHNlbGYucGVuZGluZ0Nsb3NlKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUmVhZGluZyBhIGNsb3NpbmcgZmlsZVwiKTtcbiAgICAgICAgY29uc3QgZmlyc3RQYWdlID0gTWF0aC5mbG9vcihwb3MgLyBzZWxmLnBhZ2VTaXplKTtcbiAgICAgICAgY29uc3QgbGFzdFBhZ2UgPSBNYXRoLmZsb29yKChwb3MgKyBsZW4gLTEpIC8gc2VsZi5wYWdlU2l6ZSk7XG5cbiAgICAgICAgY29uc3QgcGFnZVByb21pc2VzID0gW107XG4gICAgICAgIGZvciAobGV0IGk9Zmlyc3RQYWdlOyBpPD1sYXN0UGFnZTsgaSsrKSBwYWdlUHJvbWlzZXMucHVzaChzZWxmLl9sb2FkUGFnZShpKSk7XG5cbiAgICAgICAgc2VsZi5fdHJpZ2dlckxvYWQoKTtcblxuICAgICAgICBsZXQgcCA9IGZpcnN0UGFnZTtcbiAgICAgICAgbGV0IG8gPSBwb3MgJSBzZWxmLnBhZ2VTaXplO1xuICAgICAgICAvLyBSZW1haW5pbmcgYnl0ZXMgdG8gcmVhZFxuICAgICAgICBsZXQgciA9IHBvcyArIGxlbiA+IHNlbGYudG90YWxTaXplID8gbGVuIC0gKHBvcyArIGxlbiAtIHNlbGYudG90YWxTaXplKTogbGVuO1xuICAgICAgICB3aGlsZSAocj4wKSB7XG4gICAgICAgICAgICBhd2FpdCBwYWdlUHJvbWlzZXNbcCAtIGZpcnN0UGFnZV07XG4gICAgICAgICAgICBzZWxmLl9fc3RhdHVzUGFnZShcIkFmdGVyIEF3YWl0IChyZWFkKTogXCIsIHApO1xuXG4gICAgICAgICAgICAvLyBieXRlcyB0byBjb3B5IGZyb20gdGhpcyBwYWdlXG4gICAgICAgICAgICBjb25zdCBsID0gKG8rciA+IHNlbGYucGFnZVNpemUpID8gKHNlbGYucGFnZVNpemUgLW8pIDogcjtcbiAgICAgICAgICAgIGNvbnN0IHNyY1ZpZXcgPSBuZXcgVWludDhBcnJheShzZWxmLnBhZ2VzW3BdLmJ1ZmYuYnVmZmVyLCBzZWxmLnBhZ2VzW3BdLmJ1ZmYuYnl0ZU9mZnNldCArIG8sIGwpO1xuICAgICAgICAgICAgYnVmZkRzdC5zZXQoc3JjVmlldywgb2Zmc2V0K2xlbi1yKTtcbiAgICAgICAgICAgIHNlbGYucGFnZXNbcF0ucGVuZGluZ09wcyAtLTtcblxuICAgICAgICAgICAgc2VsZi5fX3N0YXR1c1BhZ2UoXCJBZnRlciBPcCBkb25lOiBcIiwgcCk7XG5cbiAgICAgICAgICAgIHIgPSByLWw7XG4gICAgICAgICAgICBwICsrO1xuICAgICAgICAgICAgbyA9IDA7XG4gICAgICAgICAgICBpZiAoc2VsZi5wZW5kaW5nTG9hZHMubGVuZ3RoPjApIHNldEltbWVkaWF0ZShzZWxmLl90cmlnZ2VyTG9hZC5iaW5kKHNlbGYpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucG9zID0gcG9zICsgbGVuO1xuXG4gICAgfVxuXG5cbiAgICBfdHJ5Q2xvc2UoKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBpZiAoIXNlbGYucGVuZGluZ0Nsb3NlKSByZXR1cm47XG4gICAgICAgIGlmIChzZWxmLmVycm9yKSB7XG4gICAgICAgICAgICBzZWxmLnBlbmRpbmdDbG9zZVJlamVjdChzZWxmLmVycm9yKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwID0gc2VsZi5fZ2V0RGlydHlQYWdlKCk7XG4gICAgICAgIGlmICgocD49MCkgfHwgKHNlbGYud3JpdGluZykgfHwgKHNlbGYucmVhZGluZykgfHwgKHNlbGYucGVuZGluZ0xvYWRzLmxlbmd0aD4wKSkgcmV0dXJuO1xuICAgICAgICBzZWxmLnBlbmRpbmdDbG9zZSgpO1xuICAgIH1cblxuICAgIGNsb3NlKCkge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgaWYgKHNlbGYucGVuZGluZ0Nsb3NlKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2xvc2luZyB0aGUgZmlsZSB0d2ljZVwiKTtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHNlbGYucGVuZGluZ0Nsb3NlID0gcmVzb2x2ZTtcbiAgICAgICAgICAgIHNlbGYucGVuZGluZ0Nsb3NlUmVqZWN0ID0gcmVqZWN0O1xuICAgICAgICAgICAgc2VsZi5fdHJ5Q2xvc2UoKTtcbiAgICAgICAgfSkudGhlbigoKT0+IHtcbiAgICAgICAgICAgIHNlbGYuZmQuY2xvc2UoKTtcbiAgICAgICAgfSwgKGVycikgPT4ge1xuICAgICAgICAgICAgc2VsZi5mZC5jbG9zZSgpO1xuICAgICAgICAgICAgdGhyb3cgKGVycik7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGFzeW5jIGRpc2NhcmQoKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBhd2FpdCBzZWxmLmNsb3NlKCk7XG4gICAgICAgIGF3YWl0IGZzLnByb21pc2VzLnVubGluayh0aGlzLmZpbGVOYW1lKTtcbiAgICB9XG5cbiAgICBhc3luYyB3cml0ZVVMRTMyKHYsIHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgY29uc3QgdG1wQnVmZjMyID0gbmV3IFVpbnQ4QXJyYXkoNCk7XG4gICAgICAgIGNvbnN0IHRtcEJ1ZmYzMnYgPSBuZXcgRGF0YVZpZXcodG1wQnVmZjMyLmJ1ZmZlcik7XG5cbiAgICAgICAgdG1wQnVmZjMydi5zZXRVaW50MzIoMCwgdiwgdHJ1ZSk7XG5cbiAgICAgICAgYXdhaXQgc2VsZi53cml0ZSh0bXBCdWZmMzIsIHBvcyk7XG4gICAgfVxuXG4gICAgYXN5bmMgd3JpdGVVQkUzMih2LCBwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICAgICAgY29uc3QgdG1wQnVmZjMyID0gbmV3IFVpbnQ4QXJyYXkoNCk7XG4gICAgICAgIGNvbnN0IHRtcEJ1ZmYzMnYgPSBuZXcgRGF0YVZpZXcodG1wQnVmZjMyLmJ1ZmZlcik7XG5cbiAgICAgICAgdG1wQnVmZjMydi5zZXRVaW50MzIoMCwgdiwgZmFsc2UpO1xuXG4gICAgICAgIGF3YWl0IHNlbGYud3JpdGUodG1wQnVmZjMyLCBwb3MpO1xuICAgIH1cblxuXG4gICAgYXN5bmMgd3JpdGVVTEU2NCh2LCBwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICAgICAgY29uc3QgdG1wQnVmZjY0ID0gbmV3IFVpbnQ4QXJyYXkoOCk7XG4gICAgICAgIGNvbnN0IHRtcEJ1ZmY2NHYgPSBuZXcgRGF0YVZpZXcodG1wQnVmZjY0LmJ1ZmZlcik7XG5cbiAgICAgICAgdG1wQnVmZjY0di5zZXRVaW50MzIoMCwgdiAmIDB4RkZGRkZGRkYsIHRydWUpO1xuICAgICAgICB0bXBCdWZmNjR2LnNldFVpbnQzMig0LCBNYXRoLmZsb29yKHYgLyAweDEwMDAwMDAwMCkgLCB0cnVlKTtcblxuICAgICAgICBhd2FpdCBzZWxmLndyaXRlKHRtcEJ1ZmY2NCwgcG9zKTtcbiAgICB9XG5cbiAgICBhc3luYyByZWFkVUxFMzIocG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBjb25zdCBiID0gYXdhaXQgc2VsZi5yZWFkKDQsIHBvcyk7XG5cbiAgICAgICAgY29uc3QgdmlldyA9IG5ldyBVaW50MzJBcnJheShiLmJ1ZmZlcik7XG5cbiAgICAgICAgcmV0dXJuIHZpZXdbMF07XG4gICAgfVxuXG4gICAgYXN5bmMgcmVhZFVCRTMyKHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgY29uc3QgYiA9IGF3YWl0IHNlbGYucmVhZCg0LCBwb3MpO1xuXG4gICAgICAgIGNvbnN0IHZpZXcgPSBuZXcgRGF0YVZpZXcoYi5idWZmZXIpO1xuXG4gICAgICAgIHJldHVybiB2aWV3LmdldFVpbnQzMigwLCBmYWxzZSk7XG4gICAgfVxuXG4gICAgYXN5bmMgcmVhZFVMRTY0KHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgY29uc3QgYiA9IGF3YWl0IHNlbGYucmVhZCg4LCBwb3MpO1xuXG4gICAgICAgIGNvbnN0IHZpZXcgPSBuZXcgVWludDMyQXJyYXkoYi5idWZmZXIpO1xuXG4gICAgICAgIHJldHVybiB2aWV3WzFdICogMHgxMDAwMDAwMDAgKyB2aWV3WzBdO1xuICAgIH1cblxuICAgIGFzeW5jIHJlYWRTdHJpbmcocG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gICAgICAgIGlmIChzZWxmLnBlbmRpbmdDbG9zZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUmVhZGluZyBhIGNsb3NpbmcgZmlsZVwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBjdXJyZW50UG9zaXRpb24gPSB0eXBlb2YgcG9zID09IFwidW5kZWZpbmVkXCIgPyBzZWxmLnBvcyA6IHBvcztcbiAgICAgICAgbGV0IGN1cnJlbnRQYWdlID0gTWF0aC5mbG9vcihjdXJyZW50UG9zaXRpb24gLyBzZWxmLnBhZ2VTaXplKTtcblxuICAgICAgICBsZXQgZW5kT2ZTdHJpbmdGb3VuZCA9IGZhbHNlO1xuICAgICAgICBsZXQgc3RyID0gXCJcIjtcblxuICAgICAgICB3aGlsZSAoIWVuZE9mU3RyaW5nRm91bmQpIHtcbiAgICAgICAgICAgIC8vUmVhZCBwYWdlXG4gICAgICAgICAgICBsZXQgcGFnZVByb21pc2UgPSBzZWxmLl9sb2FkUGFnZShjdXJyZW50UGFnZSk7XG4gICAgICAgICAgICBzZWxmLl90cmlnZ2VyTG9hZCgpO1xuICAgICAgICAgICAgYXdhaXQgcGFnZVByb21pc2U7XG4gICAgICAgICAgICBzZWxmLl9fc3RhdHVzUGFnZShcIkFmdGVyIEF3YWl0IChyZWFkKTogXCIsIGN1cnJlbnRQYWdlKTtcblxuICAgICAgICAgICAgbGV0IG9mZnNldE9uUGFnZSA9IGN1cnJlbnRQb3NpdGlvbiAlIHNlbGYucGFnZVNpemU7XG5cbiAgICAgICAgICAgIGNvbnN0IGRhdGFBcnJheSA9IG5ldyBVaW50OEFycmF5KFxuICAgICAgICAgICAgICAgIHNlbGYucGFnZXNbY3VycmVudFBhZ2VdLmJ1ZmYuYnVmZmVyLFxuICAgICAgICAgICAgICAgIHNlbGYucGFnZXNbY3VycmVudFBhZ2VdLmJ1ZmYuYnl0ZU9mZnNldCArIG9mZnNldE9uUGFnZSxcbiAgICAgICAgICAgICAgICBzZWxmLnBhZ2VTaXplIC0gb2Zmc2V0T25QYWdlXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICBsZXQgaW5kZXhFbmRPZlN0cmluZyA9IGRhdGFBcnJheS5maW5kSW5kZXgoZWxlbWVudCA9PiBlbGVtZW50ID09PSAwKTtcbiAgICAgICAgICAgIGVuZE9mU3RyaW5nRm91bmQgPSBpbmRleEVuZE9mU3RyaW5nICE9PSAtMTtcblxuICAgICAgICAgICAgaWYgKGVuZE9mU3RyaW5nRm91bmQpIHtcbiAgICAgICAgICAgICAgICBzdHIgKz0gbmV3IFRleHREZWNvZGVyKCkuZGVjb2RlKGRhdGFBcnJheS5zbGljZSgwLCBpbmRleEVuZE9mU3RyaW5nKSk7XG4gICAgICAgICAgICAgICAgc2VsZi5wb3MgPSBjdXJyZW50UGFnZSAqIHRoaXMucGFnZVNpemUgKyBvZmZzZXRPblBhZ2UgKyBpbmRleEVuZE9mU3RyaW5nICsgMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3RyICs9IG5ldyBUZXh0RGVjb2RlcigpLmRlY29kZShkYXRhQXJyYXkpO1xuICAgICAgICAgICAgICAgIHNlbGYucG9zID0gY3VycmVudFBhZ2UgKiB0aGlzLnBhZ2VTaXplICsgb2Zmc2V0T25QYWdlICsgZGF0YUFycmF5Lmxlbmd0aDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc2VsZi5wYWdlc1tjdXJyZW50UGFnZV0ucGVuZGluZ09wcy0tO1xuICAgICAgICAgICAgc2VsZi5fX3N0YXR1c1BhZ2UoXCJBZnRlciBPcCBkb25lOiBcIiwgY3VycmVudFBhZ2UpO1xuXG4gICAgICAgICAgICBjdXJyZW50UG9zaXRpb24gPSBzZWxmLnBvcztcbiAgICAgICAgICAgIGN1cnJlbnRQYWdlKys7XG5cbiAgICAgICAgICAgIGlmIChzZWxmLnBlbmRpbmdMb2Fkcy5sZW5ndGggPiAwKSBzZXRJbW1lZGlhdGUoc2VsZi5fdHJpZ2dlckxvYWQuYmluZChzZWxmKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc3RyO1xuICAgIH1cbn1cbiIsImV4cG9ydCBmdW5jdGlvbiBjcmVhdGVOZXcobykge1xuICAgIGNvbnN0IGluaXRpYWxTaXplID0gby5pbml0aWFsU2l6ZSB8fCAxPDwyMDtcbiAgICBjb25zdCBmZCA9IG5ldyBNZW1GaWxlKCk7XG4gICAgZmQubyA9IG87XG4gICAgZmQuby5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoaW5pdGlhbFNpemUpO1xuICAgIGZkLmFsbG9jU2l6ZSA9IGluaXRpYWxTaXplO1xuICAgIGZkLnRvdGFsU2l6ZSA9IDA7XG4gICAgZmQucmVhZE9ubHkgPSBmYWxzZTtcbiAgICBmZC5wb3MgPSAwO1xuICAgIHJldHVybiBmZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlYWRFeGlzdGluZyhvKSB7XG4gICAgY29uc3QgZmQgPSBuZXcgTWVtRmlsZSgpO1xuICAgIGZkLm8gPSBvO1xuICAgIGZkLmFsbG9jU2l6ZSA9IG8uZGF0YS5ieXRlTGVuZ3RoO1xuICAgIGZkLnRvdGFsU2l6ZSA9IG8uZGF0YS5ieXRlTGVuZ3RoO1xuICAgIGZkLnJlYWRPbmx5ID0gdHJ1ZTtcbiAgICBmZC5wb3MgPSAwO1xuICAgIHJldHVybiBmZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlYWRXcml0ZUV4aXN0aW5nKG8pIHtcbiAgICBjb25zdCBmZCA9IG5ldyBNZW1GaWxlKCk7XG4gICAgZmQubyA9IG87XG4gICAgZmQuYWxsb2NTaXplID0gby5kYXRhLmJ5dGVMZW5ndGg7XG4gICAgZmQudG90YWxTaXplID0gby5kYXRhLmJ5dGVMZW5ndGg7XG4gICAgZmQucmVhZE9ubHkgPSBmYWxzZTtcbiAgICBmZC5wb3MgPSAwO1xuICAgIHJldHVybiBmZDtcbn1cblxuY29uc3QgdG1wQnVmZjMyID0gbmV3IFVpbnQ4QXJyYXkoNCk7XG5jb25zdCB0bXBCdWZmMzJ2ID0gbmV3IERhdGFWaWV3KHRtcEJ1ZmYzMi5idWZmZXIpO1xuY29uc3QgdG1wQnVmZjY0ID0gbmV3IFVpbnQ4QXJyYXkoOCk7XG5jb25zdCB0bXBCdWZmNjR2ID0gbmV3IERhdGFWaWV3KHRtcEJ1ZmY2NC5idWZmZXIpO1xuXG5jbGFzcyBNZW1GaWxlIHtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLnBhZ2VTaXplID0gMSA8PCAxNDsgIC8vIGZvciBjb21wYXRpYmlsaXR5XG4gICAgfVxuXG4gICAgX3Jlc2l6ZUlmTmVlZGVkKG5ld0xlbikge1xuICAgICAgICBpZiAobmV3TGVuID4gdGhpcy5hbGxvY1NpemUpIHtcbiAgICAgICAgICAgIGNvbnN0IG5ld0FsbG9jU2l6ZSA9IE1hdGgubWF4KFxuICAgICAgICAgICAgICAgIHRoaXMuYWxsb2NTaXplICsgKDEgPDwgMjApLFxuICAgICAgICAgICAgICAgIE1hdGguZmxvb3IodGhpcy5hbGxvY1NpemUgKiAxLjEpLFxuICAgICAgICAgICAgICAgIG5ld0xlblxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IG5ld0RhdGEgPSBuZXcgVWludDhBcnJheShuZXdBbGxvY1NpemUpO1xuICAgICAgICAgICAgbmV3RGF0YS5zZXQodGhpcy5vLmRhdGEpO1xuICAgICAgICAgICAgdGhpcy5vLmRhdGEgPSBuZXdEYXRhO1xuICAgICAgICAgICAgdGhpcy5hbGxvY1NpemUgPSBuZXdBbGxvY1NpemU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhc3luYyB3cml0ZShidWZmLCBwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9dGhpcztcbiAgICAgICAgaWYgKHR5cGVvZiBwb3MgPT0gXCJ1bmRlZmluZWRcIikgcG9zID0gc2VsZi5wb3M7XG4gICAgICAgIGlmICh0aGlzLnJlYWRPbmx5KSB0aHJvdyBuZXcgRXJyb3IoXCJXcml0aW5nIGEgcmVhZCBvbmx5IGZpbGVcIik7XG5cbiAgICAgICAgdGhpcy5fcmVzaXplSWZOZWVkZWQocG9zICsgYnVmZi5ieXRlTGVuZ3RoKTtcblxuICAgICAgICB0aGlzLm8uZGF0YS5zZXQoYnVmZi5zbGljZSgpLCBwb3MpO1xuXG4gICAgICAgIGlmIChwb3MgKyBidWZmLmJ5dGVMZW5ndGggPiB0aGlzLnRvdGFsU2l6ZSkgdGhpcy50b3RhbFNpemUgPSBwb3MgKyBidWZmLmJ5dGVMZW5ndGg7XG5cbiAgICAgICAgdGhpcy5wb3MgPSBwb3MgKyBidWZmLmJ5dGVMZW5ndGg7XG4gICAgfVxuXG4gICAgYXN5bmMgcmVhZFRvQnVmZmVyKGJ1ZmZEZXN0LCBvZmZzZXQsIGxlbiwgcG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBpZiAodHlwZW9mIHBvcyA9PSBcInVuZGVmaW5lZFwiKSBwb3MgPSBzZWxmLnBvcztcbiAgICAgICAgaWYgKHRoaXMucmVhZE9ubHkpIHtcbiAgICAgICAgICAgIGlmIChwb3MgKyBsZW4gPiB0aGlzLnRvdGFsU2l6ZSkgdGhyb3cgbmV3IEVycm9yKFwiUmVhZGluZyBvdXQgb2YgYm91bmRzXCIpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3Jlc2l6ZUlmTmVlZGVkKHBvcyArIGxlbik7XG5cbiAgICAgICAgY29uc3QgYnVmZlNyYyA9IG5ldyBVaW50OEFycmF5KHRoaXMuby5kYXRhLmJ1ZmZlciwgdGhpcy5vLmRhdGEuYnl0ZU9mZnNldCArIHBvcywgbGVuKTtcblxuICAgICAgICBidWZmRGVzdC5zZXQoYnVmZlNyYywgb2Zmc2V0KTtcblxuICAgICAgICB0aGlzLnBvcyA9IHBvcyArIGxlbjtcbiAgICB9XG5cbiAgICBhc3luYyByZWFkKGxlbiwgcG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gICAgICAgIGNvbnN0IGJ1ZmYgPSBuZXcgVWludDhBcnJheShsZW4pO1xuICAgICAgICBhd2FpdCBzZWxmLnJlYWRUb0J1ZmZlcihidWZmLCAwLCBsZW4sIHBvcyk7XG5cbiAgICAgICAgcmV0dXJuIGJ1ZmY7XG4gICAgfVxuXG4gICAgY2xvc2UoKSB7XG4gICAgICAgIGlmICh0aGlzLm8uZGF0YS5ieXRlTGVuZ3RoICE9IHRoaXMudG90YWxTaXplKSB7XG4gICAgICAgICAgICB0aGlzLm8uZGF0YSA9IHRoaXMuby5kYXRhLnNsaWNlKDAsIHRoaXMudG90YWxTaXplKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIGRpc2NhcmQoKSB7XG4gICAgfVxuXG5cbiAgICBhc3luYyB3cml0ZVVMRTMyKHYsIHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcblxuICAgICAgICB0bXBCdWZmMzJ2LnNldFVpbnQzMigwLCB2LCB0cnVlKTtcblxuICAgICAgICBhd2FpdCBzZWxmLndyaXRlKHRtcEJ1ZmYzMiwgcG9zKTtcbiAgICB9XG5cbiAgICBhc3luYyB3cml0ZVVCRTMyKHYsIHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcblxuICAgICAgICB0bXBCdWZmMzJ2LnNldFVpbnQzMigwLCB2LCBmYWxzZSk7XG5cbiAgICAgICAgYXdhaXQgc2VsZi53cml0ZSh0bXBCdWZmMzIsIHBvcyk7XG4gICAgfVxuXG5cbiAgICBhc3luYyB3cml0ZVVMRTY0KHYsIHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcblxuICAgICAgICB0bXBCdWZmNjR2LnNldFVpbnQzMigwLCB2ICYgMHhGRkZGRkZGRiwgdHJ1ZSk7XG4gICAgICAgIHRtcEJ1ZmY2NHYuc2V0VWludDMyKDQsIE1hdGguZmxvb3IodiAvIDB4MTAwMDAwMDAwKSAsIHRydWUpO1xuXG4gICAgICAgIGF3YWl0IHNlbGYud3JpdGUodG1wQnVmZjY0LCBwb3MpO1xuICAgIH1cblxuXG4gICAgYXN5bmMgcmVhZFVMRTMyKHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgY29uc3QgYiA9IGF3YWl0IHNlbGYucmVhZCg0LCBwb3MpO1xuXG4gICAgICAgIGNvbnN0IHZpZXcgPSBuZXcgVWludDMyQXJyYXkoYi5idWZmZXIpO1xuXG4gICAgICAgIHJldHVybiB2aWV3WzBdO1xuICAgIH1cblxuICAgIGFzeW5jIHJlYWRVQkUzMihwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGNvbnN0IGIgPSBhd2FpdCBzZWxmLnJlYWQoNCwgcG9zKTtcblxuICAgICAgICBjb25zdCB2aWV3ID0gbmV3IERhdGFWaWV3KGIuYnVmZmVyKTtcblxuICAgICAgICByZXR1cm4gdmlldy5nZXRVaW50MzIoMCwgZmFsc2UpO1xuICAgIH1cblxuICAgIGFzeW5jIHJlYWRVTEU2NChwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGNvbnN0IGIgPSBhd2FpdCBzZWxmLnJlYWQoOCwgcG9zKTtcblxuICAgICAgICBjb25zdCB2aWV3ID0gbmV3IFVpbnQzMkFycmF5KGIuYnVmZmVyKTtcblxuICAgICAgICByZXR1cm4gdmlld1sxXSAqIDB4MTAwMDAwMDAwICsgdmlld1swXTtcbiAgICB9XG5cbiAgICBhc3luYyByZWFkU3RyaW5nKHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcblxuICAgICAgICBsZXQgY3VycmVudFBvc2l0aW9uID0gdHlwZW9mIHBvcyA9PSBcInVuZGVmaW5lZFwiID8gc2VsZi5wb3MgOiBwb3M7XG5cbiAgICAgICAgaWYgKGN1cnJlbnRQb3NpdGlvbiA+IHRoaXMudG90YWxTaXplKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkT25seSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlJlYWRpbmcgb3V0IG9mIGJvdW5kc1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3Jlc2l6ZUlmTmVlZGVkKHBvcyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZGF0YUFycmF5ID0gbmV3IFVpbnQ4QXJyYXkoXG4gICAgICAgICAgICBzZWxmLm8uZGF0YS5idWZmZXIsXG4gICAgICAgICAgICBjdXJyZW50UG9zaXRpb24sXG4gICAgICAgICAgICB0aGlzLnRvdGFsU2l6ZSAtIGN1cnJlbnRQb3NpdGlvblxuICAgICAgICApO1xuXG4gICAgICAgIGxldCBpbmRleEVuZE9mU3RyaW5nID0gZGF0YUFycmF5LmZpbmRJbmRleChlbGVtZW50ID0+IGVsZW1lbnQgPT09IDApO1xuICAgICAgICBsZXQgZW5kT2ZTdHJpbmdGb3VuZCA9IGluZGV4RW5kT2ZTdHJpbmcgIT09IC0xO1xuXG4gICAgICAgIGxldCBzdHIgPSBcIlwiO1xuICAgICAgICBpZiAoZW5kT2ZTdHJpbmdGb3VuZCkge1xuICAgICAgICAgICAgc3RyID0gbmV3IFRleHREZWNvZGVyKCkuZGVjb2RlKGRhdGFBcnJheS5zbGljZSgwLCBpbmRleEVuZE9mU3RyaW5nKSk7XG4gICAgICAgICAgICBzZWxmLnBvcyA9IGN1cnJlbnRQb3NpdGlvbiArIGluZGV4RW5kT2ZTdHJpbmcgKyAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2VsZi5wb3MgPSBjdXJyZW50UG9zaXRpb247XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0cjtcbiAgICB9XG59XG4iLCJjb25zdCBQQUdFX1NJWkUgPSAxPDwyMjtcblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZU5ldyhvKSB7XG4gICAgY29uc3QgaW5pdGlhbFNpemUgPSBvLmluaXRpYWxTaXplIHx8IDA7XG4gICAgY29uc3QgZmQgPSBuZXcgQmlnTWVtRmlsZSgpO1xuICAgIGZkLm8gPSBvO1xuICAgIGNvbnN0IG5QYWdlcyA9IGluaXRpYWxTaXplID8gTWF0aC5mbG9vcigoaW5pdGlhbFNpemUgLSAxKSAvIFBBR0VfU0laRSkrMSA6IDA7XG4gICAgZmQuby5kYXRhID0gW107XG4gICAgZm9yIChsZXQgaT0wOyBpPG5QYWdlcy0xOyBpKyspIHtcbiAgICAgICAgZmQuby5kYXRhLnB1c2goIG5ldyBVaW50OEFycmF5KFBBR0VfU0laRSkpO1xuICAgIH1cbiAgICBpZiAoblBhZ2VzKSBmZC5vLmRhdGEucHVzaCggbmV3IFVpbnQ4QXJyYXkoaW5pdGlhbFNpemUgLSBQQUdFX1NJWkUqKG5QYWdlcy0xKSkpO1xuICAgIGZkLnRvdGFsU2l6ZSA9IDA7XG4gICAgZmQucmVhZE9ubHkgPSBmYWxzZTtcbiAgICBmZC5wb3MgPSAwO1xuICAgIHJldHVybiBmZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlYWRFeGlzdGluZyhvKSB7XG4gICAgY29uc3QgZmQgPSBuZXcgQmlnTWVtRmlsZSgpO1xuICAgIGZkLm8gPSBvO1xuICAgIGZkLnRvdGFsU2l6ZSA9IChvLmRhdGEubGVuZ3RoLTEpKiBQQUdFX1NJWkUgKyBvLmRhdGFbby5kYXRhLmxlbmd0aC0xXS5ieXRlTGVuZ3RoO1xuICAgIGZkLnJlYWRPbmx5ID0gdHJ1ZTtcbiAgICBmZC5wb3MgPSAwO1xuICAgIHJldHVybiBmZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlYWRXcml0ZUV4aXN0aW5nKG8pIHtcbiAgICBjb25zdCBmZCA9IG5ldyBCaWdNZW1GaWxlKCk7XG4gICAgZmQubyA9IG87XG4gICAgZmQudG90YWxTaXplID0gKG8uZGF0YS5sZW5ndGgtMSkqIFBBR0VfU0laRSArIG8uZGF0YVtvLmRhdGEubGVuZ3RoLTFdLmJ5dGVMZW5ndGg7XG4gICAgZmQucmVhZE9ubHkgPSBmYWxzZTtcbiAgICBmZC5wb3MgPSAwO1xuICAgIHJldHVybiBmZDtcbn1cblxuY29uc3QgdG1wQnVmZjMyID0gbmV3IFVpbnQ4QXJyYXkoNCk7XG5jb25zdCB0bXBCdWZmMzJ2ID0gbmV3IERhdGFWaWV3KHRtcEJ1ZmYzMi5idWZmZXIpO1xuY29uc3QgdG1wQnVmZjY0ID0gbmV3IFVpbnQ4QXJyYXkoOCk7XG5jb25zdCB0bXBCdWZmNjR2ID0gbmV3IERhdGFWaWV3KHRtcEJ1ZmY2NC5idWZmZXIpO1xuXG5jbGFzcyBCaWdNZW1GaWxlIHtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLnBhZ2VTaXplID0gMSA8PCAxNDsgIC8vIGZvciBjb21wYXRpYmlsaXR5XG4gICAgfVxuXG4gICAgX3Jlc2l6ZUlmTmVlZGVkKG5ld0xlbikge1xuXG4gICAgICAgIGlmIChuZXdMZW4gPD0gdGhpcy50b3RhbFNpemUpIHJldHVybjtcblxuICAgICAgICBpZiAodGhpcy5yZWFkT25seSkgdGhyb3cgbmV3IEVycm9yKFwiUmVhZGluZyBvdXQgb2YgZmlsZSBib3VuZHNcIik7XG5cbiAgICAgICAgY29uc3QgblBhZ2VzID0gTWF0aC5mbG9vcigobmV3TGVuIC0gMSkgLyBQQUdFX1NJWkUpKzE7XG4gICAgICAgIGZvciAobGV0IGk9IE1hdGgubWF4KHRoaXMuby5kYXRhLmxlbmd0aC0xLCAwKTsgaTxuUGFnZXM7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgbmV3U2l6ZSA9IGk8blBhZ2VzLTEgPyBQQUdFX1NJWkUgOiBuZXdMZW4gLSAoblBhZ2VzLTEpKlBBR0VfU0laRTtcbiAgICAgICAgICAgIGNvbnN0IHAgPSBuZXcgVWludDhBcnJheShuZXdTaXplKTtcbiAgICAgICAgICAgIGlmIChpID09IHRoaXMuby5kYXRhLmxlbmd0aC0xKSBwLnNldCh0aGlzLm8uZGF0YVtpXSk7XG4gICAgICAgICAgICB0aGlzLm8uZGF0YVtpXSA9IHA7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy50b3RhbFNpemUgPSBuZXdMZW47XG4gICAgfVxuXG4gICAgYXN5bmMgd3JpdGUoYnVmZiwgcG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPXRoaXM7XG4gICAgICAgIGlmICh0eXBlb2YgcG9zID09IFwidW5kZWZpbmVkXCIpIHBvcyA9IHNlbGYucG9zO1xuICAgICAgICBpZiAodGhpcy5yZWFkT25seSkgdGhyb3cgbmV3IEVycm9yKFwiV3JpdGluZyBhIHJlYWQgb25seSBmaWxlXCIpO1xuXG4gICAgICAgIHRoaXMuX3Jlc2l6ZUlmTmVlZGVkKHBvcyArIGJ1ZmYuYnl0ZUxlbmd0aCk7XG5cbiAgICAgICAgY29uc3QgZmlyc3RQYWdlID0gTWF0aC5mbG9vcihwb3MgLyBQQUdFX1NJWkUpO1xuXG4gICAgICAgIGxldCBwID0gZmlyc3RQYWdlO1xuICAgICAgICBsZXQgbyA9IHBvcyAlIFBBR0VfU0laRTtcbiAgICAgICAgbGV0IHIgPSBidWZmLmJ5dGVMZW5ndGg7XG4gICAgICAgIHdoaWxlIChyPjApIHtcbiAgICAgICAgICAgIGNvbnN0IGwgPSAobytyID4gUEFHRV9TSVpFKSA/IChQQUdFX1NJWkUgLW8pIDogcjtcbiAgICAgICAgICAgIGNvbnN0IHNyY1ZpZXcgPSBidWZmLnNsaWNlKGJ1ZmYuYnl0ZUxlbmd0aCAtIHIsIGJ1ZmYuYnl0ZUxlbmd0aCAtIHIgKyBsKTtcbiAgICAgICAgICAgIGNvbnN0IGRzdFZpZXcgPSBuZXcgVWludDhBcnJheShzZWxmLm8uZGF0YVtwXS5idWZmZXIsIG8sIGwpO1xuICAgICAgICAgICAgZHN0Vmlldy5zZXQoc3JjVmlldyk7XG4gICAgICAgICAgICByID0gci1sO1xuICAgICAgICAgICAgcCArKztcbiAgICAgICAgICAgIG8gPSAwO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5wb3MgPSBwb3MgKyBidWZmLmJ5dGVMZW5ndGg7XG4gICAgfVxuXG4gICAgYXN5bmMgcmVhZFRvQnVmZmVyKGJ1ZmZEc3QsIG9mZnNldCwgbGVuLCBwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGlmICh0eXBlb2YgcG9zID09IFwidW5kZWZpbmVkXCIpIHBvcyA9IHNlbGYucG9zO1xuICAgICAgICBpZiAodGhpcy5yZWFkT25seSkge1xuICAgICAgICAgICAgaWYgKHBvcyArIGxlbiA+IHRoaXMudG90YWxTaXplKSB0aHJvdyBuZXcgRXJyb3IoXCJSZWFkaW5nIG91dCBvZiBib3VuZHNcIik7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcmVzaXplSWZOZWVkZWQocG9zICsgbGVuKTtcblxuICAgICAgICBjb25zdCBmaXJzdFBhZ2UgPSBNYXRoLmZsb29yKHBvcyAvIFBBR0VfU0laRSk7XG5cbiAgICAgICAgbGV0IHAgPSBmaXJzdFBhZ2U7XG4gICAgICAgIGxldCBvID0gcG9zICUgUEFHRV9TSVpFO1xuICAgICAgICAvLyBSZW1haW5pbmcgYnl0ZXMgdG8gcmVhZFxuICAgICAgICBsZXQgciA9IGxlbjtcbiAgICAgICAgd2hpbGUgKHI+MCkge1xuICAgICAgICAgICAgLy8gYnl0ZXMgdG8gY29weSBmcm9tIHRoaXMgcGFnZVxuICAgICAgICAgICAgY29uc3QgbCA9IChvK3IgPiBQQUdFX1NJWkUpID8gKFBBR0VfU0laRSAtbykgOiByO1xuICAgICAgICAgICAgY29uc3Qgc3JjVmlldyA9IG5ldyBVaW50OEFycmF5KHNlbGYuby5kYXRhW3BdLmJ1ZmZlciwgbywgbCk7XG4gICAgICAgICAgICBidWZmRHN0LnNldChzcmNWaWV3LCBvZmZzZXQrbGVuLXIpO1xuICAgICAgICAgICAgciA9IHItbDtcbiAgICAgICAgICAgIHAgKys7XG4gICAgICAgICAgICBvID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucG9zID0gcG9zICsgbGVuO1xuICAgIH1cblxuICAgIGFzeW5jIHJlYWQobGVuLCBwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGNvbnN0IGJ1ZmYgPSBuZXcgVWludDhBcnJheShsZW4pO1xuXG4gICAgICAgIGF3YWl0IHNlbGYucmVhZFRvQnVmZmVyKGJ1ZmYsIDAsIGxlbiwgcG9zKTtcblxuICAgICAgICByZXR1cm4gYnVmZjtcbiAgICB9XG5cbiAgICBjbG9zZSgpIHtcbiAgICB9XG5cbiAgICBhc3luYyBkaXNjYXJkKCkge1xuICAgIH1cblxuXG4gICAgYXN5bmMgd3JpdGVVTEUzMih2LCBwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICAgICAgdG1wQnVmZjMydi5zZXRVaW50MzIoMCwgdiwgdHJ1ZSk7XG5cbiAgICAgICAgYXdhaXQgc2VsZi53cml0ZSh0bXBCdWZmMzIsIHBvcyk7XG4gICAgfVxuXG4gICAgYXN5bmMgd3JpdGVVQkUzMih2LCBwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICAgICAgdG1wQnVmZjMydi5zZXRVaW50MzIoMCwgdiwgZmFsc2UpO1xuXG4gICAgICAgIGF3YWl0IHNlbGYud3JpdGUodG1wQnVmZjMyLCBwb3MpO1xuICAgIH1cblxuXG4gICAgYXN5bmMgd3JpdGVVTEU2NCh2LCBwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICAgICAgdG1wQnVmZjY0di5zZXRVaW50MzIoMCwgdiAmIDB4RkZGRkZGRkYsIHRydWUpO1xuICAgICAgICB0bXBCdWZmNjR2LnNldFVpbnQzMig0LCBNYXRoLmZsb29yKHYgLyAweDEwMDAwMDAwMCkgLCB0cnVlKTtcblxuICAgICAgICBhd2FpdCBzZWxmLndyaXRlKHRtcEJ1ZmY2NCwgcG9zKTtcbiAgICB9XG5cblxuICAgIGFzeW5jIHJlYWRVTEUzMihwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGNvbnN0IGIgPSBhd2FpdCBzZWxmLnJlYWQoNCwgcG9zKTtcblxuICAgICAgICBjb25zdCB2aWV3ID0gbmV3IFVpbnQzMkFycmF5KGIuYnVmZmVyKTtcblxuICAgICAgICByZXR1cm4gdmlld1swXTtcbiAgICB9XG5cbiAgICBhc3luYyByZWFkVUJFMzIocG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBjb25zdCBiID0gYXdhaXQgc2VsZi5yZWFkKDQsIHBvcyk7XG5cbiAgICAgICAgY29uc3QgdmlldyA9IG5ldyBEYXRhVmlldyhiLmJ1ZmZlcik7XG5cbiAgICAgICAgcmV0dXJuIHZpZXcuZ2V0VWludDMyKDAsIGZhbHNlKTtcbiAgICB9XG5cbiAgICBhc3luYyByZWFkVUxFNjQocG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBjb25zdCBiID0gYXdhaXQgc2VsZi5yZWFkKDgsIHBvcyk7XG5cbiAgICAgICAgY29uc3QgdmlldyA9IG5ldyBVaW50MzJBcnJheShiLmJ1ZmZlcik7XG5cbiAgICAgICAgcmV0dXJuIHZpZXdbMV0gKiAweDEwMDAwMDAwMCArIHZpZXdbMF07XG4gICAgfVxuXG4gICAgYXN5bmMgcmVhZFN0cmluZyhwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGNvbnN0IGZpeGVkU2l6ZSA9IDIwNDg7XG5cbiAgICAgICAgbGV0IGN1cnJlbnRQb3NpdGlvbiA9IHR5cGVvZiBwb3MgPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYucG9zIDogcG9zO1xuXG4gICAgICAgIGlmIChjdXJyZW50UG9zaXRpb24gPiB0aGlzLnRvdGFsU2l6ZSkge1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE9ubHkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJSZWFkaW5nIG91dCBvZiBib3VuZHNcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9yZXNpemVJZk5lZWRlZChwb3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGVuZE9mU3RyaW5nRm91bmQgPSBmYWxzZTtcbiAgICAgICAgbGV0IHN0ciA9IFwiXCI7XG5cbiAgICAgICAgd2hpbGUgKCFlbmRPZlN0cmluZ0ZvdW5kKSB7XG4gICAgICAgICAgICBsZXQgY3VycmVudFBhZ2UgPSBNYXRoLmZsb29yKGN1cnJlbnRQb3NpdGlvbiAvIFBBR0VfU0laRSk7XG4gICAgICAgICAgICBsZXQgb2Zmc2V0T25QYWdlID0gY3VycmVudFBvc2l0aW9uICUgUEFHRV9TSVpFO1xuXG4gICAgICAgICAgICBpZiAoc2VsZi5vLmRhdGFbY3VycmVudFBhZ2VdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJFUlJPUlwiKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV0IHJlYWRMZW5ndGggPSBNYXRoLm1pbihmaXhlZFNpemUsIHNlbGYuby5kYXRhW2N1cnJlbnRQYWdlXS5sZW5ndGggLSBvZmZzZXRPblBhZ2UpO1xuICAgICAgICAgICAgY29uc3QgZGF0YUFycmF5ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5vLmRhdGFbY3VycmVudFBhZ2VdLmJ1ZmZlciwgb2Zmc2V0T25QYWdlLCByZWFkTGVuZ3RoKTtcblxuICAgICAgICAgICAgbGV0IGluZGV4RW5kT2ZTdHJpbmcgPSBkYXRhQXJyYXkuZmluZEluZGV4KGVsZW1lbnQgPT4gZWxlbWVudCA9PT0gMCk7XG4gICAgICAgICAgICBlbmRPZlN0cmluZ0ZvdW5kID0gaW5kZXhFbmRPZlN0cmluZyAhPT0gLTE7XG5cbiAgICAgICAgICAgIGlmIChlbmRPZlN0cmluZ0ZvdW5kKSB7XG4gICAgICAgICAgICAgICAgc3RyICs9IG5ldyBUZXh0RGVjb2RlcigpLmRlY29kZShkYXRhQXJyYXkuc2xpY2UoMCwgaW5kZXhFbmRPZlN0cmluZykpO1xuICAgICAgICAgICAgICAgIHNlbGYucG9zID0gY3VycmVudFBhZ2UgKiBQQUdFX1NJWkUgKyBvZmZzZXRPblBhZ2UgKyBpbmRleEVuZE9mU3RyaW5nICsgMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3RyICs9IG5ldyBUZXh0RGVjb2RlcigpLmRlY29kZShkYXRhQXJyYXkpO1xuICAgICAgICAgICAgICAgIHNlbGYucG9zID0gY3VycmVudFBhZ2UgKiBQQUdFX1NJWkUgKyBvZmZzZXRPblBhZ2UgKyBkYXRhQXJyYXkubGVuZ3RoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjdXJyZW50UG9zaXRpb24gPSBzZWxmLnBvcztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3RyO1xuICAgIH1cbn1cbiIsIi8qIGdsb2JhbCBmZXRjaCAqL1xuaW1wb3J0IHsgb3BlbiB9IGZyb20gXCIuL29zZmlsZS5qc1wiO1xuaW1wb3J0ICogYXMgbWVtRmlsZSBmcm9tIFwiLi9tZW1maWxlLmpzXCI7XG5pbXBvcnQgKiBhcyBiaWdNZW1GaWxlIGZyb20gXCIuL2JpZ21lbWZpbGUuanNcIjtcbmltcG9ydCB7IE9fVFJVTkMsIE9fQ1JFQVQsIE9fUkRXUiwgT19FWENMLCBPX1JET05MWSB9IGZyb20gXCJjb25zdGFudHNcIjtcblxuY29uc3QgREVGQVVMVF9DQUNIRV9TSVpFID0gKDEgPDwgMTYpO1xuY29uc3QgREVGQVVMVF9QQUdFX1NJWkUgPSAoMSA8PCAxMyk7XG5cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZU92ZXJyaWRlKG8sIGIsIGMpIHtcbiAgICBpZiAodHlwZW9mIG8gPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgbyA9IHtcbiAgICAgICAgICAgIHR5cGU6IFwiZmlsZVwiLFxuICAgICAgICAgICAgZmlsZU5hbWU6IG8sXG4gICAgICAgICAgICBjYWNoZVNpemU6IGIgfHwgREVGQVVMVF9DQUNIRV9TSVpFLFxuICAgICAgICAgICAgcGFnZVNpemU6IGMgfHwgREVGQVVMVF9QQUdFX1NJWkVcbiAgICAgICAgfTtcbiAgICB9XG4gICAgaWYgKG8udHlwZSA9PSBcImZpbGVcIikge1xuICAgICAgICByZXR1cm4gYXdhaXQgb3BlbihvLmZpbGVOYW1lLCBPX1RSVU5DIHwgT19DUkVBVCB8IE9fUkRXUiwgby5jYWNoZVNpemUsIG8ucGFnZVNpemUpO1xuICAgIH0gZWxzZSBpZiAoby50eXBlID09IFwibWVtXCIpIHtcbiAgICAgICAgcmV0dXJuIG1lbUZpbGUuY3JlYXRlTmV3KG8pO1xuICAgIH0gZWxzZSBpZiAoby50eXBlID09IFwiYmlnTWVtXCIpIHtcbiAgICAgICAgcmV0dXJuIGJpZ01lbUZpbGUuY3JlYXRlTmV3KG8pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgRmFzdEZpbGUgdHlwZTogXCIrby50eXBlKTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVOb092ZXJyaWRlKG8sIGIsIGMpIHtcbiAgICBpZiAodHlwZW9mIG8gPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgbyA9IHtcbiAgICAgICAgICAgIHR5cGU6IFwiZmlsZVwiLFxuICAgICAgICAgICAgZmlsZU5hbWU6IG8sXG4gICAgICAgICAgICBjYWNoZVNpemU6IGIgfHwgREVGQVVMVF9DQUNIRV9TSVpFLFxuICAgICAgICAgICAgcGFnZVNpemU6IGMgfHwgREVGQVVMVF9QQUdFX1NJWkVcbiAgICAgICAgfTtcbiAgICB9XG4gICAgaWYgKG8udHlwZSA9PSBcImZpbGVcIikge1xuICAgICAgICByZXR1cm4gb3BlbihvLmZpbGVOYW1lLCBPX1RSVU5DIHwgT19DUkVBVCB8IE9fUkRXUiB8IE9fRVhDTCwgby5jYWNoZVNpemUsIG8ucGFnZVNpemUpO1xuICAgIH0gZWxzZSBpZiAoby50eXBlID09IFwibWVtXCIpIHtcbiAgICAgICAgcmV0dXJuIG1lbUZpbGUuY3JlYXRlTmV3KG8pO1xuICAgIH0gZWxzZSBpZiAoby50eXBlID09IFwiYmlnTWVtXCIpIHtcbiAgICAgICAgcmV0dXJuIGJpZ01lbUZpbGUuY3JlYXRlTmV3KG8pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgRmFzdEZpbGUgdHlwZTogXCIrby50eXBlKTtcbiAgICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWFkRXhpc3RpbmcobywgYiwgYykge1xuICAgIGlmIChvIGluc3RhbmNlb2YgVWludDhBcnJheSkge1xuICAgICAgICBvID0ge1xuICAgICAgICAgICAgdHlwZTogXCJtZW1cIixcbiAgICAgICAgICAgIGRhdGE6IG9cbiAgICAgICAgfTtcbiAgICB9XG4gICAgaWYgKHByb2Nlc3MuYnJvd3Nlcikge1xuICAgICAgICBpZiAodHlwZW9mIG8gPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmYgPSBhd2FpdCBmZXRjaChvKS50aGVuKCBmdW5jdGlvbihyZXMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzLmFycmF5QnVmZmVyKCk7XG4gICAgICAgICAgICB9KS50aGVuKGZ1bmN0aW9uIChhYikge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShhYik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIG8gPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJtZW1cIixcbiAgICAgICAgICAgICAgICBkYXRhOiBidWZmXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKHR5cGVvZiBvID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICBvID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6IFwiZmlsZVwiLFxuICAgICAgICAgICAgICAgIGZpbGVOYW1lOiBvLFxuICAgICAgICAgICAgICAgIGNhY2hlU2l6ZTogYiB8fCBERUZBVUxUX0NBQ0hFX1NJWkUsXG4gICAgICAgICAgICAgICAgcGFnZVNpemU6IGMgfHwgREVGQVVMVF9QQUdFX1NJWkVcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKG8udHlwZSA9PSBcImZpbGVcIikge1xuICAgICAgICByZXR1cm4gYXdhaXQgb3BlbihvLmZpbGVOYW1lLCBPX1JET05MWSwgby5jYWNoZVNpemUsIG8ucGFnZVNpemUpO1xuICAgIH0gZWxzZSBpZiAoby50eXBlID09IFwibWVtXCIpIHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IG1lbUZpbGUucmVhZEV4aXN0aW5nKG8pO1xuICAgIH0gZWxzZSBpZiAoby50eXBlID09IFwiYmlnTWVtXCIpIHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IGJpZ01lbUZpbGUucmVhZEV4aXN0aW5nKG8pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgRmFzdEZpbGUgdHlwZTogXCIrby50eXBlKTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWFkV3JpdGVFeGlzdGluZyhvLCBiLCBjKSB7XG4gICAgaWYgKHR5cGVvZiBvID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIG8gPSB7XG4gICAgICAgICAgICB0eXBlOiBcImZpbGVcIixcbiAgICAgICAgICAgIGZpbGVOYW1lOiBvLFxuICAgICAgICAgICAgY2FjaGVTaXplOiBiIHx8IERFRkFVTFRfQ0FDSEVfU0laRSxcbiAgICAgICAgICAgIHBhZ2VTaXplOiBjIHx8IERFRkFVTFRfUEFHRV9TSVpFXG4gICAgICAgIH07XG4gICAgfVxuICAgIGlmIChvLnR5cGUgPT0gXCJmaWxlXCIpIHtcbiAgICAgICAgcmV0dXJuIG9wZW4oby5maWxlTmFtZSwgT19DUkVBVCB8IE9fUkRXUiwgby5jYWNoZVNpemUsIG8ucGFnZVNpemUpO1xuICAgIH0gZWxzZSBpZiAoby50eXBlID09IFwibWVtXCIpIHtcbiAgICAgICAgcmV0dXJuIG1lbUZpbGUucmVhZFdyaXRlRXhpc3Rpbmcobyk7XG4gICAgfSBlbHNlIGlmIChvLnR5cGUgPT0gXCJiaWdNZW1cIikge1xuICAgICAgICByZXR1cm4gYmlnTWVtRmlsZS5yZWFkV3JpdGVFeGlzdGluZyhvKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIEZhc3RGaWxlIHR5cGU6IFwiK28udHlwZSk7XG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVhZFdyaXRlRXhpc3RpbmdPckNyZWF0ZShvLCBiLCBjKSB7XG4gICAgaWYgKHR5cGVvZiBvID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIG8gPSB7XG4gICAgICAgICAgICB0eXBlOiBcImZpbGVcIixcbiAgICAgICAgICAgIGZpbGVOYW1lOiBvLFxuICAgICAgICAgICAgY2FjaGVTaXplOiBiIHx8IERFRkFVTFRfQ0FDSEVfU0laRSxcbiAgICAgICAgICAgIHBhZ2VTaXplOiBjIHx8IERFRkFVTFRfUEFHRV9TSVpFXG4gICAgICAgIH07XG4gICAgfVxuICAgIGlmIChvLnR5cGUgPT0gXCJmaWxlXCIpIHtcbiAgICAgICAgcmV0dXJuIG9wZW4oby5maWxlTmFtZSwgT19DUkVBVCB8IE9fUkRXUiB8IE9fRVhDTCwgby5jYWNoZVNpemUpO1xuICAgIH0gZWxzZSBpZiAoby50eXBlID09IFwibWVtXCIpIHtcbiAgICAgICAgcmV0dXJuIG1lbUZpbGUucmVhZFdyaXRlRXhpc3Rpbmcobyk7XG4gICAgfSBlbHNlIGlmIChvLnR5cGUgPT0gXCJiaWdNZW1cIikge1xuICAgICAgICByZXR1cm4gYmlnTWVtRmlsZS5yZWFkV3JpdGVFeGlzdGluZyhvKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIEZhc3RGaWxlIHR5cGU6IFwiK28udHlwZSk7XG4gICAgfVxufVxuIiwiLypcblxuQ29weXJpZ2h0IDIwMjAgMEtJTVMgYXNzb2NpYXRpb24uXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5leHBvcnQgZnVuY3Rpb24gZmxhdEFycmF5KGEpIHtcbiAgICBsZXQgcmVzID0gW107XG4gICAgZmlsbEFycmF5KHJlcywgYSk7XG4gICAgcmV0dXJuIHJlcztcblxuICAgIGZ1bmN0aW9uIGZpbGxBcnJheShyZXMsIGEpIHtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoYSkpIHtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGZpbGxBcnJheShyZXMsIGFbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzLnB1c2goYSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8vIFJlZiBodHRwczovL2dpdGh1Yi5jb20vaWRlbjMvY2lyY29tL2NvbW1pdC9lYzYzODhjZjZlYjYyNDYzNTM5Y2I0YzQwY2MzY2VhZTk4MjZkZTE5XG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXplKG4sIHByaW1lKSB7XG4gICAgbGV0IHJlcyA9IEJpZ0ludChuKSAlIHByaW1lO1xuICAgIGlmIChyZXMgPCAwKSByZXMgKz0gcHJpbWU7XG4gICAgcmV0dXJuIHJlcztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZudkhhc2goc3RyKSB7XG4gICAgY29uc3QgdWludDY0X21heCA9IEJpZ0ludCgyKSAqKiBCaWdJbnQoNjQpO1xuICAgIGxldCBoYXNoID0gQmlnSW50KFwiMHhDQkYyOUNFNDg0MjIyMzI1XCIpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGhhc2ggXj0gQmlnSW50KHN0cltpXS5jaGFyQ29kZUF0KDApKTtcbiAgICAgICAgaGFzaCAqPSBCaWdJbnQoMHgxMDAwMDAwMDFCMyk7XG4gICAgICAgIGhhc2ggJT0gdWludDY0X21heDtcbiAgICB9XG4gICAgbGV0IHNoYXNoID0gaGFzaC50b1N0cmluZygxNik7XG4gICAgbGV0IG4gPSAxNiAtIHNoYXNoLmxlbmd0aDtcbiAgICBzaGFzaCA9IFwiMFwiLnJlcGVhdChuKS5jb25jYXQoc2hhc2gpO1xuICAgIHJldHVybiBzaGFzaDtcbn1cblxuLy8gTm90ZSB0aGF0IHRoaXMgcGFkcyB6ZXJvc1xuZXhwb3J0IGZ1bmN0aW9uIHRvQXJyYXkzMihzLCBzaXplKSB7XG4gICAgY29uc3QgcmVzID0gW107IC8vbmV3IFVpbnQzMkFycmF5KHNpemUpOyAvL2hhcyBubyB1bnNoaWZ0XG4gICAgbGV0IHJlbSA9IEJpZ0ludChzKTtcbiAgICBjb25zdCByYWRpeCA9IEJpZ0ludCgweDEwMDAwMDAwMCk7XG4gICAgd2hpbGUgKHJlbSkge1xuICAgICAgICByZXMudW5zaGlmdChOdW1iZXIocmVtICUgcmFkaXgpKTtcbiAgICAgICAgcmVtID0gcmVtIC8gcmFkaXg7XG4gICAgfVxuICAgIGlmIChzaXplKSB7XG4gICAgICAgIGxldCBpID0gc2l6ZSAtIHJlcy5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpID4gMCkge1xuICAgICAgICAgICAgcmVzLnVuc2hpZnQoMCk7XG4gICAgICAgICAgICBpLS07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbn1cbiIsIi8qIGdsb2JhbHMgV2ViQXNzZW1ibHkgKi9cbi8qXG5cbkNvcHlyaWdodCAyMDIwIDBLSU1TIGFzc29jaWF0aW9uLlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHtmbGF0QXJyYXksIGZudkhhc2gsIHRvQXJyYXkzMiwgbm9ybWFsaXplfSBmcm9tIFwiLi91dGlscy5qc1wiO1xuaW1wb3J0IHtTY2FsYXIsIEYxRmllbGR9IGZyb20gXCJmZmphdmFzY3JpcHRcIjtcblxuZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gYnVpbGRlcihjb2RlLCBvcHRpb25zKSB7XG4gICAgbGV0IGluc3RhbmNlO1xuICAgIGxldCB3YztcbiAgICBsZXQgbWVtb3J5O1xuICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gICAgLy8gT25seSBjaXJjb20gMiBpbXBsZW1lbnRzIHZlcnNpb24gbG9va3VwIHRocm91Z2ggZXhwb3J0cyBpbiB0aGUgV0FTTVxuICAgIC8vIFdlIGRlZmF1bHQgdG8gYDFgIGFuZCB1cGRhdGUgaWYgd2Ugc2VlIHRoZSBgZ2V0VmVyc2lvbmAgZXhwb3J0IChtYWpvciB2ZXJzaW9uKVxuICAgIC8vIFRoZXNlIGFyZSB1cGRhdGVkIGFmdGVyIHRoZSBpbnN0YW5jZSBpcyBpbnN0YW50aWF0ZWQsIGFzc3VtaW5nIHRoZSBmdW5jdGlvbnMgYXJlIGF2YWlsYWJsZVxuICAgIGxldCBtYWpvclZlcnNpb24gPSAxO1xuICAgIC8vIEFmdGVyIENpcmNvbSAyLjAuNywgQmxhaW5lIGFkZGVkIGV4cG9ydGVkIGZ1bmN0aW9ucyBmb3IgZ2V0dGluZyBtaW5vciBhbmQgcGF0Y2ggdmVyc2lvbnNcbiAgICBsZXQgbWlub3JWZXJzaW9uID0gMDtcbiAgICAvLyBJZiB3ZSBjYW4ndCBsb29rIHVwIHRoZSBwYXRjaCB2ZXJzaW9uLCBhc3N1bWUgdGhlIGxvd2VzdFxuICAgIGxldCBwYXRjaFZlcnNpb24gPSAwO1xuXG4gICAgbGV0IGNvZGVJc1dlYkFzc2VtYmx5SW5zdGFuY2UgPSBmYWxzZTtcblxuICAgIC8vIElmIGNvZGUgaXMgYWxyZWFkeSBwcmVwYXJlZCBXZWJBc3NlbWJseS5JbnN0YW5jZSwgd2UgdXNlIGl0IGRpcmVjdGx5XG4gICAgaWYgKGNvZGUgaW5zdGFuY2VvZiBXZWJBc3NlbWJseS5JbnN0YW5jZSkge1xuICAgICAgICBpbnN0YW5jZSA9IGNvZGU7XG4gICAgICAgIGNvZGVJc1dlYkFzc2VtYmx5SW5zdGFuY2UgPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGxldCBtZW1vcnlTaXplID0gMzI3Njc7XG5cbiAgICAgICAgaWYgKG9wdGlvbnMubWVtb3J5U2l6ZSkge1xuICAgICAgICAgICAgLy8gbWFrZSBzdXJlIHdlIGhhdmUgaW50XG4gICAgICAgICAgICBtZW1vcnlTaXplID0gcGFyc2VJbnQob3B0aW9ucy5tZW1vcnlTaXplKTtcbiAgICAgICAgICAgIGlmIChtZW1vcnlTaXplIDwgMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgbWVtb3J5IHNpemVcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgbWVtb3J5QWxsb2NhdGVkID0gZmFsc2U7XG4gICAgICAgIHdoaWxlICghbWVtb3J5QWxsb2NhdGVkKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIG1lbW9yeSA9IG5ldyBXZWJBc3NlbWJseS5NZW1vcnkoe2luaXRpYWw6IG1lbW9yeVNpemV9KTtcbiAgICAgICAgICAgICAgICBtZW1vcnlBbGxvY2F0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgaWYgKG1lbW9yeVNpemUgPD0gMSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkNvdWxkIG5vdCBhbGxvY2F0ZSBcIiArIG1lbW9yeVNpemUgKiAxMDI0ICogNjQgKyBcIiBieXRlcy4gVGhpcyBtYXkgY2F1c2Ugc2V2ZXJlIGluc3RhYmlsaXR5LiBUcnlpbmcgd2l0aCBcIiArIG1lbW9yeVNpemUgKiAxMDI0ICogNjQgLyAyICsgXCIgYnl0ZXNcIik7XG4gICAgICAgICAgICAgICAgbWVtb3J5U2l6ZSA9IE1hdGguZmxvb3IobWVtb3J5U2l6ZSAvIDIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgd2FzbU1vZHVsZSA9IGF3YWl0IFdlYkFzc2VtYmx5LmNvbXBpbGUoY29kZSk7XG5cbiAgICAgICAgbGV0IGVyclN0ciA9IFwiXCI7XG4gICAgICAgIGxldCBtc2dTdHIgPSBcIlwiO1xuXG4gICAgICAgIGluc3RhbmNlID0gYXdhaXQgV2ViQXNzZW1ibHkuaW5zdGFudGlhdGUod2FzbU1vZHVsZSwge1xuICAgICAgICAgICAgZW52OiB7XG4gICAgICAgICAgICAgICAgXCJtZW1vcnlcIjogbWVtb3J5XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcnVudGltZToge1xuICAgICAgICAgICAgICAgIHByaW50RGVidWcgOiBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcInByaW50RGVidWc6XCIsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGV4Y2VwdGlvbkhhbmRsZXI6IGZ1bmN0aW9uIChjb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBlcnI7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb2RlID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnIgPSBcIlNpZ25hbCBub3QgZm91bmQuIFwiO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGNvZGUgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVyciA9IFwiVG9vIG1hbnkgc2lnbmFscyBzZXQuIFwiO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGNvZGUgPT09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVyciA9IFwiU2lnbmFsIGFscmVhZHkgc2V0LiBcIjtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjb2RlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnIgPSBcIkFzc2VydCBGYWlsZWQuIFwiO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGNvZGUgPT09IDUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVyciA9IFwiTm90IGVub3VnaCBtZW1vcnkuIFwiO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGNvZGUgPT09IDYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVyciA9IFwiSW5wdXQgc2lnbmFsIGFycmF5IGFjY2VzcyBleGNlZWRzIHRoZSBzaXplLiBcIjtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVyciA9IFwiVW5rbm93biBlcnJvci4gXCI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVSUk9SOiBcIiwgY29kZSwgZXJyU3RyKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVyciArIGVyclN0cik7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAvLyBBIG5ldyB3YXkgb2YgbG9nZ2luZyBtZXNzYWdlcyB3YXMgYWRkZWQgaW4gQ2lyY29tIDIuMC43IHRoYXQgcmVxdWlyZXMgMiBuZXcgaW1wb3J0c1xuICAgICAgICAgICAgICAgIC8vIGBwcmludEVycm9yTWVzc2FnZWAgYW5kIGB3cml0ZUJ1ZmZlck1lc3NhZ2VgLlxuICAgICAgICAgICAgICAgIHByaW50RXJyb3JNZXNzYWdlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGVyclN0ciArPSBnZXRNZXNzYWdlKCkgKyBcIlxcblwiO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgd3JpdGVCdWZmZXJNZXNzYWdlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG1zZyA9IGdldE1lc3NhZ2UoKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gQW55IGNhbGxzIHRvIGBsb2coKWAgd2lsbCBhbHdheXMgZW5kIHdpdGggYSBgXFxuYCwgc28gdGhhdCdzIHdoZW4gd2UgcHJpbnQgYW5kIHJlc2V0XG4gICAgICAgICAgICAgICAgICAgIGlmIChtc2cgPT09IFwiXFxuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKG1zZ1N0cik7XG4gICAgICAgICAgICAgICAgICAgICAgICBtc2dTdHIgPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgd2UndmUgYnVmZmVyZWQgb3RoZXIgY29udGVudCwgcHV0IGEgc3BhY2UgaW4gYmV0d2VlbiB0aGUgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtc2dTdHIgIT09IFwiXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtc2dTdHIgKz0gXCIgXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGVuIGFwcGVuZCB0aGUgbWVzc2FnZSB0byB0aGUgbWVzc2FnZSB3ZSBhcmUgY3JlYXRpbmdcbiAgICAgICAgICAgICAgICAgICAgICAgIG1zZ1N0ciArPSBtc2c7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNob3dTaGFyZWRSV01lbW9yeTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzaGFyZWRfcndfbWVtb3J5X3NpemUgPSBpbnN0YW5jZS5leHBvcnRzLmdldEZpZWxkTnVtTGVuMzIoKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYXJyID0gbmV3IFVpbnQzMkFycmF5KHNoYXJlZF9yd19tZW1vcnlfc2l6ZSk7XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgc2hhcmVkX3J3X21lbW9yeV9zaXplOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFycltzaGFyZWRfcndfbWVtb3J5X3NpemUgLSAxIC0gal0gPSBpbnN0YW5jZS5leHBvcnRzLnJlYWRTaGFyZWRSV01lbW9yeShqKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEluIGNpcmNvbSAyLjAuNywgdGhleSBjaGFuZ2VkIHRoZSBsb2coKSBmdW5jdGlvbiB0byBhbGxvdyBzdHJpbmdzIGFuZCBjaGFuZ2VkIHRoZVxuICAgICAgICAgICAgICAgICAgICAvLyBvdXRwdXQgQVBJLiBUaGlzIHNtb290aGVzIG92ZXIgdGhlIGJyZWFraW5nIGNoYW5nZS5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1ham9yVmVyc2lvbiA+PSAyICYmIChtaW5vclZlcnNpb24gPj0gMSB8fCBwYXRjaFZlcnNpb24gPj0gNykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHdlJ3ZlIGJ1ZmZlcmVkIG90aGVyIGNvbnRlbnQsIHB1dCBhIHNwYWNlIGluIGJldHdlZW4gdGhlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobXNnU3RyICE9PSBcIlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXNnU3RyICs9IFwiIFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlbiBhcHBlbmQgdGhlIHZhbHVlIHRvIHRoZSBtZXNzYWdlIHdlIGFyZSBjcmVhdGluZ1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbXNnID0gKFNjYWxhci5mcm9tQXJyYXkoYXJyLCAweDEwMDAwMDAwMCkudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBtc2dTdHIgKz0gbXNnO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coU2NhbGFyLmZyb21BcnJheShhcnIsIDB4MTAwMDAwMDAwKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbiAoY29kZSwgcHN0ciwgYSwgYiwgYywgZCkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgZXJyU3RyO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY29kZSA9PT0gNykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyU3RyID0gcDJzdHIocHN0cikgKyBcIiBcIiArIHdjLmdldEZyKGIpLnRvU3RyaW5nKCkgKyBcIiAhPSBcIiArIHdjLmdldEZyKGMpLnRvU3RyaW5nKCkgKyBcIiBcIiArIHAyc3RyKGQpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGNvZGUgPT09IDkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVyclN0ciA9IHAyc3RyKHBzdHIpICsgXCIgXCIgKyB3Yy5nZXRGcihiKS50b1N0cmluZygpICsgXCIgXCIgKyBwMnN0cihjKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICgoY29kZSA9PT0gNSkgJiYgKG9wdGlvbnMuc3ltKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyU3RyID0gcDJzdHIocHN0cikgKyBcIiBcIiArIG9wdGlvbnMuc3ltLmxhYmVsSWR4Mk5hbWVbY107XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJTdHIgPSBwMnN0cihwc3RyKSArIFwiIFwiICsgYSArIFwiIFwiICsgYiArIFwiIFwiICsgYyArIFwiIFwiICsgZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIkVSUk9SOiBcIiwgY29kZSwgZXJyU3RyKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVyclN0cik7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBsb2c6IGZ1bmN0aW9uIChhKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKHdjLmdldEZyKGEpLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgbG9nR2V0U2lnbmFsOiBmdW5jdGlvbiAoc2lnbmFsLCBwVmFsKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmxvZ0dldFNpZ25hbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy5sb2dHZXRTaWduYWwoc2lnbmFsLCB3Yy5nZXRGcihwVmFsKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGxvZ1NldFNpZ25hbDogZnVuY3Rpb24gKHNpZ25hbCwgcFZhbCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5sb2dTZXRTaWduYWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMubG9nU2V0U2lnbmFsKHNpZ25hbCwgd2MuZ2V0RnIocFZhbCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBsb2dTdGFydENvbXBvbmVudDogZnVuY3Rpb24gKGNJZHgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMubG9nU3RhcnRDb21wb25lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMubG9nU3RhcnRDb21wb25lbnQoY0lkeCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGxvZ0ZpbmlzaENvbXBvbmVudDogZnVuY3Rpb24gKGNJZHgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMubG9nRmluaXNoQ29tcG9uZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zLmxvZ0ZpbmlzaENvbXBvbmVudChjSWR4KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBpbnN0YW5jZS5leHBvcnRzLmdldFZlcnNpb24gPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgIG1ham9yVmVyc2lvbiA9IGluc3RhbmNlLmV4cG9ydHMuZ2V0VmVyc2lvbigpO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGluc3RhbmNlLmV4cG9ydHMuZ2V0TWlub3JWZXJzaW9uID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICBtaW5vclZlcnNpb24gPSBpbnN0YW5jZS5leHBvcnRzLmdldE1pbm9yVmVyc2lvbigpO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGluc3RhbmNlLmV4cG9ydHMuZ2V0UGF0Y2hWZXJzaW9uID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICBwYXRjaFZlcnNpb24gPSBpbnN0YW5jZS5leHBvcnRzLmdldFBhdGNoVmVyc2lvbigpO1xuICAgIH1cblxuICAgIGNvbnN0IHNhbml0eUNoZWNrID1cbiAgICAgICAgb3B0aW9ucyAmJlxuICAgICAgICAoXG4gICAgICAgICAgICBvcHRpb25zLnNhbml0eUNoZWNrIHx8XG4gICAgICAgICAgICBvcHRpb25zLmxvZ0dldFNpZ25hbCB8fFxuICAgICAgICAgICAgb3B0aW9ucy5sb2dTZXRTaWduYWwgfHxcbiAgICAgICAgICAgIG9wdGlvbnMubG9nU3RhcnRDb21wb25lbnQgfHxcbiAgICAgICAgICAgIG9wdGlvbnMubG9nRmluaXNoQ29tcG9uZW50XG4gICAgICAgICk7XG5cbiAgICAvLyBXZSBleHBsaWNpdGx5IGNoZWNrIGZvciBtYWpvciB2ZXJzaW9uIDIgaW4gY2FzZSB0aGVyZSdzIGEgY2lyY29tIHYzIGluIHRoZSBmdXR1cmVcbiAgICBpZiAobWFqb3JWZXJzaW9uID09PSAyKSB7XG4gICAgICAgIHdjID0gbmV3IFdpdG5lc3NDYWxjdWxhdG9yQ2lyY29tMihpbnN0YW5jZSwgc2FuaXR5Q2hlY2spO1xuICAgIH0gZWxzZSBpZiAobWFqb3JWZXJzaW9uID09PSAxKSB7XG4gICAgICAgIGlmIChjb2RlSXNXZWJBc3NlbWJseUluc3RhbmNlKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0xvYWRpbmcgY29kZSBmcm9tIFdlYkFzc2VtYmx5IGluc3RhbmNlIGlzIG5vdCBzdXBwb3J0ZWQgZm9yIGNpcmNvbSB2ZXJzaW9uIDEnKTtcbiAgICAgICAgfVxuICAgICAgICB3YyA9IG5ldyBXaXRuZXNzQ2FsY3VsYXRvckNpcmNvbTEobWVtb3J5LCBpbnN0YW5jZSwgc2FuaXR5Q2hlY2spO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgY2lyY29tIHZlcnNpb246ICR7bWFqb3JWZXJzaW9ufWApO1xuICAgIH1cbiAgICByZXR1cm4gd2M7XG5cbiAgICBmdW5jdGlvbiBnZXRNZXNzYWdlKCkge1xuICAgICAgICBsZXQgbWVzc2FnZSA9IFwiXCI7XG4gICAgICAgIGxldCBjID0gaW5zdGFuY2UuZXhwb3J0cy5nZXRNZXNzYWdlQ2hhcigpO1xuICAgICAgICB3aGlsZSAoYyAhPT0gMCkge1xuICAgICAgICAgICAgbWVzc2FnZSArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGMpO1xuICAgICAgICAgICAgYyA9IGluc3RhbmNlLmV4cG9ydHMuZ2V0TWVzc2FnZUNoYXIoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwMnN0cihwKSB7XG4gICAgICAgIGNvbnN0IGk4ID0gbmV3IFVpbnQ4QXJyYXkobWVtb3J5LmJ1ZmZlcik7XG5cbiAgICAgICAgY29uc3QgYnl0ZXMgPSBbXTtcblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaThbcCArIGldID4gMDsgaSsrKSBieXRlcy5wdXNoKGk4W3AgKyBpXSk7XG5cbiAgICAgICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgYnl0ZXMpO1xuICAgIH1cbn1cblxuY2xhc3MgV2l0bmVzc0NhbGN1bGF0b3JDaXJjb20xIHtcbiAgICBjb25zdHJ1Y3RvcihtZW1vcnksIGluc3RhbmNlLCBzYW5pdHlDaGVjaykge1xuICAgICAgICB0aGlzLm1lbW9yeSA9IG1lbW9yeTtcbiAgICAgICAgdGhpcy5pMzIgPSBuZXcgVWludDMyQXJyYXkobWVtb3J5LmJ1ZmZlcik7XG4gICAgICAgIHRoaXMuaW5zdGFuY2UgPSBpbnN0YW5jZTtcblxuICAgICAgICB0aGlzLm4zMiA9ICh0aGlzLmluc3RhbmNlLmV4cG9ydHMuZ2V0RnJMZW4oKSA+PiAyKSAtIDI7XG4gICAgICAgIGNvbnN0IHBSYXdQcmltZSA9IHRoaXMuaW5zdGFuY2UuZXhwb3J0cy5nZXRQUmF3UHJpbWUoKTtcblxuICAgICAgICBjb25zdCBhcnIgPSBuZXcgQXJyYXkodGhpcy5uMzIpO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubjMyOyBpKyspIHtcbiAgICAgICAgICAgIGFyclt0aGlzLm4zMiAtIDEgLSBpXSA9IHRoaXMuaTMyWyhwUmF3UHJpbWUgPj4gMikgKyBpXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucHJpbWUgPSBTY2FsYXIuZnJvbUFycmF5KGFyciwgMHgxMDAwMDAwMDApO1xuXG4gICAgICAgIHRoaXMuRnIgPSBuZXcgRjFGaWVsZCh0aGlzLnByaW1lKTtcblxuICAgICAgICB0aGlzLm1hc2szMiA9IFNjYWxhci5mcm9tU3RyaW5nKFwiRkZGRkZGRkZcIiwgMTYpO1xuICAgICAgICB0aGlzLk5WYXJzID0gdGhpcy5pbnN0YW5jZS5leHBvcnRzLmdldE5WYXJzKCk7XG4gICAgICAgIHRoaXMubjY0ID0gTWF0aC5mbG9vcigodGhpcy5Gci5iaXRMZW5ndGggLSAxKSAvIDY0KSArIDE7XG4gICAgICAgIHRoaXMuUiA9IHRoaXMuRnIuZShTY2FsYXIuc2hpZnRMZWZ0KDEsIHRoaXMubjY0ICogNjQpKTtcbiAgICAgICAgdGhpcy5SSW52ID0gdGhpcy5Gci5pbnYodGhpcy5SKTtcbiAgICAgICAgdGhpcy5zYW5pdHlDaGVjayA9IHNhbml0eUNoZWNrO1xuICAgIH1cblxuICAgIGNpcmNvbV92ZXJzaW9uKCkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICB9XG5cbiAgICBhc3luYyBfZG9DYWxjdWxhdGVXaXRuZXNzKGlucHV0LCBzYW5pdHlDaGVjaykge1xuICAgICAgICB0aGlzLmluc3RhbmNlLmV4cG9ydHMuaW5pdCgodGhpcy5zYW5pdHlDaGVjayB8fCBzYW5pdHlDaGVjaykgPyAxIDogMCk7XG4gICAgICAgIGNvbnN0IHBTaWdPZmZzZXQgPSB0aGlzLmFsbG9jSW50KCk7XG4gICAgICAgIGNvbnN0IHBGciA9IHRoaXMuYWxsb2NGcigpO1xuICAgICAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMoaW5wdXQpO1xuICAgICAgICBrZXlzLmZvckVhY2goKGspID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGggPSBmbnZIYXNoKGspO1xuICAgICAgICAgICAgY29uc3QgaE1TQiA9IHBhcnNlSW50KGguc2xpY2UoMCwgOCksIDE2KTtcbiAgICAgICAgICAgIGNvbnN0IGhMU0IgPSBwYXJzZUludChoLnNsaWNlKDgsIDE2KSwgMTYpO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB0aGlzLmluc3RhbmNlLmV4cG9ydHMuZ2V0U2lnbmFsT2Zmc2V0MzIocFNpZ09mZnNldCwgMCwgaE1TQiwgaExTQik7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFNpZ25hbCAke2t9IGlzIG5vdCBhbiBpbnB1dCBvZiB0aGUgY2lyY3VpdC5gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHNpZ09mZnNldCA9IHRoaXMuZ2V0SW50KHBTaWdPZmZzZXQpO1xuICAgICAgICAgICAgY29uc3QgZkFyciA9IGZsYXRBcnJheShpbnB1dFtrXSk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZBcnIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldEZyKHBGciwgZkFycltpXSk7XG4gICAgICAgICAgICAgICAgdGhpcy5pbnN0YW5jZS5leHBvcnRzLnNldFNpZ25hbCgwLCAwLCBzaWdPZmZzZXQgKyBpLCBwRnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBhc3luYyBjYWxjdWxhdGVXaXRuZXNzKGlucHV0LCBzYW5pdHlDaGVjaykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcblxuICAgICAgICBjb25zdCBvbGQwID0gc2VsZi5pMzJbMF07XG4gICAgICAgIGNvbnN0IHcgPSBbXTtcblxuICAgICAgICBhd2FpdCBzZWxmLl9kb0NhbGN1bGF0ZVdpdG5lc3MoaW5wdXQsIHNhbml0eUNoZWNrKTtcblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNlbGYuTlZhcnM7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgcFdpdG5lc3MgPSBzZWxmLmluc3RhbmNlLmV4cG9ydHMuZ2V0UFdpdG5lc3MoaSk7XG4gICAgICAgICAgICB3LnB1c2goc2VsZi5nZXRGcihwV2l0bmVzcykpO1xuICAgICAgICB9XG5cbiAgICAgICAgc2VsZi5pMzJbMF0gPSBvbGQwO1xuICAgICAgICByZXR1cm4gdztcbiAgICB9XG5cbiAgICBhc3luYyBjYWxjdWxhdGVCaW5XaXRuZXNzKGlucHV0LCBzYW5pdHlDaGVjaykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcblxuICAgICAgICBjb25zdCBvbGQwID0gc2VsZi5pMzJbMF07XG5cbiAgICAgICAgYXdhaXQgc2VsZi5fZG9DYWxjdWxhdGVXaXRuZXNzKGlucHV0LCBzYW5pdHlDaGVjayk7XG5cbiAgICAgICAgY29uc3QgcFdpdG5lc3NCdWZmZXIgPSBzZWxmLmluc3RhbmNlLmV4cG9ydHMuZ2V0V2l0bmVzc0J1ZmZlcigpO1xuXG4gICAgICAgIHNlbGYuaTMyWzBdID0gb2xkMDtcblxuICAgICAgICBjb25zdCBidWZmID0gc2VsZi5tZW1vcnkuYnVmZmVyLnNsaWNlKHBXaXRuZXNzQnVmZmVyLCBwV2l0bmVzc0J1ZmZlciArIChzZWxmLk5WYXJzICogc2VsZi5uNjQgKiA4KSk7XG4gICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShidWZmKTtcbiAgICB9XG5cbiAgICBhbGxvY0ludCgpIHtcbiAgICAgICAgY29uc3QgcCA9IHRoaXMuaTMyWzBdO1xuICAgICAgICB0aGlzLmkzMlswXSA9IHAgKyA4O1xuICAgICAgICByZXR1cm4gcDtcbiAgICB9XG5cbiAgICBhbGxvY0ZyKCkge1xuICAgICAgICBjb25zdCBwID0gdGhpcy5pMzJbMF07XG4gICAgICAgIHRoaXMuaTMyWzBdID0gcCArIHRoaXMubjMyICogNCArIDg7XG4gICAgICAgIHJldHVybiBwO1xuICAgIH1cblxuICAgIGdldEludChwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmkzMltwID4+IDJdO1xuICAgIH1cblxuICAgIHNldEludChwLCB2KSB7XG4gICAgICAgIHRoaXMuaTMyW3AgPj4gMl0gPSB2O1xuICAgIH1cblxuICAgIGdldEZyKHApIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGNvbnN0IGlkeCA9IChwID4+IDIpO1xuXG4gICAgICAgIGlmIChzZWxmLmkzMltpZHggKyAxXSAmIDB4ODAwMDAwMDApIHtcbiAgICAgICAgICAgIGNvbnN0IGFyciA9IG5ldyBBcnJheShzZWxmLm4zMik7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNlbGYubjMyOyBpKyspIHtcbiAgICAgICAgICAgICAgICBhcnJbc2VsZi5uMzIgLSAxIC0gaV0gPSBzZWxmLmkzMltpZHggKyAyICsgaV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByZXMgPSBzZWxmLkZyLmUoU2NhbGFyLmZyb21BcnJheShhcnIsIDB4MTAwMDAwMDAwKSk7XG4gICAgICAgICAgICBpZiAoc2VsZi5pMzJbaWR4ICsgMV0gJiAweDQwMDAwMDAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZyb21Nb250Z29tZXJ5KHJlcyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChzZWxmLmkzMltpZHhdICYgMHg4MDAwMDAwMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmLkZyLmUoc2VsZi5pMzJbaWR4XSAtIDB4MTAwMDAwMDAwKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGYuRnIuZShzZWxmLmkzMltpZHhdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGZyb21Nb250Z29tZXJ5KG4pIHtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLkZyLm11bChzZWxmLlJJbnYsIG4pO1xuICAgICAgICB9XG5cbiAgICB9XG5cblxuICAgIHNldEZyKHAsIHYpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICAgICAgdiA9IHNlbGYuRnIuZSh2KTtcblxuICAgICAgICBjb25zdCBtaW5TaG9ydCA9IHNlbGYuRnIubmVnKHNlbGYuRnIuZShcIjgwMDAwMDAwXCIsIDE2KSk7XG4gICAgICAgIGNvbnN0IG1heFNob3J0ID0gc2VsZi5Gci5lKFwiN0ZGRkZGRkZcIiwgMTYpO1xuXG4gICAgICAgIGlmICgoc2VsZi5Gci5nZXEodiwgbWluU2hvcnQpKVxuICAgICAgICAgICAgJiYgKHNlbGYuRnIubGVxKHYsIG1heFNob3J0KSkpIHtcbiAgICAgICAgICAgIGxldCBhO1xuICAgICAgICAgICAgaWYgKHNlbGYuRnIuZ2VxKHYsIHNlbGYuRnIuemVybykpIHtcbiAgICAgICAgICAgICAgICBhID0gU2NhbGFyLnRvTnVtYmVyKHYpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhID0gU2NhbGFyLnRvTnVtYmVyKHNlbGYuRnIuc3ViKHYsIG1pblNob3J0KSk7XG4gICAgICAgICAgICAgICAgYSA9IGEgLSAweDgwMDAwMDAwO1xuICAgICAgICAgICAgICAgIGEgPSAweDEwMDAwMDAwMCArIGE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLmkzMlsocCA+PiAyKV0gPSBhO1xuICAgICAgICAgICAgc2VsZi5pMzJbKHAgPj4gMikgKyAxXSA9IDA7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBzZWxmLmkzMlsocCA+PiAyKV0gPSAwO1xuICAgICAgICBzZWxmLmkzMlsocCA+PiAyKSArIDFdID0gMHg4MDAwMDAwMDtcbiAgICAgICAgY29uc3QgYXJyID0gU2NhbGFyLnRvQXJyYXkodiwgMHgxMDAwMDAwMDApO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNlbGYubjMyOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGlkeCA9IGFyci5sZW5ndGggLSAxIC0gaTtcblxuICAgICAgICAgICAgaWYgKGlkeCA+PSAwKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5pMzJbKHAgPj4gMikgKyAyICsgaV0gPSBhcnJbaWR4XTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2VsZi5pMzJbKHAgPj4gMikgKyAyICsgaV0gPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5jbGFzcyBXaXRuZXNzQ2FsY3VsYXRvckNpcmNvbTIge1xuICAgIGNvbnN0cnVjdG9yKGluc3RhbmNlLCBzYW5pdHlDaGVjaykge1xuICAgICAgICB0aGlzLmluc3RhbmNlID0gaW5zdGFuY2U7XG5cbiAgICAgICAgdGhpcy52ZXJzaW9uID0gdGhpcy5pbnN0YW5jZS5leHBvcnRzLmdldFZlcnNpb24oKTtcbiAgICAgICAgdGhpcy5uMzIgPSB0aGlzLmluc3RhbmNlLmV4cG9ydHMuZ2V0RmllbGROdW1MZW4zMigpO1xuXG4gICAgICAgIHRoaXMuaW5zdGFuY2UuZXhwb3J0cy5nZXRSYXdQcmltZSgpO1xuICAgICAgICBjb25zdCBhcnIgPSBuZXcgVWludDMyQXJyYXkodGhpcy5uMzIpO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubjMyOyBpKyspIHtcbiAgICAgICAgICAgIGFyclt0aGlzLm4zMiAtIDEgLSBpXSA9IHRoaXMuaW5zdGFuY2UuZXhwb3J0cy5yZWFkU2hhcmVkUldNZW1vcnkoaSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5wcmltZSA9IFNjYWxhci5mcm9tQXJyYXkoYXJyLCAweDEwMDAwMDAwMCk7XG5cbiAgICAgICAgdGhpcy53aXRuZXNzU2l6ZSA9IHRoaXMuaW5zdGFuY2UuZXhwb3J0cy5nZXRXaXRuZXNzU2l6ZSgpO1xuXG4gICAgICAgIHRoaXMuc2FuaXR5Q2hlY2sgPSBzYW5pdHlDaGVjaztcbiAgICB9XG5cbiAgICBjaXJjb21fdmVyc2lvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaW5zdGFuY2UuZXhwb3J0cy5nZXRWZXJzaW9uKCk7XG4gICAgfVxuXG4gICAgYXN5bmMgX2RvQ2FsY3VsYXRlV2l0bmVzcyhpbnB1dCwgc2FuaXR5Q2hlY2spIHtcbiAgICAgICAgLy9pbnB1dCBpcyBhc3N1bWVkIHRvIGJlIGEgbWFwIGZyb20gc2lnbmFscyB0byBhcnJheXMgb2YgYmlnaW50c1xuICAgICAgICB0aGlzLmluc3RhbmNlLmV4cG9ydHMuaW5pdCgodGhpcy5zYW5pdHlDaGVjayB8fCBzYW5pdHlDaGVjaykgPyAxIDogMCk7XG4gICAgICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhpbnB1dCk7XG4gICAgICAgIGxldCBpbnB1dF9jb3VudGVyID0gMDtcbiAgICAgICAga2V5cy5mb3JFYWNoKChrKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBoID0gZm52SGFzaChrKTtcbiAgICAgICAgICAgIGNvbnN0IGhNU0IgPSBwYXJzZUludChoLnNsaWNlKDAsIDgpLCAxNik7XG4gICAgICAgICAgICBjb25zdCBoTFNCID0gcGFyc2VJbnQoaC5zbGljZSg4LCAxNiksIDE2KTtcbiAgICAgICAgICAgIGNvbnN0IGZBcnIgPSBmbGF0QXJyYXkoaW5wdXRba10pO1xuICAgICAgICAgICAgLy8gU2xpZ2h0IGRldmlhdGlvbiBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9pZGVuMy9jaXJjb20vYmxvYi92Mi4xLjYvY29kZV9wcm9kdWNlcnMvc3JjL3dhc21fZWxlbWVudHMvY29tbW9uL3dpdG5lc3NfY2FsY3VsYXRvci5qc1xuICAgICAgICAgICAgLy8gYmVjYXVzZSBJIGRvbid0IGtub3cgd2hlbiB0aGlzIGV4cG9ydGVkIGZ1bmN0aW9uIHdhcyBhZGRlZFxuICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLmluc3RhbmNlLmV4cG9ydHMuZ2V0SW5wdXRTaWduYWxTaXplID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICBsZXQgc2lnbmFsU2l6ZSA9IHRoaXMuaW5zdGFuY2UuZXhwb3J0cy5nZXRJbnB1dFNpZ25hbFNpemUoaE1TQiwgaExTQik7XG4gICAgICAgICAgICAgICAgaWYgKHNpZ25hbFNpemUgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgU2lnbmFsICR7a30gbm90IGZvdW5kXFxuYCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChmQXJyLmxlbmd0aCA8IHNpZ25hbFNpemUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBOb3QgZW5vdWdoIHZhbHVlcyBmb3IgaW5wdXQgc2lnbmFsICR7a31cXG5gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGZBcnIubGVuZ3RoID4gc2lnbmFsU2l6ZSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRvbyBtYW55IHZhbHVlcyBmb3IgaW5wdXQgc2lnbmFsICR7a31cXG5gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZBcnIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBhcnJGciA9IHRvQXJyYXkzMihub3JtYWxpemUoZkFycltpXSwgdGhpcy5wcmltZSksIHRoaXMubjMyKTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHRoaXMubjMyOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnN0YW5jZS5leHBvcnRzLndyaXRlU2hhcmVkUldNZW1vcnkoaiwgYXJyRnJbdGhpcy5uMzIgLSAxIC0gal0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmluc3RhbmNlLmV4cG9ydHMuc2V0SW5wdXRTaWduYWwoaE1TQiwgaExTQiwgaSk7XG4gICAgICAgICAgICAgICAgICAgIGlucHV0X2NvdW50ZXIrKztcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coYEFmdGVyIGFkZGluZyBzaWduYWwgJHtpfSBvZiAke2t9YClcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVycik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoaW5wdXRfY291bnRlciA8IHRoaXMuaW5zdGFuY2UuZXhwb3J0cy5nZXRJbnB1dFNpemUoKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBOb3QgYWxsIGlucHV0cyBoYXZlIGJlZW4gc2V0LiBPbmx5ICR7aW5wdXRfY291bnRlcn0gb3V0IG9mICR7dGhpcy5pbnN0YW5jZS5leHBvcnRzLmdldElucHV0U2l6ZSgpfWApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMgY2FsY3VsYXRlV2l0bmVzcyhpbnB1dCwgc2FuaXR5Q2hlY2spIHtcbiAgICAgICAgY29uc3QgdyA9IFtdO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuX2RvQ2FsY3VsYXRlV2l0bmVzcyhpbnB1dCwgc2FuaXR5Q2hlY2spO1xuXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy53aXRuZXNzU2l6ZTsgaSsrKSB7XG4gICAgICAgICAgICB0aGlzLmluc3RhbmNlLmV4cG9ydHMuZ2V0V2l0bmVzcyhpKTtcbiAgICAgICAgICAgIGNvbnN0IGFyciA9IG5ldyBVaW50MzJBcnJheSh0aGlzLm4zMik7XG4gICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHRoaXMubjMyOyBqKyspIHtcbiAgICAgICAgICAgICAgICBhcnJbdGhpcy5uMzIgLSAxIC0gal0gPSB0aGlzLmluc3RhbmNlLmV4cG9ydHMucmVhZFNoYXJlZFJXTWVtb3J5KGopO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdy5wdXNoKFNjYWxhci5mcm9tQXJyYXkoYXJyLCAweDEwMDAwMDAwMCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHc7XG4gICAgfVxuXG4gICAgYXN5bmMgY2FsY3VsYXRlV1ROU0JpbihpbnB1dCwgc2FuaXR5Q2hlY2spIHtcbiAgICAgICAgY29uc3QgYnVmZjMyID0gbmV3IFVpbnQzMkFycmF5KHRoaXMud2l0bmVzc1NpemUgKiB0aGlzLm4zMiArIHRoaXMubjMyICsgMTEpO1xuICAgICAgICBjb25zdCBidWZmID0gbmV3IFVpbnQ4QXJyYXkoYnVmZjMyLmJ1ZmZlcik7XG4gICAgICAgIGF3YWl0IHRoaXMuX2RvQ2FsY3VsYXRlV2l0bmVzcyhpbnB1dCwgc2FuaXR5Q2hlY2spO1xuXG4gICAgICAgIC8vXCJ3dG5zXCJcbiAgICAgICAgYnVmZlswXSA9IFwid1wiLmNoYXJDb2RlQXQoMCk7XG4gICAgICAgIGJ1ZmZbMV0gPSBcInRcIi5jaGFyQ29kZUF0KDApO1xuICAgICAgICBidWZmWzJdID0gXCJuXCIuY2hhckNvZGVBdCgwKTtcbiAgICAgICAgYnVmZlszXSA9IFwic1wiLmNoYXJDb2RlQXQoMCk7XG5cbiAgICAgICAgLy92ZXJzaW9uIDJcbiAgICAgICAgYnVmZjMyWzFdID0gMjtcblxuICAgICAgICAvL251bWJlciBvZiBzZWN0aW9uczogMlxuICAgICAgICBidWZmMzJbMl0gPSAyO1xuXG4gICAgICAgIC8vaWQgc2VjdGlvbiAxXG4gICAgICAgIGJ1ZmYzMlszXSA9IDE7XG5cbiAgICAgICAgY29uc3QgbjggPSB0aGlzLm4zMiAqIDQ7XG4gICAgICAgIC8vaWQgc2VjdGlvbiAxIGxlbmd0aCBpbiA2NGJ5dGVzXG4gICAgICAgIGNvbnN0IGlkU2VjdGlvbjFsZW5ndGggPSA4ICsgbjg7XG4gICAgICAgIGNvbnN0IGlkU2VjdGlvbjFsZW5ndGhIZXggPSBpZFNlY3Rpb24xbGVuZ3RoLnRvU3RyaW5nKDE2KTtcbiAgICAgICAgYnVmZjMyWzRdID0gcGFyc2VJbnQoaWRTZWN0aW9uMWxlbmd0aEhleC5zbGljZSgwLCA4KSwgMTYpO1xuICAgICAgICBidWZmMzJbNV0gPSBwYXJzZUludChpZFNlY3Rpb24xbGVuZ3RoSGV4LnNsaWNlKDgsIDE2KSwgMTYpO1xuXG4gICAgICAgIC8vdGhpcy5uMzJcbiAgICAgICAgYnVmZjMyWzZdID0gbjg7XG5cbiAgICAgICAgLy9wcmltZSBudW1iZXJcbiAgICAgICAgdGhpcy5pbnN0YW5jZS5leHBvcnRzLmdldFJhd1ByaW1lKCk7XG5cbiAgICAgICAgbGV0IHBvcyA9IDc7XG4gICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGhpcy5uMzI7IGorKykge1xuICAgICAgICAgICAgYnVmZjMyW3BvcyArIGpdID0gdGhpcy5pbnN0YW5jZS5leHBvcnRzLnJlYWRTaGFyZWRSV01lbW9yeShqKTtcbiAgICAgICAgfVxuICAgICAgICBwb3MgKz0gdGhpcy5uMzI7XG5cbiAgICAgICAgLy8gd2l0bmVzcyBzaXplXG4gICAgICAgIGJ1ZmYzMltwb3NdID0gdGhpcy53aXRuZXNzU2l6ZTtcbiAgICAgICAgcG9zKys7XG5cbiAgICAgICAgLy9pZCBzZWN0aW9uIDJcbiAgICAgICAgYnVmZjMyW3Bvc10gPSAyO1xuICAgICAgICBwb3MrKztcblxuICAgICAgICAvLyBzZWN0aW9uIDIgbGVuZ3RoXG4gICAgICAgIGNvbnN0IGlkU2VjdGlvbjJsZW5ndGggPSBuOCAqIHRoaXMud2l0bmVzc1NpemU7XG4gICAgICAgIGNvbnN0IGlkU2VjdGlvbjJsZW5ndGhIZXggPSBpZFNlY3Rpb24ybGVuZ3RoLnRvU3RyaW5nKDE2KTtcbiAgICAgICAgYnVmZjMyW3Bvc10gPSBwYXJzZUludChpZFNlY3Rpb24ybGVuZ3RoSGV4LnNsaWNlKDAsIDgpLCAxNik7XG4gICAgICAgIGJ1ZmYzMltwb3MgKyAxXSA9IHBhcnNlSW50KGlkU2VjdGlvbjJsZW5ndGhIZXguc2xpY2UoOCwgMTYpLCAxNik7XG5cbiAgICAgICAgcG9zICs9IDI7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy53aXRuZXNzU2l6ZTsgaSsrKSB7XG4gICAgICAgICAgICB0aGlzLmluc3RhbmNlLmV4cG9ydHMuZ2V0V2l0bmVzcyhpKTtcbiAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGhpcy5uMzI7IGorKykge1xuICAgICAgICAgICAgICAgIGJ1ZmYzMltwb3MgKyBqXSA9IHRoaXMuaW5zdGFuY2UuZXhwb3J0cy5yZWFkU2hhcmVkUldNZW1vcnkoaik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwb3MgKz0gdGhpcy5uMzI7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYnVmZjtcbiAgICB9XG5cbn1cbiIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMTggMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya0pTLlxuXG4gICAgc25hcmtKUyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJrSlMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggc25hcmtKUy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbmltcG9ydCAqIGFzIGZhc3RGaWxlIGZyb20gXCJmYXN0ZmlsZVwiO1xuaW1wb3J0IHsgV2l0bmVzc0NhbGN1bGF0b3JCdWlsZGVyIH0gZnJvbSBcImNpcmNvbV9ydW50aW1lXCI7XG5pbXBvcnQgKiBhcyB3dG5zVXRpbHMgZnJvbSBcIi4vd3Ruc191dGlscy5qc1wiO1xuaW1wb3J0ICogYXMgYmluRmlsZVV0aWxzIGZyb20gXCJAaWRlbjMvYmluZmlsZXV0aWxzXCI7XG5pbXBvcnQgeyAgdXRpbHMgfSAgIGZyb20gXCJmZmphdmFzY3JpcHRcIjtcbmNvbnN0IHsgdW5zdHJpbmdpZnlCaWdJbnRzfSA9IHV0aWxzO1xuXG5leHBvcnQgZGVmYXVsdCBhc3luYyBmdW5jdGlvbiB3dG5zQ2FsY3VsYXRlKF9pbnB1dCwgd2FzbUZpbGVOYW1lLCB3dG5zRmlsZU5hbWUsIG9wdGlvbnMpIHtcbiAgICBjb25zdCBpbnB1dCA9IHVuc3RyaW5naWZ5QmlnSW50cyhfaW5wdXQpO1xuXG4gICAgY29uc3QgZmRXYXNtID0gYXdhaXQgZmFzdEZpbGUucmVhZEV4aXN0aW5nKHdhc21GaWxlTmFtZSk7XG4gICAgY29uc3Qgd2FzbSA9IGF3YWl0IGZkV2FzbS5yZWFkKGZkV2FzbS50b3RhbFNpemUpO1xuICAgIGF3YWl0IGZkV2FzbS5jbG9zZSgpO1xuXG4gICAgY29uc3Qgd2MgPSBhd2FpdCBXaXRuZXNzQ2FsY3VsYXRvckJ1aWxkZXIod2FzbSwgb3B0aW9ucyk7XG4gICAgaWYgKHdjLmNpcmNvbV92ZXJzaW9uKCkgPT09IDEpIHtcbiAgICAgICAgY29uc3QgdyA9IGF3YWl0IHdjLmNhbGN1bGF0ZUJpbldpdG5lc3MoaW5wdXQpO1xuXG4gICAgICAgIGNvbnN0IGZkV3RucyA9IGF3YWl0IGJpbkZpbGVVdGlscy5jcmVhdGVCaW5GaWxlKHd0bnNGaWxlTmFtZSwgXCJ3dG5zXCIsIDIsIDIpO1xuXG4gICAgICAgIGF3YWl0IHd0bnNVdGlscy53cml0ZUJpbihmZFd0bnMsIHcsIHdjLnByaW1lKTtcbiAgICAgICAgYXdhaXQgZmRXdG5zLmNsb3NlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgZmRXdG5zID0gYXdhaXQgZmFzdEZpbGUuY3JlYXRlT3ZlcnJpZGUod3Ruc0ZpbGVOYW1lKTtcblxuICAgICAgICBjb25zdCB3ID0gYXdhaXQgd2MuY2FsY3VsYXRlV1ROU0JpbihpbnB1dCk7XG5cbiAgICAgICAgYXdhaXQgZmRXdG5zLndyaXRlKHcpO1xuICAgICAgICBhd2FpdCBmZFd0bnMuY2xvc2UoKTtcbiAgICB9XG59XG4iLCIvKlxuICAgIENvcHlyaWdodCAyMDE4IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygc25hcmtKUy5cblxuICAgIHNuYXJrSlMgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gICAgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAgICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICAgIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICBzbmFya0pTIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHNuYXJrSlMuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG5pbXBvcnQgZ3JvdGgxNl9wcm92ZSBmcm9tIFwiLi9ncm90aDE2X3Byb3ZlLmpzXCI7XG5pbXBvcnQgd3Ruc19jYWxjdWxhdGUgZnJvbSBcIi4vd3Ruc19jYWxjdWxhdGUuanNcIjtcbmltcG9ydCB7dXRpbHN9IGZyb20gXCJmZmphdmFzY3JpcHRcIjtcbmNvbnN0IHt1bnN0cmluZ2lmeUJpZ0ludHN9ID0gdXRpbHM7XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uIGdyb3RoMTZGdWxsUHJvdmUoX2lucHV0LCB3YXNtRmlsZSwgemtleUZpbGVOYW1lLCBsb2dnZXIsIHd0bnNDYWxjT3B0aW9ucywgcHJvdmVyT3B0aW9ucykge1xuICAgIGNvbnN0IGlucHV0ID0gdW5zdHJpbmdpZnlCaWdJbnRzKF9pbnB1dCk7XG5cbiAgICBjb25zdCB3dG5zPSB7XG4gICAgICAgIHR5cGU6IFwibWVtXCJcbiAgICB9O1xuICAgIGF3YWl0IHd0bnNfY2FsY3VsYXRlKGlucHV0LCB3YXNtRmlsZSwgd3Rucywgd3Ruc0NhbGNPcHRpb25zKTtcbiAgICByZXR1cm4gYXdhaXQgZ3JvdGgxNl9wcm92ZSh6a2V5RmlsZU5hbWUsIHd0bnMsIGxvZ2dlciwgcHJvdmVyT3B0aW9ucyk7XG59XG4iLCIvKlxuICAgIENvcHlyaWdodCAyMDE4IDBraW1zIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygc25hcmtqcy5cblxuICAgIHNuYXJranMgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3JcbiAgICBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlXG4gICAgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pXG4gICAgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICBzbmFya2pzIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gICAgYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yXG4gICAgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYWxvbmcgd2l0aFxuICAgIHNuYXJranMuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG4vKiBJbXBsZW1lbnRhdGlvbiBvZiB0aGlzIHBhcGVyOiBodHRwczovL2VwcmludC5pYWNyLm9yZy8yMDE2LzI2MC5wZGYgKi9cbmltcG9ydCB7IFNjYWxhciB9IGZyb20gXCJmZmphdmFzY3JpcHRcIjtcbmltcG9ydCAqIGFzIGN1cnZlcyBmcm9tIFwiLi9jdXJ2ZXMuanNcIjtcbmltcG9ydCB7ICB1dGlscyB9ICAgZnJvbSBcImZmamF2YXNjcmlwdFwiO1xuY29uc3Qge3Vuc3RyaW5naWZ5QmlnSW50c30gPSB1dGlscztcblxuZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gZ3JvdGgxNlZlcmlmeShfdmtfdmVyaWZpZXIsIF9wdWJsaWNTaWduYWxzLCBfcHJvb2YsIGxvZ2dlcikge1xuLypcbiAgICBsZXQgY3B1YiA9IHZrX3ZlcmlmaWVyLklDWzBdO1xuICAgIGZvciAobGV0IHM9IDA7IHM8IHZrX3ZlcmlmaWVyLm5QdWJsaWM7IHMrKykge1xuICAgICAgICBjcHViICA9IEcxLmFkZCggY3B1YiwgRzEudGltZXNTY2FsYXIoIHZrX3ZlcmlmaWVyLklDW3MrMV0sIHB1YmxpY1NpZ25hbHNbc10pKTtcbiAgICB9XG4qL1xuXG4gICAgY29uc3QgdmtfdmVyaWZpZXIgPSB1bnN0cmluZ2lmeUJpZ0ludHMoX3ZrX3ZlcmlmaWVyKTtcbiAgICBjb25zdCBwcm9vZiA9IHVuc3RyaW5naWZ5QmlnSW50cyhfcHJvb2YpO1xuICAgIGNvbnN0IHB1YmxpY1NpZ25hbHMgPSB1bnN0cmluZ2lmeUJpZ0ludHMoX3B1YmxpY1NpZ25hbHMpO1xuXG4gICAgY29uc3QgY3VydmUgPSBhd2FpdCBjdXJ2ZXMuZ2V0Q3VydmVGcm9tTmFtZSh2a192ZXJpZmllci5jdXJ2ZSk7XG5cbiAgICBjb25zdCBJQzAgPSBjdXJ2ZS5HMS5mcm9tT2JqZWN0KHZrX3ZlcmlmaWVyLklDWzBdKTtcbiAgICBjb25zdCBJQyA9IG5ldyBVaW50OEFycmF5KGN1cnZlLkcxLkYubjgqMiAqIHB1YmxpY1NpZ25hbHMubGVuZ3RoKTtcbiAgICBjb25zdCB3ID0gbmV3IFVpbnQ4QXJyYXkoY3VydmUuRnIubjggKiBwdWJsaWNTaWduYWxzLmxlbmd0aCk7XG5cbiAgICBpZiAoIXB1YmxpY0lucHV0c0FyZVZhbGlkKGN1cnZlLCBwdWJsaWNTaWduYWxzKSkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJQdWJsaWMgaW5wdXRzIGFyZSBub3QgdmFsaWQuXCIpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZm9yIChsZXQgaT0wOyBpPHB1YmxpY1NpZ25hbHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgYnVmZlAgPSBjdXJ2ZS5HMS5mcm9tT2JqZWN0KHZrX3ZlcmlmaWVyLklDW2krMV0pO1xuICAgICAgICBJQy5zZXQoYnVmZlAsIGkqY3VydmUuRzEuRi5uOCoyKTtcbiAgICAgICAgU2NhbGFyLnRvUnByTEUodywgY3VydmUuRnIubjgqaSwgcHVibGljU2lnbmFsc1tpXSwgY3VydmUuRnIubjgpO1xuICAgIH1cblxuICAgIGxldCBjcHViID0gYXdhaXQgY3VydmUuRzEubXVsdGlFeHBBZmZpbmUoSUMsIHcpO1xuICAgIGNwdWIgPSBjdXJ2ZS5HMS5hZGQoY3B1YiwgSUMwKTtcblxuICAgIGNvbnN0IHBpX2EgPSBjdXJ2ZS5HMS5mcm9tT2JqZWN0KHByb29mLnBpX2EpO1xuICAgIGNvbnN0IHBpX2IgPSBjdXJ2ZS5HMi5mcm9tT2JqZWN0KHByb29mLnBpX2IpO1xuICAgIGNvbnN0IHBpX2MgPSBjdXJ2ZS5HMS5mcm9tT2JqZWN0KHByb29mLnBpX2MpO1xuXG4gICAgaWYgKCFpc1dlbGxDb25zdHJ1Y3RlZChjdXJ2ZSwge3BpX2EsIHBpX2IsIHBpX2N9KSkge1xuICAgICAgICBpZihsb2dnZXIpIGxvZ2dlci5lcnJvcihcIlByb29mIGNvbW1pdG1lbnRzIGFyZSBub3QgdmFsaWQuXCIpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgdmtfZ2FtbWFfMiA9IGN1cnZlLkcyLmZyb21PYmplY3QodmtfdmVyaWZpZXIudmtfZ2FtbWFfMik7XG4gICAgY29uc3QgdmtfZGVsdGFfMiA9IGN1cnZlLkcyLmZyb21PYmplY3QodmtfdmVyaWZpZXIudmtfZGVsdGFfMik7XG4gICAgY29uc3QgdmtfYWxwaGFfMSA9IGN1cnZlLkcxLmZyb21PYmplY3QodmtfdmVyaWZpZXIudmtfYWxwaGFfMSk7XG4gICAgY29uc3QgdmtfYmV0YV8yID0gY3VydmUuRzIuZnJvbU9iamVjdCh2a192ZXJpZmllci52a19iZXRhXzIpO1xuXG4gICAgY29uc3QgcmVzID0gYXdhaXQgY3VydmUucGFpcmluZ0VxKFxuICAgICAgICBjdXJ2ZS5HMS5uZWcocGlfYSkgLCBwaV9iLFxuICAgICAgICBjcHViICwgdmtfZ2FtbWFfMixcbiAgICAgICAgcGlfYyAsIHZrX2RlbHRhXzIsXG5cbiAgICAgICAgdmtfYWxwaGFfMSwgdmtfYmV0YV8yXG4gICAgKTtcblxuICAgIGlmICghIHJlcykge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJJbnZhbGlkIHByb29mXCIpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCJPSyFcIik7XG4gICAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIGlzV2VsbENvbnN0cnVjdGVkKGN1cnZlLCBwcm9vZikge1xuICAgIGNvbnN0IEcxID0gY3VydmUuRzE7XG4gICAgY29uc3QgRzIgPSBjdXJ2ZS5HMjtcblxuICAgIHJldHVybiBHMS5pc1ZhbGlkKHByb29mLnBpX2EpXG4gICAgICAgICYmIEcyLmlzVmFsaWQocHJvb2YucGlfYilcbiAgICAgICAgJiYgRzEuaXNWYWxpZChwcm9vZi5waV9jKTtcbn1cblxuZnVuY3Rpb24gY2hlY2tWYWx1ZUJlbG9uZ1RvRmllbGQoY3VydmUsIHZhbHVlKSB7XG4gICAgcmV0dXJuIFNjYWxhci5nZXEodmFsdWUsIDApICYmIFNjYWxhci5sdCh2YWx1ZSwgY3VydmUucik7XG59XG5cbmZ1bmN0aW9uIHB1YmxpY0lucHV0c0FyZVZhbGlkKGN1cnZlLCBwdWJsaWNJbnB1dHMpIHtcbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgcHVibGljSW5wdXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKCFjaGVja1ZhbHVlQmVsb25nVG9GaWVsZChjdXJ2ZSwgcHVibGljSW5wdXRzW2ldKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuIiwiLypcbiAgICBDb3B5cmlnaHQgMjAxOCAwS0lNUyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJrSlMuXG5cbiAgICBzbmFya0pTIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICAgIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gICAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAgICAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtKUyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVFxuICAgIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpY1xuICAgIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gICAgYWxvbmcgd2l0aCBzbmFya0pTLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cbmltcG9ydCB7ICB1dGlscyB9ICAgZnJvbSBcImZmamF2YXNjcmlwdFwiO1xuY29uc3QgeyB1bnN0cmluZ2lmeUJpZ0ludHN9ID0gdXRpbHM7XG5cbmZ1bmN0aW9uIHAyNTYobikge1xuICAgIGxldCBuc3RyID0gbi50b1N0cmluZygxNik7XG4gICAgd2hpbGUgKG5zdHIubGVuZ3RoIDwgNjQpIG5zdHIgPSBcIjBcIituc3RyO1xuICAgIG5zdHIgPSBgXCIweCR7bnN0cn1cImA7XG4gICAgcmV0dXJuIG5zdHI7XG59XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uIGdyb3RoMTZFeHBvcnRTb2xpZGl0eUNhbGxEYXRhKF9wcm9vZiwgX3B1Yikge1xuICAgIGNvbnN0IHByb29mID0gdW5zdHJpbmdpZnlCaWdJbnRzKF9wcm9vZik7XG4gICAgY29uc3QgcHViID0gdW5zdHJpbmdpZnlCaWdJbnRzKF9wdWIpO1xuXG4gICAgbGV0IGlucHV0cyA9IFwiXCI7XG4gICAgZm9yIChsZXQgaT0wOyBpPHB1Yi5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoaW5wdXRzICE9IFwiXCIpIGlucHV0cyA9IGlucHV0cyArIFwiLFwiO1xuICAgICAgICBpbnB1dHMgPSBpbnB1dHMgKyBwMjU2KHB1YltpXSk7XG4gICAgfVxuXG4gICAgbGV0IFM7XG4gICAgUz1gWyR7cDI1Nihwcm9vZi5waV9hWzBdKX0sICR7cDI1Nihwcm9vZi5waV9hWzFdKX1dLGAgK1xuICAgICAgICBgW1ske3AyNTYocHJvb2YucGlfYlswXVsxXSl9LCAke3AyNTYocHJvb2YucGlfYlswXVswXSl9XSxbJHtwMjU2KHByb29mLnBpX2JbMV1bMV0pfSwgJHtwMjU2KHByb29mLnBpX2JbMV1bMF0pfV1dLGAgK1xuICAgICAgICBgWyR7cDI1Nihwcm9vZi5waV9jWzBdKX0sICR7cDI1Nihwcm9vZi5waV9jWzFdKX1dLGAgK1xuICAgICAgICBgWyR7aW5wdXRzfV1gO1xuXG4gICAgcmV0dXJuIFM7XG59XG4iLCIvKlxuICAgIENvcHlyaWdodCAyMDE4IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygc25hcmtKUy5cblxuICAgIHNuYXJrSlMgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gICAgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAgICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICAgIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICBzbmFya0pTIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHNuYXJrSlMuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG5leHBvcnQge2RlZmF1bHQgYXMgZnVsbFByb3ZlfSBmcm9tIFwiLi9ncm90aDE2X2Z1bGxwcm92ZS5qc1wiO1xuZXhwb3J0IHtkZWZhdWx0IGFzIHByb3ZlfSBmcm9tIFwiLi9ncm90aDE2X3Byb3ZlLmpzXCI7XG5leHBvcnQge2RlZmF1bHQgYXMgdmVyaWZ5fSBmcm9tIFwiLi9ncm90aDE2X3ZlcmlmeS5qc1wiO1xuZXhwb3J0IHtkZWZhdWx0IGFzIGV4cG9ydFNvbGlkaXR5Q2FsbERhdGF9IGZyb20gXCIuL2dyb3RoMTZfZXhwb3J0c29saWRpdHljYWxsZGF0YS5qc1wiO1xuIiwiLypcbiAgICBDb3B5cmlnaHQgMjAxOCAwS0lNUyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJrSlMuXG5cbiAgICBzbmFya0pTIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICAgIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gICAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAgICAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtKUyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVFxuICAgIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpY1xuICAgIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gICAgYWxvbmcgd2l0aCBzbmFya0pTLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuaW1wb3J0IHsgYmxha2UyYiB9IGZyb20gXCJAbm9ibGUvaGFzaGVzL2JsYWtlMmJcIjtcblxuaW1wb3J0IHsgQ2hhQ2hhIH0gZnJvbSBcImZmamF2YXNjcmlwdFwiO1xuXG5leHBvcnQgZnVuY3Rpb24gaGFzaFRvRzIoY3VydmUsIGhhc2gpIHtcbiAgICBjb25zdCBoYXNoViA9IG5ldyBEYXRhVmlldyhoYXNoLmJ1ZmZlciwgaGFzaC5ieXRlT2Zmc2V0LCBoYXNoLmJ5dGVMZW5ndGgpO1xuICAgIGNvbnN0IHNlZWQgPSBbXTtcbiAgICBmb3IgKGxldCBpPTA7IGk8ODsgaSsrKSB7XG4gICAgICAgIHNlZWRbaV0gPSBoYXNoVi5nZXRVaW50MzIoaSo0KTtcbiAgICB9XG5cbiAgICBjb25zdCBybmcgPSBuZXcgQ2hhQ2hhKHNlZWQpO1xuXG4gICAgY29uc3QgZzJfc3AgPSBjdXJ2ZS5HMi5mcm9tUm5nKHJuZyk7XG5cbiAgICByZXR1cm4gZzJfc3A7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRHMnNwKGN1cnZlLCBwZXJzaW5hbGl6YXRpb24sIGNoYWxsZW5nZSwgZzFzLCBnMXN4KSB7XG5cbiAgICBjb25zdCBoID0gYmxha2UyYi5jcmVhdGUoeyBka0xlbjogNjQgfSk7XG4gICAgY29uc3QgYjEgPSBuZXcgVWludDhBcnJheShbcGVyc2luYWxpemF0aW9uXSk7XG4gICAgaC51cGRhdGUoYjEpO1xuICAgIGgudXBkYXRlKGNoYWxsZW5nZSk7XG4gICAgY29uc3QgYjMgPSBjdXJ2ZS5HMS50b1VuY29tcHJlc3NlZChnMXMpO1xuICAgIGgudXBkYXRlKCBiMyk7XG4gICAgY29uc3QgYjQgPSBjdXJ2ZS5HMS50b1VuY29tcHJlc3NlZChnMXN4KTtcbiAgICBoLnVwZGF0ZSggYjQpO1xuICAgIGNvbnN0IGhhc2ggPWguZGlnZXN0KCk7XG5cbiAgICByZXR1cm4gaGFzaFRvRzIoY3VydmUsIGhhc2gpO1xufVxuXG5mdW5jdGlvbiBjYWxjdWxhdGVQdWJLZXkoaywgY3VydmUsIHBlcnNvbmFsaXphdGlvbiwgY2hhbGxlbmdlSGFzaCwgcm5nICkge1xuICAgIGsuZzFfcyA9IGN1cnZlLkcxLnRvQWZmaW5lKGN1cnZlLkcxLmZyb21Sbmcocm5nKSk7XG4gICAgay5nMV9zeCA9IGN1cnZlLkcxLnRvQWZmaW5lKGN1cnZlLkcxLnRpbWVzRnIoay5nMV9zLCBrLnBydktleSkpO1xuICAgIGsuZzJfc3AgPSBjdXJ2ZS5HMi50b0FmZmluZShnZXRHMnNwKGN1cnZlLCBwZXJzb25hbGl6YXRpb24sIGNoYWxsZW5nZUhhc2gsIGsuZzFfcywgay5nMV9zeCkpO1xuICAgIGsuZzJfc3B4ID0gY3VydmUuRzIudG9BZmZpbmUoY3VydmUuRzIudGltZXNGcihrLmcyX3NwLCBrLnBydktleSkpO1xuICAgIHJldHVybiBrO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUFRhdUtleShjdXJ2ZSwgY2hhbGxlbmdlSGFzaCwgcm5nKSB7XG4gICAgY29uc3Qga2V5ID0ge1xuICAgICAgICB0YXU6IHt9LFxuICAgICAgICBhbHBoYToge30sXG4gICAgICAgIGJldGE6IHt9XG4gICAgfTtcbiAgICBrZXkudGF1LnBydktleSA9IGN1cnZlLkZyLmZyb21Sbmcocm5nKTtcbiAgICBrZXkuYWxwaGEucHJ2S2V5ID0gY3VydmUuRnIuZnJvbVJuZyhybmcpO1xuICAgIGtleS5iZXRhLnBydktleSA9IGN1cnZlLkZyLmZyb21Sbmcocm5nKTtcbiAgICBjYWxjdWxhdGVQdWJLZXkoa2V5LnRhdSwgY3VydmUsIDAsIGNoYWxsZW5nZUhhc2gsIHJuZyk7XG4gICAgY2FsY3VsYXRlUHViS2V5KGtleS5hbHBoYSwgY3VydmUsIDEsIGNoYWxsZW5nZUhhc2gsIHJuZyk7XG4gICAgY2FsY3VsYXRlUHViS2V5KGtleS5iZXRhLCBjdXJ2ZSwgMiwgY2hhbGxlbmdlSGFzaCwgcm5nKTtcbiAgICByZXR1cm4ga2V5O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlRGVsdGFLZXkoY3VydmUsIHRyYW5zY3JpcHQsIHJuZykge1xuICAgIGNvbnN0IGRlbHRhID0ge307XG4gICAgZGVsdGEucHJ2S2V5ID0gY3VydmUuRnIuZnJvbVJuZyhybmcpO1xuICAgIGRlbHRhLmcxX3MgPSBjdXJ2ZS5HMS50b0FmZmluZShjdXJ2ZS5HMS5mcm9tUm5nKHJuZykpO1xuICAgIGRlbHRhLmcxX3N4ID0gY3VydmUuRzEudG9BZmZpbmUoY3VydmUuRzEudGltZXNTY2FsYXIoZGVsdGEuZzFfcywgZGVsdGEucHJ2S2V5KSk7XG4gICAgZGVsdGEuZzJfc3AgPSBoYXNoVG9HMihjdXJ2ZSwgdHJhbnNjcmlwdCk7XG4gICAgZGVsdGEuZzJfc3B4ID0gY3VydmUuRzIudG9BZmZpbmUoY3VydmUuRzIudGltZXNTY2FsYXIoZGVsdGEuZzJfc3AsIGRlbHRhLnBydktleSkpO1xuICAgIHJldHVybiBkZWx0YTtcbn1cbiIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMTggMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya0pTLlxuXG4gICAgc25hcmtKUyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJrSlMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggc25hcmtKUy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbmltcG9ydCB7IFNjYWxhciB9IGZyb20gXCJmZmphdmFzY3JpcHRcIjtcbmltcG9ydCB7IGJsYWtlMmIgfSBmcm9tIFwiQG5vYmxlL2hhc2hlcy9ibGFrZTJiXCI7XG5pbXBvcnQgKiBhcyBrZXlQYWlyIGZyb20gXCIuL2tleXBhaXIuanNcIjtcbmltcG9ydCAqIGFzIG1pc2MgZnJvbSBcIi4vbWlzYy5qc1wiO1xuaW1wb3J0IHsgZ2V0Q3VydmVGcm9tUSB9IGZyb20gXCIuL2N1cnZlcy5qc1wiO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd3JpdGVQVGF1SGVhZGVyKGZkLCBjdXJ2ZSwgcG93ZXIsIGNlcmVtb255UG93ZXIpIHtcbiAgICAvLyBXcml0ZSB0aGUgaGVhZGVyXG4gICAgLy8vLy8vLy8vLy9cblxuICAgIGlmICghIGNlcmVtb255UG93ZXIpIGNlcmVtb255UG93ZXIgPSBwb3dlcjtcbiAgICBhd2FpdCBmZC53cml0ZVVMRTMyKDEpOyAvLyBIZWFkZXIgdHlwZVxuICAgIGNvbnN0IHBIZWFkZXJTaXplID0gZmQucG9zO1xuICAgIGF3YWl0IGZkLndyaXRlVUxFNjQoMCk7IC8vIFRlbXBvcmFsbHkgc2V0IHRvIDAgbGVuZ3RoXG5cbiAgICBhd2FpdCBmZC53cml0ZVVMRTMyKGN1cnZlLkYxLm42NCo4KTtcblxuICAgIGNvbnN0IGJ1ZmYgPSBuZXcgVWludDhBcnJheShjdXJ2ZS5GMS5uOCk7XG4gICAgU2NhbGFyLnRvUnByTEUoYnVmZiwgMCwgY3VydmUucSwgY3VydmUuRjEubjgpO1xuICAgIGF3YWl0IGZkLndyaXRlKGJ1ZmYpO1xuICAgIGF3YWl0IGZkLndyaXRlVUxFMzIocG93ZXIpOyAgICAgICAgICAgICAgICAgICAgLy8gcG93ZXJcbiAgICBhd2FpdCBmZC53cml0ZVVMRTMyKGNlcmVtb255UG93ZXIpOyAgICAgICAgICAgICAgIC8vIHBvd2VyXG5cbiAgICBjb25zdCBoZWFkZXJTaXplID0gZmQucG9zIC0gcEhlYWRlclNpemUgLSA4O1xuXG4gICAgY29uc3Qgb2xkUG9zID0gZmQucG9zO1xuXG4gICAgYXdhaXQgZmQud3JpdGVVTEU2NChoZWFkZXJTaXplLCBwSGVhZGVyU2l6ZSk7XG5cbiAgICBmZC5wb3MgPSBvbGRQb3M7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWFkUFRhdUhlYWRlcihmZCwgc2VjdGlvbnMpIHtcbiAgICBpZiAoIXNlY3Rpb25zWzFdKSAgdGhyb3cgbmV3IEVycm9yKGZkLmZpbGVOYW1lICsgXCI6IEZpbGUgaGFzIG5vICBoZWFkZXJcIik7XG4gICAgaWYgKHNlY3Rpb25zWzFdLmxlbmd0aD4xKSB0aHJvdyBuZXcgRXJyb3IoZmQuZmlsZU5hbWUgK1wiOiBGaWxlIGhhcyBtb3JlIHRoYW4gb25lIGhlYWRlclwiKTtcblxuICAgIGZkLnBvcyA9IHNlY3Rpb25zWzFdWzBdLnA7XG4gICAgY29uc3QgbjggPSBhd2FpdCBmZC5yZWFkVUxFMzIoKTtcbiAgICBjb25zdCBidWZmID0gYXdhaXQgZmQucmVhZChuOCk7XG4gICAgY29uc3QgcSA9IFNjYWxhci5mcm9tUnByTEUoYnVmZik7XG5cbiAgICBjb25zdCBjdXJ2ZSA9IGF3YWl0IGdldEN1cnZlRnJvbVEocSk7XG5cbiAgICBpZiAoY3VydmUuRjEubjY0KjggIT0gbjgpIHRocm93IG5ldyBFcnJvcihmZC5maWxlTmFtZSArXCI6IEludmFsaWQgc2l6ZVwiKTtcblxuICAgIGNvbnN0IHBvd2VyID0gYXdhaXQgZmQucmVhZFVMRTMyKCk7XG4gICAgY29uc3QgY2VyZW1vbnlQb3dlciA9IGF3YWl0IGZkLnJlYWRVTEUzMigpO1xuXG4gICAgaWYgKGZkLnBvcy1zZWN0aW9uc1sxXVswXS5wICE9IHNlY3Rpb25zWzFdWzBdLnNpemUpIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgUFRhdSBoZWFkZXIgc2l6ZVwiKTtcblxuICAgIHJldHVybiB7Y3VydmUsIHBvd2VyLCBjZXJlbW9ueVBvd2VyfTtcbn1cblxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZFB0YXVQdWJLZXkoZmQsIGN1cnZlLCBtb250Z29tZXJ5KSB7XG5cbiAgICBjb25zdCBidWZmID0gYXdhaXQgZmQucmVhZChjdXJ2ZS5GMS5uOCoyKjYgKyBjdXJ2ZS5GMi5uOCoyKjMpO1xuXG4gICAgcmV0dXJuIGZyb21QdGF1UHViS2V5UnByKGJ1ZmYsIDAsIGN1cnZlLCBtb250Z29tZXJ5KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZyb21QdGF1UHViS2V5UnByKGJ1ZmYsIHBvcywgY3VydmUsIG1vbnRnb21lcnkpIHtcblxuICAgIGNvbnN0IGtleSA9IHtcbiAgICAgICAgdGF1OiB7fSxcbiAgICAgICAgYWxwaGE6IHt9LFxuICAgICAgICBiZXRhOiB7fVxuICAgIH07XG5cbiAgICBrZXkudGF1LmcxX3MgPSByZWFkRzEoKTtcbiAgICBrZXkudGF1LmcxX3N4ID0gcmVhZEcxKCk7XG4gICAga2V5LmFscGhhLmcxX3MgPSByZWFkRzEoKTtcbiAgICBrZXkuYWxwaGEuZzFfc3ggPSByZWFkRzEoKTtcbiAgICBrZXkuYmV0YS5nMV9zID0gcmVhZEcxKCk7XG4gICAga2V5LmJldGEuZzFfc3ggPSByZWFkRzEoKTtcbiAgICBrZXkudGF1LmcyX3NweCA9IHJlYWRHMigpO1xuICAgIGtleS5hbHBoYS5nMl9zcHggPSByZWFkRzIoKTtcbiAgICBrZXkuYmV0YS5nMl9zcHggPSByZWFkRzIoKTtcblxuICAgIHJldHVybiBrZXk7XG5cbiAgICBmdW5jdGlvbiByZWFkRzEoKSB7XG4gICAgICAgIGxldCBwO1xuICAgICAgICBpZiAobW9udGdvbWVyeSkge1xuICAgICAgICAgICAgcCA9IGN1cnZlLkcxLmZyb21ScHJMRU0oIGJ1ZmYsIHBvcyApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcCA9IGN1cnZlLkcxLmZyb21ScHJVbmNvbXByZXNzZWQoIGJ1ZmYsIHBvcyApO1xuICAgICAgICB9XG4gICAgICAgIHBvcyArPSBjdXJ2ZS5HMS5GLm44KjI7XG4gICAgICAgIHJldHVybiBwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlYWRHMigpIHtcbiAgICAgICAgbGV0IHA7XG4gICAgICAgIGlmIChtb250Z29tZXJ5KSB7XG4gICAgICAgICAgICBwID0gY3VydmUuRzIuZnJvbVJwckxFTSggYnVmZiwgcG9zICk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwID0gY3VydmUuRzIuZnJvbVJwclVuY29tcHJlc3NlZCggYnVmZiwgcG9zICk7XG4gICAgICAgIH1cbiAgICAgICAgcG9zICs9IGN1cnZlLkcyLkYubjgqMjtcbiAgICAgICAgcmV0dXJuIHA7XG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdG9QdGF1UHViS2V5UnByKGJ1ZmYsIHBvcywgY3VydmUsIGtleSwgbW9udGdvbWVyeSkge1xuXG4gICAgd3JpdGVHMShrZXkudGF1LmcxX3MpO1xuICAgIHdyaXRlRzEoa2V5LnRhdS5nMV9zeCk7XG4gICAgd3JpdGVHMShrZXkuYWxwaGEuZzFfcyk7XG4gICAgd3JpdGVHMShrZXkuYWxwaGEuZzFfc3gpO1xuICAgIHdyaXRlRzEoa2V5LmJldGEuZzFfcyk7XG4gICAgd3JpdGVHMShrZXkuYmV0YS5nMV9zeCk7XG4gICAgd3JpdGVHMihrZXkudGF1LmcyX3NweCk7XG4gICAgd3JpdGVHMihrZXkuYWxwaGEuZzJfc3B4KTtcbiAgICB3cml0ZUcyKGtleS5iZXRhLmcyX3NweCk7XG5cbiAgICBhc3luYyBmdW5jdGlvbiB3cml0ZUcxKHApIHtcbiAgICAgICAgaWYgKG1vbnRnb21lcnkpIHtcbiAgICAgICAgICAgIGN1cnZlLkcxLnRvUnByTEVNKGJ1ZmYsIHBvcywgcCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjdXJ2ZS5HMS50b1JwclVuY29tcHJlc3NlZChidWZmLCBwb3MsIHApO1xuICAgICAgICB9XG4gICAgICAgIHBvcyArPSBjdXJ2ZS5GMS5uOCoyO1xuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHdyaXRlRzIocCkge1xuICAgICAgICBpZiAobW9udGdvbWVyeSkge1xuICAgICAgICAgICAgY3VydmUuRzIudG9ScHJMRU0oYnVmZiwgcG9zLCBwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGN1cnZlLkcyLnRvUnByVW5jb21wcmVzc2VkKGJ1ZmYsIHBvcywgcCk7XG4gICAgICAgIH1cbiAgICAgICAgcG9zICs9IGN1cnZlLkYyLm44KjI7XG4gICAgfVxuXG4gICAgcmV0dXJuIGJ1ZmY7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3cml0ZVB0YXVQdWJLZXkoZmQsIGN1cnZlLCBrZXksIG1vbnRnb21lcnkpIHtcbiAgICBjb25zdCBidWZmID0gbmV3IFVpbnQ4QXJyYXkoY3VydmUuRjEubjgqMio2ICsgY3VydmUuRjIubjgqMiozKTtcbiAgICB0b1B0YXVQdWJLZXlScHIoYnVmZiwgMCwgY3VydmUsIGtleSwgbW9udGdvbWVyeSk7XG4gICAgYXdhaXQgZmQud3JpdGUoYnVmZik7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlYWRDb250cmlidXRpb24oZmQsIGN1cnZlKSB7XG4gICAgY29uc3QgYyA9IHt9O1xuXG4gICAgYy50YXVHMSA9IGF3YWl0IHJlYWRHMSgpO1xuICAgIGMudGF1RzIgPSBhd2FpdCByZWFkRzIoKTtcbiAgICBjLmFscGhhRzEgPSBhd2FpdCByZWFkRzEoKTtcbiAgICBjLmJldGFHMSA9IGF3YWl0IHJlYWRHMSgpO1xuICAgIGMuYmV0YUcyID0gYXdhaXQgcmVhZEcyKCk7XG4gICAgYy5rZXkgPSBhd2FpdCByZWFkUHRhdVB1YktleShmZCwgY3VydmUsIHRydWUpO1xuICAgIGMucGFydGlhbEhhc2ggPSBhd2FpdCBmZC5yZWFkKDIxNik7XG4gICAgYy5uZXh0Q2hhbGxlbmdlID0gYXdhaXQgZmQucmVhZCg2NCk7XG4gICAgYy50eXBlID0gYXdhaXQgZmQucmVhZFVMRTMyKCk7XG5cbiAgICBjb25zdCBidWZmViAgPSBuZXcgVWludDhBcnJheShjdXJ2ZS5HMS5GLm44KjIqNitjdXJ2ZS5HMi5GLm44KjIqMyk7XG4gICAgdG9QdGF1UHViS2V5UnByKGJ1ZmZWLCAwLCBjdXJ2ZSwgYy5rZXksIGZhbHNlKTtcblxuICAgIGNvbnN0IHJlc3BvbnNlSGFzaGVyID0gIG1pc2MuZnJvbVBhcnRpYWxIYXNoKGMucGFydGlhbEhhc2gpO1xuICAgIHJlc3BvbnNlSGFzaGVyLnVwZGF0ZShidWZmVik7XG4gICAgYy5yZXNwb25zZUhhc2ggPSByZXNwb25zZUhhc2hlci5kaWdlc3QoKTtcblxuICAgIGNvbnN0IHBhcmFtTGVuZ3RoID0gYXdhaXQgZmQucmVhZFVMRTMyKCk7XG4gICAgY29uc3QgY3VyUG9zID0gZmQucG9zO1xuICAgIGxldCBsYXN0VHlwZSA9MDtcbiAgICB3aGlsZSAoZmQucG9zLWN1clBvcyA8IHBhcmFtTGVuZ3RoKSB7XG4gICAgICAgIGNvbnN0IGJ1ZmZUeXBlID0gYXdhaXQgcmVhZERWKDEpO1xuICAgICAgICBpZiAoYnVmZlR5cGVbMF08PSBsYXN0VHlwZSkgdGhyb3cgbmV3IEVycm9yKFwiUGFyYW1ldGVycyBpbiB0aGUgY29udHJpYnV0aW9uIG11c3QgYmUgc29ydGVkXCIpO1xuICAgICAgICBsYXN0VHlwZSA9IGJ1ZmZUeXBlWzBdO1xuICAgICAgICBpZiAoYnVmZlR5cGVbMF09PTEpIHsgICAgIC8vIE5hbWVcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmZMZW4gPSBhd2FpdCByZWFkRFYoMSk7XG4gICAgICAgICAgICBjb25zdCBidWZmU3RyID0gYXdhaXQgcmVhZERWKGJ1ZmZMZW5bMF0pO1xuICAgICAgICAgICAgYy5uYW1lID0gbmV3IFRleHREZWNvZGVyKCkuZGVjb2RlKGJ1ZmZTdHIpO1xuICAgICAgICB9IGVsc2UgaWYgKGJ1ZmZUeXBlWzBdPT0yKSB7XG4gICAgICAgICAgICBjb25zdCBidWZmRXhwID0gYXdhaXQgcmVhZERWKDEpO1xuICAgICAgICAgICAgYy5udW1JdGVyYXRpb25zRXhwID0gYnVmZkV4cFswXTtcbiAgICAgICAgfSBlbHNlIGlmIChidWZmVHlwZVswXT09Mykge1xuICAgICAgICAgICAgY29uc3QgYnVmZkxlbiA9IGF3YWl0IHJlYWREVigxKTtcbiAgICAgICAgICAgIGMuYmVhY29uSGFzaCA9IGF3YWl0IHJlYWREVihidWZmTGVuWzBdKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlBhcmFtZXRlciBub3QgcmVjb2duaXplZFwiKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoZmQucG9zICE9IGN1clBvcyArIHBhcmFtTGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlBhcmFtZXRlcnMgZG8gbm90IG1hdGNoXCIpO1xuICAgIH1cblxuICAgIHJldHVybiBjO1xuXG4gICAgYXN5bmMgZnVuY3Rpb24gcmVhZEcxKCkge1xuICAgICAgICBjb25zdCBwQnVmZiA9IGF3YWl0IGZkLnJlYWQoY3VydmUuRzEuRi5uOCoyKTtcbiAgICAgICAgcmV0dXJuIGN1cnZlLkcxLmZyb21ScHJMRU0oIHBCdWZmICk7XG4gICAgfVxuXG4gICAgYXN5bmMgZnVuY3Rpb24gcmVhZEcyKCkge1xuICAgICAgICBjb25zdCBwQnVmZiA9IGF3YWl0IGZkLnJlYWQoY3VydmUuRzIuRi5uOCoyKTtcbiAgICAgICAgcmV0dXJuIGN1cnZlLkcyLmZyb21ScHJMRU0oIHBCdWZmICk7XG4gICAgfVxuXG4gICAgYXN5bmMgZnVuY3Rpb24gcmVhZERWKG4pIHtcbiAgICAgICAgY29uc3QgYiA9IGF3YWl0IGZkLnJlYWQobik7XG4gICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShiKTtcbiAgICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWFkQ29udHJpYnV0aW9ucyhmZCwgY3VydmUsIHNlY3Rpb25zKSB7XG4gICAgaWYgKCFzZWN0aW9uc1s3XSkgIHRocm93IG5ldyBFcnJvcihmZC5maWxlTmFtZSArIFwiOiBGaWxlIGhhcyBubyAgY29udHJpYnV0aW9uc1wiKTtcbiAgICBpZiAoc2VjdGlvbnNbN11bMF0ubGVuZ3RoPjEpIHRocm93IG5ldyBFcnJvcihmZC5maWxlTmFtZSArXCI6IEZpbGUgaGFzIG1vcmUgdGhhbiBvbmUgY29udHJpYnV0aW9ucyBzZWN0aW9uXCIpO1xuXG4gICAgZmQucG9zID0gc2VjdGlvbnNbN11bMF0ucDtcbiAgICBjb25zdCBuQ29udHJpYnV0aW9ucyA9IGF3YWl0IGZkLnJlYWRVTEUzMigpO1xuICAgIGNvbnN0IGNvbnRyaWJ1dGlvbnMgPSBbXTtcbiAgICBmb3IgKGxldCBpPTA7IGk8bkNvbnRyaWJ1dGlvbnM7IGkrKykge1xuICAgICAgICBjb25zdCBjID0gYXdhaXQgcmVhZENvbnRyaWJ1dGlvbihmZCwgY3VydmUpO1xuICAgICAgICBjLmlkID0gaSsxO1xuICAgICAgICBjb250cmlidXRpb25zLnB1c2goYyk7XG4gICAgfVxuXG4gICAgaWYgKGZkLnBvcy1zZWN0aW9uc1s3XVswXS5wICE9IHNlY3Rpb25zWzddWzBdLnNpemUpIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgY29udHJpYnV0aW9uIHNlY3Rpb24gc2l6ZVwiKTtcblxuICAgIHJldHVybiBjb250cmlidXRpb25zO1xufVxuXG5hc3luYyBmdW5jdGlvbiB3cml0ZUNvbnRyaWJ1dGlvbihmZCwgY3VydmUsIGNvbnRyaWJ1dGlvbikge1xuXG4gICAgY29uc3QgYnVmZkcxID0gbmV3IFVpbnQ4QXJyYXkoY3VydmUuRjEubjgqMik7XG4gICAgY29uc3QgYnVmZkcyID0gbmV3IFVpbnQ4QXJyYXkoY3VydmUuRjIubjgqMik7XG4gICAgYXdhaXQgd3JpdGVHMShjb250cmlidXRpb24udGF1RzEpO1xuICAgIGF3YWl0IHdyaXRlRzIoY29udHJpYnV0aW9uLnRhdUcyKTtcbiAgICBhd2FpdCB3cml0ZUcxKGNvbnRyaWJ1dGlvbi5hbHBoYUcxKTtcbiAgICBhd2FpdCB3cml0ZUcxKGNvbnRyaWJ1dGlvbi5iZXRhRzEpO1xuICAgIGF3YWl0IHdyaXRlRzIoY29udHJpYnV0aW9uLmJldGFHMik7XG4gICAgYXdhaXQgd3JpdGVQdGF1UHViS2V5KGZkLCBjdXJ2ZSwgY29udHJpYnV0aW9uLmtleSwgdHJ1ZSk7XG4gICAgYXdhaXQgZmQud3JpdGUoY29udHJpYnV0aW9uLnBhcnRpYWxIYXNoKTtcbiAgICBhd2FpdCBmZC53cml0ZShjb250cmlidXRpb24ubmV4dENoYWxsZW5nZSk7XG4gICAgYXdhaXQgZmQud3JpdGVVTEUzMihjb250cmlidXRpb24udHlwZSB8fCAwKTtcblxuICAgIGNvbnN0IHBhcmFtcyA9IFtdO1xuICAgIGlmIChjb250cmlidXRpb24ubmFtZSkge1xuICAgICAgICBwYXJhbXMucHVzaCgxKTsgICAgICAvLyBQYXJhbSBOYW1lXG4gICAgICAgIGNvbnN0IG5hbWVEYXRhID0gbmV3IFRleHRFbmNvZGVyKFwidXRmLThcIikuZW5jb2RlKGNvbnRyaWJ1dGlvbi5uYW1lLnN1YnN0cmluZygwLDY0KSk7XG4gICAgICAgIHBhcmFtcy5wdXNoKG5hbWVEYXRhLmJ5dGVMZW5ndGgpO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8bmFtZURhdGEuYnl0ZUxlbmd0aDsgaSsrKSBwYXJhbXMucHVzaChuYW1lRGF0YVtpXSk7XG4gICAgfVxuICAgIGlmIChjb250cmlidXRpb24udHlwZSA9PSAxKSB7XG4gICAgICAgIHBhcmFtcy5wdXNoKDIpOyAgICAgIC8vIFBhcmFtIG51bUl0ZXJhdGlvbnNFeHBcbiAgICAgICAgcGFyYW1zLnB1c2goY29udHJpYnV0aW9uLm51bUl0ZXJhdGlvbnNFeHApO1xuXG4gICAgICAgIHBhcmFtcy5wdXNoKDMpOyAgICAgIC8vIEJlYWNvbiBIYXNoXG4gICAgICAgIHBhcmFtcy5wdXNoKGNvbnRyaWJ1dGlvbi5iZWFjb25IYXNoLmJ5dGVMZW5ndGgpO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8Y29udHJpYnV0aW9uLmJlYWNvbkhhc2guYnl0ZUxlbmd0aDsgaSsrKSBwYXJhbXMucHVzaChjb250cmlidXRpb24uYmVhY29uSGFzaFtpXSk7XG4gICAgfVxuICAgIGlmIChwYXJhbXMubGVuZ3RoPjApIHtcbiAgICAgICAgY29uc3QgcGFyYW1zQnVmZiA9IG5ldyBVaW50OEFycmF5KHBhcmFtcyk7XG4gICAgICAgIGF3YWl0IGZkLndyaXRlVUxFMzIocGFyYW1zQnVmZi5ieXRlTGVuZ3RoKTtcbiAgICAgICAgYXdhaXQgZmQud3JpdGUocGFyYW1zQnVmZik7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYXdhaXQgZmQud3JpdGVVTEUzMigwKTtcbiAgICB9XG5cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHdyaXRlRzEocCkge1xuICAgICAgICBjdXJ2ZS5HMS50b1JwckxFTShidWZmRzEsIDAsIHApO1xuICAgICAgICBhd2FpdCBmZC53cml0ZShidWZmRzEpO1xuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHdyaXRlRzIocCkge1xuICAgICAgICBjdXJ2ZS5HMi50b1JwckxFTShidWZmRzIsIDAsIHApO1xuICAgICAgICBhd2FpdCBmZC53cml0ZShidWZmRzIpO1xuICAgIH1cblxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd3JpdGVDb250cmlidXRpb25zKGZkLCBjdXJ2ZSwgY29udHJpYnV0aW9ucykge1xuXG4gICAgYXdhaXQgZmQud3JpdGVVTEUzMig3KTsgLy8gSGVhZGVyIHR5cGVcbiAgICBjb25zdCBwQ29udHJpYnV0aW9uc1NpemUgPSBmZC5wb3M7XG4gICAgYXdhaXQgZmQud3JpdGVVTEU2NCgwKTsgLy8gVGVtcG9yYWxseSBzZXQgdG8gMCBsZW5ndGhcblxuICAgIGF3YWl0IGZkLndyaXRlVUxFMzIoY29udHJpYnV0aW9ucy5sZW5ndGgpO1xuICAgIGZvciAobGV0IGk9MDsgaTwgY29udHJpYnV0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICBhd2FpdCB3cml0ZUNvbnRyaWJ1dGlvbihmZCwgY3VydmUsIGNvbnRyaWJ1dGlvbnNbaV0pO1xuICAgIH1cbiAgICBjb25zdCBjb250cmlidXRpb25zU2l6ZSA9IGZkLnBvcyAtIHBDb250cmlidXRpb25zU2l6ZSAtIDg7XG5cbiAgICBjb25zdCBvbGRQb3MgPSBmZC5wb3M7XG5cbiAgICBhd2FpdCBmZC53cml0ZVVMRTY0KGNvbnRyaWJ1dGlvbnNTaXplLCBwQ29udHJpYnV0aW9uc1NpemUpO1xuICAgIGZkLnBvcyA9IG9sZFBvcztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNhbGN1bGF0ZUZpcnN0Q2hhbGxlbmdlSGFzaChjdXJ2ZSwgcG93ZXIsIGxvZ2dlcikge1xuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIkNhbGN1bGF0aW5nIEZpcnN0IENoYWxsZW5nZSBIYXNoXCIpO1xuXG4gICAgY29uc3QgaGFzaGVyID0gYmxha2UyYi5jcmVhdGUoeyBka0xlbjogNjQgfSk7XG5cbiAgICBjb25zdCB2RzEgPSBuZXcgVWludDhBcnJheShjdXJ2ZS5HMS5GLm44KjIpO1xuICAgIGNvbnN0IHZHMiA9IG5ldyBVaW50OEFycmF5KGN1cnZlLkcyLkYubjgqMik7XG4gICAgY3VydmUuRzEudG9ScHJVbmNvbXByZXNzZWQodkcxLCAwLCBjdXJ2ZS5HMS5nKTtcbiAgICBjdXJ2ZS5HMi50b1JwclVuY29tcHJlc3NlZCh2RzIsIDAsIGN1cnZlLkcyLmcpO1xuXG4gICAgaGFzaGVyLnVwZGF0ZShibGFrZTJiLmNyZWF0ZSh7IGRrTGVuOiA2NCB9KS5kaWdlc3QoKSk7XG5cbiAgICBsZXQgbjtcblxuICAgIG49KDIgKiogcG93ZXIpKjIgLTE7XG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKFwiQ2FsY3VsYXRlIEluaXRpYWwgSGFzaDogdGF1RzFcIik7XG4gICAgaGFzaEJsb2NrKHZHMSwgbik7XG4gICAgbj0gMiAqKiBwb3dlcjtcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCJDYWxjdWxhdGUgSW5pdGlhbCBIYXNoOiB0YXVHMlwiKTtcbiAgICBoYXNoQmxvY2sodkcyLCBuKTtcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCJDYWxjdWxhdGUgSW5pdGlhbCBIYXNoOiBhbHBoYVRhdUcxXCIpO1xuICAgIGhhc2hCbG9jayh2RzEsIG4pO1xuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIkNhbGN1bGF0ZSBJbml0aWFsIEhhc2g6IGJldGFUYXVHMVwiKTtcbiAgICBoYXNoQmxvY2sodkcxLCBuKTtcbiAgICBoYXNoZXIudXBkYXRlKHZHMik7XG5cbiAgICByZXR1cm4gaGFzaGVyLmRpZ2VzdCgpO1xuXG4gICAgZnVuY3Rpb24gaGFzaEJsb2NrKGJ1ZmYsIG4pIHtcbiAgICAgICAgLy8gdGhpcyBibG9jayBzaXplIGlzIGEgZ29vZCBjb21wcm9taXNlIGJldHdlZW4gc3BlZWQgYW5kIHRoZSBtYXhpbXVtXG4gICAgICAgIC8vIGlucHV0IHNpemUgb2YgdGhlIEJsYWtlMmIgdXBkYXRlIG1ldGhvZCAoNjUsNTM1LDcyMCBieXRlcykuXG4gICAgICAgIGNvbnN0IGJsb2NrU2l6ZSA9IDM0MTAwMDtcbiAgICAgICAgY29uc3QgbkJsb2NrcyA9IE1hdGguZmxvb3IobiAvIGJsb2NrU2l6ZSk7XG4gICAgICAgIGNvbnN0IHJlbSA9IG4gJSBibG9ja1NpemU7XG4gICAgICAgIGNvbnN0IGJpZ0J1ZmYgPSBuZXcgVWludDhBcnJheShibG9ja1NpemUgKiBidWZmLmJ5dGVMZW5ndGgpO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8YmxvY2tTaXplOyBpKyspIHtcbiAgICAgICAgICAgIGJpZ0J1ZmYuc2V0KGJ1ZmYsIGkqYnVmZi5ieXRlTGVuZ3RoKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGxldCBpPTA7IGk8bkJsb2NrczsgaSsrKSB7XG4gICAgICAgICAgICBoYXNoZXIudXBkYXRlKGJpZ0J1ZmYpO1xuICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKFwiSW5pdGlhbCBoYXNoOiBcIiAraSpibG9ja1NpemUpO1xuICAgICAgICB9XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxyZW07IGkrKykge1xuICAgICAgICAgICAgaGFzaGVyLnVwZGF0ZShidWZmKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24ga2V5RnJvbUJlYWNvbihjdXJ2ZSwgY2hhbGxlbmdlSGFzaCwgYmVhY29uSGFzaCwgbnVtSXRlcmF0aW9uc0V4cCkge1xuXG4gICAgY29uc3Qgcm5nID0gYXdhaXQgbWlzYy5ybmdGcm9tQmVhY29uUGFyYW1zKGJlYWNvbkhhc2gsIG51bUl0ZXJhdGlvbnNFeHApO1xuXG4gICAgY29uc3Qga2V5ID0ga2V5UGFpci5jcmVhdGVQVGF1S2V5KGN1cnZlLCBjaGFsbGVuZ2VIYXNoLCBybmcpO1xuXG4gICAgcmV0dXJuIGtleTtcbn1cblxuIiwiLypcbiAgICBDb3B5cmlnaHQgMjAxOCAwS0lNUyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJrSlMuXG5cbiAgICBzbmFya0pTIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICAgIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gICAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAgICAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtKUyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVFxuICAgIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpY1xuICAgIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gICAgYWxvbmcgd2l0aCBzbmFya0pTLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuLypcbkhlYWRlcigxKVxuICAgIG44XG4gICAgcHJpbWVcbiAgICBwb3dlclxudGF1RzEoMilcbiAgICB7KDIgKiogcG93ZXIpKjItMX0gW1xuICAgICAgICBHMSwgdGF1KkcxLCB0YXVeMiAqIEcxLCAuLi4uXG4gICAgXVxudGF1RzIoMylcbiAgICB7MiAqKiBwb3dlcn1bXG4gICAgICAgIEcyLCB0YXUqRzIsIHRhdV4yICogRzIsIC4uLlxuICAgIF1cbmFscGhhVGF1RzEoNClcbiAgICB7MiAqKiBwb3dlcn1bXG4gICAgICAgIGFscGhhKkcxLCBhbHBoYSp0YXUqRzEsIGFscGhhKnRhdV4yKkcxLC4uLi5cbiAgICBdXG5iZXRhVGF1RzEoNSlcbiAgICB7MiAqKiBwb3dlcn0gW11cbiAgICAgICAgYmV0YSpHMSwgYmV0YSp0YXUqRzEsIGJldGEqdGF1XjIqRzEsIC4uLi5cbiAgICBdXG5iZXRhRzIoNilcbiAgICB7MX1bXG4gICAgICAgIGJldGEqRzJcbiAgICBdXG5jb250cmlidXRpb25zKDcpXG4gICAgTkNvbnRyaWJ1dGlvbnNcbiAgICB7TkNvbnRyaWJ1dGlvbnN9W1xuICAgICAgICB0YXUqRzFcbiAgICAgICAgdGF1KkcyXG4gICAgICAgIGFscGhhKkcxXG4gICAgICAgIGJldGEqRzFcbiAgICAgICAgYmV0YSpHMlxuICAgICAgICBwdWJLZXlcbiAgICAgICAgICAgIHRhdV9nMXNcbiAgICAgICAgICAgIHRhdV9nMXN4XG4gICAgICAgICAgICB0YXVfZzJzcHhcbiAgICAgICAgICAgIGFscGhhX2cxc1xuICAgICAgICAgICAgYWxwaGFfZzFzeFxuICAgICAgICAgICAgYWxwaGFfZzFzcHhcbiAgICAgICAgICAgIGJldGFfZzFzXG4gICAgICAgICAgICBiZXRhX2cxc3hcbiAgICAgICAgICAgIGJldGFfZzFzcHhcbiAgICAgICAgcGFydGlhbEhhc2ggKDIxNiBieXRlcykgU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9tYWZpbnRvc2gvYmxha2UyYi13YXNtL2Jsb2IvMjNiZWUwNjk0NTgwNjMwOTk3N2FmODAyYmMzNzQ3Mjc1NDI2MTdjNy9ibGFrZTJiLndhdCNMOVxuICAgICAgICBoYXNoTmV3Q2hhbGxlbmdlXG4gICAgXVxuICovXG5cbmltcG9ydCAqIGFzIHB0YXVVdGlscyBmcm9tIFwiLi9wb3dlcnNvZnRhdV91dGlscy5qc1wiO1xuaW1wb3J0ICogYXMgYmluRmlsZVV0aWxzIGZyb20gXCJAaWRlbjMvYmluZmlsZXV0aWxzXCI7XG5pbXBvcnQgeyBibGFrZTJiIH0gZnJvbSBcIkBub2JsZS9oYXNoZXMvYmxha2UyYlwiO1xuaW1wb3J0ICogYXMgbWlzYyBmcm9tIFwiLi9taXNjLmpzXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uIG5ld0FjY3VtdWxhdG9yKGN1cnZlLCBwb3dlciwgZmlsZU5hbWUsIGxvZ2dlcikge1xuXG4gICAgY29uc3QgZmQgPSBhd2FpdCBiaW5GaWxlVXRpbHMuY3JlYXRlQmluRmlsZShmaWxlTmFtZSwgXCJwdGF1XCIsIDEsIDcpO1xuXG4gICAgYXdhaXQgcHRhdVV0aWxzLndyaXRlUFRhdUhlYWRlcihmZCwgY3VydmUsIHBvd2VyLCAwKTtcblxuICAgIGNvbnN0IGJ1ZmZHMSA9IGN1cnZlLkcxLm9uZUFmZmluZTtcbiAgICBjb25zdCBidWZmRzIgPSBjdXJ2ZS5HMi5vbmVBZmZpbmU7XG5cbiAgICAvLyBXcml0ZSB0YXVHMVxuICAgIC8vLy8vLy8vLy8vXG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLnN0YXJ0V3JpdGVTZWN0aW9uKGZkLCAyKTtcbiAgICBjb25zdCBuVGF1RzEgPSAoMiAqKiBwb3dlcikgKiAyIC0xO1xuICAgIGZvciAobGV0IGk9MDsgaTwgblRhdUcxOyBpKyspIHtcbiAgICAgICAgYXdhaXQgZmQud3JpdGUoYnVmZkcxKTtcbiAgICAgICAgaWYgKChsb2dnZXIpJiYoKGklMTAwMDAwKSA9PSAwKSYmaSkgbG9nZ2VyLmxvZyhcInRhdUcxOiBcIiArIGkpO1xuICAgIH1cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kV3JpdGVTZWN0aW9uKGZkKTtcblxuICAgIC8vIFdyaXRlIHRhdUcyXG4gICAgLy8vLy8vLy8vLy9cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuc3RhcnRXcml0ZVNlY3Rpb24oZmQsIDMpO1xuICAgIGNvbnN0IG5UYXVHMiA9ICgyICoqIHBvd2VyKTtcbiAgICBmb3IgKGxldCBpPTA7IGk8IG5UYXVHMjsgaSsrKSB7XG4gICAgICAgIGF3YWl0IGZkLndyaXRlKGJ1ZmZHMik7XG4gICAgICAgIGlmICgobG9nZ2VyKSYmKChpJTEwMDAwMCkgPT0gMCkmJmkpIGxvZ2dlci5sb2coXCJ0YXVHMjogXCIgKyBpKTtcbiAgICB9XG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmVuZFdyaXRlU2VjdGlvbihmZCk7XG5cbiAgICAvLyBXcml0ZSBhbHBoYVRhdUcxXG4gICAgLy8vLy8vLy8vLy9cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuc3RhcnRXcml0ZVNlY3Rpb24oZmQsIDQpO1xuICAgIGNvbnN0IG5BbGZhVGF1RzEgPSAoMiAqKiBwb3dlcik7XG4gICAgZm9yIChsZXQgaT0wOyBpPCBuQWxmYVRhdUcxOyBpKyspIHtcbiAgICAgICAgYXdhaXQgZmQud3JpdGUoYnVmZkcxKTtcbiAgICAgICAgaWYgKChsb2dnZXIpJiYoKGklMTAwMDAwKSA9PSAwKSYmaSkgbG9nZ2VyLmxvZyhcImFscGhhVGF1RzE6IFwiICsgaSk7XG4gICAgfVxuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5lbmRXcml0ZVNlY3Rpb24oZmQpO1xuXG4gICAgLy8gV3JpdGUgYmV0YVRhdUcxXG4gICAgLy8vLy8vLy8vLy9cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuc3RhcnRXcml0ZVNlY3Rpb24oZmQsIDUpO1xuICAgIGNvbnN0IG5CZXRhVGF1RzEgPSAoMiAqKiBwb3dlcik7XG4gICAgZm9yIChsZXQgaT0wOyBpPCBuQmV0YVRhdUcxOyBpKyspIHtcbiAgICAgICAgYXdhaXQgZmQud3JpdGUoYnVmZkcxKTtcbiAgICAgICAgaWYgKChsb2dnZXIpJiYoKGklMTAwMDAwKSA9PSAwKSYmaSkgbG9nZ2VyLmxvZyhcImJldGFUYXVHMTogXCIgKyBpKTtcbiAgICB9XG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmVuZFdyaXRlU2VjdGlvbihmZCk7XG5cbiAgICAvLyBXcml0ZSBiZXRhRzJcbiAgICAvLy8vLy8vLy8vL1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFdyaXRlU2VjdGlvbihmZCwgNik7XG4gICAgYXdhaXQgZmQud3JpdGUoYnVmZkcyKTtcbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kV3JpdGVTZWN0aW9uKGZkKTtcblxuICAgIC8vIENvbnRyaWJ1dGlvbnNcbiAgICAvLy8vLy8vLy8vL1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFdyaXRlU2VjdGlvbihmZCwgNyk7XG4gICAgYXdhaXQgZmQud3JpdGVVTEUzMigwKTsgLy8gMCBDb250cmlidXRpb25zXG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmVuZFdyaXRlU2VjdGlvbihmZCk7XG5cbiAgICBhd2FpdCBmZC5jbG9zZSgpO1xuXG4gICAgY29uc3QgZmlyc3RDaGFsbGVuZ2VIYXNoID0gcHRhdVV0aWxzLmNhbGN1bGF0ZUZpcnN0Q2hhbGxlbmdlSGFzaChjdXJ2ZSwgcG93ZXIsIGxvZ2dlcik7XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcobWlzYy5mb3JtYXRIYXNoKGJsYWtlMmIuY3JlYXRlKHsgZGtMZW46IDY0IH0pLmRpZ2VzdCgpLCBcIkJsYW5rIENvbnRyaWJ1dGlvbiBIYXNoOlwiKSk7XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhtaXNjLmZvcm1hdEhhc2goZmlyc3RDaGFsbGVuZ2VIYXNoLCBcIkZpcnN0IENvbnRyaWJ1dGlvbiBIYXNoOlwiKSk7XG5cbiAgICByZXR1cm4gZmlyc3RDaGFsbGVuZ2VIYXNoO1xuXG59XG4iLCIvLyBGb3JtYXQgb2YgdGhlIG91dHB1XG4vLyAgICAgSGFzaCBvZiB0aGUgbGFzdCBjb250cmlidXRpb24gIDY0Qnl0ZXNcbi8vICAgICAyXk4gKiAyIC0xICBUYXVHMSBwb2ludHMgKHVuY29tcHJlc3NlZClcbi8vICAgICAyXk4gIFRhdUcyIFBvaW50cyAodW5jb21wcmVzc2VkKVxuLy8gICAgIDJeTiAgQWxwaGFUYXVHMSBQb2ludHMgKHVuY29tcHJlc3NlZClcbi8vICAgICAyXk4gIEJldGFUYXVHMSBQb2ludHMgKHVuY29tcHJlc3NlZClcbi8vICAgICBCZXRhRzIgKHVuY29tcHJlc3NlZClcblxuaW1wb3J0ICogYXMgZmFzdEZpbGUgZnJvbSBcImZhc3RmaWxlXCI7XG5pbXBvcnQgeyBibGFrZTJiIH0gZnJvbSBcIkBub2JsZS9oYXNoZXMvYmxha2UyYlwiO1xuaW1wb3J0ICogYXMgdXRpbHMgZnJvbSBcIi4vcG93ZXJzb2Z0YXVfdXRpbHMuanNcIjtcbmltcG9ydCAqIGFzIGJpbkZpbGVVdGlscyBmcm9tIFwiQGlkZW4zL2JpbmZpbGV1dGlsc1wiO1xuaW1wb3J0ICogYXMgbWlzYyBmcm9tIFwiLi9taXNjLmpzXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uIGV4cG9ydENoYWxsZW5nZShwVGF1RmlsZW5hbWUsIGNoYWxsZW5nZUZpbGVuYW1lLCBsb2dnZXIpIHtcbiAgICBjb25zdCB7ZmQ6IGZkRnJvbSwgc2VjdGlvbnN9ID0gYXdhaXQgYmluRmlsZVV0aWxzLnJlYWRCaW5GaWxlKHBUYXVGaWxlbmFtZSwgXCJwdGF1XCIsIDEpO1xuXG4gICAgY29uc3Qge2N1cnZlLCBwb3dlcn0gPSBhd2FpdCB1dGlscy5yZWFkUFRhdUhlYWRlcihmZEZyb20sIHNlY3Rpb25zKTtcblxuICAgIGNvbnN0IGNvbnRyaWJ1dGlvbnMgPSBhd2FpdCB1dGlscy5yZWFkQ29udHJpYnV0aW9ucyhmZEZyb20sIGN1cnZlLCBzZWN0aW9ucyk7XG4gICAgbGV0IGxhc3RSZXNwb25zZUhhc2gsIGN1ckNoYWxsZW5nZUhhc2g7XG4gICAgaWYgKGNvbnRyaWJ1dGlvbnMubGVuZ3RoID09IDApIHtcbiAgICAgICAgbGFzdFJlc3BvbnNlSGFzaCA9IGJsYWtlMmIuY3JlYXRlKHsgZGtMZW46IDY0IH0pLmRpZ2VzdCgpO1xuICAgICAgICBjdXJDaGFsbGVuZ2VIYXNoID0gdXRpbHMuY2FsY3VsYXRlRmlyc3RDaGFsbGVuZ2VIYXNoKGN1cnZlLCBwb3dlcik7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbGFzdFJlc3BvbnNlSGFzaCA9IGNvbnRyaWJ1dGlvbnNbY29udHJpYnV0aW9ucy5sZW5ndGgtMV0ucmVzcG9uc2VIYXNoO1xuICAgICAgICBjdXJDaGFsbGVuZ2VIYXNoID0gY29udHJpYnV0aW9uc1tjb250cmlidXRpb25zLmxlbmd0aC0xXS5uZXh0Q2hhbGxlbmdlO1xuICAgIH1cblxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKG1pc2MuZm9ybWF0SGFzaChsYXN0UmVzcG9uc2VIYXNoLCBcIkxhc3QgUmVzcG9uc2UgSGFzaDogXCIpKTtcblxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKG1pc2MuZm9ybWF0SGFzaChjdXJDaGFsbGVuZ2VIYXNoLCBcIk5ldyBDaGFsbGVuZ2UgSGFzaDogXCIpKTtcblxuXG4gICAgY29uc3QgZmRUbyA9IGF3YWl0IGZhc3RGaWxlLmNyZWF0ZU92ZXJyaWRlKGNoYWxsZW5nZUZpbGVuYW1lKTtcblxuICAgIGNvbnN0IHRvSGFzaCA9IGJsYWtlMmIuY3JlYXRlKHsgZGtMZW46IDY0IH0pO1xuICAgIGF3YWl0IGZkVG8ud3JpdGUobGFzdFJlc3BvbnNlSGFzaCk7XG4gICAgdG9IYXNoLnVwZGF0ZShsYXN0UmVzcG9uc2VIYXNoKTtcblxuICAgIGF3YWl0IGV4cG9ydFNlY3Rpb24oMiwgXCJHMVwiLCAoMiAqKiBwb3dlcikgKiAyIC0xLCBcInRhdUcxXCIpO1xuICAgIGF3YWl0IGV4cG9ydFNlY3Rpb24oMywgXCJHMlwiLCAoMiAqKiBwb3dlcikgICAgICAgLCBcInRhdUcyXCIpO1xuICAgIGF3YWl0IGV4cG9ydFNlY3Rpb24oNCwgXCJHMVwiLCAoMiAqKiBwb3dlcikgICAgICAgLCBcImFscGhhVGF1RzFcIik7XG4gICAgYXdhaXQgZXhwb3J0U2VjdGlvbig1LCBcIkcxXCIsICgyICoqIHBvd2VyKSAgICAgICAsIFwiYmV0YVRhdUcxXCIpO1xuICAgIGF3YWl0IGV4cG9ydFNlY3Rpb24oNiwgXCJHMlwiLCAxICAgICAgICAgICAgICAgICAgLCBcImJldGFHMlwiKTtcblxuICAgIGF3YWl0IGZkRnJvbS5jbG9zZSgpO1xuICAgIGF3YWl0IGZkVG8uY2xvc2UoKTtcblxuICAgIGNvbnN0IGNhbGNDdXJDaGFsbGVuZ2VIYXNoID0gdG9IYXNoLmRpZ2VzdCgpO1xuXG4gICAgaWYgKCFtaXNjLmhhc2hJc0VxdWFsIChjdXJDaGFsbGVuZ2VIYXNoLCBjYWxjQ3VyQ2hhbGxlbmdlSGFzaCkpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8obWlzYy5mb3JtYXRIYXNoKGNhbGNDdXJDaGFsbGVuZ2VIYXNoLCBcIkNhbGMgQ3VycmV0IENoYWxsZW5nZSBIYXNoOiBcIikpO1xuXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihcIlBUYXUgZmlsZSBpcyBjb3JydXB0ZWQuIENhbGN1bGF0ZWQgbmV3IGNoYWxsZW5nZSBoYXNoIGRvZXMgbm90IG1hdGNoIHdpdGggdGhlIGVjbGFyZWQgb25lXCIpO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJQVGF1IGZpbGUgaXMgY29ycnVwdGVkLiBDYWxjdWxhdGVkIG5ldyBjaGFsbGVuZ2UgaGFzaCBkb2VzIG5vdCBtYXRjaCB3aXRoIHRoZSBlY2xhcmVkIG9uZVwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY3VyQ2hhbGxlbmdlSGFzaDtcblxuICAgIGFzeW5jIGZ1bmN0aW9uIGV4cG9ydFNlY3Rpb24oc2VjdGlvbklkLCBncm91cE5hbWUsIG5Qb2ludHMsIHNlY3Rpb25OYW1lKSB7XG4gICAgICAgIGNvbnN0IEcgPSBjdXJ2ZVtncm91cE5hbWVdO1xuICAgICAgICBjb25zdCBzRyA9IEcuRi5uOCoyO1xuICAgICAgICBjb25zdCBuUG9pbnRzQ2h1bmsgPSBNYXRoLmZsb29yKCgxPDwyNCkvc0cpO1xuXG4gICAgICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFJlYWRVbmlxdWVTZWN0aW9uKGZkRnJvbSwgc2VjdGlvbnMsIHNlY3Rpb25JZCk7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTwgblBvaW50czsgaSs9IG5Qb2ludHNDaHVuaykge1xuICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKGBFeHBvcnRpbmcgJHtzZWN0aW9uTmFtZX06ICR7aX0vJHtuUG9pbnRzfWApO1xuICAgICAgICAgICAgY29uc3QgbiA9IE1hdGgubWluKG5Qb2ludHMtaSwgblBvaW50c0NodW5rKTtcbiAgICAgICAgICAgIGxldCBidWZmO1xuICAgICAgICAgICAgYnVmZiA9IGF3YWl0IGZkRnJvbS5yZWFkKG4qc0cpO1xuICAgICAgICAgICAgYnVmZiA9IGF3YWl0IEcuYmF0Y2hMRU10b1UoYnVmZik7XG4gICAgICAgICAgICBhd2FpdCBmZFRvLndyaXRlKGJ1ZmYpO1xuICAgICAgICAgICAgdG9IYXNoLnVwZGF0ZShidWZmKTtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kUmVhZFNlY3Rpb24oZmRGcm9tKTtcbiAgICB9XG5cblxufVxuXG4iLCIvKlxuICAgIENvcHlyaWdodCAyMDE4IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygc25hcmtKUy5cblxuICAgIHNuYXJrSlMgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gICAgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAgICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICAgIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICBzbmFya0pTIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHNuYXJrSlMuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG5pbXBvcnQgKiBhcyBmYXN0RmlsZSBmcm9tIFwiZmFzdGZpbGVcIjtcbmltcG9ydCB7IGJsYWtlMmIgfSBmcm9tIFwiQG5vYmxlL2hhc2hlcy9ibGFrZTJiXCI7XG5pbXBvcnQgKiBhcyB1dGlscyBmcm9tIFwiLi9wb3dlcnNvZnRhdV91dGlscy5qc1wiO1xuaW1wb3J0ICogYXMgYmluRmlsZVV0aWxzIGZyb20gXCJAaWRlbjMvYmluZmlsZXV0aWxzXCI7XG5pbXBvcnQgKiBhcyBtaXNjIGZyb20gXCIuL21pc2MuanNcIjtcblxuZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gaW1wb3J0UmVzcG9uc2Uob2xkUHRhdUZpbGVuYW1lLCBjb250cmlidXRpb25GaWxlbmFtZSwgbmV3UFRhdUZpbGVuYW1lLCBuYW1lLCBpbXBvcnRQb2ludHMsIGxvZ2dlcikge1xuXG4gICAgY29uc3Qgbm9IYXNoID0gbmV3IFVpbnQ4QXJyYXkoNjQpO1xuICAgIGZvciAobGV0IGk9MDsgaTw2NDsgaSsrKSBub0hhc2hbaV0gPSAweEZGO1xuXG4gICAgY29uc3Qge2ZkOiBmZE9sZCwgc2VjdGlvbnN9ID0gYXdhaXQgYmluRmlsZVV0aWxzLnJlYWRCaW5GaWxlKG9sZFB0YXVGaWxlbmFtZSwgXCJwdGF1XCIsIDEpO1xuICAgIGNvbnN0IHtjdXJ2ZSwgcG93ZXJ9ID0gYXdhaXQgdXRpbHMucmVhZFBUYXVIZWFkZXIoZmRPbGQsIHNlY3Rpb25zKTtcbiAgICBjb25zdCBjb250cmlidXRpb25zID0gYXdhaXQgdXRpbHMucmVhZENvbnRyaWJ1dGlvbnMoZmRPbGQsIGN1cnZlLCBzZWN0aW9ucyk7XG4gICAgY29uc3QgY3VycmVudENvbnRyaWJ1dGlvbiA9IHt9O1xuXG4gICAgaWYgKG5hbWUpIGN1cnJlbnRDb250cmlidXRpb24ubmFtZSA9IG5hbWU7XG5cbiAgICBjb25zdCBzRzEgPSBjdXJ2ZS5GMS5uOCoyO1xuICAgIGNvbnN0IHNjRzEgPSBjdXJ2ZS5GMS5uODsgLy8gQ29tcHJlc3NlZCBzaXplXG4gICAgY29uc3Qgc0cyID0gY3VydmUuRjIubjgqMjtcbiAgICBjb25zdCBzY0cyID0gY3VydmUuRjIubjg7IC8vIENvbXByZXNzZWQgc2l6ZVxuXG4gICAgY29uc3QgZmRSZXNwb25zZSA9IGF3YWl0IGZhc3RGaWxlLnJlYWRFeGlzdGluZyhjb250cmlidXRpb25GaWxlbmFtZSk7XG5cbiAgICBpZiAgKGZkUmVzcG9uc2UudG90YWxTaXplICE9XG4gICAgICAgIDY0ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT2xkIEhhc2hcbiAgICAgICAgKCgyICoqIHBvd2VyKSoyLTEpKnNjRzEgK1xuICAgICAgICAoMiAqKiBwb3dlcikqc2NHMiArXG4gICAgICAgICgyICoqIHBvd2VyKSpzY0cxICtcbiAgICAgICAgKDIgKiogcG93ZXIpKnNjRzEgK1xuICAgICAgICBzY0cyICtcbiAgICAgICAgc0cxKjYgKyBzRzIqMylcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU2l6ZSBvZiB0aGUgY29udHJpYnV0aW9uIGlzIGludmFsaWRcIik7XG5cbiAgICBsZXQgbGFzdENoYWxsZW5nZUhhc2g7XG5cbiAgICBpZiAoY29udHJpYnV0aW9ucy5sZW5ndGg+MCkge1xuICAgICAgICBsYXN0Q2hhbGxlbmdlSGFzaCA9IGNvbnRyaWJ1dGlvbnNbY29udHJpYnV0aW9ucy5sZW5ndGgtMV0ubmV4dENoYWxsZW5nZTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBsYXN0Q2hhbGxlbmdlSGFzaCA9IHV0aWxzLmNhbGN1bGF0ZUZpcnN0Q2hhbGxlbmdlSGFzaChjdXJ2ZSwgcG93ZXIsIGxvZ2dlcik7XG4gICAgfVxuXG4gICAgY29uc3QgZmROZXcgPSBhd2FpdCBiaW5GaWxlVXRpbHMuY3JlYXRlQmluRmlsZShuZXdQVGF1RmlsZW5hbWUsIFwicHRhdVwiLCAxLCBpbXBvcnRQb2ludHMgPyA3OiAyKTtcbiAgICBhd2FpdCB1dGlscy53cml0ZVBUYXVIZWFkZXIoZmROZXcsIGN1cnZlLCBwb3dlcik7XG5cbiAgICBjb25zdCBjb250cmlidXRpb25QcmV2aW91c0hhc2ggPSBhd2FpdCBmZFJlc3BvbnNlLnJlYWQoNjQpO1xuXG4gICAgaWYgKG1pc2MuaGFzaElzRXF1YWwobm9IYXNoLGxhc3RDaGFsbGVuZ2VIYXNoKSkge1xuICAgICAgICBsYXN0Q2hhbGxlbmdlSGFzaCA9IGNvbnRyaWJ1dGlvblByZXZpb3VzSGFzaDtcbiAgICAgICAgY29udHJpYnV0aW9uc1tjb250cmlidXRpb25zLmxlbmd0aC0xXS5uZXh0Q2hhbGxlbmdlID0gbGFzdENoYWxsZW5nZUhhc2g7XG4gICAgfVxuXG4gICAgaWYoIW1pc2MuaGFzaElzRXF1YWwoY29udHJpYnV0aW9uUHJldmlvdXNIYXNoLGxhc3RDaGFsbGVuZ2VIYXNoKSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiV3JvbmcgY29udHJpYnV0aW9uLiBUaGlzIGNvbnRyaWJ1dGlvbiBpcyBub3QgYmFzZWQgb24gdGhlIHByZXZpb3VzIGhhc2hcIik7XG5cbiAgICBjb25zdCBoYXNoZXJSZXNwb25zZSA9IGJsYWtlMmIuY3JlYXRlKHsgZGtMZW46IDY0IH0pO1xuICAgIGhhc2hlclJlc3BvbnNlLnVwZGF0ZShjb250cmlidXRpb25QcmV2aW91c0hhc2gpO1xuXG4gICAgY29uc3Qgc3RhcnRTZWN0aW9ucyA9IFtdO1xuICAgIGxldCByZXM7XG4gICAgcmVzID0gYXdhaXQgcHJvY2Vzc1NlY3Rpb24oZmRSZXNwb25zZSwgZmROZXcsIFwiRzFcIiwgMiwgKDIgKiogcG93ZXIpICogMiAtMSwgWzFdLCBcInRhdUcxXCIpO1xuICAgIGN1cnJlbnRDb250cmlidXRpb24udGF1RzEgPSByZXNbMF07XG4gICAgcmVzID0gYXdhaXQgcHJvY2Vzc1NlY3Rpb24oZmRSZXNwb25zZSwgZmROZXcsIFwiRzJcIiwgMywgKDIgKiogcG93ZXIpICAgICAgICwgWzFdLCBcInRhdUcyXCIpO1xuICAgIGN1cnJlbnRDb250cmlidXRpb24udGF1RzIgPSByZXNbMF07XG4gICAgcmVzID0gYXdhaXQgcHJvY2Vzc1NlY3Rpb24oZmRSZXNwb25zZSwgZmROZXcsIFwiRzFcIiwgNCwgKDIgKiogcG93ZXIpICAgICAgICwgWzBdLCBcImFscGhhRzFcIik7XG4gICAgY3VycmVudENvbnRyaWJ1dGlvbi5hbHBoYUcxID0gcmVzWzBdO1xuICAgIHJlcyA9IGF3YWl0IHByb2Nlc3NTZWN0aW9uKGZkUmVzcG9uc2UsIGZkTmV3LCBcIkcxXCIsIDUsICgyICoqIHBvd2VyKSAgICAgICAsIFswXSwgXCJiZXRhRzFcIik7XG4gICAgY3VycmVudENvbnRyaWJ1dGlvbi5iZXRhRzEgPSByZXNbMF07XG4gICAgcmVzID0gYXdhaXQgcHJvY2Vzc1NlY3Rpb24oZmRSZXNwb25zZSwgZmROZXcsIFwiRzJcIiwgNiwgMSAgICAgICAgICAgICAgICAgICwgWzBdLCBcImJldGFHMlwiKTtcbiAgICBjdXJyZW50Q29udHJpYnV0aW9uLmJldGFHMiA9IHJlc1swXTtcblxuICAgIGN1cnJlbnRDb250cmlidXRpb24ucGFydGlhbEhhc2ggPSBtaXNjLnRvUGFydGlhbEhhc2goaGFzaGVyUmVzcG9uc2UpO1xuXG5cbiAgICBjb25zdCBidWZmS2V5ID0gYXdhaXQgZmRSZXNwb25zZS5yZWFkKGN1cnZlLkYxLm44KjIqNitjdXJ2ZS5GMi5uOCoyKjMpO1xuXG4gICAgY3VycmVudENvbnRyaWJ1dGlvbi5rZXkgPSB1dGlscy5mcm9tUHRhdVB1YktleVJwcihidWZmS2V5LCAwLCBjdXJ2ZSwgZmFsc2UpO1xuXG4gICAgaGFzaGVyUmVzcG9uc2UudXBkYXRlKG5ldyBVaW50OEFycmF5KGJ1ZmZLZXkpKTtcbiAgICBjb25zdCBoYXNoUmVzcG9uc2UgPSBoYXNoZXJSZXNwb25zZS5kaWdlc3QoKTtcblxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKG1pc2MuZm9ybWF0SGFzaChoYXNoUmVzcG9uc2UsIFwiQ29udHJpYnV0aW9uIFJlc3BvbnNlIEhhc2ggaW1wb3J0ZWQ6IFwiKSk7XG5cbiAgICBpZiAoaW1wb3J0UG9pbnRzKSB7XG4gICAgICAgIGNvbnN0IG5leHRDaGFsbGVuZ2VIYXNoZXIgPSBibGFrZTJiLmNyZWF0ZSh7IGRrTGVuOiA2NCB9KTtcbiAgICAgICAgbmV4dENoYWxsZW5nZUhhc2hlci51cGRhdGUoaGFzaFJlc3BvbnNlKTtcblxuICAgICAgICBhd2FpdCBoYXNoU2VjdGlvbihuZXh0Q2hhbGxlbmdlSGFzaGVyLCBmZE5ldywgXCJHMVwiLCAyLCAoMiAqKiBwb3dlcikgKiAyIC0xLCBcInRhdUcxXCIsIGxvZ2dlcik7XG4gICAgICAgIGF3YWl0IGhhc2hTZWN0aW9uKG5leHRDaGFsbGVuZ2VIYXNoZXIsIGZkTmV3LCBcIkcyXCIsIDMsICgyICoqIHBvd2VyKSAgICAgICAsIFwidGF1RzJcIiwgbG9nZ2VyKTtcbiAgICAgICAgYXdhaXQgaGFzaFNlY3Rpb24obmV4dENoYWxsZW5nZUhhc2hlciwgZmROZXcsIFwiRzFcIiwgNCwgKDIgKiogcG93ZXIpICAgICAgICwgXCJhbHBoYVRhdUcxXCIsIGxvZ2dlcik7XG4gICAgICAgIGF3YWl0IGhhc2hTZWN0aW9uKG5leHRDaGFsbGVuZ2VIYXNoZXIsIGZkTmV3LCBcIkcxXCIsIDUsICgyICoqIHBvd2VyKSAgICAgICAsIFwiYmV0YVRhdUcxXCIsIGxvZ2dlcik7XG4gICAgICAgIGF3YWl0IGhhc2hTZWN0aW9uKG5leHRDaGFsbGVuZ2VIYXNoZXIsIGZkTmV3LCBcIkcyXCIsIDYsIDEgICAgICAgICAgICAgICAgICAsIFwiYmV0YUcyXCIsIGxvZ2dlcik7XG5cbiAgICAgICAgY3VycmVudENvbnRyaWJ1dGlvbi5uZXh0Q2hhbGxlbmdlID0gbmV4dENoYWxsZW5nZUhhc2hlci5kaWdlc3QoKTtcblxuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhtaXNjLmZvcm1hdEhhc2goY3VycmVudENvbnRyaWJ1dGlvbi5uZXh0Q2hhbGxlbmdlLCBcIk5leHQgQ2hhbGxlbmdlIEhhc2g6IFwiKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY3VycmVudENvbnRyaWJ1dGlvbi5uZXh0Q2hhbGxlbmdlID0gbm9IYXNoO1xuICAgIH1cblxuICAgIGNvbnRyaWJ1dGlvbnMucHVzaChjdXJyZW50Q29udHJpYnV0aW9uKTtcblxuICAgIGF3YWl0IHV0aWxzLndyaXRlQ29udHJpYnV0aW9ucyhmZE5ldywgY3VydmUsIGNvbnRyaWJ1dGlvbnMpO1xuXG4gICAgYXdhaXQgZmRSZXNwb25zZS5jbG9zZSgpO1xuICAgIGF3YWl0IGZkTmV3LmNsb3NlKCk7XG4gICAgYXdhaXQgZmRPbGQuY2xvc2UoKTtcblxuICAgIHJldHVybiBjdXJyZW50Q29udHJpYnV0aW9uLm5leHRDaGFsbGVuZ2U7XG5cbiAgICBhc3luYyBmdW5jdGlvbiBwcm9jZXNzU2VjdGlvbihmZEZyb20sIGZkVG8sIGdyb3VwTmFtZSwgc2VjdGlvbklkLCBuUG9pbnRzLCBzaW5ndWxhclBvaW50SW5kZXhlcywgc2VjdGlvbk5hbWUpIHtcbiAgICAgICAgaWYgKGltcG9ydFBvaW50cykge1xuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHByb2Nlc3NTZWN0aW9uSW1wb3J0UG9pbnRzKGZkRnJvbSwgZmRUbywgZ3JvdXBOYW1lLCBzZWN0aW9uSWQsIG5Qb2ludHMsIHNpbmd1bGFyUG9pbnRJbmRleGVzLCBzZWN0aW9uTmFtZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgcHJvY2Vzc1NlY3Rpb25Ob0ltcG9ydFBvaW50cyhmZEZyb20sIGZkVG8sIGdyb3VwTmFtZSwgc2VjdGlvbklkLCBuUG9pbnRzLCBzaW5ndWxhclBvaW50SW5kZXhlcywgc2VjdGlvbk5hbWUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMgZnVuY3Rpb24gcHJvY2Vzc1NlY3Rpb25JbXBvcnRQb2ludHMoZmRGcm9tLCBmZFRvLCBncm91cE5hbWUsIHNlY3Rpb25JZCwgblBvaW50cywgc2luZ3VsYXJQb2ludEluZGV4ZXMsIHNlY3Rpb25OYW1lKSB7XG5cbiAgICAgICAgY29uc3QgRyA9IGN1cnZlW2dyb3VwTmFtZV07XG4gICAgICAgIGNvbnN0IHNjRyA9IEcuRi5uODtcbiAgICAgICAgY29uc3Qgc0cgPSBHLkYubjgqMjtcblxuICAgICAgICBjb25zdCBzaW5ndWxhclBvaW50cyA9IFtdO1xuXG4gICAgICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFdyaXRlU2VjdGlvbihmZFRvLCBzZWN0aW9uSWQpO1xuICAgICAgICBjb25zdCBuUG9pbnRzQ2h1bmsgPSBNYXRoLmZsb29yKCgxPDwyNCkvc0cpO1xuXG4gICAgICAgIHN0YXJ0U2VjdGlvbnNbc2VjdGlvbklkXSA9IGZkVG8ucG9zO1xuXG4gICAgICAgIGZvciAobGV0IGk9MDsgaTwgblBvaW50czsgaSArPSBuUG9pbnRzQ2h1bmspIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhgSW1wb3J0aW5nICR7c2VjdGlvbk5hbWV9OiAke2l9LyR7blBvaW50c31gKTtcbiAgICAgICAgICAgIGNvbnN0IG4gPSBNYXRoLm1pbihuUG9pbnRzLWksIG5Qb2ludHNDaHVuayk7XG5cbiAgICAgICAgICAgIGNvbnN0IGJ1ZmZDID0gYXdhaXQgZmRGcm9tLnJlYWQobiAqIHNjRyk7XG4gICAgICAgICAgICBoYXNoZXJSZXNwb25zZS51cGRhdGUoYnVmZkMpO1xuXG4gICAgICAgICAgICBjb25zdCBidWZmTEVNID0gYXdhaXQgRy5iYXRjaEN0b0xFTShidWZmQyk7XG5cbiAgICAgICAgICAgIGF3YWl0IGZkVG8ud3JpdGUoYnVmZkxFTSk7XG4gICAgICAgICAgICBmb3IgKGxldCBqPTA7IGo8c2luZ3VsYXJQb2ludEluZGV4ZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzcCA9IHNpbmd1bGFyUG9pbnRJbmRleGVzW2pdO1xuICAgICAgICAgICAgICAgIGlmICgoc3AgPj1pKSAmJiAoc3AgPCBpK24pKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IFAgPSBHLmZyb21ScHJMRU0oYnVmZkxFTSwgKHNwLWkpKnNHKTtcbiAgICAgICAgICAgICAgICAgICAgc2luZ3VsYXJQb2ludHMucHVzaChQKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kV3JpdGVTZWN0aW9uKGZkVG8pO1xuXG4gICAgICAgIHJldHVybiBzaW5ndWxhclBvaW50cztcbiAgICB9XG5cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHByb2Nlc3NTZWN0aW9uTm9JbXBvcnRQb2ludHMoZmRGcm9tLCBmZFRvLCBncm91cE5hbWUsIHNlY3Rpb25JZCwgblBvaW50cywgc2luZ3VsYXJQb2ludEluZGV4ZXMsIHNlY3Rpb25OYW1lKSB7XG5cbiAgICAgICAgY29uc3QgRyA9IGN1cnZlW2dyb3VwTmFtZV07XG4gICAgICAgIGNvbnN0IHNjRyA9IEcuRi5uODtcblxuICAgICAgICBjb25zdCBzaW5ndWxhclBvaW50cyA9IFtdO1xuXG4gICAgICAgIGNvbnN0IG5Qb2ludHNDaHVuayA9IE1hdGguZmxvb3IoKDE8PDI0KS9zY0cpO1xuXG4gICAgICAgIGZvciAobGV0IGk9MDsgaTwgblBvaW50czsgaSArPSBuUG9pbnRzQ2h1bmspIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhgSW1wb3J0aW5nICR7c2VjdGlvbk5hbWV9OiAke2l9LyR7blBvaW50c31gKTtcbiAgICAgICAgICAgIGNvbnN0IG4gPSBNYXRoLm1pbihuUG9pbnRzLWksIG5Qb2ludHNDaHVuayk7XG5cbiAgICAgICAgICAgIGNvbnN0IGJ1ZmZDID0gYXdhaXQgZmRGcm9tLnJlYWQobiAqIHNjRyk7XG4gICAgICAgICAgICBoYXNoZXJSZXNwb25zZS51cGRhdGUoYnVmZkMpO1xuXG4gICAgICAgICAgICBmb3IgKGxldCBqPTA7IGo8c2luZ3VsYXJQb2ludEluZGV4ZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzcCA9IHNpbmd1bGFyUG9pbnRJbmRleGVzW2pdO1xuICAgICAgICAgICAgICAgIGlmICgoc3AgPj1pKSAmJiAoc3AgPCBpK24pKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IFAgPSBHLmZyb21ScHJDb21wcmVzc2VkKGJ1ZmZDLCAoc3AtaSkqc2NHKTtcbiAgICAgICAgICAgICAgICAgICAgc2luZ3VsYXJQb2ludHMucHVzaChQKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc2luZ3VsYXJQb2ludHM7XG4gICAgfVxuXG5cbiAgICBhc3luYyBmdW5jdGlvbiBoYXNoU2VjdGlvbihuZXh0Q2hhbGxlbmdlSGFzaGVyLCBmZFRvLCBncm91cE5hbWUsIHNlY3Rpb25JZCwgblBvaW50cywgc2VjdGlvbk5hbWUsIGxvZ2dlcikge1xuXG4gICAgICAgIGNvbnN0IEcgPSBjdXJ2ZVtncm91cE5hbWVdO1xuICAgICAgICBjb25zdCBzRyA9IEcuRi5uOCoyO1xuICAgICAgICBjb25zdCBuUG9pbnRzQ2h1bmsgPSBNYXRoLmZsb29yKCgxPDwyNCkvc0cpO1xuXG4gICAgICAgIGNvbnN0IG9sZFBvcyA9IGZkVG8ucG9zO1xuICAgICAgICBmZFRvLnBvcyA9IHN0YXJ0U2VjdGlvbnNbc2VjdGlvbklkXTtcblxuICAgICAgICBmb3IgKGxldCBpPTA7IGk8IG5Qb2ludHM7IGkgKz0gblBvaW50c0NodW5rKSB7XG4gICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoYEhhc2hpbmcgJHtzZWN0aW9uTmFtZX06ICR7aX0vJHtuUG9pbnRzfWApO1xuICAgICAgICAgICAgY29uc3QgbiA9IE1hdGgubWluKG5Qb2ludHMtaSwgblBvaW50c0NodW5rKTtcblxuICAgICAgICAgICAgY29uc3QgYnVmZkxFTSA9IGF3YWl0IGZkVG8ucmVhZChuICogc0cpO1xuXG4gICAgICAgICAgICBjb25zdCBidWZmVSA9IGF3YWl0IEcuYmF0Y2hMRU10b1UoYnVmZkxFTSk7XG5cbiAgICAgICAgICAgIG5leHRDaGFsbGVuZ2VIYXNoZXIudXBkYXRlKGJ1ZmZVKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZkVG8ucG9zID0gb2xkUG9zO1xuICAgIH1cblxufVxuXG4iLCIvKlxuICAgIENvcHlyaWdodCAyMDE4IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygc25hcmtKUy5cblxuICAgIHNuYXJrSlMgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gICAgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAgICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICAgIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICBzbmFya0pTIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHNuYXJrSlMuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG5pbXBvcnQgeyBibGFrZTJiIH0gZnJvbSBcIkBub2JsZS9oYXNoZXMvYmxha2UyYlwiO1xuaW1wb3J0ICogYXMgdXRpbHMgZnJvbSBcIi4vcG93ZXJzb2Z0YXVfdXRpbHMuanNcIjtcbmltcG9ydCAqIGFzIGtleVBhaXIgZnJvbSBcIi4va2V5cGFpci5qc1wiO1xuaW1wb3J0ICogYXMgYmluRmlsZVV0aWxzIGZyb20gXCJAaWRlbjMvYmluZmlsZXV0aWxzXCI7XG5pbXBvcnQgeyBDaGFDaGEsIEJpZ0J1ZmZlciB9IGZyb20gXCJmZmphdmFzY3JpcHRcIjtcbmltcG9ydCAqIGFzIG1pc2MgZnJvbSBcIi4vbWlzYy5qc1wiO1xuY29uc3Qgc2FtZVJhdGlvID0gbWlzYy5zYW1lUmF0aW87XG5cbmFzeW5jIGZ1bmN0aW9uIHZlcmlmeUNvbnRyaWJ1dGlvbihjdXJ2ZSwgY3VyLCBwcmV2LCBsb2dnZXIpIHtcbiAgICBsZXQgc3I7XG4gICAgaWYgKGN1ci50eXBlID09IDEpIHsgICAgLy8gVmVyaWZ5IHRoZSBiZWFjb24uXG4gICAgICAgIGNvbnN0IGJlYWNvbktleSA9IGF3YWl0IHV0aWxzLmtleUZyb21CZWFjb24oY3VydmUsIHByZXYubmV4dENoYWxsZW5nZSwgY3VyLmJlYWNvbkhhc2gsIGN1ci5udW1JdGVyYXRpb25zRXhwKTtcblxuICAgICAgICBpZiAoIWN1cnZlLkcxLmVxKGN1ci5rZXkudGF1LmcxX3MsIGJlYWNvbktleS50YXUuZzFfcykpIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihgQkVBQ09OIGtleSAodGF1RzFfcykgaXMgbm90IGdlbmVyYXRlZCBjb3JyZWN0bHkgaW4gY2hhbGxlbmdlICMke2N1ci5pZH0gICR7Y3VyLm5hbWUgfHwgXCJcIn1gICk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFjdXJ2ZS5HMS5lcShjdXIua2V5LnRhdS5nMV9zeCwgYmVhY29uS2V5LnRhdS5nMV9zeCkpIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihgQkVBQ09OIGtleSAodGF1RzFfc3gpIGlzIG5vdCBnZW5lcmF0ZWQgY29ycmVjdGx5IGluIGNoYWxsZW5nZSAjJHtjdXIuaWR9ICAke2N1ci5uYW1lIHx8IFwiXCJ9YCApO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmICghY3VydmUuRzIuZXEoY3VyLmtleS50YXUuZzJfc3B4LCBiZWFjb25LZXkudGF1LmcyX3NweCkpIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihgQkVBQ09OIGtleSAodGF1RzJfc3B4KSBpcyBub3QgZ2VuZXJhdGVkIGNvcnJlY3RseSBpbiBjaGFsbGVuZ2UgIyR7Y3VyLmlkfSAgJHtjdXIubmFtZSB8fCBcIlwifWAgKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghY3VydmUuRzEuZXEoY3VyLmtleS5hbHBoYS5nMV9zLCBiZWFjb25LZXkuYWxwaGEuZzFfcykpIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihgQkVBQ09OIGtleSAoYWxwaGFHMV9zKSBpcyBub3QgZ2VuZXJhdGVkIGNvcnJlY3RseSBpbiBjaGFsbGVuZ2UgIyR7Y3VyLmlkfSAgJHtjdXIubmFtZSB8fCBcIlwifWAgKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWN1cnZlLkcxLmVxKGN1ci5rZXkuYWxwaGEuZzFfc3gsIGJlYWNvbktleS5hbHBoYS5nMV9zeCkpIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihgQkVBQ09OIGtleSAoYWxwaGFHMV9zeCkgaXMgbm90IGdlbmVyYXRlZCBjb3JyZWN0bHkgaW4gY2hhbGxlbmdlICMke2N1ci5pZH0gICR7Y3VyLm5hbWUgfHwgXCJcIn1gICk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFjdXJ2ZS5HMi5lcShjdXIua2V5LmFscGhhLmcyX3NweCwgYmVhY29uS2V5LmFscGhhLmcyX3NweCkpIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihgQkVBQ09OIGtleSAoYWxwaGFHMl9zcHgpIGlzIG5vdCBnZW5lcmF0ZWQgY29ycmVjdGx5IGluIGNoYWxsZW5nZSAjJHtjdXIuaWR9ICAke2N1ci5uYW1lIHx8IFwiXCJ9YCApO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFjdXJ2ZS5HMS5lcShjdXIua2V5LmJldGEuZzFfcywgYmVhY29uS2V5LmJldGEuZzFfcykpIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihgQkVBQ09OIGtleSAoYmV0YUcxX3MpIGlzIG5vdCBnZW5lcmF0ZWQgY29ycmVjdGx5IGluIGNoYWxsZW5nZSAjJHtjdXIuaWR9ICAke2N1ci5uYW1lIHx8IFwiXCJ9YCApO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmICghY3VydmUuRzEuZXEoY3VyLmtleS5iZXRhLmcxX3N4LCBiZWFjb25LZXkuYmV0YS5nMV9zeCkpIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihgQkVBQ09OIGtleSAoYmV0YUcxX3N4KSBpcyBub3QgZ2VuZXJhdGVkIGNvcnJlY3RseSBpbiBjaGFsbGVuZ2UgIyR7Y3VyLmlkfSAgJHtjdXIubmFtZSB8fCBcIlwifWAgKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWN1cnZlLkcyLmVxKGN1ci5rZXkuYmV0YS5nMl9zcHgsIGJlYWNvbktleS5iZXRhLmcyX3NweCkpIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihgQkVBQ09OIGtleSAoYmV0YUcyX3NweCkgaXMgbm90IGdlbmVyYXRlZCBjb3JyZWN0bHkgaW4gY2hhbGxlbmdlICMke2N1ci5pZH0gICR7Y3VyLm5hbWUgfHwgXCJcIn1gICk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjdXIua2V5LnRhdS5nMl9zcCA9IGN1cnZlLkcyLnRvQWZmaW5lKGtleVBhaXIuZ2V0RzJzcChjdXJ2ZSwgMCwgcHJldi5uZXh0Q2hhbGxlbmdlLCBjdXIua2V5LnRhdS5nMV9zLCBjdXIua2V5LnRhdS5nMV9zeCkpO1xuICAgIGN1ci5rZXkuYWxwaGEuZzJfc3AgPSBjdXJ2ZS5HMi50b0FmZmluZShrZXlQYWlyLmdldEcyc3AoY3VydmUsIDEsIHByZXYubmV4dENoYWxsZW5nZSwgY3VyLmtleS5hbHBoYS5nMV9zLCBjdXIua2V5LmFscGhhLmcxX3N4KSk7XG4gICAgY3VyLmtleS5iZXRhLmcyX3NwID0gY3VydmUuRzIudG9BZmZpbmUoa2V5UGFpci5nZXRHMnNwKGN1cnZlLCAyLCBwcmV2Lm5leHRDaGFsbGVuZ2UsIGN1ci5rZXkuYmV0YS5nMV9zLCBjdXIua2V5LmJldGEuZzFfc3gpKTtcblxuICAgIHNyID0gYXdhaXQgc2FtZVJhdGlvKGN1cnZlLCBjdXIua2V5LnRhdS5nMV9zLCBjdXIua2V5LnRhdS5nMV9zeCwgY3VyLmtleS50YXUuZzJfc3AsIGN1ci5rZXkudGF1LmcyX3NweCk7XG4gICAgaWYgKHNyICE9PSB0cnVlKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihcIklOVkFMSUQga2V5ICh0YXUpIGluIGNoYWxsZW5nZSAjXCIrY3VyLmlkKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHNyID0gYXdhaXQgc2FtZVJhdGlvKGN1cnZlLCBjdXIua2V5LmFscGhhLmcxX3MsIGN1ci5rZXkuYWxwaGEuZzFfc3gsIGN1ci5rZXkuYWxwaGEuZzJfc3AsIGN1ci5rZXkuYWxwaGEuZzJfc3B4KTtcbiAgICBpZiAoc3IgIT09IHRydWUpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiSU5WQUxJRCBrZXkgKGFscGhhKSBpbiBjaGFsbGVuZ2UgI1wiK2N1ci5pZCk7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBzciA9IGF3YWl0IHNhbWVSYXRpbyhjdXJ2ZSwgY3VyLmtleS5iZXRhLmcxX3MsIGN1ci5rZXkuYmV0YS5nMV9zeCwgY3VyLmtleS5iZXRhLmcyX3NwLCBjdXIua2V5LmJldGEuZzJfc3B4KTtcbiAgICBpZiAoc3IgIT09IHRydWUpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiSU5WQUxJRCBrZXkgKGJldGEpIGluIGNoYWxsZW5nZSAjXCIrY3VyLmlkKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHNyID0gYXdhaXQgc2FtZVJhdGlvKGN1cnZlLCBwcmV2LnRhdUcxLCBjdXIudGF1RzEsIGN1ci5rZXkudGF1LmcyX3NwLCBjdXIua2V5LnRhdS5nMl9zcHgpO1xuICAgIGlmIChzciAhPT0gdHJ1ZSkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJJTlZBTElEIHRhdSpHMS4gY2hhbGxlbmdlICNcIitjdXIuaWQrXCIgSXQgZG9lcyBub3QgZm9sbG93IHRoZSBwcmV2aW91cyBjb250cmlidXRpb25cIik7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBzciA9IGF3YWl0IHNhbWVSYXRpbyhjdXJ2ZSwgIGN1ci5rZXkudGF1LmcxX3MsIGN1ci5rZXkudGF1LmcxX3N4LCBwcmV2LnRhdUcyLCBjdXIudGF1RzIpO1xuICAgIGlmIChzciAhPT0gdHJ1ZSkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJJTlZBTElEIHRhdSpHMi4gY2hhbGxlbmdlICNcIitjdXIuaWQrXCIgSXQgZG9lcyBub3QgZm9sbG93IHRoZSBwcmV2aW91cyBjb250cmlidXRpb25cIik7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBzciA9IGF3YWl0IHNhbWVSYXRpbyhjdXJ2ZSwgcHJldi5hbHBoYUcxLCBjdXIuYWxwaGFHMSwgY3VyLmtleS5hbHBoYS5nMl9zcCwgY3VyLmtleS5hbHBoYS5nMl9zcHgpO1xuICAgIGlmIChzciAhPT0gdHJ1ZSkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJJTlZBTElEIGFscGhhKkcxLiBjaGFsbGVuZ2UgI1wiK2N1ci5pZCtcIiBJdCBkb2VzIG5vdCBmb2xsb3cgdGhlIHByZXZpb3VzIGNvbnRyaWJ1dGlvblwiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHNyID0gYXdhaXQgc2FtZVJhdGlvKGN1cnZlLCBwcmV2LmJldGFHMSwgY3VyLmJldGFHMSwgY3VyLmtleS5iZXRhLmcyX3NwLCBjdXIua2V5LmJldGEuZzJfc3B4KTtcbiAgICBpZiAoc3IgIT09IHRydWUpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiSU5WQUxJRCBiZXRhKkcxLiBjaGFsbGVuZ2UgI1wiK2N1ci5pZCtcIiBJdCBkb2VzIG5vdCBmb2xsb3cgdGhlIHByZXZpb3VzIGNvbnRyaWJ1dGlvblwiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHNyID0gYXdhaXQgc2FtZVJhdGlvKGN1cnZlLCAgY3VyLmtleS5iZXRhLmcxX3MsIGN1ci5rZXkuYmV0YS5nMV9zeCwgcHJldi5iZXRhRzIsIGN1ci5iZXRhRzIpO1xuICAgIGlmIChzciAhPT0gdHJ1ZSkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJJTlZBTElEIGJldGEqRzIuIGNoYWxsZW5nZSAjXCIrY3VyLmlkK1wiSXQgZG9lcyBub3QgZm9sbG93IHRoZSBwcmV2aW91cyBjb250cmlidXRpb25cIik7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIlBvd2VycyBPZiB0YXUgZmlsZSBPSyFcIik7XG4gICAgcmV0dXJuIHRydWU7XG59XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uIHZlcmlmeSh0YXVGaWxlbmFtZSwgbG9nZ2VyKSB7XG4gICAgbGV0IHNyO1xuXG4gICAgY29uc3Qge2ZkLCBzZWN0aW9uc30gPSBhd2FpdCBiaW5GaWxlVXRpbHMucmVhZEJpbkZpbGUodGF1RmlsZW5hbWUsIFwicHRhdVwiLCAxKTtcbiAgICBjb25zdCB7Y3VydmUsIHBvd2VyLCBjZXJlbW9ueVBvd2VyfSA9IGF3YWl0IHV0aWxzLnJlYWRQVGF1SGVhZGVyKGZkLCBzZWN0aW9ucyk7XG4gICAgY29uc3QgY29udHJzID0gYXdhaXQgdXRpbHMucmVhZENvbnRyaWJ1dGlvbnMoZmQsIGN1cnZlLCBzZWN0aW9ucyk7XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCJwb3dlcjogMioqXCIgKyBwb3dlcik7XG4gICAgLy8gVmVyaWZ5IExhc3QgY29udHJpYnV0aW9uXG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCJDb21wdXRpbmcgaW5pdGlhbCBjb250cmlidXRpb24gaGFzaFwiKTtcbiAgICBjb25zdCBpbml0aWFsQ29udHJpYnV0aW9uID0ge1xuICAgICAgICB0YXVHMTogY3VydmUuRzEuZyxcbiAgICAgICAgdGF1RzI6IGN1cnZlLkcyLmcsXG4gICAgICAgIGFscGhhRzE6IGN1cnZlLkcxLmcsXG4gICAgICAgIGJldGFHMTogY3VydmUuRzEuZyxcbiAgICAgICAgYmV0YUcyOiBjdXJ2ZS5HMi5nLFxuICAgICAgICBuZXh0Q2hhbGxlbmdlOiB1dGlscy5jYWxjdWxhdGVGaXJzdENoYWxsZW5nZUhhc2goY3VydmUsIGNlcmVtb255UG93ZXIsIGxvZ2dlciksXG4gICAgICAgIHJlc3BvbnNlSGFzaDogYmxha2UyYi5jcmVhdGUoeyBka0xlbjogNjQgfSkuZGlnZXN0KClcbiAgICB9O1xuXG4gICAgaWYgKGNvbnRycy5sZW5ndGggPT0gMCkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJUaGlzIGZpbGUgaGFzIG5vIGNvbnRyaWJ1dGlvbiEgSXQgY2Fubm90IGJlIHVzZWQgaW4gcHJvZHVjdGlvblwiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGxldCBwcmV2Q29udHI7XG4gICAgaWYgKGNvbnRycy5sZW5ndGg+MSkge1xuICAgICAgICBwcmV2Q29udHIgPSBjb250cnNbY29udHJzLmxlbmd0aC0yXTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBwcmV2Q29udHIgPSBpbml0aWFsQ29udHJpYnV0aW9uO1xuICAgIH1cbiAgICBjb25zdCBjdXJDb250ciA9IGNvbnRyc1tjb250cnMubGVuZ3RoLTFdO1xuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIlZhbGlkYXRpbmcgY29udHJpYnV0aW9uICNcIitjb250cnNbY29udHJzLmxlbmd0aC0xXS5pZCk7XG4gICAgY29uc3QgcmVzID0gYXdhaXQgdmVyaWZ5Q29udHJpYnV0aW9uKGN1cnZlLCBjdXJDb250ciwgcHJldkNvbnRyLCBsb2dnZXIpO1xuICAgIGlmICghcmVzKSByZXR1cm4gZmFsc2U7XG5cblxuICAgIGNvbnN0IG5leHRDb250cmlidXRpb25IYXNoZXIgPSBibGFrZTJiLmNyZWF0ZSh7IGRrTGVuOiA2NCB9KTtcbiAgICBuZXh0Q29udHJpYnV0aW9uSGFzaGVyLnVwZGF0ZShjdXJDb250ci5yZXNwb25zZUhhc2gpO1xuXG4gICAgLy8gVmVyaWZ5IHBvd2VycyBhbmQgY29tcHV0ZSBuZXh0Q2hhbGxlbmdlSGFzaFxuXG4gICAgLy8gYXdhaXQgdGVzdCgpO1xuXG4gICAgLy8gVmVyaWZ5IFNlY3Rpb24gdGF1KkcxXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKFwiVmVyaWZ5aW5nIHBvd2VycyBpbiB0YXUqRzEgc2VjdGlvblwiKTtcbiAgICBjb25zdCByVGF1MSA9IGF3YWl0IHByb2Nlc3NTZWN0aW9uKDIsIFwiRzFcIiwgXCJ0YXVHMVwiLCAoMiAqKiBwb3dlcikqMi0xLCBbMCwgMV0sIGxvZ2dlcik7XG4gICAgc3IgPSBhd2FpdCBzYW1lUmF0aW8oY3VydmUsIHJUYXUxLlIxLCByVGF1MS5SMiwgY3VydmUuRzIuZywgY3VyQ29udHIudGF1RzIpO1xuICAgIGlmIChzciAhPT0gdHJ1ZSkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJ0YXVHMSBzZWN0aW9uLiBQb3dlcnMgZG8gbm90IG1hdGNoXCIpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmICghY3VydmUuRzEuZXEoY3VydmUuRzEuZywgclRhdTEuc2luZ3VsYXJQb2ludHNbMF0pKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihcIkZpcnN0IGVsZW1lbnQgb2YgdGF1KkcxIHNlY3Rpb24gbXVzdCBiZSB0aGUgZ2VuZXJhdG9yXCIpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmICghY3VydmUuRzEuZXEoY3VyQ29udHIudGF1RzEsIHJUYXUxLnNpbmd1bGFyUG9pbnRzWzFdKSkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJTZWNvbmQgZWxlbWVudCBvZiB0YXUqRzEgc2VjdGlvbiBkb2VzIG5vdCBtYXRjaCB0aGUgb25lIGluIHRoZSBjb250cmlidXRpb24gc2VjdGlvblwiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8vIGF3YWl0IHRlc3QoKTtcblxuICAgIC8vIFZlcmlmeSBTZWN0aW9uIHRhdSpHMlxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIlZlcmlmeWluZyBwb3dlcnMgaW4gdGF1KkcyIHNlY3Rpb25cIik7XG4gICAgY29uc3QgclRhdTIgPSBhd2FpdCBwcm9jZXNzU2VjdGlvbigzLCBcIkcyXCIsIFwidGF1RzJcIiwgMiAqKiBwb3dlciwgWzAsIDFdLCAgbG9nZ2VyKTtcbiAgICBzciA9IGF3YWl0IHNhbWVSYXRpbyhjdXJ2ZSwgY3VydmUuRzEuZywgY3VyQ29udHIudGF1RzEsIHJUYXUyLlIxLCByVGF1Mi5SMik7XG4gICAgaWYgKHNyICE9PSB0cnVlKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihcInRhdUcyIHNlY3Rpb24uIFBvd2VycyBkbyBub3QgbWF0Y2hcIik7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgaWYgKCFjdXJ2ZS5HMi5lcShjdXJ2ZS5HMi5nLCByVGF1Mi5zaW5ndWxhclBvaW50c1swXSkpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiRmlyc3QgZWxlbWVudCBvZiB0YXUqRzIgc2VjdGlvbiBtdXN0IGJlIHRoZSBnZW5lcmF0b3JcIik7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgaWYgKCFjdXJ2ZS5HMi5lcShjdXJDb250ci50YXVHMiwgclRhdTIuc2luZ3VsYXJQb2ludHNbMV0pKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihcIlNlY29uZCBlbGVtZW50IG9mIHRhdSpHMiBzZWN0aW9uIGRvZXMgbm90IG1hdGNoIHRoZSBvbmUgaW4gdGhlIGNvbnRyaWJ1dGlvbiBzZWN0aW9uXCIpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gVmVyaWZ5IFNlY3Rpb24gYWxwaGEqdGF1KkcxXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKFwiVmVyaWZ5aW5nIHBvd2VycyBpbiBhbHBoYSp0YXUqRzEgc2VjdGlvblwiKTtcbiAgICBjb25zdCByQWxwaGFUYXVHMSA9IGF3YWl0IHByb2Nlc3NTZWN0aW9uKDQsIFwiRzFcIiwgXCJhbHBoYXRhdUcxXCIsIDIgKiogcG93ZXIsIFswXSwgbG9nZ2VyKTtcbiAgICBzciA9IGF3YWl0IHNhbWVSYXRpbyhjdXJ2ZSwgckFscGhhVGF1RzEuUjEsIHJBbHBoYVRhdUcxLlIyLCBjdXJ2ZS5HMi5nLCBjdXJDb250ci50YXVHMik7XG4gICAgaWYgKHNyICE9PSB0cnVlKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihcImFscGhhVGF1RzEgc2VjdGlvbi4gUG93ZXJzIGRvIG5vdCBtYXRjaFwiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAoIWN1cnZlLkcxLmVxKGN1ckNvbnRyLmFscGhhRzEsIHJBbHBoYVRhdUcxLnNpbmd1bGFyUG9pbnRzWzBdKSkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJGaXJzdCBlbGVtZW50IG9mIGFscGhhKnRhdSpHMSBzZWN0aW9uIChhbHBoYSpHMSkgZG9lcyBub3QgbWF0Y2ggdGhlIG9uZSBpbiB0aGUgY29udHJpYnV0aW9uIHNlY3Rpb25cIik7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBWZXJpZnkgU2VjdGlvbiBiZXRhKnRhdSpHMVxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIlZlcmlmeWluZyBwb3dlcnMgaW4gYmV0YSp0YXUqRzEgc2VjdGlvblwiKTtcbiAgICBjb25zdCByQmV0YVRhdUcxID0gYXdhaXQgcHJvY2Vzc1NlY3Rpb24oNSwgXCJHMVwiLCBcImJldGF0YXVHMVwiLCAyICoqIHBvd2VyLCBbMF0sIGxvZ2dlcik7XG4gICAgc3IgPSBhd2FpdCBzYW1lUmF0aW8oY3VydmUsIHJCZXRhVGF1RzEuUjEsIHJCZXRhVGF1RzEuUjIsIGN1cnZlLkcyLmcsIGN1ckNvbnRyLnRhdUcyKTtcbiAgICBpZiAoc3IgIT09IHRydWUpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiYmV0YVRhdUcxIHNlY3Rpb24uIFBvd2VycyBkbyBub3QgbWF0Y2hcIik7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgaWYgKCFjdXJ2ZS5HMS5lcShjdXJDb250ci5iZXRhRzEsIHJCZXRhVGF1RzEuc2luZ3VsYXJQb2ludHNbMF0pKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihcIkZpcnN0IGVsZW1lbnQgb2YgYmV0YSp0YXUqRzEgc2VjdGlvbiAoYmV0YSpHMSkgZG9lcyBub3QgbWF0Y2ggdGhlIG9uZSBpbiB0aGUgY29udHJpYnV0aW9uIHNlY3Rpb25cIik7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvL1ZlcmlmeSBCZXRhIEcyXG4gICAgY29uc3QgYmV0YUcyID0gYXdhaXQgcHJvY2Vzc1NlY3Rpb25CZXRhRzIobG9nZ2VyKTtcbiAgICBpZiAoIWN1cnZlLkcyLmVxKGN1ckNvbnRyLmJldGFHMiwgYmV0YUcyKSkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJiZXRhRzIgZWxlbWVudCBpbiBiZXRhRzIgc2VjdGlvbiBkb2VzIG5vdCBtYXRjaCB0aGUgb25lIGluIHRoZSBjb250cmlidXRpb24gc2VjdGlvblwiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuXG4gICAgY29uc3QgbmV4dENvbnRyaWJ1dGlvbkhhc2ggPSBuZXh0Q29udHJpYnV0aW9uSGFzaGVyLmRpZ2VzdCgpO1xuXG4gICAgLy8gQ2hlY2sgdGhlIG5leHRDaGFsbGVuZ2VIYXNoXG4gICAgaWYgKHBvd2VyID09IGNlcmVtb255UG93ZXIpIHtcbiAgICAgICAgaWYgKCFtaXNjLmhhc2hJc0VxdWFsKG5leHRDb250cmlidXRpb25IYXNoLGN1ckNvbnRyLm5leHRDaGFsbGVuZ2UpKSB7XG4gICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJIYXNoIG9mIHRoZSB2YWx1ZXMgZG9lcyBub3QgbWF0Y2ggdGhlIG5leHQgY2hhbGxlbmdlIG9mIHRoZSBsYXN0IGNvbnRyaWJ1dG9yIGluIHRoZSBjb250cmlidXRpb25zIHNlY3Rpb25cIik7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhtaXNjLmZvcm1hdEhhc2gobmV4dENvbnRyaWJ1dGlvbkhhc2gsIFwiTmV4dCBjaGFsbGVuZ2UgaGFzaDogXCIpKTtcblxuICAgIC8vIFZlcmlmeSBQcmV2aW91cyBjb250cmlidXRpb25zXG5cbiAgICBwcmludENvbnRyaWJ1dGlvbihjdXJDb250ciwgcHJldkNvbnRyKTtcbiAgICBmb3IgKGxldCBpID0gY29udHJzLmxlbmd0aC0yOyBpPj0wOyBpLS0pIHtcbiAgICAgICAgY29uc3QgY3VyQ29udHIgPSBjb250cnNbaV07XG4gICAgICAgIGNvbnN0IHByZXZDb250ciA9ICAoaT4wKSA/IGNvbnRyc1tpLTFdIDogaW5pdGlhbENvbnRyaWJ1dGlvbjtcbiAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgdmVyaWZ5Q29udHJpYnV0aW9uKGN1cnZlLCBjdXJDb250ciwgcHJldkNvbnRyLCBsb2dnZXIpO1xuICAgICAgICBpZiAoIXJlcykgcmV0dXJuIGZhbHNlO1xuICAgICAgICBwcmludENvbnRyaWJ1dGlvbihjdXJDb250ciwgcHJldkNvbnRyLCBsb2dnZXIpO1xuICAgIH1cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXCIpO1xuXG4gICAgaWYgKCghc2VjdGlvbnNbMTJdKSB8fCAoIXNlY3Rpb25zWzEzXSkgfHwgKCFzZWN0aW9uc1sxNF0pIHx8ICghc2VjdGlvbnNbMTVdKSkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIud2FybihcbiAgICAgICAgICAgIFwidGhpcyBmaWxlIGRvZXMgbm90IGNvbnRhaW4gcGhhc2UyIHByZWNhbGN1bGF0ZWQgdmFsdWVzLiBQbGVhc2UgcnVuOiBcXG5cIiArXG4gICAgICAgICAgICBcIiAgIHNuYXJranMgXFxcInBvd2Vyc29mdGF1IHByZXBhcmVwaGFzZTJcXFwiIHRvIHByZXBhcmUgdGhpcyBmaWxlIHRvIGJlIHVzZWQgaW4gdGhlIHBoYXNlMiBjZXJlbW9ueS5cIlxuICAgICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGxldCByZXM7XG4gICAgICAgIHJlcyA9IGF3YWl0IHZlcmlmeUxhZ3JhbmdlRXZhbHVhdGlvbnMoXCJHMVwiLCAyLCAxMiwgXCJ0YXVHMVwiLCBsb2dnZXIpO1xuICAgICAgICBpZiAoIXJlcykgcmV0dXJuIGZhbHNlO1xuICAgICAgICByZXMgPSBhd2FpdCB2ZXJpZnlMYWdyYW5nZUV2YWx1YXRpb25zKFwiRzJcIiwgMywgMTMsIFwidGF1RzJcIiwgbG9nZ2VyKTtcbiAgICAgICAgaWYgKCFyZXMpIHJldHVybiBmYWxzZTtcbiAgICAgICAgcmVzID0gYXdhaXQgdmVyaWZ5TGFncmFuZ2VFdmFsdWF0aW9ucyhcIkcxXCIsIDQsIDE0LCBcImFscGhhVGF1RzFcIiwgbG9nZ2VyKTtcbiAgICAgICAgaWYgKCFyZXMpIHJldHVybiBmYWxzZTtcbiAgICAgICAgcmVzID0gYXdhaXQgdmVyaWZ5TGFncmFuZ2VFdmFsdWF0aW9ucyhcIkcxXCIsIDUsIDE1LCBcImJldGFUYXVHMVwiLCBsb2dnZXIpO1xuICAgICAgICBpZiAoIXJlcykgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGF3YWl0IGZkLmNsb3NlKCk7XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIlBvd2VycyBvZiBUYXUgT2shXCIpO1xuXG4gICAgcmV0dXJuIHRydWU7XG5cbiAgICBmdW5jdGlvbiBwcmludENvbnRyaWJ1dGlvbihjdXJDb250ciwgcHJldkNvbnRyKSB7XG4gICAgICAgIGlmICghbG9nZ2VyKSByZXR1cm47XG4gICAgICAgIGxvZ2dlci5pbmZvKFwiLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGxvZ2dlci5pbmZvKGBDb250cmlidXRpb24gIyR7Y3VyQ29udHIuaWR9OiAke2N1ckNvbnRyLm5hbWUgfHxcIlwifWApO1xuXG4gICAgICAgIGxvZ2dlci5pbmZvKG1pc2MuZm9ybWF0SGFzaChjdXJDb250ci5uZXh0Q2hhbGxlbmdlLCBcIk5leHQgQ2hhbGxlbmdlOiBcIikpO1xuXG4gICAgICAgIGNvbnN0IGJ1ZmZWICA9IG5ldyBVaW50OEFycmF5KGN1cnZlLkcxLkYubjgqMio2K2N1cnZlLkcyLkYubjgqMiozKTtcbiAgICAgICAgdXRpbHMudG9QdGF1UHViS2V5UnByKGJ1ZmZWLCAwLCBjdXJ2ZSwgY3VyQ29udHIua2V5LCBmYWxzZSk7XG5cbiAgICAgICAgY29uc3QgcmVzcG9uc2VIYXNoZXIgPSAgbWlzYy5mcm9tUGFydGlhbEhhc2goY3VyQ29udHIucGFydGlhbEhhc2gpO1xuICAgICAgICByZXNwb25zZUhhc2hlci51cGRhdGUoYnVmZlYpO1xuICAgICAgICBjb25zdCByZXNwb25zZUhhc2ggPSByZXNwb25zZUhhc2hlci5kaWdlc3QoKTtcblxuICAgICAgICBsb2dnZXIuaW5mbyhtaXNjLmZvcm1hdEhhc2gocmVzcG9uc2VIYXNoLCBcIlJlc3BvbnNlIEhhc2g6XCIpKTtcblxuICAgICAgICBsb2dnZXIuaW5mbyhtaXNjLmZvcm1hdEhhc2gocHJldkNvbnRyLm5leHRDaGFsbGVuZ2UsIFwiUmVzcG9uc2UgSGFzaDpcIikpO1xuXG4gICAgICAgIGlmIChjdXJDb250ci50eXBlID09IDEpIHtcbiAgICAgICAgICAgIGxvZ2dlci5pbmZvKGBCZWFjb24gZ2VuZXJhdG9yOiAke21pc2MuYnl0ZUFycmF5MmhleChjdXJDb250ci5iZWFjb25IYXNoKX1gKTtcbiAgICAgICAgICAgIGxvZ2dlci5pbmZvKGBCZWFjb24gaXRlcmF0aW9ucyBFeHA6ICR7Y3VyQ29udHIubnVtSXRlcmF0aW9uc0V4cH1gKTtcbiAgICAgICAgfVxuXG4gICAgfVxuXG4gICAgYXN5bmMgZnVuY3Rpb24gcHJvY2Vzc1NlY3Rpb25CZXRhRzIobG9nZ2VyKSB7XG4gICAgICAgIGNvbnN0IEcgPSBjdXJ2ZS5HMjtcbiAgICAgICAgY29uc3Qgc0cgPSBHLkYubjgqMjtcbiAgICAgICAgY29uc3QgYnVmZlV2ID0gbmV3IFVpbnQ4QXJyYXkoc0cpO1xuXG4gICAgICAgIGlmICghc2VjdGlvbnNbNl0pICB7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoXCJGaWxlIGhhcyBubyBCZXRhRzIgc2VjdGlvblwiKTtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkZpbGUgaGFzIG5vIEJldGFHMiBzZWN0aW9uXCIpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzZWN0aW9uc1s2XS5sZW5ndGg+MSkge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFwiRmlsZSBoYXMgbm8gQmV0YUcyIHNlY3Rpb25cIik7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJGaWxlIGhhcyBtb3JlIHRoYW4gb25lIEdldGFHMiBzZWN0aW9uXCIpO1xuICAgICAgICB9XG4gICAgICAgIGZkLnBvcyA9IHNlY3Rpb25zWzZdWzBdLnA7XG5cbiAgICAgICAgY29uc3QgYnVmZiA9IGF3YWl0IGZkLnJlYWQoc0cpO1xuICAgICAgICBjb25zdCBQID0gRy5mcm9tUnByTEVNKGJ1ZmYpO1xuXG4gICAgICAgIEcudG9ScHJVbmNvbXByZXNzZWQoYnVmZlV2LCAwLCBQKTtcbiAgICAgICAgbmV4dENvbnRyaWJ1dGlvbkhhc2hlci51cGRhdGUoYnVmZlV2KTtcblxuICAgICAgICByZXR1cm4gUDtcbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiBwcm9jZXNzU2VjdGlvbihpZFNlY3Rpb24sIGdyb3VwTmFtZSwgc2VjdGlvbk5hbWUsIG5Qb2ludHMsIHNpbmd1bGFyUG9pbnRJbmRleGVzLCBsb2dnZXIpIHtcbiAgICAgICAgY29uc3QgTUFYX0NIVU5LX1NJWkUgPSAxPDwxNjtcbiAgICAgICAgY29uc3QgRyA9IGN1cnZlW2dyb3VwTmFtZV07XG4gICAgICAgIGNvbnN0IHNHID0gRy5GLm44KjI7XG4gICAgICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFJlYWRVbmlxdWVTZWN0aW9uKGZkLCBzZWN0aW9ucywgaWRTZWN0aW9uKTtcblxuICAgICAgICBjb25zdCBzaW5ndWxhclBvaW50cyA9IFtdO1xuXG4gICAgICAgIGxldCBSMSA9IEcuemVybztcbiAgICAgICAgbGV0IFIyID0gRy56ZXJvO1xuXG4gICAgICAgIGxldCBsYXN0QmFzZSA9IEcuemVybztcblxuICAgICAgICBmb3IgKGxldCBpPTA7IGk8blBvaW50czsgaSArPSBNQVhfQ0hVTktfU0laRSkge1xuICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKGBwb2ludHMgcmVsYXRpb25zOiAke3NlY3Rpb25OYW1lfTogJHtpfS8ke25Qb2ludHN9IGApO1xuICAgICAgICAgICAgY29uc3QgbiA9IE1hdGgubWluKG5Qb2ludHMgLSBpLCBNQVhfQ0hVTktfU0laRSk7XG4gICAgICAgICAgICBjb25zdCBiYXNlcyA9IGF3YWl0IGZkLnJlYWQobipzRyk7XG5cbiAgICAgICAgICAgIGNvbnN0IGJhc2VzVSA9IGF3YWl0IEcuYmF0Y2hMRU10b1UoYmFzZXMpO1xuICAgICAgICAgICAgbmV4dENvbnRyaWJ1dGlvbkhhc2hlci51cGRhdGUoYmFzZXNVKTtcblxuICAgICAgICAgICAgY29uc3Qgc2NhbGFycyA9IG1pc2MuZ2V0UmFuZG9tQnl0ZXMoNCoobi0xKSk7XG5cbiAgICAgICAgICAgIGlmIChpPjApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBmaXJzdEJhc2UgPSBHLmZyb21ScHJMRU0oYmFzZXMsIDApO1xuICAgICAgICAgICAgICAgIGNvbnN0IHIgPSBtaXNjLnJlYWRVSW50MzJCRShtaXNjLmdldFJhbmRvbUJ5dGVzKDQpLCAwKTtcblxuICAgICAgICAgICAgICAgIFIxID0gRy5hZGQoUjEsIEcudGltZXNTY2FsYXIobGFzdEJhc2UsIHIpKTtcbiAgICAgICAgICAgICAgICBSMiA9IEcuYWRkKFIyLCBHLnRpbWVzU2NhbGFyKGZpcnN0QmFzZSwgcikpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCByMSA9IGF3YWl0IEcubXVsdGlFeHBBZmZpbmUoYmFzZXMuc2xpY2UoMCwgKG4tMSkqc0cpLCBzY2FsYXJzKTtcbiAgICAgICAgICAgIGNvbnN0IHIyID0gYXdhaXQgRy5tdWx0aUV4cEFmZmluZShiYXNlcy5zbGljZShzRyksIHNjYWxhcnMpO1xuXG4gICAgICAgICAgICBSMSA9IEcuYWRkKFIxLCByMSk7XG4gICAgICAgICAgICBSMiA9IEcuYWRkKFIyLCByMik7XG5cbiAgICAgICAgICAgIGxhc3RCYXNlID0gRy5mcm9tUnByTEVNKCBiYXNlcywgKG4tMSkqc0cpO1xuXG4gICAgICAgICAgICBmb3IgKGxldCBqPTA7IGo8c2luZ3VsYXJQb2ludEluZGV4ZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzcCA9IHNpbmd1bGFyUG9pbnRJbmRleGVzW2pdO1xuICAgICAgICAgICAgICAgIGlmICgoc3AgPj1pKSAmJiAoc3AgPCBpK24pKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IFAgPSBHLmZyb21ScHJMRU0oYmFzZXMsIChzcC1pKSpzRyk7XG4gICAgICAgICAgICAgICAgICAgIHNpbmd1bGFyUG9pbnRzLnB1c2goUCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgYmluRmlsZVV0aWxzLmVuZFJlYWRTZWN0aW9uKGZkKTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgUjE6IFIxLFxuICAgICAgICAgICAgUjI6IFIyLFxuICAgICAgICAgICAgc2luZ3VsYXJQb2ludHM6IHNpbmd1bGFyUG9pbnRzXG4gICAgICAgIH07XG5cbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiB2ZXJpZnlMYWdyYW5nZUV2YWx1YXRpb25zKGdOYW1lLCB0YXVTZWN0aW9uLCBsYWdyYW5nZVNlY3Rpb24sIHNlY3Rpb25OYW1lLCBsb2dnZXIpIHtcblxuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoYFZlcmlmeWluZyBwaGFzZTIgY2FsY3VsYXRlZCB2YWx1ZXMgJHtzZWN0aW9uTmFtZX0uLi5gKTtcbiAgICAgICAgY29uc3QgRyA9IGN1cnZlW2dOYW1lXTtcbiAgICAgICAgY29uc3Qgc0cgPSBHLkYubjgqMjtcblxuICAgICAgICBjb25zdCBzZWVkPSBuZXcgQXJyYXkoOCk7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTw4OyBpKyspIHtcbiAgICAgICAgICAgIHNlZWRbaV0gPSBtaXNjLnJlYWRVSW50MzJCRShtaXNjLmdldFJhbmRvbUJ5dGVzKDQpLCAwKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAobGV0IHA9MDsgcDw9IHBvd2VyOyBwICsrKSB7XG4gICAgICAgICAgICBjb25zdCByZXMgPSBhd2FpdCB2ZXJpZnlQb3dlcihwKTtcbiAgICAgICAgICAgIGlmICghcmVzKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGF1U2VjdGlvbiA9PSAyKSB7XG4gICAgICAgICAgICBjb25zdCByZXMgPSBhd2FpdCB2ZXJpZnlQb3dlcihwb3dlcisxKTtcbiAgICAgICAgICAgIGlmICghcmVzKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdHJ1ZTtcblxuICAgICAgICBhc3luYyBmdW5jdGlvbiB2ZXJpZnlQb3dlcihwKSB7XG4gICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoYFBvd2VyICR7cH0uLi5gKTtcbiAgICAgICAgICAgIGNvbnN0IG44ciA9IGN1cnZlLkZyLm44O1xuICAgICAgICAgICAgY29uc3QgblBvaW50cyA9IDIgKiogcDtcbiAgICAgICAgICAgIGxldCBidWZmX3IgPSBuZXcgVWludDMyQXJyYXkoblBvaW50cyk7XG4gICAgICAgICAgICBsZXQgYnVmZkc7XG5cbiAgICAgICAgICAgIGxldCBybmcgPSBuZXcgQ2hhQ2hhKHNlZWQpO1xuXG4gICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoYENyZWF0aW5nIHJhbmRvbSBudW1iZXJzIFBvd2VycyR7cH0uLi5gKTtcbiAgICAgICAgICAgIGZvciAobGV0IGk9MDsgaTxuUG9pbnRzOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoKHAgPT0gcG93ZXIrMSkmJihpID09IG5Qb2ludHMtMSkpIHtcbiAgICAgICAgICAgICAgICAgICAgYnVmZl9yW2ldID0gMDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBidWZmX3JbaV0gPSBybmcubmV4dFUzMigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYnVmZl9yID0gbmV3IFVpbnQ4QXJyYXkoYnVmZl9yLmJ1ZmZlciwgYnVmZl9yLmJ5dGVPZmZzZXQsIGJ1ZmZfci5ieXRlTGVuZ3RoKTtcblxuICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKGByZWFkaW5nIHBvaW50cyBQb3dlcnMke3B9Li4uYCk7XG4gICAgICAgICAgICBhd2FpdCBiaW5GaWxlVXRpbHMuc3RhcnRSZWFkVW5pcXVlU2VjdGlvbihmZCwgc2VjdGlvbnMsIHRhdVNlY3Rpb24pO1xuICAgICAgICAgICAgYnVmZkcgPSBuZXcgQmlnQnVmZmVyKG5Qb2ludHMqc0cpO1xuICAgICAgICAgICAgaWYgKHAgPT0gcG93ZXIrMSkge1xuICAgICAgICAgICAgICAgIGF3YWl0IGZkLnJlYWRUb0J1ZmZlcihidWZmRywgMCwgKG5Qb2ludHMtMSkqc0cpO1xuICAgICAgICAgICAgICAgIGJ1ZmZHLnNldChjdXJ2ZS5HMS56ZXJvQWZmaW5lLCAoblBvaW50cy0xKSpzRyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGF3YWl0IGZkLnJlYWRUb0J1ZmZlcihidWZmRywgMCwgblBvaW50cypzRyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kUmVhZFNlY3Rpb24oZmQsIHRydWUpO1xuXG4gICAgICAgICAgICBjb25zdCByZXNUYXUgPSBhd2FpdCBHLm11bHRpRXhwQWZmaW5lKGJ1ZmZHLCBidWZmX3IsIGxvZ2dlciwgc2VjdGlvbk5hbWUgKyBcIl9cIiArIHApO1xuXG4gICAgICAgICAgICBidWZmX3IgPSBuZXcgQmlnQnVmZmVyKG5Qb2ludHMgKiBuOHIpO1xuXG4gICAgICAgICAgICBybmcgPSBuZXcgQ2hhQ2hhKHNlZWQpO1xuXG4gICAgICAgICAgICBjb25zdCBidWZmNCA9IG5ldyBVaW50OEFycmF5KDQpO1xuICAgICAgICAgICAgY29uc3QgYnVmZjRWID0gbmV3IERhdGFWaWV3KGJ1ZmY0LmJ1ZmZlcik7XG5cbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhgQ3JlYXRpbmcgcmFuZG9tIG51bWJlcnMgUG93ZXJzJHtwfS4uLmApO1xuICAgICAgICAgICAgZm9yIChsZXQgaT0wOyBpPG5Qb2ludHM7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmICgoaSAhPSBuUG9pbnRzLTEpIHx8IChwICE9IHBvd2VyKzEpKSB7XG4gICAgICAgICAgICAgICAgICAgIGJ1ZmY0Vi5zZXRVaW50MzIoMCwgcm5nLm5leHRVMzIoKSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIGJ1ZmZfci5zZXQoYnVmZjQsIGkqbjhyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhgYmF0Y2hUb01vbnRnb21lcnkgJHtwfS4uLmApO1xuICAgICAgICAgICAgYnVmZl9yID0gYXdhaXQgY3VydmUuRnIuYmF0Y2hUb01vbnRnb21lcnkoYnVmZl9yKTtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhgZmZ0ICR7cH0uLi5gKTtcbiAgICAgICAgICAgIGJ1ZmZfciA9IGF3YWl0IGN1cnZlLkZyLmZmdChidWZmX3IpO1xuICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKGBiYXRjaEZyb21Nb250Z29tZXJ5ICR7cH0uLi5gKTtcbiAgICAgICAgICAgIGJ1ZmZfciA9IGF3YWl0IGN1cnZlLkZyLmJhdGNoRnJvbU1vbnRnb21lcnkoYnVmZl9yKTtcblxuICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKGByZWFkaW5nIHBvaW50cyBMYWdyYW5nZSR7cH0uLi5gKTtcbiAgICAgICAgICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFJlYWRVbmlxdWVTZWN0aW9uKGZkLCBzZWN0aW9ucywgbGFncmFuZ2VTZWN0aW9uKTtcbiAgICAgICAgICAgIGZkLnBvcyArPSBzRyooKDIgKiogcCktMSk7XG4gICAgICAgICAgICBhd2FpdCBmZC5yZWFkVG9CdWZmZXIoYnVmZkcsIDAsIG5Qb2ludHMqc0cpO1xuICAgICAgICAgICAgYXdhaXQgYmluRmlsZVV0aWxzLmVuZFJlYWRTZWN0aW9uKGZkLCB0cnVlKTtcblxuICAgICAgICAgICAgY29uc3QgcmVzTGFncmFuZ2UgPSBhd2FpdCBHLm11bHRpRXhwQWZmaW5lKGJ1ZmZHLCBidWZmX3IsIGxvZ2dlciwgc2VjdGlvbk5hbWUgKyBcIl9cIiArIHAgKyBcIl90cmFuc2Zvcm1lZFwiKTtcblxuICAgICAgICAgICAgaWYgKCFHLmVxKHJlc1RhdSwgcmVzTGFncmFuZ2UpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiUGhhc2UyIGNhY2x1dGF0aW9uIGRvZXMgbm90IG1hdGNoIHdpdGggcG93ZXJzIG9mIHRhdVwiKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxufVxuIiwiLypcbiAgICBDb3B5cmlnaHQgMjAxOCAwS0lNUyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJrSlMuXG5cbiAgICBzbmFya0pTIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICAgIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gICAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAgICAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtKUyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVFxuICAgIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpY1xuICAgIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gICAgYWxvbmcgd2l0aCBzbmFya0pTLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuaW1wb3J0ICogYXMgYmluRmlsZVV0aWxzIGZyb20gXCJAaWRlbjMvYmluZmlsZXV0aWxzXCI7XG5cbi8qXG4gICAgVGhpcyBmdW5jdGlvbiBjcmVhdGVzIGEgbmV3IHNlY3Rpb24gaW4gdGhlIGZkVG8gZmlsZSB3aXRoIGlkIGlkU2VjdGlvbi5cbiAgICBJdCBtdWx0aXBsaWVzIHRoZSBwb2ludHMgaW4gZmRGcm9tIGJ5IGZpcnN0LCBmaXJzdCppbmMsIGZpcnN0KmluY14yLCAuLi4uXG4gICAgblBvaW50IFRpbWVzLlxuICAgIEl0IGFsc28gdXBkYXRlcyB0aGUgbmV3Q2hhbGxlbmdlSGFzaGVyIHdpdGggdGhlIG5ldyBwb2ludHNcbiovXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhcHBseUtleVRvU2VjdGlvbihmZE9sZCwgc2VjdGlvbnMsIGZkTmV3LCBpZFNlY3Rpb24sIGN1cnZlLCBncm91cE5hbWUsIGZpcnN0LCBpbmMsIHNlY3Rpb25OYW1lLCBsb2dnZXIpIHtcbiAgICBjb25zdCBNQVhfQ0hVTktfU0laRSA9IDEgPDwgMTY7XG4gICAgY29uc3QgRyA9IGN1cnZlW2dyb3VwTmFtZV07XG4gICAgY29uc3Qgc0cgPSBHLkYubjgqMjtcbiAgICBjb25zdCBuUG9pbnRzID0gc2VjdGlvbnNbaWRTZWN0aW9uXVswXS5zaXplIC8gc0c7XG5cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuc3RhcnRSZWFkVW5pcXVlU2VjdGlvbihmZE9sZCwgc2VjdGlvbnMsaWRTZWN0aW9uICk7XG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLnN0YXJ0V3JpdGVTZWN0aW9uKGZkTmV3LCBpZFNlY3Rpb24pO1xuXG4gICAgbGV0IHQgPSBmaXJzdDtcbiAgICBmb3IgKGxldCBpPTA7IGk8blBvaW50czsgaSArPSBNQVhfQ0hVTktfU0laRSkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoYEFwcGx5aW5nIGtleTogJHtzZWN0aW9uTmFtZX06ICR7aX0vJHtuUG9pbnRzfWApO1xuICAgICAgICBjb25zdCBuPSBNYXRoLm1pbihuUG9pbnRzIC0gaSwgTUFYX0NIVU5LX1NJWkUpO1xuICAgICAgICBsZXQgYnVmZjtcbiAgICAgICAgYnVmZiA9IGF3YWl0IGZkT2xkLnJlYWQobipzRyk7XG4gICAgICAgIGJ1ZmYgPSBhd2FpdCBHLmJhdGNoQXBwbHlLZXkoYnVmZiwgdCwgaW5jKTtcbiAgICAgICAgYXdhaXQgZmROZXcud3JpdGUoYnVmZik7XG4gICAgICAgIHQgPSBjdXJ2ZS5Gci5tdWwodCwgY3VydmUuRnIuZXhwKGluYywgbikpO1xuICAgIH1cblxuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5lbmRXcml0ZVNlY3Rpb24oZmROZXcpO1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5lbmRSZWFkU2VjdGlvbihmZE9sZCk7XG59XG5cblxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYXBwbHlLZXlUb0NoYWxsZW5nZVNlY3Rpb24oZmRPbGQsIGZkTmV3LCByZXNwb25zZUhhc2hlciwgY3VydmUsIGdyb3VwTmFtZSwgblBvaW50cywgZmlyc3QsIGluYywgZm9ybWF0T3V0LCBzZWN0aW9uTmFtZSwgbG9nZ2VyKSB7XG4gICAgY29uc3QgRyA9IGN1cnZlW2dyb3VwTmFtZV07XG4gICAgY29uc3Qgc0cgPSBHLkYubjgqMjtcbiAgICBjb25zdCBjaHVua1NpemUgPSBNYXRoLmZsb29yKCgxPDwyMCkgLyBzRyk7ICAgLy8gMTI4TWIgY2h1bmtzXG4gICAgbGV0IHQgPSBmaXJzdDtcbiAgICBmb3IgKGxldCBpPTAgOyBpPG5Qb2ludHMgOyBpKz0gY2h1bmtTaXplKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhgQXBwbHlpbmcga2V5ICR7c2VjdGlvbk5hbWV9OiAke2l9LyR7blBvaW50c31gKTtcbiAgICAgICAgY29uc3Qgbj0gTWF0aC5taW4oblBvaW50cy1pLCBjaHVua1NpemUgKTtcbiAgICAgICAgY29uc3QgYnVmZkluVSA9IGF3YWl0IGZkT2xkLnJlYWQobiAqIHNHKTtcbiAgICAgICAgY29uc3QgYnVmZkluTEVNID0gYXdhaXQgRy5iYXRjaFV0b0xFTShidWZmSW5VKTtcbiAgICAgICAgY29uc3QgYnVmZk91dExFTSA9IGF3YWl0IEcuYmF0Y2hBcHBseUtleShidWZmSW5MRU0sIHQsIGluYyk7XG4gICAgICAgIGxldCBidWZmT3V0O1xuICAgICAgICBpZiAoZm9ybWF0T3V0ID09IFwiQ09NUFJFU1NFRFwiKSB7XG4gICAgICAgICAgICBidWZmT3V0ID0gYXdhaXQgRy5iYXRjaExFTXRvQyhidWZmT3V0TEVNKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGJ1ZmZPdXQgPSBhd2FpdCBHLmJhdGNoTEVNdG9VKGJ1ZmZPdXRMRU0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJlc3BvbnNlSGFzaGVyKSByZXNwb25zZUhhc2hlci51cGRhdGUoYnVmZk91dCk7XG4gICAgICAgIGF3YWl0IGZkTmV3LndyaXRlKGJ1ZmZPdXQpO1xuICAgICAgICB0ID0gY3VydmUuRnIubXVsKHQsIGN1cnZlLkZyLmV4cChpbmMsIG4pKTtcbiAgICB9XG59XG5cbiIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMTggMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya0pTLlxuXG4gICAgc25hcmtKUyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJrSlMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggc25hcmtKUy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbi8vIEZvcm1hdCBvZiB0aGUgb3V0cHV0XG4vLyAgICAgIEhhc2ggb2YgdGhlIGxhc3QgY29udHJpYnV0aW9uICA2NCBCeXRlc1xuLy8gICAgICAyXk4qMi0xIFRhdUcxIFBvaW50cyAoY29tcHJlc3NlZClcbi8vICAgICAgMl5OIFRhdUcyIFBvaW50cyAoY29tcHJlc3NlZClcbi8vICAgICAgMl5OIEFscGhhVGF1RzEgUG9pbnRzIChjb21wcmVzc2VkKVxuLy8gICAgICAyXk4gQmV0YVRhdUcxIFBvaW50cyAoY29tcHJlc3NlZClcbi8vICAgICAgUHVibGljIEtleVxuLy8gICAgICAgICAgQmV0YUcyIChjb21wcmVzc2VkKVxuLy8gICAgICAgICAgRzEqcyAoY29tcHJlc3NlZClcbi8vICAgICAgICAgIEcxKnMqdGF1IChjb21wcmVzc2VkKVxuLy8gICAgICAgICAgRzEqdCAoY29tcHJlc3NlZClcbi8vICAgICAgICAgIEcxKnQqYWxwaGEgKGNvbXByZXNzZWQpXG4vLyAgICAgICAgICBHMSp1IChjb21wcmVzc2VkKVxuLy8gICAgICAgICAgRzEqdSpiZXRhIChjb21wcmVzc2VkKVxuLy8gICAgICAgICAgRzIqc3AqdGF1IChjb21wcmVzc2VkKVxuLy8gICAgICAgICAgRzIqdHAqYWxwaGEgKGNvbXByZXNzZWQpXG4vLyAgICAgICAgICBHMip1cCpiZXRhIChjb21wcmVzc2VkKVxuXG5pbXBvcnQgKiBhcyBmYXN0RmlsZSBmcm9tIFwiZmFzdGZpbGVcIjtcbmltcG9ydCB7IGJsYWtlMmIgfSBmcm9tIFwiQG5vYmxlL2hhc2hlcy9ibGFrZTJiXCI7XG5pbXBvcnQgKiBhcyB1dGlscyBmcm9tIFwiLi9wb3dlcnNvZnRhdV91dGlscy5qc1wiO1xuaW1wb3J0ICogYXMgbWlzYyBmcm9tIFwiLi9taXNjLmpzXCI7XG5pbXBvcnQgeyBhcHBseUtleVRvQ2hhbGxlbmdlU2VjdGlvbiB9IGZyb20gXCIuL21wY19hcHBseWtleS5qc1wiO1xuaW1wb3J0ICogYXMga2V5UGFpciBmcm9tIFwiLi9rZXlwYWlyLmpzXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uIGNoYWxsZW5nZUNvbnRyaWJ1dGUoY3VydmUsIGNoYWxsZW5nZUZpbGVuYW1lLCByZXNwb25zZUZpbGVOYW1lLCBlbnRyb3B5LCBsb2dnZXIpIHtcbiAgICBjb25zdCBmZEZyb20gPSBhd2FpdCBmYXN0RmlsZS5yZWFkRXhpc3RpbmcoY2hhbGxlbmdlRmlsZW5hbWUpO1xuXG5cbiAgICBjb25zdCBzRzEgPSBjdXJ2ZS5GMS5uNjQqOCoyO1xuICAgIGNvbnN0IHNHMiA9IGN1cnZlLkYyLm42NCo4KjI7XG4gICAgY29uc3QgZG9tYWluU2l6ZSA9IChmZEZyb20udG90YWxTaXplICsgc0cxIC0gNjQgLSBzRzIpIC8gKDQqc0cxICsgc0cyKTtcbiAgICBsZXQgZSA9IGRvbWFpblNpemU7XG4gICAgbGV0IHBvd2VyID0gMDtcbiAgICB3aGlsZSAoZT4xKSB7XG4gICAgICAgIGUgPSBlIC8yO1xuICAgICAgICBwb3dlciArPSAxO1xuICAgIH1cblxuICAgIGlmICgyICoqIHBvd2VyICE9IGRvbWFpblNpemUpIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgZmlsZSBzaXplXCIpO1xuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIlBvd2VyIHRvIHRhdSBzaXplOiBcIitwb3dlcik7XG5cbiAgICBjb25zdCBybmcgPSBhd2FpdCBtaXNjLmdldFJhbmRvbVJuZyhlbnRyb3B5KTtcblxuICAgIGNvbnN0IGZkVG8gPSBhd2FpdCBmYXN0RmlsZS5jcmVhdGVPdmVycmlkZShyZXNwb25zZUZpbGVOYW1lKTtcblxuICAgIC8vIENhbGN1bGF0ZSB0aGUgaGFzaFxuICAgIGNvbnN0IGNoYWxsZW5nZUhhc2hlciA9IGJsYWtlMmIuY3JlYXRlKHsgZGtMZW46IDY0IH0pO1xuICAgIGZvciAobGV0IGk9MDsgaTxmZEZyb20udG90YWxTaXplOyBpKz0gZmRGcm9tLnBhZ2VTaXplKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhgSGFzaGluZyBjaGFsbGVuZ2UgJHtpfS8ke2ZkRnJvbS50b3RhbFNpemV9YCk7XG4gICAgICAgIGNvbnN0IHMgPSBNYXRoLm1pbihmZEZyb20udG90YWxTaXplIC0gaSwgZmRGcm9tLnBhZ2VTaXplKTtcbiAgICAgICAgY29uc3QgYnVmZiA9IGF3YWl0IGZkRnJvbS5yZWFkKHMpO1xuICAgICAgICBjaGFsbGVuZ2VIYXNoZXIudXBkYXRlKGJ1ZmYpO1xuICAgIH1cblxuICAgIGNvbnN0IGNsYWltZWRIYXNoID0gYXdhaXQgZmRGcm9tLnJlYWQoNjQsIDApO1xuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKG1pc2MuZm9ybWF0SGFzaChjbGFpbWVkSGFzaCwgXCJDbGFpbWVkIFByZXZpb3VzIFJlc3BvbnNlIEhhc2g6IFwiKSk7XG5cbiAgICBjb25zdCBjaGFsbGVuZ2VIYXNoID0gY2hhbGxlbmdlSGFzaGVyLmRpZ2VzdCgpO1xuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKG1pc2MuZm9ybWF0SGFzaChjaGFsbGVuZ2VIYXNoLCBcIkN1cnJlbnQgQ2hhbGxlbmdlIEhhc2g6IFwiKSk7XG5cbiAgICBjb25zdCBrZXkgPSBrZXlQYWlyLmNyZWF0ZVBUYXVLZXkoY3VydmUsIGNoYWxsZW5nZUhhc2gsIHJuZyk7XG5cbiAgICBpZiAobG9nZ2VyKSB7XG4gICAgICAgIFtcInRhdVwiLCBcImFscGhhXCIsIFwiYmV0YVwiXS5mb3JFYWNoKCAoaykgPT4ge1xuICAgICAgICAgICAgbG9nZ2VyLmRlYnVnKGsgKyBcIi5nMV9zOiBcIiArIGN1cnZlLkcxLnRvU3RyaW5nKGtleVtrXS5nMV9zLCAxNikpO1xuICAgICAgICAgICAgbG9nZ2VyLmRlYnVnKGsgKyBcIi5nMV9zeDogXCIgKyBjdXJ2ZS5HMS50b1N0cmluZyhrZXlba10uZzFfc3gsIDE2KSk7XG4gICAgICAgICAgICBsb2dnZXIuZGVidWcoayArIFwiLmcyX3NwOiBcIiArIGN1cnZlLkcyLnRvU3RyaW5nKGtleVtrXS5nMl9zcCwgMTYpKTtcbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZyhrICsgXCIuZzJfc3B4OiBcIiArIGN1cnZlLkcyLnRvU3RyaW5nKGtleVtrXS5nMl9zcHgsIDE2KSk7XG4gICAgICAgICAgICBsb2dnZXIuZGVidWcoXCJcIik7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGNvbnN0IHJlc3BvbnNlSGFzaGVyID0gYmxha2UyYi5jcmVhdGUoeyBka0xlbjogNjQgfSk7XG5cbiAgICBhd2FpdCBmZFRvLndyaXRlKGNoYWxsZW5nZUhhc2gpO1xuICAgIHJlc3BvbnNlSGFzaGVyLnVwZGF0ZShjaGFsbGVuZ2VIYXNoKTtcblxuICAgIGF3YWl0IGFwcGx5S2V5VG9DaGFsbGVuZ2VTZWN0aW9uKGZkRnJvbSwgZmRUbywgcmVzcG9uc2VIYXNoZXIsIGN1cnZlLCBcIkcxXCIsICgyICoqIHBvd2VyKSoyLTEsIGN1cnZlLkZyLm9uZSAgICAsIGtleS50YXUucHJ2S2V5LCBcIkNPTVBSRVNTRURcIiwgXCJ0YXVHMVwiICAgICAsIGxvZ2dlciApO1xuICAgIGF3YWl0IGFwcGx5S2V5VG9DaGFsbGVuZ2VTZWN0aW9uKGZkRnJvbSwgZmRUbywgcmVzcG9uc2VIYXNoZXIsIGN1cnZlLCBcIkcyXCIsICgyICoqIHBvd2VyKSAgICAsIGN1cnZlLkZyLm9uZSAgICAsIGtleS50YXUucHJ2S2V5LCBcIkNPTVBSRVNTRURcIiwgXCJ0YXVHMlwiICAgICAsIGxvZ2dlciApO1xuICAgIGF3YWl0IGFwcGx5S2V5VG9DaGFsbGVuZ2VTZWN0aW9uKGZkRnJvbSwgZmRUbywgcmVzcG9uc2VIYXNoZXIsIGN1cnZlLCBcIkcxXCIsICgyICoqIHBvd2VyKSAgICAsIGtleS5hbHBoYS5wcnZLZXksIGtleS50YXUucHJ2S2V5LCBcIkNPTVBSRVNTRURcIiwgXCJhbHBoYVRhdUcxXCIsIGxvZ2dlciApO1xuICAgIGF3YWl0IGFwcGx5S2V5VG9DaGFsbGVuZ2VTZWN0aW9uKGZkRnJvbSwgZmRUbywgcmVzcG9uc2VIYXNoZXIsIGN1cnZlLCBcIkcxXCIsICgyICoqIHBvd2VyKSAgICAsIGtleS5iZXRhLnBydktleSAsIGtleS50YXUucHJ2S2V5LCBcIkNPTVBSRVNTRURcIiwgXCJiZXRhVGF1RzFcIiAsIGxvZ2dlciApO1xuICAgIGF3YWl0IGFwcGx5S2V5VG9DaGFsbGVuZ2VTZWN0aW9uKGZkRnJvbSwgZmRUbywgcmVzcG9uc2VIYXNoZXIsIGN1cnZlLCBcIkcyXCIsIDEgICAgICAgICAgICAgLCBrZXkuYmV0YS5wcnZLZXkgLCBrZXkudGF1LnBydktleSwgXCJDT01QUkVTU0VEXCIsIFwiYmV0YVRhdUcyXCIgLCBsb2dnZXIgKTtcblxuICAgIC8vIFdyaXRlIGFuZCBoYXNoIGtleVxuICAgIGNvbnN0IGJ1ZmZLZXkgPSBuZXcgVWludDhBcnJheShjdXJ2ZS5GMS5uOCoyKjYrY3VydmUuRjIubjgqMiozKTtcbiAgICB1dGlscy50b1B0YXVQdWJLZXlScHIoYnVmZktleSwgMCwgY3VydmUsIGtleSwgZmFsc2UpO1xuICAgIGF3YWl0IGZkVG8ud3JpdGUoYnVmZktleSk7XG4gICAgcmVzcG9uc2VIYXNoZXIudXBkYXRlKGJ1ZmZLZXkpO1xuICAgIGNvbnN0IHJlc3BvbnNlSGFzaCA9IHJlc3BvbnNlSGFzaGVyLmRpZ2VzdCgpO1xuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKG1pc2MuZm9ybWF0SGFzaChyZXNwb25zZUhhc2gsIFwiQ29udHJpYnV0aW9uIFJlc3BvbnNlIEhhc2g6IFwiKSk7XG5cbiAgICBhd2FpdCBmZFRvLmNsb3NlKCk7XG4gICAgYXdhaXQgZmRGcm9tLmNsb3NlKCk7XG59XG5cbiIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMTggMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya0pTLlxuXG4gICAgc25hcmtKUyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJrSlMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggc25hcmtKUy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbmltcG9ydCB7IGJsYWtlMmIgfSBmcm9tIFwiQG5vYmxlL2hhc2hlcy9ibGFrZTJiXCI7XG5pbXBvcnQgKiBhcyB1dGlscyBmcm9tIFwiLi9wb3dlcnNvZnRhdV91dGlscy5qc1wiO1xuaW1wb3J0ICogYXMgbWlzYyBmcm9tIFwiLi9taXNjLmpzXCI7XG5pbXBvcnQgKiBhcyBiaW5GaWxlVXRpbHMgZnJvbSBcIkBpZGVuMy9iaW5maWxldXRpbHNcIjtcblxuZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gYmVhY29uKG9sZFB0YXVGaWxlbmFtZSwgbmV3UFRhdUZpbGVuYW1lLCBuYW1lLCAgYmVhY29uSGFzaFN0cixudW1JdGVyYXRpb25zRXhwLCBsb2dnZXIpIHtcbiAgICBjb25zdCBiZWFjb25IYXNoID0gbWlzYy5oZXgyQnl0ZUFycmF5KGJlYWNvbkhhc2hTdHIpO1xuICAgIGlmICggICAoYmVhY29uSGFzaC5ieXRlTGVuZ3RoID09IDApXG4gICAgICAgIHx8IChiZWFjb25IYXNoLmJ5dGVMZW5ndGgqMiAhPWJlYWNvbkhhc2hTdHIubGVuZ3RoKSlcbiAgICB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihcIkludmFsaWQgQmVhY29uIEhhc2guIChJdCBtdXN0IGJlIGEgdmFsaWQgaGV4YWRlY2ltYWwgc2VxdWVuY2UpXCIpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmIChiZWFjb25IYXNoLmxlbmd0aD49MjU2KSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihcIk1heGltdW0gbGVuZ3RoIG9mIGJlYWNvbiBoYXNoIGlzIDI1NSBieXRlc1wiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIG51bUl0ZXJhdGlvbnNFeHAgPSBwYXJzZUludChudW1JdGVyYXRpb25zRXhwKTtcbiAgICBpZiAoKG51bUl0ZXJhdGlvbnNFeHA8MTApfHwobnVtSXRlcmF0aW9uc0V4cD42MykpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiSW52YWxpZCBudW1JdGVyYXRpb25zRXhwLiAoTXVzdCBiZSBiZXR3ZWVuIDEwIGFuZCA2MylcIik7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cblxuICAgIGNvbnN0IHtmZDogZmRPbGQsIHNlY3Rpb25zfSA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkQmluRmlsZShvbGRQdGF1RmlsZW5hbWUsIFwicHRhdVwiLCAxKTtcbiAgICBjb25zdCB7Y3VydmUsIHBvd2VyLCBjZXJlbW9ueVBvd2VyfSA9IGF3YWl0IHV0aWxzLnJlYWRQVGF1SGVhZGVyKGZkT2xkLCBzZWN0aW9ucyk7XG4gICAgaWYgKHBvd2VyICE9IGNlcmVtb255UG93ZXIpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiVGhpcyBmaWxlIGhhcyBiZWVuIHJlZHVjZWQuIFlvdSBjYW5ub3QgY29udHJpYnV0ZSBpbnRvIGEgcmVkdWNlZCBmaWxlLlwiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAoc2VjdGlvbnNbMTJdKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci53YXJuKFwiQ29udHJpYnV0aW5nIGludG8gYSBmaWxlIHRoYXQgaGFzIHBoYXNlMiBjYWxjdWxhdGVkLiBZb3Ugd2lsbCBoYXZlIHRvIHByZXBhcmUgcGhhc2UyIGFnYWluLlwiKTtcbiAgICB9XG4gICAgY29uc3QgY29udHJpYnV0aW9ucyA9IGF3YWl0IHV0aWxzLnJlYWRDb250cmlidXRpb25zKGZkT2xkLCBjdXJ2ZSwgc2VjdGlvbnMpO1xuICAgIGNvbnN0IGN1ckNvbnRyaWJ1dGlvbiA9IHtcbiAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgdHlwZTogMSwgLy8gQmVhY29uXG4gICAgICAgIG51bUl0ZXJhdGlvbnNFeHA6IG51bUl0ZXJhdGlvbnNFeHAsXG4gICAgICAgIGJlYWNvbkhhc2g6IGJlYWNvbkhhc2hcbiAgICB9O1xuXG4gICAgbGV0IGxhc3RDaGFsbGVuZ2VIYXNoO1xuXG4gICAgaWYgKGNvbnRyaWJ1dGlvbnMubGVuZ3RoPjApIHtcbiAgICAgICAgbGFzdENoYWxsZW5nZUhhc2ggPSBjb250cmlidXRpb25zW2NvbnRyaWJ1dGlvbnMubGVuZ3RoLTFdLm5leHRDaGFsbGVuZ2U7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbGFzdENoYWxsZW5nZUhhc2ggPSB1dGlscy5jYWxjdWxhdGVGaXJzdENoYWxsZW5nZUhhc2goY3VydmUsIHBvd2VyLCBsb2dnZXIpO1xuICAgIH1cblxuICAgIGN1ckNvbnRyaWJ1dGlvbi5rZXkgPSBhd2FpdCB1dGlscy5rZXlGcm9tQmVhY29uKGN1cnZlLCBsYXN0Q2hhbGxlbmdlSGFzaCwgYmVhY29uSGFzaCwgbnVtSXRlcmF0aW9uc0V4cCk7XG5cbiAgICBjb25zdCByZXNwb25zZUhhc2hlciA9IGJsYWtlMmIuY3JlYXRlKHsgZGtMZW46IDY0IH0pO1xuICAgIHJlc3BvbnNlSGFzaGVyLnVwZGF0ZShsYXN0Q2hhbGxlbmdlSGFzaCk7XG5cbiAgICBjb25zdCBmZE5ldyA9IGF3YWl0IGJpbkZpbGVVdGlscy5jcmVhdGVCaW5GaWxlKG5ld1BUYXVGaWxlbmFtZSwgXCJwdGF1XCIsIDEsIDcpO1xuICAgIGF3YWl0IHV0aWxzLndyaXRlUFRhdUhlYWRlcihmZE5ldywgY3VydmUsIHBvd2VyKTtcblxuICAgIGNvbnN0IHN0YXJ0U2VjdGlvbnMgPSBbXTtcblxuICAgIGxldCBmaXJzdFBvaW50cztcbiAgICBmaXJzdFBvaW50cyA9IGF3YWl0IHByb2Nlc3NTZWN0aW9uKDIsIFwiRzFcIiwgICgyICoqIHBvd2VyKSAqIDIgLTEsIGN1cnZlLkZyLmUoMSksIGN1ckNvbnRyaWJ1dGlvbi5rZXkudGF1LnBydktleSwgXCJ0YXVHMVwiLCBsb2dnZXIgKTtcbiAgICBjdXJDb250cmlidXRpb24udGF1RzEgPSBmaXJzdFBvaW50c1sxXTtcbiAgICBmaXJzdFBvaW50cyA9IGF3YWl0IHByb2Nlc3NTZWN0aW9uKDMsIFwiRzJcIiwgICgyICoqIHBvd2VyKSAsIGN1cnZlLkZyLmUoMSksIGN1ckNvbnRyaWJ1dGlvbi5rZXkudGF1LnBydktleSwgXCJ0YXVHMlwiLCBsb2dnZXIgKTtcbiAgICBjdXJDb250cmlidXRpb24udGF1RzIgPSBmaXJzdFBvaW50c1sxXTtcbiAgICBmaXJzdFBvaW50cyA9IGF3YWl0IHByb2Nlc3NTZWN0aW9uKDQsIFwiRzFcIiwgICgyICoqIHBvd2VyKSAsIGN1ckNvbnRyaWJ1dGlvbi5rZXkuYWxwaGEucHJ2S2V5LCBjdXJDb250cmlidXRpb24ua2V5LnRhdS5wcnZLZXksIFwiYWxwaGFUYXVHMVwiLCBsb2dnZXIgKTtcbiAgICBjdXJDb250cmlidXRpb24uYWxwaGFHMSA9IGZpcnN0UG9pbnRzWzBdO1xuICAgIGZpcnN0UG9pbnRzID0gYXdhaXQgcHJvY2Vzc1NlY3Rpb24oNSwgXCJHMVwiLCAgKDIgKiogcG93ZXIpICwgY3VyQ29udHJpYnV0aW9uLmtleS5iZXRhLnBydktleSwgY3VyQ29udHJpYnV0aW9uLmtleS50YXUucHJ2S2V5LCBcImJldGFUYXVHMVwiLCBsb2dnZXIgKTtcbiAgICBjdXJDb250cmlidXRpb24uYmV0YUcxID0gZmlyc3RQb2ludHNbMF07XG4gICAgZmlyc3RQb2ludHMgPSBhd2FpdCBwcm9jZXNzU2VjdGlvbig2LCBcIkcyXCIsICAxLCBjdXJDb250cmlidXRpb24ua2V5LmJldGEucHJ2S2V5LCBjdXJDb250cmlidXRpb24ua2V5LnRhdS5wcnZLZXksIFwiYmV0YVRhdUcyXCIsIGxvZ2dlciApO1xuICAgIGN1ckNvbnRyaWJ1dGlvbi5iZXRhRzIgPSBmaXJzdFBvaW50c1swXTtcblxuICAgIGN1ckNvbnRyaWJ1dGlvbi5wYXJ0aWFsSGFzaCA9IG1pc2MudG9QYXJ0aWFsSGFzaChyZXNwb25zZUhhc2hlcik7XG5cbiAgICBjb25zdCBidWZmS2V5ID0gbmV3IFVpbnQ4QXJyYXkoY3VydmUuRjEubjgqMio2K2N1cnZlLkYyLm44KjIqMyk7XG5cbiAgICB1dGlscy50b1B0YXVQdWJLZXlScHIoYnVmZktleSwgMCwgY3VydmUsIGN1ckNvbnRyaWJ1dGlvbi5rZXksIGZhbHNlKTtcblxuICAgIHJlc3BvbnNlSGFzaGVyLnVwZGF0ZShuZXcgVWludDhBcnJheShidWZmS2V5KSk7XG4gICAgY29uc3QgaGFzaFJlc3BvbnNlID0gcmVzcG9uc2VIYXNoZXIuZGlnZXN0KCk7XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhtaXNjLmZvcm1hdEhhc2goaGFzaFJlc3BvbnNlLCBcIkNvbnRyaWJ1dGlvbiBSZXNwb25zZSBIYXNoIGltcG9ydGVkOiBcIikpO1xuXG4gICAgY29uc3QgbmV4dENoYWxsZW5nZUhhc2hlciA9IGJsYWtlMmIuY3JlYXRlKHsgZGtMZW46IDY0IH0pO1xuICAgIG5leHRDaGFsbGVuZ2VIYXNoZXIudXBkYXRlKGhhc2hSZXNwb25zZSk7XG5cbiAgICBhd2FpdCBoYXNoU2VjdGlvbihmZE5ldywgXCJHMVwiLCAyLCAoMiAqKiBwb3dlcikgKiAyIC0xLCBcInRhdUcxXCIsIGxvZ2dlcik7XG4gICAgYXdhaXQgaGFzaFNlY3Rpb24oZmROZXcsIFwiRzJcIiwgMywgKDIgKiogcG93ZXIpICAgICAgICwgXCJ0YXVHMlwiLCBsb2dnZXIpO1xuICAgIGF3YWl0IGhhc2hTZWN0aW9uKGZkTmV3LCBcIkcxXCIsIDQsICgyICoqIHBvd2VyKSAgICAgICAsIFwiYWxwaGFUYXVHMVwiLCBsb2dnZXIpO1xuICAgIGF3YWl0IGhhc2hTZWN0aW9uKGZkTmV3LCBcIkcxXCIsIDUsICgyICoqIHBvd2VyKSAgICAgICAsIFwiYmV0YVRhdUcxXCIsIGxvZ2dlcik7XG4gICAgYXdhaXQgaGFzaFNlY3Rpb24oZmROZXcsIFwiRzJcIiwgNiwgMSAgICAgICAgICAgICAgICAgICwgXCJiZXRhRzJcIiwgbG9nZ2VyKTtcblxuICAgIGN1ckNvbnRyaWJ1dGlvbi5uZXh0Q2hhbGxlbmdlID0gbmV4dENoYWxsZW5nZUhhc2hlci5kaWdlc3QoKTtcblxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKG1pc2MuZm9ybWF0SGFzaChjdXJDb250cmlidXRpb24ubmV4dENoYWxsZW5nZSwgXCJOZXh0IENoYWxsZW5nZSBIYXNoOiBcIikpO1xuXG4gICAgY29udHJpYnV0aW9ucy5wdXNoKGN1ckNvbnRyaWJ1dGlvbik7XG5cbiAgICBhd2FpdCB1dGlscy53cml0ZUNvbnRyaWJ1dGlvbnMoZmROZXcsIGN1cnZlLCBjb250cmlidXRpb25zKTtcblxuICAgIGF3YWl0IGZkT2xkLmNsb3NlKCk7XG4gICAgYXdhaXQgZmROZXcuY2xvc2UoKTtcblxuICAgIHJldHVybiBoYXNoUmVzcG9uc2U7XG5cbiAgICBhc3luYyBmdW5jdGlvbiBwcm9jZXNzU2VjdGlvbihzZWN0aW9uSWQsIGdyb3VwTmFtZSwgTlBvaW50cywgZmlyc3QsIGluYywgc2VjdGlvbk5hbWUsIGxvZ2dlcikge1xuICAgICAgICBjb25zdCByZXMgPSBbXTtcbiAgICAgICAgZmRPbGQucG9zID0gc2VjdGlvbnNbc2VjdGlvbklkXVswXS5wO1xuXG4gICAgICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFdyaXRlU2VjdGlvbihmZE5ldywgc2VjdGlvbklkKTtcblxuICAgICAgICBzdGFydFNlY3Rpb25zW3NlY3Rpb25JZF0gPSBmZE5ldy5wb3M7XG5cbiAgICAgICAgY29uc3QgRyA9IGN1cnZlW2dyb3VwTmFtZV07XG4gICAgICAgIGNvbnN0IHNHID0gRy5GLm44KjI7XG4gICAgICAgIGNvbnN0IGNodW5rU2l6ZSA9IE1hdGguZmxvb3IoKDE8PDIwKSAvIHNHKTsgICAvLyAxMjhNYiBjaHVua3NcbiAgICAgICAgbGV0IHQgPSBmaXJzdDtcbiAgICAgICAgZm9yIChsZXQgaT0wIDsgaTxOUG9pbnRzIDsgaSs9IGNodW5rU2l6ZSkge1xuICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKGBhcHBseWluZyBrZXkke3NlY3Rpb25OYW1lfTogJHtpfS8ke05Qb2ludHN9YCk7XG4gICAgICAgICAgICBjb25zdCBuPSBNYXRoLm1pbihOUG9pbnRzLWksIGNodW5rU2l6ZSApO1xuICAgICAgICAgICAgY29uc3QgYnVmZkluID0gYXdhaXQgZmRPbGQucmVhZChuICogc0cpO1xuICAgICAgICAgICAgY29uc3QgYnVmZk91dExFTSA9IGF3YWl0IEcuYmF0Y2hBcHBseUtleShidWZmSW4sIHQsIGluYyk7XG5cbiAgICAgICAgICAgIC8qIENvZGUgdG8gdGVzdCB0aGUgY2FzZSB3aGVyZSB3ZSBkb24ndCBoYXZlIHRoZSAyXm0tMiBjb21wb25lbnRcbiAgICAgICAgICAgIGlmIChzZWN0aW9uTmFtZT09IFwidGF1RzFcIikge1xuICAgICAgICAgICAgICAgIGNvbnN0IGJ6ID0gbmV3IFVpbnQ4QXJyYXkoNjQpO1xuICAgICAgICAgICAgICAgIGJ1ZmZPdXRMRU0uc2V0KGJ6LCA2NCooKDIgKiogcG93ZXIpIC0gMSApKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgIGNvbnN0IHByb21pc2VXcml0ZSA9IGZkTmV3LndyaXRlKGJ1ZmZPdXRMRU0pO1xuICAgICAgICAgICAgY29uc3QgYnVmZk91dEMgPSBhd2FpdCBHLmJhdGNoTEVNdG9DKGJ1ZmZPdXRMRU0pO1xuXG4gICAgICAgICAgICByZXNwb25zZUhhc2hlci51cGRhdGUoYnVmZk91dEMpO1xuICAgICAgICAgICAgYXdhaXQgcHJvbWlzZVdyaXRlO1xuICAgICAgICAgICAgaWYgKGk9PTApICAgLy8gUmV0dXJuIHRoZSAyIGZpcnN0IHBvaW50cy5cbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqPTA7IGo8TWF0aC5taW4oMiwgTlBvaW50cyk7IGorKylcbiAgICAgICAgICAgICAgICAgICAgcmVzLnB1c2goRy5mcm9tUnByTEVNKGJ1ZmZPdXRMRU0sIGoqc0cpKTtcbiAgICAgICAgICAgIHQgPSBjdXJ2ZS5Gci5tdWwodCwgY3VydmUuRnIuZXhwKGluYywgbikpO1xuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgYmluRmlsZVV0aWxzLmVuZFdyaXRlU2VjdGlvbihmZE5ldyk7XG5cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cblxuICAgIGFzeW5jIGZ1bmN0aW9uIGhhc2hTZWN0aW9uKGZkVG8sIGdyb3VwTmFtZSwgc2VjdGlvbklkLCBuUG9pbnRzLCBzZWN0aW9uTmFtZSwgbG9nZ2VyKSB7XG5cbiAgICAgICAgY29uc3QgRyA9IGN1cnZlW2dyb3VwTmFtZV07XG4gICAgICAgIGNvbnN0IHNHID0gRy5GLm44KjI7XG4gICAgICAgIGNvbnN0IG5Qb2ludHNDaHVuayA9IE1hdGguZmxvb3IoKDE8PDI0KS9zRyk7XG5cbiAgICAgICAgY29uc3Qgb2xkUG9zID0gZmRUby5wb3M7XG4gICAgICAgIGZkVG8ucG9zID0gc3RhcnRTZWN0aW9uc1tzZWN0aW9uSWRdO1xuXG4gICAgICAgIGZvciAobGV0IGk9MDsgaTwgblBvaW50czsgaSArPSBuUG9pbnRzQ2h1bmspIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhgSGFzaGluZyAke3NlY3Rpb25OYW1lfTogJHtpfS8ke25Qb2ludHN9YCk7XG4gICAgICAgICAgICBjb25zdCBuID0gTWF0aC5taW4oblBvaW50cy1pLCBuUG9pbnRzQ2h1bmspO1xuXG4gICAgICAgICAgICBjb25zdCBidWZmTEVNID0gYXdhaXQgZmRUby5yZWFkKG4gKiBzRyk7XG5cbiAgICAgICAgICAgIGNvbnN0IGJ1ZmZVID0gYXdhaXQgRy5iYXRjaExFTXRvVShidWZmTEVNKTtcblxuICAgICAgICAgICAgbmV4dENoYWxsZW5nZUhhc2hlci51cGRhdGUoYnVmZlUpO1xuICAgICAgICB9XG5cbiAgICAgICAgZmRUby5wb3MgPSBvbGRQb3M7XG4gICAgfVxufVxuXG4iLCIvKlxuICAgIENvcHlyaWdodCAyMDE4IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygc25hcmtKUy5cblxuICAgIHNuYXJrSlMgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gICAgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAgICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICAgIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICBzbmFya0pTIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHNuYXJrSlMuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG4vLyBGb3JtYXQgb2YgdGhlIG91dHB1dFxuLy8gICAgICBIYXNoIG9mIHRoZSBsYXN0IGNvbnRyaWJ1dGlvbiAgNjQgQnl0ZXNcbi8vICAgICAgMl5OKjItMSBUYXVHMSBQb2ludHMgKHVuY29tcHJlc3NlZClcbi8vICAgICAgMl5OIFRhdUcyIFBvaW50cyAodW5jb21wcmVzc2VkKVxuLy8gICAgICAyXk4gQWxwaGFUYXVHMSBQb2ludHMgKHVuY29tcHJlc3NlZClcbi8vICAgICAgMl5OIEJldGFUYXVHMSBQb2ludHMgKHVuY29tcHJlc3NlZClcblxuaW1wb3J0IHsgYmxha2UyYiB9IGZyb20gXCJAbm9ibGUvaGFzaGVzL2JsYWtlMmJcIjtcbmltcG9ydCAqIGFzIHV0aWxzIGZyb20gXCIuL3Bvd2Vyc29mdGF1X3V0aWxzLmpzXCI7XG5pbXBvcnQgKiBhcyBrZXlQYWlyIGZyb20gXCIuL2tleXBhaXIuanNcIjtcbmltcG9ydCAqIGFzIGJpbkZpbGVVdGlscyBmcm9tIFwiQGlkZW4zL2JpbmZpbGV1dGlsc1wiO1xuaW1wb3J0ICogYXMgbWlzYyBmcm9tIFwiLi9taXNjLmpzXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uIGNvbnRyaWJ1dGUob2xkUHRhdUZpbGVuYW1lLCBuZXdQVGF1RmlsZW5hbWUsIG5hbWUsIGVudHJvcHksIGxvZ2dlcikge1xuXG4gICAgY29uc3Qge2ZkOiBmZE9sZCwgc2VjdGlvbnN9ID0gYXdhaXQgYmluRmlsZVV0aWxzLnJlYWRCaW5GaWxlKG9sZFB0YXVGaWxlbmFtZSwgXCJwdGF1XCIsIDEpO1xuICAgIGNvbnN0IHtjdXJ2ZSwgcG93ZXIsIGNlcmVtb255UG93ZXJ9ID0gYXdhaXQgdXRpbHMucmVhZFBUYXVIZWFkZXIoZmRPbGQsIHNlY3Rpb25zKTtcbiAgICBpZiAocG93ZXIgIT0gY2VyZW1vbnlQb3dlcikge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJUaGlzIGZpbGUgaGFzIGJlZW4gcmVkdWNlZC4gWW91IGNhbm5vdCBjb250cmlidXRlIGludG8gYSByZWR1Y2VkIGZpbGUuXCIpO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGlzIGZpbGUgaGFzIGJlZW4gcmVkdWNlZC4gWW91IGNhbm5vdCBjb250cmlidXRlIGludG8gYSByZWR1Y2VkIGZpbGUuXCIpO1xuICAgIH1cbiAgICBpZiAoc2VjdGlvbnNbMTJdKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci53YXJuKFwiV0FSTklORzogQ29udHJpYnV0aW5nIGludG8gYSBmaWxlIHRoYXQgaGFzIHBoYXNlMiBjYWxjdWxhdGVkLiBZb3Ugd2lsbCBoYXZlIHRvIHByZXBhcmUgcGhhc2UyIGFnYWluLlwiKTtcbiAgICB9XG4gICAgY29uc3QgY29udHJpYnV0aW9ucyA9IGF3YWl0IHV0aWxzLnJlYWRDb250cmlidXRpb25zKGZkT2xkLCBjdXJ2ZSwgc2VjdGlvbnMpO1xuICAgIGNvbnN0IGN1ckNvbnRyaWJ1dGlvbiA9IHtcbiAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgdHlwZTogMCwgLy8gQmVhY29uXG4gICAgfTtcblxuICAgIGxldCBsYXN0Q2hhbGxlbmdlSGFzaDtcblxuICAgIGNvbnN0IHJuZyA9IGF3YWl0IG1pc2MuZ2V0UmFuZG9tUm5nKGVudHJvcHkpO1xuXG4gICAgaWYgKGNvbnRyaWJ1dGlvbnMubGVuZ3RoPjApIHtcbiAgICAgICAgbGFzdENoYWxsZW5nZUhhc2ggPSBjb250cmlidXRpb25zW2NvbnRyaWJ1dGlvbnMubGVuZ3RoLTFdLm5leHRDaGFsbGVuZ2U7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbGFzdENoYWxsZW5nZUhhc2ggPSB1dGlscy5jYWxjdWxhdGVGaXJzdENoYWxsZW5nZUhhc2goY3VydmUsIHBvd2VyLCBsb2dnZXIpO1xuICAgIH1cblxuICAgIC8vIEdlbmVyYXRlIGEgcmFuZG9tIGtleVxuXG5cbiAgICBjdXJDb250cmlidXRpb24ua2V5ID0ga2V5UGFpci5jcmVhdGVQVGF1S2V5KGN1cnZlLCBsYXN0Q2hhbGxlbmdlSGFzaCwgcm5nKTtcblxuXG4gICAgY29uc3QgcmVzcG9uc2VIYXNoZXIgPSBibGFrZTJiLmNyZWF0ZSh7IGRrTGVuOiA2NCB9KTtcbiAgICByZXNwb25zZUhhc2hlci51cGRhdGUobGFzdENoYWxsZW5nZUhhc2gpO1xuXG4gICAgY29uc3QgZmROZXcgPSBhd2FpdCBiaW5GaWxlVXRpbHMuY3JlYXRlQmluRmlsZShuZXdQVGF1RmlsZW5hbWUsIFwicHRhdVwiLCAxLCA3KTtcbiAgICBhd2FpdCB1dGlscy53cml0ZVBUYXVIZWFkZXIoZmROZXcsIGN1cnZlLCBwb3dlcik7XG5cbiAgICBjb25zdCBzdGFydFNlY3Rpb25zID0gW107XG5cbiAgICBsZXQgZmlyc3RQb2ludHM7XG4gICAgZmlyc3RQb2ludHMgPSBhd2FpdCBwcm9jZXNzU2VjdGlvbigyLCBcIkcxXCIsICAoMiAqKiBwb3dlcikgKiAyIC0xLCBjdXJ2ZS5Gci5lKDEpLCBjdXJDb250cmlidXRpb24ua2V5LnRhdS5wcnZLZXksIFwidGF1RzFcIiApO1xuICAgIGN1ckNvbnRyaWJ1dGlvbi50YXVHMSA9IGZpcnN0UG9pbnRzWzFdO1xuICAgIGZpcnN0UG9pbnRzID0gYXdhaXQgcHJvY2Vzc1NlY3Rpb24oMywgXCJHMlwiLCAgKDIgKiogcG93ZXIpICwgY3VydmUuRnIuZSgxKSwgY3VyQ29udHJpYnV0aW9uLmtleS50YXUucHJ2S2V5LCBcInRhdUcyXCIgKTtcbiAgICBjdXJDb250cmlidXRpb24udGF1RzIgPSBmaXJzdFBvaW50c1sxXTtcbiAgICBmaXJzdFBvaW50cyA9IGF3YWl0IHByb2Nlc3NTZWN0aW9uKDQsIFwiRzFcIiwgICgyICoqIHBvd2VyKSAsIGN1ckNvbnRyaWJ1dGlvbi5rZXkuYWxwaGEucHJ2S2V5LCBjdXJDb250cmlidXRpb24ua2V5LnRhdS5wcnZLZXksIFwiYWxwaGFUYXVHMVwiICk7XG4gICAgY3VyQ29udHJpYnV0aW9uLmFscGhhRzEgPSBmaXJzdFBvaW50c1swXTtcbiAgICBmaXJzdFBvaW50cyA9IGF3YWl0IHByb2Nlc3NTZWN0aW9uKDUsIFwiRzFcIiwgICgyICoqIHBvd2VyKSAsIGN1ckNvbnRyaWJ1dGlvbi5rZXkuYmV0YS5wcnZLZXksIGN1ckNvbnRyaWJ1dGlvbi5rZXkudGF1LnBydktleSwgXCJiZXRhVGF1RzFcIiApO1xuICAgIGN1ckNvbnRyaWJ1dGlvbi5iZXRhRzEgPSBmaXJzdFBvaW50c1swXTtcbiAgICBmaXJzdFBvaW50cyA9IGF3YWl0IHByb2Nlc3NTZWN0aW9uKDYsIFwiRzJcIiwgIDEsIGN1ckNvbnRyaWJ1dGlvbi5rZXkuYmV0YS5wcnZLZXksIGN1ckNvbnRyaWJ1dGlvbi5rZXkudGF1LnBydktleSwgXCJiZXRhVGF1RzJcIiApO1xuICAgIGN1ckNvbnRyaWJ1dGlvbi5iZXRhRzIgPSBmaXJzdFBvaW50c1swXTtcblxuICAgIGN1ckNvbnRyaWJ1dGlvbi5wYXJ0aWFsSGFzaCA9IG1pc2MudG9QYXJ0aWFsSGFzaChyZXNwb25zZUhhc2hlcik7XG5cbiAgICBjb25zdCBidWZmS2V5ID0gbmV3IFVpbnQ4QXJyYXkoY3VydmUuRjEubjgqMio2K2N1cnZlLkYyLm44KjIqMyk7XG5cbiAgICB1dGlscy50b1B0YXVQdWJLZXlScHIoYnVmZktleSwgMCwgY3VydmUsIGN1ckNvbnRyaWJ1dGlvbi5rZXksIGZhbHNlKTtcblxuICAgIHJlc3BvbnNlSGFzaGVyLnVwZGF0ZShuZXcgVWludDhBcnJheShidWZmS2V5KSk7XG4gICAgY29uc3QgaGFzaFJlc3BvbnNlID0gcmVzcG9uc2VIYXNoZXIuZGlnZXN0KCk7XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhtaXNjLmZvcm1hdEhhc2goaGFzaFJlc3BvbnNlLCBcIkNvbnRyaWJ1dGlvbiBSZXNwb25zZSBIYXNoIGltcG9ydGVkOiBcIikpO1xuXG4gICAgY29uc3QgbmV4dENoYWxsZW5nZUhhc2hlciA9IGJsYWtlMmIuY3JlYXRlKHsgZGtMZW46IDY0IH0pO1xuICAgIG5leHRDaGFsbGVuZ2VIYXNoZXIudXBkYXRlKGhhc2hSZXNwb25zZSk7XG5cbiAgICBhd2FpdCBoYXNoU2VjdGlvbihmZE5ldywgXCJHMVwiLCAyLCAoMiAqKiBwb3dlcikgKiAyIC0xLCBcInRhdUcxXCIpO1xuICAgIGF3YWl0IGhhc2hTZWN0aW9uKGZkTmV3LCBcIkcyXCIsIDMsICgyICoqIHBvd2VyKSAgICAgICAsIFwidGF1RzJcIik7XG4gICAgYXdhaXQgaGFzaFNlY3Rpb24oZmROZXcsIFwiRzFcIiwgNCwgKDIgKiogcG93ZXIpICAgICAgICwgXCJhbHBoYVRhdUcxXCIpO1xuICAgIGF3YWl0IGhhc2hTZWN0aW9uKGZkTmV3LCBcIkcxXCIsIDUsICgyICoqIHBvd2VyKSAgICAgICAsIFwiYmV0YVRhdUcxXCIpO1xuICAgIGF3YWl0IGhhc2hTZWN0aW9uKGZkTmV3LCBcIkcyXCIsIDYsIDEgICAgICAgICAgICAgICAgICAsIFwiYmV0YUcyXCIpO1xuXG4gICAgY3VyQ29udHJpYnV0aW9uLm5leHRDaGFsbGVuZ2UgPSBuZXh0Q2hhbGxlbmdlSGFzaGVyLmRpZ2VzdCgpO1xuXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8obWlzYy5mb3JtYXRIYXNoKGN1ckNvbnRyaWJ1dGlvbi5uZXh0Q2hhbGxlbmdlLCBcIk5leHQgQ2hhbGxlbmdlIEhhc2g6IFwiKSk7XG5cbiAgICBjb250cmlidXRpb25zLnB1c2goY3VyQ29udHJpYnV0aW9uKTtcblxuICAgIGF3YWl0IHV0aWxzLndyaXRlQ29udHJpYnV0aW9ucyhmZE5ldywgY3VydmUsIGNvbnRyaWJ1dGlvbnMpO1xuXG4gICAgYXdhaXQgZmRPbGQuY2xvc2UoKTtcbiAgICBhd2FpdCBmZE5ldy5jbG9zZSgpO1xuXG4gICAgcmV0dXJuIGhhc2hSZXNwb25zZTtcblxuICAgIGFzeW5jIGZ1bmN0aW9uIHByb2Nlc3NTZWN0aW9uKHNlY3Rpb25JZCwgZ3JvdXBOYW1lLCBOUG9pbnRzLCBmaXJzdCwgaW5jLCBzZWN0aW9uTmFtZSkge1xuICAgICAgICBjb25zdCByZXMgPSBbXTtcbiAgICAgICAgZmRPbGQucG9zID0gc2VjdGlvbnNbc2VjdGlvbklkXVswXS5wO1xuXG4gICAgICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFdyaXRlU2VjdGlvbihmZE5ldywgc2VjdGlvbklkKTtcblxuICAgICAgICBzdGFydFNlY3Rpb25zW3NlY3Rpb25JZF0gPSBmZE5ldy5wb3M7XG5cbiAgICAgICAgY29uc3QgRyA9IGN1cnZlW2dyb3VwTmFtZV07XG4gICAgICAgIGNvbnN0IHNHID0gRy5GLm44KjI7XG4gICAgICAgIGNvbnN0IGNodW5rU2l6ZSA9IE1hdGguZmxvb3IoKDE8PDIwKSAvIHNHKTsgICAvLyAxMjhNYiBjaHVua3NcbiAgICAgICAgbGV0IHQgPSBmaXJzdDtcbiAgICAgICAgZm9yIChsZXQgaT0wIDsgaTxOUG9pbnRzIDsgaSs9IGNodW5rU2l6ZSkge1xuICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKGBwcm9jZXNzaW5nOiAke3NlY3Rpb25OYW1lfTogJHtpfS8ke05Qb2ludHN9YCk7XG4gICAgICAgICAgICBjb25zdCBuPSBNYXRoLm1pbihOUG9pbnRzLWksIGNodW5rU2l6ZSApO1xuICAgICAgICAgICAgY29uc3QgYnVmZkluID0gYXdhaXQgZmRPbGQucmVhZChuICogc0cpO1xuICAgICAgICAgICAgY29uc3QgYnVmZk91dExFTSA9IGF3YWl0IEcuYmF0Y2hBcHBseUtleShidWZmSW4sIHQsIGluYyk7XG5cbiAgICAgICAgICAgIC8qIENvZGUgdG8gdGVzdCB0aGUgY2FzZSB3aGVyZSB3ZSBkb24ndCBoYXZlIHRoZSAyXm0tMiBjb21wb25lbnRcbiAgICAgICAgICAgIGlmIChzZWN0aW9uTmFtZT09IFwidGF1RzFcIikge1xuICAgICAgICAgICAgICAgIGNvbnN0IGJ6ID0gbmV3IFVpbnQ4QXJyYXkoNjQpO1xuICAgICAgICAgICAgICAgIGJ1ZmZPdXRMRU0uc2V0KGJ6LCA2NCooKDIgKiogcG93ZXIpIC0gMSApKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgIGNvbnN0IHByb21pc2VXcml0ZSA9IGZkTmV3LndyaXRlKGJ1ZmZPdXRMRU0pO1xuICAgICAgICAgICAgY29uc3QgYnVmZk91dEMgPSBhd2FpdCBHLmJhdGNoTEVNdG9DKGJ1ZmZPdXRMRU0pO1xuXG4gICAgICAgICAgICByZXNwb25zZUhhc2hlci51cGRhdGUoYnVmZk91dEMpO1xuICAgICAgICAgICAgYXdhaXQgcHJvbWlzZVdyaXRlO1xuICAgICAgICAgICAgaWYgKGk9PTApICAgLy8gUmV0dXJuIHRoZSAyIGZpcnN0IHBvaW50cy5cbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqPTA7IGo8TWF0aC5taW4oMiwgTlBvaW50cyk7IGorKylcbiAgICAgICAgICAgICAgICAgICAgcmVzLnB1c2goRy5mcm9tUnByTEVNKGJ1ZmZPdXRMRU0sIGoqc0cpKTtcbiAgICAgICAgICAgIHQgPSBjdXJ2ZS5Gci5tdWwodCwgY3VydmUuRnIuZXhwKGluYywgbikpO1xuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgYmluRmlsZVV0aWxzLmVuZFdyaXRlU2VjdGlvbihmZE5ldyk7XG5cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cblxuICAgIGFzeW5jIGZ1bmN0aW9uIGhhc2hTZWN0aW9uKGZkVG8sIGdyb3VwTmFtZSwgc2VjdGlvbklkLCBuUG9pbnRzLCBzZWN0aW9uTmFtZSkge1xuXG4gICAgICAgIGNvbnN0IEcgPSBjdXJ2ZVtncm91cE5hbWVdO1xuICAgICAgICBjb25zdCBzRyA9IEcuRi5uOCoyO1xuICAgICAgICBjb25zdCBuUG9pbnRzQ2h1bmsgPSBNYXRoLmZsb29yKCgxPDwyNCkvc0cpO1xuXG4gICAgICAgIGNvbnN0IG9sZFBvcyA9IGZkVG8ucG9zO1xuICAgICAgICBmZFRvLnBvcyA9IHN0YXJ0U2VjdGlvbnNbc2VjdGlvbklkXTtcblxuICAgICAgICBmb3IgKGxldCBpPTA7IGk8IG5Qb2ludHM7IGkgKz0gblBvaW50c0NodW5rKSB7XG4gICAgICAgICAgICBpZiAoKGxvZ2dlcikmJmkpIGxvZ2dlci5kZWJ1ZyhgSGFzaGluZyAke3NlY3Rpb25OYW1lfTogYCArIGkpO1xuICAgICAgICAgICAgY29uc3QgbiA9IE1hdGgubWluKG5Qb2ludHMtaSwgblBvaW50c0NodW5rKTtcblxuICAgICAgICAgICAgY29uc3QgYnVmZkxFTSA9IGF3YWl0IGZkVG8ucmVhZChuICogc0cpO1xuXG4gICAgICAgICAgICBjb25zdCBidWZmVSA9IGF3YWl0IEcuYmF0Y2hMRU10b1UoYnVmZkxFTSk7XG5cbiAgICAgICAgICAgIG5leHRDaGFsbGVuZ2VIYXNoZXIudXBkYXRlKGJ1ZmZVKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZkVG8ucG9zID0gb2xkUG9zO1xuICAgIH1cblxuXG59XG5cbiIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMTggMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya0pTLlxuXG4gICAgc25hcmtKUyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJrSlMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggc25hcmtKUy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbmltcG9ydCAqIGFzIGJpbkZpbGVVdGlscyBmcm9tIFwiQGlkZW4zL2JpbmZpbGV1dGlsc1wiO1xuaW1wb3J0ICogYXMgdXRpbHMgZnJvbSBcIi4vcG93ZXJzb2Z0YXVfdXRpbHMuanNcIjtcbmltcG9ydCB7QmlnQnVmZmVyfSBmcm9tIFwiZmZqYXZhc2NyaXB0XCI7XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uIHByZXBhcmVQaGFzZTIob2xkUHRhdUZpbGVuYW1lLCBuZXdQVGF1RmlsZW5hbWUsIGxvZ2dlcikge1xuXG4gICAgY29uc3Qge2ZkOiBmZE9sZCwgc2VjdGlvbnN9ID0gYXdhaXQgYmluRmlsZVV0aWxzLnJlYWRCaW5GaWxlKG9sZFB0YXVGaWxlbmFtZSwgXCJwdGF1XCIsIDEpO1xuICAgIGNvbnN0IHtjdXJ2ZSwgcG93ZXJ9ID0gYXdhaXQgdXRpbHMucmVhZFBUYXVIZWFkZXIoZmRPbGQsIHNlY3Rpb25zKTtcblxuICAgIGNvbnN0IGZkTmV3ID0gYXdhaXQgYmluRmlsZVV0aWxzLmNyZWF0ZUJpbkZpbGUobmV3UFRhdUZpbGVuYW1lLCBcInB0YXVcIiwgMSwgMTEpO1xuICAgIGF3YWl0IHV0aWxzLndyaXRlUFRhdUhlYWRlcihmZE5ldywgY3VydmUsIHBvd2VyKTtcblxuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5jb3B5U2VjdGlvbihmZE9sZCwgc2VjdGlvbnMsIGZkTmV3LCAyKTtcbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuY29weVNlY3Rpb24oZmRPbGQsIHNlY3Rpb25zLCBmZE5ldywgMyk7XG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmNvcHlTZWN0aW9uKGZkT2xkLCBzZWN0aW9ucywgZmROZXcsIDQpO1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5jb3B5U2VjdGlvbihmZE9sZCwgc2VjdGlvbnMsIGZkTmV3LCA1KTtcbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuY29weVNlY3Rpb24oZmRPbGQsIHNlY3Rpb25zLCBmZE5ldywgNik7XG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmNvcHlTZWN0aW9uKGZkT2xkLCBzZWN0aW9ucywgZmROZXcsIDcpO1xuXG4gICAgYXdhaXQgcHJvY2Vzc1NlY3Rpb24oMiwgMTIsIFwiRzFcIiwgXCJ0YXVHMVwiICk7XG4gICAgYXdhaXQgcHJvY2Vzc1NlY3Rpb24oMywgMTMsIFwiRzJcIiwgXCJ0YXVHMlwiICk7XG4gICAgYXdhaXQgcHJvY2Vzc1NlY3Rpb24oNCwgMTQsIFwiRzFcIiwgXCJhbHBoYVRhdUcxXCIgKTtcbiAgICBhd2FpdCBwcm9jZXNzU2VjdGlvbig1LCAxNSwgXCJHMVwiLCBcImJldGFUYXVHMVwiICk7XG5cbiAgICBhd2FpdCBmZE9sZC5jbG9zZSgpO1xuICAgIGF3YWl0IGZkTmV3LmNsb3NlKCk7XG5cbiAgICAvLyBhd2FpdCBmcy5wcm9taXNlcy51bmxpbmsobmV3UFRhdUZpbGVuYW1lKyBcIi50bXBcIik7XG5cbiAgICByZXR1cm47XG5cbiAgICBhc3luYyBmdW5jdGlvbiBwcm9jZXNzU2VjdGlvbihvbGRTZWN0aW9uSWQsIG5ld1NlY3Rpb25JZCwgR3N0ciwgc2VjdGlvbk5hbWUpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKFwiU3RhcnRpbmcgc2VjdGlvbjogXCIrc2VjdGlvbk5hbWUpO1xuXG4gICAgICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFdyaXRlU2VjdGlvbihmZE5ldywgbmV3U2VjdGlvbklkKTtcblxuICAgICAgICBmb3IgKGxldCBwPTA7IHA8PXBvd2VyOyBwKyspIHtcbiAgICAgICAgICAgIGF3YWl0IHByb2Nlc3NTZWN0aW9uUG93ZXIocCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAob2xkU2VjdGlvbklkID09IDIpIHtcbiAgICAgICAgICAgIGF3YWl0IHByb2Nlc3NTZWN0aW9uUG93ZXIocG93ZXIrMSk7XG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kV3JpdGVTZWN0aW9uKGZkTmV3KTtcblxuXG4gICAgICAgIGFzeW5jIGZ1bmN0aW9uIHByb2Nlc3NTZWN0aW9uUG93ZXIocCkge1xuICAgICAgICAgICAgY29uc3QgblBvaW50cyA9IDIgKiogcDtcbiAgICAgICAgICAgIGNvbnN0IEcgPSBjdXJ2ZVtHc3RyXTtcbiAgICAgICAgICAgIGNvbnN0IEZyID0gY3VydmUuRnI7XG4gICAgICAgICAgICBjb25zdCBzR2luID0gRy5GLm44KjI7XG4gICAgICAgICAgICBjb25zdCBzR21pZCA9IEcuRi5uOCozO1xuXG4gICAgICAgICAgICBsZXQgYnVmZjtcbiAgICAgICAgICAgIGJ1ZmYgPSBuZXcgQmlnQnVmZmVyKG5Qb2ludHMqc0dpbik7XG5cbiAgICAgICAgICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFJlYWRVbmlxdWVTZWN0aW9uKGZkT2xkLCBzZWN0aW9ucywgb2xkU2VjdGlvbklkKTtcbiAgICAgICAgICAgIGlmICgob2xkU2VjdGlvbklkID09IDIpJiYocD09cG93ZXIrMSkpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCBmZE9sZC5yZWFkVG9CdWZmZXIoYnVmZiwgMCwoblBvaW50cy0xKSpzR2luICk7XG4gICAgICAgICAgICAgICAgYnVmZi5zZXQoY3VydmUuRzEuemVyb0FmZmluZSwgKG5Qb2ludHMtMSkqc0dpbiApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhd2FpdCBmZE9sZC5yZWFkVG9CdWZmZXIoYnVmZiwgMCxuUG9pbnRzKnNHaW4gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGF3YWl0IGJpbkZpbGVVdGlscy5lbmRSZWFkU2VjdGlvbihmZE9sZCwgdHJ1ZSk7XG5cblxuICAgICAgICAgICAgYnVmZiA9IGF3YWl0IEcubGFncmFuZ2VFdmFsdWF0aW9ucyhidWZmLCBcImFmZmluZVwiLCBcImFmZmluZVwiLCBsb2dnZXIsIHNlY3Rpb25OYW1lKTtcbiAgICAgICAgICAgIGF3YWl0IGZkTmV3LndyaXRlKGJ1ZmYpO1xuXG4vKlxuICAgICAgICAgICAgaWYgKHAgPD0gY3VydmUuRnIucykge1xuICAgICAgICAgICAgICAgIGJ1ZmYgPSBhd2FpdCBHLmlmZnQoYnVmZiwgXCJhZmZpbmVcIiwgXCJhZmZpbmVcIiwgbG9nZ2VyLCBzZWN0aW9uTmFtZSk7XG4gICAgICAgICAgICAgICAgYXdhaXQgZmROZXcud3JpdGUoYnVmZik7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHAgPT0gY3VydmUuRnIucysxKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc21hbGxNID0gMTw8Y3VydmUuRnIucztcbiAgICAgICAgICAgICAgICBsZXQgdDAgPSBuZXcgQmlnQnVmZmVyKCBzbWFsbE0gKiBzR21pZCApO1xuICAgICAgICAgICAgICAgIGxldCB0MSA9IG5ldyBCaWdCdWZmZXIoIHNtYWxsTSAqIHNHbWlkICk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBzaGlmdF90b19zbWFsbF9tID0gRnIuZXhwKEZyLnNoaWZ0LCBzbWFsbE0pO1xuICAgICAgICAgICAgICAgIGNvbnN0IG9uZV9vdmVyX2Rlbm9tID0gRnIuaW52KEZyLnN1YihzaGlmdF90b19zbWFsbF9tLCBGci5vbmUpKTtcblxuICAgICAgICAgICAgICAgIGxldCBzSW52QWNjID0gRnIub25lO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGk9MDsgaTxzbWFsbE07IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB0aSA9ICBidWZmLnNsaWNlKGkqc0dpbiwgKGkrMSkqc0dpbik7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRtaSA9IGJ1ZmYuc2xpY2UoKGkrc21hbGxNKSpzR2luLCAoaStzbWFsbE0rMSkqc0dpbik7XG5cbiAgICAgICAgICAgICAgICAgICAgdDAuc2V0KFxuICAgICAgICAgICAgICAgICAgICAgICAgRy50aW1lc0ZyKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEcuc3ViKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHLnRpbWVzRnIodGkgLCBzaGlmdF90b19zbWFsbF9tKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbmVfb3Zlcl9kZW5vbVxuICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGkqc0dtaWRcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgdDEuc2V0KFxuICAgICAgICAgICAgICAgICAgICAgICAgRy50aW1lc0ZyKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEcuc3ViKCB0bWksIHRpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBGci5tdWwoc0ludkFjYywgb25lX292ZXJfZGVub20pXG4gICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgaSpzR21pZFxuICAgICAgICAgICAgICAgICAgICApO1xuXG5cbiAgICAgICAgICAgICAgICAgICAgc0ludkFjYyA9IEZyLm11bChzSW52QWNjLCBGci5zaGlmdEludik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHQwID0gYXdhaXQgRy5pZmZ0KHQwLCBcImphY29iaWFuXCIsIFwiYWZmaW5lXCIsIGxvZ2dlciwgc2VjdGlvbk5hbWUgKyBcIiB0MFwiKTtcbiAgICAgICAgICAgICAgICBhd2FpdCBmZE5ldy53cml0ZSh0MCk7XG4gICAgICAgICAgICAgICAgdDAgPSBudWxsO1xuICAgICAgICAgICAgICAgIHQxID0gYXdhaXQgRy5pZmZ0KHQxLCBcImphY29iaWFuXCIsIFwiYWZmaW5lXCIsIGxvZ2dlciwgc2VjdGlvbk5hbWUgKyBcIiB0MFwiKTtcbiAgICAgICAgICAgICAgICBhd2FpdCBmZE5ldy53cml0ZSh0MSk7XG5cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiUG93ZXIgdG9vIGJpZ1wiKTtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJQb3dlciB0byBiaWdcIik7XG4gICAgICAgICAgICB9XG4qL1xuICAgICAgICB9XG4gICAgfVxufVxuXG4iLCIvKlxuICAgIENvcHlyaWdodCAyMDE4IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygc25hcmtKUy5cblxuICAgIHNuYXJrSlMgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gICAgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAgICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICAgIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICBzbmFya0pTIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHNuYXJrSlMuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG5pbXBvcnQgKiBhcyBiaW5GaWxlVXRpbHMgZnJvbSBcIkBpZGVuMy9iaW5maWxldXRpbHNcIjtcbmltcG9ydCAqIGFzIHV0aWxzIGZyb20gXCIuL3Bvd2Vyc29mdGF1X3V0aWxzLmpzXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uIHRydW5jYXRlKHB0YXVGaWxlbmFtZSwgdGVtcGxhdGUsIGxvZ2dlcikge1xuXG4gICAgY29uc3Qge2ZkOiBmZE9sZCwgc2VjdGlvbnN9ID0gYXdhaXQgYmluRmlsZVV0aWxzLnJlYWRCaW5GaWxlKHB0YXVGaWxlbmFtZSwgXCJwdGF1XCIsIDEpO1xuICAgIGNvbnN0IHtjdXJ2ZSwgcG93ZXIsIGNlcmVtb255UG93ZXJ9ID0gYXdhaXQgdXRpbHMucmVhZFBUYXVIZWFkZXIoZmRPbGQsIHNlY3Rpb25zKTtcblxuICAgIGNvbnN0IHNHMSA9IGN1cnZlLkcxLkYubjgqMjtcbiAgICBjb25zdCBzRzIgPSBjdXJ2ZS5HMi5GLm44KjI7XG5cbiAgICBmb3IgKGxldCBwPTE7IHA8cG93ZXI7IHArKykge1xuICAgICAgICBhd2FpdCBnZW5lcmF0ZVRydW5jYXRlKHApO1xuICAgIH1cblxuICAgIGF3YWl0IGZkT2xkLmNsb3NlKCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcblxuICAgIGFzeW5jIGZ1bmN0aW9uIGdlbmVyYXRlVHJ1bmNhdGUocCkge1xuXG4gICAgICAgIGxldCBzUCA9IHAudG9TdHJpbmcoKTtcbiAgICAgICAgd2hpbGUgKHNQLmxlbmd0aDwyKSBzUCA9IFwiMFwiICsgc1A7XG5cbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKFwiV3JpdGluZyBQb3dlcjogXCIrc1ApO1xuXG4gICAgICAgIGNvbnN0IGZkTmV3ID0gYXdhaXQgYmluRmlsZVV0aWxzLmNyZWF0ZUJpbkZpbGUodGVtcGxhdGUgKyBzUCArIFwiLnB0YXVcIiwgXCJwdGF1XCIsIDEsIDExKTtcbiAgICAgICAgYXdhaXQgdXRpbHMud3JpdGVQVGF1SGVhZGVyKGZkTmV3LCBjdXJ2ZSwgcCwgY2VyZW1vbnlQb3dlcik7XG5cbiAgICAgICAgYXdhaXQgYmluRmlsZVV0aWxzLmNvcHlTZWN0aW9uKGZkT2xkLCBzZWN0aW9ucywgZmROZXcsIDIsICgoMiAqKiBwKSoyLTEpICogc0cxICk7IC8vIHRhZ0cxXG4gICAgICAgIGF3YWl0IGJpbkZpbGVVdGlscy5jb3B5U2VjdGlvbihmZE9sZCwgc2VjdGlvbnMsIGZkTmV3LCAzLCAoMiAqKiBwKSAqIHNHMik7IC8vIHRhdUcyXG4gICAgICAgIGF3YWl0IGJpbkZpbGVVdGlscy5jb3B5U2VjdGlvbihmZE9sZCwgc2VjdGlvbnMsIGZkTmV3LCA0LCAoMiAqKiBwKSAqIHNHMSk7IC8vIGFsZmFUYXVHMVxuICAgICAgICBhd2FpdCBiaW5GaWxlVXRpbHMuY29weVNlY3Rpb24oZmRPbGQsIHNlY3Rpb25zLCBmZE5ldywgNSwgKDIgKiogcCkgKiBzRzEpOyAvLyBiZXRhVGF1RzFcbiAgICAgICAgYXdhaXQgYmluRmlsZVV0aWxzLmNvcHlTZWN0aW9uKGZkT2xkLCBzZWN0aW9ucywgZmROZXcsIDYsICBzRzIpOyAvLyBiZXRhVGF1RzJcbiAgICAgICAgYXdhaXQgYmluRmlsZVV0aWxzLmNvcHlTZWN0aW9uKGZkT2xkLCBzZWN0aW9ucywgZmROZXcsIDcpOyAvLyBjb250cmlidXRpb25zXG4gICAgICAgIGF3YWl0IGJpbkZpbGVVdGlscy5jb3B5U2VjdGlvbihmZE9sZCwgc2VjdGlvbnMsIGZkTmV3LCAxMiwgKCgyICoqIChwKzEpKSoyIC0xKSAqIHNHMSk7IC8vIExfdGF1RzFcbiAgICAgICAgYXdhaXQgYmluRmlsZVV0aWxzLmNvcHlTZWN0aW9uKGZkT2xkLCBzZWN0aW9ucywgZmROZXcsIDEzLCAoKDIgKiogcCkqMiAtMSkgKiBzRzIpOyAvLyBMX3RhdUcyXG4gICAgICAgIGF3YWl0IGJpbkZpbGVVdGlscy5jb3B5U2VjdGlvbihmZE9sZCwgc2VjdGlvbnMsIGZkTmV3LCAxNCwgKCgyICoqIHApKjIgLTEpICogc0cxKTsgLy8gTF9hbGZhVGF1RzFcbiAgICAgICAgYXdhaXQgYmluRmlsZVV0aWxzLmNvcHlTZWN0aW9uKGZkT2xkLCBzZWN0aW9ucywgZmROZXcsIDE1LCAoKDIgKiogcCkqMiAtMSkgKiBzRzEpOyAvLyBMX2JldGFUYXVHMVxuXG4gICAgICAgIGF3YWl0IGZkTmV3LmNsb3NlKCk7XG4gICAgfVxuXG5cbn1cbiIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMTggMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya0pTLlxuXG4gICAgc25hcmtKUyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJrSlMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggc25hcmtKUy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbmltcG9ydCAqIGFzIGJpbkZpbGVVdGlscyBmcm9tIFwiQGlkZW4zL2JpbmZpbGV1dGlsc1wiO1xuaW1wb3J0ICogYXMgdXRpbHMgZnJvbSBcIi4vcG93ZXJzb2Z0YXVfdXRpbHMuanNcIjtcbmltcG9ydCAqIGFzIGZhc3RGaWxlIGZyb20gXCJmYXN0ZmlsZVwiO1xuaW1wb3J0IHtCaWdCdWZmZXJ9IGZyb20gXCJmZmphdmFzY3JpcHRcIjtcblxuZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gY29udmVydChvbGRQdGF1RmlsZW5hbWUsIG5ld1BUYXVGaWxlbmFtZSwgbG9nZ2VyKSB7XG5cbiAgICBjb25zdCB7ZmQ6IGZkT2xkLCBzZWN0aW9uc30gPSBhd2FpdCBiaW5GaWxlVXRpbHMucmVhZEJpbkZpbGUob2xkUHRhdUZpbGVuYW1lLCBcInB0YXVcIiwgMSk7XG4gICAgY29uc3Qge2N1cnZlLCBwb3dlcn0gPSBhd2FpdCB1dGlscy5yZWFkUFRhdUhlYWRlcihmZE9sZCwgc2VjdGlvbnMpO1xuXG4gICAgY29uc3QgZmROZXcgPSBhd2FpdCBiaW5GaWxlVXRpbHMuY3JlYXRlQmluRmlsZShuZXdQVGF1RmlsZW5hbWUsIFwicHRhdVwiLCAxLCAxMSk7XG4gICAgYXdhaXQgdXRpbHMud3JpdGVQVGF1SGVhZGVyKGZkTmV3LCBjdXJ2ZSwgcG93ZXIpO1xuXG4gICAgLy8gY29uc3QgZmRUbXAgPSBhd2FpdCBmYXN0RmlsZS5jcmVhdGVPdmVycmlkZShuZXdQVGF1RmlsZW5hbWUrIFwiLnRtcFwiKTtcblxuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5jb3B5U2VjdGlvbihmZE9sZCwgc2VjdGlvbnMsIGZkTmV3LCAyKTtcbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuY29weVNlY3Rpb24oZmRPbGQsIHNlY3Rpb25zLCBmZE5ldywgMyk7XG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmNvcHlTZWN0aW9uKGZkT2xkLCBzZWN0aW9ucywgZmROZXcsIDQpO1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5jb3B5U2VjdGlvbihmZE9sZCwgc2VjdGlvbnMsIGZkTmV3LCA1KTtcbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuY29weVNlY3Rpb24oZmRPbGQsIHNlY3Rpb25zLCBmZE5ldywgNik7XG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmNvcHlTZWN0aW9uKGZkT2xkLCBzZWN0aW9ucywgZmROZXcsIDcpO1xuXG4gICAgYXdhaXQgcHJvY2Vzc1NlY3Rpb24oMiwgMTIsIFwiRzFcIiwgXCJ0YXVHMVwiICk7XG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmNvcHlTZWN0aW9uKGZkT2xkLCBzZWN0aW9ucywgZmROZXcsIDEzKTtcbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuY29weVNlY3Rpb24oZmRPbGQsIHNlY3Rpb25zLCBmZE5ldywgMTQpO1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5jb3B5U2VjdGlvbihmZE9sZCwgc2VjdGlvbnMsIGZkTmV3LCAxNSk7XG5cbiAgICBhd2FpdCBmZE9sZC5jbG9zZSgpO1xuICAgIGF3YWl0IGZkTmV3LmNsb3NlKCk7XG5cbiAgICAvLyBhd2FpdCBmcy5wcm9taXNlcy51bmxpbmsobmV3UFRhdUZpbGVuYW1lKyBcIi50bXBcIik7XG5cbiAgICByZXR1cm47XG5cbiAgICBhc3luYyBmdW5jdGlvbiBwcm9jZXNzU2VjdGlvbihvbGRTZWN0aW9uSWQsIG5ld1NlY3Rpb25JZCwgR3N0ciwgc2VjdGlvbk5hbWUpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKFwiU3RhcnRpbmcgc2VjdGlvbjogXCIrc2VjdGlvbk5hbWUpO1xuXG4gICAgICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFdyaXRlU2VjdGlvbihmZE5ldywgbmV3U2VjdGlvbklkKTtcblxuICAgICAgICBjb25zdCBzaXplID0gc2VjdGlvbnNbbmV3U2VjdGlvbklkXVswXS5zaXplO1xuICAgICAgICBjb25zdCBjaHVua1NpemUgPSBmZE9sZC5wYWdlU2l6ZTtcbiAgICAgICAgYXdhaXQgYmluRmlsZVV0aWxzLnN0YXJ0UmVhZFVuaXF1ZVNlY3Rpb24oZmRPbGQsIHNlY3Rpb25zLCBuZXdTZWN0aW9uSWQpO1xuICAgICAgICBmb3IgKGxldCBwPTA7IHA8c2l6ZTsgcCs9Y2h1bmtTaXplKSB7XG4gICAgICAgICAgICBjb25zdCBsID0gTWF0aC5taW4oc2l6ZSAtcCwgY2h1bmtTaXplKTtcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmYgPSBhd2FpdCBmZE9sZC5yZWFkKGwpO1xuICAgICAgICAgICAgYXdhaXQgZmROZXcud3JpdGUoYnVmZik7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgYmluRmlsZVV0aWxzLmVuZFJlYWRTZWN0aW9uKGZkT2xkKTtcblxuICAgICAgICBpZiAob2xkU2VjdGlvbklkID09IDIpIHtcbiAgICAgICAgICAgIGF3YWl0IHByb2Nlc3NTZWN0aW9uUG93ZXIocG93ZXIrMSk7XG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kV3JpdGVTZWN0aW9uKGZkTmV3KTtcblxuICAgICAgICBhc3luYyBmdW5jdGlvbiBwcm9jZXNzU2VjdGlvblBvd2VyKHApIHtcbiAgICAgICAgICAgIGNvbnN0IG5Qb2ludHMgPSAyICoqIHA7XG4gICAgICAgICAgICBjb25zdCBHID0gY3VydmVbR3N0cl07XG4gICAgICAgICAgICBjb25zdCBzR2luID0gRy5GLm44KjI7XG5cbiAgICAgICAgICAgIGxldCBidWZmO1xuICAgICAgICAgICAgYnVmZiA9IG5ldyBCaWdCdWZmZXIoblBvaW50cypzR2luKTtcblxuICAgICAgICAgICAgYXdhaXQgYmluRmlsZVV0aWxzLnN0YXJ0UmVhZFVuaXF1ZVNlY3Rpb24oZmRPbGQsIHNlY3Rpb25zLCBvbGRTZWN0aW9uSWQpO1xuICAgICAgICAgICAgaWYgKChvbGRTZWN0aW9uSWQgPT0gMikmJihwPT1wb3dlcisxKSkge1xuICAgICAgICAgICAgICAgIGF3YWl0IGZkT2xkLnJlYWRUb0J1ZmZlcihidWZmLCAwLChuUG9pbnRzLTEpKnNHaW4gKTtcbiAgICAgICAgICAgICAgICBidWZmLnNldChjdXJ2ZS5HMS56ZXJvQWZmaW5lLCAoblBvaW50cy0xKSpzR2luICk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGF3YWl0IGZkT2xkLnJlYWRUb0J1ZmZlcihidWZmLCAwLG5Qb2ludHMqc0dpbiApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYXdhaXQgYmluRmlsZVV0aWxzLmVuZFJlYWRTZWN0aW9uKGZkT2xkLCB0cnVlKTtcblxuICAgICAgICAgICAgYnVmZiA9IGF3YWl0IEcubGFncmFuZ2VFdmFsdWF0aW9ucyhidWZmLCBcImFmZmluZVwiLCBcImFmZmluZVwiLCBsb2dnZXIsIHNlY3Rpb25OYW1lKTtcbiAgICAgICAgICAgIGF3YWl0IGZkTmV3LndyaXRlKGJ1ZmYpO1xuXG4vKlxuICAgICAgICAgICAgaWYgKHAgPD0gY3VydmUuRnIucykge1xuICAgICAgICAgICAgICAgIGJ1ZmYgPSBhd2FpdCBHLmlmZnQoYnVmZiwgXCJhZmZpbmVcIiwgXCJhZmZpbmVcIiwgbG9nZ2VyLCBzZWN0aW9uTmFtZSk7XG4gICAgICAgICAgICAgICAgYXdhaXQgZmROZXcud3JpdGUoYnVmZik7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHAgPT0gY3VydmUuRnIucysxKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc21hbGxNID0gMTw8Y3VydmUuRnIucztcbiAgICAgICAgICAgICAgICBsZXQgdDAgPSBuZXcgQmlnQnVmZmVyKCBzbWFsbE0gKiBzR21pZCApO1xuICAgICAgICAgICAgICAgIGxldCB0MSA9IG5ldyBCaWdCdWZmZXIoIHNtYWxsTSAqIHNHbWlkICk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBzaGlmdF90b19zbWFsbF9tID0gRnIuZXhwKEZyLnNoaWZ0LCBzbWFsbE0pO1xuICAgICAgICAgICAgICAgIGNvbnN0IG9uZV9vdmVyX2Rlbm9tID0gRnIuaW52KEZyLnN1YihzaGlmdF90b19zbWFsbF9tLCBGci5vbmUpKTtcblxuICAgICAgICAgICAgICAgIGxldCBzSW52QWNjID0gRnIub25lO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGk9MDsgaTxzbWFsbE07IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSUxMDAwMCkgbG9nZ2VyLmRlYnVnKGBzZWN0aW9uTmFtZSBwcmVwYXJlIEwgY2FsYzogJHtzZWN0aW9uTmFtZX0sICR7aX0vJHtzbWFsbE19YCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRpID0gIGJ1ZmYuc2xpY2UoaSpzR2luLCAoaSsxKSpzR2luKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdG1pID0gYnVmZi5zbGljZSgoaStzbWFsbE0pKnNHaW4sIChpK3NtYWxsTSsxKSpzR2luKTtcblxuICAgICAgICAgICAgICAgICAgICB0MC5zZXQoXG4gICAgICAgICAgICAgICAgICAgICAgICBHLnRpbWVzRnIoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgRy5zdWIoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEcudGltZXNGcih0aSAsIHNoaWZ0X3RvX3NtYWxsX20pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bWlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uZV9vdmVyX2Rlbm9tXG4gICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgaSpzR21pZFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB0MS5zZXQoXG4gICAgICAgICAgICAgICAgICAgICAgICBHLnRpbWVzRnIoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgRy5zdWIoIHRtaSwgdGkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZyLm11bChzSW52QWNjLCBvbmVfb3Zlcl9kZW5vbSlcbiAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICBpKnNHbWlkXG4gICAgICAgICAgICAgICAgICAgICk7XG5cblxuICAgICAgICAgICAgICAgICAgICBzSW52QWNjID0gRnIubXVsKHNJbnZBY2MsIEZyLnNoaWZ0SW52KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdDAgPSBhd2FpdCBHLmlmZnQodDAsIFwiamFjb2JpYW5cIiwgXCJhZmZpbmVcIiwgbG9nZ2VyLCBzZWN0aW9uTmFtZSArIFwiIHQwXCIpO1xuICAgICAgICAgICAgICAgIGF3YWl0IGZkTmV3LndyaXRlKHQwKTtcbiAgICAgICAgICAgICAgICB0MCA9IG51bGw7XG4gICAgICAgICAgICAgICAgdDEgPSBhd2FpdCBHLmlmZnQodDEsIFwiamFjb2JpYW5cIiwgXCJhZmZpbmVcIiwgbG9nZ2VyLCBzZWN0aW9uTmFtZSArIFwiIHQxXCIpO1xuICAgICAgICAgICAgICAgIGF3YWl0IGZkTmV3LndyaXRlKHQxKTtcblxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJQb3dlciB0b28gYmlnXCIpO1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlBvd2VyIHRvIGJpZ1wiKTtcbiAgICAgICAgICAgIH1cbiovXG4gICAgICAgIH1cblxuXG4gICAgfVxufVxuXG4iLCIvKlxuICAgIENvcHlyaWdodCAyMDE4IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygc25hcmtKUy5cblxuICAgIHNuYXJrSlMgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gICAgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAgICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICAgIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICBzbmFya0pTIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHNuYXJrSlMuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG5pbXBvcnQgKiBhcyB1dGlscyBmcm9tIFwiLi9wb3dlcnNvZnRhdV91dGlscy5qc1wiO1xuaW1wb3J0ICogYXMgYmluRmlsZVV0aWxzIGZyb20gXCJAaWRlbjMvYmluZmlsZXV0aWxzXCI7XG5pbXBvcnQgeyBzdHJpbmdpZnlCaWdJbnRzV2l0aEZpZWxkIH0gZnJvbSBcIi4vbWlzYy5qc1wiO1xuXG5leHBvcnQgZGVmYXVsdCBhc3luYyBmdW5jdGlvbiBleHBvcnRKc29uKHBUYXVGaWxlbmFtZSwgdmVyYm9zZSkge1xuICAgIGNvbnN0IHtmZCwgc2VjdGlvbnN9ID0gYXdhaXQgYmluRmlsZVV0aWxzLnJlYWRCaW5GaWxlKHBUYXVGaWxlbmFtZSwgXCJwdGF1XCIsIDEpO1xuXG4gICAgY29uc3Qge2N1cnZlLCBwb3dlcn0gPSBhd2FpdCB1dGlscy5yZWFkUFRhdUhlYWRlcihmZCwgc2VjdGlvbnMpO1xuXG4gICAgY29uc3QgcFRhdSA9IHt9O1xuICAgIHBUYXUucSA9IGN1cnZlLnE7XG4gICAgcFRhdS5wb3dlciA9IHBvd2VyO1xuICAgIHBUYXUuY29udHJpYnV0aW9ucyA9IGF3YWl0IHV0aWxzLnJlYWRDb250cmlidXRpb25zKGZkLCBjdXJ2ZSwgc2VjdGlvbnMpO1xuXG4gICAgcFRhdS50YXVHMSA9IGF3YWl0IGV4cG9ydFNlY3Rpb24oMiwgXCJHMVwiLCAoMiAqKiBwb3dlcikqMiAtMSwgXCJ0YXVHMVwiKTtcbiAgICBwVGF1LnRhdUcyID0gYXdhaXQgZXhwb3J0U2VjdGlvbigzLCBcIkcyXCIsICgyICoqIHBvd2VyKSwgXCJ0YXVHMlwiKTtcbiAgICBwVGF1LmFscGhhVGF1RzEgPSBhd2FpdCBleHBvcnRTZWN0aW9uKDQsIFwiRzFcIiwgKDIgKiogcG93ZXIpLCBcImFscGhhVGF1RzFcIik7XG4gICAgcFRhdS5iZXRhVGF1RzEgPSBhd2FpdCBleHBvcnRTZWN0aW9uKDUsIFwiRzFcIiwgKDIgKiogcG93ZXIpLCBcImJldGFUYXVHMVwiKTtcbiAgICBwVGF1LmJldGFHMiA9IGF3YWl0IGV4cG9ydFNlY3Rpb24oNiwgXCJHMlwiLCAxLCBcImJldGFHMlwiKTtcblxuICAgIHBUYXUubFRhdUcxID0gYXdhaXQgZXhwb3J0TGFncmFuZ2UoMTIsIFwiRzFcIiwgXCJsVGF1RzFcIik7XG4gICAgcFRhdS5sVGF1RzIgPSBhd2FpdCBleHBvcnRMYWdyYW5nZSgxMywgXCJHMlwiLCBcImxUYXVHMlwiKTtcbiAgICBwVGF1LmxBbHBoYVRhdUcxID0gYXdhaXQgZXhwb3J0TGFncmFuZ2UoMTQsIFwiRzFcIiwgXCJsQWxwaGFUYXVHMlwiKTtcbiAgICBwVGF1LmxCZXRhVGF1RzEgPSBhd2FpdCBleHBvcnRMYWdyYW5nZSgxNSwgXCJHMVwiLCBcImxCZXRhVGF1RzJcIik7XG5cbiAgICBhd2FpdCBmZC5jbG9zZSgpO1xuXG4gICAgcmV0dXJuIHN0cmluZ2lmeUJpZ0ludHNXaXRoRmllbGQoY3VydmUuRnIsIHBUYXUpO1xuXG5cblxuICAgIGFzeW5jIGZ1bmN0aW9uIGV4cG9ydFNlY3Rpb24oc2VjdGlvbklkLCBncm91cE5hbWUsIG5Qb2ludHMsIHNlY3Rpb25OYW1lKSB7XG4gICAgICAgIGNvbnN0IEcgPSBjdXJ2ZVtncm91cE5hbWVdO1xuICAgICAgICBjb25zdCBzRyA9IEcuRi5uOCoyO1xuXG4gICAgICAgIGNvbnN0IHJlcyA9IFtdO1xuICAgICAgICBhd2FpdCBiaW5GaWxlVXRpbHMuc3RhcnRSZWFkVW5pcXVlU2VjdGlvbihmZCwgc2VjdGlvbnMsIHNlY3Rpb25JZCk7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTwgblBvaW50czsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoKHZlcmJvc2UpJiZpJiYoaSUxMDAwMCA9PSAwKSkgY29uc29sZS5sb2coYCR7c2VjdGlvbk5hbWV9OiBgICsgaSk7XG4gICAgICAgICAgICBjb25zdCBidWZmID0gYXdhaXQgZmQucmVhZChzRyk7XG4gICAgICAgICAgICByZXMucHVzaChHLmZyb21ScHJMRU0oYnVmZiwgMCkpO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IGJpbkZpbGVVdGlscy5lbmRSZWFkU2VjdGlvbihmZCk7XG5cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiBleHBvcnRMYWdyYW5nZShzZWN0aW9uSWQsIGdyb3VwTmFtZSwgc2VjdGlvbk5hbWUpIHtcbiAgICAgICAgY29uc3QgRyA9IGN1cnZlW2dyb3VwTmFtZV07XG4gICAgICAgIGNvbnN0IHNHID0gRy5GLm44KjI7XG5cbiAgICAgICAgY29uc3QgcmVzID0gW107XG4gICAgICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFJlYWRVbmlxdWVTZWN0aW9uKGZkLCBzZWN0aW9ucywgc2VjdGlvbklkKTtcbiAgICAgICAgZm9yIChsZXQgcD0wOyBwPD1wb3dlcjsgcCsrKSB7XG4gICAgICAgICAgICBpZiAodmVyYm9zZSkgY29uc29sZS5sb2coYCR7c2VjdGlvbk5hbWV9OiBQb3dlcjogJHtwfWApO1xuICAgICAgICAgICAgcmVzW3BdID0gW107XG4gICAgICAgICAgICBjb25zdCBuUG9pbnRzID0gKDIgKiogcCk7XG4gICAgICAgICAgICBmb3IgKGxldCBpPTA7IGk8blBvaW50czsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKCh2ZXJib3NlKSYmaSYmKGklMTAwMDAgPT0gMCkpIGNvbnNvbGUubG9nKGAke3NlY3Rpb25OYW1lfTogJHtpfS8ke25Qb2ludHN9YCk7XG4gICAgICAgICAgICAgICAgY29uc3QgYnVmZiA9IGF3YWl0IGZkLnJlYWQoc0cpO1xuICAgICAgICAgICAgICAgIHJlc1twXS5wdXNoKEcuZnJvbVJwckxFTShidWZmLCAwKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgYmluRmlsZVV0aWxzLmVuZFJlYWRTZWN0aW9uKGZkLCB0cnVlKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cblxufVxuXG5cbiIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMTggMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya0pTLlxuXG4gICAgc25hcmtKUyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJrSlMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggc25hcmtKUy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbmV4cG9ydCB7ZGVmYXVsdCBhcyBuZXdBY2N1bXVsYXRvcn0gZnJvbSBcIi4vcG93ZXJzb2Z0YXVfbmV3LmpzXCI7XG5leHBvcnQge2RlZmF1bHQgYXMgZXhwb3J0Q2hhbGxlbmdlfSBmcm9tIFwiLi9wb3dlcnNvZnRhdV9leHBvcnRfY2hhbGxlbmdlLmpzXCI7XG5leHBvcnQge2RlZmF1bHQgYXMgaW1wb3J0UmVzcG9uc2V9IGZyb20gXCIuL3Bvd2Vyc29mdGF1X2ltcG9ydC5qc1wiO1xuZXhwb3J0IHtkZWZhdWx0IGFzIHZlcmlmeX0gZnJvbSBcIi4vcG93ZXJzb2Z0YXVfdmVyaWZ5LmpzXCI7XG5leHBvcnQge2RlZmF1bHQgYXMgY2hhbGxlbmdlQ29udHJpYnV0ZX0gZnJvbSBcIi4vcG93ZXJzb2Z0YXVfY2hhbGxlbmdlX2NvbnRyaWJ1dGUuanNcIjtcbmV4cG9ydCB7ZGVmYXVsdCBhcyBiZWFjb259IGZyb20gXCIuL3Bvd2Vyc29mdGF1X2JlYWNvbi5qc1wiO1xuZXhwb3J0IHtkZWZhdWx0IGFzIGNvbnRyaWJ1dGV9IGZyb20gXCIuL3Bvd2Vyc29mdGF1X2NvbnRyaWJ1dGUuanNcIjtcbmV4cG9ydCB7ZGVmYXVsdCBhcyBwcmVwYXJlUGhhc2UyfSBmcm9tIFwiLi9wb3dlcnNvZnRhdV9wcmVwYXJlcGhhc2UyLmpzXCI7XG5leHBvcnQge2RlZmF1bHQgYXMgdHJ1bmNhdGV9IGZyb20gXCIuL3Bvd2Vyc29mdGF1X3RydW5jYXRlLmpzXCI7XG5leHBvcnQge2RlZmF1bHQgYXMgY29udmVydH0gZnJvbSBcIi4vcG93ZXJzb2Z0YXVfY29udmVydC5qc1wiO1xuZXhwb3J0IHtkZWZhdWx0IGFzIGV4cG9ydEpzb259IGZyb20gXCIuL3Bvd2Vyc29mdGF1X2V4cG9ydF9qc29uLmpzXCI7XG4iLCIvKlxuICAgIENvcHlyaWdodCAyMDE4IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygc25hcmtKUy5cblxuICAgIHNuYXJrSlMgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gICAgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAgICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICAgIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICBzbmFya0pTIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHNuYXJrSlMuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiByMWNzUHJpbnQocjFjcywgc3ltcywgbG9nZ2VyKSB7XG4gICAgZm9yIChsZXQgaT0wOyBpPHIxY3MuY29uc3RyYWludHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcHJpbnRDb3N0cmFpbnQocjFjcy5jb25zdHJhaW50c1tpXSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHByaW50Q29zdHJhaW50KGMpIHtcbiAgICAgICAgY29uc3QgbGMyc3RyID0gKGxjKSA9PiB7XG4gICAgICAgICAgICBsZXQgUyA9IFwiXCI7XG4gICAgICAgICAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMobGMpO1xuICAgICAgICAgICAga2V5cy5mb3JFYWNoKCAoaykgPT4ge1xuICAgICAgICAgICAgICAgIGxldCBuYW1lID0gc3ltcy52YXJJZHgyTmFtZVtrXTtcbiAgICAgICAgICAgICAgICBpZiAobmFtZSA9PSBcIm9uZVwiKSBuYW1lID0gXCIxXCI7XG5cbiAgICAgICAgICAgICAgICBsZXQgdnMgPSByMWNzLmN1cnZlLkZyLnRvU3RyaW5nKGxjW2tdKTtcbiAgICAgICAgICAgICAgICBpZiAodnMgPT0gXCIxXCIpIHZzID0gXCJcIjsgIC8vIERvIG5vdCBzaG93IG9uZXNcbiAgICAgICAgICAgICAgICBpZiAodnMgPT0gXCItMVwiKSB2cyA9IFwiLVwiOyAgLy8gRG8gbm90IHNob3cgb25lc1xuICAgICAgICAgICAgICAgIGlmICgoUyE9XCJcIikmJih2c1swXSE9XCItXCIpKSB2cyA9IFwiK1wiK3ZzO1xuICAgICAgICAgICAgICAgIGlmIChTIT1cIlwiKSB2cyA9IFwiIFwiK3ZzO1xuICAgICAgICAgICAgICAgIFM9IFMgKyB2cyAgICsgbmFtZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIFM7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IFMgPSBgWyAke2xjMnN0cihjWzBdKX0gXSAqIFsgJHtsYzJzdHIoY1sxXSl9IF0gLSBbICR7bGMyc3RyKGNbMl0pfSBdID0gMGA7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFMpO1xuICAgIH1cblxufVxuIiwiY29uc3QgU1VCQVJSQVlfU0laRSA9IDB4NDAwMDA7XG5cbmNvbnN0IEJpZ0FycmF5SGFuZGxlciA9IHtcbiAgICBnZXQ6IGZ1bmN0aW9uKG9iaiwgcHJvcCkge1xuICAgICAgICBpZiAoIWlzTmFOKHByb3ApKSB7XG4gICAgICAgICAgICByZXR1cm4gb2JqLmdldEVsZW1lbnQocHJvcCk7XG4gICAgICAgIH0gZWxzZSByZXR1cm4gb2JqW3Byb3BdO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbihvYmosIHByb3AsIHZhbHVlKSB7XG4gICAgICAgIGlmICghaXNOYU4ocHJvcCkpIHtcbiAgICAgICAgICAgIHJldHVybiBvYmouc2V0RWxlbWVudChwcm9wLCB2YWx1ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBvYmpbcHJvcF0gPSB2YWx1ZTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuY2xhc3MgX0JpZ0FycmF5IHtcbiAgICBjb25zdHJ1Y3RvciAoaW5pdFNpemUpIHtcbiAgICAgICAgdGhpcy5sZW5ndGggPSBpbml0U2l6ZSB8fCAwO1xuICAgICAgICB0aGlzLmFyciA9IG5ldyBBcnJheShTVUJBUlJBWV9TSVpFKTtcblxuICAgICAgICBmb3IgKGxldCBpPTA7IGk8aW5pdFNpemU7IGkrPVNVQkFSUkFZX1NJWkUpIHtcbiAgICAgICAgICAgIHRoaXMuYXJyW2kvU1VCQVJSQVlfU0laRV0gPSBuZXcgQXJyYXkoTWF0aC5taW4oU1VCQVJSQVlfU0laRSwgaW5pdFNpemUgLSBpKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIHB1c2ggKCkge1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8YXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0aGlzLnNldEVsZW1lbnQgKHRoaXMubGVuZ3RoLCBhcmd1bWVudHNbaV0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc2xpY2UgKGYsIHQpIHtcbiAgICAgICAgY29uc3QgYXJyID0gbmV3IEFycmF5KHQtZik7XG4gICAgICAgIGZvciAobGV0IGk9ZjsgaTwgdDsgaSsrKSBhcnJbaS1mXSA9IHRoaXMuZ2V0RWxlbWVudChpKTtcbiAgICAgICAgcmV0dXJuIGFycjtcbiAgICB9XG4gICAgZ2V0RWxlbWVudChpZHgpIHtcbiAgICAgICAgaWR4ID0gcGFyc2VJbnQoaWR4KTtcbiAgICAgICAgY29uc3QgaWR4MSA9IE1hdGguZmxvb3IoaWR4IC8gU1VCQVJSQVlfU0laRSk7XG4gICAgICAgIGNvbnN0IGlkeDIgPSBpZHggJSBTVUJBUlJBWV9TSVpFO1xuICAgICAgICByZXR1cm4gdGhpcy5hcnJbaWR4MV0gPyB0aGlzLmFycltpZHgxXVtpZHgyXSA6IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgc2V0RWxlbWVudChpZHgsIHZhbHVlKSB7XG4gICAgICAgIGlkeCA9IHBhcnNlSW50KGlkeCk7XG4gICAgICAgIGNvbnN0IGlkeDEgPSBNYXRoLmZsb29yKGlkeCAvIFNVQkFSUkFZX1NJWkUpO1xuICAgICAgICBpZiAoIXRoaXMuYXJyW2lkeDFdKSB7XG4gICAgICAgICAgICB0aGlzLmFycltpZHgxXSA9IG5ldyBBcnJheShTVUJBUlJBWV9TSVpFKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBpZHgyID0gaWR4ICUgU1VCQVJSQVlfU0laRTtcbiAgICAgICAgdGhpcy5hcnJbaWR4MV1baWR4Ml0gPSB2YWx1ZTtcbiAgICAgICAgaWYgKGlkeCA+PSB0aGlzLmxlbmd0aCkgdGhpcy5sZW5ndGggPSBpZHgrMTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGdldEtleXMoKSB7XG4gICAgICAgIGNvbnN0IG5ld0EgPSBuZXcgQmlnQXJyYXkoKTtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPHRoaXMuYXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hcnJbaV0pIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqPTA7IGo8dGhpcy5hcnJbaV0ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLmFycltpXVtqXSAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3QS5wdXNoKGkqU1VCQVJSQVlfU0laRStqKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3QTtcbiAgICB9XG59XG5cbmNsYXNzIEJpZ0FycmF5IHtcbiAgICBjb25zdHJ1Y3RvciggaW5pdFNpemUgKSB7XG4gICAgICAgIGNvbnN0IG9iaiA9IG5ldyBfQmlnQXJyYXkoaW5pdFNpemUpO1xuICAgICAgICBjb25zdCBleHRPYmogPSBuZXcgUHJveHkob2JqLCBCaWdBcnJheUhhbmRsZXIpO1xuICAgICAgICByZXR1cm4gZXh0T2JqO1xuICAgIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgQmlnQXJyYXk7XG4iLCJcbmltcG9ydCBmcyBmcm9tXCJmc1wiO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gb3BlbihmaWxlTmFtZSwgb3BlbkZsYWdzLCBjYWNoZVNpemUsIHBhZ2VTaXplKSB7XG4gICAgY2FjaGVTaXplID0gY2FjaGVTaXplIHx8IDQwOTYqNjQ7XG4gICAgaWYgKHR5cGVvZiBvcGVuRmxhZ3MgIT09IFwibnVtYmVyXCIgJiYgW1widytcIiwgXCJ3eCtcIiwgXCJyXCIsIFwiYXgrXCIsIFwiYStcIl0uaW5kZXhPZihvcGVuRmxhZ3MpIDwwKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIG9wZW4gb3B0aW9uXCIpO1xuICAgIGNvbnN0IGZkID1hd2FpdCBmcy5wcm9taXNlcy5vcGVuKGZpbGVOYW1lLCBvcGVuRmxhZ3MpO1xuXG4gICAgY29uc3Qgc3RhdHMgPSBhd2FpdCBmZC5zdGF0KCk7XG5cbiAgICByZXR1cm4gIG5ldyBGYXN0RmlsZShmZCwgc3RhdHMsIGNhY2hlU2l6ZSwgcGFnZVNpemUsIGZpbGVOYW1lKTtcbn1cblxuXG5jbGFzcyBGYXN0RmlsZSB7XG5cbiAgICBjb25zdHJ1Y3RvcihmZCwgc3RhdHMsIGNhY2hlU2l6ZSwgcGFnZVNpemUsIGZpbGVOYW1lKSB7XG4gICAgICAgIHRoaXMuZmlsZU5hbWUgPSBmaWxlTmFtZTtcbiAgICAgICAgdGhpcy5mZCA9IGZkO1xuICAgICAgICB0aGlzLnBvcyA9IDA7XG4gICAgICAgIHRoaXMucGFnZVNpemUgPSBwYWdlU2l6ZSB8fCAoMSA8PCA4KTtcbiAgICAgICAgd2hpbGUgKHRoaXMucGFnZVNpemUgPCBzdGF0cy5ibGtzaXplKSB7XG4gICAgICAgICAgICB0aGlzLnBhZ2VTaXplICo9IDI7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy50b3RhbFNpemUgPSBzdGF0cy5zaXplO1xuICAgICAgICB0aGlzLnRvdGFsUGFnZXMgPSBNYXRoLmZsb29yKChzdGF0cy5zaXplIC0xKSAvIHRoaXMucGFnZVNpemUpKzE7XG4gICAgICAgIHRoaXMubWF4UGFnZXNMb2FkZWQgPSBNYXRoLmZsb29yKCBjYWNoZVNpemUgLyB0aGlzLnBhZ2VTaXplKSsxO1xuICAgICAgICB0aGlzLnBhZ2VzID0ge307XG4gICAgICAgIHRoaXMucGVuZGluZ0xvYWRzID0gW107XG4gICAgICAgIHRoaXMud3JpdGluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLnJlYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5hdkJ1ZmZzID0gW107XG4gICAgICAgIHRoaXMuaGlzdG9yeSA9IHt9O1xuICAgIH1cblxuICAgIF9sb2FkUGFnZShwKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBjb25zdCBQID0gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCk9PiB7XG4gICAgICAgICAgICBzZWxmLnBlbmRpbmdMb2Fkcy5wdXNoKHtcbiAgICAgICAgICAgICAgICBwYWdlOiBwLFxuICAgICAgICAgICAgICAgIHJlc29sdmU6IHJlc29sdmUsXG4gICAgICAgICAgICAgICAgcmVqZWN0OiByZWplY3RcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgc2VsZi5fX3N0YXR1c1BhZ2UoXCJBZnRlciBMb2FkIHJlcXVlc3Q6IFwiLCBwKTtcbiAgICAgICAgcmV0dXJuIFA7XG4gICAgfVxuXG4gICAgX19zdGF0dXNQYWdlKHMsIHApIHtcbiAgICAgICAgY29uc3QgbG9nRW50cnkgPSBbXTtcbiAgICAgICAgY29uc3Qgc2VsZj10aGlzO1xuICAgICAgICBpZiAoIXNlbGYubG9nSGlzdG9yeSkgcmV0dXJuO1xuICAgICAgICBsb2dFbnRyeS5wdXNoKFwiPT1cIiArIHMrIFwiIFwiICtwKTtcbiAgICAgICAgbGV0IFMgPSBcIlwiO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8c2VsZi5wZW5kaW5nTG9hZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChzZWxmLnBlbmRpbmdMb2Fkc1tpXS5wYWdlID09IHApIFMgPSBTICsgXCIgXCIgKyBpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChTKSBsb2dFbnRyeS5wdXNoKFwiUGVuZGluZyBsb2FkczpcIitTKTtcbiAgICAgICAgaWYgKHR5cGVvZiBzZWxmLnBhZ2VzW3BdICE9IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgIGNvbnN0IHBhZ2UgPSBzZWxmLnBhZ2VzW3BdO1xuICAgICAgICAgICAgbG9nRW50cnkucHVzaChcIkxvYWRlZFwiKTtcbiAgICAgICAgICAgIGxvZ0VudHJ5LnB1c2goXCJwZW5kaW5nT3BzOiBcIitwYWdlLnBlbmRpbmdPcHMpO1xuICAgICAgICAgICAgaWYgKHBhZ2UubG9hZGluZykgbG9nRW50cnkucHVzaChcImxvYWRpbmc6IFwiK3BhZ2UubG9hZGluZyk7XG4gICAgICAgICAgICBpZiAocGFnZS53cml0aW5nKSBsb2dFbnRyeS5wdXNoKFwid3JpdGluZ1wiKTtcbiAgICAgICAgICAgIGlmIChwYWdlLmRpcnR5KSBsb2dFbnRyeS5wdXNoKFwiZGlydHlcIik7XG4gICAgICAgIH1cbiAgICAgICAgbG9nRW50cnkucHVzaChcIj09XCIpO1xuXG4gICAgICAgIGlmICghc2VsZi5oaXN0b3J5W3BdKSBzZWxmLmhpc3RvcnlbcF0gPSBbXTtcbiAgICAgICAgc2VsZi5oaXN0b3J5W3BdLnB1c2gobG9nRW50cnkpO1xuICAgIH1cblxuICAgIF9fcHJpbnRIaXN0b3J5KHApIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGlmICghc2VsZi5oaXN0b3J5W3BdKSBjb25zb2xlLmxvZyhcIkVtcHR5IEhpc3RvcnkgXCIsIHApO1xuICAgICAgICBjb25zb2xlLmxvZyhcIkhpc3RvcnkgXCIrcCk7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxzZWxmLmhpc3RvcnlbcF0ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGZvciAobGV0IGo9MDsgajxzZWxmLmhpc3RvcnlbcF1baV0ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIi0+IFwiICsgc2VsZi5oaXN0b3J5W3BdW2ldW2pdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuXG5cbiAgICBfdHJpZ2dlckxvYWQoKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gICAgICAgIGlmIChzZWxmLnJlYWRpbmcpIHJldHVybjtcbiAgICAgICAgaWYgKHNlbGYucGVuZGluZ0xvYWRzLmxlbmd0aD09MCkgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IHBhZ2VJZHhzID0gT2JqZWN0LmtleXMoc2VsZi5wYWdlcyk7XG5cbiAgICAgICAgY29uc3QgZGVsZXRhYmxlUGFnZXMgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPHBhZ2VJZHhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBwYWdlID0gc2VsZi5wYWdlc1twYXJzZUludChwYWdlSWR4c1tpXSldO1xuICAgICAgICAgICAgaWYgKChwYWdlLmRpcnR5ID09IGZhbHNlKSYmKHBhZ2UucGVuZGluZ09wcz09MCkmJighcGFnZS53cml0aW5nKSYmKCFwYWdlLmxvYWRpbmcpKSBkZWxldGFibGVQYWdlcy5wdXNoKHBhcnNlSW50KHBhZ2VJZHhzW2ldKSk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgZnJlZVBhZ2VzID0gc2VsZi5tYXhQYWdlc0xvYWRlZCAtIHBhZ2VJZHhzLmxlbmd0aDtcblxuICAgICAgICBjb25zdCBvcHMgPSBbXTtcblxuICAgICAgICAvLyB3aGlsZSBwZW5kaW5nIGxvYWRzIGFuZFxuICAgICAgICAvLyAgICAgdGhlIHBhZ2UgaXMgbG9hZGVkIG9yIEkgY2FuIHJlY292ZXIgb25lLlxuICAgICAgICB3aGlsZSAoXG4gICAgICAgICAgICAoc2VsZi5wZW5kaW5nTG9hZHMubGVuZ3RoPjApICYmXG4gICAgICAgICAgICAoICAgKHR5cGVvZiBzZWxmLnBhZ2VzW3NlbGYucGVuZGluZ0xvYWRzWzBdLnBhZ2VdICE9IFwidW5kZWZpbmVkXCIgKVxuICAgICAgICAgICAgICB8fCggIChmcmVlUGFnZXM+MClcbiAgICAgICAgICAgICAgICAgfHwoZGVsZXRhYmxlUGFnZXMubGVuZ3RoPjApKSkpIHtcbiAgICAgICAgICAgIGNvbnN0IGxvYWQgPSBzZWxmLnBlbmRpbmdMb2Fkcy5zaGlmdCgpO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBzZWxmLnBhZ2VzW2xvYWQucGFnZV0gIT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgICAgIHNlbGYucGFnZXNbbG9hZC5wYWdlXS5wZW5kaW5nT3BzICsrO1xuICAgICAgICAgICAgICAgIGNvbnN0IGlkeCA9IGRlbGV0YWJsZVBhZ2VzLmluZGV4T2YobG9hZC5wYWdlKTtcbiAgICAgICAgICAgICAgICBpZiAoaWR4Pj0wKSBkZWxldGFibGVQYWdlcy5zcGxpY2UoaWR4LCAxKTtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZi5wYWdlc1tsb2FkLnBhZ2VdLmxvYWRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5wYWdlc1tsb2FkLnBhZ2VdLmxvYWRpbmcucHVzaChsb2FkKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBsb2FkLnJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2VsZi5fX3N0YXR1c1BhZ2UoXCJBZnRlciBMb2FkIChjYWNoZWQpOiBcIiwgbG9hZC5wYWdlKTtcblxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoZnJlZVBhZ2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGZyZWVQYWdlcy0tO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGZwID0gZGVsZXRhYmxlUGFnZXMuc2hpZnQoKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fX3N0YXR1c1BhZ2UoXCJCZWZvcmUgVW5sb2FkOiBcIiwgZnApO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLmF2QnVmZnMudW5zaGlmdChzZWxmLnBhZ2VzW2ZwXSk7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBzZWxmLnBhZ2VzW2ZwXTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fX3N0YXR1c1BhZ2UoXCJBZnRlciBVbmxvYWQ6IFwiLCBmcCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGxvYWQucGFnZT49c2VsZi50b3RhbFBhZ2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYucGFnZXNbbG9hZC5wYWdlXSA9IGdldE5ld1BhZ2UoKTtcbiAgICAgICAgICAgICAgICAgICAgbG9hZC5yZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX19zdGF0dXNQYWdlKFwiQWZ0ZXIgTG9hZCAobmV3KTogXCIsIGxvYWQucGFnZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5yZWFkaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5wYWdlc1tsb2FkLnBhZ2VdID0gZ2V0TmV3UGFnZSgpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnBhZ2VzW2xvYWQucGFnZV0ubG9hZGluZyA9IFtsb2FkXTtcbiAgICAgICAgICAgICAgICAgICAgb3BzLnB1c2goc2VsZi5mZC5yZWFkKHNlbGYucGFnZXNbbG9hZC5wYWdlXS5idWZmLCAwLCBzZWxmLnBhZ2VTaXplLCBsb2FkLnBhZ2Uqc2VsZi5wYWdlU2l6ZSkudGhlbigocmVzKT0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYucGFnZXNbbG9hZC5wYWdlXS5zaXplID0gcmVzLmJ5dGVzUmVhZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxvYWRpbmcgPSBzZWxmLnBhZ2VzW2xvYWQucGFnZV0ubG9hZGluZztcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBzZWxmLnBhZ2VzW2xvYWQucGFnZV0ubG9hZGluZztcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGk9MDsgaTxsb2FkaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9hZGluZ1tpXS5yZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9fc3RhdHVzUGFnZShcIkFmdGVyIExvYWQgKGxvYWRlZCk6IFwiLCBsb2FkLnBhZ2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgICAgICAgICAgICAgICAgfSwgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9hZC5yZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9fc3RhdHVzUGFnZShcIkFmdGVyIExvYWQgKGxvYWRpbmcpOiBcIiwgbG9hZC5wYWdlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgKG9wcy5sZW5ndGg+MSkgY29uc29sZS5sb2cob3BzLmxlbmd0aCk7XG5cbiAgICAgICAgUHJvbWlzZS5hbGwob3BzKS50aGVuKCAoKSA9PiB7XG4gICAgICAgICAgICBzZWxmLnJlYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmIChzZWxmLnBlbmRpbmdMb2Fkcy5sZW5ndGg+MCkgc2V0SW1tZWRpYXRlKHNlbGYuX3RyaWdnZXJMb2FkLmJpbmQoc2VsZikpO1xuICAgICAgICAgICAgc2VsZi5fdHJ5Q2xvc2UoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgZnVuY3Rpb24gZ2V0TmV3UGFnZSgpIHtcbiAgICAgICAgICAgIGlmIChzZWxmLmF2QnVmZnMubGVuZ3RoPjApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwID0gc2VsZi5hdkJ1ZmZzLnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgcC5kaXJ0eSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHAucGVuZGluZ09wcyA9IDE7XG4gICAgICAgICAgICAgICAgcC5zaXplID0wO1xuICAgICAgICAgICAgICAgIHJldHVybiBwO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBkaXJ0eTogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIGJ1ZmY6IG5ldyBVaW50OEFycmF5KHNlbGYucGFnZVNpemUpLFxuICAgICAgICAgICAgICAgICAgICBwZW5kaW5nT3BzOiAxLFxuICAgICAgICAgICAgICAgICAgICBzaXplOiAwXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgfVxuXG5cbiAgICBfdHJpZ2dlcldyaXRlKCkge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgaWYgKHNlbGYud3JpdGluZykgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IHBhZ2VJZHhzID0gT2JqZWN0LmtleXMoc2VsZi5wYWdlcyk7XG5cbiAgICAgICAgY29uc3Qgb3BzID0gW107XG5cbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPHBhZ2VJZHhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBwYWdlID0gc2VsZi5wYWdlc1twYXJzZUludChwYWdlSWR4c1tpXSldO1xuICAgICAgICAgICAgaWYgKHBhZ2UuZGlydHkpIHtcbiAgICAgICAgICAgICAgICBwYWdlLmRpcnR5ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcGFnZS53cml0aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBzZWxmLndyaXRpbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIG9wcy5wdXNoKCBzZWxmLmZkLndyaXRlKHBhZ2UuYnVmZiwgMCwgcGFnZS5zaXplLCBwYXJzZUludChwYWdlSWR4c1tpXSkqc2VsZi5wYWdlU2l6ZSkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHBhZ2Uud3JpdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSwgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIkVSUk9SIFdyaXRpbmc6IFwiK2Vycik7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuZXJyb3IgPSBlcnI7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3RyeUNsb3NlKCk7XG4gICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNlbGYud3JpdGluZykge1xuICAgICAgICAgICAgUHJvbWlzZS5hbGwob3BzKS50aGVuKCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgc2VsZi53cml0aW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgc2V0SW1tZWRpYXRlKHNlbGYuX3RyaWdnZXJXcml0ZS5iaW5kKHNlbGYpKTtcbiAgICAgICAgICAgICAgICBzZWxmLl90cnlDbG9zZSgpO1xuICAgICAgICAgICAgICAgIGlmIChzZWxmLnBlbmRpbmdMb2Fkcy5sZW5ndGg+MCkgc2V0SW1tZWRpYXRlKHNlbGYuX3RyaWdnZXJMb2FkLmJpbmQoc2VsZikpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBfZ2V0RGlydHlQYWdlKCkge1xuICAgICAgICBmb3IgKGxldCBwIGluIHRoaXMucGFnZXMpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnBhZ2VzW3BdLmRpcnR5KSByZXR1cm4gcDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgYXN5bmMgd3JpdGUoYnVmZiwgcG9zKSB7XG4gICAgICAgIGlmIChidWZmLmJ5dGVMZW5ndGggPT0gMCkgcmV0dXJuO1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbi8qXG4gICAgICAgIGlmIChidWZmLmJ5dGVMZW5ndGggPiBzZWxmLnBhZ2VTaXplKnNlbGYubWF4UGFnZXNMb2FkZWQqMC44KSB7XG4gICAgICAgICAgICBjb25zdCBjYWNoZVNpemUgPSBNYXRoLmZsb29yKGJ1ZmYuYnl0ZUxlbmd0aCAqIDEuMSk7XG4gICAgICAgICAgICB0aGlzLm1heFBhZ2VzTG9hZGVkID0gTWF0aC5mbG9vciggY2FjaGVTaXplIC8gc2VsZi5wYWdlU2l6ZSkrMTtcbiAgICAgICAgfVxuKi9cbiAgICAgICAgaWYgKHR5cGVvZiBwb3MgPT0gXCJ1bmRlZmluZWRcIikgcG9zID0gc2VsZi5wb3M7XG4gICAgICAgIHNlbGYucG9zID0gcG9zK2J1ZmYuYnl0ZUxlbmd0aDtcbiAgICAgICAgaWYgKHNlbGYudG90YWxTaXplIDwgcG9zICsgYnVmZi5ieXRlTGVuZ3RoKSBzZWxmLnRvdGFsU2l6ZSA9IHBvcyArIGJ1ZmYuYnl0ZUxlbmd0aDtcbiAgICAgICAgaWYgKHNlbGYucGVuZGluZ0Nsb3NlKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiV3JpdGluZyBhIGNsb3NpbmcgZmlsZVwiKTtcbiAgICAgICAgY29uc3QgZmlyc3RQYWdlID0gTWF0aC5mbG9vcihwb3MgLyBzZWxmLnBhZ2VTaXplKTtcbiAgICAgICAgY29uc3QgbGFzdFBhZ2UgPSBNYXRoLmZsb29yKChwb3MgKyBidWZmLmJ5dGVMZW5ndGggLTEpIC8gc2VsZi5wYWdlU2l6ZSk7XG5cbiAgICAgICAgY29uc3QgcGFnZVByb21pc2VzID0gW107XG4gICAgICAgIGZvciAobGV0IGk9Zmlyc3RQYWdlOyBpPD1sYXN0UGFnZTsgaSsrKSBwYWdlUHJvbWlzZXMucHVzaChzZWxmLl9sb2FkUGFnZShpKSk7XG4gICAgICAgIHNlbGYuX3RyaWdnZXJMb2FkKCk7XG5cbiAgICAgICAgbGV0IHAgPSBmaXJzdFBhZ2U7XG4gICAgICAgIGxldCBvID0gcG9zICUgc2VsZi5wYWdlU2l6ZTtcbiAgICAgICAgbGV0IHIgPSBidWZmLmJ5dGVMZW5ndGg7XG4gICAgICAgIHdoaWxlIChyPjApIHtcbiAgICAgICAgICAgIGF3YWl0IHBhZ2VQcm9taXNlc1twLWZpcnN0UGFnZV07XG4gICAgICAgICAgICBjb25zdCBsID0gKG8rciA+IHNlbGYucGFnZVNpemUpID8gKHNlbGYucGFnZVNpemUgLW8pIDogcjtcbiAgICAgICAgICAgIGNvbnN0IHNyY1ZpZXcgPSBidWZmLnNsaWNlKCBidWZmLmJ5dGVMZW5ndGggLSByLCBidWZmLmJ5dGVMZW5ndGggLSByICsgbCk7XG4gICAgICAgICAgICBjb25zdCBkc3RWaWV3ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5wYWdlc1twXS5idWZmLmJ1ZmZlciwgbywgbCk7XG4gICAgICAgICAgICBkc3RWaWV3LnNldChzcmNWaWV3KTtcbiAgICAgICAgICAgIHNlbGYucGFnZXNbcF0uZGlydHkgPSB0cnVlO1xuICAgICAgICAgICAgc2VsZi5wYWdlc1twXS5wZW5kaW5nT3BzIC0tO1xuICAgICAgICAgICAgc2VsZi5wYWdlc1twXS5zaXplID0gTWF0aC5tYXgobytsLCBzZWxmLnBhZ2VzW3BdLnNpemUpO1xuICAgICAgICAgICAgaWYgKHA+PXNlbGYudG90YWxQYWdlcykge1xuICAgICAgICAgICAgICAgIHNlbGYudG90YWxQYWdlcyA9IHArMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHIgPSByLWw7XG4gICAgICAgICAgICBwICsrO1xuICAgICAgICAgICAgbyA9IDA7XG4gICAgICAgICAgICBpZiAoIXNlbGYud3JpdGluZykgc2V0SW1tZWRpYXRlKHNlbGYuX3RyaWdnZXJXcml0ZS5iaW5kKHNlbGYpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIHJlYWQobGVuLCBwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGxldCBidWZmID0gbmV3IFVpbnQ4QXJyYXkobGVuKTtcbiAgICAgICAgYXdhaXQgc2VsZi5yZWFkVG9CdWZmZXIoYnVmZiwgMCwgbGVuLCBwb3MpO1xuXG4gICAgICAgIHJldHVybiBidWZmO1xuICAgIH1cblxuICAgIGFzeW5jIHJlYWRUb0J1ZmZlcihidWZmRHN0LCBvZmZzZXQsIGxlbiwgcG9zKSB7XG4gICAgICAgIGlmIChsZW4gPT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBpZiAobGVuID4gc2VsZi5wYWdlU2l6ZSpzZWxmLm1heFBhZ2VzTG9hZGVkKjAuOCkge1xuICAgICAgICAgICAgY29uc3QgY2FjaGVTaXplID0gTWF0aC5mbG9vcihsZW4gKiAxLjEpO1xuICAgICAgICAgICAgdGhpcy5tYXhQYWdlc0xvYWRlZCA9IE1hdGguZmxvb3IoIGNhY2hlU2l6ZSAvIHNlbGYucGFnZVNpemUpKzE7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiBwb3MgPT0gXCJ1bmRlZmluZWRcIikgcG9zID0gc2VsZi5wb3M7XG4gICAgICAgIHNlbGYucG9zID0gcG9zK2xlbjtcbiAgICAgICAgaWYgKHNlbGYucGVuZGluZ0Nsb3NlKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUmVhZGluZyBhIGNsb3NpbmcgZmlsZVwiKTtcbiAgICAgICAgY29uc3QgZmlyc3RQYWdlID0gTWF0aC5mbG9vcihwb3MgLyBzZWxmLnBhZ2VTaXplKTtcbiAgICAgICAgY29uc3QgbGFzdFBhZ2UgPSBNYXRoLmZsb29yKChwb3MgKyBsZW4gLTEpIC8gc2VsZi5wYWdlU2l6ZSk7XG5cbiAgICAgICAgY29uc3QgcGFnZVByb21pc2VzID0gW107XG4gICAgICAgIGZvciAobGV0IGk9Zmlyc3RQYWdlOyBpPD1sYXN0UGFnZTsgaSsrKSBwYWdlUHJvbWlzZXMucHVzaChzZWxmLl9sb2FkUGFnZShpKSk7XG5cbiAgICAgICAgc2VsZi5fdHJpZ2dlckxvYWQoKTtcblxuICAgICAgICBsZXQgcCA9IGZpcnN0UGFnZTtcbiAgICAgICAgbGV0IG8gPSBwb3MgJSBzZWxmLnBhZ2VTaXplO1xuICAgICAgICAvLyBSZW1haW5pbmcgYnl0ZXMgdG8gcmVhZFxuICAgICAgICBsZXQgciA9IHBvcyArIGxlbiA+IHNlbGYudG90YWxTaXplID8gbGVuIC0gKHBvcyArIGxlbiAtIHNlbGYudG90YWxTaXplKTogbGVuO1xuICAgICAgICB3aGlsZSAocj4wKSB7XG4gICAgICAgICAgICBhd2FpdCBwYWdlUHJvbWlzZXNbcCAtIGZpcnN0UGFnZV07XG4gICAgICAgICAgICBzZWxmLl9fc3RhdHVzUGFnZShcIkFmdGVyIEF3YWl0IChyZWFkKTogXCIsIHApO1xuXG4gICAgICAgICAgICAvLyBieXRlcyB0byBjb3B5IGZyb20gdGhpcyBwYWdlXG4gICAgICAgICAgICBjb25zdCBsID0gKG8rciA+IHNlbGYucGFnZVNpemUpID8gKHNlbGYucGFnZVNpemUgLW8pIDogcjtcbiAgICAgICAgICAgIGNvbnN0IHNyY1ZpZXcgPSBuZXcgVWludDhBcnJheShzZWxmLnBhZ2VzW3BdLmJ1ZmYuYnVmZmVyLCBzZWxmLnBhZ2VzW3BdLmJ1ZmYuYnl0ZU9mZnNldCArIG8sIGwpO1xuICAgICAgICAgICAgYnVmZkRzdC5zZXQoc3JjVmlldywgb2Zmc2V0K2xlbi1yKTtcbiAgICAgICAgICAgIHNlbGYucGFnZXNbcF0ucGVuZGluZ09wcyAtLTtcblxuICAgICAgICAgICAgc2VsZi5fX3N0YXR1c1BhZ2UoXCJBZnRlciBPcCBkb25lOiBcIiwgcCk7XG5cbiAgICAgICAgICAgIHIgPSByLWw7XG4gICAgICAgICAgICBwICsrO1xuICAgICAgICAgICAgbyA9IDA7XG4gICAgICAgICAgICBpZiAoc2VsZi5wZW5kaW5nTG9hZHMubGVuZ3RoPjApIHNldEltbWVkaWF0ZShzZWxmLl90cmlnZ2VyTG9hZC5iaW5kKHNlbGYpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucG9zID0gcG9zICsgbGVuO1xuXG4gICAgfVxuXG5cbiAgICBfdHJ5Q2xvc2UoKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBpZiAoIXNlbGYucGVuZGluZ0Nsb3NlKSByZXR1cm47XG4gICAgICAgIGlmIChzZWxmLmVycm9yKSB7XG4gICAgICAgICAgICBzZWxmLnBlbmRpbmdDbG9zZVJlamVjdChzZWxmLmVycm9yKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwID0gc2VsZi5fZ2V0RGlydHlQYWdlKCk7XG4gICAgICAgIGlmICgocD49MCkgfHwgKHNlbGYud3JpdGluZykgfHwgKHNlbGYucmVhZGluZykgfHwgKHNlbGYucGVuZGluZ0xvYWRzLmxlbmd0aD4wKSkgcmV0dXJuO1xuICAgICAgICBzZWxmLnBlbmRpbmdDbG9zZSgpO1xuICAgIH1cblxuICAgIGNsb3NlKCkge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgaWYgKHNlbGYucGVuZGluZ0Nsb3NlKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2xvc2luZyB0aGUgZmlsZSB0d2ljZVwiKTtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHNlbGYucGVuZGluZ0Nsb3NlID0gcmVzb2x2ZTtcbiAgICAgICAgICAgIHNlbGYucGVuZGluZ0Nsb3NlUmVqZWN0ID0gcmVqZWN0O1xuICAgICAgICAgICAgc2VsZi5fdHJ5Q2xvc2UoKTtcbiAgICAgICAgfSkudGhlbigoKT0+IHtcbiAgICAgICAgICAgIHNlbGYuZmQuY2xvc2UoKTtcbiAgICAgICAgfSwgKGVycikgPT4ge1xuICAgICAgICAgICAgc2VsZi5mZC5jbG9zZSgpO1xuICAgICAgICAgICAgdGhyb3cgKGVycik7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGFzeW5jIGRpc2NhcmQoKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBhd2FpdCBzZWxmLmNsb3NlKCk7XG4gICAgICAgIGF3YWl0IGZzLnByb21pc2VzLnVubGluayh0aGlzLmZpbGVOYW1lKTtcbiAgICB9XG5cbiAgICBhc3luYyB3cml0ZVVMRTMyKHYsIHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgY29uc3QgdG1wQnVmZjMyID0gbmV3IFVpbnQ4QXJyYXkoNCk7XG4gICAgICAgIGNvbnN0IHRtcEJ1ZmYzMnYgPSBuZXcgRGF0YVZpZXcodG1wQnVmZjMyLmJ1ZmZlcik7XG5cbiAgICAgICAgdG1wQnVmZjMydi5zZXRVaW50MzIoMCwgdiwgdHJ1ZSk7XG5cbiAgICAgICAgYXdhaXQgc2VsZi53cml0ZSh0bXBCdWZmMzIsIHBvcyk7XG4gICAgfVxuXG4gICAgYXN5bmMgd3JpdGVVQkUzMih2LCBwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICAgICAgY29uc3QgdG1wQnVmZjMyID0gbmV3IFVpbnQ4QXJyYXkoNCk7XG4gICAgICAgIGNvbnN0IHRtcEJ1ZmYzMnYgPSBuZXcgRGF0YVZpZXcodG1wQnVmZjMyLmJ1ZmZlcik7XG5cbiAgICAgICAgdG1wQnVmZjMydi5zZXRVaW50MzIoMCwgdiwgZmFsc2UpO1xuXG4gICAgICAgIGF3YWl0IHNlbGYud3JpdGUodG1wQnVmZjMyLCBwb3MpO1xuICAgIH1cblxuXG4gICAgYXN5bmMgd3JpdGVVTEU2NCh2LCBwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICAgICAgY29uc3QgdG1wQnVmZjY0ID0gbmV3IFVpbnQ4QXJyYXkoOCk7XG4gICAgICAgIGNvbnN0IHRtcEJ1ZmY2NHYgPSBuZXcgRGF0YVZpZXcodG1wQnVmZjY0LmJ1ZmZlcik7XG5cbiAgICAgICAgdG1wQnVmZjY0di5zZXRVaW50MzIoMCwgdiAmIDB4RkZGRkZGRkYsIHRydWUpO1xuICAgICAgICB0bXBCdWZmNjR2LnNldFVpbnQzMig0LCBNYXRoLmZsb29yKHYgLyAweDEwMDAwMDAwMCkgLCB0cnVlKTtcblxuICAgICAgICBhd2FpdCBzZWxmLndyaXRlKHRtcEJ1ZmY2NCwgcG9zKTtcbiAgICB9XG5cbiAgICBhc3luYyByZWFkVUxFMzIocG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBjb25zdCBiID0gYXdhaXQgc2VsZi5yZWFkKDQsIHBvcyk7XG5cbiAgICAgICAgY29uc3QgdmlldyA9IG5ldyBVaW50MzJBcnJheShiLmJ1ZmZlcik7XG5cbiAgICAgICAgcmV0dXJuIHZpZXdbMF07XG4gICAgfVxuXG4gICAgYXN5bmMgcmVhZFVCRTMyKHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgY29uc3QgYiA9IGF3YWl0IHNlbGYucmVhZCg0LCBwb3MpO1xuXG4gICAgICAgIGNvbnN0IHZpZXcgPSBuZXcgRGF0YVZpZXcoYi5idWZmZXIpO1xuXG4gICAgICAgIHJldHVybiB2aWV3LmdldFVpbnQzMigwLCBmYWxzZSk7XG4gICAgfVxuXG4gICAgYXN5bmMgcmVhZFVMRTY0KHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgY29uc3QgYiA9IGF3YWl0IHNlbGYucmVhZCg4LCBwb3MpO1xuXG4gICAgICAgIGNvbnN0IHZpZXcgPSBuZXcgVWludDMyQXJyYXkoYi5idWZmZXIpO1xuXG4gICAgICAgIHJldHVybiB2aWV3WzFdICogMHgxMDAwMDAwMDAgKyB2aWV3WzBdO1xuICAgIH1cblxuICAgIGFzeW5jIHJlYWRTdHJpbmcocG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gICAgICAgIGlmIChzZWxmLnBlbmRpbmdDbG9zZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUmVhZGluZyBhIGNsb3NpbmcgZmlsZVwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBjdXJyZW50UG9zaXRpb24gPSB0eXBlb2YgcG9zID09IFwidW5kZWZpbmVkXCIgPyBzZWxmLnBvcyA6IHBvcztcbiAgICAgICAgbGV0IGN1cnJlbnRQYWdlID0gTWF0aC5mbG9vcihjdXJyZW50UG9zaXRpb24gLyBzZWxmLnBhZ2VTaXplKTtcblxuICAgICAgICBsZXQgZW5kT2ZTdHJpbmdGb3VuZCA9IGZhbHNlO1xuICAgICAgICBsZXQgc3RyID0gXCJcIjtcblxuICAgICAgICB3aGlsZSAoIWVuZE9mU3RyaW5nRm91bmQpIHtcbiAgICAgICAgICAgIC8vUmVhZCBwYWdlXG4gICAgICAgICAgICBsZXQgcGFnZVByb21pc2UgPSBzZWxmLl9sb2FkUGFnZShjdXJyZW50UGFnZSk7XG4gICAgICAgICAgICBzZWxmLl90cmlnZ2VyTG9hZCgpO1xuICAgICAgICAgICAgYXdhaXQgcGFnZVByb21pc2U7XG4gICAgICAgICAgICBzZWxmLl9fc3RhdHVzUGFnZShcIkFmdGVyIEF3YWl0IChyZWFkKTogXCIsIGN1cnJlbnRQYWdlKTtcblxuICAgICAgICAgICAgbGV0IG9mZnNldE9uUGFnZSA9IGN1cnJlbnRQb3NpdGlvbiAlIHNlbGYucGFnZVNpemU7XG5cbiAgICAgICAgICAgIGNvbnN0IGRhdGFBcnJheSA9IG5ldyBVaW50OEFycmF5KFxuICAgICAgICAgICAgICAgIHNlbGYucGFnZXNbY3VycmVudFBhZ2VdLmJ1ZmYuYnVmZmVyLFxuICAgICAgICAgICAgICAgIHNlbGYucGFnZXNbY3VycmVudFBhZ2VdLmJ1ZmYuYnl0ZU9mZnNldCArIG9mZnNldE9uUGFnZSxcbiAgICAgICAgICAgICAgICBzZWxmLnBhZ2VTaXplIC0gb2Zmc2V0T25QYWdlXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICBsZXQgaW5kZXhFbmRPZlN0cmluZyA9IGRhdGFBcnJheS5maW5kSW5kZXgoZWxlbWVudCA9PiBlbGVtZW50ID09PSAwKTtcbiAgICAgICAgICAgIGVuZE9mU3RyaW5nRm91bmQgPSBpbmRleEVuZE9mU3RyaW5nICE9PSAtMTtcblxuICAgICAgICAgICAgaWYgKGVuZE9mU3RyaW5nRm91bmQpIHtcbiAgICAgICAgICAgICAgICBzdHIgKz0gbmV3IFRleHREZWNvZGVyKCkuZGVjb2RlKGRhdGFBcnJheS5zbGljZSgwLCBpbmRleEVuZE9mU3RyaW5nKSk7XG4gICAgICAgICAgICAgICAgc2VsZi5wb3MgPSBjdXJyZW50UGFnZSAqIHRoaXMucGFnZVNpemUgKyBvZmZzZXRPblBhZ2UgKyBpbmRleEVuZE9mU3RyaW5nICsgMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3RyICs9IG5ldyBUZXh0RGVjb2RlcigpLmRlY29kZShkYXRhQXJyYXkpO1xuICAgICAgICAgICAgICAgIHNlbGYucG9zID0gY3VycmVudFBhZ2UgKiB0aGlzLnBhZ2VTaXplICsgb2Zmc2V0T25QYWdlICsgZGF0YUFycmF5Lmxlbmd0aDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc2VsZi5wYWdlc1tjdXJyZW50UGFnZV0ucGVuZGluZ09wcy0tO1xuICAgICAgICAgICAgc2VsZi5fX3N0YXR1c1BhZ2UoXCJBZnRlciBPcCBkb25lOiBcIiwgY3VycmVudFBhZ2UpO1xuXG4gICAgICAgICAgICBjdXJyZW50UG9zaXRpb24gPSBzZWxmLnBvcztcbiAgICAgICAgICAgIGN1cnJlbnRQYWdlKys7XG5cbiAgICAgICAgICAgIGlmIChzZWxmLnBlbmRpbmdMb2Fkcy5sZW5ndGggPiAwKSBzZXRJbW1lZGlhdGUoc2VsZi5fdHJpZ2dlckxvYWQuYmluZChzZWxmKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc3RyO1xuICAgIH1cbn1cbiIsImV4cG9ydCBmdW5jdGlvbiBjcmVhdGVOZXcobykge1xuICAgIGNvbnN0IGluaXRpYWxTaXplID0gby5pbml0aWFsU2l6ZSB8fCAxPDwyMDtcbiAgICBjb25zdCBmZCA9IG5ldyBNZW1GaWxlKCk7XG4gICAgZmQubyA9IG87XG4gICAgZmQuby5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoaW5pdGlhbFNpemUpO1xuICAgIGZkLmFsbG9jU2l6ZSA9IGluaXRpYWxTaXplO1xuICAgIGZkLnRvdGFsU2l6ZSA9IDA7XG4gICAgZmQucmVhZE9ubHkgPSBmYWxzZTtcbiAgICBmZC5wb3MgPSAwO1xuICAgIHJldHVybiBmZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlYWRFeGlzdGluZyhvKSB7XG4gICAgY29uc3QgZmQgPSBuZXcgTWVtRmlsZSgpO1xuICAgIGZkLm8gPSBvO1xuICAgIGZkLmFsbG9jU2l6ZSA9IG8uZGF0YS5ieXRlTGVuZ3RoO1xuICAgIGZkLnRvdGFsU2l6ZSA9IG8uZGF0YS5ieXRlTGVuZ3RoO1xuICAgIGZkLnJlYWRPbmx5ID0gdHJ1ZTtcbiAgICBmZC5wb3MgPSAwO1xuICAgIHJldHVybiBmZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlYWRXcml0ZUV4aXN0aW5nKG8pIHtcbiAgICBjb25zdCBmZCA9IG5ldyBNZW1GaWxlKCk7XG4gICAgZmQubyA9IG87XG4gICAgZmQuYWxsb2NTaXplID0gby5kYXRhLmJ5dGVMZW5ndGg7XG4gICAgZmQudG90YWxTaXplID0gby5kYXRhLmJ5dGVMZW5ndGg7XG4gICAgZmQucmVhZE9ubHkgPSBmYWxzZTtcbiAgICBmZC5wb3MgPSAwO1xuICAgIHJldHVybiBmZDtcbn1cblxuY29uc3QgdG1wQnVmZjMyID0gbmV3IFVpbnQ4QXJyYXkoNCk7XG5jb25zdCB0bXBCdWZmMzJ2ID0gbmV3IERhdGFWaWV3KHRtcEJ1ZmYzMi5idWZmZXIpO1xuY29uc3QgdG1wQnVmZjY0ID0gbmV3IFVpbnQ4QXJyYXkoOCk7XG5jb25zdCB0bXBCdWZmNjR2ID0gbmV3IERhdGFWaWV3KHRtcEJ1ZmY2NC5idWZmZXIpO1xuXG5jbGFzcyBNZW1GaWxlIHtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLnBhZ2VTaXplID0gMSA8PCAxNDsgIC8vIGZvciBjb21wYXRpYmlsaXR5XG4gICAgfVxuXG4gICAgX3Jlc2l6ZUlmTmVlZGVkKG5ld0xlbikge1xuICAgICAgICBpZiAobmV3TGVuID4gdGhpcy5hbGxvY1NpemUpIHtcbiAgICAgICAgICAgIGNvbnN0IG5ld0FsbG9jU2l6ZSA9IE1hdGgubWF4KFxuICAgICAgICAgICAgICAgIHRoaXMuYWxsb2NTaXplICsgKDEgPDwgMjApLFxuICAgICAgICAgICAgICAgIE1hdGguZmxvb3IodGhpcy5hbGxvY1NpemUgKiAxLjEpLFxuICAgICAgICAgICAgICAgIG5ld0xlblxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IG5ld0RhdGEgPSBuZXcgVWludDhBcnJheShuZXdBbGxvY1NpemUpO1xuICAgICAgICAgICAgbmV3RGF0YS5zZXQodGhpcy5vLmRhdGEpO1xuICAgICAgICAgICAgdGhpcy5vLmRhdGEgPSBuZXdEYXRhO1xuICAgICAgICAgICAgdGhpcy5hbGxvY1NpemUgPSBuZXdBbGxvY1NpemU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhc3luYyB3cml0ZShidWZmLCBwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9dGhpcztcbiAgICAgICAgaWYgKHR5cGVvZiBwb3MgPT0gXCJ1bmRlZmluZWRcIikgcG9zID0gc2VsZi5wb3M7XG4gICAgICAgIGlmICh0aGlzLnJlYWRPbmx5KSB0aHJvdyBuZXcgRXJyb3IoXCJXcml0aW5nIGEgcmVhZCBvbmx5IGZpbGVcIik7XG5cbiAgICAgICAgdGhpcy5fcmVzaXplSWZOZWVkZWQocG9zICsgYnVmZi5ieXRlTGVuZ3RoKTtcblxuICAgICAgICB0aGlzLm8uZGF0YS5zZXQoYnVmZi5zbGljZSgpLCBwb3MpO1xuXG4gICAgICAgIGlmIChwb3MgKyBidWZmLmJ5dGVMZW5ndGggPiB0aGlzLnRvdGFsU2l6ZSkgdGhpcy50b3RhbFNpemUgPSBwb3MgKyBidWZmLmJ5dGVMZW5ndGg7XG5cbiAgICAgICAgdGhpcy5wb3MgPSBwb3MgKyBidWZmLmJ5dGVMZW5ndGg7XG4gICAgfVxuXG4gICAgYXN5bmMgcmVhZFRvQnVmZmVyKGJ1ZmZEZXN0LCBvZmZzZXQsIGxlbiwgcG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBpZiAodHlwZW9mIHBvcyA9PSBcInVuZGVmaW5lZFwiKSBwb3MgPSBzZWxmLnBvcztcbiAgICAgICAgaWYgKHRoaXMucmVhZE9ubHkpIHtcbiAgICAgICAgICAgIGlmIChwb3MgKyBsZW4gPiB0aGlzLnRvdGFsU2l6ZSkgdGhyb3cgbmV3IEVycm9yKFwiUmVhZGluZyBvdXQgb2YgYm91bmRzXCIpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3Jlc2l6ZUlmTmVlZGVkKHBvcyArIGxlbik7XG5cbiAgICAgICAgY29uc3QgYnVmZlNyYyA9IG5ldyBVaW50OEFycmF5KHRoaXMuby5kYXRhLmJ1ZmZlciwgdGhpcy5vLmRhdGEuYnl0ZU9mZnNldCArIHBvcywgbGVuKTtcblxuICAgICAgICBidWZmRGVzdC5zZXQoYnVmZlNyYywgb2Zmc2V0KTtcblxuICAgICAgICB0aGlzLnBvcyA9IHBvcyArIGxlbjtcbiAgICB9XG5cbiAgICBhc3luYyByZWFkKGxlbiwgcG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gICAgICAgIGNvbnN0IGJ1ZmYgPSBuZXcgVWludDhBcnJheShsZW4pO1xuICAgICAgICBhd2FpdCBzZWxmLnJlYWRUb0J1ZmZlcihidWZmLCAwLCBsZW4sIHBvcyk7XG5cbiAgICAgICAgcmV0dXJuIGJ1ZmY7XG4gICAgfVxuXG4gICAgY2xvc2UoKSB7XG4gICAgICAgIGlmICh0aGlzLm8uZGF0YS5ieXRlTGVuZ3RoICE9IHRoaXMudG90YWxTaXplKSB7XG4gICAgICAgICAgICB0aGlzLm8uZGF0YSA9IHRoaXMuby5kYXRhLnNsaWNlKDAsIHRoaXMudG90YWxTaXplKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIGRpc2NhcmQoKSB7XG4gICAgfVxuXG5cbiAgICBhc3luYyB3cml0ZVVMRTMyKHYsIHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcblxuICAgICAgICB0bXBCdWZmMzJ2LnNldFVpbnQzMigwLCB2LCB0cnVlKTtcblxuICAgICAgICBhd2FpdCBzZWxmLndyaXRlKHRtcEJ1ZmYzMiwgcG9zKTtcbiAgICB9XG5cbiAgICBhc3luYyB3cml0ZVVCRTMyKHYsIHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcblxuICAgICAgICB0bXBCdWZmMzJ2LnNldFVpbnQzMigwLCB2LCBmYWxzZSk7XG5cbiAgICAgICAgYXdhaXQgc2VsZi53cml0ZSh0bXBCdWZmMzIsIHBvcyk7XG4gICAgfVxuXG5cbiAgICBhc3luYyB3cml0ZVVMRTY0KHYsIHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcblxuICAgICAgICB0bXBCdWZmNjR2LnNldFVpbnQzMigwLCB2ICYgMHhGRkZGRkZGRiwgdHJ1ZSk7XG4gICAgICAgIHRtcEJ1ZmY2NHYuc2V0VWludDMyKDQsIE1hdGguZmxvb3IodiAvIDB4MTAwMDAwMDAwKSAsIHRydWUpO1xuXG4gICAgICAgIGF3YWl0IHNlbGYud3JpdGUodG1wQnVmZjY0LCBwb3MpO1xuICAgIH1cblxuXG4gICAgYXN5bmMgcmVhZFVMRTMyKHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgY29uc3QgYiA9IGF3YWl0IHNlbGYucmVhZCg0LCBwb3MpO1xuXG4gICAgICAgIGNvbnN0IHZpZXcgPSBuZXcgVWludDMyQXJyYXkoYi5idWZmZXIpO1xuXG4gICAgICAgIHJldHVybiB2aWV3WzBdO1xuICAgIH1cblxuICAgIGFzeW5jIHJlYWRVQkUzMihwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGNvbnN0IGIgPSBhd2FpdCBzZWxmLnJlYWQoNCwgcG9zKTtcblxuICAgICAgICBjb25zdCB2aWV3ID0gbmV3IERhdGFWaWV3KGIuYnVmZmVyKTtcblxuICAgICAgICByZXR1cm4gdmlldy5nZXRVaW50MzIoMCwgZmFsc2UpO1xuICAgIH1cblxuICAgIGFzeW5jIHJlYWRVTEU2NChwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGNvbnN0IGIgPSBhd2FpdCBzZWxmLnJlYWQoOCwgcG9zKTtcblxuICAgICAgICBjb25zdCB2aWV3ID0gbmV3IFVpbnQzMkFycmF5KGIuYnVmZmVyKTtcblxuICAgICAgICByZXR1cm4gdmlld1sxXSAqIDB4MTAwMDAwMDAwICsgdmlld1swXTtcbiAgICB9XG5cbiAgICBhc3luYyByZWFkU3RyaW5nKHBvcykge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcblxuICAgICAgICBsZXQgY3VycmVudFBvc2l0aW9uID0gdHlwZW9mIHBvcyA9PSBcInVuZGVmaW5lZFwiID8gc2VsZi5wb3MgOiBwb3M7XG5cbiAgICAgICAgaWYgKGN1cnJlbnRQb3NpdGlvbiA+IHRoaXMudG90YWxTaXplKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkT25seSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlJlYWRpbmcgb3V0IG9mIGJvdW5kc1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3Jlc2l6ZUlmTmVlZGVkKHBvcyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZGF0YUFycmF5ID0gbmV3IFVpbnQ4QXJyYXkoXG4gICAgICAgICAgICBzZWxmLm8uZGF0YS5idWZmZXIsXG4gICAgICAgICAgICBjdXJyZW50UG9zaXRpb24sXG4gICAgICAgICAgICB0aGlzLnRvdGFsU2l6ZSAtIGN1cnJlbnRQb3NpdGlvblxuICAgICAgICApO1xuXG4gICAgICAgIGxldCBpbmRleEVuZE9mU3RyaW5nID0gZGF0YUFycmF5LmZpbmRJbmRleChlbGVtZW50ID0+IGVsZW1lbnQgPT09IDApO1xuICAgICAgICBsZXQgZW5kT2ZTdHJpbmdGb3VuZCA9IGluZGV4RW5kT2ZTdHJpbmcgIT09IC0xO1xuXG4gICAgICAgIGxldCBzdHIgPSBcIlwiO1xuICAgICAgICBpZiAoZW5kT2ZTdHJpbmdGb3VuZCkge1xuICAgICAgICAgICAgc3RyID0gbmV3IFRleHREZWNvZGVyKCkuZGVjb2RlKGRhdGFBcnJheS5zbGljZSgwLCBpbmRleEVuZE9mU3RyaW5nKSk7XG4gICAgICAgICAgICBzZWxmLnBvcyA9IGN1cnJlbnRQb3NpdGlvbiArIGluZGV4RW5kT2ZTdHJpbmcgKyAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2VsZi5wb3MgPSBjdXJyZW50UG9zaXRpb247XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0cjtcbiAgICB9XG59XG4iLCJjb25zdCBQQUdFX1NJWkUgPSAxPDwyMjtcblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZU5ldyhvKSB7XG4gICAgY29uc3QgaW5pdGlhbFNpemUgPSBvLmluaXRpYWxTaXplIHx8IDA7XG4gICAgY29uc3QgZmQgPSBuZXcgQmlnTWVtRmlsZSgpO1xuICAgIGZkLm8gPSBvO1xuICAgIGNvbnN0IG5QYWdlcyA9IGluaXRpYWxTaXplID8gTWF0aC5mbG9vcigoaW5pdGlhbFNpemUgLSAxKSAvIFBBR0VfU0laRSkrMSA6IDA7XG4gICAgZmQuby5kYXRhID0gW107XG4gICAgZm9yIChsZXQgaT0wOyBpPG5QYWdlcy0xOyBpKyspIHtcbiAgICAgICAgZmQuby5kYXRhLnB1c2goIG5ldyBVaW50OEFycmF5KFBBR0VfU0laRSkpO1xuICAgIH1cbiAgICBpZiAoblBhZ2VzKSBmZC5vLmRhdGEucHVzaCggbmV3IFVpbnQ4QXJyYXkoaW5pdGlhbFNpemUgLSBQQUdFX1NJWkUqKG5QYWdlcy0xKSkpO1xuICAgIGZkLnRvdGFsU2l6ZSA9IDA7XG4gICAgZmQucmVhZE9ubHkgPSBmYWxzZTtcbiAgICBmZC5wb3MgPSAwO1xuICAgIHJldHVybiBmZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlYWRFeGlzdGluZyhvKSB7XG4gICAgY29uc3QgZmQgPSBuZXcgQmlnTWVtRmlsZSgpO1xuICAgIGZkLm8gPSBvO1xuICAgIGZkLnRvdGFsU2l6ZSA9IChvLmRhdGEubGVuZ3RoLTEpKiBQQUdFX1NJWkUgKyBvLmRhdGFbby5kYXRhLmxlbmd0aC0xXS5ieXRlTGVuZ3RoO1xuICAgIGZkLnJlYWRPbmx5ID0gdHJ1ZTtcbiAgICBmZC5wb3MgPSAwO1xuICAgIHJldHVybiBmZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlYWRXcml0ZUV4aXN0aW5nKG8pIHtcbiAgICBjb25zdCBmZCA9IG5ldyBCaWdNZW1GaWxlKCk7XG4gICAgZmQubyA9IG87XG4gICAgZmQudG90YWxTaXplID0gKG8uZGF0YS5sZW5ndGgtMSkqIFBBR0VfU0laRSArIG8uZGF0YVtvLmRhdGEubGVuZ3RoLTFdLmJ5dGVMZW5ndGg7XG4gICAgZmQucmVhZE9ubHkgPSBmYWxzZTtcbiAgICBmZC5wb3MgPSAwO1xuICAgIHJldHVybiBmZDtcbn1cblxuY29uc3QgdG1wQnVmZjMyID0gbmV3IFVpbnQ4QXJyYXkoNCk7XG5jb25zdCB0bXBCdWZmMzJ2ID0gbmV3IERhdGFWaWV3KHRtcEJ1ZmYzMi5idWZmZXIpO1xuY29uc3QgdG1wQnVmZjY0ID0gbmV3IFVpbnQ4QXJyYXkoOCk7XG5jb25zdCB0bXBCdWZmNjR2ID0gbmV3IERhdGFWaWV3KHRtcEJ1ZmY2NC5idWZmZXIpO1xuXG5jbGFzcyBCaWdNZW1GaWxlIHtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLnBhZ2VTaXplID0gMSA8PCAxNDsgIC8vIGZvciBjb21wYXRpYmlsaXR5XG4gICAgfVxuXG4gICAgX3Jlc2l6ZUlmTmVlZGVkKG5ld0xlbikge1xuXG4gICAgICAgIGlmIChuZXdMZW4gPD0gdGhpcy50b3RhbFNpemUpIHJldHVybjtcblxuICAgICAgICBpZiAodGhpcy5yZWFkT25seSkgdGhyb3cgbmV3IEVycm9yKFwiUmVhZGluZyBvdXQgb2YgZmlsZSBib3VuZHNcIik7XG5cbiAgICAgICAgY29uc3QgblBhZ2VzID0gTWF0aC5mbG9vcigobmV3TGVuIC0gMSkgLyBQQUdFX1NJWkUpKzE7XG4gICAgICAgIGZvciAobGV0IGk9IE1hdGgubWF4KHRoaXMuby5kYXRhLmxlbmd0aC0xLCAwKTsgaTxuUGFnZXM7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgbmV3U2l6ZSA9IGk8blBhZ2VzLTEgPyBQQUdFX1NJWkUgOiBuZXdMZW4gLSAoblBhZ2VzLTEpKlBBR0VfU0laRTtcbiAgICAgICAgICAgIGNvbnN0IHAgPSBuZXcgVWludDhBcnJheShuZXdTaXplKTtcbiAgICAgICAgICAgIGlmIChpID09IHRoaXMuby5kYXRhLmxlbmd0aC0xKSBwLnNldCh0aGlzLm8uZGF0YVtpXSk7XG4gICAgICAgICAgICB0aGlzLm8uZGF0YVtpXSA9IHA7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy50b3RhbFNpemUgPSBuZXdMZW47XG4gICAgfVxuXG4gICAgYXN5bmMgd3JpdGUoYnVmZiwgcG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPXRoaXM7XG4gICAgICAgIGlmICh0eXBlb2YgcG9zID09IFwidW5kZWZpbmVkXCIpIHBvcyA9IHNlbGYucG9zO1xuICAgICAgICBpZiAodGhpcy5yZWFkT25seSkgdGhyb3cgbmV3IEVycm9yKFwiV3JpdGluZyBhIHJlYWQgb25seSBmaWxlXCIpO1xuXG4gICAgICAgIHRoaXMuX3Jlc2l6ZUlmTmVlZGVkKHBvcyArIGJ1ZmYuYnl0ZUxlbmd0aCk7XG5cbiAgICAgICAgY29uc3QgZmlyc3RQYWdlID0gTWF0aC5mbG9vcihwb3MgLyBQQUdFX1NJWkUpO1xuXG4gICAgICAgIGxldCBwID0gZmlyc3RQYWdlO1xuICAgICAgICBsZXQgbyA9IHBvcyAlIFBBR0VfU0laRTtcbiAgICAgICAgbGV0IHIgPSBidWZmLmJ5dGVMZW5ndGg7XG4gICAgICAgIHdoaWxlIChyPjApIHtcbiAgICAgICAgICAgIGNvbnN0IGwgPSAobytyID4gUEFHRV9TSVpFKSA/IChQQUdFX1NJWkUgLW8pIDogcjtcbiAgICAgICAgICAgIGNvbnN0IHNyY1ZpZXcgPSBidWZmLnNsaWNlKGJ1ZmYuYnl0ZUxlbmd0aCAtIHIsIGJ1ZmYuYnl0ZUxlbmd0aCAtIHIgKyBsKTtcbiAgICAgICAgICAgIGNvbnN0IGRzdFZpZXcgPSBuZXcgVWludDhBcnJheShzZWxmLm8uZGF0YVtwXS5idWZmZXIsIG8sIGwpO1xuICAgICAgICAgICAgZHN0Vmlldy5zZXQoc3JjVmlldyk7XG4gICAgICAgICAgICByID0gci1sO1xuICAgICAgICAgICAgcCArKztcbiAgICAgICAgICAgIG8gPSAwO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5wb3MgPSBwb3MgKyBidWZmLmJ5dGVMZW5ndGg7XG4gICAgfVxuXG4gICAgYXN5bmMgcmVhZFRvQnVmZmVyKGJ1ZmZEc3QsIG9mZnNldCwgbGVuLCBwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGlmICh0eXBlb2YgcG9zID09IFwidW5kZWZpbmVkXCIpIHBvcyA9IHNlbGYucG9zO1xuICAgICAgICBpZiAodGhpcy5yZWFkT25seSkge1xuICAgICAgICAgICAgaWYgKHBvcyArIGxlbiA+IHRoaXMudG90YWxTaXplKSB0aHJvdyBuZXcgRXJyb3IoXCJSZWFkaW5nIG91dCBvZiBib3VuZHNcIik7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcmVzaXplSWZOZWVkZWQocG9zICsgbGVuKTtcblxuICAgICAgICBjb25zdCBmaXJzdFBhZ2UgPSBNYXRoLmZsb29yKHBvcyAvIFBBR0VfU0laRSk7XG5cbiAgICAgICAgbGV0IHAgPSBmaXJzdFBhZ2U7XG4gICAgICAgIGxldCBvID0gcG9zICUgUEFHRV9TSVpFO1xuICAgICAgICAvLyBSZW1haW5pbmcgYnl0ZXMgdG8gcmVhZFxuICAgICAgICBsZXQgciA9IGxlbjtcbiAgICAgICAgd2hpbGUgKHI+MCkge1xuICAgICAgICAgICAgLy8gYnl0ZXMgdG8gY29weSBmcm9tIHRoaXMgcGFnZVxuICAgICAgICAgICAgY29uc3QgbCA9IChvK3IgPiBQQUdFX1NJWkUpID8gKFBBR0VfU0laRSAtbykgOiByO1xuICAgICAgICAgICAgY29uc3Qgc3JjVmlldyA9IG5ldyBVaW50OEFycmF5KHNlbGYuby5kYXRhW3BdLmJ1ZmZlciwgbywgbCk7XG4gICAgICAgICAgICBidWZmRHN0LnNldChzcmNWaWV3LCBvZmZzZXQrbGVuLXIpO1xuICAgICAgICAgICAgciA9IHItbDtcbiAgICAgICAgICAgIHAgKys7XG4gICAgICAgICAgICBvID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucG9zID0gcG9zICsgbGVuO1xuICAgIH1cblxuICAgIGFzeW5jIHJlYWQobGVuLCBwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGNvbnN0IGJ1ZmYgPSBuZXcgVWludDhBcnJheShsZW4pO1xuXG4gICAgICAgIGF3YWl0IHNlbGYucmVhZFRvQnVmZmVyKGJ1ZmYsIDAsIGxlbiwgcG9zKTtcblxuICAgICAgICByZXR1cm4gYnVmZjtcbiAgICB9XG5cbiAgICBjbG9zZSgpIHtcbiAgICB9XG5cbiAgICBhc3luYyBkaXNjYXJkKCkge1xuICAgIH1cblxuXG4gICAgYXN5bmMgd3JpdGVVTEUzMih2LCBwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICAgICAgdG1wQnVmZjMydi5zZXRVaW50MzIoMCwgdiwgdHJ1ZSk7XG5cbiAgICAgICAgYXdhaXQgc2VsZi53cml0ZSh0bXBCdWZmMzIsIHBvcyk7XG4gICAgfVxuXG4gICAgYXN5bmMgd3JpdGVVQkUzMih2LCBwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICAgICAgdG1wQnVmZjMydi5zZXRVaW50MzIoMCwgdiwgZmFsc2UpO1xuXG4gICAgICAgIGF3YWl0IHNlbGYud3JpdGUodG1wQnVmZjMyLCBwb3MpO1xuICAgIH1cblxuXG4gICAgYXN5bmMgd3JpdGVVTEU2NCh2LCBwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICAgICAgdG1wQnVmZjY0di5zZXRVaW50MzIoMCwgdiAmIDB4RkZGRkZGRkYsIHRydWUpO1xuICAgICAgICB0bXBCdWZmNjR2LnNldFVpbnQzMig0LCBNYXRoLmZsb29yKHYgLyAweDEwMDAwMDAwMCkgLCB0cnVlKTtcblxuICAgICAgICBhd2FpdCBzZWxmLndyaXRlKHRtcEJ1ZmY2NCwgcG9zKTtcbiAgICB9XG5cblxuICAgIGFzeW5jIHJlYWRVTEUzMihwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGNvbnN0IGIgPSBhd2FpdCBzZWxmLnJlYWQoNCwgcG9zKTtcblxuICAgICAgICBjb25zdCB2aWV3ID0gbmV3IFVpbnQzMkFycmF5KGIuYnVmZmVyKTtcblxuICAgICAgICByZXR1cm4gdmlld1swXTtcbiAgICB9XG5cbiAgICBhc3luYyByZWFkVUJFMzIocG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBjb25zdCBiID0gYXdhaXQgc2VsZi5yZWFkKDQsIHBvcyk7XG5cbiAgICAgICAgY29uc3QgdmlldyA9IG5ldyBEYXRhVmlldyhiLmJ1ZmZlcik7XG5cbiAgICAgICAgcmV0dXJuIHZpZXcuZ2V0VWludDMyKDAsIGZhbHNlKTtcbiAgICB9XG5cbiAgICBhc3luYyByZWFkVUxFNjQocG9zKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBjb25zdCBiID0gYXdhaXQgc2VsZi5yZWFkKDgsIHBvcyk7XG5cbiAgICAgICAgY29uc3QgdmlldyA9IG5ldyBVaW50MzJBcnJheShiLmJ1ZmZlcik7XG5cbiAgICAgICAgcmV0dXJuIHZpZXdbMV0gKiAweDEwMDAwMDAwMCArIHZpZXdbMF07XG4gICAgfVxuXG4gICAgYXN5bmMgcmVhZFN0cmluZyhwb3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGNvbnN0IGZpeGVkU2l6ZSA9IDIwNDg7XG5cbiAgICAgICAgbGV0IGN1cnJlbnRQb3NpdGlvbiA9IHR5cGVvZiBwb3MgPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYucG9zIDogcG9zO1xuXG4gICAgICAgIGlmIChjdXJyZW50UG9zaXRpb24gPiB0aGlzLnRvdGFsU2l6ZSkge1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZE9ubHkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJSZWFkaW5nIG91dCBvZiBib3VuZHNcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9yZXNpemVJZk5lZWRlZChwb3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGVuZE9mU3RyaW5nRm91bmQgPSBmYWxzZTtcbiAgICAgICAgbGV0IHN0ciA9IFwiXCI7XG5cbiAgICAgICAgd2hpbGUgKCFlbmRPZlN0cmluZ0ZvdW5kKSB7XG4gICAgICAgICAgICBsZXQgY3VycmVudFBhZ2UgPSBNYXRoLmZsb29yKGN1cnJlbnRQb3NpdGlvbiAvIFBBR0VfU0laRSk7XG4gICAgICAgICAgICBsZXQgb2Zmc2V0T25QYWdlID0gY3VycmVudFBvc2l0aW9uICUgUEFHRV9TSVpFO1xuXG4gICAgICAgICAgICBpZiAoc2VsZi5vLmRhdGFbY3VycmVudFBhZ2VdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJFUlJPUlwiKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV0IHJlYWRMZW5ndGggPSBNYXRoLm1pbihmaXhlZFNpemUsIHNlbGYuby5kYXRhW2N1cnJlbnRQYWdlXS5sZW5ndGggLSBvZmZzZXRPblBhZ2UpO1xuICAgICAgICAgICAgY29uc3QgZGF0YUFycmF5ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5vLmRhdGFbY3VycmVudFBhZ2VdLmJ1ZmZlciwgb2Zmc2V0T25QYWdlLCByZWFkTGVuZ3RoKTtcblxuICAgICAgICAgICAgbGV0IGluZGV4RW5kT2ZTdHJpbmcgPSBkYXRhQXJyYXkuZmluZEluZGV4KGVsZW1lbnQgPT4gZWxlbWVudCA9PT0gMCk7XG4gICAgICAgICAgICBlbmRPZlN0cmluZ0ZvdW5kID0gaW5kZXhFbmRPZlN0cmluZyAhPT0gLTE7XG5cbiAgICAgICAgICAgIGlmIChlbmRPZlN0cmluZ0ZvdW5kKSB7XG4gICAgICAgICAgICAgICAgc3RyICs9IG5ldyBUZXh0RGVjb2RlcigpLmRlY29kZShkYXRhQXJyYXkuc2xpY2UoMCwgaW5kZXhFbmRPZlN0cmluZykpO1xuICAgICAgICAgICAgICAgIHNlbGYucG9zID0gY3VycmVudFBhZ2UgKiBQQUdFX1NJWkUgKyBvZmZzZXRPblBhZ2UgKyBpbmRleEVuZE9mU3RyaW5nICsgMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3RyICs9IG5ldyBUZXh0RGVjb2RlcigpLmRlY29kZShkYXRhQXJyYXkpO1xuICAgICAgICAgICAgICAgIHNlbGYucG9zID0gY3VycmVudFBhZ2UgKiBQQUdFX1NJWkUgKyBvZmZzZXRPblBhZ2UgKyBkYXRhQXJyYXkubGVuZ3RoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjdXJyZW50UG9zaXRpb24gPSBzZWxmLnBvcztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3RyO1xuICAgIH1cbn1cbiIsIi8qIGdsb2JhbCBmZXRjaCAqL1xuaW1wb3J0IHsgb3BlbiB9IGZyb20gXCIuL29zZmlsZS5qc1wiO1xuaW1wb3J0ICogYXMgbWVtRmlsZSBmcm9tIFwiLi9tZW1maWxlLmpzXCI7XG5pbXBvcnQgKiBhcyBiaWdNZW1GaWxlIGZyb20gXCIuL2JpZ21lbWZpbGUuanNcIjtcbmltcG9ydCB7IE9fVFJVTkMsIE9fQ1JFQVQsIE9fUkRXUiwgT19FWENMLCBPX1JET05MWSB9IGZyb20gXCJjb25zdGFudHNcIjtcblxuY29uc3QgREVGQVVMVF9DQUNIRV9TSVpFID0gKDEgPDwgMTYpO1xuY29uc3QgREVGQVVMVF9QQUdFX1NJWkUgPSAoMSA8PCAxMyk7XG5cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZU92ZXJyaWRlKG8sIGIsIGMpIHtcbiAgICBpZiAodHlwZW9mIG8gPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgbyA9IHtcbiAgICAgICAgICAgIHR5cGU6IFwiZmlsZVwiLFxuICAgICAgICAgICAgZmlsZU5hbWU6IG8sXG4gICAgICAgICAgICBjYWNoZVNpemU6IGIgfHwgREVGQVVMVF9DQUNIRV9TSVpFLFxuICAgICAgICAgICAgcGFnZVNpemU6IGMgfHwgREVGQVVMVF9QQUdFX1NJWkVcbiAgICAgICAgfTtcbiAgICB9XG4gICAgaWYgKG8udHlwZSA9PSBcImZpbGVcIikge1xuICAgICAgICByZXR1cm4gYXdhaXQgb3BlbihvLmZpbGVOYW1lLCBPX1RSVU5DIHwgT19DUkVBVCB8IE9fUkRXUiwgby5jYWNoZVNpemUsIG8ucGFnZVNpemUpO1xuICAgIH0gZWxzZSBpZiAoby50eXBlID09IFwibWVtXCIpIHtcbiAgICAgICAgcmV0dXJuIG1lbUZpbGUuY3JlYXRlTmV3KG8pO1xuICAgIH0gZWxzZSBpZiAoby50eXBlID09IFwiYmlnTWVtXCIpIHtcbiAgICAgICAgcmV0dXJuIGJpZ01lbUZpbGUuY3JlYXRlTmV3KG8pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgRmFzdEZpbGUgdHlwZTogXCIrby50eXBlKTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVOb092ZXJyaWRlKG8sIGIsIGMpIHtcbiAgICBpZiAodHlwZW9mIG8gPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgbyA9IHtcbiAgICAgICAgICAgIHR5cGU6IFwiZmlsZVwiLFxuICAgICAgICAgICAgZmlsZU5hbWU6IG8sXG4gICAgICAgICAgICBjYWNoZVNpemU6IGIgfHwgREVGQVVMVF9DQUNIRV9TSVpFLFxuICAgICAgICAgICAgcGFnZVNpemU6IGMgfHwgREVGQVVMVF9QQUdFX1NJWkVcbiAgICAgICAgfTtcbiAgICB9XG4gICAgaWYgKG8udHlwZSA9PSBcImZpbGVcIikge1xuICAgICAgICByZXR1cm4gb3BlbihvLmZpbGVOYW1lLCBPX1RSVU5DIHwgT19DUkVBVCB8IE9fUkRXUiB8IE9fRVhDTCwgby5jYWNoZVNpemUsIG8ucGFnZVNpemUpO1xuICAgIH0gZWxzZSBpZiAoby50eXBlID09IFwibWVtXCIpIHtcbiAgICAgICAgcmV0dXJuIG1lbUZpbGUuY3JlYXRlTmV3KG8pO1xuICAgIH0gZWxzZSBpZiAoby50eXBlID09IFwiYmlnTWVtXCIpIHtcbiAgICAgICAgcmV0dXJuIGJpZ01lbUZpbGUuY3JlYXRlTmV3KG8pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgRmFzdEZpbGUgdHlwZTogXCIrby50eXBlKTtcbiAgICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWFkRXhpc3RpbmcobywgYiwgYykge1xuICAgIGlmIChvIGluc3RhbmNlb2YgVWludDhBcnJheSkge1xuICAgICAgICBvID0ge1xuICAgICAgICAgICAgdHlwZTogXCJtZW1cIixcbiAgICAgICAgICAgIGRhdGE6IG9cbiAgICAgICAgfTtcbiAgICB9XG4gICAgaWYgKHByb2Nlc3MuYnJvd3Nlcikge1xuICAgICAgICBpZiAodHlwZW9mIG8gPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmYgPSBhd2FpdCBmZXRjaChvKS50aGVuKCBmdW5jdGlvbihyZXMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzLmFycmF5QnVmZmVyKCk7XG4gICAgICAgICAgICB9KS50aGVuKGZ1bmN0aW9uIChhYikge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShhYik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIG8gPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJtZW1cIixcbiAgICAgICAgICAgICAgICBkYXRhOiBidWZmXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKHR5cGVvZiBvID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICBvID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6IFwiZmlsZVwiLFxuICAgICAgICAgICAgICAgIGZpbGVOYW1lOiBvLFxuICAgICAgICAgICAgICAgIGNhY2hlU2l6ZTogYiB8fCBERUZBVUxUX0NBQ0hFX1NJWkUsXG4gICAgICAgICAgICAgICAgcGFnZVNpemU6IGMgfHwgREVGQVVMVF9QQUdFX1NJWkVcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKG8udHlwZSA9PSBcImZpbGVcIikge1xuICAgICAgICByZXR1cm4gYXdhaXQgb3BlbihvLmZpbGVOYW1lLCBPX1JET05MWSwgby5jYWNoZVNpemUsIG8ucGFnZVNpemUpO1xuICAgIH0gZWxzZSBpZiAoby50eXBlID09IFwibWVtXCIpIHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IG1lbUZpbGUucmVhZEV4aXN0aW5nKG8pO1xuICAgIH0gZWxzZSBpZiAoby50eXBlID09IFwiYmlnTWVtXCIpIHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IGJpZ01lbUZpbGUucmVhZEV4aXN0aW5nKG8pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgRmFzdEZpbGUgdHlwZTogXCIrby50eXBlKTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWFkV3JpdGVFeGlzdGluZyhvLCBiLCBjKSB7XG4gICAgaWYgKHR5cGVvZiBvID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIG8gPSB7XG4gICAgICAgICAgICB0eXBlOiBcImZpbGVcIixcbiAgICAgICAgICAgIGZpbGVOYW1lOiBvLFxuICAgICAgICAgICAgY2FjaGVTaXplOiBiIHx8IERFRkFVTFRfQ0FDSEVfU0laRSxcbiAgICAgICAgICAgIHBhZ2VTaXplOiBjIHx8IERFRkFVTFRfUEFHRV9TSVpFXG4gICAgICAgIH07XG4gICAgfVxuICAgIGlmIChvLnR5cGUgPT0gXCJmaWxlXCIpIHtcbiAgICAgICAgcmV0dXJuIG9wZW4oby5maWxlTmFtZSwgT19DUkVBVCB8IE9fUkRXUiwgby5jYWNoZVNpemUsIG8ucGFnZVNpemUpO1xuICAgIH0gZWxzZSBpZiAoby50eXBlID09IFwibWVtXCIpIHtcbiAgICAgICAgcmV0dXJuIG1lbUZpbGUucmVhZFdyaXRlRXhpc3Rpbmcobyk7XG4gICAgfSBlbHNlIGlmIChvLnR5cGUgPT0gXCJiaWdNZW1cIikge1xuICAgICAgICByZXR1cm4gYmlnTWVtRmlsZS5yZWFkV3JpdGVFeGlzdGluZyhvKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIEZhc3RGaWxlIHR5cGU6IFwiK28udHlwZSk7XG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVhZFdyaXRlRXhpc3RpbmdPckNyZWF0ZShvLCBiLCBjKSB7XG4gICAgaWYgKHR5cGVvZiBvID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIG8gPSB7XG4gICAgICAgICAgICB0eXBlOiBcImZpbGVcIixcbiAgICAgICAgICAgIGZpbGVOYW1lOiBvLFxuICAgICAgICAgICAgY2FjaGVTaXplOiBiIHx8IERFRkFVTFRfQ0FDSEVfU0laRSxcbiAgICAgICAgICAgIHBhZ2VTaXplOiBjIHx8IERFRkFVTFRfUEFHRV9TSVpFXG4gICAgICAgIH07XG4gICAgfVxuICAgIGlmIChvLnR5cGUgPT0gXCJmaWxlXCIpIHtcbiAgICAgICAgcmV0dXJuIG9wZW4oby5maWxlTmFtZSwgT19DUkVBVCB8IE9fUkRXUiB8IE9fRVhDTCwgby5jYWNoZVNpemUpO1xuICAgIH0gZWxzZSBpZiAoby50eXBlID09IFwibWVtXCIpIHtcbiAgICAgICAgcmV0dXJuIG1lbUZpbGUucmVhZFdyaXRlRXhpc3Rpbmcobyk7XG4gICAgfSBlbHNlIGlmIChvLnR5cGUgPT0gXCJiaWdNZW1cIikge1xuICAgICAgICByZXR1cm4gYmlnTWVtRmlsZS5yZWFkV3JpdGVFeGlzdGluZyhvKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIEZhc3RGaWxlIHR5cGU6IFwiK28udHlwZSk7XG4gICAgfVxufVxuIiwiXG5pbXBvcnQgIHsgU2NhbGFyLCBCaWdCdWZmZXIgfSBmcm9tIFwiZmZqYXZhc2NyaXB0XCI7XG5pbXBvcnQgKiBhcyBmYXN0RmlsZSBmcm9tIFwiZmFzdGZpbGVcIjtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRCaW5GaWxlKGZpbGVOYW1lLCB0eXBlLCBtYXhWZXJzaW9uLCBjYWNoZVNpemUsIHBhZ2VTaXplKSB7XG5cbiAgICBjb25zdCBmZCA9IGF3YWl0IGZhc3RGaWxlLnJlYWRFeGlzdGluZyhmaWxlTmFtZSwgY2FjaGVTaXplLCBwYWdlU2l6ZSk7XG5cbiAgICBjb25zdCBiID0gYXdhaXQgZmQucmVhZCg0KTtcbiAgICBsZXQgcmVhZGVkVHlwZSA9IFwiXCI7XG4gICAgZm9yIChsZXQgaT0wOyBpPDQ7IGkrKykgcmVhZGVkVHlwZSArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJbaV0pO1xuXG4gICAgaWYgKHJlYWRlZFR5cGUgIT0gdHlwZSkgdGhyb3cgbmV3IEVycm9yKGZpbGVOYW1lICsgXCI6IEludmFsaWQgRmlsZSBmb3JtYXRcIik7XG5cbiAgICBsZXQgdiA9IGF3YWl0IGZkLnJlYWRVTEUzMigpO1xuXG4gICAgaWYgKHY+bWF4VmVyc2lvbikgdGhyb3cgbmV3IEVycm9yKFwiVmVyc2lvbiBub3Qgc3VwcG9ydGVkXCIpO1xuXG4gICAgY29uc3QgblNlY3Rpb25zID0gYXdhaXQgZmQucmVhZFVMRTMyKCk7XG5cbiAgICAvLyBTY2FuIHNlY3Rpb25zXG4gICAgbGV0IHNlY3Rpb25zID0gW107XG4gICAgZm9yIChsZXQgaT0wOyBpPG5TZWN0aW9uczsgaSsrKSB7XG4gICAgICAgIGxldCBodCA9IGF3YWl0IGZkLnJlYWRVTEUzMigpO1xuICAgICAgICBsZXQgaGwgPSBhd2FpdCBmZC5yZWFkVUxFNjQoKTtcbiAgICAgICAgaWYgKHR5cGVvZiBzZWN0aW9uc1todF0gPT0gXCJ1bmRlZmluZWRcIikgc2VjdGlvbnNbaHRdID0gW107XG4gICAgICAgIHNlY3Rpb25zW2h0XS5wdXNoKHtcbiAgICAgICAgICAgIHA6IGZkLnBvcyxcbiAgICAgICAgICAgIHNpemU6IGhsXG4gICAgICAgIH0pO1xuICAgICAgICBmZC5wb3MgKz0gaGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtmZCwgc2VjdGlvbnN9O1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlQmluRmlsZShmaWxlTmFtZSwgdHlwZSwgdmVyc2lvbiwgblNlY3Rpb25zLCBjYWNoZVNpemUsIHBhZ2VTaXplKSB7XG5cbiAgICBjb25zdCBmZCA9IGF3YWl0IGZhc3RGaWxlLmNyZWF0ZU92ZXJyaWRlKGZpbGVOYW1lLCBjYWNoZVNpemUsIHBhZ2VTaXplKTtcblxuICAgIGNvbnN0IGJ1ZmYgPSBuZXcgVWludDhBcnJheSg0KTtcbiAgICBmb3IgKGxldCBpPTA7IGk8NDsgaSsrKSBidWZmW2ldID0gdHlwZS5jaGFyQ29kZUF0KGkpO1xuICAgIGF3YWl0IGZkLndyaXRlKGJ1ZmYsIDApOyAvLyBNYWdpYyBcInIxY3NcIlxuXG4gICAgYXdhaXQgZmQud3JpdGVVTEUzMih2ZXJzaW9uKTsgLy8gVmVyc2lvblxuICAgIGF3YWl0IGZkLndyaXRlVUxFMzIoblNlY3Rpb25zKTsgLy8gTnVtYmVyIG9mIFNlY3Rpb25zXG5cbiAgICByZXR1cm4gZmQ7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdGFydFdyaXRlU2VjdGlvbihmZCwgaWRTZWN0aW9uKSB7XG4gICAgaWYgKHR5cGVvZiBmZC53cml0aW5nU2VjdGlvbiAhPT0gXCJ1bmRlZmluZWRcIikgdGhyb3cgbmV3IEVycm9yKFwiQWxyZWFkeSB3cml0aW5nIGEgc2VjdGlvblwiKTtcbiAgICBhd2FpdCBmZC53cml0ZVVMRTMyKGlkU2VjdGlvbik7IC8vIEhlYWRlciB0eXBlXG4gICAgZmQud3JpdGluZ1NlY3Rpb24gPSB7XG4gICAgICAgIHBTZWN0aW9uU2l6ZTogZmQucG9zXG4gICAgfTtcbiAgICBhd2FpdCBmZC53cml0ZVVMRTY0KDApOyAvLyBUZW1wb3JhbGx5IHNldCB0byAwIGxlbmd0aFxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZW5kV3JpdGVTZWN0aW9uKGZkKSB7XG4gICAgaWYgKHR5cGVvZiBmZC53cml0aW5nU2VjdGlvbiA9PT0gXCJ1bmRlZmluZWRcIikgdGhyb3cgbmV3IEVycm9yKFwiTm90IHdyaXRpbmcgYSBzZWN0aW9uXCIpO1xuXG4gICAgY29uc3Qgc2VjdGlvblNpemUgPSBmZC5wb3MgLSBmZC53cml0aW5nU2VjdGlvbi5wU2VjdGlvblNpemUgLSA4O1xuICAgIGNvbnN0IG9sZFBvcyA9IGZkLnBvcztcbiAgICBmZC5wb3MgPSBmZC53cml0aW5nU2VjdGlvbi5wU2VjdGlvblNpemU7XG4gICAgYXdhaXQgZmQud3JpdGVVTEU2NChzZWN0aW9uU2l6ZSk7XG4gICAgZmQucG9zID0gb2xkUG9zO1xuICAgIGRlbGV0ZSBmZC53cml0aW5nU2VjdGlvbjtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHN0YXJ0UmVhZFVuaXF1ZVNlY3Rpb24oZmQsIHNlY3Rpb25zLCBpZFNlY3Rpb24pIHtcbiAgICBpZiAodHlwZW9mIGZkLnJlYWRpbmdTZWN0aW9uICE9PSBcInVuZGVmaW5lZFwiKSB0aHJvdyBuZXcgRXJyb3IoXCJBbHJlYWR5IHJlYWRpbmcgYSBzZWN0aW9uXCIpO1xuICAgIGlmICghc2VjdGlvbnNbaWRTZWN0aW9uXSkgIHRocm93IG5ldyBFcnJvcihmZC5maWxlTmFtZSArIFwiOiBNaXNzaW5nIHNlY3Rpb24gXCIrIGlkU2VjdGlvbiApO1xuICAgIGlmIChzZWN0aW9uc1tpZFNlY3Rpb25dLmxlbmd0aD4xKSB0aHJvdyBuZXcgRXJyb3IoZmQuZmlsZU5hbWUgK1wiOiBTZWN0aW9uIER1cGxpY2F0ZWQgXCIgK2lkU2VjdGlvbik7XG5cbiAgICBmZC5wb3MgPSBzZWN0aW9uc1tpZFNlY3Rpb25dWzBdLnA7XG5cbiAgICBmZC5yZWFkaW5nU2VjdGlvbiA9IHNlY3Rpb25zW2lkU2VjdGlvbl1bMF07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBlbmRSZWFkU2VjdGlvbihmZCwgbm9DaGVjaykge1xuICAgIGlmICh0eXBlb2YgZmQucmVhZGluZ1NlY3Rpb24gPT09IFwidW5kZWZpbmVkXCIpIHRocm93IG5ldyBFcnJvcihcIk5vdCByZWFkaW5nIGEgc2VjdGlvblwiKTtcbiAgICBpZiAoIW5vQ2hlY2spIHtcbiAgICAgICAgaWYgKGZkLnBvcy1mZC5yZWFkaW5nU2VjdGlvbi5wICE9ICBmZC5yZWFkaW5nU2VjdGlvbi5zaXplKSB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNlY3Rpb24gc2l6ZSByZWFkaW5nXCIpO1xuICAgIH1cbiAgICBkZWxldGUgZmQucmVhZGluZ1NlY3Rpb247XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3cml0ZUJpZ0ludChmZCwgbiwgbjgsIHBvcykge1xuICAgIGNvbnN0IGJ1ZmYgPSBuZXcgVWludDhBcnJheShuOCk7XG4gICAgU2NhbGFyLnRvUnByTEUoYnVmZiwgMCwgbiwgbjgpO1xuICAgIGF3YWl0IGZkLndyaXRlKGJ1ZmYsIHBvcyk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWFkQmlnSW50KGZkLCBuOCwgcG9zKSB7XG4gICAgY29uc3QgYnVmZiA9IGF3YWl0IGZkLnJlYWQobjgsIHBvcyk7XG4gICAgcmV0dXJuIFNjYWxhci5mcm9tUnByTEUoYnVmZiwgMCwgbjgpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY29weVNlY3Rpb24oZmRGcm9tLCBzZWN0aW9ucywgZmRUbywgc2VjdGlvbklkLCBzaXplKSB7XG4gICAgaWYgKHR5cGVvZiBzaXplID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgIHNpemUgPSBzZWN0aW9uc1tzZWN0aW9uSWRdWzBdLnNpemU7XG4gICAgfVxuICAgIGNvbnN0IGNodW5rU2l6ZSA9IGZkRnJvbS5wYWdlU2l6ZTtcbiAgICBhd2FpdCBzdGFydFJlYWRVbmlxdWVTZWN0aW9uKGZkRnJvbSwgc2VjdGlvbnMsIHNlY3Rpb25JZCk7XG4gICAgYXdhaXQgc3RhcnRXcml0ZVNlY3Rpb24oZmRUbywgc2VjdGlvbklkKTtcbiAgICBmb3IgKGxldCBwPTA7IHA8c2l6ZTsgcCs9Y2h1bmtTaXplKSB7XG4gICAgICAgIGNvbnN0IGwgPSBNYXRoLm1pbihzaXplIC1wLCBjaHVua1NpemUpO1xuICAgICAgICBjb25zdCBidWZmID0gYXdhaXQgZmRGcm9tLnJlYWQobCk7XG4gICAgICAgIGF3YWl0IGZkVG8ud3JpdGUoYnVmZik7XG4gICAgfVxuICAgIGF3YWl0IGVuZFdyaXRlU2VjdGlvbihmZFRvKTtcbiAgICBhd2FpdCBlbmRSZWFkU2VjdGlvbihmZEZyb20sIHNpemUgIT0gc2VjdGlvbnNbc2VjdGlvbklkXVswXS5zaXplKTtcblxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZFNlY3Rpb24oZmQsIHNlY3Rpb25zLCBpZFNlY3Rpb24sIG9mZnNldCwgbGVuZ3RoKSB7XG5cbiAgICBvZmZzZXQgPSAodHlwZW9mIG9mZnNldCA9PT0gXCJ1bmRlZmluZWRcIikgPyAwIDogb2Zmc2V0O1xuICAgIGxlbmd0aCA9ICh0eXBlb2YgbGVuZ3RoID09PSBcInVuZGVmaW5lZFwiKSA/IHNlY3Rpb25zW2lkU2VjdGlvbl1bMF0uc2l6ZSAtIG9mZnNldCA6IGxlbmd0aDtcblxuICAgIGlmIChvZmZzZXQgKyBsZW5ndGggPiBzZWN0aW9uc1tpZFNlY3Rpb25dWzBdLnNpemUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUmVhZGluZyBvdXQgb2YgdGhlIHJhbmdlIG9mIHRoZSBzZWN0aW9uXCIpO1xuICAgIH1cblxuICAgIGxldCBidWZmO1xuICAgIGlmIChsZW5ndGggPCAoMSA8PCAzMCkgKSB7XG4gICAgICAgIGJ1ZmYgPSBuZXcgVWludDhBcnJheShsZW5ndGgpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGJ1ZmYgPSBuZXcgQmlnQnVmZmVyKGxlbmd0aCk7XG4gICAgfVxuXG4gICAgYXdhaXQgZmQucmVhZFRvQnVmZmVyKGJ1ZmYsIDAsIGxlbmd0aCwgc2VjdGlvbnNbaWRTZWN0aW9uXVswXS5wICsgb2Zmc2V0KTtcbiAgICByZXR1cm4gYnVmZjtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNlY3Rpb25Jc0VxdWFsKGZkMSwgc2VjdGlvbnMxLCBmZDIsIHNlY3Rpb25zMiwgaWRTZWN0aW9uKSB7XG4gICAgY29uc3QgTUFYX0JVRkZfU0laRSA9IGZkMS5wYWdlU2l6ZSAqIDE2O1xuICAgIGF3YWl0IHN0YXJ0UmVhZFVuaXF1ZVNlY3Rpb24oZmQxLCBzZWN0aW9uczEsIGlkU2VjdGlvbik7XG4gICAgYXdhaXQgc3RhcnRSZWFkVW5pcXVlU2VjdGlvbihmZDIsIHNlY3Rpb25zMiwgaWRTZWN0aW9uKTtcbiAgICBpZiAoc2VjdGlvbnMxW2lkU2VjdGlvbl1bMF0uc2l6ZSAhPSBzZWN0aW9uczJbaWRTZWN0aW9uXVswXS5zaXplKSByZXR1cm4gZmFsc2U7XG4gICAgY29uc3QgdG90YWxCeXRlcz1zZWN0aW9uczFbaWRTZWN0aW9uXVswXS5zaXplO1xuICAgIGZvciAobGV0IGk9MDsgaTx0b3RhbEJ5dGVzOyBpKz0gTUFYX0JVRkZfU0laRSkge1xuICAgICAgICBjb25zdCBuID0gTWF0aC5taW4odG90YWxCeXRlcy1pLCBNQVhfQlVGRl9TSVpFKTtcbiAgICAgICAgY29uc3QgYnVmZjEgPSBhd2FpdCBmZDEucmVhZChuKTtcbiAgICAgICAgY29uc3QgYnVmZjIgPSBhd2FpdCBmZDIucmVhZChuKTtcbiAgICAgICAgZm9yIChsZXQgaj0wOyBqPG47IGorKykgaWYgKGJ1ZmYxW2pdICE9IGJ1ZmYyW2pdKSByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGF3YWl0IGVuZFJlYWRTZWN0aW9uKGZkMSk7XG4gICAgYXdhaXQgZW5kUmVhZFNlY3Rpb24oZmQyKTtcbiAgICByZXR1cm4gdHJ1ZTtcbn1cbiIsImltcG9ydCB7RjFGaWVsZCwgZ2V0Q3VydmVGcm9tUn0gZnJvbSBcImZmamF2YXNjcmlwdFwiO1xuaW1wb3J0ICBCaWdBcnJheSBmcm9tIFwiQGlkZW4zL2JpZ2FycmF5XCI7XG5pbXBvcnQgKiBhcyBiaW5GaWxlVXRpbHMgZnJvbSBcIkBpZGVuMy9iaW5maWxldXRpbHNcIjtcblxuZXhwb3J0IGNvbnN0IFIxQ1NfRklMRV9IRUFERVJfU0VDVElPTiA9IDE7XG5leHBvcnQgY29uc3QgUjFDU19GSUxFX0NPTlNUUkFJTlRTX1NFQ1RJT04gPSAyO1xuZXhwb3J0IGNvbnN0IFIxQ1NfRklMRV9XSVJFMkxBQkVMSURfU0VDVElPTiA9IDM7XG5leHBvcnQgY29uc3QgUjFDU19GSUxFX0NVU1RPTV9HQVRFU19MSVNUX1NFQ1RJT04gPSA0O1xuZXhwb3J0IGNvbnN0IFIxQ1NfRklMRV9DVVNUT01fR0FURVNfVVNFU19TRUNUSU9OID0gNTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRSMWNzSGVhZGVyKGZkLHNlY3Rpb25zLHNpbmdsZVRocmVhZCkge1xuICAgIGxldCBvcHRpb25zO1xuICAgIGlmICh0eXBlb2Ygc2luZ2xlVGhyZWFkID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIG9wdGlvbnMgPSBzaW5nbGVUaHJlYWQ7XG4gICAgfSBlbHNlIGlmICh0eXBlb2Ygc2luZ2xlVGhyZWFkID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgIG9wdGlvbnM9IHtcbiAgICAgICAgICAgIHNpbmdsZVRocmVhZDogZmFsc2UsXG4gICAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgIHNpbmdsZVRocmVhZDogc2luZ2xlVGhyZWFkLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IHJlcyA9IHt9O1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFJlYWRVbmlxdWVTZWN0aW9uKGZkLCBzZWN0aW9ucywgMSk7XG4gICAgLy8gUmVhZCBIZWFkZXJcbiAgICByZXMubjggPSBhd2FpdCBmZC5yZWFkVUxFMzIoKTtcbiAgICByZXMucHJpbWUgPSBhd2FpdCBiaW5GaWxlVXRpbHMucmVhZEJpZ0ludChmZCwgcmVzLm44KTtcblxuICAgIGlmIChvcHRpb25zLkYpIHtcbiAgICAgICAgaWYgKG9wdGlvbnMuRi5wICE9IHJlcy5wcmltZSkgdGhyb3cgbmV3IEVycm9yKFwiRGlmZmVyZW50IFByaW1lXCIpO1xuICAgICAgICByZXMuRiA9IG9wdGlvbnMuRjtcbiAgICB9IGVsc2UgaWYgKG9wdGlvbnMuZ2V0RmllbGRGcm9tUHJpbWUpIHtcbiAgICAgICAgcmVzLkYgPSBhd2FpdCBvcHRpb25zLmdldEZpZWxkRnJvbVByaW1lKHJlcy5wcmltZSwgb3B0aW9ucy5zaW5nbGVUaHJlYWQpO1xuICAgIH0gZWxzZSBpZiAob3B0aW9ucy5nZXRDdXJ2ZUZyb21QcmltZSkge1xuICAgICAgICByZXMuY3VydmUgPSBhd2FpdCBvcHRpb25zLmdldEN1cnZlRnJvbVByaW1lKHJlcy5wcmltZSwgb3B0aW9ucy5zaW5nbGVUaHJlYWQpO1xuICAgICAgICByZXMuRiA9IHJlcy5jdXJ2ZS5GcjtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmVzLmN1cnZlID0gYXdhaXQgZ2V0Q3VydmVGcm9tUihyZXMucHJpbWUsIG9wdGlvbnMuc2luZ2xlVGhyZWFkKTtcbiAgICAgICAgICAgIHJlcy5GID0gcmVzLmN1cnZlLkZyO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIHJlcy5GID0gbmV3IEYxRmllbGQocmVzLnByaW1lKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJlcy5uVmFycyA9IGF3YWl0IGZkLnJlYWRVTEUzMigpO1xuICAgIHJlcy5uT3V0cHV0cyA9IGF3YWl0IGZkLnJlYWRVTEUzMigpO1xuICAgIHJlcy5uUHViSW5wdXRzID0gYXdhaXQgZmQucmVhZFVMRTMyKCk7XG4gICAgcmVzLm5QcnZJbnB1dHMgPSBhd2FpdCBmZC5yZWFkVUxFMzIoKTtcbiAgICByZXMubkxhYmVscyA9IGF3YWl0IGZkLnJlYWRVTEU2NCgpO1xuICAgIHJlcy5uQ29uc3RyYWludHMgPSBhd2FpdCBmZC5yZWFkVUxFMzIoKTtcbiAgICByZXMudXNlQ3VzdG9tR2F0ZXMgPSB0eXBlb2Ygc2VjdGlvbnNbUjFDU19GSUxFX0NVU1RPTV9HQVRFU19MSVNUX1NFQ1RJT05dICE9PSBcInVuZGVmaW5lZFwiICYmIHNlY3Rpb25zW1IxQ1NfRklMRV9DVVNUT01fR0FURVNfTElTVF9TRUNUSU9OXSAhPT0gbnVsbFxuICAgICAgICAmJiB0eXBlb2Ygc2VjdGlvbnNbUjFDU19GSUxFX0NVU1RPTV9HQVRFU19VU0VTX1NFQ1RJT05dICE9PSBcInVuZGVmaW5lZFwiICYmIHNlY3Rpb25zW1IxQ1NfRklMRV9DVVNUT01fR0FURVNfVVNFU19TRUNUSU9OXSAhPT0gbnVsbDtcblxuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5lbmRSZWFkU2VjdGlvbihmZCk7XG5cbiAgICByZXR1cm4gcmVzO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZENvbnN0cmFpbnRzKGZkLHNlY3Rpb25zLCByMWNzLCBsb2dnZXIsIGxvZ2dlckN0eCkge1xuICAgIGxldCBvcHRpb25zO1xuICAgIGlmICh0eXBlb2YgbG9nZ2VyID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIG9wdGlvbnMgPSBsb2dnZXI7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgbG9nZ2VyID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgIG9wdGlvbnM9IHt9O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG9wdGlvbnMgPSB7XG4gICAgICAgICAgICBsb2dnZXI6IGxvZ2dlcixcbiAgICAgICAgICAgIGxvZ2dlckN0eDogbG9nZ2VyQ3R4LFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IGJSMWNzID0gYXdhaXQgYmluRmlsZVV0aWxzLnJlYWRTZWN0aW9uKGZkLCBzZWN0aW9ucywgMik7XG4gICAgbGV0IGJSMWNzUG9zID0gMDtcbiAgICBsZXQgY29uc3RyYWludHM7XG4gICAgaWYgKHIxY3MubkNvbnN0cmFpbnRzPjE8PDIwKSB7XG4gICAgICAgIGNvbnN0cmFpbnRzID0gbmV3IEJpZ0FycmF5KCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3RyYWludHMgPSBbXTtcbiAgICB9XG4gICAgZm9yIChsZXQgaT0wOyBpPHIxY3MubkNvbnN0cmFpbnRzOyBpKyspIHtcbiAgICAgICAgaWYgKChvcHRpb25zLmxvZ2dlcikmJihpJTEwMDAwMCA9PSAwKSkgb3B0aW9ucy5sb2dnZXIuaW5mbyhgJHtvcHRpb25zLmxvZ2dlckN0eH06IExvYWRpbmcgY29uc3RyYWludHM6ICR7aX0vJHtyMWNzLm5Db25zdHJhaW50c31gKTtcbiAgICAgICAgY29uc3QgYyA9IHJlYWRDb25zdHJhaW50KCk7XG4gICAgICAgIGNvbnN0cmFpbnRzLnB1c2goYyk7XG4gICAgfVxuICAgIHJldHVybiBjb25zdHJhaW50cztcblxuXG4gICAgZnVuY3Rpb24gcmVhZENvbnN0cmFpbnQoKSB7XG4gICAgICAgIGNvbnN0IGMgPSBbXTtcbiAgICAgICAgY1swXSA9IHJlYWRMQygpO1xuICAgICAgICBjWzFdID0gcmVhZExDKCk7XG4gICAgICAgIGNbMl0gPSByZWFkTEMoKTtcbiAgICAgICAgcmV0dXJuIGM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVhZExDKCkge1xuICAgICAgICBjb25zdCBsYz0ge307XG5cbiAgICAgICAgY29uc3QgYnVmZlVMMzIgPSBiUjFjcy5zbGljZShiUjFjc1BvcywgYlIxY3NQb3MrNCk7XG4gICAgICAgIGJSMWNzUG9zICs9IDQ7XG4gICAgICAgIGNvbnN0IGJ1ZmZVTDMyViA9IG5ldyBEYXRhVmlldyhidWZmVUwzMi5idWZmZXIpO1xuICAgICAgICBjb25zdCBuSWR4ID0gYnVmZlVMMzJWLmdldFVpbnQzMigwLCB0cnVlKTtcblxuICAgICAgICBjb25zdCBidWZmID0gYlIxY3Muc2xpY2UoYlIxY3NQb3MsIGJSMWNzUG9zICsgKDQrcjFjcy5uOCkqbklkeCApO1xuICAgICAgICBiUjFjc1BvcyArPSAoNCtyMWNzLm44KSpuSWR4O1xuICAgICAgICBjb25zdCBidWZmViA9IG5ldyBEYXRhVmlldyhidWZmLmJ1ZmZlcik7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxuSWR4OyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGlkeCA9IGJ1ZmZWLmdldFVpbnQzMihpKig0K3IxY3MubjgpLCB0cnVlKTtcbiAgICAgICAgICAgIGNvbnN0IHZhbCA9IHIxY3MuRi5mcm9tUnByTEUoYnVmZiwgaSooNCtyMWNzLm44KSs0KTtcbiAgICAgICAgICAgIGxjW2lkeF0gPSB2YWw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGxjO1xuICAgIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRNYXAoZmQsIHNlY3Rpb25zLCByMWNzLCBsb2dnZXIsIGxvZ2dlckN0eCkge1xuICAgIGxldCBvcHRpb25zO1xuICAgIGlmICh0eXBlb2YgbG9nZ2VyID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIG9wdGlvbnMgPSBsb2dnZXI7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgbG9nZ2VyID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgIG9wdGlvbnM9IHt9O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG9wdGlvbnMgPSB7XG4gICAgICAgICAgICBsb2dnZXI6IGxvZ2dlcixcbiAgICAgICAgICAgIGxvZ2dlckN0eDogbG9nZ2VyQ3R4LFxuICAgICAgICB9O1xuICAgIH1cbiAgICBjb25zdCBiTWFwID0gYXdhaXQgYmluRmlsZVV0aWxzLnJlYWRTZWN0aW9uKGZkLCBzZWN0aW9ucywgMyk7XG4gICAgbGV0IGJNYXBQb3MgPSAwO1xuICAgIGxldCBtYXA7XG5cbiAgICBpZiAocjFjcy5uVmFycz4xPDwyMCkge1xuICAgICAgICBtYXAgPSBuZXcgQmlnQXJyYXkoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBtYXAgPSBbXTtcbiAgICB9XG4gICAgZm9yIChsZXQgaT0wOyBpPHIxY3MublZhcnM7IGkrKykge1xuICAgICAgICBpZiAoKG9wdGlvbnMubG9nZ2VyKSYmKGklMTAwMDAgPT0gMCkpIG9wdGlvbnMubG9nZ2VyLmluZm8oYCR7b3B0aW9ucy5sb2dnZXJDdHh9OiBMb2FkaW5nIG1hcDogJHtpfS8ke3IxY3MublZhcnN9YCk7XG4gICAgICAgIGNvbnN0IGlkeCA9IHJlYWRVTEU2NCgpO1xuICAgICAgICBtYXAucHVzaChpZHgpO1xuICAgIH1cblxuICAgIHJldHVybiBtYXA7XG5cbiAgICBmdW5jdGlvbiByZWFkVUxFNjQoKSB7XG4gICAgICAgIGNvbnN0IGJ1ZmZVTEU2NCA9IGJNYXAuc2xpY2UoYk1hcFBvcywgYk1hcFBvcys4KTtcbiAgICAgICAgYk1hcFBvcyArPSA4O1xuICAgICAgICBjb25zdCBidWZmVUxFNjRWID0gbmV3IERhdGFWaWV3KGJ1ZmZVTEU2NC5idWZmZXIpO1xuICAgICAgICBjb25zdCBMU0IgPSBidWZmVUxFNjRWLmdldFVpbnQzMigwLCB0cnVlKTtcbiAgICAgICAgY29uc3QgTVNCID0gYnVmZlVMRTY0Vi5nZXRVaW50MzIoNCwgdHJ1ZSk7XG5cbiAgICAgICAgcmV0dXJuIE1TQiAqIDB4MTAwMDAwMDAwICsgTFNCO1xuICAgIH1cblxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZFIxY3NGZChmZCwgc2VjdGlvbnMsIG9wdGlvbnMpIHtcbiAgICAvKipcbiAgICAgKiBPcHRpb25zIHByb3BlcnRpZXM6XG4gICAgICogIGxvYWRDb25zdHJhaW50czogPGJvb2w+IHRydWUgYnkgZGVmYXVsdFxuICAgICAqICBsb2FkTWFwOiAgICAgICAgIDxib29sPiBmYWxzZSBieSBkZWZhdWx0XG4gICAgICogIGxvYWRDdXN0b21HYXRlczogPGJvb2w+IHRydWUgYnkgZGVmYXVsdFxuICAgICAqL1xuXG4gICAgaWYodHlwZW9mIG9wdGlvbnMgIT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwicmVhZFIxY3NGZDogb3B0aW9ucyBtdXN0IGJlIGFuIG9iamVjdFwiKTtcbiAgICB9XG5cbiAgICBvcHRpb25zLmxvYWRDb25zdHJhaW50cyA9IFwibG9hZENvbnN0cmFpbnRzXCIgaW4gb3B0aW9ucyA/IG9wdGlvbnMubG9hZENvbnN0cmFpbnRzIDogdHJ1ZTtcbiAgICBvcHRpb25zLmxvYWRNYXAgPSBcImxvYWRNYXBcIiBpbiBvcHRpb25zID8gb3B0aW9ucy5sb2FkTWFwIDogZmFsc2U7XG4gICAgb3B0aW9ucy5sb2FkQ3VzdG9tR2F0ZXMgPSBcImxvYWRDdXN0b21HYXRlc1wiIGluIG9wdGlvbnMgPyBvcHRpb25zLmxvYWRDdXN0b21HYXRlcyA6IHRydWU7XG5cbiAgICBjb25zdCByZXMgPSBhd2FpdCByZWFkUjFjc0hlYWRlcihmZCwgc2VjdGlvbnMsIG9wdGlvbnMpO1xuXG4gICAgaWYgKG9wdGlvbnMubG9hZENvbnN0cmFpbnRzKSB7XG4gICAgICAgIHJlcy5jb25zdHJhaW50cyA9IGF3YWl0IHJlYWRDb25zdHJhaW50cyhmZCwgc2VjdGlvbnMsIHJlcywgb3B0aW9ucyk7XG4gICAgfVxuXG4gICAgLy8gUmVhZCBMYWJlbHNcblxuICAgIGlmIChvcHRpb25zLmxvYWRNYXApIHtcbiAgICAgICAgcmVzLm1hcCA9IGF3YWl0IHJlYWRNYXAoZmQsIHNlY3Rpb25zLCByZXMsIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLmxvYWRDdXN0b21HYXRlcykge1xuICAgICAgICBpZiAocmVzLnVzZUN1c3RvbUdhdGVzKSB7XG4gICAgICAgICAgICByZXMuY3VzdG9tR2F0ZXMgPSBhd2FpdCByZWFkQ3VzdG9tR2F0ZXNMaXN0U2VjdGlvbihmZCwgc2VjdGlvbnMsIHJlcyk7XG4gICAgICAgICAgICByZXMuY3VzdG9tR2F0ZXNVc2VzID0gYXdhaXQgcmVhZEN1c3RvbUdhdGVzVXNlc1NlY3Rpb24oZmQsIHNlY3Rpb25zLCBvcHRpb25zKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcy5jdXN0b21HYXRlcyA9IFtdO1xuICAgICAgICAgICAgcmVzLmN1c3RvbUdhdGVzVXNlcyA9IFtdO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXM7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWFkUjFjcyhmaWxlTmFtZSwgbG9hZENvbnN0cmFpbnRzLCBsb2FkTWFwLCBzaW5nbGVUaHJlYWQsIGxvZ2dlciwgbG9nZ2VyQ3R4KSB7XG4gICAgbGV0IG9wdGlvbnM7XG4gICAgaWYgKHR5cGVvZiBsb2FkQ29uc3RyYWludHMgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgb3B0aW9ucyA9IGxvYWRDb25zdHJhaW50cztcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBsb2FkQ29uc3RyYWludHMgPT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgb3B0aW9ucz0ge1xuICAgICAgICAgICAgbG9hZENvbnN0cmFpbnRzOiB0cnVlLFxuICAgICAgICAgICAgbG9hZE1hcDogZmFsc2UsXG4gICAgICAgICAgICBsb2FkQ3VzdG9tR2F0ZXM6IHRydWVcbiAgICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBvcHRpb25zID0ge1xuICAgICAgICAgICAgbG9hZENvbnN0cmFpbnRzOiBsb2FkQ29uc3RyYWludHMsXG4gICAgICAgICAgICBsb2FkTWFwOiBsb2FkTWFwLFxuICAgICAgICAgICAgc2luZ2xlVGhyZWFkOiBzaW5nbGVUaHJlYWQsXG4gICAgICAgICAgICBsb2dnZXI6IGxvZ2dlcixcbiAgICAgICAgICAgIGxvZ2dlckN0eDogbG9nZ2VyQ3R4XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3Qge2ZkLCBzZWN0aW9uc30gPSBhd2FpdCBiaW5GaWxlVXRpbHMucmVhZEJpbkZpbGUoZmlsZU5hbWUsIFwicjFjc1wiLCAxLCAxPDwyNSwgMTw8MjIpO1xuXG4gICAgY29uc3QgcmVzID0gYXdhaXQgcmVhZFIxY3NGZChmZCwgc2VjdGlvbnMsIG9wdGlvbnMpO1xuXG4gICAgYXdhaXQgZmQuY2xvc2UoKTtcblxuICAgIHJldHVybiByZXM7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWFkQ3VzdG9tR2F0ZXNMaXN0U2VjdGlvbihmZCwgc2VjdGlvbnMsIHJlcykge1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFJlYWRVbmlxdWVTZWN0aW9uKGZkLCBzZWN0aW9ucywgUjFDU19GSUxFX0NVU1RPTV9HQVRFU19MSVNUX1NFQ1RJT04pO1xuXG4gICAgbGV0IG51bSA9IGF3YWl0IGZkLnJlYWRVTEUzMigpO1xuXG4gICAgbGV0IGN1c3RvbUdhdGVzID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW07IGkrKykge1xuICAgICAgICBsZXQgY3VzdG9tR2F0ZSA9IHt9O1xuICAgICAgICBjdXN0b21HYXRlLnRlbXBsYXRlTmFtZSA9IGF3YWl0IGZkLnJlYWRTdHJpbmcoKTtcbiAgICAgICAgbGV0IG51bVBhcmFtZXRlcnMgPSBhd2FpdCBmZC5yZWFkVUxFMzIoKTtcblxuICAgICAgICBjdXN0b21HYXRlLnBhcmFtZXRlcnMgPSBBcnJheShudW1QYXJhbWV0ZXJzKTtcbiAgICAgICAgbGV0IGJ1ZmYgPSBhd2FpdCBmZC5yZWFkKHJlcy5uOCAqIG51bVBhcmFtZXRlcnMpO1xuXG4gICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgbnVtUGFyYW1ldGVyczsgaisrKSB7XG4gICAgICAgICAgICBjdXN0b21HYXRlLnBhcmFtZXRlcnNbal0gPSByZXMuRi5mcm9tUnByTEUoYnVmZiwgaiAqIHJlcy5uOCwgcmVzLm44KTs7XG4gICAgICAgIH1cbiAgICAgICAgY3VzdG9tR2F0ZXMucHVzaChjdXN0b21HYXRlKTtcbiAgICB9XG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmVuZFJlYWRTZWN0aW9uKGZkKTtcblxuICAgIHJldHVybiBjdXN0b21HYXRlcztcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRDdXN0b21HYXRlc1VzZXNTZWN0aW9uKGZkLHNlY3Rpb25zLCBvcHRpb25zKSB7XG4gICAgY29uc3QgYlIxY3MgPSBhd2FpdCBiaW5GaWxlVXRpbHMucmVhZFNlY3Rpb24oZmQsIHNlY3Rpb25zLCBSMUNTX0ZJTEVfQ1VTVE9NX0dBVEVTX1VTRVNfU0VDVElPTik7XG4gICAgY29uc3QgYlIxY3MzMiA9IG5ldyBVaW50MzJBcnJheShiUjFjcy5idWZmZXIsIGJSMWNzLmJ5dGVPZmZzZXQsIGJSMWNzLmJ5dGVMZW5ndGgvNCk7XG4gICAgY29uc3QgbkN1c3RvbUdhdGVVc2VzID0gYlIxY3MzMlswXTtcbiAgICBsZXQgYlIxY3NQb3MgPSAxO1xuICAgIGxldCBjdXN0b21HYXRlc1VzZXM7XG4gICAgaWYgKG5DdXN0b21HYXRlVXNlcz4xPDwyMCkge1xuICAgICAgICBjdXN0b21HYXRlc1VzZXMgPSBuZXcgQmlnQXJyYXkoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBjdXN0b21HYXRlc1VzZXMgPSBbXTtcbiAgICB9XG4gICAgZm9yIChsZXQgaT0wOyBpPG5DdXN0b21HYXRlVXNlczsgaSsrKSB7XG4gICAgICAgIGlmICgob3B0aW9ucy5sb2dnZXIpJiYoaSUxMDAwMDAgPT0gMCkpIG9wdGlvbnMubG9nZ2VyLmluZm8oYCR7b3B0aW9ucy5sb2dnZXJDdHh9OiBMb2FkaW5nIGN1c3RvbSBnYXRlIHVzZXM6ICR7aX0vJHtuQ3VzdG9tR2F0ZVVzZXN9YCk7XG4gICAgICAgIGxldCBjID0ge307XG4gICAgICAgIGMuaWQgPSBiUjFjczMyW2JSMWNzUG9zKytdO1xuICAgICAgICBsZXQgbnVtU2lnbmFscyA9IGJSMWNzMzJbYlIxY3NQb3MrK107XG4gICAgICAgIGMuc2lnbmFscyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IG51bVNpZ25hbHM7IGorKykge1xuICAgICAgICAgICAgY29uc3QgTFNCID0gYlIxY3MzMltiUjFjc1BvcysrXTtcbiAgICAgICAgICAgIGNvbnN0IE1TQiA9IGJSMWNzMzJbYlIxY3NQb3MrK107XG4gICAgICAgICAgICBjLnNpZ25hbHMucHVzaChNU0IgKiAweDEwMDAwMDAwMCArIExTQik7XG4gICAgICAgIH1cbiAgICAgICAgY3VzdG9tR2F0ZXNVc2VzLnB1c2goYyk7XG4gICAgfVxuICAgIHJldHVybiBjdXN0b21HYXRlc1VzZXM7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3cml0ZVIxY3NIZWFkZXIoZmQsIGNpcikge1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFdyaXRlU2VjdGlvbihmZCwgMSk7XG4gICAgYXdhaXQgZmQud3JpdGVVTEUzMihjaXIubjgpOyAvLyBUZW1wb3JhbGx5IHNldCB0byAwIGxlbmd0aFxuICAgIGF3YWl0IGJpbkZpbGVVdGlscy53cml0ZUJpZ0ludChmZCwgY2lyLnByaW1lLCBjaXIubjgpO1xuXG4gICAgYXdhaXQgZmQud3JpdGVVTEUzMihjaXIublZhcnMpO1xuICAgIGF3YWl0IGZkLndyaXRlVUxFMzIoY2lyLm5PdXRwdXRzKTtcbiAgICBhd2FpdCBmZC53cml0ZVVMRTMyKGNpci5uUHViSW5wdXRzKTtcbiAgICBhd2FpdCBmZC53cml0ZVVMRTMyKGNpci5uUHJ2SW5wdXRzKTtcbiAgICBhd2FpdCBmZC53cml0ZVVMRTY0KGNpci5uTGFiZWxzKTtcbiAgICBhd2FpdCBmZC53cml0ZVVMRTMyKGNpci5jb25zdHJhaW50cy5sZW5ndGgpO1xuXG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmVuZFdyaXRlU2VjdGlvbihmZCk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3cml0ZVIxY3NDb25zdHJhaW50cyhmZCwgY2lyLCBsb2dnZXIsIGxvZ2dlckN0eCkge1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFdyaXRlU2VjdGlvbihmZCwgMik7XG5cbiAgICBmb3IgKGxldCBpPTA7IGk8Y2lyLmNvbnN0cmFpbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmICgobG9nZ2VyKSYmKGklMTAwMDAgPT0gMCkpIGxvZ2dlci5pbmZvKGAke2xvZ2dlckN0eH06IHdyaXRpbmcgY29uc3RyYWludDogJHtpfS8ke2Npci5jb25zdHJhaW50cy5sZW5ndGh9YCk7XG4gICAgICAgIGF3YWl0IHdyaXRlQ29uc3RyYWludChjaXIuY29uc3RyYWludHNbaV0pO1xuICAgIH1cblxuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5lbmRXcml0ZVNlY3Rpb24oZmQpO1xuXG5cbiAgICBmdW5jdGlvbiB3cml0ZUNvbnN0cmFpbnQoYykge1xuICAgICAgICBjb25zdCBuOCA9IGNpci5uODtcbiAgICAgICAgY29uc3QgRiA9IGNpci5GIHx8IGNpci5jdXJ2ZS5GcjtcbiAgICAgICAgY29uc3QgaWR4QSA9IE9iamVjdC5rZXlzKGNbMF0pO1xuICAgICAgICBjb25zdCBpZHhCID0gT2JqZWN0LmtleXMoY1sxXSk7XG4gICAgICAgIGNvbnN0IGlkeEMgPSBPYmplY3Qua2V5cyhjWzJdKTtcbiAgICAgICAgY29uc3QgYnVmZiA9IG5ldyBVaW50OEFycmF5KChpZHhBLmxlbmd0aCtpZHhCLmxlbmd0aCtpZHhDLmxlbmd0aCkqKG44KzQpICsgMTIpO1xuICAgICAgICBjb25zdCBidWZmViA9IG5ldyBEYXRhVmlldyhidWZmLmJ1ZmZlcik7XG4gICAgICAgIGxldCBvPTA7XG5cbiAgICAgICAgYnVmZlYuc2V0VWludDMyKG8sIGlkeEEubGVuZ3RoLCB0cnVlKTsgbys9NDtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPGlkeEEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGNvZWYgPSBpZHhBW2ldO1xuICAgICAgICAgICAgYnVmZlYuc2V0VWludDMyKG8sIGNvZWYsIHRydWUpOyBvKz00O1xuICAgICAgICAgICAgRi50b1JwckxFKGJ1ZmYsIG8sIGNbMF1bY29lZl0pOyBvKz1uODtcbiAgICAgICAgfVxuXG4gICAgICAgIGJ1ZmZWLnNldFVpbnQzMihvLCBpZHhCLmxlbmd0aCwgdHJ1ZSk7IG8rPTQ7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxpZHhCLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBjb2VmID0gaWR4QltpXTtcbiAgICAgICAgICAgIGJ1ZmZWLnNldFVpbnQzMihvLCBjb2VmLCB0cnVlKTsgbys9NDtcbiAgICAgICAgICAgIEYudG9ScHJMRShidWZmLCBvLCBjWzFdW2NvZWZdKTsgbys9bjg7XG4gICAgICAgIH1cblxuICAgICAgICBidWZmVi5zZXRVaW50MzIobywgaWR4Qy5sZW5ndGgsIHRydWUpOyBvKz00O1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8aWR4Qy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgY29lZiA9IGlkeENbaV07XG4gICAgICAgICAgICBidWZmVi5zZXRVaW50MzIobywgY29lZiwgdHJ1ZSk7IG8rPTQ7XG4gICAgICAgICAgICBGLnRvUnByTEUoYnVmZiwgbywgY1syXVtjb2VmXSk7IG8rPW44O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZkLndyaXRlKGJ1ZmYpO1xuICAgIH1cblxufVxuXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3cml0ZVIxY3NNYXAoZmQsIGNpciwgbG9nZ2VyLCBsb2dnZXJDdHgpIHtcbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuc3RhcnRXcml0ZVNlY3Rpb24oZmQsIDMpO1xuXG4gICAgaWYgKGNpci5tYXAubGVuZ3RoICE9IGNpci5uVmFycykgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBtYXAgc2l6ZVwiKTtcbiAgICBmb3IgKGxldCBpPTA7IGk8Y2lyLm5WYXJzOyBpKyspIHtcbiAgICAgICAgaWYgKChsb2dnZXIpJiYoaSUxMDAwMCA9PSAwKSkgbG9nZ2VyLmluZm8oYCR7bG9nZ2VyQ3R4fTogd3JpdGluZyBtYXA6ICR7aX0vJHtjaXIublZhcnN9YCk7XG4gICAgICAgIGF3YWl0IGZkLndyaXRlVUxFNjQoY2lyLm1hcFtpXSk7XG4gICAgfVxuXG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmVuZFdyaXRlU2VjdGlvbihmZCk7XG59XG5cblxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd3JpdGVSMWNzKGZpbGVOYW1lLCBjaXIsIGxvZ2dlciwgbG9nZ2VyQ3R4KSB7XG5cbiAgICBjb25zdCBmZCA9IGF3YWl0IGJpbkZpbGVVdGlscy5jcmVhdGVCaW5GaWxlKGZpbGVOYW1lLCBcInIxY3NcIiwgMSwgMywgMTw8MjUsIDE8PDIyKTtcblxuICAgIGF3YWl0IHdyaXRlUjFjc0hlYWRlcihmZCwgY2lyKTtcblxuICAgIGF3YWl0IHdyaXRlUjFjc0NvbnN0cmFpbnRzKGZkLCBjaXIsIGxvZ2dlciwgbG9nZ2VyQ3R4KTtcblxuICAgIGF3YWl0IHdyaXRlUjFjc01hcChmZCwgY2lyLCBsb2dnZXIsIGxvZ2dlckN0eCk7XG5cbiAgICBhd2FpdCBmZC5jbG9zZSgpO1xufVxuIiwiLypcbiAgICBDb3B5cmlnaHQgMjAxOCAwS0lNUyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJrSlMuXG5cbiAgICBzbmFya0pTIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICAgIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gICAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAgICAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtKUyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVFxuICAgIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpY1xuICAgIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gICAgYWxvbmcgd2l0aCBzbmFya0pTLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuaW1wb3J0IHsgU2NhbGFyIH0gZnJvbSBcImZmamF2YXNjcmlwdFwiO1xuaW1wb3J0IHsgcmVhZFIxY3MgfSAgZnJvbSBcInIxY3NmaWxlXCI7XG5cbmNvbnN0IGJsczEyMzgxciA9IFNjYWxhci5lKFwiNzNlZGE3NTMyOTlkN2Q0ODMzMzlkODA4MDlhMWQ4MDU1M2JkYTQwMmZmZmU1YmZlZmZmZmZmZmYwMDAwMDAwMVwiLCAxNik7XG5jb25zdCBibjEyOHIgPSBTY2FsYXIuZShcIjIxODg4MjQyODcxODM5Mjc1MjIyMjQ2NDA1NzQ1MjU3Mjc1MDg4NTQ4MzY0NDAwNDE2MDM0MzQzNjk4MjA0MTg2NTc1ODA4NDk1NjE3XCIpO1xuXG5leHBvcnQgZGVmYXVsdCBhc3luYyBmdW5jdGlvbiByMWNzSW5mbyhyMWNzTmFtZSwgbG9nZ2VyKSB7XG5cbiAgICBjb25zdCBjaXIgPSBhd2FpdCByZWFkUjFjcyhyMWNzTmFtZSk7XG5cbiAgICBpZiAoU2NhbGFyLmVxKGNpci5wcmltZSwgYm4xMjhyKSkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIkN1cnZlOiBibi0xMjhcIik7XG4gICAgfSBlbHNlIGlmIChTY2FsYXIuZXEoY2lyLnByaW1lLCBibHMxMjM4MXIpKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiQ3VydmU6IGJsczEyLTM4MVwiKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhgVW5rbm93biBDdXJ2ZS4gUHJpbWU6ICR7U2NhbGFyLnRvU3RyaW5nKGNpci5wcmltZSl9YCk7XG4gICAgfVxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKGAjIG9mIFdpcmVzOiAke2Npci5uVmFyc31gKTtcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhgIyBvZiBDb25zdHJhaW50czogJHtjaXIubkNvbnN0cmFpbnRzfWApO1xuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKGAjIG9mIFByaXZhdGUgSW5wdXRzOiAke2Npci5uUHJ2SW5wdXRzfWApO1xuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKGAjIG9mIFB1YmxpYyBJbnB1dHM6ICR7Y2lyLm5QdWJJbnB1dHN9YCk7XG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oYCMgb2YgTGFiZWxzOiAke2Npci5uTGFiZWxzfWApO1xuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKGAjIG9mIE91dHB1dHM6ICR7Y2lyLm5PdXRwdXRzfWApO1xuXG4gICAgcmV0dXJuIGNpcjtcbn1cbiIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMTggMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya0pTLlxuXG4gICAgc25hcmtKUyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJrSlMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggc25hcmtKUy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbmltcG9ydCB7cmVhZFIxY3N9ICBmcm9tIFwicjFjc2ZpbGVcIjtcbmltcG9ydCB7IHN0cmluZ2lmeUJpZ0ludHNXaXRoRmllbGQgfSBmcm9tIFwiLi9taXNjLmpzXCI7XG5cblxuZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gcjFjc0V4cG9ydEpzb24ocjFjc0ZpbGVOYW1lLCBsb2dnZXIpIHtcblxuICAgIGNvbnN0IGNpciA9IGF3YWl0IHJlYWRSMWNzKHIxY3NGaWxlTmFtZSwgdHJ1ZSwgdHJ1ZSwgdHJ1ZSwgbG9nZ2VyKTtcbiAgICBjb25zdCBGcj1jaXIuY3VydmUuRnI7XG4gICAgZGVsZXRlIGNpci5jdXJ2ZTtcbiAgICBkZWxldGUgY2lyLkY7XG5cbiAgICByZXR1cm4gc3RyaW5naWZ5QmlnSW50c1dpdGhGaWVsZChGciwgY2lyKTtcbn1cbiIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMTggMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya0pTLlxuXG4gICAgc25hcmtKUyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJrSlMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggc25hcmtKUy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbmV4cG9ydCB7ZGVmYXVsdCBhcyBwcmludH0gZnJvbSBcIi4vcjFjc19wcmludC5qc1wiO1xuZXhwb3J0IHtkZWZhdWx0IGFzIGluZm99IGZyb20gXCIuL3IxY3NfaW5mby5qc1wiO1xuZXhwb3J0IHtkZWZhdWx0IGFzIGV4cG9ydEpzb259IGZyb20gXCIuL3IxY3NfZXhwb3J0X2pzb24uanNcIjtcblxuIiwiLypcbiAgICBDb3B5cmlnaHQgMjAxOCAwS0lNUyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJrSlMuXG5cbiAgICBzbmFya0pTIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICAgIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gICAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAgICAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtKUyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVFxuICAgIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpY1xuICAgIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gICAgYWxvbmcgd2l0aCBzbmFya0pTLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuaW1wb3J0ICogYXMgZmFzdEZpbGUgZnJvbSBcImZhc3RmaWxlXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uIGxvYWRTeW1ib2xzKHN5bUZpbGVOYW1lKSB7XG4gICAgY29uc3Qgc3ltID0ge1xuICAgICAgICBsYWJlbElkeDJOYW1lOiBbIFwib25lXCIgXSxcbiAgICAgICAgdmFySWR4Mk5hbWU6IFsgXCJvbmVcIiBdLFxuICAgICAgICBjb21wb25lbnRJZHgyTmFtZTogW11cbiAgICB9O1xuICAgIGNvbnN0IGZkID0gYXdhaXQgZmFzdEZpbGUucmVhZEV4aXN0aW5nKHN5bUZpbGVOYW1lKTtcbiAgICBjb25zdCBidWZmID0gYXdhaXQgZmQucmVhZChmZC50b3RhbFNpemUpO1xuICAgIGNvbnN0IHN5bXNTdHIgPSBuZXcgVGV4dERlY29kZXIoXCJ1dGYtOFwiKS5kZWNvZGUoYnVmZik7XG4gICAgY29uc3QgbGluZXMgPSBzeW1zU3RyLnNwbGl0KFwiXFxuXCIpO1xuICAgIGZvciAobGV0IGk9MDsgaTxsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBhcnIgPSBsaW5lc1tpXS5zcGxpdChcIixcIik7XG4gICAgICAgIGlmIChhcnIubGVuZ3RoIT00KSBjb250aW51ZTtcbiAgICAgICAgaWYgKHN5bS52YXJJZHgyTmFtZVthcnJbMV1dKSB7XG4gICAgICAgICAgICBzeW0udmFySWR4Mk5hbWVbYXJyWzFdXSArPSBcInxcIiArIGFyclszXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHN5bS52YXJJZHgyTmFtZVthcnJbMV1dID0gYXJyWzNdO1xuICAgICAgICB9XG4gICAgICAgIHN5bS5sYWJlbElkeDJOYW1lW2FyclswXV0gPSBhcnJbM107XG4gICAgICAgIGlmICghc3ltLmNvbXBvbmVudElkeDJOYW1lW2FyclsyXV0pIHtcbiAgICAgICAgICAgIHN5bS5jb21wb25lbnRJZHgyTmFtZVthcnJbMl1dID0gZXh0cmFjdENvbXBvbmVudChhcnJbM10pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXdhaXQgZmQuY2xvc2UoKTtcblxuICAgIHJldHVybiBzeW07XG5cbiAgICBmdW5jdGlvbiBleHRyYWN0Q29tcG9uZW50KG5hbWUpIHtcbiAgICAgICAgY29uc3QgYXJyID0gbmFtZS5zcGxpdChcIi5cIik7XG4gICAgICAgIGFyci5wb3AoKTsgLy8gUmVtb3ZlIHRoZSBsYXNyIGVsZW1lbnRcbiAgICAgICAgcmV0dXJuIGFyci5qb2luKFwiLlwiKTtcbiAgICB9XG59XG4iLCIvKlxuICAgIENvcHlyaWdodCAyMDE4IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygc25hcmtKUy5cblxuICAgIHNuYXJrSlMgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gICAgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAgICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICAgIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICBzbmFya0pTIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHNuYXJrSlMuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG5pbXBvcnQgKiBhcyBmYXN0RmlsZSBmcm9tIFwiZmFzdGZpbGVcIjtcbmltcG9ydCB7IFdpdG5lc3NDYWxjdWxhdG9yQnVpbGRlciB9IGZyb20gXCJjaXJjb21fcnVudGltZVwiO1xuaW1wb3J0ICogYXMgd3Ruc1V0aWxzIGZyb20gXCIuL3d0bnNfdXRpbHMuanNcIjtcbmltcG9ydCAqIGFzIGJpbkZpbGVVdGlscyBmcm9tIFwiQGlkZW4zL2JpbmZpbGV1dGlsc1wiO1xuaW1wb3J0IGxvYWRTeW1zIGZyb20gXCIuL2xvYWRzeW1zLmpzXCI7XG5pbXBvcnQgeyAgdXRpbHMgfSAgIGZyb20gXCJmZmphdmFzY3JpcHRcIjtcbmNvbnN0IHt1bnN0cmluZ2lmeUJpZ0ludHN9ID0gdXRpbHM7XG5cblxuZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gd3Ruc0RlYnVnKF9pbnB1dCwgd2FzbUZpbGVOYW1lLCB3dG5zRmlsZU5hbWUsIHN5bU5hbWUsIG9wdGlvbnMsIGxvZ2dlcikge1xuXG4gICAgY29uc3QgaW5wdXQgPSB1bnN0cmluZ2lmeUJpZ0ludHMoX2lucHV0KTtcblxuICAgIGNvbnN0IGZkV2FzbSA9IGF3YWl0IGZhc3RGaWxlLnJlYWRFeGlzdGluZyh3YXNtRmlsZU5hbWUpO1xuICAgIGNvbnN0IHdhc20gPSBhd2FpdCBmZFdhc20ucmVhZChmZFdhc20udG90YWxTaXplKTtcbiAgICBhd2FpdCBmZFdhc20uY2xvc2UoKTtcblxuICAgIGNvbnN0IHdjT3BzID0gey4uLm9wdGlvbnMsIHNhbml0eUNoZWNrOiB0cnVlfTtcbiAgICBsZXQgc3ltID0gYXdhaXQgbG9hZFN5bXMoc3ltTmFtZSk7XG4gICAgaWYgKG9wdGlvbnMuc2V0KSB7XG4gICAgICAgIGlmICghc3ltKSBzeW0gPSBhd2FpdCBsb2FkU3ltcyhzeW1OYW1lKTtcbiAgICAgICAgd2NPcHMubG9nU2V0U2lnbmFsPSBmdW5jdGlvbihsYWJlbElkeCwgdmFsdWUpIHtcbiAgICAgICAgICAgIC8vIFRoZSBsaW5lIGJlbG93IHNwbGl0cyB0aGUgYXJyb3cgbG9nIGludG8gMiBzdHJpbmdzIHRvIGF2b2lkIHNvbWUgU2VjdXJlIEVDTUFTY3JpcHQgaXNzdWVzXG4gICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIlNFVCBcIiArIHN5bS5sYWJlbElkeDJOYW1lW2xhYmVsSWR4XSArIFwiIDxcIiArIFwiLS0gXCIgKyB2YWx1ZS50b1N0cmluZygpKTtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMuZ2V0KSB7XG4gICAgICAgIGlmICghc3ltKSBzeW0gPSBhd2FpdCBsb2FkU3ltcyhzeW1OYW1lKTtcbiAgICAgICAgd2NPcHMubG9nR2V0U2lnbmFsPSBmdW5jdGlvbih2YXJJZHgsIHZhbHVlKSB7XG4gICAgICAgICAgICAvLyBUaGUgbGluZSBiZWxvdyBzcGxpdHMgdGhlIGFycm93IGxvZyBpbnRvIDIgc3RyaW5ncyB0byBhdm9pZCBzb21lIFNlY3VyZSBFQ01BU2NyaXB0IGlzc3Vlc1xuICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCJHRVQgXCIgKyBzeW0ubGFiZWxJZHgyTmFtZVt2YXJJZHhdICsgXCIgLS1cIiArIFwiPiBcIiArIHZhbHVlLnRvU3RyaW5nKCkpO1xuICAgICAgICB9O1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy50cmlnZ2VyKSB7XG4gICAgICAgIGlmICghc3ltKSBzeW0gPSBhd2FpdCBsb2FkU3ltcyhzeW1OYW1lKTtcbiAgICAgICAgd2NPcHMubG9nU3RhcnRDb21wb25lbnQ9IGZ1bmN0aW9uKGNJZHgpIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiU1RBUlQ6IFwiICsgc3ltLmNvbXBvbmVudElkeDJOYW1lW2NJZHhdKTtcbiAgICAgICAgfTtcbiAgICAgICAgd2NPcHMubG9nRmluaXNoQ29tcG9uZW50PSBmdW5jdGlvbihjSWR4KSB7XG4gICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIkZJTklTSDogXCIgKyBzeW0uY29tcG9uZW50SWR4Mk5hbWVbY0lkeF0pO1xuICAgICAgICB9O1xuICAgIH1cbiAgICB3Y09wcy5zeW0gPSBzeW07XG5cbiAgICBjb25zdCB3YyA9IGF3YWl0IFdpdG5lc3NDYWxjdWxhdG9yQnVpbGRlcih3YXNtLCB3Y09wcyk7XG4gICAgY29uc3QgdyA9IGF3YWl0IHdjLmNhbGN1bGF0ZVdpdG5lc3MoaW5wdXQsIHRydWUpO1xuXG4gICAgY29uc3QgZmRXdG5zID0gYXdhaXQgYmluRmlsZVV0aWxzLmNyZWF0ZUJpbkZpbGUod3Ruc0ZpbGVOYW1lLCBcInd0bnNcIiwgMiwgMik7XG5cbiAgICBhd2FpdCB3dG5zVXRpbHMud3JpdGUoZmRXdG5zLCB3LCB3Yy5wcmltZSk7XG5cbiAgICBhd2FpdCBmZFd0bnMuY2xvc2UoKTtcbn1cbiIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMTggMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya0pTLlxuXG4gICAgc25hcmtKUyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJrSlMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggc25hcmtKUy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbmltcG9ydCB7cmVhZH0gZnJvbSBcIi4vd3Ruc191dGlscy5qc1wiO1xuXG5leHBvcnQgZGVmYXVsdCBhc3luYyBmdW5jdGlvbiB3dG5zRXhwb3J0SnNvbih3dG5zRmlsZU5hbWUpIHtcblxuICAgIGNvbnN0IHcgPSBhd2FpdCByZWFkKHd0bnNGaWxlTmFtZSk7XG5cbiAgICByZXR1cm4gdztcbn1cbiIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMTggMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya0pTLlxuXG4gICAgc25hcmtKUyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJrSlMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggc25hcmtKUy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbmltcG9ydCAqIGFzIGJpbkZpbGVVdGlscyBmcm9tIFwiQGlkZW4zL2JpbmZpbGV1dGlsc1wiO1xuaW1wb3J0ICogYXMgd3Ruc1V0aWxzIGZyb20gXCIuL3d0bnNfdXRpbHMuanNcIjtcbmltcG9ydCB7IHJlYWRSMWNzRmQgfSBmcm9tIFwicjFjc2ZpbGVcIjtcbmltcG9ydCB7IFNjYWxhciB9IGZyb20gXCJmZmphdmFzY3JpcHRcIjtcbmltcG9ydCAqIGFzIGN1cnZlcyBmcm9tIFwiLi9jdXJ2ZXMuanNcIjtcblxuZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gd3Ruc0NoZWNrKHIxY3NGaWxlbmFtZSwgd3Ruc0ZpbGVuYW1lLCBsb2dnZXIpIHtcblxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiV0lUTkVTUyBDSEVDS0lORyBTVEFSVEVEXCIpO1xuXG4gICAgLy8gUmVhZCByMWNzIGZpbGVcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gUmVhZGluZyByMWNzIGZpbGVcIik7XG4gICAgY29uc3Qge1xuICAgICAgICBmZDogZmRSMWNzLFxuICAgICAgICBzZWN0aW9uczogc2VjdGlvbnNSMWNzXG4gICAgfSA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkQmluRmlsZShyMWNzRmlsZW5hbWUsIFwicjFjc1wiLCAxLCAxIDw8IDIyLCAxIDw8IDI0KTtcbiAgICBjb25zdCByMWNzID0gYXdhaXQgcmVhZFIxY3NGZChmZFIxY3MsIHNlY3Rpb25zUjFjcywgeyBsb2FkQ29uc3RyYWludHM6IGZhbHNlLCBsb2FkQ3VzdG9tR2F0ZXM6IGZhbHNlIH0pO1xuXG4gICAgLy8gUmVhZCB3aXRuZXNzIGZpbGVcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gUmVhZGluZyB3aXRuZXNzIGZpbGVcIik7XG4gICAgY29uc3Qge1xuICAgICAgICBmZDogZmRXdG5zLFxuICAgICAgICBzZWN0aW9uczogd3Ruc1NlY3Rpb25zXG4gICAgfSA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkQmluRmlsZSh3dG5zRmlsZW5hbWUsIFwid3Ruc1wiLCAyLCAxIDw8IDIyLCAxIDw8IDI0KTtcbiAgICBjb25zdCB3dG5zSGVhZGVyID0gYXdhaXQgd3Ruc1V0aWxzLnJlYWRIZWFkZXIoZmRXdG5zLCB3dG5zU2VjdGlvbnMpO1xuXG4gICAgaWYgKCFTY2FsYXIuZXEocjFjcy5wcmltZSwgd3Ruc0hlYWRlci5xKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDdXJ2ZSBvZiB0aGUgd2l0bmVzcyBkb2VzIG5vdCBtYXRjaCB0aGUgY3VydmUgb2YgdGhlIHByb3Zpbmcga2V5XCIpO1xuICAgIH1cblxuICAgIGNvbnN0IGJ1ZmZXaXRuZXNzID0gYXdhaXQgYmluRmlsZVV0aWxzLnJlYWRTZWN0aW9uKGZkV3Rucywgd3Ruc1NlY3Rpb25zLCAyKTtcbiAgICBhd2FpdCBmZFd0bnMuY2xvc2UoKTtcblxuICAgIGNvbnN0IGN1cnZlID0gYXdhaXQgY3VydmVzLmdldEN1cnZlRnJvbVIocjFjcy5wcmltZSk7XG4gICAgY29uc3QgRnIgPSBjdXJ2ZS5GcjtcbiAgICBjb25zdCBzRnIgPSBGci5uODtcblxuICAgIGNvbnN0IGJSMWNzID0gYXdhaXQgYmluRmlsZVV0aWxzLnJlYWRTZWN0aW9uKGZkUjFjcywgc2VjdGlvbnNSMWNzLCAyKTtcblxuICAgIGlmIChsb2dnZXIpIHtcbiAgICAgICAgbG9nZ2VyLmluZm8oXCItLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXCIpO1xuICAgICAgICBsb2dnZXIuaW5mbyhcIiAgV0lUTkVTUyBDSEVDS1wiKTtcbiAgICAgICAgbG9nZ2VyLmluZm8oYCAgQ3VydmU6ICAgICAgICAgICR7cjFjcy5jdXJ2ZS5uYW1lfWApO1xuICAgICAgICBsb2dnZXIuaW5mbyhgICBWYXJzICh3aXJlcyk6ICAgJHtyMWNzLm5WYXJzfWApO1xuICAgICAgICBsb2dnZXIuaW5mbyhgICBPdXRwdXRzOiAgICAgICAgJHtyMWNzLm5PdXRwdXRzfWApO1xuICAgICAgICBsb2dnZXIuaW5mbyhgICBQdWJsaWMgSW5wdXRzOiAgJHtyMWNzLm5QdWJJbnB1dHN9YCk7XG4gICAgICAgIGxvZ2dlci5pbmZvKGAgIFByaXZhdGUgSW5wdXRzOiAke3IxY3MublBydklucHV0c31gKTtcbiAgICAgICAgbG9nZ2VyLmluZm8oYCAgTGFiZWxzOiAgICAgICAgICR7cjFjcy5uTGFiZWxzfWApO1xuICAgICAgICBsb2dnZXIuaW5mbyhgICBDb25zdHJhaW50czogICAgJHtyMWNzLm5Db25zdHJhaW50c31gKTtcbiAgICAgICAgbG9nZ2VyLmluZm8oYCAgQ3VzdG9tIEdhdGVzOiAgICR7cjFjcy51c2VDdXN0b21HYXRlc31gKTtcbiAgICAgICAgbG9nZ2VyLmluZm8oXCItLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXCIpO1xuICAgIH1cblxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBDaGVja2luZyB3aXRuZXNzIGNvcnJlY3RuZXNzXCIpO1xuXG4gICAgbGV0IGJSMWNzUG9zID0gMDtcbiAgICBsZXQgcmVzID0gdHJ1ZTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHIxY3MubkNvbnN0cmFpbnRzOyBpKyspIHtcbiAgICAgICAgaWYgKChsb2dnZXIpICYmIChpICE9PSAwKSAmJiAoaSAlIDUwMDAwMCA9PT0gMCkpIHtcbiAgICAgICAgICAgIGxvZ2dlci5pbmZvKGDCt8K3wrcgcHJvY2Vzc2luZyByMWNzIGNvbnN0cmFpbnRzICR7aX0vJHtyMWNzLm5Db25zdHJhaW50c31gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vUmVhZCB0aGUgdGhyZWUgbGluZWFyIGNvbWJpbmF0aW9ucyBvZiB0aGUgY29uc3RyYWludCB3aGVyZSBBICogQiAtIEMgPSAwXG4gICAgICAgIGNvbnN0IGxjQSA9IHJlYWRMQygpO1xuICAgICAgICBjb25zdCBsY0IgPSByZWFkTEMoKTtcbiAgICAgICAgY29uc3QgbGNDID0gcmVhZExDKCk7XG5cbiAgICAgICAgLy8gRXZhbHVhdGUgdGhlIGxpbmVhciBjb21iaW5hdGlvbnNcbiAgICAgICAgY29uc3QgZXZhbEEgPSBFdmFsdWF0ZUxpbmVhckNvbWJpbmF0aW9uKGxjQSk7XG4gICAgICAgIGNvbnN0IGV2YWxCID0gRXZhbHVhdGVMaW5lYXJDb21iaW5hdGlvbihsY0IpO1xuICAgICAgICBjb25zdCBldmFsQyA9IEV2YWx1YXRlTGluZWFyQ29tYmluYXRpb24obGNDKTtcblxuICAgICAgICAvLyBDaGVjayB0aGF0IEEgKiBCIC0gQyA9PSAwXG4gICAgICAgIGlmICghRnIuZXEoRnIuc3ViKEZyLm11bChldmFsQSwgZXZhbEIpLCBldmFsQyksIEZyLnplcm8pKSB7XG4gICAgICAgICAgICBsb2dnZXIud2FybihcIsK3wrfCtyBhYm9ydGluZyBjaGVja2luZyBwcm9jZXNzIGF0IGNvbnN0cmFpbnQgXCIgKyBpKTtcbiAgICAgICAgICAgIHJlcyA9IGZhbHNlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmZFIxY3MuY2xvc2UoKTtcblxuICAgIGlmIChsb2dnZXIpIHtcbiAgICAgICAgaWYgKHJlcykge1xuICAgICAgICAgICAgbG9nZ2VyLmluZm8oXCJXSVRORVNTIElTIENPUlJFQ1RcIik7XG4gICAgICAgICAgICBsb2dnZXIuaW5mbyhcIldJVE5FU1MgQ0hFQ0tJTkcgRklOSVNIRUQgU1VDQ0VTU0ZVTExZXCIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbG9nZ2VyLndhcm4oXCJXSVRORVNTIElTIE5PVCBDT1JSRUNUXCIpO1xuICAgICAgICAgICAgbG9nZ2VyLndhcm4oXCJXSVRORVNTIENIRUNLSU5HIEZJTklTSEVEIFVOU1VDQ0VTU0ZVTExZXCIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlcztcblxuICAgIGZ1bmN0aW9uIEV2YWx1YXRlTGluZWFyQ29tYmluYXRpb24obGMpIHtcbiAgICAgICAgbGV0IHJlcyA9IEZyLnplcm87XG5cbiAgICAgICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKGxjKTtcbiAgICAgICAga2V5cy5mb3JFYWNoKChzaWduYWxJZCkgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc2lnbmFsVmFsdWUgPSBnZXRXaXRuZXNzVmFsdWUoc2lnbmFsSWQpO1xuICAgICAgICAgICAgY29uc3Qgc2lnbmFsRmFjdG9yID0gbGNbc2lnbmFsSWRdO1xuXG4gICAgICAgICAgICByZXMgPSBGci5hZGQocmVzLCBGci5tdWwoc2lnbmFsVmFsdWUsIHNpZ25hbEZhY3RvcikpO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlYWRMQygpIHtcbiAgICAgICAgY29uc3QgbGMgPSB7fTtcblxuICAgICAgICBjb25zdCBidWZmVUwzMiA9IGJSMWNzLnNsaWNlKGJSMWNzUG9zLCBiUjFjc1BvcyArIDQpO1xuICAgICAgICBiUjFjc1BvcyArPSA0O1xuICAgICAgICBjb25zdCBidWZmVUwzMlYgPSBuZXcgRGF0YVZpZXcoYnVmZlVMMzIuYnVmZmVyKTtcbiAgICAgICAgY29uc3QgbklkeCA9IGJ1ZmZVTDMyVi5nZXRVaW50MzIoMCwgdHJ1ZSk7XG5cbiAgICAgICAgY29uc3QgYnVmZiA9IGJSMWNzLnNsaWNlKGJSMWNzUG9zLCBiUjFjc1BvcyArICg0ICsgcjFjcy5uOCkgKiBuSWR4KTtcbiAgICAgICAgYlIxY3NQb3MgKz0gKDQgKyByMWNzLm44KSAqIG5JZHg7XG4gICAgICAgIGNvbnN0IGJ1ZmZWID0gbmV3IERhdGFWaWV3KGJ1ZmYuYnVmZmVyKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuSWR4OyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGlkeCA9IGJ1ZmZWLmdldFVpbnQzMihpICogKDQgKyByMWNzLm44KSwgdHJ1ZSk7XG4gICAgICAgICAgICBjb25zdCB2YWwgPSByMWNzLkYuZnJvbVJwckxFKGJ1ZmYsIGkgKiAoNCArIHIxY3MubjgpICsgNCk7XG4gICAgICAgICAgICBsY1tpZHhdID0gdmFsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsYztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRXaXRuZXNzVmFsdWUoc2lnbmFsSWQpIHtcbiAgICAgICAgcmV0dXJuIEZyLmZyb21ScHJMRShidWZmV2l0bmVzcy5zbGljZShzaWduYWxJZCAqIHNGciwgc2lnbmFsSWQgKiBzRnIgKyBzRnIpKTtcbiAgICB9XG59IiwiLypcbiAgICBDb3B5cmlnaHQgMjAxOCAwS0lNUyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJrSlMuXG5cbiAgICBzbmFya0pTIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICAgIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gICAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAgICAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtKUyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVFxuICAgIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpY1xuICAgIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gICAgYWxvbmcgd2l0aCBzbmFya0pTLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuZXhwb3J0IHtkZWZhdWx0IGFzIGNhbGN1bGF0ZX0gZnJvbSBcIi4vd3Ruc19jYWxjdWxhdGUuanNcIjtcbmV4cG9ydCB7ZGVmYXVsdCBhcyBkZWJ1Z30gZnJvbSBcIi4vd3Ruc19kZWJ1Zy5qc1wiO1xuZXhwb3J0IHtkZWZhdWx0IGFzIGV4cG9ydEpzb259IGZyb20gXCIuL3d0bnNfZXhwb3J0X2pzb24uanNcIjtcbmV4cG9ydCB7ZGVmYXVsdCBhcyBjaGVja30gZnJvbSBcIi4vd3Ruc19jaGVjay5qc1wiOyIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMTggMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya0pTLlxuXG4gICAgc25hcmtKUyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJrSlMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggc25hcmtKUy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbmNvbnN0IFNVQkFSUkFZX1NJWkUgPSAweDQwMDAwO1xuXG5jb25zdCBCaWdBcnJheUhhbmRsZXIgPSB7XG4gICAgZ2V0OiBmdW5jdGlvbihvYmosIHByb3ApIHtcbiAgICAgICAgaWYgKCFpc05hTihwcm9wKSkge1xuICAgICAgICAgICAgcmV0dXJuIG9iai5nZXRFbGVtZW50KHByb3ApO1xuICAgICAgICB9IGVsc2UgcmV0dXJuIG9ialtwcm9wXTtcbiAgICB9LFxuICAgIHNldDogZnVuY3Rpb24ob2JqLCBwcm9wLCB2YWx1ZSkge1xuICAgICAgICBpZiAoIWlzTmFOKHByb3ApKSB7XG4gICAgICAgICAgICByZXR1cm4gb2JqLnNldEVsZW1lbnQocHJvcCwgdmFsdWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb2JqW3Byb3BdID0gdmFsdWU7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbmNsYXNzIF9CaWdBcnJheSB7XG4gICAgY29uc3RydWN0b3IgKGluaXRTaXplKSB7XG4gICAgICAgIHRoaXMubGVuZ3RoID0gaW5pdFNpemUgfHwgMDtcbiAgICAgICAgdGhpcy5hcnIgPSBuZXcgQXJyYXkoU1VCQVJSQVlfU0laRSk7XG5cbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPGluaXRTaXplOyBpKz1TVUJBUlJBWV9TSVpFKSB7XG4gICAgICAgICAgICB0aGlzLmFycltpL1NVQkFSUkFZX1NJWkVdID0gbmV3IEFycmF5KE1hdGgubWluKFNVQkFSUkFZX1NJWkUsIGluaXRTaXplIC0gaSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBwdXNoICgpIHtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdGhpcy5zZXRFbGVtZW50ICh0aGlzLmxlbmd0aCwgYXJndW1lbnRzW2ldKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNsaWNlIChmLCB0KSB7XG4gICAgICAgIGNvbnN0IGFyciA9IG5ldyBBcnJheSh0LWYpO1xuICAgICAgICBmb3IgKGxldCBpPWY7IGk8IHQ7IGkrKykgYXJyW2ktZl0gPSB0aGlzLmdldEVsZW1lbnQoaSk7XG4gICAgICAgIHJldHVybiBhcnI7XG4gICAgfVxuICAgIGdldEVsZW1lbnQoaWR4KSB7XG4gICAgICAgIGlkeCA9IHBhcnNlSW50KGlkeCk7XG4gICAgICAgIGNvbnN0IGlkeDEgPSBNYXRoLmZsb29yKGlkeCAvIFNVQkFSUkFZX1NJWkUpO1xuICAgICAgICBjb25zdCBpZHgyID0gaWR4ICUgU1VCQVJSQVlfU0laRTtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXJyW2lkeDFdID8gdGhpcy5hcnJbaWR4MV1baWR4Ml0gOiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHNldEVsZW1lbnQoaWR4LCB2YWx1ZSkge1xuICAgICAgICBpZHggPSBwYXJzZUludChpZHgpO1xuICAgICAgICBjb25zdCBpZHgxID0gTWF0aC5mbG9vcihpZHggLyBTVUJBUlJBWV9TSVpFKTtcbiAgICAgICAgaWYgKCF0aGlzLmFycltpZHgxXSkge1xuICAgICAgICAgICAgdGhpcy5hcnJbaWR4MV0gPSBuZXcgQXJyYXkoU1VCQVJSQVlfU0laRSk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgaWR4MiA9IGlkeCAlIFNVQkFSUkFZX1NJWkU7XG4gICAgICAgIHRoaXMuYXJyW2lkeDFdW2lkeDJdID0gdmFsdWU7XG4gICAgICAgIGlmIChpZHggPj0gdGhpcy5sZW5ndGgpIHRoaXMubGVuZ3RoID0gaWR4KzE7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBnZXRLZXlzKCkge1xuICAgICAgICBjb25zdCBuZXdBID0gbmV3IEJpZ0FycmF5KCk7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTx0aGlzLmFyci5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYXJyW2ldKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaj0wOyBqPHRoaXMuYXJyW2ldLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5hcnJbaV1bal0gIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0EucHVzaChpKlNVQkFSUkFZX1NJWkUraik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ld0E7XG4gICAgfVxufVxuXG5jbGFzcyBCaWdBcnJheSB7XG4gICAgY29uc3RydWN0b3IoIGluaXRTaXplICkge1xuICAgICAgICBjb25zdCBvYmogPSBuZXcgX0JpZ0FycmF5KGluaXRTaXplKTtcbiAgICAgICAgY29uc3QgZXh0T2JqID0gbmV3IFByb3h5KG9iaiwgQmlnQXJyYXlIYW5kbGVyKTtcbiAgICAgICAgcmV0dXJuIGV4dE9iajtcbiAgICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEJpZ0FycmF5O1xuIiwiLypcbiAgICBDb3B5cmlnaHQgMjAxOCAwS0lNUyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJrSlMuXG5cbiAgICBzbmFya0pTIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICAgIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gICAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAgICAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtKUyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVFxuICAgIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpY1xuICAgIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gICAgYWxvbmcgd2l0aCBzbmFya0pTLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuaW1wb3J0IHtyZWFkUjFjc0hlYWRlcn0gZnJvbSBcInIxY3NmaWxlXCI7XG5pbXBvcnQgKiBhcyB1dGlscyBmcm9tIFwiLi9wb3dlcnNvZnRhdV91dGlscy5qc1wiO1xuaW1wb3J0IHtcbiAgICByZWFkQmluRmlsZSxcbiAgICBjcmVhdGVCaW5GaWxlLFxuICAgIHJlYWRTZWN0aW9uLFxuICAgIHdyaXRlQmlnSW50LFxuICAgIHN0YXJ0V3JpdGVTZWN0aW9uLFxuICAgIGVuZFdyaXRlU2VjdGlvbixcbn0gZnJvbSBcIkBpZGVuMy9iaW5maWxldXRpbHNcIjtcbmltcG9ydCB7IGxvZzIsIGZvcm1hdEhhc2ggfSBmcm9tIFwiLi9taXNjLmpzXCI7XG5pbXBvcnQgeyBTY2FsYXIsIEJpZ0J1ZmZlciB9IGZyb20gXCJmZmphdmFzY3JpcHRcIjtcbmltcG9ydCB7IGJsYWtlMmIgfSBmcm9tIFwiQG5vYmxlL2hhc2hlcy9ibGFrZTJiXCI7XG5pbXBvcnQgQmlnQXJyYXkgZnJvbSBcIi4vYmlnYXJyYXkuanNcIjtcblxuZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gbmV3WktleShyMWNzTmFtZSwgcHRhdU5hbWUsIHprZXlOYW1lLCBsb2dnZXIpIHtcblxuICAgIGNvbnN0IFRBVV9HMSA9IDA7XG4gICAgY29uc3QgVEFVX0cyID0gMTtcbiAgICBjb25zdCBBTFBIQVRBVV9HMSA9IDI7XG4gICAgY29uc3QgQkVUQVRBVV9HMSA9IDM7XG4gICAgY29uc3QgY3NIYXNoZXIgPSBibGFrZTJiLmNyZWF0ZSh7IGRrTGVuOiA2NCB9KTtcblxuICAgIGNvbnN0IHtmZDogZmRQVGF1LCBzZWN0aW9uczogc2VjdGlvbnNQVGF1fSA9IGF3YWl0IHJlYWRCaW5GaWxlKHB0YXVOYW1lLCBcInB0YXVcIiwgMSwgMTw8MjIsIDE8PDI0KTtcbiAgICBjb25zdCB7Y3VydmUsIHBvd2VyfSA9IGF3YWl0IHV0aWxzLnJlYWRQVGF1SGVhZGVyKGZkUFRhdSwgc2VjdGlvbnNQVGF1KTtcbiAgICBjb25zdCB7ZmQ6IGZkUjFjcywgc2VjdGlvbnM6IHNlY3Rpb25zUjFjc30gPSBhd2FpdCByZWFkQmluRmlsZShyMWNzTmFtZSwgXCJyMWNzXCIsIDEsIDE8PDIyLCAxPDwyNCk7XG4gICAgY29uc3QgcjFjcyA9IGF3YWl0IHJlYWRSMWNzSGVhZGVyKGZkUjFjcywgc2VjdGlvbnNSMWNzLCBmYWxzZSk7XG5cbiAgICBjb25zdCBmZFpLZXkgPSBhd2FpdCBjcmVhdGVCaW5GaWxlKHprZXlOYW1lLCBcInprZXlcIiwgMSwgMTAsIDE8PDIyLCAxPDwyNCk7XG5cbiAgICBjb25zdCBzRzEgPSBjdXJ2ZS5HMS5GLm44KjI7XG4gICAgY29uc3Qgc0cyID0gY3VydmUuRzIuRi5uOCoyO1xuXG4gICAgaWYgKHIxY3MucHJpbWUgIT0gY3VydmUucikge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJyMWNzIGN1cnZlIGRvZXMgbm90IG1hdGNoIHBvd2VycyBvZiB0YXUgY2VyZW1vbnkgY3VydmVcIik7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICB9XG5cbiAgICBjb25zdCBjaXJQb3dlciA9IGxvZzIocjFjcy5uQ29uc3RyYWludHMgKyByMWNzLm5QdWJJbnB1dHMgKyByMWNzLm5PdXRwdXRzICsxIC0xKSArMTtcblxuICAgIGlmIChjaXJQb3dlciA+IHBvd2VyKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihgY2lyY3VpdCB0b28gYmlnIGZvciB0aGlzIHBvd2VyIG9mIHRhdSBjZXJlbW9ueS4gJHtyMWNzLm5Db25zdHJhaW50c30qMiA+IDIqKiR7cG93ZXJ9YCk7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICB9XG5cbiAgICBpZiAoIXNlY3Rpb25zUFRhdVsxMl0pIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiUG93ZXJzIG9mIHRhdSBpcyBub3QgcHJlcGFyZWQuXCIpO1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgY29uc3QgblB1YmxpYyA9IHIxY3Mubk91dHB1dHMgKyByMWNzLm5QdWJJbnB1dHM7XG4gICAgY29uc3QgZG9tYWluU2l6ZSA9IDIgKiogY2lyUG93ZXI7XG5cbiAgICAvLyBXcml0ZSB0aGUgaGVhZGVyXG4gICAgLy8vLy8vLy8vLy9cbiAgICBhd2FpdCBzdGFydFdyaXRlU2VjdGlvbihmZFpLZXksIDEpO1xuICAgIGF3YWl0IGZkWktleS53cml0ZVVMRTMyKDEpOyAvLyBHcm90aFxuICAgIGF3YWl0IGVuZFdyaXRlU2VjdGlvbihmZFpLZXkpO1xuXG4gICAgLy8gV3JpdGUgdGhlIEdyb3RoIGhlYWRlciBzZWN0aW9uXG4gICAgLy8vLy8vLy8vLy9cblxuICAgIGF3YWl0IHN0YXJ0V3JpdGVTZWN0aW9uKGZkWktleSwgMik7XG4gICAgY29uc3QgcHJpbWVRID0gY3VydmUucTtcbiAgICBjb25zdCBuOHEgPSAoTWF0aC5mbG9vciggKFNjYWxhci5iaXRMZW5ndGgocHJpbWVRKSAtIDEpIC8gNjQpICsxKSo4O1xuXG4gICAgY29uc3QgcHJpbWVSID0gY3VydmUucjtcbiAgICBjb25zdCBuOHIgPSAoTWF0aC5mbG9vciggKFNjYWxhci5iaXRMZW5ndGgocHJpbWVSKSAtIDEpIC8gNjQpICsxKSo4O1xuICAgIGNvbnN0IFJyID0gU2NhbGFyLm1vZChTY2FsYXIuc2hsKDEsIG44cio4KSwgcHJpbWVSKTtcbiAgICBjb25zdCBSMnIgPSBjdXJ2ZS5Gci5lKFNjYWxhci5tb2QoU2NhbGFyLm11bChScixSciksIHByaW1lUikpO1xuXG4gICAgYXdhaXQgZmRaS2V5LndyaXRlVUxFMzIobjhxKTtcbiAgICBhd2FpdCB3cml0ZUJpZ0ludChmZFpLZXksIHByaW1lUSwgbjhxKTtcbiAgICBhd2FpdCBmZFpLZXkud3JpdGVVTEUzMihuOHIpO1xuICAgIGF3YWl0IHdyaXRlQmlnSW50KGZkWktleSwgcHJpbWVSLCBuOHIpO1xuICAgIGF3YWl0IGZkWktleS53cml0ZVVMRTMyKHIxY3MublZhcnMpOyAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUb3RhbCBudW1iZXIgb2YgYmFyc1xuICAgIGF3YWl0IGZkWktleS53cml0ZVVMRTMyKG5QdWJsaWMpOyAgICAgICAgICAgICAgICAgICAgICAgLy8gVG90YWwgbnVtYmVyIG9mIHB1YmxpYyB2YXJzIChub3QgaW5jbHVkaW5nIE9ORSlcbiAgICBhd2FpdCBmZFpLZXkud3JpdGVVTEUzMihkb21haW5TaXplKTsgICAgICAgICAgICAgICAgICAvLyBkb21haW5TaXplXG5cbiAgICBsZXQgYkFscGhhMTtcbiAgICBiQWxwaGExID0gYXdhaXQgZmRQVGF1LnJlYWQoc0cxLCBzZWN0aW9uc1BUYXVbNF1bMF0ucCk7XG4gICAgYXdhaXQgZmRaS2V5LndyaXRlKGJBbHBoYTEpO1xuICAgIGJBbHBoYTEgPSBhd2FpdCBjdXJ2ZS5HMS5iYXRjaExFTXRvVShiQWxwaGExKTtcbiAgICBjc0hhc2hlci51cGRhdGUoYkFscGhhMSk7XG5cbiAgICBsZXQgYkJldGExO1xuICAgIGJCZXRhMSA9IGF3YWl0IGZkUFRhdS5yZWFkKHNHMSwgc2VjdGlvbnNQVGF1WzVdWzBdLnApO1xuICAgIGF3YWl0IGZkWktleS53cml0ZShiQmV0YTEpO1xuICAgIGJCZXRhMSA9IGF3YWl0IGN1cnZlLkcxLmJhdGNoTEVNdG9VKGJCZXRhMSk7XG4gICAgY3NIYXNoZXIudXBkYXRlKGJCZXRhMSk7XG5cbiAgICBsZXQgYkJldGEyO1xuICAgIGJCZXRhMiA9IGF3YWl0IGZkUFRhdS5yZWFkKHNHMiwgc2VjdGlvbnNQVGF1WzZdWzBdLnApO1xuICAgIGF3YWl0IGZkWktleS53cml0ZShiQmV0YTIpO1xuICAgIGJCZXRhMiA9IGF3YWl0IGN1cnZlLkcyLmJhdGNoTEVNdG9VKGJCZXRhMik7XG4gICAgY3NIYXNoZXIudXBkYXRlKGJCZXRhMik7XG5cbiAgICBjb25zdCBiZzEgPSBuZXcgVWludDhBcnJheShzRzEpO1xuICAgIGN1cnZlLkcxLnRvUnByTEVNKGJnMSwgMCwgY3VydmUuRzEuZyk7XG4gICAgY29uc3QgYmcyID0gbmV3IFVpbnQ4QXJyYXkoc0cyKTtcbiAgICBjdXJ2ZS5HMi50b1JwckxFTShiZzIsIDAsIGN1cnZlLkcyLmcpO1xuICAgIGNvbnN0IGJnMVUgPSBuZXcgVWludDhBcnJheShzRzEpO1xuICAgIGN1cnZlLkcxLnRvUnByVW5jb21wcmVzc2VkKGJnMVUsIDAsIGN1cnZlLkcxLmcpO1xuICAgIGNvbnN0IGJnMlUgPSBuZXcgVWludDhBcnJheShzRzIpO1xuICAgIGN1cnZlLkcyLnRvUnByVW5jb21wcmVzc2VkKGJnMlUsIDAsIGN1cnZlLkcyLmcpO1xuXG4gICAgYXdhaXQgZmRaS2V5LndyaXRlKGJnMik7ICAgICAgICAvLyBnYW1tYTJcbiAgICBhd2FpdCBmZFpLZXkud3JpdGUoYmcxKTsgICAgICAgIC8vIGRlbHRhMVxuICAgIGF3YWl0IGZkWktleS53cml0ZShiZzIpOyAgICAgICAgLy8gZGVsdGEyXG4gICAgY3NIYXNoZXIudXBkYXRlKGJnMlUpOyAgICAgIC8vIGdhbW1hMlxuICAgIGNzSGFzaGVyLnVwZGF0ZShiZzFVKTsgICAgICAvLyBkZWx0YTFcbiAgICBjc0hhc2hlci51cGRhdGUoYmcyVSk7ICAgICAgLy8gZGVsdGEyXG4gICAgYXdhaXQgZW5kV3JpdGVTZWN0aW9uKGZkWktleSk7XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhtZW1Vc2FnZSgpKTtcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIlJlYWRpbmcgcjFjc1wiKTtcbiAgICBsZXQgc1IxY3MgPSBhd2FpdCByZWFkU2VjdGlvbihmZFIxY3MsIHNlY3Rpb25zUjFjcywgMik7XG4gICAgYXdhaXQgZmRSMWNzLmNsb3NlKCk7XG5cbiAgICBsZXQgQSA9IG5ldyBCaWdBcnJheShyMWNzLm5WYXJzKTtcbiAgICBsZXQgQjEgPSBuZXcgQmlnQXJyYXkocjFjcy5uVmFycyk7XG4gICAgbGV0IEIyID0gbmV3IEJpZ0FycmF5KHIxY3MublZhcnMpO1xuICAgIGxldCBDID0gbmV3IEJpZ0FycmF5KHIxY3MublZhcnMtIG5QdWJsaWMgLTEpO1xuICAgIGxldCBJQyA9IG5ldyBBcnJheShuUHVibGljKzEpO1xuXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8obWVtVXNhZ2UoKSk7XG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCJSZWFkaW5nIHRhdUcxXCIpO1xuICAgIGxldCBzVGF1RzEgPSBhd2FpdCByZWFkU2VjdGlvbihmZFBUYXUsIHNlY3Rpb25zUFRhdSwgMTIsIChkb21haW5TaXplIC0xKSpzRzEsIGRvbWFpblNpemUqc0cxKTtcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIlJlYWRpbmcgdGF1RzJcIik7XG4gICAgbGV0IHNUYXVHMiA9IGF3YWl0IHJlYWRTZWN0aW9uKGZkUFRhdSwgc2VjdGlvbnNQVGF1LCAxMywgKGRvbWFpblNpemUgLTEpKnNHMiwgZG9tYWluU2l6ZSpzRzIpO1xuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiUmVhZGluZyBhbHBoYXRhdUcxXCIpO1xuICAgIGxldCBzQWxwaGFUYXVHMSA9IGF3YWl0IHJlYWRTZWN0aW9uKGZkUFRhdSwgc2VjdGlvbnNQVGF1LCAxNCwgKGRvbWFpblNpemUgLTEpKnNHMSwgZG9tYWluU2l6ZSpzRzEpO1xuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiUmVhZGluZyBiZXRhdGF1RzFcIik7XG4gICAgbGV0IHNCZXRhVGF1RzEgPSBhd2FpdCByZWFkU2VjdGlvbihmZFBUYXUsIHNlY3Rpb25zUFRhdSwgMTUsIChkb21haW5TaXplIC0xKSpzRzEsIGRvbWFpblNpemUqc0cxKTtcblxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKG1lbVVzYWdlKCkpO1xuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwicHJvY2Vzc0NvbnN0cmFpbnRzXCIpO1xuICAgIGF3YWl0IHByb2Nlc3NDb25zdHJhaW50cygpO1xuXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8obWVtVXNhZ2UoKSk7XG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCJjb21wb3NlQW5kV3JpdGVQb2ludHNcIik7XG4gICAgYXdhaXQgY29tcG9zZUFuZFdyaXRlUG9pbnRzKDMsIFwiRzFcIiwgSUMsIFwiSUNcIik7XG5cbiAgICBJQyA9IG51bGw7XG4gICAgLy8gY29uc3QgZ2MgPSBydW5Jbk5ld0NvbnRleHQoXCJnY1wiKTsgLy8gbm9jb21taXRcbiAgICAvLyBnYygpO1xuXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8obWVtVXNhZ2UoKSk7XG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCJ3cml0ZUhzXCIpO1xuICAgIGF3YWl0IHdyaXRlSHMoKTtcblxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKG1lbVVzYWdlKCkpO1xuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiaGFzaEhQb2ludHNcIik7XG4gICAgYXdhaXQgaGFzaEhQb2ludHMoKTtcblxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKG1lbVVzYWdlKCkpO1xuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiY29tcG9zZUFuZFdyaXRlUG9pbnRzIDggRzEgQ1wiKTtcbiAgICBhd2FpdCBjb21wb3NlQW5kV3JpdGVQb2ludHMoOCwgXCJHMVwiLCBDLCBcIkNcIik7XG5cbiAgICBDID0gbnVsbDtcbiAgICAvLyBnYygpO1xuXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8obWVtVXNhZ2UoKSk7XG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCJjb21wb3NlQW5kV3JpdGVQb2ludHMgNSBHMSBBXCIpO1xuICAgIGF3YWl0IGNvbXBvc2VBbmRXcml0ZVBvaW50cyg1LCBcIkcxXCIsIEEsIFwiQVwiKTtcblxuICAgIEEgPSBudWxsO1xuICAgIC8vIGdjKCk7XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhtZW1Vc2FnZSgpKTtcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcImNvbXBvc2VBbmRXcml0ZVBvaW50cyA2IEcxIEIxXCIpO1xuICAgIGF3YWl0IGNvbXBvc2VBbmRXcml0ZVBvaW50cyg2LCBcIkcxXCIsIEIxLCBcIkIxXCIpO1xuXG4gICAgQjEgPSBudWxsO1xuICAgIC8vIGdjKCk7XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhtZW1Vc2FnZSgpKTtcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcImNvbXBvc2VBbmRXcml0ZVBvaW50cyA3IEcyIEIyXCIpO1xuICAgIGF3YWl0IGNvbXBvc2VBbmRXcml0ZVBvaW50cyg3LCBcIkcyXCIsIEIyLCBcIkIyXCIpO1xuXG4gICAgQjIgPSBudWxsO1xuICAgIC8vIGdjKCk7XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhtZW1Vc2FnZSgpKTtcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIkNvbnRyaWJ1dGlvbnMgc2VjdGlvblwiKTtcbiAgICBjb25zdCBjc0hhc2ggPSBjc0hhc2hlci5kaWdlc3QoKTtcbiAgICAvLyBDb250cmlidXRpb25zIHNlY3Rpb25cbiAgICBhd2FpdCBzdGFydFdyaXRlU2VjdGlvbihmZFpLZXksIDEwKTtcbiAgICBhd2FpdCBmZFpLZXkud3JpdGUoY3NIYXNoKTtcbiAgICBhd2FpdCBmZFpLZXkud3JpdGVVTEUzMigwKTtcbiAgICBhd2FpdCBlbmRXcml0ZVNlY3Rpb24oZmRaS2V5KTtcblxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKGZvcm1hdEhhc2goY3NIYXNoLCBcIkNpcmN1aXQgaGFzaDogXCIpKTtcblxuXG4gICAgYXdhaXQgZmRaS2V5LmNsb3NlKCk7XG4gICAgYXdhaXQgZmRQVGF1LmNsb3NlKCk7XG5cbiAgICByZXR1cm4gY3NIYXNoO1xuXG4gICAgYXN5bmMgZnVuY3Rpb24gd3JpdGVIcygpIHtcbiAgICAgICAgYXdhaXQgc3RhcnRXcml0ZVNlY3Rpb24oZmRaS2V5LCA5KTtcbiAgICAgICAgY29uc3QgYnVmZk91dCA9IG5ldyBCaWdCdWZmZXIoZG9tYWluU2l6ZSpzRzEpO1xuICAgICAgICBpZiAoY2lyUG93ZXIgPCBjdXJ2ZS5Gci5zKSB7XG4gICAgICAgICAgICBsZXQgc1RhdUcxID0gYXdhaXQgcmVhZFNlY3Rpb24oZmRQVGF1LCBzZWN0aW9uc1BUYXUsIDEyLCAoZG9tYWluU2l6ZSoyLTEpKnNHMSwgZG9tYWluU2l6ZSoyKnNHMSk7XG4gICAgICAgICAgICBmb3IgKGxldCBpPTA7IGk8IGRvbWFpblNpemU7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmICgobG9nZ2VyKSYmKGklMTAwMDAgPT0gMCkpIGxvZ2dlci5kZWJ1Zyhgc3BsaXR0aW5nIGJ1ZmZlcjogJHtpfS8ke2RvbWFpblNpemV9YCk7XG4gICAgICAgICAgICAgICAgY29uc3QgYnVmZiA9IHNUYXVHMS5zbGljZSggKGkqMisxKSpzRzEsIChpKjIrMSkqc0cxICsgc0cxICk7XG4gICAgICAgICAgICAgICAgYnVmZk91dC5zZXQoYnVmZiwgaSpzRzEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGNpclBvd2VyID09IGN1cnZlLkZyLnMpIHtcbiAgICAgICAgICAgIGNvbnN0IG8gPSBzZWN0aW9uc1BUYXVbMTJdWzBdLnAgKyAoKDIgKiogKGNpclBvd2VyKzEpKSAtMSkqc0cxO1xuICAgICAgICAgICAgYXdhaXQgZmRQVGF1LnJlYWRUb0J1ZmZlcihidWZmT3V0LCAwLCBkb21haW5TaXplKnNHMSwgbyArIGRvbWFpblNpemUqc0cxKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihcIkNpcmN1aXQgdG9vIGJpZ1wiKTtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNpcmN1aXQgdG9vIGJpZyBmb3IgdGhpcyBjdXJ2ZVwiKTtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCBmZFpLZXkud3JpdGUoYnVmZk91dCk7XG4gICAgICAgIGF3YWl0IGVuZFdyaXRlU2VjdGlvbihmZFpLZXkpO1xuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHByb2Nlc3NDb25zdHJhaW50cygpIHtcbiAgICAgICAgY29uc3QgYnVmZkNvZWZmID0gbmV3IFVpbnQ4QXJyYXkoMTIgKyBjdXJ2ZS5Gci5uOCk7XG4gICAgICAgIGNvbnN0IGJ1ZmZDb2VmZlYgPSBuZXcgRGF0YVZpZXcoYnVmZkNvZWZmLmJ1ZmZlcik7XG4gICAgICAgIGNvbnN0IGJPbmUgPSBuZXcgVWludDhBcnJheShjdXJ2ZS5Gci5uOCk7XG4gICAgICAgIGN1cnZlLkZyLnRvUnByTEUoYk9uZSwgMCwgY3VydmUuRnIuZSgxKSk7XG5cbiAgICAgICAgbGV0IHIxY3NQb3MgPSAwO1xuXG4gICAgICAgIGZ1bmN0aW9uIHIxY3NfcmVhZFVMRTMyKCkge1xuICAgICAgICAgICAgY29uc3QgYnVmZiA9IHNSMWNzLnNsaWNlKHIxY3NQb3MsIHIxY3NQb3MrNCk7XG4gICAgICAgICAgICByMWNzUG9zICs9IDQ7XG4gICAgICAgICAgICBjb25zdCBidWZmViA9IG5ldyBEYXRhVmlldyhidWZmLmJ1ZmZlcik7XG4gICAgICAgICAgICByZXR1cm4gYnVmZlYuZ2V0VWludDMyKDAsIHRydWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY29lZnMgPSBuZXcgQmlnQXJyYXkoKTtcbiAgICAgICAgZm9yIChsZXQgYz0wOyBjPHIxY3MubkNvbnN0cmFpbnRzOyBjKyspIHtcbiAgICAgICAgICAgIGlmICgobG9nZ2VyKSYmKGMlMTAwMDAgPT0gMCkpIGxvZ2dlci5kZWJ1ZyhgcHJvY2Vzc2luZyBjb25zdHJhaW50czogJHtjfS8ke3IxY3MubkNvbnN0cmFpbnRzfWApO1xuICAgICAgICAgICAgY29uc3QgbkEgPSByMWNzX3JlYWRVTEUzMigpO1xuICAgICAgICAgICAgZm9yIChsZXQgaT0wOyBpPG5BOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzID0gcjFjc19yZWFkVUxFMzIoKTtcbiAgICAgICAgICAgICAgICBjb25zdCBjb2VmcCA9IHIxY3NQb3M7XG4gICAgICAgICAgICAgICAgcjFjc1BvcyArPSBjdXJ2ZS5Gci5uODtcblxuICAgICAgICAgICAgICAgIGNvbnN0IGwxdCA9IFRBVV9HMTtcbiAgICAgICAgICAgICAgICBjb25zdCBsMSA9IHNHMSpjO1xuICAgICAgICAgICAgICAgIGNvbnN0IGwydCA9IEJFVEFUQVVfRzE7XG4gICAgICAgICAgICAgICAgY29uc3QgbDIgPSBzRzEqYztcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIEFbc10gPT09IFwidW5kZWZpbmVkXCIpIEFbc10gPSBbXTtcbiAgICAgICAgICAgICAgICBBW3NdLnB1c2goW2wxdCwgbDEsIGNvZWZwXSk7XG5cbiAgICAgICAgICAgICAgICBpZiAocyA8PSBuUHVibGljKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgSUNbc10gPT09IFwidW5kZWZpbmVkXCIpIElDW3NdID0gW107XG4gICAgICAgICAgICAgICAgICAgIElDW3NdLnB1c2goW2wydCwgbDIsIGNvZWZwXSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBDW3MtIG5QdWJsaWMgLTFdID09PSBcInVuZGVmaW5lZFwiKSBDW3MtIG5QdWJsaWMgLTFdID0gW107XG4gICAgICAgICAgICAgICAgICAgIENbcyAtIG5QdWJsaWMgLTFdLnB1c2goW2wydCwgbDIsIGNvZWZwXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvZWZzLnB1c2goWzAsIGMsIHMsIGNvZWZwXSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IG5CID0gcjFjc19yZWFkVUxFMzIoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGk9MDsgaTxuQjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcyA9IHIxY3NfcmVhZFVMRTMyKCk7XG4gICAgICAgICAgICAgICAgY29uc3QgY29lZnAgPSByMWNzUG9zO1xuICAgICAgICAgICAgICAgIHIxY3NQb3MgKz0gY3VydmUuRnIubjg7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBsMXQgPSBUQVVfRzE7XG4gICAgICAgICAgICAgICAgY29uc3QgbDEgPSBzRzEqYztcbiAgICAgICAgICAgICAgICBjb25zdCBsMnQgPSBUQVVfRzI7XG4gICAgICAgICAgICAgICAgY29uc3QgbDIgPSBzRzIqYztcbiAgICAgICAgICAgICAgICBjb25zdCBsM3QgPSBBTFBIQVRBVV9HMTtcbiAgICAgICAgICAgICAgICBjb25zdCBsMyA9IHNHMSpjO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgQjFbc10gPT09IFwidW5kZWZpbmVkXCIpIEIxW3NdID0gW107XG4gICAgICAgICAgICAgICAgQjFbc10ucHVzaChbbDF0LCBsMSwgY29lZnBdKTtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIEIyW3NdID09PSBcInVuZGVmaW5lZFwiKSBCMltzXSA9IFtdO1xuICAgICAgICAgICAgICAgIEIyW3NdLnB1c2goW2wydCwgbDIsIGNvZWZwXSk7XG5cbiAgICAgICAgICAgICAgICBpZiAocyA8PSBuUHVibGljKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgSUNbc10gPT09IFwidW5kZWZpbmVkXCIpIElDW3NdID0gW107XG4gICAgICAgICAgICAgICAgICAgIElDW3NdLnB1c2goW2wzdCwgbDMsIGNvZWZwXSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBDW3MtIG5QdWJsaWMgLTFdID09PSBcInVuZGVmaW5lZFwiKSBDW3MtIG5QdWJsaWMgLTFdID0gW107XG4gICAgICAgICAgICAgICAgICAgIENbcy0gblB1YmxpYyAtMV0ucHVzaChbbDN0LCBsMywgY29lZnBdKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb2Vmcy5wdXNoKFsxLCBjLCBzLCBjb2VmcF0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBuQyA9IHIxY3NfcmVhZFVMRTMyKCk7XG4gICAgICAgICAgICBmb3IgKGxldCBpPTA7IGk8bkM7IGkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHMgPSByMWNzX3JlYWRVTEUzMigpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvZWZwID0gcjFjc1BvcztcbiAgICAgICAgICAgICAgICByMWNzUG9zICs9IGN1cnZlLkZyLm44O1xuXG4gICAgICAgICAgICAgICAgY29uc3QgbDF0ID0gVEFVX0cxO1xuICAgICAgICAgICAgICAgIGNvbnN0IGwxID0gc0cxKmM7XG4gICAgICAgICAgICAgICAgaWYgKHMgPD0gblB1YmxpYykge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIElDW3NdID09PSBcInVuZGVmaW5lZFwiKSBJQ1tzXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBJQ1tzXS5wdXNoKFtsMXQsIGwxLCBjb2VmcF0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgQ1tzLSBuUHVibGljIC0xXSA9PT0gXCJ1bmRlZmluZWRcIikgQ1tzLSBuUHVibGljIC0xXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBDW3MtIG5QdWJsaWMgLTFdLnB1c2goW2wxdCwgbDEsIGNvZWZwXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChsZXQgcyA9IDA7IHMgPD0gblB1YmxpYyA7IHMrKykge1xuICAgICAgICAgICAgY29uc3QgbDF0ID0gVEFVX0cxO1xuICAgICAgICAgICAgY29uc3QgbDEgPSBzRzEqKHIxY3MubkNvbnN0cmFpbnRzICsgcyk7XG4gICAgICAgICAgICBjb25zdCBsMnQgPSBCRVRBVEFVX0cxO1xuICAgICAgICAgICAgY29uc3QgbDIgPSBzRzEqKHIxY3MubkNvbnN0cmFpbnRzICsgcyk7XG4gICAgICAgICAgICBpZiAodHlwZW9mIEFbc10gPT09IFwidW5kZWZpbmVkXCIpIEFbc10gPSBbXTtcbiAgICAgICAgICAgIEFbc10ucHVzaChbbDF0LCBsMSwgLTFdKTtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgSUNbc10gPT09IFwidW5kZWZpbmVkXCIpIElDW3NdID0gW107XG4gICAgICAgICAgICBJQ1tzXS5wdXNoKFtsMnQsIGwyLCAtMV0pO1xuICAgICAgICAgICAgY29lZnMucHVzaChbMCwgcjFjcy5uQ29uc3RyYWludHMgKyBzLCBzLCAtMV0pO1xuICAgICAgICB9XG5cblxuICAgICAgICBhd2FpdCBzdGFydFdyaXRlU2VjdGlvbihmZFpLZXksIDQpO1xuXG4gICAgICAgIGNvbnN0IGJ1ZmZTZWN0aW9uID0gbmV3IEJpZ0J1ZmZlcihjb2Vmcy5sZW5ndGgqKDEyK2N1cnZlLkZyLm44KSArIDQpO1xuXG4gICAgICAgIGNvbnN0IGJ1ZmY0ID0gbmV3IFVpbnQ4QXJyYXkoNCk7XG4gICAgICAgIGNvbnN0IGJ1ZmY0ViA9IG5ldyBEYXRhVmlldyhidWZmNC5idWZmZXIpO1xuICAgICAgICBidWZmNFYuc2V0VWludDMyKDAsIGNvZWZzLmxlbmd0aCwgdHJ1ZSk7XG4gICAgICAgIGJ1ZmZTZWN0aW9uLnNldChidWZmNCk7XG4gICAgICAgIGxldCBjb2Vmc1BvcyA9IDQ7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxjb2Vmcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKChsb2dnZXIpJiYoaSUxMDAwMDAgPT0gMCkpIGxvZ2dlci5kZWJ1Zyhgd3JpdGluZyBjb2VmZnM6ICR7aX0vJHtjb2Vmcy5sZW5ndGh9YCk7XG4gICAgICAgICAgICB3cml0ZUNvZWYoY29lZnNbaV0pO1xuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgZmRaS2V5LndyaXRlKGJ1ZmZTZWN0aW9uKTtcbiAgICAgICAgYXdhaXQgZW5kV3JpdGVTZWN0aW9uKGZkWktleSk7XG5cbiAgICAgICAgZnVuY3Rpb24gd3JpdGVDb2VmKGMpIHtcbiAgICAgICAgICAgIGJ1ZmZDb2VmZlYuc2V0VWludDMyKDAsIGNbMF0sIHRydWUpO1xuICAgICAgICAgICAgYnVmZkNvZWZmVi5zZXRVaW50MzIoNCwgY1sxXSwgdHJ1ZSk7XG4gICAgICAgICAgICBidWZmQ29lZmZWLnNldFVpbnQzMig4LCBjWzJdLCB0cnVlKTtcbiAgICAgICAgICAgIGxldCBuO1xuICAgICAgICAgICAgaWYgKGNbM10+PTApIHtcbiAgICAgICAgICAgICAgICBuID0gY3VydmUuRnIuZnJvbVJwckxFKHNSMWNzLnNsaWNlKGNbM10sIGNbM10gKyBjdXJ2ZS5Gci5uOCksIDApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBuID0gY3VydmUuRnIuZnJvbVJwckxFKGJPbmUsIDApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgblIyID0gY3VydmUuRnIubXVsKG4sIFIycik7XG4gICAgICAgICAgICBjdXJ2ZS5Gci50b1JwckxFKGJ1ZmZDb2VmZiwgMTIsIG5SMik7XG4gICAgICAgICAgICBidWZmU2VjdGlvbi5zZXQoYnVmZkNvZWZmLCBjb2Vmc1Bvcyk7XG4gICAgICAgICAgICBjb2Vmc1BvcyArPSBidWZmQ29lZmYubGVuZ3RoO1xuICAgICAgICB9XG5cbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiBjb21wb3NlQW5kV3JpdGVQb2ludHMoaWRTZWN0aW9uLCBncm91cE5hbWUsIGFyciwgc2VjdGlvbk5hbWUpIHtcbiAgICAgICAgY29uc3QgQ0hVTktfU0laRT0gMTw8MTU7XG4gICAgICAgIGNvbnN0IEcgPSBjdXJ2ZVtncm91cE5hbWVdO1xuXG4gICAgICAgIGhhc2hVMzIoYXJyLmxlbmd0aCk7XG4gICAgICAgIGF3YWl0IHN0YXJ0V3JpdGVTZWN0aW9uKGZkWktleSwgaWRTZWN0aW9uKTtcblxuICAgICAgICBsZXQgb3BQcm9taXNlcyA9IFtdO1xuXG4gICAgICAgIGxldCBpPTA7XG4gICAgICAgIHdoaWxlIChpPGFyci5sZW5ndGgpIHtcblxuICAgICAgICAgICAgbGV0IHQ9MDtcbiAgICAgICAgICAgIHdoaWxlICgoaTxhcnIubGVuZ3RoKSYmKHQ8Y3VydmUudG0uY29uY3VycmVuY3kpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGxvZ2dlcikgIGxvZ2dlci5kZWJ1ZyhgV3JpdGluZyBwb2ludHMgc3RhcnQgJHtzZWN0aW9uTmFtZX06ICR7aX0vJHthcnIubGVuZ3RofWApO1xuICAgICAgICAgICAgICAgIGxldCBuID0gMTtcbiAgICAgICAgICAgICAgICBsZXQgblAgPSAoYXJyW2ldID8gYXJyW2ldLmxlbmd0aCA6IDApO1xuICAgICAgICAgICAgICAgIHdoaWxlICgoaSArIG4gPCBhcnIubGVuZ3RoKSAmJiAoblAgKyAoYXJyW2krbl0gPyBhcnJbaStuXS5sZW5ndGggOiAwKSA8IENIVU5LX1NJWkUpICYmIChuPENIVU5LX1NJWkUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5QICs9IChhcnJbaStuXSA/IGFycltpK25dLmxlbmd0aCA6IDApO1xuICAgICAgICAgICAgICAgICAgICBuICsrO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiYmVmb3JlIHNsaWNlOlwiKTtcbiAgICAgICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhtZW1Vc2FnZSgpKTtcbiAgICAgICAgICAgICAgICBjb25zdCBzdWJBcnIgPSBhcnIuc2xpY2UoaSwgaSArIG4pO1xuICAgICAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiYWZ0ZXIgc2xpY2U6XCIpO1xuICAgICAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKG1lbVVzYWdlKCkpO1xuICAgICAgICAgICAgICAgIGNvbnN0IF9pID0gaTtcbiAgICAgICAgICAgICAgICBvcFByb21pc2VzLnB1c2goY29tcG9zZUFuZFdyaXRlUG9pbnRzVGhyZWFkKGdyb3VwTmFtZSwgc3ViQXJyLCBsb2dnZXIsIHNlY3Rpb25OYW1lKS50aGVuKCAocikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAobG9nZ2VyKSAgbG9nZ2VyLmRlYnVnKGBXcml0aW5nIHBvaW50cyBlbmQgJHtzZWN0aW9uTmFtZX06ICR7X2l9LyR7YXJyLmxlbmd0aH1gKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHI7XG4gICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgIGkgKz0gbjtcbiAgICAgICAgICAgICAgICB0Kys7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IFByb21pc2UuYWxsKG9wUHJvbWlzZXMpO1xuXG4gICAgICAgICAgICBmb3IgKGxldCBrPTA7IGs8cmVzdWx0Lmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgZmRaS2V5LndyaXRlKHJlc3VsdFtrXVswXSk7XG4gICAgICAgICAgICAgICAgY29uc3QgYnVmZiA9IGF3YWl0IEcuYmF0Y2hMRU10b1UocmVzdWx0W2tdWzBdKTtcbiAgICAgICAgICAgICAgICBjc0hhc2hlci51cGRhdGUoYnVmZik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvcFByb21pc2VzID0gW107XG5cbiAgICAgICAgfVxuICAgICAgICBhd2FpdCBlbmRXcml0ZVNlY3Rpb24oZmRaS2V5KTtcblxuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIGNvbXBvc2VBbmRXcml0ZVBvaW50c1RocmVhZChncm91cE5hbWUsIGFyciwgbG9nZ2VyLCBzZWN0aW9uTmFtZSkge1xuICAgICAgICBjb25zdCBHID0gY3VydmVbZ3JvdXBOYW1lXTtcbiAgICAgICAgY29uc3Qgc0dpbiA9IEcuRi5uOCoyO1xuICAgICAgICBjb25zdCBzR21pZCA9IEcuRi5uOCozO1xuICAgICAgICBjb25zdCBzR291dCA9IEcuRi5uOCoyO1xuICAgICAgICBsZXQgZm5FeHAsIGZuTXVsdGlFeHAsIGZuQmF0Y2hUb0FmZmluZSwgZm5aZXJvO1xuICAgICAgICBpZiAoZ3JvdXBOYW1lID09IFwiRzFcIikge1xuICAgICAgICAgICAgZm5FeHAgPSBcImcxbV90aW1lc1NjYWxhckFmZmluZVwiO1xuICAgICAgICAgICAgZm5NdWx0aUV4cCA9IFwiZzFtX211bHRpZXhwQWZmaW5lXCI7XG4gICAgICAgICAgICBmbkJhdGNoVG9BZmZpbmUgPSBcImcxbV9iYXRjaFRvQWZmaW5lXCI7XG4gICAgICAgICAgICBmblplcm8gPSBcImcxbV96ZXJvXCI7XG4gICAgICAgIH0gZWxzZSBpZiAoZ3JvdXBOYW1lID09IFwiRzJcIikge1xuICAgICAgICAgICAgZm5FeHAgPSBcImcybV90aW1lc1NjYWxhckFmZmluZVwiO1xuICAgICAgICAgICAgZm5NdWx0aUV4cCA9IFwiZzJtX211bHRpZXhwQWZmaW5lXCI7XG4gICAgICAgICAgICBmbkJhdGNoVG9BZmZpbmUgPSBcImcybV9iYXRjaFRvQWZmaW5lXCI7XG4gICAgICAgICAgICBmblplcm8gPSBcImcybV96ZXJvXCI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIGdyb3VwXCIpO1xuICAgICAgICB9XG4gICAgICAgIGxldCBhY2MgPTA7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxhcnIubGVuZ3RoOyBpKyspIGFjYyArPSBhcnJbaV0gPyBhcnJbaV0ubGVuZ3RoIDogMDtcbiAgICAgICAgbGV0IGJCYXNlcywgYlNjYWxhcnM7XG4gICAgICAgIGlmIChhY2M+IDI8PDE0KSB7XG4gICAgICAgICAgICBiQmFzZXMgPSBuZXcgQmlnQnVmZmVyKGFjYypzR2luKTtcbiAgICAgICAgICAgIGJTY2FsYXJzID0gbmV3IEJpZ0J1ZmZlcihhY2MqY3VydmUuRnIubjgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYkJhc2VzID0gbmV3IFVpbnQ4QXJyYXkoYWNjKnNHaW4pO1xuICAgICAgICAgICAgYlNjYWxhcnMgPSBuZXcgVWludDhBcnJheShhY2MqY3VydmUuRnIubjgpO1xuICAgICAgICB9XG4gICAgICAgIGxldCBwQiA9MDtcbiAgICAgICAgbGV0IHBTID0wO1xuXG4gICAgICAgIGNvbnN0IHNCdWZmcyA9IFtcbiAgICAgICAgICAgIHNUYXVHMSxcbiAgICAgICAgICAgIHNUYXVHMixcbiAgICAgICAgICAgIHNBbHBoYVRhdUcxLFxuICAgICAgICAgICAgc0JldGFUYXVHMVxuICAgICAgICBdO1xuXG4gICAgICAgIGNvbnN0IGJPbmUgPSBuZXcgVWludDhBcnJheShjdXJ2ZS5Gci5uOCk7XG4gICAgICAgIGN1cnZlLkZyLnRvUnByTEUoYk9uZSwgMCwgY3VydmUuRnIuZSgxKSk7XG5cbiAgICAgICAgbGV0IG9mZnNldCA9IDA7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxhcnIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICghYXJyW2ldKSBjb250aW51ZTtcbiAgICAgICAgICAgIGZvciAobGV0IGo9MDsgajxhcnJbaV0ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoKGxvZ2dlcikmJihqKSYmKGolMTAwMDAgPT0gMCkpICBsb2dnZXIuZGVidWcoYENvbmZpZ3VyaW5nIGJpZyBhcnJheSAke3NlY3Rpb25OYW1lfTogJHtqfS8ke2FycltpXS5sZW5ndGh9YCk7XG4gICAgICAgICAgICAgICAgYkJhc2VzLnNldChcbiAgICAgICAgICAgICAgICAgICAgc0J1ZmZzW2FycltpXVtqXVswXV0uc2xpY2UoXG4gICAgICAgICAgICAgICAgICAgICAgICBhcnJbaV1bal1bMV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBhcnJbaV1bal1bMV0gKyBzR2luXG4gICAgICAgICAgICAgICAgICAgICksIG9mZnNldCpzR2luXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBpZiAoYXJyW2ldW2pdWzJdPj0wKSB7XG4gICAgICAgICAgICAgICAgICAgIGJTY2FsYXJzLnNldChcbiAgICAgICAgICAgICAgICAgICAgICAgIHNSMWNzLnNsaWNlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFycltpXVtqXVsyXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcnJbaV1bal1bMl0gKyBjdXJ2ZS5Gci5uOFxuICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldCpjdXJ2ZS5Gci5uOFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGJTY2FsYXJzLnNldChiT25lLCBvZmZzZXQqY3VydmUuRnIubjgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBvZmZzZXQgKys7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYXJyLmxlbmd0aD4xKSB7XG4gICAgICAgICAgICBjb25zdCB0YXNrID0gW107XG4gICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJBTExPQ1NFVFwiLCB2YXI6IDAsIGJ1ZmY6IGJCYXNlc30pO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQUxMT0NTRVRcIiwgdmFyOiAxLCBidWZmOiBiU2NhbGFyc30pO1xuICAgICAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQUxMT0NcIiwgdmFyOiAyLCBsZW46IGFyci5sZW5ndGgqc0dtaWR9KTtcbiAgICAgICAgICAgIHBCID0gMDtcbiAgICAgICAgICAgIHBTID0gMDtcbiAgICAgICAgICAgIGxldCBwRCA9MDtcbiAgICAgICAgICAgIGZvciAobGV0IGk9MDsgaTxhcnIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoIWFycltpXSkge1xuICAgICAgICAgICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJDQUxMXCIsIGZuTmFtZTogZm5aZXJvLCBwYXJhbXM6IFtcbiAgICAgICAgICAgICAgICAgICAgICAgIHt2YXI6IDIsIG9mZnNldDogcER9XG4gICAgICAgICAgICAgICAgICAgIF19KTtcbiAgICAgICAgICAgICAgICAgICAgcEQgKz0gc0dtaWQ7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoYXJyW2ldLmxlbmd0aCA9PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkNBTExcIiwgZm5OYW1lOiBmbkV4cCwgcGFyYW1zOiBbXG4gICAgICAgICAgICAgICAgICAgICAgICB7dmFyOiAwLCBvZmZzZXQ6IHBCfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHt2YXI6IDEsIG9mZnNldDogcFN9LFxuICAgICAgICAgICAgICAgICAgICAgICAge3ZhbDogY3VydmUuRnIubjh9LFxuICAgICAgICAgICAgICAgICAgICAgICAge3ZhcjogMiwgb2Zmc2V0OiBwRH1cbiAgICAgICAgICAgICAgICAgICAgXX0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkNBTExcIiwgZm5OYW1lOiBmbk11bHRpRXhwLCBwYXJhbXM6IFtcbiAgICAgICAgICAgICAgICAgICAgICAgIHt2YXI6IDAsIG9mZnNldDogcEJ9LFxuICAgICAgICAgICAgICAgICAgICAgICAge3ZhcjogMSwgb2Zmc2V0OiBwU30sXG4gICAgICAgICAgICAgICAgICAgICAgICB7dmFsOiBjdXJ2ZS5Gci5uOH0sXG4gICAgICAgICAgICAgICAgICAgICAgICB7dmFsOiBhcnJbaV0ubGVuZ3RofSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHt2YXI6IDIsIG9mZnNldDogcER9XG4gICAgICAgICAgICAgICAgICAgIF19KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcEIgKz0gc0dpbiphcnJbaV0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHBTICs9IGN1cnZlLkZyLm44KmFycltpXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgcEQgKz0gc0dtaWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJDQUxMXCIsIGZuTmFtZTogZm5CYXRjaFRvQWZmaW5lLCBwYXJhbXM6IFtcbiAgICAgICAgICAgICAgICB7dmFyOiAyfSxcbiAgICAgICAgICAgICAgICB7dmFsOiBhcnIubGVuZ3RofSxcbiAgICAgICAgICAgICAgICB7dmFyOiAyfSxcbiAgICAgICAgICAgIF19KTtcbiAgICAgICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkdFVFwiLCBvdXQ6IDAsIHZhcjogMiwgbGVuOiBhcnIubGVuZ3RoKnNHb3V0fSk7XG5cbiAgICAgICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGN1cnZlLnRtLnF1ZXVlQWN0aW9uKHRhc2spO1xuICAgICAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxldCByZXMgPSBhd2FpdCBHLm11bHRpRXhwQWZmaW5lKGJCYXNlcywgYlNjYWxhcnMsIGxvZ2dlciwgc2VjdGlvbk5hbWUpO1xuICAgICAgICAgICAgcmVzID0gWyBHLnRvQWZmaW5lKHJlcykgXTtcbiAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIGFzeW5jIGZ1bmN0aW9uIGhhc2hIUG9pbnRzKCkge1xuICAgICAgICBjb25zdCBDSFVOS19TSVpFID0gMTw8MTQ7XG5cbiAgICAgICAgaGFzaFUzMihkb21haW5TaXplLTEpO1xuXG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxkb21haW5TaXplLTE7IGkrPSBDSFVOS19TSVpFKSB7XG4gICAgICAgICAgICBpZiAobG9nZ2VyKSAgbG9nZ2VyLmRlYnVnKGBIYXNoaW5nSFBvaW50czogJHtpfS8ke2RvbWFpblNpemV9YCk7XG4gICAgICAgICAgICBjb25zdCBuID0gTWF0aC5taW4oZG9tYWluU2l6ZS0xLCBDSFVOS19TSVpFKTtcbiAgICAgICAgICAgIGF3YWl0IGhhc2hIUG9pbnRzQ2h1bmsoaSwgbik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiBoYXNoSFBvaW50c0NodW5rKG9mZnNldCwgblBvaW50cykge1xuICAgICAgICBjb25zdCBidWZmMSA9IGF3YWl0IGZkUFRhdS5yZWFkKG5Qb2ludHMgKnNHMSwgc2VjdGlvbnNQVGF1WzJdWzBdLnAgKyAob2Zmc2V0ICsgZG9tYWluU2l6ZSkqc0cxKTtcbiAgICAgICAgY29uc3QgYnVmZjIgPSBhd2FpdCBmZFBUYXUucmVhZChuUG9pbnRzICpzRzEsIHNlY3Rpb25zUFRhdVsyXVswXS5wICsgb2Zmc2V0KnNHMSk7XG4gICAgICAgIGNvbnN0IGNvbmN1cnJlbmN5PSBjdXJ2ZS50bS5jb25jdXJyZW5jeTtcbiAgICAgICAgY29uc3QgblBvaW50c1BlclRocmVhZCA9IE1hdGguZmxvb3IoblBvaW50cyAvIGNvbmN1cnJlbmN5KTtcbiAgICAgICAgY29uc3Qgb3BQcm9taXNlcyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8Y29uY3VycmVuY3k7IGkrKykge1xuICAgICAgICAgICAgbGV0IG47XG4gICAgICAgICAgICBpZiAoaTwgY29uY3VycmVuY3ktMSkge1xuICAgICAgICAgICAgICAgIG4gPSBuUG9pbnRzUGVyVGhyZWFkO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBuID0gblBvaW50cyAtIGkqblBvaW50c1BlclRocmVhZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChuPT0wKSBjb250aW51ZTtcblxuICAgICAgICAgICAgY29uc3Qgc3ViQnVmZjEgPSBidWZmMS5zbGljZShpKm5Qb2ludHNQZXJUaHJlYWQqc0cxLCAoaSpuUG9pbnRzUGVyVGhyZWFkK24pKnNHMSk7XG4gICAgICAgICAgICBjb25zdCBzdWJCdWZmMiA9IGJ1ZmYyLnNsaWNlKGkqblBvaW50c1BlclRocmVhZCpzRzEsIChpKm5Qb2ludHNQZXJUaHJlYWQrbikqc0cxKTtcbiAgICAgICAgICAgIG9wUHJvbWlzZXMucHVzaChoYXNoSFBvaW50c1RocmVhZChzdWJCdWZmMSwgc3ViQnVmZjIpKTtcbiAgICAgICAgfVxuXG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgUHJvbWlzZS5hbGwob3BQcm9taXNlcyk7XG5cbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPHJlc3VsdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY3NIYXNoZXIudXBkYXRlKHJlc3VsdFtpXVswXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiBoYXNoSFBvaW50c1RocmVhZChidWZmMSwgYnVmZjIpIHtcbiAgICAgICAgY29uc3QgblBvaW50cyA9IGJ1ZmYxLmJ5dGVMZW5ndGgvc0cxO1xuICAgICAgICBjb25zdCBzR21pZCA9IGN1cnZlLkcxLkYubjgqMztcbiAgICAgICAgY29uc3QgdGFzayA9IFtdO1xuICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJBTExPQ1NFVFwiLCB2YXI6IDAsIGJ1ZmY6IGJ1ZmYxfSk7XG4gICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkFMTE9DU0VUXCIsIHZhcjogMSwgYnVmZjogYnVmZjJ9KTtcbiAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQUxMT0NcIiwgdmFyOiAyLCBsZW46IG5Qb2ludHMqc0dtaWR9KTtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPG5Qb2ludHM7IGkrKykge1xuICAgICAgICAgICAgdGFzay5wdXNoKHtcbiAgICAgICAgICAgICAgICBjbWQ6IFwiQ0FMTFwiLFxuICAgICAgICAgICAgICAgIGZuTmFtZTogXCJnMW1fc3ViQWZmaW5lXCIsXG4gICAgICAgICAgICAgICAgcGFyYW1zOiBbXG4gICAgICAgICAgICAgICAgICAgIHt2YXI6IDAsIG9mZnNldDogaSpzRzF9LFxuICAgICAgICAgICAgICAgICAgICB7dmFyOiAxLCBvZmZzZXQ6IGkqc0cxfSxcbiAgICAgICAgICAgICAgICAgICAge3ZhcjogMiwgb2Zmc2V0OiBpKnNHbWlkfSxcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJDQUxMXCIsIGZuTmFtZTogXCJnMW1fYmF0Y2hUb0FmZmluZVwiLCBwYXJhbXM6IFtcbiAgICAgICAgICAgIHt2YXI6IDJ9LFxuICAgICAgICAgICAge3ZhbDogblBvaW50c30sXG4gICAgICAgICAgICB7dmFyOiAyfSxcbiAgICAgICAgXX0pO1xuICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJDQUxMXCIsIGZuTmFtZTogXCJnMW1fYmF0Y2hMRU10b1VcIiwgcGFyYW1zOiBbXG4gICAgICAgICAgICB7dmFyOiAyfSxcbiAgICAgICAgICAgIHt2YWw6IG5Qb2ludHN9LFxuICAgICAgICAgICAge3ZhcjogMn0sXG4gICAgICAgIF19KTtcbiAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiR0VUXCIsIG91dDogMCwgdmFyOiAyLCBsZW46IG5Qb2ludHMqc0cxfSk7XG5cbiAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgY3VydmUudG0ucXVldWVBY3Rpb24odGFzayk7XG5cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBoYXNoVTMyKG4pIHtcbiAgICAgICAgY29uc3QgYnVmZiA9IG5ldyBVaW50OEFycmF5KDQpO1xuICAgICAgICBjb25zdCBidWZmViA9IG5ldyBEYXRhVmlldyhidWZmLmJ1ZmZlciwgYnVmZi5ieXRlT2Zmc2V0LCBidWZmLmJ5dGVMZW5ndGgpO1xuICAgICAgICBidWZmVi5zZXRVaW50MzIoMCwgbiwgZmFsc2UpO1xuICAgICAgICBjc0hhc2hlci51cGRhdGUoYnVmZik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWVtVXNhZ2UoKSB7XG4gICAgICAgIGxldCBtID0gcHJvY2Vzcy5tZW1vcnlVc2FnZSgpO1xuICAgICAgICBmb3IgKGNvbnN0IGkgaW4gbSkge1xuICAgICAgICAgICAgbVtpXSA9IE1hdGgucm91bmQobVtpXSAvICgxMDI0KjEwMjQpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbTtcbiAgICB9XG5cbn1cblxuXG4iLCJcbmltcG9ydCAqIGFzIGJpbkZpbGVVdGlscyBmcm9tIFwiQGlkZW4zL2JpbmZpbGV1dGlsc1wiO1xuaW1wb3J0ICogYXMgemtleVV0aWxzIGZyb20gXCIuL3prZXlfdXRpbHMuanNcIjtcbmltcG9ydCAqIGFzIGZhc3RGaWxlIGZyb20gXCJmYXN0ZmlsZVwiO1xuaW1wb3J0IHsgZ2V0Q3VydmVGcm9tUSBhcyBnZXRDdXJ2ZSB9IGZyb20gXCIuL2N1cnZlcy5qc1wiO1xuXG5leHBvcnQgZGVmYXVsdCBhc3luYyBmdW5jdGlvbiBwaGFzZTJleHBvcnRNUENQYXJhbXMoemtleU5hbWUsIG1wY3BhcmFtc05hbWUsIGxvZ2dlcikge1xuXG4gICAgY29uc3Qge2ZkOiBmZFpLZXksIHNlY3Rpb25zOiBzZWN0aW9uc1pLZXl9ID0gYXdhaXQgYmluRmlsZVV0aWxzLnJlYWRCaW5GaWxlKHprZXlOYW1lLCBcInprZXlcIiwgMik7XG4gICAgY29uc3QgemtleSA9IGF3YWl0IHprZXlVdGlscy5yZWFkSGVhZGVyKGZkWktleSwgc2VjdGlvbnNaS2V5KTtcbiAgICBpZiAoemtleS5wcm90b2NvbCAhPSBcImdyb3RoMTZcIikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ6a2V5IGZpbGUgaXMgbm90IGdyb3RoMTZcIik7XG4gICAgfVxuXG4gICAgY29uc3QgY3VydmUgPSBhd2FpdCBnZXRDdXJ2ZSh6a2V5LnEpO1xuICAgIGNvbnN0IHNHMSA9IGN1cnZlLkcxLkYubjgqMjtcbiAgICBjb25zdCBzRzIgPSBjdXJ2ZS5HMi5GLm44KjI7XG5cbiAgICBjb25zdCBtcGNQYXJhbXMgPSBhd2FpdCB6a2V5VXRpbHMucmVhZE1QQ1BhcmFtcyhmZFpLZXksIGN1cnZlLCBzZWN0aW9uc1pLZXkpO1xuXG4gICAgY29uc3QgZmRNUENQYXJhbXMgPSBhd2FpdCBmYXN0RmlsZS5jcmVhdGVPdmVycmlkZShtcGNwYXJhbXNOYW1lKTtcblxuICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAgIC8vIFZlcmlmaWNhdGlvbiBLZXkgU2VjdGlvblxuICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAgIGF3YWl0IHdyaXRlRzEoemtleS52a19hbHBoYV8xKTtcbiAgICBhd2FpdCB3cml0ZUcxKHprZXkudmtfYmV0YV8xKTtcbiAgICBhd2FpdCB3cml0ZUcyKHprZXkudmtfYmV0YV8yKTtcbiAgICBhd2FpdCB3cml0ZUcyKHprZXkudmtfZ2FtbWFfMik7XG4gICAgYXdhaXQgd3JpdGVHMSh6a2V5LnZrX2RlbHRhXzEpO1xuICAgIGF3YWl0IHdyaXRlRzIoemtleS52a19kZWx0YV8yKTtcblxuICAgIC8vIElDXG4gICAgbGV0IGJ1ZmZCYXNlc0lDO1xuICAgIGJ1ZmZCYXNlc0lDID0gYXdhaXQgYmluRmlsZVV0aWxzLnJlYWRTZWN0aW9uKGZkWktleSwgc2VjdGlvbnNaS2V5LCAzKTtcbiAgICBidWZmQmFzZXNJQyA9IGF3YWl0IGN1cnZlLkcxLmJhdGNoTEVNdG9VKGJ1ZmZCYXNlc0lDKTtcblxuICAgIGF3YWl0IHdyaXRlUG9pbnRBcnJheShcIkcxXCIsIGJ1ZmZCYXNlc0lDKTtcblxuICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAgIC8vIGggU2VjdGlvblxuICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAgIGNvbnN0IGJ1ZmZCYXNlc0hfTG9kZCA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkU2VjdGlvbihmZFpLZXksIHNlY3Rpb25zWktleSwgOSk7XG5cbiAgICBsZXQgYnVmZkJhc2VzSF9UYXU7XG4gICAgYnVmZkJhc2VzSF9UYXUgPSBhd2FpdCBjdXJ2ZS5HMS5mZnQoYnVmZkJhc2VzSF9Mb2RkLCBcImFmZmluZVwiLCBcImphY29iaWFuXCIsIGxvZ2dlcik7XG4gICAgYnVmZkJhc2VzSF9UYXUgPSBhd2FpdCBjdXJ2ZS5HMS5iYXRjaEFwcGx5S2V5KGJ1ZmZCYXNlc0hfVGF1LCBjdXJ2ZS5Gci5uZWcoY3VydmUuRnIuZSgyKSksIGN1cnZlLkZyLndbemtleS5wb3dlcisxXSwgXCJqYWNvYmlhblwiLCBcImFmZmluZVwiLCBsb2dnZXIpO1xuXG4gICAgLy8gUmVtb3ZlIGxhc3QgZWxlbWVudC4gIChUaGUgZGVncmVlIG9mIEggd2lsbCBiZSBhbHdheXMgbS0yKVxuICAgIGJ1ZmZCYXNlc0hfVGF1ID0gYnVmZkJhc2VzSF9UYXUuc2xpY2UoMCwgYnVmZkJhc2VzSF9UYXUuYnl0ZUxlbmd0aCAtIHNHMSk7XG4gICAgYnVmZkJhc2VzSF9UYXUgPSBhd2FpdCBjdXJ2ZS5HMS5iYXRjaExFTXRvVShidWZmQmFzZXNIX1RhdSk7XG4gICAgYXdhaXQgd3JpdGVQb2ludEFycmF5KFwiRzFcIiwgYnVmZkJhc2VzSF9UYXUpO1xuXG4gICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gICAgLy8gTCBzZWN0aW9uXG4gICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gICAgbGV0IGJ1ZmZCYXNlc0M7XG4gICAgYnVmZkJhc2VzQyA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkU2VjdGlvbihmZFpLZXksIHNlY3Rpb25zWktleSwgOCk7XG4gICAgYnVmZkJhc2VzQyA9IGF3YWl0IGN1cnZlLkcxLmJhdGNoTEVNdG9VKGJ1ZmZCYXNlc0MpO1xuICAgIGF3YWl0IHdyaXRlUG9pbnRBcnJheShcIkcxXCIsIGJ1ZmZCYXNlc0MpO1xuXG4gICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gICAgLy8gQSBTZWN0aW9uIChDIHNlY3Rpb24pXG4gICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gICAgbGV0IGJ1ZmZCYXNlc0E7XG4gICAgYnVmZkJhc2VzQSA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkU2VjdGlvbihmZFpLZXksIHNlY3Rpb25zWktleSwgNSk7XG4gICAgYnVmZkJhc2VzQSA9IGF3YWl0IGN1cnZlLkcxLmJhdGNoTEVNdG9VKGJ1ZmZCYXNlc0EpO1xuICAgIGF3YWl0IHdyaXRlUG9pbnRBcnJheShcIkcxXCIsIGJ1ZmZCYXNlc0EpO1xuXG4gICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gICAgLy8gQjEgU2VjdGlvblxuICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAgIGxldCBidWZmQmFzZXNCMTtcbiAgICBidWZmQmFzZXNCMSA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkU2VjdGlvbihmZFpLZXksIHNlY3Rpb25zWktleSwgNik7XG4gICAgYnVmZkJhc2VzQjEgPSBhd2FpdCBjdXJ2ZS5HMS5iYXRjaExFTXRvVShidWZmQmFzZXNCMSk7XG4gICAgYXdhaXQgd3JpdGVQb2ludEFycmF5KFwiRzFcIiwgYnVmZkJhc2VzQjEpO1xuXG4gICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gICAgLy8gQjIgU2VjdGlvblxuICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAgIGxldCBidWZmQmFzZXNCMjtcbiAgICBidWZmQmFzZXNCMiA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkU2VjdGlvbihmZFpLZXksIHNlY3Rpb25zWktleSwgNyk7XG4gICAgYnVmZkJhc2VzQjIgPSBhd2FpdCBjdXJ2ZS5HMi5iYXRjaExFTXRvVShidWZmQmFzZXNCMik7XG4gICAgYXdhaXQgd3JpdGVQb2ludEFycmF5KFwiRzJcIiwgYnVmZkJhc2VzQjIpO1xuXG4gICAgYXdhaXQgZmRNUENQYXJhbXMud3JpdGUobXBjUGFyYW1zLmNzSGFzaCk7XG4gICAgYXdhaXQgd3JpdGVVMzIobXBjUGFyYW1zLmNvbnRyaWJ1dGlvbnMubGVuZ3RoKTtcblxuICAgIGZvciAobGV0IGk9MDsgaTxtcGNQYXJhbXMuY29udHJpYnV0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBjID0gbXBjUGFyYW1zLmNvbnRyaWJ1dGlvbnNbaV07XG4gICAgICAgIGF3YWl0IHdyaXRlRzEoYy5kZWx0YUFmdGVyKTtcbiAgICAgICAgYXdhaXQgd3JpdGVHMShjLmRlbHRhLmcxX3MpO1xuICAgICAgICBhd2FpdCB3cml0ZUcxKGMuZGVsdGEuZzFfc3gpO1xuICAgICAgICBhd2FpdCB3cml0ZUcyKGMuZGVsdGEuZzJfc3B4KTtcbiAgICAgICAgYXdhaXQgZmRNUENQYXJhbXMud3JpdGUoYy50cmFuc2NyaXB0KTtcbiAgICB9XG5cbiAgICBhd2FpdCBmZFpLZXkuY2xvc2UoKTtcbiAgICBhd2FpdCBmZE1QQ1BhcmFtcy5jbG9zZSgpO1xuXG4gICAgYXN5bmMgZnVuY3Rpb24gd3JpdGVHMShQKSB7XG4gICAgICAgIGNvbnN0IGJ1ZmYgPSBuZXcgVWludDhBcnJheShzRzEpO1xuICAgICAgICBjdXJ2ZS5HMS50b1JwclVuY29tcHJlc3NlZChidWZmLCAwLCBQKTtcbiAgICAgICAgYXdhaXQgZmRNUENQYXJhbXMud3JpdGUoYnVmZik7XG4gICAgfVxuXG4gICAgYXN5bmMgZnVuY3Rpb24gd3JpdGVHMihQKSB7XG4gICAgICAgIGNvbnN0IGJ1ZmYgPSBuZXcgVWludDhBcnJheShzRzIpO1xuICAgICAgICBjdXJ2ZS5HMi50b1JwclVuY29tcHJlc3NlZChidWZmLCAwLCBQKTtcbiAgICAgICAgYXdhaXQgZmRNUENQYXJhbXMud3JpdGUoYnVmZik7XG4gICAgfVxuXG4gICAgYXN5bmMgZnVuY3Rpb24gd3JpdGVQb2ludEFycmF5KGdyb3VwTmFtZSwgYnVmZikge1xuICAgICAgICBsZXQgc0c7XG4gICAgICAgIGlmIChncm91cE5hbWUgPT0gXCJHMVwiKSB7XG4gICAgICAgICAgICBzRyA9IHNHMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNHID0gc0cyO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYnVmZlNpemUgPSBuZXcgVWludDhBcnJheSg0KTtcbiAgICAgICAgY29uc3QgYnVmZlNpemVWID0gbmV3IERhdGFWaWV3KGJ1ZmZTaXplLmJ1ZmZlciwgYnVmZlNpemUuYnl0ZU9mZnNldCwgYnVmZlNpemUuYnl0ZUxlbmd0aCk7XG4gICAgICAgIGJ1ZmZTaXplVi5zZXRVaW50MzIoMCwgYnVmZi5ieXRlTGVuZ3RoIC8gc0csIGZhbHNlKTtcblxuICAgICAgICBhd2FpdCBmZE1QQ1BhcmFtcy53cml0ZShidWZmU2l6ZSk7XG4gICAgICAgIGF3YWl0IGZkTVBDUGFyYW1zLndyaXRlKGJ1ZmYpO1xuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHdyaXRlVTMyKG4pIHtcbiAgICAgICAgY29uc3QgYnVmZlNpemUgPSBuZXcgVWludDhBcnJheSg0KTtcbiAgICAgICAgY29uc3QgYnVmZlNpemVWID0gbmV3IERhdGFWaWV3KGJ1ZmZTaXplLmJ1ZmZlciwgYnVmZlNpemUuYnl0ZU9mZnNldCwgYnVmZlNpemUuYnl0ZUxlbmd0aCk7XG4gICAgICAgIGJ1ZmZTaXplVi5zZXRVaW50MzIoMCwgbiwgZmFsc2UpO1xuXG4gICAgICAgIGF3YWl0IGZkTVBDUGFyYW1zLndyaXRlKGJ1ZmZTaXplKTtcbiAgICB9XG5cblxuXG59XG4iLCIvKlxuICAgIENvcHlyaWdodCAyMDE4IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygc25hcmtKUy5cblxuICAgIHNuYXJrSlMgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gICAgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAgICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICAgIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICBzbmFya0pTIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHNuYXJrSlMuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG5pbXBvcnQgKiBhcyB6a2V5VXRpbHMgZnJvbSBcIi4vemtleV91dGlscy5qc1wiO1xuaW1wb3J0ICogYXMgYmluRmlsZVV0aWxzIGZyb20gXCJAaWRlbjMvYmluZmlsZXV0aWxzXCI7XG5pbXBvcnQgKiBhcyBmYXN0RmlsZSBmcm9tIFwiZmFzdGZpbGVcIjtcbmltcG9ydCB7IGdldEN1cnZlRnJvbVEgYXMgZ2V0Q3VydmUgfSBmcm9tIFwiLi9jdXJ2ZXMuanNcIjtcbmltcG9ydCAqIGFzIG1pc2MgZnJvbSBcIi4vbWlzYy5qc1wiO1xuXG5leHBvcnQgZGVmYXVsdCBhc3luYyBmdW5jdGlvbiBwaGFzZTJpbXBvcnRNUENQYXJhbXMoemtleU5hbWVPbGQsIG1wY3BhcmFtc05hbWUsIHprZXlOYW1lTmV3LCBuYW1lLCBsb2dnZXIpIHtcblxuICAgIGNvbnN0IHtmZDogZmRaS2V5T2xkLCBzZWN0aW9uczogc2VjdGlvbnNaS2V5T2xkfSA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkQmluRmlsZSh6a2V5TmFtZU9sZCwgXCJ6a2V5XCIsIDIpO1xuICAgIGNvbnN0IHprZXlIZWFkZXIgPSBhd2FpdCB6a2V5VXRpbHMucmVhZEhlYWRlcihmZFpLZXlPbGQsIHNlY3Rpb25zWktleU9sZCwgZmFsc2UpO1xuICAgIGlmICh6a2V5SGVhZGVyLnByb3RvY29sICE9IFwiZ3JvdGgxNlwiKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcInprZXkgZmlsZSBpcyBub3QgZ3JvdGgxNlwiKTtcbiAgICB9XG5cbiAgICBjb25zdCBjdXJ2ZSA9IGF3YWl0IGdldEN1cnZlKHprZXlIZWFkZXIucSk7XG4gICAgY29uc3Qgc0cxID0gY3VydmUuRzEuRi5uOCoyO1xuICAgIGNvbnN0IHNHMiA9IGN1cnZlLkcyLkYubjgqMjtcblxuICAgIGNvbnN0IG9sZE1QQ1BhcmFtcyA9IGF3YWl0IHprZXlVdGlscy5yZWFkTVBDUGFyYW1zKGZkWktleU9sZCwgY3VydmUsIHNlY3Rpb25zWktleU9sZCk7XG4gICAgY29uc3QgbmV3TVBDUGFyYW1zID0ge307XG5cbiAgICBjb25zdCBmZE1QQ1BhcmFtcyA9IGF3YWl0IGZhc3RGaWxlLnJlYWRFeGlzdGluZyhtcGNwYXJhbXNOYW1lKTtcblxuICAgIGZkTVBDUGFyYW1zLnBvcyA9XG4gICAgICAgIHNHMSozICsgc0cyKjMgKyAgICAgICAgICAgICAgICAgICAgIC8vIHZLZXlcbiAgICAgICAgOCArIHNHMSp6a2V5SGVhZGVyLm5WYXJzICsgICAgICAgICAgICAgIC8vIElDICsgQ1xuICAgICAgICA0ICsgc0cxKih6a2V5SGVhZGVyLmRvbWFpblNpemUtMSkgKyAgICAgLy8gSFxuICAgICAgICA0ICsgc0cxKnprZXlIZWFkZXIublZhcnMgKyAgICAgICAgICAgICAgLy8gQVxuICAgICAgICA0ICsgc0cxKnprZXlIZWFkZXIublZhcnMgKyAgICAgICAgICAgICAgLy8gQjFcbiAgICAgICAgNCArIHNHMip6a2V5SGVhZGVyLm5WYXJzOyAgICAgICAgICAgICAgIC8vIEIyXG5cbiAgICAvLyBjc0hhc2hcbiAgICBuZXdNUENQYXJhbXMuY3NIYXNoID0gIGF3YWl0IGZkTVBDUGFyYW1zLnJlYWQoNjQpO1xuXG4gICAgY29uc3QgbkNvbnRyaWJ1dGlvbnMgPSBhd2FpdCBmZE1QQ1BhcmFtcy5yZWFkVUJFMzIoKTtcbiAgICBuZXdNUENQYXJhbXMuY29udHJpYnV0aW9ucyA9IFtdO1xuICAgIGZvciAobGV0IGk9MDsgaTxuQ29udHJpYnV0aW9uczsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGMgPSB7IGRlbHRhOnt9IH07XG4gICAgICAgIGMuZGVsdGFBZnRlciA9IGF3YWl0IHJlYWRHMShmZE1QQ1BhcmFtcyk7XG4gICAgICAgIGMuZGVsdGEuZzFfcyA9IGF3YWl0IHJlYWRHMShmZE1QQ1BhcmFtcyk7XG4gICAgICAgIGMuZGVsdGEuZzFfc3ggPSBhd2FpdCByZWFkRzEoZmRNUENQYXJhbXMpO1xuICAgICAgICBjLmRlbHRhLmcyX3NweCA9IGF3YWl0IHJlYWRHMihmZE1QQ1BhcmFtcyk7XG4gICAgICAgIGMudHJhbnNjcmlwdCA9IGF3YWl0IGZkTVBDUGFyYW1zLnJlYWQoNjQpO1xuICAgICAgICBpZiAoaTxvbGRNUENQYXJhbXMuY29udHJpYnV0aW9ucy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGMudHlwZSA9IG9sZE1QQ1BhcmFtcy5jb250cmlidXRpb25zW2ldLnR5cGU7XG4gICAgICAgICAgICBpZiAoYy50eXBlPT0xKSB7XG4gICAgICAgICAgICAgICAgYy5iZWFjb25IYXNoID0gb2xkTVBDUGFyYW1zLmNvbnRyaWJ1dGlvbnNbaV0uYmVhY29uSGFzaDtcbiAgICAgICAgICAgICAgICBjLm51bUl0ZXJhdGlvbnNFeHAgPSBvbGRNUENQYXJhbXMuY29udHJpYnV0aW9uc1tpXS5udW1JdGVyYXRpb25zRXhwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9sZE1QQ1BhcmFtcy5jb250cmlidXRpb25zW2ldLm5hbWUpIHtcbiAgICAgICAgICAgICAgICBjLm5hbWUgPSBvbGRNUENQYXJhbXMuY29udHJpYnV0aW9uc1tpXS5uYW1lO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIG5ld01QQ1BhcmFtcy5jb250cmlidXRpb25zLnB1c2goYyk7XG4gICAgfVxuXG4gICAgaWYgKCFtaXNjLmhhc2hJc0VxdWFsKG5ld01QQ1BhcmFtcy5jc0hhc2gsIG9sZE1QQ1BhcmFtcy5jc0hhc2gpKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihcIkhhc2ggb2YgdGhlIG9yaWdpbmFsIGNpcmN1aXQgZG9lcyBub3QgbWF0Y2ggd2l0aCB0aGUgTVBDIG9uZVwiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmIChvbGRNUENQYXJhbXMuY29udHJpYnV0aW9ucy5sZW5ndGggPiBuZXdNUENQYXJhbXMuY29udHJpYnV0aW9ucy5sZW5ndGgpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiVGhlIGltcG9lcnRlZCBmaWxlIGRvZXMgbm90IGluY2x1ZGUgbmV3IGNvbnRyaWJ1dGlvbnNcIik7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBpPTA7IGk8b2xkTVBDUGFyYW1zLmNvbnRyaWJ1dGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKCFjb250cmlidXRpb25Jc0VxdWFsKG9sZE1QQ1BhcmFtcy5jb250cmlidXRpb25zW2ldLCBuZXdNUENQYXJhbXMuY29udHJpYnV0aW9uc1tpXSkpIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihgUHJldmlvdXMgY29udHJpYnV0aW9uICR7aX0gZG9lcyBub3QgbWF0Y2hgKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLy8gU2V0IHRoZSBzYW1lIG5hbWUgdG8gYWxsIG5ldyBjb250cmlidXRpb25zXG4gICAgaWYgKG5hbWUpIHtcbiAgICAgICAgZm9yIChsZXQgaT1vbGRNUENQYXJhbXMuY29udHJpYnV0aW9ucy5sZW5ndGg7IGk8bmV3TVBDUGFyYW1zLmNvbnRyaWJ1dGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIG5ld01QQ1BhcmFtcy5jb250cmlidXRpb25zW2ldLm5hbWUgPSBuYW1lO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgZmRaS2V5TmV3ID0gYXdhaXQgYmluRmlsZVV0aWxzLmNyZWF0ZUJpbkZpbGUoemtleU5hbWVOZXcsIFwiemtleVwiLCAxLCAxMCk7XG4gICAgZmRNUENQYXJhbXMucG9zID0gMDtcblxuICAgIC8vIEhlYWRlclxuICAgIGZkTVBDUGFyYW1zLnBvcyArPSBzRzE7ICAvLyBpZ25vcmUgYWxwaGExIChrZWVwIG9yaWdpbmFsKVxuICAgIGZkTVBDUGFyYW1zLnBvcyArPSBzRzE7ICAvLyBpZ25vcmUgYmV0YTFcbiAgICBmZE1QQ1BhcmFtcy5wb3MgKz0gc0cyOyAgLy8gaWdub3JlIGJldGEyXG4gICAgZmRNUENQYXJhbXMucG9zICs9IHNHMjsgIC8vIGlnbm9yZSBnYW1tYTJcbiAgICB6a2V5SGVhZGVyLnZrX2RlbHRhXzEgPSBhd2FpdCByZWFkRzEoZmRNUENQYXJhbXMpO1xuICAgIHprZXlIZWFkZXIudmtfZGVsdGFfMiA9IGF3YWl0IHJlYWRHMihmZE1QQ1BhcmFtcyk7XG4gICAgYXdhaXQgemtleVV0aWxzLndyaXRlSGVhZGVyKGZkWktleU5ldywgemtleUhlYWRlcik7XG5cbiAgICAvLyBJQyAoS2VlcCBvcmlnaW5hbClcbiAgICBjb25zdCBuSUMgPSBhd2FpdCBmZE1QQ1BhcmFtcy5yZWFkVUJFMzIoKTtcbiAgICBpZiAobklDICE9IHprZXlIZWFkZXIublB1YmxpYyArMSkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJJbnZhbGlkIG51bWJlciBvZiBwb2ludHMgaW4gSUNcIik7XG4gICAgICAgIGF3YWl0IGZkWktleU5ldy5kaXNjYXJkKCk7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgZmRNUENQYXJhbXMucG9zICs9IHNHMSooemtleUhlYWRlci5uUHVibGljKzEpO1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5jb3B5U2VjdGlvbihmZFpLZXlPbGQsIHNlY3Rpb25zWktleU9sZCwgZmRaS2V5TmV3LCAzKTtcblxuICAgIC8vIENvZWZmcyAoS2VlcCBvcmlnaW5hbClcbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuY29weVNlY3Rpb24oZmRaS2V5T2xkLCBzZWN0aW9uc1pLZXlPbGQsIGZkWktleU5ldywgNCk7XG5cbiAgICAvLyBIIFNlY3Rpb25cbiAgICBjb25zdCBuSCA9IGF3YWl0IGZkTVBDUGFyYW1zLnJlYWRVQkUzMigpO1xuICAgIGlmIChuSCAhPSB6a2V5SGVhZGVyLmRvbWFpblNpemUtMSkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJJbnZhbGlkIG51bWJlciBvZiBwb2ludHMgaW4gSFwiKTtcbiAgICAgICAgYXdhaXQgZmRaS2V5TmV3LmRpc2NhcmQoKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBsZXQgYnVmZkg7XG4gICAgY29uc3QgYnVmZlRhdVUgPSBhd2FpdCBmZE1QQ1BhcmFtcy5yZWFkKHNHMSooemtleUhlYWRlci5kb21haW5TaXplLTEpKTtcbiAgICBjb25zdCBidWZmVGF1TEVNID0gYXdhaXQgY3VydmUuRzEuYmF0Y2hVdG9MRU0oYnVmZlRhdVUpO1xuICAgIGJ1ZmZIID0gbmV3IFVpbnQ4QXJyYXkoemtleUhlYWRlci5kb21haW5TaXplKnNHMSk7XG4gICAgYnVmZkguc2V0KGJ1ZmZUYXVMRU0pOyAgIC8vIExldCB0aGUgbGFzdCBvbmUgdG8gemVyby5cbiAgICBjdXJ2ZS5HMS50b1JwckxFTShidWZmSCwgc0cxKih6a2V5SGVhZGVyLmRvbWFpblNpemUtMSksIGN1cnZlLkcxLnplcm9BZmZpbmUpO1xuICAgIGNvbnN0IG4ySW52ID0gY3VydmUuRnIubmVnKGN1cnZlLkZyLmludihjdXJ2ZS5Gci5lKDIpKSk7XG4gICAgY29uc3Qgd0ludiA9IGN1cnZlLkZyLmludihjdXJ2ZS5Gci53W3prZXlIZWFkZXIucG93ZXIrMV0pO1xuICAgIGJ1ZmZIID0gYXdhaXQgY3VydmUuRzEuYmF0Y2hBcHBseUtleShidWZmSCwgbjJJbnYsIHdJbnYsIFwiYWZmaW5lXCIsIFwiamFjb2JpYW5cIiwgbG9nZ2VyKTtcbiAgICBidWZmSCA9IGF3YWl0IGN1cnZlLkcxLmlmZnQoYnVmZkgsIFwiamFjb2JpYW5cIiwgXCJhZmZpbmVcIiwgbG9nZ2VyKTtcbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuc3RhcnRXcml0ZVNlY3Rpb24oZmRaS2V5TmV3LCA5KTtcbiAgICBhd2FpdCBmZFpLZXlOZXcud3JpdGUoYnVmZkgpO1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5lbmRXcml0ZVNlY3Rpb24oZmRaS2V5TmV3KTtcblxuICAgIC8vIEMgU2VjdGlvbiAoTCBzZWN0aW9uKVxuICAgIGNvbnN0IG5MID0gYXdhaXQgZmRNUENQYXJhbXMucmVhZFVCRTMyKCk7XG4gICAgaWYgKG5MICE9ICh6a2V5SGVhZGVyLm5WYXJzLXprZXlIZWFkZXIublB1YmxpYy0xKSkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJJbnZhbGlkIG51bWJlciBvZiBwb2ludHMgaW4gTFwiKTtcbiAgICAgICAgYXdhaXQgZmRaS2V5TmV3LmRpc2NhcmQoKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBsZXQgYnVmZkw7XG4gICAgYnVmZkwgPSBhd2FpdCBmZE1QQ1BhcmFtcy5yZWFkKHNHMSooemtleUhlYWRlci5uVmFycy16a2V5SGVhZGVyLm5QdWJsaWMtMSkpO1xuICAgIGJ1ZmZMID0gYXdhaXQgY3VydmUuRzEuYmF0Y2hVdG9MRU0oYnVmZkwpO1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFdyaXRlU2VjdGlvbihmZFpLZXlOZXcsIDgpO1xuICAgIGF3YWl0IGZkWktleU5ldy53cml0ZShidWZmTCk7XG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmVuZFdyaXRlU2VjdGlvbihmZFpLZXlOZXcpO1xuXG4gICAgLy8gQSBTZWN0aW9uXG4gICAgY29uc3QgbkEgPSBhd2FpdCBmZE1QQ1BhcmFtcy5yZWFkVUJFMzIoKTtcbiAgICBpZiAobkEgIT0gemtleUhlYWRlci5uVmFycykge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJJbnZhbGlkIG51bWJlciBvZiBwb2ludHMgaW4gQVwiKTtcbiAgICAgICAgYXdhaXQgZmRaS2V5TmV3LmRpc2NhcmQoKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBmZE1QQ1BhcmFtcy5wb3MgKz0gc0cxKih6a2V5SGVhZGVyLm5WYXJzKTtcbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuY29weVNlY3Rpb24oZmRaS2V5T2xkLCBzZWN0aW9uc1pLZXlPbGQsIGZkWktleU5ldywgNSk7XG5cbiAgICAvLyBCMSBTZWN0aW9uXG4gICAgY29uc3QgbkIxID0gYXdhaXQgZmRNUENQYXJhbXMucmVhZFVCRTMyKCk7XG4gICAgaWYgKG5CMSAhPSB6a2V5SGVhZGVyLm5WYXJzKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihcIkludmFsaWQgbnVtYmVyIG9mIHBvaW50cyBpbiBCMVwiKTtcbiAgICAgICAgYXdhaXQgZmRaS2V5TmV3LmRpc2NhcmQoKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBmZE1QQ1BhcmFtcy5wb3MgKz0gc0cxKih6a2V5SGVhZGVyLm5WYXJzKTtcbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuY29weVNlY3Rpb24oZmRaS2V5T2xkLCBzZWN0aW9uc1pLZXlPbGQsIGZkWktleU5ldywgNik7XG5cbiAgICAvLyBCMiBTZWN0aW9uXG4gICAgY29uc3QgbkIyID0gYXdhaXQgZmRNUENQYXJhbXMucmVhZFVCRTMyKCk7XG4gICAgaWYgKG5CMiAhPSB6a2V5SGVhZGVyLm5WYXJzKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihcIkludmFsaWQgbnVtYmVyIG9mIHBvaW50cyBpbiBCMlwiKTtcbiAgICAgICAgYXdhaXQgZmRaS2V5TmV3LmRpc2NhcmQoKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBmZE1QQ1BhcmFtcy5wb3MgKz0gc0cyKih6a2V5SGVhZGVyLm5WYXJzKTtcbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuY29weVNlY3Rpb24oZmRaS2V5T2xkLCBzZWN0aW9uc1pLZXlPbGQsIGZkWktleU5ldywgNyk7XG5cbiAgICBhd2FpdCB6a2V5VXRpbHMud3JpdGVNUENQYXJhbXMoZmRaS2V5TmV3LCBjdXJ2ZSwgbmV3TVBDUGFyYW1zKTtcblxuICAgIGF3YWl0IGZkTVBDUGFyYW1zLmNsb3NlKCk7XG4gICAgYXdhaXQgZmRaS2V5TmV3LmNsb3NlKCk7XG4gICAgYXdhaXQgZmRaS2V5T2xkLmNsb3NlKCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcblxuICAgIGFzeW5jIGZ1bmN0aW9uIHJlYWRHMShmZCkge1xuICAgICAgICBjb25zdCBidWZmID0gYXdhaXQgZmQucmVhZChjdXJ2ZS5HMS5GLm44KjIpO1xuICAgICAgICByZXR1cm4gY3VydmUuRzEuZnJvbVJwclVuY29tcHJlc3NlZChidWZmLCAwKTtcbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiByZWFkRzIoZmQpIHtcbiAgICAgICAgY29uc3QgYnVmZiA9IGF3YWl0IGZkLnJlYWQoY3VydmUuRzIuRi5uOCoyKTtcbiAgICAgICAgcmV0dXJuIGN1cnZlLkcyLmZyb21ScHJVbmNvbXByZXNzZWQoYnVmZiwgMCk7XG4gICAgfVxuXG5cbiAgICBmdW5jdGlvbiBjb250cmlidXRpb25Jc0VxdWFsKGMxLCBjMikge1xuICAgICAgICBpZiAoIWN1cnZlLkcxLmVxKGMxLmRlbHRhQWZ0ZXIgICAsIGMyLmRlbHRhQWZ0ZXIpKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIGlmICghY3VydmUuRzEuZXEoYzEuZGVsdGEuZzFfcyAgICwgYzIuZGVsdGEuZzFfcykpIHJldHVybiBmYWxzZTtcbiAgICAgICAgaWYgKCFjdXJ2ZS5HMS5lcShjMS5kZWx0YS5nMV9zeCAgLCBjMi5kZWx0YS5nMV9zeCkpIHJldHVybiBmYWxzZTtcbiAgICAgICAgaWYgKCFjdXJ2ZS5HMi5lcShjMS5kZWx0YS5nMl9zcHggLCBjMi5kZWx0YS5nMl9zcHgpKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIGlmICghbWlzYy5oYXNoSXNFcXVhbChjMS50cmFuc2NyaXB0LCBjMi50cmFuc2NyaXB0KSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cblxufVxuXG4iLCIvKlxuICAgIENvcHlyaWdodCAyMDE4IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygc25hcmtKUy5cblxuICAgIHNuYXJrSlMgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gICAgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAgICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICAgIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICBzbmFya0pTIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHNuYXJrSlMuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG5pbXBvcnQgKiBhcyBiaW5GaWxlVXRpbHMgZnJvbSBcIkBpZGVuMy9iaW5maWxldXRpbHNcIjtcbmltcG9ydCAqIGFzIHprZXlVdGlscyBmcm9tIFwiLi96a2V5X3V0aWxzLmpzXCI7XG5pbXBvcnQgeyBnZXRDdXJ2ZUZyb21RIGFzIGdldEN1cnZlIH0gZnJvbSBcIi4vY3VydmVzLmpzXCI7XG5pbXBvcnQgeyBibGFrZTJiIH0gZnJvbSBcIkBub2JsZS9oYXNoZXMvYmxha2UyYlwiO1xuaW1wb3J0ICogYXMgbWlzYyBmcm9tIFwiLi9taXNjLmpzXCI7XG5pbXBvcnQgeyBoYXNoVG9HMiBhcyBoYXNoVG9HMiB9IGZyb20gXCIuL2tleXBhaXIuanNcIjtcbmNvbnN0IHNhbWVSYXRpbyA9IG1pc2Muc2FtZVJhdGlvO1xuaW1wb3J0IHtoYXNoRzEsIGhhc2hQdWJLZXl9IGZyb20gXCIuL3prZXlfdXRpbHMuanNcIjtcbmltcG9ydCB7IFNjYWxhciwgQ2hhQ2hhLCBCaWdCdWZmZXIgfSBmcm9tIFwiZmZqYXZhc2NyaXB0XCI7XG5cblxuXG5leHBvcnQgZGVmYXVsdCBhc3luYyBmdW5jdGlvbiBwaGFzZTJ2ZXJpZnlGcm9tSW5pdChpbml0RmlsZU5hbWUsIHBUYXVGaWxlTmFtZSwgemtleUZpbGVOYW1lLCBsb2dnZXIpIHtcblxuICAgIGxldCBzcjtcbiAgICBjb25zdCB7ZmQsIHNlY3Rpb25zfSA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkQmluRmlsZSh6a2V5RmlsZU5hbWUsIFwiemtleVwiLCAyKTtcbiAgICBjb25zdCB6a2V5ID0gYXdhaXQgemtleVV0aWxzLnJlYWRIZWFkZXIoZmQsIHNlY3Rpb25zLCBmYWxzZSk7XG4gICAgaWYgKHprZXkucHJvdG9jb2wgIT0gXCJncm90aDE2XCIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiemtleSBmaWxlIGlzIG5vdCBncm90aDE2XCIpO1xuICAgIH1cblxuICAgIGNvbnN0IGN1cnZlID0gYXdhaXQgZ2V0Q3VydmUoemtleS5xKTtcbiAgICBjb25zdCBzRzEgPSBjdXJ2ZS5HMS5GLm44KjI7XG5cbiAgICBjb25zdCBtcGNQYXJhbXMgPSBhd2FpdCB6a2V5VXRpbHMucmVhZE1QQ1BhcmFtcyhmZCwgY3VydmUsIHNlY3Rpb25zKTtcblxuICAgIGNvbnN0IGFjY3VtdWxhdGVkSGFzaGVyID0gYmxha2UyYi5jcmVhdGUoeyBka0xlbjogNjQgfSk7XG4gICAgYWNjdW11bGF0ZWRIYXNoZXIudXBkYXRlKG1wY1BhcmFtcy5jc0hhc2gpO1xuICAgIGxldCBjdXJEZWx0YSA9IGN1cnZlLkcxLmc7XG4gICAgZm9yIChsZXQgaT0wOyBpPG1wY1BhcmFtcy5jb250cmlidXRpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGMgPSBtcGNQYXJhbXMuY29udHJpYnV0aW9uc1tpXTtcbiAgICAgICAgY29uc3Qgb3VySGFzaGVyID0gbWlzYy5jbG9uZUhhc2hlcihhY2N1bXVsYXRlZEhhc2hlcik7XG5cbiAgICAgICAgaGFzaEcxKG91ckhhc2hlciwgY3VydmUsIGMuZGVsdGEuZzFfcyk7XG4gICAgICAgIGhhc2hHMShvdXJIYXNoZXIsIGN1cnZlLCBjLmRlbHRhLmcxX3N4KTtcblxuICAgICAgICBpZiAoIW1pc2MuaGFzaElzRXF1YWwob3VySGFzaGVyLmRpZ2VzdCgpLCBjLnRyYW5zY3JpcHQpKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgSU5WQUxJRCgke2l9KTogSW5jb25zaXN0ZW50IHRyYW5zY3JpcHQgYCk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBkZWx0YV9nMl9zcCA9IGhhc2hUb0cyKGN1cnZlLCBjLnRyYW5zY3JpcHQpO1xuXG4gICAgICAgIHNyID0gYXdhaXQgc2FtZVJhdGlvKGN1cnZlLCBjLmRlbHRhLmcxX3MsIGMuZGVsdGEuZzFfc3gsIGRlbHRhX2cyX3NwLCBjLmRlbHRhLmcyX3NweCk7XG4gICAgICAgIGlmIChzciAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgY29uc29sZS5sb2coYElOVkFMSUQoJHtpfSk6IHB1YmxpYyBrZXkgRzEgYW5kIEcyIGRvIG5vdCBoYXZlIHRoZSBzYW1lIHJhdGlvbiBgKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNyID0gYXdhaXQgc2FtZVJhdGlvKGN1cnZlLCBjdXJEZWx0YSwgYy5kZWx0YUFmdGVyLCBkZWx0YV9nMl9zcCwgYy5kZWx0YS5nMl9zcHgpO1xuICAgICAgICBpZiAoc3IgIT09IHRydWUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBJTlZBTElEKCR7aX0pOiBkZWx0YUFmdGVyIGRvZXMgbm90IGZpbGxvdyB0aGUgcHVibGljIGtleSBgKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjLnR5cGUgPT0gMSkge1xuICAgICAgICAgICAgY29uc3Qgcm5nID0gYXdhaXQgbWlzYy5ybmdGcm9tQmVhY29uUGFyYW1zKGMuYmVhY29uSGFzaCwgYy5udW1JdGVyYXRpb25zRXhwKTtcbiAgICAgICAgICAgIGNvbnN0IGV4cGVjdGVkX3BydktleSA9IGN1cnZlLkZyLmZyb21Sbmcocm5nKTtcbiAgICAgICAgICAgIGNvbnN0IGV4cGVjdGVkX2cxX3MgPSBjdXJ2ZS5HMS50b0FmZmluZShjdXJ2ZS5HMS5mcm9tUm5nKHJuZykpO1xuICAgICAgICAgICAgY29uc3QgZXhwZWN0ZWRfZzFfc3ggPSBjdXJ2ZS5HMS50b0FmZmluZShjdXJ2ZS5HMS50aW1lc0ZyKGV4cGVjdGVkX2cxX3MsIGV4cGVjdGVkX3BydktleSkpO1xuICAgICAgICAgICAgaWYgKGN1cnZlLkcxLmVxKGV4cGVjdGVkX2cxX3MsIGMuZGVsdGEuZzFfcykgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhgSU5WQUxJRCgke2l9KTogS2V5IG9mIHRoZSBiZWFjb24gZG9lcyBub3QgbWF0Y2guIGcxX3MgYCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGN1cnZlLkcxLmVxKGV4cGVjdGVkX2cxX3N4LCBjLmRlbHRhLmcxX3N4KSAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGBJTlZBTElEKCR7aX0pOiBLZXkgb2YgdGhlIGJlYWNvbiBkb2VzIG5vdCBtYXRjaC4gZzFfc3ggYCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaGFzaFB1YktleShhY2N1bXVsYXRlZEhhc2hlciwgY3VydmUsIGMpO1xuXG4gICAgICAgIGNvbnN0IGNvbnRyaWJ1dGlvbkhhc2hlciA9IGJsYWtlMmIuY3JlYXRlKHsgZGtMZW46IDY0IH0pO1xuICAgICAgICBoYXNoUHViS2V5KGNvbnRyaWJ1dGlvbkhhc2hlciwgY3VydmUsIGMpO1xuXG4gICAgICAgIGMuY29udHJpYnV0aW9uSGFzaCA9IGNvbnRyaWJ1dGlvbkhhc2hlci5kaWdlc3QoKTtcblxuICAgICAgICBjdXJEZWx0YSA9IGMuZGVsdGFBZnRlcjtcbiAgICB9XG5cblxuICAgIGNvbnN0IHtmZDogZmRJbml0LCBzZWN0aW9uczogc2VjdGlvbnNJbml0fSA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkQmluRmlsZShpbml0RmlsZU5hbWUsIFwiemtleVwiLCAyKTtcbiAgICBjb25zdCB6a2V5SW5pdCA9IGF3YWl0IHprZXlVdGlscy5yZWFkSGVhZGVyKGZkSW5pdCwgc2VjdGlvbnNJbml0LCBmYWxzZSk7XG5cbiAgICBpZiAoemtleUluaXQucHJvdG9jb2wgIT0gXCJncm90aDE2XCIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiemtleWluaXQgZmlsZSBpcyBub3QgZ3JvdGgxNlwiKTtcbiAgICB9XG5cbiAgICBpZiAoICAoIVNjYWxhci5lcSh6a2V5SW5pdC5xLCB6a2V5LnEpKVxuICAgICAgICB8fCghU2NhbGFyLmVxKHprZXlJbml0LnIsIHprZXkucikpXG4gICAgICAgIHx8KHprZXlJbml0Lm44cSAhPSB6a2V5Lm44cSlcbiAgICAgICAgfHwoemtleUluaXQubjhyICE9IHprZXkubjhyKSlcbiAgICB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihcIklOVkFMSUQ6ICBEaWZmZXJlbnQgY3VydmVzXCIpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKCAgKHprZXlJbml0Lm5WYXJzICE9IHprZXkublZhcnMpXG4gICAgICAgIHx8KHprZXlJbml0Lm5QdWJsaWMgIT0gIHprZXkublB1YmxpYylcbiAgICAgICAgfHwoemtleUluaXQuZG9tYWluU2l6ZSAhPSB6a2V5LmRvbWFpblNpemUpKVxuICAgIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiSU5WQUxJRDogIERpZmZlcmVudCBjaXJjdWl0IHBhcmFtZXRlcnNcIik7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoIWN1cnZlLkcxLmVxKHprZXkudmtfYWxwaGFfMSwgemtleUluaXQudmtfYWxwaGFfMSkpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiSU5WQUxJRDogIEludmFsaWQgYWxwaGExXCIpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmICghY3VydmUuRzEuZXEoemtleS52a19iZXRhXzEsIHprZXlJbml0LnZrX2JldGFfMSkpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiSU5WQUxJRDogIEludmFsaWQgYmV0YTFcIik7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgaWYgKCFjdXJ2ZS5HMi5lcSh6a2V5LnZrX2JldGFfMiwgemtleUluaXQudmtfYmV0YV8yKSkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJJTlZBTElEOiAgSW52YWxpZCBiZXRhMlwiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAoIWN1cnZlLkcyLmVxKHprZXkudmtfZ2FtbWFfMiwgemtleUluaXQudmtfZ2FtbWFfMikpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiSU5WQUxJRDogIEludmFsaWQgZ2FtbWEyXCIpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmICghY3VydmUuRzEuZXEoemtleS52a19kZWx0YV8xLCBjdXJEZWx0YSkpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiSU5WQUxJRDogIEludmFsaWQgZGVsdGExXCIpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHNyID0gYXdhaXQgc2FtZVJhdGlvKGN1cnZlLCBjdXJ2ZS5HMS5nLCBjdXJEZWx0YSwgY3VydmUuRzIuZywgemtleS52a19kZWx0YV8yKTtcbiAgICBpZiAoc3IgIT09IHRydWUpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiSU5WQUxJRDogIEludmFsaWQgZGVsdGEyXCIpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgbXBjUGFyYW1zSW5pdCA9IGF3YWl0IHprZXlVdGlscy5yZWFkTVBDUGFyYW1zKGZkSW5pdCwgY3VydmUsIHNlY3Rpb25zSW5pdCk7XG4gICAgaWYgKCFtaXNjLmhhc2hJc0VxdWFsKG1wY1BhcmFtcy5jc0hhc2gsIG1wY1BhcmFtc0luaXQuY3NIYXNoKSkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJJTlZBTElEOiAgQ2lyY3VpdCBkb2VzIG5vdCBtYXRjaFwiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8vIENoZWNrIHNpemVzIG9mIHNlY3Rpb25zXG4gICAgaWYgKHNlY3Rpb25zWzhdWzBdLnNpemUgIT0gc0cxKih6a2V5Lm5WYXJzLXprZXkublB1YmxpYy0xKSkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJJTlZBTElEOiAgSW52YWxpZCBMIHNlY3Rpb24gc2l6ZVwiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmIChzZWN0aW9uc1s5XVswXS5zaXplICE9IHNHMSooemtleS5kb21haW5TaXplKSkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJJTlZBTElEOiAgSW52YWxpZCBIIHNlY3Rpb24gc2l6ZVwiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGxldCBzcztcbiAgICBzcyA9IGF3YWl0IGJpbkZpbGVVdGlscy5zZWN0aW9uSXNFcXVhbChmZCwgc2VjdGlvbnMsIGZkSW5pdCwgc2VjdGlvbnNJbml0LCAzKTtcbiAgICBpZiAoIXNzKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihcIklOVkFMSUQ6ICBJQyBzZWN0aW9uIGlzIG5vdCBpZGVudGljYWxcIik7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBzcyA9IGF3YWl0IGJpbkZpbGVVdGlscy5zZWN0aW9uSXNFcXVhbChmZCwgc2VjdGlvbnMsIGZkSW5pdCwgc2VjdGlvbnNJbml0LCA0KTtcbiAgICBpZiAoIXNzKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihcIkNvZWZmcyBzZWN0aW9uIGlzIG5vdCBpZGVudGljYWxcIik7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBzcyA9IGF3YWl0IGJpbkZpbGVVdGlscy5zZWN0aW9uSXNFcXVhbChmZCwgc2VjdGlvbnMsIGZkSW5pdCwgc2VjdGlvbnNJbml0LCA1KTtcbiAgICBpZiAoIXNzKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihcIkEgc2VjdGlvbiBpcyBub3QgaWRlbnRpY2FsXCIpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgc3MgPSBhd2FpdCBiaW5GaWxlVXRpbHMuc2VjdGlvbklzRXF1YWwoZmQsIHNlY3Rpb25zLCBmZEluaXQsIHNlY3Rpb25zSW5pdCwgNik7XG4gICAgaWYgKCFzcykge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJCMSBzZWN0aW9uIGlzIG5vdCBpZGVudGljYWxcIik7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBzcyA9IGF3YWl0IGJpbkZpbGVVdGlscy5zZWN0aW9uSXNFcXVhbChmZCwgc2VjdGlvbnMsIGZkSW5pdCwgc2VjdGlvbnNJbml0LCA3KTtcbiAgICBpZiAoIXNzKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihcIkIyIHNlY3Rpb24gaXMgbm90IGlkZW50aWNhbFwiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8vIENoZWNrIExcbiAgICBzciA9IGF3YWl0IHNlY3Rpb25IYXNTYW1lUmF0aW8oXCJHMVwiLCBmZEluaXQsIHNlY3Rpb25zSW5pdCwgZmQsIHNlY3Rpb25zLCA4LCB6a2V5LnZrX2RlbHRhXzIsIHprZXlJbml0LnZrX2RlbHRhXzIsIFwiTCBzZWN0aW9uXCIpO1xuICAgIGlmIChzciE9PXRydWUpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiTCBzZWN0aW9uIGRvZXMgbm90IG1hdGNoXCIpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgSFxuICAgIHNyID0gYXdhaXQgc2FtZVJhdGlvSCgpO1xuICAgIGlmIChzciE9PXRydWUpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiSCBzZWN0aW9uIGRvZXMgbm90IG1hdGNoXCIpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8obWlzYy5mb3JtYXRIYXNoKG1wY1BhcmFtcy5jc0hhc2gsIFwiQ2lyY3VpdCBIYXNoOiBcIikpO1xuXG4gICAgYXdhaXQgZmQuY2xvc2UoKTtcbiAgICBhd2FpdCBmZEluaXQuY2xvc2UoKTtcblxuICAgIGZvciAobGV0IGk9bXBjUGFyYW1zLmNvbnRyaWJ1dGlvbnMubGVuZ3RoLTE7IGk+PTA7IGktLSkge1xuICAgICAgICBjb25zdCBjID0gbXBjUGFyYW1zLmNvbnRyaWJ1dGlvbnNbaV07XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8obWlzYy5mb3JtYXRIYXNoKGMuY29udHJpYnV0aW9uSGFzaCwgYGNvbnRyaWJ1dGlvbiAjJHtpKzF9ICR7Yy5uYW1lID8gYy5uYW1lIDogXCJcIn06YCkpO1xuICAgICAgICBpZiAoYy50eXBlID09IDEpIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKGBCZWFjb24gZ2VuZXJhdG9yOiAke21pc2MuYnl0ZUFycmF5MmhleChjLmJlYWNvbkhhc2gpfWApO1xuICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oYEJlYWNvbiBpdGVyYXRpb25zIEV4cDogJHtjLm51bUl0ZXJhdGlvbnNFeHB9YCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCItLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXCIpO1xuXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCJaS2V5IE9rIVwiKTtcblxuICAgIHJldHVybiB0cnVlO1xuXG5cbiAgICBhc3luYyBmdW5jdGlvbiBzZWN0aW9uSGFzU2FtZVJhdGlvKGdyb3VwTmFtZSwgZmQxLCBzZWN0aW9uczEsIGZkMiwgc2VjdGlvbnMyLCBpZFNlY3Rpb24sIGcyc3AsIGcyc3B4LCBzZWN0aW9uTmFtZSkge1xuICAgICAgICBjb25zdCBNQVhfQ0hVTktfU0laRSA9IDE8PDIwO1xuICAgICAgICBjb25zdCBHID0gY3VydmVbZ3JvdXBOYW1lXTtcbiAgICAgICAgY29uc3Qgc0cgPSBHLkYubjgqMjtcbiAgICAgICAgYXdhaXQgYmluRmlsZVV0aWxzLnN0YXJ0UmVhZFVuaXF1ZVNlY3Rpb24oZmQxLCBzZWN0aW9uczEsIGlkU2VjdGlvbik7XG4gICAgICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFJlYWRVbmlxdWVTZWN0aW9uKGZkMiwgc2VjdGlvbnMyLCBpZFNlY3Rpb24pO1xuXG4gICAgICAgIGxldCBSMSA9IEcuemVybztcbiAgICAgICAgbGV0IFIyID0gRy56ZXJvO1xuXG4gICAgICAgIGNvbnN0IG5Qb2ludHMgPSBzZWN0aW9uczFbaWRTZWN0aW9uXVswXS5zaXplIC8gc0c7XG5cbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPG5Qb2ludHM7IGkgKz0gTUFYX0NIVU5LX1NJWkUpIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhgU2FtZSByYXRpbyBjaGVjayAke3NlY3Rpb25OYW1lfTogICR7aX0vJHtuUG9pbnRzfWApO1xuICAgICAgICAgICAgY29uc3QgbiA9IE1hdGgubWluKG5Qb2ludHMgLSBpLCBNQVhfQ0hVTktfU0laRSk7XG4gICAgICAgICAgICBjb25zdCBiYXNlczEgPSBhd2FpdCBmZDEucmVhZChuKnNHKTtcbiAgICAgICAgICAgIGNvbnN0IGJhc2VzMiA9IGF3YWl0IGZkMi5yZWFkKG4qc0cpO1xuXG4gICAgICAgICAgICBjb25zdCBzY2FsYXJzID0gbWlzYy5nZXRSYW5kb21CeXRlcyg0Km4pO1xuXG4gICAgICAgICAgICBjb25zdCByMSA9IGF3YWl0IEcubXVsdGlFeHBBZmZpbmUoYmFzZXMxLCBzY2FsYXJzKTtcbiAgICAgICAgICAgIGNvbnN0IHIyID0gYXdhaXQgRy5tdWx0aUV4cEFmZmluZShiYXNlczIsIHNjYWxhcnMpO1xuXG4gICAgICAgICAgICBSMSA9IEcuYWRkKFIxLCByMSk7XG4gICAgICAgICAgICBSMiA9IEcuYWRkKFIyLCByMik7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgYmluRmlsZVV0aWxzLmVuZFJlYWRTZWN0aW9uKGZkMSk7XG4gICAgICAgIGF3YWl0IGJpbkZpbGVVdGlscy5lbmRSZWFkU2VjdGlvbihmZDIpO1xuXG4gICAgICAgIGlmIChuUG9pbnRzID09IDApIHJldHVybiB0cnVlO1xuXG4gICAgICAgIHNyID0gYXdhaXQgc2FtZVJhdGlvKGN1cnZlLCBSMSwgUjIsIGcyc3AsIGcyc3B4KTtcbiAgICAgICAgaWYgKHNyICE9PSB0cnVlKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgYXN5bmMgZnVuY3Rpb24gc2FtZVJhdGlvSCgpIHtcbiAgICAgICAgY29uc3QgTUFYX0NIVU5LX1NJWkUgPSAxPDwyMDtcbiAgICAgICAgY29uc3QgRyA9IGN1cnZlLkcxO1xuICAgICAgICBjb25zdCBGciA9IGN1cnZlLkZyO1xuICAgICAgICBjb25zdCBzRyA9IEcuRi5uOCoyO1xuXG4gICAgICAgIGNvbnN0IHtmZDogZmRQVGF1LCBzZWN0aW9uczogc2VjdGlvbnNQVGF1fSA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkQmluRmlsZShwVGF1RmlsZU5hbWUsIFwicHRhdVwiLCAxKTtcblxuICAgICAgICBsZXQgYnVmZl9yID0gbmV3IEJpZ0J1ZmZlcih6a2V5LmRvbWFpblNpemUgKiB6a2V5Lm44cik7XG5cbiAgICAgICAgY29uc3Qgc2VlZD0gbmV3IEFycmF5KDgpO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8ODsgaSsrKSB7XG4gICAgICAgICAgICBzZWVkW2ldID0gbWlzYy5yZWFkVUludDMyQkUobWlzYy5nZXRSYW5kb21CeXRlcyg0KSwgMCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgcm5nID0gbmV3IENoYUNoYShzZWVkKTtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPHprZXkuZG9tYWluU2l6ZS0xOyBpKyspIHsgICAvLyBOb3RlIHRoYXQgbGFzdCBvbmUgaXMgemVyb1xuICAgICAgICAgICAgY29uc3QgZSA9IEZyLmZyb21Sbmcocm5nKTtcbiAgICAgICAgICAgIEZyLnRvUnByTEUoYnVmZl9yLCBpKnprZXkubjhyLCBlKTtcbiAgICAgICAgfVxuICAgICAgICBGci50b1JwckxFKGJ1ZmZfciwgKHprZXkuZG9tYWluU2l6ZS0xKSp6a2V5Lm44ciwgRnIuemVybyk7XG5cbiAgICAgICAgbGV0IFIxID0gRy56ZXJvO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8emtleS5kb21haW5TaXplOyBpICs9IE1BWF9DSFVOS19TSVpFKSB7XG4gICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoYEggVmVyaWZpY2F0aW9uKHRhdSk6ICAke2l9LyR7emtleS5kb21haW5TaXplfWApO1xuICAgICAgICAgICAgY29uc3QgbiA9IE1hdGgubWluKHprZXkuZG9tYWluU2l6ZSAtIGksIE1BWF9DSFVOS19TSVpFKTtcblxuICAgICAgICAgICAgY29uc3QgYnVmZjEgPSBhd2FpdCBmZFBUYXUucmVhZChzRypuLCBzZWN0aW9uc1BUYXVbMl1bMF0ucCArIHprZXkuZG9tYWluU2l6ZSpzRyArIGkqc0cpO1xuICAgICAgICAgICAgY29uc3QgYnVmZjIgPSBhd2FpdCBmZFBUYXUucmVhZChzRypuLCBzZWN0aW9uc1BUYXVbMl1bMF0ucCArIGkqc0cpO1xuXG4gICAgICAgICAgICBjb25zdCBidWZmQiA9IGF3YWl0IGJhdGNoU3VidHJhY3QoYnVmZjEsIGJ1ZmYyKTtcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmZTID0gYnVmZl9yLnNsaWNlKGkqemtleS5uOHIsIChpK24pKnprZXkubjhyKTtcbiAgICAgICAgICAgIGNvbnN0IHIgPSBhd2FpdCBHLm11bHRpRXhwQWZmaW5lKGJ1ZmZCLCBidWZmUyk7XG5cbiAgICAgICAgICAgIFIxID0gRy5hZGQoUjEsIHIpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIG9kZCBjb2VmZmljaWVudHMgaW4gdHJhbnNmb3JtZWQgZG9tYWluXG5cbiAgICAgICAgYnVmZl9yID0gYXdhaXQgRnIuYmF0Y2hUb01vbnRnb21lcnkoYnVmZl9yKTtcbiAgICAgICAgLy8gY29uc3QgZmlyc3QgPSBjdXJ2ZS5Gci5uZWcoY3VydmUuRnIuaW52KGN1cnZlLkZyLmUoMikpKTtcbiAgICAgICAgLy8gV29ya3MqMiAgIGNvbnN0IGZpcnN0ID0gY3VydmUuRnIubmVnKGN1cnZlLkZyLmUoMikpO1xuXG5cbiAgICAgICAgbGV0IGZpcnN0O1xuXG4gICAgICAgIGlmICh6a2V5LnBvd2VyIDwgRnIucykge1xuICAgICAgICAgICAgZmlyc3QgPSBGci5uZWcoRnIuZSgyKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBzbWFsbF9tICA9IDIgKiogRnIucztcbiAgICAgICAgICAgIGNvbnN0IHNoaWZ0X3RvX3NtYWxsX20gPSBGci5leHAoRnIuc2hpZnQsIHNtYWxsX20pO1xuICAgICAgICAgICAgZmlyc3QgPSBGci5zdWIoIHNoaWZ0X3RvX3NtYWxsX20sIEZyLm9uZSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjb25zdCBpbmMgPSBjdXJ2ZS5Gci5pbnYoY3VydmUuUEZyLndbemtleS5wb3dlcisxXSk7XG4gICAgICAgIGNvbnN0IGluYyA9IHprZXkucG93ZXIgPCBGci5zID8gRnIud1t6a2V5LnBvd2VyKzFdIDogRnIuc2hpZnQ7XG4gICAgICAgIGJ1ZmZfciA9IGF3YWl0IEZyLmJhdGNoQXBwbHlLZXkoYnVmZl9yLCBmaXJzdCwgaW5jKTtcbiAgICAgICAgYnVmZl9yID0gYXdhaXQgRnIuZmZ0KGJ1ZmZfcik7XG4gICAgICAgIGJ1ZmZfciA9IGF3YWl0IEZyLmJhdGNoRnJvbU1vbnRnb21lcnkoYnVmZl9yKTtcblxuICAgICAgICBhd2FpdCBiaW5GaWxlVXRpbHMuc3RhcnRSZWFkVW5pcXVlU2VjdGlvbihmZCwgc2VjdGlvbnMsIDkpO1xuICAgICAgICBsZXQgUjIgPSBHLnplcm87XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTx6a2V5LmRvbWFpblNpemU7IGkgKz0gTUFYX0NIVU5LX1NJWkUpIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhgSCBWZXJpZmljYXRpb24obGFncmFuZ2UpOiAgJHtpfS8ke3prZXkuZG9tYWluU2l6ZX1gKTtcbiAgICAgICAgICAgIGNvbnN0IG4gPSBNYXRoLm1pbih6a2V5LmRvbWFpblNpemUgLSBpLCBNQVhfQ0hVTktfU0laRSk7XG5cbiAgICAgICAgICAgIGNvbnN0IGJ1ZmYgPSBhd2FpdCBmZC5yZWFkKHNHKm4pO1xuICAgICAgICAgICAgY29uc3QgYnVmZlMgPSBidWZmX3Iuc2xpY2UoaSp6a2V5Lm44ciwgKGkrbikqemtleS5uOHIpO1xuICAgICAgICAgICAgY29uc3QgciA9IGF3YWl0IEcubXVsdGlFeHBBZmZpbmUoYnVmZiwgYnVmZlMpO1xuXG4gICAgICAgICAgICBSMiA9IEcuYWRkKFIyLCByKTtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kUmVhZFNlY3Rpb24oZmQpO1xuXG4gICAgICAgIHNyID0gYXdhaXQgc2FtZVJhdGlvKGN1cnZlLCBSMSwgUjIsIHprZXkudmtfZGVsdGFfMiwgemtleUluaXQudmtfZGVsdGFfMik7XG4gICAgICAgIGlmIChzciAhPT0gdHJ1ZSkgcmV0dXJuIGZhbHNlO1xuXG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG5cbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiBiYXRjaFN1YnRyYWN0KGJ1ZmYxLCBidWZmMikge1xuICAgICAgICBjb25zdCBzRyA9IGN1cnZlLkcxLkYubjgqMjtcbiAgICAgICAgY29uc3QgblBvaW50cyA9IGJ1ZmYxLmJ5dGVMZW5ndGggLyBzRztcbiAgICAgICAgY29uc3QgY29uY3VycmVuY3k9IGN1cnZlLnRtLmNvbmN1cnJlbmN5O1xuICAgICAgICBjb25zdCBuUG9pbnRzUGVyVGhyZWFkID0gTWF0aC5mbG9vcihuUG9pbnRzIC8gY29uY3VycmVuY3kpO1xuICAgICAgICBjb25zdCBvcFByb21pc2VzID0gW107XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxjb25jdXJyZW5jeTsgaSsrKSB7XG4gICAgICAgICAgICBsZXQgbjtcbiAgICAgICAgICAgIGlmIChpPCBjb25jdXJyZW5jeS0xKSB7XG4gICAgICAgICAgICAgICAgbiA9IG5Qb2ludHNQZXJUaHJlYWQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG4gPSBuUG9pbnRzIC0gaSpuUG9pbnRzUGVyVGhyZWFkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG49PTApIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICBjb25zdCBzdWJCdWZmMSA9IGJ1ZmYxLnNsaWNlKGkqblBvaW50c1BlclRocmVhZCpzRzEsIChpKm5Qb2ludHNQZXJUaHJlYWQrbikqc0cxKTtcbiAgICAgICAgICAgIGNvbnN0IHN1YkJ1ZmYyID0gYnVmZjIuc2xpY2UoaSpuUG9pbnRzUGVyVGhyZWFkKnNHMSwgKGkqblBvaW50c1BlclRocmVhZCtuKSpzRzEpO1xuICAgICAgICAgICAgb3BQcm9taXNlcy5wdXNoKGJhdGNoU3VidHJhY3RUaHJlYWQoc3ViQnVmZjEsIHN1YkJ1ZmYyKSk7XG4gICAgICAgIH1cblxuXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IFByb21pc2UuYWxsKG9wUHJvbWlzZXMpO1xuXG4gICAgICAgIGNvbnN0IGZ1bGxCdWZmT3V0ID0gbmV3IFVpbnQ4QXJyYXkoblBvaW50cypzRyk7XG4gICAgICAgIGxldCBwID0wO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8cmVzdWx0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBmdWxsQnVmZk91dC5zZXQocmVzdWx0W2ldWzBdLCBwKTtcbiAgICAgICAgICAgIHArPXJlc3VsdFtpXVswXS5ieXRlTGVuZ3RoO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZ1bGxCdWZmT3V0O1xuICAgIH1cblxuXG4gICAgYXN5bmMgZnVuY3Rpb24gYmF0Y2hTdWJ0cmFjdFRocmVhZChidWZmMSwgYnVmZjIpIHtcbiAgICAgICAgY29uc3Qgc0cxID0gY3VydmUuRzEuRi5uOCoyO1xuICAgICAgICBjb25zdCBzR21pZCA9IGN1cnZlLkcxLkYubjgqMztcbiAgICAgICAgY29uc3QgblBvaW50cyA9IGJ1ZmYxLmJ5dGVMZW5ndGgvc0cxO1xuICAgICAgICBjb25zdCB0YXNrID0gW107XG4gICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkFMTE9DU0VUXCIsIHZhcjogMCwgYnVmZjogYnVmZjF9KTtcbiAgICAgICAgdGFzay5wdXNoKHtjbWQ6IFwiQUxMT0NTRVRcIiwgdmFyOiAxLCBidWZmOiBidWZmMn0pO1xuICAgICAgICB0YXNrLnB1c2goe2NtZDogXCJBTExPQ1wiLCB2YXI6IDIsIGxlbjogblBvaW50cypzR21pZH0pO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8blBvaW50czsgaSsrKSB7XG4gICAgICAgICAgICB0YXNrLnB1c2goe1xuICAgICAgICAgICAgICAgIGNtZDogXCJDQUxMXCIsXG4gICAgICAgICAgICAgICAgZm5OYW1lOiBcImcxbV9zdWJBZmZpbmVcIixcbiAgICAgICAgICAgICAgICBwYXJhbXM6IFtcbiAgICAgICAgICAgICAgICAgICAge3ZhcjogMCwgb2Zmc2V0OiBpKnNHMX0sXG4gICAgICAgICAgICAgICAgICAgIHt2YXI6IDEsIG9mZnNldDogaSpzRzF9LFxuICAgICAgICAgICAgICAgICAgICB7dmFyOiAyLCBvZmZzZXQ6IGkqc0dtaWR9LFxuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkNBTExcIiwgZm5OYW1lOiBcImcxbV9iYXRjaFRvQWZmaW5lXCIsIHBhcmFtczogW1xuICAgICAgICAgICAge3ZhcjogMn0sXG4gICAgICAgICAgICB7dmFsOiBuUG9pbnRzfSxcbiAgICAgICAgICAgIHt2YXI6IDJ9LFxuICAgICAgICBdfSk7XG4gICAgICAgIHRhc2sucHVzaCh7Y21kOiBcIkdFVFwiLCBvdXQ6IDAsIHZhcjogMiwgbGVuOiBuUG9pbnRzKnNHMX0pO1xuXG4gICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGN1cnZlLnRtLnF1ZXVlQWN0aW9uKHRhc2spO1xuXG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuXG59XG5cbiIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMTggMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya0pTLlxuXG4gICAgc25hcmtKUyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJrSlMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggc25hcmtKUy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbmltcG9ydCBuZXdaS2V5IGZyb20gXCIuL3prZXlfbmV3LmpzXCI7XG5pbXBvcnQgcGhhc2UydmVyaWZ5RnJvbUluaXQgZnJvbSBcIi4vemtleV92ZXJpZnlfZnJvbWluaXQuanNcIjtcblxuZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gcGhhc2UydmVyaWZ5RnJvbVIxY3MocjFjc0ZpbGVOYW1lLCBwVGF1RmlsZU5hbWUsIHprZXlGaWxlTmFtZSwgbG9nZ2VyKSB7XG5cbiAgICAvLyBjb25zdCBpbml0RmlsZU5hbWUgPSBcIn5cIiArIHprZXlGaWxlTmFtZSArIFwiLmluaXRcIjtcbiAgICBjb25zdCBpbml0RmlsZU5hbWUgPSB7dHlwZTogXCJiaWdNZW1cIn07XG4gICAgYXdhaXQgbmV3WktleShyMWNzRmlsZU5hbWUsIHBUYXVGaWxlTmFtZSwgaW5pdEZpbGVOYW1lLCBsb2dnZXIpO1xuXG4gICAgcmV0dXJuIGF3YWl0IHBoYXNlMnZlcmlmeUZyb21Jbml0KGluaXRGaWxlTmFtZSwgcFRhdUZpbGVOYW1lLCB6a2V5RmlsZU5hbWUsIGxvZ2dlcik7XG59XG5cbiIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMTggMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya0pTLlxuXG4gICAgc25hcmtKUyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJrSlMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggc25hcmtKUy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbmltcG9ydCAqIGFzIGJpbkZpbGVVdGlscyBmcm9tIFwiQGlkZW4zL2JpbmZpbGV1dGlsc1wiO1xuaW1wb3J0ICogYXMgemtleVV0aWxzIGZyb20gXCIuL3prZXlfdXRpbHMuanNcIjtcbmltcG9ydCB7IGdldEN1cnZlRnJvbVEgYXMgZ2V0Q3VydmUgfSBmcm9tIFwiLi9jdXJ2ZXMuanNcIjtcbmltcG9ydCAqIGFzIG1pc2MgZnJvbSBcIi4vbWlzYy5qc1wiO1xuaW1wb3J0IHsgYmxha2UyYiB9IGZyb20gXCJAbm9ibGUvaGFzaGVzL2JsYWtlMmJcIjtcbmltcG9ydCAqIGFzIHV0aWxzIGZyb20gXCIuL3prZXlfdXRpbHMuanNcIjtcbmltcG9ydCB7IGhhc2hUb0cyIGFzIGhhc2hUb0cyIH0gZnJvbSBcIi4va2V5cGFpci5qc1wiO1xuaW1wb3J0IHsgYXBwbHlLZXlUb1NlY3Rpb24gfSBmcm9tIFwiLi9tcGNfYXBwbHlrZXkuanNcIjtcblxuZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gcGhhc2UyY29udHJpYnV0ZSh6a2V5TmFtZU9sZCwgemtleU5hbWVOZXcsIG5hbWUsIGVudHJvcHksIGxvZ2dlcikge1xuXG4gICAgY29uc3Qge2ZkOiBmZE9sZCwgc2VjdGlvbnM6IHNlY3Rpb25zfSA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkQmluRmlsZSh6a2V5TmFtZU9sZCwgXCJ6a2V5XCIsIDIpO1xuICAgIGNvbnN0IHprZXkgPSBhd2FpdCB6a2V5VXRpbHMucmVhZEhlYWRlcihmZE9sZCwgc2VjdGlvbnMpO1xuICAgIGlmICh6a2V5LnByb3RvY29sICE9IFwiZ3JvdGgxNlwiKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcInprZXkgZmlsZSBpcyBub3QgZ3JvdGgxNlwiKTtcbiAgICB9XG5cbiAgICBjb25zdCBjdXJ2ZSA9IGF3YWl0IGdldEN1cnZlKHprZXkucSk7XG5cbiAgICBjb25zdCBtcGNQYXJhbXMgPSBhd2FpdCB6a2V5VXRpbHMucmVhZE1QQ1BhcmFtcyhmZE9sZCwgY3VydmUsIHNlY3Rpb25zKTtcblxuICAgIGNvbnN0IGZkTmV3ID0gYXdhaXQgYmluRmlsZVV0aWxzLmNyZWF0ZUJpbkZpbGUoemtleU5hbWVOZXcsIFwiemtleVwiLCAxLCAxMCk7XG5cblxuICAgIGNvbnN0IHJuZyA9IGF3YWl0IG1pc2MuZ2V0UmFuZG9tUm5nKGVudHJvcHkpO1xuXG4gICAgY29uc3QgdHJhbnNjcmlwdEhhc2hlciA9IGJsYWtlMmIuY3JlYXRlKHsgZGtMZW46IDY0IH0pO1xuICAgIHRyYW5zY3JpcHRIYXNoZXIudXBkYXRlKG1wY1BhcmFtcy5jc0hhc2gpO1xuICAgIGZvciAobGV0IGk9MDsgaTxtcGNQYXJhbXMuY29udHJpYnV0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICB1dGlscy5oYXNoUHViS2V5KHRyYW5zY3JpcHRIYXNoZXIsIGN1cnZlLCBtcGNQYXJhbXMuY29udHJpYnV0aW9uc1tpXSk7XG4gICAgfVxuXG4gICAgY29uc3QgY3VyQ29udHJpYnV0aW9uID0ge307XG4gICAgY3VyQ29udHJpYnV0aW9uLmRlbHRhID0ge307XG4gICAgY3VyQ29udHJpYnV0aW9uLmRlbHRhLnBydktleSA9IGN1cnZlLkZyLmZyb21Sbmcocm5nKTtcbiAgICBjdXJDb250cmlidXRpb24uZGVsdGEuZzFfcyA9IGN1cnZlLkcxLnRvQWZmaW5lKGN1cnZlLkcxLmZyb21Sbmcocm5nKSk7XG4gICAgY3VyQ29udHJpYnV0aW9uLmRlbHRhLmcxX3N4ID0gY3VydmUuRzEudG9BZmZpbmUoY3VydmUuRzEudGltZXNGcihjdXJDb250cmlidXRpb24uZGVsdGEuZzFfcywgY3VyQ29udHJpYnV0aW9uLmRlbHRhLnBydktleSkpO1xuICAgIHV0aWxzLmhhc2hHMSh0cmFuc2NyaXB0SGFzaGVyLCBjdXJ2ZSwgY3VyQ29udHJpYnV0aW9uLmRlbHRhLmcxX3MpO1xuICAgIHV0aWxzLmhhc2hHMSh0cmFuc2NyaXB0SGFzaGVyLCBjdXJ2ZSwgY3VyQ29udHJpYnV0aW9uLmRlbHRhLmcxX3N4KTtcbiAgICBjdXJDb250cmlidXRpb24udHJhbnNjcmlwdCA9IHRyYW5zY3JpcHRIYXNoZXIuZGlnZXN0KCk7XG4gICAgY3VyQ29udHJpYnV0aW9uLmRlbHRhLmcyX3NwID0gaGFzaFRvRzIoY3VydmUsIGN1ckNvbnRyaWJ1dGlvbi50cmFuc2NyaXB0KTtcbiAgICBjdXJDb250cmlidXRpb24uZGVsdGEuZzJfc3B4ID0gY3VydmUuRzIudG9BZmZpbmUoY3VydmUuRzIudGltZXNGcihjdXJDb250cmlidXRpb24uZGVsdGEuZzJfc3AsIGN1ckNvbnRyaWJ1dGlvbi5kZWx0YS5wcnZLZXkpKTtcblxuICAgIHprZXkudmtfZGVsdGFfMSA9IGN1cnZlLkcxLnRpbWVzRnIoemtleS52a19kZWx0YV8xLCBjdXJDb250cmlidXRpb24uZGVsdGEucHJ2S2V5KTtcbiAgICB6a2V5LnZrX2RlbHRhXzIgPSBjdXJ2ZS5HMi50aW1lc0ZyKHprZXkudmtfZGVsdGFfMiwgY3VyQ29udHJpYnV0aW9uLmRlbHRhLnBydktleSk7XG5cbiAgICBjdXJDb250cmlidXRpb24uZGVsdGFBZnRlciA9IHprZXkudmtfZGVsdGFfMTtcblxuICAgIGN1ckNvbnRyaWJ1dGlvbi50eXBlID0gMDtcbiAgICBpZiAobmFtZSkgY3VyQ29udHJpYnV0aW9uLm5hbWUgPSBuYW1lO1xuXG4gICAgbXBjUGFyYW1zLmNvbnRyaWJ1dGlvbnMucHVzaChjdXJDb250cmlidXRpb24pO1xuXG4gICAgYXdhaXQgemtleVV0aWxzLndyaXRlSGVhZGVyKGZkTmV3LCB6a2V5KTtcblxuICAgIC8vIElDXG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmNvcHlTZWN0aW9uKGZkT2xkLCBzZWN0aW9ucywgZmROZXcsIDMpO1xuXG4gICAgLy8gQ29lZmZzIChLZWVwIG9yaWdpbmFsKVxuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5jb3B5U2VjdGlvbihmZE9sZCwgc2VjdGlvbnMsIGZkTmV3LCA0KTtcblxuICAgIC8vIEEgU2VjdGlvblxuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5jb3B5U2VjdGlvbihmZE9sZCwgc2VjdGlvbnMsIGZkTmV3LCA1KTtcblxuICAgIC8vIEIxIFNlY3Rpb25cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuY29weVNlY3Rpb24oZmRPbGQsIHNlY3Rpb25zLCBmZE5ldywgNik7XG5cbiAgICAvLyBCMiBTZWN0aW9uXG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmNvcHlTZWN0aW9uKGZkT2xkLCBzZWN0aW9ucywgZmROZXcsIDcpO1xuXG4gICAgY29uc3QgaW52RGVsdGEgPSBjdXJ2ZS5Gci5pbnYoY3VyQ29udHJpYnV0aW9uLmRlbHRhLnBydktleSk7XG4gICAgYXdhaXQgYXBwbHlLZXlUb1NlY3Rpb24oZmRPbGQsIHNlY3Rpb25zLCBmZE5ldywgOCwgY3VydmUsIFwiRzFcIiwgaW52RGVsdGEsIGN1cnZlLkZyLmUoMSksIFwiTCBTZWN0aW9uXCIsIGxvZ2dlcik7XG4gICAgYXdhaXQgYXBwbHlLZXlUb1NlY3Rpb24oZmRPbGQsIHNlY3Rpb25zLCBmZE5ldywgOSwgY3VydmUsIFwiRzFcIiwgaW52RGVsdGEsIGN1cnZlLkZyLmUoMSksIFwiSCBTZWN0aW9uXCIsIGxvZ2dlcik7XG5cbiAgICBhd2FpdCB6a2V5VXRpbHMud3JpdGVNUENQYXJhbXMoZmROZXcsIGN1cnZlLCBtcGNQYXJhbXMpO1xuXG4gICAgYXdhaXQgZmRPbGQuY2xvc2UoKTtcbiAgICBhd2FpdCBmZE5ldy5jbG9zZSgpO1xuXG4gICAgY29uc3QgY29udHJpYnV0aW9uSGFzaGVyID0gYmxha2UyYi5jcmVhdGUoeyBka0xlbjogNjQgfSk7XG4gICAgdXRpbHMuaGFzaFB1YktleShjb250cmlidXRpb25IYXNoZXIsIGN1cnZlLCBjdXJDb250cmlidXRpb24pO1xuXG4gICAgY29uc3QgY29udHJpYnV0aW9uSGFzaCA9IGNvbnRyaWJ1dGlvbkhhc2hlci5kaWdlc3QoKTtcblxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKG1pc2MuZm9ybWF0SGFzaChtcGNQYXJhbXMuY3NIYXNoLCBcIkNpcmN1aXQgSGFzaDogXCIpKTtcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhtaXNjLmZvcm1hdEhhc2goY29udHJpYnV0aW9uSGFzaCwgXCJDb250cmlidXRpb24gSGFzaDogXCIpKTtcblxuICAgIHJldHVybiBjb250cmlidXRpb25IYXNoO1xufVxuIiwiLypcbiAgICBDb3B5cmlnaHQgMjAxOCAwS0lNUyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJrSlMuXG5cbiAgICBzbmFya0pTIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICAgIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gICAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAgICAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtKUyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVFxuICAgIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpY1xuICAgIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gICAgYWxvbmcgd2l0aCBzbmFya0pTLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuaW1wb3J0ICogYXMgYmluRmlsZVV0aWxzIGZyb20gXCJAaWRlbjMvYmluZmlsZXV0aWxzXCI7XG5pbXBvcnQgKiBhcyB6a2V5VXRpbHMgZnJvbSBcIi4vemtleV91dGlscy5qc1wiO1xuaW1wb3J0IHsgZ2V0Q3VydmVGcm9tUSBhcyBnZXRDdXJ2ZSB9IGZyb20gXCIuL2N1cnZlcy5qc1wiO1xuaW1wb3J0ICogYXMgbWlzYyBmcm9tIFwiLi9taXNjLmpzXCI7XG5pbXBvcnQgeyBibGFrZTJiIH0gZnJvbSBcIkBub2JsZS9oYXNoZXMvYmxha2UyYlwiO1xuaW1wb3J0ICogYXMgdXRpbHMgZnJvbSBcIi4vemtleV91dGlscy5qc1wiO1xuaW1wb3J0IHsgaGFzaFRvRzIgYXMgaGFzaFRvRzIgfSBmcm9tIFwiLi9rZXlwYWlyLmpzXCI7XG5pbXBvcnQgeyBhcHBseUtleVRvU2VjdGlvbiB9IGZyb20gXCIuL21wY19hcHBseWtleS5qc1wiO1xuXG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uIGJlYWNvbih6a2V5TmFtZU9sZCwgemtleU5hbWVOZXcsIG5hbWUsIGJlYWNvbkhhc2hTdHIsIG51bUl0ZXJhdGlvbnNFeHAsIGxvZ2dlcikge1xuICAgIGNvbnN0IGJlYWNvbkhhc2ggPSBtaXNjLmhleDJCeXRlQXJyYXkoYmVhY29uSGFzaFN0cik7XG4gICAgaWYgKCAgIChiZWFjb25IYXNoLmJ5dGVMZW5ndGggPT0gMClcbiAgICAgICAgfHwgKGJlYWNvbkhhc2guYnl0ZUxlbmd0aCoyICE9YmVhY29uSGFzaFN0ci5sZW5ndGgpKVxuICAgIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiSW52YWxpZCBCZWFjb24gSGFzaC4gKEl0IG11c3QgYmUgYSB2YWxpZCBoZXhhZGVjaW1hbCBzZXF1ZW5jZSlcIik7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgaWYgKGJlYWNvbkhhc2gubGVuZ3RoPj0yNTYpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiTWF4aW11bSBsZW5ndGggb2YgYmVhY29uIGhhc2ggaXMgMjU1IGJ5dGVzXCIpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgbnVtSXRlcmF0aW9uc0V4cCA9IHBhcnNlSW50KG51bUl0ZXJhdGlvbnNFeHApO1xuICAgIGlmICgobnVtSXRlcmF0aW9uc0V4cDwxMCl8fChudW1JdGVyYXRpb25zRXhwPjYzKSkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJJbnZhbGlkIG51bUl0ZXJhdGlvbnNFeHAuIChNdXN0IGJlIGJldHdlZW4gMTAgYW5kIDYzKVwiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuXG4gICAgY29uc3Qge2ZkOiBmZE9sZCwgc2VjdGlvbnM6IHNlY3Rpb25zfSA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkQmluRmlsZSh6a2V5TmFtZU9sZCwgXCJ6a2V5XCIsIDIpO1xuICAgIGNvbnN0IHprZXkgPSBhd2FpdCB6a2V5VXRpbHMucmVhZEhlYWRlcihmZE9sZCwgc2VjdGlvbnMpO1xuXG4gICAgaWYgKHprZXkucHJvdG9jb2wgIT0gXCJncm90aDE2XCIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiemtleSBmaWxlIGlzIG5vdCBncm90aDE2XCIpO1xuICAgIH1cblxuXG4gICAgY29uc3QgY3VydmUgPSBhd2FpdCBnZXRDdXJ2ZSh6a2V5LnEpO1xuXG4gICAgY29uc3QgbXBjUGFyYW1zID0gYXdhaXQgemtleVV0aWxzLnJlYWRNUENQYXJhbXMoZmRPbGQsIGN1cnZlLCBzZWN0aW9ucyk7XG5cbiAgICBjb25zdCBmZE5ldyA9IGF3YWl0IGJpbkZpbGVVdGlscy5jcmVhdGVCaW5GaWxlKHprZXlOYW1lTmV3LCBcInprZXlcIiwgMSwgMTApO1xuXG4gICAgY29uc3Qgcm5nID0gYXdhaXQgbWlzYy5ybmdGcm9tQmVhY29uUGFyYW1zKGJlYWNvbkhhc2gsIG51bUl0ZXJhdGlvbnNFeHApO1xuXG4gICAgY29uc3QgdHJhbnNjcmlwdEhhc2hlciA9IGJsYWtlMmIuY3JlYXRlKHsgZGtMZW46IDY0IH0pOztcbiAgICB0cmFuc2NyaXB0SGFzaGVyLnVwZGF0ZShtcGNQYXJhbXMuY3NIYXNoKTtcbiAgICBmb3IgKGxldCBpPTA7IGk8bXBjUGFyYW1zLmNvbnRyaWJ1dGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdXRpbHMuaGFzaFB1YktleSh0cmFuc2NyaXB0SGFzaGVyLCBjdXJ2ZSwgbXBjUGFyYW1zLmNvbnRyaWJ1dGlvbnNbaV0pO1xuICAgIH1cblxuICAgIGNvbnN0IGN1ckNvbnRyaWJ1dGlvbiA9IHt9O1xuICAgIGN1ckNvbnRyaWJ1dGlvbi5kZWx0YSA9IHt9O1xuICAgIGN1ckNvbnRyaWJ1dGlvbi5kZWx0YS5wcnZLZXkgPSBjdXJ2ZS5Gci5mcm9tUm5nKHJuZyk7XG4gICAgY3VyQ29udHJpYnV0aW9uLmRlbHRhLmcxX3MgPSBjdXJ2ZS5HMS50b0FmZmluZShjdXJ2ZS5HMS5mcm9tUm5nKHJuZykpO1xuICAgIGN1ckNvbnRyaWJ1dGlvbi5kZWx0YS5nMV9zeCA9IGN1cnZlLkcxLnRvQWZmaW5lKGN1cnZlLkcxLnRpbWVzRnIoY3VyQ29udHJpYnV0aW9uLmRlbHRhLmcxX3MsIGN1ckNvbnRyaWJ1dGlvbi5kZWx0YS5wcnZLZXkpKTtcbiAgICB1dGlscy5oYXNoRzEodHJhbnNjcmlwdEhhc2hlciwgY3VydmUsIGN1ckNvbnRyaWJ1dGlvbi5kZWx0YS5nMV9zKTtcbiAgICB1dGlscy5oYXNoRzEodHJhbnNjcmlwdEhhc2hlciwgY3VydmUsIGN1ckNvbnRyaWJ1dGlvbi5kZWx0YS5nMV9zeCk7XG4gICAgY3VyQ29udHJpYnV0aW9uLnRyYW5zY3JpcHQgPSB0cmFuc2NyaXB0SGFzaGVyLmRpZ2VzdCgpO1xuICAgIGN1ckNvbnRyaWJ1dGlvbi5kZWx0YS5nMl9zcCA9IGhhc2hUb0cyKGN1cnZlLCBjdXJDb250cmlidXRpb24udHJhbnNjcmlwdCk7XG4gICAgY3VyQ29udHJpYnV0aW9uLmRlbHRhLmcyX3NweCA9IGN1cnZlLkcyLnRvQWZmaW5lKGN1cnZlLkcyLnRpbWVzRnIoY3VyQ29udHJpYnV0aW9uLmRlbHRhLmcyX3NwLCBjdXJDb250cmlidXRpb24uZGVsdGEucHJ2S2V5KSk7XG5cbiAgICB6a2V5LnZrX2RlbHRhXzEgPSBjdXJ2ZS5HMS50aW1lc0ZyKHprZXkudmtfZGVsdGFfMSwgY3VyQ29udHJpYnV0aW9uLmRlbHRhLnBydktleSk7XG4gICAgemtleS52a19kZWx0YV8yID0gY3VydmUuRzIudGltZXNGcih6a2V5LnZrX2RlbHRhXzIsIGN1ckNvbnRyaWJ1dGlvbi5kZWx0YS5wcnZLZXkpO1xuXG4gICAgY3VyQ29udHJpYnV0aW9uLmRlbHRhQWZ0ZXIgPSB6a2V5LnZrX2RlbHRhXzE7XG5cbiAgICBjdXJDb250cmlidXRpb24udHlwZSA9IDE7XG4gICAgY3VyQ29udHJpYnV0aW9uLm51bUl0ZXJhdGlvbnNFeHAgPSBudW1JdGVyYXRpb25zRXhwO1xuICAgIGN1ckNvbnRyaWJ1dGlvbi5iZWFjb25IYXNoID0gYmVhY29uSGFzaDtcblxuICAgIGlmIChuYW1lKSBjdXJDb250cmlidXRpb24ubmFtZSA9IG5hbWU7XG5cbiAgICBtcGNQYXJhbXMuY29udHJpYnV0aW9ucy5wdXNoKGN1ckNvbnRyaWJ1dGlvbik7XG5cbiAgICBhd2FpdCB6a2V5VXRpbHMud3JpdGVIZWFkZXIoZmROZXcsIHprZXkpO1xuXG4gICAgLy8gSUNcbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuY29weVNlY3Rpb24oZmRPbGQsIHNlY3Rpb25zLCBmZE5ldywgMyk7XG5cbiAgICAvLyBDb2VmZnMgKEtlZXAgb3JpZ2luYWwpXG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmNvcHlTZWN0aW9uKGZkT2xkLCBzZWN0aW9ucywgZmROZXcsIDQpO1xuXG4gICAgLy8gQSBTZWN0aW9uXG4gICAgYXdhaXQgYmluRmlsZVV0aWxzLmNvcHlTZWN0aW9uKGZkT2xkLCBzZWN0aW9ucywgZmROZXcsIDUpO1xuXG4gICAgLy8gQjEgU2VjdGlvblxuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5jb3B5U2VjdGlvbihmZE9sZCwgc2VjdGlvbnMsIGZkTmV3LCA2KTtcblxuICAgIC8vIEIyIFNlY3Rpb25cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuY29weVNlY3Rpb24oZmRPbGQsIHNlY3Rpb25zLCBmZE5ldywgNyk7XG5cbiAgICBjb25zdCBpbnZEZWx0YSA9IGN1cnZlLkZyLmludihjdXJDb250cmlidXRpb24uZGVsdGEucHJ2S2V5KTtcbiAgICBhd2FpdCBhcHBseUtleVRvU2VjdGlvbihmZE9sZCwgc2VjdGlvbnMsIGZkTmV3LCA4LCBjdXJ2ZSwgXCJHMVwiLCBpbnZEZWx0YSwgY3VydmUuRnIuZSgxKSwgXCJMIFNlY3Rpb25cIiwgbG9nZ2VyKTtcbiAgICBhd2FpdCBhcHBseUtleVRvU2VjdGlvbihmZE9sZCwgc2VjdGlvbnMsIGZkTmV3LCA5LCBjdXJ2ZSwgXCJHMVwiLCBpbnZEZWx0YSwgY3VydmUuRnIuZSgxKSwgXCJIIFNlY3Rpb25cIiwgbG9nZ2VyKTtcblxuICAgIGF3YWl0IHprZXlVdGlscy53cml0ZU1QQ1BhcmFtcyhmZE5ldywgY3VydmUsIG1wY1BhcmFtcyk7XG5cbiAgICBhd2FpdCBmZE9sZC5jbG9zZSgpO1xuICAgIGF3YWl0IGZkTmV3LmNsb3NlKCk7XG5cbiAgICBjb25zdCBjb250cmlidXRpb25IYXNoZXIgPSBibGFrZTJiLmNyZWF0ZSh7IGRrTGVuOiA2NCB9KTs7XG4gICAgdXRpbHMuaGFzaFB1YktleShjb250cmlidXRpb25IYXNoZXIsIGN1cnZlLCBjdXJDb250cmlidXRpb24pO1xuXG4gICAgY29uc3QgY29udHJpYnV0aW9uSGFzaCA9IGNvbnRyaWJ1dGlvbkhhc2hlci5kaWdlc3QoKTtcblxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKG1pc2MuZm9ybWF0SGFzaChjb250cmlidXRpb25IYXNoLCBcIkNvbnRyaWJ1dGlvbiBIYXNoOiBcIikpO1xuXG4gICAgcmV0dXJuIGNvbnRyaWJ1dGlvbkhhc2g7XG59XG4iLCJpbXBvcnQgeyByZWFkWktleSBhcyByZWFkWktleSB9IGZyb20gXCIuL3prZXlfdXRpbHMuanNcIjtcbmltcG9ydCB7IHV0aWxzIH0gZnJvbSBcImZmamF2YXNjcmlwdFwiO1xuXG5leHBvcnQgZGVmYXVsdCBhc3luYyBmdW5jdGlvbiB6a2V5RXhwb3J0SnNvbih6a2V5RmlsZU5hbWUpIHtcblxuICAgIGNvbnN0IHpLZXkgPSBhd2FpdCByZWFkWktleSh6a2V5RmlsZU5hbWUsIHRydWUpO1xuICAgIGRlbGV0ZSB6S2V5LmN1cnZlO1xuICAgIGRlbGV0ZSB6S2V5LkY7XG5cbiAgICByZXR1cm4gdXRpbHMuc3RyaW5naWZ5QmlnSW50cyh6S2V5KTtcbn1cbiIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMTggMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya0pTLlxuXG4gICAgc25hcmtKUyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJrSlMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggc25hcmtKUy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbi8vIEZvcm1hdCBvZiB0aGUgb3V0cHV0XG4vLyAgICAgIEhhc2ggb2YgdGhlIGxhc3QgY29udHJpYnV0aW9uICA2NCBCeXRlc1xuLy8gICAgICAyXk4qMi0xIFRhdUcxIFBvaW50cyAoY29tcHJlc3NlZClcbi8vICAgICAgMl5OIFRhdUcyIFBvaW50cyAoY29tcHJlc3NlZClcbi8vICAgICAgMl5OIEFscGhhVGF1RzEgUG9pbnRzIChjb21wcmVzc2VkKVxuLy8gICAgICAyXk4gQmV0YVRhdUcxIFBvaW50cyAoY29tcHJlc3NlZClcbi8vICAgICAgUHVibGljIEtleVxuLy8gICAgICAgICAgQmV0YUcyIChjb21wcmVzc2VkKVxuLy8gICAgICAgICAgRzEqcyAoY29tcHJlc3NlZClcbi8vICAgICAgICAgIEcxKnMqdGF1IChjb21wcmVzc2VkKVxuLy8gICAgICAgICAgRzEqdCAoY29tcHJlc3NlZClcbi8vICAgICAgICAgIEcxKnQqYWxwaGEgKGNvbXByZXNzZWQpXG4vLyAgICAgICAgICBHMSp1IChjb21wcmVzc2VkKVxuLy8gICAgICAgICAgRzEqdSpiZXRhIChjb21wcmVzc2VkKVxuLy8gICAgICAgICAgRzIqc3AqdGF1IChjb21wcmVzc2VkKVxuLy8gICAgICAgICAgRzIqdHAqYWxwaGEgKGNvbXByZXNzZWQpXG4vLyAgICAgICAgICBHMip1cCpiZXRhIChjb21wcmVzc2VkKVxuXG5pbXBvcnQgKiBhcyBmYXN0RmlsZSBmcm9tIFwiZmFzdGZpbGVcIjtcbmltcG9ydCB7IGJsYWtlMmIgfSBmcm9tIFwiQG5vYmxlL2hhc2hlcy9ibGFrZTJiXCI7XG5pbXBvcnQgKiBhcyB1dGlscyBmcm9tIFwiLi96a2V5X3V0aWxzLmpzXCI7XG5pbXBvcnQgKiBhcyBtaXNjIGZyb20gXCIuL21pc2MuanNcIjtcbmltcG9ydCB7IGFwcGx5S2V5VG9DaGFsbGVuZ2VTZWN0aW9uIH0gZnJvbSBcIi4vbXBjX2FwcGx5a2V5LmpzXCI7XG5pbXBvcnQgeyBoYXNoUHViS2V5IH0gZnJvbSBcIi4vemtleV91dGlscy5qc1wiO1xuaW1wb3J0IHsgaGFzaFRvRzIgYXMgaGFzaFRvRzIgfSBmcm9tIFwiLi9rZXlwYWlyLmpzXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uIGJlbGxtYW5Db250cmlidXRlKGN1cnZlLCBjaGFsbGVuZ2VGaWxlbmFtZSwgcmVzcG9uc2VGaWxlTmFtZSwgZW50cm9weSwgbG9nZ2VyKSB7XG4gICAgY29uc3Qgcm5nID0gYXdhaXQgbWlzYy5nZXRSYW5kb21SbmcoZW50cm9weSk7XG5cbiAgICBjb25zdCBkZWx0YSA9IGN1cnZlLkZyLmZyb21Sbmcocm5nKTtcbiAgICBjb25zdCBpbnZEZWx0YSA9IGN1cnZlLkZyLmludihkZWx0YSk7XG5cbiAgICBjb25zdCBzRzEgPSBjdXJ2ZS5HMS5GLm44KjI7XG4gICAgY29uc3Qgc0cyID0gY3VydmUuRzIuRi5uOCoyO1xuXG4gICAgY29uc3QgZmRGcm9tID0gYXdhaXQgZmFzdEZpbGUucmVhZEV4aXN0aW5nKGNoYWxsZW5nZUZpbGVuYW1lKTtcbiAgICBjb25zdCBmZFRvID0gYXdhaXQgZmFzdEZpbGUuY3JlYXRlT3ZlcnJpZGUocmVzcG9uc2VGaWxlTmFtZSk7XG5cblxuICAgIGF3YWl0IGNvcHkoc0cxKTsgLy8gYWxwaGExXG4gICAgYXdhaXQgY29weShzRzEpOyAvLyBiZXRhMVxuICAgIGF3YWl0IGNvcHkoc0cyKTsgLy8gYmV0YTJcbiAgICBhd2FpdCBjb3B5KHNHMik7IC8vIGdhbW1hMlxuICAgIGNvbnN0IG9sZERlbHRhMSA9IGF3YWl0IHJlYWRHMSgpO1xuICAgIGNvbnN0IGRlbHRhMSA9IGN1cnZlLkcxLnRpbWVzRnIob2xkRGVsdGExLCBkZWx0YSk7XG4gICAgYXdhaXQgd3JpdGVHMShkZWx0YTEpO1xuICAgIGNvbnN0IG9sZERlbHRhMiA9IGF3YWl0IHJlYWRHMigpO1xuICAgIGNvbnN0IGRlbHRhMiA9IGN1cnZlLkcyLnRpbWVzRnIob2xkRGVsdGEyLCBkZWx0YSk7XG4gICAgYXdhaXQgd3JpdGVHMihkZWx0YTIpO1xuXG4gICAgLy8gSUNcbiAgICBjb25zdCBuSUMgPSBhd2FpdCBmZEZyb20ucmVhZFVCRTMyKCk7XG4gICAgYXdhaXQgZmRUby53cml0ZVVCRTMyKG5JQyk7XG4gICAgYXdhaXQgY29weShuSUMqc0cxKTtcblxuICAgIC8vIEhcbiAgICBjb25zdCBuSCA9IGF3YWl0IGZkRnJvbS5yZWFkVUJFMzIoKTtcbiAgICBhd2FpdCBmZFRvLndyaXRlVUJFMzIobkgpO1xuICAgIGF3YWl0IGFwcGx5S2V5VG9DaGFsbGVuZ2VTZWN0aW9uKGZkRnJvbSwgZmRUbywgbnVsbCwgY3VydmUsIFwiRzFcIiwgbkgsIGludkRlbHRhLCBjdXJ2ZS5Gci5lKDEpLCBcIlVOQ09NUFJFU1NFRFwiLCBcIkhcIiwgbG9nZ2VyKTtcblxuICAgIC8vIExcbiAgICBjb25zdCBuTCA9IGF3YWl0IGZkRnJvbS5yZWFkVUJFMzIoKTtcbiAgICBhd2FpdCBmZFRvLndyaXRlVUJFMzIobkwpO1xuICAgIGF3YWl0IGFwcGx5S2V5VG9DaGFsbGVuZ2VTZWN0aW9uKGZkRnJvbSwgZmRUbywgbnVsbCwgY3VydmUsIFwiRzFcIiwgbkwsIGludkRlbHRhLCBjdXJ2ZS5Gci5lKDEpLCBcIlVOQ09NUFJFU1NFRFwiLCBcIkxcIiwgbG9nZ2VyKTtcblxuICAgIC8vIEFcbiAgICBjb25zdCBuQSA9IGF3YWl0IGZkRnJvbS5yZWFkVUJFMzIoKTtcbiAgICBhd2FpdCBmZFRvLndyaXRlVUJFMzIobkEpO1xuICAgIGF3YWl0IGNvcHkobkEqc0cxKTtcblxuICAgIC8vIEIxXG4gICAgY29uc3QgbkIxID0gYXdhaXQgZmRGcm9tLnJlYWRVQkUzMigpO1xuICAgIGF3YWl0IGZkVG8ud3JpdGVVQkUzMihuQjEpO1xuICAgIGF3YWl0IGNvcHkobkIxKnNHMSk7XG5cbiAgICAvLyBCMlxuICAgIGNvbnN0IG5CMiA9IGF3YWl0IGZkRnJvbS5yZWFkVUJFMzIoKTtcbiAgICBhd2FpdCBmZFRvLndyaXRlVUJFMzIobkIyKTtcbiAgICBhd2FpdCBjb3B5KG5CMipzRzIpO1xuXG5cbiAgICAvLy8vLy8vLy8vXG4gICAgLy8vIFJlYWQgY29udHJpYnV0aW9uc1xuICAgIC8vLy8vLy8vLy9cbiAgICBjb25zdCB0cmFuc2NyaXB0SGFzaGVyID0gYmxha2UyYi5jcmVhdGUoeyBka0xlbjogNjQgfSk7O1xuXG4gICAgY29uc3QgbXBjUGFyYW1zID0ge307XG4gICAgLy8gY3NIYXNoXG4gICAgbXBjUGFyYW1zLmNzSGFzaCA9ICBhd2FpdCBmZEZyb20ucmVhZCg2NCk7XG4gICAgdHJhbnNjcmlwdEhhc2hlci51cGRhdGUobXBjUGFyYW1zLmNzSGFzaCk7XG5cbiAgICBjb25zdCBuQ29udHJpYnV0aW9ucyA9IGF3YWl0IGZkRnJvbS5yZWFkVUJFMzIoKTtcbiAgICBtcGNQYXJhbXMuY29udHJpYnV0aW9ucyA9IFtdO1xuICAgIGZvciAobGV0IGk9MDsgaTxuQ29udHJpYnV0aW9uczsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGMgPSB7IGRlbHRhOnt9IH07XG4gICAgICAgIGMuZGVsdGFBZnRlciA9IGF3YWl0IHJlYWRHMSgpO1xuICAgICAgICBjLmRlbHRhLmcxX3MgPSBhd2FpdCByZWFkRzEoKTtcbiAgICAgICAgYy5kZWx0YS5nMV9zeCA9IGF3YWl0IHJlYWRHMSgpO1xuICAgICAgICBjLmRlbHRhLmcyX3NweCA9IGF3YWl0IHJlYWRHMigpO1xuICAgICAgICBjLnRyYW5zY3JpcHQgPSBhd2FpdCBmZEZyb20ucmVhZCg2NCk7XG4gICAgICAgIG1wY1BhcmFtcy5jb250cmlidXRpb25zLnB1c2goYyk7XG4gICAgICAgIGhhc2hQdWJLZXkodHJhbnNjcmlwdEhhc2hlciwgY3VydmUsIGMpO1xuICAgIH1cblxuICAgIGNvbnN0IGN1ckNvbnRyaWJ1dGlvbiA9IHt9O1xuICAgIGN1ckNvbnRyaWJ1dGlvbi5kZWx0YSA9IHt9O1xuICAgIGN1ckNvbnRyaWJ1dGlvbi5kZWx0YS5wcnZLZXkgPSBkZWx0YTtcbiAgICBjdXJDb250cmlidXRpb24uZGVsdGEuZzFfcyA9IGN1cnZlLkcxLnRvQWZmaW5lKGN1cnZlLkcxLmZyb21Sbmcocm5nKSk7XG4gICAgY3VyQ29udHJpYnV0aW9uLmRlbHRhLmcxX3N4ID0gY3VydmUuRzEudG9BZmZpbmUoY3VydmUuRzEudGltZXNGcihjdXJDb250cmlidXRpb24uZGVsdGEuZzFfcywgZGVsdGEpKTtcbiAgICB1dGlscy5oYXNoRzEodHJhbnNjcmlwdEhhc2hlciwgY3VydmUsIGN1ckNvbnRyaWJ1dGlvbi5kZWx0YS5nMV9zKTtcbiAgICB1dGlscy5oYXNoRzEodHJhbnNjcmlwdEhhc2hlciwgY3VydmUsIGN1ckNvbnRyaWJ1dGlvbi5kZWx0YS5nMV9zeCk7XG4gICAgY3VyQ29udHJpYnV0aW9uLnRyYW5zY3JpcHQgPSB0cmFuc2NyaXB0SGFzaGVyLmRpZ2VzdCgpO1xuICAgIGN1ckNvbnRyaWJ1dGlvbi5kZWx0YS5nMl9zcCA9IGhhc2hUb0cyKGN1cnZlLCBjdXJDb250cmlidXRpb24udHJhbnNjcmlwdCk7XG4gICAgY3VyQ29udHJpYnV0aW9uLmRlbHRhLmcyX3NweCA9IGN1cnZlLkcyLnRvQWZmaW5lKGN1cnZlLkcyLnRpbWVzRnIoY3VyQ29udHJpYnV0aW9uLmRlbHRhLmcyX3NwLCBkZWx0YSkpO1xuICAgIGN1ckNvbnRyaWJ1dGlvbi5kZWx0YUFmdGVyID0gZGVsdGExO1xuICAgIGN1ckNvbnRyaWJ1dGlvbi50eXBlID0gMDtcbiAgICBtcGNQYXJhbXMuY29udHJpYnV0aW9ucy5wdXNoKGN1ckNvbnRyaWJ1dGlvbik7XG5cblxuICAgIC8vLy8vLy8vLy9cbiAgICAvLy8gV3JpdGUgQ29udHJpYnV0aW9uXG4gICAgLy8vLy8vLy8vL1xuXG4gICAgYXdhaXQgZmRUby53cml0ZShtcGNQYXJhbXMuY3NIYXNoKTtcbiAgICBhd2FpdCBmZFRvLndyaXRlVUJFMzIobXBjUGFyYW1zLmNvbnRyaWJ1dGlvbnMubGVuZ3RoKTtcblxuICAgIGZvciAobGV0IGk9MDsgaTxtcGNQYXJhbXMuY29udHJpYnV0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBjID0gbXBjUGFyYW1zLmNvbnRyaWJ1dGlvbnNbaV07XG4gICAgICAgIGF3YWl0IHdyaXRlRzEoYy5kZWx0YUFmdGVyKTtcbiAgICAgICAgYXdhaXQgd3JpdGVHMShjLmRlbHRhLmcxX3MpO1xuICAgICAgICBhd2FpdCB3cml0ZUcxKGMuZGVsdGEuZzFfc3gpO1xuICAgICAgICBhd2FpdCB3cml0ZUcyKGMuZGVsdGEuZzJfc3B4KTtcbiAgICAgICAgYXdhaXQgZmRUby53cml0ZShjLnRyYW5zY3JpcHQpO1xuICAgIH1cblxuICAgIGNvbnN0IGNvbnRyaWJ1dGlvbkhhc2hlciA9IGJsYWtlMmIuY3JlYXRlKHsgZGtMZW46IDY0IH0pOztcbiAgICBoYXNoUHViS2V5KGNvbnRyaWJ1dGlvbkhhc2hlciwgY3VydmUsIGN1ckNvbnRyaWJ1dGlvbik7XG5cbiAgICBjb25zdCBjb250cmlidXRpb25IYXNoID0gY29udHJpYnV0aW9uSGFzaGVyLmRpZ2VzdCgpO1xuXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8obWlzYy5mb3JtYXRIYXNoKGNvbnRyaWJ1dGlvbkhhc2gsIFwiQ29udHJpYnV0aW9uIEhhc2g6IFwiKSk7XG5cbiAgICBhd2FpdCBmZFRvLmNsb3NlKCk7XG4gICAgYXdhaXQgZmRGcm9tLmNsb3NlKCk7XG5cbiAgICByZXR1cm4gY29udHJpYnV0aW9uSGFzaDtcblxuICAgIGFzeW5jIGZ1bmN0aW9uIGNvcHkobkJ5dGVzKSB7XG4gICAgICAgIGNvbnN0IENIVU5LX1NJWkUgPSBmZEZyb20ucGFnZVNpemUqMjtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPG5CeXRlczsgaSs9IENIVU5LX1NJWkUpIHtcbiAgICAgICAgICAgIGNvbnN0IG4gPSBNYXRoLm1pbihuQnl0ZXMgLWksIENIVU5LX1NJWkUpO1xuICAgICAgICAgICAgY29uc3QgYnVmZiA9IGF3YWl0IGZkRnJvbS5yZWFkKG4pO1xuICAgICAgICAgICAgYXdhaXQgZmRUby53cml0ZShidWZmKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHJlYWRHMSgpIHtcbiAgICAgICAgY29uc3QgYnVmZiA9IGF3YWl0IGZkRnJvbS5yZWFkKGN1cnZlLkcxLkYubjgqMik7XG4gICAgICAgIHJldHVybiBjdXJ2ZS5HMS5mcm9tUnByVW5jb21wcmVzc2VkKGJ1ZmYsIDApO1xuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHJlYWRHMigpIHtcbiAgICAgICAgY29uc3QgYnVmZiA9IGF3YWl0IGZkRnJvbS5yZWFkKGN1cnZlLkcyLkYubjgqMik7XG4gICAgICAgIHJldHVybiBjdXJ2ZS5HMi5mcm9tUnByVW5jb21wcmVzc2VkKGJ1ZmYsIDApO1xuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHdyaXRlRzEoUCkge1xuICAgICAgICBjb25zdCBidWZmID0gbmV3IFVpbnQ4QXJyYXkoc0cxKTtcbiAgICAgICAgY3VydmUuRzEudG9ScHJVbmNvbXByZXNzZWQoYnVmZiwgMCwgUCk7XG4gICAgICAgIGF3YWl0IGZkVG8ud3JpdGUoYnVmZik7XG4gICAgfVxuXG4gICAgYXN5bmMgZnVuY3Rpb24gd3JpdGVHMihQKSB7XG4gICAgICAgIGNvbnN0IGJ1ZmYgPSBuZXcgVWludDhBcnJheShzRzIpO1xuICAgICAgICBjdXJ2ZS5HMi50b1JwclVuY29tcHJlc3NlZChidWZmLCAwLCBQKTtcbiAgICAgICAgYXdhaXQgZmRUby53cml0ZShidWZmKTtcbiAgICB9XG5cblxufVxuIiwiLypcbiAgICBDb3B5cmlnaHQgMjAxOCAwS0lNUyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJrSlMuXG5cbiAgICBzbmFya0pTIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdFxuICAgIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gICAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAgICAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtKUyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVFxuICAgIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpY1xuICAgIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gICAgYWxvbmcgd2l0aCBzbmFya0pTLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuaW1wb3J0ICogYXMgYmluRmlsZVV0aWxzIGZyb20gXCJAaWRlbjMvYmluZmlsZXV0aWxzXCI7XG5pbXBvcnQgKiBhcyB6a2V5VXRpbHMgZnJvbSBcIi4vemtleV91dGlscy5qc1wiO1xuaW1wb3J0IHtnZXRDdXJ2ZUZyb21RIGFzIGdldEN1cnZlfSBmcm9tIFwiLi9jdXJ2ZXMuanNcIjtcbmltcG9ydCB7dXRpbHN9IGZyb20gXCJmZmphdmFzY3JpcHRcIjtcbmltcG9ydCB7RkZMT05LX1BST1RPQ09MX0lEfSBmcm9tIFwiLi96a2V5X2NvbnN0YW50cy5qc1wiO1xuXG5jb25zdCB7c3RyaW5naWZ5QmlnSW50c30gPSB1dGlscztcblxuZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gemtleUV4cG9ydFZlcmlmaWNhdGlvbktleSh6a2V5TmFtZSwgbG9nZ2VyKSB7XG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCJFWFBPUlQgVkVSSUZJQ0FUSU9OIEtFWSBTVEFSVEVEXCIpO1xuXG4gICAgY29uc3Qge2ZkLCBzZWN0aW9uc30gPSBhd2FpdCBiaW5GaWxlVXRpbHMucmVhZEJpbkZpbGUoemtleU5hbWUsIFwiemtleVwiLCAyKTtcbiAgICBjb25zdCB6a2V5ID0gYXdhaXQgemtleVV0aWxzLnJlYWRIZWFkZXIoZmQsIHNlY3Rpb25zKTtcblxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBEZXRlY3RlZCBwcm90b2NvbDogXCIgKyB6a2V5LnByb3RvY29sKTtcblxuICAgIGxldCByZXM7XG4gICAgaWYgKHprZXkucHJvdG9jb2wgPT09IFwiZ3JvdGgxNlwiKSB7XG4gICAgICAgIHJlcyA9IGF3YWl0IGdyb3RoMTZWayh6a2V5LCBmZCwgc2VjdGlvbnMpO1xuICAgIH0gZWxzZSBpZiAoemtleS5wcm90b2NvbCA9PT0gXCJwbG9ua1wiKSB7XG4gICAgICAgIHJlcyA9IGF3YWl0IHBsb25rVmsoemtleSk7XG4gICAgfSBlbHNlIGlmICh6a2V5LnByb3RvY29sSWQgJiYgemtleS5wcm90b2NvbElkID09PSBGRkxPTktfUFJPVE9DT0xfSUQpIHtcbiAgICAgICAgcmVzID0gYXdhaXQgZXhwb3J0RkZsb25rVmsoemtleSwgbG9nZ2VyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ6a2V5IGZpbGUgcHJvdG9jb2wgdW5yZWNvZ25pemVkXCIpO1xuICAgIH1cblxuICAgIGF3YWl0IGZkLmNsb3NlKCk7XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIkVYUE9SVCBWRVJJRklDQVRJT04gS0VZIEZJTklTSEVEXCIpO1xuXG4gICAgcmV0dXJuIHJlcztcbn1cblxuXG5hc3luYyBmdW5jdGlvbiBncm90aDE2VmsoemtleSwgZmQsIHNlY3Rpb25zKSB7XG4gICAgY29uc3QgY3VydmUgPSBhd2FpdCBnZXRDdXJ2ZSh6a2V5LnEpO1xuICAgIGNvbnN0IHNHMSA9IGN1cnZlLkcxLkYubjggKiAyO1xuXG4gICAgY29uc3QgYWxwaGFCZXRhID0gYXdhaXQgY3VydmUucGFpcmluZyh6a2V5LnZrX2FscGhhXzEsIHprZXkudmtfYmV0YV8yKTtcblxuICAgIGxldCB2S2V5ID0ge1xuICAgICAgICBwcm90b2NvbDogemtleS5wcm90b2NvbCxcbiAgICAgICAgY3VydmU6IGN1cnZlLm5hbWUsXG4gICAgICAgIG5QdWJsaWM6IHprZXkublB1YmxpYyxcblxuICAgICAgICB2a19hbHBoYV8xOiBjdXJ2ZS5HMS50b09iamVjdCh6a2V5LnZrX2FscGhhXzEpLFxuXG4gICAgICAgIHZrX2JldGFfMjogY3VydmUuRzIudG9PYmplY3QoemtleS52a19iZXRhXzIpLFxuICAgICAgICB2a19nYW1tYV8yOiBjdXJ2ZS5HMi50b09iamVjdCh6a2V5LnZrX2dhbW1hXzIpLFxuICAgICAgICB2a19kZWx0YV8yOiBjdXJ2ZS5HMi50b09iamVjdCh6a2V5LnZrX2RlbHRhXzIpLFxuXG4gICAgICAgIHZrX2FscGhhYmV0YV8xMjogY3VydmUuR3QudG9PYmplY3QoYWxwaGFCZXRhKVxuICAgIH07XG5cbiAgICAvLyBSZWFkIElDIFNlY3Rpb25cbiAgICAvLy8vLy8vLy8vL1xuICAgIGF3YWl0IGJpbkZpbGVVdGlscy5zdGFydFJlYWRVbmlxdWVTZWN0aW9uKGZkLCBzZWN0aW9ucywgMyk7XG4gICAgdktleS5JQyA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDw9IHprZXkublB1YmxpYzsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGJ1ZmYgPSBhd2FpdCBmZC5yZWFkKHNHMSk7XG4gICAgICAgIGNvbnN0IFAgPSBjdXJ2ZS5HMS50b09iamVjdChidWZmKTtcbiAgICAgICAgdktleS5JQy5wdXNoKFApO1xuICAgIH1cbiAgICBhd2FpdCBiaW5GaWxlVXRpbHMuZW5kUmVhZFNlY3Rpb24oZmQpO1xuXG4gICAgdktleSA9IHN0cmluZ2lmeUJpZ0ludHModktleSk7XG5cbiAgICByZXR1cm4gdktleTtcbn1cblxuXG5hc3luYyBmdW5jdGlvbiBwbG9ua1ZrKHprZXkpIHtcbiAgICBjb25zdCBjdXJ2ZSA9IGF3YWl0IGdldEN1cnZlKHprZXkucSk7XG5cbiAgICBsZXQgdktleSA9IHtcbiAgICAgICAgcHJvdG9jb2w6IHprZXkucHJvdG9jb2wsXG4gICAgICAgIGN1cnZlOiBjdXJ2ZS5uYW1lLFxuICAgICAgICBuUHVibGljOiB6a2V5Lm5QdWJsaWMsXG4gICAgICAgIHBvd2VyOiB6a2V5LnBvd2VyLFxuXG4gICAgICAgIGsxOiBjdXJ2ZS5Gci50b09iamVjdCh6a2V5LmsxKSxcbiAgICAgICAgazI6IGN1cnZlLkZyLnRvT2JqZWN0KHprZXkuazIpLFxuXG4gICAgICAgIFFtOiBjdXJ2ZS5HMS50b09iamVjdCh6a2V5LlFtKSxcbiAgICAgICAgUWw6IGN1cnZlLkcxLnRvT2JqZWN0KHprZXkuUWwpLFxuICAgICAgICBRcjogY3VydmUuRzEudG9PYmplY3QoemtleS5RciksXG4gICAgICAgIFFvOiBjdXJ2ZS5HMS50b09iamVjdCh6a2V5LlFvKSxcbiAgICAgICAgUWM6IGN1cnZlLkcxLnRvT2JqZWN0KHprZXkuUWMpLFxuICAgICAgICBTMTogY3VydmUuRzEudG9PYmplY3QoemtleS5TMSksXG4gICAgICAgIFMyOiBjdXJ2ZS5HMS50b09iamVjdCh6a2V5LlMyKSxcbiAgICAgICAgUzM6IGN1cnZlLkcxLnRvT2JqZWN0KHprZXkuUzMpLFxuXG4gICAgICAgIFhfMjogY3VydmUuRzIudG9PYmplY3QoemtleS5YXzIpLFxuXG4gICAgICAgIHc6IGN1cnZlLkZyLnRvT2JqZWN0KGN1cnZlLkZyLndbemtleS5wb3dlcl0pXG4gICAgfTtcblxuICAgIHZLZXkgPSBzdHJpbmdpZnlCaWdJbnRzKHZLZXkpO1xuXG4gICAgcmV0dXJuIHZLZXk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGV4cG9ydEZGbG9ua1ZrKHprZXksIGxvZ2dlcikge1xuICAgIGNvbnN0IGN1cnZlID0gYXdhaXQgZ2V0Q3VydmUoemtleS5xKTtcblxuICAgIGxldCB2S2V5ID0ge1xuICAgICAgICBwcm90b2NvbDogemtleS5wcm90b2NvbCxcbiAgICAgICAgY3VydmU6IGN1cnZlLm5hbWUsXG4gICAgICAgIG5QdWJsaWM6IHprZXkublB1YmxpYyxcbiAgICAgICAgcG93ZXI6IHprZXkucG93ZXIsXG5cbiAgICAgICAgazE6IGN1cnZlLkZyLnRvT2JqZWN0KHprZXkuazEpLFxuICAgICAgICBrMjogY3VydmUuRnIudG9PYmplY3QoemtleS5rMiksXG5cbiAgICAgICAgdzogY3VydmUuRnIudG9PYmplY3QoY3VydmUuRnIud1t6a2V5LnBvd2VyXSksXG4gICAgICAgIC8vd1c6IGN1cnZlLkZyLnRvT2JqZWN0KGN1cnZlLkZyLndbemtleS5wb3dlciArIDFdKSxcbiAgICAgICAgdzM6IGN1cnZlLkZyLnRvT2JqZWN0KHprZXkudzMpLFxuICAgICAgICB3NDogY3VydmUuRnIudG9PYmplY3QoemtleS53NCksXG4gICAgICAgIHc4OiBjdXJ2ZS5Gci50b09iamVjdCh6a2V5Lnc4KSxcbiAgICAgICAgd3I6IGN1cnZlLkZyLnRvT2JqZWN0KHprZXkud3IpLFxuXG4gICAgICAgIFhfMjogY3VydmUuRzIudG9PYmplY3QoemtleS5YXzIpLFxuXG4gICAgICAgIEMwOiBjdXJ2ZS5HMS50b09iamVjdCh6a2V5LkMwKSxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHN0cmluZ2lmeUJpZ0ludHModktleSk7XG59XG4iLCIvKlxuICAgIENvcHlyaWdodCAyMDIxIDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygc25hcmtKUy5cblxuICAgIHNuYXJrSlMgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gICAgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAgICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICAgIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICBzbmFya0pTIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHNuYXJrSlMuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG5pbXBvcnQge2dldEN1cnZlRnJvbU5hbWV9IGZyb20gXCIuL2N1cnZlcy5qc1wiO1xuaW1wb3J0IHt1dGlsc30gZnJvbSBcImZmamF2YXNjcmlwdFwiO1xuXG5jb25zdCB7dW5zdHJpbmdpZnlCaWdJbnRzLCBzdHJpbmdpZnlCaWdJbnRzfSA9IHV0aWxzO1xuXG5leHBvcnQgZGVmYXVsdCBhc3luYyBmdW5jdGlvbiBmZmxvbmtFeHBvcnRTb2xpZGl0eVZlcmlmaWVyKHZrLCB0ZW1wbGF0ZXMsIGxvZ2dlcikge1xuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiRkZMT05LIEVYUE9SVCBTT0xJRElUWSBWRVJJRklFUiBTVEFSVEVEXCIpO1xuXG4gICAgY29uc3QgY3VydmUgPSBhd2FpdCBnZXRDdXJ2ZUZyb21OYW1lKHZrLmN1cnZlKTtcblxuICAgIC8vIFByZWNvbXB1dGUgdzNfMiwgdzRfMiBhbmQgdzRfM1xuICAgIGxldCB3MyA9IGZyb21Wa2V5KHZrLnczKTtcbiAgICB2ay53M18yID0gdG9Wa2V5KGN1cnZlLkZyLnNxdWFyZSh3MykpO1xuXG4gICAgbGV0IHc0ID0gZnJvbVZrZXkodmsudzQpO1xuICAgIHZrLnc0XzIgPSB0b1ZrZXkoY3VydmUuRnIuc3F1YXJlKHc0KSk7XG4gICAgdmsudzRfMyA9IHRvVmtleShjdXJ2ZS5Gci5tdWwoY3VydmUuRnIuc3F1YXJlKHc0KSwgdzQpKTtcblxuICAgIGxldCB3OCA9IGZyb21Wa2V5KHZrLnc4KTtcbiAgICBsZXQgYWNjID0gY3VydmUuRnIub25lO1xuXG4gICAgZm9yIChsZXQgaSA9IDE7IGkgPCA4OyBpKyspIHtcbiAgICAgICAgYWNjID0gY3VydmUuRnIubXVsKGFjYywgdzgpO1xuICAgICAgICB2a1tcInc4X1wiICsgaV0gPSB0b1ZrZXkoYWNjKTtcbiAgICB9XG5cbiAgICBsZXQgdGVtcGxhdGUgPSB0ZW1wbGF0ZXNbdmsucHJvdG9jb2xdO1xuXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCJGRkxPTksgRVhQT1JUIFNPTElESVRZIFZFUklGSUVSIEZJTklTSEVEXCIpO1xuXG4gICAgY29uc3Qge2RlZmF1bHQ6IGVqc30gPSBhd2FpdCBpbXBvcnQoXCJlanNcIik7XG4gICAgcmV0dXJuIGVqcy5yZW5kZXIodGVtcGxhdGUsIHZrKTtcblxuICAgIGZ1bmN0aW9uIGZyb21Wa2V5KHN0cikge1xuICAgICAgICBjb25zdCB2YWwgPSB1bnN0cmluZ2lmeUJpZ0ludHMoc3RyKTtcbiAgICAgICAgcmV0dXJuIGN1cnZlLkZyLmZyb21PYmplY3QodmFsKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0b1ZrZXkodmFsKSB7XG4gICAgICAgIGNvbnN0IHN0ciA9IGN1cnZlLkZyLnRvT2JqZWN0KHZhbCk7XG4gICAgICAgIHJldHVybiBzdHJpbmdpZnlCaWdJbnRzKHN0cik7XG4gICAgfVxufVxuXG4iLCJpbXBvcnQgZXhwb3J0VmVyaWZpY2F0aW9uS2V5IGZyb20gXCIuL3prZXlfZXhwb3J0X3ZlcmlmaWNhdGlvbmtleS5qc1wiO1xuaW1wb3J0IGZmbG9ua0V4cG9ydFNvbGlkaXR5VmVyaWZpZXJDbWQgZnJvbSBcIi4vZmZsb25rX2V4cG9ydF9zb2xpZGl0eV92ZXJpZmllci5qc1wiO1xuLy8gTm90IHJlYWR5IHlldFxuLy8gbW9kdWxlLmV4cG9ydHMuZ2VuZXJhdGVWZXJpZmllcl9raW1sZWVvaCA9IGdlbmVyYXRlVmVyaWZpZXJfa2ltbGVlb2g7XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uIGV4cG9ydFNvbGlkaXR5VmVyaWZpZXIoektleU5hbWUsIHRlbXBsYXRlcywgbG9nZ2VyKSB7XG5cbiAgICBjb25zdCB2ZXJpZmljYXRpb25LZXkgPSBhd2FpdCBleHBvcnRWZXJpZmljYXRpb25LZXkoektleU5hbWUsIGxvZ2dlcik7XG5cbiAgICBpZiAoXCJmZmxvbmtcIiA9PT0gdmVyaWZpY2F0aW9uS2V5LnByb3RvY29sKSB7XG4gICAgICAgIHJldHVybiBmZmxvbmtFeHBvcnRTb2xpZGl0eVZlcmlmaWVyQ21kKHZlcmlmaWNhdGlvbktleSwgdGVtcGxhdGVzLCBsb2dnZXIpO1xuICAgIH1cblxuICAgIGxldCB0ZW1wbGF0ZSA9IHRlbXBsYXRlc1t2ZXJpZmljYXRpb25LZXkucHJvdG9jb2xdO1xuXG4gICAgY29uc3Qge2RlZmF1bHQ6IGVqc30gPSBhd2FpdCBpbXBvcnQoXCJlanNcIik7XG5cbiAgICByZXR1cm4gZWpzLnJlbmRlcih0ZW1wbGF0ZSwgdmVyaWZpY2F0aW9uS2V5KTtcbn1cbiIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMTggMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya0pTLlxuXG4gICAgc25hcmtKUyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJrSlMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggc25hcmtKUy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cblxuZXhwb3J0IHtkZWZhdWx0IGFzIG5ld1pLZXl9IGZyb20gXCIuL3prZXlfbmV3LmpzXCI7XG5leHBvcnQge2RlZmF1bHQgYXMgZXhwb3J0QmVsbG1hbn0gZnJvbSBcIi4vemtleV9leHBvcnRfYmVsbG1hbi5qc1wiO1xuZXhwb3J0IHtkZWZhdWx0IGFzIGltcG9ydEJlbGxtYW59IGZyb20gXCIuL3prZXlfaW1wb3J0X2JlbGxtYW4uanNcIjtcbmV4cG9ydCB7ZGVmYXVsdCBhcyB2ZXJpZnlGcm9tUjFjc30gZnJvbSBcIi4vemtleV92ZXJpZnlfZnJvbXIxY3MuanNcIjtcbmV4cG9ydCB7ZGVmYXVsdCBhcyB2ZXJpZnlGcm9tSW5pdH0gZnJvbSBcIi4vemtleV92ZXJpZnlfZnJvbWluaXQuanNcIjtcbmV4cG9ydCB7ZGVmYXVsdCBhcyBjb250cmlidXRlfSBmcm9tIFwiLi96a2V5X2NvbnRyaWJ1dGUuanNcIjtcbmV4cG9ydCB7ZGVmYXVsdCBhcyBiZWFjb259IGZyb20gXCIuL3prZXlfYmVhY29uLmpzXCI7XG5leHBvcnQge2RlZmF1bHQgYXMgZXhwb3J0SnNvbn0gZnJvbSBcIi4vemtleV9leHBvcnRfanNvbi5qc1wiO1xuZXhwb3J0IHtkZWZhdWx0IGFzIGJlbGxtYW5Db250cmlidXRlfSBmcm9tIFwiLi96a2V5X2JlbGxtYW5fY29udHJpYnV0ZS5qc1wiO1xuZXhwb3J0IHtkZWZhdWx0IGFzIGV4cG9ydFZlcmlmaWNhdGlvbktleX0gZnJvbSBcIi4vemtleV9leHBvcnRfdmVyaWZpY2F0aW9ua2V5LmpzXCI7XG5leHBvcnQge2RlZmF1bHQgYXMgZXhwb3J0U29saWRpdHlWZXJpZmllcn0gZnJvbSBcIi4vemtleV9leHBvcnRfc29saWRpdHl2ZXJpZmllci5qc1wiO1xuIiwiLypcbiAgICBDb3B5cmlnaHQgMjAyMSAwa2ltcyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJranMuXG5cbiAgICBzbmFya2pzIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4gICAgbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZVxuICAgIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKVxuICAgIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtqcyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICAgIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvclxuICAgIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFsb25nIHdpdGhcbiAgICBzbmFya2pzLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuLyogSW1wbGVtZW50YXRpb24gb2YgdGhpcyBwYXBlcjogaHR0cHM6Ly9lcHJpbnQuaWFjci5vcmcvMjAxOS85NTMucGRmICovXG5cbmltcG9ydCB7cmVhZFIxY3NGZH0gZnJvbSBcInIxY3NmaWxlXCI7XG5pbXBvcnQgKiBhcyB1dGlscyBmcm9tIFwiLi9wb3dlcnNvZnRhdV91dGlscy5qc1wiO1xuaW1wb3J0IHtcbiAgICByZWFkQmluRmlsZSxcbiAgICBjcmVhdGVCaW5GaWxlLFxuICAgIHJlYWRTZWN0aW9uLFxuICAgIHdyaXRlQmlnSW50LFxuICAgIHN0YXJ0V3JpdGVTZWN0aW9uLFxuICAgIGVuZFdyaXRlU2VjdGlvbixcbn0gZnJvbSBcIkBpZGVuMy9iaW5maWxldXRpbHNcIjtcbmltcG9ydCB7IGxvZzIgIH0gZnJvbSBcIi4vbWlzYy5qc1wiO1xuaW1wb3J0IHsgU2NhbGFyLCBCaWdCdWZmZXIgfSBmcm9tIFwiZmZqYXZhc2NyaXB0XCI7XG5pbXBvcnQgQmlnQXJyYXkgZnJvbSBcIi4vYmlnYXJyYXkuanNcIjtcblxuXG5leHBvcnQgZGVmYXVsdCBhc3luYyBmdW5jdGlvbiBwbG9ua1NldHVwKHIxY3NOYW1lLCBwdGF1TmFtZSwgemtleU5hbWUsIGxvZ2dlcikge1xuXG4gICAgaWYgKGdsb2JhbFRoaXMuZ2MpIHtnbG9iYWxUaGlzLmdjKCk7fVxuXG4gICAgY29uc3Qge2ZkOiBmZFBUYXUsIHNlY3Rpb25zOiBzZWN0aW9uc1BUYXV9ID0gYXdhaXQgcmVhZEJpbkZpbGUocHRhdU5hbWUsIFwicHRhdVwiLCAxLCAxPDwyMiwgMTw8MjQpO1xuICAgIGNvbnN0IHtjdXJ2ZSwgcG93ZXJ9ID0gYXdhaXQgdXRpbHMucmVhZFBUYXVIZWFkZXIoZmRQVGF1LCBzZWN0aW9uc1BUYXUpO1xuICAgIGNvbnN0IHtmZDogZmRSMWNzLCBzZWN0aW9uczogc2VjdGlvbnNSMWNzfSA9IGF3YWl0IHJlYWRCaW5GaWxlKHIxY3NOYW1lLCBcInIxY3NcIiwgMSwgMTw8MjIsIDE8PDI0KTtcblxuICAgIGNvbnN0IHIxY3MgPSBhd2FpdCByZWFkUjFjc0ZkKGZkUjFjcywgc2VjdGlvbnNSMWNzLCB7bG9hZENvbnN0cmFpbnRzOiB0cnVlLCBsb2FkQ3VzdG9tR2F0ZXM6IHRydWV9KTtcblxuICAgIGNvbnN0IHNHMSA9IGN1cnZlLkcxLkYubjgqMjtcbiAgICBjb25zdCBHMSA9IGN1cnZlLkcxO1xuICAgIGNvbnN0IHNHMiA9IGN1cnZlLkcyLkYubjgqMjtcbiAgICBjb25zdCBGciA9IGN1cnZlLkZyO1xuICAgIGNvbnN0IG44ciA9IGN1cnZlLkZyLm44O1xuXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCJSZWFkaW5nIHIxY3NcIik7XG4gICAgbGV0IHNSMWNzID0gYXdhaXQgcmVhZFNlY3Rpb24oZmRSMWNzLCBzZWN0aW9uc1IxY3MsIDIpO1xuXG4gICAgY29uc3QgcGxvbmtDb25zdHJhaW50cyA9IG5ldyBCaWdBcnJheSgpO1xuICAgIGNvbnN0IHBsb25rQWRkaXRpb25zID0gbmV3IEJpZ0FycmF5KCk7XG4gICAgbGV0IHBsb25rTlZhcnMgPSByMWNzLm5WYXJzO1xuXG4gICAgY29uc3QgblB1YmxpYyA9IHIxY3Mubk91dHB1dHMgKyByMWNzLm5QdWJJbnB1dHM7XG5cbiAgICBhd2FpdCBwcm9jZXNzQ29uc3RyYWludHMoY3VydmUuRnIsIHIxY3MsIGxvZ2dlcik7XG5cbiAgICBpZiAoZ2xvYmFsVGhpcy5nYykge2dsb2JhbFRoaXMuZ2MoKTt9XG5cbiAgICBjb25zdCBmZFpLZXkgPSBhd2FpdCBjcmVhdGVCaW5GaWxlKHprZXlOYW1lLCBcInprZXlcIiwgMSwgMTQsIDE8PDIyLCAxPDwyNCk7XG5cblxuICAgIGlmIChyMWNzLnByaW1lICE9IGN1cnZlLnIpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwicjFjcyBjdXJ2ZSBkb2VzIG5vdCBtYXRjaCBwb3dlcnMgb2YgdGF1IGNlcmVtb255IGN1cnZlXCIpO1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgbGV0IGNpclBvd2VyID0gbG9nMihwbG9ua0NvbnN0cmFpbnRzLmxlbmd0aCAtMSkgKzE7XG4gICAgaWYgKGNpclBvd2VyIDwgMykgY2lyUG93ZXIgPSAzOyAgIC8vIEFzIHRoZSB0IHBvbHlub21pYWwgaXMgbis1IHdlIG5lZWQgYXQgbGVhc3QgYSBwb3dlciBvZiA0XG4gICAgY29uc3QgZG9tYWluU2l6ZSA9IDIgKiogY2lyUG93ZXI7XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIlBsb25rIGNvbnN0cmFpbnRzOiBcIiArIHBsb25rQ29uc3RyYWludHMubGVuZ3RoKTtcbiAgICBpZiAoY2lyUG93ZXIgPiBwb3dlcikge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoYGNpcmN1aXQgdG9vIGJpZyBmb3IgdGhpcyBwb3dlciBvZiB0YXUgY2VyZW1vbnkuICR7cGxvbmtDb25zdHJhaW50cy5sZW5ndGh9ID4gMioqJHtwb3dlcn1gKTtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgIH1cblxuICAgIGlmICghc2VjdGlvbnNQVGF1WzEyXSkge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJQb3dlcnMgb2YgdGF1IGlzIG5vdCBwcmVwYXJlZC5cIik7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICB9XG5cblxuICAgIGNvbnN0IExQb2ludHMgPSBuZXcgQmlnQnVmZmVyKGRvbWFpblNpemUqc0cxKTtcbiAgICBjb25zdCBvID0gc2VjdGlvbnNQVGF1WzEyXVswXS5wICsgKCgyICoqIChjaXJQb3dlcikpIC0xKSpzRzE7XG4gICAgYXdhaXQgZmRQVGF1LnJlYWRUb0J1ZmZlcihMUG9pbnRzLCAwLCBkb21haW5TaXplKnNHMSwgbyk7XG5cbiAgICBjb25zdCBbazEsIGsyXSA9IGdldEsxSzIoKTtcblxuICAgIGNvbnN0IHZrID0ge307XG5cblxuICAgIGF3YWl0IHdyaXRlQWRkaXRpb25zKDMsIFwiQWRkaXRpb25zXCIpO1xuICAgIGlmIChnbG9iYWxUaGlzLmdjKSB7Z2xvYmFsVGhpcy5nYygpO31cbiAgICBhd2FpdCB3cml0ZVdpdG5lc3NNYXAoNCwgMCwgXCJBbWFwXCIpO1xuICAgIGlmIChnbG9iYWxUaGlzLmdjKSB7Z2xvYmFsVGhpcy5nYygpO31cbiAgICBhd2FpdCB3cml0ZVdpdG5lc3NNYXAoNSwgMSwgXCJCbWFwXCIpO1xuICAgIGlmIChnbG9iYWxUaGlzLmdjKSB7Z2xvYmFsVGhpcy5nYygpO31cbiAgICBhd2FpdCB3cml0ZVdpdG5lc3NNYXAoNiwgMiwgXCJDbWFwXCIpO1xuICAgIGlmIChnbG9iYWxUaGlzLmdjKSB7Z2xvYmFsVGhpcy5nYygpO31cbiAgICBhd2FpdCB3cml0ZVFNYXAoNywgMywgXCJRbVwiKTtcbiAgICBpZiAoZ2xvYmFsVGhpcy5nYykge2dsb2JhbFRoaXMuZ2MoKTt9XG4gICAgYXdhaXQgd3JpdGVRTWFwKDgsIDQsIFwiUWxcIik7XG4gICAgaWYgKGdsb2JhbFRoaXMuZ2MpIHtnbG9iYWxUaGlzLmdjKCk7fVxuICAgIGF3YWl0IHdyaXRlUU1hcCg5LCA1LCBcIlFyXCIpO1xuICAgIGlmIChnbG9iYWxUaGlzLmdjKSB7Z2xvYmFsVGhpcy5nYygpO31cbiAgICBhd2FpdCB3cml0ZVFNYXAoMTAsIDYsIFwiUW9cIik7XG4gICAgaWYgKGdsb2JhbFRoaXMuZ2MpIHtnbG9iYWxUaGlzLmdjKCk7fVxuICAgIGF3YWl0IHdyaXRlUU1hcCgxMSwgNywgXCJRY1wiKTtcbiAgICBpZiAoZ2xvYmFsVGhpcy5nYykge2dsb2JhbFRoaXMuZ2MoKTt9XG4gICAgYXdhaXQgd3JpdGVTaWdtYSgxMiwgXCJzaWdtYVwiKTtcbiAgICBpZiAoZ2xvYmFsVGhpcy5nYykge2dsb2JhbFRoaXMuZ2MoKTt9XG4gICAgYXdhaXQgd3JpdGVMcygxMywgXCJsYWdyYW5nZSBwb2x5bm9taWFsc1wiKTtcbiAgICBpZiAoZ2xvYmFsVGhpcy5nYykge2dsb2JhbFRoaXMuZ2MoKTt9XG5cbiAgICAvLyBXcml0ZSBQVGF1IHBvaW50c1xuICAgIC8vLy8vLy8vLy8vL1xuXG4gICAgYXdhaXQgc3RhcnRXcml0ZVNlY3Rpb24oZmRaS2V5LCAxNCk7XG4gICAgY29uc3QgYnVmZk91dCA9IG5ldyBCaWdCdWZmZXIoKGRvbWFpblNpemUrNikqc0cxKTtcbiAgICBhd2FpdCBmZFBUYXUucmVhZFRvQnVmZmVyKGJ1ZmZPdXQsIDAsIChkb21haW5TaXplKzYpKnNHMSwgc2VjdGlvbnNQVGF1WzJdWzBdLnApO1xuICAgIGF3YWl0IGZkWktleS53cml0ZShidWZmT3V0KTtcbiAgICBhd2FpdCBlbmRXcml0ZVNlY3Rpb24oZmRaS2V5KTtcbiAgICBpZiAoZ2xvYmFsVGhpcy5nYykge2dsb2JhbFRoaXMuZ2MoKTt9XG5cblxuICAgIGF3YWl0IHdyaXRlSGVhZGVycygpO1xuXG4gICAgYXdhaXQgZmRaS2V5LmNsb3NlKCk7XG4gICAgYXdhaXQgZmRSMWNzLmNsb3NlKCk7XG4gICAgYXdhaXQgZmRQVGF1LmNsb3NlKCk7XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIlNldHVwIEZpbmlzaGVkXCIpO1xuXG4gICAgcmV0dXJuIDtcblxuICAgIGFzeW5jIGZ1bmN0aW9uIHByb2Nlc3NDb25zdHJhaW50cyhGciwgcjFjcywgbG9nZ2VyKSB7XG5cbiAgICAgICAgZnVuY3Rpb24gbm9ybWFsaXplKGxpbmVhckNvbWIpIHtcbiAgICAgICAgICAgIGNvbnN0IHNzID0gT2JqZWN0LmtleXMobGluZWFyQ29tYik7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGxpbmVhckNvbWJbc3NbaV1dID09IDBuKSBkZWxldGUgbGluZWFyQ29tYltzc1tpXV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBqb2luKGxpbmVhckNvbWIxLCBrLCBsaW5lYXJDb21iMikge1xuICAgICAgICAgICAgY29uc3QgcmVzID0ge307XG5cbiAgICAgICAgICAgIGZvciAobGV0IHMgaW4gbGluZWFyQ29tYjEpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHJlc1tzXSA9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc1tzXSA9IEZyLm11bChrLCBsaW5lYXJDb21iMVtzXSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzW3NdID0gRnIuYWRkKHJlc1tzXSwgRnIubXVsKGssIGxpbmVhckNvbWIxW3NdKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IgKGxldCBzIGluIGxpbmVhckNvbWIyKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiByZXNbc10gPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgICAgICAgICByZXNbc10gPSBsaW5lYXJDb21iMltzXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXNbc10gPSBGci5hZGQocmVzW3NdLCBsaW5lYXJDb21iMltzXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbm9ybWFsaXplKHJlcyk7XG4gICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gcmVkdWNlQ29lZnMobGluZWFyQ29tYiwgbWF4Qykge1xuICAgICAgICAgICAgY29uc3QgcmVzID0ge1xuICAgICAgICAgICAgICAgIGs6IEZyLnplcm8sXG4gICAgICAgICAgICAgICAgczogW10sXG4gICAgICAgICAgICAgICAgY29lZnM6IFtdXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3QgY3MgPSBbXTtcblxuICAgICAgICAgICAgZm9yIChsZXQgcyBpbiBsaW5lYXJDb21iKSB7XG4gICAgICAgICAgICAgICAgaWYgKHMgPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXMuayA9IEZyLmFkZChyZXMuaywgbGluZWFyQ29tYltzXSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChsaW5lYXJDb21iW3NdICE9IDBuKSB7XG4gICAgICAgICAgICAgICAgICAgIGNzLnB1c2goW051bWJlcihzKSwgbGluZWFyQ29tYltzXV0pXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd2hpbGUgKGNzLmxlbmd0aCA+IG1heEMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjMSA9IGNzLnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgY29uc3QgYzIgPSBjcy5zaGlmdCgpO1xuXG4gICAgICAgICAgICAgICAgY29uc3Qgc2wgPSBjMVswXTtcbiAgICAgICAgICAgICAgICBjb25zdCBzciA9IGMyWzBdO1xuICAgICAgICAgICAgICAgIGNvbnN0IHNvID0gcGxvbmtOVmFycysrO1xuICAgICAgICAgICAgICAgIGNvbnN0IHFtID0gRnIuemVybztcbiAgICAgICAgICAgICAgICBjb25zdCBxbCA9IEZyLm5lZyhjMVsxXSk7XG4gICAgICAgICAgICAgICAgY29uc3QgcXIgPSBGci5uZWcoYzJbMV0pO1xuICAgICAgICAgICAgICAgIGNvbnN0IHFvID0gRnIub25lO1xuICAgICAgICAgICAgICAgIGNvbnN0IHFjID0gRnIuemVybztcblxuICAgICAgICAgICAgICAgIHBsb25rQ29uc3RyYWludHMucHVzaChbc2wsIHNyLCBzbywgcW0sIHFsLCBxciwgcW8sIHFjXSk7XG5cbiAgICAgICAgICAgICAgICBwbG9ua0FkZGl0aW9ucy5wdXNoKFtzbCwgc3IsIGMxWzFdLCBjMlsxXV0pO1xuXG4gICAgICAgICAgICAgICAgY3MucHVzaChbc28sIEZyLm9uZV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHJlcy5zW2ldID0gY3NbaV1bMF07XG4gICAgICAgICAgICAgICAgcmVzLmNvZWZzW2ldID0gY3NbaV1bMV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3aGlsZSAocmVzLmNvZWZzLmxlbmd0aCA8IG1heEMpIHtcbiAgICAgICAgICAgICAgICByZXMucy5wdXNoKDApO1xuICAgICAgICAgICAgICAgIHJlcy5jb2Vmcy5wdXNoKEZyLnplcm8pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGFkZENvbnN0cmFpbnRTdW0obGMpIHtcbiAgICAgICAgICAgIGNvbnN0IEMgPSByZWR1Y2VDb2VmcyhsYywgMyk7XG4gICAgICAgICAgICBjb25zdCBzbCA9IEMuc1swXTtcbiAgICAgICAgICAgIGNvbnN0IHNyID0gQy5zWzFdO1xuICAgICAgICAgICAgY29uc3Qgc28gPSBDLnNbMl07XG4gICAgICAgICAgICBjb25zdCBxbSA9IEZyLnplcm87XG4gICAgICAgICAgICBjb25zdCBxbCA9IEMuY29lZnNbMF07XG4gICAgICAgICAgICBjb25zdCBxciA9IEMuY29lZnNbMV07XG4gICAgICAgICAgICBjb25zdCBxbyA9IEMuY29lZnNbMl07XG4gICAgICAgICAgICBjb25zdCBxYyA9IEMuaztcbiAgICAgICAgICAgIHBsb25rQ29uc3RyYWludHMucHVzaChbc2wsIHNyLCBzbywgcW0sIHFsLCBxciwgcW8sIHFjXSk7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBhZGRDb25zdHJhaW50TXVsKGxjQSwgbGNCLCBsY0MpIHtcbiAgICAgICAgICAgIGNvbnN0IEEgPSByZWR1Y2VDb2VmcyhsY0EsIDEpO1xuICAgICAgICAgICAgY29uc3QgQiA9IHJlZHVjZUNvZWZzKGxjQiwgMSk7XG4gICAgICAgICAgICBjb25zdCBDID0gcmVkdWNlQ29lZnMobGNDLCAxKTtcblxuXG4gICAgICAgICAgICBjb25zdCBzbCA9IEEuc1swXTtcbiAgICAgICAgICAgIGNvbnN0IHNyID0gQi5zWzBdO1xuICAgICAgICAgICAgY29uc3Qgc28gPSBDLnNbMF07XG4gICAgICAgICAgICBjb25zdCBxbSA9IEZyLm11bChBLmNvZWZzWzBdLCBCLmNvZWZzWzBdKTtcbiAgICAgICAgICAgIGNvbnN0IHFsID0gRnIubXVsKEEuY29lZnNbMF0sIEIuayk7XG4gICAgICAgICAgICBjb25zdCBxciA9IEZyLm11bChBLmssIEIuY29lZnNbMF0pO1xuICAgICAgICAgICAgY29uc3QgcW8gPSBGci5uZWcoQy5jb2Vmc1swXSk7XG4gICAgICAgICAgICBjb25zdCBxYyA9IEZyLnN1YihGci5tdWwoQS5rLCBCLmspLCBDLmspO1xuICAgICAgICAgICAgcGxvbmtDb25zdHJhaW50cy5wdXNoKFtzbCwgc3IsIHNvLCBxbSwgcWwsIHFyLCBxbywgcWNdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGdldExpbmVhckNvbWJpbmF0aW9uVHlwZShsYykge1xuICAgICAgICAgICAgbGV0IGsgPSBGci56ZXJvO1xuICAgICAgICAgICAgbGV0IG4gPSAwO1xuICAgICAgICAgICAgY29uc3Qgc3MgPSBPYmplY3Qua2V5cyhsYyk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGxjW3NzW2ldXSA9PSAwbikge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgbGNbc3NbaV1dO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc3NbaV0gPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBrID0gRnIuYWRkKGssIGxjW3NzW2ldXSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbisrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChuID4gMCkgcmV0dXJuIG4udG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGlmIChrICE9IEZyLnplcm8pIHJldHVybiBcImtcIjtcbiAgICAgICAgICAgIHJldHVybiBcIjBcIjtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIHByb2Nlc3MobGNBLCBsY0IsIGxjQykge1xuICAgICAgICAgICAgY29uc3QgbGN0QSA9IGdldExpbmVhckNvbWJpbmF0aW9uVHlwZShsY0EpO1xuICAgICAgICAgICAgY29uc3QgbGN0QiA9IGdldExpbmVhckNvbWJpbmF0aW9uVHlwZShsY0IpO1xuICAgICAgICAgICAgaWYgKChsY3RBID09PSBcIjBcIikgfHwgKGxjdEIgPT09IFwiMFwiKSkge1xuICAgICAgICAgICAgICAgIG5vcm1hbGl6ZShsY0MpO1xuICAgICAgICAgICAgICAgIGFkZENvbnN0cmFpbnRTdW0obGNDKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobGN0QSA9PT0gXCJrXCIpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBsY0NDID0gam9pbihsY0IsIGxjQVswXSwgbGNDKTtcbiAgICAgICAgICAgICAgICBhZGRDb25zdHJhaW50U3VtKGxjQ0MpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChsY3RCID09PSBcImtcIikge1xuICAgICAgICAgICAgICAgIGNvbnN0IGxjQ0MgPSBqb2luKGxjQSwgbGNCWzBdLCBsY0MpO1xuICAgICAgICAgICAgICAgIGFkZENvbnN0cmFpbnRTdW0obGNDQyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGFkZENvbnN0cmFpbnRNdWwobGNBLCBsY0IsIGxjQyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGxldCBzID0gMTsgcyA8PSBuUHVibGljOyBzKyspIHtcbiAgICAgICAgICAgIGNvbnN0IHNsID0gcztcbiAgICAgICAgICAgIGNvbnN0IHNyID0gMDtcbiAgICAgICAgICAgIGNvbnN0IHNvID0gMDtcbiAgICAgICAgICAgIGNvbnN0IHFtID0gRnIuemVybztcbiAgICAgICAgICAgIGNvbnN0IHFsID0gRnIub25lO1xuICAgICAgICAgICAgY29uc3QgcXIgPSBGci56ZXJvO1xuICAgICAgICAgICAgY29uc3QgcW8gPSBGci56ZXJvO1xuICAgICAgICAgICAgY29uc3QgcWMgPSBGci56ZXJvO1xuXG4gICAgICAgICAgICBwbG9ua0NvbnN0cmFpbnRzLnB1c2goW3NsLCBzciwgc28sIHFtLCBxbCwgcXIsIHFvLCBxY10pO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChsZXQgYyA9IDA7IGMgPCByMWNzLmNvbnN0cmFpbnRzLmxlbmd0aDsgYysrKSB7XG4gICAgICAgICAgICBpZiAoKGxvZ2dlcikgJiYgKGMgJSAxMDAwMCA9PT0gMCkpIGxvZ2dlci5kZWJ1ZyhgcHJvY2Vzc2luZyBjb25zdHJhaW50czogJHtjfS8ke3IxY3MubkNvbnN0cmFpbnRzfWApO1xuICAgICAgICAgICAgcHJvY2VzcyguLi5yMWNzLmNvbnN0cmFpbnRzW2NdKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHdyaXRlV2l0bmVzc01hcChzZWN0aW9uTnVtLCBwb3NDb25zdHJhaW50LCBuYW1lKSB7XG4gICAgICAgIGF3YWl0IHN0YXJ0V3JpdGVTZWN0aW9uKGZkWktleSwgc2VjdGlvbk51bSk7XG4gICAgICAgIGZvciAobGV0IGk9MDsgaTxwbG9ua0NvbnN0cmFpbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBhd2FpdCBmZFpLZXkud3JpdGVVTEUzMihwbG9ua0NvbnN0cmFpbnRzW2ldW3Bvc0NvbnN0cmFpbnRdKTtcbiAgICAgICAgICAgIGlmICgobG9nZ2VyKSYmKGklMTAwMDAwMCA9PSAwKSkgbG9nZ2VyLmRlYnVnKGB3cml0aW5nICR7bmFtZX06ICR7aX0vJHtwbG9ua0NvbnN0cmFpbnRzLmxlbmd0aH1gKTtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCBlbmRXcml0ZVNlY3Rpb24oZmRaS2V5KTtcbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiB3cml0ZVFNYXAoc2VjdGlvbk51bSwgcG9zQ29uc3RyYWludCwgbmFtZSkge1xuICAgICAgICBsZXQgUSA9IG5ldyBCaWdCdWZmZXIoZG9tYWluU2l6ZSpuOHIpO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8cGxvbmtDb25zdHJhaW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgUS5zZXQocGxvbmtDb25zdHJhaW50c1tpXVtwb3NDb25zdHJhaW50XSwgaSpuOHIpO1xuICAgICAgICAgICAgaWYgKChsb2dnZXIpJiYoaSUxMDAwMDAwID09IDApKSBsb2dnZXIuZGVidWcoYHdyaXRpbmcgJHtuYW1lfTogJHtpfS8ke3Bsb25rQ29uc3RyYWludHMubGVuZ3RofWApO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IHN0YXJ0V3JpdGVTZWN0aW9uKGZkWktleSwgc2VjdGlvbk51bSk7XG4gICAgICAgIGF3YWl0IHdyaXRlUDQoUSk7XG4gICAgICAgIGF3YWl0IGVuZFdyaXRlU2VjdGlvbihmZFpLZXkpO1xuICAgICAgICBRID0gYXdhaXQgRnIuYmF0Y2hGcm9tTW9udGdvbWVyeShRKTtcbiAgICAgICAgdmtbbmFtZV09IGF3YWl0IGN1cnZlLkcxLm11bHRpRXhwQWZmaW5lKExQb2ludHMsIFEsIGxvZ2dlciwgXCJtdWx0aWV4cCBcIituYW1lKTtcbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiB3cml0ZVA0KGJ1ZmYpIHtcbiAgICAgICAgY29uc3QgcSA9IGF3YWl0IEZyLmlmZnQoYnVmZik7XG4gICAgICAgIGNvbnN0IHE0ID0gbmV3IEJpZ0J1ZmZlcihkb21haW5TaXplKm44cio0KTtcbiAgICAgICAgcTQuc2V0KHEsIDApO1xuICAgICAgICBjb25zdCBRNCA9IGF3YWl0IEZyLmZmdChxNCk7XG4gICAgICAgIGF3YWl0IGZkWktleS53cml0ZShxKTtcbiAgICAgICAgYXdhaXQgZmRaS2V5LndyaXRlKFE0KTtcbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiB3cml0ZUFkZGl0aW9ucyhzZWN0aW9uTnVtLCBuYW1lKSB7XG4gICAgICAgIGF3YWl0IHN0YXJ0V3JpdGVTZWN0aW9uKGZkWktleSwgc2VjdGlvbk51bSk7XG4gICAgICAgIGNvbnN0IGJ1ZmZPdXQgPSBuZXcgVWludDhBcnJheSgoMio0KzIqbjhyKSk7XG4gICAgICAgIGNvbnN0IGJ1ZmZPdXRWID0gbmV3IERhdGFWaWV3KGJ1ZmZPdXQuYnVmZmVyKTtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPHBsb25rQWRkaXRpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBhZGRpdGlvbj1wbG9ua0FkZGl0aW9uc1tpXTtcbiAgICAgICAgICAgIGxldCBvPTA7XG4gICAgICAgICAgICBidWZmT3V0Vi5zZXRVaW50MzIobywgYWRkaXRpb25bMF0sIHRydWUpOyBvKz00O1xuICAgICAgICAgICAgYnVmZk91dFYuc2V0VWludDMyKG8sIGFkZGl0aW9uWzFdLCB0cnVlKTsgbys9NDtcbiAgICAgICAgICAgIC8vIFRoZSB2YWx1ZSBpcyBzdG9yZWQgaW4gTW9udGdvbWVyeS4gc3RvcmVkID0gdipSXG4gICAgICAgICAgICAvLyBzbyB3aGVuIG1vbnRnb21lcnkgbXVsdGlwbGllZCBieSB0aGUgd2l0bmVzcywgaXQncyByZXN1bHQgPSB2KlIqdy9SID0gdip3XG4gICAgICAgICAgICBidWZmT3V0LnNldChhZGRpdGlvblsyXSwgbyk7IG8rPSBuOHI7XG4gICAgICAgICAgICBidWZmT3V0LnNldChhZGRpdGlvblszXSwgbyk7IG8rPSBuOHI7XG4gICAgICAgICAgICBhd2FpdCBmZFpLZXkud3JpdGUoYnVmZk91dCk7XG4gICAgICAgICAgICBpZiAoKGxvZ2dlcikmJihpJTEwMDAwMDAgPT0gMCkpIGxvZ2dlci5kZWJ1Zyhgd3JpdGluZyAke25hbWV9OiAke2l9LyR7cGxvbmtBZGRpdGlvbnMubGVuZ3RofWApO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IGVuZFdyaXRlU2VjdGlvbihmZFpLZXkpO1xuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHdyaXRlU2lnbWEoc2VjdGlvbk51bSwgbmFtZSkge1xuICAgICAgICBjb25zdCBzaWdtYSA9IG5ldyBCaWdCdWZmZXIobjhyKmRvbWFpblNpemUqMyk7XG4gICAgICAgIGNvbnN0IGxhc3RBcGFyZW5jZSA9ICBuZXcgQmlnQXJyYXkocGxvbmtOVmFycyk7XG4gICAgICAgIGNvbnN0IGZpcnN0UG9zID0gbmV3IEJpZ0FycmF5KHBsb25rTlZhcnMpO1xuICAgICAgICBsZXQgdyA9IEZyLm9uZTtcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPGRvbWFpblNpemU7aSsrKSB7XG4gICAgICAgICAgICBpZiAoaTxwbG9ua0NvbnN0cmFpbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGJ1aWxkU2lnbWEocGxvbmtDb25zdHJhaW50c1tpXVswXSwgaSk7XG4gICAgICAgICAgICAgICAgYnVpbGRTaWdtYShwbG9ua0NvbnN0cmFpbnRzW2ldWzFdLCBkb21haW5TaXplICsgaSk7XG4gICAgICAgICAgICAgICAgYnVpbGRTaWdtYShwbG9ua0NvbnN0cmFpbnRzW2ldWzJdLCBkb21haW5TaXplKjIgKyBpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYnVpbGRTaWdtYSgwLCBpKTtcbiAgICAgICAgICAgICAgICBidWlsZFNpZ21hKDAsIGRvbWFpblNpemUgKyBpKTtcbiAgICAgICAgICAgICAgICBidWlsZFNpZ21hKDAsIGRvbWFpblNpemUqMiArIGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdyA9IEZyLm11bCh3LCBGci53W2NpclBvd2VyXSk7XG4gICAgICAgICAgICBpZiAoKGxvZ2dlcikmJihpJTEwMDAwMDAgPT0gMCkpIGxvZ2dlci5kZWJ1Zyhgd3JpdGluZyAke25hbWV9IHBoYXNlMTogJHtpfS8ke3Bsb25rQ29uc3RyYWludHMubGVuZ3RofWApO1xuICAgICAgICB9XG4gICAgICAgIGZvciAobGV0IHM9MDsgczxwbG9ua05WYXJzOyBzKyspIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZmlyc3RQb3Nbc10gIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICBzaWdtYS5zZXQobGFzdEFwYXJlbmNlW3NdLCBmaXJzdFBvc1tzXSpuOHIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyB0aHJvdyBuZXcgRXJyb3IoXCJWYXJpYWJsZSBub3QgdXNlZFwiKTtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIlZhcmlhYmxlIG5vdCB1c2VkXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKChsb2dnZXIpJiYocyUxMDAwMDAwID09IDApKSBsb2dnZXIuZGVidWcoYHdyaXRpbmcgJHtuYW1lfSBwaGFzZTI6ICR7c30vJHtwbG9ua05WYXJzfWApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGdsb2JhbFRoaXMuZ2MpIHtnbG9iYWxUaGlzLmdjKCk7fVxuICAgICAgICBhd2FpdCBzdGFydFdyaXRlU2VjdGlvbihmZFpLZXksIHNlY3Rpb25OdW0pO1xuICAgICAgICBsZXQgUzEgPSBzaWdtYS5zbGljZSgwLCBkb21haW5TaXplKm44cik7XG4gICAgICAgIGF3YWl0IHdyaXRlUDQoUzEpO1xuICAgICAgICBpZiAoZ2xvYmFsVGhpcy5nYykge2dsb2JhbFRoaXMuZ2MoKTt9XG4gICAgICAgIGxldCBTMiA9IHNpZ21hLnNsaWNlKGRvbWFpblNpemUqbjhyLCBkb21haW5TaXplKm44cioyKTtcbiAgICAgICAgYXdhaXQgd3JpdGVQNChTMik7XG4gICAgICAgIGlmIChnbG9iYWxUaGlzLmdjKSB7Z2xvYmFsVGhpcy5nYygpO31cbiAgICAgICAgbGV0IFMzID0gc2lnbWEuc2xpY2UoZG9tYWluU2l6ZSpuOHIqMiwgZG9tYWluU2l6ZSpuOHIqMyk7XG4gICAgICAgIGF3YWl0IHdyaXRlUDQoUzMpO1xuICAgICAgICBpZiAoZ2xvYmFsVGhpcy5nYykge2dsb2JhbFRoaXMuZ2MoKTt9XG4gICAgICAgIGF3YWl0IGVuZFdyaXRlU2VjdGlvbihmZFpLZXkpO1xuXG4gICAgICAgIFMxID0gYXdhaXQgRnIuYmF0Y2hGcm9tTW9udGdvbWVyeShTMSk7XG4gICAgICAgIFMyID0gYXdhaXQgRnIuYmF0Y2hGcm9tTW9udGdvbWVyeShTMik7XG4gICAgICAgIFMzID0gYXdhaXQgRnIuYmF0Y2hGcm9tTW9udGdvbWVyeShTMyk7XG5cbiAgICAgICAgdmsuUzE9IGF3YWl0IGN1cnZlLkcxLm11bHRpRXhwQWZmaW5lKExQb2ludHMsIFMxLCBsb2dnZXIsIFwibXVsdGlleHAgUzFcIik7XG4gICAgICAgIGlmIChnbG9iYWxUaGlzLmdjKSB7Z2xvYmFsVGhpcy5nYygpO31cbiAgICAgICAgdmsuUzI9IGF3YWl0IGN1cnZlLkcxLm11bHRpRXhwQWZmaW5lKExQb2ludHMsIFMyLCBsb2dnZXIsIFwibXVsdGlleHAgUzJcIik7XG4gICAgICAgIGlmIChnbG9iYWxUaGlzLmdjKSB7Z2xvYmFsVGhpcy5nYygpO31cbiAgICAgICAgdmsuUzM9IGF3YWl0IGN1cnZlLkcxLm11bHRpRXhwQWZmaW5lKExQb2ludHMsIFMzLCBsb2dnZXIsIFwibXVsdGlleHAgUzNcIik7XG4gICAgICAgIGlmIChnbG9iYWxUaGlzLmdjKSB7Z2xvYmFsVGhpcy5nYygpO31cblxuICAgICAgICBmdW5jdGlvbiBidWlsZFNpZ21hKHMsIHApIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbGFzdEFwYXJlbmNlW3NdID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgZmlyc3RQb3Nbc10gPSBwO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzaWdtYS5zZXQobGFzdEFwYXJlbmNlW3NdLCBwKm44cik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgdjtcbiAgICAgICAgICAgIGlmIChwPGRvbWFpblNpemUpIHtcbiAgICAgICAgICAgICAgICB2ID0gdztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocDwyKmRvbWFpblNpemUpIHtcbiAgICAgICAgICAgICAgICB2ID0gRnIubXVsKHcsIGsxKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdiA9IEZyLm11bCh3LCBrMik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsYXN0QXBhcmVuY2Vbc109djtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHdyaXRlTHMoc2VjdGlvbk51bSwgbmFtZSkge1xuICAgICAgICBhd2FpdCBzdGFydFdyaXRlU2VjdGlvbihmZFpLZXksIHNlY3Rpb25OdW0pO1xuICAgICAgICBjb25zdCBsPU1hdGgubWF4KG5QdWJsaWMsIDEpO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8bDsgaSsrKSB7XG4gICAgICAgICAgICBsZXQgYnVmZiA9IG5ldyBCaWdCdWZmZXIoZG9tYWluU2l6ZSpuOHIpO1xuICAgICAgICAgICAgYnVmZi5zZXQoRnIub25lLCBpKm44cik7XG4gICAgICAgICAgICBhd2FpdCB3cml0ZVA0KGJ1ZmYpO1xuICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKGB3cml0aW5nICR7bmFtZX0gJHtpfS8ke2x9YCk7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgZW5kV3JpdGVTZWN0aW9uKGZkWktleSk7XG4gICAgfVxuXG4gICAgYXN5bmMgZnVuY3Rpb24gd3JpdGVIZWFkZXJzKCkge1xuXG4gICAgICAgIC8vIFdyaXRlIHRoZSBoZWFkZXJcbiAgICAgICAgLy8vLy8vLy8vLy9cbiAgICAgICAgYXdhaXQgc3RhcnRXcml0ZVNlY3Rpb24oZmRaS2V5LCAxKTtcbiAgICAgICAgYXdhaXQgZmRaS2V5LndyaXRlVUxFMzIoMik7IC8vIFBsb25rXG4gICAgICAgIGF3YWl0IGVuZFdyaXRlU2VjdGlvbihmZFpLZXkpO1xuXG4gICAgICAgIC8vIFdyaXRlIHRoZSBQbG9uayBoZWFkZXIgc2VjdGlvblxuICAgICAgICAvLy8vLy8vLy8vL1xuXG4gICAgICAgIGF3YWl0IHN0YXJ0V3JpdGVTZWN0aW9uKGZkWktleSwgMik7XG4gICAgICAgIGNvbnN0IHByaW1lUSA9IGN1cnZlLnE7XG4gICAgICAgIGNvbnN0IG44cSA9IChNYXRoLmZsb29yKCAoU2NhbGFyLmJpdExlbmd0aChwcmltZVEpIC0gMSkgLyA2NCkgKzEpKjg7XG5cbiAgICAgICAgY29uc3QgcHJpbWVSID0gY3VydmUucjtcbiAgICAgICAgY29uc3QgbjhyID0gKE1hdGguZmxvb3IoIChTY2FsYXIuYml0TGVuZ3RoKHByaW1lUikgLSAxKSAvIDY0KSArMSkqODtcblxuICAgICAgICBhd2FpdCBmZFpLZXkud3JpdGVVTEUzMihuOHEpO1xuICAgICAgICBhd2FpdCB3cml0ZUJpZ0ludChmZFpLZXksIHByaW1lUSwgbjhxKTtcbiAgICAgICAgYXdhaXQgZmRaS2V5LndyaXRlVUxFMzIobjhyKTtcbiAgICAgICAgYXdhaXQgd3JpdGVCaWdJbnQoZmRaS2V5LCBwcmltZVIsIG44cik7XG4gICAgICAgIGF3YWl0IGZkWktleS53cml0ZVVMRTMyKHBsb25rTlZhcnMpOyAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUb3RhbCBudW1iZXIgb2YgYmFyc1xuICAgICAgICBhd2FpdCBmZFpLZXkud3JpdGVVTEUzMihuUHVibGljKTsgICAgICAgICAgICAgICAgICAgICAgIC8vIFRvdGFsIG51bWJlciBvZiBwdWJsaWMgdmFycyAobm90IGluY2x1ZGluZyBPTkUpXG4gICAgICAgIGF3YWl0IGZkWktleS53cml0ZVVMRTMyKGRvbWFpblNpemUpOyAgICAgICAgICAgICAgICAgIC8vIGRvbWFpblNpemVcbiAgICAgICAgYXdhaXQgZmRaS2V5LndyaXRlVUxFMzIocGxvbmtBZGRpdGlvbnMubGVuZ3RoKTsgICAgICAgICAgICAgICAgICAvLyBkb21haW5TaXplXG4gICAgICAgIGF3YWl0IGZkWktleS53cml0ZVVMRTMyKHBsb25rQ29uc3RyYWludHMubGVuZ3RoKTsgXG5cbiAgICAgICAgYXdhaXQgZmRaS2V5LndyaXRlKGsxKTtcbiAgICAgICAgYXdhaXQgZmRaS2V5LndyaXRlKGsyKTtcblxuICAgICAgICBhd2FpdCBmZFpLZXkud3JpdGUoRzEudG9BZmZpbmUodmsuUW0pKTtcbiAgICAgICAgYXdhaXQgZmRaS2V5LndyaXRlKEcxLnRvQWZmaW5lKHZrLlFsKSk7XG4gICAgICAgIGF3YWl0IGZkWktleS53cml0ZShHMS50b0FmZmluZSh2ay5RcikpO1xuICAgICAgICBhd2FpdCBmZFpLZXkud3JpdGUoRzEudG9BZmZpbmUodmsuUW8pKTtcbiAgICAgICAgYXdhaXQgZmRaS2V5LndyaXRlKEcxLnRvQWZmaW5lKHZrLlFjKSk7XG5cbiAgICAgICAgYXdhaXQgZmRaS2V5LndyaXRlKEcxLnRvQWZmaW5lKHZrLlMxKSk7XG4gICAgICAgIGF3YWl0IGZkWktleS53cml0ZShHMS50b0FmZmluZSh2ay5TMikpO1xuICAgICAgICBhd2FpdCBmZFpLZXkud3JpdGUoRzEudG9BZmZpbmUodmsuUzMpKTtcblxuICAgICAgICBsZXQgYlhfMjtcbiAgICAgICAgYlhfMiA9IGF3YWl0IGZkUFRhdS5yZWFkKHNHMiwgc2VjdGlvbnNQVGF1WzNdWzBdLnAgKyBzRzIpO1xuICAgICAgICBhd2FpdCBmZFpLZXkud3JpdGUoYlhfMik7XG5cbiAgICAgICAgYXdhaXQgZW5kV3JpdGVTZWN0aW9uKGZkWktleSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0SzFLMigpIHtcbiAgICAgICAgbGV0IGsxID0gRnIudHdvO1xuICAgICAgICB3aGlsZSAoaXNJbmNsdWRlZChrMSwgW10sIGNpclBvd2VyKSkgRnIuYWRkKGsxLCBGci5vbmUpO1xuICAgICAgICBsZXQgazIgPSBGci5hZGQoazEsIEZyLm9uZSk7XG4gICAgICAgIHdoaWxlIChpc0luY2x1ZGVkKGsyLCBbazFdLCBjaXJQb3dlcikpIEZyLmFkZChrMiwgRnIub25lKTtcbiAgICAgICAgcmV0dXJuIFtrMSwgazJdO1xuXG5cbiAgICAgICAgZnVuY3Rpb24gaXNJbmNsdWRlZChrLCBrQXJyLCBwb3cpIHtcbiAgICAgICAgICAgIGNvbnN0IGRvbWFpblNpemU9IDIqKnBvdztcbiAgICAgICAgICAgIGxldCB3ID0gRnIub25lO1xuICAgICAgICAgICAgZm9yIChsZXQgaT0wOyBpPGRvbWFpblNpemU7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChGci5lcShrLCB3KSkgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaj0wOyBqPGtBcnIubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKEZyLmVxKGssIEZyLm11bChrQXJyW2pdLCB3KSkpIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB3ID0gRnIubXVsKHcsIEZyLndbcG93XSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG59XG5cblxuIiwiLypcbiAgICBDb3B5cmlnaHQgMjAyMiBpZGVuMyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJranMuXG5cbiAgICBzbmFya2pzIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4gICAgbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZVxuICAgIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKVxuICAgIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtqcyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICAgIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvclxuICAgIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFsb25nIHdpdGhcbiAgICBzbmFya2pzLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuZXhwb3J0IGNsYXNzIFByb29mIHtcbiAgICBjb25zdHJ1Y3RvcihjdXJ2ZSwgbG9nZ2VyKSB7XG4gICAgICAgIHRoaXMuY3VydmUgPSBjdXJ2ZTtcbiAgICAgICAgdGhpcy5sb2dnZXIgPSBsb2dnZXI7XG5cbiAgICAgICAgdGhpcy5yZXNldFByb29mKCk7XG4gICAgfVxuXG4gICAgcmVzZXRQcm9vZigpIHtcbiAgICAgICAgdGhpcy5wb2x5bm9taWFscyA9IHt9O1xuICAgICAgICB0aGlzLmV2YWx1YXRpb25zID0ge307XG4gICAgfVxuXG4gICAgYWRkUG9seW5vbWlhbChrZXksIHBvbHlub21pYWwpIHtcbiAgICAgICAgaWYgKGtleSBpbiB0aGlzLnBvbHlub21pYWxzKSB7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci53YXJuKGBwcm9vZjogcG9seW5vbWlhbC4ke2tleX0gYWxyZWFkeSBleGlzdCBpbiBwcm9vZmApO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucG9seW5vbWlhbHNba2V5XSA9IHBvbHlub21pYWw7XG4gICAgfVxuXG4gICAgZ2V0UG9seW5vbWlhbChrZXkpIHtcbiAgICAgICAgaWYgKCEoa2V5IGluIHRoaXMucG9seW5vbWlhbHMpKSB7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci53YXJuKGBwcm9vZjogcG9seW5vbWlhbCAke2tleX0gZG9lcyBub3QgZXhpc3QgaW4gcHJvb2ZgKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5wb2x5bm9taWFsc1trZXldO1xuICAgIH1cblxuICAgIGFkZEV2YWx1YXRpb24oa2V5LCBldmFsdWF0aW9uKSB7XG4gICAgICAgIGlmIChrZXkgaW4gdGhpcy5ldmFsdWF0aW9ucykge1xuICAgICAgICAgICAgdGhpcy5sb2dnZXIud2FybihgcHJvb2Y6IGV2YWx1YXRpb25zLiR7a2V5fSBhbHJlYWR5IGV4aXN0IGluIHByb29mYCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5ldmFsdWF0aW9uc1trZXldID0gZXZhbHVhdGlvbjtcbiAgICB9XG5cbiAgICBnZXRFdmFsdWF0aW9uKGtleSkge1xuICAgICAgICBpZiAoIShrZXkgaW4gdGhpcy5ldmFsdWF0aW9ucykpIHtcbiAgICAgICAgICAgIHRoaXMubG9nZ2VyLndhcm4oYHByb29mOiBldmFsdWF0aW9uICR7a2V5fSBkb2VzIG5vdCBleGlzdCBpbiBwcm9vZmApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmV2YWx1YXRpb25zW2tleV07XG4gICAgfVxuXG4gICAgdG9PYmplY3RQcm9vZihzcGxpdEZpZWxkcyA9IHRydWUpIHtcbiAgICAgICAgbGV0IHJlcyA9IHNwbGl0RmllbGRzID8ge3BvbHlub21pYWxzOiB7fSwgZXZhbHVhdGlvbnM6IHt9fSA6IHt9O1xuXG4gICAgICAgIE9iamVjdC5rZXlzKHRoaXMucG9seW5vbWlhbHMpLmZvckVhY2goa2V5ID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gdGhpcy5jdXJ2ZS5HMS50b09iamVjdCh0aGlzLnBvbHlub21pYWxzW2tleV0pO1xuICAgICAgICAgICAgaWYoc3BsaXRGaWVsZHMpIHtcbiAgICAgICAgICAgICAgICByZXMucG9seW5vbWlhbHNba2V5XSA9IHZhbHVlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXNba2V5XSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBPYmplY3Qua2V5cyh0aGlzLmV2YWx1YXRpb25zKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHRoaXMuY3VydmUuRnIudG9PYmplY3QodGhpcy5ldmFsdWF0aW9uc1trZXldKTtcbiAgICAgICAgICAgIGlmKHNwbGl0RmllbGRzKSB7XG4gICAgICAgICAgICAgICAgcmVzLmV2YWx1YXRpb25zW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICBmcm9tT2JqZWN0UHJvb2Yob2JqZWN0UHJvb2YpIHtcbiAgICAgICAgdGhpcy5yZXNldFByb29mKCk7XG5cbiAgICAgICAgT2JqZWN0LmtleXMob2JqZWN0UHJvb2YucG9seW5vbWlhbHMpLmZvckVhY2goa2V5ID0+IHtcbiAgICAgICAgICAgIHRoaXMucG9seW5vbWlhbHNba2V5XSA9IHRoaXMuY3VydmUuRzEuZnJvbU9iamVjdChvYmplY3RQcm9vZi5wb2x5bm9taWFsc1trZXldKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgT2JqZWN0LmtleXMob2JqZWN0UHJvb2YuZXZhbHVhdGlvbnMpLmZvckVhY2goa2V5ID0+IHtcbiAgICAgICAgICAgIHRoaXMuZXZhbHVhdGlvbnNba2V5XSA9IHRoaXMuY3VydmUuRnIuZnJvbU9iamVjdChvYmplY3RQcm9vZi5ldmFsdWF0aW9uc1trZXldKTtcbiAgICAgICAgfSk7XG4gICAgfVxufSIsIi8qKlxuICogU0hBMyAoa2VjY2FrKSBoYXNoIGZ1bmN0aW9uLCBiYXNlZCBvbiBhIG5ldyBcIlNwb25nZSBmdW5jdGlvblwiIGRlc2lnbi5cbiAqIERpZmZlcmVudCBmcm9tIG9sZGVyIGhhc2hlcywgdGhlIGludGVybmFsIHN0YXRlIGlzIGJpZ2dlciB0aGFuIG91dHB1dCBzaXplLlxuICpcbiAqIENoZWNrIG91dCBbRklQUy0yMDJdKGh0dHBzOi8vbnZscHVicy5uaXN0Lmdvdi9uaXN0cHVicy9GSVBTL05JU1QuRklQUy4yMDIucGRmKSxcbiAqIFtXZWJzaXRlXShodHRwczovL2tlY2Nhay50ZWFtL2tlY2Nhay5odG1sKSxcbiAqIFt0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBTSEEtMyBhbmQgS2VjY2FrXShodHRwczovL2NyeXB0by5zdGFja2V4Y2hhbmdlLmNvbS9xdWVzdGlvbnMvMTU3Mjcvd2hhdC1hcmUtdGhlLWtleS1kaWZmZXJlbmNlcy1iZXR3ZWVuLXRoZS1kcmFmdC1zaGEtMy1zdGFuZGFyZC1hbmQtdGhlLWtlY2Nhay1zdWIpLlxuICpcbiAqIENoZWNrIG91dCBgc2hhMy1hZGRvbnNgIG1vZHVsZSBmb3IgY1NIQUtFLCBrMTIsIGFuZCBvdGhlcnMuXG4gKiBAbW9kdWxlXG4gKi9cbmltcG9ydCB7IGFieXRlcywgYWV4aXN0cywgYW51bWJlciwgYW91dHB1dCB9IGZyb20gJy4vX2Fzc2VydC5qcyc7XG5pbXBvcnQgeyByb3RsQkgsIHJvdGxCTCwgcm90bFNILCByb3RsU0wsIHNwbGl0IH0gZnJvbSAnLi9fdTY0LmpzJztcbmltcG9ydCB7IGJ5dGVTd2FwMzIsIEhhc2gsIGlzTEUsIHRvQnl0ZXMsIHUzMiwgd3JhcENvbnN0cnVjdG9yLCB3cmFwWE9GQ29uc3RydWN0b3JXaXRoT3B0cywgfSBmcm9tICcuL3V0aWxzLmpzJztcbi8vIFZhcmlvdXMgcGVyIHJvdW5kIGNvbnN0YW50cyBjYWxjdWxhdGlvbnNcbmNvbnN0IFNIQTNfUEkgPSBbXTtcbmNvbnN0IFNIQTNfUk9UTCA9IFtdO1xuY29uc3QgX1NIQTNfSU9UQSA9IFtdO1xuY29uc3QgXzBuID0gLyogQF9fUFVSRV9fICovIEJpZ0ludCgwKTtcbmNvbnN0IF8xbiA9IC8qIEBfX1BVUkVfXyAqLyBCaWdJbnQoMSk7XG5jb25zdCBfMm4gPSAvKiBAX19QVVJFX18gKi8gQmlnSW50KDIpO1xuY29uc3QgXzduID0gLyogQF9fUFVSRV9fICovIEJpZ0ludCg3KTtcbmNvbnN0IF8yNTZuID0gLyogQF9fUFVSRV9fICovIEJpZ0ludCgyNTYpO1xuY29uc3QgXzB4NzFuID0gLyogQF9fUFVSRV9fICovIEJpZ0ludCgweDcxKTtcbmZvciAobGV0IHJvdW5kID0gMCwgUiA9IF8xbiwgeCA9IDEsIHkgPSAwOyByb3VuZCA8IDI0OyByb3VuZCsrKSB7XG4gICAgLy8gUGlcbiAgICBbeCwgeV0gPSBbeSwgKDIgKiB4ICsgMyAqIHkpICUgNV07XG4gICAgU0hBM19QSS5wdXNoKDIgKiAoNSAqIHkgKyB4KSk7XG4gICAgLy8gUm90YXRpb25hbFxuICAgIFNIQTNfUk9UTC5wdXNoKCgoKHJvdW5kICsgMSkgKiAocm91bmQgKyAyKSkgLyAyKSAlIDY0KTtcbiAgICAvLyBJb3RhXG4gICAgbGV0IHQgPSBfMG47XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCA3OyBqKyspIHtcbiAgICAgICAgUiA9ICgoUiA8PCBfMW4pIF4gKChSID4+IF83bikgKiBfMHg3MW4pKSAlIF8yNTZuO1xuICAgICAgICBpZiAoUiAmIF8ybilcbiAgICAgICAgICAgIHQgXj0gXzFuIDw8ICgoXzFuIDw8IC8qIEBfX1BVUkVfXyAqLyBCaWdJbnQoaikpIC0gXzFuKTtcbiAgICB9XG4gICAgX1NIQTNfSU9UQS5wdXNoKHQpO1xufVxuY29uc3QgW1NIQTNfSU9UQV9ILCBTSEEzX0lPVEFfTF0gPSAvKiBAX19QVVJFX18gKi8gc3BsaXQoX1NIQTNfSU9UQSwgdHJ1ZSk7XG4vLyBMZWZ0IHJvdGF0aW9uICh3aXRob3V0IDAsIDMyLCA2NClcbmNvbnN0IHJvdGxIID0gKGgsIGwsIHMpID0+IChzID4gMzIgPyByb3RsQkgoaCwgbCwgcykgOiByb3RsU0goaCwgbCwgcykpO1xuY29uc3Qgcm90bEwgPSAoaCwgbCwgcykgPT4gKHMgPiAzMiA/IHJvdGxCTChoLCBsLCBzKSA6IHJvdGxTTChoLCBsLCBzKSk7XG4vKiogYGtlY2Nha2YxNjAwYCBpbnRlcm5hbCBmdW5jdGlvbiwgYWRkaXRpb25hbGx5IGFsbG93cyB0byBhZGp1c3Qgcm91bmQgY291bnQuICovXG5leHBvcnQgZnVuY3Rpb24ga2VjY2FrUChzLCByb3VuZHMgPSAyNCkge1xuICAgIGNvbnN0IEIgPSBuZXcgVWludDMyQXJyYXkoNSAqIDIpO1xuICAgIC8vIE5PVEU6IGFsbCBpbmRpY2VzIGFyZSB4MiBzaW5jZSB3ZSBzdG9yZSBzdGF0ZSBhcyB1MzIgaW5zdGVhZCBvZiB1NjQgKGJpZ2ludHMgdG8gc2xvdyBpbiBqcylcbiAgICBmb3IgKGxldCByb3VuZCA9IDI0IC0gcm91bmRzOyByb3VuZCA8IDI0OyByb3VuZCsrKSB7XG4gICAgICAgIC8vIFRoZXRhIM64XG4gICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgMTA7IHgrKylcbiAgICAgICAgICAgIEJbeF0gPSBzW3hdIF4gc1t4ICsgMTBdIF4gc1t4ICsgMjBdIF4gc1t4ICsgMzBdIF4gc1t4ICsgNDBdO1xuICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IDEwOyB4ICs9IDIpIHtcbiAgICAgICAgICAgIGNvbnN0IGlkeDEgPSAoeCArIDgpICUgMTA7XG4gICAgICAgICAgICBjb25zdCBpZHgwID0gKHggKyAyKSAlIDEwO1xuICAgICAgICAgICAgY29uc3QgQjAgPSBCW2lkeDBdO1xuICAgICAgICAgICAgY29uc3QgQjEgPSBCW2lkeDAgKyAxXTtcbiAgICAgICAgICAgIGNvbnN0IFRoID0gcm90bEgoQjAsIEIxLCAxKSBeIEJbaWR4MV07XG4gICAgICAgICAgICBjb25zdCBUbCA9IHJvdGxMKEIwLCBCMSwgMSkgXiBCW2lkeDEgKyAxXTtcbiAgICAgICAgICAgIGZvciAobGV0IHkgPSAwOyB5IDwgNTA7IHkgKz0gMTApIHtcbiAgICAgICAgICAgICAgICBzW3ggKyB5XSBePSBUaDtcbiAgICAgICAgICAgICAgICBzW3ggKyB5ICsgMV0gXj0gVGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gUmhvICjPgSkgYW5kIFBpICjPgClcbiAgICAgICAgbGV0IGN1ckggPSBzWzJdO1xuICAgICAgICBsZXQgY3VyTCA9IHNbM107XG4gICAgICAgIGZvciAobGV0IHQgPSAwOyB0IDwgMjQ7IHQrKykge1xuICAgICAgICAgICAgY29uc3Qgc2hpZnQgPSBTSEEzX1JPVExbdF07XG4gICAgICAgICAgICBjb25zdCBUaCA9IHJvdGxIKGN1ckgsIGN1ckwsIHNoaWZ0KTtcbiAgICAgICAgICAgIGNvbnN0IFRsID0gcm90bEwoY3VySCwgY3VyTCwgc2hpZnQpO1xuICAgICAgICAgICAgY29uc3QgUEkgPSBTSEEzX1BJW3RdO1xuICAgICAgICAgICAgY3VySCA9IHNbUEldO1xuICAgICAgICAgICAgY3VyTCA9IHNbUEkgKyAxXTtcbiAgICAgICAgICAgIHNbUEldID0gVGg7XG4gICAgICAgICAgICBzW1BJICsgMV0gPSBUbDtcbiAgICAgICAgfVxuICAgICAgICAvLyBDaGkgKM+HKVxuICAgICAgICBmb3IgKGxldCB5ID0gMDsgeSA8IDUwOyB5ICs9IDEwKSB7XG4gICAgICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IDEwOyB4KyspXG4gICAgICAgICAgICAgICAgQlt4XSA9IHNbeSArIHhdO1xuICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCAxMDsgeCsrKVxuICAgICAgICAgICAgICAgIHNbeSArIHhdIF49IH5CWyh4ICsgMikgJSAxMF0gJiBCWyh4ICsgNCkgJSAxMF07XG4gICAgICAgIH1cbiAgICAgICAgLy8gSW90YSAozrkpXG4gICAgICAgIHNbMF0gXj0gU0hBM19JT1RBX0hbcm91bmRdO1xuICAgICAgICBzWzFdIF49IFNIQTNfSU9UQV9MW3JvdW5kXTtcbiAgICB9XG4gICAgQi5maWxsKDApO1xufVxuLyoqIEtlY2NhayBzcG9uZ2UgZnVuY3Rpb24uICovXG5leHBvcnQgY2xhc3MgS2VjY2FrIGV4dGVuZHMgSGFzaCB7XG4gICAgLy8gTk9URTogd2UgYWNjZXB0IGFyZ3VtZW50cyBpbiBieXRlcyBpbnN0ZWFkIG9mIGJpdHMgaGVyZS5cbiAgICBjb25zdHJ1Y3RvcihibG9ja0xlbiwgc3VmZml4LCBvdXRwdXRMZW4sIGVuYWJsZVhPRiA9IGZhbHNlLCByb3VuZHMgPSAyNCkge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLmJsb2NrTGVuID0gYmxvY2tMZW47XG4gICAgICAgIHRoaXMuc3VmZml4ID0gc3VmZml4O1xuICAgICAgICB0aGlzLm91dHB1dExlbiA9IG91dHB1dExlbjtcbiAgICAgICAgdGhpcy5lbmFibGVYT0YgPSBlbmFibGVYT0Y7XG4gICAgICAgIHRoaXMucm91bmRzID0gcm91bmRzO1xuICAgICAgICB0aGlzLnBvcyA9IDA7XG4gICAgICAgIHRoaXMucG9zT3V0ID0gMDtcbiAgICAgICAgdGhpcy5maW5pc2hlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmRlc3Ryb3llZCA9IGZhbHNlO1xuICAgICAgICAvLyBDYW4gYmUgcGFzc2VkIGZyb20gdXNlciBhcyBka0xlblxuICAgICAgICBhbnVtYmVyKG91dHB1dExlbik7XG4gICAgICAgIC8vIDE2MDAgPSA1eDUgbWF0cml4IG9mIDY0Yml0LiAgMTYwMCBiaXRzID09PSAyMDAgYnl0ZXNcbiAgICAgICAgLy8gMCA8IGJsb2NrTGVuIDwgMjAwXG4gICAgICAgIGlmICgwID49IHRoaXMuYmxvY2tMZW4gfHwgdGhpcy5ibG9ja0xlbiA+PSAyMDApXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1NoYTMgc3VwcG9ydHMgb25seSBrZWNjYWstZjE2MDAgZnVuY3Rpb24nKTtcbiAgICAgICAgdGhpcy5zdGF0ZSA9IG5ldyBVaW50OEFycmF5KDIwMCk7XG4gICAgICAgIHRoaXMuc3RhdGUzMiA9IHUzMih0aGlzLnN0YXRlKTtcbiAgICB9XG4gICAga2VjY2FrKCkge1xuICAgICAgICBpZiAoIWlzTEUpXG4gICAgICAgICAgICBieXRlU3dhcDMyKHRoaXMuc3RhdGUzMik7XG4gICAgICAgIGtlY2Nha1AodGhpcy5zdGF0ZTMyLCB0aGlzLnJvdW5kcyk7XG4gICAgICAgIGlmICghaXNMRSlcbiAgICAgICAgICAgIGJ5dGVTd2FwMzIodGhpcy5zdGF0ZTMyKTtcbiAgICAgICAgdGhpcy5wb3NPdXQgPSAwO1xuICAgICAgICB0aGlzLnBvcyA9IDA7XG4gICAgfVxuICAgIHVwZGF0ZShkYXRhKSB7XG4gICAgICAgIGFleGlzdHModGhpcyk7XG4gICAgICAgIGNvbnN0IHsgYmxvY2tMZW4sIHN0YXRlIH0gPSB0aGlzO1xuICAgICAgICBkYXRhID0gdG9CeXRlcyhkYXRhKTtcbiAgICAgICAgY29uc3QgbGVuID0gZGF0YS5sZW5ndGg7XG4gICAgICAgIGZvciAobGV0IHBvcyA9IDA7IHBvcyA8IGxlbjspIHtcbiAgICAgICAgICAgIGNvbnN0IHRha2UgPSBNYXRoLm1pbihibG9ja0xlbiAtIHRoaXMucG9zLCBsZW4gLSBwb3MpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0YWtlOyBpKyspXG4gICAgICAgICAgICAgICAgc3RhdGVbdGhpcy5wb3MrK10gXj0gZGF0YVtwb3MrK107XG4gICAgICAgICAgICBpZiAodGhpcy5wb3MgPT09IGJsb2NrTGVuKVxuICAgICAgICAgICAgICAgIHRoaXMua2VjY2FrKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIGZpbmlzaCgpIHtcbiAgICAgICAgaWYgKHRoaXMuZmluaXNoZWQpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIHRoaXMuZmluaXNoZWQgPSB0cnVlO1xuICAgICAgICBjb25zdCB7IHN0YXRlLCBzdWZmaXgsIHBvcywgYmxvY2tMZW4gfSA9IHRoaXM7XG4gICAgICAgIC8vIERvIHRoZSBwYWRkaW5nXG4gICAgICAgIHN0YXRlW3Bvc10gXj0gc3VmZml4O1xuICAgICAgICBpZiAoKHN1ZmZpeCAmIDB4ODApICE9PSAwICYmIHBvcyA9PT0gYmxvY2tMZW4gLSAxKVxuICAgICAgICAgICAgdGhpcy5rZWNjYWsoKTtcbiAgICAgICAgc3RhdGVbYmxvY2tMZW4gLSAxXSBePSAweDgwO1xuICAgICAgICB0aGlzLmtlY2NhaygpO1xuICAgIH1cbiAgICB3cml0ZUludG8ob3V0KSB7XG4gICAgICAgIGFleGlzdHModGhpcywgZmFsc2UpO1xuICAgICAgICBhYnl0ZXMob3V0KTtcbiAgICAgICAgdGhpcy5maW5pc2goKTtcbiAgICAgICAgY29uc3QgYnVmZmVyT3V0ID0gdGhpcy5zdGF0ZTtcbiAgICAgICAgY29uc3QgeyBibG9ja0xlbiB9ID0gdGhpcztcbiAgICAgICAgZm9yIChsZXQgcG9zID0gMCwgbGVuID0gb3V0Lmxlbmd0aDsgcG9zIDwgbGVuOykge1xuICAgICAgICAgICAgaWYgKHRoaXMucG9zT3V0ID49IGJsb2NrTGVuKVxuICAgICAgICAgICAgICAgIHRoaXMua2VjY2FrKCk7XG4gICAgICAgICAgICBjb25zdCB0YWtlID0gTWF0aC5taW4oYmxvY2tMZW4gLSB0aGlzLnBvc091dCwgbGVuIC0gcG9zKTtcbiAgICAgICAgICAgIG91dC5zZXQoYnVmZmVyT3V0LnN1YmFycmF5KHRoaXMucG9zT3V0LCB0aGlzLnBvc091dCArIHRha2UpLCBwb3MpO1xuICAgICAgICAgICAgdGhpcy5wb3NPdXQgKz0gdGFrZTtcbiAgICAgICAgICAgIHBvcyArPSB0YWtlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvdXQ7XG4gICAgfVxuICAgIHhvZkludG8ob3V0KSB7XG4gICAgICAgIC8vIFNoYTMvS2VjY2FrIHVzYWdlIHdpdGggWE9GIGlzIHByb2JhYmx5IG1pc3Rha2UsIG9ubHkgU0hBS0UgaW5zdGFuY2VzIGNhbiBkbyBYT0ZcbiAgICAgICAgaWYgKCF0aGlzLmVuYWJsZVhPRilcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignWE9GIGlzIG5vdCBwb3NzaWJsZSBmb3IgdGhpcyBpbnN0YW5jZScpO1xuICAgICAgICByZXR1cm4gdGhpcy53cml0ZUludG8ob3V0KTtcbiAgICB9XG4gICAgeG9mKGJ5dGVzKSB7XG4gICAgICAgIGFudW1iZXIoYnl0ZXMpO1xuICAgICAgICByZXR1cm4gdGhpcy54b2ZJbnRvKG5ldyBVaW50OEFycmF5KGJ5dGVzKSk7XG4gICAgfVxuICAgIGRpZ2VzdEludG8ob3V0KSB7XG4gICAgICAgIGFvdXRwdXQob3V0LCB0aGlzKTtcbiAgICAgICAgaWYgKHRoaXMuZmluaXNoZWQpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2RpZ2VzdCgpIHdhcyBhbHJlYWR5IGNhbGxlZCcpO1xuICAgICAgICB0aGlzLndyaXRlSW50byhvdXQpO1xuICAgICAgICB0aGlzLmRlc3Ryb3koKTtcbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9XG4gICAgZGlnZXN0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kaWdlc3RJbnRvKG5ldyBVaW50OEFycmF5KHRoaXMub3V0cHV0TGVuKSk7XG4gICAgfVxuICAgIGRlc3Ryb3koKSB7XG4gICAgICAgIHRoaXMuZGVzdHJveWVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5zdGF0ZS5maWxsKDApO1xuICAgIH1cbiAgICBfY2xvbmVJbnRvKHRvKSB7XG4gICAgICAgIGNvbnN0IHsgYmxvY2tMZW4sIHN1ZmZpeCwgb3V0cHV0TGVuLCByb3VuZHMsIGVuYWJsZVhPRiB9ID0gdGhpcztcbiAgICAgICAgdG8gfHwgKHRvID0gbmV3IEtlY2NhayhibG9ja0xlbiwgc3VmZml4LCBvdXRwdXRMZW4sIGVuYWJsZVhPRiwgcm91bmRzKSk7XG4gICAgICAgIHRvLnN0YXRlMzIuc2V0KHRoaXMuc3RhdGUzMik7XG4gICAgICAgIHRvLnBvcyA9IHRoaXMucG9zO1xuICAgICAgICB0by5wb3NPdXQgPSB0aGlzLnBvc091dDtcbiAgICAgICAgdG8uZmluaXNoZWQgPSB0aGlzLmZpbmlzaGVkO1xuICAgICAgICB0by5yb3VuZHMgPSByb3VuZHM7XG4gICAgICAgIC8vIFN1ZmZpeCBjYW4gY2hhbmdlIGluIGNTSEFLRVxuICAgICAgICB0by5zdWZmaXggPSBzdWZmaXg7XG4gICAgICAgIHRvLm91dHB1dExlbiA9IG91dHB1dExlbjtcbiAgICAgICAgdG8uZW5hYmxlWE9GID0gZW5hYmxlWE9GO1xuICAgICAgICB0by5kZXN0cm95ZWQgPSB0aGlzLmRlc3Ryb3llZDtcbiAgICAgICAgcmV0dXJuIHRvO1xuICAgIH1cbn1cbmNvbnN0IGdlbiA9IChzdWZmaXgsIGJsb2NrTGVuLCBvdXRwdXRMZW4pID0+IHdyYXBDb25zdHJ1Y3RvcigoKSA9PiBuZXcgS2VjY2FrKGJsb2NrTGVuLCBzdWZmaXgsIG91dHB1dExlbikpO1xuLyoqIFNIQTMtMjI0IGhhc2ggZnVuY3Rpb24uICovXG5leHBvcnQgY29uc3Qgc2hhM18yMjQgPSAvKiBAX19QVVJFX18gKi8gZ2VuKDB4MDYsIDE0NCwgMjI0IC8gOCk7XG4vKiogU0hBMy0yNTYgaGFzaCBmdW5jdGlvbi4gRGlmZmVyZW50IGZyb20ga2VjY2FrLTI1Ni4gKi9cbmV4cG9ydCBjb25zdCBzaGEzXzI1NiA9IC8qIEBfX1BVUkVfXyAqLyBnZW4oMHgwNiwgMTM2LCAyNTYgLyA4KTtcbi8qKiBTSEEzLTM4NCBoYXNoIGZ1bmN0aW9uLiAqL1xuZXhwb3J0IGNvbnN0IHNoYTNfMzg0ID0gLyogQF9fUFVSRV9fICovIGdlbigweDA2LCAxMDQsIDM4NCAvIDgpO1xuLyoqIFNIQTMtNTEyIGhhc2ggZnVuY3Rpb24uICovXG5leHBvcnQgY29uc3Qgc2hhM181MTIgPSAvKiBAX19QVVJFX18gKi8gZ2VuKDB4MDYsIDcyLCA1MTIgLyA4KTtcbi8qKiBrZWNjYWstMjI0IGhhc2ggZnVuY3Rpb24uICovXG5leHBvcnQgY29uc3Qga2VjY2FrXzIyNCA9IC8qIEBfX1BVUkVfXyAqLyBnZW4oMHgwMSwgMTQ0LCAyMjQgLyA4KTtcbi8qKiBrZWNjYWstMjU2IGhhc2ggZnVuY3Rpb24uIERpZmZlcmVudCBmcm9tIFNIQTMtMjU2LiAqL1xuZXhwb3J0IGNvbnN0IGtlY2Nha18yNTYgPSAvKiBAX19QVVJFX18gKi8gZ2VuKDB4MDEsIDEzNiwgMjU2IC8gOCk7XG4vKioga2VjY2FrLTM4NCBoYXNoIGZ1bmN0aW9uLiAqL1xuZXhwb3J0IGNvbnN0IGtlY2Nha18zODQgPSAvKiBAX19QVVJFX18gKi8gZ2VuKDB4MDEsIDEwNCwgMzg0IC8gOCk7XG4vKioga2VjY2FrLTUxMiBoYXNoIGZ1bmN0aW9uLiAqL1xuZXhwb3J0IGNvbnN0IGtlY2Nha181MTIgPSAvKiBAX19QVVJFX18gKi8gZ2VuKDB4MDEsIDcyLCA1MTIgLyA4KTtcbmNvbnN0IGdlblNoYWtlID0gKHN1ZmZpeCwgYmxvY2tMZW4sIG91dHB1dExlbikgPT4gd3JhcFhPRkNvbnN0cnVjdG9yV2l0aE9wdHMoKG9wdHMgPSB7fSkgPT4gbmV3IEtlY2NhayhibG9ja0xlbiwgc3VmZml4LCBvcHRzLmRrTGVuID09PSB1bmRlZmluZWQgPyBvdXRwdXRMZW4gOiBvcHRzLmRrTGVuLCB0cnVlKSk7XG4vKiogU0hBS0UxMjggWE9GIHdpdGggMTI4LWJpdCBzZWN1cml0eS4gKi9cbmV4cG9ydCBjb25zdCBzaGFrZTEyOCA9IC8qIEBfX1BVUkVfXyAqLyBnZW5TaGFrZSgweDFmLCAxNjgsIDEyOCAvIDgpO1xuLyoqIFNIQUtFMjU2IFhPRiB3aXRoIDI1Ni1iaXQgc2VjdXJpdHkuICovXG5leHBvcnQgY29uc3Qgc2hha2UyNTYgPSAvKiBAX19QVVJFX18gKi8gZ2VuU2hha2UoMHgxZiwgMTM2LCAyNTYgLyA4KTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXNoYTMuanMubWFwIiwiLypcbiAgICBDb3B5cmlnaHQgMjAyMiBpZGVuMyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJranMuXG5cbiAgICBzbmFya2pzIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4gICAgbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZVxuICAgIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKVxuICAgIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtqcyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICAgIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvclxuICAgIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFsb25nIHdpdGhcbiAgICBzbmFya2pzLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuaW1wb3J0IHtTY2FsYXJ9IGZyb20gXCJmZmphdmFzY3JpcHRcIjtcbmltcG9ydCB7a2VjY2FrXzI1Nn0gZnJvbSBcIkBub2JsZS9oYXNoZXMvc2hhM1wiO1xuXG5jb25zdCBQT0xZTk9NSUFMID0gMDtcbmNvbnN0IFNDQUxBUiA9IDE7XG5cbmV4cG9ydCBjbGFzcyBLZWNjYWsyNTZUcmFuc2NyaXB0IHtcbiAgICBjb25zdHJ1Y3RvcihjdXJ2ZSkge1xuICAgICAgICB0aGlzLkcxID0gY3VydmUuRzE7XG4gICAgICAgIHRoaXMuRnIgPSBjdXJ2ZS5GcjtcblxuICAgICAgICB0aGlzLnJlc2V0KCk7XG4gICAgfVxuXG4gICAgcmVzZXQoKSB7XG4gICAgICAgIHRoaXMuZGF0YSA9IFtdO1xuICAgIH1cblxuICAgIGFkZFBvbENvbW1pdG1lbnQocG9seW5vbWlhbENvbW1pdG1lbnQpIHtcbiAgICAgICAgdGhpcy5kYXRhLnB1c2goe3R5cGU6IFBPTFlOT01JQUwsIGRhdGE6IHBvbHlub21pYWxDb21taXRtZW50fSk7XG4gICAgfVxuXG4gICAgYWRkU2NhbGFyKHNjYWxhcikge1xuICAgICAgICB0aGlzLmRhdGEucHVzaCh7dHlwZTogU0NBTEFSLCBkYXRhOiBzY2FsYXJ9KTtcbiAgICB9XG5cbiAgICBnZXRDaGFsbGVuZ2UoKSB7XG4gICAgICAgIGlmKDAgPT09IHRoaXMuZGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIktlY2NhazI1NlRyYW5zY3JpcHQ6IE5vIGRhdGEgdG8gZ2VuZXJhdGUgYSB0cmFuc2NyaXB0XCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IG5Qb2x5bm9taWFscyA9IDA7XG4gICAgICAgIGxldCBuU2NhbGFycyA9IDA7XG5cbiAgICAgICAgdGhpcy5kYXRhLmZvckVhY2goZWxlbWVudCA9PiBQT0xZTk9NSUFMID09PSBlbGVtZW50LnR5cGUgPyBuUG9seW5vbWlhbHMrKyA6IG5TY2FsYXJzKyspO1xuXG4gICAgICAgIGxldCBidWZmZXIgPSBuZXcgVWludDhBcnJheShuU2NhbGFycyAqIHRoaXMuRnIubjggKyBuUG9seW5vbWlhbHMgKiB0aGlzLkcxLkYubjggKiAyKTtcbiAgICAgICAgbGV0IG9mZnNldCA9IDA7XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmRhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChQT0xZTk9NSUFMID09PSB0aGlzLmRhdGFbaV0udHlwZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuRzEudG9ScHJVbmNvbXByZXNzZWQoYnVmZmVyLCBvZmZzZXQsIHRoaXMuZGF0YVtpXS5kYXRhKTtcbiAgICAgICAgICAgICAgICBvZmZzZXQgKz0gdGhpcy5HMS5GLm44ICogMjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5Gci50b1JwckJFKGJ1ZmZlciwgb2Zmc2V0LCB0aGlzLmRhdGFbaV0uZGF0YSk7XG4gICAgICAgICAgICAgICAgb2Zmc2V0ICs9IHRoaXMuRnIubjg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB2YWx1ZSA9IFNjYWxhci5mcm9tUnByQkUoa2VjY2FrXzI1NihidWZmZXIpKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuRnIuZSh2YWx1ZSk7XG4gICAgfVxufSIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMjIgaWRlbjMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya2pzLlxuXG4gICAgc25hcmtqcyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuICAgIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGVcbiAgICBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbilcbiAgICBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJranMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAgICBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3JcbiAgICBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhbG9uZyB3aXRoXG4gICAgc25hcmtqcy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbmV4cG9ydCBjbGFzcyBNdWxaIHtcbiAgICBzdGF0aWMgZ2V0WjEoRnIpIHtcbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIEZyLnplcm8sXG4gICAgICAgICAgICBGci5hZGQoRnIuZSgtMSksIEZyLndbMl0pLFxuICAgICAgICAgICAgRnIuZSgtMiksXG4gICAgICAgICAgICBGci5zdWIoRnIuZSgtMSksIEZyLndbMl0pLFxuICAgICAgICBdO1xuICAgIH1cblxuICAgIHN0YXRpYyBnZXRaMihGcikge1xuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgRnIuemVybyxcbiAgICAgICAgICAgIEZyLmFkZChGci56ZXJvLCBGci5tdWwoRnIuZSgtMiksIEZyLndbMl0pKSxcbiAgICAgICAgICAgIEZyLmUoNCksXG4gICAgICAgICAgICBGci5zdWIoRnIuemVybywgRnIubXVsKEZyLmUoLTIpLCBGci53WzJdKSksXG4gICAgICAgIF07XG4gICAgfVxuXG4gICAgc3RhdGljIGdldFozKEZyKSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICBGci56ZXJvLFxuICAgICAgICAgICAgRnIuYWRkKEZyLmUoMiksIEZyLm11bChGci5lKDIpLCBGci53WzJdKSksXG4gICAgICAgICAgICBGci5lKC04KSxcbiAgICAgICAgICAgIEZyLnN1YihGci5lKDIpLCBGci5tdWwoRnIuZSgyKSwgRnIud1syXSkpLFxuICAgICAgICBdO1xuXG4gICAgfVxuXG4gICAgc3RhdGljIG11bDIoYSwgYiwgYXAsIGJwLCBwLCBGcikge1xuICAgICAgICBjb25zdCBaMSA9IHRoaXMuZ2V0WjEoRnIpO1xuICAgICAgICBsZXQgciwgcno7XG5cbiAgICAgICAgY29uc3QgYV9iID0gRnIubXVsKGEsIGIpO1xuICAgICAgICBjb25zdCBhX2JwID0gRnIubXVsKGEsIGJwKTtcbiAgICAgICAgY29uc3QgYXBfYiA9IEZyLm11bChhcCwgYik7XG4gICAgICAgIGNvbnN0IGFwX2JwID0gRnIubXVsKGFwLCBicCk7XG5cbiAgICAgICAgciA9IGFfYjtcblxuICAgICAgICBsZXQgYTAgPSBGci5hZGQoYV9icCwgYXBfYik7XG5cbiAgICAgICAgbGV0IGExID0gYXBfYnA7XG5cbiAgICAgICAgcnogPSBhMDtcbiAgICAgICAgaWYgKHApIHtcbiAgICAgICAgICAgIHJ6ID0gRnIuYWRkKHJ6LCBGci5tdWwoWjFbcF0sIGExKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gW3IsIHJ6XTtcbiAgICB9XG5cbiAgICBzdGF0aWMgbXVsMyhhLCBiLCBjLCBhcCwgYnAsIGNwLCBwLCBGcikge1xuICAgICAgICBjb25zdCBaMSA9IHRoaXMuZ2V0WjEoRnIpO1xuICAgICAgICBjb25zdCBaMiA9IHRoaXMuZ2V0WjIoRnIpO1xuICAgICAgICBsZXQgciwgcno7XG5cbiAgICAgICAgY29uc3QgYV9iID0gRnIubXVsKGEsIGIpO1xuICAgICAgICBjb25zdCBhX2JwID0gRnIubXVsKGEsIGJwKTtcbiAgICAgICAgY29uc3QgYXBfYiA9IEZyLm11bChhcCwgYik7XG4gICAgICAgIGNvbnN0IGFwX2JwID0gRnIubXVsKGFwLCBicCk7XG5cbiAgICAgICAgciA9IEZyLm11bChhX2IsIGMpO1xuXG4gICAgICAgIGxldCBhMCA9IEZyLm11bChhcF9iLCBjKTtcbiAgICAgICAgYTAgPSBGci5hZGQoYTAsIEZyLm11bChhX2JwLCBjKSk7XG4gICAgICAgIGEwID0gRnIuYWRkKGEwLCBGci5tdWwoYV9iLCBjcCkpO1xuXG4gICAgICAgIGxldCBhMSA9IEZyLm11bChhcF9icCwgYyk7XG4gICAgICAgIGExID0gRnIuYWRkKGExLCBGci5tdWwoYV9icCwgY3ApKTtcbiAgICAgICAgYTEgPSBGci5hZGQoYTEsIEZyLm11bChhcF9iLCBjcCkpO1xuXG4gICAgICAgIHJ6ID0gYTA7XG4gICAgICAgIGlmIChwKSB7XG4gICAgICAgICAgICBjb25zdCBhMiA9IEZyLm11bChhcF9icCwgY3ApO1xuICAgICAgICAgICAgcnogPSBGci5hZGQocnosIEZyLm11bChaMVtwXSwgYTEpKTtcbiAgICAgICAgICAgIHJ6ID0gRnIuYWRkKHJ6LCBGci5tdWwoWjJbcF0sIGEyKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gW3IsIHJ6XTtcbiAgICB9XG5cbiAgICBzdGF0aWMgbXVsNChhLCBiLCBjLCBkLCBhcCwgYnAsIGNwLCBkcCwgcCwgRnIpIHtcbiAgICAgICAgY29uc3QgWjEgPSB0aGlzLmdldFoxKEZyKTtcbiAgICAgICAgY29uc3QgWjIgPSB0aGlzLmdldFoyKEZyKTtcbiAgICAgICAgY29uc3QgWjMgPSB0aGlzLmdldFozKEZyKTtcblxuICAgICAgICBsZXQgciwgcno7XG5cbiAgICAgICAgY29uc3QgYV9iID0gRnIubXVsKGEsIGIpO1xuICAgICAgICBjb25zdCBhX2JwID0gRnIubXVsKGEsIGJwKTtcbiAgICAgICAgY29uc3QgYXBfYiA9IEZyLm11bChhcCwgYik7XG4gICAgICAgIGNvbnN0IGFwX2JwID0gRnIubXVsKGFwLCBicCk7XG5cbiAgICAgICAgY29uc3QgY19kID0gRnIubXVsKGMsIGQpO1xuICAgICAgICBjb25zdCBjX2RwID0gRnIubXVsKGMsIGRwKTtcbiAgICAgICAgY29uc3QgY3BfZCA9IEZyLm11bChjcCwgZCk7XG4gICAgICAgIGNvbnN0IGNwX2RwID0gRnIubXVsKGNwLCBkcCk7XG5cbiAgICAgICAgciA9IEZyLm11bChhX2IsIGNfZCk7XG5cbiAgICAgICAgbGV0IGEwID0gRnIubXVsKGFwX2IsIGNfZCk7XG4gICAgICAgIGEwID0gRnIuYWRkKGEwLCBGci5tdWwoYV9icCwgY19kKSk7XG4gICAgICAgIGEwID0gRnIuYWRkKGEwLCBGci5tdWwoYV9iLCBjcF9kKSk7XG4gICAgICAgIGEwID0gRnIuYWRkKGEwLCBGci5tdWwoYV9iLCBjX2RwKSk7XG5cbiAgICAgICAgbGV0IGExID0gRnIubXVsKGFwX2JwLCBjX2QpO1xuICAgICAgICBhMSA9IEZyLmFkZChhMSwgRnIubXVsKGFwX2IsIGNwX2QpKTtcbiAgICAgICAgYTEgPSBGci5hZGQoYTEsIEZyLm11bChhcF9iLCBjX2RwKSk7XG4gICAgICAgIGExID0gRnIuYWRkKGExLCBGci5tdWwoYV9icCwgY3BfZCkpO1xuICAgICAgICBhMSA9IEZyLmFkZChhMSwgRnIubXVsKGFfYnAsIGNfZHApKTtcbiAgICAgICAgYTEgPSBGci5hZGQoYTEsIEZyLm11bChhX2IsIGNwX2RwKSk7XG5cbiAgICAgICAgbGV0IGEyID0gRnIubXVsKGFfYnAsIGNwX2RwKTtcbiAgICAgICAgYTIgPSBGci5hZGQoYTIsIEZyLm11bChhcF9iLCBjcF9kcCkpO1xuICAgICAgICBhMiA9IEZyLmFkZChhMiwgRnIubXVsKGFwX2JwLCBjX2RwKSk7XG4gICAgICAgIGEyID0gRnIuYWRkKGEyLCBGci5tdWwoYXBfYnAsIGNwX2QpKTtcblxuICAgICAgICBsZXQgYTMgPSBGci5tdWwoYXBfYnAsIGNwX2RwKTtcblxuICAgICAgICByeiA9IGEwO1xuICAgICAgICBpZiAocCkge1xuICAgICAgICAgICAgcnogPSBGci5hZGQocnosIEZyLm11bChaMVtwXSwgYTEpKTtcbiAgICAgICAgICAgIHJ6ID0gRnIuYWRkKHJ6LCBGci5tdWwoWjJbcF0sIGEyKSk7XG4gICAgICAgICAgICByeiA9IEZyLmFkZChyeiwgRnIubXVsKFozW3BdLCBhMykpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFtyLCByel07XG4gICAgfVxufSIsImV4cG9ydCBjb25zdCBaS0VZX1BMX05TRUNUSU9OUyA9IDEzO1xuXG5leHBvcnQgY29uc3QgWktFWV9QTF9IRUFERVJfU0VDVElPTiA9IDI7XG5leHBvcnQgY29uc3QgWktFWV9QTF9BRERJVElPTlNfU0VDVElPTiA9IDM7XG5leHBvcnQgY29uc3QgWktFWV9QTF9BX01BUF9TRUNUSU9OID0gNDtcbmV4cG9ydCBjb25zdCBaS0VZX1BMX0JfTUFQX1NFQ1RJT04gPSA1O1xuZXhwb3J0IGNvbnN0IFpLRVlfUExfQ19NQVBfU0VDVElPTiA9IDY7XG5leHBvcnQgY29uc3QgWktFWV9QTF9RTV9TRUNUSU9OID0gNztcbmV4cG9ydCBjb25zdCBaS0VZX1BMX1FMX1NFQ1RJT04gPSA4O1xuZXhwb3J0IGNvbnN0IFpLRVlfUExfUVJfU0VDVElPTiA9IDk7XG5leHBvcnQgY29uc3QgWktFWV9QTF9RT19TRUNUSU9OID0gMTA7XG5leHBvcnQgY29uc3QgWktFWV9QTF9RQ19TRUNUSU9OID0gMTE7XG5leHBvcnQgY29uc3QgWktFWV9QTF9TSUdNQV9TRUNUSU9OID0gMTI7XG5leHBvcnQgY29uc3QgWktFWV9QTF9MQUdSQU5HRV9TRUNUSU9OID0gMTM7XG5leHBvcnQgY29uc3QgWktFWV9QTF9QVEFVX1NFQ1RJT04gPSAxNDtcblxuIiwiLypcbiAgICBDb3B5cmlnaHQgMjAyMiBpZGVuMyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJranMuXG5cbiAgICBzbmFya2pzIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4gICAgbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZVxuICAgIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKVxuICAgIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtqcyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICAgIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvclxuICAgIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFsb25nIHdpdGhcbiAgICBzbmFya2pzLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuaW1wb3J0IHtCaWdCdWZmZXJ9IGZyb20gXCJmZmphdmFzY3JpcHRcIjtcblxuZXhwb3J0IGNsYXNzIFBvbHlub21pYWwge1xuICAgIGNvbnN0cnVjdG9yKGNvZWZmaWNpZW50cywgY3VydmUsIGxvZ2dlcikge1xuICAgICAgICB0aGlzLmNvZWYgPSBjb2VmZmljaWVudHM7XG4gICAgICAgIHRoaXMuY3VydmUgPSBjdXJ2ZTtcbiAgICAgICAgdGhpcy5GciA9IGN1cnZlLkZyO1xuICAgICAgICB0aGlzLkcxID0gY3VydmUuRzE7XG4gICAgICAgIHRoaXMubG9nZ2VyID0gbG9nZ2VyO1xuICAgIH1cblxuICAgIHN0YXRpYyBhc3luYyBmcm9tRXZhbHVhdGlvbnMoYnVmZmVyLCBjdXJ2ZSwgbG9nZ2VyKSB7XG4gICAgICAgIGxldCBjb2VmZmljaWVudHMgPSBhd2FpdCBjdXJ2ZS5Gci5pZmZ0KGJ1ZmZlcik7XG5cbiAgICAgICAgcmV0dXJuIG5ldyBQb2x5bm9taWFsKGNvZWZmaWNpZW50cywgY3VydmUsIGxvZ2dlcik7XG4gICAgfVxuXG4gICAgc3RhdGljIGZyb21Db2VmZmljaWVudHNBcnJheShhcnJheSwgY3VydmUsIGxvZ2dlcikge1xuICAgICAgICBjb25zdCBGciA9IGN1cnZlLkZyO1xuICAgICAgICBsZXQgYnVmZiA9IGFycmF5Lmxlbmd0aCA+IDIgPDwgMTQgP1xuICAgICAgICAgICAgbmV3IEJpZ0J1ZmZlcihhcnJheS5sZW5ndGggKiBGci5uOCkgOiBuZXcgVWludDhBcnJheShhcnJheS5sZW5ndGggKiBGci5uOCk7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXJyYXkubGVuZ3RoOyBpKyspIGJ1ZmYuc2V0KGFycmF5W2ldLCBpICogRnIubjgpO1xuXG4gICAgICAgIHJldHVybiBuZXcgUG9seW5vbWlhbChidWZmLCBjdXJ2ZSwgbG9nZ2VyKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgZnJvbVBvbHlub21pYWwocG9seW5vbWlhbCwgY3VydmUsIGxvZ2dlcikge1xuICAgICAgICBsZXQgbGVuZ3RoID0gcG9seW5vbWlhbC5sZW5ndGgoKTtcbiAgICAgICAgbGV0IEZyID0gY3VydmUuRnI7XG5cbiAgICAgICAgbGV0IGJ1ZmYgPSBsZW5ndGggPiAyIDw8IDE0ID9cbiAgICAgICAgICAgIG5ldyBCaWdCdWZmZXIobGVuZ3RoICogRnIubjgpIDogbmV3IFVpbnQ4QXJyYXkobGVuZ3RoICogRnIubjgpO1xuICAgICAgICBidWZmLnNldChwb2x5bm9taWFsLmNvZWYuc2xpY2UoKSwgMCk7XG5cbiAgICAgICAgcmV0dXJuIG5ldyBQb2x5bm9taWFsKGJ1ZmYsIGN1cnZlLCBsb2dnZXIpO1xuICAgIH1cblxuICAgIGlzRXF1YWwocG9seW5vbWlhbCkge1xuICAgICAgICBjb25zdCBkZWdyZWUgPSB0aGlzLmRlZ3JlZSgpO1xuICAgICAgICBpZiAoZGVncmVlICE9PSBwb2x5bm9taWFsLmRlZ3JlZSgpKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkZWdyZWUgKyAxOyBpKyspIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5Gci5lcSh0aGlzLmdldENvZWYoaSksIHBvbHlub21pYWwuZ2V0Q29lZihpKSkpIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGJsaW5kQ29lZmZpY2llbnRzKGJsaW5kaW5nRmFjdG9ycykge1xuICAgICAgICBibGluZGluZ0ZhY3RvcnMgPSBibGluZGluZ0ZhY3RvcnMgfHwgW107XG5cbiAgICAgICAgY29uc3QgYmxpbmRlZENvZWZmaWNpZW50cyA9ICh0aGlzLmxlbmd0aCgpICsgYmxpbmRpbmdGYWN0b3JzLmxlbmd0aCkgPiAyIDw8IDE0ID9cbiAgICAgICAgICAgIG5ldyBCaWdCdWZmZXIoKHRoaXMubGVuZ3RoKCkgKyBibGluZGluZ0ZhY3RvcnMubGVuZ3RoKSAqIHRoaXMuRnIubjgpIDpcbiAgICAgICAgICAgIG5ldyBVaW50OEFycmF5KCh0aGlzLmxlbmd0aCgpICsgYmxpbmRpbmdGYWN0b3JzLmxlbmd0aCkgKiB0aGlzLkZyLm44KTtcblxuICAgICAgICBibGluZGVkQ29lZmZpY2llbnRzLnNldCh0aGlzLmNvZWYsIDApO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJsaW5kaW5nRmFjdG9ycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgYmxpbmRlZENvZWZmaWNpZW50cy5zZXQoXG4gICAgICAgICAgICAgICAgdGhpcy5Gci5hZGQoXG4gICAgICAgICAgICAgICAgICAgIGJsaW5kZWRDb2VmZmljaWVudHMuc2xpY2UoKHRoaXMubGVuZ3RoKCkgKyBpKSAqIHRoaXMuRnIubjgsICh0aGlzLmxlbmd0aCgpICsgaSArIDEpICogdGhpcy5Gci5uOCksXG4gICAgICAgICAgICAgICAgICAgIGJsaW5kaW5nRmFjdG9yc1tpXVxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgKHRoaXMubGVuZ3RoKCkgKyBpKSAqIHRoaXMuRnIubjhcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBibGluZGVkQ29lZmZpY2llbnRzLnNldChcbiAgICAgICAgICAgICAgICB0aGlzLkZyLnN1YihcbiAgICAgICAgICAgICAgICAgICAgYmxpbmRlZENvZWZmaWNpZW50cy5zbGljZShpICogdGhpcy5Gci5uOCwgKGkgKyAxKSAqIHRoaXMuRnIubjgpLFxuICAgICAgICAgICAgICAgICAgICBibGluZGluZ0ZhY3RvcnNbaV1cbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIGkgKiB0aGlzLkZyLm44XG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY29lZiA9IGJsaW5kZWRDb2VmZmljaWVudHM7XG4gICAgfVxuXG4gICAgZ2V0Q29lZihpbmRleCkge1xuICAgICAgICBjb25zdCBpX244ID0gaW5kZXggKiB0aGlzLkZyLm44O1xuXG4gICAgICAgIGlmIChpX244ICsgdGhpcy5Gci5uOCA+IHRoaXMuY29lZi5ieXRlTGVuZ3RoKSByZXR1cm4gdGhpcy5Gci56ZXJvO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmNvZWYuc2xpY2UoaV9uOCwgaV9uOCArIHRoaXMuRnIubjgpO1xuICAgIH1cblxuICAgIHNldENvZWYoaW5kZXgsIHZhbHVlKSB7XG4gICAgICAgIGlmIChpbmRleCA+ICh0aGlzLmxlbmd0aCgpIC0gMSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNvZWYgaW5kZXggaXMgbm90IGF2YWlsYWJsZVwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY29lZi5zZXQodmFsdWUsIGluZGV4ICogdGhpcy5Gci5uOCk7XG4gICAgfVxuXG4gICAgc3RhdGljIGFzeW5jIHRvNFQoYnVmZmVyLCBkb21haW5TaXplLCBibGluZGluZ0ZhY3RvcnMsIEZyKSB7XG4gICAgICAgIGJsaW5kaW5nRmFjdG9ycyA9IGJsaW5kaW5nRmFjdG9ycyB8fCBbXTtcbiAgICAgICAgbGV0IGEgPSBhd2FpdCBGci5pZmZ0KGJ1ZmZlcik7XG5cbiAgICAgICAgY29uc3QgYTQgPSAoZG9tYWluU2l6ZSAqIDQpID4gMiA8PCAxNCA/XG4gICAgICAgICAgICBuZXcgQmlnQnVmZmVyKGRvbWFpblNpemUgKiA0ICogRnIubjgpIDogbmV3IFVpbnQ4QXJyYXkoZG9tYWluU2l6ZSAqIDQgKiBGci5uOCk7XG4gICAgICAgIGE0LnNldChhLCAwKTtcblxuICAgICAgICBjb25zdCBBNCA9IGF3YWl0IEZyLmZmdChhNCk7XG5cbiAgICAgICAgaWYgKGJsaW5kaW5nRmFjdG9ycy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBbYSwgQTRdO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYTEgPSBkb21haW5TaXplICsgYmxpbmRpbmdGYWN0b3JzLmxlbmd0aCA+IDIgPDwgMTQgP1xuICAgICAgICAgICAgbmV3IEJpZ0J1ZmZlcigoZG9tYWluU2l6ZSArIGJsaW5kaW5nRmFjdG9ycy5sZW5ndGgpICogRnIubjgpIDpcbiAgICAgICAgICAgIG5ldyBVaW50OEFycmF5KChkb21haW5TaXplICsgYmxpbmRpbmdGYWN0b3JzLmxlbmd0aCkgKiBGci5uOCk7XG5cbiAgICAgICAgYTEuc2V0KGEsIDApO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJsaW5kaW5nRmFjdG9ycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgYTEuc2V0KFxuICAgICAgICAgICAgICAgIEZyLmFkZChcbiAgICAgICAgICAgICAgICAgICAgYTEuc2xpY2UoKGRvbWFpblNpemUgKyBpKSAqIEZyLm44LCAoZG9tYWluU2l6ZSArIGkgKyAxKSAqIEZyLm44KSxcbiAgICAgICAgICAgICAgICAgICAgYmxpbmRpbmdGYWN0b3JzW2ldXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAoZG9tYWluU2l6ZSArIGkpICogRnIubjhcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBhMS5zZXQoXG4gICAgICAgICAgICAgICAgRnIuc3ViKFxuICAgICAgICAgICAgICAgICAgICBhMS5zbGljZShpICogRnIubjgsIChpICsgMSkgKiBGci5uOCksXG4gICAgICAgICAgICAgICAgICAgIGJsaW5kaW5nRmFjdG9yc1tpXVxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgaSAqIEZyLm44XG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFthMSwgQTRdO1xuICAgIH1cblxuICAgIGxlbmd0aCgpIHtcbiAgICAgICAgbGV0IGxlbmd0aCA9IHRoaXMuY29lZi5ieXRlTGVuZ3RoIC8gdGhpcy5Gci5uODtcbiAgICAgICAgaWYgKGxlbmd0aCAhPT0gTWF0aC5mbG9vcih0aGlzLmNvZWYuYnl0ZUxlbmd0aCAvIHRoaXMuRnIubjgpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJQb2x5bm9taWFsIGNvZWZmaWNpZW50cyBidWZmZXIgaGFzIGluY29ycmVjdCBzaXplXCIpO1xuICAgICAgICB9XG4gICAgICAgIGlmICgwID09PSBsZW5ndGgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmxvZ2dlcikge1xuICAgICAgICAgICAgICAgIHRoaXMubG9nZ2VyLndhcm4oXCJQb2x5bm9taWFsIGhhcyBsZW5ndGggemVyb1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbGVuZ3RoO1xuICAgIH1cblxuICAgIGRlZ3JlZSgpIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IHRoaXMubGVuZ3RoKCkgLSAxOyBpID4gMDsgaS0tKSB7XG4gICAgICAgICAgICBjb25zdCBpX244ID0gaSAqIHRoaXMuRnIubjg7XG4gICAgICAgICAgICBpZiAoIXRoaXMuRnIuZXEodGhpcy5Gci56ZXJvLCB0aGlzLmNvZWYuc2xpY2UoaV9uOCwgaV9uOCArIHRoaXMuRnIubjgpKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgZXZhbHVhdGUocG9pbnQpIHtcbiAgICAgICAgbGV0IHJlcyA9IHRoaXMuRnIuemVybztcblxuICAgICAgICBmb3IgKGxldCBpID0gdGhpcy5kZWdyZWUoKSArIDE7IGkgPiAwOyBpLS0pIHtcbiAgICAgICAgICAgIGxldCBpX244ID0gaSAqIHRoaXMuRnIubjg7XG4gICAgICAgICAgICBjb25zdCBjdXJyZW50Q29lZmZpY2llbnQgPSB0aGlzLmNvZWYuc2xpY2UoaV9uOCAtIHRoaXMuRnIubjgsIGlfbjgpO1xuICAgICAgICAgICAgcmVzID0gdGhpcy5Gci5hZGQoY3VycmVudENvZWZmaWNpZW50LCB0aGlzLkZyLm11bChyZXMsIHBvaW50KSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIGZhc3RFdmFsdWF0ZShwb2ludCkge1xuICAgICAgICBjb25zdCBGciA9IHRoaXMuRnI7XG4gICAgICAgIGxldCBuVGhyZWFkcyA9IDM7XG5cbiAgICAgICAgbGV0IG5Db2VmcyA9IHRoaXMuZGVncmVlKCkgKyAxO1xuICAgICAgICBsZXQgY29lZnNUaHJlYWQgPSBwYXJzZUludChuQ29lZnMgLyBuVGhyZWFkcyk7XG4gICAgICAgIGxldCByZXNpZHVhbENvZWZzID0gbkNvZWZzIC0gY29lZnNUaHJlYWQgKiBuVGhyZWFkcztcblxuICAgICAgICBsZXQgcmVzID0gW107XG4gICAgICAgIGxldCB4TiA9IFtdO1xuXG4gICAgICAgIHhOWzBdID0gRnIub25lO1xuXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgblRocmVhZHM7IGkrKykge1xuICAgICAgICAgICAgcmVzW2ldID0gRnIuemVybztcblxuICAgICAgICAgICAgbGV0IG5Db2VmcyA9IGkgPT09IChuVGhyZWFkcyAtIDEpID8gY29lZnNUaHJlYWQgKyByZXNpZHVhbENvZWZzIDogY29lZnNUaHJlYWQ7XG4gICAgICAgICAgICBmb3IgKGxldCBqID0gbkNvZWZzOyBqID4gMDsgai0tKSB7XG4gICAgICAgICAgICAgICAgcmVzW2ldID0gRnIuYWRkKHRoaXMuZ2V0Q29lZigoaSAqIGNvZWZzVGhyZWFkKSArIGogLSAxKSwgRnIubXVsKHJlc1tpXSwgcG9pbnQpKTtcblxuICAgICAgICAgICAgICAgIGlmIChpID09PSAwKSB4TlswXSA9IEZyLm11bCh4TlswXSwgcG9pbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBuVGhyZWFkczsgaSsrKSB7XG4gICAgICAgICAgICByZXNbMF0gPSBGci5hZGQocmVzWzBdLCBGci5tdWwoeE5baSAtIDFdLCByZXNbaV0pKTtcbiAgICAgICAgICAgIHhOW2ldID0gRnIubXVsKHhOW2kgLSAxXSwgeE5bMF0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc1swXTtcbiAgICB9XG5cbiAgICBhZGQocG9seW5vbWlhbCwgYmxpbmRpbmdWYWx1ZSkge1xuICAgICAgICBsZXQgb3RoZXIgPSBmYWxzZTtcblxuICAgICAgICBpZiAocG9seW5vbWlhbC5sZW5ndGgoKSA+IHRoaXMubGVuZ3RoKCkpIHtcbiAgICAgICAgICAgIG90aGVyID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHRoaXNMZW5ndGggPSB0aGlzLmxlbmd0aCgpO1xuICAgICAgICBjb25zdCBwb2x5TGVuZ3RoID0gcG9seW5vbWlhbC5sZW5ndGgoKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBNYXRoLm1heCh0aGlzTGVuZ3RoLCBwb2x5TGVuZ3RoKTsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBpX244ID0gaSAqIHRoaXMuRnIubjg7XG5cbiAgICAgICAgICAgIGNvbnN0IGEgPSBpIDwgdGhpc0xlbmd0aCA/IHRoaXMuY29lZi5zbGljZShpX244LCBpX244ICsgdGhpcy5Gci5uOCkgOiB0aGlzLkZyLnplcm87XG4gICAgICAgICAgICBsZXQgYiA9IGkgPCBwb2x5TGVuZ3RoID8gcG9seW5vbWlhbC5jb2VmLnNsaWNlKGlfbjgsIGlfbjggKyB0aGlzLkZyLm44KSA6IHRoaXMuRnIuemVybztcblxuICAgICAgICAgICAgaWYgKGJsaW5kaW5nVmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGIgPSB0aGlzLkZyLm11bChiLCBibGluZGluZ1ZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvdGhlcikge1xuICAgICAgICAgICAgICAgIHBvbHlub21pYWwuY29lZi5zZXQodGhpcy5Gci5hZGQoYSwgYiksIGlfbjgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvZWYuc2V0KHRoaXMuRnIuYWRkKGEsIGIpLCBpX244KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAob3RoZXIpIHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNvZWY7XG4gICAgICAgICAgICB0aGlzLmNvZWYgPSBwb2x5bm9taWFsLmNvZWY7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzdWIocG9seW5vbWlhbCwgYmxpbmRpbmdWYWx1ZSkge1xuICAgICAgICBsZXQgb3RoZXIgPSBmYWxzZTtcblxuICAgICAgICBpZiAocG9seW5vbWlhbC5sZW5ndGgoKSA+IHRoaXMubGVuZ3RoKCkpIHtcbiAgICAgICAgICAgIG90aGVyID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHRoaXNMZW5ndGggPSB0aGlzLmxlbmd0aCgpO1xuICAgICAgICBjb25zdCBwb2x5TGVuZ3RoID0gcG9seW5vbWlhbC5sZW5ndGgoKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBNYXRoLm1heCh0aGlzTGVuZ3RoLCBwb2x5TGVuZ3RoKTsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBpX244ID0gaSAqIHRoaXMuRnIubjg7XG5cbiAgICAgICAgICAgIGNvbnN0IGEgPSBpIDwgdGhpc0xlbmd0aCA/IHRoaXMuY29lZi5zbGljZShpX244LCBpX244ICsgdGhpcy5Gci5uOCkgOiB0aGlzLkZyLnplcm87XG4gICAgICAgICAgICBsZXQgYiA9IGkgPCBwb2x5TGVuZ3RoID8gcG9seW5vbWlhbC5jb2VmLnNsaWNlKGlfbjgsIGlfbjggKyB0aGlzLkZyLm44KSA6IHRoaXMuRnIuemVybztcblxuICAgICAgICAgICAgaWYgKGJsaW5kaW5nVmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGIgPSB0aGlzLkZyLm11bChiLCBibGluZGluZ1ZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvdGhlcikge1xuICAgICAgICAgICAgICAgIHBvbHlub21pYWwuY29lZi5zZXQodGhpcy5Gci5zdWIoYSwgYiksIGlfbjgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvZWYuc2V0KHRoaXMuRnIuc3ViKGEsIGIpLCBpX244KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAob3RoZXIpIHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNvZWY7XG4gICAgICAgICAgICB0aGlzLmNvZWYgPSBwb2x5bm9taWFsLmNvZWY7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBtdWxTY2FsYXIodmFsdWUpIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aCgpOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGlfbjggPSBpICogdGhpcy5Gci5uODtcblxuICAgICAgICAgICAgdGhpcy5jb2VmLnNldCh0aGlzLkZyLm11bCh0aGlzLmNvZWYuc2xpY2UoaV9uOCwgaV9uOCArIHRoaXMuRnIubjgpLCB2YWx1ZSksIGlfbjgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYWRkU2NhbGFyKHZhbHVlKSB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRWYWx1ZSA9IDAgPT09IHRoaXMubGVuZ3RoKCkgPyB0aGlzLkZyLnplcm8gOiB0aGlzLmNvZWYuc2xpY2UoMCwgdGhpcy5Gci5uOCk7XG4gICAgICAgIHRoaXMuY29lZi5zZXQodGhpcy5Gci5hZGQoY3VycmVudFZhbHVlLCB2YWx1ZSksIDApO1xuICAgIH1cblxuICAgIHN1YlNjYWxhcih2YWx1ZSkge1xuICAgICAgICBjb25zdCBjdXJyZW50VmFsdWUgPSAwID09PSB0aGlzLmxlbmd0aCgpID8gdGhpcy5Gci56ZXJvIDogdGhpcy5jb2VmLnNsaWNlKDAsIHRoaXMuRnIubjgpO1xuICAgICAgICB0aGlzLmNvZWYuc2V0KHRoaXMuRnIuc3ViKGN1cnJlbnRWYWx1ZSwgdmFsdWUpLCAwKTtcbiAgICB9XG5cbiAgICAvLyBNdWx0aXBseSBjdXJyZW50IHBvbHlub21pYWwgYnkgdGhlIHBvbHlub21pYWwgKFggLSB2YWx1ZSlcbiAgICBieVhTdWJWYWx1ZSh2YWx1ZSkge1xuICAgICAgICBjb25zdCBGciA9IHRoaXMuRnI7XG4gICAgICAgIGNvbnN0IHJlc2l6ZSA9ICFGci5lcShGci56ZXJvLCB0aGlzLmdldENvZWYodGhpcy5sZW5ndGgoKSAtIDEpKTtcblxuICAgICAgICBjb25zdCBsZW5ndGggPSByZXNpemUgPyB0aGlzLmxlbmd0aCgpICsgMSA6IHRoaXMubGVuZ3RoKCk7XG4gICAgICAgIGNvbnN0IGJ1ZmYgPSBsZW5ndGggPiAyIDw8IDE0ID8gbmV3IEJpZ0J1ZmZlcihsZW5ndGggKiBGci5uOCkgOiBuZXcgVWludDhBcnJheShsZW5ndGggKiBGci5uOCk7XG4gICAgICAgIGxldCBwb2wgPSBuZXcgUG9seW5vbWlhbChidWZmLCB0aGlzLmN1cnZlLCB0aGlzLmxvZ2dlcik7XG5cbiAgICAgICAgLy8gU3RlcCAwOiBTZXQgY3VycmVudCBjb2VmZmljaWVudHMgdG8gdGhlIG5ldyBidWZmZXIgc2hpZnRlZCBvbmUgcG9zaXRpb25cbiAgICAgICAgcG9sLmNvZWYuc2V0KHRoaXMuY29lZi5zbGljZSgwLCAobGVuZ3RoIC0gMSkgKiBGci5uOCksIDMyKTtcblxuICAgICAgICAvLyBTdGVwIDE6IG11bHRpcGx5IGVhY2ggY29lZmZpY2llbnQgYnkgKC12YWx1ZSlcbiAgICAgICAgdGhpcy5tdWxTY2FsYXIoRnIubmVnKHZhbHVlKSk7XG5cbiAgICAgICAgLy8gU3RlcCAyOiBBZGQgY3VycmVudCBwb2x5bm9taWFsIHRvIGRlc3RpbmF0aW9uIHBvbHlub21pYWxcbiAgICAgICAgcG9sLmFkZCh0aGlzKTtcblxuICAgICAgICAvLyBTd2FwIGJ1ZmZlcnNcbiAgICAgICAgdGhpcy5jb2VmID0gcG9sLmNvZWY7XG4gICAgfVxuXG4gICAgLy8gTXVsdGlwbHkgY3VycmVudCBwb2x5bm9taWFsIGJ5IHRoZSBwb2x5bm9taWFsIChYXm4gKyB2YWx1ZSlcbiAgICBieVhOU3ViVmFsdWUobiwgdmFsdWUpIHtcbiAgICAgICAgY29uc3QgRnIgPSB0aGlzLkZyO1xuICAgICAgICBjb25zdCByZXNpemUgPSAhKHRoaXMubGVuZ3RoKCkgLSBuIC0gMSA+PSB0aGlzLmRlZ3JlZSgpKTtcblxuICAgICAgICBjb25zdCBsZW5ndGggPSByZXNpemUgPyB0aGlzLmxlbmd0aCgpICsgbiA6IHRoaXMubGVuZ3RoKCk7XG4gICAgICAgIGNvbnN0IGJ1ZmYgPSBsZW5ndGggPiAyIDw8IDE0ID8gbmV3IEJpZ0J1ZmZlcihsZW5ndGggKiBGci5uOCkgOiBuZXcgVWludDhBcnJheShsZW5ndGggKiBGci5uOCk7XG4gICAgICAgIGxldCBwb2wgPSBuZXcgUG9seW5vbWlhbChidWZmLCB0aGlzLmN1cnZlLCB0aGlzLmxvZ2dlcik7XG5cbiAgICAgICAgLy8gU3RlcCAwOiBTZXQgY3VycmVudCBjb2VmZmljaWVudHMgdG8gdGhlIG5ldyBidWZmZXIgc2hpZnRlZCBvbmUgcG9zaXRpb25cbiAgICAgICAgcG9sLmNvZWYuc2V0KHRoaXMuY29lZi5zbGljZSgwLCAodGhpcy5kZWdyZWUoKSArIDEpICogMzIsICksIG4gKiAzMik7XG5cbiAgICAgICAgLy8gU3RlcCAxOiBtdWx0aXBseSBlYWNoIGNvZWZmaWNpZW50IGJ5ICgtIHZhbHVlKVxuICAgICAgICB0aGlzLm11bFNjYWxhcih2YWx1ZSk7XG5cbiAgICAgICAgLy8gU3RlcCAyOiBBZGQgY3VycmVudCBwb2x5bm9taWFsIHRvIGRlc3RpbmF0aW9uIHBvbHlub21pYWxcbiAgICAgICAgcG9sLmFkZCh0aGlzKTtcblxuICAgICAgICAvLyBTd2FwIGJ1ZmZlcnNcbiAgICAgICAgdGhpcy5jb2VmID0gcG9sLmNvZWY7XG4gICAgfVxuXG4gICAgLy8gRXVjbGlkZWFuIGRpdmlzaW9uXG4gICAgZGl2QnkocG9seW5vbWlhbCkge1xuICAgICAgICBjb25zdCBGciA9IHRoaXMuRnI7XG4gICAgICAgIGNvbnN0IGRlZ3JlZUEgPSB0aGlzLmRlZ3JlZSgpO1xuICAgICAgICBjb25zdCBkZWdyZWVCID0gcG9seW5vbWlhbC5kZWdyZWUoKTtcblxuICAgICAgICBsZXQgcG9sUiA9IG5ldyBQb2x5bm9taWFsKHRoaXMuY29lZiwgdGhpcy5jdXJ2ZSwgdGhpcy5sb2dnZXIpO1xuXG4gICAgICAgIHRoaXMuY29lZiA9IHRoaXMubGVuZ3RoKCkgPiAyIDw8IDE0ID9cbiAgICAgICAgICAgIG5ldyBCaWdCdWZmZXIodGhpcy5sZW5ndGgoKSAqIEZyLm44KSA6IG5ldyBVaW50OEFycmF5KHRoaXMubGVuZ3RoKCkgKiBGci5uOCk7XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IGRlZ3JlZUEgLSBkZWdyZWVCOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgdGhpcy5zZXRDb2VmKGksIEZyLmRpdihwb2xSLmdldENvZWYoaSArIGRlZ3JlZUIpLCBwb2x5bm9taWFsLmdldENvZWYoZGVncmVlQikpKTtcbiAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDw9IGRlZ3JlZUI7IGorKykge1xuICAgICAgICAgICAgICAgIHBvbFIuc2V0Q29lZihpICsgaiwgRnIuc3ViKHBvbFIuZ2V0Q29lZihpICsgaiksIEZyLm11bCh0aGlzLmdldENvZWYoaSksIHBvbHlub21pYWwuZ2V0Q29lZihqKSkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBwb2xSO1xuICAgIH1cblxuICAgIC8vIERpdmlzaW9uIGJ5IGEgUG9seW5vbWlhbCBvZiB0aGUgZm9ybSAoeF5tIC0gYmV0YSlcbiAgICBkaXZCeU1vbmljKG0sIGJldGEpIHtcbiAgICAgICAgY29uc3QgRnIgPSB0aGlzLkZyO1xuXG4gICAgICAgIGxldCBkID0gdGhpcy5kZWdyZWUoKTtcblxuICAgICAgICBsZXQgYnVmZmVyID0gdGhpcy5sZW5ndGgoKSA+IDIgPDwgMTQgP1xuICAgICAgICAgICAgbmV3IEJpZ0J1ZmZlcih0aGlzLmxlbmd0aCgpICogRnIubjgpIDogbmV3IFVpbnQ4QXJyYXkodGhpcy5sZW5ndGgoKSAqIEZyLm44KTtcbiAgICAgICAgbGV0IHF1b3RpZW50ID0gbmV3IFBvbHlub21pYWwoYnVmZmVyLCB0aGlzLmN1cnZlLCB0aGlzLmxvZ2dlcik7XG5cbiAgICAgICAgbGV0IGJBcnIgPSBbXTtcblxuICAgICAgICAvLyBBZGQgdGhlIG0gbGVhZGluZyBjb2VmZmljaWVudHMgb2YgdGhpcyB0byBxdW90aWVudFxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG07IGkrKykge1xuICAgICAgICAgICAgcXVvdGllbnQuc2V0Q29lZigoZCAtIGkpIC0gbSwgdGhpcy5nZXRDb2VmKGQgLSBpKSk7XG4gICAgICAgICAgICBiQXJyW2ldID0gdGhpcy5nZXRDb2VmKGQgLSBpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBuVGhyZWFkcyA9IG07XG5cbiAgICAgICAgbGV0IGogPSAwO1xuICAgICAgICBmb3IgKGxldCBrID0gMDsgayA8IG5UaHJlYWRzOyBrKyspIHtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBkIC0gMiAqIG0gLSBrOyBpID49IDA7IGkgPSBpIC0gblRocmVhZHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoaSA8IDApIGJyZWFrO1xuICAgICAgICAgICAgICAgIGxldCBpZHggPSBrO1xuICAgICAgICAgICAgICAgIGJBcnJbaWR4XSA9IEZyLmFkZCh0aGlzLmdldENvZWYoaSArIG0pLCBGci5tdWwoYkFycltpZHhdLCBiZXRhKSk7XG5cbiAgICAgICAgICAgICAgICBxdW90aWVudC5zZXRDb2VmKGksIGJBcnJbaWR4XSk7XG4gICAgICAgICAgICAgICAgaiA9IChqICsgMSkgJSBtO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5jb2VmID0gcXVvdGllbnQuY29lZjtcbiAgICB9XG5cbiAgICBkaXZCeVZhbmlzaGluZyhuLCBiZXRhKSB7XG4gICAgICAgIGlmICh0aGlzLmRlZ3JlZSgpIDwgbikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiZGl2QnlWYW5pc2hpbmcgcG9seW5vbWlhbCBkaXZpc29yIG11c3QgYmUgb2YgZGVncmVlIGxvd2VyIHRoYW4gdGhlIGRpdmlkZW5kIHBvbHlub21pYWxcIik7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBGciA9IHRoaXMuRnI7XG5cbiAgICAgICAgbGV0IHBvbFIgPSBuZXcgUG9seW5vbWlhbCh0aGlzLmNvZWYsIHRoaXMuY3VydmUsIHRoaXMubG9nZ2VyKTtcblxuICAgICAgICB0aGlzLmNvZWYgPSB0aGlzLmxlbmd0aCgpID4gMiA8PCAxNCA/XG4gICAgICAgICAgICBuZXcgQmlnQnVmZmVyKHRoaXMubGVuZ3RoKCkgKiBGci5uOCkgOiBuZXcgVWludDhBcnJheSh0aGlzLmxlbmd0aCgpICogRnIubjgpO1xuXG4gICAgICAgIGZvciAobGV0IGkgPSB0aGlzLmxlbmd0aCgpIC0gMTsgaSA+PSBuOyBpLS0pIHtcbiAgICAgICAgICAgIGxldCBsZWFkaW5nQ29lZiA9IHBvbFIuZ2V0Q29lZihpKTtcbiAgICAgICAgICAgIGlmIChGci5lcShGci56ZXJvLCBsZWFkaW5nQ29lZikpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICBwb2xSLnNldENvZWYoaSwgRnIuemVybyk7XG4gICAgICAgICAgICBwb2xSLnNldENvZWYoaSAtIG4sIEZyLmFkZChwb2xSLmdldENvZWYoaSAtIG4pLCBGci5tdWwoYmV0YSwgbGVhZGluZ0NvZWYpKSk7XG4gICAgICAgICAgICB0aGlzLnNldENvZWYoaSAtIG4sIEZyLmFkZCh0aGlzLmdldENvZWYoaSAtIG4pLCBsZWFkaW5nQ29lZikpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHBvbFI7XG4gICAgfVxuXG4gICAgZGl2QnlWYW5pc2hpbmcyKG0sIGJldGEpIHtcbiAgICAgICAgaWYgKHRoaXMuZGVncmVlKCkgPCBtKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJkaXZCeVZhbmlzaGluZyBwb2x5bm9taWFsIGRpdmlzb3IgbXVzdCBiZSBvZiBkZWdyZWUgbG93ZXIgdGhhbiB0aGUgZGl2aWRlbmQgcG9seW5vbWlhbFwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IEZyID0gdGhpcy5GcjtcblxuICAgICAgICBsZXQgcG9sUiA9IG5ldyBQb2x5bm9taWFsKHRoaXMuY29lZiwgdGhpcy5jdXJ2ZSwgdGhpcy5sb2dnZXIpO1xuXG4gICAgICAgIHRoaXMuY29lZiA9IHRoaXMubGVuZ3RoKCkgPiAyIDw8IDE0ID9cbiAgICAgICAgICAgIG5ldyBCaWdCdWZmZXIodGhpcy5sZW5ndGgoKSAqIEZyLm44KSA6IG5ldyBVaW50OEFycmF5KHRoaXMubGVuZ3RoKCkgKiBGci5uOCk7XG5cbiAgICAgICAgbGV0IG5UaHJlYWRzID0gMztcbiAgICAgICAgbGV0IG5Ub3RhbCA9IHRoaXMubGVuZ3RoKCkgLSBtO1xuICAgICAgICBsZXQgbkVsZW1lbnRzQ2h1bmsgPSBNYXRoLmZsb29yKG5Ub3RhbCAvIG5UaHJlYWRzKTtcbiAgICAgICAgbGV0IG5FbGVtZW50c0xhc3QgPSBuVG90YWwgLSAoblRocmVhZHMgLSAxKSAqIG5FbGVtZW50c0NodW5rO1xuXG4gICAgICAgIGNvbnNvbGUubG9nKG5Ub3RhbCk7XG4gICAgICAgIGNvbnNvbGUubG9nKG5FbGVtZW50c0NodW5rICsgXCIgIFwiICsgbkVsZW1lbnRzTGFzdCk7XG4gICAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwgblRocmVhZHM7IGsrKykge1xuICAgICAgICAgICAgY29uc29sZS5sb2coXCI+IFRocmVhZCBcIiArIGspO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IChrID09PSAwID8gbkVsZW1lbnRzTGFzdCA6IG5FbGVtZW50c0NodW5rKTsgaSA+IDA7IGktLSkge1xuICAgICAgICAgICAgICAgIGxldCBpZHhEc3QgPSBpIC0gMTtcbiAgICAgICAgICAgICAgICBpZiAoayAhPT0gMCkgaWR4RHN0ICs9IChrIC0gMSkgKiBuRWxlbWVudHNDaHVuayArIG5FbGVtZW50c0xhc3Q7XG4gICAgICAgICAgICAgICAgbGV0IGlkeFNyYyA9IGlkeERzdCArIG07XG5cbiAgICAgICAgICAgICAgICBsZXQgbGVhZGluZ0NvZWYgPSBwb2xSLmdldENvZWYoaWR4U3JjKTtcbiAgICAgICAgICAgICAgICBpZiAoRnIuZXEoRnIuemVybywgbGVhZGluZ0NvZWYpKSBjb250aW51ZTtcblxuICAgICAgICAgICAgICAgIHBvbFIuc2V0Q29lZihpZHhTcmMsIEZyLnplcm8pO1xuICAgICAgICAgICAgICAgIHBvbFIuc2V0Q29lZihpZHhEc3QsIEZyLmFkZChwb2xSLmdldENvZWYoaWR4RHN0KSwgRnIubXVsKGJldGEsIGxlYWRpbmdDb2VmKSkpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0Q29lZihpZHhEc3QsIEZyLmFkZCh0aGlzLmdldENvZWYoaWR4RHN0KSwgbGVhZGluZ0NvZWYpKTtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhpZHhEc3QgKyBcIiA8LS0gXCIgKyBpZHhTcmMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5wcmludCgpO1xuICAgICAgICByZXR1cm4gcG9sUjtcbiAgICB9XG5cbiAgICBmYXN0RGl2QnlWYW5pc2hpbmcoZGF0YSkge1xuICAgICAgICBjb25zdCBGciA9IHRoaXMuRnI7XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgICAgIGxldCBtID0gZGF0YVtpXVswXTtcbiAgICAgICAgICAgIGxldCBiZXRhID0gZGF0YVtpXVsxXTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuZGVncmVlKCkgPCBtKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiZGl2QnlWYW5pc2hpbmcgcG9seW5vbWlhbCBkaXZpc29yIG11c3QgYmUgb2YgZGVncmVlIGxvd2VyIHRoYW4gdGhlIGRpdmlkZW5kIHBvbHlub21pYWxcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBuVGhyZWFkcyA9IDU7XG4gICAgICAgICAgICBsZXQgbkVsZW1lbnRzID0gdGhpcy5sZW5ndGgoKSAtIG07XG4gICAgICAgICAgICBsZXQgbkVsZW1lbnRzQnVja2V0ID0gTWF0aC5mbG9vcihuRWxlbWVudHMgLyBuVGhyZWFkcyAvIG0pO1xuICAgICAgICAgICAgbGV0IG5FbGVtZW50c0NodW5rID0gbkVsZW1lbnRzQnVja2V0ICogbTtcbiAgICAgICAgICAgIGxldCBuRWxlbWVudHNMYXN0ID0gbkVsZW1lbnRzIC0gblRocmVhZHMgKiBuRWxlbWVudHNDaHVuaztcblxuICAgICAgICAgICAgLy9JbiBDKysgaW1wbGVtZW50YXRpb24gdGhpcyBidWZmZXIgd2lsbCBiZSBhbGxvY2F0ZWQgb25seSBvbmNlIG91dHNpZGUgdGhlIGxvb3BcbiAgICAgICAgICAgIGxldCBwb2xUbXAgPSBuZXcgUG9seW5vbWlhbCh0aGlzLmxlbmd0aCgpID4gMiA8PCAxNCA/XG4gICAgICAgICAgICAgICAgbmV3IEJpZ0J1ZmZlcih0aGlzLmxlbmd0aCgpICogRnIubjgpIDogbmV3IFVpbnQ4QXJyYXkodGhpcy5sZW5ndGgoKSAqIEZyLm44KSwgdGhpcy5jdXJ2ZSwgdGhpcy5sb2dnZXIpO1xuXG4gICAgICAgICAgICBsZXQgcHRyID0gdGhpcy5jb2VmO1xuICAgICAgICAgICAgdGhpcy5jb2VmID0gcG9sVG1wLmNvZWY7XG4gICAgICAgICAgICBwb2xUbXAuY29lZiA9IHB0cjtcblxuICAgICAgICAgICAgLy8gU1RFUCAxOiBTZXRlamFyIGVscyBtIHZhbG9ycyBkZWwgc2Vnw7xlbnQgYnVja2V0IGFsIGNodW5rIGFjdHVhbCwgUEFSQUxFTMK3TElUWkFSXG4gICAgICAgICAgICBmb3IgKGxldCBrID0gMDsgayA8IG5UaHJlYWRzOyBrKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgaWR4MCA9IChrICsgMSkgKiBuRWxlbWVudHNDaHVuayArIG5FbGVtZW50c0xhc3Q7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRDb2VmKGlkeDAgKyBpIC0gbSwgcG9sVG1wLmdldENvZWYoaWR4MCArIGkpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5FbGVtZW50c0NodW5rIC0gbTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBvZmZzZXQgPSBpZHgwIC0gaSAtIDE7XG4gICAgICAgICAgICAgICAgICAgIGxldCB2YWwgPSBGci5hZGQocG9sVG1wLmdldENvZWYob2Zmc2V0KSwgRnIubXVsKGJldGEsIHRoaXMuZ2V0Q29lZihvZmZzZXQpKSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0Q29lZihvZmZzZXQgLSBtLCB2YWwpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy9TVEVQIDI6IFNldGVqYXIgZWxzIHZhbG9ycyBkZWwgZWxlbWVudHMgbGFzdCBOTyBQQVJBTMK3TEVMSVRaQVJcbiAgICAgICAgICAgIGxldCBpZHgwID0gbkVsZW1lbnRzTGFzdDtcbiAgICAgICAgICAgIGxldCBwZW5kaW5nID0gbkVsZW1lbnRzTGFzdDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbSAmJiBwZW5kaW5nOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldENvZWYoaWR4MCAtIGkgLSAxLCBwb2xUbXAuZ2V0Q29lZihpZHgwICsgbSAtIGkgLSAxKSk7XG4gICAgICAgICAgICAgICAgcGVuZGluZy0tO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBlbmRpbmc7IGkrKykge1xuICAgICAgICAgICAgICAgIGxldCBvZmZzZXQgPSBpZHgwIC0gaSAtIDE7XG4gICAgICAgICAgICAgICAgbGV0IHZhbCA9IEZyLmFkZChwb2xUbXAuZ2V0Q29lZihvZmZzZXQpLCBGci5tdWwoYmV0YSwgdGhpcy5nZXRDb2VmKG9mZnNldCkpKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNldENvZWYob2Zmc2V0IC0gbSwgdmFsKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy9TdGVwIDM6IGNhbGN1bGFyIGFjdW11bGF0cyBOTyAgUEFSQUxFTMK3TElUWkFSXG5cbiAgICAgICAgICAgIGxldCBhY2MgPSBbXTtcbiAgICAgICAgICAgIGxldCBiZXRhUG93ID0gRnIub25lO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuRWxlbWVudHNCdWNrZXQ7IGkrKykge1xuICAgICAgICAgICAgICAgIGJldGFQb3cgPSBGci5tdWwoYmV0YVBvdywgYmV0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgY3VycmVudEJldGEgPSBGci5vbmU7XG5cbiAgICAgICAgICAgIGZvciAobGV0IGsgPSBuVGhyZWFkczsgayA+IDA7IGstLSkge1xuICAgICAgICAgICAgICAgIGxldCBpZFRocmVhZCA9IGsgLSAxO1xuICAgICAgICAgICAgICAgIGxldCBpZHgwID0gaWRUaHJlYWQgKiBuRWxlbWVudHNDaHVuayArIG5FbGVtZW50c0xhc3Q7XG4gICAgICAgICAgICAgICAgYWNjW2lkVGhyZWFkXSA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgYWNjW2lkVGhyZWFkXVtpXSA9IHRoaXMuZ2V0Q29lZihpZHgwICsgaSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGsgIT09IG5UaHJlYWRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhY2NbaWRUaHJlYWRdW2ldID0gRnIuYWRkKGFjY1tpZFRocmVhZF1baV0sIEZyLm11bChiZXRhUG93LCBhY2NbaWRUaHJlYWQgKyAxXVtpXSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGN1cnJlbnRCZXRhID0gRnIubXVsKGN1cnJlbnRCZXRhLCBiZXRhUG93KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy9TVEVQIDQgcmVjYWxjdWxhciAgUEFSQUxFTMK3TElUWkFSXG4gICAgICAgICAgICBmb3IgKGxldCBrID0gMDsgayA8IG5UaHJlYWRzOyBrKyspIHtcblxuICAgICAgICAgICAgICAgIGxldCBpZHgwID0gayAqIG5FbGVtZW50c0NodW5rICsgbkVsZW1lbnRzTGFzdDtcbiAgICAgICAgICAgICAgICBsZXQgY3VycmVudEJldGEgPSBiZXRhOyAvL1F1YW4gaG9wYXNzZW0gYSBDKysgaSBobyBwYXJhbGVsaXR6ZW0gYXF1ZXN0YSB2YXJpYWJsZSBoYSBkZSBzZXIgcHJpdmFkYVxuICAgICAgICAgICAgICAgIGxldCBjdXJyZW50TSA9IG0gLSAxO1xuXG4gICAgICAgICAgICAgICAgbGV0IGxpbWl0ID0gayA9PT0gMCA/IG5FbGVtZW50c0xhc3QgOiBuRWxlbWVudHNDaHVuaztcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpbWl0OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IG9mZnNldCA9IGlkeDAgLSBpIC0gMTtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHZhbCA9IEZyLmFkZCh0aGlzLmdldENvZWYob2Zmc2V0KSwgRnIubXVsKGN1cnJlbnRCZXRhLCBhY2Nba11bY3VycmVudE1dKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRDb2VmKG9mZnNldCwgdmFsKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBUbyBhdm9pZCBtb2R1bGFyIG9wZXJhdGlvbnMgaW4gZWFjaCBsb29wLi4uXG4gICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50TSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudE0gPSBtIC0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRCZXRhID0gRnIubXVsKGN1cnJlbnRCZXRhLCBiZXRhKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRNLS07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8vIERpdmlkZSBwb2x5bm9taWFsIGJ5IFggLSB2YWx1ZVxuICAgIGRpdkJ5WFN1YlZhbHVlKHZhbHVlKSB7XG4gICAgICAgIGNvbnN0IGNvZWZzID0gdGhpcy5sZW5ndGgoKSA+IDIgPDwgMTQgP1xuICAgICAgICAgICAgbmV3IEJpZ0J1ZmZlcih0aGlzLmxlbmd0aCgpICogdGhpcy5Gci5uOCkgOiBuZXcgVWludDhBcnJheSh0aGlzLmxlbmd0aCgpICogdGhpcy5Gci5uOCk7XG5cbiAgICAgICAgY29lZnMuc2V0KHRoaXMuRnIuemVybywgKHRoaXMubGVuZ3RoKCkgLSAxKSAqIHRoaXMuRnIubjgpO1xuICAgICAgICBjb2Vmcy5zZXQodGhpcy5jb2VmLnNsaWNlKCh0aGlzLmxlbmd0aCgpIC0gMSkgKiB0aGlzLkZyLm44LCB0aGlzLmxlbmd0aCgpICogdGhpcy5Gci5uOCksICh0aGlzLmxlbmd0aCgpIC0gMikgKiB0aGlzLkZyLm44KTtcbiAgICAgICAgZm9yIChsZXQgaSA9IHRoaXMubGVuZ3RoKCkgLSAzOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgbGV0IGlfbjggPSBpICogdGhpcy5Gci5uODtcbiAgICAgICAgICAgIGNvZWZzLnNldChcbiAgICAgICAgICAgICAgICB0aGlzLkZyLmFkZChcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb2VmLnNsaWNlKGlfbjggKyB0aGlzLkZyLm44LCBpX244ICsgMiAqIHRoaXMuRnIubjgpLFxuICAgICAgICAgICAgICAgICAgICB0aGlzLkZyLm11bCh2YWx1ZSwgY29lZnMuc2xpY2UoaV9uOCArIHRoaXMuRnIubjgsIGlfbjggKyAyICogdGhpcy5Gci5uOCkpXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBpICogdGhpcy5Gci5uOFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMuRnIuZXEoXG4gICAgICAgICAgICB0aGlzLmNvZWYuc2xpY2UoMCwgdGhpcy5Gci5uOCksXG4gICAgICAgICAgICB0aGlzLkZyLm11bCh0aGlzLkZyLm5lZyh2YWx1ZSksIGNvZWZzLnNsaWNlKDAsIHRoaXMuRnIubjgpKVxuICAgICAgICApKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJQb2x5bm9taWFsIGRvZXMgbm90IGRpdmlkZVwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY29lZiA9IGNvZWZzO1xuICAgIH1cblxuICAgIGRpdlpoKGRvbWFpblNpemUsIGV4dGVuc2lvbnMgPSA0KSB7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZG9tYWluU2l6ZTsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBpX244ID0gaSAqIHRoaXMuRnIubjg7XG4gICAgICAgICAgICB0aGlzLmNvZWYuc2V0KHRoaXMuRnIubmVnKHRoaXMuY29lZi5zbGljZShpX244LCBpX244ICsgdGhpcy5Gci5uOCkpLCBpX244KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHVwcGVyQm91bmQgPSB0aGlzLmNvZWYuYnl0ZUxlbmd0aCAvIHRoaXMuRnIubjg7XG4gICAgICAgIGZvciAobGV0IGkgPSBkb21haW5TaXplOyBpIDwgdXBwZXJCb3VuZDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBpX244ID0gaSAqIHRoaXMuRnIubjg7XG5cbiAgICAgICAgICAgIGNvbnN0IGEgPSB0aGlzLkZyLnN1YihcbiAgICAgICAgICAgICAgICB0aGlzLmNvZWYuc2xpY2UoKGkgLSBkb21haW5TaXplKSAqIHRoaXMuRnIubjgsIChpIC0gZG9tYWluU2l6ZSkgKiB0aGlzLkZyLm44ICsgdGhpcy5Gci5uOCksXG4gICAgICAgICAgICAgICAgdGhpcy5jb2VmLnNsaWNlKGlfbjgsIGlfbjggKyB0aGlzLkZyLm44KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHRoaXMuY29lZi5zZXQoYSwgaV9uOCk7XG4gICAgICAgICAgICBpZiAoaSA+IChkb21haW5TaXplICogKGV4dGVuc2lvbnMtMSkgLSBleHRlbnNpb25zKSkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5Gci5pc1plcm8oYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUG9seW5vbWlhbCBpcyBub3QgZGl2aXNpYmxlXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGRpdkJ5WmVyb2ZpZXIobiwgYmV0YSkge1xuICAgICAgICBsZXQgRnIgPSB0aGlzLkZyO1xuICAgICAgICBjb25zdCBpbnZCZXRhID0gRnIuaW52KGJldGEpO1xuICAgICAgICBjb25zdCBpbnZCZXRhTmVnID0gRnIubmVnKGludkJldGEpO1xuXG4gICAgICAgIGxldCBpc09uZSA9IEZyLmVxKEZyLm9uZSwgaW52QmV0YU5lZyk7XG4gICAgICAgIGxldCBpc05lZ09uZSA9IEZyLmVxKEZyLm5lZ29uZSwgaW52QmV0YU5lZyk7XG5cbiAgICAgICAgaWYgKCFpc09uZSkge1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBpX244ID0gaSAqIHRoaXMuRnIubjg7XG4gICAgICAgICAgICAgICAgbGV0IGVsZW1lbnQ7XG5cbiAgICAgICAgICAgICAgICAvLyBJZiBpbnZCZXRhTmVnID09PSAtMSB3ZSdsbCBzYXZlIGEgbXVsdGlwbGljYXRpb24gY2hhbmdpbmcgaXQgYnkgYSBuZWcgZnVuY3Rpb24gY2FsbFxuICAgICAgICAgICAgICAgIGlmIChpc05lZ09uZSkge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50ID0gRnIubmVnKHRoaXMuY29lZi5zbGljZShpX244LCBpX244ICsgdGhpcy5Gci5uOCkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQgPSBGci5tdWwoaW52QmV0YU5lZywgdGhpcy5jb2VmLnNsaWNlKGlfbjgsIGlfbjggKyB0aGlzLkZyLm44KSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5jb2VmLnNldChlbGVtZW50LCBpX244KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlzT25lID0gRnIuZXEoRnIub25lLCBpbnZCZXRhKTtcbiAgICAgICAgaXNOZWdPbmUgPSBGci5lcShGci5uZWdvbmUsIGludkJldGEpO1xuXG4gICAgICAgIGZvciAobGV0IGkgPSBuOyBpIDwgdGhpcy5sZW5ndGgoKTsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBpX244ID0gaSAqIHRoaXMuRnIubjg7XG4gICAgICAgICAgICBjb25zdCBpX3ByZXZfbjggPSAoaSAtIG4pICogdGhpcy5Gci5uODtcblxuICAgICAgICAgICAgbGV0IGVsZW1lbnQgPSB0aGlzLkZyLnN1YihcbiAgICAgICAgICAgICAgICB0aGlzLmNvZWYuc2xpY2UoaV9wcmV2X244LCBpX3ByZXZfbjggKyB0aGlzLkZyLm44KSxcbiAgICAgICAgICAgICAgICB0aGlzLmNvZWYuc2xpY2UoaV9uOCwgaV9uOCArIHRoaXMuRnIubjgpXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAvLyBJZiBpbnZCZXRhID09PSAxIHdlJ2xsIG5vdCBkbyBhbnl0aGluZ1xuICAgICAgICAgICAgaWYoIWlzT25lKSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgaW52QmV0YSA9PT0gLTEgd2UnbGwgc2F2ZSBhIG11bHRpcGxpY2F0aW9uIGNoYW5naW5nIGl0IGJ5IGEgbmVnIGZ1bmN0aW9uIGNhbGxcbiAgICAgICAgICAgICAgICBpZihpc05lZ09uZSkge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50ID0gRnIubmVnKGVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQgPSBGci5tdWwoaW52QmV0YSwgZWxlbWVudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmNvZWYuc2V0KGVsZW1lbnQsIGlfbjgpO1xuXG4gICAgICAgICAgICAvLyBDaGVjayBpZiBwb2x5bm9taWFsIGlzIGRpdmlzaWJsZSBieSBjaGVja2luZyBpZiBuIGhpZ2ggY29lZmZpY2llbnRzIGFyZSB6ZXJvXG4gICAgICAgICAgICBpZiAoaSA+IHRoaXMubGVuZ3RoKCkgLSBuIC0gMSkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5Gci5pc1plcm8oZWxlbWVudCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUG9seW5vbWlhbCBpcyBub3QgZGl2aXNpYmxlXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuLy8gZnVuY3Rpb24gZGl2aWRlQnlWYW5pc2hpbmcoZiwgbiwgcCkge1xuLy8gICAgIC8vIHBvbHlub21pYWwgZGl2aXNpb24gZihYKSAvIChYXm4gLSAxKSB3aXRoIHJlbWFpbmRlclxuLy8gICAgIC8vIHZlcnkgY2hlYXAsIDAgbXVsdGlwbGljYXRpb25zXG4vLyAgICAgLy8gc3RyYXRlZ3k6XG4vLyAgICAgLy8gc3RhcnQgd2l0aCBxKFgpID0gMCwgcihYKSA9IGYoWClcbi8vICAgICAvLyB0aGVuIHN0YXJ0IGNoYW5naW5nIHEsIHIgd2hpbGUgcHJlc2VydmluZyB0aGUgaWRlbnRpdHk6XG4vLyAgICAgLy8gZihYKSA9IHEoWCkgKiAoWF5uIC0gMSkgKyByKFgpXG4vLyAgICAgLy8gaW4gZXZlcnkgc3RlcCwgbW92ZSBoaWdoZXN0LWRlZ3JlZSB0ZXJtIG9mIHIgaW50byB0aGUgcHJvZHVjdFxuLy8gICAgIC8vID0+IHIgZXZlbnR1YWxseSBoYXMgZGVncmVlIDwgbiBhbmQgd2UncmUgZG9uZVxuLy8gICAgIGxldCBxID0gQXJyYXkoZi5sZW5ndGgpLmZpbGwoMG4pO1xuLy8gICAgIGxldCByID0gWy4uLmZdO1xuLy8gICAgIGZvciAobGV0IGkgPSBmLmxlbmd0aCAtIDE7IGkgPj0gbjsgaS0tKSB7XG4vLyAgICAgICAgIGxldCBsZWFkaW5nQ29lZmYgPSByW2ldO1xuLy8gICAgICAgICBpZiAobGVhZGluZ0NvZWZmID09PSAwbikgY29udGludWU7XG4vLyAgICAgICAgIHJbaV0gPSAwbjtcbi8vICAgICAgICAgcltpIC0gbl0gPSBtb2QocltpIC0gbl0gKyBsZWFkaW5nQ29lZmYsIHApO1xuLy8gICAgICAgICBxW2kgLSBuXSA9IG1vZChxW2kgLSBuXSArIGxlYWRpbmdDb2VmZiwgcCk7XG4vLyAgICAgfVxuLy8gICAgIHJldHVybiBbcSwgcl07XG4vLyB9XG5cbiAgICBieVgoKSB7XG4gICAgICAgIGNvbnN0IGNvZWZzID0gKHRoaXMubGVuZ3RoKCkgKyAxKSA+IDIgPDwgMTQgP1xuICAgICAgICAgICAgbmV3IEJpZ0J1ZmZlcih0aGlzLmNvZWYuYnl0ZUxlbmd0aCArIHRoaXMuRnIubjgpIDogbmV3IFVpbnQ4QXJyYXkodGhpcy5jb2VmLmJ5dGVMZW5ndGggKyB0aGlzLkZyLm44KTtcbiAgICAgICAgY29lZnMuc2V0KHRoaXMuRnIuemVybywgMCk7XG4gICAgICAgIGNvZWZzLnNldCh0aGlzLmNvZWYsIHRoaXMuRnIubjgpO1xuXG4gICAgICAgIHRoaXMuY29lZiA9IGNvZWZzO1xuICAgIH1cblxuLy8gQ29tcHV0ZSBhIG5ldyBwb2x5bm9taWFsIGYoeF5uKSBmcm9tIGYoeClcbi8vIGYoeCkgICA9IGFfMCArIGFfMcK3eCArIGFfMsK3eF4yICsgLi4uICsgYV9qwrd4Xmpcbi8vIGYoeF5uKSA9IGFfMCArIGFfMcK3eF5uICsgYV8ywrd4XjJuICsgLi4uICsgYV9qwrd4XmpuXG4gICAgc3RhdGljXG4gICAgYXN5bmMgZXhwWChwb2x5bm9taWFsLCBuLCB0cnVuY2F0ZSA9IGZhbHNlKSB7XG4gICAgICAgIGNvbnN0IEZyID0gcG9seW5vbWlhbC5GcjtcblxuICAgICAgICBpZiAobiA8IDEpIHtcbiAgICAgICAgICAgIC8vIG4gPT0gMCBub3QgYWxsb3dlZCBiZWNhdXNlIGl0IGhhcyBubyBzZW5zZSwgYnV0IGlmIGl0J3MgbmVjZXNzYXJ5IHdlIGhhdmUgdG8gcmV0dXJuXG4gICAgICAgICAgICAvLyBhIHplcm8gZGVncmVlIHBvbHlub21pYWwgd2l0aCBhIGNvbnN0YW50IGNvZWZmaWNpZW50IGVxdWFscyB0byB0aGUgc3VtIG9mIGFsbCB0aGUgb3JpZ2luYWwgY29lZmZpY2llbnRzXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb21wdXRlIGEgbmV3IHBvbHlub21pYWwgdG8gYSB6ZXJvIG9yIG5lZ2F0aXZlIG51bWJlciBpcyBub3QgYWxsb3dlZFwiKTtcbiAgICAgICAgfSBlbHNlIGlmICgxID09PSBuKSB7XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgUG9seW5vbWlhbC5mcm9tRXZhbHVhdGlvbnMocG9seW5vbWlhbC5jb2VmLCBjdXJ2ZSwgcG9seW5vbWlhbC5sb2dnZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gbGVuZ3RoIGlzIHRoZSBsZW5ndGggb2Ygbm9uLWNvbnN0YW50IGNvZWZmaWNpZW50c1xuICAgICAgICAvLyBpZiB0cnVuY2F0ZSA9PT0gdHJ1ZSwgdGhlIGhpZ2hlc3QgemVybyBjb2VmZmljaWVudHMgKGlmIGV4aXN0KSB3aWxsIGJlIHJlbW92ZWRcbiAgICAgICAgY29uc3QgbGVuZ3RoID0gdHJ1bmNhdGUgPyBwb2x5bm9taWFsLmRlZ3JlZSgpIDogKHBvbHlub21pYWwubGVuZ3RoKCkgLSAxKTtcbiAgICAgICAgY29uc3QgYnVmZmVyRHN0ID0gKGxlbmd0aCAqIG4gKyAxKSA+IDIgPDwgMTQgP1xuICAgICAgICAgICAgbmV3IEJpZ0J1ZmZlcigobGVuZ3RoICogbiArIDEpICogRnIubjgpIDogbmV3IFVpbnQ4QXJyYXkoKGxlbmd0aCAqIG4gKyAxKSAqIEZyLm44KTtcblxuICAgICAgICAvLyBDb3B5IGNvbnN0YW50IGNvZWZmaWNpZW50IGFzIGlzIGJlY2F1c2UgaXMgbm90IHJlbGF0ZWQgdG8geFxuICAgICAgICBidWZmZXJEc3Quc2V0KHBvbHlub21pYWwuZ2V0Q29lZigwKSwgMCk7XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPD0gbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGlfc0ZyID0gaSAqIEZyLm44O1xuXG4gICAgICAgICAgICBjb25zdCBjb2VmID0gcG9seW5vbWlhbC5nZXRDb2VmKGkpO1xuICAgICAgICAgICAgYnVmZmVyRHN0LnNldChjb2VmLCBpX3NGciAqIG4pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5ldyBQb2x5bm9taWFsKGJ1ZmZlckRzdCwgcG9seW5vbWlhbC5jdXJ2ZSwgcG9seW5vbWlhbC5sb2dnZXIpO1xuICAgIH1cblxuICAgIHNwbGl0KG51bVBvbHMsIGRlZ1BvbHMsIGJsaW5kaW5nRmFjdG9ycykge1xuICAgICAgICBpZiAobnVtUG9scyA8IDEpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgUG9seW5vbWlhbHMgY2FuJ3QgYmUgc3BsaXQgaW4gJHtudW1Qb2xzfSBwYXJ0c2ApO1xuICAgICAgICB9IGVsc2UgaWYgKDEgPT09IG51bVBvbHMpIHtcbiAgICAgICAgICAgIHJldHVybiBbdGhpc107XG4gICAgICAgIH1cblxuICAgICAgICAvL2JsaW5kaW5nIGZhY3RvcnMgY2FuIGJlIHZvaWQgb3IgbXVzdCBoYXZlIGEgbGVuZ3RoIG9mIG51bVBvbHMgLSAxXG4gICAgICAgIGlmICgwICE9PSBibGluZGluZ0ZhY3RvcnMubGVuZ3RoICYmIGJsaW5kaW5nRmFjdG9ycy5sZW5ndGggPCBudW1Qb2xzIC0gMSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBCbGluZGluZyBmYWN0b3JzIGxlbmd0aCBtdXN0IGJlICR7bnVtUG9scyAtIDF9YCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjaHVua0J5dGVMZW5ndGggPSAoZGVnUG9scyArIDEpICogdGhpcy5Gci5uODtcbiAgICAgICAgbGV0IHJlcyA9IFtdO1xuXG4gICAgICAgIC8vIENoZWNrIHBvbHlub21pYWwgY2FuIGJlIHNwbGl0IGluIG51bUNodW5rcyBwYXJ0cyBvZiBjaHVua1NpemUgYnl0ZXMuLi5cbiAgICAgICAgY29uc3QgbnVtUmVhbFBvbHMgPSBNYXRoLmNlaWwoKHRoaXMuZGVncmVlKCkgKyAxKSAqIHRoaXMuRnIubjggLyBjaHVua0J5dGVMZW5ndGgpO1xuICAgICAgICBpZiAobnVtUmVhbFBvbHMgPCBudW1Qb2xzKSB7XG4gICAgICAgICAgICAvL3Rocm93IG5ldyBFcnJvcihgUG9seW5vbWlhbCBpcyBzaG9ydCB0byBiZSBzcGxpdCBpbiAke251bVBvbHN9IHBhcnRzIG9mICR7ZGVnUG9sc30gY29lZmZpY2llbnRzIGVhY2guYCk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gbnVtUmVhbFBvbHM7IGkgPCBudW1Qb2xzOyBpKyspIHtcbiAgICAgICAgICAgICAgICByZXNbaV0gPSBuZXcgUG9seW5vbWlhbChuZXcgVWludDhBcnJheSh0aGlzLkZyLm44KSwgdGhpcy5jdXJ2ZSwgdGhpcy5sb2dnZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbnVtUG9scyA9IE1hdGgubWluKG51bVBvbHMsIG51bVJlYWxQb2xzKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1Qb2xzOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGlzTGFzdCA9IChudW1Qb2xzIC0gMSkgPT09IGk7XG4gICAgICAgICAgICBjb25zdCBieXRlTGVuZ3RoID0gaXNMYXN0ID8gdGhpcy5jb2VmLmJ5dGVMZW5ndGggLSAoKG51bVBvbHMgLSAxKSAqIGNodW5rQnl0ZUxlbmd0aCkgOiBjaHVua0J5dGVMZW5ndGggKyB0aGlzLkZyLm44O1xuXG4gICAgICAgICAgICBsZXQgYnVmZiA9IChieXRlTGVuZ3RoIC8gdGhpcy5Gci5uOCkgPiAyIDw8IDE0ID8gbmV3IEJpZ0J1ZmZlcihieXRlTGVuZ3RoKSA6IG5ldyBVaW50OEFycmF5KGJ5dGVMZW5ndGgpO1xuICAgICAgICAgICAgcmVzW2ldID0gbmV3IFBvbHlub21pYWwoYnVmZiwgdGhpcy5jdXJ2ZSwgdGhpcy5sb2dnZXIpO1xuXG4gICAgICAgICAgICBjb25zdCBmciA9IGkgKiBjaHVua0J5dGVMZW5ndGg7XG4gICAgICAgICAgICBjb25zdCB0byA9IGlzTGFzdCA/IHRoaXMuY29lZi5ieXRlTGVuZ3RoIDogKGkgKyAxKSAqIGNodW5rQnl0ZUxlbmd0aDtcbiAgICAgICAgICAgIHJlc1tpXS5jb2VmLnNldCh0aGlzLmNvZWYuc2xpY2UoZnIsIHRvKSwgMCk7XG5cbiAgICAgICAgICAgIC8vIEFkZCBhIGJsaW5kaW5nIGZhY3RvciBhcyBoaWdoZXIgZGVncmVlXG4gICAgICAgICAgICBpZiAoIWlzTGFzdCkge1xuICAgICAgICAgICAgICAgIHJlc1tpXS5jb2VmLnNldChibGluZGluZ0ZhY3RvcnNbaV0sIGNodW5rQnl0ZUxlbmd0aCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFN1YiBibGluZGluZyBmYWN0b3IgdG8gdGhlIGxvd2VzdCBkZWdyZWVcbiAgICAgICAgICAgIGlmICgwICE9PSBpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbG93ZXN0RGVncmVlID0gdGhpcy5Gci5zdWIocmVzW2ldLmNvZWYuc2xpY2UoMCwgdGhpcy5Gci5uOCksIGJsaW5kaW5nRmFjdG9yc1tpIC0gMV0pO1xuICAgICAgICAgICAgICAgIHJlc1tpXS5jb2VmLnNldChsb3dlc3REZWdyZWUsIDApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoaXNMYXN0KSB7XG4gICAgICAgICAgICAgICAgcmVzW2ldLnRydW5jYXRlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzO1xuXG4gICAgICAgIC8vIC8vIGNvbXB1dGUgdF9sb3coWClcbiAgICAgICAgLy8gbGV0IHBvbFRMb3cgPSBuZXcgQmlnQnVmZmVyKChjaHVua1NpemUgKyAxKSAqIG44cik7XG4gICAgICAgIC8vIHBvbFRMb3cuc2V0KHQuc2xpY2UoMCwgemtleS5kb21haW5TaXplICogbjhyKSwgMCk7XG4gICAgICAgIC8vIC8vIEFkZCBibGluZGluZyBzY2FsYXIgYl8xMCBhcyBhIG5ldyBjb2VmZmljaWVudCBuXG4gICAgICAgIC8vIHBvbFRMb3cuc2V0KGNoLmJbMTBdLCB6a2V5LmRvbWFpblNpemUgKiBuOHIpO1xuICAgICAgICAvL1xuICAgICAgICAvLyAvLyBjb21wdXRlIHRfbWlkKFgpXG4gICAgICAgIC8vIGxldCBwb2xUTWlkID0gbmV3IEJpZ0J1ZmZlcigoemtleS5kb21haW5TaXplICsgMSkgKiBuOHIpO1xuICAgICAgICAvLyBwb2xUTWlkLnNldCh0LnNsaWNlKHprZXkuZG9tYWluU2l6ZSAqIG44ciwgemtleS5kb21haW5TaXplICogMiAqIG44ciksIDApO1xuICAgICAgICAvLyAvLyBTdWJ0cmFjdCBibGluZGluZyBzY2FsYXIgYl8xMCB0byB0aGUgbG93ZXN0IGNvZWZmaWNpZW50IG9mIHRfbWlkXG4gICAgICAgIC8vIGNvbnN0IGxvd2VzdE1pZCA9IEZyLnN1Yihwb2xUTWlkLnNsaWNlKDAsIG44ciksIGNoLmJbMTBdKTtcbiAgICAgICAgLy8gcG9sVE1pZC5zZXQobG93ZXN0TWlkLCAwKTtcbiAgICAgICAgLy8gLy8gQWRkIGJsaW5kaW5nIHNjYWxhciBiXzExIGFzIGEgbmV3IGNvZWZmaWNpZW50IG5cbiAgICAgICAgLy8gcG9sVE1pZC5zZXQoY2guYlsxMV0sIHprZXkuZG9tYWluU2l6ZSAqIG44cik7XG4gICAgICAgIC8vXG4gICAgICAgIC8vIC8vIGNvbXB1dGUgdF9oaWdoKFgpXG4gICAgICAgIC8vIGxldCBwb2xUSGlnaCA9IG5ldyBCaWdCdWZmZXIoKHprZXkuZG9tYWluU2l6ZSArIDYpICogbjhyKTtcbiAgICAgICAgLy8gcG9sVEhpZ2guc2V0KHQuc2xpY2UoemtleS5kb21haW5TaXplICogMiAqIG44ciwgKHprZXkuZG9tYWluU2l6ZSAqIDMgKyA2KSAqIG44ciksIDApO1xuICAgICAgICAvLyAvL1N1YnRyYWN0IGJsaW5kaW5nIHNjYWxhciBiXzExIHRvIHRoZSBsb3dlc3QgY29lZmZpY2llbnQgb2YgdF9oaWdoXG4gICAgICAgIC8vIGNvbnN0IGxvd2VzdEhpZ2ggPSBGci5zdWIocG9sVEhpZ2guc2xpY2UoMCwgbjhyKSwgY2guYlsxMV0pO1xuICAgICAgICAvLyBwb2xUSGlnaC5zZXQobG93ZXN0SGlnaCwgMCk7XG4gICAgICAgIC8vXG4gICAgICAgIC8vIHByb29mLlQxID0gYXdhaXQgZXhwVGF1KHBvbFRMb3csIFwibXVsdGlleHAgVDFcIik7XG4gICAgICAgIC8vIHByb29mLlQyID0gYXdhaXQgZXhwVGF1KHBvbFRNaWQsIFwibXVsdGlleHAgVDJcIik7XG4gICAgICAgIC8vIHByb29mLlQzID0gYXdhaXQgZXhwVGF1KHBvbFRIaWdoLCBcIm11bHRpZXhwIFQzXCIpO1xuICAgIH1cblxuLy8gc3BsaXQyKGRlZ1BvbHMsIGJsaW5kaW5nRmFjdG9ycykge1xuLy8gICAgIGxldCBjdXJyZW50RGVncmVlID0gdGhpcy5kZWdyZWUoKTtcbi8vICAgICBjb25zdCBudW1GaWxsZWRQb2xzID0gTWF0aC5jZWlsKChjdXJyZW50RGVncmVlICsgMSkgLyAoZGVnUG9scyArIDEpKTtcbi8vXG4vLyAgICAgLy9ibGluZGluZyBmYWN0b3JzIGNhbiBiZSB2b2lkIG9yIG11c3QgaGF2ZSBhIGxlbmd0aCBvZiBudW1Qb2xzIC0gMVxuLy8gICAgIGlmICgwICE9PSBibGluZGluZ0ZhY3RvcnMubGVuZ3RoICYmIGJsaW5kaW5nRmFjdG9ycy5sZW5ndGggPCBudW1GaWxsZWRQb2xzIC0gMSkge1xuLy8gICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEJsaW5kaW5nIGZhY3RvcnMgbGVuZ3RoIG11c3QgYmUgJHtudW1GaWxsZWRQb2xzIC0gMX1gKTtcbi8vICAgICB9XG4vL1xuLy8gICAgIGNvbnN0IGNodW5rQnl0ZUxlbmd0aCA9IChkZWdQb2xzICsgMSkgKiB0aGlzLkZyLm44O1xuLy9cbi8vICAgICAvLyBDaGVjayBwb2x5bm9taWFsIGNhbiBiZSBzcGxpdCBpbiBudW1DaHVua3MgcGFydHMgb2YgY2h1bmtTaXplIGJ5dGVzLi4uXG4vLyAgICAgaWYgKHRoaXMuY29lZi5ieXRlTGVuZ3RoIC8gY2h1bmtCeXRlTGVuZ3RoIDw9IG51bUZpbGxlZFBvbHMgLSAxKSB7XG4vLyAgICAgICAgIHRocm93IG5ldyBFcnJvcihgUG9seW5vbWlhbCBpcyBzaG9ydCB0byBiZSBzcGxpdCBpbiAke251bUZpbGxlZFBvbHN9IHBhcnRzIG9mICR7ZGVnUG9sc30gY29lZmZpY2llbnRzIGVhY2guYCk7XG4vLyAgICAgfVxuLy9cbi8vICAgICBsZXQgcmVzID0gW107XG4vLyAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1GaWxsZWRQb2xzOyBpKyspIHtcbi8vICAgICAgICAgY29uc3QgaXNMYXN0ID0gKG51bUZpbGxlZFBvbHMgLSAxKSA9PT0gaTtcbi8vICAgICAgICAgY29uc3QgYnl0ZUxlbmd0aCA9IGlzTGFzdCA/IChjdXJyZW50RGVncmVlICsgMSkgKiB0aGlzLkZyLm44IC0gKChudW1GaWxsZWRQb2xzIC0gMSkgKiBjaHVua0J5dGVMZW5ndGgpIDogY2h1bmtCeXRlTGVuZ3RoICsgdGhpcy5Gci5uODtcbi8vXG4vLyAgICAgICAgIHJlc1tpXSA9IG5ldyBQb2x5bm9taWFsKG5ldyBCaWdCdWZmZXIoYnl0ZUxlbmd0aCksIHRoaXMuRnIsIHRoaXMubG9nZ2VyKTtcbi8vICAgICAgICAgY29uc3QgZnIgPSBpICogY2h1bmtCeXRlTGVuZ3RoO1xuLy8gICAgICAgICBjb25zdCB0byA9IGlzTGFzdCA/IChjdXJyZW50RGVncmVlICsgMSkgKiB0aGlzLkZyLm44IDogKGkgKyAxKSAqIGNodW5rQnl0ZUxlbmd0aDtcbi8vICAgICAgICAgcmVzW2ldLmNvZWYuc2V0KHRoaXMuY29lZi5zbGljZShmciwgdG8pLCAwKTtcbi8vXG4vLyAgICAgICAgIC8vIEFkZCBhIGJsaW5kaW5nIGZhY3RvciBhcyBoaWdoZXIgZGVncmVlXG4vLyAgICAgICAgIGlmICghaXNMYXN0KSB7XG4vLyAgICAgICAgICAgICByZXNbaV0uY29lZi5zZXQoYmxpbmRpbmdGYWN0b3JzW2ldLCBjaHVua0J5dGVMZW5ndGgpO1xuLy8gICAgICAgICB9XG4vL1xuLy8gICAgICAgICAvLyBTdWIgYmxpbmRpbmcgZmFjdG9yIHRvIHRoZSBsb3dlc3QgZGVncmVlXG4vLyAgICAgICAgIGlmICgwICE9PSBpKSB7XG4vLyAgICAgICAgICAgICBjb25zdCBsb3dlc3REZWdyZWUgPSB0aGlzLkZyLnN1YihyZXNbaV0uY29lZi5zbGljZSgwLCB0aGlzLkZyLm44KSwgYmxpbmRpbmdGYWN0b3JzW2kgLSAxXSk7XG4vLyAgICAgICAgICAgICByZXNbaV0uY29lZi5zZXQobG93ZXN0RGVncmVlLCAwKTtcbi8vICAgICAgICAgfVxuLy8gICAgIH1cbi8vXG4vLyAgICAgcmV0dXJuIHJlcztcbi8vIH1cblxuLy8gbWVyZ2UocG9scywgb3ZlcmxhcCA9IHRydWUpIHtcbi8vICAgICBsZXQgbGVuZ3RoID0gMDtcbi8vICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBvbHMubGVuZ3RoOyBpKyspIHtcbi8vICAgICAgICAgbGVuZ3RoICs9IHBvbHNbaV0ubGVuZ3RoKCk7XG4vLyAgICAgfVxuLy9cbi8vICAgICBpZiAob3ZlcmxhcCkge1xuLy8gICAgICAgICBsZW5ndGggLT0gcG9scy5sZW5ndGggLSAxO1xuLy8gICAgIH1cbi8vXG4vLyAgICAgbGV0IHJlcyA9IG5ldyBQb2x5bm9taWFsKG5ldyBCaWdCdWZmZXIobGVuZ3RoICogdGhpcy5Gci5uOCkpO1xuLy8gICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcG9scy5sZW5ndGg7IGkrKykge1xuLy8gICAgICAgICBjb25zdCBieXRlTGVuZ3RoID0gcG9sc1tpXS5jb2VmLmJ5dGVMZW5ndGg7XG4vLyAgICAgICAgIGlmICgwID09PSBpKSB7XG4vLyAgICAgICAgICAgICByZXMuY29lZi5zZXQocG9sc1tpXS5jb2VmLCAwKTtcbi8vICAgICAgICAgfSBlbHNlIHtcbi8vXG4vLyAgICAgICAgIH1cbi8vICAgICB9XG4vL1xuLy8gICAgIHJldHVybiByZXM7XG4vLyB9XG5cbiAgICB0cnVuY2F0ZSgpIHtcbiAgICAgICAgY29uc3QgZGVnID0gdGhpcy5kZWdyZWUoKTtcbiAgICAgICAgaWYgKGRlZyArIDEgPCB0aGlzLmNvZWYuYnl0ZUxlbmd0aCAvIHRoaXMuRnIubjgpIHtcbiAgICAgICAgICAgIGNvbnN0IG5ld0NvZWZzID0gKGRlZyArIDEpID4gMiA8PCAxNCA/XG4gICAgICAgICAgICAgICAgbmV3IEJpZ0J1ZmZlcigoZGVnICsgMSkgKiB0aGlzLkZyLm44KSA6IG5ldyBVaW50OEFycmF5KChkZWcgKyAxKSAqIHRoaXMuRnIubjgpO1xuXG4gICAgICAgICAgICBuZXdDb2Vmcy5zZXQodGhpcy5jb2VmLnNsaWNlKDAsIChkZWcgKyAxKSAqIHRoaXMuRnIubjgpLCAwKTtcbiAgICAgICAgICAgIHRoaXMuY29lZiA9IG5ld0NvZWZzO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc3RhdGljIGxhZ3JhbmdlUG9seW5vbWlhbEludGVycG9sYXRpb24oeEFyciwgeUFyciwgY3VydmUpIHtcbiAgICAgICAgY29uc3QgRnIgPSBjdXJ2ZS5GcjtcbiAgICAgICAgbGV0IHBvbHlub21pYWwgPSBjb21wdXRlTGFncmFuZ2VQb2x5bm9taWFsKDApO1xuICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IHhBcnIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHBvbHlub21pYWwuYWRkKGNvbXB1dGVMYWdyYW5nZVBvbHlub21pYWwoaSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHBvbHlub21pYWw7XG5cbiAgICAgICAgZnVuY3Rpb24gY29tcHV0ZUxhZ3JhbmdlUG9seW5vbWlhbChpKSB7XG4gICAgICAgICAgICBsZXQgcG9seW5vbWlhbDtcblxuICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB4QXJyLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGogPT09IGkpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBvbHlub21pYWwgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgYnVmZiA9ICh4QXJyLmxlbmd0aCkgPiAyIDw8IDE0ID9cbiAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBCaWdCdWZmZXIoKHhBcnIubGVuZ3RoKSAqIEZyLm44KSA6IG5ldyBVaW50OEFycmF5KCh4QXJyLmxlbmd0aCkgKiBGci5uOCk7XG4gICAgICAgICAgICAgICAgICAgIHBvbHlub21pYWwgPSBuZXcgUG9seW5vbWlhbChidWZmLCBjdXJ2ZSk7XG4gICAgICAgICAgICAgICAgICAgIHBvbHlub21pYWwuc2V0Q29lZigwLCBGci5uZWcoeEFycltqXSkpO1xuICAgICAgICAgICAgICAgICAgICBwb2x5bm9taWFsLnNldENvZWYoMSwgRnIub25lKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBwb2x5bm9taWFsLmJ5WFN1YlZhbHVlKHhBcnJbal0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV0IGRlbm9taW5hdG9yID0gcG9seW5vbWlhbC5ldmFsdWF0ZSh4QXJyW2ldKTtcbiAgICAgICAgICAgIGRlbm9taW5hdG9yID0gRnIuaW52KGRlbm9taW5hdG9yKTtcbiAgICAgICAgICAgIGNvbnN0IG11bEZhY3RvciA9IEZyLm11bCh5QXJyW2ldLCBkZW5vbWluYXRvcik7XG5cbiAgICAgICAgICAgIHBvbHlub21pYWwubXVsU2NhbGFyKG11bEZhY3Rvcik7XG5cbiAgICAgICAgICAgIHJldHVybiBwb2x5bm9taWFsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc3RhdGljIHplcm9maWVyUG9seW5vbWlhbCh4QXJyLCBjdXJ2ZSkge1xuICAgICAgICBjb25zdCBGciA9IGN1cnZlLkZyO1xuICAgICAgICBsZXQgYnVmZiA9ICh4QXJyLmxlbmd0aCArIDEpID4gMiA8PCAxNCA/XG4gICAgICAgICAgICBuZXcgQmlnQnVmZmVyKCh4QXJyLmxlbmd0aCArIDEpICogRnIubjgpIDogbmV3IFVpbnQ4QXJyYXkoKHhBcnIubGVuZ3RoICsgMSkgKiBGci5uOCk7XG4gICAgICAgIGxldCBwb2x5bm9taWFsID0gbmV3IFBvbHlub21pYWwoYnVmZiwgY3VydmUpO1xuXG4gICAgICAgIC8vIEJ1aWxkIGEgemVyb2ZpZXIgcG9seW5vbWlhbCB3aXRoIHRoZSBmb2xsb3dpbmcgZm9ybTpcbiAgICAgICAgLy8gemVyb2ZpZXIoWCkgPSAoWC14QXJyWzBdKShYLXhBcnJbMV0pLi4uKFgteEFycltuXSlcbiAgICAgICAgcG9seW5vbWlhbC5zZXRDb2VmKDAsIEZyLm5lZyh4QXJyWzBdKSk7XG4gICAgICAgIHBvbHlub21pYWwuc2V0Q29lZigxLCBGci5vbmUpO1xuXG4gICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgeEFyci5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgcG9seW5vbWlhbC5ieVhTdWJWYWx1ZSh4QXJyW2ldKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBwb2x5bm9taWFsO1xuICAgIH1cblxuICAgIHByaW50KCkge1xuICAgICAgICBjb25zdCBGciA9IHRoaXMuRnI7XG4gICAgICAgIGxldCByZXMgPSBcIlwiO1xuICAgICAgICBmb3IgKGxldCBpID0gdGhpcy5kZWdyZWUoKTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgIGNvbnN0IGNvZWYgPSB0aGlzLmdldENvZWYoaSk7XG4gICAgICAgICAgICBpZiAoIUZyLmVxKEZyLnplcm8sIGNvZWYpKSB7XG4gICAgICAgICAgICAgICAgaWYgKEZyLmlzTmVnYXRpdmUoY29lZikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzICs9IFwiIC0gXCI7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpICE9PSB0aGlzLmRlZ3JlZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlcyArPSBcIiArIFwiO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXMgKz0gRnIudG9TdHJpbmcoY29lZik7XG4gICAgICAgICAgICAgICAgaWYgKGkgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlcyArPSBpID4gMSA/IFwieF5cIiArIGkgOiBcInhcIjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS5sb2cocmVzKTtcbiAgICB9XG5cbiAgICBhc3luYyBtdWx0aUV4cG9uZW50aWF0aW9uKFBUYXUsIG5hbWUpIHtcbiAgICAgICAgY29uc3QgbiA9IHRoaXMuY29lZi5ieXRlTGVuZ3RoIC8gdGhpcy5Gci5uODtcbiAgICAgICAgY29uc3QgUFRhdU4gPSBQVGF1LnNsaWNlKDAsIG4gKiB0aGlzLkcxLkYubjggKiAyKTtcbiAgICAgICAgY29uc3QgYm0gPSBhd2FpdCB0aGlzLkZyLmJhdGNoRnJvbU1vbnRnb21lcnkodGhpcy5jb2VmKTtcbiAgICAgICAgbGV0IHJlcyA9IGF3YWl0IHRoaXMuRzEubXVsdGlFeHBBZmZpbmUoUFRhdU4sIGJtLCB0aGlzLmxvZ2dlciwgbmFtZSk7XG4gICAgICAgIHJlcyA9IHRoaXMuRzEudG9BZmZpbmUocmVzKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG59IiwiLypcbiAgICBDb3B5cmlnaHQgMjAyMiBpZGVuMyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJranMuXG5cbiAgICBzbmFya2pzIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4gICAgbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZVxuICAgIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKVxuICAgIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtqcyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICAgIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvclxuICAgIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFsb25nIHdpdGhcbiAgICBzbmFya2pzLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuaW1wb3J0IHtCaWdCdWZmZXJ9IGZyb20gXCJmZmphdmFzY3JpcHRcIjtcblxuZXhwb3J0IGNsYXNzIEV2YWx1YXRpb25zIHtcbiAgICBjb25zdHJ1Y3RvcihldmFsdWF0aW9ucywgY3VydmUsIGxvZ2dlcikge1xuICAgICAgICB0aGlzLmV2YWwgPSBldmFsdWF0aW9ucztcbiAgICAgICAgdGhpcy5jdXJ2ZSA9IGN1cnZlO1xuICAgICAgICB0aGlzLkZyID0gY3VydmUuRnI7XG4gICAgICAgIHRoaXMubG9nZ2VyID0gbG9nZ2VyO1xuICAgIH1cblxuICAgIHN0YXRpYyBhc3luYyBmcm9tUG9seW5vbWlhbChwb2x5bm9taWFsLCBleHRlbnNpb24sIGN1cnZlLCBsb2dnZXIpIHtcbiAgICAgICAgY29uc3QgY29lZmZpY2llbnRzTiA9IG5ldyBCaWdCdWZmZXIocG9seW5vbWlhbC5sZW5ndGgoKSAqIGV4dGVuc2lvbiAqIGN1cnZlLkZyLm44KTtcbiAgICAgICAgY29lZmZpY2llbnRzTi5zZXQocG9seW5vbWlhbC5jb2VmLCAwKTtcblxuICAgICAgICBjb25zdCBldmFsdWF0aW9ucyA9IGF3YWl0IGN1cnZlLkZyLmZmdChjb2VmZmljaWVudHNOKTtcblxuICAgICAgICByZXR1cm4gbmV3IEV2YWx1YXRpb25zKGV2YWx1YXRpb25zLCBjdXJ2ZSwgbG9nZ2VyKTtcbiAgICB9XG5cbiAgICBnZXRFdmFsdWF0aW9uKGluZGV4KSB7XG4gICAgICAgIGNvbnN0IGlfbjggPSBpbmRleCAqIHRoaXMuRnIubjg7XG5cbiAgICAgICAgaWYgKGlfbjggKyB0aGlzLkZyLm44ID4gdGhpcy5ldmFsLmJ5dGVMZW5ndGgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkV2YWx1YXRpb25zLmdldEV2YWx1YXRpb24oKSBvdXQgb2YgYm91bmRzXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuZXZhbC5zbGljZShpX244LCBpX244ICsgdGhpcy5Gci5uOCk7XG4gICAgfVxuXG4gICAgbGVuZ3RoKCkge1xuICAgICAgICBsZXQgbGVuZ3RoID0gdGhpcy5ldmFsLmJ5dGVMZW5ndGggLyB0aGlzLkZyLm44O1xuICAgICAgICBpZiAobGVuZ3RoICE9PSBNYXRoLmZsb29yKHRoaXMuZXZhbC5ieXRlTGVuZ3RoIC8gdGhpcy5Gci5uOCkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlBvbHlub21pYWwgZXZhbHVhdGlvbnMgYnVmZmVyIGhhcyBpbmNvcnJlY3Qgc2l6ZVwiKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoMCA9PT0gbGVuZ3RoKSB7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci53YXJuKFwiUG9seW5vbWlhbCBoYXMgbGVuZ3RoIHplcm9cIik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGxlbmd0aDtcbiAgICB9XG59IiwiLypcbiAgICBDb3B5cmlnaHQgMjAyMSAwa2ltcyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJranMuXG5cbiAgICBzbmFya2pzIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4gICAgbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZVxuICAgIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKVxuICAgIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtqcyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICAgIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvclxuICAgIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFsb25nIHdpdGhcbiAgICBzbmFya2pzLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuLyogSW1wbGVtZW50YXRpb24gb2YgdGhpcyBwYXBlcjogaHR0cHM6Ly9lcHJpbnQuaWFjci5vcmcvMjAxOS85NTMucGRmIHNlY3Rpb24gOC40ICovXG5cbmltcG9ydCAqIGFzIGJpbkZpbGVVdGlscyBmcm9tIFwiQGlkZW4zL2JpbmZpbGV1dGlsc1wiO1xuaW1wb3J0ICogYXMgemtleVV0aWxzIGZyb20gXCIuL3prZXlfdXRpbHMuanNcIjtcbmltcG9ydCAqIGFzIHd0bnNVdGlscyBmcm9tIFwiLi93dG5zX3V0aWxzLmpzXCI7XG5pbXBvcnQgeyBTY2FsYXIsIHV0aWxzLCBCaWdCdWZmZXIgfSBmcm9tIFwiZmZqYXZhc2NyaXB0XCI7XG5jb25zdCB7c3RyaW5naWZ5QmlnSW50c30gPSB1dGlscztcbmltcG9ydCB7IFByb29mIH0gZnJvbSBcIi4vcHJvb2YuanNcIjtcbmltcG9ydCB7IEtlY2NhazI1NlRyYW5zY3JpcHQgfSBmcm9tIFwiLi9LZWNjYWsyNTZUcmFuc2NyaXB0LmpzXCI7XG5pbXBvcnQgeyBNdWxaIH0gZnJvbSBcIi4vbXVsX3ouanNcIjtcbmltcG9ydCB7ICBaS0VZX1BMX0hFQURFUl9TRUNUSU9OLFxuICAgIFpLRVlfUExfQURESVRJT05TX1NFQ1RJT04sXG4gICAgWktFWV9QTF9BX01BUF9TRUNUSU9OLFxuICAgIFpLRVlfUExfQl9NQVBfU0VDVElPTixcbiAgICBaS0VZX1BMX0NfTUFQX1NFQ1RJT04sXG4gICAgWktFWV9QTF9RTV9TRUNUSU9OLFxuICAgIFpLRVlfUExfUUxfU0VDVElPTixcbiAgICBaS0VZX1BMX1FSX1NFQ1RJT04sXG4gICAgWktFWV9QTF9RT19TRUNUSU9OLFxuICAgIFpLRVlfUExfUUNfU0VDVElPTixcbiAgICBaS0VZX1BMX1NJR01BX1NFQ1RJT04sXG4gICAgWktFWV9QTF9MQUdSQU5HRV9TRUNUSU9OLFxuICAgIFpLRVlfUExfUFRBVV9TRUNUSU9OLFxufSBmcm9tIFwiLi9wbG9ua19jb25zdGFudHMuanNcIjtcbmltcG9ydCB7IFBvbHlub21pYWwgfSBmcm9tIFwiLi9wb2x5bm9taWFsL3BvbHlub21pYWwuanNcIjtcbmltcG9ydCB7IEV2YWx1YXRpb25zIH0gZnJvbSBcIi4vcG9seW5vbWlhbC9ldmFsdWF0aW9ucy5qc1wiO1xuICAgIFxuZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gcGxvbmsxNlByb3ZlKHprZXlGaWxlTmFtZSwgd2l0bmVzc0ZpbGVOYW1lLCBsb2dnZXIsIG9wdGlvbnMpIHtcbiAgICBjb25zdCB7ZmQ6IGZkV3Rucywgc2VjdGlvbnM6IHNlY3Rpb25zV3Ruc30gPSBhd2FpdCBiaW5GaWxlVXRpbHMucmVhZEJpbkZpbGUod2l0bmVzc0ZpbGVOYW1lLCBcInd0bnNcIiwgMiwgMTw8MjUsIDE8PDIzKTtcblxuICAgIC8vIFJlYWQgd2l0bmVzcyBmaWxlXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKFwiPiBSZWFkaW5nIHdpdG5lc3MgZmlsZVwiKTtcbiAgICBjb25zdCB3dG5zID0gYXdhaXQgd3Ruc1V0aWxzLnJlYWRIZWFkZXIoZmRXdG5zLCBzZWN0aW9uc1d0bnMpO1xuXG4gICAgLy8gUmVhZCB6a2V5IGZpbGVcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCI+IFJlYWRpbmcgemtleSBmaWxlXCIpO1xuICAgIGNvbnN0IHtmZDogZmRaS2V5LCBzZWN0aW9uczogemtleVNlY3Rpb25zfSA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkQmluRmlsZSh6a2V5RmlsZU5hbWUsIFwiemtleVwiLCAyLCAxPDwyNSwgMTw8MjMpO1xuXG4gICAgY29uc3QgemtleSA9IGF3YWl0IHprZXlVdGlscy5yZWFkSGVhZGVyKGZkWktleSwgemtleVNlY3Rpb25zLCB1bmRlZmluZWQsIG9wdGlvbnMpO1xuICAgIGlmICh6a2V5LnByb3RvY29sICE9IFwicGxvbmtcIikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ6a2V5IGZpbGUgaXMgbm90IHBsb25rXCIpO1xuICAgIH1cblxuICAgIGlmICghU2NhbGFyLmVxKHprZXkuciwgIHd0bnMucSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ3VydmUgb2YgdGhlIHdpdG5lc3MgZG9lcyBub3QgbWF0Y2ggdGhlIGN1cnZlIG9mIHRoZSBwcm92aW5nIGtleVwiKTtcbiAgICB9XG5cbiAgICBpZiAod3Rucy5uV2l0bmVzcyAhPSB6a2V5Lm5WYXJzIC16a2V5Lm5BZGRpdGlvbnMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHdpdG5lc3MgbGVuZ3RoLiBDaXJjdWl0OiAke3prZXkublZhcnN9LCB3aXRuZXNzOiAke3d0bnMubldpdG5lc3N9LCAke3prZXkubkFkZGl0aW9uc31gKTtcbiAgICB9XG5cbiAgICBjb25zdCBjdXJ2ZSA9IHprZXkuY3VydmU7XG5cbiAgICBjb25zdCBGciA9IGN1cnZlLkZyO1xuICAgIGNvbnN0IG44ciA9IGN1cnZlLkZyLm44O1xuICAgIGNvbnN0IHNEb21haW4gPSB6a2V5LmRvbWFpblNpemUgKiBuOHI7XG5cbiAgICBpZiAobG9nZ2VyKSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhcIiAgUExPTksgUFJPVkUgU0VUVElOR1NcIik7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhgICBDdXJ2ZTogICAgICAgICAke2N1cnZlLm5hbWV9YCk7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhgICBDaXJjdWl0IHBvd2VyOiAke3prZXkucG93ZXJ9YCk7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhgICBEb21haW4gc2l6ZTogICAke3prZXkuZG9tYWluU2l6ZX1gKTtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKGAgIFZhcnM6ICAgICAgICAgICR7emtleS5uVmFyc31gKTtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKGAgIFB1YmxpYyB2YXJzOiAgICR7emtleS5uUHVibGljfWApO1xuICAgICAgICBsb2dnZXIuZGVidWcoYCAgQ29uc3RyYWludHM6ICAgJHt6a2V5Lm5Db25zdHJhaW50c31gKTtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKGAgIEFkZGl0aW9uczogICAgICR7emtleS5uQWRkaXRpb25zfWApO1xuICAgICAgICBsb2dnZXIuZGVidWcoXCItLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXCIpO1xuICAgIH1cblxuICAgIC8vUmVhZCB3aXRuZXNzIGRhdGFcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCI+IFJlYWRpbmcgd2l0bmVzcyBmaWxlIGRhdGFcIik7XG4gICAgY29uc3QgYnVmZldpdG5lc3MgPSBhd2FpdCBiaW5GaWxlVXRpbHMucmVhZFNlY3Rpb24oZmRXdG5zLCBzZWN0aW9uc1d0bnMsIDIpO1xuXG4gICAgLy8gRmlyc3QgZWxlbWVudCBpbiBwbG9uayBpcyBub3QgdXNlZCBhbmQgY2FuIGJlIGFueSB2YWx1ZS4gKEJ1dCBhbHdheXMgdGhlIHNhbWUpLlxuICAgIC8vIFdlIHNldCBpdCB0byB6ZXJvIHRvIGdvIGZhc3RlciBpbiB0aGUgZXhwb25lbnRpYXRpb25zLlxuICAgIGJ1ZmZXaXRuZXNzLnNldChGci56ZXJvLCAwKTtcbiAgICBjb25zdCBidWZmSW50ZXJuYWxXaXRuZXNzID0gbmV3IEJpZ0J1ZmZlcihuOHIqemtleS5uQWRkaXRpb25zKTtcblxuICAgIGxldCBidWZmZXJzID0ge307XG4gICAgbGV0IHBvbHlub21pYWxzID0ge307XG4gICAgbGV0IGV2YWx1YXRpb25zID0ge307XG5cbiAgICBsZXQgY2hhbGxlbmdlcyA9IHt9O1xuICAgIGxldCBwcm9vZiA9IG5ldyBQcm9vZihjdXJ2ZSwgbG9nZ2VyKTtcbiAgICBjb25zdCB0cmFuc2NyaXB0ID0gbmV3IEtlY2NhazI1NlRyYW5zY3JpcHQoY3VydmUpO1xuXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKGA+IFJlYWRpbmcgU2VjdGlvbiAke1pLRVlfUExfQURESVRJT05TX1NFQ1RJT059LiBBZGRpdGlvbnNgKTtcbiAgICBhd2FpdCBjYWxjdWxhdGVBZGRpdGlvbnMoKTtcblxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhgPiBSZWFkaW5nIFNlY3Rpb24gJHtaS0VZX1BMX1NJR01BX1NFQ1RJT059LiBTaWdtYTEsIFNpZ21hMiAmIFNpZ21hIDNgKTtcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCLCt8K3wrcgUmVhZGluZyBTaWdtYSBwb2x5bm9taWFscyBcIik7XG4gICAgcG9seW5vbWlhbHMuU2lnbWExID0gbmV3IFBvbHlub21pYWwobmV3IEJpZ0J1ZmZlcihzRG9tYWluKSwgY3VydmUsIGxvZ2dlcik7XG4gICAgcG9seW5vbWlhbHMuU2lnbWEyID0gbmV3IFBvbHlub21pYWwobmV3IEJpZ0J1ZmZlcihzRG9tYWluKSwgY3VydmUsIGxvZ2dlcik7XG4gICAgcG9seW5vbWlhbHMuU2lnbWEzID0gbmV3IFBvbHlub21pYWwobmV3IEJpZ0J1ZmZlcihzRG9tYWluKSwgY3VydmUsIGxvZ2dlcik7XG5cbiAgICBhd2FpdCBmZFpLZXkucmVhZFRvQnVmZmVyKHBvbHlub21pYWxzLlNpZ21hMS5jb2VmLCAwLCBzRG9tYWluLCB6a2V5U2VjdGlvbnNbWktFWV9QTF9TSUdNQV9TRUNUSU9OXVswXS5wKTtcbiAgICBhd2FpdCBmZFpLZXkucmVhZFRvQnVmZmVyKHBvbHlub21pYWxzLlNpZ21hMi5jb2VmLCAwLCBzRG9tYWluLCB6a2V5U2VjdGlvbnNbWktFWV9QTF9TSUdNQV9TRUNUSU9OXVswXS5wICsgNSAqIHNEb21haW4pO1xuICAgIGF3YWl0IGZkWktleS5yZWFkVG9CdWZmZXIocG9seW5vbWlhbHMuU2lnbWEzLmNvZWYsIDAsIHNEb21haW4sIHprZXlTZWN0aW9uc1taS0VZX1BMX1NJR01BX1NFQ1RJT05dWzBdLnAgKyAxMCAqIHNEb21haW4pO1xuXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKFwiwrfCt8K3IFJlYWRpbmcgU2lnbWEgZXZhbHVhdGlvbnNcIik7XG4gICAgZXZhbHVhdGlvbnMuU2lnbWExID0gbmV3IEV2YWx1YXRpb25zKG5ldyBCaWdCdWZmZXIoc0RvbWFpbiAqIDQpLCBjdXJ2ZSwgbG9nZ2VyKTtcbiAgICBldmFsdWF0aW9ucy5TaWdtYTIgPSBuZXcgRXZhbHVhdGlvbnMobmV3IEJpZ0J1ZmZlcihzRG9tYWluICogNCksIGN1cnZlLCBsb2dnZXIpO1xuICAgIGV2YWx1YXRpb25zLlNpZ21hMyA9IG5ldyBFdmFsdWF0aW9ucyhuZXcgQmlnQnVmZmVyKHNEb21haW4gKiA0KSwgY3VydmUsIGxvZ2dlcik7XG5cbiAgICBhd2FpdCBmZFpLZXkucmVhZFRvQnVmZmVyKGV2YWx1YXRpb25zLlNpZ21hMS5ldmFsLCAwLCBzRG9tYWluICogNCwgemtleVNlY3Rpb25zW1pLRVlfUExfU0lHTUFfU0VDVElPTl1bMF0ucCArIHNEb21haW4pO1xuICAgIGF3YWl0IGZkWktleS5yZWFkVG9CdWZmZXIoZXZhbHVhdGlvbnMuU2lnbWEyLmV2YWwsIDAsIHNEb21haW4gKiA0LCB6a2V5U2VjdGlvbnNbWktFWV9QTF9TSUdNQV9TRUNUSU9OXVswXS5wICsgNiAqIHNEb21haW4pO1xuICAgIGF3YWl0IGZkWktleS5yZWFkVG9CdWZmZXIoZXZhbHVhdGlvbnMuU2lnbWEzLmV2YWwsIDAsIHNEb21haW4gKiA0LCB6a2V5U2VjdGlvbnNbWktFWV9QTF9TSUdNQV9TRUNUSU9OXVswXS5wICsgMTEgKiBzRG9tYWluKTtcblxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhgPiBSZWFkaW5nIFNlY3Rpb24gJHtaS0VZX1BMX1BUQVVfU0VDVElPTn0uIFBvd2VycyBvZiBUYXVgKTtcbiAgICBjb25zdCBQVGF1ID0gYXdhaXQgYmluRmlsZVV0aWxzLnJlYWRTZWN0aW9uKGZkWktleSwgemtleVNlY3Rpb25zLCBaS0VZX1BMX1BUQVVfU0VDVElPTik7XG5cbiAgICBsZXQgcHVibGljU2lnbmFscyA9IFtdO1xuXG4gICAgZm9yIChsZXQgaT0xOyBpPD0gemtleS5uUHVibGljOyBpKyspIHtcbiAgICAgICAgY29uc3QgcHViID0gYnVmZldpdG5lc3Muc2xpY2UoaSpGci5uOCwgaSpGci5uOCtGci5uOCk7XG4gICAgICAgIHB1YmxpY1NpZ25hbHMucHVzaChTY2FsYXIuZnJvbVJwckxFKHB1YikpO1xuICAgIH1cblxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIlwiKTtcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCI+IFJPVU5EIDFcIik7XG4gICAgYXdhaXQgcm91bmQxKCk7XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCI+IFJPVU5EIDJcIik7XG4gICAgYXdhaXQgcm91bmQyKCk7XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCI+IFJPVU5EIDNcIik7XG4gICAgYXdhaXQgcm91bmQzKCk7XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCI+IFJPVU5EIDRcIik7XG4gICAgYXdhaXQgcm91bmQ0KCk7XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCI+IFJPVU5EIDVcIik7XG4gICAgYXdhaXQgcm91bmQ1KCk7XG5cbiAgICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAgIC8vIEZpbmFsIGFkanVzdG1lbnRzIC8vXG4gICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cblxuICAgIGF3YWl0IGZkWktleS5jbG9zZSgpO1xuICAgIGF3YWl0IGZkV3Rucy5jbG9zZSgpO1xuXG4gICAgLy8gUHJlcGFyZSBwcm9vZlxuICAgIGxldCBfcHJvb2YgPSBwcm9vZi50b09iamVjdFByb29mKGZhbHNlKTtcbiAgICBfcHJvb2YucHJvdG9jb2wgPSBcInBsb25rXCI7XG4gICAgX3Byb29mLmN1cnZlID0gY3VydmUubmFtZTtcbiAgICBcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCJQTE9OSyBQUk9WRVIgRklOSVNIRURcIik7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBwcm9vZjogc3RyaW5naWZ5QmlnSW50cyhfcHJvb2YpLFxuICAgICAgICBwdWJsaWNTaWduYWxzOiBzdHJpbmdpZnlCaWdJbnRzKHB1YmxpY1NpZ25hbHMpXG4gICAgfTtcblxuICAgIGFzeW5jIGZ1bmN0aW9uIGNhbGN1bGF0ZUFkZGl0aW9ucygpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKFwiwrfCt8K3IENvbXB1dGluZyBhZGRpdGlvbnNcIik7XG4gICAgICAgIGNvbnN0IGFkZGl0aW9uc0J1ZmYgPSBhd2FpdCBiaW5GaWxlVXRpbHMucmVhZFNlY3Rpb24oZmRaS2V5LCB6a2V5U2VjdGlvbnMsIFpLRVlfUExfQURESVRJT05TX1NFQ1RJT04pO1xuXG4gICAgICAgIC8vIHNpemVzOiB3aXJlSWRfeCA9IDQgYnl0ZXMgKDMyIGJpdHMpLCBmYWN0b3JfeCA9IGZpZWxkIHNpemUgYml0c1xuICAgICAgICAvLyBBZGRpdGlvbiBmb3JtOiB3aXJlSWRfYSB3aXJlSWRfYiBmYWN0b3JfYSBmYWN0b3JfYiAoc2l6ZSBpcyA0ICsgNCArIHNGciArIHNGcilcbiAgICAgICAgY29uc3Qgc1N1bSA9IDggKyBuOHIgKiAyO1xuXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgemtleS5uQWRkaXRpb25zOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIgJiYgKDAgIT09IGkpICYmIChpICUgMTAwMDAwID09PSAwKSkgbG9nZ2VyLmRlYnVnKGAgICAgYWRkaXRpb24gJHtpfS8ke3prZXkubkFkZGl0aW9uc31gKTtcblxuICAgICAgICAgICAgLy8gUmVhZCBhZGRpdGlvbiB2YWx1ZXNcbiAgICAgICAgICAgIGxldCBvZmZzZXQgPSBpICogc1N1bTtcbiAgICAgICAgICAgIGNvbnN0IHNpZ25hbElkMSA9IHJlYWRVSW50MzIoYWRkaXRpb25zQnVmZiwgb2Zmc2V0KTtcbiAgICAgICAgICAgIG9mZnNldCArPSA0O1xuICAgICAgICAgICAgY29uc3Qgc2lnbmFsSWQyID0gcmVhZFVJbnQzMihhZGRpdGlvbnNCdWZmLCBvZmZzZXQpO1xuICAgICAgICAgICAgb2Zmc2V0ICs9IDQ7XG4gICAgICAgICAgICBjb25zdCBmYWN0b3IxID0gYWRkaXRpb25zQnVmZi5zbGljZShvZmZzZXQsIG9mZnNldCArIG44cik7XG4gICAgICAgICAgICBvZmZzZXQgKz0gbjhyO1xuICAgICAgICAgICAgY29uc3QgZmFjdG9yMiA9IGFkZGl0aW9uc0J1ZmYuc2xpY2Uob2Zmc2V0LCBvZmZzZXQgKyBuOHIpO1xuXG4gICAgICAgICAgICAvLyBHZXQgd2l0bmVzcyB2YWx1ZVxuICAgICAgICAgICAgY29uc3Qgd2l0bmVzczEgPSBnZXRXaXRuZXNzKHNpZ25hbElkMSk7XG4gICAgICAgICAgICBjb25zdCB3aXRuZXNzMiA9IGdldFdpdG5lc3Moc2lnbmFsSWQyKTtcblxuICAgICAgICAgICAgLy9DYWxjdWxhdGUgZmluYWwgcmVzdWx0XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBGci5hZGQoRnIubXVsKGZhY3RvcjEsIHdpdG5lc3MxKSwgRnIubXVsKGZhY3RvcjIsIHdpdG5lc3MyKSk7XG5cbiAgICAgICAgICAgIGJ1ZmZJbnRlcm5hbFdpdG5lc3Muc2V0KHJlc3VsdCwgbjhyICogaSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZWFkVUludDMyKGIsIG8pIHtcbiAgICAgICAgY29uc3QgYnVmZiA9IGIuc2xpY2Uobywgbys0KTtcbiAgICAgICAgY29uc3QgYnVmZlYgPSBuZXcgRGF0YVZpZXcoYnVmZi5idWZmZXIsIGJ1ZmYuYnl0ZU9mZnNldCwgYnVmZi5ieXRlTGVuZ3RoKTtcbiAgICAgICAgcmV0dXJuIGJ1ZmZWLmdldFVpbnQzMigwLCB0cnVlKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRXaXRuZXNzKGlkeCkge1xuICAgICAgICBpZiAoaWR4IDwgemtleS5uVmFycy16a2V5Lm5BZGRpdGlvbnMpIHtcbiAgICAgICAgICAgIHJldHVybiBidWZmV2l0bmVzcy5zbGljZShpZHgqbjhyLCBpZHgqbjhyK244cik7XG4gICAgICAgIH0gZWxzZSBpZiAoaWR4IDwgemtleS5uVmFycykge1xuICAgICAgICAgICAgcmV0dXJuIGJ1ZmZJbnRlcm5hbFdpdG5lc3Muc2xpY2UoKGlkeCAtICh6a2V5Lm5WYXJzLXprZXkubkFkZGl0aW9ucykpKm44ciwgKGlkeC0oemtleS5uVmFycy16a2V5Lm5BZGRpdGlvbnMpKSpuOHIgKyBuOHIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGN1cnZlLkZyLnplcm87XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiByb3VuZDEoKSB7XG4gICAgICAgIC8vIFNURVAgMS4xIC0gR2VuZXJhdGUgcmFuZG9tIGJsaW5kaW5nIHNjYWxhcnMgKGIxLCAuLi4sIGIxMSkg4oiIIEZcbiAgICAgICAgY2hhbGxlbmdlcy5iID0gW107XG4gICAgICAgIGZvciAobGV0IGk9MTsgaTw9MTE7IGkrKykge1xuICAgICAgICAgICAgY2hhbGxlbmdlcy5iW2ldID0gY3VydmUuRnIucmFuZG9tKCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTVEVQIDEuMiAtIENvbXB1dGUgd2lyZSBwb2x5bm9taWFscyBhKFgpLCBiKFgpIGFuZCBjKFgpXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIj4gQ29tcHV0aW5nIEEsIEIsIEMgd2lyZSBwb2x5bm9taWFsc1wiKTtcbiAgICAgICAgYXdhaXQgY29tcHV0ZVdpcmVQb2x5bm9taWFscygpO1xuXG4gICAgICAgIC8vIFNURVAgMS4zIC0gQ29tcHV0ZSBbYV1fMSwgW2JdXzEsIFtjXV8xXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIj4gQ29tcHV0aW5nIEEsIEIsIEMgTVNNXCIpO1xuICAgICAgICBsZXQgY29tbWl0QSA9IGF3YWl0IHBvbHlub21pYWxzLkEubXVsdGlFeHBvbmVudGlhdGlvbihQVGF1LCBcIkFcIik7XG4gICAgICAgIGxldCBjb21taXRCID0gYXdhaXQgcG9seW5vbWlhbHMuQi5tdWx0aUV4cG9uZW50aWF0aW9uKFBUYXUsIFwiQlwiKTtcbiAgICAgICAgbGV0IGNvbW1pdEMgPSBhd2FpdCBwb2x5bm9taWFscy5DLm11bHRpRXhwb25lbnRpYXRpb24oUFRhdSwgXCJDXCIpO1xuXG4gICAgICAgIC8vIEZpcnN0IG91dHB1dCBvZiB0aGUgcHJvdmVyIGlzIChbQV1fMSwgW0JdXzEsIFtDXV8xKVxuICAgICAgICBwcm9vZi5hZGRQb2x5bm9taWFsKFwiQVwiLCBjb21taXRBKTtcbiAgICAgICAgcHJvb2YuYWRkUG9seW5vbWlhbChcIkJcIiwgY29tbWl0Qik7XG4gICAgICAgIHByb29mLmFkZFBvbHlub21pYWwoXCJDXCIsIGNvbW1pdEMpO1xuXG4gICAgICAgIHJldHVybiAwO1xuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIGNvbXB1dGVXaXJlUG9seW5vbWlhbHMoKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIsK3wrfCtyBSZWFkaW5nIGRhdGEgZnJvbSB6a2V5IGZpbGVcIik7XG5cbiAgICAgICAgLy8gQnVpbGQgQSwgQiBhbmQgQyBldmFsdWF0aW9ucyBidWZmZXIgZnJvbSB6a2V5IGFuZCB3aXRuZXNzIGZpbGVzXG4gICAgICAgIGJ1ZmZlcnMuQSA9IG5ldyBCaWdCdWZmZXIoc0RvbWFpbik7XG4gICAgICAgIGJ1ZmZlcnMuQiA9IG5ldyBCaWdCdWZmZXIoc0RvbWFpbik7XG4gICAgICAgIGJ1ZmZlcnMuQyA9IG5ldyBCaWdCdWZmZXIoc0RvbWFpbik7XG5cbiAgICAgICAgLy8gUmVhZCB6a2V5IGZpbGUgdG8gdGhlIGJ1ZmZlcnNcbiAgICAgICAgY29uc3QgYU1hcEJ1ZmYgPSBhd2FpdCBiaW5GaWxlVXRpbHMucmVhZFNlY3Rpb24oZmRaS2V5LCB6a2V5U2VjdGlvbnMsIFpLRVlfUExfQV9NQVBfU0VDVElPTik7XG4gICAgICAgIGNvbnN0IGJNYXBCdWZmID0gYXdhaXQgYmluRmlsZVV0aWxzLnJlYWRTZWN0aW9uKGZkWktleSwgemtleVNlY3Rpb25zLCBaS0VZX1BMX0JfTUFQX1NFQ1RJT04pO1xuICAgICAgICBjb25zdCBjTWFwQnVmZiA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkU2VjdGlvbihmZFpLZXksIHprZXlTZWN0aW9ucywgWktFWV9QTF9DX01BUF9TRUNUSU9OKTtcblxuICAgICAgICAvLyBDb21wdXRlIGFsbCB3aXRuZXNzIGZyb20gc2lnbmFsIGlkcyBhbmQgc2V0IHRoZW0gdG8gQSxCICYgQyBidWZmZXJzXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgemtleS5uQ29uc3RyYWludHM7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgaV9zRnIgPSBpICogbjhyO1xuICAgICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gaSAqIDQ7XG5cbiAgICAgICAgICAgIC8vIENvbXB1dGUgQSB2YWx1ZSBmcm9tIGEgc2lnbmFsIGlkXG4gICAgICAgICAgICBjb25zdCBzaWduYWxJZEEgPSByZWFkVUludDMyKGFNYXBCdWZmLCBvZmZzZXQpO1xuICAgICAgICAgICAgYnVmZmVycy5BLnNldChnZXRXaXRuZXNzKHNpZ25hbElkQSksIGlfc0ZyKTtcblxuICAgICAgICAgICAgLy8gQ29tcHV0ZSBCIHZhbHVlIGZyb20gYSBzaWduYWwgaWRcbiAgICAgICAgICAgIGNvbnN0IHNpZ25hbElkQiA9IHJlYWRVSW50MzIoYk1hcEJ1ZmYsIG9mZnNldCk7XG4gICAgICAgICAgICBidWZmZXJzLkIuc2V0KGdldFdpdG5lc3Moc2lnbmFsSWRCKSwgaV9zRnIpO1xuXG4gICAgICAgICAgICAvLyBDb21wdXRlIEMgdmFsdWUgZnJvbSBhIHNpZ25hbCBpZFxuICAgICAgICAgICAgY29uc3Qgc2lnbmFsSWRDID0gcmVhZFVJbnQzMihjTWFwQnVmZiwgb2Zmc2V0KTtcbiAgICAgICAgICAgIGJ1ZmZlcnMuQy5zZXQoZ2V0V2l0bmVzcyhzaWduYWxJZEMpLCBpX3NGcik7XG4gICAgICAgIH1cblxuICAgICAgICBidWZmZXJzLkEgPSBhd2FpdCBGci5iYXRjaFRvTW9udGdvbWVyeShidWZmZXJzLkEpO1xuICAgICAgICBidWZmZXJzLkIgPSBhd2FpdCBGci5iYXRjaFRvTW9udGdvbWVyeShidWZmZXJzLkIpO1xuICAgICAgICBidWZmZXJzLkMgPSBhd2FpdCBGci5iYXRjaFRvTW9udGdvbWVyeShidWZmZXJzLkMpO1xuXG4gICAgICAgIC8vIENvbXB1dGUgdGhlIGNvZWZmaWNpZW50cyBvZiB0aGUgd2lyZSBwb2x5bm9taWFscyBhKFgpLCBiKFgpIGFuZCBjKFgpIGZyb20gQSxCICYgQyBidWZmZXJzXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIsK3wrfCtyBDb21wdXRpbmcgQSBpZmZ0XCIpO1xuICAgICAgICBwb2x5bm9taWFscy5BID0gYXdhaXQgUG9seW5vbWlhbC5mcm9tRXZhbHVhdGlvbnMoYnVmZmVycy5BLCBjdXJ2ZSwgbG9nZ2VyKTtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKFwiwrfCt8K3IENvbXB1dGluZyBCIGlmZnRcIik7XG4gICAgICAgIHBvbHlub21pYWxzLkIgPSBhd2FpdCBQb2x5bm9taWFsLmZyb21FdmFsdWF0aW9ucyhidWZmZXJzLkIsIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCLCt8K3wrcgQ29tcHV0aW5nIEMgaWZmdFwiKTtcbiAgICAgICAgcG9seW5vbWlhbHMuQyA9IGF3YWl0IFBvbHlub21pYWwuZnJvbUV2YWx1YXRpb25zKGJ1ZmZlcnMuQywgY3VydmUsIGxvZ2dlcik7XG5cbiAgICAgICAgLy8gQ29tcHV0ZSBleHRlbmRlZCBldmFsdWF0aW9ucyBvZiBhKFgpLCBiKFgpIGFuZCBjKFgpIHBvbHlub21pYWxzXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIsK3wrfCtyBDb21wdXRpbmcgQSBmZnRcIik7XG4gICAgICAgIGV2YWx1YXRpb25zLkEgPSBhd2FpdCBFdmFsdWF0aW9ucy5mcm9tUG9seW5vbWlhbChwb2x5bm9taWFscy5BLCA0LCBjdXJ2ZSwgbG9nZ2VyKTtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKFwiwrfCt8K3IENvbXB1dGluZyBCIGZmdFwiKTtcbiAgICAgICAgZXZhbHVhdGlvbnMuQiA9IGF3YWl0IEV2YWx1YXRpb25zLmZyb21Qb2x5bm9taWFsKHBvbHlub21pYWxzLkIsIDQsIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCLCt8K3wrcgQ29tcHV0aW5nIEMgZmZ0XCIpO1xuICAgICAgICBldmFsdWF0aW9ucy5DID0gYXdhaXQgRXZhbHVhdGlvbnMuZnJvbVBvbHlub21pYWwocG9seW5vbWlhbHMuQywgNCwgY3VydmUsIGxvZ2dlcik7XG5cbiAgICAgICAgLy8gQmxpbmQgYShYKSwgYihYKSBhbmQgYyhYKSBwb2x5bm9taWFscyBjb2VmZmljaWVudHMgd2l0aCBibGluZGluZyBzY2FsYXJzIGJcbiAgICAgICAgcG9seW5vbWlhbHMuQS5ibGluZENvZWZmaWNpZW50cyhbY2hhbGxlbmdlcy5iWzJdLCBjaGFsbGVuZ2VzLmJbMV1dKTtcbiAgICAgICAgcG9seW5vbWlhbHMuQi5ibGluZENvZWZmaWNpZW50cyhbY2hhbGxlbmdlcy5iWzRdLCBjaGFsbGVuZ2VzLmJbM11dKTtcbiAgICAgICAgcG9seW5vbWlhbHMuQy5ibGluZENvZWZmaWNpZW50cyhbY2hhbGxlbmdlcy5iWzZdLCBjaGFsbGVuZ2VzLmJbNV1dKTtcblxuICAgICAgICAvLyBDaGVjayBkZWdyZWVzXG4gICAgICAgIGlmIChwb2x5bm9taWFscy5BLmRlZ3JlZSgpID49IHprZXkuZG9tYWluU2l6ZSArIDIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkEgUG9seW5vbWlhbCBpcyBub3Qgd2VsbCBjYWxjdWxhdGVkXCIpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwb2x5bm9taWFscy5CLmRlZ3JlZSgpID49IHprZXkuZG9tYWluU2l6ZSArIDIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkIgUG9seW5vbWlhbCBpcyBub3Qgd2VsbCBjYWxjdWxhdGVkXCIpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwb2x5bm9taWFscy5DLmRlZ3JlZSgpID49IHprZXkuZG9tYWluU2l6ZSArIDIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkMgUG9seW5vbWlhbCBpcyBub3Qgd2VsbCBjYWxjdWxhdGVkXCIpO1xuICAgICAgICB9ICAgICAgICBcbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiByb3VuZDIoKSB7XG4gICAgICAgIC8vIFNURVAgMi4xIC0gQ29tcHV0ZSBwZXJtdXRhdGlvbiBjaGFsbGVuZ2UgYmV0YSBhbmQgZ2FtbWEg4oiIIEZcbiAgICAgICAgLy8gQ29tcHV0ZSBwZXJtdXRhdGlvbiBjaGFsbGVuZ2UgYmV0YVxuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCI+IENvbXB1dGluZyBjaGFsbGVuZ2VzIGJldGEgYW5kIGdhbW1hXCIpO1xuICAgICAgICB0cmFuc2NyaXB0LnJlc2V0KCk7XG5cbiAgICAgICAgdHJhbnNjcmlwdC5hZGRQb2xDb21taXRtZW50KHprZXkuUW0pO1xuICAgICAgICB0cmFuc2NyaXB0LmFkZFBvbENvbW1pdG1lbnQoemtleS5RbCk7XG4gICAgICAgIHRyYW5zY3JpcHQuYWRkUG9sQ29tbWl0bWVudCh6a2V5LlFyKTtcbiAgICAgICAgdHJhbnNjcmlwdC5hZGRQb2xDb21taXRtZW50KHprZXkuUW8pO1xuICAgICAgICB0cmFuc2NyaXB0LmFkZFBvbENvbW1pdG1lbnQoemtleS5RYyk7XG4gICAgICAgIHRyYW5zY3JpcHQuYWRkUG9sQ29tbWl0bWVudCh6a2V5LlMxKTtcbiAgICAgICAgdHJhbnNjcmlwdC5hZGRQb2xDb21taXRtZW50KHprZXkuUzIpO1xuICAgICAgICB0cmFuc2NyaXB0LmFkZFBvbENvbW1pdG1lbnQoemtleS5TMyk7XG5cbiAgICAgICAgLy8gQWRkIEEgdG8gdGhlIHRyYW5zY3JpcHRcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB6a2V5Lm5QdWJsaWM7IGkrKykge1xuICAgICAgICAgICAgdHJhbnNjcmlwdC5hZGRTY2FsYXIoYnVmZmVycy5BLnNsaWNlKGkgKiBuOHIsIGkgKiBuOHIgKyBuOHIpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEFkZCBBLCBCLCBDIHRvIHRoZSB0cmFuc2NyaXB0XG4gICAgICAgIHRyYW5zY3JpcHQuYWRkUG9sQ29tbWl0bWVudChwcm9vZi5nZXRQb2x5bm9taWFsKFwiQVwiKSk7XG4gICAgICAgIHRyYW5zY3JpcHQuYWRkUG9sQ29tbWl0bWVudChwcm9vZi5nZXRQb2x5bm9taWFsKFwiQlwiKSk7XG4gICAgICAgIHRyYW5zY3JpcHQuYWRkUG9sQ29tbWl0bWVudChwcm9vZi5nZXRQb2x5bm9taWFsKFwiQ1wiKSk7XG5cbiAgICAgICAgY2hhbGxlbmdlcy5iZXRhID0gdHJhbnNjcmlwdC5nZXRDaGFsbGVuZ2UoKTtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKFwiwrfCt8K3IGNoYWxsZW5nZXMuYmV0YTogXCIgKyBGci50b1N0cmluZyhjaGFsbGVuZ2VzLmJldGEsIDE2KSk7XG5cbiAgICAgICAgLy8gQ29tcHV0ZSBwZXJtdXRhdGlvbiBjaGFsbGVuZ2UgZ2FtbWFcbiAgICAgICAgdHJhbnNjcmlwdC5yZXNldCgpO1xuICAgICAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihjaGFsbGVuZ2VzLmJldGEpO1xuICAgICAgICBjaGFsbGVuZ2VzLmdhbW1hID0gdHJhbnNjcmlwdC5nZXRDaGFsbGVuZ2UoKTtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKFwiwrfCt8K3IGNoYWxsZW5nZXMuZ2FtbWE6IFwiICsgRnIudG9TdHJpbmcoY2hhbGxlbmdlcy5nYW1tYSwgMTYpKTtcbiAgICBcbiAgICAgICAgLy8gU1RFUCAyLjIgLSBDb21wdXRlIHBlcm11dGF0aW9uIHBvbHlub21pYWwgeihYKVxuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCI+IENvbXB1dGluZyBaIHBvbHlub21pYWxcIik7XG4gICAgICAgIGF3YWl0IGNvbXB1dGVaKCk7XG5cbiAgICAgICAgLy8gU1RFUCAyLjMgLSBDb21wdXRlIHBlcm11dGF0aW9uIFt6XV8xXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIj4gQ29tcHV0aW5nIFogTVNNXCIpO1xuICAgICAgICBsZXQgY29tbWl0WiA9IGF3YWl0IHBvbHlub21pYWxzLloubXVsdGlFeHBvbmVudGlhdGlvbihQVGF1LCBcIlpcIik7XG5cbiAgICAgICAgLy8gU2Vjb25kIG91dHB1dCBvZiB0aGUgcHJvdmVyIGlzIChbWl1fMSlcbiAgICAgICAgcHJvb2YuYWRkUG9seW5vbWlhbChcIlpcIiwgY29tbWl0Wik7XG4gICAgfVxuXG4gICAgYXN5bmMgZnVuY3Rpb24gY29tcHV0ZVooKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIsK3wrfCtyBDb21wdXRpbmcgWiBldmFsdWF0aW9uc1wiKTtcblxuICAgICAgICBsZXQgbnVtQXJyID0gbmV3IEJpZ0J1ZmZlcihzRG9tYWluKTtcbiAgICAgICAgbGV0IGRlbkFyciA9IG5ldyBCaWdCdWZmZXIoc0RvbWFpbik7XG5cbiAgICAgICAgLy8gU2V0IHRoZSBmaXJzdCB2YWx1ZXMgdG8gMVxuICAgICAgICBudW1BcnIuc2V0KEZyLm9uZSwgMCk7XG4gICAgICAgIGRlbkFyci5zZXQoRnIub25lLCAwKTtcblxuICAgICAgICAvLyBTZXQgaW5pdGlhbCBvbWVnYVxuICAgICAgICBsZXQgdyA9IEZyLm9uZTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB6a2V5LmRvbWFpblNpemU7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgaV9uOHIgPSBpICogbjhyO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBjb25zdCBhID0gYnVmZmVycy5BLnNsaWNlKGlfbjhyLCBpX244ciArIG44cik7XG4gICAgICAgICAgICBjb25zdCBiID0gYnVmZmVycy5CLnNsaWNlKGlfbjhyLCBpX244ciArIG44cik7XG4gICAgICAgICAgICBjb25zdCBjID0gYnVmZmVycy5DLnNsaWNlKGlfbjhyLCBpX244ciArIG44cik7XG5cbiAgICAgICAgICAgIC8vIFooWCkgOj0gbnVtQXJyIC8gZGVuQXJyXG4gICAgICAgICAgICAvLyBudW1BcnIgOj0gKGEgKyBiZXRhwrfPiSArIGdhbW1hKShiICsgYmV0YcK3z4nCt2sxICsgZ2FtbWEpKGMgKyBiZXRhwrfPicK3azIgKyBnYW1tYSlcbiAgICAgICAgICAgIGNvbnN0IGJldGF3ID0gRnIubXVsKGNoYWxsZW5nZXMuYmV0YSwgdyk7XG5cbiAgICAgICAgICAgIGxldCBuMSA9IEZyLmFkZChhLCBiZXRhdyk7XG4gICAgICAgICAgICBuMSA9IEZyLmFkZChuMSwgY2hhbGxlbmdlcy5nYW1tYSk7XG5cbiAgICAgICAgICAgIGxldCBuMiA9IEZyLmFkZChiLCBGci5tdWwoemtleS5rMSwgYmV0YXcpKTtcbiAgICAgICAgICAgIG4yID0gRnIuYWRkKG4yLCBjaGFsbGVuZ2VzLmdhbW1hKTtcblxuICAgICAgICAgICAgbGV0IG4zID0gRnIuYWRkKGMsIEZyLm11bCh6a2V5LmsyLCBiZXRhdykpO1xuICAgICAgICAgICAgbjMgPSBGci5hZGQobjMsIGNoYWxsZW5nZXMuZ2FtbWEpO1xuXG4gICAgICAgICAgICBsZXQgbnVtID0gRnIubXVsKG4xLCBGci5tdWwobjIsIG4zKSk7XG5cbiAgICAgICAgICAgIC8vIGRlbkFyciA6PSAoYSArIGJldGHCt3NpZ21hMSArIGdhbW1hKShiICsgYmV0YcK3c2lnbWEyICsgZ2FtbWEpKGMgKyBiZXRhwrdzaWdtYTMgKyBnYW1tYSlcbiAgICAgICAgICAgIGxldCBkMSA9IEZyLmFkZChhLCBGci5tdWwoZXZhbHVhdGlvbnMuU2lnbWExLmdldEV2YWx1YXRpb24oaSAqIDQpLCBjaGFsbGVuZ2VzLmJldGEpKTtcbiAgICAgICAgICAgIGQxID0gRnIuYWRkKGQxLCBjaGFsbGVuZ2VzLmdhbW1hKTtcblxuICAgICAgICAgICAgbGV0IGQyID0gRnIuYWRkKGIsIEZyLm11bChldmFsdWF0aW9ucy5TaWdtYTIuZ2V0RXZhbHVhdGlvbihpICogNCksIGNoYWxsZW5nZXMuYmV0YSkpO1xuICAgICAgICAgICAgZDIgPSBGci5hZGQoZDIsIGNoYWxsZW5nZXMuZ2FtbWEpO1xuXG4gICAgICAgICAgICBsZXQgZDMgPSBGci5hZGQoYywgRnIubXVsKGV2YWx1YXRpb25zLlNpZ21hMy5nZXRFdmFsdWF0aW9uKGkgKiA0KSwgY2hhbGxlbmdlcy5iZXRhKSk7XG4gICAgICAgICAgICBkMyA9IEZyLmFkZChkMywgY2hhbGxlbmdlcy5nYW1tYSk7XG5cbiAgICAgICAgICAgIGxldCBkZW4gPSBGci5tdWwoZDEsIEZyLm11bChkMiwgZDMpKTtcblxuICAgICAgICAgICAgLy8gTXVsdGlwbHkgY3VycmVudCBudW0gdmFsdWUgd2l0aCB0aGUgcHJldmlvdXMgb25lIHNhdmVkIGluIG51bUFyclxuICAgICAgICAgICAgbnVtID0gRnIubXVsKG51bUFyci5zbGljZShpX244ciwgaV9uOHIgKyBuOHIpLCBudW0pO1xuICAgICAgICAgICAgbnVtQXJyLnNldChudW0sICgoaSArIDEpICUgemtleS5kb21haW5TaXplKSAqIG44cik7XG5cbiAgICAgICAgICAgIC8vIE11bHRpcGx5IGN1cnJlbnQgZGVuIHZhbHVlIHdpdGggdGhlIHByZXZpb3VzIG9uZSBzYXZlZCBpbiBkZW5BcnJcbiAgICAgICAgICAgIGRlbiA9IEZyLm11bChkZW5BcnIuc2xpY2UoaV9uOHIsIGlfbjhyICsgbjhyKSwgZGVuKTtcbiAgICAgICAgICAgIGRlbkFyci5zZXQoZGVuLCAoKGkgKyAxKSAlIHprZXkuZG9tYWluU2l6ZSkgKiBuOHIpO1xuXG4gICAgICAgICAgICB3ID0gRnIubXVsKHcsIEZyLndbemtleS5wb3dlcl0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ29tcHV0ZSB0aGUgaW52ZXJzZSBvZiBkZW5BcnIgdG8gY29tcHV0ZSBpbiB0aGUgbmV4dCBjb21tYW5kIHRoZVxuICAgICAgICAvLyBkaXZpc2lvbiBudW1BcnIvZGVuQXJyIGJ5IG11bHRpcGx5aW5nIG51bSDCtyAxL2RlbkFyclxuICAgICAgICBkZW5BcnIgPSBhd2FpdCBGci5iYXRjaEludmVyc2UoZGVuQXJyKTtcblxuICAgICAgICAvLyBUT0RPOiBEbyBpdCBpbiBhc3NlbWJseSBhbmQgaW4gcGFyYWxsZWxcbiAgICAgICAgLy8gTXVsdGlwbHkgbnVtQXJyIMK3IGRlbkFyciB3aGVyZSBkZW5BcnIgd2FzIGludmVydGVkIGluIHRoZSBwcmV2aW91cyBjb21tYW5kXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgemtleS5kb21haW5TaXplOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGlfc0ZyID0gaSAqIG44cjtcblxuICAgICAgICAgICAgY29uc3QgeiA9IEZyLm11bChudW1BcnIuc2xpY2UoaV9zRnIsIGlfc0ZyICsgbjhyKSwgZGVuQXJyLnNsaWNlKGlfc0ZyLCBpX3NGciArIG44cikpO1xuICAgICAgICAgICAgbnVtQXJyLnNldCh6LCBpX3NGcik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBGcm9tIG5vdyBvbiB0aGUgdmFsdWVzIHNhdmVkIG9uIG51bUFyciB3aWxsIGJlIFooWCkgYnVmZmVyXG4gICAgICAgIGJ1ZmZlcnMuWiA9IG51bUFycjtcblxuICAgICAgICBpZiAoIUZyLmVxKG51bUFyci5zbGljZSgwLCBuOHIpLCBGci5vbmUpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb3B5IGNvbnN0cmFpbnRzIGRvZXMgbm90IG1hdGNoXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ29tcHV0ZSBwb2x5bm9taWFsIGNvZWZmaWNpZW50cyB6KFgpIGZyb20gYnVmZmVycy5aXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIsK3wrfCtyBDb21wdXRpbmcgWiBpZmZ0XCIpO1xuICAgICAgICBwb2x5bm9taWFscy5aID0gYXdhaXQgUG9seW5vbWlhbC5mcm9tRXZhbHVhdGlvbnMoYnVmZmVycy5aLCBjdXJ2ZSwgbG9nZ2VyKTtcblxuICAgICAgICAvLyBDb21wdXRlIGV4dGVuZGVkIGV2YWx1YXRpb25zIG9mIHooWCkgcG9seW5vbWlhbFxuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCLCt8K3wrcgQ29tcHV0aW5nIFogZmZ0XCIpO1xuICAgICAgICBldmFsdWF0aW9ucy5aID0gYXdhaXQgRXZhbHVhdGlvbnMuZnJvbVBvbHlub21pYWwocG9seW5vbWlhbHMuWiwgNCwgY3VydmUsIGxvZ2dlcik7XG5cbiAgICAgICAgLy8gQmxpbmQgeihYKSBwb2x5bm9taWFsIGNvZWZmaWNpZW50cyB3aXRoIGJsaW5kaW5nIHNjYWxhcnMgYlxuICAgICAgICBwb2x5bm9taWFscy5aLmJsaW5kQ29lZmZpY2llbnRzKFtjaGFsbGVuZ2VzLmJbOV0sIGNoYWxsZW5nZXMuYls4XSwgY2hhbGxlbmdlcy5iWzddXSk7XG5cbiAgICAgICAgLy8gQ2hlY2sgZGVncmVlXG4gICAgICAgIGlmIChwb2x5bm9taWFscy5aLmRlZ3JlZSgpID49IHprZXkuZG9tYWluU2l6ZSArIDMpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlogUG9seW5vbWlhbCBpcyBub3Qgd2VsbCBjYWxjdWxhdGVkXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgZGVsZXRlIGJ1ZmZlcnMuWjtcbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiByb3VuZDMoKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIj4gQ29tcHV0aW5nIGNoYWxsZW5nZSBhbHBoYVwiKTtcblxuICAgICAgICAvLyBTVEVQIDMuMSAtIENvbXB1dGUgZXZhbHVhdGlvbiBjaGFsbGVuZ2UgYWxwaGEg4oiIIEZcbiAgICAgICAgdHJhbnNjcmlwdC5yZXNldCgpO1xuICAgICAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihjaGFsbGVuZ2VzLmJldGEpO1xuICAgICAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihjaGFsbGVuZ2VzLmdhbW1hKTtcbiAgICAgICAgdHJhbnNjcmlwdC5hZGRQb2xDb21taXRtZW50KHByb29mLmdldFBvbHlub21pYWwoXCJaXCIpKTtcblxuICAgICAgICBjaGFsbGVuZ2VzLmFscGhhID0gdHJhbnNjcmlwdC5nZXRDaGFsbGVuZ2UoKTtcbiAgICAgICAgY2hhbGxlbmdlcy5hbHBoYTIgPSBGci5zcXVhcmUoY2hhbGxlbmdlcy5hbHBoYSk7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIsK3wrfCtyBjaGFsbGVuZ2VzLmFscGhhOiBcIiArIEZyLnRvU3RyaW5nKGNoYWxsZW5nZXMuYWxwaGEsIDE2KSk7XG5cbiAgICAgICAgLy8gQ29tcHV0ZSBxdW90aWVudCBwb2x5bm9taWFsIFQoWClcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKFwiPiBDb21wdXRpbmcgVCBwb2x5bm9taWFsXCIpO1xuICAgICAgICBhd2FpdCBjb21wdXRlVCgpO1xuXG4gICAgICAgIC8vIENvbXB1dGUgW1QxXV8xLCBbVDJdXzEsIFtUM11fMVxuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCI+IENvbXB1dGluZyBUIE1TTVwiKTtcbiAgICAgICAgbGV0IGNvbW1pdFQxID0gYXdhaXQgcG9seW5vbWlhbHMuVDEubXVsdGlFeHBvbmVudGlhdGlvbihQVGF1LCBcIlQxXCIpO1xuICAgICAgICBsZXQgY29tbWl0VDIgPSBhd2FpdCBwb2x5bm9taWFscy5UMi5tdWx0aUV4cG9uZW50aWF0aW9uKFBUYXUsIFwiVDJcIik7XG4gICAgICAgIGxldCBjb21taXRUMyA9IGF3YWl0IHBvbHlub21pYWxzLlQzLm11bHRpRXhwb25lbnRpYXRpb24oUFRhdSwgXCJUM1wiKTtcblxuICAgICAgICAvLyBUaGlyZCBvdXRwdXQgb2YgdGhlIHByb3ZlciBpcyAoW1QxXV8xLCBbVDJdXzEsIFtUM11fMSlcbiAgICAgICAgcHJvb2YuYWRkUG9seW5vbWlhbChcIlQxXCIsIGNvbW1pdFQxKTtcbiAgICAgICAgcHJvb2YuYWRkUG9seW5vbWlhbChcIlQyXCIsIGNvbW1pdFQyKTtcbiAgICAgICAgcHJvb2YuYWRkUG9seW5vbWlhbChcIlQzXCIsIGNvbW1pdFQzKTsgICAgICAgIFxuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIGNvbXB1dGVUKCkge1xuICAgICAgICBpZiAobG9nZ2VyKVxuICAgICAgICAgICAgbG9nZ2VyLmRlYnVnKGDCt8K3wrcgUmVhZGluZyBzZWN0aW9ucyAke1pLRVlfUExfUUxfU0VDVElPTn0sICR7WktFWV9QTF9RUl9TRUNUSU9OfWAgK1xuICAgICAgICAgICAgICAgIGAsICR7WktFWV9QTF9RTV9TRUNUSU9OfSwgJHtaS0VZX1BMX1FPX1NFQ1RJT059LCAke1pLRVlfUExfUUNfU0VDVElPTn0uIFEgc2VsZWN0b3JzYCk7XG4gICAgICAgIC8vIFJlc2VydmUgbWVtb3J5IGZvciBRJ3MgZXZhbHVhdGlvbnNcbiAgICAgICAgZXZhbHVhdGlvbnMuUUwgPSBuZXcgRXZhbHVhdGlvbnMobmV3IEJpZ0J1ZmZlcihzRG9tYWluICogNCksIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICBldmFsdWF0aW9ucy5RUiA9IG5ldyBFdmFsdWF0aW9ucyhuZXcgQmlnQnVmZmVyKHNEb21haW4gKiA0KSwgY3VydmUsIGxvZ2dlcik7XG4gICAgICAgIGV2YWx1YXRpb25zLlFNID0gbmV3IEV2YWx1YXRpb25zKG5ldyBCaWdCdWZmZXIoc0RvbWFpbiAqIDQpLCBjdXJ2ZSwgbG9nZ2VyKTtcbiAgICAgICAgZXZhbHVhdGlvbnMuUU8gPSBuZXcgRXZhbHVhdGlvbnMobmV3IEJpZ0J1ZmZlcihzRG9tYWluICogNCksIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICBldmFsdWF0aW9ucy5RQyA9IG5ldyBFdmFsdWF0aW9ucyhuZXcgQmlnQnVmZmVyKHNEb21haW4gKiA0KSwgY3VydmUsIGxvZ2dlcik7XG5cbiAgICAgICAgLy8gUmVhZCBRJ3MgZXZhbHVhdGlvbnMgZnJvbSB6a2V5IGZpbGVcbiAgICAgICAgYXdhaXQgZmRaS2V5LnJlYWRUb0J1ZmZlcihldmFsdWF0aW9ucy5RTC5ldmFsLCAwLCBzRG9tYWluICogNCwgemtleVNlY3Rpb25zW1pLRVlfUExfUUxfU0VDVElPTl1bMF0ucCArIHNEb21haW4pO1xuICAgICAgICBhd2FpdCBmZFpLZXkucmVhZFRvQnVmZmVyKGV2YWx1YXRpb25zLlFSLmV2YWwsIDAsIHNEb21haW4gKiA0LCB6a2V5U2VjdGlvbnNbWktFWV9QTF9RUl9TRUNUSU9OXVswXS5wICsgc0RvbWFpbik7XG4gICAgICAgIGF3YWl0IGZkWktleS5yZWFkVG9CdWZmZXIoZXZhbHVhdGlvbnMuUU0uZXZhbCwgMCwgc0RvbWFpbiAqIDQsIHprZXlTZWN0aW9uc1taS0VZX1BMX1FNX1NFQ1RJT05dWzBdLnAgKyBzRG9tYWluKTtcbiAgICAgICAgYXdhaXQgZmRaS2V5LnJlYWRUb0J1ZmZlcihldmFsdWF0aW9ucy5RTy5ldmFsLCAwLCBzRG9tYWluICogNCwgemtleVNlY3Rpb25zW1pLRVlfUExfUU9fU0VDVElPTl1bMF0ucCArIHNEb21haW4pO1xuICAgICAgICBhd2FpdCBmZFpLZXkucmVhZFRvQnVmZmVyKGV2YWx1YXRpb25zLlFDLmV2YWwsIDAsIHNEb21haW4gKiA0LCB6a2V5U2VjdGlvbnNbWktFWV9QTF9RQ19TRUNUSU9OXVswXS5wICsgc0RvbWFpbik7XG5cbiAgICAgICAgLy8gUmVhZCBMYWdyYW5nZSBwb2x5bm9taWFscyAmIGV2YWx1YXRpb25zIGZyb20gemtleSBmaWxlXG4gICAgICAgIGV2YWx1YXRpb25zLkxhZ3JhbmdlID0gbmV3IEV2YWx1YXRpb25zKG5ldyBCaWdCdWZmZXIoc0RvbWFpbiAqIDQgKiB6a2V5Lm5QdWJsaWMpLCBjdXJ2ZSwgbG9nZ2VyKTtcblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHprZXkublB1YmxpYzsgaSsrKSB7XG4gICAgICAgICAgICBhd2FpdCBmZFpLZXkucmVhZFRvQnVmZmVyKGV2YWx1YXRpb25zLkxhZ3JhbmdlLmV2YWwsIGkgKiBzRG9tYWluICogNCwgc0RvbWFpbiAqIDQsIHprZXlTZWN0aW9uc1taS0VZX1BMX0xBR1JBTkdFX1NFQ1RJT05dWzBdLnAgKyBpICogNSAqIHNEb21haW4gKyBzRG9tYWluKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGJ1ZmZlcnMuVCA9IG5ldyBCaWdCdWZmZXIoc0RvbWFpbiAqIDQpO1xuICAgICAgICBidWZmZXJzLlR6ID0gbmV3IEJpZ0J1ZmZlcihzRG9tYWluICogNCk7XG5cbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKFwiwrfCt8K3IENvbXB1dGluZyBUIGV2YWx1YXRpb25zXCIpO1xuXG4gICAgICAgIGxldCB3ID0gRnIub25lO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHprZXkuZG9tYWluU2l6ZSAqIDQ7IGkrKykge1xuICAgICAgICAgICAgaWYgKGxvZ2dlciAmJiAoMCAhPT0gaSkgJiYgKGkgJSAxMDAwMDAgPT09IDApKVxuICAgICAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZyhgICAgICAgVCBldmFsdWF0aW9uICR7aX0vJHt6a2V5LmRvbWFpblNpemUgKiA0fWApO1xuXG4gICAgICAgICAgICBjb25zdCBhID0gZXZhbHVhdGlvbnMuQS5nZXRFdmFsdWF0aW9uKGkpO1xuICAgICAgICAgICAgY29uc3QgYiA9IGV2YWx1YXRpb25zLkIuZ2V0RXZhbHVhdGlvbihpKTtcbiAgICAgICAgICAgIGNvbnN0IGMgPSBldmFsdWF0aW9ucy5DLmdldEV2YWx1YXRpb24oaSk7XG4gICAgICAgICAgICBjb25zdCB6ID0gZXZhbHVhdGlvbnMuWi5nZXRFdmFsdWF0aW9uKGkpO1xuICAgICAgICAgICAgY29uc3QgencgPSBldmFsdWF0aW9ucy5aLmdldEV2YWx1YXRpb24oKHprZXkuZG9tYWluU2l6ZSAqIDQgKyA0ICsgaSkgJSAoemtleS5kb21haW5TaXplICogNCkpO1xuXG4gICAgICAgICAgICBjb25zdCBxbSA9IGV2YWx1YXRpb25zLlFNLmdldEV2YWx1YXRpb24oaSk7XG4gICAgICAgICAgICBjb25zdCBxbCA9IGV2YWx1YXRpb25zLlFMLmdldEV2YWx1YXRpb24oaSk7XG4gICAgICAgICAgICBjb25zdCBxciA9IGV2YWx1YXRpb25zLlFSLmdldEV2YWx1YXRpb24oaSk7XG4gICAgICAgICAgICBjb25zdCBxbyA9IGV2YWx1YXRpb25zLlFPLmdldEV2YWx1YXRpb24oaSk7XG4gICAgICAgICAgICBjb25zdCBxYyA9IGV2YWx1YXRpb25zLlFDLmdldEV2YWx1YXRpb24oaSk7XG4gICAgICAgICAgICBjb25zdCBzMSA9IGV2YWx1YXRpb25zLlNpZ21hMS5nZXRFdmFsdWF0aW9uKGkpO1xuICAgICAgICAgICAgY29uc3QgczIgPSBldmFsdWF0aW9ucy5TaWdtYTIuZ2V0RXZhbHVhdGlvbihpKTtcbiAgICAgICAgICAgIGNvbnN0IHMzID0gZXZhbHVhdGlvbnMuU2lnbWEzLmdldEV2YWx1YXRpb24oaSk7XG5cbiAgICAgICAgICAgIGNvbnN0IGFwID0gRnIuYWRkKGNoYWxsZW5nZXMuYlsyXSwgRnIubXVsKGNoYWxsZW5nZXMuYlsxXSwgdykpO1xuICAgICAgICAgICAgY29uc3QgYnAgPSBGci5hZGQoY2hhbGxlbmdlcy5iWzRdLCBGci5tdWwoY2hhbGxlbmdlcy5iWzNdLCB3KSk7XG4gICAgICAgICAgICBjb25zdCBjcCA9IEZyLmFkZChjaGFsbGVuZ2VzLmJbNl0sIEZyLm11bChjaGFsbGVuZ2VzLmJbNV0sIHcpKTtcblxuICAgICAgICAgICAgY29uc3QgdzIgPSBGci5zcXVhcmUodyk7XG4gICAgICAgICAgICBjb25zdCB6cCA9IEZyLmFkZChGci5hZGQoRnIubXVsKGNoYWxsZW5nZXMuYls3XSwgdzIpLCBGci5tdWwoY2hhbGxlbmdlcy5iWzhdLCB3KSksIGNoYWxsZW5nZXMuYls5XSk7XG4gICAgICAgICAgICBjb25zdCB3VyA9IEZyLm11bCh3LCBGci53W3prZXkucG93ZXJdKTtcbiAgICAgICAgICAgIGNvbnN0IHdXMiA9IEZyLnNxdWFyZSh3Vyk7XG4gICAgICAgICAgICBjb25zdCB6V3AgPSBGci5hZGQoRnIuYWRkKEZyLm11bChjaGFsbGVuZ2VzLmJbN10sIHdXMiksIEZyLm11bChjaGFsbGVuZ2VzLmJbOF0sIHdXKSksIGNoYWxsZW5nZXMuYls5XSk7XG5cbiAgICAgICAgICAgIGxldCBwaSA9IEZyLnplcm87XG4gICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHprZXkublB1YmxpYzsgaisrKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gKGogKiA0ICogemtleS5kb21haW5TaXplKSArIGk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBsUG9sID0gZXZhbHVhdGlvbnMuTGFncmFuZ2UuZ2V0RXZhbHVhdGlvbihvZmZzZXQpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGFWYWwgPSBidWZmZXJzLkEuc2xpY2UoaiAqIG44ciwgKGogKyAxKSAqIG44cik7XG5cbiAgICAgICAgICAgICAgICBwaSA9IEZyLnN1YihwaSwgRnIubXVsKGxQb2wsIGFWYWwpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gZTEgOj0gYShYKWIoWClxTShYKSArIGEoWClxTChYKSArIGIoWClxUihYKSArIGMoWClxTyhYKSArIFBJKFgpICsgcUMoWClcbiAgICAgICAgICAgIGxldCBbZTEsIGUxel0gPSBNdWxaLm11bDIoYSwgYiwgYXAsIGJwLCBpICUgNCwgRnIpO1xuICAgICAgICAgICAgZTEgPSBGci5tdWwoZTEsIHFtKTtcbiAgICAgICAgICAgIGUxeiA9IEZyLm11bChlMXosIHFtKTtcblxuICAgICAgICAgICAgZTEgPSBGci5hZGQoZTEsIEZyLm11bChhLCBxbCkpO1xuICAgICAgICAgICAgZTF6ID0gRnIuYWRkKGUxeiwgRnIubXVsKGFwLCBxbCkpO1xuXG4gICAgICAgICAgICBlMSA9IEZyLmFkZChlMSwgRnIubXVsKGIsIHFyKSk7XG4gICAgICAgICAgICBlMXogPSBGci5hZGQoZTF6LCBGci5tdWwoYnAsIHFyKSk7XG5cbiAgICAgICAgICAgIGUxID0gRnIuYWRkKGUxLCBGci5tdWwoYywgcW8pKTtcbiAgICAgICAgICAgIGUxeiA9IEZyLmFkZChlMXosIEZyLm11bChjcCwgcW8pKTtcblxuICAgICAgICAgICAgZTEgPSBGci5hZGQoZTEsIHBpKTtcbiAgICAgICAgICAgIGUxID0gRnIuYWRkKGUxLCBxYyk7XG5cbiAgICAgICAgICAgIC8vIGUyIDo9IM6xWyhhKFgpICsgzrJYICsgzrMpKGIoWCkgKyDOsmsxWCArIM6zKShjKFgpICsgzrJrMlggKyDOsyl6KFgpXVxuICAgICAgICAgICAgY29uc3QgYmV0YXcgPSBGci5tdWwoY2hhbGxlbmdlcy5iZXRhLCB3KTtcbiAgICAgICAgICAgIGxldCBlMmEgPSBhO1xuICAgICAgICAgICAgZTJhID0gRnIuYWRkKGUyYSwgYmV0YXcpO1xuICAgICAgICAgICAgZTJhID0gRnIuYWRkKGUyYSwgY2hhbGxlbmdlcy5nYW1tYSk7XG5cbiAgICAgICAgICAgIGxldCBlMmIgPSBiO1xuICAgICAgICAgICAgZTJiID0gRnIuYWRkKGUyYiwgRnIubXVsKGJldGF3LCB6a2V5LmsxKSk7XG4gICAgICAgICAgICBlMmIgPSBGci5hZGQoZTJiLCBjaGFsbGVuZ2VzLmdhbW1hKTtcblxuICAgICAgICAgICAgbGV0IGUyYyA9IGM7XG4gICAgICAgICAgICBlMmMgPSBGci5hZGQoZTJjLCBGci5tdWwoYmV0YXcsIHprZXkuazIpKTtcbiAgICAgICAgICAgIGUyYyA9IEZyLmFkZChlMmMsIGNoYWxsZW5nZXMuZ2FtbWEpO1xuXG4gICAgICAgICAgICBsZXQgZTJkID0gejtcblxuICAgICAgICAgICAgbGV0IFtlMiwgZTJ6XSA9IE11bFoubXVsNChlMmEsIGUyYiwgZTJjLCBlMmQsIGFwLCBicCwgY3AsIHpwLCBpICUgNCwgRnIpO1xuICAgICAgICAgICAgZTIgPSBGci5tdWwoZTIsIGNoYWxsZW5nZXMuYWxwaGEpO1xuICAgICAgICAgICAgZTJ6ID0gRnIubXVsKGUyeiwgY2hhbGxlbmdlcy5hbHBoYSk7XG5cbiAgICAgICAgICAgIC8vIGUzIDo9IM6xWyhhKFgpICsgzrJTz4MxKFgpICsgzrMpKGIoWCkgKyDOslPPgzIoWCkgKyDOsykoYyhYKSArIM6yU8+DMyhYKSArIM6zKXooWM+JKV1cbiAgICAgICAgICAgIGxldCBlM2EgPSBhO1xuICAgICAgICAgICAgZTNhID0gRnIuYWRkKGUzYSwgRnIubXVsKGNoYWxsZW5nZXMuYmV0YSwgczEpKTtcbiAgICAgICAgICAgIGUzYSA9IEZyLmFkZChlM2EsIGNoYWxsZW5nZXMuZ2FtbWEpO1xuXG4gICAgICAgICAgICBsZXQgZTNiID0gYjtcbiAgICAgICAgICAgIGUzYiA9IEZyLmFkZChlM2IsIEZyLm11bChjaGFsbGVuZ2VzLmJldGEsIHMyKSk7XG4gICAgICAgICAgICBlM2IgPSBGci5hZGQoZTNiLCBjaGFsbGVuZ2VzLmdhbW1hKTtcblxuICAgICAgICAgICAgbGV0IGUzYyA9IGM7XG4gICAgICAgICAgICBlM2MgPSBGci5hZGQoZTNjLCBGci5tdWwoY2hhbGxlbmdlcy5iZXRhLCBzMykpO1xuICAgICAgICAgICAgZTNjID0gRnIuYWRkKGUzYywgY2hhbGxlbmdlcy5nYW1tYSk7XG5cbiAgICAgICAgICAgIGxldCBlM2QgPSB6dztcbiAgICAgICAgICAgIGxldCBbZTMsIGUzel0gPSBNdWxaLm11bDQoZTNhLCBlM2IsIGUzYywgZTNkLCBhcCwgYnAsIGNwLCB6V3AsIGkgJSA0LCBGcik7XG5cbiAgICAgICAgICAgIGUzID0gRnIubXVsKGUzLCBjaGFsbGVuZ2VzLmFscGhhKTtcbiAgICAgICAgICAgIGUzeiA9IEZyLm11bChlM3osIGNoYWxsZW5nZXMuYWxwaGEpO1xuXG4gICAgICAgICAgICAvLyBlNCA6PSDOsV4yKHooWCniiJIxKUwxKFgpXG4gICAgICAgICAgICBsZXQgZTQgPSBGci5zdWIoeiwgRnIub25lKTtcbiAgICAgICAgICAgIGU0ID0gRnIubXVsKGU0LCBldmFsdWF0aW9ucy5MYWdyYW5nZS5nZXRFdmFsdWF0aW9uKGkpKTtcbiAgICAgICAgICAgIGU0ID0gRnIubXVsKGU0LCBjaGFsbGVuZ2VzLmFscGhhMik7XG5cbiAgICAgICAgICAgIGxldCBlNHogPSBGci5tdWwoenAsIGV2YWx1YXRpb25zLkxhZ3JhbmdlLmdldEV2YWx1YXRpb24oaSkpO1xuICAgICAgICAgICAgZTR6ID0gRnIubXVsKGU0eiwgY2hhbGxlbmdlcy5hbHBoYTIpO1xuXG5cbiAgICAgICAgICAgIGxldCB0ID0gRnIuYWRkKEZyLnN1YihGci5hZGQoZTEsIGUyKSwgZTMpLCBlNCk7XG4gICAgICAgICAgICBsZXQgdHogPSBGci5hZGQoRnIuc3ViKEZyLmFkZChlMXosIGUyeiksIGUzeiksIGU0eik7XG5cbiAgICAgICAgICAgIGJ1ZmZlcnMuVC5zZXQodCwgaSAqIG44cik7XG4gICAgICAgICAgICBidWZmZXJzLlR6LnNldCh0eiwgaSAqIG44cik7XG5cbiAgICAgICAgICAgIHcgPSBGci5tdWwodywgRnIud1t6a2V5LnBvd2VyICsgMl0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ29tcHV0ZSB0aGUgY29lZmZpY2llbnRzIG9mIHRoZSBwb2x5bm9taWFsIFQwKFgpIGZyb20gYnVmZmVycy5UMFxuICAgICAgICBpZiAobG9nZ2VyKVxuICAgICAgICAgICAgbG9nZ2VyLmRlYnVnKFwiwrfCt8K3IENvbXB1dGluZyBUIGlmZnRcIik7XG4gICAgICAgIHBvbHlub21pYWxzLlQgPSBhd2FpdCBQb2x5bm9taWFsLmZyb21FdmFsdWF0aW9ucyhidWZmZXJzLlQsIGN1cnZlLCBsb2dnZXIpO1xuXG4gICAgICAgIC8vIERpdmlkZSB0aGUgcG9seW5vbWlhbCBUMCBieSBaX0goWClcbiAgICAgICAgaWYgKGxvZ2dlcilcbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZyhcIsK3wrfCtyBDb21wdXRpbmcgVCAvIFpIXCIpO1xuICAgICAgICBwb2x5bm9taWFscy5ULmRpdlpoKHprZXkuZG9tYWluU2l6ZSwgNCk7XG5cbiAgICAgICAgLy8gQ29tcHV0ZSB0aGUgY29lZmZpY2llbnRzIG9mIHRoZSBwb2x5bm9taWFsIFR6KFgpIGZyb20gYnVmZmVycy5UelxuICAgICAgICBpZiAobG9nZ2VyKVxuICAgICAgICAgICAgbG9nZ2VyLmRlYnVnKFwiwrfCt8K3IENvbXB1dGluZyBUeiBpZmZ0XCIpO1xuICAgICAgICBwb2x5bm9taWFscy5UeiA9IGF3YWl0IFBvbHlub21pYWwuZnJvbUV2YWx1YXRpb25zKGJ1ZmZlcnMuVHosIGN1cnZlLCBsb2dnZXIpO1xuXG4gICAgICAgIC8vIEFkZCB0aGUgcG9seW5vbWlhbCBUMXogdG8gVDEgdG8gZ2V0IHRoZSBmaW5hbCBwb2x5bm9taWFsIFQxXG4gICAgICAgIHBvbHlub21pYWxzLlQuYWRkKHBvbHlub21pYWxzLlR6KTtcblxuICAgICAgICAvLyBDaGVjayBkZWdyZWVcbiAgICAgICAgaWYgKHBvbHlub21pYWxzLlQuZGVncmVlKCkgPj0gemtleS5kb21haW5TaXplICogMyArIDYpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlQgUG9seW5vbWlhbCBpcyBub3Qgd2VsbCBjYWxjdWxhdGVkXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdCh4KSBoYXMgZGVncmVlIDNuICsgNSwgd2UgYXJlIGdvaW5nIHRvIHNwbGl0IHQoeCkgaW50byB0aHJlZSBzbWFsbGVyIHBvbHlub21pYWxzOlxuICAgICAgICAvLyBUMScgYW5kIFQyJyAgd2l0aCBhIGRlZ3JlZSA8IG4gYW5kIFQzJyB3aXRoIGEgZGVncmVlIG4rNVxuICAgICAgICAvLyBzdWNoIHRoYXQgdCh4KSA9IFQxJyhYKSArIFhebiBUMicoWCkgKyBYXnsybn0gVDMnKFgpXG4gICAgICAgIC8vIFRvIHJhbmRvbWl6ZSB0aGUgcGFydHMgd2UgdXNlIGJsaW5kaW5nIHNjYWxhcnMgYl8xMCBhbmQgYl8xMSBpbiBhIHdheSB0aGF0IGRvZXNuJ3QgY2hhbmdlIHQoWCk6XG4gICAgICAgIC8vIFQxKFgpID0gVDEnKFgpICsgYl8xMCBYXm5cbiAgICAgICAgLy8gVDIoWCkgPSBUMicoWCkgLSBiXzEwICsgYl8xMSBYXm5cbiAgICAgICAgLy8gVDMoWCkgPSBUMycoWCkgLSBiXzExXG4gICAgICAgIC8vIHN1Y2ggdGhhdFxuICAgICAgICAvLyB0KFgpID0gVDEoWCkgKyBYXm4gVDIoWCkgKyBYXjJuIFQzKFgpXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIsK3wrfCtyBDb21wdXRpbmcgVDEsIFQyLCBUMyBwb2x5bm9taWFsc1wiKTtcbiAgICAgICAgcG9seW5vbWlhbHMuVDEgPSBuZXcgUG9seW5vbWlhbChuZXcgQmlnQnVmZmVyKCh6a2V5LmRvbWFpblNpemUgKyAxKSAqIG44ciksIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICBwb2x5bm9taWFscy5UMiA9IG5ldyBQb2x5bm9taWFsKG5ldyBCaWdCdWZmZXIoKHprZXkuZG9tYWluU2l6ZSArIDEpICogbjhyKSwgY3VydmUsIGxvZ2dlcik7XG4gICAgICAgIHBvbHlub21pYWxzLlQzID0gbmV3IFBvbHlub21pYWwobmV3IEJpZ0J1ZmZlcigoemtleS5kb21haW5TaXplICsgNikgKiBuOHIpLCBjdXJ2ZSwgbG9nZ2VyKTtcblxuICAgICAgICBwb2x5bm9taWFscy5UMS5jb2VmLnNldChwb2x5bm9taWFscy5ULmNvZWYuc2xpY2UoMCwgc0RvbWFpbiksIDApO1xuICAgICAgICBwb2x5bm9taWFscy5UMi5jb2VmLnNldChwb2x5bm9taWFscy5ULmNvZWYuc2xpY2Uoc0RvbWFpbiwgc0RvbWFpbiAqIDIpLCAwKTtcbiAgICAgICAgcG9seW5vbWlhbHMuVDMuY29lZi5zZXQocG9seW5vbWlhbHMuVC5jb2VmLnNsaWNlKHNEb21haW4gKiAyLCBzRG9tYWluICogMyArIDYgKiBuOHIpLCAwKTtcblxuICAgICAgICAvLyBBZGQgYmxpbmRpbmcgc2NhbGFyIGJfMTAgYXMgYSBuZXcgY29lZmZpY2llbnQgblxuICAgICAgICBwb2x5bm9taWFscy5UMS5zZXRDb2VmKHprZXkuZG9tYWluU2l6ZSwgY2hhbGxlbmdlcy5iWzEwXSk7XG5cbiAgICAgICAgLy8gY29tcHV0ZSB0X21pZChYKVxuICAgICAgICAvLyBTdWJ0cmFjdCBibGluZGluZyBzY2FsYXIgYl8xMCB0byB0aGUgbG93ZXN0IGNvZWZmaWNpZW50IG9mIHRfbWlkXG4gICAgICAgIGNvbnN0IGxvd2VzdE1pZCA9IEZyLnN1Yihwb2x5bm9taWFscy5UMi5nZXRDb2VmKDApLCBjaGFsbGVuZ2VzLmJbMTBdKTtcbiAgICAgICAgcG9seW5vbWlhbHMuVDIuc2V0Q29lZigwLCBsb3dlc3RNaWQpO1xuICAgICAgICBwb2x5bm9taWFscy5UMi5zZXRDb2VmKHprZXkuZG9tYWluU2l6ZSwgY2hhbGxlbmdlcy5iWzExXSk7XG5cbiAgICAgICAgLy8gY29tcHV0ZSB0X2hpZ2goWClcbiAgICAgICAgLy9TdWJ0cmFjdCBibGluZGluZyBzY2FsYXIgYl8xMSB0byB0aGUgbG93ZXN0IGNvZWZmaWNpZW50IG9mIHRfaGlnaFxuICAgICAgICBjb25zdCBsb3dlc3RIaWdoID0gRnIuc3ViKHBvbHlub21pYWxzLlQzLmdldENvZWYoMCksIGNoYWxsZW5nZXMuYlsxMV0pO1xuICAgICAgICBwb2x5bm9taWFscy5UMy5zZXRDb2VmKDAsIGxvd2VzdEhpZ2gpO1xuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHJvdW5kNCgpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKFwiPiBDb21wdXRpbmcgY2hhbGxlbmdlIHhpXCIpO1xuXG4gICAgICAgIC8vIFNURVAgNC4xIC0gQ29tcHV0ZSBldmFsdWF0aW9uIGNoYWxsZW5nZSB4aSDiiIggRlxuICAgICAgICB0cmFuc2NyaXB0LnJlc2V0KCk7XG4gICAgICAgIHRyYW5zY3JpcHQuYWRkU2NhbGFyKGNoYWxsZW5nZXMuYWxwaGEpO1xuICAgICAgICB0cmFuc2NyaXB0LmFkZFBvbENvbW1pdG1lbnQocHJvb2YuZ2V0UG9seW5vbWlhbChcIlQxXCIpKTtcbiAgICAgICAgdHJhbnNjcmlwdC5hZGRQb2xDb21taXRtZW50KHByb29mLmdldFBvbHlub21pYWwoXCJUMlwiKSk7XG4gICAgICAgIHRyYW5zY3JpcHQuYWRkUG9sQ29tbWl0bWVudChwcm9vZi5nZXRQb2x5bm9taWFsKFwiVDNcIikpO1xuXG4gICAgICAgIGNoYWxsZW5nZXMueGkgPSB0cmFuc2NyaXB0LmdldENoYWxsZW5nZSgpO1xuICAgICAgICBjaGFsbGVuZ2VzLnhpdyA9IEZyLm11bChjaGFsbGVuZ2VzLnhpLCBGci53W3prZXkucG93ZXJdKTtcbiAgICAgICAgXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIsK3wrfCtyBjaGFsbGVuZ2VzLnhpOiBcIiArIEZyLnRvU3RyaW5nKGNoYWxsZW5nZXMueGksIDE2KSk7ICBcblxuICAgICAgICAvLyBGb3VydGggb3V0cHV0IG9mIHRoZSBwcm92ZXIgaXMgKCBhKHhpKSwgYih4aSksIGMoeGkpLCBzMSh4aSksIHMyKHhpKSwgeih4aXcpIClcbiAgICAgICAgcHJvb2YuYWRkRXZhbHVhdGlvbihcImV2YWxfYVwiLCBwb2x5bm9taWFscy5BLmV2YWx1YXRlKGNoYWxsZW5nZXMueGkpKTtcbiAgICAgICAgcHJvb2YuYWRkRXZhbHVhdGlvbihcImV2YWxfYlwiLCBwb2x5bm9taWFscy5CLmV2YWx1YXRlKGNoYWxsZW5nZXMueGkpKTtcbiAgICAgICAgcHJvb2YuYWRkRXZhbHVhdGlvbihcImV2YWxfY1wiLCBwb2x5bm9taWFscy5DLmV2YWx1YXRlKGNoYWxsZW5nZXMueGkpKTtcbiAgICAgICAgcHJvb2YuYWRkRXZhbHVhdGlvbihcImV2YWxfczFcIiwgcG9seW5vbWlhbHMuU2lnbWExLmV2YWx1YXRlKGNoYWxsZW5nZXMueGkpKTtcbiAgICAgICAgcHJvb2YuYWRkRXZhbHVhdGlvbihcImV2YWxfczJcIiwgcG9seW5vbWlhbHMuU2lnbWEyLmV2YWx1YXRlKGNoYWxsZW5nZXMueGkpKTtcbiAgICAgICAgcHJvb2YuYWRkRXZhbHVhdGlvbihcImV2YWxfendcIiwgcG9seW5vbWlhbHMuWi5ldmFsdWF0ZShjaGFsbGVuZ2VzLnhpdykpO1xuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHJvdW5kNSgpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmRlYnVnKFwiPiBDb21wdXRpbmcgY2hhbGxlbmdlIHZcIik7XG4gICAgICAgIFxuICAgICAgICAvLyBTVEVQIDUuMSAtIENvbXB1dGUgZXZhbHVhdGlvbiBjaGFsbGVuZ2UgdiDiiIggRlxuICAgICAgICB0cmFuc2NyaXB0LnJlc2V0KCk7XG4gICAgICAgIHRyYW5zY3JpcHQuYWRkU2NhbGFyKGNoYWxsZW5nZXMueGkpO1xuICAgICAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihwcm9vZi5nZXRFdmFsdWF0aW9uKFwiZXZhbF9hXCIpKTtcbiAgICAgICAgdHJhbnNjcmlwdC5hZGRTY2FsYXIocHJvb2YuZ2V0RXZhbHVhdGlvbihcImV2YWxfYlwiKSk7XG4gICAgICAgIHRyYW5zY3JpcHQuYWRkU2NhbGFyKHByb29mLmdldEV2YWx1YXRpb24oXCJldmFsX2NcIikpO1xuICAgICAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihwcm9vZi5nZXRFdmFsdWF0aW9uKFwiZXZhbF9zMVwiKSk7XG4gICAgICAgIHRyYW5zY3JpcHQuYWRkU2NhbGFyKHByb29mLmdldEV2YWx1YXRpb24oXCJldmFsX3MyXCIpKTtcbiAgICAgICAgdHJhbnNjcmlwdC5hZGRTY2FsYXIocHJvb2YuZ2V0RXZhbHVhdGlvbihcImV2YWxfendcIikpO1xuXG4gICAgICAgIGNoYWxsZW5nZXMudiA9IFtdO1xuICAgICAgICBjaGFsbGVuZ2VzLnZbMV0gPSB0cmFuc2NyaXB0LmdldENoYWxsZW5nZSgpO1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCLCt8K3wrcgY2hhbGxlbmdlcy52OiBcIiArIEZyLnRvU3RyaW5nKGNoYWxsZW5nZXMudlsxXSwgMTYpKTtcblxuICAgICAgICBmb3IgKGxldCBpID0gMjsgaSA8IDY7IGkrKykge1xuICAgICAgICAgICAgY2hhbGxlbmdlcy52W2ldID0gRnIubXVsKGNoYWxsZW5nZXMudltpIC0gMV0sIGNoYWxsZW5nZXMudlsxXSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTVEVQIDUuMiBDb21wdXRlIGxpbmVhcmlzYXRpb24gcG9seW5vbWlhbCByKFgpXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIj4gQ29tcHV0aW5nIGxpbmVhcmlzYXRpb24gcG9seW5vbWlhbCBSKFgpXCIpO1xuICAgICAgICBhd2FpdCBjb21wdXRlUigpO1xuXG4gICAgICAgIC8vU1RFUCA1LjMgQ29tcHV0ZSBvcGVuaW5nIHByb29mIHBvbHlub21pYWwgV3hpKFgpXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIj4gQ29tcHV0aW5nIG9wZW5pbmcgcHJvb2YgcG9seW5vbWlhbCBXeGkoWCkgcG9seW5vbWlhbFwiKTtcbiAgICAgICAgY29tcHV0ZVd4aSgpO1xuXG4gICAgICAgIC8vU1RFUCA1LjQgQ29tcHV0ZSBvcGVuaW5nIHByb29mIHBvbHlub21pYWwgV3hpdyhYKVxuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCI+IENvbXB1dGluZyBvcGVuaW5nIHByb29mIHBvbHlub21pYWwgV3hpdyhYKSBwb2x5bm9taWFsXCIpO1xuICAgICAgICBjb21wdXRlV3hpdygpO1xuXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIj4gQ29tcHV0aW5nIFd4aSwgV3hpdyBNU01cIik7XG4gICAgICAgIGxldCBjb21taXRXeGkgPSBhd2FpdCBwb2x5bm9taWFscy5XeGkubXVsdGlFeHBvbmVudGlhdGlvbihQVGF1LCBcIld4aVwiKTtcbiAgICAgICAgbGV0IGNvbW1pdFd4aXcgPSBhd2FpdCBwb2x5bm9taWFscy5XeGl3Lm11bHRpRXhwb25lbnRpYXRpb24oUFRhdSwgXCJXeGl3XCIpO1xuXG4gICAgICAgIC8vIEZpZnRoIG91dHB1dCBvZiB0aGUgcHJvdmVyIGlzIChbV3hpXV8xLCBbV3hpd11fMSlcbiAgICAgICAgcHJvb2YuYWRkUG9seW5vbWlhbChcIld4aVwiLCBjb21taXRXeGkpO1xuICAgICAgICBwcm9vZi5hZGRQb2x5bm9taWFsKFwiV3hpd1wiLCBjb21taXRXeGl3KTtcbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiBjb21wdXRlUigpIHtcbiAgICAgICAgY29uc3QgRnIgPSBjdXJ2ZS5GcjtcbiAgICBcbiAgICAgICAgLy8gUmVzZXJ2ZSBtZW1vcnkgZm9yIFEncyBwb2x5bm9taWFsc1xuICAgICAgICBwb2x5bm9taWFscy5RTCA9IG5ldyBQb2x5bm9taWFsKG5ldyBCaWdCdWZmZXIoc0RvbWFpbiksIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICBwb2x5bm9taWFscy5RUiA9IG5ldyBQb2x5bm9taWFsKG5ldyBCaWdCdWZmZXIoc0RvbWFpbiksIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICBwb2x5bm9taWFscy5RTSA9IG5ldyBQb2x5bm9taWFsKG5ldyBCaWdCdWZmZXIoc0RvbWFpbiksIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICBwb2x5bm9taWFscy5RTyA9IG5ldyBQb2x5bm9taWFsKG5ldyBCaWdCdWZmZXIoc0RvbWFpbiksIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICBwb2x5bm9taWFscy5RQyA9IG5ldyBQb2x5bm9taWFsKG5ldyBCaWdCdWZmZXIoc0RvbWFpbiksIGN1cnZlLCBsb2dnZXIpO1xuXG4gICAgICAgIC8vIFJlYWQgUSdzIGV2YWx1YXRpb25zIGZyb20gemtleSBmaWxlXG4gICAgICAgIGF3YWl0IGZkWktleS5yZWFkVG9CdWZmZXIocG9seW5vbWlhbHMuUUwuY29lZiwgMCwgc0RvbWFpbiwgemtleVNlY3Rpb25zW1pLRVlfUExfUUxfU0VDVElPTl1bMF0ucCk7XG4gICAgICAgIGF3YWl0IGZkWktleS5yZWFkVG9CdWZmZXIocG9seW5vbWlhbHMuUVIuY29lZiwgMCwgc0RvbWFpbiwgemtleVNlY3Rpb25zW1pLRVlfUExfUVJfU0VDVElPTl1bMF0ucCk7XG4gICAgICAgIGF3YWl0IGZkWktleS5yZWFkVG9CdWZmZXIocG9seW5vbWlhbHMuUU0uY29lZiwgMCwgc0RvbWFpbiwgemtleVNlY3Rpb25zW1pLRVlfUExfUU1fU0VDVElPTl1bMF0ucCk7XG4gICAgICAgIGF3YWl0IGZkWktleS5yZWFkVG9CdWZmZXIocG9seW5vbWlhbHMuUU8uY29lZiwgMCwgc0RvbWFpbiwgemtleVNlY3Rpb25zW1pLRVlfUExfUU9fU0VDVElPTl1bMF0ucCk7XG4gICAgICAgIGF3YWl0IGZkWktleS5yZWFkVG9CdWZmZXIocG9seW5vbWlhbHMuUUMuY29lZiwgMCwgc0RvbWFpbiwgemtleVNlY3Rpb25zW1pLRVlfUExfUUNfU0VDVElPTl1bMF0ucCk7ICAgXG4gICAgICAgIFxuICAgICAgICBjaGFsbGVuZ2VzLnhpbiA9IGNoYWxsZW5nZXMueGk7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgemtleS5wb3dlcjsgaSsrKSB7XG4gICAgICAgICAgICBjaGFsbGVuZ2VzLnhpbiA9IEZyLnNxdWFyZShjaGFsbGVuZ2VzLnhpbik7XG4gICAgICAgIH1cblxuICAgICAgICBjaGFsbGVuZ2VzLnpoID0gRnIuc3ViKGNoYWxsZW5nZXMueGluLCBGci5vbmUpO1xuXG4gICAgICAgIGNvbnN0IEwgPSBbXTtcblxuICAgICAgICBjb25zdCBuID0gRnIuZSh6a2V5LmRvbWFpblNpemUpO1xuICAgICAgICBsZXQgdyA9IEZyLm9uZTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPD0gTWF0aC5tYXgoMSwgemtleS5uUHVibGljKTsgaSsrKSB7XG4gICAgICAgICAgICBMW2ldID0gRnIuZGl2KEZyLm11bCh3LCBjaGFsbGVuZ2VzLnpoKSwgRnIubXVsKG4sIEZyLnN1YihjaGFsbGVuZ2VzLnhpLCB3KSkpO1xuICAgICAgICAgICAgdyA9IEZyLm11bCh3LCBGci53W3prZXkucG93ZXJdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGV2YWxfbDEgPSBGci5kaXYoXG4gICAgICAgICAgICBGci5zdWIoY2hhbGxlbmdlcy54aW4sIEZyLm9uZSksXG4gICAgICAgICAgICBGci5tdWwobiwgRnIuc3ViKGNoYWxsZW5nZXMueGksIEZyLm9uZSkpXG4gICAgICAgICk7XG5cbiAgICAgICAgaWYgKGxvZ2dlcikge1xuICAgICAgICAgICAgbG9nZ2VyLmRlYnVnKFwiTGFncmFuZ2UgRXZhbHVhdGlvbnM6IFwiKTtcbiAgICAgICAgICAgIGZvciAobGV0IGk9MTsgaTxMLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmRlYnVnKGBMJHtpfSh4aSk9YCArIEZyLnRvU3RyaW5nKExbaV0sIDE2KSk7ICAgIFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGV2YWxfcGkgPSBGci56ZXJvO1xuICAgICAgICBmb3IgKGxldCBpPTA7IGk8cHVibGljU2lnbmFscy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgdyA9IEZyLmUocHVibGljU2lnbmFsc1tpXSk7XG4gICAgICAgICAgICBldmFsX3BpID0gRnIuc3ViKGV2YWxfcGksIEZyLm11bCh3LCBMW2krMV0pKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5kZWJ1ZyhcIlBJOiBcIiArIEZyLnRvU3RyaW5nKGV2YWxfcGksIDE2KSk7XG5cbiAgICAgICAgLy8gQ29tcHV0ZSBjb25zdGFudCBwYXJ0cyBvZiBSKFgpXG4gICAgICAgIGNvbnN0IGNvZWZfYWIgPSBGci5tdWwocHJvb2YuZXZhbHVhdGlvbnMuZXZhbF9hLCBwcm9vZi5ldmFsdWF0aW9ucy5ldmFsX2IpO1xuXG4gICAgICAgIGxldCBlMmEgPSBwcm9vZi5ldmFsdWF0aW9ucy5ldmFsX2E7XG4gICAgICAgIGNvbnN0IGJldGF4aSA9IEZyLm11bChjaGFsbGVuZ2VzLmJldGEsIGNoYWxsZW5nZXMueGkpO1xuICAgICAgICBlMmEgPSBGci5hZGQoZTJhLCBiZXRheGkpO1xuICAgICAgICBlMmEgPSBGci5hZGQoZTJhLCBjaGFsbGVuZ2VzLmdhbW1hKTtcblxuICAgICAgICBsZXQgZTJiID0gcHJvb2YuZXZhbHVhdGlvbnMuZXZhbF9iO1xuICAgICAgICBlMmIgPSBGci5hZGQoZTJiLCBGci5tdWwoYmV0YXhpLCB6a2V5LmsxKSk7XG4gICAgICAgIGUyYiA9IEZyLmFkZChlMmIsIGNoYWxsZW5nZXMuZ2FtbWEpO1xuXG4gICAgICAgIGxldCBlMmMgPSBwcm9vZi5ldmFsdWF0aW9ucy5ldmFsX2M7XG4gICAgICAgIGUyYyA9IEZyLmFkZChlMmMsIEZyLm11bChiZXRheGksIHprZXkuazIpKTtcbiAgICAgICAgZTJjID0gRnIuYWRkKGUyYywgY2hhbGxlbmdlcy5nYW1tYSk7XG5cbiAgICAgICAgY29uc3QgZTIgPSBGci5tdWwoRnIubXVsKEZyLm11bChlMmEsIGUyYiksIGUyYyksIGNoYWxsZW5nZXMuYWxwaGEpO1xuXG4gICAgICAgIGxldCBlM2EgPSBwcm9vZi5ldmFsdWF0aW9ucy5ldmFsX2E7XG4gICAgICAgIGUzYSA9IEZyLmFkZChlM2EsIEZyLm11bChjaGFsbGVuZ2VzLmJldGEsIHByb29mLmV2YWx1YXRpb25zLmV2YWxfczEpKTtcbiAgICAgICAgZTNhID0gRnIuYWRkKGUzYSwgY2hhbGxlbmdlcy5nYW1tYSk7XG5cbiAgICAgICAgbGV0IGUzYiA9IHByb29mLmV2YWx1YXRpb25zLmV2YWxfYjtcbiAgICAgICAgZTNiID0gRnIuYWRkKGUzYiwgRnIubXVsKGNoYWxsZW5nZXMuYmV0YSwgcHJvb2YuZXZhbHVhdGlvbnMuZXZhbF9zMikpO1xuICAgICAgICBlM2IgPSBGci5hZGQoZTNiLCBjaGFsbGVuZ2VzLmdhbW1hKTtcblxuICAgICAgICBsZXQgZTMgPSBGci5tdWwoZTNhLCBlM2IpO1xuICAgICAgICBlMyA9IEZyLm11bChlMywgcHJvb2YuZXZhbHVhdGlvbnMuZXZhbF96dyk7XG4gICAgICAgIGUzID0gRnIubXVsKGUzLCBjaGFsbGVuZ2VzLmFscGhhKTtcblxuICAgICAgICBjb25zdCBlNCA9IEZyLm11bChldmFsX2wxLCBjaGFsbGVuZ2VzLmFscGhhMik7XG5cbiAgICAgICAgcG9seW5vbWlhbHMuUiA9IG5ldyBQb2x5bm9taWFsKG5ldyBCaWdCdWZmZXIoKHprZXkuZG9tYWluU2l6ZSArIDYpICogbjhyKSwgY3VydmUsIGxvZ2dlcik7XG5cbiAgICAgICAgcG9seW5vbWlhbHMuUi5hZGQocG9seW5vbWlhbHMuUU0sIGNvZWZfYWIpO1xuICAgICAgICBwb2x5bm9taWFscy5SLmFkZChwb2x5bm9taWFscy5RTCwgcHJvb2YuZXZhbHVhdGlvbnMuZXZhbF9hKTtcbiAgICAgICAgcG9seW5vbWlhbHMuUi5hZGQocG9seW5vbWlhbHMuUVIsIHByb29mLmV2YWx1YXRpb25zLmV2YWxfYik7XG4gICAgICAgIHBvbHlub21pYWxzLlIuYWRkKHBvbHlub21pYWxzLlFPLCBwcm9vZi5ldmFsdWF0aW9ucy5ldmFsX2MpO1xuICAgICAgICBwb2x5bm9taWFscy5SLmFkZChwb2x5bm9taWFscy5RQyk7XG4gICAgICAgIHBvbHlub21pYWxzLlIuYWRkKHBvbHlub21pYWxzLlosIGUyKTtcbiAgICAgICAgcG9seW5vbWlhbHMuUi5zdWIocG9seW5vbWlhbHMuU2lnbWEzLCBGci5tdWwoZTMsIGNoYWxsZW5nZXMuYmV0YSkpO1xuICAgICAgICBwb2x5bm9taWFscy5SLmFkZChwb2x5bm9taWFscy5aLCBlNCk7XG5cbiAgICAgICAgbGV0IHRtcCA9IFBvbHlub21pYWwuZnJvbVBvbHlub21pYWwocG9seW5vbWlhbHMuVDMsIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICB0bXAubXVsU2NhbGFyKEZyLnNxdWFyZShjaGFsbGVuZ2VzLnhpbikpO1xuICAgICAgICB0bXAuYWRkKHBvbHlub21pYWxzLlQyLCBjaGFsbGVuZ2VzLnhpbik7XG4gICAgICAgIHRtcC5hZGQocG9seW5vbWlhbHMuVDEpO1xuICAgICAgICB0bXAubXVsU2NhbGFyKGNoYWxsZW5nZXMuemgpO1xuXG4gICAgICAgIHBvbHlub21pYWxzLlIuc3ViKHRtcCk7XG5cbiAgICAgICAgbGV0IHIwID0gRnIuc3ViKGV2YWxfcGksIEZyLm11bChlMywgRnIuYWRkKHByb29mLmV2YWx1YXRpb25zLmV2YWxfYywgY2hhbGxlbmdlcy5nYW1tYSkpKTtcbiAgICAgICAgcjAgPSBGci5zdWIocjAsIGU0KTtcblxuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCJyMDogXCIgKyBGci50b1N0cmluZyhyMCwgMTYpKTtcblxuICAgICAgICBwb2x5bm9taWFscy5SLmFkZFNjYWxhcihyMCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29tcHV0ZVd4aSgpIHtcbiAgICAgICAgcG9seW5vbWlhbHMuV3hpID0gbmV3IFBvbHlub21pYWwobmV3IEJpZ0J1ZmZlcihzRG9tYWluICsgNiAqIG44ciksIGN1cnZlLCBsb2dnZXIpO1xuXG4gICAgICAgIHBvbHlub21pYWxzLld4aS5hZGQocG9seW5vbWlhbHMuUik7XG4gICAgICAgIHBvbHlub21pYWxzLld4aS5hZGQocG9seW5vbWlhbHMuQSwgY2hhbGxlbmdlcy52WzFdKTtcbiAgICAgICAgcG9seW5vbWlhbHMuV3hpLmFkZChwb2x5bm9taWFscy5CLCBjaGFsbGVuZ2VzLnZbMl0pO1xuICAgICAgICBwb2x5bm9taWFscy5XeGkuYWRkKHBvbHlub21pYWxzLkMsIGNoYWxsZW5nZXMudlszXSk7XG4gICAgICAgIHBvbHlub21pYWxzLld4aS5hZGQocG9seW5vbWlhbHMuU2lnbWExLCBjaGFsbGVuZ2VzLnZbNF0pO1xuICAgICAgICBwb2x5bm9taWFscy5XeGkuYWRkKHBvbHlub21pYWxzLlNpZ21hMiwgY2hhbGxlbmdlcy52WzVdKTtcblxuICAgICAgICBwb2x5bm9taWFscy5XeGkuc3ViU2NhbGFyKEZyLm11bChjaGFsbGVuZ2VzLnZbMV0sIHByb29mLmV2YWx1YXRpb25zLmV2YWxfYSkpO1xuICAgICAgICBwb2x5bm9taWFscy5XeGkuc3ViU2NhbGFyKEZyLm11bChjaGFsbGVuZ2VzLnZbMl0sIHByb29mLmV2YWx1YXRpb25zLmV2YWxfYikpO1xuICAgICAgICBwb2x5bm9taWFscy5XeGkuc3ViU2NhbGFyKEZyLm11bChjaGFsbGVuZ2VzLnZbM10sIHByb29mLmV2YWx1YXRpb25zLmV2YWxfYykpO1xuICAgICAgICBwb2x5bm9taWFscy5XeGkuc3ViU2NhbGFyKEZyLm11bChjaGFsbGVuZ2VzLnZbNF0sIHByb29mLmV2YWx1YXRpb25zLmV2YWxfczEpKTtcbiAgICAgICAgcG9seW5vbWlhbHMuV3hpLnN1YlNjYWxhcihGci5tdWwoY2hhbGxlbmdlcy52WzVdLCBwcm9vZi5ldmFsdWF0aW9ucy5ldmFsX3MyKSk7XG5cbiAgICAgICAgcG9seW5vbWlhbHMuV3hpLmRpdkJ5WmVyb2ZpZXIoMSwgY2hhbGxlbmdlcy54aSk7XG4gICAgfVxuXG4gICAgYXN5bmMgZnVuY3Rpb24gY29tcHV0ZVd4aXcoKSB7XG4gICAgICAgIHBvbHlub21pYWxzLld4aXcgPSBQb2x5bm9taWFsLmZyb21Qb2x5bm9taWFsKHBvbHlub21pYWxzLlosIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICBwb2x5bm9taWFscy5XeGl3LnN1YlNjYWxhcihwcm9vZi5ldmFsdWF0aW9ucy5ldmFsX3p3KTtcblxuICAgICAgICBwb2x5bm9taWFscy5XeGl3LmRpdkJ5WmVyb2ZpZXIoMSwgY2hhbGxlbmdlcy54aXcpO1xuICAgIH1cbn1cbiIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMjEgMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya0pTLlxuXG4gICAgc25hcmtKUyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJrSlMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggc25hcmtKUy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbmltcG9ydCBwbG9ua19wcm92ZSBmcm9tIFwiLi9wbG9ua19wcm92ZS5qc1wiO1xuaW1wb3J0IHd0bnNfY2FsY3VsYXRlIGZyb20gXCIuL3d0bnNfY2FsY3VsYXRlLmpzXCI7XG5pbXBvcnQge3V0aWxzfSBmcm9tIFwiZmZqYXZhc2NyaXB0XCI7XG5jb25zdCB7dW5zdHJpbmdpZnlCaWdJbnRzfSA9IHV0aWxzO1xuXG5leHBvcnQgZGVmYXVsdCBhc3luYyBmdW5jdGlvbiBwbG9ua0Z1bGxQcm92ZShfaW5wdXQsIHdhc21GaWxlLCB6a2V5RmlsZU5hbWUsIGxvZ2dlciwgd3Ruc0NhbGNPcHRpb25zLCBwcm92ZXJPcHRpb25zKSB7XG4gICAgY29uc3QgaW5wdXQgPSB1bnN0cmluZ2lmeUJpZ0ludHMoX2lucHV0KTtcblxuICAgIGNvbnN0IHd0bnM9IHtcbiAgICAgICAgdHlwZTogXCJtZW1cIlxuICAgIH07XG4gICAgYXdhaXQgd3Ruc19jYWxjdWxhdGUoaW5wdXQsIHdhc21GaWxlLCB3dG5zLCB3dG5zQ2FsY09wdGlvbnMpO1xuICAgIHJldHVybiBhd2FpdCBwbG9ua19wcm92ZSh6a2V5RmlsZU5hbWUsIHd0bnMsIGxvZ2dlciwgcHJvdmVyT3B0aW9ucyk7XG59XG4iLCIvKlxuICAgIENvcHlyaWdodCAyMDIxIDBraW1zIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygc25hcmtqcy5cblxuICAgIHNuYXJranMgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3JcbiAgICBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlXG4gICAgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pXG4gICAgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICBzbmFya2pzIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gICAgYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yXG4gICAgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYWxvbmcgd2l0aFxuICAgIHNuYXJranMuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG4vKiBJbXBsZW1lbnRhdGlvbiBvZiB0aGlzIHBhcGVyOiBodHRwczovL2VwcmludC5pYWNyLm9yZy8yMDE5Lzk1My5wZGYgKi9cblxuaW1wb3J0ICogYXMgY3VydmVzIGZyb20gXCIuL2N1cnZlcy5qc1wiO1xuaW1wb3J0IHsgdXRpbHMgfSAgIGZyb20gXCJmZmphdmFzY3JpcHRcIjtcbmltcG9ydCB7IEtlY2NhazI1NlRyYW5zY3JpcHQgfSBmcm9tIFwiLi9LZWNjYWsyNTZUcmFuc2NyaXB0LmpzXCI7XG5pbXBvcnQgeyBTY2FsYXIgfSBmcm9tIFwiZmZqYXZhc2NyaXB0XCI7XG5cbmNvbnN0IHsgdW5zdHJpbmdpZnlCaWdJbnRzIH0gPSB1dGlscztcblxuZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gcGxvbmtWZXJpZnkoX3ZrX3ZlcmlmaWVyLCBfcHVibGljU2lnbmFscywgX3Byb29mLCBsb2dnZXIpIHtcbiAgICBsZXQgdmtfdmVyaWZpZXIgPSB1bnN0cmluZ2lmeUJpZ0ludHMoX3ZrX3ZlcmlmaWVyKTtcbiAgICBfcHJvb2YgPSB1bnN0cmluZ2lmeUJpZ0ludHMoX3Byb29mKTtcbiAgICBsZXQgcHVibGljU2lnbmFscyA9IHVuc3RyaW5naWZ5QmlnSW50cyhfcHVibGljU2lnbmFscyk7XG5cbiAgICBjb25zdCBjdXJ2ZSA9IGF3YWl0IGN1cnZlcy5nZXRDdXJ2ZUZyb21OYW1lKHZrX3ZlcmlmaWVyLmN1cnZlKTtcblxuICAgIGNvbnN0IEZyID0gY3VydmUuRnI7XG4gICAgY29uc3QgRzEgPSBjdXJ2ZS5HMTtcblxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiUExPTksgVkVSSUZJRVIgU1RBUlRFRFwiKTtcblxuICAgIGxldCBwcm9vZiA9IGZyb21PYmplY3RQcm9vZihjdXJ2ZSxfcHJvb2YpO1xuICAgIHZrX3ZlcmlmaWVyID0gZnJvbU9iamVjdFZrKGN1cnZlLCB2a192ZXJpZmllcik7XG5cbiAgICBpZiAoIWlzV2VsbENvbnN0cnVjdGVkKGN1cnZlLCBwcm9vZikpIHtcbiAgICAgICAgbG9nZ2VyLmVycm9yKFwiUHJvb2YgY29tbWl0bWVudHMgYXJlIG5vdCB2YWxpZC5cIik7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAocHVibGljU2lnbmFscy5sZW5ndGggIT0gdmtfdmVyaWZpZXIublB1YmxpYykge1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZXJyb3IoXCJJbnZhbGlkIG51bWJlciBvZiBwdWJsaWMgaW5wdXRzXCIpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKCFldmFsdWF0aW9uc0FyZVZhbGlkKGN1cnZlLCBwcm9vZikpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiUHJvb2YgZXZhbHVhdGlvbnMgYXJlIG5vdCB2YWxpZFwiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmICghcHVibGljSW5wdXRzQXJlVmFsaWQoY3VydmUsIHB1YmxpY1NpZ25hbHMpKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihcIlB1YmxpYyBpbnB1dHMgYXJlIG5vdCB2YWxpZC5cIik7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBjaGFsbGVuZ2VzID0gY2FsY3VsYXRlY2hhbGxlbmdlcyhjdXJ2ZSwgcHJvb2YsIHB1YmxpY1NpZ25hbHMsIHZrX3ZlcmlmaWVyKTtcbiAgICBpZiAobG9nZ2VyKSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhcImJldGE6IFwiICsgRnIudG9TdHJpbmcoY2hhbGxlbmdlcy5iZXRhLCAxNikpOyAgICBcbiAgICAgICAgbG9nZ2VyLmRlYnVnKFwiZ2FtbWE6IFwiICsgRnIudG9TdHJpbmcoY2hhbGxlbmdlcy5nYW1tYSwgMTYpKTsgICAgXG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhcImFscGhhOiBcIiArIEZyLnRvU3RyaW5nKGNoYWxsZW5nZXMuYWxwaGEsIDE2KSk7ICAgIFxuICAgICAgICBsb2dnZXIuZGVidWcoXCJ4aTogXCIgKyBGci50b1N0cmluZyhjaGFsbGVuZ2VzLnhpLCAxNikpO1xuICAgICAgICBmb3IobGV0IGk9MTtpPDY7aSsrKSB7XG4gICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuZGVidWcoXCJ2OiBcIiArIEZyLnRvU3RyaW5nKGNoYWxsZW5nZXMudltpXSwgMTYpKTtcbiAgICAgICAgfVxuICAgICAgICBsb2dnZXIuZGVidWcoXCJ1OiBcIiArIEZyLnRvU3RyaW5nKGNoYWxsZW5nZXMudSwgMTYpKTsgICAgXG4gICAgfVxuICAgIGNvbnN0IEwgPSBjYWxjdWxhdGVMYWdyYW5nZUV2YWx1YXRpb25zKGN1cnZlLCBjaGFsbGVuZ2VzLCB2a192ZXJpZmllcik7XG4gICAgaWYgKGxvZ2dlcikge1xuICAgICAgICBmb3IgKGxldCBpPTE7IGk8TC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbG9nZ2VyLmRlYnVnKGBMJHtpfSh4aSk9YCArIEZyLnRvU3RyaW5nKExbaV0sIDE2KSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgaWYgKHB1YmxpY1NpZ25hbHMubGVuZ3RoICE9IHZrX3ZlcmlmaWVyLm5QdWJsaWMpIHtcbiAgICAgICAgbG9nZ2VyLmVycm9yKFwiTnVtYmVyIG9mIHB1YmxpYyBzaWduYWxzIGRvZXMgbm90IG1hdGNoIHdpdGggdmtcIik7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBwaSA9IGNhbGN1bGF0ZVBJKGN1cnZlLCBwdWJsaWNTaWduYWxzLCBMKTtcbiAgICBpZiAobG9nZ2VyKSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhcIlBJKHhpKTogXCIgKyBGci50b1N0cmluZyhwaSwgMTYpKTtcbiAgICB9XG4gICAgXG4gICAgY29uc3QgcjAgPSBjYWxjdWxhdGVSMChjdXJ2ZSwgcHJvb2YsIGNoYWxsZW5nZXMsIHBpLCBMWzFdKTtcbiAgICBpZiAobG9nZ2VyKSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhcInIwOiBcIiArIEZyLnRvU3RyaW5nKHIwLCAxNikpO1xuICAgIH1cblxuICAgIGNvbnN0IEQgPSBjYWxjdWxhdGVEKGN1cnZlLCBwcm9vZiwgY2hhbGxlbmdlcywgdmtfdmVyaWZpZXIsIExbMV0pO1xuICAgIGlmIChsb2dnZXIpIHtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKFwiRDogXCIgKyBHMS50b1N0cmluZyhHMS50b0FmZmluZShEKSwgMTYpKTtcbiAgICB9XG5cbiAgICBjb25zdCBGID0gY2FsY3VsYXRlRihjdXJ2ZSwgcHJvb2YsIGNoYWxsZW5nZXMsIHZrX3ZlcmlmaWVyLCBEKTtcbiAgICBpZiAobG9nZ2VyKSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhcIkY6IFwiICsgRzEudG9TdHJpbmcoRzEudG9BZmZpbmUoRiksIDE2KSk7XG4gICAgfVxuXG4gICAgY29uc3QgRSA9IGNhbGN1bGF0ZUUoY3VydmUsIHByb29mLCBjaGFsbGVuZ2VzLCByMCk7XG4gICAgaWYgKGxvZ2dlcikge1xuICAgICAgICBsb2dnZXIuZGVidWcoXCJFOiBcIiArIEcxLnRvU3RyaW5nKEcxLnRvQWZmaW5lKEUpLCAxNikpO1xuICAgIH1cblxuICAgIGNvbnN0IHJlcyA9IGF3YWl0IGlzVmFsaWRQYWlyaW5nKGN1cnZlLCBwcm9vZiwgY2hhbGxlbmdlcywgdmtfdmVyaWZpZXIsIEUsIEYpO1xuXG4gICAgaWYgKGxvZ2dlcikge1xuICAgICAgICBpZiAocmVzKSB7XG4gICAgICAgICAgICBsb2dnZXIuaW5mbyhcIk9LIVwiKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKFwiSW52YWxpZCBQcm9vZlwiKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXM7XG59XG5cblxuZnVuY3Rpb24gZnJvbU9iamVjdFByb29mKGN1cnZlLCBwcm9vZikge1xuICAgIGNvbnN0IEcxID0gY3VydmUuRzE7XG4gICAgY29uc3QgRnIgPSBjdXJ2ZS5GcjtcbiAgICBjb25zdCByZXMgPSB7fTtcbiAgICByZXMuQSA9IEcxLmZyb21PYmplY3QocHJvb2YuQSk7XG4gICAgcmVzLkIgPSBHMS5mcm9tT2JqZWN0KHByb29mLkIpO1xuICAgIHJlcy5DID0gRzEuZnJvbU9iamVjdChwcm9vZi5DKTtcbiAgICByZXMuWiA9IEcxLmZyb21PYmplY3QocHJvb2YuWik7XG4gICAgcmVzLlQxID0gRzEuZnJvbU9iamVjdChwcm9vZi5UMSk7XG4gICAgcmVzLlQyID0gRzEuZnJvbU9iamVjdChwcm9vZi5UMik7XG4gICAgcmVzLlQzID0gRzEuZnJvbU9iamVjdChwcm9vZi5UMyk7XG4gICAgcmVzLmV2YWxfYSA9IEZyLmZyb21PYmplY3QocHJvb2YuZXZhbF9hKTtcbiAgICByZXMuZXZhbF9iID0gRnIuZnJvbU9iamVjdChwcm9vZi5ldmFsX2IpO1xuICAgIHJlcy5ldmFsX2MgPSBGci5mcm9tT2JqZWN0KHByb29mLmV2YWxfYyk7XG4gICAgcmVzLmV2YWxfencgPSBGci5mcm9tT2JqZWN0KHByb29mLmV2YWxfencpO1xuICAgIHJlcy5ldmFsX3MxID0gRnIuZnJvbU9iamVjdChwcm9vZi5ldmFsX3MxKTtcbiAgICByZXMuZXZhbF9zMiA9IEZyLmZyb21PYmplY3QocHJvb2YuZXZhbF9zMik7XG4gICAgcmVzLld4aSA9IEcxLmZyb21PYmplY3QocHJvb2YuV3hpKTtcbiAgICByZXMuV3hpdyA9IEcxLmZyb21PYmplY3QocHJvb2YuV3hpdyk7XG4gICAgcmV0dXJuIHJlcztcbn1cblxuZnVuY3Rpb24gZnJvbU9iamVjdFZrKGN1cnZlLCB2aykge1xuICAgIGNvbnN0IEcxID0gY3VydmUuRzE7XG4gICAgY29uc3QgRzIgPSBjdXJ2ZS5HMjtcbiAgICBjb25zdCBGciA9IGN1cnZlLkZyO1xuICAgIGNvbnN0IHJlcyA9IHZrO1xuICAgIHJlcy5RbSA9IEcxLmZyb21PYmplY3QodmsuUW0pO1xuICAgIHJlcy5RbCA9IEcxLmZyb21PYmplY3QodmsuUWwpO1xuICAgIHJlcy5RciA9IEcxLmZyb21PYmplY3QodmsuUXIpO1xuICAgIHJlcy5RbyA9IEcxLmZyb21PYmplY3QodmsuUW8pO1xuICAgIHJlcy5RYyA9IEcxLmZyb21PYmplY3QodmsuUWMpO1xuICAgIHJlcy5TMSA9IEcxLmZyb21PYmplY3QodmsuUzEpO1xuICAgIHJlcy5TMiA9IEcxLmZyb21PYmplY3QodmsuUzIpO1xuICAgIHJlcy5TMyA9IEcxLmZyb21PYmplY3QodmsuUzMpO1xuICAgIHJlcy5rMSA9IEZyLmZyb21PYmplY3QodmsuazEpO1xuICAgIHJlcy5rMiA9IEZyLmZyb21PYmplY3QodmsuazIpO1xuICAgIHJlcy5YXzIgPSBHMi5mcm9tT2JqZWN0KHZrLlhfMik7XG5cbiAgICByZXR1cm4gcmVzO1xufVxuXG5mdW5jdGlvbiBpc1dlbGxDb25zdHJ1Y3RlZChjdXJ2ZSwgcHJvb2YpIHtcbiAgICBjb25zdCBHMSA9IGN1cnZlLkcxO1xuICAgIGlmICghRzEuaXNWYWxpZChwcm9vZi5BKSkgcmV0dXJuIGZhbHNlO1xuICAgIGlmICghRzEuaXNWYWxpZChwcm9vZi5CKSkgcmV0dXJuIGZhbHNlO1xuICAgIGlmICghRzEuaXNWYWxpZChwcm9vZi5DKSkgcmV0dXJuIGZhbHNlO1xuICAgIGlmICghRzEuaXNWYWxpZChwcm9vZi5aKSkgcmV0dXJuIGZhbHNlO1xuICAgIGlmICghRzEuaXNWYWxpZChwcm9vZi5UMSkpIHJldHVybiBmYWxzZTtcbiAgICBpZiAoIUcxLmlzVmFsaWQocHJvb2YuVDIpKSByZXR1cm4gZmFsc2U7XG4gICAgaWYgKCFHMS5pc1ZhbGlkKHByb29mLlQzKSkgcmV0dXJuIGZhbHNlO1xuICAgIGlmICghRzEuaXNWYWxpZChwcm9vZi5XeGkpKSByZXR1cm4gZmFsc2U7XG4gICAgaWYgKCFHMS5pc1ZhbGlkKHByb29mLld4aXcpKSByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIGNoZWNrVmFsdWVCZWxvbmdUb0ZpZWxkKGN1cnZlLCB2YWx1ZSkge1xuICAgIHJldHVybiBTY2FsYXIuZ2VxKHZhbHVlLCAwKSAmJiBTY2FsYXIubHQodmFsdWUsIGN1cnZlLnIpO1xufVxuXG5mdW5jdGlvbiBjaGVja0V2YWx1YXRpb25Jc1ZhbGlkKGN1cnZlLCBldmFsdWF0aW9uKSB7XG4gICAgcmV0dXJuIGNoZWNrVmFsdWVCZWxvbmdUb0ZpZWxkKGN1cnZlLCBTY2FsYXIuZnJvbVJwckxFKGV2YWx1YXRpb24pKTtcbn1cblxuZnVuY3Rpb24gZXZhbHVhdGlvbnNBcmVWYWxpZChjdXJ2ZSwgcHJvb2YpIHtcbiAgICByZXR1cm4gY2hlY2tFdmFsdWF0aW9uSXNWYWxpZChjdXJ2ZSwgcHJvb2YuZXZhbF9hKVxuICAgICAgICAmJiBjaGVja0V2YWx1YXRpb25Jc1ZhbGlkKGN1cnZlLCBwcm9vZi5ldmFsX2IpXG4gICAgICAgICYmIGNoZWNrRXZhbHVhdGlvbklzVmFsaWQoY3VydmUsIHByb29mLmV2YWxfYylcbiAgICAgICAgJiYgY2hlY2tFdmFsdWF0aW9uSXNWYWxpZChjdXJ2ZSwgcHJvb2YuZXZhbF9zMSlcbiAgICAgICAgJiYgY2hlY2tFdmFsdWF0aW9uSXNWYWxpZChjdXJ2ZSwgcHJvb2YuZXZhbF9zMilcbiAgICAgICAgJiYgY2hlY2tFdmFsdWF0aW9uSXNWYWxpZChjdXJ2ZSwgcHJvb2YuZXZhbF96dyk7XG59XG5cbmZ1bmN0aW9uIHB1YmxpY0lucHV0c0FyZVZhbGlkKGN1cnZlLCBwdWJsaWNJbnB1dHMpIHtcbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgcHVibGljSW5wdXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKCFjaGVja1ZhbHVlQmVsb25nVG9GaWVsZChjdXJ2ZSwgcHVibGljSW5wdXRzW2ldKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBjYWxjdWxhdGVjaGFsbGVuZ2VzKGN1cnZlLCBwcm9vZiwgcHVibGljU2lnbmFscywgdmspIHtcbiAgICBjb25zdCBGciA9IGN1cnZlLkZyO1xuICAgIGNvbnN0IHJlcyA9IHt9O1xuICAgIGNvbnN0IHRyYW5zY3JpcHQgPSBuZXcgS2VjY2FrMjU2VHJhbnNjcmlwdChjdXJ2ZSk7XG5cbiAgICAvLyBDaGFsbGVuZ2Ugcm91bmQgMjogYmV0YSBhbmQgZ2FtbWFcbiAgICB0cmFuc2NyaXB0LmFkZFBvbENvbW1pdG1lbnQodmsuUW0pO1xuICAgIHRyYW5zY3JpcHQuYWRkUG9sQ29tbWl0bWVudCh2ay5RbCk7XG4gICAgdHJhbnNjcmlwdC5hZGRQb2xDb21taXRtZW50KHZrLlFyKTtcbiAgICB0cmFuc2NyaXB0LmFkZFBvbENvbW1pdG1lbnQodmsuUW8pO1xuICAgIHRyYW5zY3JpcHQuYWRkUG9sQ29tbWl0bWVudCh2ay5RYyk7XG4gICAgdHJhbnNjcmlwdC5hZGRQb2xDb21taXRtZW50KHZrLlMxKTtcbiAgICB0cmFuc2NyaXB0LmFkZFBvbENvbW1pdG1lbnQodmsuUzIpO1xuICAgIHRyYW5zY3JpcHQuYWRkUG9sQ29tbWl0bWVudCh2ay5TMyk7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHB1YmxpY1NpZ25hbHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdHJhbnNjcmlwdC5hZGRTY2FsYXIoRnIuZShwdWJsaWNTaWduYWxzW2ldKSk7XG4gICAgfVxuXG4gICAgdHJhbnNjcmlwdC5hZGRQb2xDb21taXRtZW50KHByb29mLkEpO1xuICAgIHRyYW5zY3JpcHQuYWRkUG9sQ29tbWl0bWVudChwcm9vZi5CKTtcbiAgICB0cmFuc2NyaXB0LmFkZFBvbENvbW1pdG1lbnQocHJvb2YuQyk7XG5cbiAgICByZXMuYmV0YSA9IHRyYW5zY3JpcHQuZ2V0Q2hhbGxlbmdlKCk7XG5cbiAgICB0cmFuc2NyaXB0LnJlc2V0KCk7XG4gICAgdHJhbnNjcmlwdC5hZGRTY2FsYXIocmVzLmJldGEpO1xuICAgIHJlcy5nYW1tYSA9IHRyYW5zY3JpcHQuZ2V0Q2hhbGxlbmdlKCk7XG5cbiAgICAvLyBDaGFsbGVuZ2Ugcm91bmQgMzogYWxwaGFcbiAgICB0cmFuc2NyaXB0LnJlc2V0KCk7XG4gICAgdHJhbnNjcmlwdC5hZGRTY2FsYXIocmVzLmJldGEpO1xuICAgIHRyYW5zY3JpcHQuYWRkU2NhbGFyKHJlcy5nYW1tYSk7XG4gICAgdHJhbnNjcmlwdC5hZGRQb2xDb21taXRtZW50KHByb29mLlopO1xuICAgIHJlcy5hbHBoYSA9IHRyYW5zY3JpcHQuZ2V0Q2hhbGxlbmdlKCk7XG5cbiAgICAvLyBDaGFsbGVuZ2Ugcm91bmQgNDogeGlcbiAgICB0cmFuc2NyaXB0LnJlc2V0KCk7XG4gICAgdHJhbnNjcmlwdC5hZGRTY2FsYXIocmVzLmFscGhhKTtcbiAgICB0cmFuc2NyaXB0LmFkZFBvbENvbW1pdG1lbnQocHJvb2YuVDEpO1xuICAgIHRyYW5zY3JpcHQuYWRkUG9sQ29tbWl0bWVudChwcm9vZi5UMik7XG4gICAgdHJhbnNjcmlwdC5hZGRQb2xDb21taXRtZW50KHByb29mLlQzKTtcbiAgICByZXMueGkgPSB0cmFuc2NyaXB0LmdldENoYWxsZW5nZSgpO1xuICAgIFxuICAgIC8vIENoYWxsZW5nZSByb3VuZCA1OiB2XG4gICAgdHJhbnNjcmlwdC5yZXNldCgpO1xuICAgIHRyYW5zY3JpcHQuYWRkU2NhbGFyKHJlcy54aSk7XG4gICAgdHJhbnNjcmlwdC5hZGRTY2FsYXIocHJvb2YuZXZhbF9hKTtcbiAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihwcm9vZi5ldmFsX2IpO1xuICAgIHRyYW5zY3JpcHQuYWRkU2NhbGFyKHByb29mLmV2YWxfYyk7XG4gICAgdHJhbnNjcmlwdC5hZGRTY2FsYXIocHJvb2YuZXZhbF9zMSk7XG4gICAgdHJhbnNjcmlwdC5hZGRTY2FsYXIocHJvb2YuZXZhbF9zMik7XG4gICAgdHJhbnNjcmlwdC5hZGRTY2FsYXIocHJvb2YuZXZhbF96dyk7XG4gICAgcmVzLnYgPSBbXTtcbiAgICByZXMudlsxXSA9IHRyYW5zY3JpcHQuZ2V0Q2hhbGxlbmdlKCk7XG5cbiAgICBmb3IgKGxldCBpPTI7IGk8NjsgaSsrICkgcmVzLnZbaV0gPSBGci5tdWwocmVzLnZbaS0xXSwgcmVzLnZbMV0pO1xuXG4gICAgLy8gQ2hhbGxlbmdlOiB1XG4gICAgdHJhbnNjcmlwdC5yZXNldCgpO1xuICAgIHRyYW5zY3JpcHQuYWRkUG9sQ29tbWl0bWVudChwcm9vZi5XeGkpO1xuICAgIHRyYW5zY3JpcHQuYWRkUG9sQ29tbWl0bWVudChwcm9vZi5XeGl3KTtcbiAgICByZXMudSA9IHRyYW5zY3JpcHQuZ2V0Q2hhbGxlbmdlKCk7XG5cbiAgICByZXR1cm4gcmVzO1xufVxuXG5mdW5jdGlvbiBjYWxjdWxhdGVMYWdyYW5nZUV2YWx1YXRpb25zKGN1cnZlLCBjaGFsbGVuZ2VzLCB2aykge1xuICAgIGNvbnN0IEZyID0gY3VydmUuRnI7XG5cbiAgICBsZXQgeGluID0gY2hhbGxlbmdlcy54aTtcbiAgICBsZXQgZG9tYWluU2l6ZSA9IDE7XG4gICAgZm9yIChsZXQgaT0wOyBpPHZrLnBvd2VyOyBpKyspIHtcbiAgICAgICAgeGluID0gRnIuc3F1YXJlKHhpbik7XG4gICAgICAgIGRvbWFpblNpemUgKj0gMjtcbiAgICB9XG4gICAgY2hhbGxlbmdlcy54aW4gPSB4aW47XG5cbiAgICBjaGFsbGVuZ2VzLnpoID0gRnIuc3ViKHhpbiwgRnIub25lKTtcblxuICAgIGNvbnN0IEwgPSBbXTtcblxuICAgIGNvbnN0IG4gPSBGci5lKGRvbWFpblNpemUpO1xuICAgIGxldCB3ID0gRnIub25lO1xuICAgIGZvciAobGV0IGk9MTsgaTw9TWF0aC5tYXgoMSwgdmsublB1YmxpYyk7IGkrKykge1xuICAgICAgICBMW2ldID0gRnIuZGl2KEZyLm11bCh3LCBjaGFsbGVuZ2VzLnpoKSwgRnIubXVsKG4sIEZyLnN1YihjaGFsbGVuZ2VzLnhpLCB3KSkpO1xuICAgICAgICB3ID0gRnIubXVsKHcsIEZyLndbdmsucG93ZXJdKTtcbiAgICB9XG5cbiAgICByZXR1cm4gTDtcbn1cblxuZnVuY3Rpb24gY2FsY3VsYXRlUEkoY3VydmUsIHB1YmxpY1NpZ25hbHMsIEwpIHtcbiAgICBjb25zdCBGciA9IGN1cnZlLkZyO1xuXG4gICAgbGV0IHBpID0gRnIuemVybztcbiAgICBmb3IgKGxldCBpPTA7IGk8cHVibGljU2lnbmFscy5sZW5ndGg7IGkrKykgeyAgICAgICAgXG4gICAgICAgIGNvbnN0IHcgPSBGci5lKHB1YmxpY1NpZ25hbHNbaV0pO1xuICAgICAgICBwaSA9IEZyLnN1YihwaSwgRnIubXVsKHcsIExbaSsxXSkpO1xuICAgIH1cbiAgICByZXR1cm4gcGk7XG59XG5cbmZ1bmN0aW9uIGNhbGN1bGF0ZVIwKGN1cnZlLCBwcm9vZiwgY2hhbGxlbmdlcywgcGksIGwxKSB7XG4gICAgY29uc3QgRnIgPSBjdXJ2ZS5GcjtcblxuICAgIGNvbnN0IGUxID0gcGk7XG5cbiAgICBjb25zdCBlMiA9IEZyLm11bChsMSwgRnIuc3F1YXJlKGNoYWxsZW5nZXMuYWxwaGEpKTtcblxuICAgIGxldCBlM2EgPSBGci5hZGQocHJvb2YuZXZhbF9hLCBGci5tdWwoY2hhbGxlbmdlcy5iZXRhLCBwcm9vZi5ldmFsX3MxKSk7XG4gICAgZTNhID0gRnIuYWRkKGUzYSwgY2hhbGxlbmdlcy5nYW1tYSk7XG5cbiAgICBsZXQgZTNiID0gRnIuYWRkKHByb29mLmV2YWxfYiwgRnIubXVsKGNoYWxsZW5nZXMuYmV0YSwgcHJvb2YuZXZhbF9zMikpO1xuICAgIGUzYiA9IEZyLmFkZChlM2IsIGNoYWxsZW5nZXMuZ2FtbWEpO1xuXG4gICAgbGV0IGUzYyA9IEZyLmFkZChwcm9vZi5ldmFsX2MsIGNoYWxsZW5nZXMuZ2FtbWEpO1xuXG4gICAgbGV0IGUzID0gRnIubXVsKEZyLm11bChlM2EsIGUzYiksIGUzYyk7XG4gICAgZTMgPSBGci5tdWwoZTMsIHByb29mLmV2YWxfencpO1xuICAgIGUzID0gRnIubXVsKGUzLCBjaGFsbGVuZ2VzLmFscGhhKTtcblxuICAgIGNvbnN0IHIwID0gRnIuc3ViKEZyLnN1YihlMSwgZTIpLCBlMyk7XG5cbiAgICByZXR1cm4gcjA7XG59XG5cbmZ1bmN0aW9uIGNhbGN1bGF0ZUQoY3VydmUsIHByb29mLCBjaGFsbGVuZ2VzLCB2aywgbDEpIHtcbiAgICBjb25zdCBHMSA9IGN1cnZlLkcxO1xuICAgIGNvbnN0IEZyID0gY3VydmUuRnI7XG4gICAgXG4gICAgbGV0IGQxID0gRzEudGltZXNGcih2ay5RbSwgRnIubXVsKHByb29mLmV2YWxfYSwgcHJvb2YuZXZhbF9iKSk7XG4gICAgZDEgPSBHMS5hZGQoZDEsIEcxLnRpbWVzRnIodmsuUWwsIHByb29mLmV2YWxfYSkpO1xuICAgIGQxID0gRzEuYWRkKGQxLCBHMS50aW1lc0ZyKHZrLlFyLCBwcm9vZi5ldmFsX2IpKTtcbiAgICBkMSA9IEcxLmFkZChkMSwgRzEudGltZXNGcih2ay5RbywgcHJvb2YuZXZhbF9jKSk7XG4gICAgZDEgPSBHMS5hZGQoZDEsIHZrLlFjKTtcblxuICAgIGNvbnN0IGJldGF4aSA9IEZyLm11bChjaGFsbGVuZ2VzLmJldGEsIGNoYWxsZW5nZXMueGkpO1xuXG4gICAgY29uc3QgZDJhMSA9IEZyLmFkZChGci5hZGQocHJvb2YuZXZhbF9hLCBiZXRheGkpLCBjaGFsbGVuZ2VzLmdhbW1hKTtcbiAgICBjb25zdCBkMmEyID0gRnIuYWRkKEZyLmFkZChwcm9vZi5ldmFsX2IsIEZyLm11bChiZXRheGksIHZrLmsxKSksIGNoYWxsZW5nZXMuZ2FtbWEpO1xuICAgIGNvbnN0IGQyYTMgPSBGci5hZGQoRnIuYWRkKHByb29mLmV2YWxfYywgRnIubXVsKGJldGF4aSwgdmsuazIpKSwgY2hhbGxlbmdlcy5nYW1tYSk7XG5cbiAgICBjb25zdCBkMmEgPSBGci5tdWwoRnIubXVsKEZyLm11bChkMmExLCBkMmEyKSwgZDJhMyksIGNoYWxsZW5nZXMuYWxwaGEpO1xuXG4gICAgY29uc3QgZDJiID0gRnIubXVsKGwxLCBGci5zcXVhcmUoY2hhbGxlbmdlcy5hbHBoYSkpO1xuXG4gICAgY29uc3QgZDIgPSBHMS50aW1lc0ZyKHByb29mLlosIEZyLmFkZChGci5hZGQoZDJhLCBkMmIpLCBjaGFsbGVuZ2VzLnUpKTtcblxuICAgIGNvbnN0IGQzYSA9IEZyLmFkZChGci5hZGQocHJvb2YuZXZhbF9hLCBGci5tdWwoY2hhbGxlbmdlcy5iZXRhLCBwcm9vZi5ldmFsX3MxKSksIGNoYWxsZW5nZXMuZ2FtbWEpO1xuICAgIGNvbnN0IGQzYiA9IEZyLmFkZChGci5hZGQocHJvb2YuZXZhbF9iLCBGci5tdWwoY2hhbGxlbmdlcy5iZXRhLCBwcm9vZi5ldmFsX3MyKSksIGNoYWxsZW5nZXMuZ2FtbWEpO1xuICAgIGNvbnN0IGQzYyA9IEZyLm11bChGci5tdWwoY2hhbGxlbmdlcy5hbHBoYSwgY2hhbGxlbmdlcy5iZXRhKSwgcHJvb2YuZXZhbF96dyk7XG5cbiAgICBjb25zdCBkMyA9IEcxLnRpbWVzRnIodmsuUzMsIEZyLm11bChGci5tdWwoZDNhLCBkM2IpLCBkM2MpKTtcbiAgICBcbiAgICBjb25zdCBkNGxvdyA9IHByb29mLlQxO1xuICAgIGNvbnN0IGQ0bWlkID0gRzEudGltZXNGcihwcm9vZi5UMiwgY2hhbGxlbmdlcy54aW4pO1xuICAgIGNvbnN0IGQ0aGlnaCA9IEcxLnRpbWVzRnIocHJvb2YuVDMsIEZyLnNxdWFyZShjaGFsbGVuZ2VzLnhpbikpO1xuICAgIGxldCBkNCA9IEcxLmFkZChkNGxvdywgRzEuYWRkKGQ0bWlkLCBkNGhpZ2gpKTtcbiAgICBkNCA9IEcxLnRpbWVzRnIoZDQsIGNoYWxsZW5nZXMuemgpO1xuXG4gICAgY29uc3QgZCA9IEcxLnN1YihHMS5zdWIoRzEuYWRkKGQxLCBkMiksIGQzKSwgZDQpO1xuXG4gICAgcmV0dXJuIGQ7XG59XG5cbmZ1bmN0aW9uIGNhbGN1bGF0ZUYoY3VydmUsIHByb29mLCBjaGFsbGVuZ2VzLCB2aywgRCkge1xuICAgIGNvbnN0IEcxID0gY3VydmUuRzE7XG5cbiAgICBsZXQgcmVzID0gRzEuYWRkKEQsIEcxLnRpbWVzRnIocHJvb2YuQSwgY2hhbGxlbmdlcy52WzFdKSk7XG4gICAgcmVzID0gRzEuYWRkKHJlcywgRzEudGltZXNGcihwcm9vZi5CLCBjaGFsbGVuZ2VzLnZbMl0pKTtcbiAgICByZXMgPSBHMS5hZGQocmVzLCBHMS50aW1lc0ZyKHByb29mLkMsIGNoYWxsZW5nZXMudlszXSkpO1xuICAgIHJlcyA9IEcxLmFkZChyZXMsIEcxLnRpbWVzRnIodmsuUzEsIGNoYWxsZW5nZXMudls0XSkpO1xuICAgIHJlcyA9IEcxLmFkZChyZXMsIEcxLnRpbWVzRnIodmsuUzIsIGNoYWxsZW5nZXMudls1XSkpO1xuXG4gICAgcmV0dXJuIHJlcztcbn1cblxuZnVuY3Rpb24gY2FsY3VsYXRlRShjdXJ2ZSwgcHJvb2YsIGNoYWxsZW5nZXMsIHIwKSB7XG4gICAgY29uc3QgRzEgPSBjdXJ2ZS5HMTtcbiAgICBjb25zdCBGciA9IGN1cnZlLkZyO1xuXG4gICAgbGV0IGUgPSBGci5hZGQoRnIubmVnKHIwKSwgRnIubXVsKGNoYWxsZW5nZXMudlsxXSwgcHJvb2YuZXZhbF9hKSk7XG4gICAgZSA9IEZyLmFkZChlLCBGci5tdWwoY2hhbGxlbmdlcy52WzJdLCBwcm9vZi5ldmFsX2IpKTtcbiAgICBlID0gRnIuYWRkKGUsIEZyLm11bChjaGFsbGVuZ2VzLnZbM10sIHByb29mLmV2YWxfYykpO1xuICAgIGUgPSBGci5hZGQoZSwgRnIubXVsKGNoYWxsZW5nZXMudls0XSwgcHJvb2YuZXZhbF9zMSkpO1xuICAgIGUgPSBGci5hZGQoZSwgRnIubXVsKGNoYWxsZW5nZXMudls1XSwgcHJvb2YuZXZhbF9zMikpO1xuICAgIGUgPSBGci5hZGQoZSwgRnIubXVsKGNoYWxsZW5nZXMudSwgcHJvb2YuZXZhbF96dykpO1xuXG4gICAgY29uc3QgcmVzID0gRzEudGltZXNGcihHMS5vbmUsIGUpO1xuXG4gICAgcmV0dXJuIHJlcztcbn1cblxuYXN5bmMgZnVuY3Rpb24gaXNWYWxpZFBhaXJpbmcoY3VydmUsIHByb29mLCBjaGFsbGVuZ2VzLCB2aywgRSwgRikge1xuICAgIGNvbnN0IEcxID0gY3VydmUuRzE7XG4gICAgY29uc3QgRnIgPSBjdXJ2ZS5GcjtcblxuICAgIGxldCBBMSA9IHByb29mLld4aTtcbiAgICBBMSA9IEcxLmFkZChBMSwgRzEudGltZXNGcihwcm9vZi5XeGl3LCBjaGFsbGVuZ2VzLnUpKTtcblxuICAgIGxldCBCMSA9IEcxLnRpbWVzRnIocHJvb2YuV3hpLCBjaGFsbGVuZ2VzLnhpKTtcbiAgICBjb25zdCBzID0gRnIubXVsKEZyLm11bChjaGFsbGVuZ2VzLnUsIGNoYWxsZW5nZXMueGkpLCBGci53W3ZrLnBvd2VyXSk7XG4gICAgQjEgPSBHMS5hZGQoQjEsIEcxLnRpbWVzRnIocHJvb2YuV3hpdywgcykpO1xuICAgIEIxID0gRzEuYWRkKEIxLCBGKTtcbiAgICBCMSA9IEcxLnN1YihCMSwgRSk7XG5cbiAgICBjb25zdCByZXMgPSBhd2FpdCBjdXJ2ZS5wYWlyaW5nRXEoXG4gICAgICAgIEcxLm5lZyhBMSkgLCB2ay5YXzIsXG4gICAgICAgIEIxICwgY3VydmUuRzIub25lXG4gICAgKTtcblxuICAgIHJldHVybiByZXM7XG59XG4iLCIvKlxuICAgIENvcHlyaWdodCAyMDIxIDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygc25hcmtKUy5cblxuICAgIHNuYXJrSlMgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gICAgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAgICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICAgIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICBzbmFya0pTIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHNuYXJrSlMuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG5pbXBvcnQgeyBnZXRDdXJ2ZUZyb21OYW1lIH0gZnJvbSBcIi4vY3VydmVzLmpzXCI7XG5pbXBvcnQgeyAgdXRpbHMgfSAgIGZyb20gXCJmZmphdmFzY3JpcHRcIjtcbmNvbnN0IHsgdW5zdHJpbmdpZnlCaWdJbnRzfSA9IHV0aWxzO1xuXG5mdW5jdGlvbiBpMmhleChpKSB7XG4gICAgcmV0dXJuIChcIjBcIiArIGkudG9TdHJpbmcoMTYpKS5zbGljZSgtMik7XG59XG5cbmZ1bmN0aW9uIHAyNTYobikge1xuICAgIGxldCBuc3RyID0gbi50b1N0cmluZygxNik7XG4gICAgd2hpbGUgKG5zdHIubGVuZ3RoIDwgNjQpIG5zdHIgPSBcIjBcIituc3RyO1xuICAgIG5zdHIgPSBgXCIweCR7bnN0cn1cImA7XG4gICAgcmV0dXJuIG5zdHI7XG59XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uIHBsb25rRXhwb3J0U29saWRpdHlDYWxsRGF0YShfcHJvb2YsIF9wdWIpIHtcbiAgICBjb25zdCBwcm9vZiA9IHVuc3RyaW5naWZ5QmlnSW50cyhfcHJvb2YpO1xuICAgIGNvbnN0IHB1YiA9IHVuc3RyaW5naWZ5QmlnSW50cyhfcHViKTtcblxuICAgIGNvbnN0IGN1cnZlID0gYXdhaXQgZ2V0Q3VydmVGcm9tTmFtZShwcm9vZi5jdXJ2ZSk7XG4gICAgY29uc3QgRzEgPSBjdXJ2ZS5HMTtcbiAgICBjb25zdCBGciA9IGN1cnZlLkZyO1xuXG4gICAgbGV0IGlucHV0cyA9IFwiXCI7XG4gICAgZm9yIChsZXQgaT0wOyBpPHB1Yi5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoaW5wdXRzICE9IFwiXCIpIGlucHV0cyA9IGlucHV0cyArIFwiLFwiO1xuICAgICAgICBpbnB1dHMgPSBpbnB1dHMgKyBwMjU2KHB1YltpXSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGBbJHtwMjU2KHByb29mLkFbMF0pfSwgJHtwMjU2KHByb29mLkFbMV0pfSxgICtcbiAgICBgJHtwMjU2KHByb29mLkJbMF0pfSwke3AyNTYocHJvb2YuQlsxXSl9LGAgK1xuICAgIGAke3AyNTYocHJvb2YuQ1swXSl9LCR7cDI1Nihwcm9vZi5DWzFdKX0sYCArXG4gICAgYCR7cDI1Nihwcm9vZi5aWzBdKX0sJHtwMjU2KHByb29mLlpbMV0pfSxgICtcbiAgICBgJHtwMjU2KHByb29mLlQxWzBdKX0sJHtwMjU2KHByb29mLlQxWzFdKX0sYCArXG4gICAgYCR7cDI1Nihwcm9vZi5UMlswXSl9LCR7cDI1Nihwcm9vZi5UMlsxXSl9LGAgK1xuICAgIGAke3AyNTYocHJvb2YuVDNbMF0pfSwke3AyNTYocHJvb2YuVDNbMV0pfSxgICtcbiAgICBgJHtwMjU2KHByb29mLld4aVswXSl9LCR7cDI1Nihwcm9vZi5XeGlbMV0pfSxgICtcbiAgICBgJHtwMjU2KHByb29mLld4aXdbMF0pfSwke3AyNTYocHJvb2YuV3hpd1sxXSl9LGAgK1xuICAgIGAke3AyNTYocHJvb2YuZXZhbF9hKX0sYCArIFxuICAgIGAke3AyNTYocHJvb2YuZXZhbF9iKX0sYCArIFxuICAgIGAke3AyNTYocHJvb2YuZXZhbF9jKX0sYCArIFxuICAgIGAke3AyNTYocHJvb2YuZXZhbF9zMSl9LGAgKyBcbiAgICBgJHtwMjU2KHByb29mLmV2YWxfczIpfSxgICsgXG4gICAgYCR7cDI1Nihwcm9vZi5ldmFsX3p3KX1dYCArIFxuICAgIGBbJHtpbnB1dHN9XWA7XG59XG4iLCIvKlxuICAgIENvcHlyaWdodCAyMDE4IDBLSU1TIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygc25hcmtKUy5cblxuICAgIHNuYXJrSlMgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0XG4gICAgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAgICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICAgIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICBzbmFya0pTIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG4gICAgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljXG4gICAgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIHNuYXJrSlMuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG4vLyBaS0VZIGNvbnN0YW50c1xuZXhwb3J0IHtkZWZhdWx0IGFzIHNldHVwfSBmcm9tIFwiLi9wbG9ua19zZXR1cC5qc1wiO1xuZXhwb3J0IHtkZWZhdWx0IGFzIGZ1bGxQcm92ZX0gZnJvbSBcIi4vcGxvbmtfZnVsbHByb3ZlLmpzXCI7XG5leHBvcnQge2RlZmF1bHQgYXMgcHJvdmV9IGZyb20gXCIuL3Bsb25rX3Byb3ZlLmpzXCI7XG5leHBvcnQge2RlZmF1bHQgYXMgdmVyaWZ5fSBmcm9tIFwiLi9wbG9ua192ZXJpZnkuanNcIjtcbmV4cG9ydCB7ZGVmYXVsdCBhcyBleHBvcnRTb2xpZGl0eUNhbGxEYXRhfSBmcm9tIFwiLi9wbG9ua19leHBvcnRzb2xpZGl0eWNhbGxkYXRhLmpzXCI7XG4iLCIvKlxuICAgIENvcHlyaWdodCAyMDIyIGlkZW4zIGFzc29jaWF0aW9uLlxuXG4gICAgVGhpcyBmaWxlIGlzIHBhcnQgb2Ygc25hcmtqcy5cblxuICAgIHNuYXJranMgaXMgYSBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3JcbiAgICBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlXG4gICAgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pXG4gICAgYW55IGxhdGVyIHZlcnNpb24uXG5cbiAgICBzbmFya2pzIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gICAgYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZXG4gICAgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yXG4gICAgbW9yZSBkZXRhaWxzLlxuXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYWxvbmcgd2l0aFxuICAgIHNuYXJranMuIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG4vLyBXZSBleHBvcnQgdG8gemtleSB0aGUgc2lnbmFscyBhbmQgdmFsdWVzIG9mIHRoZSBhLCBiLCBjLCBxbCwgcXIsIHFtLCBxbyBhbmQgcWNcblxuLy8gYSwgYiBhbmQgYyBhcmUgc2lnbmFscyBpZCAoMzItYml0IGludGVnZXJzKVxuLy8gcWwsIHFyLCBxbSwgcW8gYW5kIHFjIGFyZSBmaWVsZCB2YWx1ZXNcblxuZXhwb3J0IGZ1bmN0aW9uIGdldEZGbG9ua0NvbnN0YW50Q29uc3RyYWludChzaWduYWwxLCBGcikge1xuICAgIHJldHVybiBbc2lnbmFsMSwgMCwgMCwgRnIub25lLCBGci56ZXJvLCBGci56ZXJvLCBGci56ZXJvLCBGci56ZXJvXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEZGbG9ua0FkZGl0aW9uQ29uc3RyYWludChzaWduYWwxLCBzaWduYWwyLCBzaWduYWxPdXQsIHFsLCBxciwgcW0sIHFvLCBxYykge1xuICAgIHJldHVybiBbc2lnbmFsMSwgc2lnbmFsMiwgc2lnbmFsT3V0LCBxbCwgcXIsIHFtLCBxbywgcWNdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RkZsb25rTXVsdGlwbGljYXRpb25Db25zdHJhaW50KHNpZ25hbDEsIHNpZ25hbDIsIHNpZ25hbE91dCwgcWwsIHFyLCBxbSwgcW8sIHFjLCBGcikge1xuICAgIHJldHVybiBbc2lnbmFsMSwgc2lnbmFsMiwgc2lnbmFsT3V0LCBxbCwgcXIsIHFtLCBxbywgcWNdO1xufVxuIiwiLypcbiAgICBDb3B5cmlnaHQgMjAyMiBpZGVuMyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJranMuXG5cbiAgICBzbmFya2pzIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4gICAgbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZVxuICAgIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKVxuICAgIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtqcyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICAgIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvclxuICAgIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFsb25nIHdpdGhcbiAgICBzbmFya2pzLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuY29uc3QgTElORUFSX0NPTUJJTkFUSU9OX05VTExBQkxFID0gMDtcbmNvbnN0IExJTkVBUl9DT01CSU5BVElPTl9DT05TVEFOVCA9IDE7XG5jb25zdCBMSU5FQVJfQ09NQklOQVRJT05fVkFSSUFCTEUgPSAyO1xuXG5leHBvcnQgY2xhc3MgcjFjc0NvbnN0cmFpbnRQcm9jZXNzb3Ige1xuICAgIGNvbnN0cnVjdG9yKEZyLCBmbkdldENvbnN0YW50Q29uc3RyYWludCwgZm5HZXRBZGRpdGlvbkNvbnN0cmFpbnQsIGZuR2V0TXVsdGlwbGljYXRpb25Db25zdHJhaW50LCBsb2dnZXIpIHtcbiAgICAgICAgdGhpcy5GciA9IEZyO1xuICAgICAgICB0aGlzLmxvZ2dlciA9IGxvZ2dlcjtcbiAgICAgICAgdGhpcy5mbkdldEFkZGl0aW9uQ29uc3RyYWludCA9IGZuR2V0QWRkaXRpb25Db25zdHJhaW50O1xuICAgICAgICB0aGlzLmZuR2V0TXVsdGlwbGljYXRpb25Db25zdHJhaW50ID0gZm5HZXRNdWx0aXBsaWNhdGlvbkNvbnN0cmFpbnQ7XG4gICAgfVxuXG4gICAgcHJvY2Vzc1IxY3NDb25zdHJhaW50KHNldHRpbmdzLCBsY0EsIGxjQiwgbGNDKSB7XG4gICAgICAgIHRoaXMubm9ybWFsaXplTGluZWFyQ29tYmluYXRpb24obGNBKTtcbiAgICAgICAgdGhpcy5ub3JtYWxpemVMaW5lYXJDb21iaW5hdGlvbihsY0IpO1xuICAgICAgICB0aGlzLm5vcm1hbGl6ZUxpbmVhckNvbWJpbmF0aW9uKGxjQyk7XG5cbiAgICAgICAgY29uc3QgbGN0QSA9IHRoaXMuZ2V0TGluZWFyQ29tYmluYXRpb25UeXBlKGxjQSk7XG4gICAgICAgIGNvbnN0IGxjdEIgPSB0aGlzLmdldExpbmVhckNvbWJpbmF0aW9uVHlwZShsY0IpO1xuXG4gICAgICAgIGlmICgobGN0QSA9PT0gTElORUFSX0NPTUJJTkFUSU9OX05VTExBQkxFKSB8fCAobGN0QiA9PT0gTElORUFSX0NPTUJJTkFUSU9OX05VTExBQkxFKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHJvY2Vzc1IxY3NBZGRpdGlvbkNvbnN0cmFpbnQoc2V0dGluZ3MsIGxjQyk7XG4gICAgICAgIH0gZWxzZSBpZiAobGN0QSA9PT0gTElORUFSX0NPTUJJTkFUSU9OX0NPTlNUQU5UKSB7XG4gICAgICAgICAgICBjb25zdCBsY0NDID0gdGhpcy5qb2luTGluZWFyQ29tYmluYXRpb25zKGxjQiwgbGNDLCBsY0FbMF0pO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHJvY2Vzc1IxY3NBZGRpdGlvbkNvbnN0cmFpbnQoc2V0dGluZ3MsIGxjQ0MpO1xuICAgICAgICB9IGVsc2UgaWYgKGxjdEIgPT09IExJTkVBUl9DT01CSU5BVElPTl9DT05TVEFOVCkge1xuICAgICAgICAgICAgY29uc3QgbGNDQyA9IHRoaXMuam9pbkxpbmVhckNvbWJpbmF0aW9ucyhsY0EsIGxjQywgbGNCWzBdKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnByb2Nlc3NSMWNzQWRkaXRpb25Db25zdHJhaW50KHNldHRpbmdzLCBsY0NDKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnByb2Nlc3NSMWNzTXVsdGlwbGljYXRpb25Db25zdHJhaW50KHNldHRpbmdzLCBsY0EsIGxjQiwgbGNDKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGdldExpbmVhckNvbWJpbmF0aW9uVHlwZShsaW5Db20pIHtcbiAgICAgICAgLy8gbGV0IGsgPSB0aGlzLkZyLnplcm87XG4gICAgICAgIC8vXG4gICAgICAgIC8vIGNvbnN0IHNpZ25hbElkcyA9IE9iamVjdC5rZXlzKGxpbkNvbSk7XG4gICAgICAgIC8vIGZvciAobGV0IGkgPSAwOyBpIDwgc2lnbmFsSWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIC8vICAgICBpZiAoc2lnbmFsSWRzW2ldID09PSBcIjBcIikge1xuICAgICAgICAvLyAgICAgICAgIGsgPSB0aGlzLkZyLmFkZChrLCBsaW5Db21bc2lnbmFsSWRzW2ldXSk7XG4gICAgICAgIC8vICAgICB9IGVsc2Uge1xuICAgICAgICAvLyAgICAgICAgIHJldHVybiBMSU5FQVJfQ09NQklOQVRJT05fVkFSSUFCTEU7XG4gICAgICAgIC8vICAgICB9XG4gICAgICAgIC8vIH1cbiAgICAgICAgLy9cbiAgICAgICAgLy8gaWYgKCF0aGlzLkZyLmVxKGssIHRoaXMuRnIuemVybykpIHJldHVybiBMSU5FQVJfQ09NQklOQVRJT05fQ09OU1RBTlQ7XG4gICAgICAgIC8vXG4gICAgICAgIC8vIHJldHVybiBMSU5FQVJfQ09NQklOQVRJT05fTlVMTEFCTEU7XG5cbiAgICAgICAgbGV0IGsgPSB0aGlzLkZyLnplcm87XG4gICAgICAgIGxldCBuID0gMDtcbiAgICAgICAgY29uc3Qgc3MgPSBPYmplY3Qua2V5cyhsaW5Db20pO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAobGluQ29tW3NzW2ldXSA9PSAwbikge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBsaW5Db21bc3NbaV1dO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChzc1tpXSA9PSAwKSB7XG4gICAgICAgICAgICAgICAgayA9IHRoaXMuRnIuYWRkKGssIGxpbkNvbVtzc1tpXV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBuKys7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG4gPiAwKSByZXR1cm4gTElORUFSX0NPTUJJTkFUSU9OX1ZBUklBQkxFO1xuICAgICAgICBpZiAoIXRoaXMuRnIuaXNaZXJvKGspKSByZXR1cm4gTElORUFSX0NPTUJJTkFUSU9OX0NPTlNUQU5UO1xuICAgICAgICByZXR1cm4gTElORUFSX0NPTUJJTkFUSU9OX05VTExBQkxFO1xuICAgIH1cblxuICAgIG5vcm1hbGl6ZUxpbmVhckNvbWJpbmF0aW9uKGxpbkNvbSkge1xuICAgICAgICBjb25zdCBzaWduYWxJZHMgPSBPYmplY3Qua2V5cyhsaW5Db20pO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNpZ25hbElkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHRoaXMuRnIuaXNaZXJvKGxpbkNvbVtzaWduYWxJZHNbaV1dKSkgZGVsZXRlIGxpbkNvbVtzaWduYWxJZHNbaV1dO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGxpbkNvbTtcbiAgICB9XG5cbiAgICBqb2luTGluZWFyQ29tYmluYXRpb25zKGxpbkNvbTEsIGxpbkNvbTIsIGspIHtcbiAgICAgICAgY29uc3QgcmVzID0ge307XG5cbiAgICAgICAgLy8gZm9yIChsZXQgcyBpbiBsaW5Db20xKSB7XG4gICAgICAgIC8vICAgICBjb25zdCB2YWwgPSB0aGlzLkZyLm11bChrLCBsaW5Db20xW3NdKTtcbiAgICAgICAgLy8gICAgIHJlc1tzXSA9ICEocyBpbiByZXMpID8gdmFsIDogdGhpcy5Gci5hZGQodmFsLCByZXNbc10pO1xuICAgICAgICAvLyB9XG4gICAgICAgIC8vXG4gICAgICAgIC8vIGZvciAobGV0IHMgaW4gbGluQ29tMikge1xuICAgICAgICAvLyAgICAgY29uc3QgdmFsID0gdGhpcy5Gci5tdWwoaywgbGluQ29tMltzXSk7XG4gICAgICAgIC8vICAgICByZXNbc10gPSAhKHMgaW4gcmVzKSA/IHZhbCA6IHRoaXMuRnIuYWRkKHZhbCwgcmVzW3NdKTtcbiAgICAgICAgLy8gfVxuXG4gICAgICAgIGZvciAobGV0IHMgaW4gbGluQ29tMSkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiByZXNbc10gPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgICAgIHJlc1tzXSA9IHRoaXMuRnIubXVsKGssIGxpbkNvbTFbc10pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXNbc10gPSB0aGlzLkZyLmFkZChyZXNbc10sIHRoaXMuRnIubXVsKGssIGxpbkNvbTFbc10pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAobGV0IHMgaW4gbGluQ29tMikge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiByZXNbc10gPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgICAgIHJlc1tzXSA9IGxpbkNvbTJbc107XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc1tzXSA9IHRoaXMuRnIuYWRkKHJlc1tzXSwgbGluQ29tMltzXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5ub3JtYWxpemVMaW5lYXJDb21iaW5hdGlvbihyZXMpO1xuICAgIH1cblxuICAgIHJlZHVjZUNvZWZzKHNldHRpbmdzLCBjb25zdHJhaW50c0FyciwgYWRkaXRpb25zQXJyLCBsaW5Db20sIG1heEMpIHtcbiAgICAgICAgY29uc3QgcmVzID0ge1xuICAgICAgICAgICAgazogdGhpcy5Gci56ZXJvLFxuICAgICAgICAgICAgc2lnbmFsczogW10sXG4gICAgICAgICAgICBjb2VmczogW11cbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgY3MgPSBbXTtcblxuICAgICAgICBmb3IgKGxldCBzaWduYWxJZCBpbiBsaW5Db20pIHtcbiAgICAgICAgICAgIGlmIChzaWduYWxJZCA9PSAwKSB7XG4gICAgICAgICAgICAgICAgcmVzLmsgPSB0aGlzLkZyLmFkZChyZXMuaywgbGluQ29tW3NpZ25hbElkXSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGxpbkNvbVtzaWduYWxJZF0gIT0gMG4pIHtcbiAgICAgICAgICAgICAgICBjcy5wdXNoKFtOdW1iZXIoc2lnbmFsSWQpLCBsaW5Db21bc2lnbmFsSWRdXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB3aGlsZSAoY3MubGVuZ3RoID4gbWF4Qykge1xuICAgICAgICAgICAgY29uc3QgYzEgPSBjcy5zaGlmdCgpO1xuICAgICAgICAgICAgY29uc3QgYzIgPSBjcy5zaGlmdCgpO1xuICAgICAgICAgICAgY29uc3Qgc28gPSBzZXR0aW5ncy5uVmFycysrO1xuXG4gICAgICAgICAgICBjb25zdCBjb25zdHJhaW50cyA9IHRoaXMuZm5HZXRBZGRpdGlvbkNvbnN0cmFpbnQoXG4gICAgICAgICAgICAgICAgYzFbMF0sIGMyWzBdLCBzbyxcbiAgICAgICAgICAgICAgICB0aGlzLkZyLm5lZyhjMVsxXSksIHRoaXMuRnIubmVnKGMyWzFdKSwgdGhpcy5Gci56ZXJvLCB0aGlzLkZyLm9uZSwgdGhpcy5Gci56ZXJvKTtcblxuICAgICAgICAgICAgY29uc3RyYWludHNBcnIucHVzaChjb25zdHJhaW50cyk7XG4gICAgICAgICAgICBhZGRpdGlvbnNBcnIucHVzaChbYzFbMF0sIGMyWzBdLCBjMVsxXSwgYzJbMV1dKTtcblxuICAgICAgICAgICAgY3MucHVzaChbc28sIHRoaXMuRnIub25lXSk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICByZXMuc2lnbmFsc1tpXSA9IGNzW2ldWzBdO1xuICAgICAgICAgICAgcmVzLmNvZWZzW2ldID0gY3NbaV1bMV07XG4gICAgICAgIH1cblxuICAgICAgICB3aGlsZSAocmVzLmNvZWZzLmxlbmd0aCA8IG1heEMpIHtcbiAgICAgICAgICAgIHJlcy5zaWduYWxzLnB1c2goMCk7XG4gICAgICAgICAgICByZXMuY29lZnMucHVzaCh0aGlzLkZyLnplcm8pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICBwcm9jZXNzUjFjc0FkZGl0aW9uQ29uc3RyYWludChzZXR0aW5ncywgbGluQ29tKSB7XG4gICAgICAgIGNvbnN0IGNvbnN0cmFpbnRzQXJyID0gW107XG4gICAgICAgIGNvbnN0IGFkZGl0aW9uc0FyciA9IFtdO1xuXG4gICAgICAgIGNvbnN0IEMgPSB0aGlzLnJlZHVjZUNvZWZzKHNldHRpbmdzLCBjb25zdHJhaW50c0FyciwgYWRkaXRpb25zQXJyLCBsaW5Db20sIDMpO1xuXG4gICAgICAgIGNvbnN0IGNvbnN0cmFpbnRzID0gdGhpcy5mbkdldEFkZGl0aW9uQ29uc3RyYWludChcbiAgICAgICAgICAgIEMuc2lnbmFsc1swXSwgQy5zaWduYWxzWzFdLCBDLnNpZ25hbHNbMl0sXG4gICAgICAgICAgICBDLmNvZWZzWzBdLCBDLmNvZWZzWzFdLCB0aGlzLkZyLnplcm8sIEMuY29lZnNbMl0sIEMuayk7XG5cbiAgICAgICAgY29uc3RyYWludHNBcnIucHVzaChjb25zdHJhaW50cyk7XG5cbiAgICAgICAgcmV0dXJuIFtjb25zdHJhaW50c0FyciwgYWRkaXRpb25zQXJyXTtcbiAgICB9XG5cbiAgICBwcm9jZXNzUjFjc011bHRpcGxpY2F0aW9uQ29uc3RyYWludChzZXR0aW5ncywgbGNBLCBsY0IsIGxjQykge1xuICAgICAgICBjb25zdCBjb25zdHJhaW50c0FyciA9IFtdO1xuICAgICAgICBjb25zdCBhZGRpdGlvbnNBcnIgPSBbXTtcblxuICAgICAgICBjb25zdCBBID0gdGhpcy5yZWR1Y2VDb2VmcyhzZXR0aW5ncywgY29uc3RyYWludHNBcnIsIGFkZGl0aW9uc0FyciwgbGNBLCAxKTtcbiAgICAgICAgY29uc3QgQiA9IHRoaXMucmVkdWNlQ29lZnMoc2V0dGluZ3MsIGNvbnN0cmFpbnRzQXJyLCBhZGRpdGlvbnNBcnIsIGxjQiwgMSk7XG4gICAgICAgIGNvbnN0IEMgPSB0aGlzLnJlZHVjZUNvZWZzKHNldHRpbmdzLCBjb25zdHJhaW50c0FyciwgYWRkaXRpb25zQXJyLCBsY0MsIDEpO1xuXG4gICAgICAgIGNvbnN0IGNvbnN0cmFpbnRzID0gdGhpcy5mbkdldE11bHRpcGxpY2F0aW9uQ29uc3RyYWludChcbiAgICAgICAgICAgIEEuc2lnbmFsc1swXSwgQi5zaWduYWxzWzBdLCBDLnNpZ25hbHNbMF0sXG4gICAgICAgICAgICB0aGlzLkZyLm11bChBLmNvZWZzWzBdLCBCLmspLFxuICAgICAgICAgICAgdGhpcy5Gci5tdWwoQS5rLCBCLmNvZWZzWzBdKSxcbiAgICAgICAgICAgIHRoaXMuRnIubXVsKEEuY29lZnNbMF0sIEIuY29lZnNbMF0pLFxuICAgICAgICAgICAgdGhpcy5Gci5uZWcoQy5jb2Vmc1swXSksXG4gICAgICAgICAgICB0aGlzLkZyLnN1Yih0aGlzLkZyLm11bChBLmssIEIuayksIEMuaykpO1xuXG4gICAgICAgIGNvbnN0cmFpbnRzQXJyLnB1c2goY29uc3RyYWludHMpO1xuXG4gICAgICAgIHJldHVybiBbY29uc3RyYWludHNBcnIsIGFkZGl0aW9uc0Fycl07XG4gICAgfVxufSIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMjIgaWRlbjMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya2pzLlxuXG4gICAgc25hcmtqcyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuICAgIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGVcbiAgICBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbilcbiAgICBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJranMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAgICBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3JcbiAgICBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhbG9uZyB3aXRoXG4gICAgc25hcmtqcy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbi8vIENQb2x5bm9taWFsIGlzIGEgQ29tYmluZWQgUG9seW5vbWlhbCBvZiB0aGUgdHlwZSA6XG4vLyBDUG9seW5vbWlhbChYKSA6PSBQXzAoWF5uKSArIFjCt1BfMShYXm4pICsgLi4uICsgWF57bi0xfcK3UF97bi0xfShYXm4pXG4vLyBXZSBjYW4gdXNlIHRoaXMgY2xhc3MgdG8gYXZvaWQgdGhlIGFsbG9jYXRpb24gb2YgYSBiaWcgbWVtb3J5IGJ1ZmZlclxuLy8gZm9yIHRoZSBjb2VmZmljaWVudHMgYmVjYXVzZSBpbiBzb21lIGNhc2VzIGEgYmlnIG51bWJlciBvZiB0aGUgY29lZmZpY2llbnRzIGFyZSB6ZXJvXG5cbmltcG9ydCB7QmlnQnVmZmVyfSBmcm9tIFwiZmZqYXZhc2NyaXB0XCI7XG5pbXBvcnQge2xvZzJ9IGZyb20gXCIuLi9taXNjLmpzXCI7XG5pbXBvcnQge1BvbHlub21pYWx9IGZyb20gXCIuL3BvbHlub21pYWwuanNcIjtcblxuZXhwb3J0IGNsYXNzIENQb2x5bm9taWFsIHtcbiAgICBjb25zdHJ1Y3RvcihuLCBjdXJ2ZSwgbG9nZ2VyKSB7XG4gICAgICAgIHRoaXMubiA9IG47XG4gICAgICAgIHRoaXMucG9seW5vbWlhbHMgPSBBcnJheShuKS5maWxsKHVuZGVmaW5lZCk7XG4gICAgICAgIHRoaXMuY3VydmUgPSBjdXJ2ZTtcbiAgICAgICAgdGhpcy5GciA9IGN1cnZlLkZyO1xuICAgICAgICB0aGlzLkcxID0gY3VydmUuRzE7XG4gICAgICAgIHRoaXMubG9nZ2VyID0gbG9nZ2VyO1xuICAgIH1cblxuICAgIGFkZFBvbHlub21pYWwocG9zaXRpb24sIHBvbHlub21pYWwpIHtcbiAgICAgICAgaWYgKHBvc2l0aW9uID4gdGhpcy5uIC0gMSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ1BvbHlub21pYWw6YWRkUG9seW5vbWlhbCwgY2Fubm90IGFkZCBhIHBvbHlub21pYWwgdG8gYSBwb3NpdGlvbiBncmVhdGVyIHRoYW4gbi0xXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5wb2x5bm9taWFsc1twb3NpdGlvbl0gPSBwb2x5bm9taWFsO1xuICAgIH1cblxuICAgIGRlZ3JlZSgpIHtcbiAgICAgICAgbGV0IGRlZ3JlZXMgPSB0aGlzLnBvbHlub21pYWxzLm1hcChcbiAgICAgICAgICAgIChwb2x5bm9taWFsLCBpbmRleCkgPT4gcG9seW5vbWlhbCA9PT0gdW5kZWZpbmVkID8gMCA6IHBvbHlub21pYWwuZGVncmVlKCkgKiB0aGlzLm4gKyBpbmRleCk7XG4gICAgICAgIHJldHVybiBNYXRoLm1heCguLi5kZWdyZWVzKTtcbiAgICB9XG5cbiAgICBnZXRQb2x5bm9taWFsKCkge1xuICAgICAgICBsZXQgZGVncmVlcyA9IHRoaXMucG9seW5vbWlhbHMubWFwKHBvbHlub21pYWwgPT4gcG9seW5vbWlhbCA9PT0gdW5kZWZpbmVkID8gMCA6IHBvbHlub21pYWwuZGVncmVlKCkpO1xuICAgICAgICBjb25zdCBtYXhEZWdyZWUgPSB0aGlzLmRlZ3JlZSgpO1xuICAgICAgICBjb25zdCBsZW5ndGhCdWZmZXIgPSAyICoqIChsb2cyKG1heERlZ3JlZSAtIDEpICsgMSk7XG4gICAgICAgIGNvbnN0IHNGciA9IHRoaXMuRnIubjg7XG5cbiAgICAgICAgbGV0IHBvbHlub21pYWwgPSBuZXcgUG9seW5vbWlhbChuZXcgQmlnQnVmZmVyKGxlbmd0aEJ1ZmZlciAqIHNGciksIHRoaXMuY3VydmUsIHRoaXMubG9nZ2VyKTtcblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG1heERlZ3JlZTsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBpX244ID0gaSAqIHNGcjtcbiAgICAgICAgICAgIGNvbnN0IGlfc0ZyID0gaV9uOCAqIHRoaXMubjtcblxuICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB0aGlzLm47IGorKykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnBvbHlub21pYWxzW2pdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkgPD0gZGVncmVlc1tqXSkgcG9seW5vbWlhbC5jb2VmLnNldCh0aGlzLnBvbHlub21pYWxzW2pdLmNvZWYuc2xpY2UoaV9uOCwgaV9uOCArIHNGciksIGlfc0ZyICsgaiAqIHNGcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHBvbHlub21pYWw7XG4gICAgfVxuXG4gICAgYXN5bmMgbXVsdGlFeHBvbmVudGlhdGlvbihQVGF1LCBuYW1lKSB7XG4gICAgICAgIGxldCBwb2x5bm9taWFsID0gdGhpcy5nZXRQb2x5bm9taWFsKCk7XG4gICAgICAgIGNvbnN0IG4gPSBwb2x5bm9taWFsLmNvZWYuYnl0ZUxlbmd0aCAvIHRoaXMuRnIubjg7XG4gICAgICAgIGNvbnN0IFBUYXVOID0gUFRhdS5zbGljZSgwLCBuICogdGhpcy5HMS5GLm44ICogMik7XG4gICAgICAgIGNvbnN0IGJtID0gYXdhaXQgdGhpcy5Gci5iYXRjaEZyb21Nb250Z29tZXJ5KHBvbHlub21pYWwuY29lZik7XG4gICAgICAgIGxldCByZXMgPSBhd2FpdCB0aGlzLkcxLm11bHRpRXhwQWZmaW5lKFBUYXVOLCBibSwgdGhpcy5sb2dnZXIsIG5hbWUpO1xuICAgICAgICByZXMgPSB0aGlzLkcxLnRvQWZmaW5lKHJlcyk7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxufSIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMjIgaWRlbjMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya2pzLlxuXG4gICAgc25hcmtqcyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuICAgIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGVcbiAgICBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbilcbiAgICBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJranMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAgICBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3JcbiAgICBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhbG9uZyB3aXRoXG4gICAgc25hcmtqcy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbmltcG9ydCB7cmVhZFIxY3NGZH0gZnJvbSBcInIxY3NmaWxlXCI7XG5pbXBvcnQgKiBhcyB1dGlscyBmcm9tIFwiLi9wb3dlcnNvZnRhdV91dGlscy5qc1wiO1xuaW1wb3J0IHtjcmVhdGVCaW5GaWxlLCBlbmRXcml0ZVNlY3Rpb24sIHJlYWRCaW5GaWxlLCBzdGFydFdyaXRlU2VjdGlvbiwgd3JpdGVCaWdJbnQsfSBmcm9tIFwiQGlkZW4zL2JpbmZpbGV1dGlsc1wiO1xuaW1wb3J0IHtsb2cyfSBmcm9tIFwiLi9taXNjLmpzXCI7XG5pbXBvcnQge0JpZ0J1ZmZlciwgU2NhbGFyfSBmcm9tIFwiZmZqYXZhc2NyaXB0XCI7XG5pbXBvcnQgQmlnQXJyYXkgZnJvbSBcIi4vYmlnYXJyYXkuanNcIjtcbmltcG9ydCB7XG4gICAgWktFWV9GRl9IRUFERVJfU0VDVElPTixcbiAgICBaS0VZX0ZGX0FERElUSU9OU19TRUNUSU9OLFxuICAgIFpLRVlfRkZfQV9NQVBfU0VDVElPTixcbiAgICBaS0VZX0ZGX0JfTUFQX1NFQ1RJT04sXG4gICAgWktFWV9GRl9DX01BUF9TRUNUSU9OLFxuICAgIFpLRVlfRkZfUUxfU0VDVElPTixcbiAgICBaS0VZX0ZGX1FSX1NFQ1RJT04sXG4gICAgWktFWV9GRl9RTV9TRUNUSU9OLFxuICAgIFpLRVlfRkZfUU9fU0VDVElPTixcbiAgICBaS0VZX0ZGX1FDX1NFQ1RJT04sXG4gICAgWktFWV9GRl9TSUdNQTFfU0VDVElPTixcbiAgICBaS0VZX0ZGX1NJR01BMl9TRUNUSU9OLFxuICAgIFpLRVlfRkZfU0lHTUEzX1NFQ1RJT04sXG4gICAgWktFWV9GRl9MQUdSQU5HRV9TRUNUSU9OLFxuICAgIFpLRVlfRkZfUFRBVV9TRUNUSU9OLFxuICAgIEZGX1RfUE9MX0RFR19NSU4sXG4gICAgWktFWV9GRl9OU0VDVElPTlMsXG4gICAgWktFWV9GRl9DMF9TRUNUSU9OLFxufSBmcm9tIFwiLi9mZmxvbmtfY29uc3RhbnRzLmpzXCI7XG5pbXBvcnQge0ZGTE9OS19QUk9UT0NPTF9JRCwgSEVBREVSX1pLRVlfU0VDVElPTn0gZnJvbSBcIi4vemtleV9jb25zdGFudHMuanNcIjtcbmltcG9ydCB7XG4gICAgZ2V0RkZsb25rQWRkaXRpb25Db25zdHJhaW50LFxuICAgIGdldEZGbG9ua0NvbnN0YW50Q29uc3RyYWludCxcbiAgICBnZXRGRmxvbmtNdWx0aXBsaWNhdGlvbkNvbnN0cmFpbnRcbn0gZnJvbSBcIi4vcGxvbmtfZXF1YXRpb24uanNcIjtcbmltcG9ydCB7cjFjc0NvbnN0cmFpbnRQcm9jZXNzb3J9IGZyb20gXCIuL3IxY3NfY29uc3RyYWludF9wcm9jZXNzb3IuanNcIjtcbmltcG9ydCB7UG9seW5vbWlhbH0gZnJvbSBcIi4vcG9seW5vbWlhbC9wb2x5bm9taWFsLmpzXCI7XG5pbXBvcnQgKiBhcyBiaW5GaWxlVXRpbHMgZnJvbSBcIkBpZGVuMy9iaW5maWxldXRpbHNcIjtcbmltcG9ydCB7RXZhbHVhdGlvbnN9IGZyb20gXCIuL3BvbHlub21pYWwvZXZhbHVhdGlvbnMuanNcIjtcbmltcG9ydCB7Q1BvbHlub21pYWx9IGZyb20gXCIuL3BvbHlub21pYWwvY3BvbHlub21pYWwuanNcIjtcblxuXG5leHBvcnQgZGVmYXVsdCBhc3luYyBmdW5jdGlvbiBmZmxvbmtTZXR1cChyMWNzRmlsZW5hbWUsIHB0YXVGaWxlbmFtZSwgemtleUZpbGVuYW1lLCBsb2dnZXIpIHtcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIkZGTE9OSyBTRVRVUCBTVEFSVEVEXCIpO1xuXG4gICAgaWYgKGdsb2JhbFRoaXMuZ2MpIGdsb2JhbFRoaXMuZ2MoKTtcblxuICAgIC8vIFJlYWQgUFRhdSBmaWxlXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCI+IFJlYWRpbmcgUFRhdSBmaWxlXCIpO1xuICAgIGNvbnN0IHtmZDogZmRQVGF1LCBzZWN0aW9uczogcFRhdVNlY3Rpb25zfSA9IGF3YWl0IHJlYWRCaW5GaWxlKHB0YXVGaWxlbmFtZSwgXCJwdGF1XCIsIDEsIDEgPDwgMjIsIDEgPDwgMjQpO1xuICAgIGlmICghcFRhdVNlY3Rpb25zWzEyXSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJQb3dlcnMgb2YgVGF1IGlzIG5vdCB3ZWxsIHByZXBhcmVkLiBTZWN0aW9uIDEyIG1pc3NpbmcuXCIpO1xuICAgIH1cblxuICAgIC8vIEdldCBjdXJ2ZSBkZWZpbmVkIGluIFBUYXVcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gR2V0dGluZyBjdXJ2ZSBmcm9tIFBUYXUgc2V0dGluZ3NcIik7XG4gICAgY29uc3Qge2N1cnZlfSA9IGF3YWl0IHV0aWxzLnJlYWRQVGF1SGVhZGVyKGZkUFRhdSwgcFRhdVNlY3Rpb25zKTtcblxuICAgIC8vIFJlYWQgcjFjcyBmaWxlXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCI+IFJlYWRpbmcgcjFjcyBmaWxlXCIpO1xuICAgIGNvbnN0IHtmZDogZmRSMWNzLCBzZWN0aW9uczogc2VjdGlvbnNSMWNzfSA9IGF3YWl0IHJlYWRCaW5GaWxlKHIxY3NGaWxlbmFtZSwgXCJyMWNzXCIsIDEsIDEgPDwgMjIsIDEgPDwgMjQpO1xuICAgIGNvbnN0IHIxY3MgPSBhd2FpdCByZWFkUjFjc0ZkKGZkUjFjcywgc2VjdGlvbnNSMWNzLCB7bG9hZENvbnN0cmFpbnRzOiBmYWxzZSwgbG9hZEN1c3RvbUdhdGVzOiB0cnVlfSk7XG5cbiAgICAvLyBQb3RlbnRpYWwgZXJyb3IgY2hlY2tzXG4gICAgaWYgKHIxY3MucHJpbWUgIT09IGN1cnZlLnIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwicjFjcyBjdXJ2ZSBkb2VzIG5vdCBtYXRjaCBwb3dlcnMgb2YgdGF1IGNlcmVtb255IGN1cnZlXCIpO1xuICAgIH1cblxuICAgIC8vIEluaXRpYWxpemF0aW9uc1xuICAgIGNvbnN0IEZyID0gY3VydmUuRnI7XG5cbiAgICBjb25zdCBzRnIgPSBjdXJ2ZS5Gci5uODtcbiAgICBjb25zdCBzRzEgPSBjdXJ2ZS5HMS5GLm44ICogMjtcbiAgICBjb25zdCBzRzIgPSBjdXJ2ZS5HMi5GLm44ICogMjtcblxuICAgIGxldCBwb2x5bm9taWFscyA9IHt9O1xuICAgIGxldCBldmFsdWF0aW9ucyA9IHt9O1xuICAgIGxldCBQVGF1O1xuXG4gICAgbGV0IHNldHRpbmdzID0ge1xuICAgICAgICBuVmFyczogcjFjcy5uVmFycyxcbiAgICAgICAgblB1YmxpYzogcjFjcy5uT3V0cHV0cyArIHIxY3MublB1YklucHV0c1xuICAgIH07XG5cbiAgICBjb25zdCBwbG9ua0NvbnN0cmFpbnRzID0gbmV3IEJpZ0FycmF5KCk7XG4gICAgbGV0IHBsb25rQWRkaXRpb25zID0gbmV3IEJpZ0FycmF5KCk7XG5cbiAgICAvLyBQcm9jZXNzIGNvbnN0cmFpbnRzIGluc2lkZSByMWNzXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCI+IFByb2Nlc3NpbmcgRkZsb25rIGNvbnN0cmFpbnRzXCIpO1xuICAgIGF3YWl0IGNvbXB1dGVGRkNvbnN0cmFpbnRzKGN1cnZlLkZyLCByMWNzLCBsb2dnZXIpO1xuICAgIGlmIChnbG9iYWxUaGlzLmdjKSBnbG9iYWxUaGlzLmdjKCk7XG5cbiAgICAvLyBBcyB0aGUgdCBwb2x5bm9taWFsIGlzIG4rNSB3ZSBuZWVkIGF0IGxlYXN0IGEgcG93ZXIgb2YgNFxuICAgIC8vVE9ETyBjaGVjayEhISFcbiAgICAvLyBOT1RFIDogcGxvbmtDb25zdHJhaW50cyArIDIgPSAjY29uc3RyYWludHMgKyBibGluZGluZyBjb2VmZmljaWVudHMgZm9yIGVhY2ggd2lyZSBwb2x5bm9taWFsXG4gICAgc2V0dGluZ3MuY2lyUG93ZXIgPSBNYXRoLm1heChGRl9UX1BPTF9ERUdfTUlOLCBsb2cyKChwbG9ua0NvbnN0cmFpbnRzLmxlbmd0aCArIDIpIC0gMSkgKyAxKTtcbiAgICBzZXR0aW5ncy5kb21haW5TaXplID0gMiAqKiBzZXR0aW5ncy5jaXJQb3dlcjtcblxuICAgIGlmIChwVGF1U2VjdGlvbnNbMl1bMF0uc2l6ZSA8IChzZXR0aW5ncy5kb21haW5TaXplICogOSArIDE4KSAqIHNHMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJQb3dlcnMgb2YgVGF1IGlzIG5vdCBiaWcgZW5vdWdoIGZvciB0aGlzIGNpcmN1aXQgc2l6ZS4gU2VjdGlvbiAyIHRvbyBzbWFsbC5cIik7XG4gICAgfVxuICAgIGlmIChwVGF1U2VjdGlvbnNbM11bMF0uc2l6ZSA8IHNHMikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJQb3dlcnMgb2YgVGF1IGlzIG5vdCB3ZWxsIHByZXBhcmVkLiBTZWN0aW9uIDMgdG9vIHNtYWxsLlwiKTtcbiAgICB9XG5cbiAgICBpZiAobG9nZ2VyKSB7XG4gICAgICAgIGxvZ2dlci5pbmZvKFwiLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgbG9nZ2VyLmluZm8oXCIgIEZGTE9OSyBTRVRVUCBTRVRUSU5HU1wiKTtcbiAgICAgICAgbG9nZ2VyLmluZm8oYCAgQ3VydmU6ICAgICAgICAgJHtjdXJ2ZS5uYW1lfWApO1xuICAgICAgICBsb2dnZXIuaW5mbyhgICBDaXJjdWl0IHBvd2VyOiAke3NldHRpbmdzLmNpclBvd2VyfWApO1xuICAgICAgICBsb2dnZXIuaW5mbyhgICBEb21haW4gc2l6ZTogICAke3NldHRpbmdzLmRvbWFpblNpemV9YCk7XG4gICAgICAgIGxvZ2dlci5pbmZvKGAgIFZhcnM6ICAgICAgICAgICR7c2V0dGluZ3MublZhcnN9YCk7XG4gICAgICAgIGxvZ2dlci5pbmZvKGAgIFB1YmxpYyB2YXJzOiAgICR7c2V0dGluZ3MublB1YmxpY31gKTtcbiAgICAgICAgbG9nZ2VyLmluZm8oYCAgQ29uc3RyYWludHM6ICAgJHtwbG9ua0NvbnN0cmFpbnRzLmxlbmd0aH1gKTtcbiAgICAgICAgbG9nZ2VyLmluZm8oYCAgQWRkaXRpb25zOiAgICAgJHtwbG9ua0FkZGl0aW9ucy5sZW5ndGh9YCk7XG4gICAgICAgIGxvZ2dlci5pbmZvKFwiLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVwiKTtcbiAgICB9XG5cbiAgICAvLyBDb21wdXRlIGsxIGFuZCBrMiB0byBiZSB1c2VkIGluIHRoZSBwZXJtdXRhdGlvbiBjaGVja3NcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gY29tcHV0aW5nIGsxIGFuZCBrMlwiKTtcbiAgICBjb25zdCBbazEsIGsyXSA9IGNvbXB1dGVLMUsyKCk7XG5cbiAgICAvLyBDb21wdXRlIG9tZWdhIDMgKHczKSBhbmQgb21lZ2EgNCAodzQpIHRvIGJlIHVzZWQgaW4gdGhlIHByb3ZlciBhbmQgdGhlIHZlcmlmaWVyXG4gICAgLy8gdzNeMyA9IDEgYW5kICB3NF40ID0gMVxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBjb21wdXRpbmcgdzNcIik7XG4gICAgY29uc3QgdzMgPSBjb21wdXRlVzMoKTtcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gY29tcHV0aW5nIHc0XCIpO1xuICAgIGNvbnN0IHc0ID0gY29tcHV0ZVc0KCk7XG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCI+IGNvbXB1dGluZyB3OFwiKTtcbiAgICBjb25zdCB3OCA9IGNvbXB1dGVXOCgpO1xuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBjb21wdXRpbmcgd3JcIik7XG4gICAgY29uc3Qgd3IgPSBnZXRPbWVnYUN1YmljUm9vdChzZXR0aW5ncy5jaXJQb3dlciwgY3VydmUuRnIpO1xuXG4gICAgLy8gV3JpdGUgb3V0cHV0IHprZXkgZmlsZVxuICAgIGF3YWl0IHdyaXRlWmtleUZpbGUoKTtcblxuICAgIGF3YWl0IGZkUjFjcy5jbG9zZSgpO1xuICAgIGF3YWl0IGZkUFRhdS5jbG9zZSgpO1xuXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCJGRkxPTksgU0VUVVAgRklOSVNIRURcIik7XG5cbiAgICByZXR1cm4gMDtcblxuICAgIGFzeW5jIGZ1bmN0aW9uIGNvbXB1dGVGRkNvbnN0cmFpbnRzKEZyLCByMWNzLCBsb2dnZXIpIHtcbiAgICAgICAgLy8gQWRkIHB1YmxpYyBpbnB1dHMgYW5kIG91dHB1dHNcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZXR0aW5ncy5uUHVibGljOyBpKyspIHtcbiAgICAgICAgICAgIHBsb25rQ29uc3RyYWludHMucHVzaChnZXRGRmxvbmtDb25zdGFudENvbnN0cmFpbnQoaSArIDEsIEZyKSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgYWxsIGNvbnN0cmFpbnRzIGZyb20gcjFjcyBmaWxlXG4gICAgICAgIGNvbnN0IHIxY3NQcm9jZXNzb3IgPSBuZXcgcjFjc0NvbnN0cmFpbnRQcm9jZXNzb3IoRnIsIGdldEZGbG9ua0NvbnN0YW50Q29uc3RyYWludCwgZ2V0RkZsb25rQWRkaXRpb25Db25zdHJhaW50LCBnZXRGRmxvbmtNdWx0aXBsaWNhdGlvbkNvbnN0cmFpbnQsIGxvZ2dlcik7XG5cbiAgICAgICAgY29uc3QgYlIxY3MgPSBhd2FpdCBiaW5GaWxlVXRpbHMucmVhZFNlY3Rpb24oZmRSMWNzLCBzZWN0aW9uc1IxY3MsIDIpO1xuICAgICAgICBsZXQgYlIxY3NQb3MgPSAwO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHIxY3MubkNvbnN0cmFpbnRzOyBpKyspIHtcbiAgICAgICAgICAgIGlmICgobG9nZ2VyKSAmJiAoaSAhPT0gMCkgJiYgKGkgJSA1MDAwMDAgPT09IDApKSB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYCAgICBwcm9jZXNzaW5nIHIxY3MgY29uc3RyYWludHMgJHtpfS8ke3IxY3MubkNvbnN0cmFpbnRzfWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgW2NvbnN0cmFpbnRzLCBhZGRpdGlvbnNdID0gcjFjc1Byb2Nlc3Nvci5wcm9jZXNzUjFjc0NvbnN0cmFpbnQoc2V0dGluZ3MsIC4uLnJlYWRDb25zdHJhaW50KCkpO1xuXG4gICAgICAgICAgICBwbG9ua0NvbnN0cmFpbnRzLnB1c2goLi4uY29uc3RyYWludHMpO1xuICAgICAgICAgICAgcGxvbmtBZGRpdGlvbnMucHVzaCguLi5hZGRpdGlvbnMpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gcmVhZENvbnN0cmFpbnQoKSB7XG4gICAgICAgICAgICBjb25zdCBjID0gW107XG4gICAgICAgICAgICBjWzBdID0gcmVhZExDKCk7XG4gICAgICAgICAgICBjWzFdID0gcmVhZExDKCk7XG4gICAgICAgICAgICBjWzJdID0gcmVhZExDKCk7XG4gICAgICAgICAgICByZXR1cm4gYztcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIHJlYWRMQygpIHtcbiAgICAgICAgICAgIGNvbnN0IGxjID0ge307XG5cbiAgICAgICAgICAgIGNvbnN0IGJ1ZmZVTDMyID0gYlIxY3Muc2xpY2UoYlIxY3NQb3MsIGJSMWNzUG9zICsgNCk7XG4gICAgICAgICAgICBiUjFjc1BvcyArPSA0O1xuICAgICAgICAgICAgY29uc3QgYnVmZlVMMzJWID0gbmV3IERhdGFWaWV3KGJ1ZmZVTDMyLmJ1ZmZlcik7XG4gICAgICAgICAgICBjb25zdCBuSWR4ID0gYnVmZlVMMzJWLmdldFVpbnQzMigwLCB0cnVlKTtcblxuICAgICAgICAgICAgY29uc3QgYnVmZiA9IGJSMWNzLnNsaWNlKGJSMWNzUG9zLCBiUjFjc1BvcyArICg0ICsgcjFjcy5uOCkgKiBuSWR4KTtcbiAgICAgICAgICAgIGJSMWNzUG9zICs9ICg0ICsgcjFjcy5uOCkgKiBuSWR4O1xuICAgICAgICAgICAgY29uc3QgYnVmZlYgPSBuZXcgRGF0YVZpZXcoYnVmZi5idWZmZXIpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuSWR4OyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBpZHggPSBidWZmVi5nZXRVaW50MzIoaSAqICg0ICsgcjFjcy5uOCksIHRydWUpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHZhbCA9IHIxY3MuRi5mcm9tUnByTEUoYnVmZiwgaSAqICg0ICsgcjFjcy5uOCkgKyA0KTtcbiAgICAgICAgICAgICAgICBsY1tpZHhdID0gdmFsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGxjO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgYXN5bmMgZnVuY3Rpb24gd3JpdGVaa2V5RmlsZSgpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCI+IFdyaXRpbmcgdGhlIHprZXkgZmlsZVwiKTtcbiAgICAgICAgY29uc3QgZmRaS2V5ID0gYXdhaXQgY3JlYXRlQmluRmlsZSh6a2V5RmlsZW5hbWUsIFwiemtleVwiLCAxLCBaS0VZX0ZGX05TRUNUSU9OUywgMSA8PCAyMiwgMSA8PCAyNCk7XG5cbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oYMK3wrfCtyBXcml0aW5nIFNlY3Rpb24gJHtIRUFERVJfWktFWV9TRUNUSU9OfS4gWmtleSBIZWFkZXJgKTtcbiAgICAgICAgYXdhaXQgd3JpdGVaa2V5SGVhZGVyKGZkWktleSk7XG5cbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oYMK3wrfCtyBXcml0aW5nIFNlY3Rpb24gJHtaS0VZX0ZGX0FERElUSU9OU19TRUNUSU9OfS4gQWRkaXRpb25zYCk7XG4gICAgICAgIGF3YWl0IHdyaXRlQWRkaXRpb25zKGZkWktleSk7XG4gICAgICAgIGlmIChnbG9iYWxUaGlzLmdjKSBnbG9iYWxUaGlzLmdjKCk7XG5cbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oYMK3wrfCtyBXcml0aW5nIFNlY3Rpb24gJHtaS0VZX0ZGX0FfTUFQX1NFQ1RJT059LiBBIE1hcGApO1xuICAgICAgICBhd2FpdCB3cml0ZVdpdG5lc3NNYXAoZmRaS2V5LCBaS0VZX0ZGX0FfTUFQX1NFQ1RJT04sIDAsIFwiQSBtYXBcIik7XG4gICAgICAgIGlmIChnbG9iYWxUaGlzLmdjKSBnbG9iYWxUaGlzLmdjKCk7XG5cbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oYMK3wrfCtyBXcml0aW5nIFNlY3Rpb24gJHtaS0VZX0ZGX0JfTUFQX1NFQ1RJT059LiBCIE1hcGApO1xuICAgICAgICBhd2FpdCB3cml0ZVdpdG5lc3NNYXAoZmRaS2V5LCBaS0VZX0ZGX0JfTUFQX1NFQ1RJT04sIDEsIFwiQiBtYXBcIik7XG4gICAgICAgIGlmIChnbG9iYWxUaGlzLmdjKSBnbG9iYWxUaGlzLmdjKCk7XG5cbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oYMK3wrfCtyBXcml0aW5nIFNlY3Rpb24gJHtaS0VZX0ZGX0NfTUFQX1NFQ1RJT059LiBDIE1hcGApO1xuICAgICAgICBhd2FpdCB3cml0ZVdpdG5lc3NNYXAoZmRaS2V5LCBaS0VZX0ZGX0NfTUFQX1NFQ1RJT04sIDIsIFwiQyBtYXBcIik7XG4gICAgICAgIGlmIChnbG9iYWxUaGlzLmdjKSBnbG9iYWxUaGlzLmdjKCk7XG5cbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oYMK3wrfCtyBXcml0aW5nIFNlY3Rpb24gJHtaS0VZX0ZGX1FMX1NFQ1RJT059LiBRTGApO1xuICAgICAgICBhd2FpdCB3cml0ZVFNYXAoZmRaS2V5LCBaS0VZX0ZGX1FMX1NFQ1RJT04sIDMsIFwiUUxcIik7XG4gICAgICAgIGlmIChnbG9iYWxUaGlzLmdjKSBnbG9iYWxUaGlzLmdjKCk7XG5cbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oYMK3wrfCtyBXcml0aW5nIFNlY3Rpb24gJHtaS0VZX0ZGX1FSX1NFQ1RJT059LiBRUmApO1xuICAgICAgICBhd2FpdCB3cml0ZVFNYXAoZmRaS2V5LCBaS0VZX0ZGX1FSX1NFQ1RJT04sIDQsIFwiUVJcIik7XG4gICAgICAgIGlmIChnbG9iYWxUaGlzLmdjKSBnbG9iYWxUaGlzLmdjKCk7XG5cbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oYMK3wrfCtyBXcml0aW5nIFNlY3Rpb24gJHtaS0VZX0ZGX1FNX1NFQ1RJT059LiBRTWApO1xuICAgICAgICBhd2FpdCB3cml0ZVFNYXAoZmRaS2V5LCBaS0VZX0ZGX1FNX1NFQ1RJT04sIDUsIFwiUU1cIik7XG4gICAgICAgIGlmIChnbG9iYWxUaGlzLmdjKSBnbG9iYWxUaGlzLmdjKCk7XG5cbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oYMK3wrfCtyBXcml0aW5nIFNlY3Rpb24gJHtaS0VZX0ZGX1FPX1NFQ1RJT059LiBRT2ApO1xuICAgICAgICBhd2FpdCB3cml0ZVFNYXAoZmRaS2V5LCBaS0VZX0ZGX1FPX1NFQ1RJT04sIDYsIFwiUU9cIik7XG4gICAgICAgIGlmIChnbG9iYWxUaGlzLmdjKSBnbG9iYWxUaGlzLmdjKCk7XG5cbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oYMK3wrfCtyBXcml0aW5nIFNlY3Rpb24gJHtaS0VZX0ZGX1FDX1NFQ1RJT059LiBRQ2ApO1xuICAgICAgICBhd2FpdCB3cml0ZVFNYXAoZmRaS2V5LCBaS0VZX0ZGX1FDX1NFQ1RJT04sIDcsIFwiUUNcIik7XG4gICAgICAgIGlmIChnbG9iYWxUaGlzLmdjKSBnbG9iYWxUaGlzLmdjKCk7XG5cbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oYMK3wrfCtyBXcml0aW5nIFNlY3Rpb25zICR7WktFWV9GRl9TSUdNQTFfU0VDVElPTn0sJHtaS0VZX0ZGX1NJR01BMl9TRUNUSU9OfSwke1pLRVlfRkZfU0lHTUEzX1NFQ1RJT059LiBTaWdtYTEsIFNpZ21hMiAmIFNpZ21hIDNgKTtcbiAgICAgICAgYXdhaXQgd3JpdGVTaWdtYShmZFpLZXkpO1xuICAgICAgICBpZiAoZ2xvYmFsVGhpcy5nYykgZ2xvYmFsVGhpcy5nYygpO1xuXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKGDCt8K3wrcgV3JpdGluZyBTZWN0aW9uICR7WktFWV9GRl9MQUdSQU5HRV9TRUNUSU9OfS4gTGFncmFuZ2UgUG9seW5vbWlhbHNgKTtcbiAgICAgICAgYXdhaXQgd3JpdGVMYWdyYW5nZVBvbHlub21pYWxzKGZkWktleSk7XG4gICAgICAgIGlmIChnbG9iYWxUaGlzLmdjKSBnbG9iYWxUaGlzLmdjKCk7XG5cbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oYMK3wrfCtyBXcml0aW5nIFNlY3Rpb24gJHtaS0VZX0ZGX1BUQVVfU0VDVElPTn0uIFBvd2VycyBvZiBUYXVgKTtcbiAgICAgICAgYXdhaXQgd3JpdGVQdGF1KGZkWktleSk7XG4gICAgICAgIGlmIChnbG9iYWxUaGlzLmdjKSBnbG9iYWxUaGlzLmdjKCk7XG5cbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oYMK3wrfCtyBXcml0aW5nIFNlY3Rpb24gJHtaS0VZX0ZGX0MwX1NFQ1RJT059LiBDMGApO1xuICAgICAgICBhd2FpdCB3cml0ZUMwKGZkWktleSk7XG4gICAgICAgIGlmIChnbG9iYWxUaGlzLmdjKSBnbG9iYWxUaGlzLmdjKCk7XG5cbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oYMK3wrfCtyBXcml0aW5nIFNlY3Rpb24gJHtaS0VZX0ZGX0hFQURFUl9TRUNUSU9OfS4gRkZsb25rIEhlYWRlcmApO1xuICAgICAgICBhd2FpdCB3cml0ZUZGbG9ua0hlYWRlcihmZFpLZXkpO1xuICAgICAgICBpZiAoZ2xvYmFsVGhpcy5nYykgZ2xvYmFsVGhpcy5nYygpO1xuXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBXcml0aW5nIHRoZSB6a2V5IGZpbGUgZmluaXNoZWRcIik7XG5cbiAgICAgICAgYXdhaXQgZmRaS2V5LmNsb3NlKCk7XG4gICAgfVxuXG4gICAgYXN5bmMgZnVuY3Rpb24gd3JpdGVaa2V5SGVhZGVyKGZkWktleSkge1xuICAgICAgICBhd2FpdCBzdGFydFdyaXRlU2VjdGlvbihmZFpLZXksIEhFQURFUl9aS0VZX1NFQ1RJT04pO1xuICAgICAgICBhd2FpdCBmZFpLZXkud3JpdGVVTEUzMihGRkxPTktfUFJPVE9DT0xfSUQpO1xuICAgICAgICBhd2FpdCBlbmRXcml0ZVNlY3Rpb24oZmRaS2V5KTtcbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiB3cml0ZUFkZGl0aW9ucyhmZFpLZXkpIHtcbiAgICAgICAgYXdhaXQgc3RhcnRXcml0ZVNlY3Rpb24oZmRaS2V5LCBaS0VZX0ZGX0FERElUSU9OU19TRUNUSU9OKTtcblxuICAgICAgICAvLyBXcml0dGVuIHZhbHVlcyBhcmUgMiAqIDMyIGJpdCBpbnRlZ2VycyAoMiAqIDQgYnl0ZXMpICsgMiBmaWVsZCBzaXplIHZhbHVlcyAoIDIgKiBzRnIgYnl0ZXMpXG4gICAgICAgIGNvbnN0IGJ1ZmZPdXQgPSBuZXcgVWludDhBcnJheSg4ICsgMiAqIHNGcik7XG4gICAgICAgIGNvbnN0IGJ1ZmZPdXRWID0gbmV3IERhdGFWaWV3KGJ1ZmZPdXQuYnVmZmVyKTtcblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBsb25rQWRkaXRpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoKGxvZ2dlcikgJiYgKGkgIT09IDApICYmIChpICUgNTAwMDAwID09PSAwKSkgbG9nZ2VyLmluZm8oYCAgICAgIHdyaXRpbmcgQWRkaXRpb25zOiAke2l9LyR7cGxvbmtBZGRpdGlvbnMubGVuZ3RofWApO1xuXG4gICAgICAgICAgICBjb25zdCBhZGRpdGlvbiA9IHBsb25rQWRkaXRpb25zW2ldO1xuXG4gICAgICAgICAgICBidWZmT3V0Vi5zZXRVaW50MzIoMCwgYWRkaXRpb25bMF0sIHRydWUpO1xuICAgICAgICAgICAgYnVmZk91dFYuc2V0VWludDMyKDQsIGFkZGl0aW9uWzFdLCB0cnVlKTtcbiAgICAgICAgICAgIGJ1ZmZPdXQuc2V0KGFkZGl0aW9uWzJdLCA4KTtcbiAgICAgICAgICAgIGJ1ZmZPdXQuc2V0KGFkZGl0aW9uWzNdLCA4ICsgc0ZyKTtcblxuICAgICAgICAgICAgYXdhaXQgZmRaS2V5LndyaXRlKGJ1ZmZPdXQpO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IGVuZFdyaXRlU2VjdGlvbihmZFpLZXkpO1xuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHdyaXRlV2l0bmVzc01hcChmZFpLZXksIHNlY3Rpb25OdW0sIHBvc0NvbnN0cmFpbnQsIG5hbWUpIHtcbiAgICAgICAgYXdhaXQgc3RhcnRXcml0ZVNlY3Rpb24oZmRaS2V5LCBzZWN0aW9uTnVtKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwbG9ua0NvbnN0cmFpbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAobG9nZ2VyICYmIChpICE9PSAwKSAmJiAoaSAlIDUwMDAwMCA9PT0gMCkpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhgICAgICAgd3JpdGluZyB3aXRuZXNzICR7bmFtZX06ICR7aX0vJHtwbG9ua0NvbnN0cmFpbnRzLmxlbmd0aH1gKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYXdhaXQgZmRaS2V5LndyaXRlVUxFMzIocGxvbmtDb25zdHJhaW50c1tpXVtwb3NDb25zdHJhaW50XSk7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgZW5kV3JpdGVTZWN0aW9uKGZkWktleSk7XG4gICAgfVxuXG4gICAgYXN5bmMgZnVuY3Rpb24gd3JpdGVRTWFwKGZkWktleSwgc2VjdGlvbk51bSwgcG9zQ29uc3RyYWludCwgbmFtZSkge1xuICAgICAgICAvLyBDb21wdXRlIFEgZnJvbSBxIGV2YWx1YXRpb25zXG4gICAgICAgIGxldCBRID0gbmV3IEJpZ0J1ZmZlcihzZXR0aW5ncy5kb21haW5TaXplICogc0ZyKTtcblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBsb25rQ29uc3RyYWludHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIFEuc2V0KHBsb25rQ29uc3RyYWludHNbaV1bcG9zQ29uc3RyYWludF0sIGkgKiBzRnIpO1xuICAgICAgICAgICAgaWYgKChsb2dnZXIpICYmIChpICE9PSAwKSAmJiAoaSAlIDUwMDAwMCA9PT0gMCkpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhgICAgICAgd3JpdGluZyAke25hbWV9OiAke2l9LyR7cGxvbmtDb25zdHJhaW50cy5sZW5ndGh9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBwb2x5bm9taWFsc1tuYW1lXSA9IGF3YWl0IFBvbHlub21pYWwuZnJvbUV2YWx1YXRpb25zKFEsIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICBldmFsdWF0aW9uc1tuYW1lXSA9IGF3YWl0IEV2YWx1YXRpb25zLmZyb21Qb2x5bm9taWFsKHBvbHlub21pYWxzW25hbWVdLCA0LCBjdXJ2ZSwgbG9nZ2VyKTtcblxuICAgICAgICAvLyBXcml0ZSBRIGNvZWZmaWNpZW50cyBhbmQgZXZhbHVhdGlvbnNcbiAgICAgICAgYXdhaXQgc3RhcnRXcml0ZVNlY3Rpb24oZmRaS2V5LCBzZWN0aW9uTnVtKTtcbiAgICAgICAgYXdhaXQgZmRaS2V5LndyaXRlKHBvbHlub21pYWxzW25hbWVdLmNvZWYpO1xuICAgICAgICBhd2FpdCBmZFpLZXkud3JpdGUoZXZhbHVhdGlvbnNbbmFtZV0uZXZhbCk7XG4gICAgICAgIGF3YWl0IGVuZFdyaXRlU2VjdGlvbihmZFpLZXkpO1xuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHdyaXRlU2lnbWEoZmRaS2V5KSB7XG4gICAgICAgIC8vIENvbXB1dGUgc2lnbWFcbiAgICAgICAgY29uc3Qgc2lnbWEgPSBuZXcgQmlnQnVmZmVyKHNGciAqIHNldHRpbmdzLmRvbWFpblNpemUgKiAzKTtcbiAgICAgICAgY29uc3QgbGFzdFNlZW4gPSBuZXcgQmlnQXJyYXkoc2V0dGluZ3MublZhcnMpO1xuICAgICAgICBjb25zdCBmaXJzdFBvcyA9IG5ldyBCaWdBcnJheShzZXR0aW5ncy5uVmFycyk7XG5cbiAgICAgICAgbGV0IHcgPSBGci5vbmU7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2V0dGluZ3MuZG9tYWluU2l6ZTsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoaSA8IHBsb25rQ29uc3RyYWludHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgYnVpbGRTaWdtYShwbG9ua0NvbnN0cmFpbnRzW2ldWzBdLCBpKTtcbiAgICAgICAgICAgICAgICBidWlsZFNpZ21hKHBsb25rQ29uc3RyYWludHNbaV1bMV0sIHNldHRpbmdzLmRvbWFpblNpemUgKyBpKTtcbiAgICAgICAgICAgICAgICBidWlsZFNpZ21hKHBsb25rQ29uc3RyYWludHNbaV1bMl0sIHNldHRpbmdzLmRvbWFpblNpemUgKiAyICsgaSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGkgPCBzZXR0aW5ncy5kb21haW5TaXplIC0gMikge1xuICAgICAgICAgICAgICAgIGJ1aWxkU2lnbWEoMCwgaSk7XG4gICAgICAgICAgICAgICAgYnVpbGRTaWdtYSgwLCBzZXR0aW5ncy5kb21haW5TaXplICsgaSk7XG4gICAgICAgICAgICAgICAgYnVpbGRTaWdtYSgwLCBzZXR0aW5ncy5kb21haW5TaXplICogMiArIGkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzaWdtYS5zZXQodywgaSAqIHNGcik7XG4gICAgICAgICAgICAgICAgc2lnbWEuc2V0KEZyLm11bCh3LCBrMSksIChzZXR0aW5ncy5kb21haW5TaXplICsgaSkgKiBzRnIpO1xuICAgICAgICAgICAgICAgIHNpZ21hLnNldChGci5tdWwodywgazIpLCAoc2V0dGluZ3MuZG9tYWluU2l6ZSAqIDIgKyBpKSAqIHNGcik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHcgPSBGci5tdWwodywgRnIud1tzZXR0aW5ncy5jaXJQb3dlcl0pO1xuXG4gICAgICAgICAgICBpZiAoKGxvZ2dlcikgJiYgKGkgIT09IDApICYmIChpICUgNTAwMDAwID09PSAwKSkge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGAgICAgICB3cml0aW5nIHNpZ21hIHBoYXNlMTogJHtpfS8ke3Bsb25rQ29uc3RyYWludHMubGVuZ3RofWApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZXR0aW5ncy5uVmFyczsgaSsrKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGZpcnN0UG9zW2ldICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgc2lnbWEuc2V0KGxhc3RTZWVuW2ldLCBmaXJzdFBvc1tpXSAqIHNGcik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIHRocm93IG5ldyBFcnJvcihcIlZhcmlhYmxlIG5vdCB1c2VkXCIpO1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiVmFyaWFibGUgbm90IHVzZWRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoKGxvZ2dlcikgJiYgKGkgIT09IDApICYmIChpICUgNTAwMDAwID09PSAwKSkgbG9nZ2VyLmluZm8oYCAgICAgIHdyaXRpbmcgc2lnbWEgcGhhc2UyOiAke2l9LyR7c2V0dGluZ3MublZhcnN9YCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZ2xvYmFsVGhpcy5nYykgZ2xvYmFsVGhpcy5nYygpO1xuXG4gICAgICAgIC8vIFdyaXRlIHNpZ21hIGNvZWZmaWNpZW50cyBhbmQgZXZhbHVhdGlvbnNcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAzOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IHNlY3Rpb25JZCA9IDAgPT09IGkgPyBaS0VZX0ZGX1NJR01BMV9TRUNUSU9OIDogMSA9PT0gaSA/IFpLRVlfRkZfU0lHTUEyX1NFQ1RJT04gOiBaS0VZX0ZGX1NJR01BM19TRUNUSU9OO1xuXG4gICAgICAgICAgICBsZXQgbmFtZSA9IFwiU1wiICsgKGkgKyAxKTtcbiAgICAgICAgICAgIHBvbHlub21pYWxzW25hbWVdID0gYXdhaXQgUG9seW5vbWlhbC5mcm9tRXZhbHVhdGlvbnMoc2lnbWEuc2xpY2Uoc2V0dGluZ3MuZG9tYWluU2l6ZSAqIHNGciAqIGksIHNldHRpbmdzLmRvbWFpblNpemUgKiBzRnIgKiAoaSArIDEpKSwgY3VydmUsIGxvZ2dlcik7XG4gICAgICAgICAgICBldmFsdWF0aW9uc1tuYW1lXSA9IGF3YWl0IEV2YWx1YXRpb25zLmZyb21Qb2x5bm9taWFsKHBvbHlub21pYWxzW25hbWVdLCA0LCBjdXJ2ZSwgbG9nZ2VyKTtcbiAgICAgICAgICAgIGF3YWl0IHN0YXJ0V3JpdGVTZWN0aW9uKGZkWktleSwgc2VjdGlvbklkKTtcbiAgICAgICAgICAgIGF3YWl0IGZkWktleS53cml0ZShwb2x5bm9taWFsc1tuYW1lXS5jb2VmKTtcbiAgICAgICAgICAgIGF3YWl0IGZkWktleS53cml0ZShldmFsdWF0aW9uc1tuYW1lXS5ldmFsKTtcbiAgICAgICAgICAgIGF3YWl0IGVuZFdyaXRlU2VjdGlvbihmZFpLZXkpO1xuXG4gICAgICAgICAgICBpZiAoZ2xvYmFsVGhpcy5nYykgZ2xvYmFsVGhpcy5nYygpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIDA7XG5cbiAgICAgICAgZnVuY3Rpb24gYnVpbGRTaWdtYShzaWduYWxJZCwgaWR4KSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGxhc3RTZWVuW3NpZ25hbElkXSA9PT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgICAgIGZpcnN0UG9zW3NpZ25hbElkXSA9IGlkeDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2lnbWEuc2V0KGxhc3RTZWVuW3NpZ25hbElkXSwgaWR4ICogc0ZyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCB2O1xuICAgICAgICAgICAgaWYgKGlkeCA8IHNldHRpbmdzLmRvbWFpblNpemUpIHtcbiAgICAgICAgICAgICAgICB2ID0gdztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaWR4IDwgMiAqIHNldHRpbmdzLmRvbWFpblNpemUpIHtcbiAgICAgICAgICAgICAgICB2ID0gRnIubXVsKHcsIGsxKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdiA9IEZyLm11bCh3LCBrMik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxhc3RTZWVuW3NpZ25hbElkXSA9IHY7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiB3cml0ZUxhZ3JhbmdlUG9seW5vbWlhbHMoZmRaS2V5KSB7XG4gICAgICAgIGF3YWl0IHN0YXJ0V3JpdGVTZWN0aW9uKGZkWktleSwgWktFWV9GRl9MQUdSQU5HRV9TRUNUSU9OKTtcblxuICAgICAgICBjb25zdCBsID0gTWF0aC5tYXgoc2V0dGluZ3MublB1YmxpYywgMSk7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgICBsZXQgYnVmZiA9IG5ldyBCaWdCdWZmZXIoc2V0dGluZ3MuZG9tYWluU2l6ZSAqIHNGcik7XG4gICAgICAgICAgICBidWZmLnNldChGci5vbmUsIGkgKiBzRnIpO1xuXG4gICAgICAgICAgICBhd2FpdCB3cml0ZVA0KGZkWktleSwgYnVmZik7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgZW5kV3JpdGVTZWN0aW9uKGZkWktleSk7XG4gICAgfVxuXG4gICAgYXN5bmMgZnVuY3Rpb24gd3JpdGVQdGF1KGZkWktleSkge1xuICAgICAgICBhd2FpdCBzdGFydFdyaXRlU2VjdGlvbihmZFpLZXksIFpLRVlfRkZfUFRBVV9TRUNUSU9OKTtcblxuICAgICAgICAvLyBkb21haW5TaXplICogOSArIDE4ID0gbWF4aW11bSBTUlMgbGVuZ3RoIG5lZWRlZCwgc3BlY2lmaWNhbGx5IHRvIGNvbW1pdCBDMlxuICAgICAgICBQVGF1ID0gbmV3IEJpZ0J1ZmZlcigoc2V0dGluZ3MuZG9tYWluU2l6ZSAqIDkgKyAxOCkgKiBzRzEpO1xuICAgICAgICBhd2FpdCBmZFBUYXUucmVhZFRvQnVmZmVyKFBUYXUsIDAsIChzZXR0aW5ncy5kb21haW5TaXplICogOSArIDE4KSAqIHNHMSwgcFRhdVNlY3Rpb25zWzJdWzBdLnApO1xuXG4gICAgICAgIGF3YWl0IGZkWktleS53cml0ZShQVGF1KTtcbiAgICAgICAgYXdhaXQgZW5kV3JpdGVTZWN0aW9uKGZkWktleSk7XG4gICAgfVxuXG4gICAgYXN5bmMgZnVuY3Rpb24gd3JpdGVDMChmZFpLZXkpIHtcbiAgICAgICAgLy8gQzAoWCkgOj0gUUwoWF44KSArIFggwrcgUVIoWF44KSArIFheMiDCtyBRTyhYXjgpICsgWF4zIMK3IFFNKFheOCkgKyBYXjQgwrcgUUMoWF44KVxuICAgICAgICAvLyAgICAgICAgICAgICsgWF41IMK3IFNJR01BMShYXjgpICsgWF42IMK3IFNJR01BMihYXjgpICsgWF43IMK3IFNJR01BMyhYXjgpXG4gICAgICAgIGxldCBDMCA9IG5ldyBDUG9seW5vbWlhbCg4LCBjdXJ2ZSwgbG9nZ2VyKTtcbiAgICAgICAgQzAuYWRkUG9seW5vbWlhbCgwLCBwb2x5bm9taWFscy5RTCk7XG4gICAgICAgIEMwLmFkZFBvbHlub21pYWwoMSwgcG9seW5vbWlhbHMuUVIpO1xuICAgICAgICBDMC5hZGRQb2x5bm9taWFsKDIsIHBvbHlub21pYWxzLlFPKTtcbiAgICAgICAgQzAuYWRkUG9seW5vbWlhbCgzLCBwb2x5bm9taWFscy5RTSk7XG4gICAgICAgIEMwLmFkZFBvbHlub21pYWwoNCwgcG9seW5vbWlhbHMuUUMpO1xuICAgICAgICBDMC5hZGRQb2x5bm9taWFsKDUsIHBvbHlub21pYWxzLlMxKTtcbiAgICAgICAgQzAuYWRkUG9seW5vbWlhbCg2LCBwb2x5bm9taWFscy5TMik7XG4gICAgICAgIEMwLmFkZFBvbHlub21pYWwoNywgcG9seW5vbWlhbHMuUzMpO1xuXG4gICAgICAgIHBvbHlub21pYWxzLkMwID0gQzAuZ2V0UG9seW5vbWlhbCgpO1xuXG4gICAgICAgIC8vIENoZWNrIGRlZ3JlZVxuICAgICAgICBpZiAocG9seW5vbWlhbHMuQzAuZGVncmVlKCkgPj0gOCAqIHNldHRpbmdzLmRvbWFpblNpemUpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkMwIFBvbHlub21pYWwgaXMgbm90IHdlbGwgY2FsY3VsYXRlZFwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGF3YWl0IHN0YXJ0V3JpdGVTZWN0aW9uKGZkWktleSwgWktFWV9GRl9DMF9TRUNUSU9OKTtcbiAgICAgICAgYXdhaXQgZmRaS2V5LndyaXRlKHBvbHlub21pYWxzLkMwLmNvZWYpO1xuICAgICAgICBhd2FpdCBlbmRXcml0ZVNlY3Rpb24oZmRaS2V5KTtcbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiB3cml0ZUZGbG9ua0hlYWRlcihmZFpLZXkpIHtcbiAgICAgICAgYXdhaXQgc3RhcnRXcml0ZVNlY3Rpb24oZmRaS2V5LCBaS0VZX0ZGX0hFQURFUl9TRUNUSU9OKTtcblxuICAgICAgICBjb25zdCBwcmltZVEgPSBjdXJ2ZS5xO1xuICAgICAgICBjb25zdCBuOHEgPSAoTWF0aC5mbG9vcigoU2NhbGFyLmJpdExlbmd0aChwcmltZVEpIC0gMSkgLyA2NCkgKyAxKSAqIDg7XG4gICAgICAgIGF3YWl0IGZkWktleS53cml0ZVVMRTMyKG44cSk7XG4gICAgICAgIGF3YWl0IHdyaXRlQmlnSW50KGZkWktleSwgcHJpbWVRLCBuOHEpO1xuXG4gICAgICAgIGNvbnN0IHByaW1lUiA9IGN1cnZlLnI7XG4gICAgICAgIGNvbnN0IG44ciA9IChNYXRoLmZsb29yKChTY2FsYXIuYml0TGVuZ3RoKHByaW1lUikgLSAxKSAvIDY0KSArIDEpICogODtcbiAgICAgICAgYXdhaXQgZmRaS2V5LndyaXRlVUxFMzIobjhyKTtcbiAgICAgICAgYXdhaXQgd3JpdGVCaWdJbnQoZmRaS2V5LCBwcmltZVIsIG44cik7XG5cbiAgICAgICAgLy8gVG90YWwgbnVtYmVyIG9mIHIxY3MgdmFyc1xuICAgICAgICBhd2FpdCBmZFpLZXkud3JpdGVVTEUzMihzZXR0aW5ncy5uVmFycyk7XG4gICAgICAgIC8vIFRvdGFsIG51bWJlciBvZiByMWNzIHB1YmxpYyB2YXJzID0gb3V0cHV0cyArIHB1YmxpYyBpbnB1dHNcbiAgICAgICAgYXdhaXQgZmRaS2V5LndyaXRlVUxFMzIoc2V0dGluZ3MublB1YmxpYyk7XG4gICAgICAgIGF3YWl0IGZkWktleS53cml0ZVVMRTMyKHNldHRpbmdzLmRvbWFpblNpemUpO1xuICAgICAgICBhd2FpdCBmZFpLZXkud3JpdGVVTEUzMihwbG9ua0FkZGl0aW9ucy5sZW5ndGgpO1xuICAgICAgICBhd2FpdCBmZFpLZXkud3JpdGVVTEUzMihwbG9ua0NvbnN0cmFpbnRzLmxlbmd0aCk7XG5cbiAgICAgICAgYXdhaXQgZmRaS2V5LndyaXRlKGsxKTtcbiAgICAgICAgYXdhaXQgZmRaS2V5LndyaXRlKGsyKTtcblxuICAgICAgICBhd2FpdCBmZFpLZXkud3JpdGUodzMpO1xuICAgICAgICBhd2FpdCBmZFpLZXkud3JpdGUodzQpO1xuICAgICAgICBhd2FpdCBmZFpLZXkud3JpdGUodzgpO1xuICAgICAgICBhd2FpdCBmZFpLZXkud3JpdGUod3IpO1xuXG4gICAgICAgIGxldCBiWF8yO1xuICAgICAgICBiWF8yID0gYXdhaXQgZmRQVGF1LnJlYWQoc0cyLCBwVGF1U2VjdGlvbnNbM11bMF0ucCArIHNHMik7XG4gICAgICAgIGF3YWl0IGZkWktleS53cml0ZShiWF8yKTtcblxuICAgICAgICBsZXQgY29tbWl0QzAgPSBhd2FpdCBwb2x5bm9taWFscy5DMC5tdWx0aUV4cG9uZW50aWF0aW9uKFBUYXUsIFwiQzBcIik7XG4gICAgICAgIGF3YWl0IGZkWktleS53cml0ZShjb21taXRDMCk7XG5cbiAgICAgICAgYXdhaXQgZW5kV3JpdGVTZWN0aW9uKGZkWktleSk7XG4gICAgfVxuXG4gICAgYXN5bmMgZnVuY3Rpb24gd3JpdGVQNChmZFpLZXksIGJ1ZmYpIHtcbiAgICAgICAgY29uc3QgW2NvZWZmaWNpZW50cywgZXZhbHVhdGlvbnM0XSA9IGF3YWl0IFBvbHlub21pYWwudG80VChidWZmLCBzZXR0aW5ncy5kb21haW5TaXplLCBbXSwgRnIpO1xuICAgICAgICBhd2FpdCBmZFpLZXkud3JpdGUoY29lZmZpY2llbnRzKTtcbiAgICAgICAgYXdhaXQgZmRaS2V5LndyaXRlKGV2YWx1YXRpb25zNCk7XG5cbiAgICAgICAgcmV0dXJuIFtjb2VmZmljaWVudHMsIGV2YWx1YXRpb25zNF07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29tcHV0ZUsxSzIoKSB7XG4gICAgICAgIGxldCBrMSA9IEZyLnR3bztcbiAgICAgICAgd2hpbGUgKGlzSW5jbHVkZWQoazEsIFtdLCBzZXR0aW5ncy5jaXJQb3dlcikpIEZyLmFkZChrMSwgRnIub25lKTtcbiAgICAgICAgbGV0IGsyID0gRnIuYWRkKGsxLCBGci5vbmUpO1xuICAgICAgICB3aGlsZSAoaXNJbmNsdWRlZChrMiwgW2sxXSwgc2V0dGluZ3MuY2lyUG93ZXIpKSBGci5hZGQoazIsIEZyLm9uZSk7XG4gICAgICAgIHJldHVybiBbazEsIGsyXTtcblxuICAgICAgICBmdW5jdGlvbiBpc0luY2x1ZGVkKGssIGtBcnIsIHBvdykge1xuICAgICAgICAgICAgY29uc3QgZG9tYWluU2l6ZSA9IDIgKiogcG93O1xuICAgICAgICAgICAgbGV0IHcgPSBGci5vbmU7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRvbWFpblNpemU7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChGci5lcShrLCB3KSkgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBrQXJyLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChGci5lcShrLCBGci5tdWwoa0FycltqXSwgdykpKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdyA9IEZyLm11bCh3LCBGci53W3Bvd10pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29tcHV0ZVczKCkge1xuICAgICAgICBsZXQgZ2VuZXJhdG9yID0gRnIuZSgzMTYyNCk7XG5cbiAgICAgICAgLy8gRXhwb25lbnQgaXMgb3JkZXIociAtIDEpIC8gM1xuICAgICAgICBsZXQgb3JkZXJSc3ViMSA9IDM2NDgwNDA0Nzg2Mzk4NzkyMDM3MDc3MzQyOTA4NzYyMTI1MTQ3NTgwNjA3MzM0MDI2NzIzOTA2MTYzNjczNjQ0MjkzMDE0MTU5MzZuO1xuICAgICAgICBsZXQgZXhwb25lbnQgPSBTY2FsYXIuZGl2KG9yZGVyUnN1YjEsIFNjYWxhci5lKDMpKTtcblxuICAgICAgICByZXR1cm4gRnIuZXhwKGdlbmVyYXRvciwgZXhwb25lbnQpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNvbXB1dGVXNCgpIHtcbiAgICAgICAgcmV0dXJuIEZyLndbMl07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29tcHV0ZVc4KCkge1xuICAgICAgICByZXR1cm4gRnIud1szXTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRPbWVnYUN1YmljUm9vdChwb3dlciwgRnIpIHtcbiAgICAgICAgLy8gSGFyZGNvcmRlZCAzdGgtcm9vdCBvZiBGci53WzI4XVxuICAgICAgICBjb25zdCBmaXJzdFJvb3QgPSBGci5lKDQ2Nzc5OTE2NTg4NjA2OTYxMDAzNjA0Njg2Njc5OTI2NDAyNjQ4MTM0NDI5OTA3OTAxMTc2MjAyNjc3NDUzMzc3NDM0NTk4ODA4MG4pO1xuXG4gICAgICAgIHJldHVybiBGci5leHAoZmlyc3RSb290LCAyICoqICgyOCAtIHBvd2VyKSk7XG4gICAgfVxufVxuXG5cbiIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMjIgaWRlbjMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya2pzLlxuXG4gICAgc25hcmtqcyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuICAgIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGVcbiAgICBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbilcbiAgICBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJranMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAgICBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3JcbiAgICBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhbG9uZyB3aXRoXG4gICAgc25hcmtqcy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbmltcG9ydCAqIGFzIGJpbkZpbGVVdGlscyBmcm9tIFwiQGlkZW4zL2JpbmZpbGV1dGlsc1wiO1xuaW1wb3J0ICogYXMgemtleVV0aWxzIGZyb20gXCIuL3prZXlfdXRpbHMuanNcIjtcbmltcG9ydCAqIGFzIHd0bnNVdGlscyBmcm9tIFwiLi93dG5zX3V0aWxzLmpzXCI7XG5pbXBvcnQgeyBCaWdCdWZmZXIsIFNjYWxhciwgdXRpbHMgfSBmcm9tIFwiZmZqYXZhc2NyaXB0XCI7XG5pbXBvcnQgeyBGRkxPTktfUFJPVE9DT0xfSUQgfSBmcm9tIFwiLi96a2V5X2NvbnN0YW50cy5qc1wiO1xuaW1wb3J0IHtcbiAgICBaS0VZX0ZGX0FfTUFQX1NFQ1RJT04sXG4gICAgWktFWV9GRl9BRERJVElPTlNfU0VDVElPTixcbiAgICBaS0VZX0ZGX0JfTUFQX1NFQ1RJT04sXG4gICAgWktFWV9GRl9DMF9TRUNUSU9OLFxuICAgIFpLRVlfRkZfQ19NQVBfU0VDVElPTixcbiAgICBaS0VZX0ZGX0xBR1JBTkdFX1NFQ1RJT04sXG4gICAgWktFWV9GRl9QVEFVX1NFQ1RJT04sXG4gICAgWktFWV9GRl9RQ19TRUNUSU9OLFxuICAgIFpLRVlfRkZfUUxfU0VDVElPTixcbiAgICBaS0VZX0ZGX1FNX1NFQ1RJT04sXG4gICAgWktFWV9GRl9RT19TRUNUSU9OLFxuICAgIFpLRVlfRkZfUVJfU0VDVElPTixcbiAgICBaS0VZX0ZGX1NJR01BMV9TRUNUSU9OLFxuICAgIFpLRVlfRkZfU0lHTUEyX1NFQ1RJT04sXG4gICAgWktFWV9GRl9TSUdNQTNfU0VDVElPTixcbn0gZnJvbSBcIi4vZmZsb25rX2NvbnN0YW50cy5qc1wiO1xuaW1wb3J0IHsgS2VjY2FrMjU2VHJhbnNjcmlwdCB9IGZyb20gXCIuL0tlY2NhazI1NlRyYW5zY3JpcHQuanNcIjtcbmltcG9ydCB7IFByb29mIH0gZnJvbSBcIi4vcHJvb2YuanNcIjtcbmltcG9ydCB7IFBvbHlub21pYWwgfSBmcm9tIFwiLi9wb2x5bm9taWFsL3BvbHlub21pYWwuanNcIjtcbmltcG9ydCB7IEV2YWx1YXRpb25zIH0gZnJvbSBcIi4vcG9seW5vbWlhbC9ldmFsdWF0aW9ucy5qc1wiO1xuaW1wb3J0IHsgQ1BvbHlub21pYWwgfSBmcm9tIFwiLi9wb2x5bm9taWFsL2Nwb2x5bm9taWFsLmpzXCI7XG5cbmNvbnN0IHsgc3RyaW5naWZ5QmlnSW50cyB9ID0gdXRpbHM7XG5cblxuZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gZmZsb25rUHJvdmUoemtleUZpbGVOYW1lLCB3aXRuZXNzRmlsZU5hbWUsIGxvZ2dlciwgb3B0aW9ucykge1xuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiRkZMT05LIFBST1ZFUiBTVEFSVEVEXCIpO1xuXG4gICAgLy8gUmVhZCB3aXRuZXNzIGZpbGVcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gUmVhZGluZyB3aXRuZXNzIGZpbGVcIik7XG4gICAgY29uc3Qge1xuICAgICAgICBmZDogZmRXdG5zLFxuICAgICAgICBzZWN0aW9uczogd3Ruc1NlY3Rpb25zXG4gICAgfSA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkQmluRmlsZSh3aXRuZXNzRmlsZU5hbWUsIFwid3Ruc1wiLCAyLCAxIDw8IDI1LCAxIDw8IDIzKTtcbiAgICBjb25zdCB3dG5zID0gYXdhaXQgd3Ruc1V0aWxzLnJlYWRIZWFkZXIoZmRXdG5zLCB3dG5zU2VjdGlvbnMpO1xuXG4gICAgLy9SZWFkIHprZXkgZmlsZVxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBSZWFkaW5nIHprZXkgZmlsZVwiKTtcbiAgICBjb25zdCB7XG4gICAgICAgIGZkOiBmZFpLZXksXG4gICAgICAgIHNlY3Rpb25zOiB6a2V5U2VjdGlvbnNcbiAgICB9ID0gYXdhaXQgYmluRmlsZVV0aWxzLnJlYWRCaW5GaWxlKHprZXlGaWxlTmFtZSwgXCJ6a2V5XCIsIDIsIDEgPDwgMjUsIDEgPDwgMjMpO1xuXG4gICAgY29uc3QgemtleSA9IGF3YWl0IHprZXlVdGlscy5yZWFkSGVhZGVyKGZkWktleSwgemtleVNlY3Rpb25zLCB1bmRlZmluZWQsIG9wdGlvbnMpO1xuXG4gICAgaWYgKHprZXkucHJvdG9jb2xJZCAhPT0gRkZMT05LX1BST1RPQ09MX0lEKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcInprZXkgZmlsZSBpcyBub3QgZmZsb25rXCIpO1xuICAgIH1cblxuICAgIGlmICghU2NhbGFyLmVxKHprZXkuciwgd3Rucy5xKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDdXJ2ZSBvZiB0aGUgd2l0bmVzcyBkb2VzIG5vdCBtYXRjaCB0aGUgY3VydmUgb2YgdGhlIHByb3Zpbmcga2V5XCIpO1xuICAgIH1cblxuICAgIGlmICh3dG5zLm5XaXRuZXNzICE9PSB6a2V5Lm5WYXJzIC0gemtleS5uQWRkaXRpb25zKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCB3aXRuZXNzIGxlbmd0aC4gQ2lyY3VpdDogJHt6a2V5Lm5WYXJzfSwgd2l0bmVzczogJHt3dG5zLm5XaXRuZXNzfSwgJHt6a2V5Lm5BZGRpdGlvbnN9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgY3VydmUgPSB6a2V5LmN1cnZlO1xuXG4gICAgY29uc3QgRnIgPSBjdXJ2ZS5GcjtcblxuICAgIGNvbnN0IHNGciA9IGN1cnZlLkZyLm44O1xuICAgIGNvbnN0IHNHMSA9IGN1cnZlLkcxLkYubjggKiAyO1xuICAgIGNvbnN0IHNEb21haW4gPSB6a2V5LmRvbWFpblNpemUgKiBzRnI7XG5cbiAgICBpZiAobG9nZ2VyKSB7XG4gICAgICAgIGxvZ2dlci5pbmZvKFwiLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgbG9nZ2VyLmluZm8oXCIgIEZGTE9OSyBQUk9WRSBTRVRUSU5HU1wiKTtcbiAgICAgICAgbG9nZ2VyLmluZm8oYCAgQ3VydmU6ICAgICAgICAgJHtjdXJ2ZS5uYW1lfWApO1xuICAgICAgICBsb2dnZXIuaW5mbyhgICBDaXJjdWl0IHBvd2VyOiAke3prZXkucG93ZXJ9YCk7XG4gICAgICAgIGxvZ2dlci5pbmZvKGAgIERvbWFpbiBzaXplOiAgICR7emtleS5kb21haW5TaXplfWApO1xuICAgICAgICBsb2dnZXIuaW5mbyhgICBWYXJzOiAgICAgICAgICAke3prZXkublZhcnN9YCk7XG4gICAgICAgIGxvZ2dlci5pbmZvKGAgIFB1YmxpYyB2YXJzOiAgICR7emtleS5uUHVibGljfWApO1xuICAgICAgICBsb2dnZXIuaW5mbyhgICBDb25zdHJhaW50czogICAke3prZXkubkNvbnN0cmFpbnRzfWApO1xuICAgICAgICBsb2dnZXIuaW5mbyhgICBBZGRpdGlvbnM6ICAgICAke3prZXkubkFkZGl0aW9uc31gKTtcbiAgICAgICAgbG9nZ2VyLmluZm8oXCItLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXCIpO1xuICAgIH1cblxuICAgIC8vUmVhZCB3aXRuZXNzIGRhdGFcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gUmVhZGluZyB3aXRuZXNzIGZpbGUgZGF0YVwiKTtcbiAgICBjb25zdCBidWZmV2l0bmVzcyA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkU2VjdGlvbihmZFd0bnMsIHd0bnNTZWN0aW9ucywgMik7XG4gICAgYXdhaXQgZmRXdG5zLmNsb3NlKCk7XG5cbiAgICAvLyBGaXJzdCBlbGVtZW50IGluIHBsb25rIGlzIG5vdCB1c2VkIGFuZCBjYW4gYmUgYW55IHZhbHVlLiAoQnV0IGFsd2F5cyB0aGUgc2FtZSkuXG4gICAgLy8gV2Ugc2V0IGl0IHRvIHplcm8gdG8gZ28gZmFzdGVyIGluIHRoZSBleHBvbmVudGlhdGlvbnMuXG4gICAgYnVmZldpdG5lc3Muc2V0KEZyLnplcm8sIDApO1xuICAgIGNvbnN0IGJ1ZmZJbnRlcm5hbFdpdG5lc3MgPSBuZXcgQmlnQnVmZmVyKHprZXkubkFkZGl0aW9ucyAqIHNGcik7XG5cbiAgICBsZXQgYnVmZmVycyA9IHt9O1xuICAgIGxldCBwb2x5bm9taWFscyA9IHt9O1xuICAgIGxldCBldmFsdWF0aW9ucyA9IHt9O1xuXG4gICAgLy8gVG8gZGl2aWRlIHByaW1lIGZpZWxkcyB0aGUgRXh0ZW5kZWQgRXVjbGlkZWFuIEFsZ29yaXRobSBmb3IgY29tcHV0aW5nIG1vZHVsYXIgaW52ZXJzZXMgaXMgbmVlZGVkLlxuICAgIC8vIE5PVEU6IFRoaXMgaXMgdGhlIGVxdWl2YWxlbnQgb2YgY29tcHV0ZSAxL2Rlbm9taW5hdG9yIGFuZCB0aGVuIG11bHRpcGx5IGl0IGJ5IHRoZSBudW1lcmF0b3IuXG4gICAgLy8gVGhlIEV4dGVuZGVkIEV1Y2xpZGVhbiBBbGdvcml0aG0gaXMgZXhwZW5zaXZlIGluIHRlcm1zIG9mIGNvbXB1dGF0aW9uLlxuICAgIC8vIEZvciB0aGUgc3BlY2lhbCBjYXNlIHdoZXJlIHdlIG5lZWQgdG8gZG8gbWFueSBtb2R1bGFyIGludmVyc2VzLCB0aGVyZSdzIGEgc2ltcGxlIG1hdGhlbWF0aWNhbCB0cmlja1xuICAgIC8vIHRoYXQgYWxsb3dzIHVzIHRvIGNvbXB1dGUgbWFueSBpbnZlcnNlcywgY2FsbGVkIE1vbnRnb21lcnkgYmF0Y2ggaW52ZXJzaW9uLlxuICAgIC8vIE1vcmUgaW5mbzogaHR0cHM6Ly92aXRhbGlrLmNhL2dlbmVyYWwvMjAxOC8wNy8yMS9zdGFya3NfcGFydF8zLmh0bWxcbiAgICAvLyBNb250Z29tZXJ5IGJhdGNoIGludmVyc2lvbiByZWR1Y2VzIHRoZSBuIGludmVyc2UgY29tcHV0YXRpb25zIHRvIGEgc2luZ2xlIG9uZVxuICAgIC8vIFRvIHNhdmUgdGhpcyAoc2luZ2xlKSBpbnZlcnNlIGNvbXB1dGF0aW9uIG9uLWNoYWluLCB3aWxsIGNvbXB1dGUgaXQgaW4gcHJvdmluZyB0aW1lIGFuZCBzZW5kIGl0IHRvIHRoZSB2ZXJpZmllci5cbiAgICAvLyBUaGUgdmVyaWZpZXIgd2lsbCBoYXZlIHRvIGNoZWNrOlxuICAgIC8vIDEpIHRoZSBkZW5vbWluYXRvciBpcyBjb3JyZWN0IG11bHRpcGx5aW5nIGJ5IGhpbXNlbGYgbm9uLWludmVydGVkIC0+IGEgKiAxL2EgPT0gMVxuICAgIC8vIDIpIGNvbXB1dGUgdGhlIHJlc3Qgb2YgdGhlIGRlbm9taW5hdG9ycyB1c2luZyB0aGUgTW9udGdvbWVyeSBiYXRjaCBpbnZlcnNpb25cbiAgICAvLyBUaGUgaW52ZXJzaW9ucyBhcmU6XG4gICAgLy8gICDCtyBkZW5vbWluYXRvciBuZWVkZWQgaW4gc3RlcCA4IGFuZCA5IG9mIHRoZSB2ZXJpZmllciB0byBtdWx0aXBseSBieSAxL1pfSCh4aSlcbiAgICAvLyAgIMK3IGRlbm9taW5hdG9yIG5lZWRlZCBpbiBzdGVwIDEwIGFuZCAxMSBvZiB0aGUgdmVyaWZpZXJcbiAgICAvLyAgIMK3IGRlbm9taW5hdG9yIG5lZWRlZCBpbiB0aGUgdmVyaWZpZXIgd2hlbiBjb21wdXRpbmcgTF9pXntTMX0oWCkgYW5kIExfaV57UzJ9KFgpXG4gICAgLy8gICDCtyBMX2kgaT0xIHRvIG51bSBwdWJsaWMgaW5wdXRzLCBuZWVkZWQgaW4gc3RlcCA2IGFuZCA3IG9mIHRoZSB2ZXJpZmllciB0byBjb21wdXRlIExfMSh4aSkgYW5kIFBJKHhpKVxuICAgIGxldCB0b0ludmVyc2UgPSB7fTtcblxuICAgIGxldCBjaGFsbGVuZ2VzID0ge307XG4gICAgbGV0IHJvb3RzID0ge307XG5cbiAgICBsZXQgcHJvb2YgPSBuZXcgUHJvb2YoY3VydmUsIGxvZ2dlcik7XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhgPiBSZWFkaW5nIFNlY3Rpb24gJHtaS0VZX0ZGX0FERElUSU9OU19TRUNUSU9OfS4gQWRkaXRpb25zYCk7XG4gICAgYXdhaXQgY2FsY3VsYXRlQWRkaXRpb25zKCk7XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhgPiBSZWFkaW5nIFNlY3Rpb25zICR7WktFWV9GRl9TSUdNQTFfU0VDVElPTn0sJHtaS0VZX0ZGX1NJR01BMl9TRUNUSU9OfSwke1pLRVlfRkZfU0lHTUEzX1NFQ1RJT059LiBTaWdtYTEsIFNpZ21hMiAmIFNpZ21hIDNgKTtcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIsK3wrfCtyBSZWFkaW5nIFNpZ21hIHBvbHlub21pYWxzIFwiKTtcbiAgICBwb2x5bm9taWFscy5TaWdtYTEgPSBuZXcgUG9seW5vbWlhbChuZXcgQmlnQnVmZmVyKHNEb21haW4pLCBjdXJ2ZSwgbG9nZ2VyKTtcbiAgICBwb2x5bm9taWFscy5TaWdtYTIgPSBuZXcgUG9seW5vbWlhbChuZXcgQmlnQnVmZmVyKHNEb21haW4pLCBjdXJ2ZSwgbG9nZ2VyKTtcbiAgICBwb2x5bm9taWFscy5TaWdtYTMgPSBuZXcgUG9seW5vbWlhbChuZXcgQmlnQnVmZmVyKHNEb21haW4pLCBjdXJ2ZSwgbG9nZ2VyKTtcblxuICAgIGF3YWl0IGZkWktleS5yZWFkVG9CdWZmZXIocG9seW5vbWlhbHMuU2lnbWExLmNvZWYsIDAsIHNEb21haW4sIHprZXlTZWN0aW9uc1taS0VZX0ZGX1NJR01BMV9TRUNUSU9OXVswXS5wKTtcbiAgICBhd2FpdCBmZFpLZXkucmVhZFRvQnVmZmVyKHBvbHlub21pYWxzLlNpZ21hMi5jb2VmLCAwLCBzRG9tYWluLCB6a2V5U2VjdGlvbnNbWktFWV9GRl9TSUdNQTJfU0VDVElPTl1bMF0ucCk7XG4gICAgYXdhaXQgZmRaS2V5LnJlYWRUb0J1ZmZlcihwb2x5bm9taWFscy5TaWdtYTMuY29lZiwgMCwgc0RvbWFpbiwgemtleVNlY3Rpb25zW1pLRVlfRkZfU0lHTUEzX1NFQ1RJT05dWzBdLnApO1xuXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCLCt8K3wrcgUmVhZGluZyBTaWdtYSBldmFsdWF0aW9uc1wiKTtcbiAgICBldmFsdWF0aW9ucy5TaWdtYTEgPSBuZXcgRXZhbHVhdGlvbnMobmV3IEJpZ0J1ZmZlcihzRG9tYWluICogNCksIGN1cnZlLCBsb2dnZXIpO1xuICAgIGV2YWx1YXRpb25zLlNpZ21hMiA9IG5ldyBFdmFsdWF0aW9ucyhuZXcgQmlnQnVmZmVyKHNEb21haW4gKiA0KSwgY3VydmUsIGxvZ2dlcik7XG4gICAgZXZhbHVhdGlvbnMuU2lnbWEzID0gbmV3IEV2YWx1YXRpb25zKG5ldyBCaWdCdWZmZXIoc0RvbWFpbiAqIDQpLCBjdXJ2ZSwgbG9nZ2VyKTtcblxuICAgIGF3YWl0IGZkWktleS5yZWFkVG9CdWZmZXIoZXZhbHVhdGlvbnMuU2lnbWExLmV2YWwsIDAsIHNEb21haW4gKiA0LCB6a2V5U2VjdGlvbnNbWktFWV9GRl9TSUdNQTFfU0VDVElPTl1bMF0ucCArIHNEb21haW4pO1xuICAgIGF3YWl0IGZkWktleS5yZWFkVG9CdWZmZXIoZXZhbHVhdGlvbnMuU2lnbWEyLmV2YWwsIDAsIHNEb21haW4gKiA0LCB6a2V5U2VjdGlvbnNbWktFWV9GRl9TSUdNQTJfU0VDVElPTl1bMF0ucCArIHNEb21haW4pO1xuICAgIGF3YWl0IGZkWktleS5yZWFkVG9CdWZmZXIoZXZhbHVhdGlvbnMuU2lnbWEzLmV2YWwsIDAsIHNEb21haW4gKiA0LCB6a2V5U2VjdGlvbnNbWktFWV9GRl9TSUdNQTNfU0VDVElPTl1bMF0ucCArIHNEb21haW4pO1xuXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oYD4gUmVhZGluZyBTZWN0aW9uICR7WktFWV9GRl9QVEFVX1NFQ1RJT059LiBQb3dlcnMgb2YgVGF1YCk7XG4gICAgY29uc3QgUFRhdSA9IG5ldyBCaWdCdWZmZXIoemtleS5kb21haW5TaXplICogMTYgKiBzRzEpO1xuICAgIC8vIGRvbWFpblNpemUgKiA5ICsgMTggPSBTUlMgbGVuZ3RoIGluIHRoZSB6a2V5IHNhdmVkIGluIHNldHVwIHByb2Nlc3MuXG4gICAgLy8gaXQgY29ycmVzcG9uZHMgdG8gdGhlIG1heGltdW0gU1JTIGxlbmd0aCBuZWVkZWQsIHNwZWNpZmljYWxseSB0byBjb21taXQgQzJcbiAgICAvLyBub3RpY2UgdGhhdCB0aGUgcmVzZXJ2ZWQgYnVmZmVycyBzaXplIGlzIHprZXkuZG9tYWluU2l6ZSAqIDE2ICogc0cxIGJlY2F1c2UgYSBwb3dlciBvZiB0d28gYnVmZmVyIHNpemUgaXMgbmVlZGVkXG4gICAgLy8gdGhlIHJlbWFpbmluZyBidWZmZXIgbm90IGZpbGxlZCBmcm9tIFNSUyBhcmUgc2V0IHRvIDBcbiAgICBhd2FpdCBmZFpLZXkucmVhZFRvQnVmZmVyKFBUYXUsIDAsICh6a2V5LmRvbWFpblNpemUgKiA5ICsgMTgpICogc0cxLCB6a2V5U2VjdGlvbnNbWktFWV9GRl9QVEFVX1NFQ1RJT05dWzBdLnApO1xuXG4gICAgLy8gU1RBUlQgRkZMT05LIFBST1ZFUiBQUk9UT0NPTFxuICAgIGlmIChnbG9iYWxUaGlzLmdjKSBnbG9iYWxUaGlzLmdjKCk7XG5cbiAgICAvLyBST1VORCAxLiBDb21wdXRlIEMxKFgpIHBvbHlub21pYWxcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIlwiKTtcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gUk9VTkQgMVwiKTtcbiAgICBhd2FpdCByb3VuZDEoKTtcblxuICAgIGRlbGV0ZSBwb2x5bm9taWFscy5UMDtcbiAgICBkZWxldGUgZXZhbHVhdGlvbnMuUUw7XG4gICAgZGVsZXRlIGV2YWx1YXRpb25zLlFSO1xuICAgIGRlbGV0ZSBldmFsdWF0aW9ucy5RTTtcbiAgICBkZWxldGUgZXZhbHVhdGlvbnMuUU87XG4gICAgZGVsZXRlIGV2YWx1YXRpb25zLlFDO1xuICAgIGlmIChnbG9iYWxUaGlzLmdjKSBnbG9iYWxUaGlzLmdjKCk7XG5cbiAgICAvLyBST1VORCAyLiBDb21wdXRlIEMyKFgpIHBvbHlub21pYWxcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gUk9VTkQgMlwiKTtcbiAgICBhd2FpdCByb3VuZDIoKTtcblxuICAgIGRlbGV0ZSBidWZmZXJzLkE7XG4gICAgZGVsZXRlIGJ1ZmZlcnMuQjtcbiAgICBkZWxldGUgYnVmZmVycy5DO1xuICAgIGRlbGV0ZSBldmFsdWF0aW9ucy5BO1xuICAgIGRlbGV0ZSBldmFsdWF0aW9ucy5CO1xuICAgIGRlbGV0ZSBldmFsdWF0aW9ucy5DO1xuICAgIGRlbGV0ZSBldmFsdWF0aW9ucy5TaWdtYTE7XG4gICAgZGVsZXRlIGV2YWx1YXRpb25zLlNpZ21hMjtcbiAgICBkZWxldGUgZXZhbHVhdGlvbnMuU2lnbWEzO1xuICAgIGRlbGV0ZSBldmFsdWF0aW9ucy5sYWdyYW5nZTE7XG4gICAgZGVsZXRlIGV2YWx1YXRpb25zLlo7XG4gICAgaWYgKGdsb2JhbFRoaXMuZ2MpIGdsb2JhbFRoaXMuZ2MoKTtcblxuICAgIC8vIFJPVU5EIDMuIENvbXB1dGUgb3BlbmluZyBldmFsdWF0aW9uc1xuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBST1VORCAzXCIpO1xuICAgIGF3YWl0IHJvdW5kMygpO1xuXG4gICAgZGVsZXRlIHBvbHlub21pYWxzLkE7XG4gICAgZGVsZXRlIHBvbHlub21pYWxzLkI7XG4gICAgZGVsZXRlIHBvbHlub21pYWxzLkM7XG4gICAgZGVsZXRlIHBvbHlub21pYWxzLlo7XG4gICAgZGVsZXRlIHBvbHlub21pYWxzLlQxO1xuICAgIGRlbGV0ZSBwb2x5bm9taWFscy5UMjtcbiAgICBkZWxldGUgcG9seW5vbWlhbHMuU2lnbWExO1xuICAgIGRlbGV0ZSBwb2x5bm9taWFscy5TaWdtYTI7XG4gICAgZGVsZXRlIHBvbHlub21pYWxzLlNpZ21hMztcbiAgICBkZWxldGUgcG9seW5vbWlhbHMuUUw7XG4gICAgZGVsZXRlIHBvbHlub21pYWxzLlFSO1xuICAgIGRlbGV0ZSBwb2x5bm9taWFscy5RTTtcbiAgICBkZWxldGUgcG9seW5vbWlhbHMuUUM7XG4gICAgZGVsZXRlIHBvbHlub21pYWxzLlFPO1xuICAgIGlmIChnbG9iYWxUaGlzLmdjKSBnbG9iYWxUaGlzLmdjKCk7XG5cbiAgICAvLyBST1VORCA0LiBDb21wdXRlIFcoWCkgcG9seW5vbWlhbFxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBST1VORCA0XCIpO1xuICAgIGF3YWl0IHJvdW5kNCgpO1xuICAgIGlmIChnbG9iYWxUaGlzLmdjKSBnbG9iYWxUaGlzLmdjKCk7XG5cbiAgICAvLyBST1VORCA1LiBDb21wdXRlIFcnKFgpIHBvbHlub21pYWxcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gUk9VTkQgNVwiKTtcbiAgICBhd2FpdCByb3VuZDUoKTtcblxuICAgIGRlbGV0ZSBwb2x5bm9taWFscy5DMDtcbiAgICBkZWxldGUgcG9seW5vbWlhbHMuQzE7XG4gICAgZGVsZXRlIHBvbHlub21pYWxzLkMyO1xuICAgIGRlbGV0ZSBwb2x5bm9taWFscy5SMTtcbiAgICBkZWxldGUgcG9seW5vbWlhbHMuUjI7XG4gICAgZGVsZXRlIHBvbHlub21pYWxzLkY7XG4gICAgZGVsZXRlIHBvbHlub21pYWxzLkw7XG4gICAgZGVsZXRlIHBvbHlub21pYWxzLlpUO1xuICAgIGRlbGV0ZSBwb2x5bm9taWFscy5aVFMyO1xuICAgIGF3YWl0IGZkWktleS5jbG9zZSgpO1xuICAgIGlmIChnbG9iYWxUaGlzLmdjKSBnbG9iYWxUaGlzLmdjKCk7XG5cbiAgICBwcm9vZi5hZGRFdmFsdWF0aW9uKFwiaW52XCIsIGdldE1vbnRnb21lcnlCYXRjaGVkSW52ZXJzZSgpKTtcblxuICAgIC8vIFByZXBhcmUgcHJvb2ZcbiAgICBsZXQgX3Byb29mID0gcHJvb2YudG9PYmplY3RQcm9vZigpO1xuICAgIF9wcm9vZi5wcm90b2NvbCA9IFwiZmZsb25rXCI7XG4gICAgX3Byb29mLmN1cnZlID0gY3VydmUubmFtZTtcblxuICAgIC8vIFByZXBhcmUgcHVibGljIGlucHV0c1xuICAgIGxldCBwdWJsaWNTaWduYWxzID0gW107XG5cbiAgICBmb3IgKGxldCBpID0gMTsgaSA8PSB6a2V5Lm5QdWJsaWM7IGkrKykge1xuICAgICAgICBjb25zdCBpX3NGciA9IGkgKiBzRnI7XG5cbiAgICAgICAgY29uc3QgcHViID0gYnVmZldpdG5lc3Muc2xpY2UoaV9zRnIsIGlfc0ZyICsgc0ZyKTtcbiAgICAgICAgcHVibGljU2lnbmFscy5wdXNoKFNjYWxhci5mcm9tUnByTEUocHViKSk7XG4gICAgfVxuXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCJGRkxPTksgUFJPVkVSIEZJTklTSEVEXCIpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgcHJvb2Y6IHN0cmluZ2lmeUJpZ0ludHMoX3Byb29mKSxcbiAgICAgICAgcHVibGljU2lnbmFsczogc3RyaW5naWZ5QmlnSW50cyhwdWJsaWNTaWduYWxzKVxuICAgIH07XG5cbiAgICBhc3luYyBmdW5jdGlvbiBjYWxjdWxhdGVBZGRpdGlvbnMoKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiwrfCt8K3IENvbXB1dGluZyBhZGRpdGlvbnNcIik7XG4gICAgICAgIGNvbnN0IGFkZGl0aW9uc0J1ZmYgPSBhd2FpdCBiaW5GaWxlVXRpbHMucmVhZFNlY3Rpb24oZmRaS2V5LCB6a2V5U2VjdGlvbnMsIFpLRVlfRkZfQURESVRJT05TX1NFQ1RJT04pO1xuXG4gICAgICAgIC8vIHNpemVzOiB3aXJlSWRfeCA9IDQgYnl0ZXMgKDMyIGJpdHMpLCBmYWN0b3JfeCA9IGZpZWxkIHNpemUgYml0c1xuICAgICAgICAvLyBBZGRpdGlvbiBmb3JtOiB3aXJlSWRfYSB3aXJlSWRfYiBmYWN0b3JfYSBmYWN0b3JfYiAoc2l6ZSBpcyA0ICsgNCArIHNGciArIHNGcilcbiAgICAgICAgY29uc3Qgc1N1bSA9IDggKyBzRnIgKiAyO1xuXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgemtleS5uQWRkaXRpb25zOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIgJiYgKDAgIT09IGkpICYmIChpICUgMTAwMDAwID09PSAwKSkgbG9nZ2VyLmluZm8oYCAgICBhZGRpdGlvbiAke2l9LyR7emtleS5uQWRkaXRpb25zfWApO1xuXG4gICAgICAgICAgICAvLyBSZWFkIGFkZGl0aW9uIHZhbHVlc1xuICAgICAgICAgICAgbGV0IG9mZnNldCA9IGkgKiBzU3VtO1xuICAgICAgICAgICAgY29uc3Qgc2lnbmFsSWQxID0gcmVhZFVJbnQzMihhZGRpdGlvbnNCdWZmLCBvZmZzZXQpO1xuICAgICAgICAgICAgb2Zmc2V0ICs9IDQ7XG4gICAgICAgICAgICBjb25zdCBzaWduYWxJZDIgPSByZWFkVUludDMyKGFkZGl0aW9uc0J1ZmYsIG9mZnNldCk7XG4gICAgICAgICAgICBvZmZzZXQgKz0gNDtcbiAgICAgICAgICAgIGNvbnN0IGZhY3RvcjEgPSBhZGRpdGlvbnNCdWZmLnNsaWNlKG9mZnNldCwgb2Zmc2V0ICsgc0ZyKTtcbiAgICAgICAgICAgIG9mZnNldCArPSBzRnI7XG4gICAgICAgICAgICBjb25zdCBmYWN0b3IyID0gYWRkaXRpb25zQnVmZi5zbGljZShvZmZzZXQsIG9mZnNldCArIHNGcik7XG5cbiAgICAgICAgICAgIC8vIEdldCB3aXRuZXNzIHZhbHVlXG4gICAgICAgICAgICBjb25zdCB3aXRuZXNzMSA9IGdldFdpdG5lc3Moc2lnbmFsSWQxKTtcbiAgICAgICAgICAgIGNvbnN0IHdpdG5lc3MyID0gZ2V0V2l0bmVzcyhzaWduYWxJZDIpO1xuXG4gICAgICAgICAgICAvL0NhbGN1bGF0ZSBmaW5hbCByZXN1bHRcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IEZyLmFkZChGci5tdWwoZmFjdG9yMSwgd2l0bmVzczEpLCBGci5tdWwoZmFjdG9yMiwgd2l0bmVzczIpKTtcblxuICAgICAgICAgICAgYnVmZkludGVybmFsV2l0bmVzcy5zZXQocmVzdWx0LCBzRnIgKiBpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlYWRVSW50MzIoYiwgbykge1xuICAgICAgICBjb25zdCBidWZmID0gYi5zbGljZShvLCBvICsgNCk7XG4gICAgICAgIGNvbnN0IGJ1ZmZWID0gbmV3IERhdGFWaWV3KGJ1ZmYuYnVmZmVyLCBidWZmLmJ5dGVPZmZzZXQsIGJ1ZmYuYnl0ZUxlbmd0aCk7XG4gICAgICAgIHJldHVybiBidWZmVi5nZXRVaW50MzIoMCwgdHJ1ZSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0V2l0bmVzcyhpZHgpIHtcbiAgICAgICAgbGV0IGRpZmYgPSB6a2V5Lm5WYXJzIC0gemtleS5uQWRkaXRpb25zO1xuICAgICAgICBpZiAoaWR4IDwgZGlmZikge1xuICAgICAgICAgICAgcmV0dXJuIGJ1ZmZXaXRuZXNzLnNsaWNlKGlkeCAqIHNGciwgaWR4ICogc0ZyICsgc0ZyKTtcbiAgICAgICAgfSBlbHNlIGlmIChpZHggPCB6a2V5Lm5WYXJzKSB7XG4gICAgICAgICAgICBjb25zdCBvZmZzZXQgPSAoaWR4IC0gZGlmZikgKiBzRnI7XG4gICAgICAgICAgICByZXR1cm4gYnVmZkludGVybmFsV2l0bmVzcy5zbGljZShvZmZzZXQsIG9mZnNldCArIHNGcik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gRnIuemVybztcbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiByb3VuZDEoKSB7XG4gICAgICAgIC8vIFNURVAgMS4xIC0gR2VuZXJhdGUgcmFuZG9tIGJsaW5kaW5nIHNjYWxhcnMgKGJfMSwgLi4uLCBiOSkg4oiIIEZcbiAgICAgICAgY2hhbGxlbmdlcy5iID0gW107XG4gICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDw9IDk7IGkrKykge1xuICAgICAgICAgICAgY2hhbGxlbmdlcy5iW2ldID0gRnIucmFuZG9tKCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTVEVQIDEuMiAtIENvbXB1dGUgd2lyZSBwb2x5bm9taWFscyBhKFgpLCBiKFgpIGFuZCBjKFgpXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBDb21wdXRpbmcgQSwgQiwgQyB3aXJlIHBvbHlub21pYWxzXCIpO1xuICAgICAgICBhd2FpdCBjb21wdXRlV2lyZVBvbHlub21pYWxzKCk7XG5cbiAgICAgICAgLy8gU1RFUCAxLjMgLSBDb21wdXRlIHRoZSBxdW90aWVudCBwb2x5bm9taWFsIFQwKFgpXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBDb21wdXRpbmcgVDAgcG9seW5vbWlhbFwiKTtcbiAgICAgICAgYXdhaXQgY29tcHV0ZVQwKCk7XG5cbiAgICAgICAgLy8gU1RFUCAxLjQgLSBDb21wdXRlIHRoZSBGRlQtc3R5bGUgY29tYmluYXRpb24gcG9seW5vbWlhbCBDMShYKVxuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gQ29tcHV0aW5nIEMxIHBvbHlub21pYWxcIik7XG4gICAgICAgIGF3YWl0IGNvbXB1dGVDMSgpO1xuXG4gICAgICAgIC8vIFRoZSBmaXJzdCBvdXRwdXQgb2YgdGhlIHByb3ZlciBpcyAoW0MxXV8xKVxuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gQ29tcHV0aW5nIEMxIG11bHRpIGV4cG9uZW50aWF0aW9uXCIpO1xuICAgICAgICBsZXQgY29tbWl0QzEgPSBhd2FpdCBwb2x5bm9taWFscy5DMS5tdWx0aUV4cG9uZW50aWF0aW9uKFBUYXUsIFwiQzFcIik7XG4gICAgICAgIHByb29mLmFkZFBvbHlub21pYWwoXCJDMVwiLCBjb21taXRDMSk7XG5cbiAgICAgICAgcmV0dXJuIDA7XG5cbiAgICAgICAgYXN5bmMgZnVuY3Rpb24gY29tcHV0ZVdpcmVQb2x5bm9taWFscygpIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiwrfCt8K3IFJlYWRpbmcgZGF0YSBmcm9tIHprZXkgZmlsZVwiKTtcbiAgICAgICAgICAgIC8vIEJ1aWxkIEEsIEIgYW5kIEMgZXZhbHVhdGlvbnMgYnVmZmVyIGZyb20gemtleSBhbmQgd2l0bmVzcyBmaWxlc1xuICAgICAgICAgICAgYnVmZmVycy5BID0gbmV3IEJpZ0J1ZmZlcihzRG9tYWluKTtcbiAgICAgICAgICAgIGJ1ZmZlcnMuQiA9IG5ldyBCaWdCdWZmZXIoc0RvbWFpbik7XG4gICAgICAgICAgICBidWZmZXJzLkMgPSBuZXcgQmlnQnVmZmVyKHNEb21haW4pO1xuXG4gICAgICAgICAgICAvLyBSZWFkIHprZXkgc2VjdGlvbnMgYW5kIGZpbGwgdGhlIGJ1ZmZlcnNcbiAgICAgICAgICAgIGNvbnN0IGFNYXBCdWZmID0gYXdhaXQgYmluRmlsZVV0aWxzLnJlYWRTZWN0aW9uKGZkWktleSwgemtleVNlY3Rpb25zLCBaS0VZX0ZGX0FfTUFQX1NFQ1RJT04pO1xuICAgICAgICAgICAgY29uc3QgYk1hcEJ1ZmYgPSBhd2FpdCBiaW5GaWxlVXRpbHMucmVhZFNlY3Rpb24oZmRaS2V5LCB6a2V5U2VjdGlvbnMsIFpLRVlfRkZfQl9NQVBfU0VDVElPTik7XG4gICAgICAgICAgICBjb25zdCBjTWFwQnVmZiA9IGF3YWl0IGJpbkZpbGVVdGlscy5yZWFkU2VjdGlvbihmZFpLZXksIHprZXlTZWN0aW9ucywgWktFWV9GRl9DX01BUF9TRUNUSU9OKTtcblxuICAgICAgICAgICAgLy8gQ29tcHV0ZSBhbGwgd2l0bmVzcyBmcm9tIHNpZ25hbCBpZHMgYW5kIHNldCB0aGVtIHRvIEEsQiAmIEMgYnVmZmVyc1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB6a2V5Lm5Db25zdHJhaW50czsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaV9zRnIgPSBpICogc0ZyO1xuICAgICAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IGkgKiA0O1xuXG4gICAgICAgICAgICAgICAgLy8gQ29tcHV0ZSBBIHZhbHVlIGZyb20gYSBzaWduYWwgaWRcbiAgICAgICAgICAgICAgICBjb25zdCBzaWduYWxJZEEgPSByZWFkVUludDMyKGFNYXBCdWZmLCBvZmZzZXQpO1xuICAgICAgICAgICAgICAgIGJ1ZmZlcnMuQS5zZXQoZ2V0V2l0bmVzcyhzaWduYWxJZEEpLCBpX3NGcik7XG5cbiAgICAgICAgICAgICAgICAvLyBDb21wdXRlIEIgdmFsdWUgZnJvbSBhIHNpZ25hbCBpZFxuICAgICAgICAgICAgICAgIGNvbnN0IHNpZ25hbElkQiA9IHJlYWRVSW50MzIoYk1hcEJ1ZmYsIG9mZnNldCk7XG4gICAgICAgICAgICAgICAgYnVmZmVycy5CLnNldChnZXRXaXRuZXNzKHNpZ25hbElkQiksIGlfc0ZyKTtcblxuICAgICAgICAgICAgICAgIC8vIENvbXB1dGUgQyB2YWx1ZSBmcm9tIGEgc2lnbmFsIGlkXG4gICAgICAgICAgICAgICAgY29uc3Qgc2lnbmFsSWRDID0gcmVhZFVJbnQzMihjTWFwQnVmZiwgb2Zmc2V0KTtcbiAgICAgICAgICAgICAgICBidWZmZXJzLkMuc2V0KGdldFdpdG5lc3Moc2lnbmFsSWRDKSwgaV9zRnIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBCbGluZCBhKFgpLCBiKFgpIGFuZCBjKFgpIHBvbHlub21pYWxzIGNvZWZmaWNpZW50cyB3aXRoIGJsaW5kaW5nIHNjYWxhcnMgYlxuICAgICAgICAgICAgYnVmZmVycy5BLnNldChjaGFsbGVuZ2VzLmJbMV0sIHNEb21haW4gLSA2NCk7XG4gICAgICAgICAgICBidWZmZXJzLkEuc2V0KGNoYWxsZW5nZXMuYlsyXSwgc0RvbWFpbiAtIDMyKTtcbiAgICAgICAgICAgIGJ1ZmZlcnMuQi5zZXQoY2hhbGxlbmdlcy5iWzNdLCBzRG9tYWluIC0gNjQpO1xuICAgICAgICAgICAgYnVmZmVycy5CLnNldChjaGFsbGVuZ2VzLmJbNF0sIHNEb21haW4gLSAzMik7XG4gICAgICAgICAgICBidWZmZXJzLkMuc2V0KGNoYWxsZW5nZXMuYls1XSwgc0RvbWFpbiAtIDY0KTtcbiAgICAgICAgICAgIGJ1ZmZlcnMuQy5zZXQoY2hhbGxlbmdlcy5iWzZdLCBzRG9tYWluIC0gMzIpO1xuXG4gICAgICAgICAgICBidWZmZXJzLkEgPSBhd2FpdCBGci5iYXRjaFRvTW9udGdvbWVyeShidWZmZXJzLkEpO1xuICAgICAgICAgICAgYnVmZmVycy5CID0gYXdhaXQgRnIuYmF0Y2hUb01vbnRnb21lcnkoYnVmZmVycy5CKTtcbiAgICAgICAgICAgIGJ1ZmZlcnMuQyA9IGF3YWl0IEZyLmJhdGNoVG9Nb250Z29tZXJ5KGJ1ZmZlcnMuQyk7XG5cbiAgICAgICAgICAgIC8vIENvbXB1dGUgdGhlIGNvZWZmaWNpZW50cyBvZiB0aGUgd2lyZSBwb2x5bm9taWFscyBhKFgpLCBiKFgpIGFuZCBjKFgpIGZyb20gQSxCICYgQyBidWZmZXJzXG4gICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIsK3wrfCtyBDb21wdXRpbmcgQSBpZmZ0XCIpO1xuICAgICAgICAgICAgcG9seW5vbWlhbHMuQSA9IGF3YWl0IFBvbHlub21pYWwuZnJvbUV2YWx1YXRpb25zKGJ1ZmZlcnMuQSwgY3VydmUsIGxvZ2dlcik7XG4gICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIsK3wrfCtyBDb21wdXRpbmcgQiBpZmZ0XCIpO1xuICAgICAgICAgICAgcG9seW5vbWlhbHMuQiA9IGF3YWl0IFBvbHlub21pYWwuZnJvbUV2YWx1YXRpb25zKGJ1ZmZlcnMuQiwgY3VydmUsIGxvZ2dlcik7XG4gICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIsK3wrfCtyBDb21wdXRpbmcgQyBpZmZ0XCIpO1xuICAgICAgICAgICAgcG9seW5vbWlhbHMuQyA9IGF3YWl0IFBvbHlub21pYWwuZnJvbUV2YWx1YXRpb25zKGJ1ZmZlcnMuQywgY3VydmUsIGxvZ2dlcik7XG5cbiAgICAgICAgICAgIC8vIENvbXB1dGUgZXh0ZW5kZWQgZXZhbHVhdGlvbnMgb2YgYShYKSwgYihYKSBhbmQgYyhYKSBwb2x5bm9taWFsc1xuICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCLCt8K3wrcgQ29tcHV0aW5nIEEgZmZ0XCIpO1xuICAgICAgICAgICAgZXZhbHVhdGlvbnMuQSA9IGF3YWl0IEV2YWx1YXRpb25zLmZyb21Qb2x5bm9taWFsKHBvbHlub21pYWxzLkEsIDQsIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCLCt8K3wrcgQ29tcHV0aW5nIEIgZmZ0XCIpO1xuICAgICAgICAgICAgZXZhbHVhdGlvbnMuQiA9IGF3YWl0IEV2YWx1YXRpb25zLmZyb21Qb2x5bm9taWFsKHBvbHlub21pYWxzLkIsIDQsIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCLCt8K3wrcgQ29tcHV0aW5nIEMgZmZ0XCIpO1xuICAgICAgICAgICAgZXZhbHVhdGlvbnMuQyA9IGF3YWl0IEV2YWx1YXRpb25zLmZyb21Qb2x5bm9taWFsKHBvbHlub21pYWxzLkMsIDQsIGN1cnZlLCBsb2dnZXIpO1xuXG4gICAgICAgICAgICAvLyBDaGVjayBkZWdyZWVzXG4gICAgICAgICAgICBpZiAocG9seW5vbWlhbHMuQS5kZWdyZWUoKSA+PSB6a2V5LmRvbWFpblNpemUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJBIFBvbHlub21pYWwgaXMgbm90IHdlbGwgY2FsY3VsYXRlZFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChwb2x5bm9taWFscy5CLmRlZ3JlZSgpID49IHprZXkuZG9tYWluU2l6ZSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkIgUG9seW5vbWlhbCBpcyBub3Qgd2VsbCBjYWxjdWxhdGVkXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHBvbHlub21pYWxzLkMuZGVncmVlKCkgPj0gemtleS5kb21haW5TaXplKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQyBQb2x5bm9taWFsIGlzIG5vdCB3ZWxsIGNhbGN1bGF0ZWRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBhc3luYyBmdW5jdGlvbiBjb21wdXRlVDAoKSB7XG4gICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhgwrfCt8K3IFJlYWRpbmcgc2VjdGlvbnMgJHtaS0VZX0ZGX1FMX1NFQ1RJT059LCAke1pLRVlfRkZfUVJfU0VDVElPTn1gICtcbiAgICAgICAgICAgICAgICBgLCAke1pLRVlfRkZfUU1fU0VDVElPTn0sICR7WktFWV9GRl9RT19TRUNUSU9OfSwgJHtaS0VZX0ZGX1FDX1NFQ1RJT059LiBRIHNlbGVjdG9yc2ApO1xuICAgICAgICAgICAgLy8gUmVzZXJ2ZSBtZW1vcnkgZm9yIFEncyBldmFsdWF0aW9uc1xuICAgICAgICAgICAgZXZhbHVhdGlvbnMuUUwgPSBuZXcgRXZhbHVhdGlvbnMobmV3IEJpZ0J1ZmZlcihzRG9tYWluICogNCksIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICAgICAgZXZhbHVhdGlvbnMuUVIgPSBuZXcgRXZhbHVhdGlvbnMobmV3IEJpZ0J1ZmZlcihzRG9tYWluICogNCksIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICAgICAgZXZhbHVhdGlvbnMuUU0gPSBuZXcgRXZhbHVhdGlvbnMobmV3IEJpZ0J1ZmZlcihzRG9tYWluICogNCksIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICAgICAgZXZhbHVhdGlvbnMuUU8gPSBuZXcgRXZhbHVhdGlvbnMobmV3IEJpZ0J1ZmZlcihzRG9tYWluICogNCksIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICAgICAgZXZhbHVhdGlvbnMuUUMgPSBuZXcgRXZhbHVhdGlvbnMobmV3IEJpZ0J1ZmZlcihzRG9tYWluICogNCksIGN1cnZlLCBsb2dnZXIpO1xuXG4gICAgICAgICAgICAvLyBSZWFkIFEncyBldmFsdWF0aW9ucyBmcm9tIHprZXkgZmlsZVxuICAgICAgICAgICAgYXdhaXQgZmRaS2V5LnJlYWRUb0J1ZmZlcihldmFsdWF0aW9ucy5RTC5ldmFsLCAwLCBzRG9tYWluICogNCwgemtleVNlY3Rpb25zW1pLRVlfRkZfUUxfU0VDVElPTl1bMF0ucCArIHNEb21haW4pO1xuICAgICAgICAgICAgYXdhaXQgZmRaS2V5LnJlYWRUb0J1ZmZlcihldmFsdWF0aW9ucy5RUi5ldmFsLCAwLCBzRG9tYWluICogNCwgemtleVNlY3Rpb25zW1pLRVlfRkZfUVJfU0VDVElPTl1bMF0ucCArIHNEb21haW4pO1xuICAgICAgICAgICAgYXdhaXQgZmRaS2V5LnJlYWRUb0J1ZmZlcihldmFsdWF0aW9ucy5RTS5ldmFsLCAwLCBzRG9tYWluICogNCwgemtleVNlY3Rpb25zW1pLRVlfRkZfUU1fU0VDVElPTl1bMF0ucCArIHNEb21haW4pO1xuICAgICAgICAgICAgYXdhaXQgZmRaS2V5LnJlYWRUb0J1ZmZlcihldmFsdWF0aW9ucy5RTy5ldmFsLCAwLCBzRG9tYWluICogNCwgemtleVNlY3Rpb25zW1pLRVlfRkZfUU9fU0VDVElPTl1bMF0ucCArIHNEb21haW4pO1xuICAgICAgICAgICAgYXdhaXQgZmRaS2V5LnJlYWRUb0J1ZmZlcihldmFsdWF0aW9ucy5RQy5ldmFsLCAwLCBzRG9tYWluICogNCwgemtleVNlY3Rpb25zW1pLRVlfRkZfUUNfU0VDVElPTl1bMF0ucCArIHNEb21haW4pO1xuXG4gICAgICAgICAgICAvLyBSZWFkIExhZ3JhbmdlIHBvbHlub21pYWxzICYgZXZhbHVhdGlvbnMgZnJvbSB6a2V5IGZpbGVcbiAgICAgICAgICAgIGNvbnN0IGxhZ3JhbmdlUG9seW5vbWlhbHMgPSBhd2FpdCBiaW5GaWxlVXRpbHMucmVhZFNlY3Rpb24oZmRaS2V5LCB6a2V5U2VjdGlvbnMsIFpLRVlfRkZfTEFHUkFOR0VfU0VDVElPTik7XG4gICAgICAgICAgICBldmFsdWF0aW9ucy5sYWdyYW5nZTEgPSBuZXcgRXZhbHVhdGlvbnMobGFncmFuZ2VQb2x5bm9taWFscywgY3VydmUsIGxvZ2dlcik7XG5cbiAgICAgICAgICAgIC8vIFJlc2VydmUgbWVtb3J5IGZvciBidWZmZXJzIFQwXG4gICAgICAgICAgICBidWZmZXJzLlQwID0gbmV3IEJpZ0J1ZmZlcihzRG9tYWluICogNCk7XG5cbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiwrfCt8K3IENvbXB1dGluZyBUMCBldmFsdWF0aW9uc1wiKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgemtleS5kb21haW5TaXplICogNDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGxvZ2dlciAmJiAoMCAhPT0gaSkgJiYgKGkgJSAxMDAwMDAgPT09IDApKSBsb2dnZXIuaW5mbyhgICAgICAgVDAgZXZhbHVhdGlvbiAke2l9LyR7emtleS5kb21haW5TaXplICogNH1gKTtcblxuICAgICAgICAgICAgICAgIC8vIEdldCByZWxhdGVkIGV2YWx1YXRpb25zIHRvIGNvbXB1dGUgY3VycmVudCBUMCBldmFsdWF0aW9uXG4gICAgICAgICAgICAgICAgY29uc3QgYSA9IGV2YWx1YXRpb25zLkEuZ2V0RXZhbHVhdGlvbihpKTtcbiAgICAgICAgICAgICAgICBjb25zdCBiID0gZXZhbHVhdGlvbnMuQi5nZXRFdmFsdWF0aW9uKGkpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGMgPSBldmFsdWF0aW9ucy5DLmdldEV2YWx1YXRpb24oaSk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBxbCA9IGV2YWx1YXRpb25zLlFMLmdldEV2YWx1YXRpb24oaSk7XG4gICAgICAgICAgICAgICAgY29uc3QgcXIgPSBldmFsdWF0aW9ucy5RUi5nZXRFdmFsdWF0aW9uKGkpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHFtID0gZXZhbHVhdGlvbnMuUU0uZ2V0RXZhbHVhdGlvbihpKTtcbiAgICAgICAgICAgICAgICBjb25zdCBxbyA9IGV2YWx1YXRpb25zLlFPLmdldEV2YWx1YXRpb24oaSk7XG4gICAgICAgICAgICAgICAgY29uc3QgcWMgPSBldmFsdWF0aW9ucy5RQy5nZXRFdmFsdWF0aW9uKGkpO1xuXG4gICAgICAgICAgICAgICAgLy8gQ29tcHV0ZSBjdXJyZW50IHB1YmxpYyBpbnB1dFxuICAgICAgICAgICAgICAgIGxldCBwaSA9IEZyLnplcm87XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB6a2V5Lm5QdWJsaWM7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBvZmZzZXQgPSAoaiAqIDUgKiB6a2V5LmRvbWFpblNpemUpICsgemtleS5kb21haW5TaXplICsgaTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBsUG9sID0gZXZhbHVhdGlvbnMubGFncmFuZ2UxLmdldEV2YWx1YXRpb24ob2Zmc2V0KTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYVZhbCA9IGJ1ZmZlcnMuQS5zbGljZShqICogc0ZyLCAoaiArIDEpICogc0ZyKTtcblxuICAgICAgICAgICAgICAgICAgICBwaSA9IEZyLnN1YihwaSwgRnIubXVsKGxQb2wsIGFWYWwpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvL1QwKFgpID0gW3FfTChYKcK3YShYKSArIHFfUihYKcK3YihYKSArIHFfTShYKcK3YShYKcK3YihYKSArIHFfTyhYKcK3YyhYKSArIHFfQyhYKSArIFBJKFgpXSDCtyAxL1pfSChYKVxuICAgICAgICAgICAgICAgIC8vIENvbXB1dGUgZmlyc3QgVDAoWCnCt1pfSChYKSwgc28gZGl2aWRlIGxhdGVyIHRoZSByZXN1bHRpbmcgcG9seW5vbWlhbCBieSBaX0goWClcbiAgICAgICAgICAgICAgICAvLyBleHByZXNzaW9uIDEgLT4gcV9MKFgpwrdhKFgpXG4gICAgICAgICAgICAgICAgY29uc3QgZTEgPSBGci5tdWwoYSwgcWwpO1xuXG4gICAgICAgICAgICAgICAgLy8gZXhwcmVzc2lvbiAyIC0+IHFfUihYKcK3YihYKVxuICAgICAgICAgICAgICAgIGNvbnN0IGUyID0gRnIubXVsKGIsIHFyKTtcblxuICAgICAgICAgICAgICAgIC8vIGV4cHJlc3Npb24gMyAtPiBxX00oWCnCt2EoWCnCt2IoWClcbiAgICAgICAgICAgICAgICBjb25zdCBlMyA9IEZyLm11bChGci5tdWwoYSwgYiksIHFtKTtcblxuICAgICAgICAgICAgICAgIC8vIGV4cHJlc3Npb24gNCAtPiBxX08oWCnCt2MoWClcbiAgICAgICAgICAgICAgICBjb25zdCBlNCA9IEZyLm11bChjLCBxbyk7XG5cbiAgICAgICAgICAgICAgICAvLyB0MCA9IGV4cHJlc3Npb25zIDEgKyBleHByZXNzaW9uIDIgKyBleHByZXNzaW9uIDMgKyBleHByZXNzaW9uIDQgKyBxYyArIHBpXG4gICAgICAgICAgICAgICAgY29uc3QgdDAgPSBGci5hZGQoZTEsIEZyLmFkZChlMiwgRnIuYWRkKGUzLCBGci5hZGQoZTQsIEZyLmFkZChxYywgcGkpKSkpKTtcblxuICAgICAgICAgICAgICAgIGJ1ZmZlcnMuVDAuc2V0KHQwLCBpICogc0ZyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCJidWZmZXIgVDA6IFwiICsgYnVmZmVycy5UMC5ieXRlTGVuZ3RoIC8gc0ZyKTtcblxuICAgICAgICAgICAgLy8gQ29tcHV0ZSB0aGUgY29lZmZpY2llbnRzIG9mIHRoZSBwb2x5bm9taWFsIFQwKFgpIGZyb20gYnVmZmVycy5UMFxuICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCLCt8K3wrcgQ29tcHV0aW5nIFQwIGlmZnRcIik7XG4gICAgICAgICAgICBwb2x5bm9taWFscy5UMCA9IGF3YWl0IFBvbHlub21pYWwuZnJvbUV2YWx1YXRpb25zKGJ1ZmZlcnMuVDAsIGN1cnZlLCBsb2dnZXIpO1xuXG4gICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIlQwIGxlbmd0aDogXCIgKyBwb2x5bm9taWFscy5UMC5sZW5ndGgoKSk7XG4gICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIlQwIGRlZ3JlZTogXCIgKyBwb2x5bm9taWFscy5UMC5kZWdyZWUoKSk7XG5cbiAgICAgICAgICAgIC8vIERpdmlkZSB0aGUgcG9seW5vbWlhbCBUMCBieSBaX0goWClcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiwrfCt8K3IENvbXB1dGluZyBUMCAvIFpIXCIpO1xuICAgICAgICAgICAgcG9seW5vbWlhbHMuVDAuZGl2QnlaZXJvZmllcih6a2V5LmRvbWFpblNpemUsIEZyLm9uZSk7XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGRlZ3JlZVxuICAgICAgICAgICAgaWYgKHBvbHlub21pYWxzLlQwLmRlZ3JlZSgpID49IDIgKiB6a2V5LmRvbWFpblNpemUgLSAyKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUMCBQb2x5bm9taWFsIGlzIG5vdCB3ZWxsIGNhbGN1bGF0ZWQgKGRlZ3JlZSBpcyAke3BvbHlub21pYWxzLlQwLmRlZ3JlZSgpfSBhbmQgbXVzdCBiZSBsZXNzIHRoYW4gJHsyICogemtleS5kb21haW5TaXplICsgMn1gKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZGVsZXRlIGJ1ZmZlcnMuVDA7XG4gICAgICAgIH1cblxuICAgICAgICBhc3luYyBmdW5jdGlvbiBjb21wdXRlQzEoKSB7XG4gICAgICAgICAgICBsZXQgQzEgPSBuZXcgQ1BvbHlub21pYWwoNCwgY3VydmUsIGxvZ2dlcik7XG4gICAgICAgICAgICBDMS5hZGRQb2x5bm9taWFsKDAsIHBvbHlub21pYWxzLkEpO1xuICAgICAgICAgICAgQzEuYWRkUG9seW5vbWlhbCgxLCBwb2x5bm9taWFscy5CKTtcbiAgICAgICAgICAgIEMxLmFkZFBvbHlub21pYWwoMiwgcG9seW5vbWlhbHMuQyk7XG4gICAgICAgICAgICBDMS5hZGRQb2x5bm9taWFsKDMsIHBvbHlub21pYWxzLlQwKTtcblxuICAgICAgICAgICAgcG9seW5vbWlhbHMuQzEgPSBDMS5nZXRQb2x5bm9taWFsKCk7XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGRlZ3JlZVxuICAgICAgICAgICAgaWYgKHBvbHlub21pYWxzLkMxLmRlZ3JlZSgpID49IDggKiB6a2V5LmRvbWFpblNpemUgLSA4KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQzEgUG9seW5vbWlhbCBpcyBub3Qgd2VsbCBjYWxjdWxhdGVkXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMgZnVuY3Rpb24gcm91bmQyKCkge1xuICAgICAgICAvLyBTVEVQIDIuMSAtIENvbXB1dGUgcGVybXV0YXRpb24gY2hhbGxlbmdlIGJldGEgYW5kIGdhbW1hIOKIiCBGXG4gICAgICAgIC8vIENvbXB1dGUgcGVybXV0YXRpb24gY2hhbGxlbmdlIGJldGFcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCI+IENvbXB1dGluZyBjaGFsbGVuZ2VzIGJldGEgYW5kIGdhbW1hXCIpO1xuICAgICAgICBjb25zdCB0cmFuc2NyaXB0ID0gbmV3IEtlY2NhazI1NlRyYW5zY3JpcHQoY3VydmUpO1xuXG4gICAgICAgIC8vIEFkZCBDMCB0byB0aGUgdHJhbnNjcmlwdFxuICAgICAgICB0cmFuc2NyaXB0LmFkZFBvbENvbW1pdG1lbnQoemtleS5DMCk7XG5cbiAgICAgICAgLy8gQWRkIEEgdG8gdGhlIHRyYW5zY3JpcHRcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB6a2V5Lm5QdWJsaWM7IGkrKykge1xuICAgICAgICAgICAgdHJhbnNjcmlwdC5hZGRTY2FsYXIoYnVmZmVycy5BLnNsaWNlKGkgKiBzRnIsIGkgKiBzRnIgKyBzRnIpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEFkZCBDMSB0byB0aGUgdHJhbnNjcmlwdFxuICAgICAgICB0cmFuc2NyaXB0LmFkZFBvbENvbW1pdG1lbnQocHJvb2YuZ2V0UG9seW5vbWlhbChcIkMxXCIpKTtcblxuICAgICAgICBjaGFsbGVuZ2VzLmJldGEgPSB0cmFuc2NyaXB0LmdldENoYWxsZW5nZSgpO1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIsK3wrfCtyBjaGFsbGVuZ2VzLmJldGE6IFwiICsgRnIudG9TdHJpbmcoY2hhbGxlbmdlcy5iZXRhKSk7XG5cbiAgICAgICAgLy8gQ29tcHV0ZSBwZXJtdXRhdGlvbiBjaGFsbGVuZ2UgZ2FtbWFcbiAgICAgICAgdHJhbnNjcmlwdC5yZXNldCgpO1xuICAgICAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihjaGFsbGVuZ2VzLmJldGEpO1xuICAgICAgICBjaGFsbGVuZ2VzLmdhbW1hID0gdHJhbnNjcmlwdC5nZXRDaGFsbGVuZ2UoKTtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCLCt8K3wrcgY2hhbGxlbmdlcy5nYW1tYTogXCIgKyBGci50b1N0cmluZyhjaGFsbGVuZ2VzLmdhbW1hKSk7XG5cbiAgICAgICAgLy8gU1RFUCAyLjIgLSBDb21wdXRlIHBlcm11dGF0aW9uIHBvbHlub21pYWwgeihYKVxuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gQ29tcHV0aW5nIFogcG9seW5vbWlhbFwiKTtcbiAgICAgICAgYXdhaXQgY29tcHV0ZVooKTtcblxuICAgICAgICAvLyBTVEVQIDIuMyAtIENvbXB1dGUgcXVvdGllbnQgcG9seW5vbWlhbCBUMShYKSBhbmQgVDIoWClcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCI+IENvbXB1dGluZyBUMSBwb2x5bm9taWFsXCIpO1xuICAgICAgICBhd2FpdCBjb21wdXRlVDEoKTtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCI+IENvbXB1dGluZyBUMiBwb2x5bm9taWFsXCIpO1xuICAgICAgICBhd2FpdCBjb21wdXRlVDIoKTtcblxuICAgICAgICAvLyBTVEVQIDIuNCAtIENvbXB1dGUgdGhlIEZGVC1zdHlsZSBjb21iaW5hdGlvbiBwb2x5bm9taWFsIEMyKFgpXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBDb21wdXRpbmcgQzIgcG9seW5vbWlhbFwiKTtcbiAgICAgICAgYXdhaXQgY29tcHV0ZUMyKCk7XG5cbiAgICAgICAgLy8gVGhlIHNlY29uZCBvdXRwdXQgb2YgdGhlIHByb3ZlciBpcyAoW0MyXV8xKVxuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gQ29tcHV0aW5nIEMyIG11bHRpIGV4cG9uZW50aWF0aW9uXCIpO1xuICAgICAgICBsZXQgY29tbWl0QzIgPSBhd2FpdCBwb2x5bm9taWFscy5DMi5tdWx0aUV4cG9uZW50aWF0aW9uKFBUYXUsIFwiQzJcIik7XG4gICAgICAgIHByb29mLmFkZFBvbHlub21pYWwoXCJDMlwiLCBjb21taXRDMik7XG5cbiAgICAgICAgcmV0dXJuIDA7XG5cbiAgICAgICAgYXN5bmMgZnVuY3Rpb24gY29tcHV0ZVooKSB7XG4gICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIsK3wrfCtyBDb21wdXRpbmcgWiBldmFsdWF0aW9uc1wiKTtcblxuICAgICAgICAgICAgbGV0IG51bUFyciA9IG5ldyBCaWdCdWZmZXIoc0RvbWFpbik7XG4gICAgICAgICAgICBsZXQgZGVuQXJyID0gbmV3IEJpZ0J1ZmZlcihzRG9tYWluKTtcblxuICAgICAgICAgICAgLy8gU2V0IHRoZSBmaXJzdCB2YWx1ZXMgdG8gMVxuICAgICAgICAgICAgbnVtQXJyLnNldChGci5vbmUsIDApO1xuICAgICAgICAgICAgZGVuQXJyLnNldChGci5vbmUsIDApO1xuXG4gICAgICAgICAgICAvLyBTZXQgaW5pdGlhbCBvbWVnYVxuICAgICAgICAgICAgbGV0IHcgPSBGci5vbmU7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHprZXkuZG9tYWluU2l6ZTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGxvZ2dlciAmJiAoMCAhPT0gaSkgJiYgKGkgJSAxMDAwMDAgPT09IDApKSBsb2dnZXIuaW5mbyhgICAgIFogZXZhbHVhdGlvbiAke2l9LyR7emtleS5kb21haW5TaXplfWApO1xuICAgICAgICAgICAgICAgIGNvbnN0IGlfc0ZyID0gaSAqIHNGcjtcblxuICAgICAgICAgICAgICAgIC8vIFooWCkgOj0gbnVtQXJyIC8gZGVuQXJyXG4gICAgICAgICAgICAgICAgLy8gbnVtQXJyIDo9IChhICsgYmV0YcK3z4kgKyBnYW1tYSkoYiArIGJldGHCt8+JwrdrMSArIGdhbW1hKShjICsgYmV0YcK3z4nCt2syICsgZ2FtbWEpXG4gICAgICAgICAgICAgICAgY29uc3QgYmV0YXcgPSBGci5tdWwoY2hhbGxlbmdlcy5iZXRhLCB3KTtcblxuICAgICAgICAgICAgICAgIGxldCBudW0xID0gYnVmZmVycy5BLnNsaWNlKGlfc0ZyLCBpX3NGciArIHNGcik7XG4gICAgICAgICAgICAgICAgbnVtMSA9IEZyLmFkZChudW0xLCBiZXRhdyk7XG4gICAgICAgICAgICAgICAgbnVtMSA9IEZyLmFkZChudW0xLCBjaGFsbGVuZ2VzLmdhbW1hKTtcblxuICAgICAgICAgICAgICAgIGxldCBudW0yID0gYnVmZmVycy5CLnNsaWNlKGlfc0ZyLCBpX3NGciArIHNGcik7XG4gICAgICAgICAgICAgICAgbnVtMiA9IEZyLmFkZChudW0yLCBGci5tdWwoemtleS5rMSwgYmV0YXcpKTtcbiAgICAgICAgICAgICAgICBudW0yID0gRnIuYWRkKG51bTIsIGNoYWxsZW5nZXMuZ2FtbWEpO1xuXG4gICAgICAgICAgICAgICAgbGV0IG51bTMgPSBidWZmZXJzLkMuc2xpY2UoaV9zRnIsIGlfc0ZyICsgc0ZyKTtcbiAgICAgICAgICAgICAgICBudW0zID0gRnIuYWRkKG51bTMsIEZyLm11bCh6a2V5LmsyLCBiZXRhdykpO1xuICAgICAgICAgICAgICAgIG51bTMgPSBGci5hZGQobnVtMywgY2hhbGxlbmdlcy5nYW1tYSk7XG5cbiAgICAgICAgICAgICAgICBsZXQgbnVtID0gRnIubXVsKG51bTEsIEZyLm11bChudW0yLCBudW0zKSk7XG5cbiAgICAgICAgICAgICAgICAvLyBkZW5BcnIgOj0gKGEgKyBiZXRhwrdzaWdtYTEgKyBnYW1tYSkoYiArIGJldGHCt3NpZ21hMiArIGdhbW1hKShjICsgYmV0YcK3c2lnbWEzICsgZ2FtbWEpXG4gICAgICAgICAgICAgICAgbGV0IGRlbjEgPSBidWZmZXJzLkEuc2xpY2UoaV9zRnIsIGlfc0ZyICsgc0ZyKTtcbiAgICAgICAgICAgICAgICBkZW4xID0gRnIuYWRkKGRlbjEsIEZyLm11bChjaGFsbGVuZ2VzLmJldGEsIGV2YWx1YXRpb25zLlNpZ21hMS5nZXRFdmFsdWF0aW9uKGkgKiA0KSkpO1xuICAgICAgICAgICAgICAgIGRlbjEgPSBGci5hZGQoZGVuMSwgY2hhbGxlbmdlcy5nYW1tYSk7XG5cbiAgICAgICAgICAgICAgICBsZXQgZGVuMiA9IGJ1ZmZlcnMuQi5zbGljZShpX3NGciwgaV9zRnIgKyBzRnIpO1xuICAgICAgICAgICAgICAgIGRlbjIgPSBGci5hZGQoZGVuMiwgRnIubXVsKGNoYWxsZW5nZXMuYmV0YSwgZXZhbHVhdGlvbnMuU2lnbWEyLmdldEV2YWx1YXRpb24oaSAqIDQpKSk7XG4gICAgICAgICAgICAgICAgZGVuMiA9IEZyLmFkZChkZW4yLCBjaGFsbGVuZ2VzLmdhbW1hKTtcblxuICAgICAgICAgICAgICAgIGxldCBkZW4zID0gYnVmZmVycy5DLnNsaWNlKGlfc0ZyLCBpX3NGciArIHNGcik7XG4gICAgICAgICAgICAgICAgZGVuMyA9IEZyLmFkZChkZW4zLCBGci5tdWwoY2hhbGxlbmdlcy5iZXRhLCBldmFsdWF0aW9ucy5TaWdtYTMuZ2V0RXZhbHVhdGlvbihpICogNCkpKTtcbiAgICAgICAgICAgICAgICBkZW4zID0gRnIuYWRkKGRlbjMsIGNoYWxsZW5nZXMuZ2FtbWEpO1xuXG4gICAgICAgICAgICAgICAgbGV0IGRlbiA9IEZyLm11bChkZW4xLCBGci5tdWwoZGVuMiwgZGVuMykpO1xuXG4gICAgICAgICAgICAgICAgLy8gTXVsdGlwbHkgY3VycmVudCBudW0gdmFsdWUgd2l0aCB0aGUgcHJldmlvdXMgb25lIHNhdmVkIGluIG51bUFyclxuICAgICAgICAgICAgICAgIG51bSA9IEZyLm11bChudW1BcnIuc2xpY2UoaV9zRnIsIGlfc0ZyICsgc0ZyKSwgbnVtKTtcbiAgICAgICAgICAgICAgICBudW1BcnIuc2V0KG51bSwgKChpICsgMSkgJSB6a2V5LmRvbWFpblNpemUpICogc0ZyKTtcblxuICAgICAgICAgICAgICAgIC8vIE11bHRpcGx5IGN1cnJlbnQgZGVuIHZhbHVlIHdpdGggdGhlIHByZXZpb3VzIG9uZSBzYXZlZCBpbiBkZW5BcnJcbiAgICAgICAgICAgICAgICBkZW4gPSBGci5tdWwoZGVuQXJyLnNsaWNlKGlfc0ZyLCBpX3NGciArIHNGciksIGRlbik7XG4gICAgICAgICAgICAgICAgZGVuQXJyLnNldChkZW4sICgoaSArIDEpICUgemtleS5kb21haW5TaXplKSAqIHNGcik7XG5cbiAgICAgICAgICAgICAgICAvLyBOZXh0IG9tZWdhXG4gICAgICAgICAgICAgICAgdyA9IEZyLm11bCh3LCBGci53W3prZXkucG93ZXJdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIENvbXB1dGUgdGhlIGludmVyc2Ugb2YgZGVuQXJyIHRvIGNvbXB1dGUgaW4gdGhlIG5leHQgY29tbWFuZCB0aGVcbiAgICAgICAgICAgIC8vIGRpdmlzaW9uIG51bUFyci9kZW5BcnIgYnkgbXVsdGlwbHlpbmcgbnVtIMK3IDEvZGVuQXJyXG4gICAgICAgICAgICBkZW5BcnIgPSBhd2FpdCBGci5iYXRjaEludmVyc2UoZGVuQXJyKTtcblxuICAgICAgICAgICAgLy8gVE9ETzogRG8gaXQgaW4gYXNzZW1ibHkgYW5kIGluIHBhcmFsbGVsXG4gICAgICAgICAgICAvLyBNdWx0aXBseSBudW1BcnIgwrcgZGVuQXJyIHdoZXJlIGRlbkFyciB3YXMgaW52ZXJ0ZWQgaW4gdGhlIHByZXZpb3VzIGNvbW1hbmRcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgemtleS5kb21haW5TaXplOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBpX3NGciA9IGkgKiBzRnI7XG5cbiAgICAgICAgICAgICAgICBjb25zdCB6ID0gRnIubXVsKG51bUFyci5zbGljZShpX3NGciwgaV9zRnIgKyBzRnIpLCBkZW5BcnIuc2xpY2UoaV9zRnIsIGlfc0ZyICsgc0ZyKSk7XG4gICAgICAgICAgICAgICAgbnVtQXJyLnNldCh6LCBpX3NGcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBGcm9tIG5vdyBvbiB0aGUgdmFsdWVzIHNhdmVkIG9uIG51bUFyciB3aWxsIGJlIFooWCkgYnVmZmVyXG4gICAgICAgICAgICBidWZmZXJzLlogPSBudW1BcnI7XG5cbiAgICAgICAgICAgIGlmICghRnIuZXEobnVtQXJyLnNsaWNlKDAsIHNGciksIEZyLm9uZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb3B5IGNvbnN0cmFpbnRzIGRvZXMgbm90IG1hdGNoXCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDb21wdXRlIHBvbHlub21pYWwgY29lZmZpY2llbnRzIHooWCkgZnJvbSBidWZmZXJzLlpcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiwrfCt8K3IENvbXB1dGluZyBaIGlmZnRcIik7XG4gICAgICAgICAgICBwb2x5bm9taWFscy5aID0gYXdhaXQgUG9seW5vbWlhbC5mcm9tRXZhbHVhdGlvbnMoYnVmZmVycy5aLCBjdXJ2ZSwgbG9nZ2VyKTtcblxuICAgICAgICAgICAgLy8gQ29tcHV0ZSBleHRlbmRlZCBldmFsdWF0aW9ucyBvZiB6KFgpIHBvbHlub21pYWxcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiwrfCt8K3IENvbXB1dGluZyBaIGZmdFwiKTtcbiAgICAgICAgICAgIGV2YWx1YXRpb25zLlogPSBhd2FpdCBFdmFsdWF0aW9ucy5mcm9tUG9seW5vbWlhbChwb2x5bm9taWFscy5aLCA0LCBjdXJ2ZSwgbG9nZ2VyKTtcblxuICAgICAgICAgICAgLy8gQmxpbmQgeihYKSBwb2x5bm9taWFsIGNvZWZmaWNpZW50cyB3aXRoIGJsaW5kaW5nIHNjYWxhcnMgYlxuICAgICAgICAgICAgcG9seW5vbWlhbHMuWi5ibGluZENvZWZmaWNpZW50cyhbY2hhbGxlbmdlcy5iWzldLCBjaGFsbGVuZ2VzLmJbOF0sIGNoYWxsZW5nZXMuYls3XV0pO1xuXG4gICAgICAgICAgICAvLyBDaGVjayBkZWdyZWVcbiAgICAgICAgICAgIGlmIChwb2x5bm9taWFscy5aLmRlZ3JlZSgpID49IHprZXkuZG9tYWluU2l6ZSArIDMpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJaIFBvbHlub21pYWwgaXMgbm90IHdlbGwgY2FsY3VsYXRlZFwiKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZGVsZXRlIGJ1ZmZlcnMuWjtcbiAgICAgICAgfVxuXG4gICAgICAgIGFzeW5jIGZ1bmN0aW9uIGNvbXB1dGVUMSgpIHtcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiwrfCt8K3IENvbXB1dGluZyBUMSBldmFsdWF0aW9uc1wiKTtcblxuICAgICAgICAgICAgYnVmZmVycy5UMSA9IG5ldyBCaWdCdWZmZXIoc0RvbWFpbiAqIDIpO1xuICAgICAgICAgICAgYnVmZmVycy5UMXogPSBuZXcgQmlnQnVmZmVyKHNEb21haW4gKiAyKTtcblxuICAgICAgICAgICAgLy8gU2V0IGluaXRpYWwgb21lZ2FcbiAgICAgICAgICAgIGxldCBvbWVnYSA9IEZyLm9uZTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgemtleS5kb21haW5TaXplICogMjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGxvZ2dlciAmJiAoMCAhPT0gaSkgJiYgKGkgJSAxMDAwMDAgPT09IDApKSBsb2dnZXIuaW5mbyhgICAgIFQxIGV2YWx1YXRpb24gJHtpfS8ke3prZXkuZG9tYWluU2l6ZSAqIDR9YCk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBvbWVnYTIgPSBGci5zcXVhcmUob21lZ2EpO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgeiA9IGV2YWx1YXRpb25zLlouZ2V0RXZhbHVhdGlvbihpICogMik7XG4gICAgICAgICAgICAgICAgY29uc3QgenAgPSBGci5hZGQoRnIuYWRkKEZyLm11bChjaGFsbGVuZ2VzLmJbN10sIG9tZWdhMiksIEZyLm11bChjaGFsbGVuZ2VzLmJbOF0sIG9tZWdhKSksIGNoYWxsZW5nZXMuYls5XSk7XG5cbiAgICAgICAgICAgICAgICAvLyBUMShYKSA6PSAoeihYKSAtIDEpIMK3IExfMShYKVxuICAgICAgICAgICAgICAgIC8vIENvbXB1dGUgZmlyc3QgVDEoWCnCt1pfSChYKSwgc28gZGl2aWRlIGxhdGVyIHRoZSByZXN1bHRpbmcgcG9seW5vbWlhbCBieSBaX0goWClcbiAgICAgICAgICAgICAgICBjb25zdCBsYWdyYW5nZTEgPSBldmFsdWF0aW9ucy5sYWdyYW5nZTEuZ2V0RXZhbHVhdGlvbih6a2V5LmRvbWFpblNpemUgKyBpICogMik7XG4gICAgICAgICAgICAgICAgbGV0IHQxID0gRnIubXVsKEZyLnN1Yih6LCBGci5vbmUpLCBsYWdyYW5nZTEpO1xuICAgICAgICAgICAgICAgIGxldCB0MXogPSBGci5tdWwoenAsIGxhZ3JhbmdlMSk7XG5cbiAgICAgICAgICAgICAgICBidWZmZXJzLlQxLnNldCh0MSwgaSAqIHNGcik7XG4gICAgICAgICAgICAgICAgYnVmZmVycy5UMXouc2V0KHQxeiwgaSAqIHNGcik7XG5cbiAgICAgICAgICAgICAgICAvLyBDb21wdXRlIG5leHQgb21lZ2FcbiAgICAgICAgICAgICAgICBvbWVnYSA9IEZyLm11bChvbWVnYSwgRnIud1t6a2V5LnBvd2VyICsgMV0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDb21wdXRlIHRoZSBjb2VmZmljaWVudHMgb2YgdGhlIHBvbHlub21pYWwgVDEoWCkgZnJvbSBidWZmZXJzLlQxXG4gICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIsK3wrfCtyBDb21wdXRpbmcgVDEgaWZmdFwiKTtcbiAgICAgICAgICAgIHBvbHlub21pYWxzLlQxID0gYXdhaXQgUG9seW5vbWlhbC5mcm9tRXZhbHVhdGlvbnMoYnVmZmVycy5UMSwgY3VydmUsIGxvZ2dlcik7XG5cbiAgICAgICAgICAgIC8vIERpdmlkZSB0aGUgcG9seW5vbWlhbCBUMSBieSBaX0goWClcbiAgICAgICAgICAgIHBvbHlub21pYWxzLlQxLmRpdkJ5WmVyb2ZpZXIoemtleS5kb21haW5TaXplLCBGci5vbmUpO1xuXG4gICAgICAgICAgICAvLyBDb21wdXRlIHRoZSBjb2VmZmljaWVudHMgb2YgdGhlIHBvbHlub21pYWwgVDF6KFgpIGZyb20gYnVmZmVycy5UMXpcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiwrfCt8K3IENvbXB1dGluZyBUMXogaWZmdFwiKTtcbiAgICAgICAgICAgIHBvbHlub21pYWxzLlQxeiA9IGF3YWl0IFBvbHlub21pYWwuZnJvbUV2YWx1YXRpb25zKGJ1ZmZlcnMuVDF6LCBjdXJ2ZSwgbG9nZ2VyKTtcblxuICAgICAgICAgICAgLy8gQWRkIHRoZSBwb2x5bm9taWFsIFQxeiB0byBUMSB0byBnZXQgdGhlIGZpbmFsIHBvbHlub21pYWwgVDFcbiAgICAgICAgICAgIHBvbHlub21pYWxzLlQxLmFkZChwb2x5bm9taWFscy5UMXopO1xuXG4gICAgICAgICAgICAvLyBDaGVjayBkZWdyZWVcbiAgICAgICAgICAgIGlmIChwb2x5bm9taWFscy5UMS5kZWdyZWUoKSA+PSB6a2V5LmRvbWFpblNpemUgKyAyKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVDEgUG9seW5vbWlhbCBpcyBub3Qgd2VsbCBjYWxjdWxhdGVkXCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkZWxldGUgYnVmZmVycy5UMTtcbiAgICAgICAgICAgIGRlbGV0ZSBidWZmZXJzLlQxejtcbiAgICAgICAgICAgIGRlbGV0ZSBwb2x5bm9taWFscy5UMXo7XG4gICAgICAgIH1cblxuICAgICAgICBhc3luYyBmdW5jdGlvbiBjb21wdXRlVDIoKSB7XG4gICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIsK3wrfCtyBDb21wdXRpbmcgVDIgZXZhbHVhdGlvbnNcIik7XG5cbiAgICAgICAgICAgIGJ1ZmZlcnMuVDIgPSBuZXcgQmlnQnVmZmVyKHNEb21haW4gKiA0KTtcbiAgICAgICAgICAgIGJ1ZmZlcnMuVDJ6ID0gbmV3IEJpZ0J1ZmZlcihzRG9tYWluICogNCk7XG5cbiAgICAgICAgICAgIC8vIFNldCBpbml0aWFsIG9tZWdhXG4gICAgICAgICAgICBsZXQgb21lZ2EgPSBGci5vbmU7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHprZXkuZG9tYWluU2l6ZSAqIDQ7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChsb2dnZXIgJiYgKDAgIT09IGkpICYmIChpICUgMTAwMDAwID09PSAwKSkgbG9nZ2VyLmluZm8oYCAgICBUMiBldmFsdWF0aW9uICR7aX0vJHt6a2V5LmRvbWFpblNpemUgKiA0fWApO1xuXG4gICAgICAgICAgICAgICAgY29uc3Qgb21lZ2EyID0gRnIuc3F1YXJlKG9tZWdhKTtcbiAgICAgICAgICAgICAgICBjb25zdCBvbWVnYVcgPSBGci5tdWwob21lZ2EsIEZyLndbemtleS5wb3dlcl0pO1xuICAgICAgICAgICAgICAgIGNvbnN0IG9tZWdhVzIgPSBGci5zcXVhcmUob21lZ2FXKTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IGEgPSBldmFsdWF0aW9ucy5BLmdldEV2YWx1YXRpb24oaSk7XG4gICAgICAgICAgICAgICAgY29uc3QgYiA9IGV2YWx1YXRpb25zLkIuZ2V0RXZhbHVhdGlvbihpKTtcbiAgICAgICAgICAgICAgICBjb25zdCBjID0gZXZhbHVhdGlvbnMuQy5nZXRFdmFsdWF0aW9uKGkpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHogPSBldmFsdWF0aW9ucy5aLmdldEV2YWx1YXRpb24oaSk7XG4gICAgICAgICAgICAgICAgY29uc3QgelcgPSBldmFsdWF0aW9ucy5aLmdldEV2YWx1YXRpb24oKHprZXkuZG9tYWluU2l6ZSAqIDQgKyA0ICsgaSkgJSAoemtleS5kb21haW5TaXplICogNCkpO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgenAgPSBGci5hZGQoRnIuYWRkKEZyLm11bChjaGFsbGVuZ2VzLmJbN10sIG9tZWdhMiksIEZyLm11bChjaGFsbGVuZ2VzLmJbOF0sIG9tZWdhKSksIGNoYWxsZW5nZXMuYls5XSk7XG4gICAgICAgICAgICAgICAgY29uc3QgeldwID0gRnIuYWRkKEZyLmFkZChGci5tdWwoY2hhbGxlbmdlcy5iWzddLCBvbWVnYVcyKSwgRnIubXVsKGNoYWxsZW5nZXMuYls4XSwgb21lZ2FXKSksIGNoYWxsZW5nZXMuYls5XSk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBzaWdtYTEgPSBldmFsdWF0aW9ucy5TaWdtYTEuZ2V0RXZhbHVhdGlvbihpKTtcbiAgICAgICAgICAgICAgICBjb25zdCBzaWdtYTIgPSBldmFsdWF0aW9ucy5TaWdtYTIuZ2V0RXZhbHVhdGlvbihpKTtcbiAgICAgICAgICAgICAgICBjb25zdCBzaWdtYTMgPSBldmFsdWF0aW9ucy5TaWdtYTMuZ2V0RXZhbHVhdGlvbihpKTtcblxuICAgICAgICAgICAgICAgIC8vIFQyKFgpIDo9IFsgKGEoWCkgKyBiZXRhwrdYICsgZ2FtbWEpKGIoWCkgKyBiZXRhwrdrMcK3WCArIGdhbW1hKShjKFgpICsgYmV0YcK3azLCt1ggKyBnYW1tYSl6KFgpXG4gICAgICAgICAgICAgICAgLy8gICAgICAgICAgIC0oYShYKSArIGJldGHCt3NpZ21hMShYKSArIGdhbW1hKShiKFgpICsgYmV0YcK3c2lnbWEyKFgpICsgZ2FtbWEpKGMoWCkgKyBiZXRhwrdzaWdtYTMoWCkgKyBnYW1tYSl6KFjPiSldIMK3IDEvWl9IKFgpXG4gICAgICAgICAgICAgICAgLy8gQ29tcHV0ZSBmaXJzdCBUMihYKcK3Wl9IKFgpLCBzbyBkaXZpZGUgbGF0ZXIgdGhlIHJlc3VsdGluZyBwb2x5bm9taWFsIGJ5IFpfSChYKVxuXG4gICAgICAgICAgICAgICAgLy8gZXhwcmVzc2lvbiAxIC0+IChhKFgpICsgYmV0YcK3WCArIGdhbW1hKShiKFgpICsgYmV0YcK3azHCt1ggKyBnYW1tYSkoYyhYKSArIGJldGHCt2sywrdYICsgZ2FtbWEpeihYKVxuICAgICAgICAgICAgICAgIGNvbnN0IGJldGFYID0gRnIubXVsKGNoYWxsZW5nZXMuYmV0YSwgb21lZ2EpO1xuXG4gICAgICAgICAgICAgICAgbGV0IGUxMSA9IEZyLmFkZChhLCBiZXRhWCk7XG4gICAgICAgICAgICAgICAgZTExID0gRnIuYWRkKGUxMSwgY2hhbGxlbmdlcy5nYW1tYSk7XG5cbiAgICAgICAgICAgICAgICBsZXQgZTEyID0gRnIuYWRkKGIsIEZyLm11bChiZXRhWCwgemtleS5rMSkpO1xuICAgICAgICAgICAgICAgIGUxMiA9IEZyLmFkZChlMTIsIGNoYWxsZW5nZXMuZ2FtbWEpO1xuXG4gICAgICAgICAgICAgICAgbGV0IGUxMyA9IEZyLmFkZChjLCBGci5tdWwoYmV0YVgsIHprZXkuazIpKTtcbiAgICAgICAgICAgICAgICBlMTMgPSBGci5hZGQoZTEzLCBjaGFsbGVuZ2VzLmdhbW1hKTtcblxuICAgICAgICAgICAgICAgIGxldCBlMSA9IEZyLm11bChGci5tdWwoRnIubXVsKGUxMSwgZTEyKSwgZTEzKSwgeik7XG4gICAgICAgICAgICAgICAgbGV0IGUxeiA9IEZyLm11bChGci5tdWwoRnIubXVsKGUxMSwgZTEyKSwgZTEzKSwgenApO1xuICAgICAgICAgICAgICAgIC8vIGNvbnN0IFtlMSwgZTF6XSA9IE11bFoubXVsNChlMTEsIGUxMiwgZTEzLCB6LCBhcCwgYnAsIGNwLCB6cCwgaSAlIDQsIEZyKTtcblxuICAgICAgICAgICAgICAgIC8vIGV4cHJlc3Npb24gMiAtPiAoYShYKSArIGJldGHCt3NpZ21hMShYKSArIGdhbW1hKShiKFgpICsgYmV0YcK3c2lnbWEyKFgpICsgZ2FtbWEpKGMoWCkgKyBiZXRhwrdzaWdtYTMoWCkgKyBnYW1tYSl6KFjPiSlcbiAgICAgICAgICAgICAgICBsZXQgZTIxID0gRnIuYWRkKGEsIEZyLm11bChjaGFsbGVuZ2VzLmJldGEsIHNpZ21hMSkpO1xuICAgICAgICAgICAgICAgIGUyMSA9IEZyLmFkZChlMjEsIGNoYWxsZW5nZXMuZ2FtbWEpO1xuXG4gICAgICAgICAgICAgICAgbGV0IGUyMiA9IEZyLmFkZChiLCBGci5tdWwoY2hhbGxlbmdlcy5iZXRhLCBzaWdtYTIpKTtcbiAgICAgICAgICAgICAgICBlMjIgPSBGci5hZGQoZTIyLCBjaGFsbGVuZ2VzLmdhbW1hKTtcblxuICAgICAgICAgICAgICAgIGxldCBlMjMgPSBGci5hZGQoYywgRnIubXVsKGNoYWxsZW5nZXMuYmV0YSwgc2lnbWEzKSk7XG4gICAgICAgICAgICAgICAgZTIzID0gRnIuYWRkKGUyMywgY2hhbGxlbmdlcy5nYW1tYSk7XG5cbiAgICAgICAgICAgICAgICBsZXQgZTIgPSBGci5tdWwoRnIubXVsKEZyLm11bChlMjEsIGUyMiksIGUyMyksIHpXKTtcbiAgICAgICAgICAgICAgICBsZXQgZTJ6ID0gRnIubXVsKEZyLm11bChGci5tdWwoZTIxLCBlMjIpLCBlMjMpLCB6V3ApO1xuICAgICAgICAgICAgICAgIC8vIGNvbnN0IFtlMiwgZTJ6XSA9IE11bFoubXVsNChlMjEsIGUyMiwgZTIzLCB6VywgYXAsIGJwLCBjcCwgeldwLCBpICUgNCwgRnIpO1xuXG4gICAgICAgICAgICAgICAgbGV0IHQyID0gRnIuc3ViKGUxLCBlMik7XG4gICAgICAgICAgICAgICAgbGV0IHQyeiA9IEZyLnN1YihlMXosIGUyeik7XG5cbiAgICAgICAgICAgICAgICBidWZmZXJzLlQyLnNldCh0MiwgaSAqIHNGcik7XG4gICAgICAgICAgICAgICAgYnVmZmVycy5UMnouc2V0KHQyeiwgaSAqIHNGcik7XG5cbiAgICAgICAgICAgICAgICAvLyBDb21wdXRlIG5leHQgb21lZ2FcbiAgICAgICAgICAgICAgICBvbWVnYSA9IEZyLm11bChvbWVnYSwgRnIud1t6a2V5LnBvd2VyICsgMl0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDb21wdXRlIHRoZSBjb2VmZmljaWVudHMgb2YgdGhlIHBvbHlub21pYWwgVDIoWCkgZnJvbSBidWZmZXJzLlQyXG4gICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIsK3wrfCtyBDb21wdXRpbmcgVDIgaWZmdFwiKTtcbiAgICAgICAgICAgIHBvbHlub21pYWxzLlQyID0gYXdhaXQgUG9seW5vbWlhbC5mcm9tRXZhbHVhdGlvbnMoYnVmZmVycy5UMiwgY3VydmUsIGxvZ2dlcik7XG5cbiAgICAgICAgICAgIC8vIERpdmlkZSB0aGUgcG9seW5vbWlhbCBUMiBieSBaX0goWClcbiAgICAgICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiwrfCt8K3IENvbXB1dGluZyBUMiAvIFpIXCIpO1xuICAgICAgICAgICAgcG9seW5vbWlhbHMuVDIuZGl2QnlaZXJvZmllcih6a2V5LmRvbWFpblNpemUsIEZyLm9uZSk7XG5cbiAgICAgICAgICAgIC8vIENvbXB1dGUgdGhlIGNvZWZmaWNpZW50cyBvZiB0aGUgcG9seW5vbWlhbCBUMnooWCkgZnJvbSBidWZmZXJzLlQyelxuICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCLCt8K3wrcgQ29tcHV0aW5nIFQyeiBpZmZ0XCIpO1xuICAgICAgICAgICAgcG9seW5vbWlhbHMuVDJ6ID0gYXdhaXQgUG9seW5vbWlhbC5mcm9tRXZhbHVhdGlvbnMoYnVmZmVycy5UMnosIGN1cnZlLCBsb2dnZXIpO1xuXG4gICAgICAgICAgICAvLyBBZGQgdGhlIHBvbHlub21pYWwgVDJ6IHRvIFQyIHRvIGdldCB0aGUgZmluYWwgcG9seW5vbWlhbCBUMlxuICAgICAgICAgICAgcG9seW5vbWlhbHMuVDIuYWRkKHBvbHlub21pYWxzLlQyeik7XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGRlZ3JlZVxuICAgICAgICAgICAgaWYgKHBvbHlub21pYWxzLlQyLmRlZ3JlZSgpID49IDMgKiB6a2V5LmRvbWFpblNpemUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUMiBQb2x5bm9taWFsIGlzIG5vdCB3ZWxsIGNhbGN1bGF0ZWRcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRlbGV0ZSBidWZmZXJzLlQyO1xuICAgICAgICAgICAgZGVsZXRlIGJ1ZmZlcnMuVDJ6O1xuICAgICAgICAgICAgZGVsZXRlIHBvbHlub21pYWxzLlQyejtcbiAgICAgICAgfVxuXG4gICAgICAgIGFzeW5jIGZ1bmN0aW9uIGNvbXB1dGVDMigpIHtcbiAgICAgICAgICAgIGxldCBDMiA9IG5ldyBDUG9seW5vbWlhbCgzLCBjdXJ2ZSwgbG9nZ2VyKTtcbiAgICAgICAgICAgIEMyLmFkZFBvbHlub21pYWwoMCwgcG9seW5vbWlhbHMuWik7XG4gICAgICAgICAgICBDMi5hZGRQb2x5bm9taWFsKDEsIHBvbHlub21pYWxzLlQxKTtcbiAgICAgICAgICAgIEMyLmFkZFBvbHlub21pYWwoMiwgcG9seW5vbWlhbHMuVDIpO1xuXG4gICAgICAgICAgICBwb2x5bm9taWFscy5DMiA9IEMyLmdldFBvbHlub21pYWwoKTtcblxuICAgICAgICAgICAgLy8gQ2hlY2sgZGVncmVlXG4gICAgICAgICAgICBpZiAocG9seW5vbWlhbHMuQzIuZGVncmVlKCkgPj0gOSAqIHprZXkuZG9tYWluU2l6ZSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkMyIFBvbHlub21pYWwgaXMgbm90IHdlbGwgY2FsY3VsYXRlZFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHJvdW5kMygpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCI+IENvbXB1dGluZyBjaGFsbGVuZ2UgeGlcIik7XG4gICAgICAgIC8vIFNURVAgMy4xIC0gQ29tcHV0ZSBldmFsdWF0aW9uIGNoYWxsZW5nZSB4aSDiiIggU1xuICAgICAgICBjb25zdCB0cmFuc2NyaXB0ID0gbmV3IEtlY2NhazI1NlRyYW5zY3JpcHQoY3VydmUpO1xuICAgICAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihjaGFsbGVuZ2VzLmdhbW1hKTtcbiAgICAgICAgdHJhbnNjcmlwdC5hZGRQb2xDb21taXRtZW50KHByb29mLmdldFBvbHlub21pYWwoXCJDMlwiKSk7XG5cbiAgICAgICAgLy8gT2J0YWluIGEgeGlfc2VlZGVyIGZyb20gdGhlIHRyYW5zY3JpcHRcbiAgICAgICAgLy8gVG8gZm9yY2UgaDFeNCA9IHhpLCBoMl4zID0geGkgYW5kIGhfM14yID0geGnPiVxuICAgICAgICAvLyB3ZSBjb21wdXRlIHhpID0geGlfc2VlZGVyXjEyLCBoMSA9IHhpX3NlZWRlcl4zLCBoMiA9IHhpX3NlZWRlcl40IGFuZCBoMyA9IHhpX3NlZWRlcl42XG4gICAgICAgIGNoYWxsZW5nZXMueGlTZWVkID0gdHJhbnNjcmlwdC5nZXRDaGFsbGVuZ2UoKTtcbiAgICAgICAgY29uc3QgeGlTZWVkMiA9IEZyLnNxdWFyZShjaGFsbGVuZ2VzLnhpU2VlZCk7XG5cbiAgICAgICAgLy8gQ29tcHV0ZSBvbWVnYTgsIG9tZWdhNCBhbmQgb21lZ2EzXG4gICAgICAgIHJvb3RzLnc4ID0gW107XG4gICAgICAgIHJvb3RzLnc4WzBdID0gRnIub25lO1xuICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IDg7IGkrKykge1xuICAgICAgICAgICAgcm9vdHMudzhbaV0gPSBGci5tdWwocm9vdHMudzhbaSAtIDFdLCB6a2V5Lnc4KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJvb3RzLnc0ID0gW107XG4gICAgICAgIHJvb3RzLnc0WzBdID0gRnIub25lO1xuICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IDQ7IGkrKykge1xuICAgICAgICAgICAgcm9vdHMudzRbaV0gPSBGci5tdWwocm9vdHMudzRbaSAtIDFdLCB6a2V5Lnc0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJvb3RzLnczID0gW107XG4gICAgICAgIHJvb3RzLnczWzBdID0gRnIub25lO1xuICAgICAgICByb290cy53M1sxXSA9IHprZXkudzM7XG4gICAgICAgIHJvb3RzLnczWzJdID0gRnIuc3F1YXJlKHprZXkudzMpO1xuXG4gICAgICAgIC8vIENvbXB1dGUgaDAgPSB4aVNlZWRlcl4zXG4gICAgICAgIHJvb3RzLlMwID0ge307XG4gICAgICAgIHJvb3RzLlMwLmgwdzggPSBbXTtcbiAgICAgICAgcm9vdHMuUzAuaDB3OFswXSA9IEZyLm11bCh4aVNlZWQyLCBjaGFsbGVuZ2VzLnhpU2VlZCk7XG4gICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgODsgaSsrKSB7XG4gICAgICAgICAgICByb290cy5TMC5oMHc4W2ldID0gRnIubXVsKHJvb3RzLlMwLmgwdzhbMF0sIHJvb3RzLnc4W2ldKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENvbXB1dGUgaDEgPSB4aV9zZWVkZXJeNlxuICAgICAgICByb290cy5TMSA9IHt9O1xuICAgICAgICByb290cy5TMS5oMXc0ID0gW107XG4gICAgICAgIHJvb3RzLlMxLmgxdzRbMF0gPSBGci5zcXVhcmUocm9vdHMuUzAuaDB3OFswXSk7XG4gICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgNDsgaSsrKSB7XG4gICAgICAgICAgICByb290cy5TMS5oMXc0W2ldID0gRnIubXVsKHJvb3RzLlMxLmgxdzRbMF0sIHJvb3RzLnc0W2ldKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENvbXB1dGUgaDIgPSB4aV9zZWVkZXJeOFxuICAgICAgICByb290cy5TMiA9IHt9O1xuICAgICAgICByb290cy5TMi5oMnczID0gW107XG4gICAgICAgIHJvb3RzLlMyLmgydzNbMF0gPSBGci5tdWwocm9vdHMuUzEuaDF3NFswXSwgeGlTZWVkMik7XG4gICAgICAgIHJvb3RzLlMyLmgydzNbMV0gPSBGci5tdWwocm9vdHMuUzIuaDJ3M1swXSwgcm9vdHMudzNbMV0pO1xuICAgICAgICByb290cy5TMi5oMnczWzJdID0gRnIubXVsKHJvb3RzLlMyLmgydzNbMF0sIHJvb3RzLnczWzJdKTtcblxuICAgICAgICByb290cy5TMi5oM3czID0gW107XG4gICAgICAgIC8vIE11bHRpcGx5IGgzIGJ5IHRoaXJkLXJvb3Qtb21lZ2EgdG8gb2J0YWluIGhfM14zID0geGnPiVxuICAgICAgICAvLyBTbywgaDMgPSB4aV9zZWVkZXJeOCDPiV57MS8zfVxuICAgICAgICByb290cy5TMi5oM3czWzBdID0gRnIubXVsKHJvb3RzLlMyLmgydzNbMF0sIHprZXkud3IpO1xuICAgICAgICByb290cy5TMi5oM3czWzFdID0gRnIubXVsKHJvb3RzLlMyLmgzdzNbMF0sIHJvb3RzLnczWzFdKTtcbiAgICAgICAgcm9vdHMuUzIuaDN3M1syXSA9IEZyLm11bChyb290cy5TMi5oM3czWzBdLCByb290cy53M1syXSk7XG5cbiAgICAgICAgLy8gQ29tcHV0ZSB4aSA9IHhpX3NlZWRlcl4yNFxuICAgICAgICBjaGFsbGVuZ2VzLnhpID0gRnIubXVsKEZyLnNxdWFyZShyb290cy5TMi5oMnczWzBdKSwgcm9vdHMuUzIuaDJ3M1swXSk7XG5cbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCLCt8K3wrcgY2hhbGxlbmdlcy54aTogXCIgKyBGci50b1N0cmluZyhjaGFsbGVuZ2VzLnhpKSk7XG5cbiAgICAgICAgLy8gUmVzZXJ2ZSBtZW1vcnkgZm9yIFEncyBwb2x5bm9taWFsc1xuICAgICAgICBwb2x5bm9taWFscy5RTCA9IG5ldyBQb2x5bm9taWFsKG5ldyBCaWdCdWZmZXIoc0RvbWFpbiksIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICBwb2x5bm9taWFscy5RUiA9IG5ldyBQb2x5bm9taWFsKG5ldyBCaWdCdWZmZXIoc0RvbWFpbiksIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICBwb2x5bm9taWFscy5RTSA9IG5ldyBQb2x5bm9taWFsKG5ldyBCaWdCdWZmZXIoc0RvbWFpbiksIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICBwb2x5bm9taWFscy5RTyA9IG5ldyBQb2x5bm9taWFsKG5ldyBCaWdCdWZmZXIoc0RvbWFpbiksIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICBwb2x5bm9taWFscy5RQyA9IG5ldyBQb2x5bm9taWFsKG5ldyBCaWdCdWZmZXIoc0RvbWFpbiksIGN1cnZlLCBsb2dnZXIpO1xuXG4gICAgICAgIC8vIFJlYWQgUSdzIGV2YWx1YXRpb25zIGZyb20gemtleSBmaWxlXG4gICAgICAgIGF3YWl0IGZkWktleS5yZWFkVG9CdWZmZXIocG9seW5vbWlhbHMuUUwuY29lZiwgMCwgc0RvbWFpbiwgemtleVNlY3Rpb25zW1pLRVlfRkZfUUxfU0VDVElPTl1bMF0ucCk7XG4gICAgICAgIGF3YWl0IGZkWktleS5yZWFkVG9CdWZmZXIocG9seW5vbWlhbHMuUVIuY29lZiwgMCwgc0RvbWFpbiwgemtleVNlY3Rpb25zW1pLRVlfRkZfUVJfU0VDVElPTl1bMF0ucCk7XG4gICAgICAgIGF3YWl0IGZkWktleS5yZWFkVG9CdWZmZXIocG9seW5vbWlhbHMuUU0uY29lZiwgMCwgc0RvbWFpbiwgemtleVNlY3Rpb25zW1pLRVlfRkZfUU1fU0VDVElPTl1bMF0ucCk7XG4gICAgICAgIGF3YWl0IGZkWktleS5yZWFkVG9CdWZmZXIocG9seW5vbWlhbHMuUU8uY29lZiwgMCwgc0RvbWFpbiwgemtleVNlY3Rpb25zW1pLRVlfRkZfUU9fU0VDVElPTl1bMF0ucCk7XG4gICAgICAgIGF3YWl0IGZkWktleS5yZWFkVG9CdWZmZXIocG9seW5vbWlhbHMuUUMuY29lZiwgMCwgc0RvbWFpbiwgemtleVNlY3Rpb25zW1pLRVlfRkZfUUNfU0VDVElPTl1bMF0ucCk7XG5cbiAgICAgICAgLy8gU1RFUCAzLjIgLSBDb21wdXRlIG9wZW5pbmcgZXZhbHVhdGlvbnMgYW5kIGFkZCB0aGVtIHRvIHRoZSBwcm9vZiAodGhpcmQgb3V0cHV0IG9mIHRoZSBwcm92ZXIpXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiwrfCt8K3IENvbXB1dGluZyBldmFsdWF0aW9uc1wiKTtcbiAgICAgICAgcHJvb2YuYWRkRXZhbHVhdGlvbihcInFsXCIsIHBvbHlub21pYWxzLlFMLmV2YWx1YXRlKGNoYWxsZW5nZXMueGkpKTtcbiAgICAgICAgcHJvb2YuYWRkRXZhbHVhdGlvbihcInFyXCIsIHBvbHlub21pYWxzLlFSLmV2YWx1YXRlKGNoYWxsZW5nZXMueGkpKTtcbiAgICAgICAgcHJvb2YuYWRkRXZhbHVhdGlvbihcInFtXCIsIHBvbHlub21pYWxzLlFNLmV2YWx1YXRlKGNoYWxsZW5nZXMueGkpKTtcbiAgICAgICAgcHJvb2YuYWRkRXZhbHVhdGlvbihcInFvXCIsIHBvbHlub21pYWxzLlFPLmV2YWx1YXRlKGNoYWxsZW5nZXMueGkpKTtcbiAgICAgICAgcHJvb2YuYWRkRXZhbHVhdGlvbihcInFjXCIsIHBvbHlub21pYWxzLlFDLmV2YWx1YXRlKGNoYWxsZW5nZXMueGkpKTtcbiAgICAgICAgcHJvb2YuYWRkRXZhbHVhdGlvbihcInMxXCIsIHBvbHlub21pYWxzLlNpZ21hMS5ldmFsdWF0ZShjaGFsbGVuZ2VzLnhpKSk7XG4gICAgICAgIHByb29mLmFkZEV2YWx1YXRpb24oXCJzMlwiLCBwb2x5bm9taWFscy5TaWdtYTIuZXZhbHVhdGUoY2hhbGxlbmdlcy54aSkpO1xuICAgICAgICBwcm9vZi5hZGRFdmFsdWF0aW9uKFwiczNcIiwgcG9seW5vbWlhbHMuU2lnbWEzLmV2YWx1YXRlKGNoYWxsZW5nZXMueGkpKTtcbiAgICAgICAgcHJvb2YuYWRkRXZhbHVhdGlvbihcImFcIiwgcG9seW5vbWlhbHMuQS5ldmFsdWF0ZShjaGFsbGVuZ2VzLnhpKSk7XG4gICAgICAgIHByb29mLmFkZEV2YWx1YXRpb24oXCJiXCIsIHBvbHlub21pYWxzLkIuZXZhbHVhdGUoY2hhbGxlbmdlcy54aSkpO1xuICAgICAgICBwcm9vZi5hZGRFdmFsdWF0aW9uKFwiY1wiLCBwb2x5bm9taWFscy5DLmV2YWx1YXRlKGNoYWxsZW5nZXMueGkpKTtcbiAgICAgICAgcHJvb2YuYWRkRXZhbHVhdGlvbihcInpcIiwgcG9seW5vbWlhbHMuWi5ldmFsdWF0ZShjaGFsbGVuZ2VzLnhpKSk7XG5cbiAgICAgICAgY2hhbGxlbmdlcy54aXcgPSBGci5tdWwoY2hhbGxlbmdlcy54aSwgRnIud1t6a2V5LnBvd2VyXSk7XG4gICAgICAgIHByb29mLmFkZEV2YWx1YXRpb24oXCJ6d1wiLCBwb2x5bm9taWFscy5aLmV2YWx1YXRlKGNoYWxsZW5nZXMueGl3KSk7XG4gICAgICAgIHByb29mLmFkZEV2YWx1YXRpb24oXCJ0MXdcIiwgcG9seW5vbWlhbHMuVDEuZXZhbHVhdGUoY2hhbGxlbmdlcy54aXcpKTtcbiAgICAgICAgcHJvb2YuYWRkRXZhbHVhdGlvbihcInQyd1wiLCBwb2x5bm9taWFscy5UMi5ldmFsdWF0ZShjaGFsbGVuZ2VzLnhpdykpO1xuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHJvdW5kNCgpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCI+IENvbXB1dGluZyBjaGFsbGVuZ2UgYWxwaGFcIik7XG4gICAgICAgIC8vIFNURVAgNC4xIC0gQ29tcHV0ZSBjaGFsbGVuZ2UgYWxwaGEg4oiIIEZcbiAgICAgICAgY29uc3QgdHJhbnNjcmlwdCA9IG5ldyBLZWNjYWsyNTZUcmFuc2NyaXB0KGN1cnZlKTtcbiAgICAgICAgdHJhbnNjcmlwdC5hZGRTY2FsYXIoY2hhbGxlbmdlcy54aVNlZWQpO1xuICAgICAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihwcm9vZi5nZXRFdmFsdWF0aW9uKFwicWxcIikpO1xuICAgICAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihwcm9vZi5nZXRFdmFsdWF0aW9uKFwicXJcIikpO1xuICAgICAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihwcm9vZi5nZXRFdmFsdWF0aW9uKFwicW1cIikpO1xuICAgICAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihwcm9vZi5nZXRFdmFsdWF0aW9uKFwicW9cIikpO1xuICAgICAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihwcm9vZi5nZXRFdmFsdWF0aW9uKFwicWNcIikpO1xuICAgICAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihwcm9vZi5nZXRFdmFsdWF0aW9uKFwiczFcIikpO1xuICAgICAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihwcm9vZi5nZXRFdmFsdWF0aW9uKFwiczJcIikpO1xuICAgICAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihwcm9vZi5nZXRFdmFsdWF0aW9uKFwiczNcIikpO1xuICAgICAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihwcm9vZi5nZXRFdmFsdWF0aW9uKFwiYVwiKSk7XG4gICAgICAgIHRyYW5zY3JpcHQuYWRkU2NhbGFyKHByb29mLmdldEV2YWx1YXRpb24oXCJiXCIpKTtcbiAgICAgICAgdHJhbnNjcmlwdC5hZGRTY2FsYXIocHJvb2YuZ2V0RXZhbHVhdGlvbihcImNcIikpO1xuICAgICAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihwcm9vZi5nZXRFdmFsdWF0aW9uKFwielwiKSk7XG4gICAgICAgIHRyYW5zY3JpcHQuYWRkU2NhbGFyKHByb29mLmdldEV2YWx1YXRpb24oXCJ6d1wiKSk7XG4gICAgICAgIHRyYW5zY3JpcHQuYWRkU2NhbGFyKHByb29mLmdldEV2YWx1YXRpb24oXCJ0MXdcIikpO1xuICAgICAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihwcm9vZi5nZXRFdmFsdWF0aW9uKFwidDJ3XCIpKTtcbiAgICAgICAgY2hhbGxlbmdlcy5hbHBoYSA9IHRyYW5zY3JpcHQuZ2V0Q2hhbGxlbmdlKCk7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiwrfCt8K3IGNoYWxsZW5nZXMuYWxwaGE6IFwiICsgRnIudG9TdHJpbmcoY2hhbGxlbmdlcy5hbHBoYSkpO1xuXG4gICAgICAgIC8vIFNURVAgNC4yIC0gQ29tcHV0ZSBGKFgpXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBSZWFkaW5nIEMwIHBvbHlub21pYWxcIik7XG4gICAgICAgIHBvbHlub21pYWxzLkMwID0gbmV3IFBvbHlub21pYWwobmV3IEJpZ0J1ZmZlcihzRG9tYWluICogOCksIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICBhd2FpdCBmZFpLZXkucmVhZFRvQnVmZmVyKHBvbHlub21pYWxzLkMwLmNvZWYsIDAsIHNEb21haW4gKiA4LCB6a2V5U2VjdGlvbnNbWktFWV9GRl9DMF9TRUNUSU9OXVswXS5wKTtcblxuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gQ29tcHV0aW5nIFIwIHBvbHlub21pYWxcIik7XG4gICAgICAgIGNvbXB1dGVSMCgpO1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gQ29tcHV0aW5nIFIxIHBvbHlub21pYWxcIik7XG4gICAgICAgIGNvbXB1dGVSMSgpO1xuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gQ29tcHV0aW5nIFIyIHBvbHlub21pYWxcIik7XG4gICAgICAgIGNvbXB1dGVSMigpO1xuXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBDb21wdXRpbmcgRiBwb2x5bm9taWFsXCIpO1xuICAgICAgICBhd2FpdCBjb21wdXRlRigpO1xuXG4gICAgICAgIC8vIFRoZSBmb3VydGggb3V0cHV0IG9mIHRoZSBwcm92ZXIgaXMgKFtXMV1fMSksIHdoZXJlIFcxOj0oZi9aX3QpKHgpXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBDb21wdXRpbmcgVzEgbXVsdGkgZXhwb25lbnRpYXRpb25cIik7XG4gICAgICAgIGxldCBjb21taXRXMSA9IGF3YWl0IHBvbHlub21pYWxzLkYubXVsdGlFeHBvbmVudGlhdGlvbihQVGF1LCBcIlcxXCIpO1xuICAgICAgICBwcm9vZi5hZGRQb2x5bm9taWFsKFwiVzFcIiwgY29tbWl0VzEpO1xuXG4gICAgICAgIHJldHVybiAwO1xuXG4gICAgICAgIGZ1bmN0aW9uIGNvbXB1dGVSMCgpIHtcbiAgICAgICAgICAgIC8vIENPTVBVVEUgUjBcbiAgICAgICAgICAgIC8vIENvbXB1dGUgdGhlIGNvZWZmaWNpZW50cyBvZiBSMChYKSBmcm9tIDggZXZhbHVhdGlvbnMgdXNpbmcgbGFncmFuZ2UgaW50ZXJwb2xhdGlvbi4gUjAoWCkg4oiIIEZfezw4fVtYXVxuICAgICAgICAgICAgLy8gV2UgZGVjaWRlIHRvIHVzZSBMYWdyYW5nZSBpbnRlcnBvbGF0aW9ucyBiZWNhdXNlIHRoZSBSMCBkZWdyZWUgaXMgdmVyeSBzbWFsbCAoZGVnKFIwKT09PTcpLFxuICAgICAgICAgICAgLy8gYW5kIHdlIHdlcmUgbm90IGFibGUgdG8gY29tcHV0ZSBpdCB1c2luZyBjdXJyZW50IGlmZnQgaW1wbGVtZW50YXRpb24gYmVjYXVzZSB0aGUgb21lZ2EgYXJlIGRpZmZlcmVudFxuICAgICAgICAgICAgcG9seW5vbWlhbHMuUjAgPSBQb2x5bm9taWFsLmxhZ3JhbmdlUG9seW5vbWlhbEludGVycG9sYXRpb24oXG4gICAgICAgICAgICAgICAgW3Jvb3RzLlMwLmgwdzhbMF0sIHJvb3RzLlMwLmgwdzhbMV0sIHJvb3RzLlMwLmgwdzhbMl0sIHJvb3RzLlMwLmgwdzhbM10sXG4gICAgICAgICAgICAgICAgICAgIHJvb3RzLlMwLmgwdzhbNF0sIHJvb3RzLlMwLmgwdzhbNV0sIHJvb3RzLlMwLmgwdzhbNl0sIHJvb3RzLlMwLmgwdzhbN11dLFxuICAgICAgICAgICAgICAgIFtwb2x5bm9taWFscy5DMC5ldmFsdWF0ZShyb290cy5TMC5oMHc4WzBdKSwgcG9seW5vbWlhbHMuQzAuZXZhbHVhdGUocm9vdHMuUzAuaDB3OFsxXSksXG4gICAgICAgICAgICAgICAgICAgIHBvbHlub21pYWxzLkMwLmV2YWx1YXRlKHJvb3RzLlMwLmgwdzhbMl0pLCBwb2x5bm9taWFscy5DMC5ldmFsdWF0ZShyb290cy5TMC5oMHc4WzNdKSxcbiAgICAgICAgICAgICAgICAgICAgcG9seW5vbWlhbHMuQzAuZXZhbHVhdGUocm9vdHMuUzAuaDB3OFs0XSksIHBvbHlub21pYWxzLkMwLmV2YWx1YXRlKHJvb3RzLlMwLmgwdzhbNV0pLFxuICAgICAgICAgICAgICAgICAgICBwb2x5bm9taWFscy5DMC5ldmFsdWF0ZShyb290cy5TMC5oMHc4WzZdKSwgcG9seW5vbWlhbHMuQzAuZXZhbHVhdGUocm9vdHMuUzAuaDB3OFs3XSldLCBjdXJ2ZSk7XG5cbiAgICAgICAgICAgIC8vIENoZWNrIHRoZSBkZWdyZWUgb2YgcjAoWCkgPCA4XG4gICAgICAgICAgICBpZiAocG9seW5vbWlhbHMuUjAuZGVncmVlKCkgPiA3KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUjAgUG9seW5vbWlhbCBpcyBub3Qgd2VsbCBjYWxjdWxhdGVkXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gY29tcHV0ZVIxKCkge1xuICAgICAgICAgICAgLy8gQ09NUFVURSBSMVxuICAgICAgICAgICAgLy8gQ29tcHV0ZSB0aGUgY29lZmZpY2llbnRzIG9mIFIxKFgpIGZyb20gNCBldmFsdWF0aW9ucyB1c2luZyBsYWdyYW5nZSBpbnRlcnBvbGF0aW9uLiBSMShYKSDiiIggRl97PDR9W1hdXG4gICAgICAgICAgICAvLyBXZSBkZWNpZGUgdG8gdXNlIExhZ3JhbmdlIGludGVycG9sYXRpb25zIGJlY2F1c2UgdGhlIFIxIGRlZ3JlZSBpcyB2ZXJ5IHNtYWxsIChkZWcoUjEpPT09MyksXG4gICAgICAgICAgICAvLyBhbmQgd2Ugd2VyZSBub3QgYWJsZSB0byBjb21wdXRlIGl0IHVzaW5nIGN1cnJlbnQgaWZmdCBpbXBsZW1lbnRhdGlvbiBiZWNhdXNlIHRoZSBvbWVnYSBhcmUgZGlmZmVyZW50XG4gICAgICAgICAgICBwb2x5bm9taWFscy5SMSA9IFBvbHlub21pYWwubGFncmFuZ2VQb2x5bm9taWFsSW50ZXJwb2xhdGlvbihcbiAgICAgICAgICAgICAgICBbcm9vdHMuUzEuaDF3NFswXSwgcm9vdHMuUzEuaDF3NFsxXSwgcm9vdHMuUzEuaDF3NFsyXSwgcm9vdHMuUzEuaDF3NFszXV0sXG4gICAgICAgICAgICAgICAgW3BvbHlub21pYWxzLkMxLmV2YWx1YXRlKHJvb3RzLlMxLmgxdzRbMF0pLCBwb2x5bm9taWFscy5DMS5ldmFsdWF0ZShyb290cy5TMS5oMXc0WzFdKSxcbiAgICAgICAgICAgICAgICAgICAgcG9seW5vbWlhbHMuQzEuZXZhbHVhdGUocm9vdHMuUzEuaDF3NFsyXSksIHBvbHlub21pYWxzLkMxLmV2YWx1YXRlKHJvb3RzLlMxLmgxdzRbM10pXSwgY3VydmUpO1xuXG4gICAgICAgICAgICAvLyBDaGVjayB0aGUgZGVncmVlIG9mIHIxKFgpIDwgNFxuICAgICAgICAgICAgaWYgKHBvbHlub21pYWxzLlIxLmRlZ3JlZSgpID4gMykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlIxIFBvbHlub21pYWwgaXMgbm90IHdlbGwgY2FsY3VsYXRlZFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGNvbXB1dGVSMigpIHtcbiAgICAgICAgICAgIC8vIENPTVBVVEUgUjJcbiAgICAgICAgICAgIC8vIENvbXB1dGUgdGhlIGNvZWZmaWNpZW50cyBvZiByMihYKSBmcm9tIDYgZXZhbHVhdGlvbnMgdXNpbmcgbGFncmFuZ2UgaW50ZXJwb2xhdGlvbi4gcjIoWCkg4oiIIEZfezw2fVtYXVxuICAgICAgICAgICAgLy8gV2UgZGVjaWRlIHRvIHVzZSBMYWdyYW5nZSBpbnRlcnBvbGF0aW9ucyBiZWNhdXNlIHRoZSBSMi5kZWdyZWUgaXMgdmVyeSBzbWFsbCAoZGVnKFIyKT09PTUpLFxuICAgICAgICAgICAgLy8gYW5kIHdlIHdlcmUgbm90IGFibGUgdG8gY29tcHV0ZSBpdCB1c2luZyBjdXJyZW50IGlmZnQgaW1wbGVtZW50YXRpb24gYmVjYXVzZSB0aGUgb21lZ2EgYXJlIGRpZmZlcmVudFxuICAgICAgICAgICAgcG9seW5vbWlhbHMuUjIgPSBQb2x5bm9taWFsLmxhZ3JhbmdlUG9seW5vbWlhbEludGVycG9sYXRpb24oXG4gICAgICAgICAgICAgICAgW3Jvb3RzLlMyLmgydzNbMF0sIHJvb3RzLlMyLmgydzNbMV0sIHJvb3RzLlMyLmgydzNbMl0sXG4gICAgICAgICAgICAgICAgICAgIHJvb3RzLlMyLmgzdzNbMF0sIHJvb3RzLlMyLmgzdzNbMV0sIHJvb3RzLlMyLmgzdzNbMl1dLFxuICAgICAgICAgICAgICAgIFtwb2x5bm9taWFscy5DMi5ldmFsdWF0ZShyb290cy5TMi5oMnczWzBdKSwgcG9seW5vbWlhbHMuQzIuZXZhbHVhdGUocm9vdHMuUzIuaDJ3M1sxXSksXG4gICAgICAgICAgICAgICAgICAgIHBvbHlub21pYWxzLkMyLmV2YWx1YXRlKHJvb3RzLlMyLmgydzNbMl0pLCBwb2x5bm9taWFscy5DMi5ldmFsdWF0ZShyb290cy5TMi5oM3czWzBdKSxcbiAgICAgICAgICAgICAgICAgICAgcG9seW5vbWlhbHMuQzIuZXZhbHVhdGUocm9vdHMuUzIuaDN3M1sxXSksIHBvbHlub21pYWxzLkMyLmV2YWx1YXRlKHJvb3RzLlMyLmgzdzNbMl0pXSwgY3VydmUpO1xuXG4gICAgICAgICAgICAvLyBDaGVjayB0aGUgZGVncmVlIG9mIHIyKFgpIDwgNlxuICAgICAgICAgICAgaWYgKHBvbHlub21pYWxzLlIyLmRlZ3JlZSgpID4gNSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlIyIFBvbHlub21pYWwgaXMgbm90IHdlbGwgY2FsY3VsYXRlZFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGFzeW5jIGZ1bmN0aW9uIGNvbXB1dGVGKCkge1xuICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCLCt8K3wrcgQ29tcHV0aW5nIEYgcG9seW5vbWlhbFwiKTtcblxuICAgICAgICAgICAgLy8gQ09NUFVURSBGKFgpXG4gICAgICAgICAgICBwb2x5bm9taWFscy5GID0gUG9seW5vbWlhbC5mcm9tUG9seW5vbWlhbChwb2x5bm9taWFscy5DMCwgY3VydmUsIGxvZ2dlcik7XG4gICAgICAgICAgICBwb2x5bm9taWFscy5GLnN1Yihwb2x5bm9taWFscy5SMCk7XG4gICAgICAgICAgICBwb2x5bm9taWFscy5GLmRpdkJ5WmVyb2ZpZXIoOCwgY2hhbGxlbmdlcy54aSk7XG5cbiAgICAgICAgICAgIGxldCBmMiA9IFBvbHlub21pYWwuZnJvbVBvbHlub21pYWwocG9seW5vbWlhbHMuQzEsIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICAgICAgZjIuc3ViKHBvbHlub21pYWxzLlIxKTtcbiAgICAgICAgICAgIGYyLm11bFNjYWxhcihjaGFsbGVuZ2VzLmFscGhhKTtcbiAgICAgICAgICAgIGYyLmRpdkJ5WmVyb2ZpZXIoNCwgY2hhbGxlbmdlcy54aSk7XG5cbiAgICAgICAgICAgIGxldCBmMyA9IFBvbHlub21pYWwuZnJvbVBvbHlub21pYWwocG9seW5vbWlhbHMuQzIsIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICAgICAgZjMuc3ViKHBvbHlub21pYWxzLlIyKTtcbiAgICAgICAgICAgIGYzLm11bFNjYWxhcihGci5zcXVhcmUoY2hhbGxlbmdlcy5hbHBoYSkpO1xuICAgICAgICAgICAgZjMuZGl2QnlaZXJvZmllcigzLCBjaGFsbGVuZ2VzLnhpKTtcbiAgICAgICAgICAgIGYzLmRpdkJ5WmVyb2ZpZXIoMywgY2hhbGxlbmdlcy54aXcpO1xuXG4gICAgICAgICAgICBwb2x5bm9taWFscy5GLmFkZChmMik7XG4gICAgICAgICAgICBwb2x5bm9taWFscy5GLmFkZChmMyk7XG5cbiAgICAgICAgICAgIGlmIChwb2x5bm9taWFscy5GLmRlZ3JlZSgpID49IDkgKiB6a2V5LmRvbWFpblNpemUgLSA2KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRiBQb2x5bm9taWFsIGlzIG5vdCB3ZWxsIGNhbGN1bGF0ZWRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiByb3VuZDUoKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBDb21wdXRpbmcgY2hhbGxlbmdlIHlcIik7XG5cbiAgICAgICAgLy8gU1RFUCA1LjEgLSBDb21wdXRlIHJhbmRvbSBldmFsdWF0aW9uIHBvaW50IHkg4oiIIEZcbiAgICAgICAgY29uc3QgdHJhbnNjcmlwdCA9IG5ldyBLZWNjYWsyNTZUcmFuc2NyaXB0KGN1cnZlKTtcbiAgICAgICAgdHJhbnNjcmlwdC5hZGRTY2FsYXIoY2hhbGxlbmdlcy5hbHBoYSk7XG4gICAgICAgIHRyYW5zY3JpcHQuYWRkUG9sQ29tbWl0bWVudChwcm9vZi5nZXRQb2x5bm9taWFsKFwiVzFcIikpO1xuXG4gICAgICAgIGNoYWxsZW5nZXMueSA9IHRyYW5zY3JpcHQuZ2V0Q2hhbGxlbmdlKCk7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiwrfCt8K3IGNoYWxsZW5nZXMueTogXCIgKyBGci50b1N0cmluZyhjaGFsbGVuZ2VzLnkpKTtcblxuICAgICAgICAvLyBTVEVQIDUuMiAtIENvbXB1dGUgTChYKVxuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gQ29tcHV0aW5nIEwgcG9seW5vbWlhbFwiKTtcbiAgICAgICAgYXdhaXQgY29tcHV0ZUwoKTtcblxuICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gQ29tcHV0aW5nIFpUUzIgcG9seW5vbWlhbFwiKTtcbiAgICAgICAgYXdhaXQgY29tcHV0ZVpUUzIoKTtcblxuICAgICAgICBsZXQgWlRTMlkgPSBwb2x5bm9taWFscy5aVFMyLmV2YWx1YXRlKGNoYWxsZW5nZXMueSk7XG4gICAgICAgIFpUUzJZID0gRnIuaW52KFpUUzJZKTtcbiAgICAgICAgcG9seW5vbWlhbHMuTC5tdWxTY2FsYXIoWlRTMlkpO1xuXG4gICAgICAgIGNvbnN0IHBvbERpdmlkZW5kID0gUG9seW5vbWlhbC5mcm9tQ29lZmZpY2llbnRzQXJyYXkoW0ZyLm5lZyhjaGFsbGVuZ2VzLnkpLCBGci5vbmVdLCBjdXJ2ZSk7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBDb21wdXRpbmcgVycgPSBMIC8gWlRTMiBwb2x5bm9taWFsXCIpO1xuICAgICAgICBjb25zdCBwb2xSZW1haW5kZXIgPSBwb2x5bm9taWFscy5MLmRpdkJ5KHBvbERpdmlkZW5kKTtcblxuICAgICAgICAvL0NoZWNrIHBvbFJlbWluZGVyIGRlZ3JlZSBpcyBlcXVhbCB0byB6ZXJvXG4gICAgICAgIGlmIChwb2xSZW1haW5kZXIuZGVncmVlKCkgPiAwKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYERlZ3JlZSBvZiBMKFgpLyhaVFMyKHkpKFgteSkpIHJlbWFpbmRlciBpcyAke3BvbFJlbWFpbmRlci5kZWdyZWUoKX0gYW5kIHNob3VsZCBiZSAwYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocG9seW5vbWlhbHMuTC5kZWdyZWUoKSA+PSA5ICogemtleS5kb21haW5TaXplIC0gMSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRGVncmVlIG9mIEwoWCkvKFpUUzIoeSkoWC15KSkgaXMgbm90IGNvcnJlY3RcIik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUaGUgZmlmdGggb3V0cHV0IG9mIHRoZSBwcm92ZXIgaXMgKFtXMl1fMSksIHdoZXJlIFcyOj0oZi9aX3QpKHgpXG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBDb21wdXRpbmcgVycgbXVsdGkgZXhwb25lbnRpYXRpb25cIik7XG4gICAgICAgIGxldCBjb21taXRXMiA9IGF3YWl0IHBvbHlub21pYWxzLkwubXVsdGlFeHBvbmVudGlhdGlvbihQVGF1LCBcIlcyXCIpO1xuICAgICAgICBwcm9vZi5hZGRQb2x5bm9taWFsKFwiVzJcIiwgY29tbWl0VzIpO1xuXG4gICAgICAgIHJldHVybiAwO1xuXG4gICAgICAgIGFzeW5jIGZ1bmN0aW9uIGNvbXB1dGVMKCkge1xuICAgICAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCLCt8K3wrcgQ29tcHV0aW5nIEwgcG9seW5vbWlhbFwiKTtcblxuICAgICAgICAgICAgY29uc3QgZXZhbFIwWSA9IHBvbHlub21pYWxzLlIwLmV2YWx1YXRlKGNoYWxsZW5nZXMueSk7XG4gICAgICAgICAgICBjb25zdCBldmFsUjFZID0gcG9seW5vbWlhbHMuUjEuZXZhbHVhdGUoY2hhbGxlbmdlcy55KTtcbiAgICAgICAgICAgIGNvbnN0IGV2YWxSMlkgPSBwb2x5bm9taWFscy5SMi5ldmFsdWF0ZShjaGFsbGVuZ2VzLnkpO1xuXG4gICAgICAgICAgICBsZXQgbXVsTDAgPSBGci5zdWIoY2hhbGxlbmdlcy55LCByb290cy5TMC5oMHc4WzBdKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgODsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbXVsTDAgPSBGci5tdWwobXVsTDAsIEZyLnN1YihjaGFsbGVuZ2VzLnksIHJvb3RzLlMwLmgwdzhbaV0pKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV0IG11bEwxID0gRnIuc3ViKGNoYWxsZW5nZXMueSwgcm9vdHMuUzEuaDF3NFswXSk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IDQ7IGkrKykge1xuICAgICAgICAgICAgICAgIG11bEwxID0gRnIubXVsKG11bEwxLCBGci5zdWIoY2hhbGxlbmdlcy55LCByb290cy5TMS5oMXc0W2ldKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBtdWxMMiA9IEZyLnN1YihjaGFsbGVuZ2VzLnksIHJvb3RzLlMyLmgydzNbMF0pO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCAzOyBpKyspIHtcbiAgICAgICAgICAgICAgICBtdWxMMiA9IEZyLm11bChtdWxMMiwgRnIuc3ViKGNoYWxsZW5nZXMueSwgcm9vdHMuUzIuaDJ3M1tpXSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAzOyBpKyspIHtcbiAgICAgICAgICAgICAgICBtdWxMMiA9IEZyLm11bChtdWxMMiwgRnIuc3ViKGNoYWxsZW5nZXMueSwgcm9vdHMuUzIuaDN3M1tpXSkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZXQgcHJlTDAgPSBGci5tdWwobXVsTDEsIG11bEwyKTtcbiAgICAgICAgICAgIGxldCBwcmVMMSA9IEZyLm11bChjaGFsbGVuZ2VzLmFscGhhLCBGci5tdWwobXVsTDAsIG11bEwyKSk7XG4gICAgICAgICAgICBsZXQgcHJlTDIgPSBGci5tdWwoRnIuc3F1YXJlKGNoYWxsZW5nZXMuYWxwaGEpLCBGci5tdWwobXVsTDAsIG11bEwxKSk7XG5cbiAgICAgICAgICAgIHRvSW52ZXJzZVtcImRlbkgxXCJdID0gbXVsTDE7XG4gICAgICAgICAgICB0b0ludmVyc2VbXCJkZW5IMlwiXSA9IG11bEwyO1xuXG4gICAgICAgICAgICAvLyBDT01QVVRFIEwoWClcbiAgICAgICAgICAgIHBvbHlub21pYWxzLkwgPSBQb2x5bm9taWFsLmZyb21Qb2x5bm9taWFsKHBvbHlub21pYWxzLkMwLCBjdXJ2ZSwgbG9nZ2VyKTtcbiAgICAgICAgICAgIHBvbHlub21pYWxzLkwuc3ViU2NhbGFyKGV2YWxSMFkpO1xuICAgICAgICAgICAgcG9seW5vbWlhbHMuTC5tdWxTY2FsYXIocHJlTDApO1xuXG4gICAgICAgICAgICBsZXQgbDIgPSBQb2x5bm9taWFsLmZyb21Qb2x5bm9taWFsKHBvbHlub21pYWxzLkMxLCBjdXJ2ZSwgbG9nZ2VyKTtcbiAgICAgICAgICAgIGwyLnN1YlNjYWxhcihldmFsUjFZKTtcbiAgICAgICAgICAgIGwyLm11bFNjYWxhcihwcmVMMSk7XG5cbiAgICAgICAgICAgIGxldCBsMyA9IFBvbHlub21pYWwuZnJvbVBvbHlub21pYWwocG9seW5vbWlhbHMuQzIsIGN1cnZlLCBsb2dnZXIpO1xuICAgICAgICAgICAgbDMuc3ViU2NhbGFyKGV2YWxSMlkpO1xuICAgICAgICAgICAgbDMubXVsU2NhbGFyKHByZUwyKTtcblxuICAgICAgICAgICAgcG9seW5vbWlhbHMuTC5hZGQobDIpO1xuICAgICAgICAgICAgcG9seW5vbWlhbHMuTC5hZGQobDMpO1xuXG4gICAgICAgICAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gQ29tcHV0aW5nIFpUIHBvbHlub21pYWxcIik7XG4gICAgICAgICAgICBhd2FpdCBjb21wdXRlWlQoKTtcblxuICAgICAgICAgICAgY29uc3QgZXZhbFpUWSA9IHBvbHlub21pYWxzLlpULmV2YWx1YXRlKGNoYWxsZW5nZXMueSk7XG4gICAgICAgICAgICBwb2x5bm9taWFscy5GLm11bFNjYWxhcihldmFsWlRZKTtcbiAgICAgICAgICAgIHBvbHlub21pYWxzLkwuc3ViKHBvbHlub21pYWxzLkYpO1xuXG4gICAgICAgICAgICAvLyBDaGVjayBkZWdyZWVcbiAgICAgICAgICAgIGlmIChwb2x5bm9taWFscy5MLmRlZ3JlZSgpID49IDkgKiB6a2V5LmRvbWFpblNpemUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJMIFBvbHlub21pYWwgaXMgbm90IHdlbGwgY2FsY3VsYXRlZFwiKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZGVsZXRlIGJ1ZmZlcnMuTDtcbiAgICAgICAgfVxuXG4gICAgICAgIGFzeW5jIGZ1bmN0aW9uIGNvbXB1dGVaVCgpIHtcbiAgICAgICAgICAgIHBvbHlub21pYWxzLlpUID0gUG9seW5vbWlhbC56ZXJvZmllclBvbHlub21pYWwoXG4gICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICByb290cy5TMC5oMHc4WzBdLCByb290cy5TMC5oMHc4WzFdLCByb290cy5TMC5oMHc4WzJdLCByb290cy5TMC5oMHc4WzNdLFxuICAgICAgICAgICAgICAgICAgICByb290cy5TMC5oMHc4WzRdLCByb290cy5TMC5oMHc4WzVdLCByb290cy5TMC5oMHc4WzZdLCByb290cy5TMC5oMHc4WzddLFxuICAgICAgICAgICAgICAgICAgICByb290cy5TMS5oMXc0WzBdLCByb290cy5TMS5oMXc0WzFdLCByb290cy5TMS5oMXc0WzJdLCByb290cy5TMS5oMXc0WzNdLFxuICAgICAgICAgICAgICAgICAgICByb290cy5TMi5oMnczWzBdLCByb290cy5TMi5oMnczWzFdLCByb290cy5TMi5oMnczWzJdLFxuICAgICAgICAgICAgICAgICAgICByb290cy5TMi5oM3czWzBdLCByb290cy5TMi5oM3czWzFdLCByb290cy5TMi5oM3czWzJdXSwgY3VydmUpO1xuICAgICAgICB9XG5cbiAgICAgICAgYXN5bmMgZnVuY3Rpb24gY29tcHV0ZVpUUzIoKSB7XG4gICAgICAgICAgICBwb2x5bm9taWFscy5aVFMyID0gUG9seW5vbWlhbC56ZXJvZmllclBvbHlub21pYWwoXG4gICAgICAgICAgICAgICAgW3Jvb3RzLlMxLmgxdzRbMF0sIHJvb3RzLlMxLmgxdzRbMV0sIHJvb3RzLlMxLmgxdzRbMl0sIHJvb3RzLlMxLmgxdzRbM10sXG4gICAgICAgICAgICAgICAgICAgIHJvb3RzLlMyLmgydzNbMF0sIHJvb3RzLlMyLmgydzNbMV0sIHJvb3RzLlMyLmgydzNbMl0sXG4gICAgICAgICAgICAgICAgICAgIHJvb3RzLlMyLmgzdzNbMF0sIHJvb3RzLlMyLmgzdzNbMV0sIHJvb3RzLlMyLmgzdzNbMl1dLCBjdXJ2ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRNb250Z29tZXJ5QmF0Y2hlZEludmVyc2UoKSB7XG4gICAgICAgIC8vICAgwrcgZGVub21pbmF0b3IgbmVlZGVkIGluIHN0ZXAgOCBhbmQgOSBvZiB0aGUgdmVyaWZpZXIgdG8gbXVsdGlwbHkgYnkgMS9aX0goeGkpXG4gICAgICAgIGxldCB4aU4gPSBjaGFsbGVuZ2VzLnhpO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHprZXkucG93ZXI7IGkrKykge1xuICAgICAgICAgICAgeGlOID0gRnIuc3F1YXJlKHhpTik7XG4gICAgICAgIH1cbiAgICAgICAgdG9JbnZlcnNlW1wiemhcIl0gPSBGci5zdWIoeGlOLCBGci5vbmUpO1xuXG4gICAgICAgIC8vICAgwrcgZGVub21pbmF0b3IgbmVlZGVkIGluIHN0ZXAgMTAgYW5kIDExIG9mIHRoZSB2ZXJpZmllclxuICAgICAgICAvLyAgICAgdG9JbnZlcnNlLmRlbkgxICYgdG9JbnZlcnNlLmRlbkgyICAtPiBDb21wdXRlZCBpbiByb3VuZDUsIGNvbXB1dGVMKClcblxuICAgICAgICAvLyAgIMK3IGRlbm9taW5hdG9yIG5lZWRlZCBpbiB0aGUgdmVyaWZpZXIgd2hlbiBjb21wdXRpbmcgTF9pXntTMH0oWCksIExfaV57UzF9KFgpIGFuZCBMX2lee1MyfShYKVxuICAgICAgICBjb21wdXRlTGlTMCh0b0ludmVyc2UsIHJvb3RzLlMwLmgwdzgsIGNoYWxsZW5nZXMueSwgY3VydmUpO1xuXG4gICAgICAgIGNvbXB1dGVMaVMxKHRvSW52ZXJzZSwgcm9vdHMuUzEuaDF3NCwgY2hhbGxlbmdlcy55LCBjdXJ2ZSk7XG5cbiAgICAgICAgY29tcHV0ZUxpUzIodG9JbnZlcnNlLCByb290cy5TMi5oMnczLCByb290cy5TMi5oM3czLCBjaGFsbGVuZ2VzLnksIGNoYWxsZW5nZXMueGksIGNoYWxsZW5nZXMueGl3LCBjdXJ2ZSk7XG5cbiAgICAgICAgLy8gICDCtyBMX2kgaT0xIHRvIG51bSBwdWJsaWMgaW5wdXRzLCBuZWVkZWQgaW4gc3RlcCA2IGFuZCA3IG9mIHRoZSB2ZXJpZmllciB0byBjb21wdXRlIExfMSh4aSkgYW5kIFBJKHhpKVxuICAgICAgICBjb25zdCBzaXplID0gTWF0aC5tYXgoMSwgemtleS5uUHVibGljKTtcblxuICAgICAgICBsZXQgdyA9IEZyLm9uZTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHtcbiAgICAgICAgICAgIHRvSW52ZXJzZVtcIkxpX1wiICsgKGkgKyAxKV0gPSBGci5tdWwoRnIuZSh6a2V5LmRvbWFpblNpemUpLCBGci5zdWIoY2hhbGxlbmdlcy54aSwgdykpO1xuICAgICAgICAgICAgdyA9IEZyLm11bCh3LCBGci53W3prZXkucG93ZXJdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBtdWxBY2N1bXVsYXRvciA9IEZyLm9uZTtcbiAgICAgICAgZm9yIChjb25zdCBlbGVtZW50IG9mIE9iamVjdC52YWx1ZXModG9JbnZlcnNlKSkge1xuICAgICAgICAgICAgaWYoQXJyYXkuaXNBcnJheShlbGVtZW50KSkge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgc3ViRWxlbWVudCBvZiBlbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIG11bEFjY3VtdWxhdG9yID0gRnIubXVsKG11bEFjY3VtdWxhdG9yLCBzdWJFbGVtZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG11bEFjY3VtdWxhdG9yID0gRnIubXVsKG11bEFjY3VtdWxhdG9yLCBlbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gRnIuaW52KG11bEFjY3VtdWxhdG9yKTtcblxuICAgICAgICBcbiAgICAgICAgZnVuY3Rpb24gY29tcHV0ZUxpUzAodG9JbnZlcnNlLCByb290cywgeCwgY3VydmUpIHtcbiAgICAgICAgICAgIGNvbnN0IEZyID0gY3VydmUuRnI7XG4gICAgICAgICAgICBjb25zdCBsZW4gPSByb290cy5sZW5ndGg7XG4gICAgICAgIFxuICAgICAgICAgICAgY29uc3QgZGVuMSA9IEZyLm11bChGci5lKGxlbiksIEZyLmV4cChyb290c1swXSwgbGVuIC0gMikpO1xuICAgICAgICBcbiAgICAgICAgICAgIGNvbnN0IExpID0gW107XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGVuMiA9IHJvb3RzWygobGVuIC0gMSkgKiBpKSAlIGxlbl07XG4gICAgICAgICAgICAgICAgY29uc3QgZGVuMyA9IEZyLnN1Yih4LCByb290c1tpXSk7XG4gICAgICAgIFxuICAgICAgICAgICAgICAgIHRvSW52ZXJzZVtbXCJMaVMwX1wiICsgKGkgKyAxKV1dID0gRnIubXVsKEZyLm11bChkZW4xLCBkZW4yKSwgZGVuMyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICAgICAgcmV0dXJuIExpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gY29tcHV0ZUxpUzEodG9JbnZlcnNlLCByb290cywgeCwgY3VydmUpIHtcbiAgICAgICAgICAgIGNvbnN0IEZyID0gY3VydmUuRnI7XG4gICAgICAgICAgICBjb25zdCBsZW4gPSByb290cy5sZW5ndGg7XG4gICAgICAgIFxuICAgICAgICAgICAgY29uc3QgZGVuMSA9IEZyLm11bChGci5lKGxlbiksIEZyLmV4cChyb290c1swXSwgbGVuIC0gMikpO1xuICAgICAgICBcbiAgICAgICAgICAgIGNvbnN0IExpID0gW107XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGVuMiA9IHJvb3RzWygobGVuIC0gMSkgKiBpKSAlIGxlbl07XG4gICAgICAgICAgICAgICAgY29uc3QgZGVuMyA9IEZyLnN1Yih4LCByb290c1tpXSk7XG4gICAgICAgIFxuICAgICAgICAgICAgICAgIHRvSW52ZXJzZVtbXCJMaVMxX1wiICsgKGkgKyAxKV1dID0gRnIubXVsKEZyLm11bChkZW4xLCBkZW4yKSwgZGVuMyk7XG5cbiAgICAgICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgICAgICByZXR1cm4gTGk7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBjb21wdXRlTGlTMih0b0ludmVyc2UsIFMyLCBTMnAsIHZhbHVlLCB4aSwgeGl3LCBjdXJ2ZSkge1xuICAgICAgICAgICAgY29uc3QgRnIgPSBjdXJ2ZS5GcjtcbiAgICAgICAgXG4gICAgICAgICAgICBjb25zdCBMaSA9IFtdO1xuICAgICAgICBcbiAgICAgICAgICAgIGNvbnN0IF8zaDIgPSBGci5tdWwoRnIuZSgzKSwgUzJbMF0pO1xuICAgICAgICAgICAgY29uc3QgeGlzdWJ4aXcgPSBGci5zdWIoeGksIHhpdyk7XG4gICAgICAgICAgICBsZXQgZGVuMSA9IEZyLm11bChfM2gyLCB4aXN1Ynhpdyk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDM7IGkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRlbjIgPSBTMlsyICogaSAlIDNdO1xuICAgICAgICAgICAgICAgIGNvbnN0IGRlbjMgPSBGci5zdWIodmFsdWUsIFMyW2ldKTtcbiAgICAgICAgXG4gICAgICAgICAgICAgICAgdG9JbnZlcnNlW1tcIkxpUzJfXCIgKyAoaSArIDEpXV0gPSBGci5tdWwoZGVuMSxGci5tdWwoZGVuMiwgZGVuMykpO1xuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgICAgIGNvbnN0IF8zaDMgPSBGci5tdWwoRnIuZSgzKSwgUzJwWzBdKTtcbiAgICAgICAgICAgIGNvbnN0IHhpd3N1YnhpID0gRnIuc3ViKHhpdywgeGkpO1xuICAgICAgICAgICAgZGVuMSA9IEZyLm11bChfM2gzLCB4aXdzdWJ4aSk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDM7IGkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRlbjIgPSBTMnBbMiAqIGkgJSAzXTtcbiAgICAgICAgICAgICAgICBjb25zdCBkZW4zID0gRnIuc3ViKHZhbHVlLCBTMnBbaV0pO1xuICAgICAgICBcbiAgICAgICAgICAgICAgICB0b0ludmVyc2VbW1wiTGlTMl9cIiArIChpICsgMSArIDMpXV0gPSBGci5tdWwoZGVuMSxGci5tdWwoZGVuMiwgZGVuMykpOyAgICBcbiAgICAgICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgICAgICByZXR1cm4gTGk7XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCIvKlxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJranMuXG5cbiAgICBzbmFya2pzIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4gICAgbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZVxuICAgIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKVxuICAgIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtqcyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICAgIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvclxuICAgIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFsb25nIHdpdGhcbiAgICBzbmFya2pzLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuaW1wb3J0IGZmbG9ua1Byb3ZlIGZyb20gXCIuL2ZmbG9ua19wcm92ZS5qc1wiO1xuaW1wb3J0IHd0bnNfY2FsY3VsYXRlIGZyb20gXCIuL3d0bnNfY2FsY3VsYXRlLmpzXCI7XG5pbXBvcnQge3V0aWxzfSBmcm9tIFwiZmZqYXZhc2NyaXB0XCI7XG5jb25zdCB7dW5zdHJpbmdpZnlCaWdJbnRzfSA9IHV0aWxzO1xuXG5leHBvcnQgZGVmYXVsdCBhc3luYyBmdW5jdGlvbiBmZmxvbmtGdWxsUHJvdmUoX2lucHV0LCB3YXNtRmlsZW5hbWUsIHprZXlGaWxlbmFtZSwgbG9nZ2VyLCB3dG5zQ2FsY09wdGlvbnMsIHByb3Zlck9wdGlvbnMpIHtcbiAgICBjb25zdCBpbnB1dCA9IHVuc3RyaW5naWZ5QmlnSW50cyhfaW5wdXQpO1xuXG4gICAgY29uc3Qgd3Rucz0ge3R5cGU6IFwibWVtXCJ9O1xuXG4gICAgLy8gQ29tcHV0ZSB0aGUgd2l0bmVzc1xuICAgIGF3YWl0IHd0bnNfY2FsY3VsYXRlKGlucHV0LCB3YXNtRmlsZW5hbWUsIHd0bnMsIHd0bnNDYWxjT3B0aW9ucyk7XG5cbiAgICAvLyBDb21wdXRlIHRoZSBwcm9vZlxuICAgIHJldHVybiBhd2FpdCBmZmxvbmtQcm92ZSh6a2V5RmlsZW5hbWUsIHd0bnMsIGxvZ2dlciwgcHJvdmVyT3B0aW9ucyk7XG59IiwiLypcbiAgICBDb3B5cmlnaHQgMjAyMiBpZGVuMyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJranMuXG5cbiAgICBzbmFya2pzIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4gICAgbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZVxuICAgIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKVxuICAgIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtqcyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICAgIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvclxuICAgIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFsb25nIHdpdGhcbiAgICBzbmFya2pzLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuaW1wb3J0ICogYXMgY3VydmVzIGZyb20gXCIuL2N1cnZlcy5qc1wiO1xuaW1wb3J0IHsgQmlnQnVmZmVyLCB1dGlscyB9IGZyb20gXCJmZmphdmFzY3JpcHRcIjtcbmltcG9ydCB7IFByb29mIH0gZnJvbSBcIi4vcHJvb2YuanNcIjtcbmltcG9ydCB7IEtlY2NhazI1NlRyYW5zY3JpcHQgfSBmcm9tIFwiLi9LZWNjYWsyNTZUcmFuc2NyaXB0LmpzXCI7XG5pbXBvcnQgeyBTY2FsYXIgfSBmcm9tIFwiZmZqYXZhc2NyaXB0XCI7XG5cbmNvbnN0IHsgdW5zdHJpbmdpZnlCaWdJbnRzIH0gPSB1dGlscztcblxuZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gZmZsb25rVmVyaWZ5KF92a192ZXJpZmllciwgX3B1YmxpY1NpZ25hbHMsIF9wcm9vZiwgbG9nZ2VyKSB7XG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCJGRkxPTksgVkVSSUZJRVIgU1RBUlRFRFwiKTtcblxuICAgIF92a192ZXJpZmllciA9IHVuc3RyaW5naWZ5QmlnSW50cyhfdmtfdmVyaWZpZXIpO1xuICAgIF9wcm9vZiA9IHVuc3RyaW5naWZ5QmlnSW50cyhfcHJvb2YpO1xuXG4gICAgY29uc3QgY3VydmUgPSBhd2FpdCBjdXJ2ZXMuZ2V0Q3VydmVGcm9tTmFtZShfdmtfdmVyaWZpZXIuY3VydmUpO1xuXG4gICAgY29uc3QgdmsgPSBmcm9tT2JqZWN0VmsoY3VydmUsIF92a192ZXJpZmllcik7XG5cbiAgICAvLyBUT0RPID8/PyBDb21wdXRlIHdyXjMgYW5kIGNoZWNrIGlmIGl0IG1hdGNoZXMgd2l0aCB3XG5cbiAgICBjb25zdCBwcm9vZiA9IG5ldyBQcm9vZihjdXJ2ZSwgbG9nZ2VyKTtcbiAgICBwcm9vZi5mcm9tT2JqZWN0UHJvb2YoX3Byb29mKTtcblxuICAgIGNvbnN0IHB1YmxpY1NpZ25hbHMgPSB1bnN0cmluZ2lmeUJpZ0ludHMoX3B1YmxpY1NpZ25hbHMpO1xuXG4gICAgaWYgKHB1YmxpY1NpZ25hbHMubGVuZ3RoICE9PSB2ay5uUHVibGljKSB7XG4gICAgICAgIGxvZ2dlci5lcnJvcihcIk51bWJlciBvZiBwdWJsaWMgc2lnbmFscyBkb2VzIG5vdCBtYXRjaCB3aXRoIHZrXCIpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgRnIgPSBjdXJ2ZS5GcjtcblxuICAgIGlmIChsb2dnZXIpIHtcbiAgICAgICAgbG9nZ2VyLmluZm8oXCItLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXCIpO1xuICAgICAgICBsb2dnZXIuaW5mbyhcIiAgRkZMT05LIFZFUklGWSBTRVRUSU5HU1wiKTtcbiAgICAgICAgbG9nZ2VyLmluZm8oYCAgQ3VydmU6ICAgICAgICAgJHtjdXJ2ZS5uYW1lfWApO1xuICAgICAgICBsb2dnZXIuaW5mbyhgICBDaXJjdWl0IHBvd2VyOiAke3ZrLnBvd2VyfWApO1xuICAgICAgICBsb2dnZXIuaW5mbyhgICBEb21haW4gc2l6ZTogICAkezIgKiogdmsucG93ZXJ9YCk7XG4gICAgICAgIGxvZ2dlci5pbmZvKGAgIFB1YmxpYyB2YXJzOiAgICR7dmsublB1YmxpY31gKTtcbiAgICAgICAgbG9nZ2VyLmluZm8oXCItLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXCIpO1xuICAgIH1cblxuICAgIC8vIFNURVAgMSAtIFZhbGlkYXRlIHRoYXQgYWxsIHBvbHlub21pYWwgY29tbWl0bWVudHMg4oiIIEdfMVxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBDaGVja2luZyBjb21taXRtZW50cyBiZWxvbmcgdG8gRzFcIik7XG4gICAgaWYgKCFjb21taXRtZW50c0JlbG9uZ1RvRzEoY3VydmUsIHByb29mLCB2aykpIHtcbiAgICAgICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmVycm9yKFwiUHJvb2YgY29tbWl0bWVudHMgYXJlIG5vdCB2YWxpZFwiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8vIFNURVAgMiAtIFZhbGlkYXRlIHRoYXQgYWxsIGV2YWx1YXRpb25zIOKIiCBGXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCI+IENoZWNraW5nIGV2YWx1YXRpb25zIGJlbG9uZyB0byBGXCIpO1xuICAgIGlmICghZXZhbHVhdGlvbnNBcmVWYWxpZChjdXJ2ZSwgcHJvb2YpKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihcIlByb29mIGV2YWx1YXRpb25zIGFyZSBub3QgdmFsaWQuXCIpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gU1RFUCAzIC0gVmFsaWRhdGUgdGhhdCB3X2kg4oiIIEYgZm9yIGkg4oiIIFtsXVxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBDaGVja2luZyBwdWJsaWMgaW5wdXRzIGJlbG9uZyB0byBGXCIpO1xuICAgIGlmICghcHVibGljSW5wdXRzQXJlVmFsaWQoY3VydmUsIHB1YmxpY1NpZ25hbHMpKSB7XG4gICAgICAgIGlmIChsb2dnZXIpIGxvZ2dlci5lcnJvcihcIlB1YmxpYyBpbnB1dHMgYXJlIG5vdCB2YWxpZC5cIik7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBTVEVQIDQgLSBDb21wdXRlIHRoZSBjaGFsbGVuZ2VzOiBiZXRhLCBnYW1tYSwgeGksIGFscGhhIGFuZCB5IOKIiCBGXG4gICAgLy8gYXMgaW4gcHJvdmVyIGRlc2NyaXB0aW9uLCBmcm9tIHRoZSBjb21tb24gcHJlcHJvY2Vzc2VkIGlucHV0cywgcHVibGljIGlucHV0cyBhbmQgZWxlbWVudHMgb2Ygz4BfU05BUktcbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gQ29tcHV0aW5nIGNoYWxsZW5nZXNcIik7XG4gICAgY29uc3QgeyBjaGFsbGVuZ2VzLCByb290cyB9ID0gY29tcHV0ZUNoYWxsZW5nZXMoY3VydmUsIHByb29mLCB2aywgcHVibGljU2lnbmFscywgbG9nZ2VyKTtcblxuICAgIC8vIFNURVAgNSAtIENvbXB1dGUgdGhlIHplcm8gcG9seW5vbWlhbCBldmFsdWF0aW9uIFpfSCh4aSkgPSB4aV5uIC0gMVxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBDb21wdXRpbmcgWmVybyBwb2x5bm9taWFsIGV2YWx1YXRpb24gWl9IKHhpKVwiKTtcbiAgICBjaGFsbGVuZ2VzLnpoID0gRnIuc3ViKGNoYWxsZW5nZXMueGlOLCBGci5vbmUpO1xuICAgIGNoYWxsZW5nZXMuaW52emggPSBGci5pbnYoY2hhbGxlbmdlcy56aCk7XG5cbiAgICAvLyBTVEVQIDYgLSBDb21wdXRlIHRoZSBsYWdyYW5nZSBwb2x5bm9taWFsIGV2YWx1YXRpb24gTF8xKHhpKVxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBDb21wdXRpbmcgTGFncmFuZ2UgZXZhbHVhdGlvbnNcIik7XG4gICAgY29uc3QgbGFncmFuZ2VFdmFscyA9IGF3YWl0IGNvbXB1dGVMYWdyYW5nZUV2YWx1YXRpb25zKGN1cnZlLCBjaGFsbGVuZ2VzLCB2ayk7XG5cbiAgICAvLyBTVEVQIDcgLSBDb21wdXRlIHB1YmxpYyBpbnB1dCBldmFsdWF0aW9uIFBJKHhpKVxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBDb21wdXRpbmcgcG9seW5vbWlhbCBpZGVudGl0aWVzIFBJKFgpXCIpO1xuICAgIGNvbnN0IHBpID0gY2FsY3VsYXRlUEkoY3VydmUsIHB1YmxpY1NpZ25hbHMsIGxhZ3JhbmdlRXZhbHMpO1xuXG4gICAgLy8gU1RFUCA4IC0gQ29tcHV0ZSBwb2x5bm9taWFsIHIwIOKIiCBGX3s8NH1bWF1cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gQ29tcHV0aW5nIHIwKHkpXCIpO1xuICAgIGNvbnN0IHIwID0gY29tcHV0ZVIwKHByb29mLCBjaGFsbGVuZ2VzLCByb290cywgY3VydmUsIGxvZ2dlcik7XG5cbiAgICAvLyBTVEVQIDkgLSBDb21wdXRlIHBvbHlub21pYWwgcjEg4oiIIEZfezw0fVtYXVxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBDb21wdXRpbmcgcjEoeSlcIik7XG4gICAgY29uc3QgcjEgPSBjb21wdXRlUjEocHJvb2YsIGNoYWxsZW5nZXMsIHJvb3RzLCBwaSwgY3VydmUsIGxvZ2dlcik7XG5cbiAgICAvLyBTVEVQIDkgLSBDb21wdXRlIHBvbHlub21pYWwgcjIg4oiIIEZfezw2fVtYXVxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBDb21wdXRpbmcgcjIoeSlcIik7XG4gICAgY29uc3QgcjIgPSBjb21wdXRlUjIocHJvb2YsIGNoYWxsZW5nZXMsIHJvb3RzLCBsYWdyYW5nZUV2YWxzWzFdLCB2aywgY3VydmUsIGxvZ2dlcik7XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gQ29tcHV0aW5nIEZcIik7XG4gICAgY29uc3QgRiA9IGNvbXB1dGVGKGN1cnZlLCBwcm9vZiwgdmssIGNoYWxsZW5nZXMsIHJvb3RzKTtcblxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiPiBDb21wdXRpbmcgRVwiKTtcbiAgICBjb25zdCBFID0gY29tcHV0ZUUoY3VydmUsIHByb29mLCBjaGFsbGVuZ2VzLCB2aywgcjAsIHIxLCByMik7XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gQ29tcHV0aW5nIEpcIik7XG4gICAgY29uc3QgSiA9IGNvbXB1dGVKKGN1cnZlLCBwcm9vZiwgY2hhbGxlbmdlcyk7XG5cbiAgICBpZiAobG9nZ2VyKSBsb2dnZXIuaW5mbyhcIj4gVmFsaWRhdGUgYWxsIGV2YWx1YXRpb25zIHdpdGggYSBwYWlyaW5nXCIpO1xuICAgIGNvbnN0IHJlcyA9IGF3YWl0IGlzVmFsaWRQYWlyaW5nKGN1cnZlLCBwcm9vZiwgY2hhbGxlbmdlcywgdmssIEYsIEUsIEopO1xuXG4gICAgaWYgKGxvZ2dlcikge1xuICAgICAgICBpZiAocmVzKSB7XG4gICAgICAgICAgICBsb2dnZXIuaW5mbyhcIlBST09GIFZFUklGSUVEIFNVQ0NFU1NGVUxMWVwiKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKFwiSW52YWxpZCBQcm9vZlwiKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiRkZMT05LIFZFUklGSUVSIEZJTklTSEVEXCIpO1xuXG4gICAgcmV0dXJuIHJlcztcblxufVxuXG5mdW5jdGlvbiBmcm9tT2JqZWN0VmsoY3VydmUsIHZrKSB7XG4gICAgY29uc3QgcmVzID0gdms7XG4gICAgcmVzLmsxID0gY3VydmUuRnIuZnJvbU9iamVjdCh2ay5rMSk7XG4gICAgcmVzLmsyID0gY3VydmUuRnIuZnJvbU9iamVjdCh2ay5rMik7XG4gICAgcmVzLncgPSBjdXJ2ZS5Gci5mcm9tT2JqZWN0KHZrLncpO1xuICAgIC8vIHJlcy53VyA9IGN1cnZlLkZyLmZyb21PYmplY3Qodmsud1cpO1xuICAgIHJlcy53MyA9IGN1cnZlLkZyLmZyb21PYmplY3QodmsudzMpO1xuICAgIHJlcy53NCA9IGN1cnZlLkZyLmZyb21PYmplY3QodmsudzQpO1xuICAgIHJlcy53OCA9IGN1cnZlLkZyLmZyb21PYmplY3QodmsudzgpO1xuICAgIHJlcy53ciA9IGN1cnZlLkZyLmZyb21PYmplY3Qodmsud3IpO1xuICAgIHJlcy5YXzIgPSBjdXJ2ZS5HMi5mcm9tT2JqZWN0KHZrLlhfMik7XG4gICAgcmVzLkMwID0gY3VydmUuRzEuZnJvbU9iamVjdCh2ay5DMCk7XG4gICAgcmV0dXJuIHJlcztcbn1cblxuZnVuY3Rpb24gY29tbWl0bWVudHNCZWxvbmdUb0cxKGN1cnZlLCBwcm9vZiwgdmspIHtcbiAgICBjb25zdCBHMSA9IGN1cnZlLkcxO1xuICAgIHJldHVybiBHMS5pc1ZhbGlkKHByb29mLnBvbHlub21pYWxzLkMxKVxuICAgICAgICAmJiBHMS5pc1ZhbGlkKHByb29mLnBvbHlub21pYWxzLkMyKVxuICAgICAgICAmJiBHMS5pc1ZhbGlkKHByb29mLnBvbHlub21pYWxzLlcxKVxuICAgICAgICAmJiBHMS5pc1ZhbGlkKHByb29mLnBvbHlub21pYWxzLlcyKVxuICAgICAgICAmJiBHMS5pc1ZhbGlkKHZrLkMwKTtcbn1cblxuZnVuY3Rpb24gY2hlY2tWYWx1ZUJlbG9uZ1RvRmllbGQoY3VydmUsIHZhbHVlKSB7XG4gICAgcmV0dXJuIFNjYWxhci5nZXEodmFsdWUsIDApICYmIFNjYWxhci5sdCh2YWx1ZSwgY3VydmUucik7XG59XG5cbmZ1bmN0aW9uIGNoZWNrRXZhbHVhdGlvbklzVmFsaWQoY3VydmUsIGV2YWx1YXRpb24pIHtcbiAgICByZXR1cm4gY2hlY2tWYWx1ZUJlbG9uZ1RvRmllbGQoY3VydmUsIFNjYWxhci5mcm9tUnByTEUoZXZhbHVhdGlvbikpO1xufVxuXG5mdW5jdGlvbiBldmFsdWF0aW9uc0FyZVZhbGlkKGN1cnZlLCBwcm9vZikge1xuICAgIHJldHVybiBjaGVja0V2YWx1YXRpb25Jc1ZhbGlkKGN1cnZlLCBwcm9vZi5ldmFsdWF0aW9ucy5xbClcbiAgICAgICAgJiYgY2hlY2tFdmFsdWF0aW9uSXNWYWxpZChjdXJ2ZSwgcHJvb2YuZXZhbHVhdGlvbnMucXIpXG4gICAgICAgICYmIGNoZWNrRXZhbHVhdGlvbklzVmFsaWQoY3VydmUsIHByb29mLmV2YWx1YXRpb25zLnFtKVxuICAgICAgICAmJiBjaGVja0V2YWx1YXRpb25Jc1ZhbGlkKGN1cnZlLCBwcm9vZi5ldmFsdWF0aW9ucy5xbylcbiAgICAgICAgJiYgY2hlY2tFdmFsdWF0aW9uSXNWYWxpZChjdXJ2ZSwgcHJvb2YuZXZhbHVhdGlvbnMucWMpXG4gICAgICAgICYmIGNoZWNrRXZhbHVhdGlvbklzVmFsaWQoY3VydmUsIHByb29mLmV2YWx1YXRpb25zLnMxKVxuICAgICAgICAmJiBjaGVja0V2YWx1YXRpb25Jc1ZhbGlkKGN1cnZlLCBwcm9vZi5ldmFsdWF0aW9ucy5zMilcbiAgICAgICAgJiYgY2hlY2tFdmFsdWF0aW9uSXNWYWxpZChjdXJ2ZSwgcHJvb2YuZXZhbHVhdGlvbnMuczMpXG4gICAgICAgICYmIGNoZWNrRXZhbHVhdGlvbklzVmFsaWQoY3VydmUsIHByb29mLmV2YWx1YXRpb25zLmEpXG4gICAgICAgICYmIGNoZWNrRXZhbHVhdGlvbklzVmFsaWQoY3VydmUsIHByb29mLmV2YWx1YXRpb25zLmIpXG4gICAgICAgICYmIGNoZWNrRXZhbHVhdGlvbklzVmFsaWQoY3VydmUsIHByb29mLmV2YWx1YXRpb25zLmMpXG4gICAgICAgICYmIGNoZWNrRXZhbHVhdGlvbklzVmFsaWQoY3VydmUsIHByb29mLmV2YWx1YXRpb25zLnopXG4gICAgICAgICYmIGNoZWNrRXZhbHVhdGlvbklzVmFsaWQoY3VydmUsIHByb29mLmV2YWx1YXRpb25zLnp3KVxuICAgICAgICAmJiBjaGVja0V2YWx1YXRpb25Jc1ZhbGlkKGN1cnZlLCBwcm9vZi5ldmFsdWF0aW9ucy50MXcpXG4gICAgICAgICYmIGNoZWNrRXZhbHVhdGlvbklzVmFsaWQoY3VydmUsIHByb29mLmV2YWx1YXRpb25zLnQydyk7XG59XG5cbmZ1bmN0aW9uIHB1YmxpY0lucHV0c0FyZVZhbGlkKGN1cnZlLCBwdWJsaWNJbnB1dHMpIHtcbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgcHVibGljSW5wdXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKCFjaGVja1ZhbHVlQmVsb25nVG9GaWVsZChjdXJ2ZSwgcHVibGljSW5wdXRzW2ldKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBjb21wdXRlQ2hhbGxlbmdlcyhjdXJ2ZSwgcHJvb2YsIHZrLCBwdWJsaWNTaWduYWxzLCBsb2dnZXIpIHtcbiAgICBjb25zdCBGciA9IGN1cnZlLkZyO1xuXG4gICAgY29uc3QgY2hhbGxlbmdlcyA9IHt9O1xuICAgIGNvbnN0IHJvb3RzID0ge307XG4gICAgY29uc3QgdHJhbnNjcmlwdCA9IG5ldyBLZWNjYWsyNTZUcmFuc2NyaXB0KGN1cnZlKTtcblxuICAgIC8vIEFkZCBDMCB0byB0aGUgdHJhbnNjcmlwdFxuICAgIHRyYW5zY3JpcHQuYWRkUG9sQ29tbWl0bWVudCh2ay5DMCk7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHB1YmxpY1NpZ25hbHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdHJhbnNjcmlwdC5hZGRTY2FsYXIoRnIuZShwdWJsaWNTaWduYWxzW2ldKSk7XG4gICAgfVxuXG4gICAgdHJhbnNjcmlwdC5hZGRQb2xDb21taXRtZW50KHByb29mLnBvbHlub21pYWxzLkMxKTtcbiAgICBjaGFsbGVuZ2VzLmJldGEgPSB0cmFuc2NyaXB0LmdldENoYWxsZW5nZSgpO1xuICAgIHRyYW5zY3JpcHQucmVzZXQoKTtcblxuICAgIHRyYW5zY3JpcHQuYWRkU2NhbGFyKGNoYWxsZW5nZXMuYmV0YSk7XG4gICAgY2hhbGxlbmdlcy5nYW1tYSA9IHRyYW5zY3JpcHQuZ2V0Q2hhbGxlbmdlKCk7XG5cbiAgICB0cmFuc2NyaXB0LnJlc2V0KCk7XG4gICAgdHJhbnNjcmlwdC5hZGRTY2FsYXIoY2hhbGxlbmdlcy5nYW1tYSk7XG4gICAgdHJhbnNjcmlwdC5hZGRQb2xDb21taXRtZW50KHByb29mLnBvbHlub21pYWxzLkMyKTtcbiAgICBjb25zdCB4aVNlZWQgPSB0cmFuc2NyaXB0LmdldENoYWxsZW5nZSgpO1xuICAgIGNvbnN0IHhpU2VlZDIgPSBGci5zcXVhcmUoeGlTZWVkKTtcblxuICAgIGxldCB3OCA9IFtdO1xuICAgIHc4WzFdID0gdmsudzg7XG4gICAgdzhbMl0gPSBGci5zcXVhcmUodmsudzgpO1xuICAgIHc4WzNdID0gRnIubXVsKHc4WzJdLCB2ay53OCk7XG4gICAgdzhbNF0gPSBGci5tdWwodzhbM10sIHZrLnc4KTtcbiAgICB3OFs1XSA9IEZyLm11bCh3OFs0XSwgdmsudzgpO1xuICAgIHc4WzZdID0gRnIubXVsKHc4WzVdLCB2ay53OCk7XG4gICAgdzhbN10gPSBGci5tdWwodzhbNl0sIHZrLnc4KTtcbiAgICBsZXQgdzQgPSBbXTtcbiAgICB3NFsxXSA9IHZrLnc0O1xuICAgIHc0WzJdID0gRnIuc3F1YXJlKHZrLnc0KTtcbiAgICB3NFszXSA9IEZyLm11bCh3NFsyXSwgdmsudzQpO1xuICAgIGxldCB3MyA9IFtdO1xuICAgIHczWzFdID0gdmsudzM7XG4gICAgdzNbMl0gPSBGci5zcXVhcmUodmsudzMpO1xuXG4gICAgLy8gY29uc3QgdzRfMiA9IEZyLnNxdWFyZSh2ay53NCk7XG4gICAgLy8gY29uc3QgdzRfMyA9IEZyLm11bCh3NF8yLCB2ay53NCk7XG4gICAgLy8gY29uc3QgdzNfMiA9IEZyLnNxdWFyZSh2ay53Myk7XG5cbiAgICAvLyBDb21wdXRlIGgwID0geGlTZWVkZXJeM1xuICAgIHJvb3RzLlMwID0ge307XG4gICAgcm9vdHMuUzAuaDB3OCA9IFtdO1xuICAgIHJvb3RzLlMwLmgwdzhbMF0gPSBGci5tdWwoeGlTZWVkMiwgeGlTZWVkKTtcbiAgICBmb3IgKGxldCBpID0gMTsgaSA8IDg7IGkrKykge1xuICAgICAgICByb290cy5TMC5oMHc4W2ldID0gRnIubXVsKHJvb3RzLlMwLmgwdzhbMF0sIHc4W2ldKTtcbiAgICB9XG5cbiAgICAvLyBDb21wdXRlIGgxID0geGlfc2VlZGVyXjZcbiAgICByb290cy5TMSA9IHt9O1xuICAgIHJvb3RzLlMxLmgxdzQgPSBbXTtcbiAgICByb290cy5TMS5oMXc0WzBdID0gRnIuc3F1YXJlKHJvb3RzLlMwLmgwdzhbMF0pO1xuICAgIGZvciAobGV0IGkgPSAxOyBpIDwgNDsgaSsrKSB7XG4gICAgICAgIHJvb3RzLlMxLmgxdzRbaV0gPSBGci5tdWwocm9vdHMuUzEuaDF3NFswXSwgdzRbaV0pO1xuICAgIH1cblxuICAgIC8vIENvbXB1dGUgaDIgPSB4aV9zZWVkZXJeOFxuICAgIHJvb3RzLlMyID0ge307XG4gICAgcm9vdHMuUzIuaDJ3MyA9IFtdO1xuICAgIHJvb3RzLlMyLmgydzNbMF0gPSBGci5tdWwocm9vdHMuUzEuaDF3NFswXSwgeGlTZWVkMik7XG4gICAgcm9vdHMuUzIuaDJ3M1sxXSA9IEZyLm11bChyb290cy5TMi5oMnczWzBdLCB3M1sxXSk7XG4gICAgcm9vdHMuUzIuaDJ3M1syXSA9IEZyLm11bChyb290cy5TMi5oMnczWzBdLCB3M1syXSk7XG5cbiAgICByb290cy5TMi5oM3czID0gW107XG4gICAgLy8gTXVsdGlwbHkgaDMgYnkgdGhpcmQtcm9vdC1vbWVnYSB0byBvYnRhaW4gaF8zXjMgPSB4ac+JXG4gICAgLy8gU28sIGgzID0geGlfc2VlZGVyXjggz4leezEvM31cbiAgICByb290cy5TMi5oM3czWzBdID0gRnIubXVsKHJvb3RzLlMyLmgydzNbMF0sIHZrLndyKTtcbiAgICByb290cy5TMi5oM3czWzFdID0gRnIubXVsKHJvb3RzLlMyLmgzdzNbMF0sIHczWzFdKTtcbiAgICByb290cy5TMi5oM3czWzJdID0gRnIubXVsKHJvb3RzLlMyLmgzdzNbMF0sIHczWzJdKTtcblxuICAgIC8vIENvbXB1dGUgeGkgPSB4aV9zZWVkZXJeMTJcbiAgICBjaGFsbGVuZ2VzLnhpID0gRnIubXVsKEZyLnNxdWFyZShyb290cy5TMi5oMnczWzBdKSwgcm9vdHMuUzIuaDJ3M1swXSk7XG4gICAgY2hhbGxlbmdlcy54aXcgPSBGci5tdWwoY2hhbGxlbmdlcy54aSwgRnIud1t2ay5wb3dlcl0pO1xuXG4gICAgY2hhbGxlbmdlcy54aU4gPSBjaGFsbGVuZ2VzLnhpO1xuICAgIHZrLmRvbWFpblNpemUgPSAxO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdmsucG93ZXI7IGkrKykge1xuICAgICAgICBjaGFsbGVuZ2VzLnhpTiA9IEZyLnNxdWFyZShjaGFsbGVuZ2VzLnhpTik7XG4gICAgICAgIHZrLmRvbWFpblNpemUgKj0gMjtcbiAgICB9XG5cbiAgICB0cmFuc2NyaXB0LnJlc2V0KCk7XG4gICAgdHJhbnNjcmlwdC5hZGRTY2FsYXIoeGlTZWVkKTtcbiAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihwcm9vZi5ldmFsdWF0aW9ucy5xbCk7XG4gICAgdHJhbnNjcmlwdC5hZGRTY2FsYXIocHJvb2YuZXZhbHVhdGlvbnMucXIpO1xuICAgIHRyYW5zY3JpcHQuYWRkU2NhbGFyKHByb29mLmV2YWx1YXRpb25zLnFtKTtcbiAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihwcm9vZi5ldmFsdWF0aW9ucy5xbyk7XG4gICAgdHJhbnNjcmlwdC5hZGRTY2FsYXIocHJvb2YuZXZhbHVhdGlvbnMucWMpO1xuICAgIHRyYW5zY3JpcHQuYWRkU2NhbGFyKHByb29mLmV2YWx1YXRpb25zLnMxKTtcbiAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihwcm9vZi5ldmFsdWF0aW9ucy5zMik7XG4gICAgdHJhbnNjcmlwdC5hZGRTY2FsYXIocHJvb2YuZXZhbHVhdGlvbnMuczMpO1xuICAgIHRyYW5zY3JpcHQuYWRkU2NhbGFyKHByb29mLmV2YWx1YXRpb25zLmEpO1xuICAgIHRyYW5zY3JpcHQuYWRkU2NhbGFyKHByb29mLmV2YWx1YXRpb25zLmIpO1xuICAgIHRyYW5zY3JpcHQuYWRkU2NhbGFyKHByb29mLmV2YWx1YXRpb25zLmMpO1xuICAgIHRyYW5zY3JpcHQuYWRkU2NhbGFyKHByb29mLmV2YWx1YXRpb25zLnopO1xuICAgIHRyYW5zY3JpcHQuYWRkU2NhbGFyKHByb29mLmV2YWx1YXRpb25zLnp3KTtcbiAgICB0cmFuc2NyaXB0LmFkZFNjYWxhcihwcm9vZi5ldmFsdWF0aW9ucy50MXcpO1xuICAgIHRyYW5zY3JpcHQuYWRkU2NhbGFyKHByb29mLmV2YWx1YXRpb25zLnQydyk7XG4gICAgY2hhbGxlbmdlcy5hbHBoYSA9IHRyYW5zY3JpcHQuZ2V0Q2hhbGxlbmdlKCk7XG5cbiAgICB0cmFuc2NyaXB0LnJlc2V0KCk7XG4gICAgdHJhbnNjcmlwdC5hZGRTY2FsYXIoY2hhbGxlbmdlcy5hbHBoYSk7XG4gICAgdHJhbnNjcmlwdC5hZGRQb2xDb21taXRtZW50KHByb29mLnBvbHlub21pYWxzLlcxKTtcbiAgICBjaGFsbGVuZ2VzLnkgPSB0cmFuc2NyaXB0LmdldENoYWxsZW5nZSgpO1xuXG4gICAgaWYgKGxvZ2dlcikge1xuICAgICAgICBsb2dnZXIuaW5mbyhcIsK3wrfCtyBjaGFsbGVuZ2VzLmJldGE6ICBcIiArIEZyLnRvU3RyaW5nKGNoYWxsZW5nZXMuYmV0YSkpO1xuICAgICAgICBsb2dnZXIuaW5mbyhcIsK3wrfCtyBjaGFsbGVuZ2VzLmdhbW1hOiBcIiArIEZyLnRvU3RyaW5nKGNoYWxsZW5nZXMuZ2FtbWEpKTtcbiAgICAgICAgbG9nZ2VyLmluZm8oXCLCt8K3wrcgY2hhbGxlbmdlcy54aTogICAgXCIgKyBGci50b1N0cmluZyhjaGFsbGVuZ2VzLnhpKSk7XG4gICAgICAgIGxvZ2dlci5pbmZvKFwiwrfCt8K3IGNoYWxsZW5nZXMuYWxwaGE6IFwiICsgRnIudG9TdHJpbmcoY2hhbGxlbmdlcy5hbHBoYSkpO1xuICAgICAgICBsb2dnZXIuaW5mbyhcIsK3wrfCtyBjaGFsbGVuZ2VzLnk6ICAgICBcIiArIEZyLnRvU3RyaW5nKGNoYWxsZW5nZXMueSkpO1xuICAgIH1cblxuICAgIHJldHVybiB7IGNoYWxsZW5nZXM6IGNoYWxsZW5nZXMsIHJvb3RzOiByb290cyB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBjb21wdXRlTGFncmFuZ2VFdmFsdWF0aW9ucyhjdXJ2ZSwgY2hhbGxlbmdlcywgdmspIHtcbiAgICBjb25zdCBGciA9IGN1cnZlLkZyO1xuXG4gICAgY29uc3Qgc2l6ZSA9IE1hdGgubWF4KDEsIHZrLm5QdWJsaWMpO1xuICAgIGNvbnN0IG51bUFyciA9IG5ldyBCaWdCdWZmZXIoc2l6ZSAqIEZyLm44KTtcbiAgICBsZXQgZGVuQXJyID0gbmV3IEJpZ0J1ZmZlcihzaXplICogRnIubjgpO1xuXG4gICAgbGV0IHcgPSBGci5vbmU7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHtcbiAgICAgICAgY29uc3QgaV9zRnIgPSBpICogRnIubjg7XG4gICAgICAgIG51bUFyci5zZXQoRnIubXVsKHcsIGNoYWxsZW5nZXMuemgpLCBpX3NGcik7XG4gICAgICAgIGRlbkFyci5zZXQoRnIubXVsKEZyLmUodmsuZG9tYWluU2l6ZSksIEZyLnN1YihjaGFsbGVuZ2VzLnhpLCB3KSksIGlfc0ZyKTtcbiAgICAgICAgdyA9IEZyLm11bCh3LCB2ay53KTtcbiAgICB9XG5cbiAgICBkZW5BcnIgPSBhd2FpdCBGci5iYXRjaEludmVyc2UoZGVuQXJyKTtcblxuICAgIGxldCBMID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHtcbiAgICAgICAgY29uc3QgaV9zRnIgPSBpICogRnIubjg7XG4gICAgICAgIExbaSArIDFdID0gRnIubXVsKG51bUFyci5zbGljZShpX3NGciwgaV9zRnIgKyBGci5uOCksIGRlbkFyci5zbGljZShpX3NGciwgaV9zRnIgKyBGci5uOCkpO1xuICAgIH1cbiAgICByZXR1cm4gTDtcbn1cblxuZnVuY3Rpb24gY2FsY3VsYXRlUEkoY3VydmUsIHB1YmxpY1NpZ25hbHMsIGxhZ3JhbmdlRXZhbHMpIHtcbiAgICBjb25zdCBGciA9IGN1cnZlLkZyO1xuXG4gICAgbGV0IHBpID0gRnIuemVybztcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHB1YmxpY1NpZ25hbHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgdyA9IEZyLmUocHVibGljU2lnbmFsc1tpXSk7XG4gICAgICAgIHBpID0gRnIuc3ViKHBpLCBGci5tdWwodywgbGFncmFuZ2VFdmFsc1tpICsgMV0pKTtcbiAgICB9XG4gICAgcmV0dXJuIHBpO1xufVxuXG5mdW5jdGlvbiBjb21wdXRlUjAocHJvb2YsIGNoYWxsZW5nZXMsIHJvb3RzLCBjdXJ2ZSwgbG9nZ2VyKSB7XG4gICAgY29uc3QgRnIgPSBjdXJ2ZS5GcjtcblxuICAgIGNvbnN0IExpID0gY29tcHV0ZUxhZ3JhbmdlTGlTaShyb290cy5TMC5oMHc4LCBjaGFsbGVuZ2VzLnksIGNoYWxsZW5nZXMueGksIGN1cnZlKTtcblxuICAgIC8vIHIwKHkpID0g4oiRXzFeOCBDXzAoaF8wIM+JXzhee2ktMX0pIExfaSh5KS4gVG8gdGhpcyBlbmQgd2UgbmVlZCB0byBjb21wdXRlXG5cbiAgICAvLyBDb21wdXRlIHRoZSA4IEMwIHZhbHVlc1xuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiwrfCt8K3IENvbXB1dGluZyByMCh5KVwiKTtcblxuICAgIGxldCByZXMgPSBGci56ZXJvO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgODsgaSsrKSB7XG4gICAgICAgIGxldCBjb2VmVmFsdWVzID0gW107XG4gICAgICAgIGNvZWZWYWx1ZXNbMV0gPSByb290cy5TMC5oMHc4W2ldO1xuICAgICAgICBmb3IgKGxldCBqID0gMjsgaiA8IDg7IGorKykge1xuICAgICAgICAgICAgY29lZlZhbHVlc1tqXSA9IEZyLm11bChjb2VmVmFsdWVzW2ogLSAxXSwgcm9vdHMuUzAuaDB3OFtpXSk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgYzAgPSBGci5hZGQocHJvb2YuZXZhbHVhdGlvbnMucWwsIEZyLm11bChwcm9vZi5ldmFsdWF0aW9ucy5xciwgY29lZlZhbHVlc1sxXSkpO1xuICAgICAgICBjMCA9IEZyLmFkZChjMCwgRnIubXVsKHByb29mLmV2YWx1YXRpb25zLnFvLCBjb2VmVmFsdWVzWzJdKSk7XG4gICAgICAgIGMwID0gRnIuYWRkKGMwLCBGci5tdWwocHJvb2YuZXZhbHVhdGlvbnMucW0sIGNvZWZWYWx1ZXNbM10pKTtcbiAgICAgICAgYzAgPSBGci5hZGQoYzAsIEZyLm11bChwcm9vZi5ldmFsdWF0aW9ucy5xYywgY29lZlZhbHVlc1s0XSkpO1xuICAgICAgICBjMCA9IEZyLmFkZChjMCwgRnIubXVsKHByb29mLmV2YWx1YXRpb25zLnMxLCBjb2VmVmFsdWVzWzVdKSk7XG4gICAgICAgIGMwID0gRnIuYWRkKGMwLCBGci5tdWwocHJvb2YuZXZhbHVhdGlvbnMuczIsIGNvZWZWYWx1ZXNbNl0pKTtcbiAgICAgICAgYzAgPSBGci5hZGQoYzAsIEZyLm11bChwcm9vZi5ldmFsdWF0aW9ucy5zMywgY29lZlZhbHVlc1s3XSkpO1xuXG4gICAgICAgIHJlcyA9IEZyLmFkZChyZXMsIEZyLm11bChjMCwgTGlbaV0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzO1xufVxuXG5mdW5jdGlvbiBjb21wdXRlUjEocHJvb2YsIGNoYWxsZW5nZXMsIHJvb3RzLCBwaSwgY3VydmUsIGxvZ2dlcikge1xuICAgIGNvbnN0IEZyID0gY3VydmUuRnI7XG5cbiAgICBjb25zdCBMaSA9IGNvbXB1dGVMYWdyYW5nZUxpU2kocm9vdHMuUzEuaDF3NCwgY2hhbGxlbmdlcy55LCBjaGFsbGVuZ2VzLnhpLCBjdXJ2ZSk7XG5cbiAgICAvLyByMSh5KSA9IOKIkV8xXjQgQ18xKGhfMSDPiV80XntpLTF9KSBMX2koeSkuIFRvIHRoaXMgZW5kIHdlIG5lZWQgdG8gY29tcHV0ZVxuICAgIC8vIFoxID0ge0MxKGhfMX0sIEMxKGhfMSDPiV80KSwgQzEoaF8xIM+JXzReMiksIEMxKGhfMSDPiV80XjMpfVxuICAgIC8vIHdoZXJlIENfMShoXzEgz4lfNF57aS0xfSkgPSBldmFsLmEgKyBoXzEgz4lfNF5pIGV2YWwuYiArIChoXzEgz4lfNF5pKV4yIGV2YWwuYyArIChoXzEgz4lfNF5pKV4zIFQwKHhpKSxcbiAgICAvLyB3aGVyZSBUMCh4aSkgPSBbIHFMwrdhICsgcVLCt2IgKyBxTcK3YcK3YiArIHFPwrdjICsgcUMgKyBQSSh4aSkgXSAvIFpfSCh4aSlcblxuICAgIC8vIENvbXB1dGUgVDAoeGkpXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCLCt8K3wrcgQ29tcHV0aW5nIFQwKHhpKVwiKTtcbiAgICBsZXQgdDAgPSBGci5tdWwocHJvb2YuZXZhbHVhdGlvbnMucWwsIHByb29mLmV2YWx1YXRpb25zLmEpO1xuICAgIHQwID0gRnIuYWRkKHQwLCBGci5tdWwocHJvb2YuZXZhbHVhdGlvbnMucXIsIHByb29mLmV2YWx1YXRpb25zLmIpKTtcbiAgICB0MCA9IEZyLmFkZCh0MCwgRnIubXVsKHByb29mLmV2YWx1YXRpb25zLnFtLCBGci5tdWwocHJvb2YuZXZhbHVhdGlvbnMuYSwgcHJvb2YuZXZhbHVhdGlvbnMuYikpKTtcbiAgICB0MCA9IEZyLmFkZCh0MCwgRnIubXVsKHByb29mLmV2YWx1YXRpb25zLnFvLCBwcm9vZi5ldmFsdWF0aW9ucy5jKSk7XG4gICAgdDAgPSBGci5hZGQodDAsIHByb29mLmV2YWx1YXRpb25zLnFjKTtcbiAgICB0MCA9IEZyLmFkZCh0MCwgcGkpO1xuICAgIHQwID0gRnIubXVsKHQwLCBjaGFsbGVuZ2VzLmludnpoKTtcblxuICAgIC8vIENvbXB1dGUgdGhlIDQgQzEgdmFsdWVzXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCLCt8K3wrcgQ29tcHV0aW5nIEMxKGhfMc+JXzReaSkgdmFsdWVzXCIpO1xuXG4gICAgbGV0IHJlcyA9IEZyLnplcm87XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCA0OyBpKyspIHtcbiAgICAgICAgbGV0IGMxID0gcHJvb2YuZXZhbHVhdGlvbnMuYTtcbiAgICAgICAgYzEgPSBGci5hZGQoYzEsIEZyLm11bChyb290cy5TMS5oMXc0W2ldLCBwcm9vZi5ldmFsdWF0aW9ucy5iKSk7XG4gICAgICAgIGNvbnN0IGgxdzRTcXVhcmVkID0gRnIuc3F1YXJlKHJvb3RzLlMxLmgxdzRbaV0pO1xuICAgICAgICBjMSA9IEZyLmFkZChjMSwgRnIubXVsKGgxdzRTcXVhcmVkLCBwcm9vZi5ldmFsdWF0aW9ucy5jKSk7XG4gICAgICAgIGMxID0gRnIuYWRkKGMxLCBGci5tdWwoRnIubXVsKGgxdzRTcXVhcmVkLCByb290cy5TMS5oMXc0W2ldKSwgdDApKTtcblxuICAgICAgICByZXMgPSBGci5hZGQocmVzLCBGci5tdWwoYzEsIExpW2ldKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlcztcbn1cblxuZnVuY3Rpb24gY29tcHV0ZVIyKHByb29mLCBjaGFsbGVuZ2VzLCByb290cywgbGFncmFuZ2UxLCB2aywgY3VydmUsIGxvZ2dlcikge1xuICAgIGNvbnN0IEZyID0gY3VydmUuRnI7XG5cbiAgICBjb25zdCBMaVMyID0gY29tcHV0ZUxhZ3JhbmdlTGlTMihbcm9vdHMuUzIuaDJ3Mywgcm9vdHMuUzIuaDN3M10sIGNoYWxsZW5nZXMueSwgY2hhbGxlbmdlcy54aSwgY2hhbGxlbmdlcy54aXcsIGN1cnZlKTtcblxuICAgIC8vIHIyKHkpID0g4oiRXzFeMyBDXzIoaF8yIM+JXzNee2ktMX0pIExfaSh5KSArIOKIkV8xXjMgQ18yKGhfMyDPiV8zXntpLTF9KSBMX3tpKzN9KHkpLiBUbyB0aGlzIGVuZCB3ZSBuZWVkIHRvIGNvbXB1dGVcbiAgICAvLyBaMiA9IHtbQzIoaF8yfSwgQzIoaF8yIM+JXzMpLCBDMihoXzIgz4lfM14yKV0sIFtDMihoXzN9LCBDMihoXzMgz4lfMyksIEMyKGhfMyDPiV8zXjIpXX1cbiAgICAvLyB3aGVyZSBDXzIoaF8yIM+JXzNee2ktMX0pID0gZXZhbC56ICsgaF8yIM+JXzJeaSBUMSh4aSkgKyAoaF8yIM+JXzNeaSleMiBUMih4aSksXG4gICAgLy8gd2hlcmUgQ18yKGhfMyDPiV8zXntpLTF9KSA9IGV2YWwueiArIGhfMyDPiV8yXmkgVDEoeGkpICsgKGhfMyDPiV8zXmkpXjIgVDIoeGkpLFxuICAgIC8vIHdoZXJlIFQxKHhpKSA9IFsgTF8xKHhpKSh6LTEpXSAvIFpfSCh4aSlcbiAgICAvLyBhbmQgVDIoeGkpID0gWyAgKGEgKyBiZXRhwrd4aSArIGdhbW1hKShiICsgYmV0YcK3eGnCt2sxICsgZ2FtbWEpKGMgKyBiZXRhwrd4acK3azIgKyBnYW1tYSl6XG4gICAgLy8gICAgICAgICAgICAgICAtIChhICsgYmV0YcK3c2lnbWExICsgZ2FtbWEpKGIgKyBiZXRhwrdzaWdtYTIgKyBnYW1tYSkoYyArIGJldGHCt3NpZ21hMyArIGdhbW1hKXrPiSAgXSAvIFpfSCh4aSlcblxuICAgIC8vIENvbXB1dGUgVDEoeGkpXG4gICAgaWYgKGxvZ2dlcikgbG9nZ2VyLmluZm8oXCLCt8K3wrcgQ29tcHV0aW5nIFQxKHhpKVwiKTtcbiAgICBsZXQgdDEgPSBGci5zdWIocHJvb2YuZXZhbHVhdGlvbnMueiwgRnIub25lKTtcbiAgICB0MSA9IEZyLm11bCh0MSwgbGFncmFuZ2UxKTtcbiAgICB0MSA9IEZyLm11bCh0MSwgY2hhbGxlbmdlcy5pbnZ6aCk7XG5cbiAgICAvLyBDb21wdXRlIFQyKHhpKVxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiwrfCt8K3IENvbXB1dGluZyBUMih4aSlcIik7XG4gICAgY29uc3QgYmV0YXhpID0gRnIubXVsKGNoYWxsZW5nZXMuYmV0YSwgY2hhbGxlbmdlcy54aSk7XG4gICAgY29uc3QgdDIxMSA9IEZyLmFkZChwcm9vZi5ldmFsdWF0aW9ucy5hLCBGci5hZGQoYmV0YXhpLCBjaGFsbGVuZ2VzLmdhbW1hKSk7XG4gICAgY29uc3QgdDIxMiA9IEZyLmFkZChwcm9vZi5ldmFsdWF0aW9ucy5iLCBGci5hZGQoRnIubXVsKGJldGF4aSwgdmsuazEpLCBjaGFsbGVuZ2VzLmdhbW1hKSk7XG4gICAgY29uc3QgdDIxMyA9IEZyLmFkZChwcm9vZi5ldmFsdWF0aW9ucy5jLCBGci5hZGQoRnIubXVsKGJldGF4aSwgdmsuazIpLCBjaGFsbGVuZ2VzLmdhbW1hKSk7XG4gICAgY29uc3QgdDIxID0gRnIubXVsKHQyMTEsIEZyLm11bCh0MjEyLCBGci5tdWwodDIxMywgcHJvb2YuZXZhbHVhdGlvbnMueikpKTtcblxuICAgIGNvbnN0IHQyMjEgPSBGci5hZGQocHJvb2YuZXZhbHVhdGlvbnMuYSwgRnIuYWRkKEZyLm11bChjaGFsbGVuZ2VzLmJldGEsIHByb29mLmV2YWx1YXRpb25zLnMxKSwgY2hhbGxlbmdlcy5nYW1tYSkpO1xuICAgIGNvbnN0IHQyMjIgPSBGci5hZGQocHJvb2YuZXZhbHVhdGlvbnMuYiwgRnIuYWRkKEZyLm11bChjaGFsbGVuZ2VzLmJldGEsIHByb29mLmV2YWx1YXRpb25zLnMyKSwgY2hhbGxlbmdlcy5nYW1tYSkpO1xuICAgIGNvbnN0IHQyMjMgPSBGci5hZGQocHJvb2YuZXZhbHVhdGlvbnMuYywgRnIuYWRkKEZyLm11bChjaGFsbGVuZ2VzLmJldGEsIHByb29mLmV2YWx1YXRpb25zLnMzKSwgY2hhbGxlbmdlcy5nYW1tYSkpO1xuICAgIGNvbnN0IHQyMiA9IEZyLm11bCh0MjIxLCBGci5tdWwodDIyMiwgRnIubXVsKHQyMjMsIHByb29mLmV2YWx1YXRpb25zLnp3KSkpO1xuXG4gICAgbGV0IHQyID0gRnIuc3ViKHQyMSwgdDIyKTtcbiAgICB0MiA9IEZyLm11bCh0MiwgY2hhbGxlbmdlcy5pbnZ6aCk7XG5cbiAgICAvLyBDb21wdXRlIHRoZSA2IEMyIHZhbHVlc1xuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiwrfCt8K3IENvbXB1dGluZyBDMihoXzLPiV8zXmkpIHZhbHVlc1wiKTtcbiAgICBsZXQgcmVzID0gRnIuemVybztcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDM7IGkrKykge1xuICAgICAgICBsZXQgYzIgPSBGci5hZGQocHJvb2YuZXZhbHVhdGlvbnMueiwgRnIubXVsKHJvb3RzLlMyLmgydzNbaV0sIHQxKSk7XG4gICAgICAgIGMyID0gRnIuYWRkKGMyLCBGci5tdWwoRnIuc3F1YXJlKHJvb3RzLlMyLmgydzNbaV0pLCB0MikpO1xuXG4gICAgICAgIHJlcyA9IEZyLmFkZChyZXMsIEZyLm11bChjMiwgTGlTMltpXSkpO1xuICAgIH1cblxuICAgIGlmIChsb2dnZXIpIGxvZ2dlci5pbmZvKFwiwrfCt8K3IENvbXB1dGluZyBDMihoXzPPiV8zXmkpIHZhbHVlc1wiKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDM7IGkrKykge1xuICAgICAgICBsZXQgYzIgPSBGci5hZGQocHJvb2YuZXZhbHVhdGlvbnMuencsIEZyLm11bChyb290cy5TMi5oM3czW2ldLCBwcm9vZi5ldmFsdWF0aW9ucy50MXcpKTtcbiAgICAgICAgYzIgPSBGci5hZGQoYzIsIEZyLm11bChGci5zcXVhcmUocm9vdHMuUzIuaDN3M1tpXSksIHByb29mLmV2YWx1YXRpb25zLnQydykpO1xuXG4gICAgICAgIHJlcyA9IEZyLmFkZChyZXMsIEZyLm11bChjMiwgTGlTMltpICsgM10pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzO1xufVxuXG5mdW5jdGlvbiBjb21wdXRlRihjdXJ2ZSwgcHJvb2YsIHZrLCBjaGFsbGVuZ2VzLCByb290cykge1xuICAgIGNvbnN0IEcxID0gY3VydmUuRzE7XG4gICAgY29uc3QgRnIgPSBjdXJ2ZS5GcjtcblxuICAgIGxldCBtdWxIMCA9IEZyLnN1YihjaGFsbGVuZ2VzLnksIHJvb3RzLlMwLmgwdzhbMF0pO1xuICAgIGZvciAobGV0IGkgPSAxOyBpIDwgODsgaSsrKSB7XG4gICAgICAgIG11bEgwID0gRnIubXVsKG11bEgwLCBGci5zdWIoY2hhbGxlbmdlcy55LCByb290cy5TMC5oMHc4W2ldKSk7XG4gICAgfVxuXG4gICAgY2hhbGxlbmdlcy50ZW1wID0gbXVsSDA7XG5cbiAgICBsZXQgbXVsSDEgPSBGci5zdWIoY2hhbGxlbmdlcy55LCByb290cy5TMS5oMXc0WzBdKTtcbiAgICBmb3IgKGxldCBpID0gMTsgaSA8IDQ7IGkrKykge1xuICAgICAgICBtdWxIMSA9IEZyLm11bChtdWxIMSwgRnIuc3ViKGNoYWxsZW5nZXMueSwgcm9vdHMuUzEuaDF3NFtpXSkpO1xuICAgIH1cblxuICAgIGxldCBtdWxIMiA9IEZyLnN1YihjaGFsbGVuZ2VzLnksIHJvb3RzLlMyLmgydzNbMF0pO1xuICAgIGZvciAobGV0IGkgPSAxOyBpIDwgMzsgaSsrKSB7XG4gICAgICAgIG11bEgyID0gRnIubXVsKG11bEgyLCBGci5zdWIoY2hhbGxlbmdlcy55LCByb290cy5TMi5oMnczW2ldKSk7XG4gICAgfVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMzsgaSsrKSB7XG4gICAgICAgIG11bEgyID0gRnIubXVsKG11bEgyLCBGci5zdWIoY2hhbGxlbmdlcy55LCByb290cy5TMi5oM3czW2ldKSk7XG4gICAgfVxuXG4gICAgY2hhbGxlbmdlcy5xdW90aWVudDEgPSBGci5tdWwoY2hhbGxlbmdlcy5hbHBoYSwgRnIuZGl2KG11bEgwLCBtdWxIMSkpO1xuICAgIGNoYWxsZW5nZXMucXVvdGllbnQyID0gRnIubXVsKEZyLnNxdWFyZShjaGFsbGVuZ2VzLmFscGhhKSwgRnIuZGl2KG11bEgwLCBtdWxIMikpO1xuXG4gICAgbGV0IEYyID0gRzEudGltZXNGcihwcm9vZi5wb2x5bm9taWFscy5DMSwgY2hhbGxlbmdlcy5xdW90aWVudDEpO1xuICAgIGxldCBGMyA9IEcxLnRpbWVzRnIocHJvb2YucG9seW5vbWlhbHMuQzIsIGNoYWxsZW5nZXMucXVvdGllbnQyKTtcblxuICAgIHJldHVybiBHMS5hZGQodmsuQzAsIEcxLmFkZChGMiwgRjMpKTtcbn1cblxuZnVuY3Rpb24gY29tcHV0ZUUoY3VydmUsIHByb29mLCBjaGFsbGVuZ2VzLCB2aywgcjAsIHIxLCByMikge1xuICAgIGNvbnN0IEcxID0gY3VydmUuRzE7XG4gICAgY29uc3QgRnIgPSBjdXJ2ZS5GcjtcblxuICAgIGxldCBFMiA9IEZyLm11bChyMSwgY2hhbGxlbmdlcy5xdW90aWVudDEpO1xuICAgIGxldCBFMyA9IEZyLm11bChyMiwgY2hhbGxlbmdlcy5xdW90aWVudDIpO1xuXG4gICAgcmV0dXJuIEcxLnRpbWVzRnIoRzEub25lLCBGci5hZGQocjAsIEZyLmFkZChFMiwgRTMpKSk7XG59XG5cbmZ1bmN0aW9uIGNvbXB1dGVKKGN1cnZlLCBwcm9vZiwgY2hhbGxlbmdlcykge1xuICAgIGNvbnN0IEcxID0gY3VydmUuRzE7XG5cbiAgICByZXR1cm4gRzEudGltZXNGcihwcm9vZi5wb2x5bm9taWFscy5XMSwgY2hhbGxlbmdlcy50ZW1wKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gaXNWYWxpZFBhaXJpbmcoY3VydmUsIHByb29mLCBjaGFsbGVuZ2VzLCB2aywgRiwgRSwgSikge1xuICAgIGNvbnN0IEcxID0gY3VydmUuRzE7XG5cbiAgICBsZXQgQTEgPSBHMS50aW1lc0ZyKHByb29mLnBvbHlub21pYWxzLlcyLCBjaGFsbGVuZ2VzLnkpO1xuICAgIEExID0gRzEuYWRkKEcxLnN1YihHMS5zdWIoRiwgRSksIEopLCBBMSk7XG4gICAgY29uc3QgQTIgPSBjdXJ2ZS5HMi5vbmU7XG5cbiAgICBjb25zdCBCMSA9IHByb29mLnBvbHlub21pYWxzLlcyO1xuICAgIGNvbnN0IEIyID0gdmsuWF8yO1xuXG4gICAgcmV0dXJuIGF3YWl0IGN1cnZlLnBhaXJpbmdFcShHMS5uZWcoQTEpLCBBMiwgQjEsIEIyKTtcbn1cblxuXG5leHBvcnQgZnVuY3Rpb24gY29tcHV0ZUxhZ3JhbmdlTGlTaShyb290cywgeCwgeGksIGN1cnZlKSB7XG4gICAgY29uc3QgRnIgPSBjdXJ2ZS5GcjtcbiAgICBjb25zdCBsZW4gPSByb290cy5sZW5ndGg7XG5cbiAgICBjb25zdCBudW0gPSBGci5zdWIoRnIuZXhwKHgsIGxlbiksIHhpKTtcbiAgICBjb25zdCBkZW4xID0gRnIubXVsKEZyLmUobGVuKSwgRnIuZXhwKHJvb3RzWzBdLCBsZW4gLSAyKSk7XG5cbiAgICBjb25zdCBMaSA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgY29uc3QgZGVuMiA9IHJvb3RzWygobGVuIC0gMSkgKiBpKSAlIGxlbl07XG4gICAgICAgIGNvbnN0IGRlbjMgPSBGci5zdWIoeCwgcm9vdHNbaV0pO1xuXG4gICAgICAgIExpW2ldID0gRnIuZGl2KG51bSwgRnIubXVsKEZyLm11bChkZW4xLCBkZW4yKSwgZGVuMykpO1xuICAgIH1cblxuICAgIHJldHVybiBMaTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbXB1dGVMYWdyYW5nZUxpUzIocm9vdHMsIHZhbHVlLCB4aTAsIHhpMSwgY3VydmUpIHtcbiAgICBjb25zdCBGciA9IGN1cnZlLkZyO1xuXG4gICAgY29uc3QgTGkgPSBbXTtcblxuICAgIGNvbnN0IGxlbiA9IHJvb3RzWzBdLmxlbmd0aDtcbiAgICBjb25zdCBuID0gbGVuICogcm9vdHMubGVuZ3RoO1xuXG4gICAgY29uc3QgbnVtMSA9IEZyLmV4cCh2YWx1ZSwgbik7XG4gICAgY29uc3QgbnVtMiA9IEZyLm11bChGci5hZGQoeGkwLCB4aTEpLCBGci5leHAodmFsdWUsIGxlbikpO1xuICAgIGNvbnN0IG51bTMgPSBGci5tdWwoeGkwLCB4aTEpO1xuICAgIGNvbnN0IG51bSA9IEZyLmFkZChGci5zdWIobnVtMSwgbnVtMiksIG51bTMpO1xuXG4gICAgbGV0IGRlbjEgPSBGci5tdWwoRnIubXVsKEZyLmUobGVuKSwgcm9vdHNbMF1bMF0pLCBGci5zdWIoeGkwLCB4aTEpKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGRlbjIgPSByb290c1swXVsobGVuIC0gMSkgKiBpICUgbGVuXTtcbiAgICAgICAgY29uc3QgZGVuMyA9IEZyLnN1Yih2YWx1ZSwgcm9vdHNbMF1baV0pO1xuXG4gICAgICAgIGNvbnN0IGRlbiA9IEZyLm11bChkZW4xLEZyLm11bChkZW4yLCBkZW4zKSk7XG5cbiAgICAgICAgTGlbaV0gPSBGci5kaXYobnVtLCBkZW4pO1xuICAgIH1cblxuICAgIGRlbjEgPSBGci5tdWwoRnIubXVsKEZyLmUobGVuKSwgcm9vdHNbMV1bMF0pLCBGci5zdWIoeGkxLCB4aTApKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGRlbjIgPSByb290c1sxXVsobGVuIC0gMSkgKiBpICUgbGVuXTtcbiAgICAgICAgY29uc3QgZGVuMyA9IEZyLnN1Yih2YWx1ZSwgcm9vdHNbMV1baV0pO1xuXG4gICAgICAgIGNvbnN0IGRlbiA9IEZyLm11bChkZW4xLEZyLm11bChkZW4yLCBkZW4zKSk7XG5cbiAgICAgICAgTGlbaSArIGxlbl0gPSBGci5kaXYobnVtLCBkZW4pO1xuICAgIH1cblxuICAgIHJldHVybiBMaTtcbn1cbiIsIi8qXG4gICAgQ29weXJpZ2h0IDIwMjEgMEtJTVMgYXNzb2NpYXRpb24uXG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBzbmFya0pTLlxuXG4gICAgc25hcmtKUyBpcyBhIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXRcbiAgICB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICAgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gICAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cblxuICAgIHNuYXJrSlMgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVRcbiAgICBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFlcbiAgICBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWNcbiAgICBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggc25hcmtKUy4gSWYgbm90LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiovXG5cbmltcG9ydCB7Z2V0Q3VydmVGcm9tTmFtZX0gZnJvbSBcIi4vY3VydmVzLmpzXCI7XG5pbXBvcnQge3V0aWxzfSBmcm9tIFwiZmZqYXZhc2NyaXB0XCI7XG5cbmNvbnN0IHt1bnN0cmluZ2lmeUJpZ0ludHN9ID0gdXRpbHM7XG5cbmZ1bmN0aW9uIGkyaGV4KGkpIHtcbiAgICByZXR1cm4gKFwiMFwiICsgaS50b1N0cmluZygxNikpLnNsaWNlKC0yKTtcbn1cblxuZnVuY3Rpb24gcDI1NihuKSB7XG4gICAgbGV0IG5zdHIgPSBuLnRvU3RyaW5nKDE2KTtcbiAgICB3aGlsZSAobnN0ci5sZW5ndGggPCA2NCkgbnN0ciA9IFwiMFwiICsgbnN0cjtcbiAgICBuc3RyID0gYDB4JHtuc3RyfWA7XG4gICAgcmV0dXJuIG5zdHI7XG59XG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uIGZmbG9ua0V4cG9ydENhbGxEYXRhKF9wdWIsIF9wcm9vZikge1xuICAgIGNvbnN0IHByb29mID0gdW5zdHJpbmdpZnlCaWdJbnRzKF9wcm9vZik7XG4gICAgY29uc3QgcHViID0gdW5zdHJpbmdpZnlCaWdJbnRzKF9wdWIpO1xuXG4gICAgY29uc3QgY3VydmUgPSBhd2FpdCBnZXRDdXJ2ZUZyb21OYW1lKHByb29mLmN1cnZlKTtcbiAgICBjb25zdCBHMSA9IGN1cnZlLkcxO1xuICAgIGNvbnN0IEZyID0gY3VydmUuRnI7XG5cbiAgICBsZXQgaW5wdXRzID0gXCJcIjtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHB1Yi5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoaW5wdXRzICE9PSBcIlwiKSBpbnB1dHMgPSBpbnB1dHMgKyBcIixcIjtcbiAgICAgICAgaW5wdXRzID0gaW5wdXRzICsgcDI1NihwdWJbaV0pO1xuICAgIH1cblxuICAgIHJldHVybiBgWyR7cDI1Nihwcm9vZi5wb2x5bm9taWFscy5DMVswXSl9LCAke3AyNTYocHJvb2YucG9seW5vbWlhbHMuQzFbMV0pfSxgICtcbiAgICBgJHtwMjU2KHByb29mLnBvbHlub21pYWxzLkMyWzBdKX0sJHtwMjU2KHByb29mLnBvbHlub21pYWxzLkMyWzFdKX0sYCArXG4gICAgYCR7cDI1Nihwcm9vZi5wb2x5bm9taWFscy5XMVswXSl9LCR7cDI1Nihwcm9vZi5wb2x5bm9taWFscy5XMVsxXSl9LGAgK1xuICAgIGAke3AyNTYocHJvb2YucG9seW5vbWlhbHMuVzJbMF0pfSwke3AyNTYocHJvb2YucG9seW5vbWlhbHMuVzJbMV0pfSxgICtcbiAgICBgJHtwMjU2KHByb29mLmV2YWx1YXRpb25zLnFsKX0sJHtwMjU2KHByb29mLmV2YWx1YXRpb25zLnFyKX0sJHtwMjU2KHByb29mLmV2YWx1YXRpb25zLnFtKX0sYCArXG4gICAgYCR7cDI1Nihwcm9vZi5ldmFsdWF0aW9ucy5xbyl9LCR7cDI1Nihwcm9vZi5ldmFsdWF0aW9ucy5xYyl9LCR7cDI1Nihwcm9vZi5ldmFsdWF0aW9ucy5zMSl9LGAgK1xuICAgIGAke3AyNTYocHJvb2YuZXZhbHVhdGlvbnMuczIpfSwke3AyNTYocHJvb2YuZXZhbHVhdGlvbnMuczMpfSwke3AyNTYocHJvb2YuZXZhbHVhdGlvbnMuYSl9LGAgK1xuICAgIGAke3AyNTYocHJvb2YuZXZhbHVhdGlvbnMuYil9LCR7cDI1Nihwcm9vZi5ldmFsdWF0aW9ucy5jKX0sJHtwMjU2KHByb29mLmV2YWx1YXRpb25zLnopfSxgICtcbiAgICBgJHtwMjU2KHByb29mLmV2YWx1YXRpb25zLnp3KX0sJHtwMjU2KHByb29mLmV2YWx1YXRpb25zLnQxdyl9LCR7cDI1Nihwcm9vZi5ldmFsdWF0aW9ucy50MncpfSxgICtcbiAgICBgJHtwMjU2KHByb29mLmV2YWx1YXRpb25zLmludil9XSxgICtcbiAgICBgWyR7aW5wdXRzfV1gO1xufVxuIiwiLypcbiAgICBDb3B5cmlnaHQgMjAyMiBpZGVuMyBhc3NvY2lhdGlvbi5cblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHNuYXJranMuXG5cbiAgICBzbmFya2pzIGlzIGEgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4gICAgbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZVxuICAgIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKVxuICAgIGFueSBsYXRlciB2ZXJzaW9uLlxuXG4gICAgc25hcmtqcyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICAgIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICAgIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvclxuICAgIG1vcmUgZGV0YWlscy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFsb25nIHdpdGhcbiAgICBzbmFya2pzLiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuKi9cblxuZXhwb3J0IHsgZGVmYXVsdCBhcyBzZXR1cCB9IGZyb20gXCIuL2ZmbG9ua19zZXR1cC5qc1wiO1xuZXhwb3J0IHsgZGVmYXVsdCBhcyBwcm92ZSB9IGZyb20gXCIuL2ZmbG9ua19wcm92ZS5qc1wiO1xuZXhwb3J0IHsgZGVmYXVsdCBhcyBmdWxsUHJvdmUgfSBmcm9tIFwiLi9mZmxvbmtfZnVsbF9wcm92ZS5qc1wiO1xuZXhwb3J0IHsgZGVmYXVsdCBhcyB2ZXJpZnkgfSBmcm9tIFwiLi9mZmxvbmtfdmVyaWZ5LmpzXCI7XG5leHBvcnQgeyBkZWZhdWx0IGFzIGV4cG9ydFNvbGlkaXR5VmVyaWZpZXIgfSBmcm9tIFwiLi9mZmxvbmtfZXhwb3J0X3NvbGlkaXR5X3ZlcmlmaWVyLmpzXCI7XG5leHBvcnQgeyBkZWZhdWx0IGFzIGV4cG9ydFNvbGlkaXR5Q2FsbERhdGEgfSBmcm9tIFwiLi9mZmxvbmtfZXhwb3J0X2NhbGxkYXRhLmpzXCI7XG4iXSwibmFtZXMiOlsiYWRkIiwiZ2V0UmFuZG9tQnl0ZXMiLCJzdHJpbmdpZnlCaWdJbnRzIiwidW5zdHJpbmdpZnlCaWdJbnRzIiwibG9nMiIsIlBBR0VfU0laRSIsImJsczEyMzgxciIsImJuMTI4ciIsImdldEN1cnZlRnJvbVIiLCJ1MzIiLCJvcGVuIiwiRmFzdEZpbGUiLCJjcmVhdGVOZXciLCJNZW1GaWxlIiwicmVhZEV4aXN0aW5nIiwidG1wQnVmZjMyIiwidG1wQnVmZjMydiIsInRtcEJ1ZmY2NCIsInRtcEJ1ZmY2NHYiLCJCaWdNZW1GaWxlIiwiT19UUlVOQyIsIk9fQ1JFQVQiLCJPX1JEV1IiLCJPX1JET05MWSIsImNvbnN0YW50cyIsIkRFRkFVTFRfQ0FDSEVfU0laRSIsIkRFRkFVTFRfUEFHRV9TSVpFIiwiY3JlYXRlT3ZlcnJpZGUiLCJtZW1GaWxlLmNyZWF0ZU5ldyIsImJpZ01lbUZpbGUuY3JlYXRlTmV3IiwibWVtRmlsZS5yZWFkRXhpc3RpbmciLCJiaWdNZW1GaWxlLnJlYWRFeGlzdGluZyIsInJlYWRCaW5GaWxlIiwiZmFzdEZpbGUucmVhZEV4aXN0aW5nIiwiZmFzdEZpbGUuY3JlYXRlT3ZlcnJpZGUiLCJzdGFydFJlYWRVbmlxdWVTZWN0aW9uIiwiZW5kUmVhZFNlY3Rpb24iLCJyZWFkQmlnSW50IiwicmVhZFNlY3Rpb24iLCJidWlsZEJuMTI4IiwiYnVpbGRCbHMxMjM4MSIsInU2NCIsInNhbWVSYXRpbyIsImJpbkZpbGVVdGlscy5zdGFydFdyaXRlU2VjdGlvbiIsImJpbkZpbGVVdGlscy5lbmRXcml0ZVNlY3Rpb24iLCJnZXRDdXJ2ZSIsImJpbkZpbGVVdGlscy53cml0ZUJpZ0ludCIsInJlYWRIZWFkZXIiLCJiaW5GaWxlVXRpbHMuc3RhcnRSZWFkVW5pcXVlU2VjdGlvbiIsImJpbkZpbGVVdGlscy5lbmRSZWFkU2VjdGlvbiIsImJpbkZpbGVVdGlscy5yZWFkQmlnSW50IiwiYmluRmlsZVV0aWxzLnJlYWRCaW5GaWxlIiwiRjFGaWVsZCIsInJlYWRDb250cmlidXRpb24iLCJ3cml0ZUNvbnRyaWJ1dGlvbiIsInV0aWxzIiwid3Ruc1V0aWxzLnJlYWRIZWFkZXIiLCJ6a2V5VXRpbHMucmVhZEhlYWRlciIsImJpbkZpbGVVdGlscy5yZWFkU2VjdGlvbiIsIldpdG5lc3NDYWxjdWxhdG9yQnVpbGRlciIsImJpbkZpbGVVdGlscy5jcmVhdGVCaW5GaWxlIiwid3Ruc1V0aWxzLndyaXRlQmluIiwid3Ruc19jYWxjdWxhdGUiLCJncm90aDE2X3Byb3ZlIiwiY3VydmVzLmdldEN1cnZlRnJvbU5hbWUiLCJwdWJsaWNJbnB1dHNBcmVWYWxpZCIsImlzV2VsbENvbnN0cnVjdGVkIiwiY2hlY2tWYWx1ZUJlbG9uZ1RvRmllbGQiLCJwMjU2IiwibWlzYy5mcm9tUGFydGlhbEhhc2giLCJtaXNjLnJuZ0Zyb21CZWFjb25QYXJhbXMiLCJrZXlQYWlyLmNyZWF0ZVBUYXVLZXkiLCJwdGF1VXRpbHMud3JpdGVQVGF1SGVhZGVyIiwicHRhdVV0aWxzLmNhbGN1bGF0ZUZpcnN0Q2hhbGxlbmdlSGFzaCIsIm1pc2MuZm9ybWF0SGFzaCIsInV0aWxzLnJlYWRQVGF1SGVhZGVyIiwidXRpbHMucmVhZENvbnRyaWJ1dGlvbnMiLCJ1dGlscy5jYWxjdWxhdGVGaXJzdENoYWxsZW5nZUhhc2giLCJtaXNjLmhhc2hJc0VxdWFsIiwidXRpbHMud3JpdGVQVGF1SGVhZGVyIiwibWlzYy50b1BhcnRpYWxIYXNoIiwidXRpbHMuZnJvbVB0YXVQdWJLZXlScHIiLCJ1dGlscy53cml0ZUNvbnRyaWJ1dGlvbnMiLCJtaXNjLnNhbWVSYXRpbyIsInV0aWxzLmtleUZyb21CZWFjb24iLCJrZXlQYWlyLmdldEcyc3AiLCJ1dGlscy50b1B0YXVQdWJLZXlScHIiLCJtaXNjLmJ5dGVBcnJheTJoZXgiLCJtaXNjLmdldFJhbmRvbUJ5dGVzIiwibWlzYy5yZWFkVUludDMyQkUiLCJtaXNjLmdldFJhbmRvbVJuZyIsImJlYWNvbiIsIm1pc2MuaGV4MkJ5dGVBcnJheSIsImJpbkZpbGVVdGlscy5jb3B5U2VjdGlvbiIsIlNVQkFSUkFZX1NJWkUiLCJCaWdBcnJheUhhbmRsZXIiLCJfQmlnQXJyYXkiLCJCaWdBcnJheSIsImxvYWRTeW1zIiwid3Ruc1V0aWxzLndyaXRlIiwiY3VydmVzLmdldEN1cnZlRnJvbVIiLCJ6a2V5VXRpbHMucmVhZE1QQ1BhcmFtcyIsInprZXlVdGlscy53cml0ZUhlYWRlciIsInprZXlVdGlscy53cml0ZU1QQ1BhcmFtcyIsIm1pc2MuY2xvbmVIYXNoZXIiLCJiaW5GaWxlVXRpbHMuc2VjdGlvbklzRXF1YWwiLCJ1dGlscy5oYXNoUHViS2V5IiwidXRpbHMuaGFzaEcxIiwiZXhwb3J0VmVyaWZpY2F0aW9uS2V5IiwiZmZsb25rRXhwb3J0U29saWRpdHlWZXJpZmllckNtZCIsInBsb25rX3Byb3ZlIiwiZnJvbU9iamVjdFZrIiwiZXZhbHVhdGlvbnNBcmVWYWxpZCIsImNhbGN1bGF0ZVBJIiwiaXNWYWxpZFBhaXJpbmciLCJjaGVja0V2YWx1YXRpb25Jc1ZhbGlkIl0sIm1hcHBpbmdzIjoiOzs7SUFBQTtJQUNBLE1BQU0s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LENBQUM7SUFDdEUsSUFBSSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDNUMsSUFBSSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzNGLElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM1QyxJQUFJLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQzNGLENBQUM7QUFDRDtJQUNBO0lBQ0EsU0FBUyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFO0lBQ2pDLElBQUksTUFBTSxDQUFDLEdBQUcsU0FBUyxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDekMsSUFBSSxNQUFNLENBQUMsR0FBRyxJQUFJLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxVQUFVLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ2pFLElBQUksTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzVDLElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ25ILElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDMUMsQ0FBQztBQUNEO0lBQ0E7SUFDQSxTQUFTLFNBQVMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRTtJQUNoQyxJQUFJLEVBQUUsR0FBRyxFQUFFLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUMvQixJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2YsSUFBSSxNQUFNLENBQUMsR0FBRyxJQUFJLFdBQVcsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxVQUFVLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN0RSxJQUFJLE1BQU0sQ0FBQyxHQUFHLElBQUksS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM5QixJQUFJLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztJQUM3RSxJQUFJLE9BQU8sVUFBVSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDdEMsQ0FBQztBQUNEO0lBQ0E7SUFDQSxTQUFTLFNBQVMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRTtJQUNoQyxJQUFJLEVBQUUsR0FBRyxFQUFFLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUMvQixJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2YsSUFBSSxNQUFNLENBQUMsR0FBRyxJQUFJLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxVQUFVLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ2pFLElBQUksTUFBTSxDQUFDLEdBQUcsSUFBSSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzlCLElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDL0IsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3JFLEtBQUs7SUFDTCxJQUFJLE9BQU8sVUFBVSxDQUFDLENBQUMsQ0FBQyxJ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R0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDdEMsUUFBUSxFQUFFLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDakQsS0FBSztBQUNMO0lBQ0EsSUFBSSxDQUFDLENBQUMsVUFBVSxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUMzQztJQUNBLElBQUksQ0FBQyxDQUFDLElBQUksR0FBRyxTQUFTLENBQUMsRUFBRTtJQUN6QixRQUFRLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQztJQUNyQixRQUFRLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDdkMsUUFBUSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDdkMsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQ3JFLFFBQVEsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsT0FBTyxJQUFJLENBQUM7QUFDNUM7SUFDQSxRQUFRLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUM7SUFDekIsUUFBUSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMs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QUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUMvQyxTQUFTLE1BQU07SUFDZixZQUFZLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM1RCxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUM3QixTQUFTO0lBQ1QsUUFBUSxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMvQyxLQUFLLENBQUM7SUFDTixDQUFDO0FBQ0Q7QUFDQTtJQUNBLFNBQVMsWUFBWSxDQUFDLENBQUMsRUFBRTtJQUN6QixJQUFJLENBQUMsQ0FBQyxJQUFJLEdBQUcsV0FBVztJQUN4QixRQUFRLE1BQU0sSUFBSSxLQUFLLENBQUMsNEJBQTRCLENBQUMsQ0FBQztJQUN0RCxLQUFLLENBQUM7SUFDTixDQUFDO0FBQ0Q7SUFDQSxTQUFTLFlBQVksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFO0FBQ3RDO0lBQ0EsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNsQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2xDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDNUQ7SUFDQSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2xDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDbEMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUMzRDtJQUNBLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDbEMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNsQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ3pEO0lBQ0EsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNsQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2xDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDekQsQ0FBQztBQUNEO0lBQ0EsU0FBUyxXQUFXLENBQUMsRUFBRSxFQUFFO0lBQ3pCLElBQUksWUFBWSxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNqQyxJQUFJLFlBQVksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDakMsSUFBSSxZQUFZLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2pDLElBQUksWUFBWSxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUNqQztJQUNBLElBQUksWUFBWSxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNqQyxJQUFJLFlBQVksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDakMsSUFBSSxZQUFZLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2pDLElBQUksWUFBWSxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNqQyxDQUFDO0FBQ0Q7SUFDQSxNQUFNLE1BQU0sQ0FBQztBQUNiO0lBQ0EsSUFBSSxXQUFXLENBQUMsSUFBSSxFQUFFO0lBQ3RCLFFBQVEsSUFBSSxHQUFHLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN6QyxRQUFRLElBQUksQ0FBQyxLQUFLLEdBQUc7SUFDckIsWUFBWSxVQUFVO0lBQ3RCLFlBQVksVUFBVTtJQUN0QixZQUFZLFVBQVU7SUFDdEIsWUFBWSxVQUFVO0lBQ3RCLFlBQVksSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNuQixZQUFZLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDbkIsWUFBWSxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ25CLFlBQVksSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNuQixZQUFZLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDbkIsWUFBWSxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ25CLFlBQVksSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNuQixZQUFZLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDbkIsWUFBWSxDQUFDO0lBQ2IsWUFBWSxDQUFDO0lBQ2IsWUFBWSxDQUFDO0lBQ2IsWUFBWSxDQUFDO0lBQ2IsU0FBUyxDQUFDO0lBQ1YsUUFBUSxJQUFJLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQztJQUN0QixRQUFRLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbEMsS0FBSztBQUNMO0lBQ0EsSUFBSSxPQUFPLEdBQUc7SUFDZCxRQUFRLElBQUksSUFBSSxDQUFDLEdBQUcsSUFBSSxFQUFFLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQzFDLFFBQVEsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO0lBQ3JDLEtBQUs7QUFDTDtJQUNBLElBQUksT0FBTyxHQUFHO0lBQ2QsUUFBUSxPQUFPQSxLQUFHLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsRUFBRSxXQUFXLENBQUMsRUFBRSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUNyRSxLQUFLO0FBQ0w7SUFDQSxJQUFJLFFBQVEsR0FBRztJQUNmLFFBQVEsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3pDLEtBQUs7QUFDTDtJQUNBLElBQUksTUFBTSxHQUFHO0lBQ2I7SUFDQSxRQUFRLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQzlEO0lBQ0E7SUFDQSxRQUFRLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUN4RDtJQUNBO0lBQ0EsUUFBUSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ3JGO0lBQ0EsUUFBUSxJQUFJLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQztBQUNyQjtJQUNBLFFBQVEsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNw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LENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDMUMsUUFBUSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzdCLFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQztJQUM1QixRQUFRLElBQUksQ0FBQyxDQUFDLE1BQU0sSUFBSSxDQUFDLEVBQUU7SUFDM0IsWUFBWSxNQUFNLElBQUksS0FBSyxDQUFDLDRCQUE0QixDQUFDLENBQUM7SUFDMUQsU0FBUztJQUNULFFBQVEsTUFBTSxHQUFHLElBQUksS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNoRCxRQUFRLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDdEUsUUFBUSxNQUFNLElBQUksR0FBRyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNsQyxRQUFRLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDaEMsWUFBWSxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQzFELFNBQVM7QUFDVDtJQUNBLFFBQVEsT0FBTyxJQUFJLENBQUM7SUFDcEIsS0FBSztBQUNMO0FBQ0E7SUFDQSxDQUFDO0FBQ0Q7SUFDQSxTQUFTLE1BQU0sRUFBRSxDQUFDO0lBQ2xCO0lBQ0EsSUFBSSxRQUFRLEVBQUUsRUFBRSxDQUFDLEdBQUcsVUFBVSxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksVUFBVSxFQUFFLEVBQUUsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDLEdBQUcsVUFBVSxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksVUFBVSxFQUFFLENBQUMsS0FBSyxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsR0FBRyxVQUFVLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxVQUFVLEVBQUUsQ0FBQyxLQUFLLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxHQUFHLFVBQVUsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLFVBQVUsRUFBRSxDQUFDLEtBQUssQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLEdBQUcsVUFBVSxPQUFPLENBQUMsRUFBRSxHQUFHO0lBQzVSLENBQUM7QUFDRDtBQUNBO0lBQ0EsU0FBUyxLQUFLLENBQUMsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtBQUM3QztJQUNBLElBQUksTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQztJQUN4QixJQUFJLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRTtJQUNkLFFBQVEsT0FBTyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO0lBQ2hDLEtBQUssTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUU7SUFDckIsUUFBUSxPQUFPO0lBQ2YsWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsQ0FBQztJQUN2RCxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN6RCxLQUFLO0FBQ0w7SUFDQSxJQUFJLE1BQU0sS0FBSyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDekIsSUFBSSxNQUFNLEVBQUUsR0FBRyxLQUFLLENBQUMsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdkQsSUFBSSxNQUFNLEVBQUUsR0FBRyxLQUFLLENBQUMsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQzVEO0lBQ0EsSUFBSSxNQUFNLEdBQUcsR0FBRyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUM3QjtJQUNBLElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUNoQyxRQUFRLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdkUsUUFBUSxHQUFHLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM3RSxLQUFLO0FBQ0w7SUFDQSxJQUFJLE9BQU8sR0FBRyxDQUFDO0lBQ2YsQ0FBQztBQUNEO0lBQ0E7QUFDQTtJQUNBLE1BQU0sT0FBTyxDQUFDO0lBQ2QsSUFBSSxXQUFXLENBQUMsQ0FBQyxFQUFFO0lBQ25CLFFBQVEsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7SUFDdkIsUUFBUSxJQUFJLENBQUMsR0FBRyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM3QixRQUFRLElBQUksQ0FBQyxJQUFJLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzlCLFFBQVEsSUFBSSxDQUFDLENBQUMsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDM0IsUUFBUSxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNuQixRQUFRLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDO0lBQ3RDLFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDN0IsUUFBUSxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQztJQUN2QyxRQUFRLElBQUksQ0FBQyxTQUFTLEdBQUcsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM3QyxRQUFRLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQztBQUNwRTtJQUNBLFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzNELFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUM5QixRQUFRLElBQUksQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDN0IsUUFBUSxJQUFJLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENB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QUksQ0FBQyxFQUFFLEVBQUUsRUFBRTtJQUMxQixZQUFZLEdBQUcsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2pDLFNBQVM7SUFDVCxRQUFRLElBQUksR0FBRyxHQUFHLENBQUMsRUFBRTtJQUNyQixZQUFZLElBQUksSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDO0lBQzVCLFlBQVksSUFBSSxJQUFJLElBQUksSUFBSSxDQUFDLENBQUMsRUFBRSxJQUFJLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDckQsWUFBWSxPQUFPLElBQUksQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDO0lBQ2pDLFNBQVMsTUFBTTtJQUNmLFlBQVksT0FBTyxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQztJQUNyRCxTQUFTO0FBQ1Q7SUFDQSxLQUFLO0FBQ0w7SUFDQSxJQUFJLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFO0lBQ2QsUUFBUSxNQUFNLEdBQUcsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzFCLFFBQVEsT0FBTyxHQUFHLElBQUksSUFBSSxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUM7SUFDaEQsS0FBSztBQUNMO0lBQ0EsSUFBSSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRTtJQUNkLFFBQVEsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDM0MsS0FBSztBQUNMO0lBQ0EsSUFBSSxHQUFHLENBQUMsQ0FBQyxFQUFFO0lBQ1gsUUFBUSxPQUFPLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDaEMsS0FBSztBQUNMO0lBQ0EsSUFBSSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRTtJQUNkLFFBQVEsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUM1QixLQUFLO0FBQ0w7SUFDQSxJQUFJLFNBQVMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFO0lBQ3ZCLFFBQVEsT0FBTyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDM0MsS0FBSztBQUNMO0lBQ0EsSUFBSSxNQUFNLENBQUMsQ0FBQyxFQUFFO0lBQ2QsUUFBUSxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQzlCLEtBQUs7QUFDTDtJQUNBLElBQUksRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUU7SUFDYixRQUFRLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNwQixLQUFLO0FBQ0w7SUFDQSxJQUFJLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFO0lBQ2QsUUFBUSxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDcEIsS0FBSztBQUNMO0lBQ0EsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRTtJQUNiLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDcEQsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNwRCxRQUFRLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQztJQUN2QixLQUFLO0FBQ0w7SUFDQSxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFO0lBQ2IsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENB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RyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN6RCxRQUFRLEtBQUssR0FBRyxJQUFJLElBQUksQ0FBQyxHQUFHLEdBQUcsT0FBTyxJQUFJLENBQUM7QUFDM0M7SUFDQSxRQUFRLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDdkIsUUFBUSxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO0lBQzlCLFFBQVEsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BDLFFBQVEsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7QUFDckU7SUFDQSxRQUFRLFFBQVEsQ0FBQyxJQUFJLElBQUksQ0FBQyxHQUFHLEdBQUc7SUFDaEMsWUFBWSxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BDLFlBQVksSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3RCLFlBQVksT0FBTyxFQUFFLElBQUksSUFBSSxDQUFDLEdBQUcsR0FBRztJQUNwQyxnQkFBZ0IsQ0FBQyxFQUFFLENBQUM7SUFDcEIsZ0JBQWdCLEVBQUUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3JDLGFBQWE7QUFDYjtJQUNBO0lBQ0EsWUFBWSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdEIsWUFBWSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxH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QUFDLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDdkQ7SUFDQSxRQUFRLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDekMsUUFBUSxJQUFJLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDaEQ7SUFDQSxRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDcEMsUUFBUSxJQUFJLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3BDO0lBQ0EsUUFBUSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxFQUFFLEVBQUU7SUFDbEMsWUFBWSxNQUFNLElBQUksS0FBSyxDQUFDLDRCQUE0QixDQUFDLENBQUM7SUFDMUQsU0FBUztBQUNUO0lBQ0EsUUFBUSxJQUFJLENBQUMsSUFBSSxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQzVDLFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDO0lBQzVCLFFBQVEsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM5QyxRQUFRLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUU7SUFDekMsWUFBWSxJQUFJLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFD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RSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbkQsS0FBSztBQUNMO0lBQ0EsSUFBSSxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUU7SUFDMUIsUUFBUSxJQUFJLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3RDLFFBQVEsSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN0QyxRQUFRLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3RGLEtBQUs7QUFDTDtJQUNBLElBQUksR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUU7SUFDbkIsUUFBUSxJQUFJLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3RDLFFBQVEsSUFBSSxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDN0UsUUFBUSxPQUFPLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ25ELEtBQUs7QUFDTDtJQUNBLElBQUksT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUU7SUFDdkIsUUFBUSxJQUFJLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3RDLFFBQVEsT0FBTyxDQUFDLENB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R0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckMsUUFBUSxJQUFJLENBQUMsSUFBSSxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNyQyxRQUFRLElBQUksQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3JDLFFBQVEsSUFBSSxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDOUQsUUFBUSxJQUFJLENBQUMsSUFBSSxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbkQsUUFBUSxJQUFJLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM3RCxRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUNsRDtJQUNBLFFBQVEsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN6QyxRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNoRDtJQUNBLEtBQUs7QUFDTDtJQUNBLElBQUksR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFO0lBQ3RCLFFBQVEsSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN0QyxRQUFRLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEMsUUFBUSxJQUFJLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3hGLFFBQVEsT0FBTyxJQUFJLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNuRCxLQUFLO0FBQ0w7SUFDQSxJQUFJLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRTtJQUMxQixRQUFRLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEMsUUFBUSxJQUFJLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3RDLFFBQVEsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdEYsS0FBSztBQUNMO0lBQ0EsSUFBSSxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRTtJQUNuQixRQUFRLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEMsUUFBUSxJQUFJLENBQUMsRUFBRSxDQUFDLFFBQVEs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SUFBSSxFQUFFLENBQUMsWUFBWSxVQUFVLENBQUMsRUFBRTtJQUN4QyxZQUFZLENBQUMsR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDL0IsU0FBUztJQUNULFFBQVEsSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN0QyxRQUFRLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEMsUUFBUSxJQUFJLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdEcsUUFBUSxPQUFPLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ25ELEtBQUs7QUFDTDtJQUNBLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUU7SUFDWixRQUFRLElBQUksQ0FBQyxZQUFZLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUM5QyxRQUFRLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDLEVBQUU7SUFDbkQsWUFBWSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDekMsWUFBWSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxD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QyxDQUFDO0lBQzlCLFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDaEMsUUFBUSxJQUFJLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztBQUNoQztJQUNBLFFBQVEsSUFBSSxDQUFDLElBQUksR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckMsUUFBUSxJQUFJLENBQUMsSUFBSSxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNyQyxRQUFRLElBQUksQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3JDLFFBQVEsSUFBSSxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDOUQsUUFBUSxJQUFJLENBQUMsSUFBSSxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbkQsUUFBUSxJQUFJLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM3RCxRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUNsRDtJQUNBLFFBQVEsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN6QyxRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNoRDtJQUNBLEtBQUs7QUFDTDtJQUNBLElBQUksR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFO0lBQ3RCLFFBQVEsSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN0QyxRQUFRLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEMsUUFBUSxJQUFJLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3hGLFFBQVEsT0FBTyxJQUFJLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNuRCxLQUFLO0FBQ0w7SUFDQSxJQUFJLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRTtJQUMxQixRQUFRLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEMsUUFBUSxJQUFJLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3RDLFFBQVEsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdEYsS0FBSztBQUNMO0lBQ0EsSUFBSSxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRTtJQUNuQixRQUFRLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEMsUUFBUSxJQUFJLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM3RSxRQUFRLE9BQU8sSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbkQsS0FBSztBQUNMO0lBQ0EsSUFBSSxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRTtJQUN2QixRQUFRLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEMsUUFBUSxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN0RixLQUFLO0FBQ0w7QUFDQTtJQUNBLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7SUFDWixRQUFRLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3pDLEtBQUs7QUFDTDtJQUNBLElBQUksTUFBTSxDQUFDLENBQUMsRUFBRTtJQUNkLFFBQVEsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMxQyxLQUFLO0FBQ0w7SUFDQSxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO0lBQ2IsUUFBUSxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN0QyxLQUFLO0FBQ0w7SUFDQSxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO0lBQ2IsUUFBUSxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN0QyxLQUFLO0FBQ0w7SUFDQSxJQUFJLEdBQUcsQ0FBQyxDQUFDLEVBQUU7SUFDWCxRQUFRLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbkMsS0FBSztBQUNMO0lBQ0EsSUFBSSxHQUFHLENBQUMsQ0FBQyxFQUFFO0lBQ1gsUUFBUSxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3ZDLEtBQUs7QUFDTDtJQUNBLElBQUksVUFBVSxDQUFDLENBQUMsRUFBRTtJQUNsQixRQUFRLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDOUMsS0FBSztBQUNMO0lBQ0EsSUFBSSxZQUFZLENBQUMsQ0FBQyxFQUFFO0lBQ3BCLFFBQVEsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLGVBQWUsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM1QyxLQUFLO0FBQ0w7SUFDQSxJQUFJLGNBQWMsQ0FBQyxDQUFDLEVBQUU7SUFDdEIsUUFBUSxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDOUMsS0FBSztBQUNMO0lBQ0EsSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtJQUNiLFFBQVEsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEMsS0FBSztBQUNMO0lBQ0EsSUFBSSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRTtJQUNkLFFBQVEsSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN0QyxRQUFRLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEMsUUFBUSxJQUFJLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxVQUFVLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNqRixRQUFRLElBQUksQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDeEYsUUFBUSxPQUFPLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ25ELEtBQUs7QUFDTDtJQUNBLElBQUksTUFBTSxDQUFDLENBQUMsRUFBRTtJQUNkLFFBQVEsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN0QyxLQUFLO0FBQ0w7SUFDQSxJQUFJLFFBQVEsQ0FBQyxDQUFDLEVBQUU7SUFDaEIsUUFBUSxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzVDLEtBQUs7QUFDTDtJQUNBLElBQUksSUFBSSxDQUFDLENBQUMsRUFBRTtJQUNaLFFBQVEsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNwQyxL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Q0FBQztJQUM1QyxLQUFLO0FBQ0w7SUFDQSxJQUFJLFFBQVEsQ0FBQyxDQUFDLEVBQUU7SUFDaEIsUUFBUSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDMUQsUUFBUSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDcEUsUUFBUSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3RFLFFBQVEsT0FBTyxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDNUIsS0FBSztBQUNMO0lBQ0EsSUFBSSxVQUFVLENBQUMsQ0FBQyxFQUFFO0lBQ2xCLFFBQVEsTUFBTSxJQUFJLEdBQUcsSUFBSSxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDakQsUUFBUSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzQyxRQUFRLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzNDLFFBQVEsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDM0MsUUFBUSxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3JCLFFBQVEsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNoQyxRQUFRLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xDLFFBQVEsT0FBTyxJQUFJLENBQUM7SUFDcEIsS0FBSztBQUNMO0lBQ0EsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFO0lBQ1YsUUFBUSxPQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDckMsS0FBSztBQUNMO0lBQ0EsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFO0lBQ1YsUUFBUSxPQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDL0MsS0FBSztBQUNMO0lBQ0EsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFO0lBQ1YsUUFBUSxPQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDcEMsS0FBSztBQUNMO0lBQ0EsQ0FBQztBQUNEO0lBQ0EsTUFBTSxTQUFTLENBQUM7QUFDaEI7SUFDQSxJQUFJLFdBQVcsQ0FBQyxFQUFFLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLFFBQVEsRUFBRTtJQUNwRCxRQUFRLElBQUksQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDO0lBQ3JCLFFBQVEsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7SUFDN0IsUUFBUSxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNuQjtJQUNBLFFBQVEsSUFBSSxDQUFDLElBQUksR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckMsUUFBUSxJQUFJLENBQUMsSUFBSSxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNyQyxRQUFRLElBQUksQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3JDLFFBQVEsSUFBSSxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDOUQsUUFBUSxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2RCxRQUFRLElBQUksQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsYUFBYSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3BFLFFBQVEsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDN0QsUUFBUSxJQUFJLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2pELFFBQVEsSUFBSSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFD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LENBQUM7SUFDbEMsWUFBWSxJQUFJLEdBQUcsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7SUFDdkMsU0FBUztBQUNUO0lBQ0EsUUFBUSxNQUFNLFVBQVUsR0FBRyxFQUFFLENBQUM7SUFDOUIsUUFBUSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxFQUFFO0FBQ25DO0lBQ0EsWUFBWSxNQUFNLElBQUksR0FBRyxFQUFFLENBQUM7QUFDNUI7SUFDQSxZQUFZLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMvRCxZQUFZLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDL0QsWUFBWSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztBQUNuRTtJQUNBLFlBQVksTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNsRSxZQUFZLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDL0QsWUFBWSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztBQUNuRTtJQUNBLFlBQVksSUFB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U0FBUyxDQUFDLG9CQUFvQixFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hGLFlBQVksTUFBTSxDQUFDLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEdBQUcsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0FBQ3REO0lBQ0EsWUFBWSxNQUFNLFVBQVUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzlELFlBQVksTUFBTSxJQUFJLEdBQUcsRUFBRSxDQUFDO0FBQzVCO0lBQ0EsWUFBWSxNQUFNLEVBQUUsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3JELFlBQVksTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztBQUNyRDtJQUNBLFlBQVksSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDM0QsWUFBWSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3RELFlBQVksSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDM0QsWUFBWSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFF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QUFFO0lBQzVDLFlBQVksWUFBWSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDOUMsWUFBWSxZQUFZLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM5QyxZQUFZLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDO0lBQ3ZDLFNBQVM7QUFDVDtJQUNBLFFBQVEsT0FBTyxDQUFDLFlBQVksRUFBRSxZQUFZLENBQUMsQ0FBQztJQUM1QyxLQUFLO0FBQ0w7QUFDQTtJQUNBLElBQUksQ0FBQyxDQUFDLEdBQUcsR0FBRyxlQUFlLElBQUksRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUU7SUFDckUsUUFBUSxPQUFPLE1BQU0sSUFBSSxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDM0UsS0FBSyxDQUFDO0FBQ047SUFDQSxJQUFJLENBQUMsQ0FBQyxJQUFJLEdBQUcsZUFBZSxJQUFJLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFO0lBQ3RFLFFBQVEsT0FBTyxNQUFNLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQzFFLEtBQUssQ0FBQztBQUNOO0lBQ0EsSUFBSSxDQUFDLENBQUMsbUJBQW1CLEdBQUcsZ0JBQWdCLElBQUksRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUU7SUFDdEYsUUFBUSxNQUFNLEdBQUcsTUFBTSxJQUFJLFFBQVEsQ0FBQztJQUNwQyxRQUFRLE9BQU8sR0FBRyxPQUFPLElBQUksUUFBUSxD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RUFBRSxDQUFDLEVBQUUsRUFBRTtJQUN0QyxZQUFZLE1BQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQztBQUM1QjtJQUNBLFlBQVksTUFBTSxVQUFVLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUM7SUFDNUUsWUFBWSxNQUFNLEVBQUUsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLGNBQWMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsY0FBYyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZGLFlBQVksTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxjQUFjLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLGNBQWMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUN2RixZQUFZLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDM0QsWUFBWSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLFVBQVUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzNELFlBQVksSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQztJQUNuRSxZQUFZLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDNUQsWUFBWSxJQUFJLENBQUMsSUFBSSxD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LEtBQUssQ0FBQztJQUNOLENBQUM7QUFDRDtJQUNBLGVBQWUsV0FBVyxDQUFDLE1BQU0sRUFBRTtBQUNuQztJQUNBLElBQUksTUFBTSxFQUFFLEdBQUcsTUFBTSxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztBQUMxRTtBQUNBO0lBQ0EsSUFBSSxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUM7QUFDckI7SUFDQSxJQUFJLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFDMUMsSUFBSSxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBQzFDLElBQUksS0FBSyxDQUFDLElBQUksR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDO0lBQzdCLElBQUksS0FBSyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUM7SUFDbEIsSUFBSSxLQUFLLENBQUMsUUFBUSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDO0lBQzFDLElBQUksS0FBSyxDQUFDLFFBQVEsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQztJQUMxQyxJQUFJLEtBQUssQ0FBQyxFQUFFLEdBQUcsSUFBSSxVQUFVLENBQUMsRUFBRSxFQUFFLEtBQUssRUFBRSxNQUFNLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMvRCxJQUFJLEtBQUssQ0FBQyxFQUFFLEdBQUcsSUFBSSxVQUFVLENBQUMsRUFBRSxFQUFFLEtBQUssRUFBRSxNQUFNLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMvRCxJQUFJLEtBQUssQ0FBQyxFQUFFLEdBQUcsSUFBSSxVQUFVLENBQUMsRUFBRSxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbkQsSUFBSSxLQUFLLENBQUMsRUFBRSxHQUFHLElBQUksU0FBUyxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsS0FBSyxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDM0csSUFBSSxLQUFLLENBQUMsRUFBRSxHQUFHLElBQUksU0FBUyxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsS0FBSyxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDM0csSUFBSSxLQUFLLENBQUMsRUFBRSxHQUFHLElBQUksVUFBVSxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ25ELElBQUksS0FBSyxDQUFDLEdBQUcsR0FBRyxJQUFJLFVBQVUsQ0FBQyxFQUFFLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUNwRDtJQUNBLElBQUksS0FBSyxDQUFDLEVBQUUsR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDO0FBQ3pCO0lBQ0EsSUFBSSxrQkFBa0IsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDcEMsSUFBSSxrQkFBa0IsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDcEMsSUFBSSxrQkFBa0IsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFDcEM7SUFDQSxJQUFJLGVBQWUsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDakMsSUFBSSxlQUFlLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO0FBQ2pDO0lBQ0EsSUFBSSxVQUFVLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQzVCLElBQUksVUFB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Q0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDcEQsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUMvQixRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQy9CLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDL0IsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUMvQixRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ2hDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDaEMsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNoQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ2hDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDaEMsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNoQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQ2hDO0lBQ0EsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsY0FBYyxFQUFFLENBQUM7QUFDckM7SUFDQSxRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2hELFFBQVEsTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbkQsUUFBUSxNQUFNLElBQUksR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNuRCxRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDbkMsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ25DLFFBQVEsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdkMsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3BDLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDdkM7SUFDQTtJQUNBLFFBQVEsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRTtJQUN0QixZQUFZLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDO0lBQzNCLFlBQVksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM3QyxZQUFZLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQztJQUNsQyxTQUFTLENBQUMsQ0FBQztBQUNYO0lBQ0E7SUFDQSxRQUFRLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUU7SUFDdEIsWUFBWSxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQztJQUMzQixZQUFZLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDN0MsWUFBWSxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUM7SUFDbEMsU0FBUyxDQUFDLENBQUM7QUFDWDtJQUNBO0lBQ0EsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLE9BQU8sRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDaEUsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLE9BQU8sRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDaEUsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQy9DLFFBQVEsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUNoRDtBQUNBO0lBQ0EsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2RCxRQUFRLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3ZEO0lBQ0E7SUFDQSxRQUFRLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSTtJQUNoQyxZQUFZLENBQUMsQ0FBQyxLQUFLO0lBQ25CLGdCQUFnQixDQUFDO0lBQ2pCLGdCQUFnQixDQUFDLENBQUMsTUFBTTtJQUN4QixvQkFBb0IsQ0FBQyxDQUFDLFdBQVc7SUFDakMsd0JBQXdCLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdkQsd0JBQXdCLENBQUM7SUFDekIsd0JBQXdCLENBQUM7SUFDekIscUJBQXFCO0lBQ3JCLG9CQUFvQixDQUFDLENBQUMsTUFBTTtJQUM1Qix3QkFBd0IsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUM7SUFDeEMsd0JBQXdCLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ3RDLHFCQUFxQjtJQUNyQixpQkFBaUI7SUFDakIsYUFBYTtJQUNiLFlBQVksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN6RSxZQUFZLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ25CLFNBQVMsQ0FBQyxDQUFDLENBQUM7QUFDWjtJQUNBLFFBQVEsQ0FBQyxDQUFDLE9BQU87SUFDakIsWUFBWSxDQUFDLENBQUMsUUFBUTtJQUN0QixnQkFBZ0IsSUFBSTtJQUNwQixnQkFBZ0IsQ0FBQyxDQUFDLE9BQU87SUFDekIsb0JBQW9CLENBQUMsQ0FBQyxZQUFZO0lBQ2xDLHdCQUF3QixDQUFDLENBQUMsT0FBTztJQUNqQyw0QkFBNEIsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMzRCw0QkFBNEIsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDMUMseUJBQXlCO0lBQ3pCLHdCQUF3QixDQUFDO0lBQ3pCLHdCQUF3QixDQUFDO0lBQ3pCLHFCQUFxQjtJQUNyQixvQkFBb0IsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDbEMsaUJBQWlCO0lBQ2pCLGFBQWE7SUFDYixTQUFTLENBQUM7QUFDVjtJQUNBO0lBQ0EsUUFBUSxDQUFDLENBQUMsT0FBTztJQUNqQixZQUFZLENBQUMsQ0FBQyxFQUFFO0lBQ2hCLGdCQUFnQixDQUFDLENBQUMsTUFBTTtJQUN4QixvQkFBb0IsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUM7SUFDcEMsb0JBQW9CLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ2xDLGlCQUFpQjtJQUNqQixnQkFBZ0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ25FLGFBQWE7SUFDYixTQUFTLENBQUM7QUFDVjtJQUNBLFFBQVEsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJO0FBQ2hDO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUk7SUFDMUIsZ0JBQWdCLENBQUMsQ0FBQyxLQUFLO0lBQ3ZCLG9CQUFvQixDQUFDO0lBQ3JCLG9CQUFvQixDQUFDLENBQUMsTUFBTTtJQUM1Qix3QkFBd0IsQ0FBQyxDQUFDLFdBQVc7SUFDckMsNEJBQTRCLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDM0QsNEJBQTRCLENBQUM7SUFDN0IsNEJBQTRCLENBQUM7SUFDN0IseUJBQXlCO0lBQ3pCLHdCQUF3QixDQUFDLENBQUMsTUFBTTtJQUNoQyw0QkFBNEIsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUM7SUFDNUMsNEJBQTRCLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQzFDLHlCQUF5QjtJQUN6QixxQkFBcUI7SUFDckIsaUJBQWlCO0lBQ2pCLGdCQUFnQixDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzdFLGdCQUFnQixDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN2QixhQUFhLENBQUM7QUFDZDtJQUNBLFlBQVksQ0FBQyxDQUFDLFFBQVE7SUFDdEIsZ0JBQWdCLElBQUk7SUFDcEIsZ0JBQWdCLENBQUMsQ0FBQyxRQUFRO0lBQzFCLG9CQUFvQixDQUFDLENBQUMsT0FBTztJQUM3Qix3QkFBd0IsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN2RCx3QkFBd0IsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDdEMscUJBQXFCO0lBQ3JCLG9CQUFvQixDQUFDO0lBQ3JCLG9CQUFvQixDQUFDO0lBQ3JCLGlCQUFpQjtJQUNqQixhQUFhO0FBQ2I7SUFDQSxZQUFZLENBQUMsQ0FBQyxRQUFRO0lBQ3RCLGdCQUFnQixJQUFJO0lBQ3BCLGdCQUFnQixDQUFDLENBQUMsU0FBUztJQUMzQixvQkFBb0IsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUM7SUFDcEMsb0JBQW9CLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDO0lBQ3BDLGlCQUFpQjtJQUNqQixhQUFhO0lBQ2IsWUFBWSxDQUFDLENBQUMsUUFBUTtJQUN0QixnQkFBZ0IsSUFBSTtJQUNwQixnQkFBZ0IsQ0FBQyxDQUFDLE9BQU87SUFDekIsb0JBQW9CLENBQUMsQ0FBQyxPQUFPO0lBQzdCLHdCQUF3QixDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQztJQUN4Qyx3QkFBd0IsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUM7SUFDeEMscUJBQXFCO0lBQ3JCLG9CQUFvQixDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztJQUNsQyxpQkFBaUI7SUFDakIsYUFBYTtBQUNiO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUk7SUFDMUIsZ0JBQWdCLENBQUMsQ0FBQyxLQUFLO0lBQ3ZCLG9CQUFvQixDQUFDO0lBQ3JCLG9CQUFvQixDQUFDLENBQUMsT0FBTztJQUM3Qix3QkFBd0IsQ0FBQyxDQUFDLE9BQU87SUFDakMsNEJBQTRCLENBQUMsQ0FBQyxPQUFPO0lBQ3JDLGdDQUFnQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQztJQUNoRCxnQ0FBZ0MsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxvQkFBb0IsQ0FBQztJQUNqRSw2QkFBNkI7SUFDN0IseUJBQXlCO0lBQ3pCLHdCQUF3QixDQUFDLENBQUMsUUFBUTtJQUNsQyw0QkFBNEIsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUM7SUFDNUMsNEJBQTRCLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQzFDLHlCQUF5QjtJQUN6QixxQkFBcUI7SUFDckIsaUJBQWlCO0FBQ2pCO0lBQ0EsZ0JBQWdCLENBQUMsQ0FBQyxRQUFRO0lBQzFCLG9CQUFvQixJQUFJO0lBQ3hCLG9CQUFvQixDQUFDLENBQUMsU0FBUztJQUMvQix3QkFBd0IsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUM7SUFDeEMsd0JBQXdCLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ3RDLHFCQUFxQjtJQUNyQixpQkFBaUI7QUFDakI7SUFDQSxnQkFBZ0IsQ0FBQyxDQUFDLFFBQVE7SUFDMUIsb0JBQW9CLElBQUk7SUFDeEIsb0JBQW9CLENBQUMsQ0FBQyxPQUFPO0lBQzdCLHdCQUF3QixDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQztJQUN4Qyx3QkFBd0IsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDdEMscUJBQXFCO0lBQ3JCLGlCQUFpQjtJQUNqQixnQkFBZ0IsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdkIsYUFBYSxDQUFDO0FBQ2Q7SUFDQSxZQUFZLENBQUMsQ0FBQyxFQUFFO0lBQ2hCLGdCQUFnQixDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDM0MsZ0JBQWdCO0lBQ2hCLG9CQUFvQixHQUFHLENBQUMsQ0FBQyxLQUFLO0lBQzlCLHdCQUF3QixDQUFDO0lBQ3pCLHdCQUF3QixDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDaEUscUJBQXFCO0lBQ3JCLG9CQUFvQixHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdkQsb0JBQW9CLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2RCxpQkFBaUI7SUFDakIsYUFBYTtBQUNiO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxRQUFRLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDO0lBQzlELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSTtJQUN6QixnQkFBZ0IsTUFBTSxHQUFHLE1BQU07SUFDL0IsZ0JBQWdCLENBQUM7SUFDakIsZ0JBQWdCLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDL0MsZ0JBQWdCLENBQUM7SUFDakIsYUFBYSxDQUFDO0lBQ2QsWUFBWSxDQUFDLENBQUMsSUFBSTtJQUNsQixnQkFBZ0IsTUFBTSxHQUFHLFFBQVE7SUFDakMsZ0JBQWdCLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDOUMsZ0JBQWdCLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDO0lBQ2hDLGFBQWE7SUFDYixZQUFZLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ25CLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDWixLQUFLO0FBQ0w7SUFDQSxJQUFJLFNBQVMsZUFBZSxHQUFHO0FBQy9CO0lBQ0EsUUFBUSxNQUFNLENBQUMsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUMzRCxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ2hDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDaEMsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNoQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQy9CLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDbEMsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUMvQixRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ2hDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDaEMsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNsQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ2pDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDL0IsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNuQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3RDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDbkM7SUFDQSxRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxjQUFjLEVBQUUsQ0FBQztBQUNyQztJQUNBLFFBQVEsTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbkQsUUFBUSxNQUFNLElBQUksR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNuRCxRQUFRLE1BQU0sSUFBSSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ25ELFFBQVEsTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbkQsUUFBUSxNQUFNLElBQUksR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNuRCxRQUFRLE1BQU0sSUFBSSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ25ELFFBQVEsTUFBTSxPQUFPLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hELFFBQVEsTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDbkQ7SUFDQSxRQUFRLENBQUMsQ0FBQyxPQUFPO0lBQ2pCLFlBQVksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFD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UUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDcEcsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckcsS0FBSztBQUNMO0lBQ0EsSUFBSSxTQUFTLFdBQVcsR0FBRztJQUMzQixRQUFRLE1BQU0sQ0FBQyxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3ZELFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDL0IsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztBQUMvQjtJQUNBLFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLGNBQWMsRUFBRSxDQUFDO0FBQ3JDO0lBQ0EsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDOUYsS0FBSztBQUNMO0FBQ0E7SUFDQSxJQUFJLFNBQVMsWUFBWSxHQUFHO0FBQzVCO0lBQ0EsUUFBUSxN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QUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0FBQ2pFO0lBQ0EsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNsRCxRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ2xELFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDbEQsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztBQUNsRDtBQUNBO0lBQ0EsUUFBUSxDQUFDLENBQUMsT0FBTztJQUNqQixZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNqRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztBQUNqRDtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ2pELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ2pELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxD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RUFBRSxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDbkMsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0FBQ2pFO0lBQ0EsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNuRCxRQUFRLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ3BELFFBQVEsTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDckQsUUFBUSxNQUFNLE1BQU0sR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztBQUN2RDtBQUNBO0lBQ0EsUUFBUSxDQUFDLENBQUMsT0FBTztJQUNqQjtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQ2xEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsQ0FBQztBQUNuRDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxFQUFFLEVBQUUsSUFBSSxDQUFDO0lBQzdDLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDO0FBQ3REO0lBQ0E7SUFDQSxZQUFZ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QUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3JELFFBQVEsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDekMsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3BDLFFBQVEsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNyQyxRQUFRLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzFDLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3JELFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3BEO0lBQ0EsUUFBUSxDQUFDLENBQUMsT0FBTztBQUNqQjtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxFQUFFLEVBQUUsQ0FBQztJQUN2QyxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQzNDO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDO0FBQ2xFO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLFNBQVMsRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDO0lBQ2pELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcs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QUM7SUFDbEMsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckQsUUFBUSxNQUFNLEtBQUssR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEQsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckQsUUFBUSxNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN6QyxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDcEM7SUFDQSxRQUFRLENBQUMsQ0FBQyxPQUFPO0FBQ2pCO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLEVBQUUsRUFBRSxDQUFDO0lBQ3ZDLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDM0M7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7QUFDbEU7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsU0FBUyxFQUFFLEVBQUUsRUFBRSxLQUFLLENBQUM7SUFDakQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUM7QUFDcEQ7SUFDQTtJQUNBLFlBQVks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USxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNqRSxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ25FLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNuQyxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDakUsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNuRSxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDbkMsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ2pFLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7QUFDbkU7SUFDQSxRQUFRLENBQUMsQ0FBQyxPQUFPO0lBQ2pCLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFF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LE9BQU8sQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNuRSxRQUFRLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ3JFLFFBQVEsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNwQyxRQUFRLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDcEUsUUFBUSxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztBQUN0RTtJQUNBLFFBQVEsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDcEQsUUFBUSxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNwRCxRQUFRLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ3BELFFBQVEsTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDckQsUUFBUSxNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNyRCxRQUFRLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ3JELFFBQVEsTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDckQsUUFBUSxNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNyRCxRQUFRLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ3JELFFBQVEsTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDdkQsUUFBUSxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUN2RCxRQUFRLE1BQU0sS0FBSyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ3ZELFFBQVEsTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7QUFDckQ7QUFDQTtJQUNBLFFBQVEsQ0FBQyxDQUFDLE9BQU87SUFDakIsWUFBWSxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7SUFDakQsWUFBWSxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7SUFDakQsWUFBWSxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7QUFDakQ7SUFDQSxZQUFZLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQztJQUNsRCxZQUFZLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQztJQUNsRCxZQUFZLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQztJQUNsRCxZQUFZLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQztJQUNsRCxZQUFZLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQztJQUNsRCxZQUFZLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQztBQUNsRDtJQUNBLFlBQVksRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDO0lBQ3RELFlBQVksRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDO0lBQ3RELFlBQVksRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDO0FBQ3REO0lBQ0EsWUFBWSxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxFQUFFLENBQUM7SUFDckQsWUFBWSxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUM7SUFDdEQsWUFBWSxFQUFFLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQzVDLFlBQVksRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQ25EO0lBQ0EsWUFBWSxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxFQUFFLENBQUM7SUFDckQsWUFBWSxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUM7SUFDdEQsWUFBWSxFQUFFLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxFQUFFLEVBQUUsR0FBRyxDQUFDO0lBQzdDLFlBQVksRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDO0FBQ3BEO0lBQ0EsWUFBWSxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxFQUFFLENBQUM7SUFDckQsWUFBWSxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUM7SUFDdEQsWUFBWSxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbkQsU0FBUyxDQUFDO0FBQ1Y7SUFDQSxLQUFLO0FBQ0w7SUFDQSxJQUFJLFNBQVMsV0FBVyxHQUFHO0lBQzNCLFFBQVEsTUFBTSxDQUFDLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDdkQsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUMvQixRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQy9CO0lBQ0EsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsY0FBYyxFQUFFLENBQUM7QUFDckM7SUFDQSxRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDbEMsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ2hFLFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDbEUsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ25DLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNqRSxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0FBQ25FO0lBQ0EsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNuRCxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ25ELFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDbkQsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNuRCxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ25ELFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDbkQsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztBQUNuRDtBQUNBO0lBQ0EsUUFBUSxDQUFDLENBQUMsT0FBTztBQUNqQjtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7SUFDaEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7SUFDaEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDbEQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztJQUNoRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztJQUNqRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQ2pEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7SUFDaEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDbEQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO0FBQ2hEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQzNDLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQ2xEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQzNDLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQ2xEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFB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SUFDbkMsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ2pFLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7QUFDbkU7SUFDQSxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ25ELFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDbkQsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNuRCxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ25ELFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDbkQsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNuRCxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ25ELFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDbkQsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNuRCxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ25ELFFBQVEsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7QUFDcEQ7SUFDQSxRQUFRLENBQUMsQ0FBQyxPQUFPO0lBQ2pCLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDL0MsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUMvQyxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQy9DLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2hELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2hELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQ2hEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQzNDLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQ2hEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQzNDLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQ2hEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDaEQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNoRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsQ0FBQztJQUNqRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQztJQUNqRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsZUFBZSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDM0MsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxHQUFHLENBQUM7SUFDakQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDakQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFVBQVUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQ2hEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENB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QUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ2pEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDakQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDakQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxTQUFTLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUNqRDtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ2pEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDbkQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLE1BQU0sQ0FBQztJQUN0RCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQztJQUNoRSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQztBQUNoRTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ25ELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcs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QyxDQUFDO0FBQ2xEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztBQUNsRDtJQUNBO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLFNBQVMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO0lBQ2xELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO0lBQ25ELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO0FBQ25EO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLFNBQVMsQ0FBQztJQUMvRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLFNBQVMsQ0FBQztJQUN6RSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLFNBQVMsQ0FBQztJQUN6RSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNuRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztJQUNuRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsU0FBUyxFQUFFLEVBQUUsQ0FBQztJQUMzRCxTQUFTLENBQUM7SUFDVixLQUFLO0FBQ0w7QUFDQTtJQUNBLElBQUksU0FBUyxhQUFhLEdB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LENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNoQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ2hDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDaEMsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNoQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQ2hDO0lBQ0EsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsY0FBYyxFQUFFLENBQUM7QUFDckM7SUFDQSxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDcEMsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2hFLFFBQVEsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDcEYsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3BDLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNwQyxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDaEUsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNwRixRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDcEMsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3BDLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNoRSxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ2xFO0lBQ0EsUUFBUSxNQUFNLElBQUksR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNuRCxRQUFRLE1BQU0sSUFBSSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ25ELFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDakQsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNqRCxRQUFRLE1BQU0sUUFBUSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3ZELFFBQVEsTUFBTSxRQUFRLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdkQsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNqRCxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2pELFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDaEQsUUFBUSxNQUFNLFdBQVcsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMxRCxRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2hELFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDaEQsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNoRCxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2pELFFBQVEsTUFB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Q0FBQyxXQUFXLEdBQUcsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2pELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsU0FBUyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDakQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDakQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUM7SUFDckUsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxTQUFTLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztJQUNsRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztBQUNsRDtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO0lBQ25ELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQ3BEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUM7SUFDdEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUM7QUFDN0Q7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNuRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztJQUNuRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQztBQUN2RDtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ3BELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsU0FBUyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbkQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxFQUFFLENBQUM7SUFDdEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxFQUFFLENBQUM7SUFDdEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7SUFDbkQsU0FBUyxDQUFDO0FBQ1Y7SUFDQSxLQUFLO0FBQ0w7QUFDQTtJQUNBLElBQUksU0FBUyxhQUFhLEdBQUc7QUFDN0I7SUFDQSxRQUFRLE1BQU0sQ0FBQyxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxHQUFHLFdBQVcsQ0FBQyxDQUFDO0lBQzNELFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDaEMsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNoQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ2hDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDaEM7SUFDQSxRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxjQUFjLEVBQUUsQ0FBQztBQUNyQztJQUNBLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNwQyxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDaEUsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNwRixRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDcEMsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3BDLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNoRSxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDcEMsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2hFLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDbEU7SUFDQSxRQUFRLE1BQU0sSUFBSSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ25ELFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDakQsUUFBUSxNQUFNLFFBQVEsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN2RCxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2pELFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDaEQsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNqRCxRQUFRLE1BQU0sV0FBVyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzFELFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDaEQsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENB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QUFDO0lBQ2xELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2pELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsTUFBTSxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsQ0FBQyxDQUFDO0lBQ3JFLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2xELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsU0FBUyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7QUFDbEQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztJQUNuRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztBQUNwRDtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDO0lBQ3RELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsTUFBTSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxDQUFDO0FBQzdEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbkQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7SUFDbkQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUM7QUFDdkQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztJQUNuRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLFNBQVMsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ25ELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDO0lBQ3RELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ3BELFNBQVMsQ0FBQztJQUNWLEtBQUs7QUFDTDtBQUNBO0lBQ0EsSUFBSSxTQUFTLGNBQWMsR0FBRztBQUM5QjtJQUNBLFFBQVEsTUFBTSxDQUFDLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEdBQUcsWUFBWSxDQUFDLENBQUM7SUFDNUQsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNoQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ2hDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDaEMsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztBQUNoQztJQUNBLFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLGNBQWMsRUFBRSxDQUFDO0FBQ3JDO0lBQ0EsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3BDLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNoRSxRQUFRLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BGLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNwQyxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDaEUsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3BDLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNoRSxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ2xFO0lBQ0EsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNoRCxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FB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LEdBQUcsTUFBTSxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsQ0FBQyxDQUFDO0lBQ3JFLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2xELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsU0FBUyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7QUFDbEQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztJQUNuRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztBQUNwRDtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDO0lBQ3RELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsTUFBTSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxDQUFDO0FBQzdEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbkQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7SUFDbkQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUM7QUFDdkQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FB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QUNyQztJQUNBLFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNuQyxRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDL0QsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNqRSxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDcEMsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2hFLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDbEU7QUFDQTtJQUNBLFFBQVEsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDcEQsUUFBUSxNQUFNLE1BQU0sR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNyRCxRQUFRLE1BQU0sTUFBTSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FB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Y0FBYyxFQUFFLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUU7SUFDM0UsWUFBWSxHQUFHLE9BQU8sQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRTtJQUMzRSxZQUFZLEdBQUcsT0FBTyxDQUFDLGNBQWMsRUFBRSxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFO0lBQzNFLFlBQVksR0FBRyxPQUFPLENBQUMsY0FBYyxFQUFFLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUU7SUFDM0UsWUFBWSxHQUFHLE9BQU8sQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRTtJQUMzRSxTQUFTO0lBQ1QsS0FBSyxDQUFDO0FBQ047SUFDQSxJQUFJLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUM7SUFDL0IsUUFBUSxHQUFHLE9BQU8sQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRTtJQUM1RCxRQUFRLEdBQUcsT0FBTyxDQUFDLGNBQWMsRUFBRSxZQUFZLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFO0lBQzVELFFBQVEsR0FBRyxPQUFPLENBQUMsY0FBYyxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUU7SUFDNUQsUUFBUSxHQUFHLE9BQU8sQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRTtJQUM1RCxRQUFRLEdBQUcsT0FBTyxDQUFDLGNBQWMsRUFBRSxZQUFZLENBQUMsQ0FBQyxDQUFDLEVBQUUs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LENBQUMsQ0FBQyxDQUFDO0lBQ3JFLFFBQVEsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7QUFDdkU7SUFDQSxRQUFRLE1BQU0sS0FBSyxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDM0MsUUFBUSxNQUFNLE1BQU0sR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQzNFLFFBQVEsTUFBTSxNQUFNLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7QUFDOUU7SUFDQSxRQUFRLE1BQU0sQ0FBQyxHQUFHLE1BQU0sQ0FBQztJQUN6QixRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3BELFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDcEQsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNwRCxRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3BELFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDcEQsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNwRCxRQUFRLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0FBQ3REO0lBQ0EsUUFBUSxDQUFDLENBQUMsT0FBTztJQUNqQjtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ2pELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ2hEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNqRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUNoRDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUMvQztJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUMvQztJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDL0M7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ2hEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQztJQUNqRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNoRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUMvQyxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztBQUNqRDtBQUNBO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztBQUNoRDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDakQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFHLENBQUM7SUFDakQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxHQUFHLENBQUM7SUFDbkQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDbkQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO0FBQ2pEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsQ0FBQztJQUNsRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQztJQUNwRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLEtBQUssQ0FBQztJQUN6RCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxjQUFjLENBQUMsRUFBRSxLQUFLLENBQUM7QUFDakY7QUFDQTtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLE1BQU0sQ0FBQztBQUNqRDtJQUNBO0lBQ0E7QUFDQTtJQUNBLFNBQVMsQ0FBQztJQUNWLEtBQUs7QUFDTDtBQUNBO0FBQ0E7SUFDQSxJQUFJLFNBQVMsbUJBQW1CLEdBQUc7SUFDbkMsUUFBUSxNQUFNLENBQUMsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxjQUFjLENBQUMsQ0FBQztJQUM3RCxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ2hDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDbkM7SUFDQSxRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxjQUFjLEVBQUUsQ0FBQztBQUNyQztJQUNBLFFBQVEsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNyQyxRQUFRLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDckUsUUFBUSxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztBQUN2RTtJQUNBLFFBQVEsTUFBTSxLQUFLLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUMzQyxRQUFRLE1BQU0sTUFBTSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDM0UsUUFBUSxNQUFNLE1BQU0sSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztBQUM5RTtJQUNBLFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDcEQsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNwRCxRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3BELFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDcEQsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNwRCxRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3BELFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDcEQsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNwRCxRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3BELFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDcEQsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNyRCxRQUFRLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0FBQ3REO0lBQ0EsUUFBUSxDQUFDLENBQUMsT0FBTztBQUNqQjtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ25FLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ2hEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBQ2hEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBQ2hEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUMvQyxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUMvQztJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ3RFO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUMvQyxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUMvQztJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDL0MsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ2xFO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQztJQUNqRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFH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Q0FBQyxDQUFDO0FBQy9CO0lBQ0EsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsY0FBYyxFQUFFLENBQUM7QUFDckM7SUFDQSxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDcEM7SUFDQSxRQUFRLE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFDLFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNsQyxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbkMsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMxQyxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUM1QztJQUNBLFFBQVEsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNwRSxRQUFRLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7QUFDekU7SUFDQSxRQUFRLE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzNDLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNwQztJQUNBLFFBQVEsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDM0MsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3BDLFFBQVEsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLENBQUM7QUFDOUM7SUFDQSxRQUFRLENBQUMsQ0FBQyxPQUFPO0lBQ2pCLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsWUFBWSxFQUFFLEVBQUUsRUFBRSxHQUFHLENBQUM7SUFDckQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxPQUFPLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQztJQUNoRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE9BQU8sRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDO0lBQ2hELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsQ0FBQztJQUMxQyxTQUFTLENBQUM7QUFDVjtJQUNBLFFBQVEsQ0FBQyxDQUFDLE9BQU87SUFDakIsWUFBWSxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2RixZQUFZLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNsRSxZQUFZLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUk7QUFDMUI7SUFDQSxnQkFBZ0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsY0FBYyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3ZFLGdCQUFnQixDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO0FBQzdGO0lBQ0EsZ0JBQWdCLENBQUMsQ0FBQyxFQUFFO0lBQ3BCLG9CQUFvQixDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsZ0JBQWdCLENBQUM7SUFDcEUsb0JBQW9CO0lBQ3BCLHdCQUF3QixHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLGNBQWMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDdkYsd0JBQXdCLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztJQUN4RyxxQkFBcUI7SUFDckIsaUJBQWlCO0lBQ2pCLGdCQUFnQixDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztJQUN6RCxnQkFBZ0IsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzRSxnQkFBZ0IsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdkIsYUFBYSxDQUFDO0lBQ2QsU0FBUyxDQUFDO0FBQ1Y7SUFDQSxRQUFRLENBQUMsQ0FBQyxPQUFPO0lBQ2pCLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsU0FBUyxFQUFFLEdBQUcsRUFBRSxFQUFFLENBQUM7SUFDL0MsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxTQUFTLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUM5QyxTQUFTLENBQUM7QUFDVjtJQUNBLFFBQVEsQ0FBQyxDQUFDLE9BQU87SUFDakIsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQztBQUNoRDtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsY0FBYyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN2RSxZQUFZLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7QUFDekY7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLGNBQWMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDdkUsWUFBWSxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO0lBQ3pGLFNBQVMsQ0FBQztJQUNWLEtBQUs7QUFDTDtJQUNBLElBQUksU0FBUyxnQkFBZ0IsR0FBRztJQUNoQyxRQUFRLE1BQU0sQ0FBQyxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLGVBQWUsQ0FBQyxDQUFDO0lBQzlELFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDbkMsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNwQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3BDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDaEM7SUFDQSxRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxjQUFjLEVBQUUsQ0FBQztBQUNyQztJQUNBLFFBQVEsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN4QyxRQUFRLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDekMsUUFBUSxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBQ3pDO0lBQ0EsUUFBUSxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ3JDO0lBQ0EsUUFBUSxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzVDLFFBQVEsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMxQyxRQUFRLE1BQU0sT0FBTyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDNUMsUUFBUSxNQUFNLE9BQU8sR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNuRCxRQUFRLE1BQU0sT0FBTyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNyRCxRQUFRLE1BQU0sT0FBTyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNyRCxRQUFRLE1BQU0sT0FBTyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNyRCxRQUFRLE1BQU0sUUFBUSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUN0RDtJQUNBLFFBQVEsQ0FBQyxDQUFDLE9BQU87QUFDakI7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE9BQU8sRUFBRSxFQUFFLEVBQUUsT0FBTyxDQUFDO0lBQ3BELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsT0FBTyxFQUFFLE9BQU8sQ0FBQztJQUNoRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE9BQU8sRUFBRSxFQUFFLEVBQUUsT0FBTyxDQUFDO0lBQ3BELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsT0FBTyxFQUFFLE9BQU8sQ0FBQztJQUNoRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE9BQU8sRUFBRSxFQUFFLEVBQUUsT0FBTyxDQUFDO0lBQ3BELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsT0FBTyxFQUFFLFFBQVEsQ0FBQztJQUNqRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNyRCxTQUFTLENBQUM7SUFDVixLQUFLO0FBQ0w7SUFDQSxJQUFJLFNBQVMsYUFBYSxHQUFHO0lBQzdCLFFBQVEsTUFBTSxDQUFDLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsWUFBWSxDQUFDLENBQUM7SUFDM0QsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNuQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3BDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDcEMsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztBQUNoQztJQUNBLFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLGNBQWMsRUFBRSxDQUFDO0FBQ3JDO0lBQ0EsUUFBUSxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3hDLFFBQVEsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN6QyxRQUFRLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDekM7SUFDQSxRQUFRLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDckMsUUFBUSxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNuRSxRQUFRLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ25FLFFBQVEsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbkUsUUFBUSxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNuRSxRQUFRLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQ3BFO0lBQ0EsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNyRCxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JELFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDckQsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNyRCxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JELFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDckQsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNyRCxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JELFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDckQsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNyRCxRQUFRLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0FBQ3REO0lBQ0EsUUFBUSxDQUFDLENBQUMsT0FBTztBQUNqQjtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNsRDtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNsRDtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQ2xEO0FBQ0E7SUFDQTtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNsRDtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUMxRSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNsRDtBQUNBO0lBQ0E7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNsRDtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUMxRTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNsRDtBQUNBO0FBQ0E7QUFDQTtJQUNBO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNsRDtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxDQUFDO0lBQ25ELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDO0lBQ25EO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztBQUNsRDtBQUNBO0lBQ0E7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNsRDtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxHQUFHLENBQUM7SUFDbkQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLENBQUM7SUFDbkQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDMUU7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNsRDtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQ7QUFDQTtJQUNBO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNsRDtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQzFFO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNsRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsQ0FBQztJQUNuRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQztJQUNuRDtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xEO0FBQ0E7SUFDQTtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNsRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNsRDtBQUNBO0lBQ0EsU0FBUyxDQUFDO0lBQ1YsS0FBSztBQUNMO0FBQ0E7SUFDQSxJQUFJLFNBQVMsZUFBZSxHQUFHO0lBQy9CLFFBQVEsTUFBTSxDQUFDLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsYUFBYSxDQUFDLENBQUM7SUFDNUQsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNuQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ25DLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDL0IsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNuQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQy9CO0lBQ0EsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsY0FBYyxFQUFFLENBQUM7QUFDckM7SUFDQSxRQUFRLE1BQU0sT0FBTyxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDNUMsUUFBUSxNQUFNLE9BQU8sR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0FBQzVFO0lBQ0EsUUFBUSxNQUFNLEtBQUssSUFBSSxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzNDLFFBQVEsTUFBTSxNQUFNLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUMzRSxRQUFRLE1BQU0sTUFBTSxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxNQUFN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QUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JFLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7QUFDckU7SUFDQSxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDbkMsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ25FLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDckUsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNyRSxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JFLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7QUFDckU7SUFDQSxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JELFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDckQsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNyRCxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JELFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDckQsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNyRCxRQUFRLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3RELFFBQVEsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7QUFDdEQ7QUFDQTtJQUNBLFFBQVEsQ0FBQyxDQUFDLE9BQU87SUFDakI7SUFDQTtJQUNBO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsQ0FBQztJQUNuRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsRUFBRSxFQUFFLENBQUM7SUFDMUUsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxHQUFHLENBQUM7SUFDbkQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbkQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDO0lBQzVFLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDO0lBQ3JELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDO0lBQ25ELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDO0FBQ3BEO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsQ0FBQztJQUNuRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsRUFBRSxFQUFFLENBQUM7SUFDMUUsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxHQUFHLENBQUM7SUFDbkQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbkQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDO0lBQzVFLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDO0lBQ3JELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDO0lBQ25ELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDO0FBQ3BEO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsQ0FBQztJQUNuRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsRUFBRSxFQUFFLENBQUM7SUFDMUUsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxHQUFHLENBQUM7SUFDbkQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbkQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDO0lBQzVFLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDO0lBQ3JELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDO0lBQ25ELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDO0FBQ3BEO0lBQ0E7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDbEQ7SUFDQTtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLEVBQUUsR0FBRyxDQUFDO0lBQzVFLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ25ELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ25EO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDbEQ7SUFDQTtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FB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Q0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNwRCxRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3BELFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDcEQsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNwRCxRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3BELFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDcEQsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNwRCxRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3BELFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDcEQsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNwRCxRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3BELFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDcEQsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNwRCxRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3BELFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDcEQsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNwRCxRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3BELFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDcEQsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztBQUNwRDtJQUNBLFFBQVEsQ0FBQyxDQUFDLE9BQU87QUFDakI7QUFDQTtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxvQkFBb0IsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO0lBQ3pELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsWUFBWSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbEQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLG9CQUFvQixFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDdkQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLG9CQUFvQixFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDdkQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUMvQztJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsb0JBQW9CLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN2RCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLFlBQVksRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2xEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxvQkFBb0IsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxvQkFBb0IsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsWUFBWSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbEQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLFlBQVksRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2xEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxZQUFZLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNsRDtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQy9DO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMs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LENBQUMsY0FBYyxFQUFFLFlBQVksQ0FBQyxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO0lBQ2hGLElBQUksTUFBTSxTQUFTLEdBQUcsVUFBVSxDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO0FBQzdEO0lBQ0EsSUFBSSxRQUFRLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0FBQ3JEO0lBQ0EsSUFBSSxRQUFRLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNuQyxJQUFJLFFBQVEsQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQ25DO0lBQ0EsSUFBSSxNQUFNLFNBQVMsR0FBRyxRQUFRLENBQUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDaEUsSUFBSSxNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDO0lBQzlCLFFBQVEsR0FBRyxLQUFLLENBQUMsY0FBYyxFQUFFLFlBQVksQ0FBQyxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUU7SUFDM0QsUUFBUSxHQUFHLEtBQUssQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRTtJQUMzRCxLQUFLLENBQUMsQ0FBQztJQUNQLElBQUksTUFBTSxTQUFTLEdBQUcsVUFBVSxDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO0FBQzdEO0FBQ0E7SUFDQSxJQUFJLFNBQVMsYUFBYSxDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUU7SUFDMUMsUUFBUSxNQUFNLENBQUMsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzdDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDaEMsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNqQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQ2hDO0lBQ0EsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsY0FBYyxFQUFFLENBQUM7QUFDckM7SUFDQSxRQUFRLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0FBQ25EO0lBQ0EsUUFBUSxDQUFDLENBQUMsT0FBTztJQUNqQixZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRSxHQUFHLENBQUM7SUFDaEUsWUFBWSxDQUFDLENBQUMsSUFBSTtJQUNsQixnQkFBZ0IsS0FBSztJQUNyQixnQkFBZ0IsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUM7SUFDaEMsZ0JBQWdCLEdBQUc7SUFDbkIsZ0JBQWdCLENBQUMsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDO0lBQ2hDLGdCQUFnQixDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQztJQUNoQyxhQUFhO0lBQ2IsU0FBUyxDQUFDO0FBQ1Y7SUFDQSxRQUFRLE1BQU0sQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDdEMsS0FBSztJQUNMLElBQUksYUFBYSxDQUFDLGFBQWEsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO0lBQ3BELElBQUksUUFBUSxDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxhQUFhLENBQUMsQ0FBQztBQUN6RDtJQUNBLElBQUksYUFBYSxDQUFDLGFBQWEsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO0lBQ3BELElBQUksUUFBUSxDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxhQUFhLENBQUMsQ0FBQztBQUN6RDtJQUNBLElBQUksYUFBYSxDQUFDLG1CQUFtQixFQUFFLHVCQUF1QixDQUFDLENBQUM7SUFDaEUsSUFBSSxhQUFhLENBQUMsbUJBQW1CLEVBQUUsdUJBQXVCLENBQUMsQ0FBQztBQUNoRTtJQUNBLElBQUksYUFBYSxDQUFDLE1BQU0sRUFBRSxtQkFBbUIsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQ3ZGLElBQUksYUFBYSxDQUFDLE1BQU0sRUFBRSxtQkFBbUIsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsYUFBYSxDQUFDLENBQUM7SUFDL0YsSUFBSSxhQUFhLENBQUMsTUFBTSxFQUFFLHdCQUF3QixFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO0lBQzFHLElBQUksYUFBYSxDQUFDLE1BQU0sRUFBRSxtQkFBbUIsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxhQUFhLENBQUMsQ0FBQztJQUNuRyxJQUFJLGFBQWEsQ0FBQyxNQUFNLEVBQUUsd0JBQXdCLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsbUJBQW1CLENBQUMsQ0FBQztBQUM5RztBQUNBO0lBQ0EsSUFBSSxTQUFTLFlBQVksQ0FBQyxDQUFDLEVBQUU7SUFDN0IsUUFBUSxPQUFPLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN4RCxLQUFLO0FBQ0w7SUFDQSxJQUFJLE1BQU0sS0FBSyxHQUFHO0lBQ2xCLFFBQVEsb0hBQW9IO0lBQzVILFFBQVEsb0hBQW9IO0lBQzVILFFBQVEsRUFBRTtJQUNWLEtBQUssQ0FBQztBQUNOO0lBQ0EsSUFBSSxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsS0FBSztJQUMvQixRQUFRO0lBQ1IsWUFBWSxHQUFHLEtBQUssQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRTtJQUNyRSxZQUFZLEdBQUcsS0FBSyxDQUFDLGNBQWMsRUFBRSxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFO0lBQ3JFLFlBQVksR0FBRyxLQUFLLENBQUMsY0FBYyxFQUFFLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUU7SUFDckUsU0FBUztJQUNULEtBQUssQ0FBQztBQUNOO0lBQ0EsSUFBSSxNQUFNLE1BQU0sR0FBRztJQUNuQixRQUFRLEVBQUU7SUFDVixRQUFRLEVBQUU7SUFDVixRQUFRLEVBQUU7SUFDVixLQUFLLENBQUM7QUFDTjtJQUNBLElBQUksTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLEtBQUs7SUFDaEMsUUFBUTtJQUNSLFlBQVksR0FBRyxLQUFLLENBQUMsY0FBYyxFQUFFLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUU7SUFDdEUsWUFBWSxHQUFHLEtBQUssQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRTtJQUN0RSxZQUFZLEdBQUcsS0FBSyxDQUFDLGNBQWMsRUFBRSxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFO0lBQ3RFLFNBQVM7SUFDVCxLQUFLLENBQUM7QUFDTjtJQUNBLElBQUksTUFBTSxLQUFLLEdBQUc7SUFDbEIsUUFBUTtJQUNSLFlBQVksbUhBQW1IO0lBQy9ILFlBQVksb0hBQW9IO0lBQ2hJLFNBQVMsQ0FBQztJQUNWLFlBQVksb0hBQW9IO0lBQ2hJLFlBQVksbUhBQW1IO0lBQy9ILFNBQVMsQ0FBQztJQUNWLFlBQVksRUFBRTtJQUNkLFlBQVksRUFBRTtJQUNkLFNBQVM7SUFDVCxLQUFLLENBQUM7QUFDTjtJQUNBLElBQUksTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLEtBQUs7SUFDL0IsUUFBUTtJQUNSLFlBQVksR0FBRyxLQUFLLENBQUMsY0FBYyxFQUFFLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUU7SUFDeEUsWUFBWSxHQUFHLEtBQUssQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRTtJQUN4RSxZQUFZLEdBQUcsS0FBSyxDQUFDLGNBQWMsRUFBRSxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFO0lBQ3hFLFlBQVksR0FBRyxLQUFLLENBQUMsY0FBYyxFQUFFLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUU7SUFDeEUsWUFBWSxHQUFHLEtBQUssQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRTtJQUN4RSxZQUFZLEdBQUcsS0FBSyxDQUFDLGNBQWMsRUFBRSxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFO0lBQ3hFLFNBQVM7SUFDVCxLQUFLLENBQUM7QUFDTjtJQUNBLElBQUksTUFBTSxNQUFNLEdBQUc7SUFDbkIsUUFBUTtJQUNSLFlBQVksRUFBRTtJQUNkLFlBQVksRUFBRTtJQUNkLFNBQVMsQ0FBQztJQUNWLFlBQVksRUFBRTtJQUNkLFlBQVksRUFBRTtJQUNkLFNBQVMsQ0FBQztJQUNWLFlBQVksRUFBRTtJQUNkLFlBQVksRUFBRTtJQUNkLFNBQVM7SUFDVCxLQUFLLENBQUM7QUFDTjtJQUNBLElBQUksTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLEtBQUs7SUFDaEMsUUFBUTtJQUNSLFlBQVksR0FBRyxLQUFLLENBQUMsY0FBYyxFQUFFLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUU7SUFDekUsWUFBWSxHQUFHLEtBQUssQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRTtJQUN6RSxZQUFZLEdBQUcsS0FBSyxDQUFDLGNBQWMsRUFBRSxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFO0lBQ3pFLFlBQVksR0FBRyxLQUFLLENBQUMsY0FBYyxFQUFFLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUU7SUFDekUsWUFBWSxHQUFHLEtBQUssQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRTtJQUN6RSxZQUFZLEdBQUcsS0FBSyxDQUFDLGNBQWMsRUFBRSxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFO0lBQ3pFLFNBQVM7SUFDVCxLQUFLLENBQUM7QUFDTjtJQUNBLElBQUksTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQztJQUMvQixRQUFRLEdBQUcsS0FBSyxDQUFDLGNBQWMsRUFBRSxZQUFZLENBQUMsRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFO0lBQzNELFFBQVEsR0FBRyxLQUFLLENBQUMsY0FBYyxFQUFFLFlBQVksQ0FBQyxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUU7SUFDM0QsUUFBUSxHQUFHLEtBQUssQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRTtJQUMzRCxRQUFRLEdBQUcsS0FBSyxDQUFDLGNBQWMsRUFBRSxZQUFZLENBQUMsRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFO0lBQzNELFFBQVEsR0FBRyxLQUFLLENBQUMsY0FBYyxFQUFFLFlBQVksQ0FBQyxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUU7SUFDM0QsUUFBUSxHQUFHLEtBQUssQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRTtJQUMzRCxRQUFRLEdBQUcsS0FBSyxDQUFDLGNBQWMsRUFBRSxZQUFZLENBQUMsRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFO0lBQzNELFFBQVEsR0FBRyxLQUFLLENBQUMsY0FBYyxFQUFFLFlBQVksQ0FBQyxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUU7SUFDM0QsUUFBUSxHQUFHLEtBQUssQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRTtJQUMzRCxRQUFRLEdBQUcsS0FBSyxDQUFDLGNBQWMsRUFBRSxZQUFZLENBQUMsRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFO0lBQzNELFFBQVEsR0FBRyxLQUFLLENBQUMsY0FBYyxFQUFFLFlBQVksQ0FBQyxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUU7SUFDM0QsUUFBUSxHQUFHLEtBQUssQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRTtJQUMzRCxLQUFLLENBQUMsQ0FBQztBQUNQO0lBQ0EsSUFBSSxNQUFNLGNBQWMs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LENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDM0QsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNyRCxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JELFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDckQsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztBQUNyRDtJQUNBLFFBQVEsQ0FBQyxDQUFDLE9BQU87QUFDakI7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDakQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDakQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDakQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDakQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDbEQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQ2xEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNsRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztBQUNsRDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDbEQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDakQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxFQUFFLEVBQUUsRUFBRSxRQUFRLENBQUM7QUFDdkQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQ2xEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNsRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2pELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxRQUFRLEVBQUUsRUFBRSxDQUFDO0FBQ3hEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNsRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztBQUNsRDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDbEQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQ2xEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztBQUNsRDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDbEQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxRQUFRLEVBQUUsRUFBRSxDQUFDO0FBQ3hEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVB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QyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ25FLFFBQVEsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7QUFDbkU7SUFDQSxRQUFRLE1BQU0sUUFBUSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQzNELFFBQVEsTUFBTSxRQUFRLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDM0QsUUFBUSxNQUFNLFNBQVMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUM1RCxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JELFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDckQsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNyRCxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JELFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDckQsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNyRCxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JELFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7QUFDckQ7SUFDQSxRQUFRLENBQUMsQ0FBQyxPQUFPO0FBQ2pCO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsRUFBRSxFQUFFLEVBQUUsUUFBUSxDQUFDO0FBQ3ZEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsRUFBRSxFQUFFLEVBQUUsUUFBUSxDQUFDO0FBQ3ZEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztBQUN4RDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNqRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLEVBQUUsQ0FBQztJQUN4RCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLEVBQUUsQ0FBQztJQUN4RCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLEVBQUUsQ0FBQztBQUN4RDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDbEQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDakQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQ2xEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztBQUNsRDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDbEQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQ2xEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztBQUNsRDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDbEQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDakQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDbEQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDakQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxFQUFFLENBQUM7SUFDeEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDbEQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxDQUFDO0FBQ25EO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNsRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztBQUNsRDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDbEQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQ2xEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztBQUNsRDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQztJQUNuRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLEdBQUcsQ0FBQztBQUMxRDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLEVBQUUsRUFBRSxFQUFFLFNBQVMsQ0FBQztBQUN4RDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxHQUFHLENBQUM7QUFDM0Q7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDO0FBQ25EO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsQ0FBQztBQUNuRDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztB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QUFHLENBQUMsQ0FBQyxjQUFjLEVBQUUsQ0FBQztBQUNyQztJQUNBLFFBQVEsTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN0QyxRQUFRLE1BQU0sSUFBSSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hFLFFBQVEsTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDeEU7SUFDQSxRQUFRLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDdEM7SUFDQSxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDcEMsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN0RSxRQUFRLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3ZFO0lBQ0EsUUFBUSxNQUFNLE9BQU8sR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDNUQsUUFBUSxNQUFNLE9BQU8sR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDNUQ7SUFDQSxRQUFRLENBQUMsQ0FBQyxPQUFPO0FBQ2pCO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxPQUFPLENBQUM7SUFDM0QsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxPQUFPLENBQUM7QUFDM0Q7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsR0FBRyxDQUFDO0FBQ3JEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUN2RCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQztBQUNuRDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxRQUFRLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztBQUNoRDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDdkQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLENBQUM7SUFDbkQsU0FBUyxDQUFDO0lBQ1YsS0FBSztJQUNMLElBQUksV0FBVyxFQUFFLENBQUM7QUFDbEI7SUFDQSxJQUFJLFNBQVMsWUFBWSxHQUFHO0lBQzVCLFFBQVEsTUFBTSxDQUFDLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDMUQsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNoQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ2pDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDakMsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztBQUNoQztJQUNBLFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLGNBQWMsRUFBRSxDQUFDO0FBQ3JDO0lBQ0EsUUFBUSxNQUFNLElBQUksR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3RDLFFBQVEsTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEUsUUFBUSxNQUFNLElBQUksR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUN4RTtJQUNBLFFBQVEsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN0QyxRQUFRLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDdEM7SUFDQSxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDcEMsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN0RSxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3RFO0lBQ0EsUUFBUSxNQUFNLEdBQUcsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEQsUUFBUSxNQUFNLEdBQUcsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEQsUUFBUSxNQUFNLE9BQU8sR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDNUQsUUFBUSxNQUFNLE9BQU8sR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDNUQ7SUFDQSxRQUFRLENBQUMsQ0FBQyxPQUFPO0lBQ2pCO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxHQUFHLENBQUM7QUFDckQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsR0FBRyxDQUFDO0FBQ3JEO0FBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLE9BQU8sQ0FBQztJQUMzRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLE9BQU8sQ0FBQztBQUMzRDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxFQUFFLENBQUM7SUFDdEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLENBQUM7QUFDbkQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsUUFBUSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDaEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLENBQUM7QUFDbkQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDO0lBQ3ZELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDO0lBQ25ELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDO0FBQ25EO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUN2RCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQztJQUNuRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQztBQUNuRDtBQUNBO0lBQ0EsU0FBUyxDQUFDO0lBQ1YsS0FBSztJQUNMLElBQUksWUFBWSxFQUFFLENBQUM7QUFDbkI7QUFDQTtJQUNBLElBQUksU0FBUyxjQUFjLEdBQUc7QUFDOUI7SUFDQSxRQUFRLE1BQU0sQ0FBQyxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQzNELFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDaEMsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNqQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ2pDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDakMsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztBQUNoQztJQUNBLFFBQVEsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLGNBQWMsRUFBRSxDQUFDO0FBQ3JDO0FBQ0E7SUFDQSxRQUFRLE1BQU0sSUFBSSxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdEMsUUFBUSxNQUFNLElBQUksR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUN4RTtJQUNBLFFBQVEsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN0QyxRQUFRLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDdEMsUUFBUSxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3RDO0lBQ0EsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdkQsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdkQsUUFBUSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEQ7SUFDQSxRQUFRLE1BQU0sSUFBSSxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdEMsUUFBUSxNQUFNLElBQUksR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUN4RTtJQUNBLFFBQVEsQ0FBQyxDQUFDLE9BQU87SUFDakI7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLFFBQVEsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDMUQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsT0FBTyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQ3JEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztBQUNqRDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUM7QUFDeEQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsUUFBUSxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQztBQUMzRDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxJQUFJLENBQUM7SUFDdEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxJQUFJLENBQUM7QUFDdEQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsT0FBTyxFQUFFLEVBQUUsRUFBRSxJQUFJLENBQUM7QUFDakQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsUUFBUSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUM7QUFDcEQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsSUFBSSxDQUFDO0lBQ3RELFNBQVMsQ0FBQztJQUNWLEtBQUs7SUFDTCxJQUFJLGNBQWMsRUFBRSxDQUFDO0FBQ3JCO0FBQ0E7SUFDQSxJQUFJLFNBQVMsUUFBUSxHQUFHO0lBQ3hCLFFBQVEsTUFBTSxDQUFDLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDckQsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNoQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3BDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDaEM7SUFDQSxRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxjQUFjLEVBQUUsQ0FBQztBQUNyQztJQUNBLFFBQVEsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNyQyxRQUFRLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7QUFDbEU7SUFDQSxRQUFRLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDcEM7SUFDQSxRQUFRLE1BQU0sT0FBTyxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDOUMsUUFBUSxNQUFNLE9BQU8sSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQzlFLFFBQVEsTUFBTSxPQUFPLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDaEYsUUFBUSxNQUFNLE9BQU8sSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNoRixRQUFRLE1BQU0sS0FBSyxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQzlFO0lBQ0EsUUFBUSxNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzQyxRQUFRLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDckMsUUFBUSxNQUFNLEtBQUssR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3ZDLFFBQVEsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDOUM7SUFDQSxRQUFRLE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzNDLFFBQVEsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNyQyxRQUFRLE1BQU0sS0FBSyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdkMsUUFBUSxNQUFNLEtBQUssR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUM5QyxRQUFRLENBQUMsQ0FBQyxPQUFPO0lBQ2pCO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0FBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQztJQUMxRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQztJQUMxRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFH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QVMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNyRSxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JFLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7QUFDckU7SUFDQSxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDbkMsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ25FLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDckUsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNyRSxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JFLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7QUFDckU7SUFDQSxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JELFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDckQsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNyRCxRQUFRLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JELFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDckQsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNyRCxRQUFRLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3RELFFBQVEsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7QUFDdEQ7QUFDQTtJQUNBLFFBQVEsQ0FBQyxDQUFDLE9BQU87SUFDakI7SUFDQTtJQUNBO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsQ0FBQztJQUNuRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLFFBQVEsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2hELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxDQUFDO0lBQ25ELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ25ELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsUUFBUSxFQUFFLEdBQUcsRUFBRSxHQUFHLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLENBQUM7SUFDckQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLENBQUM7SUFDbkQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxFQUFFLENBQUM7QUFDcEQ7SUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxDQUFDO0lBQ25ELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsUUFBUSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDaEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxHQUFHLENBQUM7SUFDbkQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbkQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxRQUFRLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQztJQUNsRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQztJQUNyRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQztJQUNuRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQztBQUNwRDtJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxHQUFHLENBQUM7SUFDbkQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxRQUFRLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNoRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNsRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsQ0FBQztJQUNuRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNuRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLFFBQVEsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDO0lBQ2xELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDO0lBQ3JELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDO0lBQ25ELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDO0FBQ3BEO0lBQ0E7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDbEQ7SUFDQTtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLEVBQUUsR0FBRyxDQUFDO0lBQzVFLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ25ELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ25EO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDbEQ7SUFDQTtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbEQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJ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RSxDQUFDO0FBQ3pEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLFlBQVksRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQ3BEO0lBQ0E7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNsRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztBQUNsRDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxZQUFZLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztBQUNwRDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDbEQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsZ0JBQWdCLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztBQUN4RDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDbEQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsZ0JBQWdCLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztBQUN4RDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDbEQ7SUFDQTtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsZ0JBQWdCLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztBQUN4RDtJQUNBO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxD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LENBQUMsQ0FBQztJQUN4QyxRQUFRLE1BQU0sTUFBTSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQy9DLFFBQVEsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDNUMsUUFBUSxNQUFNLE1BQU0sR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMvQyxRQUFRLE1BQU0sTUFBTSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN0RCxRQUFRLE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzNDLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNwQyxRQUFRLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDckMsUUFBUSxNQUFNLE1BQU0sR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3hDLFFBQVEsTUFBTSxNQUFNLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDL0MsUUFBUSxNQUFNLEdBQUcsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUM1QyxRQUFRLE1BQU0sTUFBTSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQy9DLFFBQVEsTUFBTSxNQUFNLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3RELFFBQVEsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQzlDO0FBQ0E7SUFDQSxRQUFRLENBQUMsQ0FBQyxPQUFPO0lBQ2pCLFlBQVksQ0FBQyxDQUFDLEVBQUU7SUFDaEIsZ0JBQWdCLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLGVBQWUsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3BFLGdCQUFnQixDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdEMsYUFBYTtJQUNiLFlBQVksQ0FBQyxDQUFDLEVBQUU7SUFDaEIsZ0JBQWdCLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsZ0JBQWdCLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ2hGLGdCQUFnQixDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdEMsYUFBYTtJQUNiLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDO0lBQ3hELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDO0FBQ3hEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxHQUFHLENBQUM7SUFDNUQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsQ0FBQztBQUNuRDtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLE1BQU0sRUFBRSxHQUFHLENBQUM7SUFDbkQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxHQUFHLENBQUM7QUFDM0Q7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsQ0FBQztJQUMzRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQztJQUM5RCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxDQUFDO0FBQ3BEO0lBQ0EsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxHQUFHLENBQUM7SUFDM0QsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUM7SUFDOUQsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sQ0FBQztBQUNwRDtJQUNBLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsR0FBRyxDQUFDO0lBQzNELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDO0lBQzlELFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLENBQUM7QUFDcEQ7SUFDQSxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsQ0FBQztJQUMzRCxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLE1B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Q0FBQyxDQUFDLENBQUMsQ0FBQztBQUNoRztJQUNBLFFBQVEsTUFBTSxNQUFNLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNuRjtBQUNBO0lBQ0EsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ25DLFFBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztBQUNuRTtJQUNBLFFBQVEsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDM0MsUUFBUSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3BDLFFBQVEsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNyQyxRQUFRLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQzVDO0lBQ0EsUUFBUSxNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM1QyxRQUFRLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdEMsUUFBUSxNQUFNLElBQUksR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3ZDLFFBQVEsTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDOUM7SUFDQSxRQUFRLENBQUMsQ0FB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RSxDQUFDO0lBQ3BCLElBQUksSUFBSSxDQUFDLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hCLElBQUksSUFBSSxVQUFVLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO0lBQ3BFLElBQUksT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRTtJQUN2QixRQUFRLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ3JDLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDcEIsS0FBSztJQUNMLElBQUksSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3JDLElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ3hDLFFBQVEsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUM7SUFDakMsS0FBSztJQUNMLElBQUksT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztBQUNEO0lBQ0EsU0FBUyxNQUFNLENBQUMsRUFBRSxFQUFFO0lBQ3BCLElBQUksSUFBSSxDQUFDLEVBQUUsSUFBSSxDQUFDO0lBQ2hCLElBQUksTUFBTSxJQUFJLEdBQUcsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQy9CLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFO0lBQ2QsUUFBUSxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQ3BCLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDdEMsS0FBSyxNQUFNO0lBQ1gsUUFBUSxJQUFJLEdBQUcsS0FBSyxD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QUksRUFBRSxLQUFLLEVBQUUsR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUMvRCxLQUFLO0FBQ0w7SUFDQSxJQUFJLFlBQVksQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRTtJQUMzQyxRQUFRLE1BQU0sTUFBTSxHQUFHLE9BQU8sSUFBSSxDQUFDLENBQUM7SUFDcEMsUUFBUSxNQUFNLEtBQUssR0FBRyxDQUFDLE1BQU0sS0FBSyxTQUFTLElBQUksQ0FBQyxHQUFHLE1BQU0sQ0FBQztJQUMxRCxRQUFRLE9BQU8sQ0FBQyxHQUFHLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDL0QsS0FBSztBQUNMO0lBQ0EsSUFBSSxZQUFZLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUU7SUFDM0MsUUFBUSxNQUFNLE1BQU0sR0FBRyxPQUFPLElBQUksQ0FBQyxDQUFDO0lBQ3BDLFFBQVEsTUFBTSxLQUFLLEdBQUcsQ0FBQyxNQUFNLEtBQUssU0FBUyxJQUFJLENBQUMsR0FBRyxNQUFNLENBQUM7SUFDMUQsUUFBUSxPQUFPLENBQUMsR0FBRyxPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQy9ELEtBQUs7QUFDTDtJQUNBLElBQUksWUFBWSxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFO0lBQzNDLFFBQVEsTUFBTSxNQUFNLEdBQUcsT0FBTyxJQUFJLENBQUMsQ0FBQztJQUNwQyxRQUFRLE1BQU0sS0FBSyxHQUFHLENBQUMsTUFBTSxLQUFLLFNBQVMsSUFBSSxDQUFDLEdBQUcsTUFBTSxDQUFDO0lBQzFELFFBQVEsT0FBTyxDQUFDLEdBQUcsT0FBTyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUMvRCxLQUFLO0FBQ0w7SUFDQSxJQUFJ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SUFDbkMsUUFBUSxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUU7SUFDcEMsWUFBWSxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ3ZCLFlBQVksS0FBSyxHQUFHLENBQUMsQ0FBQztJQUN0QixZQUFZLE9BQU8sR0FBRyxPQUFPLENBQUM7SUFDOUIsU0FBUyxNQUFNLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRTtJQUMxQyxZQUFZLE1BQU0sR0FBRyxPQUFPLENBQUM7SUFDN0IsWUFBWSxLQUFLLEdBQUcsQ0FBQyxDQUFDO0lBQ3RCLFlBQVksT0FBTyxHQUFHLE1BQU0sQ0FBQztJQUM3QixTQUFTLE1BQU0sSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxFQUFFO0lBQzVDLFlBQVksTUFBTSxHQUFHLE9BQU8sQ0FBQztJQUM3QixZQUFZLEtBQUssR0FBRyxNQUFNLENBQUM7SUFDM0IsWUFBWSxPQUFPLEdBQUcsUUFBUSxDQUFDO0lBQy9CLFNBQVM7SUFDVCxRQUFRLE9BQU8sQ0FBQyxHQUFHLE9BQU8sRUFBRSxHQUFHLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDM0UsS0FBSztBQUNMO0lBQ0EsSUFBSSxXQUFXLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUU7SUFDMUMsUUFBUSxNQUFNLE1BQU0sR0FBRyxPQUFPLElBQUksQ0FBQyxDQUFDO0lBQ3BDLFFBQVEsTUFBTSxLQUFLLEdBQUcsQ0FBQyxNQUFNLEtBQUssU0FBUyxJQUFJLENBQUMsR0FBRyxNQUFNLENBQUM7SUFDMUQsUUFBUSxPQUFPLENBQUMsR0FBRyxPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQy9ELEtBQUs7QUFDTDtJQUNBLElBQUksV0FBVyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFO0lBQzFDLFFBQVEsTUFBTSxNQUFNLEdBQUcsT0FBTyxJQUFJLENBQUMsQ0FBQztJQUNwQyxRQUFRLE1BQU0sS0FBSyxHQUFHLENBQUMsTUFBTSxLQUFLLFNBQVMsSUFBSSxDQUFDLEdBQUcsTUFBTSxDQUFDO0lBQzFELFFBQVEsT0FBTyxDQUFDLEdBQUcsT0FBTyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUMvRCxLQUFLO0FBQ0w7SUFDQSxJQUFJLFlBQVksQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRTtJQUMzQyxRQUFRLE1BQU0sTUFBTSxHQUFHLE9BQU8sSUFBSSxDQUFDLENBQUM7SUFDcEMsUUFBUSxNQUFNLEtBQUssR0FBRyxDQUFDLE1BQU0sS0FBSyxTQUFTLElBQUksQ0FBQyxHQUFHLE1BQU0sQ0FBQztJQUMxRCxRQUFRLE9BQU8sQ0FBQyxHQUFHLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDL0QsS0FBSztBQUNMO0lBQ0EsSUFBSSxZQUFZLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUU7SUFDM0MsUUFBUSxNQUFNLE1BQU0sR0FBRyxPQUFPLElBQUksQ0FBQyxDQUFDO0lBQ3BDLFFBQVEsTUFBTSxLQUFLLEdBQUcsQ0FBQyxNQUFNLEtBQUssU0FBUyxJQUFJLENBQUMsR0FBRyxNQUFNLENBQUM7SUFDMUQsUUFBUSxPQUFPLENBQUMsR0FBRyxPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQy9ELEtBQUs7QUFDTDtJQUNBLElBQUksUUFBUSxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFO0lBQ3ZDLFFBQVEsTUFBTSxNQUFNLEdBQUcsT0FBTyxJQUFJLENBQUMsQ0FBQztJQUNwQyxRQUFRLE1BQU0sS0FBSyxHQUFHLENBQUMsTUFB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SUFBSSxDQUFDLEtBQUssRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLEtBQUssR0FBRyxJQUFJLENBQUMsQ0FBQyxFQUFFO0FBQzdDO0lBQ0EsSUFBSSxTQUFTLENBQUMsR0FBRyxFQUFFLEVBQUUsT0FBTyxDQUFDLElBQUksRUFBRSxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUU7SUFDdkQsSUFBSSxTQUFTLENBQUMsR0FBRyxFQUFFLEVBQUUsT0FBTyxDQUFDLElBQUksRUFBRSxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUU7QUFDdkQ7QUFDQTtJQUNBLElBQUksT0FBTyxDQUFDLE1BQU0sRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFO0lBQ2pELElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsR0FBRyxPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRTtJQUN2RSxJQUFJLE1BQU0sQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsT0FBTyxDQUFDLEdBQUcsT0FBTyxFQUFFLEdBQUcsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDLEVBQUU7SUFDdkUsSUFBSSxRQUFRLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLE9BQU8sRUFBRSxHQUFHLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFO0lBQ3pFLElBQUksUUFBUSxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsR0FBRyxPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRTtJQUN6RSxJQUFJLFFBQVEsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsT0FBTyxDQUFDLEdBQUcsT0FBTyxFQUFFLEdBQUcsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDLEVBQUU7SUFDekUsSUFBSSxRQUFRLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLE9BQU8sRUFBRSxHQUFHLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFO0lBQ3pFLElBQUksUUFBUSxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsR0FBRyxPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRTtJQUN6RSxJQUFJLFFBQVEsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsT0FBTyxDQUFDLEdBQUcsT0FBTyxFQUFFLEdBQUcsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDLEVBQUU7SUFDekUsSUFBSSxRQUFRLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLE9BQU8sRUFBRSxHQUFHLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFO0lBQ3pFLElBQUksUUFBUSxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsR0FBRyxPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRTtJQUN6RSxJQUFJLE9BQU8sQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsT0FBTyxDQUFDLEdBQUcsT0FBTyxFQUFFLEdBQUcsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDLEVBQUU7SUFDeEUsSUFBSSxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLE9BQU8sRUFBRSxHQUFHLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFO0lBQ3hFLElBQUksT0FBTyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsR0FBRyxPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRTtJQUN4RSxJQUFJLFNBQVMsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsT0FBTyxDQUFDLEdBQUcsT0FBTyxFQUFFLEdBQUcsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDLEVBQUU7SUFDMUUsSUFBSSxTQUFTLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLE9BQU8sRUFBRSxHQUFHLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFO0lBQzFFLElBQUksU0FBUyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsR0FBRyxPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRTtJQUMxRSxJQUFJLFNBQVMsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsT0FBTyxDQUFDLEdBQUcsT0FBTyxFQUFFLEdBQUcsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDLEVBQUU7SUFDMUUsSUFBSSxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLE9BQU8sRUFBRSxHQUFHLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFO0lBQ3hFLElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsR0FBRyxPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRTtJQUN2RSxJQUFJLE9BQU8sQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsT0FBTyxDQUFDLEdBQUcsT0FBTyxFQUFFLEdBQUcsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDLEVBQUU7SUFDeEUsSUFBSSxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLE9BQU8sRUFBRSxHQUFHLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFO0lBQ3hFLElBQUksU0FBUyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsR0FBRyxPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRTtJQUMxRSxJQUFJLFNBQVMsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsT0FBTyxDQUFDLEdBQUcsT0FBTyxFQUFFLEdBQUcsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDLEVBQUU7SUFDMUUsSUFBSSxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsR0FBRyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRTtJQUM1RCxJQUFJLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFO0lBQzVELElBQUksT0FBTyxDQUFDLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFO0lBQ25ELElBQUksT0FBTyxDQUFDLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFO0FBQ25EO0lBQ0EsSUFBSSxPQUFPLENBQUMsT0FBTyxFQUFFLEVBQUUsT0FBTyxDQUFDLEdBQUcsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDLEVBQUU7SUFDbkQsSUFBSSxNQUFNLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLE9BQU8sRUFBRSxHQUFHLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFO0lBQ3ZFLElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsR0FBRyxPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRTtJQUN2RSxJQUFJLFFBQVEsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsT0FBTyxDQUFDLEdBQUcsT0FBTyxFQUFFLEdBQUcsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDLEVBQUU7SUFDekUsSUFBSSxRQUFRLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLE9BQU8sRUFBRSxHQUFHLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFO0lBQ3pFLElBQUksUUFBUSxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsR0FBRyxPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRTtJQUN6RSxJQUFJLFFBQVEsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsT0FBTyxDQUFDLEdBQUcsT0FBTyxFQUFFLEdBQUcsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDLEVBQUU7SUFDekUsSUFBSSxRQUFRLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLE9BQU8sRUFBRSxHQUFHLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFO0lBQ3pFLElBQUksUUFBUSxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsR0FBRyxPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRTtJQUN6RSxJQUFJLFFBQVEsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsT0FBTyxDQUFDLEdBQUcsT0FBTyxFQUFFLEdBQUcsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDLEVBQUU7SUFDekUsSUFBSSxRQUFRLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLE9BQU8sRUFBRSxHQUFHLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFO0lBQ3pFLElBQUksT0FBTyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsR0FBRyxPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRTtJQUN4RSxJQUFJLE9BQU8sQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsT0FBTyxDQUFDLEdBQUcsT0FBTyxFQUFFLEdBQUcsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDLEVBQUU7SUFDeEUsSUFBSSxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLE9BQU8sRUFBRSxHQUFHLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFO0lBQ3hFLElBQUksU0FBUyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsR0FBRyxPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRTtJQUMxRSxJQUFJLFNBQVMsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsT0FBTyxDQUFDLEdBQUcsT0FBTyxFQUFFLEdBQUcsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDLEVBQUU7SUFDMUUsSUFBSSxTQUFTLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLE9BQU8sRUFBRSxHQUFHLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFO0lBQzFFLElBQUksU0FBUyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsR0FBRyxPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRTtJQUMxRSxJQUFJLE9BQU8sQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsT0FBTyxDQUFDLEdBQUcsT0FBTyxFQUFFLEdBQUcsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDLEVBQUU7SUFDeEUsSUFBSSxNQUFNLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLE9BQU8sRUFBRSxHQUFHLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFO0lBQ3ZFLElBQUksT0FBTyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsR0FBRyxPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRTtJQUN4RSxJQUFJLE9BQU8sQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsT0FBTyxDQUFDLEdBQUcsT0FBTyxFQUFF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QTtJQUNBO0lBQ0E7SUFDQTtJQUNBLFFBQVEsSUFBSSxPQUFPLEdBQUcsSUFBSSxXQUFXLEVBQUUsR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUM7SUFDdEQsUUFBUSxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDO0lBQ3ZDLFFBQVEsSUFBSSxJQUFJLENBQUMsU0FBUyxHQUFHLEdBQUcsR0FBRyxJQUFJLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxTQUFTLEdBQUcsR0FBRyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUM7SUFDM0YsUUFBUSxJQUFJLElBQUksQ0FBQyxZQUFZO0lBQzdCLFlBQVksTUFBTSxJQUFJLEtBQUssQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO0lBQ3RELFFBQVEsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQzFELFFBQVEsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUMsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDaEY7SUFDQSxRQUFRLE1BQU0sWUFBWSxHQUFHLEVBQUUsQ0FBQztJQUNoQyxRQUFRLEtBQUssSUFBSSxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUMsRUFBRSxRQUFRLEVBQUUsQ0FBQyxFQUFFLEVBQUUsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckYsUUFBUSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7QUFDNUI7SUFDQSxRQUFRLElBQUksQ0FBQyxHQUFHLFNBQVMsQ0FBQztJQUMxQixRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO0lBQ3BDLFFBQVEsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUNo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RyxFQUFFO0lBQ3hCLFNBQVMsQ0FBQyxDQUFDO0lBQ1gsS0FBSztBQUNMO0lBQ0EsSUFBSSxNQUFNLE9BQU8sR0FBRztJQUNwQixRQUFRLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQztJQUMxQixRQUFRLE1BQU0sSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQzNCLFFBQVEsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDaEQsS0FBSztBQUNMO0lBQ0EsSUFBSSxNQUFNLFVBQVUsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFO0lBQzdCLFFBQVEsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQzFCLFFBQVEsTUFBTSxTQUFTLEdBQUcsSUFBSSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDNUMsUUFBUSxNQUFNLFVBQVUsR0FBRyxJQUFJLFFBQVEsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDMUQ7SUFDQSxRQUFRLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztBQUN6QztJQUNBLFFBQVEsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUN6QyxLQUFLO0FBQ0w7SUFDQSxJQUFJLE1BQU0sVUFBVSxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUU7SUFDN0IsUUFBUSxNQUFNLElBQUksR0FBRyxJQUFJLENBQUM7QUFDMUI7SUFDQSxRQUFRLE1BQU0sU0FBUyxHQUFHLElBQUksVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVDLFFBQVEsTUFBTSxVQUFVLEdBQUcsSUFBSSxRQUFRLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQzFEO0lBQ0EsUUFBUSxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDMUM7SUFDQSxRQUFRLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDekMsS0FBSztBQUNMO0FBQ0E7SUFDQSxJQUFJLE1BQU0sVUFBVSxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUU7SUFDN0IsUUFBUSxNQUFNLElBQUksR0FBRyxJQUFJLENBQUM7QUFDMUI7SUFDQSxRQUFRLE1BQU0sU0FBUyxHQUFHLElBQUksVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVDLFFBQVEsTUFBTSxVQUFVLEdBQUcsSUFBSSxRQUFRLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQzFEO0lBQ0EsUUFBUSxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDLEdBQUcsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3RELFFBQVEsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsV0FBVyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7QUFDcEU7SUFDQSxRQUFRLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDekMsS0FBSztBQUNMO0lBQ0EsSUFBSSxNQUFNLFNBQVMsQ0FBQyxHQUFHLEVBQUU7SUFDekIsUUFBUSxNQUFNLElBQUksR0FBRyxJQUFJLENBQUM7SUFDMUIsUUFBUSxNQUFNLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQzFDO0lBQ0EsUUFBUSxNQUFNLElBQUksR0FBRyxJQUFJLFdBQVcsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDL0M7SUFDQSxRQUFRLE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZCLEtBQUs7QUFDTDtJQUNBLElBQUksTUFBTSxTQUFTLENBQUMsR0FBRyxFQUFFO0lBQ3pCLFFBQVEsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQzFCLFFBQVEsTUFBTSxDQUFDLEdB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Q0QsV0FBUyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3pDLEtBQUs7QUFDTDtBQUNBO0lBQ0EsSUFBSSxNQUFNLFNBQVMsQ0FBQyxHQUFHLEVBQUU7SUFDekIsUUFBUSxNQUFNLElBQUksR0FBRyxJQUFJLENBQUM7SUFDMUIsUUFBUSxNQUFNLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQzFDO0lBQ0EsUUFBUSxNQUFNLElBQUksR0FBRyxJQUFJLFdBQVcsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDL0M7SUFDQSxRQUFRLE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZCLEtBQUs7QUFDTDtJQUNBLElBQUksTUFBTSxTQUFTLENBQUMsR0FBRyxFQUFFO0lBQ3pCLFFBQVEsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQzFCLFFBQVEsTUFBTSxDQUFDLEdBQUcsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztBQUMxQztJQUNBLFFBQVEsTUFBTSxJQUFJLEdBQUcsSUFBSSxRQUFRLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQzVDO0lBQ0EsUUFBUSxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3hDLEtBQUs7QUFDTDtJQUNBLElBQUksTUFBTSxTQUFTLENBQUMsR0FBRyxFQUFFO0lBQ3pCLFFBQVEsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQzFCLFFBQVEsTUFBTSxDQUFDLEdBQUcsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztBQUMxQztJQUNBLFFBQVEsTUFBTSxJQUFJLEdBQUcsSUFBSSxXQUFXLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQy9DO0lBQ0EsUUFBUSxPQUFPLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxXQUFXLEdB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SUFDQTtJQUNBO0lBQ08sTUFBTSxLQUFLLG1CQUFtQixJQUFJLFVBQVUsQ0FBQztJQUNwRCxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUU7SUFDeEQsSUFBSSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQ3hELElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztJQUN4RCxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDeEQsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ3hELElBQUksQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQztJQUN4RCxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDeEQsSUFBSSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ3hELElBQUksQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUN4RCxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDeEQsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFO0lBQ3hELElBQUksRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztJQUN4RDtJQUNBLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztJQUN4RCxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDeEQsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ3hELElBQUksQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVB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QUFRLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2hDLEtBQUs7SUFDTCxJQUFJLE9BQU8sQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDcEIsQ0FBQztJQUNELE1BQU0sS0FBSyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksSUFBSSxJQUFJLE1BQU0sQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDcEU7SUFDQSxNQUFNLEtBQUssR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDcEMsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ3ZEO0lBQ0EsTUFBTSxNQUFNLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hELE1BQU0sTUFBTSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUN4RDtJQUNBLE1BQU0sTUFBTSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMvRCxNQUFNLE1BQU0sR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDL0Q7SUFDQSxNQUFNLE9BQU8sR0FBRyxDQUFDLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzdCLE1BQU0sT0FBTyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDN0I7SUFDQSxNQUFNLE1BQU0sR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEQsTUFBTSxNQUFNLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hEO0lBQ0EsTUFBTSxNQUFNLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQy9ELE1BQU0sTUFBTSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMvRDtJQUNBO0lBQ0EsU0FBUyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFO0lBQzdCLElBQUksTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUN0QyxJQUFJLE9BQU8sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7SUFDaEUsQ0FBQztJQUNEO0lBQ0EsTUFBTSxLQUFLLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDLEVBQUUsS0FBSyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUNuRSxNQUFNLEtBQUssR0FBRyxDQUFDLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRyxHQUFHLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzlFLE1BQU0sS0FBSyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxLQUFLLENBQUMsRUFBRSxLQUFLLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUNwRixNQUFNLEtBQUssR0FBRyxDQUFDLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHLEdBQUcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdkYsTUFBTSxLQUFLLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxLQUFLLENBQUMsRUFBRSxLQUFLLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDckcsTUFBTSxLQUFLLEdBQUcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHLEdBQUcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7SUFHaEc7SUFDQSxNQUFNLEdBQUcsR0FBRztJQUNaLElBQUksT0FBTyxFQUFFLEtBQUssRUFBRSxLQUFLO0lBQ3pCLElBQUksS0FBSyxFQUFFLEtBQUs7SUFDaEIsSUFBSSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNO0lBQ2xDLElBQUksT0FBTyxFQUFFLE9BQU87SUFDcEIsSUFBSSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNO0lBQ2xDLElBQUksR0FBRyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSztJQUNqRCxDQUFDLENBQUM7QUFDRixnQkFBZSxHQUFHOztJQ2hFbEI7SUFDQTtJQUNBO0lBQ0E7SUFJQTtJQUNBO0lBQ0EsTUFBTSxNQUFNLG1CQUFtQixJQUFJLFdBQVcsQ0FBQztJQUMvQyxJQUFJLFVBQVUsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxVQUFVO0lBQ2xHLElBQUksVUFBVSxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLFVBQVU7SUFDbEcsQ0FBQyxDQUFDLENBQUM7SUFDSDtJQUNBLE1BQU0sSUFBSSxtQkFBbUIsSUFBSSxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDakQ7SUFDQSxTQUFTLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRTtJQUNqQztJQUNBLElBQUksTUFBTSxFQUFFLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3ZDLElBQUksSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDL0MsSUFBSSxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUMvQyxJQUFJLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQy9DLElBQUksSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDL0M7SUFDQSxJQUFJLElBQUksRUFBRSxHQUFHQyxLQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDbkMsSUFBSSxFQUFFLEdBQUdBLEtBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDbkMsSUFBSSxFQUFFLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUNoQjtJQUNBLElBQUksQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUU7SUFDaEQsSUFBSSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFQSxLQUFHLENBQUMsT0FBTyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUVBLEtBQUcsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDeEU7SUFDQSxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsR0FBR0EsS0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRTtJQUNqRDtJQUNBLElBQUksQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUU7SUFDaEQsSUFBSSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFQSxLQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFQSxLQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUM5RSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDL0MsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO0lBQy9DLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsSUFBSSxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUMvQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUNELFNBQVMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFO0lBQ2pDO0lBQ0EsSUFBSSxNQUFNLEVBQUUsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDdkMsSUFBSSxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUMvQyxJQUFJLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQy9DLElBQUksSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDL0MsSUFBSSxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUMvQztJQUNBLElBQUksSUFBSSxFQUFFLEdBQUdBLEtBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNuQyxJQUFJLEVBQUUsR0FBR0EsS0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNuQyxJQUFJLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ2hCO0lBQ0EsSUFBSSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRTtJQUNoRCxJQUFJLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUVBLEtBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUVBLEtBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQzlFO0lBQ0EsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUdBLEtBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUU7SUFDakQ7SUFDQSxJQUFJLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFO0lBQ2hELElBQUksQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRUEsS0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRUEsS0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDOUUsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO0lBQy9DLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsSUFBSSxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUMvQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDL0MsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO0lBQy9DLENBQUM7SUFDTSxNQUFNLE9BQU8sU0FBUyxLQUFLLENBQUM7SUFDbkMsSUFBSSxXQUFXLENBQUMsSUFBSSxHQUFHLEVBQUUsRUFBRTtJQUMzQixRQUFRLEtBQUssQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLEtBQUssS0FBSyxTQUFTLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDakY7SUFDQSxRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqQyxRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqQyxRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqQyxRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqQyxRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqQyxRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqQyxRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqQyxRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqQyxRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqQyxRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqQyxRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNsQyxRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNsQyxRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNsQyxRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNsQyxRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNsQyxRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNsQyxRQUFRLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ3pELFFBQVEsSUFBSSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsU0FBUyxJQUFJLFNBQVMsSUFBSSxDQUFDLENBQUMsSUFBSSxJQUFJLElBQUksRUFBRSxDQUFDLElBQUksSUFBSSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ3BGLFFBQVEsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFO0lBQ3ZCLFlBQVksTUFBTSxJQUFJLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNqRCxZQUFZLElBQUksQ0FBQyxHQUFHLElBQUksWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzlDLFlBQVksSUFBSSxDQUFDLEdBQUcsSUFBSSxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDOUMsWUFBWSxJQUFJLENBQUMsR0FBRyxJQUFJLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM5QyxZQUFZLElBQUksQ0FBQyxHQUFHLElBQUksWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzlDLFNBQVM7SUFDVCxRQUFRLElBQUksSUFBSSxDQUFDLGVBQWUsRUFBRTtJQUNsQyxZQUFZLE1BQU0sSUFBSSxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUM7SUFDNUQsWUFBWSxJQUFJLENBQUMsR0FBRyxJQUFJLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM5QyxZQUFZLElBQUksQ0FBQyxHQUFHLElBQUksWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzlDLFlBQVksSUFBSSxDQUFDLEdBQUcsSUFBSSxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDOUMsWUFBWSxJQUFJLENBQUMsR0FBRyxJQUFJLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM5QyxTQUFTO0lBQ1QsUUFBUSxJQUFJLElBQUksQ0FBQyxHQUFHLEVBQUU7SUFDdEI7SUFDQSxZQUFZLE1BQU0sR0FBRyxHQUFHLElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN0RCxZQUFZLEdBQUcsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3ZDLFlBQVksSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM3QixTQUFTO0lBQ1QsS0FBSztJQUNMO0lBQ0EsSUFBSSxHQUFHLEdBQUc7SUFDVixRQUFRLElBQUksRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUM7SUFDdEcsUUFBUSxPQUFPLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDaEcsS0FBSztJQUNMO0lBQ0EsSUFBSSxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFO0lBQ3hGLFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0lBQzNCLFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0lBQzNCLFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0lBQzNCLFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0lBQzNCLFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0lBQzNCLFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0lBQzNCLFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0lBQzNCLFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0lBQzNCLFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0lBQzNCLFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0lBQzNCLFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0lBQzNCLFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0lBQzNCLFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0lBQzNCLFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0lBQzNCLFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0lBQzNCLFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0lBQzNCLEtBQUs7SUFDTCxJQUFJLFFBQVEsQ0FBQyxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRTtJQUNsQyxRQUFRLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELFFBQVEsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDN0IsUUFBUSxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFHQSxLQUFHLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUN4RCxRQUFRLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ2pDLFFBQVEsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDakM7SUFDQSxRQUFRLElBQUksTUFBTSxFQUFFO0lBQ3BCLFlBQVksSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2pDLFlBQVksSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2pDLFNBQVM7SUFDVCxRQUFRLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNsQixRQUFRLE1BQU0sQ0FBQyxHQUFHLEtBQUssQ0FBQztJQUN4QixRQUFRLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDckMsWUFBWSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdkQsWUFBWSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdkQsWUFBWSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdkQsWUFBWSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdkQsWUFBWSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDeEQsWUFBWSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDeEQsWUFBWSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDeEQsWUFBWSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDeEQsWUFBWSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDeEQsWUFBWSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDeEQsWUFBWSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDeEQsWUFBWSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDeEQsWUFBWSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdkQsWUFBWSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdkQsWUFBWSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdkQsWUFBWSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdkQsU0FBUztJQUNULFFBQVEsSUFBSSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZDLFFBQVEsSUFBSSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZDLFFBQVEsSUFBSSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZDLFFBQVEsSUFBSSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZDLFFBQVEsSUFBSSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZDLFFBQVEsSUFBSSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZDLFFBQVEsSUFBSSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZDLFFBQVEsSUFBSSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZDLFFBQVEsSUFBSSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZDLFFBQVEsSUFBSSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZDLFFBQVEsSUFBSSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3hDLFFBQVEsSUFBSSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3hDLFFBQVEsSUFBSSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3hDLFFBQVEsSUFBSSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3hDLFFBQVEsSUFBSSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3hDLFFBQVEsSUFBSSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3hDLFFBQVEsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNyQixLQUFLO0lBQ0wsSUFBSSxPQUFPLEdBQUc7SUFDZCxRQUFRLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDO0lBQzlCLFFBQVEsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDOUIsUUFBUSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMs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LEdBQUcsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDckQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxHQUFHLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNyRCxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3JELElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksR0FBRyxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDdkQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxHQUFHLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUN2RCxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3ZELElBQUksTUFBTSxLQUFLLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUMxQixJQUFJLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDO0lBQzVDLElBQUksTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLENBQUM7SUFDNUMsSUFBSSxHQUFHLENBQUMsTUFBTSxHQUFHLEdBQUcsR0FBRyxHQUFHLENBQUM7SUFDM0IsSUFBSSxHQUFHLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQztJQUNsQixJQUFJLE9BQU8sR0FBRyxDQUFDO0lBQ2YsQ0FBQztBQUNEO0lBQ08sU0FBUyxhQUFhLENBQUMsSUFBSSxDQUFDO0lBQ25DO0lBQ0EsSUFBSSxNQUFNLEdBQUcsR0FBRyxJQUFJLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNwQyxJQUFJLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDekMsSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN6QixJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqRCxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqRCxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqRCxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqRCxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqRCxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLElBQUksS0FBSyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNuRCxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLElBQUksS0FBSyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNuRCxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLElBQUksS0FBSyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNuRCxJQUFJLEtBQUssQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDO0lBQ3pCLElBQUksS0FBSyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQztJQUNyQyxJQUFJLE9BQU8sR0FBRyxDQUFDO0lBQ2YsQ0FBQztBQUNEO0lBQ08sZUFBZUMsV0FBUyxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUU7SUFDN0QsSUFBSSxJQUFJLEtBQUssQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLE9BQU8sS0FBSyxDQUFDO0lBQzNDLElBQUksSUFBSSxLQUFLLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxPQUFPLEtBQUssQ0FBQztJQUM1QyxJQUFJLElBQUksS0FBSyxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsT0FBTyxLQUFLLENBQUM7SUFDM0MsSUFBSSxJQUFJLEtBQUssQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLE9BQU8sS0FBSyxDQUFDO0lBQzVDO0lBQ0EsSUFBSSxNQUFNLEdBQUcsR0FBRyxNQUFNLEtBQUssQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUMxRSxJQUFJLE9BQU8sR0FBRyxDQUFDO0lBQ2YsQ0FBQztBQUNEO0FBQ0E7SUFDTyxTQUFTLFVBQVUsR0FBRztJQUM3QixJQUF5QjtJQUN6QixRQUFRLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxrQ0FBa0MsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNyRSxLQVNLO0lBQ0wsQ0FBQztBQUNEO0lBQ08sU0FBUyxjQUFjLENBQUMsQ0FBQyxFQUFFO0lBQ2xDLElBQUksSUFBSSxLQUFLLEdBQUcsSUFBSSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbEMsSUFBeUI7SUFDekIsUUFBUSxVQUFVLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNqRCxLQUVLO0lBQ0wsSUFBSSxPQUFPLEtBQUssQ0FBQztJQUNqQixDQUFDO0FBQ0Q7SUFDTyxlQUFlLFlBQVksQ0FBQyxJQUFJLEVBQUU7SUFDekMsSUFBeUI7SUFDekIsUUFBUSxNQUFNLE1BQU0sR0FBRyxNQUFNLFVBQVUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3JGLFFBQVEsT0FBTyxJQUFJLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN0QyxLQUVLO0lBQ0wsQ0FBQztBQUNEO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDTyxTQUFTLFlBQVksQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFO0lBQzNDLElBQUksT0FBTyxJQUFJLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQztJQUM5RCxDQUFDO0FBQ0Q7SUFDTyxlQUFlLFlBQVksQ0FBQyxPQUFPLEVBQUU7SUFDNUM7SUFDQSxJQUFJLE9BQU8sQ0FBQyxPQUFPLEVBQUU7SUFDckIsUUFBUSxPQUFPLEdBQUcsTUFBTSxVQUFVLEVBQUUsQ0FBQztJQUNyQyxLQUFLO0lBQ0wsSUFBSSxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3RDLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN0QyxJQUFJLE1BQU0sR0FBRyxHQUFHLElBQUksV0FBVyxFQUFFLENBQUM7SUFDbEMsSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUN2QyxJQUFJLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztBQUNqQztJQUNBLElBQUksTUFBTSxJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQ3BCLElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtJQUMxQixRQUFRLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxZQUFZLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMxQyxLQUFLO0lBQ0wsSUFBSSxNQUFNLEdBQUcsR0FBRyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNqQyxJQUFJLE9BQU8sR0FBRyxDQUFDO0lBQ2YsQ0FBQztBQUNEO0lBQ08sZUFBZSxtQkFBbUIsQ0FBQyxVQUFVLEVBQUUsZ0JBQWdCLEVBQUU7SUFDeEUsSUFBSSxJQUFJLGdCQUFnQixDQUFDO0lBQ3pCLElBQUksSUFBSSxnQkFBZ0IsQ0FBQztJQUN6QixJQUFJLElBQUksZ0JBQWdCLENBQUMsRUFBRSxFQUFFO0lBQzdCLFFBQVEsZ0JBQWdCLEdBQUcsQ0FBQyxDQUFDLElBQUksZ0JBQWdCLE1BQU0sQ0FBQyxDQUFDO0lBQ3pELFFBQVEsZ0JBQWdCLEdBQUcsQ0FBQyxDQUFDO0lBQzdCLEtBQUssTUFBTTtJQUNYLFFBQVEsZ0JBQWdCLEdBQUcsV0FBVyxDQUFDO0lBQ3ZDLFFBQVEsZ0JBQWdCLEdBQUcsQ0FBQyxDQUFDLEtBQUssZ0JBQWdCLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzlELEtBQUs7QUFDTDtJQUNBLElBQUksSUFBSSxPQUFPLEdBQUcsVUFBVSxDQUFDO0lBQzdCLElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLGdCQUFnQixFQUFFLENBQUMsRUFBRSxFQUFFO0lBQzNDLFFBQVEsS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLGdCQUFnQixFQUFFLENBQUMsRUFBRSxFQUFFO0lBQy9DLFlBQVksT0FBTyxHQUFHLE1BQU0sWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ2xELFNBQVM7SUFDVCxLQUFLO0FBQ0w7SUFDQSxJQUFJLE1BQU0sUUFBUSxHQUFHLElBQUksUUFBUSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLFVBQVUsRUFBRSxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDMUYsSUFBSSxNQUFNLElBQUksR0FBRyxFQUFFLENBQUM7SUFDcEIsSUFBSSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQzVCLFFBQVEsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNqRCxLQUFLO0FBQ0w7SUFDQSxJQUFJLE1BQU0sR0FBRyxHQUFHLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ2pDO0lBQ0EsSUFBSSxPQUFPLEdBQUcsQ0FBQztJQUNmLENBQUM7QUFDRDtJQUNPLFNBQVMsYUFBYSxDQUFDLENBQUMsRUFBRTtJQUNqQyxJQUFJLElBQUksQ0FBQyxZQUFZLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUMxQyxJQUFJLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVDLElBQUksT0FBTyxJQUFJLFVBQVUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsRUFBRTtJQUNuRSxRQUFRLE9BQU8sUUFBUSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUMvQixLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ1IsQ0FBQztBQUNEO0lBQ08sU0FBUyxhQUFhLENBQUMsU0FBUyxFQUFFO0lBQ3pDLElBQUksT0FBTyxLQUFLLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFNBQVMsSUFBSSxFQUFFO0lBQzlELFFBQVEsT0FBTyxDQUFDLEdBQUcsR0FBRyxDQUFDLElBQUksR0FBRyxJQUFJLEVBQUUsUUFBUSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVELEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNoQixDQUFDO0FBQ0Q7SUFDTyxTQUFTLHlCQUF5QixDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUU7SUFDakQsSUFBSSxJQUFJLENBQUMsWUFBWSxVQUFVLEdBQUc7SUFDbEMsUUFBUSxPQUFPLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDOUIsS0FBSyxNQUFNLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRTtJQUNqQyxRQUFRLE9BQU8sQ0FBQyxDQUFDLEdBQUcsQ0FBQyx5QkFBeUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDL0QsS0FBSyxNQUFNLElBQUksT0FBTyxDQUFDLElBQUksUUFBUSxFQUFFO0lBQ3JDLFFBQVEsTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUFDO0lBQ3ZCLFFBQVEsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNwQyxRQUFRLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLEtBQUs7SUFDN0IsWUFBWSxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcseUJBQXlCLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3pELFNBQVMsQ0FBQyxDQUFDO0lBQ1gsUUFBUSxPQUFPLEdBQUcsQ0FBQztJQUNuQixLQUFLLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksUUFBUSxLQUFLLENBQUMsQ0FBQyxFQUFFLEtBQUssU0FBUyxHQUFHO0lBQy9ELFFBQVEsT0FBTyxDQUFDLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzlCLEtBQUssTUFBTTtJQUNYLFFBQVEsT0FBTyxDQUFDLENBQUM7SUFDakIsS0FBSztJQUNMOztJQ3BRTyxNQUFNLG1CQUFtQixHQUFHLENBQUMsQ0FBQztBQUNyQztJQUNPLE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxDQUFDO0lBQzlCLE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxDQUFDO0lBQzVCLE1BQU0sa0JBQWtCLEdBQUcsRUFBRTs7SUNKcEM7SUFDQTtBQUNBO0lBQ0E7QUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0FBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtBQUNBO0lBQ0E7SUFDQTtJQUNBO0FBQ0E7SUFDQTtJQUNPLE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxDQUFDO0FBSWxDO0lBQ0E7SUFDTyxNQUFNLGlCQUFpQixHQUFHLEVBQUUsQ0FBQztBQUNwQztJQUNPLE1BQU0sc0JBQXNCLEdBQUcsQ0FBQyxDQUFDO0lBQ2pDLE1BQU0seUJBQXlCLEdBQUcsQ0FBQyxDQUFDO0lBQ3BDLE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxDQUFDO0lBQ2hDLE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxDQUFDO0lBQ2hDLE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxDQUFDO0lBQ2hDLE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxDQUFDO0lBQzdCLE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxDQUFDO0lBQzdCLE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxDQUFDO0lBQzdCLE1BQU0sa0JBQWtCLEdBQUcsRUFBRSxDQUFDO0lBQzlCLE1BQU0sa0JBQWtCLEdBQUcsRUFBRSxDQUFDO0lBQzlCLE1BQU0sc0JBQXNCLEdBQUcsRUFBRSxDQUFDO0lBQ2xDLE1BQU0sc0JBQXNCLEdBQUcsRUFBRSxDQUFDO0lBQ2xDLE1BQU0sc0JBQXNCLEdBQUcsRUFBRSxDQUFDO0lBQ2xDLE1BQU0sd0JBQXdCLEdBQUcsRUFBRSxDQUFDO0lBQ3BDLE1BQU0sb0JBQW9CLEdBQUcsRUFBRSxDQUFDO0lBQ2hDLE1BQU0sa0JBQWtCLEdBQUcsRUFBRTs7SUMzQ3BDO0lBQ0E7QUFDQTtJQUNBO0FBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtBQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7QUFDQTtJQUNBO0lBQ0E7SUFDQTtBQW9DQTtJQUNPLGVBQWUsV0FBVyxDQUFDLEVBQUUsRUFBRSxJQUFJLEVBQUU7QUFDNUM7SUFDQTtJQUNBO0lBQ0EsSUFBSSxNQUFNQyxpQkFBOEIsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDaEQsSUFBSSxNQUFNLEVBQUUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDM0IsSUFBSSxNQUFNQyxlQUE0QixDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQzNDO0lBQ0E7SUFDQTtBQUNBO0lBQ0EsSUFBSSxNQUFNLEtBQUssR0FBRyxNQUFNQyxhQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3pDO0lBQ0EsSUFBSSxNQUFNRixpQkFBOEIsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDaEQsSUFBSSxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQzNCLElBQUksTUFBTSxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUN4RTtJQUNBLElBQUksTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUMzQixJQUFJLE1BQU0sR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDeEU7SUFDQSxJQUFJLE1BQU0sRUFBRSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM3QixJQUFJLE1BQU1HLFdBQXdCLENBQUMsRUFBRSxFQUFFLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQztJQUNwRCxJQUFJLE1BQU0sRUFBRSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM3QixJQUFJLE1BQU1BLFdBQXdCLENBQUMsRUFBRSxFQUFFLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQztJQUNwRCxJQUFJLE1BQU0sRUFBRSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDcEMsSUFBSSxNQUFNLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3RDLElBQUksTUFBTSxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUN6QyxJQUFJLE1BQU0sT0FBTyxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzlDLElBQUksTUFBTSxPQUFPLENBQUMsRUFBRSxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDN0MsSUFBSSxNQUFNLE9BQU8sQ0FBQyxFQUFFLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUM3QyxJQUFJLE1BQU0sT0FBTyxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzlDLElBQUksTUFBTSxPQUFPLENBQUMsRUFBRSxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDOUMsSUFBSSxNQUFNLE9BQU8sQ0FBQyxFQUFFLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztBQUM5QztJQUNBLElBQUksTUFBTUYsZUFBNEIsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUMzQztBQUNBO0lBQ0EsQ0FBQztBQTBGRDtJQUNBLGVBQWUsT0FBTyxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFO0lBQ3JDLElBQUksTUFBTSxJQUFJLEdBQUcsSUFBSSxVQUFVLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2pELElBQUksS0FBSyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNsQyxJQUFJLE1BQU0sRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN6QixDQUFDO0FBQ0Q7SUFDQSxlQUFlLE9BQU8sQ0FBQyxFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRTtJQUNyQyxJQUFJLE1BQU0sSUFBSSxHQUFHLElBQUksVUFBVSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNqRCxJQUFJLEtBQUssQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbEMsSUFBSSxNQUFNLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDekIsQ0FBQztBQUNEO0lBQ0EsZUFBZSxNQUFNLENBQUMsRUFBRSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUU7SUFDM0MsSUFBSSxNQUFNLElBQUksR0FBRyxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2hELElBQUksTUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzdDLElBQUksT0FBTyxRQUFRLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEdBQUcsR0FBRyxDQUFDO0lBQ25ELENBQUM7QUFDRDtJQUNBLGVBQWUsTUFBTSxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFO0lBQzNDLElBQUksTUFBTSxJQUFJLEdBQUcsTUFBTSxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNoRCxJQUFJLE1BQU0sR0FBRyxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM3QyxJQUFJLE9BQU8sUUFBUSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEdBQUcsQ0FBQztJQUNuRCxDQUFDO0FBQ0Q7QUFDQTtJQUNPLGVBQWVHLFlBQVUsQ0FBQyxFQUFFLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUU7SUFDbEU7SUFDQTtJQUNBLElBQUksTUFBTUMsd0JBQW1DLENBQUMsRUFBRSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMvRCxJQUFJLE1BQU0sVUFBVSxHQUFHLE1BQU0sRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQzVDLElBQUksTUFBTUMsZ0JBQTJCLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDMUM7SUFDQSxJQUFJLElBQUksVUFBVSxLQUFLLG1CQUFtQixFQUFFO0lBQzVDLFFBQVEsT0FBTyxNQUFNLGlCQUFpQixDQUFDLEVBQUUsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3hFLEtBQUssTUFBTSxJQUFJLFVBQVUsS0FBSyxpQkFBaUIsRUFBRTtJQUNqRCxRQUFRLE9BQU8sTUFBTSxlQUFlLENBQUMsRUFBRSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDdEUsS0FBSyxNQUFNLElBQUksVUFBVSxLQUFLLGtCQUFrQixFQUFFO0lBQ2xELFFBQVEsT0FBTyxNQUFNLGdCQUFnQixDQUFDLEVBQUUsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3ZFLEtBQUssTUFBTTtJQUNYLFFBQVEsTUFBTSxJQUFJLEtBQUssQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO0lBQ3BELEtBQUs7SUFDTCxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7SUFDQSxlQUFlLGlCQUFpQixDQUFDLEVBQUUsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRTtJQUNsRSxJQUFJLE1BQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQztBQUNwQjtJQUNBLElBQUksSUFBSSxDQUFDLFFBQVEsR0FBRyxTQUFTLENBQUM7QUFDOUI7SUFDQTtJQUNBO0lBQ0EsSUFBSSxNQUFNRCx3QkFBbUMsQ0FBQyxFQUFFLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQy9ELElBQUksTUFBTSxHQUFHLEdBQUcsTUFBTSxFQUFFLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDckMsSUFBSSxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQztJQUNuQixJQUFJLElBQUksQ0FBQyxDQUFDLEdBQUcsTUFBTUUsWUFBdUIsQ0FBQyxFQUFFLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDcEQ7SUFDQSxJQUFJLE1BQU0sR0FBRyxHQUFHLE1BQU0sRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQ3JDLElBQUksSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUM7SUFDbkIsSUFBSSxJQUFJLENBQUMsQ0FBQyxHQUFHLE1BQU1BLFlBQXVCLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3BELElBQUksSUFBSSxDQUFDLEtBQUssR0FBRyxNQUFNTCxhQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUNqRCxJQUFJLElBQUksQ0FBQyxLQUFLLEdBQUcsTUFBTSxFQUFFLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDdEMsSUFBSSxJQUFJLENBQUMsT0FBTyxHQUFHLE1BQU0sRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQ3hDLElBQUksSUFBSSxDQUFDLFVBQVUsR0FBRyxNQUFNLEVBQUUsQ0FBQyxTQUFTLEVBQUUsQ0FBQztJQUMzQyxJQUFJLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUN2QyxJQUFJLElBQUksQ0FBQyxVQUFVLEdBQUcsTUFBTSxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDN0QsSUFBSSxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sTUFBTSxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQzVELElBQUksSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLE1BQU0sQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQztJQUM1RCxJQUFJLElBQUksQ0FBQyxVQUFVLEdBQUcsTUFBTSxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDN0QsSUFBSSxJQUFJLENBQUMsVUFBVSxHQUFHLE1BQU0sTUFBTSxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQzdELElBQUksSUFBSSxDQUFDLFVBQVUsR0FBRyxNQUFNLE1BQU0sQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQztJQUM3RCxJQUFJLE1BQU1JLGdCQUEyQixDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQzFDO0lBQ0EsSUFBSSxPQUFPLElBQUksQ0FBQztBQUNoQjtJQUNBLENBQUM7QUFDRDtJQUNBLGVBQWUsZUFBZSxDQUFDLEVBQUUsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRTtJQUNoRSxJQUFJLE1BQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQztBQUNwQjtJQUNBLElBQUksSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUM7QUFDNUI7SUFDQTtJQUNBO0lBQ0EsSUFBSSxNQUFNRCx3QkFBbUMsQ0FBQyxFQUFFLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQy9ELElBQUksTUFBTSxHQUFHLEdBQUcsTUFBTSxFQUFFLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDckMsSUFBSSxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQztJQUNuQixJQUFJLElBQUksQ0FBQyxDQUFDLEdBQUcsTUFBTUUsWUFBdUIsQ0FBQyxFQUFFLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDcEQ7SUFDQSxJQUFJLE1BQU0sR0FBRyxHQUFHLE1BQU0sRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQ3JDLElBQUksSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUM7SUFDbkIsSUFBSSxJQUFJLENBQUMsQ0FBQyxHQUFHLE1BQU1BLFlBQXVCLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3BELElBQUksSUFBSSxDQUFDLEtBQUssR0FBRyxNQUFNTCxhQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUNqRCxJQUFJLElBQUksQ0FBQyxLQUFLLEdBQUcsTUFBTSxFQUFFLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDdEMsSUFBSSxJQUFJLENBQUMsT0FBTyxHQUFHLE1BQU0sRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQ3hDLElBQUksSUFBSSxDQUFDLFVBQVUsR0FBRyxNQUFNLEVBQUUsQ0FBQyxTQUFTLEVBQUUsQ0FBQztJQUMzQyxJQUFJLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUN2QyxJQUFJLElBQUksQ0FBQyxVQUFVLEdBQUcsTUFBTSxFQUFFLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDM0MsSUFBSSxJQUFJLENBQUMsWUFBWSxHQUFHLE1BQU0sRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQzdDLElBQUksSUFBSSxDQUFDLEVBQUUsR0FBRyxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDakMsSUFBSSxJQUFJLENBQUMsRUFBRSxHQUFHLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNqQztJQUNBLElBQUksSUFBSSxDQUFDLEVBQUUsR0FBRyxNQUFNLE1BQU0sQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQztJQUNyRCxJQUFJLElBQUksQ0FBQyxFQUFFLEdBQUcsTUFBTSxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDckQsSUFBSSxJQUFJLENBQUMsRUFBRSxHQUFHLE1BQU0sTUFBTSxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ3JELElBQUksSUFBSSxDQUFDLEVBQUUsR0FBRyxNQUFNLE1BQU0sQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQztJQUNyRCxJQUFJLElBQUksQ0FBQyxFQUFFLEdBQUcsTUFBTSxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDckQsSUFBSSxJQUFJLENBQUMsRUFBRSxHQUFHLE1BQU0sTUFBTSxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ3JELElBQUksSUFBSSxDQUFDLEVBQUUsR0FBRyxNQUFNLE1BQU0sQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQztJQUNyRCxJQUFJLElBQUksQ0FBQyxFQUFFLEdBQUcsTUFBTSxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDckQsSUFBSSxJQUFJLENBQUMsR0FBRyxHQUFHLE1BQU0sTUFBTSxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBQ3REO0lBQ0EsSUFBSSxNQUFNSSxnQkFBMkIsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUMxQztJQUNBLElBQUksT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztBQUNEO0lBQ0EsZUFBZSxnQkFBZ0IsQ0FBQyxFQUFFLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUU7SUFDakUsSUFBSSxNQUFNLElBQUksR0FBRyxFQUFFLENBQUM7QUFDcEI7SUFDQSxJQUFJLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO0lBQzdCLElBQUksSUFBSSxDQUFDLFVBQVUsR0FBRyxrQkFBa0IsQ0FBQztBQUN6QztJQUNBLElBQUksTUFBTUQsd0JBQW1DLENBQUMsRUFBRSxFQUFFLFFBQVEsRUFBRSxzQkFBc0IsQ0FBQyxDQUFDO0lBQ3BGLElBQUksTUFBTSxHQUFHLEdBQUcsTUFBTSxFQUFFLENBQUMsU0FBUyxFQUFFLENBQUM7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Q0E7SUFDQSxJQUFJLE1BQU1ELHdCQUFtQyxDQUFDLEVBQUUsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDL0QsSUFBSSxJQUFJLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQztJQUNqQixJQUFJLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ3JDLFFBQVEsTUFBTSxFQUFFLEdBQUcsTUFBTSxNQUFNLENBQUMsRUFBRSxFQUFFLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQztBQUNyRDtJQUNBLFFBQVEsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDeEIsS0FBSztJQUNMLElBQUksTUFBTUMsZ0JBQTJCLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDMUM7QUFDQTtJQUNBO0lBQ0E7SUFDQSxJQUFJLE1BQU1ELHdCQUFtQyxDQUFDLEVBQUUsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDL0QsSUFBSSxJQUFJLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQztJQUNqQixJQUFJLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ3JDLFFBQVEsTUFBTSxFQUFFLEdBQUcsTUFBTSxNQUFNLENBQUMsRUFBRSxFQUFFLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQztJQUNyRCxRQUFRLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQ3hCLEtBQUs7SUFDTCxJQUFJLE1BQU1DLGdCQUEyQixDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQzFDO0FBQ0E7SUFDQTtJQUNBO0lBQ0EsSUFBSSxNQUFNRCx3QkFBbUMsQ0FBQyxFQUFFLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQy9ELElBQUksSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFF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LENBQUMsQ0FBQztJQUMzQyxJQUFJLE1BQU0sT0FBTyxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMzQyxJQUFJLE1BQU0sT0FBTyxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUM1QyxJQUFJLE1BQU0sT0FBTyxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUM3QyxJQUFJLE1BQU0sRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDakMsSUFBSSxNQUFNLEVBQUUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQztBQUNyQztJQUNBLElBQUksTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDO0lBQ3RCLElBQUksSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFO0lBQ2hCLFFBQVEsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2QixRQUFRLE1BQU0sUUFBUSxHQUFHLElBQUksV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNqRixRQUFRLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ3pDLFFBQVEsS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzRSxLQUFLO0lBQ0wsSUFBSSxJQUFJLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxFQUFFO0lBQ3JCLFFBQVEsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2QixRQUFRLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLENBQUM7QUFDeEM7SUFDQSxRQUFRLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdkIsUUFBUSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDN0MsUUFBUSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbkYsS0FBSztJQUNMLElBQUksSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRTtJQUN6QixRQUFRLE1BQU0sVUFBVSxHQUFHLElBQUksVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2xELFFBQVEsTUFBTSxFQUFFLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNuRCxRQUFRLE1BQU0sRUFBRSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNuQyxLQUFLLE1BQU07SUFDWCxRQUFRLE1BQU0sRUFBRSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMvQixLQUFLO0FBQ0w7SUFDQSxDQUFDO0FBQ0Q7SUFDTyxlQUFlLGNBQWMsQ0FBQyxFQUFFLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRTtJQUMzRCxJQUFJLE1BQU1YLGlCQUE4QixDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNqRCxJQUFJLE1BQU0sRUFBRSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDckMsSUFBSSxNQUFNLEVBQUUsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN4RCxJQUFJLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUN6RCxRQUFRLE1BQU1XLG1CQUFpQixDQUFDLEVBQUUsRUFBRSxLQUFLLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3RFLEtBQUs7SUFDTCxJQUFJLE1BQU1WLGVBQTRCLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDM0MsQ0FBQztBQUNEO0lBQ08sU0FBUyxNQUFNLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUU7SUFDekMsSUFBSSxNQUFNLElBQUksR0FBRyxJQUFJLFVBQVUsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDakQsSUFBSSxLQUFLLENBQUMsRUFBRSxDQUFDLGlCQUFpQixDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDM0MsSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3hCLENBQUM7QUFDRDtJQUNPLFNBQVMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFO0lBQ3hDLElBQUksTUFBTSxJQUFJLEdBQUcsSUFBSSxVQUFVLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2pELElBQUksS0FBSyxDQUFDLEVBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzNDLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN4QixDQUFDO0FBQ0Q7SUFDTyxTQUFTLFVBQVUsQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRTtJQUM3QyxJQUFJLE1BQU0sQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUN4QyxJQUFJLE1BQU0sQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDeEMsSUFBSSxNQUFNLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3pDLElBQUksTUFBTSxDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMxQyxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ2hDOztJQ25qQkE7SUFDQTtBQUNBO0lBQ0E7QUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0FBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtBQUNBO0lBQ0E7SUFDQTtJQUNBO0FBS0E7QUFDQTtJQUNPLGVBQWUsS0FBSyxDQUFDLEVBQUUsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFO0FBQ2hEO0lBQ0EsSUFBSSxNQUFNRCxpQkFBOEIsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDaEQsSUFBSSxNQUFNLEVBQUUsR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3RFLElBQUksTUFBTSxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzVCLElBQUksTUFBTUcsV0FBd0IsQ0FBQyxFQUFFLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ2xELElBQUksTUFBTSxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN4QyxJQUFJLE1BQU1GLGVBQTRCLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDM0M7SUFDQSxJQUFJLE1BQU1ELGlCQUE4QixDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNoRCxJQUFJLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ3pDLFFBQVEsTUFBTUcsV0FBd0IsQ0FBQyxFQUFFLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzNELEtBQUs7SUFDTCxJQUFJLE1BQU1GLGVBQTRCLENBQUMsRUFBSyxDQUFDLENBQUM7QUFDOUM7QUFDQTtJQUNBLENBQUM7QUFDRDtJQUNPLGVBQWUsUUFBUSxDQUFDLEVBQUUsRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFO0FBQ3REO0lBQ0EsSUFBSSxNQUFNRCxpQkFBOEIsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDaEQsSUFBSSxNQUFNLEVBQUUsR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3RFLElBQUksTUFBTSxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzVCLElBQUksTUFBTUcsV0FBd0IsQ0FBQyxFQUFFLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ2xELElBQUksSUFBSSxVQUFVLENBQUMsVUFBVSxHQUFHLEVBQUUsSUFBSSxDQUFDLEVBQUU7SUFDekMsUUFBUSxNQUFNLElBQUksS0FBSyxDQUFDLHdCQUF3QixDQUFDLENBQUM7SUFDbEQsS0FBSztJQUNMLElBQUksTUFBTSxFQUFFLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxVQUFVLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDcEQsSUFBSSxNQUFNRixlQUE0QixDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQzNDO0FBQ0E7SUFDQSxJQUFJLE1BQU1ELGlCQUE4QixDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNoRCxJQUFJLE1BQU0sRUFBRSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUMvQixJQUFJLE1BQU1DLGVBQTRCLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDM0M7SUFDQSxDQUFDO0FBQ0Q7SUFDTyxlQUFlLFVBQVUsQ0FBQyxFQUFFLEVBQUUsUUFBUSxFQUFFO0FBQy9DO0lBQ0EsSUFBSSxNQUFNSSx3QkFBbUMsQ0FBQyxFQUFFLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQy9ELElBQUksTUFBTSxFQUFFLEdBQUcsTUFBTSxFQUFFLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDcEMsSUFBSSxNQUFNLENBQUMsR0FBRyxNQUFNRSxZQUF1QixDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNwRCxJQUFJLE1BQU0sUUFBUSxHQUFHLE1BQU0sRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQzFDLElBQUksTUFBTUQsZ0JBQTJCLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDMUM7SUFDQSxJQUFJLE9BQU8sQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBQzdCO0lBQ0EsQ0FBQztBQUNEO0lBQ08sZUFBZSxJQUFJLENBQUMsUUFBUSxFQUFFO0FBQ3JDO0lBQ0EsSUFBSSxNQUFNLENBQUMsRUFBRSxFQUFFLFFBQVEsQ0FBQyxHQUFHLE1BQU1FLGFBQXdCLENBQUMsUUFBUSxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztBQUMvRTtJQUNBLElBQUksTUFBTSxDQUFDLEVBQUUsRUFBRSxRQUFRLENBQUMsR0FBRyxNQUFNLFVBQVUsQ0FBQyxFQUFFLEVBQUUsUUFBUSxDQUFDLENBQUM7QUFDMUQ7SUFDQSxJQUFJLE1BQU1ILHdCQUFtQyxDQUFDLEVBQUUsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDL0QsSUFBSSxNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUM7SUFDbkIsSUFBSSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ25DLFFBQVEsTUFBTSxDQUFDLEdBQUcsTUFBTUUsWUFBdUIsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDeEQsUUFBUSxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BCLEtBQUs7SUFDTCxJQUFJLE1BQU1ELGdCQUEyQixDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQzFDO0lBQ0EsSUFBSSxNQUFNLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztBQUNyQjtJQUNBLElBQUksT0FBTyxHQUFHLENBQUM7SUFDZjs7SUMxRkE7SUFDQTtBQUNBO0lBQ0E7QUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0FBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtBQUNBO0lBQ0E7SUFDQTtJQUNBO0lBT0EsTUFBTSxtQkFBQy9DLGtCQUFnQixDQUFDLEdBQUdxRCxPQUFLLENBQUM7QUFDakM7SUFDZSxlQUFlLFlBQVksQ0FBQyxZQUFZLEVBQUUsZUFBZSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUU7QUFDM0Y7SUFDQSxJQUFJLElBQUksTUFBTSxFQUFFLGtCQUFrQixDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQztJQUMvQyxJQUFJLE1BQU0sQ0FBQyxFQUFFLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxZQUFZLENBQUMsR0FBRyxNQUFNSixhQUF3QixDQUFDLGVBQWUsRUFBRSxNQUFNLEVBQUUsQ0FBZSxDQUFDLENBQUM7QUFDMUg7SUFDQSxJQUFJLE1BQU0sSUFBSSxHQUFHLE1BQU1LLFVBQW9CLENBQUMsTUFBTSxFQUFFLFlBQVksQ0FBQyxDQUFDO0FBQ2xFO0lBQ0EsSUFBSSxNQUFNLENBQUMsRUFBRSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsWUFBWSxDQUFDLEdBQUcsTUFBTUwsYUFBd0IsQ0FBQyxZQUFZLEVBQUUsTUFBTSxFQUFFLENBQWUsQ0FBQyxDQUFDO0FBQ3ZIO0lBQ0EsSUFBSSxNQUFNLElBQUksR0FBRyxNQUFNTSxZQUFvQixDQUFDLE1BQU0sRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBQ3RGO0lBQ0EsSUFBSSxJQUFJLElBQUksQ0FBQyxRQUFRLElBQUksU0FBUyxFQUFFO0lBQ3BDLFFBQVEsTUFBTSxJQUFJLEtBQUssQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO0lBQ3BELEtBQUs7QUFDTDtJQUNBLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUU7SUFDckMsUUFBUSxNQUFNLElBQUksS0FBSyxDQUFDLGtFQUFrRSxDQUFDLENBQUM7SUFDNUYsS0FBSztBQUNMO0lBQ0EsSUFBSSxJQUFJLElBQUksQ0FBQyxRQUFRLElBQUksSUFBSSxDQUFDLEtBQUssRUFBRTtJQUNyQyxRQUFRLE1BQU0sSUFBSSxLQUFLLENBQUMsQ0FBQyxpQ0FBaUMsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3JHLEtBQUs7QUFDTDtJQUNBLElBQUksTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQztJQUM3QixJQUFJLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUM7SUFDeEIsSUFBSSxNQUFNLEVBQUUsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDO0lBQ3hCLElBQUksTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQztBQUN4QjtJQUNBLElBQUksTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztBQUN4QztJQUNBLElBQUksSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQztJQUM3QyxJQUFJLE1BQU0sV0FBVyxHQUFHLE1BQU1DLGFBQXdCLENBQUMsTUFBTSxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUMsQ0FBQztBQUNoRjtJQUNBLElBQUksSUFBSSxJQUFJLENBQUM7SUFDYixJQUFJLElBQUksV0FBVyxDQUFDO0lBQ3BCLElBQUksSUFBSSxVQUFVLENBQUM7QUFDbkI7SUFDQSxJQUFJLElBQUksVUFBVSxHQUFHLENBQUMsaUJBQWlCO0lBQ3ZDLFFBQVEsSUFBSSxPQUFPLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQztBQUN0QztJQUNBLFFBQVEsTUFBTSxDQUFDLGlCQUFpQjtJQUNoQyxZQUFZLElBQUksTUFBTSxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUN2RCxZQUFZLE9BQU8sQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUMzQyxZQUFZLE1BQU0sVUFBVSxHQUFHLE1BQU1BLGFBQXdCLENBQUMsTUFBTSxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUMsQ0FBQztBQUN2RjtJQUNBLFlBQVksSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQztBQUNyRDtJQUNBLFlBQVksT0FBTyxHQUFHLE9BQU8sSUFBSSxFQUFFLENBQUM7SUFDcEM7QUFDQTtJQUNBLFlBQVksSUFBSSxPQUFPLElBQUksT0FBTyxDQUFDLFFBQVEsR0FBRyxNQUFNLEVBQUU7SUFDdEQ7SUFDQSxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxHQUFHLE1BQU0sUUFBUSxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUMzRyxhQUFhLE1BQU0sSUFBSSxPQUFPLElBQUksT0FBTyxDQUFDLFFBQVEsR0FBRyxPQUFPLEVBQUU7SUFDOUQ7SUFDQSxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxHQUFHLE1BQU0sYUFBYSxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUNoSCxhQUFhLE1BQU07SUFDbkI7SUFDQSxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxHQUFHLE1BQU0sU0FBUyxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUM1RyxhQUFhO0lBQ2IsWUFBWSxPQUFPLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDOUMsU0FBUyxHQUFHLENBQUM7QUFDYjtJQUNBLFFBQVEsT0FBTyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztBQUNuQztJQUNBLFFBQVEsSUFBSSxVQUFVLENBQUMsRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDN0M7SUFDQSxRQUFRLE1BQU0sR0FBRyxHQUFHLEtBQUssS0FBSyxFQUFFLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUMxRTtJQUNBLFFBQVEsSUFBSSxVQUFVLENBQUM7SUFDdkIsUUFBUSxNQUFNLENBQUMsa0JBQWtCO0lBQ2pDLFlBQVksSUFBSSxLQUFLLEdBQUcsTUFBTSxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQztJQUN6RSxZQUFZLE9BQU8sR0FBRyxJQUFJLENBQUM7SUFDM0IsWUFBWSxNQUFNLFFBQVEsR0FBRyxNQUFNLEVBQUUsQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDekUsWUFBWSxVQUFVLEdBQUcsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQztJQUN6RSxTQUFTLEdBQUcsQ0FBQztBQUNiO0lBQ0EsUUFBUSxJQUFJLFVBQVUsQ0FBQztJQUN2QixRQUFRLE1BQU0sQ0FBQyxrQkFBa0I7SUFDakMsWUFBWSxNQUFNLEtBQUssR0FBRyxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQzNFLFlBQVksT0FBTyxHQUFHLElBQUksQ0FBQztJQUMzQixZQUFZLE1BQU0sUUFBUSxHQUFHLE1BQU0sRUFBRSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUN6RSxZQUFZLFVBQVUsR0FBRyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3pFLFNBQVMsR0FBRyxDQUFDO0FBQ2I7SUFDQSxRQUFRLElBQUksVUFBVSxDQUFDO0lBQ3ZCLFFBQVEsTUFBTSxDQUFDLGtCQUFrQjtJQUNqQyxZQUFZLE1BQU0sS0FBSyxHQUFHLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDM0UsWUFBWSxPQUFPLEdBQUcsSUFBSSxDQUFDO0lBQzNCLFlBQVksTUFBTSxRQUFRLEdBQUcsTUFBTSxFQUFFLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3pFLFlBQVksVUFBVSxHQUFHLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDekUsU0FBUyxHQUFHLENBQUM7QUFDYjtJQUNBLFFBQVEsSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUM3QyxRQUFRLFVBQVUsR0FBRyxNQUFNLE9BQU8sQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQzVGLFFBQVEsSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0lBQ3RELFFBQVEsVUFBVSxHQUFHLElBQUksQ0FBQztJQUMxQixRQUFRLFVBQVUsR0FBRyxJQUFJLENBQUM7SUFDMUIsUUFBUSxVQUFVLEdBQUcsSUFBSSxDQUFDO0FBQzFCO0lBQ0EsUUFBUSxJQUFJLFVBQVUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUM3QyxRQUFRLE9BQU8sQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDdEMsS0FBSyxHQUFHLENBQUM7SUFDVDtBQUNBO0lBQ0EsSUFBSSxJQUFJLEtBQUssR0FBRyxFQUFFLENBQUM7QUFDbkI7SUFDQSxJQUFJLGVBQWUsT0FBTyxFQUFFO0lBQzVCLFFBQVEsSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBQ3JELFFBQVEsTUFBTSxVQUFVLEdBQUcsTUFBTUEsYUFBd0IsQ0FBQyxNQUFNLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ25GLFFBQVEsT0FBTyxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUN0QyxRQUFRLEtBQUssQ0FBQyxJQUFJLEdBQUcsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDLGNBQWMsQ0FBQyxVQUFVLEVBQUUsV0FBVyxFQUFFLE1BQU0sRUFBRSxZQUFZLENBQUMsQ0FBQztJQUNsRyxRQUFRLE9BQU8sQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLENBQUM7SUFDekMsS0FBSztBQUNMO0lBQ0EsSUFBSSxJQUFJLFVBQVUsR0FBRyxPQUFPLEVBQUUsQ0FBQztJQUMvQjtBQUNBO0lBQ0EsSUFBSSxJQUFJLElBQUksQ0FBQztBQUNiO0lBQ0EsSUFBSSxlQUFlLFFBQVEsR0FBRztJQUM5QixRQUFRLElBQUksTUFBTSxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsbUJBQW1CLENBQUMsQ0FBQztJQUN0RCxRQUFRLE1BQU0sV0FBVyxHQUFHLE1BQU1BLGFBQXdCLENBQUMsTUFBTSxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNwRixRQUFRLE9BQU8sQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUN2QyxRQUFRLElBQUksR0FBRyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUMsY0FBYyxDQUFDLFdBQVcsRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFLGFBQWEsQ0FBQyxDQUFDO0lBQzlGLFFBQVEsT0FBTyxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0lBQzFDLEtBQUs7QUFDTDtJQUNBLElBQUksSUFBSSxXQUFXLEdBQUcsUUFBUSxFQUFFLENBQUM7SUFDakM7QUFDQTtJQUNBLElBQUksZUFBZSxPQUFPLEdBQUc7SUFDN0IsUUFBUSxJQUFJLE1BQU0sRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFDdEQsUUFBUSxNQUFNLFdBQVcsR0FBRyxNQUFNQSxhQUF3QixDQUFDLE1BQU0sRUFBRSxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDcEYsUUFBUSxPQUFPLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDO0lBQ3RDLFFBQVEsS0FBSyxDQUFDLElBQUksR0FBRyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUMsY0FBYyxDQUFDLFdBQVcsRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFLGFBQWEsQ0FBQyxDQUFDO0lBQ3BHLFFBQVEsT0FBTyxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUN6QyxLQUFLO0FBQ0w7SUFDQSxJQUFJLElBQUksVUFBVSxHQUFHLE9BQU8sRUFBRSxDQUFDO0lBQy9CO0FBQ0E7SUFDQSxJQUFJLElBQUksVUFBVSxHQUFHLENBQUMsaUJBQWlCO0lBQ3ZDLFFBQVEsSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBQ3JELFFBQVEsTUFBTSxVQUFVLEdBQUcsTUFBTUEsYUFBd0IsQ0FBQyxNQUFNLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ25GLFFBQVEsT0FBTyxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUN0QyxRQUFRLEtBQUssQ0FBQyxJQUFJLEdBQUcsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDLGNBQWMsQ0FBQyxVQUFVLEVBQUUsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLFlBQVksQ0FBQyxDQUFDO0lBQ3RJLFFBQVEsT0FBTyxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUN6QyxLQUFLLEdBQUcsQ0FBQztJQUNUO0FBQ0E7QUFDQTtJQUNBLElBQUksV0FBVyxHQUFHLENBQUMsaUJBQWlCO0lBQ3BDLFFBQVEsSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBQ3JELFFBQVEsTUFBTSxVQUFVLENBQUM7SUFDekIsUUFBUSxPQUFPLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ3BDLFFBQVEsTUFBTSxVQUFVLEdBQUcsTUFBTUEsYUFBd0IsQ0FBQyxNQUFNLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ25GO0lBQ0EsUUFBUSxJQUFJLEdBQUcsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDLGNBQWMsQ0FBQyxVQUFVLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxZQUFZLENBQUMsQ0FBQztJQUMzRjtJQUNBLFFBQVEsT0FBTyxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUN2QyxLQUFLLEdBQUcsQ0FBQztJQUNUO0FBQ0E7QUFDQTtJQUNBLElBQUksTUFBTSxDQUFDLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUNoQyxJQUFJLE1BQU0sQ0FBQyxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUM7QUFDaEM7SUFDQSxJQUFJLE1BQU0sVUFBVSxDQUFDO0lBQ3JCLElBQUksS0FBSyxDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQ3hELElBQUksS0FBSyxDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDeEU7SUFDQSxJQUFJLE1BQU0sVUFBVSxDQUFDO0lBQ3JCLElBQUksS0FBSyxDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQ3ZELElBQUksS0FBSyxDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDeEU7SUFDQSxJQUFJLE1BQU0sV0FBVyxDQUFDO0lBQ3RCLElBQUksSUFBSSxHQUFHLEVBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztJQUMxQyxJQUFJLElBQUksR0FBRyxFQUFFLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUMzRDtJQUNBLElBQUksTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsVUFBVSxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUM7SUFDakQsSUFBSSxLQUFLLENBQUMsSUFBSSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztBQUMxQztBQUNBO0lBQ0EsSUFBSSxLQUFLLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNuRSxJQUFJLEtBQUssQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDN0QsSUFBSSxLQUFLLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUMxRjtBQUNBO0lBQ0EsSUFBSSxJQUFJLGFBQWEsR0FBRyxFQUFFLENBQUM7QUFDM0I7SUFDQSxJQUFJLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ3pDLFFBQVEsTUFBTSxDQUFDLEdBQUcsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVB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N0IsUUFBUSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQzFDLFlBQVksTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDO0lBQzFCLFlBQVksSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7SUFDNUUsWUFBWSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztJQUM1RSxZQUFZLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDcEMsZ0JBQWdCLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDcEUsZ0JBQWdCLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDOUMsb0JBQW9CLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4RixvQkFBb0IsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxN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QUFJLE1BQU0sUUFBUSxHQUFHLElBQUksU0FBUyxDQUFDLElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNsRSxJQUFJLE1BQU0sUUFBUSxHQUFHLElBQUksU0FBUyxDQUFDLElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNsRSxJQUFJLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNkLElBQUksS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDNUMsUUFBUSxRQUFRLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN0QyxRQUFRLFFBQVEsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3RDLFFBQVEsUUFBUSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEMsUUFBUSxDQUFDLElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQztJQUNyQyxLQUFLO0FBQ0w7SUFDQSxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7QUFDaEM7SUFDQSxJQUFJLE9BQU8sQ0FBQyxRQUFRLEVBQUUsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBQzFDO0lBQ0EsSUFBSSxTQUFTLFdBQVcsQ0FBQyxDQUFDLEVBQUU7SUFDNUIsUUFBUSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDbEIsUUFBUSxJQUFJLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDN0IsUUFBUSxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUU7SUFDdEIsWUFBWSxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUM1QyxZQUFZLE1BQU0sRUFBRSxHQUFHLFNBQVMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNwRCxZQUFZLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRTtJQUN4QixnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDMUIsYUFBYSxNQUFNLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRTtJQUMvQixnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDMUIsYUFBYSxNQUFNO0lBQ25CLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3RCLGFBQWE7SUFDYixTQUFTO0lBQ1QsUUFBUSxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsS0FBSyxDQUFDO0lBQzdCLEtBQUs7SUFDTCxDQUFDO0FBQ0Q7QUFDQTtJQUNBLGVBQWUsT0FBTyxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFO0lBQ3JELElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUM1QixJQUFJLE1BQU0sY0FBYyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUM7QUFDbkM7SUFDQSxJQUFJLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQzNCLElBQUksTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDN0Q7SUFDQSxJQUFJLE1BQU0sUUFBUSxHQUFHLEVBQUUsQ0FBQztBQUN4QjtJQUNBLElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDLElBQUksY0FBYyxFQUFFO0lBQ3BELFFBQVEsSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMvRCxRQUFRLE1BQU0sQ0FBQyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxHQUFHLENBQUMsRUFBRSxjQUFjLENBQUMsQ0FBQztBQUN6RDtJQUNBLFFBQVEsTUFBTSxJQUFJLEdBQUcsRUFBRSxDQUFDO0FBQ3hCO0lBQ0EsUUFBUSxNQUFNLE1BQU0sR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQ2xELFFBQVEsTUFBTSxNQUFNLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNsRCxRQUFRLE1BQU0sTUFBTSxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDbEQ7SUFDQSxRQUFRLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDM0QsUUFBUSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLFVBQVUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQzNELFFBQVEsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUMzRCxRQUFRLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3JELFFBQVEsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLGFBQWEsRUFBRSxNQUFNLENBQUM7SUFDOUQsWUFBWSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDcEIsWUFBWSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDcEIsWUFBWSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDcEIsWUFBWSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDcEIsWUFBWSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDcEIsU0FBUyxDQUFDLENBQUMsQ0FBQztJQUNaLFFBQVEsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLHlCQUF5QixFQUFFLE1BQU0sQ0FBQztJQUMxRSxZQUFZLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUNwQixZQUFZLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUNwQixZQUFZLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUNwQixTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ1osUUFBUSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzNELFFBQVEsUUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FB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QyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDMUQsWUFBWSxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3RFLFlBQVksSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFLFFBQVEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDdkQsWUFBWSxJQUFJLElBQUksQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNuRCxTQUFTO0lBQ1QsUUFBUSxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQzVCO0lBQ0EsUUFBUSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUNuRCxRQUFRLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3ZDLEtBQUs7QUFDTDtJQUNBLElBQUksY0FBYyxDQUFDLENBQUMsRUFBRTtJQUN0QixRQUFRLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQztJQUMxQixRQUFRLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDL0QsUUFBUSxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNsQyxRQUFRLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUNyRCxZQUFZLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUM1RCxnQkFBZ0IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzNELGFBQWE7SUFDYixTQUFTO0lBQ1QsS0FBSztBQUNMO0FBQ0E7QUFDQTtJQUNBLElBQUksWUFBWSxHQUFHO0lBQ25CLFFBQVEsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDO0FBQzFCO0lBQ0EsUUFBUSxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUUsT0FBTztJQUNqQyxRQUFRLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLE9BQU87QUFDaEQ7SUFDQSxRQUFRLE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ2pEO0lBQ0EsUUFBUSxNQUFNLGNBQWMsR0FBRyxFQUFFLENBQUM7SUFDbEMsUUFBUSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUM5QyxZQUFZLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDM0QsWUFBWSxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssSUFBSSxLQUFLLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxjQUFjLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFJLFNBQVM7QUFDVDtJQUNBLFFBQVEsSUFBSSxTQUFTLEdBQUcsSUFBSSxDQUFDLGNBQWMsR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDO0FBQzlEO0lBQ0EsUUFBUSxNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUM7QUFDdkI7SUFDQTtJQUNBO0lBQ0EsUUFBUTtJQUNSLFlBQVksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3ZDLGdCQUFnQixDQUFDLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLFdBQVc7SUFDNUUsbUJBQW1CLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDL0Isb0JBQW9CLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO0lBQ2hELFlBQVksTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNuRCxZQUFZLElBQUksT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxXQUFXLEVBQUU7SUFDN0QsZ0JBQWdCLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLFVBQVUsR0FBRyxDQUFDO0lBQ3BELGdCQUFnQixNQUFNLEdBQUcsR0FBRyxjQUFjLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM5RCxnQkFBZ0IsSUFBSSxHQUFHLEVBQUUsQ0FBQyxFQUFFLGNBQWMsQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzFELGdCQUFnQixJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sRUFBRTtJQUNuRCxvQkFBb0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM3RCxpQkFBaUIsTUFBTTtJQUN2QixvQkFBb0IsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ25DLGlCQUFpQjtJQUNqQixnQkFBZ0IsSUFBSSxDQUFDLFlBQVksQ0FBQyx1QkFBdUIsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDdEU7SUFDQSxhQUFhLE1BQU07SUFDbkIsZ0JBQWdCLElBQUksU0FBUyxFQUFFO0lBQy9CLG9CQUFvQixTQUFTLEVBQUUsQ0FBQztJQUNoQyxpQkFBaUIsTUFBTTtJQUN2QixvQkFBb0IsTUFBTSxFQUFFLEdBQUcsY0FBYyxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ3RELG9CQUFvQixJQUFJLENBQUMsWUFBWSxDQUFDLGlCQUFpQixFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzdELG9CQUFvQixJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDekQsb0JBQW9CLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUMxQyxvQkFBb0IsSUFBSSxDQUFDLFlBQVksQ0FBQyxnQkFBZ0IsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUM1RCxpQkFBaUI7QUFDakI7SUFDQSxnQkFBZ0IsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxVQUFVLEVBQUU7SUFDaEQsb0JBQW9CLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLFVBQVUsRUFBRSxDQUFDO0lBQ3pELG9CQUFvQixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDbkMsb0JBQW9CLElBQUksQ0FBQyxZQUFZLENBQUMsb0JBQW9CLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3ZFLGlCQUFpQixNQUFNO0lBQ3ZCLG9CQUFvQixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztJQUN4QyxvQkFBb0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsVUFBVSxFQUFFLENBQUM7SUFDekQsb0JBQW9CLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzNELG9CQUFvQixHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLElBQUk7SUFDOUgsd0JBQXdCLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksR0FBRyxHQUFHLENBQUMsU0FBUyxDQUFDO0lBQ25FLHdCQUF3QixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUM7SUFDdEUsd0JBQXdCLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDO0lBQzdELHdCQUF3QixLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUM3RCw0QkFBNEIsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ2pELHlCQUF5QjtJQUN6Qix3QkFBd0IsSUFBSSxDQUFDLFlBQVksQ0FBQyx1QkFBdUIsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDOUUsd0JBQXdCLE9BQU8sR0FBRyxDQUFDO0lBQ25DLHFCQUFxQixFQUFFLENBQUMsR0FBRyxLQUFLO0lBQ2hDLHdCQUF3QixJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3pDLHFCQUFxQixDQUFDLENBQUMsQ0FBQztJQUN4QixvQkFBb0IsSUFBSSxDQUFDLFlBQVksQ0FBQyx3QkFBd0IsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDM0UsaUJBQWlCO0lBQ2pCLGFBQWE7SUFDYixTQUFTO0lBQ1Q7QUFDQTtJQUNBLFFBQVEsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsTUFBTTtJQUNyQyxZQUFZLElBQUksQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDO0lBQ2pDLFlBQVksSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsWUFBWSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDdkYsWUFBWSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDN0IsU0FBUyxDQUFDLENBQUM7QUFDWDtJQUNBLFFBQVEsU0FBUyxVQUFVLEdBQUc7SUFDOUIsWUFBWSxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRTtJQUN2QyxnQkFBZ0IsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUMvQyxnQkFBZ0IsQ0FBQyxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7SUFDaEMsZ0JBQWdCLENBQUMsQ0FBQyxVQUFVLEdBQUcsQ0FBQyxDQUFDO0lBQ2pDLGdCQUFnQixDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUMxQixnQkFBZ0IsT0FBTyxDQUFDLENBQUM7SUFDekIsYUFBYSxNQUFNO0lBQ25CLGdCQUFnQixPQUFPO0lBQ3ZCLG9CQUFvQixLQUFLLEVBQUUsS0FBSztJQUNoQyxvQkFBb0IsSUFBSSxFQUFFLElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUM7SUFDdkQsb0JBQW9CLFVBQVUsRUFBRSxDQUFDO0lBQ2pDLG9CQUFvQixJQUFJLEVBQUUsQ0FBQztJQUMzQixpQkFBaUIsQ0FBQztJQUNsQixhQUFhO0lBQ2IsU0FBUztBQUNUO0lBQ0EsS0FBSztBQUNMO0FBQ0E7SUFDQSxJQUFJLGFBQWEsR0FBRztJQUNwQixRQUFRLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQztJQUMxQixRQUFRLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRSxPQUFPO0FBQ2pDO0lBQ0EsUUFBUSxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUNqRDtJQUNBLFFBQVEsTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUFDO0FBQ3ZCO0lBQ0EsUUFBUSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUM5QyxZQUFZLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDM0QsWUFBWSxJQUFJLElBQUksQ0FBQyxLQUFLLEVBQUU7SUFDNUIsZ0JBQWdCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO0lBQ25DLGdCQUFnQixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztJQUNwQyxnQkFBZ0IsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUM7SUFDcEMsZ0JBQWdCLEdBQUcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNO0lBQ2pILG9CQUFvQixJQUFJLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQztJQUN6QyxvQkFBb0IsT0FBTztJQUMzQixpQkFBaUIsRUFBRSxDQUFDLEdBQUcsS0FBSztJQUM1QixvQkFBb0IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN2RCxvQkFBb0IsSUFBSSxDQUFDLEtBQUssR0FBRyxHQUFHLENBQUM7SUFDckMsb0JBQW9CLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztJQUNyQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7SUFDcEIsYUFBYTtJQUNiLFNBQVM7QUFDVDtJQUNBLFFBQVEsSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFO0lBQzFCLFlBQVksT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsTUFBTTtJQUN6QyxnQkFBZ0IsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7SUFDckMsZ0JBQWdCLFlBQVksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQzVELGdCQUFnQixJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDakMsZ0JBQWdCLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLFlBQVksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQzNGLGFBQWEsQ0FBQyxDQUFDO0lBQ2YsU0FBUztJQUNULEtBQUs7QUFDTDtJQUNBLElBQUksYUFBYSxHQUFHO0lBQ3BCLFFBQVEsS0FBSyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFO0lBQ2xDLFlBQVksSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQztJQUM5QyxTQUFTO0lBQ1QsUUFBUSxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBQ2xCLEtBQUs7QUFDTDtJQUNBLElBQUksTUFBTSxLQUFLLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRTtJQUMzQixRQUFRLElBQUksSUFBSSxDQUFDLFVBQVUsSUFBSSxDQUFDLEVBQUUsT0FBTztJQUN6QyxRQUFRLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQztJQUMxQjtJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQSxRQUFRLElBQUksT0FBTyxHQUFHLElBQUksV0FBVyxFQUFFLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDO0lBQ3RELFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUN2QyxRQUFRLElBQUksSUFBSSxDQUFDLFNBQVMsR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsU0FBUyxHQUFHLEdBQUcsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDO0lBQzNGLFFBQVEsSUFBSSxJQUFJLENBQUMsWUFBWTtJQUM3QixZQUFZLE1BQU0sSUFBSSxLQUFLLENBQUMsd0JBQXdCLENBQUMsQ0FBQztJQUN0RCxRQUFRLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUMxRCxRQUFRLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBQ2hGO0lBQ0EsUUFBUSxNQUFNLFlBQVksR0FBRyxFQUFFLENBQUM7SUFDaEMsUUFBUSxLQUFLLElBQUksQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsRUFBRSxFQUFFLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3JGLFFBQVEsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO0FBQzVCO0lBQ0EsUUFBUSxJQUFJLENBQUMsR0FBRyxTQUFTLENBQUM7SUFDMUIsUUFBUSxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztJQUNwQyxRQUFRLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUM7SUFDaEMsUUFBUSxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUU7SUFDcEIsWUFBWSxNQUFNLFlBQVksQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDNUMsWUFBWSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLFFBQVEsS0FBSyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDckUsWUFBWSxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxVQUFVLEdBQUcsQ0FBQyxFQUFFLElBQUksQ0FBQyxVQUFVLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3RGLFlBQVksTUFBTSxPQUFPLEdBQUcsSUFBSSxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM1RSxZQUFZLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDakMsWUFBWSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUM7SUFDdkMsWUFBWSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsR0FBRyxDQUFDO0lBQ3hDLFlBQVksSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDbkUsWUFBWSxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFO0lBQ3BDLGdCQUFnQixJQUFJLENBQUMsVUFBVSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdEMsYUFBYTtJQUNiLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDcEIsWUFBWSxDQUFDLEdBQUcsQ0FBQztJQUNqQixZQUFZLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDbEIsWUFBWSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxZQUFZLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUMzRSxTQUFTO0lBQ1QsS0FBSztBQUNMO0lBQ0EsSUFBSSxNQUFNLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFO0lBQ3pCLFFBQVEsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQzFCLFFBQVEsSUFBSSxJQUFJLEdBQUcsSUFBSSxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdkMsUUFBUSxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDbkQ7SUFDQSxRQUFRLE9BQU8sSUFBSSxDQUFDO0lBQ3BCLEtBQUs7QUFDTDtJQUNBLElBQUksTUFBTSxZQUFZLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFO0lBQ2xELFFBQVEsSUFBSSxHQUFHLElBQUksQ0FBQyxFQUFFO0lBQ3RCLFlBQVksT0FBTztJQUNuQixTQUFTO0lBQ1QsUUFBUSxNQUFNLElBQUksR0FBRyxJQUFJLENBQUM7SUFDMUIsUUFBUSxJQUFJLEdBQUcsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxFQUFFO0lBQ3pELFlBQVksTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDLENBQUM7SUFDcEQsWUFBWSxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxLQUFLLEVBQUUsU0FBUyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDM0UsU0FBUztJQUNULFFBQVEsSUFBSSxPQUFPLEdBQUcsSUFBSSxXQUFXLEVBQUUsR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUM7SUFDdEQsUUFBUSxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUM7SUFDM0IsUUFBUSxJQUFJLElBQUksQ0FBQyxZQUFZO0lBQzdCLFlBQVksTUFBTSxJQUFJLEtBQUssQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO0lBQ3RELFFBQVEsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQzFELFFBQVEsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsR0FBRyxHQUFHLEVBQUUsQ0FBQyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUNwRTtJQUNBLFFBQVEsTUFBTSxZQUFZLEdBQUcsRUFBRSxDQUFDO0lBQ2hDLFFBQVEsS0FBSyxJQUFJLENBQUMsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxFQUFFLFFBQVEsRUFBRSxDQUFDLEVBQUUsRUFBRSxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNyRjtJQUNBLFFBQVEsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO0FBQzVCO0lBQ0EsUUFBUSxJQUFJLENBQUMsR0FBRyxTQUFTLENBQUM7SUFDMUIsUUFBUSxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztJQUNwQztJQUNBLFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLEdBQUcsR0FBRyxJQUFJLENBQUMsU0FBUyxHQUFHLEdBQUcsSUFBSSxHQUFHLEdBQUcsR0FBRyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsRUFB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QUMxRDtJQUNBLFFBQVEsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQzFDO0lBQ0EsUUFBUSxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3pDLEtBQUs7QUFDTDtBQUNBO0lBQ0EsSUFBSSxNQUFNLFVBQVUsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFO0lBQzdCLFFBQVEsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDO0FBQzFCO0lBQ0EsUUFBUSxNQUFNLFNBQVMsR0FBRyxJQUFJLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM1QyxRQUFRLE1BQU0sVUFBVSxHQUFHLElBQUksUUFBUSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUMxRDtJQUNBLFFBQVEsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFVBQVUsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUN0RCxRQUFRLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLFdBQVcsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO0FBQ3BFO0lBQ0EsUUFBUSxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3pDLEtBQUs7QUFDTDtJQUNBLElBQUksTUFBTSxTQUFTLENBQUMsR0FBRyxFQUFFO0lBQ3pCLFFBQVEsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQzFCLFFBQVEsTUFBTSxDQUFDLEdBQUcsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztBQUMxQztJQUNBLFFBQVEsTUFBTSxJQUFJLEdBQUcsSUFBSSxXQUFXLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQy9DO0lBQ0EsUUFBUSxPQUFPLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2QixL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QUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsV0FBVyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7QUFDcEU7SUFDQSxRQUFRLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQ0QsV0FBUyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3pDLEtBQUs7QUFDTDtBQUNBO0lBQ0EsSUFBSSxNQUFNLFNBQVMsQ0FBQyxHQUFHLEVBQUU7SUFDekIsUUFBUSxNQUFNLElBQUksR0FBRyxJQUFJLENBQUM7SUFDMUIsUUFBUSxNQUFNLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQzFDO0lBQ0EsUUFBUSxNQUFNLElBQUksR0FBRyxJQUFJLFdBQVcsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDL0M7SUFDQSxRQUFRLE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZCLEtBQUs7QUFDTDtJQUNBLElBQUksTUFBTSxTQUFTLENBQUMsR0FBRyxFQUFFO0lBQ3pCLFFBQVEsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQzFCLFFBQVEsTUFBTSxDQUFDLEdBQUcsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztBQUMxQztJQUNBLFFBQVEsTUFBTSxJQUFJLEdBQUcsSUFBSSxRQUFRLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQzVDO0lBQ0EsUUFBUSxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3hDLEtBQUs7QUFDTDtJQUNBLElBQUksTUFBTSxTQUFTLENBQUMsR0FBRyxFQUFFO0lBQ3pCLFFBQVEsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQzFCLFFBQVEsTUFBTSxDQUFDLEdBQUcsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztBQUMxQztJQUNBLFFBQVEsTUFBTSxJ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Q0FBQyxDQUFDO0lBQ3hDLFFBQVEsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDM0MsWUFBWSxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDbkUsU0FBUztBQUNUO0lBQ0EsUUFBUSxJQUFJLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFLFdBQVcsQ0FBQyxDQUFDO0FBQ3hEO0lBQ0EsUUFBUSxJQUFJLENBQUMsRUFBRSxHQUFHLElBQUlxQixPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzFDO0lBQ0EsUUFBUSxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3hELFFBQVEsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUN0RCxRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDaEUsUUFBUSxJQUFJLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMvRCxRQUFRLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hDLFFBQVEsSUFB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QyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUVBLE1BQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFQSxNQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztJQUMxSCxRQUFRLENBQUMsQ0FBQyxFQUFFQSxNQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRUEsTUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDM0QsUUFBUSxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEI7SUFDQSxJQUFJLE9BQU8sQ0FBQyxDQUFDO0lBQ2I7O0lDN0NBO0lBQ0E7QUFDQTtJQUNBO0FBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtBQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7QUFDQTtJQUNBO0lBQ0E7SUFDQTs7Ozs7Ozs7OztJQ2pCQTtJQUNBO0FBQ0E7SUFDQTtBQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7QUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0FBQ0E7SUFDQTtJQUNBO0lBQ0E7QUFLQTtJQUNPLFNBQVMsUUFBUSxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUU7SUFDdEMsSUFBSSxNQUFNLEtBQUssR0FBRyxJQUFJLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzlFLElBQUksTUFBTSxJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQ3BCLElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUM1QixRQUFRLElBQUksQ0FBQyxDQUFDLENBQUMs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QTtJQUNBO0lBQ0EsSUFBSSxNQUFNRCxpQkFBOEIsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDaEQsSUFBSSxNQUFNLE1BQU0sSUFBSSxDQUFDLElBQUksS0FBSyxDQUFDLENBQUM7SUFDaEMsSUFBSSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ2xDLFFBQVEsTUFBTSxFQUFFLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQy9CLFFBQVEsSUFBSSxDQUFDLE1BQU0sSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3RFLEtBQUs7SUFDTCxJQUFJLE1BQU1DLGVBQTRCLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDM0M7SUFDQTtJQUNBO0lBQ0EsSUFBSSxNQUFNRCxpQkFBOEIsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDaEQsSUFBSSxNQUFNLFVBQVUsSUFBSSxDQUFDLElBQUksS0FBSyxDQUFDLENBQUM7SUFDcEMsSUFBSSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsVUFBVSxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ3RDLFFBQVEsTUFBTSxFQUFFLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQy9CLFFBQVEsSUFBSSxDQUFDLE1BQU0sSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsY0FBYyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQzNFLEtBQUs7SUFDTCxJQUFJLE1BQU1DLGVBQTRCLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDM0M7SUFDQTtJQUNBO0lBQ0EsSUFBSSxNQUFNRCxpQkFBOEIsQ0FBQyxFQUFFLEVBQUUsQ0FB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QUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUN6RixRQUFRLE1BQU1BLFdBQXdCLENBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQztJQUNsRixRQUFRLE1BQU1BLFdBQXdCLENBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQztJQUNsRixRQUFRLE1BQU1BLFdBQXdCLENBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQztJQUNsRixRQUFRLE1BQU1BLFdBQXdCLENBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0lBQ3hFLFFBQVEsTUFBTUEsV0FBd0IsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNsRSxRQUFRLE1BQU1BLFdBQXdCLENBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLElBQUksR0FBRyxDQUFDLENBQUM7SUFDOUYsUUFBUSxNQUFNQSxXQUF3QixDQUFDLEtBQUssRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDO0lBQzFGLFFBQVEsTUFBTUEsV0FBd0IsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENB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QUksVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVDLFFBQVEsTUFBTSxVQUFVLEdBQUcsSUFBSSxRQUFRLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQzFEO0lBQ0EsUUFBUSxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDMUM7SUFDQSxRQUFRLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDekMsS0FBSztBQUNMO0FBQ0E7SUFDQSxJQUFJLE1BQU0sVUFBVSxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUU7SUFDN0IsUUFBUSxNQUFNLElBQUksR0FBRyxJQUFJLENBQUM7QUFDMUI7SUFDQSxRQUFRLE1BQU0sU0FBUyxHQUFHLElBQUksVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVDLFFBQVEsTUFBTSxVQUFVLEdBQUcsSUFBSSxRQUFRLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQzFEO0lBQ0EsUUFBUSxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDLEdBQUcsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3RELFFBQVEsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsV0FBVyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7QUFDcEU7SUFDQSxRQUFRLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDekMsS0FBSztBQUNMO0lBQ0EsSUFBSSxNQUFNLFNBQVMsQ0FBQyxHQUFHLEVBQUU7SUFDekIsUUFBUSxNQUFNLElBQUksR0FBRyxJQUFJLENBQUM7SUFDMUIsUUFBUSxNQUFNLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQzFDO0lBQ0EsUUFBUSxNQUFNLElBQUksR0FB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U0FBUyxFQUFFO0lBQ3RELFlBQVksSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDL0QsU0FBUztJQUNULEtBQUs7QUFDTDtJQUNBLElBQUksTUFBTSxPQUFPLEdBQUc7SUFDcEIsS0FBSztBQUNMO0FBQ0E7SUFDQSxJQUFJLE1BQU0sVUFBVSxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUU7SUFDN0IsUUFBUSxNQUFNLElBQUksR0FBRyxJQUFJLENBQUM7QUFDMUI7SUFDQSxRQUFRRCxZQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFDekM7SUFDQSxRQUFRLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQ0QsV0FBUyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3pDLEtBQUs7QUFDTDtJQUNBLElBQUksTUFBTSxVQUFVLENBQUMsQ0FBQyxFQUFFLEdBQUcsRUFBRTtJQUM3QixRQUFRLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQztBQUMxQjtJQUNBLFFBQVFDLFlBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztBQUMxQztJQUNBLFFBQVEsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUFDRCxXQUFTLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDekMsS0FBSztBQUNMO0FBQ0E7SUFDQSxJQUFJLE1BQU0sVUFBVSxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUU7SUFDN0IsUUFBUSxNQUFNLElBQUksR0FBRyxJQUFJLENBQUM7QUFDMUI7SUFDQSxRQUFRRyxZQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDLEdBQUcsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3RELFFBQVFBLFlBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLFdBQVcsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO0FBQ3BFO0lBQ0EsUUFBUSxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUNELFdBQVMsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUN6QyxLQUFLO0FBQ0w7QUFDQTtJQUNBLElBQUksTUFBTSxTQUFTLENBQUMsR0FBRyxFQUFFO0lBQ3pCLFFBQVEsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQzFCLFFBQVEsTUFBTSxDQUFDLEdBQUcsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztBQUMxQztJQUNBLFFBQVEsTUFBTSxJQUFJLEdBQUcsSUFBSSxXQUFXLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQy9DO0lBQ0EsUUFBUSxPQUFPLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2QixLQUFLO0FBQ0w7SUFDQSxJQUFJLE1BQU0sU0FBUyxDQUFDLEdBQUcsRUFBRTtJQUN6QixRQUFRLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQztJQUMxQixRQUFRLE1BQU0sQ0FBQyxHQUFHLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDMUM7SUFDQSxRQUFRLE1BQU0sSUFBSSxHQUFHLElBQUksUUFBUSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUM1QztJQUNBLFFBQVEsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUN4QyxLQUFLO0FBQ0w7SUFDQSxJQUFJLE1BQU0sU0FBUyxDQUFDLEdBQUcsRUFBRTtJQUN6QixRQUFRLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQztJQUMxQixRQUFRLE1BQU0sQ0FBQyxHQUFHLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDMUM7SUFDQSxRQUFRLE1BQU0sSUFBSSxHQUFHLElBQUksV0FBVyxDQUFD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QUNBLFFBQVEsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO0FBQ3pDO0lBQ0EsUUFBUSxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3pDLEtBQUs7QUFDTDtJQUNBLElBQUksTUFBTSxVQUFVLENBQUMsQ0FBQyxFQUFFLEdBQUcsRUFBRTtJQUM3QixRQUFRLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQztBQUMxQjtJQUNBLFFBQVEsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQzFDO0lBQ0EsUUFBUSxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3pDLEtBQUs7QUFDTDtBQUNBO0lBQ0EsSUFBSSxNQUFNLFVBQVUsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFO0lBQzdCLFFBQVEsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDO0FBQzFCO0lBQ0EsUUFBUSxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDLEdBQUcsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3RELFFBQVEsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsV0FBVyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7QUFDcEU7SUFDQSxRQUFRLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDekMsS0FBSztBQUNMO0FBQ0E7SUFDQSxJQUFJLE1BQU0sU0FBUyxDQUFDLEdBQUcsRUFBRTtJQUN6QixRQUFRLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQztJQUMxQixRQUFRLE1BQU0sQ0FBQyxHQUFHLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDMUM7SUFDQSxRQUFRLE1BQU0sSUFBSSxHQUFHLElBQUksV0FBVyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUMvQztJQUNBLFFBQVEsT0FBTyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdkIsS0FBSztBQUNMO0lBQ0EsSUFBSSxNQUFNLFNBQVMsQ0FBQyxHQUFHLEVBQUU7SUFDekIsUUFBUSxNQUFNLElBQUksR0FBRyxJQUFJLENBQUM7SUFDMUIsUUFBUSxNQUFNLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQzFDO0lBQ0EsUUFBUSxNQUFNLElBQUksR0FBRyxJQUFJLFFBQVEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDNUM7SUFDQSxRQUFRLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDeEMsS0FBSztBQUNMO0lBQ0EsSUFBSSxNQUFNLFNBQVMsQ0FBQyxHQUFHLEVBQUU7SUFDekIsUUFBUSxNQUFNLElBQUksR0FBRyxJQUFJLENBQUM7SUFDMUIsUUFBUSxNQUFNLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQzFDO0lBQ0EsUUFBUSxNQUFNLElBQUksR0FBRyxJQUFJLFdBQVcsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDL0M7SUFDQSxRQUFRLE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLFdBQVcsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDL0MsS0FBSztBQUNMO0lBQ0EsSUFBSSxNQUFNLFVBQVUsQ0FBQyxHQUFHLEVBQUU7SUFDMUIsUUFBUSxNQUFNLElBQUksR0FBRyxJQUFJLENBQUM7SUFDMUIsUUFBUSxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUM7QUFDL0I7SUFDQSxRQUFRLElBQUksZUFBZSxHQUFHLE9BQU8sR0FBRyxJQUFJLFdBQVcsR0FBRyxJQUFJLENB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QyxHQUFHLEVBQUUsQ0FBQztJQUNyQixRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxNQUFNLEVBQUUsQ0FBQztJQUN4QixRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxNQUFNLEVBQUUsQ0FBQztJQUN4QixRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxNQUFNLEVBQUUsQ0FBQztJQUN4QixRQUFRLE9BQU8sQ0FBQyxDQUFDO0lBQ2pCLEtBQUs7QUFDTDtJQUNBLElBQUksU0FBUyxNQUFNLEdBQUc7SUFDdEIsUUFBUSxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFDckI7SUFDQSxRQUFRLE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzRCxRQUFRLFFBQVEsSUFBSSxDQUFDLENBQUM7SUFDdEIsUUFBUSxNQUFNLFNBQVMsR0FBRyxJQUFJLFFBQVEsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDeEQsUUFBUSxNQUFNLElBQUksR0FBRyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztBQUNsRDtJQUNBLFFBQVEsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsUUFBUSxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsSUFBSSxFQUFFLENBQUM7SUFDekUsUUFBUSxRQUFRLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUM7SUFDckMsUUFBUSxNQUFNLEtBQUssR0FBRyxJQUFJLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDaEQsUUFBUSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ25DLFlBQVksTUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FB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QUFDO0lBQ3RCLFFBQVEsTUFBTSxTQUFTLEdBQUcsSUFBSSxRQUFRLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3hELFFBQVEsTUFBTSxJQUFJLEdBQUcsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFDbEQ7SUFDQSxRQUFRLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLFFBQVEsR0FBRyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsRUFBRSxJQUFJLElBQUksQ0FBQyxDQUFDO0lBQzVFLFFBQVEsUUFBUSxJQUFJLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxFQUFFLElBQUksSUFBSSxDQUFDO0lBQ3pDLFFBQVEsTUFBTSxLQUFLLEdBQUcsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2hELFFBQVEsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUN2QyxZQUFZLE1BQU0sR0FBRyxHQUFHLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDakUsWUFBWSxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDdEUsWUFBWSxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsR0FBRyxDQUFDO0lBQzFCLFNBQVM7SUFDVCxRQUFRLE9BQU8sRUFBRSxDQUFDO0lBQ2xCLEtBQUs7QUFDTDtJQUNBLElBQUksU0FBUyxlQUFlLENBQUMsUUFBUSxFQUFFO0lBQ3ZDLFFBQVEsT0FBTyxFQUFFLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsUUFBUSxHQUFH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Q0FBQyxDQUFDO0FBQ2xDO0lBQ0E7SUFDQTtBQUNBO0lBQ0EsSUFBSSxNQUFNLGlCQUFpQixDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN2QyxJQUFJLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDM0IsSUFBSSxNQUFNLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ3hFO0lBQ0EsSUFBSSxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQzNCLElBQUksTUFBTSxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN4RSxJQUFJLE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ3hELElBQUksTUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO0FBQ2xFO0lBQ0EsSUFBSSxNQUFNLE1BQU0sQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDakMsSUFBSSxNQUFNLFdBQVcsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQzNDLElBQUksTUFBTSxNQUFNLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ2pDLElBQUksTUFBTSxXQUFXLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQztJQUMzQyxJQUFJLE1BQU0sTUFBTSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDeEMsSUFBSSxNQUFNLE1BQU0sQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDckMsSUFBSSxNQUFNLE1BQU0sQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUM7QUFDeEM7SUFDQSxJQUFJLElBQUksT0FBTyxDQUFDO0lBQ2hCLElBQUksT0FBTyxHQUFHLE1BQU0sTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzNELElBQUksTUFBTSxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ2hDLElBQUksT0FBTyxHQUFHLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDbEQsSUFBSSxRQUFRLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0FBQzdCO0lBQ0EsSUFBSSxJQUFJLE1BQU0sQ0FBQztJQUNmLElBQUksTUFBTSxHQUFHLE1BQU0sTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFELElBQUksTUFBTSxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQy9CLElBQUksTUFBTSxHQUFHLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDaEQsSUFBSSxRQUFRLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQzVCO0lBQ0EsSUFBSSxJQUFJLE1BQU0sQ0FBQztJQUNmLElBQUksTUFBTSxHQUFHLE1BQU0sTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFELElBQUksTUFBTSxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQy9CLElBQUksTUFBTSxHQUFHLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDaEQsSUFBSSxRQUFRLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQzVCO0lBQ0EsSUFBSSxNQUFNLEdBQUcsR0FBRyxJQUFJLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNwQyxJQUFJLEtBQUssQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMxQyxJQUFJLE1BQU0sR0FBRyxHQUFHLElBQUksVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3BDLElBQUksS0FBSyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFDLElBQUksTUFBTSxJQUFJLEdBQUcsSUFBSSxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDckMsSUFBSSxLQUFLLENBQUMsRUFBRSxDQUFDLGlCQUFpQixDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNwRCxJQUFJLE1BQU0sSUFBSSxHQUFHLElBQUksVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3JDLElBQUksS0FBSyxDQUFDLEVBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDcEQ7SUFDQSxJQUFJLE1BQU0sTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FB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O0FBQ1Q7QUFDQTtJQUNBLFFBQVEsTUFBTSxpQkFBaUIsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDM0M7SUFDQSxRQUFRLE1BQU0sV0FBVyxHQUFHLElBQUksU0FBUyxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7QUFDN0U7SUFDQSxRQUFRLE1BQU0sS0FBSyxHQUFHLElBQUksVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hDLFFBQVEsTUFBTSxNQUFNLEdBQUcsSUFBSSxRQUFRLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2xELFFBQVEsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNoRCxRQUFRLFdBQVcsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDL0IsUUFBUSxJQUFJLFFBQVEsR0FBRyxDQUFDLENBQUM7SUFDekIsUUFBUSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUMzQyxZQUFZLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDLE1BQU0sSUFBSSxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2hHLFlBQVksU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2hDLFNBQVM7QUFDVDtJQUNBLFFBQVEsTUFBTSxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ3hDLFFBQVEsTUFBTSxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDdEM7SUFDQSxRQUFRLFNBQVMsU0FB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UUFBUSxDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDO0lBQ2xELElBQUk7SUFDSixRQUFRLElBQUksTUFBTSxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsd0NBQXdDLENBQUMsQ0FBQztJQUMzRSxRQUFRLE9BQU8sS0FBSyxDQUFDO0lBQ3JCLEtBQUs7QUFDTDtJQUNBLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLFVBQVUsQ0FBQyxFQUFFO0lBQzVELFFBQVEsSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO0lBQzdELFFBQVEsT0FBTyxLQUFLLENBQUM7SUFDckIsS0FBSztJQUNMLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLFNBQVMsQ0FBQyxFQUFFO0lBQzFELFFBQVEsSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO0lBQzVELFFBQVEsT0FBTyxLQUFLLENBQUM7SUFDckIsS0FBSztJQUNMLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLFNBQVMsQ0FBQyxFQUFFO0lBQzFELFFBQVEsSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO0lBQzVELFFBQVEsT0FBTyxLQUFLLENBQUM7SUFDckIsS0FBSztJQUNMLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLFVBQVUsQ0FBQyxFQUFFO0lBQzVELFFBQVEsSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO0lB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QyxDQUFDO0FBQ3JEO0lBQ0EsUUFBUSxNQUFNLFdBQVcsR0FBRyxJQUFJLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDdkQsUUFBUSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDakIsUUFBUSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUM1QyxZQUFZLFdBQVcsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzdDLFlBQVksQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUM7SUFDdkMsU0FBUztBQUNUO0lBQ0EsUUFBUSxPQUFPLFdBQVcsQ0FBQztJQUMzQixLQUFLO0FBQ0w7QUFDQTtJQUNBLElBQUksZUFBZSxtQkFBbUIsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFO0lBQ3JELFFBQVEsTUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNwQyxRQUFRLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEMsUUFBUSxNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQztJQUM3QyxRQUFRLE1BQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUN4QixRQUFRLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDMUQsUUFBUSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLFVBQVUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQzFELFFBQVEsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDOUQsUUFBUSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ3RDLFlBQVksSUFBSSxDQUFDLElBQUksQ0FBQztJQUN0QixnQkFBZ0IsR0FBRyxFQUFFLE1BQU07SUFDM0IsZ0JBQWdCLE1BQU0sRUFBRSxlQUFlO0lBQ3ZDLGdCQUFnQixNQUFNLEVBQUU7SUFDeEIsb0JBQW9CLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQztJQUMzQyxvQkFBb0IsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDO0lBQzNDLG9CQUFvQixDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUM7SUFDN0MsaUJBQWlCO0lBQ2pCLGFBQWEsQ0FBQyxDQUFDO0lBQ2YsU0FBUztJQUNULFFBQVEsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLG1CQUFtQixFQUFFLE1BQU0sRUFBRTtJQUNyRSxZQUFZLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUNwQixZQUFZLENBQUMsR0FBRyxFQUFFLE9BQU8sQ0FBQztJQUMxQixZQUFZLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUNwQixTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ1osUUFBUSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0FBQ2xFO0lBQ0EsUUFBUSxNQUFNLEdBQUcsR0FBRyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ3JEO0lBQ0EsUUFBUSxPQUFPLEdBQUcsQ0FBQztJQUNuQixLQUFLO0FBQ0w7SUFDQTs7SUNoYUE7SUFDQTtBQUNBO0lBQ0E7QUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0FBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtBQUNBO0lBQ0E7SUFDQTtJQUNBO0FBSUE7SUFDZSxlQUFlLG9CQUFvQixDQUFDLFlBQVksRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRTtBQUNyRztJQUNBO0lBQ0EsSUFBSSxNQUFNLFlBQVksR0FBRyxDQUFDLElBQUksRUFBRSxRQUFRLENBQUMsQ0FBQztJQUMxQyxJQUFJLE1BQU0sT0FBTyxDQUFDLFlBQVksRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQ3BFO0lBQ0EsSUFBSSxPQUFPLE1BQU0sb0JBQW9CLENBQUMsWUFBWSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDeEY7O0lDN0JBO0lBQ0E7QUFDQTtJQUNBO0FBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtBQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7QUFDQTtJQUNBO0lBQ0E7SUFDQTtBQVVBO0lBQ2UsZUFBZSxnQkFBZ0IsQ0FBQyxXQUFXLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFO0FBQ2hHO0lBQ0EsSUFBSSxNQUFNLENBQUMsRUFBRSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsUUFBUSxDQUFDLEdBQUcsTUFBTUUsYUFBd0IsQ0FBQyxXQUFXLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ25HLElBQUksTUFBTSxJQUFJLEdBQUcsTUFBTU0sWUFBb0IsQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDN0QsSUFBSSxJQUFJLElBQUksQ0FBQyxRQUFRLElBQUksU0FBUyxFQUFFO0lBQ3BDLFFBQVEsTUFBTSxJQUFJLEtBQUssQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO0lBQ3BELEtBQUs7QUFDTDtJQUNBLElBQUksTUFBTSxLQUFLLEdBQUcsTUFBTVosYUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUN6QztJQUNBLElBQUksTUFBTSxTQUFTLEdBQUcsTUFBTXdELGFBQXVCLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQztBQUM1RTtJQUNBLElBQUksTUFBTSxLQUFLLEdBQUcsTUFBTXpDLGFBQTBCLENBQUMsV0FBVyxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDL0U7QUFDQTtJQUNBLElBQUksTUFBTSxHQUFHLEdBQUcsTUFBTThCLFlBQWlCLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDakQ7SUFDQSxJQUFJLE1BQU0sZ0JBQWdCLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzNELElBQUksZ0JBQWdCLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUM5QyxJQUFJLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUN6RCxRQUFRZ0IsVUFBZ0IsQ0FBQyxnQkFBZ0IsRUFBRSxLQUFLLEVBQUUsU0FBUyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzlFLEtBQUs7QUFDTDtJQUNBLElBQUksTUFBTSxlQUFlLEdBQUcsRUFBRSxDQUFDO0lBQy9CLElBQUksZUFBZSxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUM7SUFDL0IsSUFBSSxlQUFlLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN6RCxJQUFJLGVBQWUsQ0FBQyxLQUFLLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDMUUsSUFBSSxlQUFlLENBQUMsS0FBSyxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxlQUFlLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDaEksSUFBSUMsTUFBWSxDQUFDLGdCQUFnQixFQUFFLEtBQUssRUFBRSxlQUFlLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3RFLElBQUlBLE1BQVksQ0FBQyxnQkFBZ0IsRUFBRSxLQUFLLEVBQUUsZUFBZSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN2RSxJQUFJLGVBQWUsQ0FBQyxVQUFVLEdBQUcsZ0JBQWdCLENBQUMsTUFBTSxFQUFFLENBQUM7SUFDM0QsSUFBSSxlQUFlLENBQUMsS0FBSyxDQUFDLEtBQUssR0FBRyxRQUFRLENBQUMsS0FBSyxFQUFFLGVBQWUsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUM5RSxJQUFJLGVBQWUsQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLGVBQWUsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztBQUNsSTtJQUNBLElBQUksSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLGVBQWUsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDdEYsSUFBSSxJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsZUFBZSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUN0RjtJQUNBLElBQUksZUFBZSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDO0FBQ2pEO0lBQ0EsSUFBSSxlQUFlLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQztJQUM3QixJQUFJLElBQUksSUFBSSxFQUFFLGVBQWUsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO0FBQzFDO0lBQ0EsSUFBSSxTQUFTLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztBQUNsRDtJQUNBLElBQUksTUFBTUwsV0FBcUIsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFDN0M7SUFDQTtJQUNBLElBQUksTUFBTVQsV0FBd0IsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM5RDtJQUNBO0lBQ0EsSUFBSSxNQUFNQSxXQUF3QixDQUFDLEtBQUssRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlEO0lBQ0E7SUFDQSxJQUFJLE1BQU1BLFdBQXdCLENBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDOUQ7SUFDQTtJQUNBLElBQUksTUFBTUEsV0FBd0IsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM5RDtJQUNBO0lBQ0EsSUFBSSxNQUFNQSxXQUF3QixDQUFDLEtBQUssRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlEO0lBQ0EsSUFBSSxNQUFNLFFBQVEsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2hFLElBQUksTUFBTSxpQkFBaUIsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsV0FBVyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ2xILElBQUksTUFBTSxpQkFBaUIsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsV0FBVyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQ2xIO0lBQ0EsSUFBSSxNQUFNVSxjQUF3QixDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsU0FBUyxDQUFDLENBQUM7QUFDNUQ7SUFDQSxJQUFJLE1BQU0sS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ3hCLElBQUksTUFBTSxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7QUFDeEI7SUFDQSxJQUFJLE1BQU0sa0JBQWtCLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzdELElBQUlHLFVBQWdCLENBQUMsa0JBQWtCLEVBQUUsS0FBSyxFQUFFLGVBQWUsQ0FBQyxDQUFDO0FBQ2pFO0lBQ0EsSUFBSSxNQUFNLGdCQUFnQixHQUFHLGtCQUFrQixDQUFDLE1BQU0sRUFBRSxDQUFDO0FBQ3pEO0lBQ0EsSUFBSSxJQUFJLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDaEMsVUFBZSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDO0lBQ2pGLElBQUksSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQ0EsVUFBZSxDQUFDLGdCQUFnQixFQUFFLHFCQUFxQixDQUFDLENBQUMsQ0FBQztBQUN0RjtJQUNBLElBQUksT0FBTyxnQkFBZ0IsQ0FBQztJQUM1Qjs7SUMzR0E7SUFDQTtBQUNBO0lBQ0E7QUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0FBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtBQUNBO0lBQ0E7SUFDQTtJQUNBO0FBVUE7QUFDQTtJQUNlLGVBQWUsTUFBTSxDQUFDLFdBQVcsRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLEVBQUU7SUFDOUcsSUFBSSxNQUFNLFVBQVUsR0FBR2tCLGFBQWtCLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDekQsSUFBSSxPQUFPLENBQUMsVUFBVSxDQUFDLFVBQVUsSUFBSSxDQUFDO0lBQ3RDLFlBQVksVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDLEdBQUcsYUFBYSxDQUFDLE1BQU0sQ0FBQztJQUMzRCxJQUFJO0lBQ0osUUFBUSxJQUFJLE1BQU0sRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLGdFQUFnRSxDQUFDLENBQUM7SUFDbkcsUUFBUSxPQUFPLEtBQUssQ0FBQztJQUNyQixLQUFLO0lBQ0wsSUFBSSxJQUFJLFVBQVUsQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFO0lBQ2hDLFFBQVEsSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyw0Q0FBNEMsQ0FBQyxDQUFDO0lBQy9FLFFBQVEsT0FBTyxLQUFLLENBQUM7SUFDckIsS0FBSztBQUNMO0lBQ0EsSUFBSSxnQkFBZ0IsR0FBRyxRQUFRLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUNsRCxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLElBQUksZ0JBQWdCLENBQUMsRUFBRSxDQUFDLEVBQUU7SUFDdEQsUUFBUSxJQUFJLE1BQU0sRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLHVEQUF1RCxDQUFDLENBQUM7SUFDMUYsUUFBUSxPQUFPLEtBQUssQ0FBQztJQUNyQixLQUFLO0FBQ0w7QUFDQTtJQUNBLElBQUksTUFBTSxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLFFBQVEsQ0FBQyxHQUFHLE1BQU16QyxhQUF3QixDQUFDLFdBQVcsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbkcsSUFBSSxNQUFNLElBQUksR0FBRyxNQUFNTSxZQUFvQixDQUFDLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQztBQUM3RDtJQUNBLElBQUksSUFBSSxJQUFJLENBQUMsUUFBUSxJQUFJLFNBQVMsRUFBRTtJQUNwQyxRQUFRLE1BQU0sSUFBSSxLQUFLLENBQUMsMEJBQTBCLENBQUMsQ0FBQztJQUNwRCxLQUFLO0FBQ0w7QUFDQTtJQUNBLElBQUksTUFBTSxLQUFLLEdBQUcsTUFBTVosYUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUN6QztJQUNBLElBQUksTUFBTSxTQUFTLEdBQUcsTUFBTXdELGFBQXVCLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQztBQUM1RTtJQUNBLElBQUksTUFBTSxLQUFLLEdBQUcsTUFBTXpDLGFBQTBCLENBQUMsV0FBVyxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDL0U7SUFDQSxJQUFJLE1BQU0sR0FBRyxHQUFHLE1BQU1VLG1CQUF3QixDQUFDLFVBQVUsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO0FBQzdFO0lBQ0EsSUFBSSxNQUFNLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FDMUQsSUFBSSxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzlDLElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ3pELFFBQVFvQyxVQUFnQixDQUFDLGdCQUFnQixFQUFFLEtBQUssRUFBRSxTQUFTLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDOUUsS0FBSztBQUNMO0lBQ0EsSUFBSSxNQUFNLGVBQWUsR0FBRyxFQUFFLENBQUM7SUFDL0IsSUFBSSxlQUFlLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQztJQUMvQixJQUFJLGVBQWUsQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3pELElBQUksZUFBZSxDQUFDLEtBQUssQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUMxRSxJQUFJLGVBQWUsQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLGVBQWUsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNoSSxJQUFJQyxNQUFZLENBQUMsZ0JBQWdCLEVBQUUsS0FBSyxFQUFFLGVBQWUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdEUsSUFBSUEsTUFBWSxDQUFDLGdCQUFnQixFQUFFLEtBQUssRUFBRSxlQUFlLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3ZFLElBQUksZUFBZSxDQUFDLFVBQVUsR0FBRyxnQkFBZ0IsQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUMzRCxJQUFJLGVBQWUsQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFHLFFBQVEsQ0FBQyxLQUFLLEVBQUUsZUFBZSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzlFLElBQUksZUFBZSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsZUFBZSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0FBQ2xJO0lBQ0EsSUFBSSxJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsZUFBZSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN0RixJQUFJLElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxlQUFlLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ3RGO0lBQ0EsSUFBSSxlQUFlLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUM7QUFDakQ7SUFDQSxJQUFJLGVBQWUsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDO0lBQzdCLElBQUksZUFBZSxDQUFDLGdCQUFnQixHQUFHLGdCQUFnQixDQUFDO0lBQ3hELElBQUksZUFBZSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7QUFDNUM7SUFDQSxJQUFJLElBQUksSUFBSSxFQUFFLGVBQWUsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO0FBQzFDO0lBQ0EsSUFBSSxTQUFTLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztBQUNsRDtJQUNBLElBQUksTUFBTUwsV0FBcUIsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFDN0M7SUFDQTtJQUNBLElBQUksTUFBTVQsV0FBd0IsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM5RDtJQUNBO0lBQ0EsSUFBSSxNQUFNQSxXQUF3QixDQUFDLEtBQUssRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlEO0lBQ0E7SUFDQSxJQUFJLE1BQU1BLFdBQXdCLENBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDOUQ7SUFDQTtJQUNBLElBQUksTUFBTUEsV0FBd0IsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM5RDtJQUNBO0lBQ0EsSUFBSSxNQUFNQSxXQUF3QixDQUFDLEtBQUssRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzlEO0lBQ0EsSUFBSSxNQUFNLFFBQVEsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2hFLElBQUksTUFBTSxpQkFBaUIsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsV0FBVyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ2xILElBQUksTUFBTSxpQkFBaUIsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsV0FBVyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQ2xIO0lBQ0EsSUFBSSxNQUFNVSxjQUF3QixDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsU0FBUyxDQUFDLENBQUM7QUFDNUQ7SUFDQSxJQUFJLE1BQU0sS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ3hCLElBQUksTUFBTSxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7QUFDeEI7SUFDQSxJQUFJLE1BQU0sa0JBQWtCLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUM1RCxJQUFJRyxVQUFnQixDQUFDLGtCQUFrQixFQUFFLEtBQUssRUFBRSxlQUFlLENBQUMsQ0FBQztBQUNqRTtJQUNBLElBQUksTUFBTSxnQkFBZ0IsR0FBRyxrQkFBa0IsQ0FBQyxNQUFNLEVBQUUsQ0FBQztBQUN6RDtJQUNBLElBQUksSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQ2hDLFVBQWUsQ0FBQyxnQkFBZ0IsRUFBRSxxQkFBcUIsQ0FBQyxDQUFDLENBQUM7QUFDdEY7SUFDQSxJQUFJLE9BQU8sZ0JBQWdCLENBQUM7SUFDNUI7O0lDOUhlLGVBQWUsY0FBYyxDQUFDLFlBQVksRUFBRTtBQUMzRDtJQUNBLElBQUksTUFBTSxJQUFJLEdBQUcsTUFBTSxRQUFRLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3BELElBQUksT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQ3RCLElBQUksT0FBTyxJQUFJLENBQUMsQ0FBQyxDQUFDO0FBQ2xCO0lBQ0EsSUFBSSxPQUFPbkIsT0FBSyxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3hDOztJQ1ZBO0lBQ0E7QUFDQTtJQUNBO0FBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtBQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7QUFDQTtJQUNBO0lBQ0E7SUFDQTtBQTJCQTtJQUNlLGVBQWUsaUJBQWlCLENBQUMsS0FBSyxFQUFFLGlCQUFpQixFQUFFLGdCQUFnQixFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUU7SUFDN0csSUFBSSxNQUFNLEdBQUcsR0FBRyxNQUFNbUMsWUFBaUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUNqRDtJQUNBLElBQUksTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDeEMsSUFBSSxNQUFNLFFBQVEsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUN6QztJQUNBLElBQUksTUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNoQyxJQUFJLE1BQU0sR0FBRyxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDaEM7SUFDQSxJQUFJLE1BQU0sTUFBTSxHQUFHLE1BQU16RCxjQUFxQixDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFDbEUsSUFBSSxNQUFNLElBQUksR0FBRyxNQUFNQyxjQUF1QixDQUFDLGdCQUFnQixDQUFDLENBQUM7QUFDakU7QUFDQTtJQUNBLElBQUksTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDcEIsSUFBSSxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNwQixJQUFJLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3BCLElBQUksTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDcEIsSUFBSSxNQUFNLFNBQVMsR0FBRyxNQUFNLE1BQU0sRUFBRSxDQUFDO0lBQ3JDLElBQUksTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3RELElBQUksTUFBTSxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDMUIsSUFBSSxNQUFNLFNBQVMsR0FBRyxNQUFNLE1BQU0sRUFBRSxDQUFDO0lBQ3JDLElBQUksTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3RELElBQUksTUFBTSxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDMUI7SUFDQTtJQUNBLElBQUksTUFBTSxHQUFHLEdBQUcsTUFBTSxNQUFNLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDekMsSUFBSSxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDL0IsSUFBSSxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDeEI7SUFDQTtJQUNBLElBQUksTUFBTSxFQUFFLEdBQUcsTUFBTSxNQUFNLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDeEMsSUFBSSxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDOUIsSUFBSSxNQUFNLDBCQUEwQixDQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxjQUFjLEVBQUUsR0FBRyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQ2hJO0lBQ0E7SUFDQSxJQUFJLE1BQU0sRUFBRSxHQUFHLE1BQU0sTUFBTSxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQ3hDLElBQUksTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzlCLElBQUksTUFBTSwwQkFBMEIsQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxRQUFRLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsY0FBYyxFQUFFLEdBQUcsRUFBRSxNQUFNLENBQUMsQ0FBQztBQUNoSTtJQUNBO0lBQ0EsSUFBSSxNQUFNLEVBQUUsR0FBRyxNQUFNLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQztJQUN4QyxJQUFJLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUM5QixJQUFJLE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUN2QjtJQUNBO0lBQ0EsSUFBSSxNQUFNLEdBQUcsR0FBRyxNQUFNLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQztJQUN6QyxJQUFJLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUMvQixJQUFJLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUN4QjtJQUNBO0lBQ0EsSUFBSSxNQUFNLEdBQUcsR0FBRyxNQUFNLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQztJQUN6QyxJQUFJLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUMvQixJQUFJLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUN4QjtBQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0EsSUFBSSxNQUFNLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FDMUQ7SUFDQSxJQUFJLE1BQU0sU0FBUyxHQUFHLEVBQUUsQ0FBQztJQUN6QjtJQUNBLElBQUksU0FBUyxDQUFDLE1BQU0sSUFBSSxNQUFNLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDOUMsSUFBSSxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQzlDO0lBQ0EsSUFBSSxNQUFNLGNBQWMsR0FBRyxNQUFNLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQztJQUNwRCxJQUFJLFNBQVMsQ0FBQyxhQUFhLEdBQUcsRUFBRSxDQUFDO0lBQ2pDLElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLGNBQWMsRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUN6QyxRQUFRLE1BQU0sQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLEVBQUUsRUFBRSxDQUFDO0lBQy9CLFFBQVEsQ0FBQyxDQUFDLFVBQVUsR0FBRyxNQUFNLE1BQU0sRUFBRSxDQUFDO0lBQ3RDLFFBQVEsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLEdBQUcsTUFBTSxNQUFNLEVBQUUsQ0FBQztJQUN0QyxRQUFRLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFHLE1BQU0sTUFBTSxFQUFFLENBQUM7SUFDdkMsUUFBUSxDQUFDLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxNQUFNLE1BQU0sRUFBRSxDQUFDO0lBQ3hDLFFBQVEsQ0FBQyxDQUFDLFVBQVUsR0FBRyxNQUFNLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDN0MsUUFBUSxTQUFTLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4QyxRQUFRLFVBQVUsQ0FBQyxnQkFBZ0IsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDL0MsS0FBSztBQUNMO0lBQ0EsSUFBSSxNQUFNLGVBQWUsR0FBRyxFQUFFLENBQUM7SUFDL0IsSUFBSSxlQUFlLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQztJQUMvQixJQUFJLGVBQWUsQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQztJQUN6QyxJQUFJLGVBQWUsQ0FBQyxLQUFLLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDMUUsSUFBSSxlQUFlLENBQUMsS0FBSyxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ3pHLElBQUl5RSxNQUFZLENBQUMsZ0JBQWdCLEVBQUUsS0FBSyxFQUFFLGVBQWUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdEUsSUFBSUEsTUFBWSxDQUFDLGdCQUFnQixFQUFFLEtBQUssRUFBRSxlQUFlLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3ZFLElBQUksZUFBZSxDQUFDLFVBQVUsR0FBRyxnQkFBZ0IsQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUMzRCxJQUFJLGVBQWUsQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFHLFFBQVEsQ0FBQyxLQUFLLEVBQUUsZUFBZSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzlFLElBQUksZUFBZSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUMzRyxJQUFJLGVBQWUsQ0FBQyxVQUFVLEdBQUcsTUFBTSxDQUFDO0lBQ3hDLElBQUksZUFBZSxDQUFDLElBQUksR0FBRyxDQUFDLENBQUM7SUFDN0IsSUFBSSxTQUFTLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztBQUNsRDtBQUNBO0lBQ0E7SUFDQTtJQUNBO0FBQ0E7SUFDQSxJQUFJLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDdkMsSUFBSSxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUMxRDtJQUNBLElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ3pELFFBQVEsTUFBTSxDQUFDLEdBQUcsU0FBUyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM3QyxRQUFRLE1BQU0sT0FBTyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNwQyxRQUFRLE1BQU0sT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDcEMsUUFBUSxNQUFNLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3JDLFFBQVEsTUFBTSxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN0QyxRQUFRLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDdkMsS0FBSztBQUNMO0lBQ0EsSUFBSSxNQUFNLGtCQUFrQixHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FDNUQsSUFBSSxVQUFVLENBQUMsa0JBQWtCLEVBQUUsS0FBSyxFQUFFLGVBQWUsQ0FBQyxDQUFDO0FBQzNEO0lBQ0EsSUFBSSxNQUFNLGdCQUFnQixHQUFHLGtCQUFrQixDQUFDLE1BQU0sRUFBRSxDQUFDO0FBQ3pEO0lBQ0EsSUFBSSxJQUFJLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDakMsVUFBZSxDQUFDLGdCQUFnQixFQUFFLHFCQUFxQixDQUFDLENBQUMsQ0FBQztBQUN0RjtJQUNBLElBQUksTUFBTSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDdkIsSUFBSSxNQUFNLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztBQUN6QjtJQUNBLElBQUksT0FBTyxnQkFBZ0IsQ0FBQztBQUM1QjtJQUNBLElBQUksZUFBZSxJQUFJLENBQUMsTUFBTSxFQUFFO0lBQ2hDLFFBQVEsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7SUFDN0MsUUFBUSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxVQUFVLEVBQUU7SUFDaEQsWUFBWSxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDdEQsWUFBWSxNQUFNLElBQUksR0FBRyxNQUFNLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDOUMsWUFBWSxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDbkMsU0FBUztJQUNULEtBQUs7QUFDTDtJQUNBLElBQUksZUFBZSxNQUFNLEdBQUc7SUFDNUIsUUFBUSxNQUFNLElBQUksR0FBRyxNQUFNLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hELFFBQVEsT0FBTyxLQUFLLENBQUMsRUFBRSxDQUFDLG1CQUFtQixDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNyRCxLQUFLO0FBQ0w7SUFDQSxJQUFJLGVBQWUsTUFBTSxHQUFHO0lBQzVCLFFBQVEsTUFBTSxJQUFJLEdBQUcsTUFBTSxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4RCxRQUFRLE9BQU8sS0FBSyxDQUFDLEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDckQsS0FBSztBQUNMO0lBQ0EsSUFBSSxlQUFlLE9BQU8sQ0FBQyxDQUFDLEVBQUU7SUFDOUIsUUFBUSxNQUFNLElBQUksR0FBRyxJQUFJLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN6QyxRQUFRLEtBQUssQ0FBQyxFQUFFLENBQUMsaUJBQWlCLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMvQyxRQUFRLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMvQixLQUFLO0FBQ0w7SUFDQSxJQUFJLGVBQWUsT0FBTyxDQUFDLENBQUMsRUFBRTtJQUM5QixRQUFRLE1BQU0sSUFBSSxHQUFHLElBQUksVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3pDLFFBQVEsS0FBSyxDQUFDLEVBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQy9DLFFBQVEsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQy9CLEtBQUs7QUFDTDtBQUNBO0lBQ0E7O0lDdE1BO0lBQ0E7QUFDQTtJQUNBO0FBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtBQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7QUFDQTtJQUNBO0lBQ0E7SUFDQTtBQU9BO0lBQ0EsTUFBTSxtQkFBQ3hFLGtCQUFnQixDQUFDLEdBQUdxRCxPQUFLLENBQUM7QUFDakM7SUFDZSxlQUFlLHlCQUF5QixDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUU7SUFDMUUsSUFBSSxJQUFJLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLGlDQUFpQyxDQUFDLENBQUM7QUFDL0Q7SUFDQSxJQUFJLE1BQU0sQ0FBQyxFQUFFLEVBQUUsUUFBUSxDQUFDLEdBQUcsTUFBTUosYUFBd0IsQ0FBQyxRQUFRLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQy9FLElBQUksTUFBTSxJQUFJLEdBQUcsTUFBTU0sWUFBb0IsQ0FBQyxFQUFFLEVBQUUsUUFBUSxDQUFDLENBQUM7QUFDMUQ7SUFDQSxJQUFJLElBQUksTUFBTSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsdUJBQXVCLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBQ3JFO0lBQ0EsSUFBSSxJQUFJLEdBQUcsQ0FBQztJQUNaLElBQUksSUFBSSxJQUFJLENBQUMsUUFBUSxLQUFLLFNBQVMsRUFBRTtJQUNyQyxRQUFRLEdBQUcsR0FBRyxNQUFNLFNBQVMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ2xELEtBQUssTUFBTSxJQUFJLElBQUksQ0FBQyxRQUFRLEtBQUssT0FBTyxFQUFFO0lBQzFDLFFBQVEsR0FBRyxHQUFHLE1BQU0sT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2xDLEtBQUssTUFBTSxJQUFJLElBQUksQ0FBQyxVQUFVLElBQUksSUFBSSxDQUFDLFVBQVUsS0FBSyxrQkFBa0IsRUFBRTtJQUMxRSxRQUFRLEdBQUcsR0FBRyxNQUFNLGNBQWMsQ0FBQyxJQUFZLENBQUMsQ0FBQztJQUNqRCxLQUFLLE1BQU07SUFDWCxRQUFRLE1BQU0sSUFBSSxLQUFLLENBQUMsaUNBQWlDLENBQUMsQ0FBQztJQUMzRCxLQUFLO0FBQ0w7SUFDQSxJQUFJLE1BQU0sRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO0FBQ3JCO0lBQ0EsSUFBSSxJQUFJLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLGtDQUFrQyxDQUFDLENBQUM7QUFDaEU7SUFDQSxJQUFJLE9BQU8sR0FBRyxDQUFDO0lBQ2YsQ0FBQztBQUNEO0FBQ0E7SUFDQSxlQUFlLFNBQVMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRTtJQUM3QyxJQUFJLE1BQU0sS0FBSyxHQUFHLE1BQU1aLGFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDekMsSUFBSSxNQUFNLEdBQUcsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQ2xDO0lBQ0EsSUFBSSxNQUFNLFNBQVMsR0FBRyxNQUFNLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7QUFDM0U7SUFDQSxJQUFJLElBQUksSUFBSSxHQUFHO0lBQ2YsUUFBUSxRQUFRLEVBQUUsSUFBSSxDQUFDLFFBQVE7SUFDL0IsUUFBUSxLQUFLLEVBQUUsS0FBSyxDQUFDLElBQUk7SUFDekIsUUFBUSxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87QUFDN0I7SUFDQSxRQUFRLFVBQVUsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDO0FBQ3REO0lBQ0EsUUFBUSxTQUFTLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQztJQUNwRCxRQUFRLFVBQVUsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDO0lBQ3RELFFBQVEsVUFBVSxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUM7QUFDdEQ7SUFDQSxRQUFRLGVBQWUsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUM7SUFDckQsS0FBSyxDQUFDO0FBQ047SUFDQTtJQUNBO0lBQ0EsSUFBSSxNQUFNRyx3QkFBbUMsQ0FBQyxFQUFFLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQy9ELElBQUksSUFBSSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUM7SUFDakIsSUFBSSxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUM1QyxRQUFRLE1BQU0sSUFBSSxHQUFHLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN4QyxRQUFRLE1BQU0sQ0FBQyxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzFDLFFBQVEsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEIsS0FBSztJQUNMLElBQUksTUFBTUMsZ0JBQTJCLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDMUM7SUFDQSxJQUFJLElBQUksR0FBRy9DLGtCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ2xDO0lBQ0EsSUFBSSxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0FBQ0Q7QUFDQTtJQUNBLGVBQWUsT0FBTyxDQUFDLElBQUksRUFBRTtJQUM3QixJQUFJLE1BQU0sS0FBSyxHQUFHLE1BQU0yQyxhQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3pDO0lBQ0EsSUFBSSxJQUFJLElBQUksR0FBRztJQUNmLFFBQVEsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRO0lBQy9CLFFBQVEsS0FBSyxFQUFFLEtBQUssQ0FBQyxJQUFJO0lBQ3pCLFFBQVEsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPO0lBQzdCLFFBQVEsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLO0FBQ3pCO0lBQ0EsUUFBUSxFQUFFLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztJQUN0QyxRQUFRLEVBQUUsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO0FBQ3RDO0lBQ0EsUUFBUSxFQUFFLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztJQUN0QyxRQUFRLEVBQUUsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO0lBQ3RDLFFBQVEsRUFBRSxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7SUFDdEMsUUFBUSxFQUFFLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztJQUN0QyxRQUFRLEVBQUUsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO0lBQ3RDLFFBQVEsRUFBRSxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7SUFDdEMsUUFBUSxFQUFFLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztJQUN0QyxRQUFRLEVBQUUsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO0FBQ3RDO0lBQ0EsUUFBUSxHQUFHLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQztBQUN4QztJQUNBLFFBQVEsQ0FBQyxFQUFF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QUFRLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzdCLElBQUksRUFBRSxDQUFDLElBQUksR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMxQyxJQUFJLEVBQUUsQ0FBQyxJQUFJLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDNUQ7SUFDQSxJQUFJLElBQUksRUFBRSxHQUFHLFFBQVEsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDN0IsSUFBSSxJQUFJLEdBQUcsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQztBQUMzQjtJQUNBLElBQUksS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUNoQyxRQUFRLEdBQUcsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDcEMsUUFBUSxFQUFFLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNwQyxLQUFLO0FBQ0w7SUFDQSxJQUFJLElBQUksUUFBUSxHQUFHLFNBQVMsQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDMUM7SUFDQSxJQUFJLElBQUksTUFBTSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsMENBQTBDLENBQUMsQ0FBQztBQUN4RTtJQUNBLElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsR0FBRyxNQUFNLDhEQUFhLENBQUM7SUFDL0MsSUFBSSxPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBQ3BDO0lBQ0EsSUFBSSxT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QUcsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM3RDtJQUNBLElBQUksTUFBTSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsR0FBRyxPQUFPLEVBQUUsQ0FBQztBQUMvQjtJQUNBLElBQUksTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDO0FBQ2xCO0FBQ0E7SUFDQSxJQUFJLE1BQU0sY0FBYyxDQUFDLENBQUMsRUFBRSxXQUFXLENBQUMsQ0FBQztJQUN6QyxJQUFJLElBQUksVUFBVSxDQUFDLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3pDLElBQUksTUFBTSxlQUFlLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUN4QyxJQUFJLElBQUksVUFBVSxDQUFDLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3pDLElBQUksTUFBTSxlQUFlLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUN4QyxJQUFJLElBQUksVUFBVSxDQUFDLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3pDLElBQUksTUFBTSxlQUFlLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUN4QyxJQUFJLElBQUksVUFBVSxDQUFDLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3pDLElBQUksTUFBTSxTQUFTLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNoQyxJQUFJLElBQUksVUFBVSxDQUFDLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3pDLElBQUksTUFBTSxTQUFTLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNoQyxJQUFJLElBQUksVUFBVSxDQUFDLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FB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RUFBRSxNQUFNLEdBQUcsRUFBRSxFQUFFO0lBQ3hDLElBQUksTUFBTSxDQUFDLEdBQUcsSUFBSSxXQUFXLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3JDO0lBQ0EsSUFBSSxLQUFLLElBQUksS0FBSyxHQUFHLEVBQUUsR0FBRyxNQUFNLEVBQUUsS0FBSyxHQUFHLEVBQUUsRUFBRSxLQUFLLEVBQUUsRUFBRTtJQUN2RDtJQUNBLFFBQVEsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEVBQUU7SUFDbkMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDeEUsUUFBUSxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUU7SUFDeEMsWUFBWSxNQUFNLElBQUksR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ3RDLFlBQVksTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUN0QyxZQUFZLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMvQixZQUFZLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDbkMsWUFBWSxNQUFNLEVBQUUsR0FBRyxLQUFLLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDbEQsWUFBWSxNQUFNLEVBQUUsR0FBRyxLQUFL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LENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN0RCxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ25CLFlBQVksRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN0RCxTQUFTLENBQUM7SUFDVixLQUFLO0FBQ0w7SUFDQSxJQUFJLE9BQU8sS0FBSyxDQUFDLEVBQUUsRUFBRTtJQUNyQixRQUFRLE9BQU87SUFDZixZQUFZLEVBQUUsQ0FBQyxJQUFJO0lBQ25CLFlBQVksRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckQsWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BCLFlBQVksRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckQsU0FBUyxDQUFDO0FBQ1Y7SUFDQSxLQUFLO0FBQ0w7SUFDQSxJQUFJLE9BQU8sSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFO0lBQ3JDLFFBQVEsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNsQyxRQUFRLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQztBQUNsQjtJQUNBLFFBQVEsTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDakMsUUFBUSxNQUFNLElBQUksR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNuQyxRQUFRLE1BQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ25DLFFBQVEsTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDckM7SUFDQSxRQUFRLENBQUMsR0FBRyxHQUFHLENBQUM7QUFDaEI7SUFDQSxRQUFRLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO0FBQ3BDO0lBQ0EsUUFBUSxJQUFJLEVBQUUsR0FBRyxLQUFLLENBQUM7QUFDdkI7SUFDQSxRQUFRLEVBQUUsR0FBRyxFQUFFLENBQUM7SUFDaEIsUUFBUSxJQUFJLENBQUMsRUFBRTtJQUNmLFlBQVksRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDL0MsU0FBUztBQUNUO0lBQ0EsUUFBUSxPQUFPLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZCLEtBQUs7QUFDTDtJQUNBLElBQUksT0FBTyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRTtJQUM1QyxRQUFRLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbEMsUUFBUSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2xDLFFBQVEsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDO0FBQ2xCO0lBQ0EsUUFBUSxNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNqQyxRQUFRLE1BQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ25DLFFBQVEsTUFBTSxJQUFJLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbkMsUUFBUSxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztBQUNyQztJQUNBLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzNCO0lBQ0EsUUFBUSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNqQyxRQUFRLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3pDLFFBQVEsRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDekM7SUFDQSxRQUFRLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2xDLFFBQVEsRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDMUMsUUFBUSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUMxQztJQUNBLFFBQVEsRUFBRSxHQUFHLEVBQUUsQ0FBQztJQUNoQixRQUFRLElBQUksQ0FBQyxFQUFFO0lBQ2YsWUFBWSxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztJQUN6QyxZQUFZLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQy9DLFlBQVksRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDL0MsU0FBUztBQUNUO0lBQ0EsUUFBUSxPQUFPLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZCLEtBQUs7QUFDTDtJQUNBLElBQUksT0FBTyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFO0lBQ25ELFFBQVEsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNsQyxRQUFRLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbEMsUUFBUSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ2xDO0lBQ0EsUUFBUSxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7QUFDbEI7SUFDQSxRQUFRLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2pDLFFBQVEsTUFBTSxJQUFJLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDbkMsUUFBUSxNQUFNLElBQUksR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNuQyxRQUFRLE1BQU0sS0FBSyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBQ3JDO0lBQ0EsUUFBUSxNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNqQyxRQUFRLE1BQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ25DLFFBQVEsTUFBTSxJQUFJLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbkMsUUFBUSxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztBQUNyQztJQUNBLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQzdCO0lBQ0EsUUFBUSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQztJQUNuQyxRQUFRLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQzNDLFFBQVEsRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDM0MsUUFBUSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztBQUMzQztJQUNBLFFBQVEsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDcEMsUUFBUSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUM1QyxRQUFRLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQzVDLFFBQVEsRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDNUMsUUFBUSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUM1QyxRQUFRLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO0FBQzVDO0lBQ0EsUUFBUSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNyQyxRQUFRLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQzdDLFFB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QUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ2hELFlBQVksTUFBTSxJQUFJLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO0FBQ3hDO0lBQ0EsWUFBWSxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsSUFBSSxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDOUYsU0FBUztJQUNULEtBQUs7QUFDTDtJQUNBLElBQUksU0FBUyxDQUFDLEtBQUssRUFBRTtJQUNyQixRQUFRLE1BQU0sWUFBWSxHQUFHLENBQUMsS0FBSyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDakcsUUFBUSxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDM0QsS0FBSztBQUNMO0lBQ0EsSUFBSSxTQUFTLENBQUMsS0FBSyxFQUFFO0lBQ3JCLFFBQVEsTUFBTSxZQUFZLEdBQUcsQ0FBQyxLQUFLLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNqRyxRQUFRLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMzRCxLQUFLO0FBQ0w7SUFDQTtJQUNBLElBQUksV0FBVyxDQUFDLEtBQUssRUFBRTtJQUN2QixRQUFRLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUM7SUFDM0IsUUFBUSxNQUFNLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3hFO0lBQ0EsUUFBUSxNQUFNLE1BQU0sR0FBRyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7SUFDbEUsUUFBUSxNQUFNLElBQUksR0FBRyxNQUFNLEdBQUcsQ0FBQyxJQUFJLEVBQUUsR0FBRyxJQUFJLFNBQVMsQ0FBQyxNQUFNLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksVUFBVSxDQUFDLE1BQU0sR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDdkcsUUFBUSxJQUFJLEdBQUcsR0FBRyxJQUFJLFVBQVUsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDaEU7SUFDQTtJQUNBLFFBQVEsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDbkU7SUFDQTtJQUNBLFFBQVEsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7QUFDdEM7SUFDQTtJQUNBLFFBQVEsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUN0QjtJQUNBO0lBQ0EsUUFBUSxJQUFJLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUM7SUFDN0IsS0FBSztBQUNMO0lBQ0E7SUFDQSxJQUFJLFlBQVksQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFO0lBQzNCLFFBQVEsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQztJQUMzQixRQUFRLE1BQU0sTUFBTSxHQUFHLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7QUFDakU7SUFDQSxRQUFRLE1BQU0sTUFBTSxHQUFHLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUNsRSxRQUFRLE1BQU0sSUFBSSxHQUFHLE1BQU0sR0FBRyxDQUFDLElBQUksRUFBRSxHQUFHLElBQUksU0FBUyxDQUFDLE1BQU0sR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxVQUFVLENBQUMsTUFBTSxHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN2RyxRQUFRLElBQUksR0FBRyxHQUFHLElBQUksVUFBVSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUNoRTtJQUNBO0lBQ0EsUUFBUSxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztBQUM3RTtJQUNBO0lBQ0EsUUFBUSxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzlCO0lBQ0E7SUFDQSxRQUFRLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDdEI7SUFDQTtJQUNBLFFBQVEsSUFBSSxDQUFDLElBQUksR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDO0lBQzdCLEtBQUs7QUFDTDtJQUNBO0lBQ0EsSUFBSSxLQUFLLENBQUMsVUFBVSxFQUFFO0lBQ3RCLFFBQVEsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQztJQUMzQixRQUFRLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUN0QyxRQUFRLE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQztBQUM1QztJQUNBLFFBQVEsSUFBSSxJQUFJLEdBQUcsSUFBSSxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUN0RTtJQUNBLFFBQVEsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxJQUFJLEVBQUU7SUFDM0MsWUFBWSxJQUFJLFNBQVMsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDekY7SUFDQSxRQUFRLEtBQUssSUFBSSxDQUFDLEdBQUcsT0FBTyxHQUFHLE9BQU8sRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ3JELFlBQVksSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxPQUFPLENBQUMsRUFBRSxVQUFVLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM1RixZQUFZLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxPQUFPLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDL0MsZ0JBQWdCLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2pILGFBQWE7SUFDYixTQUFTO0FBQ1Q7SUFDQSxRQUFRLE9BQU8sSUFBSSxDQUFDO0lBQ3BCLEtBQUs7QUFDTDtJQUNBO0lBQ0EsSUFBSSxVQUFVLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRTtJQUN4QixRQUFRLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUM7QUFDM0I7SUFDQSxRQUFRLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztBQUM5QjtJQUNBLFFBQVEsSUFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsSUFBSSxFQUFFO0lBQzVDLFlBQVksSUFBSSxTQUFTLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3pGLFFBQVEsSUFBSSxRQUFRLEdBQUcsSUFBSSxVQUFVLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ3ZFO0lBQ0EsUUFBUSxJQUFJLElBQUksR0FBRyxFQUFFLENBQUM7QUFDdEI7SUFDQTtJQUNBLFFBQVEsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUNwQyxZQUFZLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQy9ELFlBQVksSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQzFDLFNBQVM7QUFDVDtJQUNBLFFBQVEsSUFBSSxRQUFRLEdBQUcsQ0FBQyxDQUFDO0lBR3pCLFFBQVEsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFFBQVEsRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUMzQyxZQUFZLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxRQUFRLEVBQUU7SUFDbEUsZ0JBQWdCLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxNQUFNO0lBQ2pDLGdCQUFnQixJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUM7SUFDNUIsZ0JBQWdCLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7QUFDakY7SUFDQSxnQkFBZ0IsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFFL0MsYUFBYTtJQUNiLFNBQVM7QUFDVDtJQUNBLFFBQVEsSUFBSSxDQUFDLElBQUksR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDO0lBQ2xDLEtBQUs7QUFDTDtJQUNBLElBQUksY0FBYyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUU7SUFDNUIsUUFBUSxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLEVBQUU7SUFDL0IsWUFBWSxNQUFNLElBQUksS0FBSyxDQUFDLHdGQUF3RixDQUFDLENBQUM7SUFDdEgsU0FBUztBQUNUO0lBQ0EsUUFBUSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDO0FBQzNCO0lBQ0EsUUFBUSxJQUFJLElBQUksR0FBRyxJQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ3RFO0lBQ0EsUUFBUSxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLElBQUksRUFBRTtJQUMzQyxZQUFZLElBQUksU0FBUyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxVQUFVLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUN6RjtJQUNBLFFBQVEsS0FBSyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDckQsWUFBWSxJQUFJLFdBQVcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzlDLFlBQVksSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsV0FBVyxDQUFDLEVBQUUsU0FBUztBQUN0RDtJQUNBLFlBQVksSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3JDLFlBQVksSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hGLFlBQVksSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQztJQUMxRSxTQUFTO0FBQ1Q7SUFDQSxRQUFRLE9BQU8sSUFBSSxDQUFDO0lBQ3BCLEtBQUs7QUFDTDtJQUNBLElBQUksZUFBZSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUU7SUFDN0IsUUFBUSxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLEVBQUU7SUFDL0IsWUFBWSxNQUFNLElBQUksS0FBSyxDQUFDLHdGQUF3RixDQUFDLENBQUM7SUFDdEgsU0FBUztBQUNUO0lBQ0EsUUFBUSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDO0FBQzNCO0lBQ0EsUUFBUSxJQUFJLElBQUksR0FBRyxJQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ3RFO0lBQ0EsUUFBUSxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLElBQUksRUFBRTtJQUMzQyxZQUFZLElBQUksU0FBUyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxVQUFVLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUN6RjtJQUNBLFFBQVEsSUFBSSxRQUFRLEdBQUcsQ0FBQyxDQUFDO0lBQ3pCLFFBQVEsSUFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQztJQUN2QyxRQUFRLElBQUksY0FBYyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLFFBQVEsQ0FBQyxDQUFDO0lBQzNELFFBQVEsSUFBSSxhQUFhLEdBQUcsTUFBTSxHQUFHLENBQUMsUUFBUSxHQUFHLENBQUMsSUFBSSxjQUFjLENBQUM7QUFDckU7SUFDQSxRQUFRLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDNUIsUUFBUSxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWMsR0FBRyxJQUFJLEdBQUcsYUFBYSxDQUFDLENBQUM7SUFDM0QsUUFBUSxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsUUFBUSxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQzNDLFlBQVksT0FBTyxDQUFDLEdBQUcsQ0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDekMsWUFBWSxLQUFLLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsYUFBYSxHQUFHLGNBQWMsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDakYsZ0JBQWdCLElBQUksTUFBTSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDbkMsZ0JBQWdCLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxNQUFNLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLGNBQWMsR0FBRyxhQUFhLENBQUM7SUFDaEYsZ0JBQWdCLElBQUksTUFBTSxHQUFHLE1BQU0sR0FBRyxDQUFDLENBQUM7QUFDeEM7SUFDQSxnQkFBZ0IsSUFBSSxXQUFXLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN2RCxnQkFBZ0IsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsV0FBVyxDQUFDLEVBQUUsU0FBUztBQUMxRDtJQUNBLGdCQUFnQixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDOUMsZ0JBQWdCLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDOUYsZ0JBQWdCLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFDO0lBQ2hGLGdCQUFnQixPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sR0FBRyxPQUFPLEdBQUcsTUFBTSxDQUFDLENBQUM7SUFDdkQsYUFBYTtJQUNiLFNBQVM7QUFDVDtJQUNBLFFBQVEsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ3JCLFFBQVEsT0FBTyxJQUFJLENBQUM7SUFDcEIsS0FBSztBQUNMO0lBQ0EsSUFBSSxrQkFBa0IsQ0FBQyxJQUFJLEVBQUU7SUFDN0IsUUFBUSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDO0FBQzNCO0lBQ0EsUUFBUSxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtBQUM5QztJQUNBLFlBQVksSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQy9CLFlBQVksSUFBSSxJQUFJLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ2xDO0lBQ0EsWUFBWSxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLEVBQUU7SUFDbkMsZ0JBQWdCLE1BQU0sSUFBSSxLQUFLLENBQUMsd0ZBQXdGLENBQUMsQ0FBQztJQUMxSCxhQUFhO0FBQ2I7SUFDQSxZQUFZLElBQUksUUFBUSxHQUFHLENBQUMsQ0FBQztJQUM3QixZQUFZLElBQUksU0FBUyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDOUMsWUFBWSxJQUFJLGVBQWUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsR0FBRyxRQUFRLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDdkUsWUFBWSxJQUFJLGNBQWMsR0FBRyxlQUFlLEdBQUcsQ0FBQyxDQUFDO0lBQ3JELFlBQVksSUFBSSxhQUFhLEdBQUcsU0FBUyxHQUFHLFFBQVEsR0FBRyxjQUFjLENBQUM7QUFDdEU7SUFDQTtJQUNBLFlBQVksSUFBSSxNQUFNLEdBQUcsSUFBSSxVQUFVLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsSUFBSSxFQUFFO0lBQy9ELGdCQUFnQixJQUFJLFNBQVMsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDdkg7SUFDQSxZQUFZLElBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7SUFDaEMsWUFBWSxJQUFJLENBQUMsSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUM7SUFDcEMsWUFBWSxNQUFNLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQztBQUM5QjtJQUNBO0lBQ0EsWUFBWSxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsUUFBUSxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQy9DLGdCQUFnQixJQUFJLElBQUksR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksY0FBYyxHQUFHLGFBQWEsQ0FBQztJQUNwRSxnQkFBZ0IsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUM1QyxvQkFBb0IsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3pFLGlCQUFpQjtBQUNqQjtJQUNBLGdCQUFnQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsY0FBYyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUM3RCxvQkFBb0IsSUFBSSxNQUFNLEdBQUcsSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDOUMsb0JBQW9CLElBQUksR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNqRyxvQkFBb0IsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ2xELGlCQUFpQjtJQUNqQixhQUFhO0FBQ2I7SUFDQTtJQUNBLFlBQVksSUFBSSxJQUFJLEdBQUcsYUFBYSxDQUFDO0lBQ3JDLFlBQVksSUFBSSxPQUFPLEdBQUcsYUFBYSxDQUFDO0lBQ3hDLFlBQVksS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxPQUFPLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDbkQsZ0JBQWdCLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzdFLGdCQUFnQixPQUFPLEVBQUUsQ0FBQztJQUMxQixhQUFhO0FBQ2I7SUFDQSxZQUFZLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxPQUFPLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDOUMsZ0JBQWdCLElBQUksTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzFDLGdCQUFnQixJQUFJLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDN0YsZ0JBQWdCLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUM5QyxhQUFhO0FBQ2I7SUFDQTtBQUNBO0lBQ0EsWUFBWSxJQUFJLEdBQUcsR0FBRyxFQUFFLENBQUM7SUFDekIsWUFBWSxJQUFJLE9BQU8sR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDO0lBQ2pDLFlBQVksS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLGVBQWUsRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUN0RCxnQkFBZ0IsT0FBTyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ2hELGFBQWE7SUFDYixZQUFZLElBQUksV0FBVyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUM7QUFDckM7SUFDQSxZQUFZLEtBQUssSUFBSSxDQUFDLEdBQUcsUUFBUSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDL0MsZ0JBQWdCLElBQUksUUFBUSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDckMsZ0JBQWdCLElBQUksSUFBSSxHQUFHLFFBQVEsR0FBRyxjQUFjLEdBQUcsYUFBYSxDQUFDO0lBQ3JFLGdCQUFnQixHQUFHLENBQUMsUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQ25DO0lBQ0EsZ0JBQWdCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDNUMsb0JBQW9CLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQztBQUM5RDtJQUNBLG9CQUFvQixJQUFJLENBQUMsS0FBSyxRQUFRLEVBQUU7SUFDeEMsd0JBQXdCLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzRyxxQkFBcUI7SUFDckIsaUJBQWlCO0lBQ2pCLGdCQUFnQixXQUFXLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDM0QsYUFBYTtBQUNiO0lBQ0E7SUFDQSxZQUFZLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxRQUFRLEVBQUUsQ0FBQyxFQUFFLEVBQUU7QUFDL0M7SUFDQSxnQkFBZ0IsSUFBSSxJQUFJLEdBQUcsQ0FBQyxHQUFHLGNBQWMsR0FBRyxhQUFhLENBQUM7SUFDOUQsZ0JBQWdCLElBQUksV0FBVyxHQUFHLElBQUksQ0FBQztJQUN2QyxnQkFBZ0IsSUFBSSxRQUFRLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNyQztJQUNBLGdCQUFnQixJQUFJLEtBQUssR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLGFBQWEsR0FBRyxjQUFjLENBQUM7SUFDckUsZ0JBQWdCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDaEQsb0JBQW9CLElBQUksTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzlDLG9CQUFvQixJQUFJLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNsRztJQUNBLG9CQUFvQixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQztBQUM5QztJQUNBO0lBQ0Esb0JBQW9CLElBQUksUUFBUSxLQUFLLENBQUMsRUFBRTtJQUN4Qyx3QkFBd0IsUUFBUSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDekMsd0JBQXdCLFdBQVcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNoRSxxQkFBcUIsTUFBTTtJQUMzQix3QkFBd0IsUUFBUSxFQUFFLENBQUM7SUFDbkMscUJBQXFCO0lBQ3JCLGlCQUFpQjtJQUNqQixhQUFhO0lBQ2IsU0FBUztJQUNULEtBQUs7QUFDTDtBQUNBO0lBQ0E7SUFDQSxJQUFJLGNBQWMsQ0FBQyxLQUFLLEVBQUU7SUFDMUIsUUFBUSxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxJQUFJLEVBQUU7SUFDN0MsWUFBWSxJQUFJLFNBQVMsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUNuRztJQUNBLFFBQVEsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLElBQUksSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNsRSxRQUFRLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ25JLFFBQVEsS0FBSyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDckQsWUFBWSxJQUFJLElBQUksR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7SUFDdEMsWUFBWSxLQUFLLENBQUMsR0FBRztJQUNyQixnQkFBZ0IsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHO0lBQzNCLG9CQUFvQixJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsSUFBSSxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztJQUM3RSxvQkFBb0IsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLElBQUksR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUM3RixpQkFBaUI7SUFDakIsZ0JBQWdCLENBQUMsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUU7SUFDOUIsYUFBYSxDQUFDO0lBQ2QsU0FBUztJQUNULFFBQVEsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRTtJQUN2QixZQUFZLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztJQUMxQyxZQUFZLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDdkUsU0FBUyxFQUFFO0lBQ1gsWUFBWSxNQUFNLElBQUksS0FBSyxDQUFDLDRCQUE0QixDQUFDLENBQUM7SUFDMUQsU0FBUztBQUNUO0lBQ0EsUUFBUSxJQUFJLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQztJQUMxQixLQUFLO0FBQ0w7SUFDQSxJQUFJLEtBQUssQ0FBQyxVQUFVLEVBQUUsVUFBVSxHQUFHLENBQUMsRUFBRTtJQUN0QyxRQUFRLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxVQUFVLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDN0MsWUFBWSxNQUFNLElBQUksR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7SUFDeEMsWUFBWSxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsSUFBSSxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUN2RixTQUFTO0FBQ1Q7SUFDQSxRQUFRLE1BQU0sVUFBVSxHQUFH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M0Q7SUFDQSxZQUFZLFVBQVUsQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUM7QUFDNUM7SUFDQSxZQUFZLE9BQU8sVUFBVSxDQUFDO0lBQzlCLFNBQVM7SUFDVCxLQUFLO0FBQ0w7SUFDQSxJQUFJLE9BQU8sa0JBQWtCLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRTtJQUMzQyxRQUFRLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUM7SUFDNUIsUUFBUSxJQUFJLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFO0lBQzlDLFlBQVksSUFBSSxTQUFTLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxVQUFVLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDakcsUUFBUSxJQUFJLFVBQVUsR0FBRyxJQUFJLFVBQVUsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDckQ7SUFDQTtJQUNBO0lBQ0EsUUFBUSxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDL0MsUUFBUSxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDdEM7SUFDQSxRQUFRLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQzlDLFlBQVksVUFBVSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM1QyxTQUFTO0FBQ1Q7SUFDQSxRQUFRLE9BQU8sVUFBVSxDQUFDO0lBQzFCLEtBQUs7QUFDTDtJQUNBLElBQUksS0FB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L0U7SUFDQSxJQUFJLE1BQU0sTUFBTSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLFlBQVksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzdHLElBQUksTUFBTSxNQUFNLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsWUFBWSxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxPQUFPLENBQUMsQ0FBQztJQUMzSCxJQUFJLE1BQU0sTUFBTSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLFlBQVksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLEdBQUcsT0FBTyxDQUFDLENBQUM7QUFDNUg7SUFDQSxJQUFJLElBQUksTUFBTSxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsK0JBQStCLENBQUMsQ0FBQztJQUM5RCxJQUFJLFdBQVcsQ0FBQyxNQUFNLEdBQUcsSUFBSSxXQUFXLENBQUMsSUFBSSxTQUFTLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQztJQUNwRixJQUFJLFdBQVcsQ0FBQyxNQUFNLEdBQUcsSUFBSSxXQUFXLENBQUMsSUFBSSxTQUFTLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQztJQUNwRixJQUFJLFdBQVcsQ0FBQyxNQUFNLEdBQUcsSUFBSSxXQUFXLENBQUMsSUFBSSxTQUFTLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQztBQUNwRjtJQUNBLElBQUksTUFBTSxNQUFNLENB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V0FBVyxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsSUFBSSxJQUFJLENBQUMsVUFBVSxHQUFHLENBQUMsRUFBRTtJQUMzRCxZQUFZLE1BQU0sSUFBSSxLQUFLLENBQUMscUNBQXFDLENBQUMsQ0FBQztJQUNuRSxTQUFTO0lBQ1QsUUFBUSxJQUFJLFdBQVcsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLElBQUksSUFBSSxDQUFDLFVBQVUsR0FBRyxDQUFDLEVBQUU7SUFDM0QsWUFBWSxNQUFNLElBQUksS0FBSyxDQUFDLHFDQUFxQyxDQUFDLENBQUM7SUFDbkUsU0FBUztJQUNULEtBQUs7QUFDTDtJQUNBLElBQUksZUFBZSxNQUFNLEdBQUc7SUFDNUI7SUFDQTtJQUNBLFFBQVEsSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyx1Q0FBdUMsQ0FBQyxDQUFDO0lBQzFFLFFBQVEsVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFDO0FBQzNCO0lBQ0EsUUFBUSxVQUFVLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzdDLFFBQVEsVUFBVSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUM3QyxRQUFRLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDN0MsUUFBUSxVQUFVLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzdDLFFBQVEsVUFBVSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUM3QyxRQUFRLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDN0MsUUFBUSxVQUFVLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzdDLFFBQVEsVUFBVSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUM3QztJQUNBO0lBQ0EsUUFBUSxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUMvQyxZQUFZLFVBQVUsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDMUUsU0FBUztBQUNUO0lBQ0E7SUFDQSxRQUFRLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDOUQsUUFBUSxVQUFVLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQzlELFFBQVEsVUFBVSxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztBQUM5RDtJQUNBLFFBQVEsVUFBVSxDQUFDLElBQUksR0FBRyxVQUFVLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDcEQsUUFBUSxJQUFJLE1BQU0sRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLHVCQUF1QixHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzdGO0lBQ0E7SUFDQSxRQUFRLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUMzQixRQUFRLFVBQVUsQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzlDLFFBQVEsVUFBVSxDQUFDLEtBQUssR0FBRyxVQUFVLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDckQsUUFBUSxJQUFJLE1BQU0sRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLHdCQUF3QixHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQy9GO0lBQ0E7SUFDQSxRQUFRLElBQUksTUFBTSxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsMEJBQTBCLENBQUMsQ0FBQztJQUM3RCxRQUFRLE1BQU0sUUFBUSxFQUFFLENBQUM7QUFDekI7SUFDQTtJQUNBLFFBQVEsSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0lBQ3RELFFBQVEsSUFBSSxPQUFPLEdBQUcsTUFBTSxXQUFXLENBQUMsQ0FBQyxDQUFDLG1CQUFtQixDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQztBQUN6RTtJQUNBO0lBQ0EsUUFBUSxLQUFLLENBQUMsYUFBYSxDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUMxQyxLQUFLO0FBQ0w7SUFDQSxJQUFJLGVBQWUsUUFBUSxHQUFHO0lBQzlCLFFBQVEsSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO0FBQ2hFO0lBQ0EsUUFBUSxJQUFJLE1BQU0sR0FBRyxJQUFJLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM1QyxRQUFRLElBQUksTUFBTSxHQUFHLElBQUksU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0FBQzVDO0lBQ0E7SUFDQSxRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM5QixRQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM5QjtJQUNBO0lBQ0EsUUFBUSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDO0lBQ3ZCLFFBQVEsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDbEQsWUFBWSxNQUFNLEtBQUssR0FBRyxDQUFDLEdBQUcsR0FBRyxDQUFDO0lBQ2xDO0lBQ0EsWUFBWSxNQUFNLENBQUMsR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsS0FBSyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0lBQzFELFlBQVksTUFBTSxDQUFDLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLEtBQUssR0FBRyxHQUFHLENBQUMsQ0FBQztJQUMxRCxZQUFZLE1BQU0sQ0FBQyxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxLQUFLLEdBQUcsR0FBRyxDQUFDLENBQUM7QUFDMUQ7SUFDQTtJQUNBO0lBQ0EsWUFBWSxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDckQ7SUFDQSxZQUFZLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3RDLFlBQVksRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUM5QztJQUNBLFlBQVksSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDdkQsWUFBWSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzlDO0lBQ0EsWUFBWSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUN2RCxZQUFZLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDOUM7SUFDQSxZQUFZLElBQUksR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDakQ7SUFDQTtJQUNBLFlBQVksSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDakcsWUFBWSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzlDO0lBQ0EsWUFBWSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNqRyxZQUFZLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDOUM7SUFDQSxZQUFZLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ2pHLFlBQVksRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUM5QztJQUNBLFlBQVksSUFBSSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUNqRDtJQUNBO0lBQ0EsWUFBWSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxLQUFLLEdBQUcsR0FBRyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDaEUsWUFBWSxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxJQUFJLENBQUMsVUFBVSxJQUFJLEdBQUcsQ0FBQyxDQUFDO0FBQy9EO0lBQ0E7SUFDQSxZQUFZLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLEtBQUssR0FBRyxHQUFHLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUNoRSxZQUFZLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQyxVQUFVLElBQUksR0FBRyxDQUFDLENBQUM7QUFDL0Q7SUFDQSxZQUFZLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQzVDLFNBQVM7QUFDVDtJQUNBO0lBQ0E7SUFDQSxRQUFRLE1BQU0sR0FBRyxNQUFNLEVBQUUsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDL0M7SUFDQTtJQUNBO0lBQ0EsUUFBUSxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUNsRCxZQUFZLE1BQU0sS0FBSyxHQUFHLENBQUMsR0FBRyxHQUFHLENBQUM7QUFDbEM7SUFDQSxZQUFZLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFD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QUMsQ0FBQyxDQUFDLENBQUM7QUFDMUc7SUFDQSxZQUFZLE1BQU0sRUFBRSxHQUFHLFdBQVcsQ0FBQyxFQUFFLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZELFlBQVksTUFBTSxFQUFFLEdBQUcsV0FBVyxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdkQsWUFBWSxNQUFNLEVBQUUsR0FBRyxXQUFXLENBQUMsRUFBRSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2RCxZQUFZLE1BQU0sRUFBRSxHQUFHLFdBQVcsQ0FBQyxFQUFFLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZELFlBQVksTUFBTSxFQUFFLEdBQUcsV0FBVyxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdkQsWUFBWSxNQUFNLEVBQUUsR0FBRyxXQUFXLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzRCxZQUFZLE1BQU0sRUFBRSxHQUFHLFdBQVcsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzNELFlBQVksTUFBTSxFQUFFLEdBQUcsV0FBVyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDM0Q7SUFDQSxZQUFZLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzRSxZQUFZLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzRSxZQUFZLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUMzRTtJQUNBLFlBQVksTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNwQyxZQUFZLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2hILFlBQVksTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUNuRCxZQUFZLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDdEMsWUFBWSxNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNuSDtJQUNBLFlBQVksSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQztJQUM3QixZQUFZLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ25ELGdCQUFnQixNQUFNLE1BQU0sR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsSUFBSSxDQUFDLENBQUM7QUFDN0Q7SUFDQSxnQkFBZ0IsTUFBTSxJQUFJLEdBQUcsV0FBVyxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDeEUsZ0JBQWdCLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDO0FBQ3JFO0lBQ0EsZ0JBQWdCLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ3BELGFBQWE7QUFDYjtJQUNBO0lBQ0EsWUFBWSxJQUFJLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDL0QsWUFBWSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDaEMsWUFBWSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDbEM7SUFDQSxZQUFZLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzNDLFlBQVksR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDOUM7SUFDQSxZQUFZLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzNDLFlBQVksR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDOUM7SUFDQSxZQUFZLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzNDLFlBQVksR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDOUM7SUFDQSxZQUFZLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNoQyxZQUFZLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztBQUNoQztJQUNBO0lBQ0EsWUFBWSxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDckQsWUFBWSxJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUM7SUFDeEIsWUFBWSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDckMsWUFBWSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ2hEO0lBQ0EsWUFBWSxJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUM7SUFDeEIsWUFBWSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEQsWUFBWSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ2hEO0lBQ0EsWUFBWSxJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUM7SUFDeEIsWUFBWSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEQsWUFBWSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ2hEO0lBQ0EsWUFBWSxJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUM7QUFDeEI7SUFDQSxZQUFZLElBQUksQ0FBQyxFQUFFLEVBQUUsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDckYsWUFBWSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzlDLFlBQVksR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUNoRDtJQUNBO0lBQ0EsWUFBWSxJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUM7SUFDeEIsWUFBWSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDM0QsWUFBWSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ2hEO0lBQ0EsWUFBWSxJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUM7SUFDeEIsWUFBWSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDM0QsWUFBWSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ2hEO0lBQ0EsWUFBWSxJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUM7SUFDeEIsWUFBWSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDM0QsWUFBWSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ2hEO0lBQ0EsWUFBWSxJQUFJLEdBQUcsR0FBRyxFQUFFLENBQUM7SUFDekIsWUFBWSxJQUFJLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBQ3RGO0lBQ0EsWUFBWSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzlDLFlBQVksR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUNoRDtJQUNBO0lBQ0EsWUFBWSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdkMsWUFBWSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsV0FBVyxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNuRSxZQUFZLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDL0M7SUFDQSxZQUFZLElBQUksR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLFdBQVcsQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEUsWUFBWSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ2pEO0FBQ0E7SUFDQSxZQUFZLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUMzRCxZQUFZLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFBRSxHQUFHLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztBQUNoRTtJ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QUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbkYsUUFBUSxXQUFXLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxDQUFDLEVBQUUsT0FBTyxHQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDakc7SUFDQTtJQUNBLFFBQVEsV0FBVyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDbEU7SUFDQTtJQUNBO0lBQ0EsUUFBUSxNQUFNLFNBQVMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM5RSxRQUFRLFdBQVcsQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxTQUFTLENBQUMsQ0FBQztJQUM3QyxRQUFRLFdBQVcsQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQ2xFO0lBQ0E7SUFDQTtJQUNBLFFBQVEsTUFBTSxVQUFVLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDL0UsUUFBUSxXQUFXLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDOUMsS0FBSztBQUNMO0lBQ0EsSUFBSSxlQUFlLE1BQU0sR0FBRztJQUM1QixRQUFRLElBQUksTUFBTSxFQUFFLE1B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RSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUNwRTtJQUNBO0lBQ0EsUUFBUSxNQUFNLE9BQU8sR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDbkY7SUFDQSxRQUFRLElBQUksR0FBRyxHQUFHLEtBQUssQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDO0lBQzNDLFFBQVEsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUM5RCxRQUFRLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUNsQyxRQUFRLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDNUM7SUFDQSxRQUFRLElBQUksR0FBRyxHQUFHLEtBQUssQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDO0lBQzNDLFFBQVEsR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ25ELFFBQVEsR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUM1QztJQUNBLFFBQVEsSUFBSSxHQUFHLEdBQUcsS0FBSyxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUM7SUFDM0MsUUFBUSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbkQsUUFBUSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzVDO0lBQ0EsUUFBUSxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsR0FBRyxDQUFDLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzNFO0lBQ0EsUUFBUSxJQUFJLEdBQUcsR0FBRyxLQUFLLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQztJQUMzQyxRQUFRLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBQzlFLFFBQVEsR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUM1QztJQUNBLFFBQVEsSUFBSSxHQUFHLEdBQUcsS0FBSyxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUM7SUFDM0MsUUFBUSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUM5RSxRQUFRLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDNUM7SUFDQSxRQUFRLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ2xDLFFBQVEsRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEtBQUssQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDbkQsUUFBUSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzFDO0lBQ0EsUUFBUSxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDdEQ7SUFDQSxRQUFRLFdBQVcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxVQUFVLENBQUMsSUFBSSxTQUFTLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBVSxHQUFHLENBQUMsSUFBSSxHQUFHLENBQUMsRUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFDbEc7SUFDQSxRQUFRLFdBQVcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxFQUFFLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDbkQsUUFBUSxXQUFXLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsRUFBRSxFQUFFLEtBQUssQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDcEUsUUFBUSxXQUFXLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsRUFBRSxFQUFFLEtBQUssQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDcEUsUUFBUSxXQUFXLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsRUFBRSxFQUFFLEtBQUssQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDcEUsUUFBUSxXQUFXLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDMUMsUUFBUSxXQUFXLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzdDLFFBQVEsV0FBVyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUMzRSxRQUFRLFdBQVcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDN0M7SUFDQSxRQUFRLElBQUksR0FBRyxHQUFHLFVBQVUsQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDM0UsUUFBUSxHQUFHLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDakQsUUFBUSxHQUFHLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxFQUFFLEVBQUUsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ2hELFFBQVEsR0FBRyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDaEMsUUFBUSxHQUFHLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUNyQztJQUNBLFFBQVEsV0FBVyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDL0I7SUFDQSxRQUFRLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNqRyxRQUFRLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztBQUM1QjtJQUNBLFFBQVEsSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUMvRDtJQUNBLFFBQVEsV0FBVyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDcEMsS0FBSztBQUNMO0lBQ0EsSUFBSSxTQUFTLFVBQVUsR0FBRztJQUMxQixRQUFRLFdBQVcsQ0FBQyxHQUFHLEdBQUcsSUFBSSxVQUFVLENBQUMsSUFBSSxTQUFTLENBQUMsT0FBTyxHQUFHLENBQUMsR0FBRyxHQUFHLENBQUMsRUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFDMUY7SUFDQSxRQUFRLFdBQVcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzQyxRQUFRLFdBQVcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVELFFBQVEsV0FBVyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDNUQsUUFBUSxXQUFXLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM1RCxRQUFRLFdBQVcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2pFLFFBQVEsV0FBVyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDakU7SUFDQSxRQUFRLFdBQVcsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFB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O0lBQy9ELElBQUksSUFBSSxNQUFNLEVBQUU7SUFDaEIsUUFBUSxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ25ELEtBQUs7QUFDTDtJQUNBLElBQUksTUFBTSxDQUFDLEdBQUcsVUFBVSxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN0RSxJQUFJLElBQUksTUFBTSxFQUFFO0lBQ2hCLFFBQVEsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDOUQsS0FBSztBQUNMO0lBQ0EsSUFBSSxNQUFNLENBQUMsR0FBRyxVQUFVLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ25FLElBQUksSUFBSSxNQUFNLEVBQUU7SUFDaEIsUUFBUSxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM5RCxLQUFLO0FBQ0w7SUFDQSxJQUFJLE1BQU0sQ0FBQyxHQUFHLFVBQVUsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUN2RCxJQUFJLElBQUksTUFBTSxFQUFFO0lBQ2hCLFFBQVEsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDOUQsS0FBSztBQUNMO0lBQ0EsSUFBSSxNQUFNLEdB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RSxDQUFDO0lBQ3hCLElBQUksTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQztJQUN4QixJQUFJLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQztJQUNuQixJQUFJLEdBQUcsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbEMsSUFBSSxHQUFHLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2xDLElBQUksR0FBRyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNsQyxJQUFJLEdBQUcsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbEMsSUFBSSxHQUFHLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2xDLElBQUksR0FBRyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNsQyxJQUFJLEdBQUcsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbEMsSUFBSSxHQUFHLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2xDLElBQUksR0FBRyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNsQyxJQUFJLEdBQUcsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbEMsSUFBSSxHQUFHLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQ3BDO0lBQ0EsSUFBSSxPQUFPLEdBQUcsQ0FBQztJQUNmLENBQUM7QUFDRDtJQUNBLFNBQVMsaUJBQWlCLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRTtJQUN6QyxJQUFJLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUM7SUFDeEIsSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsT0FBTyxLQUFLLENBQUM7SUFDM0MsSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsT0FBTyxLQUFLLENBQUM7SUFDM0MsSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsT0FBTyxLQUFLLENBQUM7SUFDM0MsSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsT0FBTyxLQUFLLENBQUM7SUFDM0MsSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEVBQUUsT0FBTyxLQUFLLENBQUM7SUFDNUMsSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEVBQUUsT0FBTyxLQUFLLENBQUM7SUFDNUMsSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEVBQUUsT0FBTyxLQUFLLENBQUM7SUFDNUMsSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUUsT0FBTyxLQUFLLENBQUM7SUFDN0MsSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsT0FBTyxLQUFLLENBQUM7SUFDOUMsSUFBSSxP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Q0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzNDLEtBQUs7SUFDTCxJQUFJLE9BQU8sRUFBRSxDQUFDO0lBQ2QsQ0FBQztBQUNEO0lBQ0EsU0FBUyxXQUFXLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRTtJQUN2RCxJQUFJLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUM7QUFDeEI7SUFDQSxJQUFJLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQztBQUNsQjtJQUNBLElBQUksTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztBQUN2RDtJQUNBLElBQUksSUFBSSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUMzRSxJQUFJLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDeEM7SUFDQSxJQUFJLElBQUksR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDM0UsSUFBSSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hDO0lBQ0EsSUFBSSxJQUFJLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3JEO0lBQ0EsSUFBSSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQzNDLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNuQyxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDdEM7SUFDQSxJQUFJLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDMUM7SUFDQSxJQUFJLE9BQU8sRUFBRSxDQUFDO0lBQ2QsQ0FBQztBQUNEO0lBQ0EsU0FBUyxVQUFVLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRTtJQUN0RCxJQUFJLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUM7SUFDeEIsSUFBSSxNQUFNLEVBQUUsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDO0lBQ3hCO0lBQ0EsSUFBSSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ25FLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNyRCxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDckQsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JELElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUMzQjtJQUNBLElBQUksTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUMxRDtJQUNBLElBQUksTUFBTSxJQUFJLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3hFLElBQUksTUFBTSxJQUFJLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3ZGLElBQUksTUFBTSxJQUFJLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3ZGO0lBQ0EsSUFBSSxNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsSUFBSSxDQUFDLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzNFO0lBQ0EsSUFBSSxNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0FBQ3hEO0lBQ0EsSUFBSSxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUMzRTtJQUNBLElBQUksTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN2RyxJQUFJLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDdkcsSUFBSSxNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0FBQ2pGO0lBQ0EsSUFBSSxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ2hFO0lBQ0EsSUFBSSxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDO0lBQzNCLElBQUksTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxFQUFFLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN2RCxJQUFJLE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ25FLElBQUksSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNsRCxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsRUFBRSxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDdkM7SUFDQSxJQUFJLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztBQUNyRDtJQUNBLElBQUksT0FBTyxDQUFDLENBQUM7SUFDYixDQUFDO0FBQ0Q7SUFDQSxTQUFTLFVBQVUsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFO0lBQ3JELElBQUksTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQztBQUN4QjtJQUNBLElBQUksSUFBSSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzlELElBQUksR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM1RCxJQUFJLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDNUQsSUFBSSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFELElBQUksR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUMxRDtJQUNBLElBQUksT0FBTyxHQUFHLENBQUM7SUFDZixDQUFDO0FBQ0Q7SUFDQSxTQUFTLFVBQVUsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxFQUFFLEVBQUU7SUFDbEQsSUFBSSxNQUFNLEVBQUUsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDO0lBQ3hCLElBQUksTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQztBQUN4QjtJQUNBLElBQUksSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUN0RSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDekQsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3pELElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUMxRCxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDMUQsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO0FBQ3ZEO0lBQ0EsSUFBSSxNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUs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eEIsSUFBZSxLQUFLLENBQUMsR0FBRztBQUN4QjtJQUNBLElBQUksSUFBSSxNQUFNLEdBQUcsRUFBRSxDQUFDO0lBQ3BCLElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDckMsUUFBUSxJQUFJLE1BQU0sSUFBSSxFQUFFLEVBQUUsTUFBTSxHQUFHLE1BQU0sR0FBRyxHQUFHLENBQUM7SUFDaEQsUUFBUSxNQUFNLEdBQUcsTUFBTSxHQUFHaUUsTUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZDLEtBQUs7QUFDTDtJQUNBLElBQUksT0FBTyxDQUFDLENBQUMsRUFBRUEsTUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUVBLE1BQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZELElBQUksQ0FBQyxFQUFFQSxNQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRUEsTUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDOUMsSUFBSSxDQUFDLEVBQUVBLE1BQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFQSxNQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM5QyxJQUFJLENBQUMsRUFBRUEsTUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUVBLE1BQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzlDLElBQUksQ0FBQyxFQUFFQSxNQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRUEsTUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDaEQsSUFBSSxDQUFDLEVBQUVBLE1BQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFQSxNQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNoRCxJQUFJLENBQUMsRUFBRUEsTUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUVBLE1BQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2hELElBQUksQ0FBQyxFQUFFQSxNQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRUEsTUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbEQsSUFBSSxDQUFDLEVBQUVBLE1BQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFQSxNQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNwRCxJQUFJLENBQUMsRUFBRUEsTUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDNUIsSUFBSSxDQUFDLEVBQUVBLE1BQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVCLElBQUksQ0FBQyxFQUFFQSxNQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FB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QU8sV0FBVyxDQUFDLENBQUMsQ0FBQztJQUN6QixJQUFJLE9BQU8sV0FBVyxDQUFDLE1BQU0sQ0FBQztJQUM5QixJQUFJLE9BQU8sV0FBVyxDQUFDLE1BQU0sQ0FBQztJQUM5QixJQUFJLE9BQU8sV0FBVyxDQUFDLE1BQU0sQ0FBQztJQUM5QixJQUFJLE9BQU8sV0FBVyxDQUFDLFNBQVMsQ0FBQztJQUNqQyxJQUFJLE9BQU8sV0FBVyxDQUFDLENBQUMsQ0FBQztJQUN6QixJQUFJLElBQUksVUFBVSxDQUFDLEVBQUUsRUFBRSxVQUFVLENBQUMsRUFBRSxFQUFFLENBQUM7QUFDdkM7SUFDQTtJQUNBLElBQUksSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUN6QyxJQUFJLE1BQU0sTUFBTSxFQUFFLENBQUM7QUFDbkI7SUFDQSxJQUFJLE9BQU8sV0FBVyxDQUFDLENBQUMsQ0FBQztJQUN6QixJQUFJLE9BQU8sV0FBVyxDQUFDLENBQUMsQ0FBQztJQUN6QixJQUFJLE9BQU8sV0FBVyxDQUFDLENBQUMsQ0FBQztJQUN6QixJQUFJLE9BQU8sV0FBVyxDQUFDLENBQUMsQ0FBQztJQUN6QixJQUFJLE9BQU8sV0FBVyxDQUFDLEVBQUUsQ0FBQztJQUMxQixJQUFJLE9BQU8sV0FBVyxDQUFDLEVBQUUsQ0FBQztJQUMxQixJQUFJLE9BQU8sV0FBVyxDQUFDLE1BQU0sQ0FBQztJQUM5QixJQUFJLE9BQU8sV0FBVyxDQUFDLE1BQU0sQ0FBQztJQUM5QixJQUFJLE9BQU8sV0FBVyxDQUFDLE1BQU0sQ0FBQztJQUM5QixJQUFJLE9BQU8sV0FBVyxDQUFDLEVBQUUsQ0FBQztJQUMxQixJQUFJLE9BQU8sV0FBVyxDQUFDLEVBQUUsQ0FBQztJQUMxQixJQUFJLE9BQU8sV0FBVyxDQUFDLEVBQUUsQ0FBQztJQUMxQixJQUFJLE9BQU8sV0FBVyxDQUFDLEVBQUUsQ0FBQztJQUMxQixJQUFJLE9BQU8sV0FBVyxDQUFDLEVBQUUsQ0FBQztJQUMxQixJQUFJLElBQUksVUFBVSxDQUFD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QUMsR0FBRyxDQUFDLElBQUksRUFBRSxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDdEQ7SUFDQSxnQkFBZ0IsSUFBSSxJQUFJLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLEtBQUssR0FBRyxHQUFHLENBQUMsQ0FBQztJQUMvRCxnQkFBZ0IsSUFBSSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQzVELGdCQUFnQixJQUFJLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3REO0lBQ0EsZ0JBQWdCLElBQUksSUFBSSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxLQUFLLEdBQUcsR0FBRyxDQUFDLENBQUM7SUFDL0QsZ0JBQWdCLElBQUksR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUM1RCxnQkFBZ0IsSUFBSSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUN0RDtJQUNBLGdCQUFnQixJQUFJLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO0FBQzNEO0lBQ0E7SUFDQSxnQkFBZ0IsSUFBSSxJQUFJLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLEtBQUssR0FBRyxHQUFHLENBQUMsQ0FBQztJQUMvRCxnQkFBZ0IsSUFBSSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLEVBQUUs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Q0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2xFLGdCQUFnQixJQUFJLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsR0FBRyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDcEU7QUFDQTtJQUNBO0lBQ0EsZ0JBQWdCLElBQUksR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JFLGdCQUFnQixHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3BEO0lBQ0EsZ0JBQWdCLElBQUksR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JFLGdCQUFnQixHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3BEO0lBQ0EsZ0JBQWdCLElBQUksR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JFLGdCQUFnQixHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3BEO0lBQ0EsZ0JBQWdCLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxF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QUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDM0QsU0FBUztBQUNUO0lBQ0EsUUFBUSxLQUFLLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQztJQUN0QixRQUFRLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQztJQUM3QixRQUFRLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDcEMsWUFBWSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzNELFNBQVM7QUFDVDtJQUNBLFFBQVEsS0FBSyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUM7SUFDdEIsUUFBUSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUM7SUFDN0IsUUFBUSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUM7SUFDOUIsUUFBUSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ3pDO0lBQ0E7SUFDQSxRQUFRLEtBQUssQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDO0lBQ3RCLFFBQVEsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQzNCLFFBQVEsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzlELFFBQVEsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUNwQyxZQUFZLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3JFLFNBQVM7QUFDVDtJQUNBO0lBQ0EsUUFBUSxLQUFLLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQztJQUN0QixRQUFRLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUMzQixRQUFRLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2RCxRQUFRLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDcEMsWUFBWSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNyRSxTQUFTO0FBQ1Q7SUFDQTtJQUNBLFFBQVEsS0FBSyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUM7SUFDdEIsUUFBUSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksR0FBRyxFQUFFLENBQUM7SUFDM0IsUUFBUSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQzdELFFBQVEsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDakUsUUFBUSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNqRTtJQUNBLFFBQVEsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQzNCO0lBQ0E7SUFDQSxRQUFRLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzdELFFBQVEsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDakUsUUFBUSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNqRTtJQUNBO0lBQ0EsUUFBUSxVQUFVLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDOUU7SUFDQSxRQUFRLElBQUksTUFBTSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMscUJBQXFCLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUNwRjtJQUNBO0lBQ0EsUUFBUSxXQUFXLENBQUMsRUFBRSxHQUFHLElBQUksVUFBVSxDQUFDLElBQUksU0FBUyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQztJQUMvRSxRQUFRLFdBQVcsQ0FBQyxFQUFFLEdBQUcsSUFBSSxVQUFVLENBQUMsSUFBSSxTQUFTLENBQUMsT0FBTyxDQUFDLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQy9FLFFBQVEsV0FBVyxDQUFDLEVBQUUsR0FBRyxJQUFJLFVBQVUsQ0FBQyxJQUFJLFNBQVMsQ0FBQyxPQUFPLENBQUMsRUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDL0UsUUFBUSxXQUFXLENBQUMsRUFBRSxHQUFHLElBQUksVUFBVSxDQUFDLElBQUksU0FBUyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQztJQUMvRSxRQUFRLFdBQVcsQ0FBQyxFQUFFLEdBQUcsSUFBSSxVQUFVLENBQUMsSUFBSSxTQUFTLENBQUMsT0FBTyxDQUFDLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQy9FO0lBQ0E7SUFDQSxRQUFRLE1BQU0sTUFBTSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLFlBQVksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFHLFFBQVEsTUFBTSxNQUFNLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsWUFBWSxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDMUcsUUFBUSxNQUFNLE1BQU0sQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxZQUFZLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMxRyxRQUFRLE1BQU0sTUFBTSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLFlBQVksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFHLFFBQVEsTUFBTSxNQUFNLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsWUFBWSxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDMUc7SUFDQTtJQUNBLFFBQVEsSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO0lBQzdELFFBQVEsS0FBSyxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsV0FBVyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDMUUsUUFBUSxLQUFLLENBQUMsYUFBYSxDQUFDLElBQUksRUFBRSxXQUFXLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMxRSxRQUFRLEtBQUssQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFLFdBQVcsQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzFFLFFBQVEsS0FBSyxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsV0FBVyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDMUUsUUFBUSxLQUFLLENBQUMsYUFBYSxDQUFDLElBQUksRUFBRSxXQUFXLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMxRSxRQUFRLEtBQUssQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFLFdBQVcsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzlFLFFBQVEsS0FBSyxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsV0FBVyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDOUUsUUFBUSxLQUFLLENBQUMsYUFBYSxDQUFDLElBQUksRUFBRSxXQUFXLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM5RSxRQUFRLEtBQUssQ0FBQyxhQUFhLENBQUMsR0FBRyxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3hFLFFBQVEsS0FBSyxDQUFDLGFBQWEsQ0FBQyxHQUFHLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDeEUsUUFBUSxLQUFLLENBQUMsYUFBYSxDQUFDLEdBQUcsRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN4RSxRQUFRLEtBQUssQ0FBQyxhQUFhLENBQUMsR0FBRyxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQ3hFO0lBQ0EsUUFBUSxVQUFVLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ2pFLFFBQVEsS0FBSyxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDMUUsUUFBUSxLQUFLLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxXQUFXLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUM1RSxRQUFRLEtBQUssQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQzVFLEtBQUs7QUFDTDtJQUNBLElBQUksZUFBZSxNQUFNLEdBQUc7SUFDNUIsUUFBUSxJQUFJLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLDZCQUE2QixDQUFDLENBQUM7SUFDL0Q7SUFDQSxRQUFRLE1BQU0sVUFBVSxHQUFHLElBQUksbUJBQW1CLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDMUQsUUFBUSxVQUFVLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNoRCxRQUFRLFVBQVUsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ3hELFFBQVEsVUFBVSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDeEQsUUFBUSxVQUFVLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUN4RCxRQUFRLFVBQVUsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ3hELFFBQVEsVUFBVSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDeEQsUUFBUSxVQUFVLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUN4RCxRQUFRLFVBQVUsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ3hELFFBQVEsVUFBVSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDeEQsUUFBUSxVQUFVLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUN2RCxRQUFRLFVBQVUsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3ZELFFBQVEsVUFBVSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDdkQsUUFBUSxVQUFVLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUN2RCxRQUFRLFVBQVUsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ3hELFFBQVEsVUFBVSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMs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QyxJQUFJLENBQUMsNkJBQTZCLENBQUMsQ0FBQztJQUMvRCxRQUFRLE1BQU0sV0FBVyxFQUFFLENBQUM7QUFDNUI7SUFDQSxRQUFRLElBQUksS0FBSyxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM1RCxRQUFRLEtBQUssR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzlCLFFBQVEsV0FBVyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDdkM7SUFDQSxRQUFRLE1BQU0sV0FBVyxHQUFHLFVBQVUsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNwRyxRQUFRLElBQUksTUFBTSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsc0NBQXNDLENBQUMsQ0FBQztJQUN4RSxRQUFRLE1BQU0sWUFBWSxHQUFHLFdBQVcsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0FBQzlEO0lBQ0E7SUFDQSxRQUFRLElBQUksWUFBWSxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsRUFBRTtJQUN2QyxZQUFZLE1BQU0sSUFBSSxLQUFLLENBQUMsQ0FBQywyQ0FBMkMsRUFBRSxZQUFZLENBQUMsTUFBTSxFQUFFLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDO0lBQ25ILFNBQVM7QUFDVDtJQUNBLFFBQVEsSUFBSSxXQUFXLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsVUFBVSxHQUFHLENBQUMsRUFBRTtJQUMvRCxZQUFZLE1BQU0sSUFBSSxLQUFLLENBQUMsOENBQThDLENBQUMsQ0FBQztJQUM1RSxTQUFTO0FBQ1Q7SUFDQTtJQUNBLFFBQVEsSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFD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QUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDMUYsb0JBQW9CLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUMxRixvQkFBb0IsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQzFGLG9CQUFvQixLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDeEUsb0JBQW9CLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDbEYsU0FBUztBQUNUO0lBQ0EsUUFBUSxlQUFlLFdBQVcsR0FBRztJQUNyQyxZQUFZLFdBQVcsQ0FBQyxJQUFJLEdBQUcsVUFBVSxDQUFDLGtCQUFrQjtJQUM1RCxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDdkYsb0JBQW9CLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUN4RSxvQkFBb0IsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNsRixTQUFTO0lBQ1QsS0FBSztBQUNMO0lBQ0EsSUFBSSxTQUFTLDJCQUEyQixHQUFHO0lBQzNDO0lBQ0EsUUFBUSxJQUFJLEdBQUcsR0FBRyxVQUFVLENBQUMsRUFBRSxDQUFDO0lBQ2hDLFFBQVEsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDN0MsWUFBWSxHQUFHLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqQyxTQUFTO0lBQ1QsUUFBUSxTQUFTLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQzlDO0lBQ0E7SUFDQTtBQUNBO0lBQ0E7SUFDQSxRQUFRLFdBQVcsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztBQUNuRTtJQUNBLFFBQVEsV0FBVyxDQUFDLFNBQVMsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxVQUFVLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQ25FO0lBQ0EsUUFBUSxXQUFXLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFDLEVBQUUsVUFBVSxDQUFDLEVBQUUsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQ2pIO0lBQ0E7SUFDQSxRQUFRLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUMvQztJQUNBLFFBQVEsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQztJQUN2QixRQUFRLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDdkMsWUFBWSxTQUFTLENBQUMsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDakcsWUFBWSxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJ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QUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFDbEU7SUFDQTtJQUNBLElBQUksSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0lBQ2pELElBQUksTUFBTSxFQUFFLEdBQUcsU0FBUyxDQUFDLEtBQUssRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFDdEU7SUFDQTtJQUNBLElBQUksSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0lBQ2pELElBQUksTUFBTSxFQUFFLEdBQUcsU0FBUyxDQUFDLEtBQUssRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLGFBQWEsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQ3hGO0lBQ0EsSUFBSSxJQUFJLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDO0lBQzdDLElBQUksTUFBTSxDQUFDLEdBQUcsUUFBUSxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLFVBQVUsRUFBRSxLQUFLLENBQUMsQ0FBQztBQUM1RDtJQUNBLElBQUksSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUM3QyxJQUFJLE1BQU0sQ0FBQyxHQUFHLFFBQVEsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztBQUNqRTtJQUNBLElBQUksSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUM3QyxJQUFJLE1BQU0sQ0FBQyxHQUFHLFFBQVEsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0FBQ2pEO0lBQ0EsSUFBSSxJ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QXVCLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRTtJQUMvQyxJQUFJLE9BQU8sTUFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLElBQUksTUFBTSxDQUFDLEVBQUUsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzdELENBQUM7QUFDRDtJQUNBLFNBQVMsc0JBQXNCLENBQUMsS0FBSyxFQUFFLFVBQVUsRUFBRTtJQUNuRCxJQUFJLE9BQU8sdUJBQXVCLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztJQUN4RSxDQUFDO0FBQ0Q7SUFDQSxTQUFTLG1CQUFtQixDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUU7SUFDM0MsSUFBSSxPQUFPLHNCQUFzQixDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztJQUM5RCxXQUFXLHNCQUFzQixDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztJQUM5RCxXQUFXLHNCQUFzQixDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztJQUM5RCxXQUFXLHNCQUFzQixDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztJQUM5RCxXQUFXLHNCQUFzQixDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztJQUM5RCxXQUFXLHNCQUFzQixDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztJQUM5RCxXQUFXLHNCQUFzQixDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztJQUM5RCxXQUFXLHNCQUFzQixDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztJQUM5RCxXQUFXLHNCQUFzQixDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsV0FBVyxDQUFD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RSxDQUFDO0lBQ2hCLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUM7SUFDbEIsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDN0IsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2pDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNqQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDakMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2pDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNqQyxJQUFJLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQztJQUNoQixJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQ2xCLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzdCLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNqQyxJQUFJLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQztJQUNoQixJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQ2xCLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQzdCO0lBQ0E7SUFDQTtJQUNBO0FBQ0E7SUFDQTtJQUNBLElBQUksS0FBSyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUM7SUFDbEIsSUFBSSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksR0FBRyxFQUFFLENBQUM7SUFDdkIsSUFBSSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztJQUMvQyxJQUFJLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDaEMsUUFBUSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzNELEtBQUs7QUFDTDtJQUNBO0lBQ0EsSUFBSSxLQUFLLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQztJQUNsQixJQUFJLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUN2QixJQUFJLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNuRCxJQUFJLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDaEMsUUFBUSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzNELEtBQUs7QUFDTDtJQUNBO0lBQ0EsSUFBSSxLQUFLLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQztJQUNsQixJQUFJLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUN2QixJQUFJLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDekQsSUFBSSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZELElBQUksS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUN2RDtJQUNBLElBQUksS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQ3ZCO0lBQ0E7SUFDQSxJQUFJLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZELElBQUksS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2RCxJQUFJLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdkQ7SUFDQTtJQUNBLElBQUksVUFBVSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFFLElBQUksVUFBVSxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztBQUMzRDtJQUNBLElBQUksVUFBVSxDQUFDLEdBQUcsR0FBRyxVQUFVLENBQUMsRUFBRSxDQUFDO0lBQ25DLElBQUksRUFBRSxDQUFDLFVBQVUsR0FBRyxDQUFDLENBQUM7SUFDdEIsSUFBSSxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUN2QyxRQUFRLFVBQVUsQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDbkQsUUFBUSxFQUFFLENBQUMsVUFBVSxJQUFJLENBQUMsQ0FBQztJQUMzQixLQUFLO0FBQ0w7SUFDQSxJQUFJLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUN2QixJQUFJLFVBQVUsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDakMsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDL0MsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDL0MsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDL0MsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDL0MsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDL0MsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDL0MsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDL0MsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDL0MsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDOUMsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDOUMsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDOUMsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDOUMsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDL0MsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDaEQsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDaEQsSUFBSSxVQUFVLENBQUMsS0FBSyxHQUFHLFVBQVUsQ0FBQyxZQUFZLEVBQUUsQ0FBQztBQUNqRDtJQUNBLElBQUksVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ3ZCLElBQUksVUFBVSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDM0MsSUFBSSxVQUFVLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN0RCxJQUFJLFVBQVUsQ0FBQyxDQUFDLEdBQUcsVUFBVSxDQUFDLFlBQVksRUFBRSxDQUFDO0FBQzdDO0lBQ0EsSUFBSSxJQUFJLE1BQU0sRUFBRTtJQUNoQixRQUFRLE1BQU0sQ0FBQyxJQUFJLENBQUMsd0JBQXdCLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUM3RSxRQUFRLE1BQU0sQ0FBQyxJQUFJLENBQUMsd0JBQXdCLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUM5RSxRQUFRLE1BQU0sQ0FBQyxJQUFJLENBQUMsd0JBQXdCLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMzRSxRQUFRLE1BQU0sQ0FB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QUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ3BDLFlBQVksVUFBVSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hFLFNBQVM7QUFDVDtJQUNBLFFBQVEsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDM0YsUUFBUSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3JFLFFBQVEsRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxFQUFFLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNyRSxRQUFRLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckUsUUFBUSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3JFLFFBQVEsRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxFQUFFLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNyRSxRQUFRLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDckU7SUFDQSxRQUFRLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzdDLEtBQUs7QUFDTDtJQUNBLElBQUksT0FBTyxHQUFHLENBQUM7SUFDZixDQUFDO0FBQ0Q7SUFDQSxTQUFTLFNBQVMsQ0FBQyxLQUFLLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRTtJQUNoRSxJQUFJLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUM7QUFDeEI7SUFDQSxJQUFJLE1BQU0sRUFBRSxHQUFHLG1CQUFtQixDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFDLEVBQUUsVUFBVSxDQUFDLEVBQUUsRUFBRSxLQUFLLENBQUMsQ0FBQztBQUN0RjtJQUNBO0lBQ0E7SUFDQTtJQUNBO0FBQ0E7SUFDQTtJQUNBLElBQUksSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO0lBQ3BELElBQUksSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsRUFBRSxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQy9ELElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxFQUFFLEVBQUUsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZFLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNwRyxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxFQUFFLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2RSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzFDLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3hCLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUN0QztJQUNBO0lBQ0EsSUFBSSxJQUFJLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLG1DQUFtQyxDQUFDLENBQUM7QUFDakU7SUFDQSxJQUFJLElBQUksR0FBRyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUM7SUFDdEIsSUFBSSxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ2hDLFFBQVEsSUFBSSxFQUFFLEdBQUcsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7SUFDckMsUUFBUSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdkUsUUFBUSxNQUFNLFdBQVcsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEQsUUFBUSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xFLFFBQVEsRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzNFO0lBQ0EsUUFBUSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM3QyxLQUFLO0FBQ0w7SUFDQSxJQUFJLE9BQU8sR0FBRyxDQUFDO0lBQ2YsQ0FBQztBQUNEO0lBQ0EsU0FBUyxTQUFTLENBQUMsS0FBSyxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFO0lBQzNFLElBQUksTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQztBQUN4QjtJQUNBLElBQUksTUFBTSxJQUFJLEdBQUcsbUJBQW1CLENBQUMsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLFVBQVUsQ0FBQyxDQUFDLEVBQUUsVUFBVSxDQUFDLEVBQUUsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQ3pIO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7QUFDQTtJQUNBO0lBQ0EsSUFBSSxJQUFJLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLENBQUM7SUFDcEQsSUFBSSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqRCxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxTQUFTLENBQUMsQ0FBQztJQUMvQixJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDdEM7SUFDQTtJQUNBLElBQUksSUFBSSxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO0lBQ3BELElBQUksTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUMxRCxJQUFJLE1BQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDL0UsSUFBSSxNQUFNLElBQUksR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQzlGLElBQUksTUFBTSxJQUFJLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUM5RixJQUFJLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQzlFO0lBQ0EsSUFBSSxNQUFNLElBQUksR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDdEgsSUFBSSxNQUFNLElBQUksR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDdEgsSUFBSSxNQUFNLElBQUksR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDdEgsSUFBSSxNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUMvRTtJQUNBLElBQUksSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDOUIsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3RDO0lBQ0E7SUFDQSxJQUFJLElBQUksTUFBTSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsbUNBQW1DLENBQUMsQ0FBQztJQUNqRSxJQUFJLElBQUksR0FBRyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUM7SUFDdEIsSUFBSSxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ2hDLFFBQVEsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDM0UsUUFBUSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUNqRTtJQUNBLFFBQVEsR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDL0MsS0FBSztBQUNMO0lBQ0EsSUFBSSxJQUFJLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLG1DQUFtQyxDQUFDLENBQUM7SUFDakUsSUFBSSxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ2hDLFFBQVEsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUMvRixRQUFRLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7QUFDcEY7SUFDQSxRQUFRLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNuRCxLQUFLO0FBQ0w7SUFDQSxJQUFJLE9BQU8sR0FBRyxDQUFDO0lBQ2YsQ0FBQztBQUNEO0lBQ0EsU0FBUyxRQUFRLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRTtJQUN2RCxJQUFJLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUM7SUFDeEIsSUFBSSxNQUFNLEVBQUUsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDO0FBQ3hCO0lBQ0EsSUFBSSxJQUFJLEtBQUssR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2RCxJQUFJLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDaEMsUUFBUSxLQUFLLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN0RSxLQUFLO0FBQ0w7SUFDQSxJQUFJLFVBQVUsQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDO0FBQzVCO0lBQ0EsSUFBSSxJQUFJLEtBQUssR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2RCxJQUFJLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDaEMsUUFBUSxLQUFLLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN0RSxLQUFLO0FBQ0w7SUFDQSxJQUFJLElBQUksS0FBSyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZELElBQUksS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUNoQyxRQUFRLEtBQUssR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3RFLEtBQUs7SUFDTCxJQUFJLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDaEMsUUFBUSxLQUFLLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN0RSxLQUFLO0FBQ0w7SUFDQSxJQUFJLFVBQVUsQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDMUUsSUFBSSxVQUFVLENBQUMsU0FBUyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztBQUNyRjtJQUNBLElBQUksSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsRUFBRSxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDcEUsSUFBSSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxFQUFFLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQztBQUNwRTtJQUNBLElBQUksT0FBTyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN6QyxDQUFDO0FBQ0Q7SUFDQSxTQUFTLFFBQVEsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUU7SUFDNUQsSUFBSSxNQUFNLEVBQUUsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDO0lBQ3hCLElBQUksTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQztBQUN4QjtJQUNBLElBQUksSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzlDLElBQUksSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBQzlDO0lBQ0EsSUFBSSxPQUFPLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDMUQsQ0FBQztBQUNEO0lBQ0EsU0FBUyxRQUFRLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUU7SUFDNUMsSUFBSSxNQUFNLEVBQUUsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDO0FBQ3hCO0lBQ0EsSUFBSSxPQUFPLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxFQUFFLEVBQUUsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzdELENBQUM7QUFDRDtJQUNBLGVBQWUsY0FBYyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRTtJQUNyRSxJQUFJLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUM7QUFDeEI7SUFDQSxJQUFJLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxFQUFFLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVELElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUM3QyxJQUFJLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDO0FBQzVCO0lBQ0EsSUFBSSxNQUFNLEVBQUUsR0FBRyxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztJQUNwQyxJQUFJLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUM7QUFDdEI7SUFDQSxJQUFJLE9BQU8sTUFBTSxLQUFLLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUN6RCxDQUFDO0FBQ0Q7QUFDQTtJQUNPLFNBQVMsbUJBQW1CLENBQUMsS0FBSyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFO0lBQ3pELElBQUksTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQztJQUN4QixJQUFJLE1BQU0sR0FBRyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUM7QUFDN0I7SUFDQSxJQUFJLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDM0MsSUFBSSxNQUFNLElBQUksR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDOUQ7SUFDQSxJQUFJLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQztJQUNsQixJQUFJLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDbEMsUUFBUSxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDO0lBQ2xELFFBQVEsTUFBTSxJQUFJLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDekM7SUFDQSxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDOUQsS0FBSztBQUNMO0lBQ0EsSUFBSSxPQUFPLEVBQUUsQ0FBQztJQUNkLENBQUM7QUFDRDtJQUNPLFNBQVMsbUJBQW1CLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRTtJQUNuRSxJQUFJLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUM7QUFDeEI7SUFDQSxJQUFJLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQztBQUNsQjtJQUNBLElBQUksTUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQztJQUNoQyxJQUFJLE1BQU0sQ0FBQyxHQUFHLEdBQUcsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDO0FBQ2pDO0lBQ0EsSUFBSSxNQUFNLElBQUksR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNsQyxJQUFJLE1BQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUM5RCxJQUFJLE1BQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ2xDLElBQUksTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztBQUNqRDtJQUNBLElBQUksSUFBSSxJQUFJLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUN4RSxJQUFJLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDbEMsUUFBUSxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQztJQUNuRCxRQUFRLE1BQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ2hEO0lBQ0EsUUFBUSxNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO0FBQ3BEO0lBQ0EsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDakMsS0FBSztBQUNMO0lBQ0EsSUFBSSxJQUFJLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNwRSxJQUFJLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDbEMsUUFBUSxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQztJQUNuRCxRQUFRLE1BQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsS0FBSyxF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LFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hFLElBQUksQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2hHLElBQUksQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2hHLElBQUksQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQy9GLElBQUksQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzdGLElBQUksQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xHLElBQUksQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUN0QyxJQUFJLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNsQjs7SUM1REE7SUFDQTtBQUNBO0lBQ0E7QUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0FBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtBQUNBO0lBQ0E7SUFDQTtJQUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7In0= diff --git a/build/snarkjs.min.js b/build/snarkjs.min.js index 1e6f1d85..0c46d146 100644 --- a/build/snarkjs.min.js +++ b/build/snarkjs.min.js @@ -1 +1,193 @@ -var snarkjs=function(t,e){"use strict";const a=[0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4];function i(t,e){return e&&10!=e?16==e?"0x"==t.slice(0,2)?BigInt(t):BigInt("0x"+t):void 0:BigInt(t)}const n=i;function o(t){const e=t.toString(16);return 4*(e.length-1)+a[parseInt(e[0],16)]}function l(t){return BigInt(t)>BigInt(e)}const d=s,u=c;function f(t){return(BigInt(t)&BigInt(1))==BigInt(1)}function g(t){let e=BigInt(t);const a=[];for(;e;)e&BigInt(1)?a.push(1):a.push(0),e>>=BigInt(1);return a}function h(t){if(t>BigInt(Number.MAX_SAFE_INTEGER))throw new Error("Number too big");return Number(t)}function p(t,e){return BigInt(t)+BigInt(e)}function _(t,e){return BigInt(t)-BigInt(e)}function m(t){return-BigInt(t)}function w(t,e){return BigInt(t)*BigInt(e)}function L(t,e){return BigInt(t)**BigInt(e)}function b(t,e){return BigInt(t)/BigInt(e)}function y(t,e){return BigInt(t)%BigInt(e)}function v(t,e){return BigInt(t)==BigInt(e)}function F(t,e){return BigInt(t)>BigInt(e)}function x(t,e){return BigInt(t)>=BigInt(e)}function C(t,e){return BigInt(t)&BigInt(e)}function S(t,e,a,i){const n="0000000"+a.toString(16),o=new Uint32Array(t.buffer,t.byteOffset+e,i/4),l=1+(4*(n.length-7)-1>>5);for(let t=0;t>5);for(let t=0;to[o.length-e-1]=t.toString(16).padStart(8,"0"))),i(o.join(""),16)}function B(t,e,a){a=a||t.byteLength,e=e||0;const n=new DataView(t.buffer,t.byteOffset+e,a),o=new Array(a/4);for(let t=0;t=0?BigInt(t):-BigInt(t)},add:p,band:C,bitLength:o,bits:g,bor:function(t,e){return BigInt(t)|BigInt(e)},bxor:function(t,e){return BigInt(t)^BigInt(e)},div:b,e:n,eq:v,exp:function(t,e){return BigInt(t)**BigInt(e)},fromArray:function(t,e){let a=BigInt(0);e=BigInt(e);for(let i=0;i>=BigInt(1)}return a},neg:m,neq:function(t,e){return BigInt(t)!=BigInt(e)},one:T,pow:L,shiftLeft:s,shiftRight:c,shl:d,shr:u,square:function(t){return BigInt(t)*BigInt(t)},sub:_,toArray:function(t,e){const a=[];let i=BigInt(t);for(e=BigInt(e);i;)a.unshift(Number(i%e)),i/=e;return a},toLEBuff:z,toNumber:h,toRprBE:E,toRprLE:S,toString:P,zero:I});function O(t,e,a){if(r(a))return t.one;const i=g(a);if(0==i.length)return t.one;let n=e;for(let a=i.length-2;a>=0;a--)n=t.square(n),i[a]&&(n=t.mul(n,e));return n}function q(t){if(t.m%2==1)if(v(y(t.p,4),1))if(v(y(t.p,8),1))if(v(y(t.p,16),1))!function(t){t.sqrt_q=L(t.p,t.m),t.sqrt_s=0,t.sqrt_t=_(t.sqrt_q,1);for(;!f(t.sqrt_t);)t.sqrt_s=t.sqrt_s+1,t.sqrt_t=b(t.sqrt_t,2);let e=t.one;for(;t.eq(e,t.one);){const a=t.random();t.sqrt_z=t.pow(a,t.sqrt_t),e=t.pow(t.sqrt_z,2**(t.sqrt_s-1))}t.sqrt_tm1d2=b(_(t.sqrt_t,1),2),t.sqrt=function(t){const e=this;if(e.isZero(t))return e.zero;let a=e.pow(t,e.sqrt_tm1d2);const i=e.pow(e.mul(e.square(a),t),2**(e.sqrt_s-1));if(e.eq(i,e.negone))return null;let n=e.sqrt_s,o=e.mul(t,a),l=e.mul(o,a),r=e.sqrt_z;for(;!e.eq(l,e.one);){let t=e.square(l),i=1;for(;!e.eq(t,e.one);)t=e.square(t),i++;a=r;for(let t=0;t>>0,t[n]=(t[n]^t[e])>>>0,t[n]=(t[n]<<16|t[n]>>>16&65535)>>>0,t[i]=t[i]+t[n]>>>0,t[a]=(t[a]^t[i])>>>0,t[a]=(t[a]<<12|t[a]>>>20&4095)>>>0,t[e]=t[e]+t[a]>>>0,t[n]=(t[n]^t[e])>>>0,t[n]=(t[n]<<8|t[n]>>>24&255)>>>0,t[i]=t[i]+t[n]>>>0,t[a]=(t[a]^t[i])>>>0,t[a]=(t[a]<<7|t[a]>>>25&127)>>>0}class M{constructor(t){t=t||[0,0,0,0,0,0,0,0],this.state=[1634760805,857760878,2036477234,1797285236,t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],0,0,0,0],this.idx=16,this.buff=new Array(16)}nextU32(){return 16==this.idx&&this.update(),this.buff[this.idx++]}nextU64(){return p(w(this.nextU32(),4294967296),this.nextU32())}nextBool(){return 1==(1&this.nextU32())}update(){for(let t=0;t<16;t++)this.buff[t]=this.state[t];for(let e=0;e<10;e++)U(t=this.buff,0,4,8,12),U(t,1,5,9,13),U(t,2,6,10,14),U(t,3,7,11,15),U(t,0,5,10,15),U(t,1,6,11,12),U(t,2,7,8,13),U(t,3,4,9,14);var t;for(let t=0;t<16;t++)this.buff[t]=this.buff[t]+this.state[t]>>>0;this.idx=0,this.state[12]=this.state[12]+1>>>0,0==this.state[12]&&(this.state[13]=this.state[13]+1>>>0,0==this.state[13]&&(this.state[14]=this.state[14]+1>>>0,0==this.state[14]&&(this.state[15]=this.state[15]+1>>>0)))}}function k(t){let e=new Uint8Array(t);if(void 0!==globalThis.crypto)globalThis.crypto.getRandomValues(e);else for(let a=0;a>>0;return e}let R=null;function N(){return R||(R=new M(function(){const t=k(32),e=new Uint32Array(t.buffer),a=[];for(let t=0;t<8;t++)a.push(e[t]);return a}()),R)}class j{constructor(t,e,a){this.F=e,this.G=t,this.opMulGF=a;let i=e.sqrt_t||e.t,n=e.sqrt_s||e.s,o=e.one;for(;e.eq(e.pow(o,e.half),e.one);)o=e.add(o,e.one);this.w=new Array(n+1),this.wi=new Array(n+1),this.w[n]=this.F.pow(o,i),this.wi[n]=this.F.inv(this.w[n]);let l=n-1;for(;l>=0;)this.w[l]=this.F.square(this.w[l+1]),this.wi[l]=this.F.square(this.wi[l+1]),l--;this.roots=[],this._setRoots(Math.min(n,15))}_setRoots(t){for(let e=t;e>=0&&!this.roots[e];e--){let t=this.F.one;const a=1<>1,r=V(t,e,a-1,i,2*n),s=V(t,e,a-1,i+n,2*n),c=new Array(o);for(let e=0;e>this.one,this.bitLength=o(this.p),this.mask=(this.one<>this.one;this.nqr=this.two;let a=this.pow(this.nqr,e);for(;!this.eq(a,this.negone);)this.nqr=this.nqr+this.one,a=this.pow(this.nqr,e);for(this.s=0,this.t=this.negone;(this.t&this.one)==this.zero;)this.s=this.s+1,this.t=this.t>>this.one;this.nqr_to_t=this.pow(this.nqr,this.t),q(this),this.FFT=new j(this,this,this.mul.bind(this)),this.fft=this.FFT.fft.bind(this.FFT),this.ifft=this.FFT.ifft.bind(this.FFT),this.w=this.FFT.w,this.wi=this.FFT.wi,this.shift=this.square(this.nqr),this.k=this.exp(this.nqr,2**this.s)}e(t,e){let a;if(e?16==e&&(a=BigInt("0x"+t)):a=BigInt(t),a<0){let t=-a;return t>=this.p&&(t%=this.p),this.p-t}return a>=this.p?a%this.p:a}add(t,e){const a=t+e;return a>=this.p?a-this.p:a}sub(t,e){return t>=e?t-e:this.p-e+t}neg(t){return t?this.p-t:t}mul(t,e){return t*e%this.p}mulScalar(t,e){return t*this.e(e)%this.p}square(t){return t*t%this.p}eq(t,e){return t==e}neq(t,e){return t!=e}lt(t,e){return(t>this.half?t-this.p:t)<(e>this.half?e-this.p:e)}gt(t,e){return(t>this.half?t-this.p:t)>(e>this.half?e-this.p:e)}leq(t,e){return(t>this.half?t-this.p:t)<=(e>this.half?e-this.p:e)}geq(t,e){return(t>this.half?t-this.p:t)>=(e>this.half?e-this.p:e)}div(t,e){return this.mul(t,this.inv(e))}idiv(t,e){if(!e)throw new Error("Division by zero");return t/e}inv(t){if(!t)throw new Error("Division by zero");let e=this.zero,a=this.p,i=this.one,n=t%this.p;for(;n;){let t=a/n;[e,i]=[i,e-t*i],[a,n]=[n,a-t*n]}return e=this.p?a-this.p:a}bor(t,e){const a=(t|e)&this.mask;return a>=this.p?a-this.p:a}bxor(t,e){const a=(t^e)&this.mask;return a>=this.p?a-this.p:a}bnot(t){const e=t^this.mask;return e>=this.p?e-this.p:e}shl(t,e){if(Number(e)=this.p?a-this.p:a}{const a=this.p-e;return Number(a)>a:this.zero}}shr(t,e){if(Number(e)>e;{const a=this.p-e;if(Number(a)=this.p?e-this.p:e}return 0}}land(t,e){return t&&e?this.one:this.zero}lor(t,e){return t||e?this.one:this.zero}lnot(t){return t?this.zero:this.one}sqrt_old(t){if(t==this.zero)return this.zero;if(this.pow(t,this.negone>>this.one)!=this.one)return null;let e=this.s,a=this.nqr_to_t,i=this.pow(t,this.t),n=this.pow(t,this.add(this.t,this.one)>>this.one);for(;i!=this.one;){let t=this.square(i),o=1;for(;t!=this.one;)o++,t=this.square(t);let l=a;for(let t=0;tthis.p>>this.one&&(n=this.neg(n)),n}normalize(t,e){if((t=BigInt(t,e))<0){let e=-t;return e>=this.p&&(e%=this.p),this.p-e}return t>=this.p?t%this.p:t}random(){const t=2*this.bitLength/8;let e=this.zero;for(let a=0;athis.half&&10==e){a="-"+(this.p-t).toString(e)}else a=t.toString(e);return a}isZero(t){return t==this.zero}fromRng(t){let e;do{e=this.zero;for(let a=0;a=this.p);return e=e*this.Ri%this.p,e}fft(t){return this.FFT.fft(t)}ifft(t){return this.FFT.ifft(t)}toRprLE(t,e,a){S(t,e,a,8*this.n64)}toRprBE(t,e,a){E(t,e,a,8*this.n64)}toRprBEM(t,e,a){return this.toRprBE(t,e,this.mul(this.R,a))}toRprLEM(t,e,a){return this.toRprLE(t,e,this.mul(this.R,a))}fromRprLE(t,e){return A(t,e,this.n8)}fromRprBE(t,e){return B(t,e,this.n8)}fromRprLEM(t,e){return this.mul(this.fromRprLE(t,e),this.Ri)}fromRprBEM(t,e){return this.mul(this.fromRprBE(t,e),this.Ri)}toObject(t){return t}}function Z(t,e){let a=t;void 0===e&&0==(e=Math.floor((o(t)-1)/8)+1)&&(e=1);const i=new Uint8Array(e),n=new DataView(i.buffer);let l=0;for(;l>=BigInt(32)):l+2<=e?(n.setUint16(l,Number(a&BigInt(65535)),!0),l+=2,a>>=BigInt(16)):(n.setUint8(l,Number(a&BigInt(255)),!0),l+=1,a>>=BigInt(8));if(a)throw new Error("Number does not fit in this length");return i}const H=[];for(let t=0;t<256;t++)H[t]=Q(t,8);function Q(t,e){let a=0,i=t;for(let t=0;t>=1;return a}function K(t,e){return(H[t>>>24]|H[t>>>16&255]<<8|H[t>>>8&255]<<16|H[255&t]<<24)>>>32-e}function X(t){return(0!=(4294901760&t)?(t&=4294901760,16):0)|(0!=(4278255360&t)?(t&=4278255360,8):0)|(0!=(4042322160&t)?(t&=4042322160,4):0)|(0!=(3435973836&t)?(t&=3435973836,2):0)|0!=(2863311530&t)}function Y(t,e){const a=new Uint8Array(e*t.length);for(let i=0;i0;)a>=4?(a-=4,e+=BigInt(n.getUint32(a))<=2?(a-=2,e+=BigInt(n.getUint16(a))<0;)o-4>=0?(o-=4,n.setUint32(o,Number(a&BigInt(4294967295))),a>>=BigInt(32)):o-2>=0?(o-=2,n.setUint16(o,Number(a&BigInt(65535))),a>>=BigInt(16)):(o-=1,n.setUint8(o,Number(a&BigInt(255))),a>>=BigInt(8));if(a)throw new Error("Number does not fit in this length");return i},bitReverse:K,buffReverseBits:function(t,e){const a=t.byteLength/e,i=X(a);if(a!=1<a){const i=t.slice(n*e,(n+1)*e);t.set(t.slice(a*e,(a+1)*e),n*e),t.set(i,a*e)}}},buffer2array:J,leBuff2int:function(t){let e=BigInt(0),a=0;const i=new DataView(t.buffer,t.byteOffset,t.byteLength);for(;a{a[i]=t(e[i])})),a}return e},stringifyFElements:function t(e,a){if("bigint"==typeof a||void 0!==a.eq)return a.toString(10);if(a instanceof Uint8Array)return e.toString(e.e(a));if(Array.isArray(a))return a.map(t.bind(this,e));if("object"==typeof a){const i={};return Object.keys(a).forEach((n=>{i[n]=t(e,a[n])})),i}return a},unstringifyBigInts:function t(e){if("string"==typeof e&&/^[0-9]+$/.test(e))return BigInt(e);if("string"==typeof e&&/^0x[0-9a-fA-F]+$/.test(e))return BigInt(e);if(Array.isArray(e))return e.map(t);if("object"==typeof e){if(null===e)return null;const a={};return Object.keys(e).forEach((i=>{a[i]=t(e[i])})),a}return e},unstringifyFElements:function t(e,a){if("string"==typeof a&&/^[0-9]+$/.test(a))return e.e(a);if("string"==typeof a&&/^0x[0-9a-fA-F]+$/.test(a))return e.e(a);if(Array.isArray(a))return a.map(t.bind(this,e));if("object"==typeof a){if(null===a)return null;const i={};return Object.keys(a).forEach((n=>{i[n]=t(e,a[n])})),i}return a}});const tt="undefined"!=typeof Buffer&&Buffer.constants&&Buffer.constants.MAX_LENGTH?Buffer.constants.MAX_LENGTH:1<<30;class et{constructor(t){this.buffers=[],this.byteLength=t;for(let e=0;e0;){const t=l+r>tt?tt-l:r,e=new Uint8Array(this.buffers[o].buffer,this.buffers[o].byteOffset+l,t);if(t==a)return e.slice();n||(n=a<=tt?new Uint8Array(a):new et(a)),n.set(e,a-r),r-=t,o++,l=0}return n}set(t,e){void 0===e&&(e=0);const a=t.byteLength;if(0==a)return;const i=Math.floor(e/tt);if(i==Math.floor((e+a-1)/tt))return t instanceof et&&1==t.buffers.length?this.buffers[i].set(t.buffers[0],e%tt):this.buffers[i].set(t,e%tt);let n=i,o=e%tt,l=a;for(;l>0;){const e=o+l>tt?tt-o:l,i=t.slice(a-l,a-l+e);new Uint8Array(this.buffers[n].buffer,this.buffers[n].byteOffset+o,e).set(i),l-=e,n++,o=0}}}function at(t,e,a,i){return async function(n){const o=Math.floor(n.byteLength/a);if(o*a!==n.byteLength)throw new Error("Invalid buffer size");const l=Math.floor(o/t.concurrency),r=[];for(let s=0;s=0;t--)this.w[t]=this.square(this.w[t+1]);if(!this.eq(this.w[0],this.one))throw new Error("Error calculating roots of unity");this.batchToMontgomery=at(t,e+"_batchToMontgomery",this.n8,this.n8),this.batchFromMontgomery=at(t,e+"_batchFromMontgomery",this.n8,this.n8)}op2(t,e,a){return this.tm.setBuff(this.pOp1,e),this.tm.setBuff(this.pOp2,a),this.tm.instance.exports[this.prefix+t](this.pOp1,this.pOp2,this.pOp3),this.tm.getBuff(this.pOp3,this.n8)}op2Bool(t,e,a){return this.tm.setBuff(this.pOp1,e),this.tm.setBuff(this.pOp2,a),!!this.tm.instance.exports[this.prefix+t](this.pOp1,this.pOp2)}op1(t,e){return this.tm.setBuff(this.pOp1,e),this.tm.instance.exports[this.prefix+t](this.pOp1,this.pOp3),this.tm.getBuff(this.pOp3,this.n8)}op1Bool(t,e){return this.tm.setBuff(this.pOp1,e),!!this.tm.instance.exports[this.prefix+t](this.pOp1,this.pOp3)}add(t,e){return this.op2("_add",t,e)}eq(t,e){return this.op2Bool("_eq",t,e)}isZero(t){return this.op1Bool("_isZero",t)}sub(t,e){return this.op2("_sub",t,e)}neg(t){return this.op1("_neg",t)}inv(t){return this.op1("_inverse",t)}toMontgomery(t){return this.op1("_toMontgomery",t)}fromMontgomery(t){return this.op1("_fromMontgomery",t)}mul(t,e){return this.op2("_mul",t,e)}div(t,e){return this.tm.setBuff(this.pOp1,t),this.tm.setBuff(this.pOp2,e),this.tm.instance.exports[this.prefix+"_inverse"](this.pOp2,this.pOp2),this.tm.instance.exports[this.prefix+"_mul"](this.pOp1,this.pOp2,this.pOp3),this.tm.getBuff(this.pOp3,this.n8)}square(t){return this.op1("_square",t)}isSquare(t){return this.op1Bool("_isSquare",t)}sqrt(t){return this.op1("_sqrt",t)}exp(t,e){return e instanceof Uint8Array||(e=z(n(e))),this.tm.setBuff(this.pOp1,t),this.tm.setBuff(this.pOp2,e),this.tm.instance.exports[this.prefix+"_exp"](this.pOp1,this.pOp2,e.byteLength,this.pOp3),this.tm.getBuff(this.pOp3,this.n8)}isNegative(t){return this.op1Bool("_isNegative",t)}e(t,e){if(t instanceof Uint8Array)return t;let a=n(t,e);l(a)?(a=m(a),F(a,this.p)&&(a=y(a,this.p)),a=_(this.p,a)):F(a,this.p)&&(a=y(a,this.p));const i=Z(a,this.n8);return this.toMontgomery(i)}toString(t,e){return P(A(this.fromMontgomery(t),0),e)}fromRng(t){let e;const a=new Uint8Array(this.n8);do{e=I;for(let a=0;a0&&(n=setTimeout((()=>{console.log("Shutting down thread due to inactivity"),u()}),o))}function r(t){const a=new Uint32Array(i.buffer,0,1);for(;3&a[0];)a[0]++;const n=a[0];if(a[0]+=t,a[0]+t>i.buffer.byteLength){const n=i.buffer.byteLength/65536;let o=Math.floor((a[0]+t)/65536)+1;o>e&&(o=e),i.grow(o-n),console.log("Growing memory to",i.buffer.byteLength/1024/1024,"MB")}return n}function s(t){const e=r(t.byteLength);return c(e,t),e}function c(t,e){new Uint8Array(i.buffer).set(new Uint8Array(e),t)}function d(t){if(clearTimeout(n),"INIT"===t[0].cmd)return l(t[0]);const e={vars:[],out:[]},o=new Uint32Array(i.buffer,0,1)[0];for(let n=0;n{this.reject=e,this.resolve=t}))}}let dt;const ut='(function thread(self) {\n const MAXMEM = 32767;\n let instance;\n let memory;\n let terminationTimeout = 500; // milliseconds\n let terminationTimer;\n\n if (self) {\n self.onmessage = function(e) {\n let data;\n if (e.data) {\n data = e.data;\n } else {\n data = e;\n }\n\n try {\n if (data[0].cmd === "INIT") {\n init(data[0]).then(function() {\n console.log("INIT DONE");\n self.postMessage({status: "initialized"});\n });\n } else if (data[0].cmd === "TERMINATE") {\n terminate();\n } else {\n let terminateAfterTask = false;\n if (data[data.length-1].cmd === "TERMINATE") {\n terminateAfterTask = true;\n data.pop();\n //terminationTimeout = 1;\n }\n const res = runTask(data);\n //self.postMessage(res);\n let transfers = [];\n for (let i=0; i memory.buffer.byteLength) {\n const currentPages = memory.buffer.byteLength / 0x10000;\n let requiredPages = Math.floor((u32[0] + length) / 0x10000)+1;\n if (requiredPages>MAXMEM) requiredPages=MAXMEM;\n memory.grow(requiredPages-currentPages);\n console.log("Growing memory to", memory.buffer.byteLength / 1024 / 1024, "MB");\n }\n return res;\n }\n\n function allocBuffer(buffer) {\n const p = alloc(buffer.byteLength);\n setBuffer(p, buffer);\n return p;\n }\n\n function getBuffer(pointer, length) {\n // const u8 = new Uint8Array(memory.buffer);\n // return new Uint8Array(u8.buffer, u8.byteOffset + pointer, length);\n return new Uint8Array(memory.buffer, pointer, length);\n }\n\n function setBuffer(pointer, buffer) {\n const u8 = new Uint8Array(memory.buffer);\n u8.set(new Uint8Array(buffer), pointer);\n }\n\n function runTask(task) {\n clearTimeout(terminationTimer);\n if (task[0].cmd === "INIT") {\n return init(task[0]);\n }\n const ctx = {\n vars: [],\n out: []\n };\n const u32a = new Uint32Array(memory.buffer, 0, 1);\n const oldAlloc = u32a[0];\n for (let i=0; i0) {\n terminationTimer = setTimeout( () => {\n console.log("Shutting down thread due to inactivity");\n terminate();\n }, terminationTimeout);\n }\n }\n\n function terminate() {\n clearTimeout(terminationTimer);\n instance = null;\n memory = null;\n if (self) {\n console.log("TERMINATE");\n self.postMessage({status: "terminated"});\n self.close();\n }\n }\n\n return runTask;\n})(self)';if(globalThis?.Blob){const t=(new TextEncoder).encode(ut),e=new Blob([t],{type:"application/javascript"});dt=URL.createObjectURL(e)}else dt="data:application/javascript;base64,"+globalThis.btoa(ut);class ft{constructor(){this.actionQueue=[],this.oldPFree=0}getOnMsg(t){const e=this;return function(a){let i;if(i=a&&a.data?a.data:a,i.error)throw e.working[t]=!1,e.pendingDeferreds[t].reject("Worker error: "+i.error),e.initializing[t]?(e.initializing[t]=!1,e.workers[t]=null):e.workers[t].postMessage([{cmd:"TERMINATE"}]),new Error("Worker error: "+i.error);i.status&&("initialized"===i.status?(e.initializing[t]=!1,e.initialized[t]=!0):"terminated"===i.status&&(e.initialized[t]=!1,e.initializing[t]=!1,e.workers[t]=null)),e.working[t]=!1,e.pendingDeferreds[t].resolve(i),e.processWorks()}}getOnError(t){const e=this;return function(a){throw e.working[t]=!1,e.pendingDeferreds[t].reject(a.message),new Error("Worker error: "+a.message)}}startWorker(t){this.workers[t]=new Worker(dt),this.workers[t].addEventListener("message",this.getOnMsg(t)),this.initializing[t]=!0,this.postAction(t,[{cmd:"INIT",init:st,code:this.wasmModule}]).then((()=>{this.initialized[t]=!0}))}startSyncOp(){if(0!==this.oldPFree)throw new Error("Sync operation in progress");this.oldPFree=this.u32[0]}endSyncOp(){if(0===this.oldPFree)throw new Error("No sync operation in progress");this.u32[0]=this.oldPFree,this.oldPFree=0}async postAction(t,e,a,i){if(this.working[t])throw new Error("Posting a job to a working worker");return this.working[t]=!0,this.pendingDeferreds[t]=i||new ct,await this.workers[t].postMessage(e,a),this.pendingDeferreds[t].promise}async processWorks(){for(let t=0;t0;t++)if(this.workers[t]&&this.initialized[t]&&!this.working[t]){const e=this.actionQueue.shift();this.postAction(t,e.data,e.transfers,e.deferred)}if(this.actionQueue.length>0){let t=0;for(let e=0;e=this.actionQueue.length)break;console.log(`Worker ${e} not initialized yet. Initializing...`),t++,await this.startWorker(e)}}}queueAction(t,e){const a=new ct;if(this.singleThread){const e=this.taskManager(t);a.resolve(e)}else this.actionQueue.push({data:t,transfers:e,deferred:a}),this.processWorks();return a.promise}resetMemory(){this.u32[0]=this.initalPFree}allocBuff(t){const e=this.alloc(t.byteLength);return this.setBuff(e,t),e}getBuff(t,e){return this.u8.slice(t,t+e)}setBuff(t,e){this.u8.set(new Uint8Array(e),t)}alloc(t){for(;3&this.u32[0];)this.u32[0]++;const e=this.u32[0];return this.u32[0]+=t,e}async terminate(){console.log("terminate!!!");for(let t=0;t=0;t--){if(!a.isZero(p))for(let t=0;tc&&(p=c),p<4096&&(p=4096),console.log("nChunks",_),console.log("effective nChunks",u/p);for(let e=0;e(r&&r.debug(`Multiexp end: ${s}: ${e}/${u}`),t))))}let m=await Promise.all(g),w=a.zero;for(let t=m.length-1;t>=0;t--)w=a.add(w,m[t]);return w}a.multiExp=async function(t,e,a,i){return await o(t,e,"jacobian",a,i)},a.multiExpAffine=async function(t,e,a,i){return await o(t,e,"affine",a,i)}}function _t(t,e){const a=t[e],i=t.Fr,n=a.tm;async function o(t,r,s,c,d,u){s=s||"affine",c=c||"affine";let f,g,h,p,_,m,w,L,b;"G1"==e?("affine"==s?(f=2*a.F.n8,p="g1m_batchToJacobian"):f=3*a.F.n8,g=3*a.F.n8,r&&(L="g1m_fftFinal"),w="g1m_fftJoin",m="g1m_fftMix",b="g1m_reversePermutation","affine"==c?(h=2*a.F.n8,_="g1m_batchToAffine"):h=3*a.F.n8):"G2"==e?("affine"==s?(f=2*a.F.n8,p="g2m_batchToJacobian"):f=3*a.F.n8,g=3*a.F.n8,r&&(L="g2m_fftFinal"),w="g2m_fftJoin",m="g2m_fftMix",b="g2m_reversePermutation","affine"==c?(h=2*a.F.n8,_="g2m_batchToAffine"):h=3*a.F.n8):"Fr"==e&&(f=a.n8,g=a.n8,h=a.n8,r&&(L="frm_fftFinal"),m="frm_fftMix",w="frm_fftJoin",b="frm_fftReversePermutation");let y=!1;Array.isArray(t)?(t=Y(t,f),y=!0):t=t.slice(0,t.byteLength),console.log("FFT input size:",t.byteLength," bytes");const v=t.byteLength/f,F=X(v);if(console.log("FFT points:",v," bits:",F),1<1<<28?new et(2*u[0].byteLength):new Uint8Array(2*u[0].byteLength);return f.set(u[0]),f.set(u[1],u[0].byteLength),f}(t,s,c,d,u):await async function(t,e,a,n,r){let s,c;s=t.slice(0,t.byteLength/2),c=t.slice(t.byteLength/2,t.byteLength);const d=[];[s,c]=await l(s,c,"fftJoinExt",i.one,i.shift,e,"jacobian",n,r),d.push(o(s,!1,"jacobian",a,n,r)),d.push(o(c,!1,"jacobian",a,n,r));const u=await Promise.all(d);let f;f=u[0].byteLength>1<<28?new et(2*u[0].byteLength):new Uint8Array(2*u[0].byteLength);return f.set(u[0]),f.set(u[1],u[0].byteLength),f}(t,s,c,d,u),y?J(e,h):e}let x,C;r&&(x=i.inv(i.e(v))),console.log("fnReversePermutation:",b);const S=[];S.push({cmd:"ALLOC",var:0,len:t.byteLength}),S.push({cmd:"SET",var:0,buff:t}),S.push({cmd:"CALL",fnName:b,params:[{var:0},{val:F},{var:0}]}),S.push({cmd:"GET",out:0,var:0,len:t.byteLength});const E=await n.queueAction(S,[t.buffer]);let A;t.set(E[0]);let B=Math.min(16384,v),P=v/B;for(;P=16;)P*=2,B/=2;const z=X(B),I=[];for(let e=0;e(d&&d.debug(`${u}: fft ${F} mix end: ${e}/${P}`),t))))}A=await Promise.all(I);for(let t=0;t(d&&d.debug(`${u}: fft ${F} join ${t}/${F} ${l+1}/${e} ${r}/${a/2}`),i))))}const l=await Promise.all(o);for(let t=0;t0;e--)C.set(A[e],t),t+=B*h,delete A[e];C.set(A[0].slice(0,(B-1)*h),t),delete A[0]}else for(let t=0;t65536&&(b=65536);const y=[];for(let e=0;e(u&&u.debug(`${f}: fftJoinExt End: ${e}/${L}`),t))))}const v=await Promise.all(y);let F,x;L*_>1<<28?(F=new et(L*_),x=new et(L*_)):(F=new Uint8Array(L*_),x=new Uint8Array(L*_));let C=0;for(let t=0;ti.s+1)throw s&&s.error("lagrangeEvaluations input too big"),new Error("lagrangeEvaluations input too big");let g=t.slice(0,t.byteLength/2),h=t.slice(t.byteLength/2,t.byteLength);const p=i.exp(i.shift,u/2),_=i.inv(i.sub(i.one,p));[g,h]=await l(g,h,"prepareLagrangeEvaluation",_,i.shiftInv,n,"jacobian",s,c+" prep");const m=[];let w;return m.push(o(g,!0,"jacobian",r,s,c+" t0")),m.push(o(h,!0,"jacobian",r,s,c+" t1")),[g,h]=await Promise.all(m),w=g.byteLength>1<<28?new et(2*g.byteLength):new Uint8Array(2*g.byteLength),w.set(g),w.set(h,g.byteLength),w},a.fftMix=async function(t){const o=3*a.F.n8;let l,r;if("G1"==e)l="g1m_fftMix",r="g1m_fftJoin";else if("G2"==e)l="g2m_fftMix",r="g2m_fftJoin";else{if("Fr"!=e)throw new Error("Invalid group");l="frm_fftMix",r="frm_fftJoin"}const s=Math.floor(t.byteLength/o),c=X(s);let d=1<=0;t--)g.set(f[t][0],h),h+=f[t][0].byteLength;return g}}async function mt(t){const e=await async function(t,e){const a=new ft;a.memory=new WebAssembly.Memory({initial:st}),a.u8=new Uint8Array(a.memory.buffer),a.u32=new Uint32Array(a.memory.buffer);const i=await WebAssembly.compile(t.code);if(a.instance=await WebAssembly.instantiate(i,{env:{memory:a.memory}}),globalThis?.Worker||(e=!0),a.singleThread=e,a.initalPFree=a.u32[0],a.pq=t.pq,a.pr=t.pr,a.pG1gen=t.pG1gen,a.pG1zero=t.pG1zero,a.pG2gen=t.pG2gen,a.pG2zero=t.pG2zero,a.pOneT=t.pOneT,a.code=t.code,a.wasmModule=i,e)a.taskManager=rt(),await a.taskManager([{cmd:"INIT",init:st,code:a.code.slice()}]),a.concurrency=1;else{a.workers=[],a.pendingDeferreds=[],a.working=[],a.initialized=[],a.initializing=[];let t=2;"object"==typeof navigator&&navigator.hardwareConcurrency&&(t=navigator.hardwareConcurrency),0===t&&(t=2),t>64&&(t=64),a.concurrency=t}return a}(t.wasm,t.singleThread),a={};return a.q=n(t.wasm.q.toString()),a.r=n(t.wasm.r.toString()),a.name=t.name,a.tm=e,a.prePSize=t.wasm.prePSize,a.preQSize=t.wasm.preQSize,a.Fr=new it(e,"frm",t.n8r,t.r),a.F1=new it(e,"f1m",t.n8q,t.q),a.F2=new nt(e,"f2m",a.F1),a.G1=new lt(e,"g1m",a.F1,t.wasm.pG1gen,t.wasm.pG1b,t.cofactorG1),a.G2=new lt(e,"g2m",a.F2,t.wasm.pG2gen,t.wasm.pG2b,t.cofactorG2),a.F6=new ot(e,"f6m",a.F2),a.F12=new nt(e,"ftm",a.F6),a.Gt=a.F12,gt(a,"G1"),gt(a,"G2"),gt(a,"Fr"),pt(a,"G1"),pt(a,"G2"),_t(a,"G1"),_t(a,"G2"),_t(a,"Fr"),function(t){const e=t.tm;t.pairing=function(a,i){e.startSyncOp();const n=e.allocBuff(t.G1.toJacobian(a)),o=e.allocBuff(t.G2.toJacobian(i)),l=e.alloc(t.Gt.n8);e.instance.exports[t.name+"_pairing"](n,o,l);const r=e.getBuff(l,t.Gt.n8);return e.endSyncOp(),r},t.pairingEq=async function(){let a,i;arguments.length%2==1?(a=arguments[arguments.length-1],i=(arguments.length-1)/2):(a=t.Gt.one,i=arguments.length/2);const n=[];for(let a=0;a>=8n;return a},bigInt2U32LE:function(t,e){const a=Array(e);let i=BigInt(t);for(let t=0;t>=32n;return a},isOcamNum:function(t){return!!Array.isArray(t)&&(3==t.length&&("number"==typeof t[0]&&("number"==typeof t[1]&&!!Array.isArray(t[2]))))}},St=function(t,e,a,i,n,o,l){const r=t.addFunction(e);r.addParam("base","i32"),r.addParam("scalar","i32"),r.addParam("scalarLength","i32"),r.addParam("r","i32"),r.addLocal("i","i32"),r.addLocal("b","i32");const s=r.getCodeBuilder(),c=s.i32_const(t.alloc(a));r.addCode(s.if(s.i32_eqz(s.getLocal("scalarLength")),[...s.call(l,s.getLocal("r")),...s.ret([])])),r.addCode(s.call(o,s.getLocal("base"),c)),r.addCode(s.call(l,s.getLocal("r"))),r.addCode(s.setLocal("i",s.getLocal("scalarLength"))),r.addCode(s.block(s.loop(s.setLocal("i",s.i32_sub(s.getLocal("i"),s.i32_const(1))),s.setLocal("b",s.i32_load8_u(s.i32_add(s.getLocal("scalar"),s.getLocal("i")))),...function(){const t=[];for(let e=0;e<8;e++)t.push(...s.call(n,s.getLocal("r"),s.getLocal("r")),...s.if(s.i32_ge_u(s.getLocal("b"),s.i32_const(128>>e)),[...s.setLocal("b",s.i32_sub(s.getLocal("b"),s.i32_const(128>>e))),...s.call(i,s.getLocal("r"),c,s.getLocal("r"))]));return t}(),s.br_if(1,s.i32_eqz(s.getLocal("i"))),s.br(0))))},Et=function(t,e){const a=8*t.modules[e].n64,i=t.addFunction(e+"_batchInverse");i.addParam("pIn","i32"),i.addParam("inStep","i32"),i.addParam("n","i32"),i.addParam("pOut","i32"),i.addParam("outStep","i32"),i.addLocal("itAux","i32"),i.addLocal("itIn","i32"),i.addLocal("itOut","i32"),i.addLocal("i","i32");const n=i.getCodeBuilder(),o=n.i32_const(t.alloc(a));i.addCode(n.setLocal("itAux",n.i32_load(n.i32_const(0))),n.i32_store(n.i32_const(0),n.i32_add(n.getLocal("itAux"),n.i32_mul(n.i32_add(n.getLocal("n"),n.i32_const(1)),n.i32_const(a))))),i.addCode(n.call(e+"_one",n.getLocal("itAux")),n.setLocal("itIn",n.getLocal("pIn")),n.setLocal("itAux",n.i32_add(n.getLocal("itAux"),n.i32_const(a))),n.setLocal("i",n.i32_const(0)),n.block(n.loop(n.br_if(1,n.i32_eq(n.getLocal("i"),n.getLocal("n"))),n.if(n.call(e+"_isZero",n.getLocal("itIn")),n.call(e+"_copy",n.i32_sub(n.getLocal("itAux"),n.i32_const(a)),n.getLocal("itAux")),n.call(e+"_mul",n.getLocal("itIn"),n.i32_sub(n.getLocal("itAux"),n.i32_const(a)),n.getLocal("itAux"))),n.setLocal("itIn",n.i32_add(n.getLocal("itIn"),n.getLocal("inStep"))),n.setLocal("itAux",n.i32_add(n.getLocal("itAux"),n.i32_const(a))),n.setLocal("i",n.i32_add(n.getLocal("i"),n.i32_const(1))),n.br(0))),n.setLocal("itIn",n.i32_sub(n.getLocal("itIn"),n.getLocal("inStep"))),n.setLocal("itAux",n.i32_sub(n.getLocal("itAux"),n.i32_const(a))),n.setLocal("itOut",n.i32_add(n.getLocal("pOut"),n.i32_mul(n.i32_sub(n.getLocal("n"),n.i32_const(1)),n.getLocal("outStep")))),n.call(e+"_inverse",n.getLocal("itAux"),n.getLocal("itAux")),n.block(n.loop(n.br_if(1,n.i32_eqz(n.getLocal("i"))),n.if(n.call(e+"_isZero",n.getLocal("itIn")),[...n.call(e+"_copy",n.getLocal("itAux"),n.i32_sub(n.getLocal("itAux"),n.i32_const(a))),...n.call(e+"_zero",n.getLocal("itOut"))],[...n.call(e+"_copy",n.i32_sub(n.getLocal("itAux"),n.i32_const(a)),o),...n.call(e+"_mul",n.getLocal("itAux"),n.getLocal("itIn"),n.i32_sub(n.getLocal("itAux"),n.i32_const(a))),...n.call(e+"_mul",n.getLocal("itAux"),o,n.getLocal("itOut"))]),n.setLocal("itIn",n.i32_sub(n.getLocal("itIn"),n.getLocal("inStep"))),n.setLocal("itOut",n.i32_sub(n.getLocal("itOut"),n.getLocal("outStep"))),n.setLocal("itAux",n.i32_sub(n.getLocal("itAux"),n.i32_const(a))),n.setLocal("i",n.i32_sub(n.getLocal("i"),n.i32_const(1))),n.br(0)))),i.addCode(n.i32_store(n.i32_const(0),n.getLocal("itAux")))};var At=function(t,e,a,i,n,o){void 0===o&&(o=ie?1:-1}function It(t){return t*t}function Tt(t){return t%2n!==0n}function Gt(t){return t%2n===0n}function Ot(t){return t<0n}function qt(t){return t>0n}function Ut(t){return Ot(t)?t.toString(2).length-1:t.toString(2).length}function Mt(t){return t<0n?-t:t}function kt(t){return 1n===Mt(t)}function Rt(t,e){for(var a,i,n,o=0n,l=1n,r=e,s=Mt(t);0n!==s;)a=r/s,i=o,n=r,o=l,r=s,l=i-a*l,s=n-a*s;if(!kt(r))throw new Error(t.toString()+" and "+e.toString()+" are not co-prime");return-1===zt(o,0n)&&(o+=e),Ot(t)?-o:o}function Nt(t,e,a){if(0n===a)throw new Error("Cannot take modPow with modulus 0");var i=1n,n=t%a;for(Ot(e)&&(e*=-1n,n=Rt(n,a));qt(e);){if(0n===n)return 0n;Tt(e)&&(i=i*n%a),e/=2n,n=It(n)%a}return i}function jt(t,e){return 0n!==e&&(!!kt(e)||(0===function(t,e){return(t=t>=0n?t:-t)===(e=e>=0n?e:-e)?0:t>e?1:-1}(e,2n)?Gt(t):t%e===0n))}function Dt(t,e){for(var a,i,n,o=function(t){return t-1n}(t),l=o,r=0;Gt(l);)l/=2n,r++;t:for(i=0;i>1&&i>1,t>>1)))),e.addCode(a.setLocal(s,a.i64_add(a.getLocal(s),a.i64_shr_u(a.getLocal(r),a.i64_const(32)))))),t>0&&(e.addCode(a.setLocal(r,a.i64_add(a.i64_and(a.getLocal(r),a.i64_const(4294967295)),a.i64_and(a.getLocal(c),a.i64_const(4294967295))))),e.addCode(a.setLocal(s,a.i64_add(a.i64_add(a.getLocal(s),a.i64_shr_u(a.getLocal(r),a.i64_const(32))),a.getLocal(d))))),e.addCode(a.i64_store32(a.getLocal("r"),4*t,a.getLocal(r))),e.addCode(a.setLocal(c,a.getLocal(s)),a.setLocal(d,a.i64_shr_u(a.getLocal(c),a.i64_const(32))))}e.addCode(a.i64_store32(a.getLocal("r"),4*n*2-4,a.getLocal(c)))}(),function(){const e=t.addFunction(i+"_squareOld");e.addParam("x","i32"),e.addParam("r","i32");const a=e.getCodeBuilder();e.addCode(a.call(i+"_mul",a.getLocal("x"),a.getLocal("x"),a.getLocal("r")))}(),function(){!function(){const e=t.addFunction(i+"__mul1");e.addParam("px","i32"),e.addParam("y","i64"),e.addParam("pr","i32"),e.addLocal("c","i64");const a=e.getCodeBuilder();e.addCode(a.setLocal("c",a.i64_mul(a.i64_load32_u(a.getLocal("px"),0,0),a.getLocal("y")))),e.addCode(a.i64_store32(a.getLocal("pr"),0,0,a.getLocal("c")));for(let t=1;t>1n,_=t.alloc(r,Wt.bigInt2BytesLE(p,r)),m=p+1n,w=t.alloc(r,Wt.bigInt2BytesLE(m,r));t.modules[s]={pq:d,pR2:u,n64:o,q:n,pOne:f,pZero:g,pePlusOne:w};let L=2n;if($t(n))for(;Jt(L,p,n)!==h;)L+=1n;let b=0,y=h;for(;!te(y)&&0n!==y;)b++,y>>=1n;const v=t.alloc(r,Wt.bigInt2BytesLE(y,r)),F=Jt(L,y,n),x=t.alloc(Wt.bigInt2BytesLE((F<>1n,S=t.alloc(r,Wt.bigInt2BytesLE(C,r));return t.exportFunction(c+"_copy",s+"_copy"),t.exportFunction(c+"_zero",s+"_zero"),t.exportFunction(c+"_isZero",s+"_isZero"),t.exportFunction(c+"_eq",s+"_eq"),function(){const e=t.addFunction(s+"_isOne");e.addParam("x","i32"),e.setReturnType("i32");const a=e.getCodeBuilder();e.addCode(a.ret(a.call(c+"_eq",a.getLocal("x"),a.i32_const(f))))}(),function(){const e=t.addFunction(s+"_add");e.addParam("x","i32"),e.addParam("y","i32"),e.addParam("r","i32");const a=e.getCodeBuilder();e.addCode(a.if(a.call(c+"_add",a.getLocal("x"),a.getLocal("y"),a.getLocal("r")),a.drop(a.call(c+"_sub",a.getLocal("r"),a.i32_const(d),a.getLocal("r"))),a.if(a.call(c+"_gte",a.getLocal("r"),a.i32_const(d)),a.drop(a.call(c+"_sub",a.getLocal("r"),a.i32_const(d),a.getLocal("r"))))))}(),function(){const e=t.addFunction(s+"_sub");e.addParam("x","i32"),e.addParam("y","i32"),e.addParam("r","i32");const a=e.getCodeBuilder();e.addCode(a.if(a.call(c+"_sub",a.getLocal("x"),a.getLocal("y"),a.getLocal("r")),a.drop(a.call(c+"_add",a.getLocal("r"),a.i32_const(d),a.getLocal("r")))))}(),function(){const e=t.addFunction(s+"_neg");e.addParam("x","i32"),e.addParam("r","i32");const a=e.getCodeBuilder();e.addCode(a.call(s+"_sub",a.i32_const(g),a.getLocal("x"),a.getLocal("r")))}(),function(){const e=t.alloc(l*l*8),a=t.addFunction(s+"_mReduct");a.addParam("t","i32"),a.addParam("r","i32"),a.addLocal("np32","i64"),a.addLocal("c","i64"),a.addLocal("m","i64");const i=a.getCodeBuilder(),o=Number(0x100000000n-Yt(n,0x100000000n));a.addCode(i.setLocal("np32",i.i64_const(o)));for(let t=0;t=l&&e.addCode(a.i64_store32(a.getLocal("r"),4*(t-l),a.getLocal(h))),[h,p]=[p,h],e.addCode(a.setLocal(p,a.i64_shr_u(a.getLocal(h),a.i64_const(32))))}e.addCode(a.i64_store32(a.getLocal("r"),4*l-4,a.getLocal(h))),e.addCode(a.if(a.i32_wrap_i64(a.getLocal(p)),a.drop(a.call(c+"_sub",a.getLocal("r"),a.i32_const(d),a.getLocal("r"))),a.if(a.call(c+"_gte",a.getLocal("r"),a.i32_const(d)),a.drop(a.call(c+"_sub",a.getLocal("r"),a.i32_const(d),a.getLocal("r"))))))}(),function(){const e=t.addFunction(s+"_square");e.addParam("x","i32"),e.addParam("r","i32"),e.addLocal("c0","i64"),e.addLocal("c1","i64"),e.addLocal("c0_old","i64"),e.addLocal("c1_old","i64"),e.addLocal("np32","i64");for(let t=0;t>1&&i>1,t>>1)))),e.addCode(a.setLocal(h,a.i64_add(a.getLocal(h),a.i64_shr_u(a.getLocal(g),a.i64_const(32)))))),t>0&&(e.addCode(a.setLocal(g,a.i64_add(a.i64_and(a.getLocal(g),a.i64_const(4294967295)),a.i64_and(a.getLocal(p),a.i64_const(4294967295))))),e.addCode(a.setLocal(h,a.i64_add(a.i64_add(a.getLocal(h),a.i64_shr_u(a.getLocal(g),a.i64_const(32))),a.getLocal(_)))));for(let i=Math.max(1,t-l+1);i<=t&&i=l&&e.addCode(a.i64_store32(a.getLocal("r"),4*(t-l),a.getLocal(g))),e.addCode(a.setLocal(p,a.getLocal(h)),a.setLocal(_,a.i64_shr_u(a.getLocal(p),a.i64_const(32))))}e.addCode(a.i64_store32(a.getLocal("r"),4*l-4,a.getLocal(p))),e.addCode(a.if(a.i32_wrap_i64(a.getLocal(_)),a.drop(a.call(c+"_sub",a.getLocal("r"),a.i32_const(d),a.getLocal("r"))),a.if(a.call(c+"_gte",a.getLocal("r"),a.i32_const(d)),a.drop(a.call(c+"_sub",a.getLocal("r"),a.i32_const(d),a.getLocal("r"))))))}(),function(){const e=t.addFunction(s+"_squareOld");e.addParam("x","i32"),e.addParam("r","i32");const a=e.getCodeBuilder();e.addCode(a.call(s+"_mul",a.getLocal("x"),a.getLocal("x"),a.getLocal("r")))}(),function(){const e=t.addFunction(s+"_toMontgomery");e.addParam("x","i32"),e.addParam("r","i32");const a=e.getCodeBuilder();e.addCode(a.call(s+"_mul",a.getLocal("x"),a.i32_const(u),a.getLocal("r")))}(),function(){const e=t.alloc(2*r),a=t.addFunction(s+"_fromMontgomery");a.addParam("x","i32"),a.addParam("r","i32");const i=a.getCodeBuilder();a.addCode(i.call(c+"_copy",i.getLocal("x"),i.i32_const(e))),a.addCode(i.call(c+"_zero",i.i32_const(e+r))),a.addCode(i.call(s+"_mReduct",i.i32_const(e),i.getLocal("r")))}(),function(){const e=t.addFunction(s+"_isNegative");e.addParam("x","i32"),e.setReturnType("i32");const a=e.getCodeBuilder(),i=a.i32_const(t.alloc(r));e.addCode(a.call(s+"_fromMontgomery",a.getLocal("x"),i),a.call(c+"_gte",i,a.i32_const(w)))}(),function(){const e=t.addFunction(s+"_sign");e.addParam("x","i32"),e.setReturnType("i32");const a=e.getCodeBuilder(),i=a.i32_const(t.alloc(r));e.addCode(a.if(a.call(c+"_isZero",a.getLocal("x")),a.ret(a.i32_const(0))),a.call(s+"_fromMontgomery",a.getLocal("x"),i),a.if(a.call(c+"_gte",i,a.i32_const(w)),a.ret(a.i32_const(-1))),a.ret(a.i32_const(1)))}(),function(){const e=t.addFunction(s+"_inverse");e.addParam("x","i32"),e.addParam("r","i32");const a=e.getCodeBuilder();e.addCode(a.call(s+"_fromMontgomery",a.getLocal("x"),a.getLocal("r"))),e.addCode(a.call(c+"_inverseMod",a.getLocal("r"),a.i32_const(d),a.getLocal("r"))),e.addCode(a.call(s+"_toMontgomery",a.getLocal("r"),a.getLocal("r")))}(),function(){const e=t.addFunction(s+"_one");e.addParam("pr","i32");const a=e.getCodeBuilder();e.addCode(a.call(c+"_copy",a.i32_const(f),a.getLocal("pr")))}(),function(){const e=t.addFunction(s+"_load");e.addParam("scalar","i32"),e.addParam("scalarLen","i32"),e.addParam("r","i32"),e.addLocal("p","i32"),e.addLocal("l","i32"),e.addLocal("i","i32"),e.addLocal("j","i32");const a=e.getCodeBuilder(),i=a.i32_const(t.alloc(r)),n=t.alloc(r),o=a.i32_const(n);e.addCode(a.call(c+"_zero",a.getLocal("r")),a.setLocal("i",a.i32_const(r)),a.setLocal("p",a.getLocal("scalar")),a.block(a.loop(a.br_if(1,a.i32_gt_u(a.getLocal("i"),a.getLocal("scalarLen"))),a.if(a.i32_eq(a.getLocal("i"),a.i32_const(r)),a.call(s+"_one",i),a.call(s+"_mul",i,a.i32_const(u),i)),a.call(s+"_mul",a.getLocal("p"),i,o),a.call(s+"_add",a.getLocal("r"),o,a.getLocal("r")),a.setLocal("p",a.i32_add(a.getLocal("p"),a.i32_const(r))),a.setLocal("i",a.i32_add(a.getLocal("i"),a.i32_const(r))),a.br(0))),a.setLocal("l",a.i32_rem_u(a.getLocal("scalarLen"),a.i32_const(r))),a.if(a.i32_eqz(a.getLocal("l")),a.ret([])),a.call(c+"_zero",o),a.setLocal("j",a.i32_const(0)),a.block(a.loop(a.br_if(1,a.i32_eq(a.getLocal("j"),a.getLocal("l"))),a.i32_store8(a.getLocal("j"),n,a.i32_load8_u(a.getLocal("p"))),a.setLocal("p",a.i32_add(a.getLocal("p"),a.i32_const(1))),a.setLocal("j",a.i32_add(a.getLocal("j"),a.i32_const(1))),a.br(0))),a.if(a.i32_eq(a.getLocal("i"),a.i32_const(r)),a.call(s+"_one",i),a.call(s+"_mul",i,a.i32_const(u),i)),a.call(s+"_mul",o,i,o),a.call(s+"_add",a.getLocal("r"),o,a.getLocal("r")))}(),function(){const e=t.addFunction(s+"_timesScalar");e.addParam("x","i32"),e.addParam("scalar","i32"),e.addParam("scalarLen","i32"),e.addParam("r","i32");const a=e.getCodeBuilder(),i=a.i32_const(t.alloc(r));e.addCode(a.call(s+"_load",a.getLocal("scalar"),a.getLocal("scalarLen"),i),a.call(s+"_toMontgomery",i,i),a.call(s+"_mul",a.getLocal("x"),i,a.getLocal("r")))}(),Ht(t,s),Qt(t,s+"_batchToMontgomery",s+"_toMontgomery",r,r),Qt(t,s+"_batchFromMontgomery",s+"_fromMontgomery",r,r),Qt(t,s+"_batchNeg",s+"_neg",r,r),Kt(t,s+"_batchAdd",s+"_add",r,r),Kt(t,s+"_batchSub",s+"_sub",r,r),Kt(t,s+"_batchMul",s+"_mul",r,r),t.exportFunction(s+"_add"),t.exportFunction(s+"_sub"),t.exportFunction(s+"_neg"),t.exportFunction(s+"_isNegative"),t.exportFunction(s+"_isOne"),t.exportFunction(s+"_sign"),t.exportFunction(s+"_mReduct"),t.exportFunction(s+"_mul"),t.exportFunction(s+"_square"),t.exportFunction(s+"_squareOld"),t.exportFunction(s+"_fromMontgomery"),t.exportFunction(s+"_toMontgomery"),t.exportFunction(s+"_inverse"),t.exportFunction(s+"_one"),t.exportFunction(s+"_load"),t.exportFunction(s+"_timesScalar"),Zt(t,s+"_exp",r,s+"_mul",s+"_square",c+"_copy",s+"_one"),t.exportFunction(s+"_exp"),t.exportFunction(s+"_batchInverse"),$t(n)&&(!function(){const e=t.addFunction(s+"_sqrt");e.addParam("n","i32"),e.addParam("r","i32"),e.addLocal("m","i32"),e.addLocal("i","i32"),e.addLocal("j","i32");const a=e.getCodeBuilder(),i=a.i32_const(f),n=a.i32_const(t.alloc(r)),o=a.i32_const(t.alloc(r)),l=a.i32_const(t.alloc(r)),c=a.i32_const(t.alloc(r)),d=a.i32_const(t.alloc(r));e.addCode(a.if(a.call(s+"_isZero",a.getLocal("n")),a.ret(a.call(s+"_zero",a.getLocal("r")))),a.setLocal("m",a.i32_const(b)),a.call(s+"_copy",a.i32_const(x),n),a.call(s+"_exp",a.getLocal("n"),a.i32_const(v),a.i32_const(r),o),a.call(s+"_exp",a.getLocal("n"),a.i32_const(S),a.i32_const(r),l),a.block(a.loop(a.br_if(1,a.call(s+"_eq",o,i)),a.call(s+"_square",o,c),a.setLocal("i",a.i32_const(1)),a.block(a.loop(a.br_if(1,a.call(s+"_eq",c,i)),a.call(s+"_square",c,c),a.setLocal("i",a.i32_add(a.getLocal("i"),a.i32_const(1))),a.br(0))),a.call(s+"_copy",n,d),a.setLocal("j",a.i32_sub(a.i32_sub(a.getLocal("m"),a.getLocal("i")),a.i32_const(1))),a.block(a.loop(a.br_if(1,a.i32_eqz(a.getLocal("j"))),a.call(s+"_square",d,d),a.setLocal("j",a.i32_sub(a.getLocal("j"),a.i32_const(1))),a.br(0))),a.setLocal("m",a.getLocal("i")),a.call(s+"_square",d,n),a.call(s+"_mul",o,n,o),a.call(s+"_mul",l,d,l),a.br(0))),a.if(a.call(s+"_isNegative",l),a.call(s+"_neg",l,a.getLocal("r")),a.call(s+"_copy",l,a.getLocal("r"))))}(),function(){const e=t.addFunction(s+"_isSquare");e.addParam("n","i32"),e.setReturnType("i32");const a=e.getCodeBuilder(),i=a.i32_const(f),n=a.i32_const(t.alloc(r));e.addCode(a.if(a.call(s+"_isZero",a.getLocal("n")),a.ret(a.i32_const(1))),a.call(s+"_exp",a.getLocal("n"),a.i32_const(_),a.i32_const(r),n),a.call(s+"_eq",n,i))}(),t.exportFunction(s+"_sqrt"),t.exportFunction(s+"_isSquare")),t.exportFunction(s+"_batchToMontgomery"),t.exportFunction(s+"_batchFromMontgomery"),s};const ie=ae,{bitLength:ne}=Pt;var oe=function(t,e,a,i,n){const o=BigInt(e),l=Math.floor((ne(o-1n)-1)/64)+1,r=8*l,s=a||"f1";if(t.modules[s])return s;t.modules[s]={n64:l};const c=n||"int",d=ie(t,o,i,c),u=t.modules[d].pR2,f=t.modules[d].pq,g=t.modules[d].pePlusOne;return function(){const e=t.alloc(r),a=t.addFunction(s+"_mul");a.addParam("x","i32"),a.addParam("y","i32"),a.addParam("r","i32");const i=a.getCodeBuilder();a.addCode(i.call(d+"_mul",i.getLocal("x"),i.getLocal("y"),i.i32_const(e))),a.addCode(i.call(d+"_mul",i.i32_const(e),i.i32_const(u),i.getLocal("r")))}(),function(){const e=t.addFunction(s+"_square");e.addParam("x","i32"),e.addParam("r","i32");const a=e.getCodeBuilder();e.addCode(a.call(s+"_mul",a.getLocal("x"),a.getLocal("x"),a.getLocal("r")))}(),function(){const e=t.addFunction(s+"_inverse");e.addParam("x","i32"),e.addParam("r","i32");const a=e.getCodeBuilder();e.addCode(a.call(c+"_inverseMod",a.getLocal("x"),a.i32_const(f),a.getLocal("r")))}(),function(){const e=t.addFunction(s+"_isNegative");e.addParam("x","i32"),e.setReturnType("i32");const a=e.getCodeBuilder();e.addCode(a.call(c+"_gte",a.getLocal("x"),a.i32_const(g)))}(),t.exportFunction(d+"_add",s+"_add"),t.exportFunction(d+"_sub",s+"_sub"),t.exportFunction(d+"_neg",s+"_neg"),t.exportFunction(s+"_mul"),t.exportFunction(s+"_square"),t.exportFunction(s+"_inverse"),t.exportFunction(s+"_isNegative"),t.exportFunction(d+"_copy",s+"_copy"),t.exportFunction(d+"_zero",s+"_zero"),t.exportFunction(d+"_one",s+"_one"),t.exportFunction(d+"_isZero",s+"_isZero"),t.exportFunction(d+"_eq",s+"_eq"),s};const le=St,re=Et,se=Ct;var ce=function(t,e,a,i){if(t.modules[a])return a;const n=8*t.modules[i].n64,o=t.modules[i].q;return t.modules[a]={n64:2*t.modules[i].n64},function(){const e=t.addFunction(a+"_isZero");e.addParam("x","i32"),e.setReturnType("i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n));e.addCode(o.i32_and(o.call(i+"_isZero",l),o.call(i+"_isZero",r)))}(),function(){const e=t.addFunction(a+"_isOne");e.addParam("x","i32"),e.setReturnType("i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n));e.addCode(o.ret(o.i32_and(o.call(i+"_isOne",l),o.call(i+"_isZero",r))))}(),function(){const e=t.addFunction(a+"_zero");e.addParam("x","i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n));e.addCode(o.call(i+"_zero",l),o.call(i+"_zero",r))}(),function(){const e=t.addFunction(a+"_one");e.addParam("x","i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n));e.addCode(o.call(i+"_one",l),o.call(i+"_zero",r))}(),function(){const e=t.addFunction(a+"_copy");e.addParam("x","i32"),e.addParam("r","i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.getLocal("r"),c=o.i32_add(o.getLocal("r"),o.i32_const(n));e.addCode(o.call(i+"_copy",l,s),o.call(i+"_copy",r,c))}(),function(){const o=t.addFunction(a+"_mul");o.addParam("x","i32"),o.addParam("y","i32"),o.addParam("r","i32");const l=o.getCodeBuilder(),r=l.getLocal("x"),s=l.i32_add(l.getLocal("x"),l.i32_const(n)),c=l.getLocal("y"),d=l.i32_add(l.getLocal("y"),l.i32_const(n)),u=l.getLocal("r"),f=l.i32_add(l.getLocal("r"),l.i32_const(n)),g=l.i32_const(t.alloc(n)),h=l.i32_const(t.alloc(n)),p=l.i32_const(t.alloc(n)),_=l.i32_const(t.alloc(n));o.addCode(l.call(i+"_mul",r,c,g),l.call(i+"_mul",s,d,h),l.call(i+"_add",r,s,p),l.call(i+"_add",c,d,_),l.call(i+"_mul",p,_,p),l.call(e,h,u),l.call(i+"_add",g,u,u),l.call(i+"_add",g,h,f),l.call(i+"_sub",p,f,f))}(),function(){const e=t.addFunction(a+"_mul1");e.addParam("x","i32"),e.addParam("y","i32"),e.addParam("r","i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.getLocal("y"),c=o.getLocal("r"),d=o.i32_add(o.getLocal("r"),o.i32_const(n));e.addCode(o.call(i+"_mul",l,s,c),o.call(i+"_mul",r,s,d))}(),function(){const o=t.addFunction(a+"_square");o.addParam("x","i32"),o.addParam("r","i32");const l=o.getCodeBuilder(),r=l.getLocal("x"),s=l.i32_add(l.getLocal("x"),l.i32_const(n)),c=l.getLocal("r"),d=l.i32_add(l.getLocal("r"),l.i32_const(n)),u=l.i32_const(t.alloc(n)),f=l.i32_const(t.alloc(n)),g=l.i32_const(t.alloc(n)),h=l.i32_const(t.alloc(n));o.addCode(l.call(i+"_mul",r,s,u),l.call(i+"_add",r,s,f),l.call(e,s,g),l.call(i+"_add",r,g,g),l.call(e,u,h),l.call(i+"_add",h,u,h),l.call(i+"_mul",f,g,c),l.call(i+"_sub",c,h,c),l.call(i+"_add",u,u,d))}(),function(){const e=t.addFunction(a+"_add");e.addParam("x","i32"),e.addParam("y","i32"),e.addParam("r","i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.getLocal("y"),c=o.i32_add(o.getLocal("y"),o.i32_const(n)),d=o.getLocal("r"),u=o.i32_add(o.getLocal("r"),o.i32_const(n));e.addCode(o.call(i+"_add",l,s,d),o.call(i+"_add",r,c,u))}(),function(){const e=t.addFunction(a+"_sub");e.addParam("x","i32"),e.addParam("y","i32"),e.addParam("r","i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.getLocal("y"),c=o.i32_add(o.getLocal("y"),o.i32_const(n)),d=o.getLocal("r"),u=o.i32_add(o.getLocal("r"),o.i32_const(n));e.addCode(o.call(i+"_sub",l,s,d),o.call(i+"_sub",r,c,u))}(),function(){const e=t.addFunction(a+"_neg");e.addParam("x","i32"),e.addParam("r","i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.getLocal("r"),c=o.i32_add(o.getLocal("r"),o.i32_const(n));e.addCode(o.call(i+"_neg",l,s),o.call(i+"_neg",r,c))}(),function(){const e=t.addFunction(a+"_conjugate");e.addParam("x","i32"),e.addParam("r","i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.getLocal("r"),c=o.i32_add(o.getLocal("r"),o.i32_const(n));e.addCode(o.call(i+"_copy",l,s),o.call(i+"_neg",r,c))}(),function(){const e=t.addFunction(a+"_toMontgomery");e.addParam("x","i32"),e.addParam("r","i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.getLocal("r"),c=o.i32_add(o.getLocal("r"),o.i32_const(n));e.addCode(o.call(i+"_toMontgomery",l,s),o.call(i+"_toMontgomery",r,c))}(),function(){const e=t.addFunction(a+"_fromMontgomery");e.addParam("x","i32"),e.addParam("r","i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.getLocal("r"),c=o.i32_add(o.getLocal("r"),o.i32_const(n));e.addCode(o.call(i+"_fromMontgomery",l,s),o.call(i+"_fromMontgomery",r,c))}(),function(){const e=t.addFunction(a+"_eq");e.addParam("x","i32"),e.addParam("y","i32"),e.setReturnType("i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.getLocal("y"),c=o.i32_add(o.getLocal("y"),o.i32_const(n));e.addCode(o.i32_and(o.call(i+"_eq",l,s),o.call(i+"_eq",r,c)))}(),function(){const o=t.addFunction(a+"_inverse");o.addParam("x","i32"),o.addParam("r","i32");const l=o.getCodeBuilder(),r=l.getLocal("x"),s=l.i32_add(l.getLocal("x"),l.i32_const(n)),c=l.getLocal("r"),d=l.i32_add(l.getLocal("r"),l.i32_const(n)),u=l.i32_const(t.alloc(n)),f=l.i32_const(t.alloc(n)),g=l.i32_const(t.alloc(n)),h=l.i32_const(t.alloc(n));o.addCode(l.call(i+"_square",r,u),l.call(i+"_square",s,f),l.call(e,f,g),l.call(i+"_sub",u,g,g),l.call(i+"_inverse",g,h),l.call(i+"_mul",r,h,c),l.call(i+"_mul",s,h,d),l.call(i+"_neg",d,d))}(),function(){const e=t.addFunction(a+"_timesScalar");e.addParam("x","i32"),e.addParam("scalar","i32"),e.addParam("scalarLen","i32"),e.addParam("r","i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.getLocal("r"),c=o.i32_add(o.getLocal("r"),o.i32_const(n));e.addCode(o.call(i+"_timesScalar",l,o.getLocal("scalar"),o.getLocal("scalarLen"),s),o.call(i+"_timesScalar",r,o.getLocal("scalar"),o.getLocal("scalarLen"),c))}(),function(){const e=t.addFunction(a+"_sign");e.addParam("x","i32"),e.addLocal("s","i32"),e.setReturnType("i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n));e.addCode(o.setLocal("s",o.call(i+"_sign",r)),o.if(o.getLocal("s"),o.ret(o.getLocal("s"))),o.ret(o.call(i+"_sign",l)))}(),function(){const e=t.addFunction(a+"_isNegative");e.addParam("x","i32"),e.setReturnType("i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n));e.addCode(o.if(o.call(i+"_isZero",r),o.ret(o.call(i+"_isNegative",l))),o.ret(o.call(i+"_isNegative",r)))}(),t.exportFunction(a+"_isZero"),t.exportFunction(a+"_isOne"),t.exportFunction(a+"_zero"),t.exportFunction(a+"_one"),t.exportFunction(a+"_copy"),t.exportFunction(a+"_mul"),t.exportFunction(a+"_mul1"),t.exportFunction(a+"_square"),t.exportFunction(a+"_add"),t.exportFunction(a+"_sub"),t.exportFunction(a+"_neg"),t.exportFunction(a+"_sign"),t.exportFunction(a+"_conjugate"),t.exportFunction(a+"_fromMontgomery"),t.exportFunction(a+"_toMontgomery"),t.exportFunction(a+"_eq"),t.exportFunction(a+"_inverse"),re(t,a),le(t,a+"_exp",2*n,a+"_mul",a+"_square",a+"_copy",a+"_one"),function(){const e=t.addFunction(a+"_sqrt");e.addParam("a","i32"),e.addParam("pr","i32");const l=e.getCodeBuilder(),r=l.i32_const(t.alloc(se.bigInt2BytesLE((BigInt(o||0)-3n)/4n,n))),s=l.i32_const(t.alloc(se.bigInt2BytesLE((BigInt(o||0)-1n)/2n,n))),c=l.getLocal("a"),d=l.i32_const(t.alloc(2*n)),u=l.i32_const(t.alloc(2*n)),f=l.i32_const(t.alloc(2*n)),g=t.alloc(2*n),h=l.i32_const(g),p=l.i32_const(g),_=l.i32_const(g+n),m=l.i32_const(t.alloc(2*n)),w=l.i32_const(t.alloc(2*n));e.addCode(l.call(a+"_one",h),l.call(a+"_neg",h,h),l.call(a+"_exp",c,r,l.i32_const(n),d),l.call(a+"_square",d,u),l.call(a+"_mul",c,u,u),l.call(a+"_conjugate",u,f),l.call(a+"_mul",f,u,f),l.if(l.call(a+"_eq",f,h),l.unreachable()),l.call(a+"_mul",d,c,m),l.if(l.call(a+"_eq",u,h),[...l.call(i+"_zero",p),...l.call(i+"_one",_),...l.call(a+"_mul",h,m,l.getLocal("pr"))],[...l.call(a+"_one",w),...l.call(a+"_add",w,u,w),...l.call(a+"_exp",w,s,l.i32_const(n),w),...l.call(a+"_mul",w,m,l.getLocal("pr"))]))}(),function(){const e=t.addFunction(a+"_isSquare");e.addParam("a","i32"),e.setReturnType("i32");const i=e.getCodeBuilder(),l=i.i32_const(t.alloc(se.bigInt2BytesLE((BigInt(o||0)-3n)/4n,n))),r=i.getLocal("a"),s=i.i32_const(t.alloc(2*n)),c=i.i32_const(t.alloc(2*n)),d=i.i32_const(t.alloc(2*n)),u=t.alloc(2*n),f=i.i32_const(u);e.addCode(i.call(a+"_one",f),i.call(a+"_neg",f,f),i.call(a+"_exp",r,l,i.i32_const(n),s),i.call(a+"_square",s,c),i.call(a+"_mul",r,c,c),i.call(a+"_conjugate",c,d),i.call(a+"_mul",d,c,d),i.if(i.call(a+"_eq",d,f),i.ret(i.i32_const(0))),i.ret(i.i32_const(1)))}(),t.exportFunction(a+"_exp"),t.exportFunction(a+"_timesScalar"),t.exportFunction(a+"_batchInverse"),t.exportFunction(a+"_sqrt"),t.exportFunction(a+"_isSquare"),t.exportFunction(a+"_isNegative"),a};const de=St,ue=Et;var fe=function(t,e,a,i){if(t.modules[a])return a;const n=8*t.modules[i].n64;return t.modules[a]={n64:3*t.modules[i].n64},function(){const e=t.addFunction(a+"_isZero");e.addParam("x","i32"),e.setReturnType("i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.i32_add(o.getLocal("x"),o.i32_const(2*n));e.addCode(o.i32_and(o.i32_and(o.call(i+"_isZero",l),o.call(i+"_isZero",r)),o.call(i+"_isZero",s)))}(),function(){const e=t.addFunction(a+"_isOne");e.addParam("x","i32"),e.setReturnType("i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.i32_add(o.getLocal("x"),o.i32_const(2*n));e.addCode(o.ret(o.i32_and(o.i32_and(o.call(i+"_isOne",l),o.call(i+"_isZero",r)),o.call(i+"_isZero",s))))}(),function(){const e=t.addFunction(a+"_zero");e.addParam("x","i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.i32_add(o.getLocal("x"),o.i32_const(2*n));e.addCode(o.call(i+"_zero",l),o.call(i+"_zero",r),o.call(i+"_zero",s))}(),function(){const e=t.addFunction(a+"_one");e.addParam("x","i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.i32_add(o.getLocal("x"),o.i32_const(2*n));e.addCode(o.call(i+"_one",l),o.call(i+"_zero",r),o.call(i+"_zero",s))}(),function(){const e=t.addFunction(a+"_copy");e.addParam("x","i32"),e.addParam("r","i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.i32_add(o.getLocal("x"),o.i32_const(2*n)),c=o.getLocal("r"),d=o.i32_add(o.getLocal("r"),o.i32_const(n)),u=o.i32_add(o.getLocal("r"),o.i32_const(2*n));e.addCode(o.call(i+"_copy",l,c),o.call(i+"_copy",r,d),o.call(i+"_copy",s,u))}(),function(){const o=t.addFunction(a+"_mul");o.addParam("x","i32"),o.addParam("y","i32"),o.addParam("r","i32");const l=o.getCodeBuilder(),r=l.getLocal("x"),s=l.i32_add(l.getLocal("x"),l.i32_const(n)),c=l.i32_add(l.getLocal("x"),l.i32_const(2*n)),d=l.getLocal("y"),u=l.i32_add(l.getLocal("y"),l.i32_const(n)),f=l.i32_add(l.getLocal("y"),l.i32_const(2*n)),g=l.getLocal("r"),h=l.i32_add(l.getLocal("r"),l.i32_const(n)),p=l.i32_add(l.getLocal("r"),l.i32_const(2*n)),_=l.i32_const(t.alloc(n)),m=l.i32_const(t.alloc(n)),w=l.i32_const(t.alloc(n)),L=l.i32_const(t.alloc(n)),b=l.i32_const(t.alloc(n)),y=l.i32_const(t.alloc(n)),v=l.i32_const(t.alloc(n)),F=l.i32_const(t.alloc(n)),x=l.i32_const(t.alloc(n)),C=l.i32_const(t.alloc(n)),S=l.i32_const(t.alloc(n)),E=l.i32_const(t.alloc(n)),A=l.i32_const(t.alloc(n));o.addCode(l.call(i+"_mul",r,d,_),l.call(i+"_mul",s,u,m),l.call(i+"_mul",c,f,w),l.call(i+"_add",r,s,L),l.call(i+"_add",d,u,b),l.call(i+"_add",r,c,y),l.call(i+"_add",d,f,v),l.call(i+"_add",s,c,F),l.call(i+"_add",u,f,x),l.call(i+"_add",_,m,C),l.call(i+"_add",_,w,S),l.call(i+"_add",m,w,E),l.call(i+"_mul",F,x,g),l.call(i+"_sub",g,E,g),l.call(e,g,g),l.call(i+"_add",_,g,g),l.call(i+"_mul",L,b,h),l.call(i+"_sub",h,C,h),l.call(e,w,A),l.call(i+"_add",h,A,h),l.call(i+"_mul",y,v,p),l.call(i+"_sub",p,S,p),l.call(i+"_add",p,m,p))}(),function(){const o=t.addFunction(a+"_square");o.addParam("x","i32"),o.addParam("r","i32");const l=o.getCodeBuilder(),r=l.getLocal("x"),s=l.i32_add(l.getLocal("x"),l.i32_const(n)),c=l.i32_add(l.getLocal("x"),l.i32_const(2*n)),d=l.getLocal("r"),u=l.i32_add(l.getLocal("r"),l.i32_const(n)),f=l.i32_add(l.getLocal("r"),l.i32_const(2*n)),g=l.i32_const(t.alloc(n)),h=l.i32_const(t.alloc(n)),p=l.i32_const(t.alloc(n)),_=l.i32_const(t.alloc(n)),m=l.i32_const(t.alloc(n)),w=l.i32_const(t.alloc(n)),L=l.i32_const(t.alloc(n));o.addCode(l.call(i+"_square",r,g),l.call(i+"_mul",r,s,h),l.call(i+"_add",h,h,p),l.call(i+"_sub",r,s,_),l.call(i+"_add",_,c,_),l.call(i+"_square",_,_),l.call(i+"_mul",s,c,m),l.call(i+"_add",m,m,w),l.call(i+"_square",c,L),l.call(e,w,d),l.call(i+"_add",g,d,d),l.call(e,L,u),l.call(i+"_add",p,u,u),l.call(i+"_add",g,L,f),l.call(i+"_sub",w,f,f),l.call(i+"_add",_,f,f),l.call(i+"_add",p,f,f))}(),function(){const e=t.addFunction(a+"_add");e.addParam("x","i32"),e.addParam("y","i32"),e.addParam("r","i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.i32_add(o.getLocal("x"),o.i32_const(2*n)),c=o.getLocal("y"),d=o.i32_add(o.getLocal("y"),o.i32_const(n)),u=o.i32_add(o.getLocal("y"),o.i32_const(2*n)),f=o.getLocal("r"),g=o.i32_add(o.getLocal("r"),o.i32_const(n)),h=o.i32_add(o.getLocal("r"),o.i32_const(2*n));e.addCode(o.call(i+"_add",l,c,f),o.call(i+"_add",r,d,g),o.call(i+"_add",s,u,h))}(),function(){const e=t.addFunction(a+"_sub");e.addParam("x","i32"),e.addParam("y","i32"),e.addParam("r","i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.i32_add(o.getLocal("x"),o.i32_const(2*n)),c=o.getLocal("y"),d=o.i32_add(o.getLocal("y"),o.i32_const(n)),u=o.i32_add(o.getLocal("y"),o.i32_const(2*n)),f=o.getLocal("r"),g=o.i32_add(o.getLocal("r"),o.i32_const(n)),h=o.i32_add(o.getLocal("r"),o.i32_const(2*n));e.addCode(o.call(i+"_sub",l,c,f),o.call(i+"_sub",r,d,g),o.call(i+"_sub",s,u,h))}(),function(){const e=t.addFunction(a+"_neg");e.addParam("x","i32"),e.addParam("r","i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.i32_add(o.getLocal("x"),o.i32_const(2*n)),c=o.getLocal("r"),d=o.i32_add(o.getLocal("r"),o.i32_const(n)),u=o.i32_add(o.getLocal("r"),o.i32_const(2*n));e.addCode(o.call(i+"_neg",l,c),o.call(i+"_neg",r,d),o.call(i+"_neg",s,u))}(),function(){const e=t.addFunction(a+"_sign");e.addParam("x","i32"),e.addLocal("s","i32"),e.setReturnType("i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.i32_add(o.getLocal("x"),o.i32_const(2*n));e.addCode(o.setLocal("s",o.call(i+"_sign",s)),o.if(o.getLocal("s"),o.ret(o.getLocal("s"))),o.setLocal("s",o.call(i+"_sign",r)),o.if(o.getLocal("s"),o.ret(o.getLocal("s"))),o.ret(o.call(i+"_sign",l)))}(),function(){const e=t.addFunction(a+"_toMontgomery");e.addParam("x","i32"),e.addParam("r","i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.i32_add(o.getLocal("x"),o.i32_const(2*n)),c=o.getLocal("r"),d=o.i32_add(o.getLocal("r"),o.i32_const(n)),u=o.i32_add(o.getLocal("r"),o.i32_const(2*n));e.addCode(o.call(i+"_toMontgomery",l,c),o.call(i+"_toMontgomery",r,d),o.call(i+"_toMontgomery",s,u))}(),function(){const e=t.addFunction(a+"_fromMontgomery");e.addParam("x","i32"),e.addParam("r","i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.i32_add(o.getLocal("x"),o.i32_const(2*n)),c=o.getLocal("r"),d=o.i32_add(o.getLocal("r"),o.i32_const(n)),u=o.i32_add(o.getLocal("r"),o.i32_const(2*n));e.addCode(o.call(i+"_fromMontgomery",l,c),o.call(i+"_fromMontgomery",r,d),o.call(i+"_fromMontgomery",s,u))}(),function(){const e=t.addFunction(a+"_eq");e.addParam("x","i32"),e.addParam("y","i32"),e.setReturnType("i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.i32_add(o.getLocal("x"),o.i32_const(2*n)),c=o.getLocal("y"),d=o.i32_add(o.getLocal("y"),o.i32_const(n)),u=o.i32_add(o.getLocal("y"),o.i32_const(2*n));e.addCode(o.i32_and(o.i32_and(o.call(i+"_eq",l,c),o.call(i+"_eq",r,d)),o.call(i+"_eq",s,u)))}(),function(){const o=t.addFunction(a+"_inverse");o.addParam("x","i32"),o.addParam("r","i32");const l=o.getCodeBuilder(),r=l.getLocal("x"),s=l.i32_add(l.getLocal("x"),l.i32_const(n)),c=l.i32_add(l.getLocal("x"),l.i32_const(2*n)),d=l.getLocal("r"),u=l.i32_add(l.getLocal("r"),l.i32_const(n)),f=l.i32_add(l.getLocal("r"),l.i32_const(2*n)),g=l.i32_const(t.alloc(n)),h=l.i32_const(t.alloc(n)),p=l.i32_const(t.alloc(n)),_=l.i32_const(t.alloc(n)),m=l.i32_const(t.alloc(n)),w=l.i32_const(t.alloc(n)),L=l.i32_const(t.alloc(n)),b=l.i32_const(t.alloc(n)),y=l.i32_const(t.alloc(n)),v=l.i32_const(t.alloc(n)),F=l.i32_const(t.alloc(n));o.addCode(l.call(i+"_square",r,g),l.call(i+"_square",s,h),l.call(i+"_square",c,p),l.call(i+"_mul",r,s,_),l.call(i+"_mul",r,c,m),l.call(i+"_mul",s,c,w),l.call(e,w,L),l.call(i+"_sub",g,L,L),l.call(e,p,b),l.call(i+"_sub",b,_,b),l.call(i+"_sub",h,m,y),l.call(i+"_mul",c,b,v),l.call(i+"_mul",s,y,F),l.call(i+"_add",v,F,v),l.call(e,v,v),l.call(i+"_mul",r,L,F),l.call(i+"_add",F,v,v),l.call(i+"_inverse",v,v),l.call(i+"_mul",v,L,d),l.call(i+"_mul",v,b,u),l.call(i+"_mul",v,y,f))}(),function(){const e=t.addFunction(a+"_timesScalar");e.addParam("x","i32"),e.addParam("scalar","i32"),e.addParam("scalarLen","i32"),e.addParam("r","i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.i32_add(o.getLocal("x"),o.i32_const(2*n)),c=o.getLocal("r"),d=o.i32_add(o.getLocal("r"),o.i32_const(n)),u=o.i32_add(o.getLocal("r"),o.i32_const(2*n));e.addCode(o.call(i+"_timesScalar",l,o.getLocal("scalar"),o.getLocal("scalarLen"),c),o.call(i+"_timesScalar",r,o.getLocal("scalar"),o.getLocal("scalarLen"),d),o.call(i+"_timesScalar",s,o.getLocal("scalar"),o.getLocal("scalarLen"),u))}(),function(){const e=t.addFunction(a+"_isNegative");e.addParam("x","i32"),e.setReturnType("i32");const o=e.getCodeBuilder(),l=o.getLocal("x"),r=o.i32_add(o.getLocal("x"),o.i32_const(n)),s=o.i32_add(o.getLocal("x"),o.i32_const(2*n));e.addCode(o.if(o.call(i+"_isZero",s),o.if(o.call(i+"_isZero",r),o.ret(o.call(i+"_isNegative",l)),o.ret(o.call(i+"_isNegative",r)))),o.ret(o.call(i+"_isNegative",s)))}(),t.exportFunction(a+"_isZero"),t.exportFunction(a+"_isOne"),t.exportFunction(a+"_zero"),t.exportFunction(a+"_one"),t.exportFunction(a+"_copy"),t.exportFunction(a+"_mul"),t.exportFunction(a+"_square"),t.exportFunction(a+"_add"),t.exportFunction(a+"_sub"),t.exportFunction(a+"_neg"),t.exportFunction(a+"_sign"),t.exportFunction(a+"_fromMontgomery"),t.exportFunction(a+"_toMontgomery"),t.exportFunction(a+"_eq"),t.exportFunction(a+"_inverse"),ue(t,a),de(t,a+"_exp",3*n,a+"_mul",a+"_square",a+"_copy",a+"_one"),t.exportFunction(a+"_exp"),t.exportFunction(a+"_timesScalar"),t.exportFunction(a+"_batchInverse"),t.exportFunction(a+"_isNegative"),a};const ge=function(t,e,a,i,n,o,l,r){const s=t.addFunction(e);s.addParam("base","i32"),s.addParam("scalar","i32"),s.addParam("scalarLength","i32"),s.addParam("r","i32"),s.addLocal("old0","i32"),s.addLocal("nbits","i32"),s.addLocal("i","i32"),s.addLocal("last","i32"),s.addLocal("cur","i32"),s.addLocal("carry","i32"),s.addLocal("p","i32");const c=s.getCodeBuilder(),d=c.i32_const(t.alloc(a));function u(t){return c.i32_and(c.i32_shr_u(c.i32_load(c.i32_add(c.getLocal("scalar"),c.i32_and(c.i32_shr_u(t,c.i32_const(3)),c.i32_const(4294967292)))),c.i32_and(t,c.i32_const(31))),c.i32_const(1))}function f(t){return[...c.i32_store8(c.getLocal("p"),c.i32_const(t)),...c.setLocal("p",c.i32_add(c.getLocal("p"),c.i32_const(1)))]}s.addCode(c.if(c.i32_eqz(c.getLocal("scalarLength")),[...c.call(r,c.getLocal("r")),...c.ret([])]),c.setLocal("nbits",c.i32_shl(c.getLocal("scalarLength"),c.i32_const(3))),c.setLocal("old0",c.i32_load(c.i32_const(0))),c.setLocal("p",c.getLocal("old0")),c.i32_store(c.i32_const(0),c.i32_and(c.i32_add(c.i32_add(c.getLocal("old0"),c.i32_const(32)),c.getLocal("nbits")),c.i32_const(4294967288))),c.setLocal("i",c.i32_const(1)),c.setLocal("last",u(c.i32_const(0))),c.setLocal("carry",c.i32_const(0)),c.block(c.loop(c.br_if(1,c.i32_eq(c.getLocal("i"),c.getLocal("nbits"))),c.setLocal("cur",u(c.getLocal("i"))),c.if(c.getLocal("last"),c.if(c.getLocal("cur"),c.if(c.getLocal("carry"),[...c.setLocal("last",c.i32_const(0)),...c.setLocal("carry",c.i32_const(1)),...f(1)],[...c.setLocal("last",c.i32_const(0)),...c.setLocal("carry",c.i32_const(1)),...f(255)]),c.if(c.getLocal("carry"),[...c.setLocal("last",c.i32_const(0)),...c.setLocal("carry",c.i32_const(1)),...f(255)],[...c.setLocal("last",c.i32_const(0)),...c.setLocal("carry",c.i32_const(0)),...f(1)])),c.if(c.getLocal("cur"),c.if(c.getLocal("carry"),[...c.setLocal("last",c.i32_const(0)),...c.setLocal("carry",c.i32_const(1)),...f(0)],[...c.setLocal("last",c.i32_const(1)),...c.setLocal("carry",c.i32_const(0)),...f(0)]),c.if(c.getLocal("carry"),[...c.setLocal("last",c.i32_const(1)),...c.setLocal("carry",c.i32_const(0)),...f(0)],[...c.setLocal("last",c.i32_const(0)),...c.setLocal("carry",c.i32_const(0)),...f(0)]))),c.setLocal("i",c.i32_add(c.getLocal("i"),c.i32_const(1))),c.br(0))),c.if(c.getLocal("last"),c.if(c.getLocal("carry"),[...f(255),...f(0),...f(1)],[...f(1)]),c.if(c.getLocal("carry"),[...f(0),...f(1)])),c.setLocal("p",c.i32_sub(c.getLocal("p"),c.i32_const(1))),c.call(l,c.getLocal("base"),d),c.call(r,c.getLocal("r")),c.block(c.loop(c.call(n,c.getLocal("r"),c.getLocal("r")),c.setLocal("cur",c.i32_load8_u(c.getLocal("p"))),c.if(c.getLocal("cur"),c.if(c.i32_eq(c.getLocal("cur"),c.i32_const(1)),c.call(i,c.getLocal("r"),d,c.getLocal("r")),c.call(o,c.getLocal("r"),d,c.getLocal("r")))),c.br_if(1,c.i32_eq(c.getLocal("old0"),c.getLocal("p"))),c.setLocal("p",c.i32_sub(c.getLocal("p"),c.i32_const(1))),c.br(0))),c.i32_store(c.i32_const(0),c.getLocal("old0")))},he=At,pe=function(t,e,a,i,n){const o=8*t.modules[e].n64;function l(){const i=t.addFunction(a);i.addParam("pBases","i32"),i.addParam("pScalars","i32"),i.addParam("scalarSize","i32"),i.addParam("n","i32"),i.addParam("pr","i32"),i.addLocal("chunkSize","i32"),i.addLocal("nChunks","i32"),i.addLocal("itScalar","i32"),i.addLocal("endScalar","i32"),i.addLocal("itBase","i32"),i.addLocal("itBit","i32"),i.addLocal("i","i32"),i.addLocal("j","i32"),i.addLocal("nTable","i32"),i.addLocal("pTable","i32"),i.addLocal("idx","i32"),i.addLocal("pIdxTable","i32");const n=i.getCodeBuilder(),l=n.i32_const(t.alloc(o)),r=t.alloc([17,17,17,17,17,17,17,17,17,17,16,16,15,14,13,13,12,11,10,9,8,7,7,6,5,4,3,2,1,1,1,1]);i.addCode(n.call(e+"_zero",n.getLocal("pr")),n.if(n.i32_eqz(n.getLocal("n")),n.ret([])),n.setLocal("chunkSize",n.i32_load8_u(n.i32_clz(n.getLocal("n")),r)),n.setLocal("nChunks",n.i32_add(n.i32_div_u(n.i32_sub(n.i32_shl(n.getLocal("scalarSize"),n.i32_const(3)),n.i32_const(1)),n.getLocal("chunkSize")),n.i32_const(1))),n.setLocal("itBit",n.i32_mul(n.i32_sub(n.getLocal("nChunks"),n.i32_const(1)),n.getLocal("chunkSize"))),n.block(n.loop(n.br_if(1,n.i32_lt_s(n.getLocal("itBit"),n.i32_const(0))),n.if(n.i32_eqz(n.call(e+"_isZero",n.getLocal("pr"))),[...n.setLocal("j",n.i32_const(0)),...n.block(n.loop(n.br_if(1,n.i32_eq(n.getLocal("j"),n.getLocal("chunkSize"))),n.call(e+"_double",n.getLocal("pr"),n.getLocal("pr")),n.setLocal("j",n.i32_add(n.getLocal("j"),n.i32_const(1))),n.br(0)))]),n.call(a+"_chunk",n.getLocal("pBases"),n.getLocal("pScalars"),n.getLocal("scalarSize"),n.getLocal("n"),n.getLocal("itBit"),n.getLocal("chunkSize"),l),n.call(e+"_add",n.getLocal("pr"),l,n.getLocal("pr")),n.setLocal("itBit",n.i32_sub(n.getLocal("itBit"),n.getLocal("chunkSize"))),n.br(0))))}!function(){const e=t.addFunction(a+"_getChunk");e.addParam("pScalar","i32"),e.addParam("scalarSize","i32"),e.addParam("startBit","i32"),e.addParam("chunkSize","i32"),e.addLocal("bitsToEnd","i32"),e.addLocal("mask","i32"),e.setReturnType("i32");const i=e.getCodeBuilder();e.addCode(i.setLocal("bitsToEnd",i.i32_sub(i.i32_mul(i.getLocal("scalarSize"),i.i32_const(8)),i.getLocal("startBit"))),i.if(i.i32_gt_s(i.getLocal("chunkSize"),i.getLocal("bitsToEnd")),i.setLocal("mask",i.i32_sub(i.i32_shl(i.i32_const(1),i.getLocal("bitsToEnd")),i.i32_const(1))),i.setLocal("mask",i.i32_sub(i.i32_shl(i.i32_const(1),i.getLocal("chunkSize")),i.i32_const(1)))),i.i32_and(i.i32_shr_u(i.i32_load(i.i32_add(i.getLocal("pScalar"),i.i32_shr_u(i.getLocal("startBit"),i.i32_const(3))),0,0),i.i32_and(i.getLocal("startBit"),i.i32_const(7))),i.getLocal("mask")))}(),function(){const i=t.addFunction(a+"_reduceTable");i.addParam("pTable","i32"),i.addParam("p","i32"),i.addLocal("half","i32"),i.addLocal("it1","i32"),i.addLocal("it2","i32"),i.addLocal("pAcc","i32");const n=i.getCodeBuilder();i.addCode(n.if(n.i32_eq(n.getLocal("p"),n.i32_const(1)),n.ret([])),n.setLocal("half",n.i32_shl(n.i32_const(1),n.i32_sub(n.getLocal("p"),n.i32_const(1)))),n.setLocal("it1",n.getLocal("pTable")),n.setLocal("it2",n.i32_add(n.getLocal("pTable"),n.i32_mul(n.getLocal("half"),n.i32_const(o)))),n.setLocal("pAcc",n.i32_sub(n.getLocal("it2"),n.i32_const(o))),n.block(n.loop(n.br_if(1,n.i32_eq(n.getLocal("it1"),n.getLocal("pAcc"))),n.call(e+"_add",n.getLocal("it1"),n.getLocal("it2"),n.getLocal("it1")),n.call(e+"_add",n.getLocal("pAcc"),n.getLocal("it2"),n.getLocal("pAcc")),n.setLocal("it1",n.i32_add(n.getLocal("it1"),n.i32_const(o))),n.setLocal("it2",n.i32_add(n.getLocal("it2"),n.i32_const(o))),n.br(0))),n.call(a+"_reduceTable",n.getLocal("pTable"),n.i32_sub(n.getLocal("p"),n.i32_const(1))),n.setLocal("p",n.i32_sub(n.getLocal("p"),n.i32_const(1))),n.block(n.loop(n.br_if(1,n.i32_eqz(n.getLocal("p"))),n.call(e+"_double",n.getLocal("pAcc"),n.getLocal("pAcc")),n.setLocal("p",n.i32_sub(n.getLocal("p"),n.i32_const(1))),n.br(0))),n.call(e+"_add",n.getLocal("pTable"),n.getLocal("pAcc"),n.getLocal("pTable")))}(),function(){const l=t.addFunction(a+"_chunk");l.addParam("pBases","i32"),l.addParam("pScalars","i32"),l.addParam("scalarSize","i32"),l.addParam("n","i32"),l.addParam("startBit","i32"),l.addParam("chunkSize","i32"),l.addParam("pr","i32"),l.addLocal("nChunks","i32"),l.addLocal("itScalar","i32"),l.addLocal("endScalar","i32"),l.addLocal("itBase","i32"),l.addLocal("i","i32"),l.addLocal("j","i32"),l.addLocal("nTable","i32"),l.addLocal("pTable","i32"),l.addLocal("idx","i32"),l.addLocal("pIdxTable","i32");const r=l.getCodeBuilder();l.addCode(r.if(r.i32_eqz(r.getLocal("n")),[...r.call(e+"_zero",r.getLocal("pr")),...r.ret([])]),r.setLocal("nTable",r.i32_shl(r.i32_const(1),r.getLocal("chunkSize"))),r.setLocal("pTable",r.i32_load(r.i32_const(0))),r.i32_store(r.i32_const(0),r.i32_add(r.getLocal("pTable"),r.i32_mul(r.getLocal("nTable"),r.i32_const(o)))),r.setLocal("j",r.i32_const(0)),r.block(r.loop(r.br_if(1,r.i32_eq(r.getLocal("j"),r.getLocal("nTable"))),r.call(e+"_zero",r.i32_add(r.getLocal("pTable"),r.i32_mul(r.getLocal("j"),r.i32_const(o)))),r.setLocal("j",r.i32_add(r.getLocal("j"),r.i32_const(1))),r.br(0))),r.setLocal("itBase",r.getLocal("pBases")),r.setLocal("itScalar",r.getLocal("pScalars")),r.setLocal("endScalar",r.i32_add(r.getLocal("pScalars"),r.i32_mul(r.getLocal("n"),r.getLocal("scalarSize")))),r.block(r.loop(r.br_if(1,r.i32_eq(r.getLocal("itScalar"),r.getLocal("endScalar"))),r.setLocal("idx",r.call(a+"_getChunk",r.getLocal("itScalar"),r.getLocal("scalarSize"),r.getLocal("startBit"),r.getLocal("chunkSize"))),r.if(r.getLocal("idx"),[...r.setLocal("pIdxTable",r.i32_add(r.getLocal("pTable"),r.i32_mul(r.i32_sub(r.getLocal("idx"),r.i32_const(1)),r.i32_const(o)))),...r.call(i,r.getLocal("pIdxTable"),r.getLocal("itBase"),r.getLocal("pIdxTable"))]),r.setLocal("itScalar",r.i32_add(r.getLocal("itScalar"),r.getLocal("scalarSize"))),r.setLocal("itBase",r.i32_add(r.getLocal("itBase"),r.i32_const(n))),r.br(0))),r.call(a+"_reduceTable",r.getLocal("pTable"),r.getLocal("chunkSize")),r.call(e+"_copy",r.getLocal("pTable"),r.getLocal("pr")),r.i32_store(r.i32_const(0),r.getLocal("pTable")))}(),l(),t.exportFunction(a),t.exportFunction(a+"_chunk")};var _e=function(t,e,a,i){const n=t.modules[a].n64,o=8*n;if(t.modules[e])return e;return t.modules[e]={n64:3*n},function(){const i=t.addFunction(e+"_isZeroAffine");i.addParam("p1","i32"),i.setReturnType("i32");const n=i.getCodeBuilder();i.addCode(n.i32_and(n.call(a+"_isZero",n.getLocal("p1")),n.call(a+"_isZero",n.i32_add(n.getLocal("p1"),n.i32_const(o)))))}(),function(){const i=t.addFunction(e+"_isZero");i.addParam("p1","i32"),i.setReturnType("i32");const n=i.getCodeBuilder();i.addCode(n.call(a+"_isZero",n.i32_add(n.getLocal("p1"),n.i32_const(2*o))))}(),function(){const i=t.addFunction(e+"_zeroAffine");i.addParam("pr","i32");const n=i.getCodeBuilder();i.addCode(n.call(a+"_zero",n.getLocal("pr"))),i.addCode(n.call(a+"_zero",n.i32_add(n.getLocal("pr"),n.i32_const(o))))}(),function(){const i=t.addFunction(e+"_zero");i.addParam("pr","i32");const n=i.getCodeBuilder();i.addCode(n.call(a+"_zero",n.getLocal("pr"))),i.addCode(n.call(a+"_one",n.i32_add(n.getLocal("pr"),n.i32_const(o)))),i.addCode(n.call(a+"_zero",n.i32_add(n.getLocal("pr"),n.i32_const(2*o))))}(),function(){const a=t.addFunction(e+"_copyAffine");a.addParam("ps","i32"),a.addParam("pd","i32");const i=a.getCodeBuilder();for(let t=0;t<2*n;t++)a.addCode(i.i64_store(i.getLocal("pd"),8*t,i.i64_load(i.getLocal("ps"),8*t)))}(),function(){const a=t.addFunction(e+"_copy");a.addParam("ps","i32"),a.addParam("pd","i32");const i=a.getCodeBuilder();for(let t=0;t<3*n;t++)a.addCode(i.i64_store(i.getLocal("pd"),8*t,i.i64_load(i.getLocal("ps"),8*t)))}(),function(){const i=t.addFunction(e+"_toJacobian");i.addParam("p1","i32"),i.addParam("pr","i32");const n=i.getCodeBuilder(),l=n.getLocal("p1"),r=n.i32_add(n.getLocal("p1"),n.i32_const(o)),s=n.getLocal("pr"),c=n.i32_add(n.getLocal("pr"),n.i32_const(o)),d=n.i32_add(n.getLocal("pr"),n.i32_const(2*o));i.addCode(n.if(n.call(e+"_isZeroAffine",n.getLocal("p1")),n.call(e+"_zero",n.getLocal("pr")),[...n.call(a+"_one",d),...n.call(a+"_copy",r,c),...n.call(a+"_copy",l,s)]))}(),function(){const i=t.addFunction(e+"_eqAffine");i.addParam("p1","i32"),i.addParam("p2","i32"),i.setReturnType("i32"),i.addLocal("z1","i32");const n=i.getCodeBuilder();i.addCode(n.ret(n.i32_and(n.call(a+"_eq",n.getLocal("p1"),n.getLocal("p2")),n.call(a+"_eq",n.i32_add(n.getLocal("p1"),n.i32_const(o)),n.i32_add(n.getLocal("p2"),n.i32_const(o))))))}(),function(){const i=t.addFunction(e+"_eqMixed");i.addParam("p1","i32"),i.addParam("p2","i32"),i.setReturnType("i32"),i.addLocal("z1","i32");const n=i.getCodeBuilder(),l=n.getLocal("p1"),r=n.i32_add(n.getLocal("p1"),n.i32_const(o));i.addCode(n.setLocal("z1",n.i32_add(n.getLocal("p1"),n.i32_const(2*o))));const s=n.getLocal("z1"),c=n.getLocal("p2"),d=n.i32_add(n.getLocal("p2"),n.i32_const(o)),u=n.i32_const(t.alloc(o)),f=n.i32_const(t.alloc(o)),g=n.i32_const(t.alloc(o)),h=n.i32_const(t.alloc(o));i.addCode(n.if(n.call(e+"_isZero",n.getLocal("p1")),n.ret(n.call(e+"_isZeroAffine",n.getLocal("p2")))),n.if(n.call(e+"_isZeroAffine",n.getLocal("p2")),n.ret(n.i32_const(0))),n.if(n.call(a+"_isOne",s),n.ret(n.call(e+"_eqAffine",n.getLocal("p1"),n.getLocal("p2")))),n.call(a+"_square",s,u),n.call(a+"_mul",c,u,f),n.call(a+"_mul",s,u,g),n.call(a+"_mul",d,g,h),n.if(n.call(a+"_eq",l,f),n.if(n.call(a+"_eq",r,h),n.ret(n.i32_const(1)))),n.ret(n.i32_const(0)))}(),function(){const i=t.addFunction(e+"_eq");i.addParam("p1","i32"),i.addParam("p2","i32"),i.setReturnType("i32"),i.addLocal("z1","i32"),i.addLocal("z2","i32");const n=i.getCodeBuilder(),l=n.getLocal("p1"),r=n.i32_add(n.getLocal("p1"),n.i32_const(o));i.addCode(n.setLocal("z1",n.i32_add(n.getLocal("p1"),n.i32_const(2*o))));const s=n.getLocal("z1"),c=n.getLocal("p2"),d=n.i32_add(n.getLocal("p2"),n.i32_const(o));i.addCode(n.setLocal("z2",n.i32_add(n.getLocal("p2"),n.i32_const(2*o))));const u=n.getLocal("z2"),f=n.i32_const(t.alloc(o)),g=n.i32_const(t.alloc(o)),h=n.i32_const(t.alloc(o)),p=n.i32_const(t.alloc(o)),_=n.i32_const(t.alloc(o)),m=n.i32_const(t.alloc(o)),w=n.i32_const(t.alloc(o)),L=n.i32_const(t.alloc(o));i.addCode(n.if(n.call(e+"_isZero",n.getLocal("p1")),n.ret(n.call(e+"_isZero",n.getLocal("p2")))),n.if(n.call(e+"_isZero",n.getLocal("p2")),n.ret(n.i32_const(0))),n.if(n.call(a+"_isOne",s),n.ret(n.call(e+"_eqMixed",n.getLocal("p2"),n.getLocal("p1")))),n.if(n.call(a+"_isOne",u),n.ret(n.call(e+"_eqMixed",n.getLocal("p1"),n.getLocal("p2")))),n.call(a+"_square",s,f),n.call(a+"_square",u,g),n.call(a+"_mul",l,g,h),n.call(a+"_mul",c,f,p),n.call(a+"_mul",s,f,_),n.call(a+"_mul",u,g,m),n.call(a+"_mul",r,m,w),n.call(a+"_mul",d,_,L),n.if(n.call(a+"_eq",h,p),n.if(n.call(a+"_eq",w,L),n.ret(n.i32_const(1)))),n.ret(n.i32_const(0)))}(),function(){const i=t.addFunction(e+"_doubleAffine");i.addParam("p1","i32"),i.addParam("pr","i32");const n=i.getCodeBuilder(),l=n.getLocal("p1"),r=n.i32_add(n.getLocal("p1"),n.i32_const(o)),s=n.getLocal("pr"),c=n.i32_add(n.getLocal("pr"),n.i32_const(o)),d=n.i32_add(n.getLocal("pr"),n.i32_const(2*o)),u=n.i32_const(t.alloc(o)),f=n.i32_const(t.alloc(o)),g=n.i32_const(t.alloc(o)),h=n.i32_const(t.alloc(o)),p=n.i32_const(t.alloc(o)),_=n.i32_const(t.alloc(o));i.addCode(n.if(n.call(e+"_isZeroAffine",n.getLocal("p1")),[...n.call(e+"_toJacobian",n.getLocal("p1"),n.getLocal("pr")),...n.ret([])]),n.call(a+"_square",l,u),n.call(a+"_square",r,f),n.call(a+"_square",f,g),n.call(a+"_add",l,f,h),n.call(a+"_square",h,h),n.call(a+"_sub",h,u,h),n.call(a+"_sub",h,g,h),n.call(a+"_add",h,h,h),n.call(a+"_add",u,u,p),n.call(a+"_add",p,u,p),n.call(a+"_add",r,r,d),n.call(a+"_square",p,s),n.call(a+"_sub",s,h,s),n.call(a+"_sub",s,h,s),n.call(a+"_add",g,g,_),n.call(a+"_add",_,_,_),n.call(a+"_add",_,_,_),n.call(a+"_sub",h,s,c),n.call(a+"_mul",c,p,c),n.call(a+"_sub",c,_,c))}(),function(){const i=t.addFunction(e+"_double");i.addParam("p1","i32"),i.addParam("pr","i32");const n=i.getCodeBuilder(),l=n.getLocal("p1"),r=n.i32_add(n.getLocal("p1"),n.i32_const(o)),s=n.i32_add(n.getLocal("p1"),n.i32_const(2*o)),c=n.getLocal("pr"),d=n.i32_add(n.getLocal("pr"),n.i32_const(o)),u=n.i32_add(n.getLocal("pr"),n.i32_const(2*o)),f=n.i32_const(t.alloc(o)),g=n.i32_const(t.alloc(o)),h=n.i32_const(t.alloc(o)),p=n.i32_const(t.alloc(o)),_=n.i32_const(t.alloc(o)),m=n.i32_const(t.alloc(o)),w=n.i32_const(t.alloc(o)),L=n.i32_const(t.alloc(o));i.addCode(n.if(n.call(e+"_isZero",n.getLocal("p1")),[...n.call(e+"_copy",n.getLocal("p1"),n.getLocal("pr")),...n.ret([])]),n.if(n.call(a+"_isOne",s),[...n.ret(n.call(e+"_doubleAffine",n.getLocal("p1"),n.getLocal("pr"))),...n.ret([])]),n.call(a+"_square",l,f),n.call(a+"_square",r,g),n.call(a+"_square",g,h),n.call(a+"_add",l,g,p),n.call(a+"_square",p,p),n.call(a+"_sub",p,f,p),n.call(a+"_sub",p,h,p),n.call(a+"_add",p,p,p),n.call(a+"_add",f,f,_),n.call(a+"_add",_,f,_),n.call(a+"_square",_,m),n.call(a+"_mul",r,s,w),n.call(a+"_add",p,p,c),n.call(a+"_sub",m,c,c),n.call(a+"_add",h,h,L),n.call(a+"_add",L,L,L),n.call(a+"_add",L,L,L),n.call(a+"_sub",p,c,d),n.call(a+"_mul",d,_,d),n.call(a+"_sub",d,L,d),n.call(a+"_add",w,w,u))}(),function(){const i=t.addFunction(e+"_addAffine");i.addParam("p1","i32"),i.addParam("p2","i32"),i.addParam("pr","i32"),i.addLocal("z1","i32");const n=i.getCodeBuilder(),l=n.getLocal("p1"),r=n.i32_add(n.getLocal("p1"),n.i32_const(o));i.addCode(n.setLocal("z1",n.i32_add(n.getLocal("p1"),n.i32_const(2*o))));const s=n.getLocal("p2"),c=n.i32_add(n.getLocal("p2"),n.i32_const(o)),d=n.getLocal("pr"),u=n.i32_add(n.getLocal("pr"),n.i32_const(o)),f=n.i32_add(n.getLocal("pr"),n.i32_const(2*o)),g=n.i32_const(t.alloc(o)),h=n.i32_const(t.alloc(o)),p=n.i32_const(t.alloc(o)),_=n.i32_const(t.alloc(o)),m=n.i32_const(t.alloc(o)),w=n.i32_const(t.alloc(o)),L=n.i32_const(t.alloc(o)),b=n.i32_const(t.alloc(o)),y=n.i32_const(t.alloc(o)),v=n.i32_const(t.alloc(o));i.addCode(n.if(n.call(e+"_isZeroAffine",n.getLocal("p1")),[...n.call(e+"_copyAffine",n.getLocal("p2"),n.getLocal("pr")),...n.call(a+"_one",n.i32_add(n.getLocal("pr"),n.i32_const(2*o))),...n.ret([])]),n.if(n.call(e+"_isZeroAffine",n.getLocal("p2")),[...n.call(e+"_copyAffine",n.getLocal("p1"),n.getLocal("pr")),...n.call(a+"_one",n.i32_add(n.getLocal("pr"),n.i32_const(2*o))),...n.ret([])]),n.if(n.call(a+"_eq",l,s),n.if(n.call(a+"_eq",r,c),[...n.call(e+"_doubleAffine",n.getLocal("p2"),n.getLocal("pr")),...n.ret([])])),n.call(a+"_sub",s,l,g),n.call(a+"_sub",c,r,p),n.call(a+"_square",g,h),n.call(a+"_add",h,h,_),n.call(a+"_add",_,_,_),n.call(a+"_mul",g,_,m),n.call(a+"_add",p,p,w),n.call(a+"_mul",l,_,b),n.call(a+"_square",w,L),n.call(a+"_add",b,b,y),n.call(a+"_sub",L,m,d),n.call(a+"_sub",d,y,d),n.call(a+"_mul",r,m,v),n.call(a+"_add",v,v,v),n.call(a+"_sub",b,d,u),n.call(a+"_mul",u,w,u),n.call(a+"_sub",u,v,u),n.call(a+"_add",g,g,f))}(),function(){const i=t.addFunction(e+"_addMixed");i.addParam("p1","i32"),i.addParam("p2","i32"),i.addParam("pr","i32"),i.addLocal("z1","i32");const n=i.getCodeBuilder(),l=n.getLocal("p1"),r=n.i32_add(n.getLocal("p1"),n.i32_const(o));i.addCode(n.setLocal("z1",n.i32_add(n.getLocal("p1"),n.i32_const(2*o))));const s=n.getLocal("z1"),c=n.getLocal("p2"),d=n.i32_add(n.getLocal("p2"),n.i32_const(o)),u=n.getLocal("pr"),f=n.i32_add(n.getLocal("pr"),n.i32_const(o)),g=n.i32_add(n.getLocal("pr"),n.i32_const(2*o)),h=n.i32_const(t.alloc(o)),p=n.i32_const(t.alloc(o)),_=n.i32_const(t.alloc(o)),m=n.i32_const(t.alloc(o)),w=n.i32_const(t.alloc(o)),L=n.i32_const(t.alloc(o)),b=n.i32_const(t.alloc(o)),y=n.i32_const(t.alloc(o)),v=n.i32_const(t.alloc(o)),F=n.i32_const(t.alloc(o)),x=n.i32_const(t.alloc(o)),C=n.i32_const(t.alloc(o)),S=n.i32_const(t.alloc(o)),E=n.i32_const(t.alloc(o));i.addCode(n.if(n.call(e+"_isZero",n.getLocal("p1")),[...n.call(e+"_copyAffine",n.getLocal("p2"),n.getLocal("pr")),...n.call(a+"_one",n.i32_add(n.getLocal("pr"),n.i32_const(2*o))),...n.ret([])]),n.if(n.call(e+"_isZeroAffine",n.getLocal("p2")),[...n.call(e+"_copy",n.getLocal("p1"),n.getLocal("pr")),...n.ret([])]),n.if(n.call(a+"_isOne",s),[...n.call(e+"_addAffine",l,c,u),...n.ret([])]),n.call(a+"_square",s,h),n.call(a+"_mul",c,h,p),n.call(a+"_mul",s,h,_),n.call(a+"_mul",d,_,m),n.if(n.call(a+"_eq",l,p),n.if(n.call(a+"_eq",r,m),[...n.call(e+"_doubleAffine",n.getLocal("p2"),n.getLocal("pr")),...n.ret([])])),n.call(a+"_sub",p,l,w),n.call(a+"_sub",m,r,b),n.call(a+"_square",w,L),n.call(a+"_add",L,L,y),n.call(a+"_add",y,y,y),n.call(a+"_mul",w,y,v),n.call(a+"_add",b,b,F),n.call(a+"_mul",l,y,C),n.call(a+"_square",F,x),n.call(a+"_add",C,C,S),n.call(a+"_sub",x,v,u),n.call(a+"_sub",u,S,u),n.call(a+"_mul",r,v,E),n.call(a+"_add",E,E,E),n.call(a+"_sub",C,u,f),n.call(a+"_mul",f,F,f),n.call(a+"_sub",f,E,f),n.call(a+"_add",s,w,g),n.call(a+"_square",g,g),n.call(a+"_sub",g,h,g),n.call(a+"_sub",g,L,g))}(),function(){const i=t.addFunction(e+"_add");i.addParam("p1","i32"),i.addParam("p2","i32"),i.addParam("pr","i32"),i.addLocal("z1","i32"),i.addLocal("z2","i32");const n=i.getCodeBuilder(),l=n.getLocal("p1"),r=n.i32_add(n.getLocal("p1"),n.i32_const(o));i.addCode(n.setLocal("z1",n.i32_add(n.getLocal("p1"),n.i32_const(2*o))));const s=n.getLocal("z1"),c=n.getLocal("p2"),d=n.i32_add(n.getLocal("p2"),n.i32_const(o));i.addCode(n.setLocal("z2",n.i32_add(n.getLocal("p2"),n.i32_const(2*o))));const u=n.getLocal("z2"),f=n.getLocal("pr"),g=n.i32_add(n.getLocal("pr"),n.i32_const(o)),h=n.i32_add(n.getLocal("pr"),n.i32_const(2*o)),p=n.i32_const(t.alloc(o)),_=n.i32_const(t.alloc(o)),m=n.i32_const(t.alloc(o)),w=n.i32_const(t.alloc(o)),L=n.i32_const(t.alloc(o)),b=n.i32_const(t.alloc(o)),y=n.i32_const(t.alloc(o)),v=n.i32_const(t.alloc(o)),F=n.i32_const(t.alloc(o)),x=n.i32_const(t.alloc(o)),C=n.i32_const(t.alloc(o)),S=n.i32_const(t.alloc(o)),E=n.i32_const(t.alloc(o)),A=n.i32_const(t.alloc(o)),B=n.i32_const(t.alloc(o)),P=n.i32_const(t.alloc(o)),z=n.i32_const(t.alloc(o));i.addCode(n.if(n.call(e+"_isZero",n.getLocal("p1")),[...n.call(e+"_copy",n.getLocal("p2"),n.getLocal("pr")),...n.ret([])]),n.if(n.call(e+"_isZero",n.getLocal("p2")),[...n.call(e+"_copy",n.getLocal("p1"),n.getLocal("pr")),...n.ret([])]),n.if(n.call(a+"_isOne",s),[...n.call(e+"_addMixed",c,l,f),...n.ret([])]),n.if(n.call(a+"_isOne",u),[...n.call(e+"_addMixed",l,c,f),...n.ret([])]),n.call(a+"_square",s,p),n.call(a+"_square",u,_),n.call(a+"_mul",l,_,m),n.call(a+"_mul",c,p,w),n.call(a+"_mul",s,p,L),n.call(a+"_mul",u,_,b),n.call(a+"_mul",r,b,y),n.call(a+"_mul",d,L,v),n.if(n.call(a+"_eq",m,w),n.if(n.call(a+"_eq",y,v),[...n.call(e+"_double",n.getLocal("p1"),n.getLocal("pr")),...n.ret([])])),n.call(a+"_sub",w,m,F),n.call(a+"_sub",v,y,x),n.call(a+"_add",F,F,C),n.call(a+"_square",C,C),n.call(a+"_mul",F,C,S),n.call(a+"_add",x,x,E),n.call(a+"_mul",m,C,B),n.call(a+"_square",E,A),n.call(a+"_add",B,B,P),n.call(a+"_sub",A,S,f),n.call(a+"_sub",f,P,f),n.call(a+"_mul",y,S,z),n.call(a+"_add",z,z,z),n.call(a+"_sub",B,f,g),n.call(a+"_mul",g,E,g),n.call(a+"_sub",g,z,g),n.call(a+"_add",s,u,h),n.call(a+"_square",h,h),n.call(a+"_sub",h,p,h),n.call(a+"_sub",h,_,h),n.call(a+"_mul",h,F,h))}(),function(){const i=t.addFunction(e+"_negAffine");i.addParam("p1","i32"),i.addParam("pr","i32");const n=i.getCodeBuilder(),l=n.getLocal("p1"),r=n.i32_add(n.getLocal("p1"),n.i32_const(o)),s=n.getLocal("pr"),c=n.i32_add(n.getLocal("pr"),n.i32_const(o));i.addCode(n.call(a+"_copy",l,s),n.call(a+"_neg",r,c))}(),function(){const i=t.addFunction(e+"_neg");i.addParam("p1","i32"),i.addParam("pr","i32");const n=i.getCodeBuilder(),l=n.getLocal("p1"),r=n.i32_add(n.getLocal("p1"),n.i32_const(o)),s=n.i32_add(n.getLocal("p1"),n.i32_const(2*o)),c=n.getLocal("pr"),d=n.i32_add(n.getLocal("pr"),n.i32_const(o)),u=n.i32_add(n.getLocal("pr"),n.i32_const(2*o));i.addCode(n.call(a+"_copy",l,c),n.call(a+"_neg",r,d),n.call(a+"_copy",s,u))}(),function(){const a=t.addFunction(e+"_subAffine");a.addParam("p1","i32"),a.addParam("p2","i32"),a.addParam("pr","i32");const i=a.getCodeBuilder(),n=i.i32_const(t.alloc(3*o));a.addCode(i.call(e+"_negAffine",i.getLocal("p2"),n),i.call(e+"_addAffine",i.getLocal("p1"),n,i.getLocal("pr")))}(),function(){const a=t.addFunction(e+"_subMixed");a.addParam("p1","i32"),a.addParam("p2","i32"),a.addParam("pr","i32");const i=a.getCodeBuilder(),n=i.i32_const(t.alloc(3*o));a.addCode(i.call(e+"_negAffine",i.getLocal("p2"),n),i.call(e+"_addMixed",i.getLocal("p1"),n,i.getLocal("pr")))}(),function(){const a=t.addFunction(e+"_sub");a.addParam("p1","i32"),a.addParam("p2","i32"),a.addParam("pr","i32");const i=a.getCodeBuilder(),n=i.i32_const(t.alloc(3*o));a.addCode(i.call(e+"_neg",i.getLocal("p2"),n),i.call(e+"_add",i.getLocal("p1"),n,i.getLocal("pr")))}(),function(){const i=t.addFunction(e+"_fromMontgomeryAffine");i.addParam("p1","i32"),i.addParam("pr","i32");const n=i.getCodeBuilder();i.addCode(n.call(a+"_fromMontgomery",n.getLocal("p1"),n.getLocal("pr")));for(let t=1;t<2;t++)i.addCode(n.call(a+"_fromMontgomery",n.i32_add(n.getLocal("p1"),n.i32_const(t*o)),n.i32_add(n.getLocal("pr"),n.i32_const(t*o))))}(),function(){const i=t.addFunction(e+"_fromMontgomery");i.addParam("p1","i32"),i.addParam("pr","i32");const n=i.getCodeBuilder();i.addCode(n.call(a+"_fromMontgomery",n.getLocal("p1"),n.getLocal("pr")));for(let t=1;t<3;t++)i.addCode(n.call(a+"_fromMontgomery",n.i32_add(n.getLocal("p1"),n.i32_const(t*o)),n.i32_add(n.getLocal("pr"),n.i32_const(t*o))))}(),function(){const i=t.addFunction(e+"_toMontgomeryAffine");i.addParam("p1","i32"),i.addParam("pr","i32");const n=i.getCodeBuilder();i.addCode(n.call(a+"_toMontgomery",n.getLocal("p1"),n.getLocal("pr")));for(let t=1;t<2;t++)i.addCode(n.call(a+"_toMontgomery",n.i32_add(n.getLocal("p1"),n.i32_const(t*o)),n.i32_add(n.getLocal("pr"),n.i32_const(t*o))))}(),function(){const i=t.addFunction(e+"_toMontgomery");i.addParam("p1","i32"),i.addParam("pr","i32");const n=i.getCodeBuilder();i.addCode(n.call(a+"_toMontgomery",n.getLocal("p1"),n.getLocal("pr")));for(let t=1;t<3;t++)i.addCode(n.call(a+"_toMontgomery",n.i32_add(n.getLocal("p1"),n.i32_const(t*o)),n.i32_add(n.getLocal("pr"),n.i32_const(t*o))))}(),function(){const i=t.addFunction(e+"_toAffine");i.addParam("p1","i32"),i.addParam("pr","i32");const n=i.getCodeBuilder(),l=n.getLocal("p1"),r=n.i32_add(n.getLocal("p1"),n.i32_const(o)),s=n.i32_add(n.getLocal("p1"),n.i32_const(2*o)),c=n.getLocal("pr"),d=n.i32_add(n.getLocal("pr"),n.i32_const(o)),u=n.i32_const(t.alloc(o)),f=n.i32_const(t.alloc(o)),g=n.i32_const(t.alloc(o));i.addCode(n.if(n.call(e+"_isZero",n.getLocal("p1")),[...n.call(a+"_zero",c),...n.call(a+"_zero",d)],[...n.call(a+"_inverse",s,u),...n.call(a+"_square",u,f),...n.call(a+"_mul",u,f,g),...n.call(a+"_mul",l,f,c),...n.call(a+"_mul",r,g,d)]))}(),function(){const n=t.addFunction(e+"_inCurveAffine");n.addParam("pIn","i32"),n.setReturnType("i32");const l=n.getCodeBuilder(),r=l.getLocal("pIn"),s=l.i32_add(l.getLocal("pIn"),l.i32_const(o)),c=l.i32_const(t.alloc(o)),d=l.i32_const(t.alloc(o));n.addCode(l.call(a+"_square",s,c),l.call(a+"_square",r,d),l.call(a+"_mul",r,d,d),l.call(a+"_add",d,l.i32_const(i),d),l.ret(l.call(a+"_eq",c,d)))}(),function(){const a=t.addFunction(e+"_inCurve");a.addParam("pIn","i32"),a.setReturnType("i32");const i=a.getCodeBuilder(),n=i.i32_const(t.alloc(2*o));a.addCode(i.call(e+"_toAffine",i.getLocal("pIn"),n),i.ret(i.call(e+"_inCurveAffine",n)))}(),function(){const i=t.addFunction(e+"_batchToAffine");i.addParam("pIn","i32"),i.addParam("n","i32"),i.addParam("pOut","i32"),i.addLocal("pAux","i32"),i.addLocal("itIn","i32"),i.addLocal("itAux","i32"),i.addLocal("itOut","i32"),i.addLocal("i","i32");const n=i.getCodeBuilder(),l=n.i32_const(t.alloc(o));i.addCode(n.setLocal("pAux",n.i32_load(n.i32_const(0))),n.i32_store(n.i32_const(0),n.i32_add(n.getLocal("pAux"),n.i32_mul(n.getLocal("n"),n.i32_const(o)))),n.call(a+"_batchInverse",n.i32_add(n.getLocal("pIn"),n.i32_const(2*o)),n.i32_const(3*o),n.getLocal("n"),n.getLocal("pAux"),n.i32_const(o)),n.setLocal("itIn",n.getLocal("pIn")),n.setLocal("itAux",n.getLocal("pAux")),n.setLocal("itOut",n.getLocal("pOut")),n.setLocal("i",n.i32_const(0)),n.block(n.loop(n.br_if(1,n.i32_eq(n.getLocal("i"),n.getLocal("n"))),n.if(n.call(a+"_isZero",n.getLocal("itAux")),[...n.call(a+"_zero",n.getLocal("itOut")),...n.call(a+"_zero",n.i32_add(n.getLocal("itOut"),n.i32_const(o)))],[...n.call(a+"_mul",n.getLocal("itAux"),n.i32_add(n.getLocal("itIn"),n.i32_const(o)),l),...n.call(a+"_square",n.getLocal("itAux"),n.getLocal("itAux")),...n.call(a+"_mul",n.getLocal("itAux"),n.getLocal("itIn"),n.getLocal("itOut")),...n.call(a+"_mul",n.getLocal("itAux"),l,n.i32_add(n.getLocal("itOut"),n.i32_const(o)))]),n.setLocal("itIn",n.i32_add(n.getLocal("itIn"),n.i32_const(3*o))),n.setLocal("itOut",n.i32_add(n.getLocal("itOut"),n.i32_const(2*o))),n.setLocal("itAux",n.i32_add(n.getLocal("itAux"),n.i32_const(o))),n.setLocal("i",n.i32_add(n.getLocal("i"),n.i32_const(1))),n.br(0))),n.i32_store(n.i32_const(0),n.getLocal("pAux")))}(),function(){const i=t.addFunction(e+"_normalize");i.addParam("p1","i32"),i.addParam("pr","i32");const n=i.getCodeBuilder(),l=n.getLocal("p1"),r=n.i32_add(n.getLocal("p1"),n.i32_const(o)),s=n.i32_add(n.getLocal("p1"),n.i32_const(2*o)),c=n.getLocal("pr"),d=n.i32_add(n.getLocal("pr"),n.i32_const(o)),u=n.i32_add(n.getLocal("pr"),n.i32_const(2*o)),f=n.i32_const(t.alloc(o)),g=n.i32_const(t.alloc(o)),h=n.i32_const(t.alloc(o));i.addCode(n.if(n.call(e+"_isZero",n.getLocal("p1")),n.call(e+"_zero",n.getLocal("pr")),[...n.call(a+"_inverse",s,f),...n.call(a+"_square",f,g),...n.call(a+"_mul",f,g,h),...n.call(a+"_mul",l,g,c),...n.call(a+"_mul",r,h,d),...n.call(a+"_one",u)]))}(),function(){const a=t.addFunction(e+"__reverseBytes");a.addParam("pIn","i32"),a.addParam("n","i32"),a.addParam("pOut","i32"),a.addLocal("itOut","i32"),a.addLocal("itIn","i32");const i=a.getCodeBuilder();a.addCode(i.setLocal("itOut",i.i32_sub(i.i32_add(i.getLocal("pOut"),i.getLocal("n")),i.i32_const(1))),i.setLocal("itIn",i.getLocal("pIn")),i.block(i.loop(i.br_if(1,i.i32_lt_s(i.getLocal("itOut"),i.getLocal("pOut"))),i.i32_store8(i.getLocal("itOut"),i.i32_load8_u(i.getLocal("itIn"))),i.setLocal("itOut",i.i32_sub(i.getLocal("itOut"),i.i32_const(1))),i.setLocal("itIn",i.i32_add(i.getLocal("itIn"),i.i32_const(1))),i.br(0))))}(),function(){const a=t.addFunction(e+"_LEMtoU");a.addParam("pIn","i32"),a.addParam("pOut","i32");const i=a.getCodeBuilder(),n=t.alloc(2*o),l=i.i32_const(n),r=i.i32_const(n),s=i.i32_const(n+o);a.addCode(i.if(i.call(e+"_isZeroAffine",i.getLocal("pIn")),[...i.call(e+"_zeroAffine",i.getLocal("pOut")),...i.ret([])]),i.call(e+"_fromMontgomeryAffine",i.getLocal("pIn"),l),i.call(e+"__reverseBytes",r,i.i32_const(o),i.getLocal("pOut")),i.call(e+"__reverseBytes",s,i.i32_const(o),i.i32_add(i.getLocal("pOut"),i.i32_const(o))))}(),function(){const i=t.addFunction(e+"_LEMtoC");i.addParam("pIn","i32"),i.addParam("pOut","i32");const n=i.getCodeBuilder(),l=n.i32_const(t.alloc(o));i.addCode(n.if(n.call(e+"_isZeroAffine",n.getLocal("pIn")),[...n.call(a+"_zero",n.getLocal("pOut")),...n.i32_store8(n.getLocal("pOut"),n.i32_const(64)),...n.ret([])]),n.call(a+"_fromMontgomery",n.getLocal("pIn"),l),n.call(e+"__reverseBytes",l,n.i32_const(o),n.getLocal("pOut")),n.if(n.i32_eq(n.call(a+"_sign",n.i32_add(n.getLocal("pIn"),n.i32_const(o))),n.i32_const(-1)),n.i32_store8(n.getLocal("pOut"),n.i32_or(n.i32_load8_u(n.getLocal("pOut")),n.i32_const(128)))))}(),function(){const a=t.addFunction(e+"_UtoLEM");a.addParam("pIn","i32"),a.addParam("pOut","i32");const i=a.getCodeBuilder(),n=t.alloc(2*o),l=i.i32_const(n),r=i.i32_const(n),s=i.i32_const(n+o);a.addCode(i.if(i.i32_and(i.i32_load8_u(i.getLocal("pIn")),i.i32_const(64)),[...i.call(e+"_zeroAffine",i.getLocal("pOut")),...i.ret([])]),i.call(e+"__reverseBytes",i.getLocal("pIn"),i.i32_const(o),r),i.call(e+"__reverseBytes",i.i32_add(i.getLocal("pIn"),i.i32_const(o)),i.i32_const(o),s),i.call(e+"_toMontgomeryAffine",l,i.getLocal("pOut")))}(),function(){const n=t.addFunction(e+"_CtoLEM");n.addParam("pIn","i32"),n.addParam("pOut","i32"),n.addLocal("firstByte","i32"),n.addLocal("greatest","i32");const l=n.getCodeBuilder(),r=t.alloc(2*o),s=l.i32_const(r),c=l.i32_const(r+o);n.addCode(l.setLocal("firstByte",l.i32_load8_u(l.getLocal("pIn"))),l.if(l.i32_and(l.getLocal("firstByte"),l.i32_const(64)),[...l.call(e+"_zeroAffine",l.getLocal("pOut")),...l.ret([])]),l.setLocal("greatest",l.i32_and(l.getLocal("firstByte"),l.i32_const(128))),l.call(a+"_copy",l.getLocal("pIn"),c),l.i32_store8(c,l.i32_and(l.getLocal("firstByte"),l.i32_const(63))),l.call(e+"__reverseBytes",c,l.i32_const(o),s),l.call(a+"_toMontgomery",s,l.getLocal("pOut")),l.call(a+"_square",l.getLocal("pOut"),c),l.call(a+"_mul",l.getLocal("pOut"),c,c),l.call(a+"_add",c,l.i32_const(i),c),l.call(a+"_sqrt",c,c),l.call(a+"_neg",c,s),l.if(l.i32_eq(l.call(a+"_sign",c),l.i32_const(-1)),l.if(l.getLocal("greatest"),l.call(a+"_copy",c,l.i32_add(l.getLocal("pOut"),l.i32_const(o))),l.call(a+"_neg",c,l.i32_add(l.getLocal("pOut"),l.i32_const(o)))),l.if(l.getLocal("greatest"),l.call(a+"_neg",c,l.i32_add(l.getLocal("pOut"),l.i32_const(o))),l.call(a+"_copy",c,l.i32_add(l.getLocal("pOut"),l.i32_const(o))))))}(),he(t,e+"_batchLEMtoU",e+"_LEMtoU",2*o,2*o),he(t,e+"_batchLEMtoC",e+"_LEMtoC",2*o,o),he(t,e+"_batchUtoLEM",e+"_UtoLEM",2*o,2*o),he(t,e+"_batchCtoLEM",e+"_CtoLEM",o,2*o,!0),he(t,e+"_batchToJacobian",e+"_toJacobian",2*o,3*o,!0),pe(t,e,e+"_multiexp",e+"_add",3*o),pe(t,e,e+"_multiexpAffine",e+"_addMixed",2*o),ge(t,e+"_timesScalar",3*o,e+"_add",e+"_double",e+"_sub",e+"_copy",e+"_zero"),ge(t,e+"_timesScalarAffine",2*o,e+"_addMixed",e+"_double",e+"_subMixed",e+"_copyAffine",e+"_zero"),t.exportFunction(e+"_isZero"),t.exportFunction(e+"_isZeroAffine"),t.exportFunction(e+"_eq"),t.exportFunction(e+"_eqMixed"),t.exportFunction(e+"_eqAffine"),t.exportFunction(e+"_copy"),t.exportFunction(e+"_copyAffine"),t.exportFunction(e+"_zero"),t.exportFunction(e+"_zeroAffine"),t.exportFunction(e+"_double"),t.exportFunction(e+"_doubleAffine"),t.exportFunction(e+"_add"),t.exportFunction(e+"_addMixed"),t.exportFunction(e+"_addAffine"),t.exportFunction(e+"_neg"),t.exportFunction(e+"_negAffine"),t.exportFunction(e+"_sub"),t.exportFunction(e+"_subMixed"),t.exportFunction(e+"_subAffine"),t.exportFunction(e+"_fromMontgomery"),t.exportFunction(e+"_fromMontgomeryAffine"),t.exportFunction(e+"_toMontgomery"),t.exportFunction(e+"_toMontgomeryAffine"),t.exportFunction(e+"_timesScalar"),t.exportFunction(e+"_timesScalarAffine"),t.exportFunction(e+"_normalize"),t.exportFunction(e+"_LEMtoU"),t.exportFunction(e+"_LEMtoC"),t.exportFunction(e+"_UtoLEM"),t.exportFunction(e+"_CtoLEM"),t.exportFunction(e+"_batchLEMtoU"),t.exportFunction(e+"_batchLEMtoC"),t.exportFunction(e+"_batchUtoLEM"),t.exportFunction(e+"_batchCtoLEM"),t.exportFunction(e+"_toAffine"),t.exportFunction(e+"_toJacobian"),t.exportFunction(e+"_batchToAffine"),t.exportFunction(e+"_batchToJacobian"),t.exportFunction(e+"_inCurve"),t.exportFunction(e+"_inCurveAffine"),e};const{isOdd:me,modInv:we,modPow:Le}=Pt,be=Ct;var ye=function(t,e,a,i,n){const o=8*t.modules[i].n64,l=8*t.modules[a].n64,r=t.modules[i].q;let s=r-1n,c=0;for(;!me(s);)c++,s>>=1n;let d=2n;for(;1n===Le(d,r>>1n,r);)d+=1n;const u=new Array(c+1);u[c]=Le(d,s,r);let f=c-1;for(;f>=0;)u[f]=Le(u[f+1],2n,r),f--;const g=[],h=(1n<>a);return e}const C=Array(256);for(let t=0;t<256;t++)C[t]=x(t);const S=t.alloc(C);function E(){const a=t.addFunction(e+"_fft");a.addParam("px","i32"),a.addParam("n","i32"),a.addLocal("bits","i32");const n=a.getCodeBuilder(),l=n.i32_const(t.alloc(o));a.addCode(n.setLocal("bits",n.call(e+"__log2",n.getLocal("n"))),n.call(i+"_one",l),n.call(e+"_rawfft",n.getLocal("px"),n.getLocal("bits"),n.i32_const(0),l))}!function(){const a=t.addFunction(e+"__rev");a.addParam("x","i32"),a.addParam("bits","i32"),a.setReturnType("i32");const i=a.getCodeBuilder();a.addCode(i.i32_rotl(i.i32_add(i.i32_add(i.i32_shl(i.i32_load8_u(i.i32_and(i.getLocal("x"),i.i32_const(255)),S,0),i.i32_const(24)),i.i32_shl(i.i32_load8_u(i.i32_and(i.i32_shr_u(i.getLocal("x"),i.i32_const(8)),i.i32_const(255)),S,0),i.i32_const(16))),i.i32_add(i.i32_shl(i.i32_load8_u(i.i32_and(i.i32_shr_u(i.getLocal("x"),i.i32_const(16)),i.i32_const(255)),S,0),i.i32_const(8)),i.i32_load8_u(i.i32_and(i.i32_shr_u(i.getLocal("x"),i.i32_const(24)),i.i32_const(255)),S,0))),i.getLocal("bits")))}(),function(){const i=t.addFunction(e+"__reversePermutation");i.addParam("px","i32"),i.addParam("bits","i32"),i.addLocal("n","i32"),i.addLocal("i","i32"),i.addLocal("ri","i32"),i.addLocal("idx1","i32"),i.addLocal("idx2","i32");const n=i.getCodeBuilder(),o=n.i32_const(t.alloc(l));i.addCode(n.setLocal("n",n.i32_shl(n.i32_const(1),n.getLocal("bits"))),n.setLocal("i",n.i32_const(0)),n.block(n.loop(n.br_if(1,n.i32_eq(n.getLocal("i"),n.getLocal("n"))),n.setLocal("idx1",n.i32_add(n.getLocal("px"),n.i32_mul(n.getLocal("i"),n.i32_const(l)))),n.setLocal("ri",n.call(e+"__rev",n.getLocal("i"),n.getLocal("bits"))),n.setLocal("idx2",n.i32_add(n.getLocal("px"),n.i32_mul(n.getLocal("ri"),n.i32_const(l)))),n.if(n.i32_lt_u(n.getLocal("i"),n.getLocal("ri")),[...n.call(a+"_copy",n.getLocal("idx1"),o),...n.call(a+"_copy",n.getLocal("idx2"),n.getLocal("idx1")),...n.call(a+"_copy",o,n.getLocal("idx2"))]),n.setLocal("i",n.i32_add(n.getLocal("i"),n.i32_const(1))),n.br(0))))}(),function(){const o=t.addFunction(e+"__fftFinal");o.addParam("px","i32"),o.addParam("bits","i32"),o.addParam("reverse","i32"),o.addParam("mulFactor","i32"),o.addLocal("n","i32"),o.addLocal("ndiv2","i32"),o.addLocal("pInv2","i32"),o.addLocal("i","i32"),o.addLocal("mask","i32"),o.addLocal("idx1","i32"),o.addLocal("idx2","i32");const r=o.getCodeBuilder(),s=r.i32_const(t.alloc(l));o.addCode(r.if(r.i32_and(r.i32_eqz(r.getLocal("reverse")),r.call(i+"_isOne",r.getLocal("mulFactor"))),r.ret([])),r.setLocal("n",r.i32_shl(r.i32_const(1),r.getLocal("bits"))),r.setLocal("mask",r.i32_sub(r.getLocal("n"),r.i32_const(1))),r.setLocal("i",r.i32_const(1)),r.setLocal("ndiv2",r.i32_shr_u(r.getLocal("n"),r.i32_const(1))),r.block(r.loop(r.br_if(1,r.i32_ge_u(r.getLocal("i"),r.getLocal("ndiv2"))),r.setLocal("idx1",r.i32_add(r.getLocal("px"),r.i32_mul(r.getLocal("i"),r.i32_const(l)))),r.setLocal("idx2",r.i32_add(r.getLocal("px"),r.i32_mul(r.i32_sub(r.getLocal("n"),r.getLocal("i")),r.i32_const(l)))),r.if(r.getLocal("reverse"),r.if(r.call(i+"_isOne",r.getLocal("mulFactor")),[...r.call(a+"_copy",r.getLocal("idx1"),s),...r.call(a+"_copy",r.getLocal("idx2"),r.getLocal("idx1")),...r.call(a+"_copy",s,r.getLocal("idx2"))],[...r.call(a+"_copy",r.getLocal("idx1"),s),...r.call(n,r.getLocal("idx2"),r.getLocal("mulFactor"),r.getLocal("idx1")),...r.call(n,s,r.getLocal("mulFactor"),r.getLocal("idx2"))]),r.if(r.call(i+"_isOne",r.getLocal("mulFactor")),[],[...r.call(n,r.getLocal("idx1"),r.getLocal("mulFactor"),r.getLocal("idx1")),...r.call(n,r.getLocal("idx2"),r.getLocal("mulFactor"),r.getLocal("idx2"))])),r.setLocal("i",r.i32_add(r.getLocal("i"),r.i32_const(1))),r.br(0))),r.if(r.call(i+"_isOne",r.getLocal("mulFactor")),[],[...r.call(n,r.getLocal("px"),r.getLocal("mulFactor"),r.getLocal("px")),...r.setLocal("idx2",r.i32_add(r.getLocal("px"),r.i32_mul(r.getLocal("ndiv2"),r.i32_const(l)))),...r.call(n,r.getLocal("idx2"),r.getLocal("mulFactor"),r.getLocal("idx2"))]))}(),function(){const r=t.addFunction(e+"_rawfft");r.addParam("px","i32"),r.addParam("bits","i32"),r.addParam("reverse","i32"),r.addParam("mulFactor","i32"),r.addLocal("s","i32"),r.addLocal("k","i32"),r.addLocal("j","i32"),r.addLocal("m","i32"),r.addLocal("mdiv2","i32"),r.addLocal("n","i32"),r.addLocal("pwm","i32"),r.addLocal("idx1","i32"),r.addLocal("idx2","i32");const s=r.getCodeBuilder(),c=s.i32_const(t.alloc(o)),d=s.i32_const(t.alloc(l)),u=s.i32_const(t.alloc(l));r.addCode(s.call(e+"__reversePermutation",s.getLocal("px"),s.getLocal("bits")),s.setLocal("n",s.i32_shl(s.i32_const(1),s.getLocal("bits"))),s.setLocal("s",s.i32_const(1)),s.block(s.loop(s.br_if(1,s.i32_gt_u(s.getLocal("s"),s.getLocal("bits"))),s.setLocal("m",s.i32_shl(s.i32_const(1),s.getLocal("s"))),s.setLocal("pwm",s.i32_add(s.i32_const(p),s.i32_mul(s.getLocal("s"),s.i32_const(o)))),s.setLocal("k",s.i32_const(0)),s.block(s.loop(s.br_if(1,s.i32_ge_u(s.getLocal("k"),s.getLocal("n"))),s.call(i+"_one",c),s.setLocal("mdiv2",s.i32_shr_u(s.getLocal("m"),s.i32_const(1))),s.setLocal("j",s.i32_const(0)),s.block(s.loop(s.br_if(1,s.i32_ge_u(s.getLocal("j"),s.getLocal("mdiv2"))),s.setLocal("idx1",s.i32_add(s.getLocal("px"),s.i32_mul(s.i32_add(s.getLocal("k"),s.getLocal("j")),s.i32_const(l)))),s.setLocal("idx2",s.i32_add(s.getLocal("idx1"),s.i32_mul(s.getLocal("mdiv2"),s.i32_const(l)))),s.call(n,s.getLocal("idx2"),c,d),s.call(a+"_copy",s.getLocal("idx1"),u),s.call(a+"_add",u,d,s.getLocal("idx1")),s.call(a+"_sub",u,d,s.getLocal("idx2")),s.call(i+"_mul",c,s.getLocal("pwm"),c),s.setLocal("j",s.i32_add(s.getLocal("j"),s.i32_const(1))),s.br(0))),s.setLocal("k",s.i32_add(s.getLocal("k"),s.getLocal("m"))),s.br(0))),s.setLocal("s",s.i32_add(s.getLocal("s"),s.i32_const(1))),s.br(0))),s.call(e+"__fftFinal",s.getLocal("px"),s.getLocal("bits"),s.getLocal("reverse"),s.getLocal("mulFactor")))}(),function(){const a=t.addFunction(e+"__log2");a.addParam("n","i32"),a.setReturnType("i32"),a.addLocal("bits","i32"),a.addLocal("aux","i32");const i=a.getCodeBuilder();a.addCode(i.setLocal("aux",i.i32_shr_u(i.getLocal("n"),i.i32_const(1)))),a.addCode(i.setLocal("bits",i.i32_const(0))),a.addCode(i.block(i.loop(i.br_if(1,i.i32_eqz(i.getLocal("aux"))),i.setLocal("aux",i.i32_shr_u(i.getLocal("aux"),i.i32_const(1))),i.setLocal("bits",i.i32_add(i.getLocal("bits"),i.i32_const(1))),i.br(0)))),a.addCode(i.if(i.i32_ne(i.getLocal("n"),i.i32_shl(i.i32_const(1),i.getLocal("bits"))),i.unreachable())),a.addCode(i.if(i.i32_gt_u(i.getLocal("bits"),i.i32_const(c)),i.unreachable())),a.addCode(i.getLocal("bits"))}(),E(),function(){const a=t.addFunction(e+"_ifft");a.addParam("px","i32"),a.addParam("n","i32"),a.addLocal("bits","i32"),a.addLocal("pInv2","i32");const i=a.getCodeBuilder();a.addCode(i.setLocal("bits",i.call(e+"__log2",i.getLocal("n"))),i.setLocal("pInv2",i.i32_add(i.i32_const(w),i.i32_mul(i.getLocal("bits"),i.i32_const(o)))),i.call(e+"_rawfft",i.getLocal("px"),i.getLocal("bits"),i.i32_const(1),i.getLocal("pInv2")))}(),function(){const r=t.addFunction(e+"_fftJoin");r.addParam("pBuff1","i32"),r.addParam("pBuff2","i32"),r.addParam("n","i32"),r.addParam("first","i32"),r.addParam("inc","i32"),r.addLocal("idx1","i32"),r.addLocal("idx2","i32"),r.addLocal("i","i32");const s=r.getCodeBuilder(),c=s.i32_const(t.alloc(o)),d=s.i32_const(t.alloc(l)),u=s.i32_const(t.alloc(l));r.addCode(s.call(i+"_copy",s.getLocal("first"),c),s.setLocal("i",s.i32_const(0)),s.block(s.loop(s.br_if(1,s.i32_eq(s.getLocal("i"),s.getLocal("n"))),s.setLocal("idx1",s.i32_add(s.getLocal("pBuff1"),s.i32_mul(s.getLocal("i"),s.i32_const(l)))),s.setLocal("idx2",s.i32_add(s.getLocal("pBuff2"),s.i32_mul(s.getLocal("i"),s.i32_const(l)))),s.call(n,s.getLocal("idx2"),c,d),s.call(a+"_copy",s.getLocal("idx1"),u),s.call(a+"_add",u,d,s.getLocal("idx1")),s.call(a+"_sub",u,d,s.getLocal("idx2")),s.call(i+"_mul",c,s.getLocal("inc"),c),s.setLocal("i",s.i32_add(s.getLocal("i"),s.i32_const(1))),s.br(0))))}(),function(){const r=t.addFunction(e+"_fftJoinExt");r.addParam("pBuff1","i32"),r.addParam("pBuff2","i32"),r.addParam("n","i32"),r.addParam("first","i32"),r.addParam("inc","i32"),r.addParam("totalBits","i32"),r.addLocal("idx1","i32"),r.addLocal("idx2","i32"),r.addLocal("i","i32"),r.addLocal("pShiftToM","i32");const s=r.getCodeBuilder(),c=s.i32_const(t.alloc(o)),d=s.i32_const(t.alloc(l));r.addCode(s.setLocal("pShiftToM",s.i32_add(s.i32_const(v),s.i32_mul(s.getLocal("totalBits"),s.i32_const(o)))),s.call(i+"_copy",s.getLocal("first"),c),s.setLocal("i",s.i32_const(0)),s.block(s.loop(s.br_if(1,s.i32_eq(s.getLocal("i"),s.getLocal("n"))),s.setLocal("idx1",s.i32_add(s.getLocal("pBuff1"),s.i32_mul(s.getLocal("i"),s.i32_const(l)))),s.setLocal("idx2",s.i32_add(s.getLocal("pBuff2"),s.i32_mul(s.getLocal("i"),s.i32_const(l)))),s.call(a+"_add",s.getLocal("idx1"),s.getLocal("idx2"),d),s.call(n,s.getLocal("idx2"),s.getLocal("pShiftToM"),s.getLocal("idx2")),s.call(a+"_add",s.getLocal("idx1"),s.getLocal("idx2"),s.getLocal("idx2")),s.call(n,s.getLocal("idx2"),c,s.getLocal("idx2")),s.call(a+"_copy",d,s.getLocal("idx1")),s.call(i+"_mul",c,s.getLocal("inc"),c),s.setLocal("i",s.i32_add(s.getLocal("i"),s.i32_const(1))),s.br(0))))}(),function(){const r=t.addFunction(e+"_fftJoinExtInv");r.addParam("pBuff1","i32"),r.addParam("pBuff2","i32"),r.addParam("n","i32"),r.addParam("first","i32"),r.addParam("inc","i32"),r.addParam("totalBits","i32"),r.addLocal("idx1","i32"),r.addLocal("idx2","i32"),r.addLocal("i","i32"),r.addLocal("pShiftToM","i32"),r.addLocal("pSConst","i32");const s=r.getCodeBuilder(),c=s.i32_const(t.alloc(o)),d=s.i32_const(t.alloc(l));r.addCode(s.setLocal("pShiftToM",s.i32_add(s.i32_const(v),s.i32_mul(s.getLocal("totalBits"),s.i32_const(o)))),s.setLocal("pSConst",s.i32_add(s.i32_const(F),s.i32_mul(s.getLocal("totalBits"),s.i32_const(o)))),s.call(i+"_copy",s.getLocal("first"),c),s.setLocal("i",s.i32_const(0)),s.block(s.loop(s.br_if(1,s.i32_eq(s.getLocal("i"),s.getLocal("n"))),s.setLocal("idx1",s.i32_add(s.getLocal("pBuff1"),s.i32_mul(s.getLocal("i"),s.i32_const(l)))),s.setLocal("idx2",s.i32_add(s.getLocal("pBuff2"),s.i32_mul(s.getLocal("i"),s.i32_const(l)))),s.call(n,s.getLocal("idx2"),c,d),s.call(a+"_sub",s.getLocal("idx1"),d,s.getLocal("idx2")),s.call(n,s.getLocal("idx2"),s.getLocal("pSConst"),s.getLocal("idx2")),s.call(n,s.getLocal("idx1"),s.getLocal("pShiftToM"),s.getLocal("idx1")),s.call(a+"_sub",d,s.getLocal("idx1"),s.getLocal("idx1")),s.call(n,s.getLocal("idx1"),s.getLocal("pSConst"),s.getLocal("idx1")),s.call(i+"_mul",c,s.getLocal("inc"),c),s.setLocal("i",s.i32_add(s.getLocal("i"),s.i32_const(1))),s.br(0))))}(),function(){const r=t.addFunction(e+"_fftMix");r.addParam("pBuff","i32"),r.addParam("n","i32"),r.addParam("exp","i32"),r.addLocal("nGroups","i32"),r.addLocal("nPerGroup","i32"),r.addLocal("nPerGroupDiv2","i32"),r.addLocal("pairOffset","i32"),r.addLocal("idx1","i32"),r.addLocal("idx2","i32"),r.addLocal("i","i32"),r.addLocal("j","i32"),r.addLocal("pwm","i32");const s=r.getCodeBuilder(),c=s.i32_const(t.alloc(o)),d=s.i32_const(t.alloc(l)),u=s.i32_const(t.alloc(l));r.addCode(s.setLocal("nPerGroup",s.i32_shl(s.i32_const(1),s.getLocal("exp"))),s.setLocal("nPerGroupDiv2",s.i32_shr_u(s.getLocal("nPerGroup"),s.i32_const(1))),s.setLocal("nGroups",s.i32_shr_u(s.getLocal("n"),s.getLocal("exp"))),s.setLocal("pairOffset",s.i32_mul(s.getLocal("nPerGroupDiv2"),s.i32_const(l))),s.setLocal("pwm",s.i32_add(s.i32_const(p),s.i32_mul(s.getLocal("exp"),s.i32_const(o)))),s.setLocal("i",s.i32_const(0)),s.block(s.loop(s.br_if(1,s.i32_eq(s.getLocal("i"),s.getLocal("nGroups"))),s.call(i+"_one",c),s.setLocal("j",s.i32_const(0)),s.block(s.loop(s.br_if(1,s.i32_eq(s.getLocal("j"),s.getLocal("nPerGroupDiv2"))),s.setLocal("idx1",s.i32_add(s.getLocal("pBuff"),s.i32_mul(s.i32_add(s.i32_mul(s.getLocal("i"),s.getLocal("nPerGroup")),s.getLocal("j")),s.i32_const(l)))),s.setLocal("idx2",s.i32_add(s.getLocal("idx1"),s.getLocal("pairOffset"))),s.call(n,s.getLocal("idx2"),c,d),s.call(a+"_copy",s.getLocal("idx1"),u),s.call(a+"_add",u,d,s.getLocal("idx1")),s.call(a+"_sub",u,d,s.getLocal("idx2")),s.call(i+"_mul",c,s.getLocal("pwm"),c),s.setLocal("j",s.i32_add(s.getLocal("j"),s.i32_const(1))),s.br(0))),s.setLocal("i",s.i32_add(s.getLocal("i"),s.i32_const(1))),s.br(0))))}(),function(){const i=t.addFunction(e+"_fftFinal");i.addParam("pBuff","i32"),i.addParam("n","i32"),i.addParam("factor","i32"),i.addLocal("idx1","i32"),i.addLocal("idx2","i32"),i.addLocal("i","i32"),i.addLocal("ndiv2","i32");const o=i.getCodeBuilder(),r=o.i32_const(t.alloc(l));i.addCode(o.setLocal("ndiv2",o.i32_shr_u(o.getLocal("n"),o.i32_const(1))),o.if(o.i32_and(o.getLocal("n"),o.i32_const(1)),o.call(n,o.i32_add(o.getLocal("pBuff"),o.i32_mul(o.getLocal("ndiv2"),o.i32_const(l))),o.getLocal("factor"),o.i32_add(o.getLocal("pBuff"),o.i32_mul(o.getLocal("ndiv2"),o.i32_const(l))))),o.setLocal("i",o.i32_const(0)),o.block(o.loop(o.br_if(1,o.i32_ge_u(o.getLocal("i"),o.getLocal("ndiv2"))),o.setLocal("idx1",o.i32_add(o.getLocal("pBuff"),o.i32_mul(o.getLocal("i"),o.i32_const(l)))),o.setLocal("idx2",o.i32_add(o.getLocal("pBuff"),o.i32_mul(o.i32_sub(o.i32_sub(o.getLocal("n"),o.i32_const(1)),o.getLocal("i")),o.i32_const(l)))),o.call(n,o.getLocal("idx2"),o.getLocal("factor"),r),o.call(n,o.getLocal("idx1"),o.getLocal("factor"),o.getLocal("idx2")),o.call(a+"_copy",r,o.getLocal("idx1")),o.setLocal("i",o.i32_add(o.getLocal("i"),o.i32_const(1))),o.br(0))))}(),function(){const r=t.addFunction(e+"_prepareLagrangeEvaluation");r.addParam("pBuff1","i32"),r.addParam("pBuff2","i32"),r.addParam("n","i32"),r.addParam("first","i32"),r.addParam("inc","i32"),r.addParam("totalBits","i32"),r.addLocal("idx1","i32"),r.addLocal("idx2","i32"),r.addLocal("i","i32"),r.addLocal("pShiftToM","i32"),r.addLocal("pSConst","i32");const s=r.getCodeBuilder(),c=s.i32_const(t.alloc(o)),d=s.i32_const(t.alloc(l));r.addCode(s.setLocal("pShiftToM",s.i32_add(s.i32_const(v),s.i32_mul(s.getLocal("totalBits"),s.i32_const(o)))),s.setLocal("pSConst",s.i32_add(s.i32_const(F),s.i32_mul(s.getLocal("totalBits"),s.i32_const(o)))),s.call(i+"_copy",s.getLocal("first"),c),s.setLocal("i",s.i32_const(0)),s.block(s.loop(s.br_if(1,s.i32_eq(s.getLocal("i"),s.getLocal("n"))),s.setLocal("idx1",s.i32_add(s.getLocal("pBuff1"),s.i32_mul(s.getLocal("i"),s.i32_const(l)))),s.setLocal("idx2",s.i32_add(s.getLocal("pBuff2"),s.i32_mul(s.getLocal("i"),s.i32_const(l)))),s.call(n,s.getLocal("idx1"),s.getLocal("pShiftToM"),d),s.call(a+"_sub",s.getLocal("idx2"),d,d),s.call(a+"_sub",s.getLocal("idx1"),s.getLocal("idx2"),s.getLocal("idx2")),s.call(n,d,s.getLocal("pSConst"),s.getLocal("idx1")),s.call(n,s.getLocal("idx2"),c,s.getLocal("idx2")),s.call(i+"_mul",c,s.getLocal("inc"),c),s.setLocal("i",s.i32_add(s.getLocal("i"),s.i32_const(1))),s.br(0))))}(),t.exportFunction(e+"__reversePermutation"),t.exportFunction(e+"_fft"),t.exportFunction(e+"_ifft"),t.exportFunction(e+"_rawfft"),t.exportFunction(e+"_fftJoin"),t.exportFunction(e+"_fftJoinExt"),t.exportFunction(e+"_fftJoinExtInv"),t.exportFunction(e+"_fftMix"),t.exportFunction(e+"_fftFinal"),t.exportFunction(e+"_prepareLagrangeEvaluation")},ve=function(t,e,a){const i=8*t.modules[a].n64;return function(){const n=t.addFunction(e+"_zero");n.addParam("px","i32"),n.addParam("n","i32"),n.addLocal("lastp","i32"),n.addLocal("p","i32");const o=n.getCodeBuilder();n.addCode(o.setLocal("p",o.getLocal("px")),o.setLocal("lastp",o.i32_add(o.getLocal("px"),o.i32_mul(o.getLocal("n"),o.i32_const(i)))),o.block(o.loop(o.br_if(1,o.i32_eq(o.getLocal("p"),o.getLocal("lastp"))),o.call(a+"_zero",o.getLocal("p")),o.setLocal("p",o.i32_add(o.getLocal("p"),o.i32_const(i))),o.br(0))))}(),function(){const n=t.addFunction(e+"_constructLC");n.addParam("ppolynomials","i32"),n.addParam("psignals","i32"),n.addParam("nSignals","i32"),n.addParam("pres","i32"),n.addLocal("i","i32"),n.addLocal("j","i32"),n.addLocal("pp","i32"),n.addLocal("ps","i32"),n.addLocal("pd","i32"),n.addLocal("ncoefs","i32");const o=n.getCodeBuilder(),l=o.i32_const(t.alloc(i));n.addCode(o.setLocal("i",o.i32_const(0)),o.setLocal("pp",o.getLocal("ppolynomials")),o.setLocal("ps",o.getLocal("psignals")),o.block(o.loop(o.br_if(1,o.i32_eq(o.getLocal("i"),o.getLocal("nSignals"))),o.setLocal("ncoefs",o.i32_load(o.getLocal("pp"))),o.setLocal("pp",o.i32_add(o.getLocal("pp"),o.i32_const(4))),o.setLocal("j",o.i32_const(0)),o.block(o.loop(o.br_if(1,o.i32_eq(o.getLocal("j"),o.getLocal("ncoefs"))),o.setLocal("pd",o.i32_add(o.getLocal("pres"),o.i32_mul(o.i32_load(o.getLocal("pp")),o.i32_const(i)))),o.setLocal("pp",o.i32_add(o.getLocal("pp"),o.i32_const(4))),o.call(a+"_mul",o.getLocal("ps"),o.getLocal("pp"),l),o.call(a+"_add",l,o.getLocal("pd"),o.getLocal("pd")),o.setLocal("pp",o.i32_add(o.getLocal("pp"),o.i32_const(i))),o.setLocal("j",o.i32_add(o.getLocal("j"),o.i32_const(1))),o.br(0))),o.setLocal("ps",o.i32_add(o.getLocal("ps"),o.i32_const(i))),o.setLocal("i",o.i32_add(o.getLocal("i"),o.i32_const(1))),o.br(0))))}(),t.exportFunction(e+"_zero"),t.exportFunction(e+"_constructLC"),e},Fe=function(t,e,a){const i=8*t.modules[a].n64;return function(){const n=t.addFunction(e+"_buildABC");n.addParam("pCoefs","i32"),n.addParam("nCoefs","i32"),n.addParam("pWitness","i32"),n.addParam("pA","i32"),n.addParam("pB","i32"),n.addParam("pC","i32"),n.addParam("offsetOut","i32"),n.addParam("nOut","i32"),n.addParam("offsetWitness","i32"),n.addParam("nWitness","i32"),n.addLocal("it","i32"),n.addLocal("ita","i32"),n.addLocal("itb","i32"),n.addLocal("last","i32"),n.addLocal("m","i32"),n.addLocal("c","i32"),n.addLocal("s","i32"),n.addLocal("pOut","i32");const o=n.getCodeBuilder(),l=o.i32_const(t.alloc(i));n.addCode(o.setLocal("ita",o.getLocal("pA")),o.setLocal("itb",o.getLocal("pB")),o.setLocal("last",o.i32_add(o.getLocal("pA"),o.i32_mul(o.getLocal("nOut"),o.i32_const(i)))),o.block(o.loop(o.br_if(1,o.i32_eq(o.getLocal("ita"),o.getLocal("last"))),o.call(a+"_zero",o.getLocal("ita")),o.call(a+"_zero",o.getLocal("itb")),o.setLocal("ita",o.i32_add(o.getLocal("ita"),o.i32_const(i))),o.setLocal("itb",o.i32_add(o.getLocal("itb"),o.i32_const(i))),o.br(0))),o.setLocal("it",o.getLocal("pCoefs")),o.setLocal("last",o.i32_add(o.getLocal("pCoefs"),o.i32_mul(o.getLocal("nCoefs"),o.i32_const(i+12)))),o.block(o.loop(o.br_if(1,o.i32_eq(o.getLocal("it"),o.getLocal("last"))),o.setLocal("s",o.i32_load(o.getLocal("it"),8)),o.if(o.i32_or(o.i32_lt_u(o.getLocal("s"),o.getLocal("offsetWitness")),o.i32_ge_u(o.getLocal("s"),o.i32_add(o.getLocal("offsetWitness"),o.getLocal("nWitness")))),[...o.setLocal("it",o.i32_add(o.getLocal("it"),o.i32_const(i+12))),...o.br(1)]),o.setLocal("m",o.i32_load(o.getLocal("it"))),o.if(o.i32_eq(o.getLocal("m"),o.i32_const(0)),o.setLocal("pOut",o.getLocal("pA")),o.if(o.i32_eq(o.getLocal("m"),o.i32_const(1)),o.setLocal("pOut",o.getLocal("pB")),[...o.setLocal("it",o.i32_add(o.getLocal("it"),o.i32_const(i+12))),...o.br(1)])),o.setLocal("c",o.i32_load(o.getLocal("it"),4)),o.if(o.i32_or(o.i32_lt_u(o.getLocal("c"),o.getLocal("offsetOut")),o.i32_ge_u(o.getLocal("c"),o.i32_add(o.getLocal("offsetOut"),o.getLocal("nOut")))),[...o.setLocal("it",o.i32_add(o.getLocal("it"),o.i32_const(i+12))),...o.br(1)]),o.setLocal("pOut",o.i32_add(o.getLocal("pOut"),o.i32_mul(o.i32_sub(o.getLocal("c"),o.getLocal("offsetOut")),o.i32_const(i)))),o.call(a+"_mul",o.i32_add(o.getLocal("pWitness"),o.i32_mul(o.i32_sub(o.getLocal("s"),o.getLocal("offsetWitness")),o.i32_const(i))),o.i32_add(o.getLocal("it"),o.i32_const(12)),l),o.call(a+"_add",o.getLocal("pOut"),l,o.getLocal("pOut")),o.setLocal("it",o.i32_add(o.getLocal("it"),o.i32_const(i+12))),o.br(0))),o.setLocal("ita",o.getLocal("pA")),o.setLocal("itb",o.getLocal("pB")),o.setLocal("it",o.getLocal("pC")),o.setLocal("last",o.i32_add(o.getLocal("pA"),o.i32_mul(o.getLocal("nOut"),o.i32_const(i)))),o.block(o.loop(o.br_if(1,o.i32_eq(o.getLocal("ita"),o.getLocal("last"))),o.call(a+"_mul",o.getLocal("ita"),o.getLocal("itb"),o.getLocal("it")),o.setLocal("ita",o.i32_add(o.getLocal("ita"),o.i32_const(i))),o.setLocal("itb",o.i32_add(o.getLocal("itb"),o.i32_const(i))),o.setLocal("it",o.i32_add(o.getLocal("it"),o.i32_const(i))),o.br(0))))}(),function(){const n=t.addFunction(e+"_joinABC");n.addParam("pA","i32"),n.addParam("pB","i32"),n.addParam("pC","i32"),n.addParam("n","i32"),n.addParam("pP","i32"),n.addLocal("ita","i32"),n.addLocal("itb","i32"),n.addLocal("itc","i32"),n.addLocal("itp","i32"),n.addLocal("last","i32");const o=n.getCodeBuilder(),l=o.i32_const(t.alloc(i));n.addCode(o.setLocal("ita",o.getLocal("pA")),o.setLocal("itb",o.getLocal("pB")),o.setLocal("itc",o.getLocal("pC")),o.setLocal("itp",o.getLocal("pP")),o.setLocal("last",o.i32_add(o.getLocal("pA"),o.i32_mul(o.getLocal("n"),o.i32_const(i)))),o.block(o.loop(o.br_if(1,o.i32_eq(o.getLocal("ita"),o.getLocal("last"))),o.call(a+"_mul",o.getLocal("ita"),o.getLocal("itb"),l),o.call(a+"_sub",l,o.getLocal("itc"),o.getLocal("itp")),o.setLocal("ita",o.i32_add(o.getLocal("ita"),o.i32_const(i))),o.setLocal("itb",o.i32_add(o.getLocal("itb"),o.i32_const(i))),o.setLocal("itc",o.i32_add(o.getLocal("itc"),o.i32_const(i))),o.setLocal("itp",o.i32_add(o.getLocal("itp"),o.i32_const(i))),o.br(0))))}(),function(){const n=t.addFunction(e+"_batchAdd");n.addParam("pa","i32"),n.addParam("pb","i32"),n.addParam("n","i32"),n.addParam("pr","i32"),n.addLocal("ita","i32"),n.addLocal("itb","i32"),n.addLocal("itr","i32"),n.addLocal("last","i32");const o=n.getCodeBuilder();n.addCode(o.setLocal("ita",o.getLocal("pa")),o.setLocal("itb",o.getLocal("pb")),o.setLocal("itr",o.getLocal("pr")),o.setLocal("last",o.i32_add(o.getLocal("pa"),o.i32_mul(o.getLocal("n"),o.i32_const(i)))),o.block(o.loop(o.br_if(1,o.i32_eq(o.getLocal("ita"),o.getLocal("last"))),o.call(a+"_add",o.getLocal("ita"),o.getLocal("itb"),o.getLocal("itr")),o.setLocal("ita",o.i32_add(o.getLocal("ita"),o.i32_const(i))),o.setLocal("itb",o.i32_add(o.getLocal("itb"),o.i32_const(i))),o.setLocal("itr",o.i32_add(o.getLocal("itr"),o.i32_const(i))),o.br(0))))}(),t.exportFunction(e+"_buildABC"),t.exportFunction(e+"_joinABC"),t.exportFunction(e+"_batchAdd"),e},xe=function(t,e,a,i,n,o,l,r){const s=t.addFunction(e);s.addParam("pIn","i32"),s.addParam("n","i32"),s.addParam("pFirst","i32"),s.addParam("pInc","i32"),s.addParam("pOut","i32"),s.addLocal("pOldFree","i32"),s.addLocal("i","i32"),s.addLocal("pFrom","i32"),s.addLocal("pTo","i32");const c=s.getCodeBuilder(),d=c.i32_const(t.alloc(l));s.addCode(c.setLocal("pFrom",c.getLocal("pIn")),c.setLocal("pTo",c.getLocal("pOut"))),s.addCode(c.call(i+"_copy",c.getLocal("pFirst"),d)),s.addCode(c.setLocal("i",c.i32_const(0)),c.block(c.loop(c.br_if(1,c.i32_eq(c.getLocal("i"),c.getLocal("n"))),c.call(r,c.getLocal("pFrom"),d,c.getLocal("pTo")),c.setLocal("pFrom",c.i32_add(c.getLocal("pFrom"),c.i32_const(n))),c.setLocal("pTo",c.i32_add(c.getLocal("pTo"),c.i32_const(o))),c.call(i+"_mul",d,c.getLocal("pInc"),d),c.setLocal("i",c.i32_add(c.getLocal("i"),c.i32_const(1))),c.br(0)))),t.exportFunction(e)};const Ce=Ct,Se=ae,Ee=oe,Ae=ce,Be=fe,Pe=_e,ze=ye,Ie=ve,Te=Fe,Ge=xe,{bitLength:Oe,modInv:qe,isOdd:Ue,isNegative:Me}=Pt;const ke=Ct,Re=ae,Ne=oe,je=ce,De=fe,Ve=_e,We=ye,Ze=ve,He=Fe,Qe=xe,{bitLength:Ke,isOdd:Xe,isNegative:Ye}=Pt;var Je=xt,$e=function(t,e){const a=e||"bn128";if(t.modules[a])return a;const i=21888242871839275222246405745257275088696311157297823662689037894645226208583n,n=21888242871839275222246405745257275088548364400416034343698204186575808495617n,o=Math.floor((Oe(i-1n)-1)/64)+1,l=8*o,r=l,s=l,c=2*s,d=12*s,u=t.alloc(Ce.bigInt2BytesLE(n,r)),f=Se(t,i,"f1m");Ee(t,n,"fr","frm");const g=t.alloc(Ce.bigInt2BytesLE(L(3n),s)),h=Pe(t,"g1m","f1m",g);ze(t,"frm","frm","frm","frm_mul"),Ie(t,"pol","frm"),Te(t,"qap","frm");const p=Ae(t,"f1m_neg","f2m","f1m"),_=t.alloc([...Ce.bigInt2BytesLE(L(19485874751759354771024239261021720505790618469301721065564631296452457478373n),s),...Ce.bigInt2BytesLE(L(266929791119991161246907387137283842545076965332900288569378510910307636690n),s)]),m=Pe(t,"g2m","f2m",_);function w(e,a){const i=t.addFunction(e);i.addParam("pG","i32"),i.addParam("pFr","i32"),i.addParam("pr","i32");const n=i.getCodeBuilder(),o=n.i32_const(t.alloc(l));i.addCode(n.call("frm_fromMontgomery",n.getLocal("pFr"),o),n.call(a,n.getLocal("pG"),o,n.i32_const(l),n.getLocal("pr"))),t.exportFunction(e)}function L(t){return BigInt(t)*(1n<0n;)Ue(e)?a.push(1):a.push(0),e>>=1n;return a}(29793968203157093288n),q=t.alloc(O),U=3*c,M=O.length-1,k=O.reduce(((t,e)=>t+(0!=e?1:0)),0),R=6*l,N=3*l*2+(k+M+1)*U;t.modules[a]={n64:o,pG1gen:y,pG1zero:F,pG1b:g,pG2gen:C,pG2zero:E,pG2b:_,pq:t.modules.f1m.pq,pr:u,pOneT:A,prePSize:R,preQSize:N,r:n.toString(),q:i.toString()};const j=4965661367192848881n;function D(e){const n=[[[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n]],[[1n,0n],[8376118865763821496583973867626364092589906065868298776909617916018768340080n,16469823323077808223889137241176536799009286646108169935659301613961712198316n],[21888242871839275220042445260109153167277707414472061641714758635765020556617n,0n],[11697423496358154304825782922584725312912383441159505038794027105778954184319n,303847389135065887422783454877609941456349188919719272345083954437860409601n],[21888242871839275220042445260109153167277707414472061641714758635765020556616n,0n],[3321304630594332808241809054958361220322477375291206261884409189760185844239n,5722266937896532885780051958958348231143373700109372999374820235121374419868n],[21888242871839275222246405745257275088696311157297823662689037894645226208582n,0n],[13512124006075453725662431877630910996106405091429524885779419978626457868503n,5418419548761466998357268504080738289687024511189653727029736280683514010267n],[2203960485148121921418603742825762020974279258880205651966n,0n],[10190819375481120917420622822672549775783927716138318623895010788866272024264n,21584395482704209334823622290379665147239961968378104390343953940207365798982n],[2203960485148121921418603742825762020974279258880205651967n,0n],[18566938241244942414004596690298913868373833782006617400804628704885040364344n,16165975933942742336466353786298926857552937457188450663314217659523851788715n]]],o=[[[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n]],[[1n,0n],[21575463638280843010398324269430826099269044274347216827212613867836435027261n,10307601595873709700152284273816112264069230130616436755625194854815875713954n],[21888242871839275220042445260109153167277707414472061641714758635765020556616n,0n],[3772000881919853776433695186713858239009073593817195771773381919316419345261n,2236595495967245188281701248203181795121068902605861227855261137820944008926n],[2203960485148121921418603742825762020974279258880205651966n,0n],[18429021223477853657660792034369865839114504446431234726392080002137598044644n,9344045779998320333812420223237981029506012124075525679208581902008406485703n]],[[1n,0n],[2581911344467009335267311115468803099551665605076196740867805258568234346338n,19937756971775647987995932169929341994314640652964949448313374472400716661030n],[2203960485148121921418603742825762020974279258880205651966n,0n],[5324479202449903542726783395506214481928257762400643279780343368557297135718n,16208900380737693084919495127334387981393726419856888799917914180988844123039n],[21888242871839275220042445260109153167277707414472061641714758635765020556616n,0n],[13981852324922362344252311234282257507216387789820983642040889267519694726527n,7629828391165209371577384193250820201684255241773809077146787135900891633097n]]],l=t.addFunction(a+"__frobeniusMap"+e);l.addParam("x","i32"),l.addParam("r","i32");const r=l.getCodeBuilder();for(let a=0;a<6;a++){const i=0==a?r.getLocal("x"):r.i32_add(r.getLocal("x"),r.i32_const(a*c)),u=i,g=r.i32_add(r.getLocal("x"),r.i32_const(a*c+s)),h=0==a?r.getLocal("r"):r.i32_add(r.getLocal("r"),r.i32_const(a*c)),_=h,m=r.i32_add(r.getLocal("r"),r.i32_const(a*c+s)),w=d(n[Math.floor(a/3)][e%12],o[a%3][e%6]),b=t.alloc([...Ce.bigInt2BytesLE(L(w[0]),32),...Ce.bigInt2BytesLE(L(w[1]),32)]);e%2==1?l.addCode(r.call(f+"_copy",u,_),r.call(f+"_neg",g,m),r.call(p+"_mul",h,r.i32_const(b),h)):l.addCode(r.call(p+"_mul",i,r.i32_const(b),h))}function d(t,e){const a=BigInt(t[0]),n=BigInt(t[1]),o=BigInt(e[0]),l=BigInt(e[1]),r=[(a*o-n*l)%i,(a*l+n*o)%i];return Me(r[0])&&(r[0]=r[0]+i),r}}function V(e,i){const n=function(t){let e=t;const a=[];for(;e>0n;){if(Ue(e)){const t=2-Number(e%4n);a.push(t),e-=BigInt(t)}else a.push(0);e>>=1n}return a}(e).map((t=>-1==t?255:t)),o=t.alloc(n),l=t.addFunction(a+"__cyclotomicExp_"+i);l.addParam("x","i32"),l.addParam("r","i32"),l.addLocal("bit","i32"),l.addLocal("i","i32");const r=l.getCodeBuilder(),s=r.getLocal("x"),c=r.getLocal("r"),u=r.i32_const(t.alloc(d));l.addCode(r.call(G+"_conjugate",s,u),r.call(G+"_one",c),r.if(r.teeLocal("bit",r.i32_load8_s(r.i32_const(n.length-1),o)),r.if(r.i32_eq(r.getLocal("bit"),r.i32_const(1)),r.call(G+"_mul",c,s,c),r.call(G+"_mul",c,u,c))),r.setLocal("i",r.i32_const(n.length-2)),r.block(r.loop(r.call(a+"__cyclotomicSquare",c,c),r.if(r.teeLocal("bit",r.i32_load8_s(r.getLocal("i"),o)),r.if(r.i32_eq(r.getLocal("bit"),r.i32_const(1)),r.call(G+"_mul",c,s,c),r.call(G+"_mul",c,u,c))),r.br_if(1,r.i32_eqz(r.getLocal("i"))),r.setLocal("i",r.i32_sub(r.getLocal("i"),r.i32_const(1))),r.br(0))))}function W(){!function(){const e=t.addFunction(a+"__cyclotomicSquare");e.addParam("x","i32"),e.addParam("r","i32");const i=e.getCodeBuilder(),n=i.getLocal("x"),o=i.i32_add(i.getLocal("x"),i.i32_const(c)),l=i.i32_add(i.getLocal("x"),i.i32_const(2*c)),r=i.i32_add(i.getLocal("x"),i.i32_const(3*c)),s=i.i32_add(i.getLocal("x"),i.i32_const(4*c)),d=i.i32_add(i.getLocal("x"),i.i32_const(5*c)),u=i.getLocal("r"),f=i.i32_add(i.getLocal("r"),i.i32_const(c)),g=i.i32_add(i.getLocal("r"),i.i32_const(2*c)),h=i.i32_add(i.getLocal("r"),i.i32_const(3*c)),_=i.i32_add(i.getLocal("r"),i.i32_const(4*c)),m=i.i32_add(i.getLocal("r"),i.i32_const(5*c)),w=i.i32_const(t.alloc(c)),L=i.i32_const(t.alloc(c)),b=i.i32_const(t.alloc(c)),y=i.i32_const(t.alloc(c)),v=i.i32_const(t.alloc(c)),F=i.i32_const(t.alloc(c)),x=i.i32_const(t.alloc(c)),C=i.i32_const(t.alloc(c));e.addCode(i.call(p+"_mul",n,s,x),i.call(p+"_mul",s,i.i32_const(B),w),i.call(p+"_add",n,w,w),i.call(p+"_add",n,s,C),i.call(p+"_mul",C,w,w),i.call(p+"_mul",i.i32_const(B),x,C),i.call(p+"_add",x,C,C),i.call(p+"_sub",w,C,w),i.call(p+"_add",x,x,L),i.call(p+"_mul",r,l,x),i.call(p+"_mul",l,i.i32_const(B),b),i.call(p+"_add",r,b,b),i.call(p+"_add",r,l,C),i.call(p+"_mul",C,b,b),i.call(p+"_mul",i.i32_const(B),x,C),i.call(p+"_add",x,C,C),i.call(p+"_sub",b,C,b),i.call(p+"_add",x,x,y),i.call(p+"_mul",o,d,x),i.call(p+"_mul",d,i.i32_const(B),v),i.call(p+"_add",o,v,v),i.call(p+"_add",o,d,C),i.call(p+"_mul",C,v,v),i.call(p+"_mul",i.i32_const(B),x,C),i.call(p+"_add",x,C,C),i.call(p+"_sub",v,C,v),i.call(p+"_add",x,x,F),i.call(p+"_sub",w,n,u),i.call(p+"_add",u,u,u),i.call(p+"_add",w,u,u),i.call(p+"_add",L,s,_),i.call(p+"_add",_,_,_),i.call(p+"_add",L,_,_),i.call(p+"_mul",F,i.i32_const(z),C),i.call(p+"_add",C,r,h),i.call(p+"_add",h,h,h),i.call(p+"_add",C,h,h),i.call(p+"_sub",v,l,g),i.call(p+"_add",g,g,g),i.call(p+"_add",v,g,g),i.call(p+"_sub",b,o,f),i.call(p+"_add",f,f,f),i.call(p+"_add",b,f,f),i.call(p+"_add",y,d,m),i.call(p+"_add",m,m,m),i.call(p+"_add",y,m,m))}(),V(j,"w0");const e=t.addFunction(a+"__finalExponentiationLastChunk");e.addParam("x","i32"),e.addParam("r","i32");const i=e.getCodeBuilder(),n=i.getLocal("x"),o=i.getLocal("r"),l=i.i32_const(t.alloc(d)),r=i.i32_const(t.alloc(d)),s=i.i32_const(t.alloc(d)),u=i.i32_const(t.alloc(d)),f=i.i32_const(t.alloc(d)),g=i.i32_const(t.alloc(d)),h=i.i32_const(t.alloc(d)),_=i.i32_const(t.alloc(d)),m=i.i32_const(t.alloc(d)),w=i.i32_const(t.alloc(d)),L=i.i32_const(t.alloc(d)),b=i.i32_const(t.alloc(d)),y=i.i32_const(t.alloc(d)),v=i.i32_const(t.alloc(d)),F=i.i32_const(t.alloc(d)),x=i.i32_const(t.alloc(d)),C=i.i32_const(t.alloc(d)),S=i.i32_const(t.alloc(d)),E=i.i32_const(t.alloc(d)),A=i.i32_const(t.alloc(d)),P=i.i32_const(t.alloc(d));e.addCode(i.call(a+"__cyclotomicExp_w0",n,l),i.call(G+"_conjugate",l,l),i.call(a+"__cyclotomicSquare",l,r),i.call(a+"__cyclotomicSquare",r,s),i.call(G+"_mul",s,r,u),i.call(a+"__cyclotomicExp_w0",u,f),i.call(G+"_conjugate",f,f),i.call(a+"__cyclotomicSquare",f,g),i.call(a+"__cyclotomicExp_w0",g,h),i.call(G+"_conjugate",h,h),i.call(G+"_conjugate",u,_),i.call(G+"_conjugate",h,m),i.call(G+"_mul",m,f,w),i.call(G+"_mul",w,_,L),i.call(G+"_mul",L,r,b),i.call(G+"_mul",L,f,y),i.call(G+"_mul",y,n,v),i.call(a+"__frobeniusMap1",b,F),i.call(G+"_mul",F,v,x),i.call(a+"__frobeniusMap2",L,C),i.call(G+"_mul",C,x,S),i.call(G+"_conjugate",n,E),i.call(G+"_mul",E,b,A),i.call(a+"__frobeniusMap3",A,P),i.call(G+"_mul",P,S,o))}const Z=t.alloc(R),H=t.alloc(N);function Q(e){const i=t.addFunction(a+"_pairingEq"+e);for(let t=0;t0n;)Xe(e)?a.push(1):a.push(0),e>>=1n;return a}(0xd201000000010000n),O=t.alloc(G),q=3*s,U=G.length-1,M=G.reduce(((t,e)=>t+(0!=e?1:0)),0),k=6*l,R=3*l*2+(M+U+1)*q,N=15132376222941642752n;function j(e){const a=[[[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n]],[[1n,0n],[3850754370037169011952147076051364057158807420970682438676050522613628423219637725072182697113062777891589506424760n,151655185184498381465642749684540099398075398968325446656007613510403227271200139370504932015952886146304766135027n],[793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620351n,0n],[2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530n,1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257n],[793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350n,0n],[3125332594171059424908108096204648978570118281977575435832422631601824034463382777937621250592425535493320683825557n,877076961050607968509681729531255177986764537961432449499635504522207616027455086505066378536590128544573588734230n],[4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559786n,0n],[151655185184498381465642749684540099398075398968325446656007613510403227271200139370504932015952886146304766135027n,3850754370037169011952147076051364057158807420970682438676050522613628423219637725072182697113062777891589506424760n],[4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436n,0n],[1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257n,2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530n],[4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437n,0n],[877076961050607968509681729531255177986764537961432449499635504522207616027455086505066378536590128544573588734230n,3125332594171059424908108096204648978570118281977575435832422631601824034463382777937621250592425535493320683825557n]]],n=[[[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n]],[[1n,0n],[0n,4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436n],[793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350n,0n],[0n,1n],[4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436n,0n],[0n,793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350n]],[[1n,0n],[4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437n,0n],[4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436n,0n],[4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559786n,0n],[793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350n,0n],[793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620351n,0n]]],o=t.addFunction(T+"_frobeniusMap"+e);o.addParam("x","i32"),o.addParam("r","i32");const c=o.getCodeBuilder();for(let i=0;i<6;i++){const u=0==i?c.getLocal("x"):c.i32_add(c.getLocal("x"),c.i32_const(i*s)),f=u,g=c.i32_add(c.getLocal("x"),c.i32_const(i*s+r)),p=0==i?c.getLocal("r"):c.i32_add(c.getLocal("r"),c.i32_const(i*s)),_=p,w=c.i32_add(c.getLocal("r"),c.i32_const(i*s+r)),L=d(a[Math.floor(i/3)][e%12],n[i%3][e%6]),b=t.alloc([...ke.bigInt2BytesLE(y(L[0]),l),...ke.bigInt2BytesLE(y(L[1]),l)]);e%2==1?o.addCode(c.call(h+"_copy",f,_),c.call(h+"_neg",g,w),c.call(m+"_mul",p,c.i32_const(b),p)):o.addCode(c.call(m+"_mul",u,c.i32_const(b),p))}function d(t,e){const a=t[0],n=t[1],o=e[0],l=e[1],r=[(a*o-n*l)%i,(a*l+n*o)%i];return Ye(r[0])&&(r[0]=r[0]+i),r}}function D(e,i,n){const o=function(t){let e=t;const a=[];for(;e>0n;){if(Xe(e)){const t=2-Number(e%4n);a.push(t),e-=BigInt(t)}else a.push(0);e>>=1n}return a}(e).map((t=>-1==t?255:t)),l=t.alloc(o),r=t.addFunction(a+"__cyclotomicExp_"+n);r.addParam("x","i32"),r.addParam("r","i32"),r.addLocal("bit","i32"),r.addLocal("i","i32");const s=r.getCodeBuilder(),d=s.getLocal("x"),u=s.getLocal("r"),f=s.i32_const(t.alloc(c));r.addCode(s.call(T+"_conjugate",d,f),s.call(T+"_one",u),s.if(s.teeLocal("bit",s.i32_load8_s(s.i32_const(o.length-1),l)),s.if(s.i32_eq(s.getLocal("bit"),s.i32_const(1)),s.call(T+"_mul",u,d,u),s.call(T+"_mul",u,f,u))),s.setLocal("i",s.i32_const(o.length-2)),s.block(s.loop(s.call(a+"__cyclotomicSquare",u,u),s.if(s.teeLocal("bit",s.i32_load8_s(s.getLocal("i"),l)),s.if(s.i32_eq(s.getLocal("bit"),s.i32_const(1)),s.call(T+"_mul",u,d,u),s.call(T+"_mul",u,f,u))),s.br_if(1,s.i32_eqz(s.getLocal("i"))),s.setLocal("i",s.i32_sub(s.getLocal("i"),s.i32_const(1))),s.br(0)))),i&&r.addCode(s.call(T+"_conjugate",u,u))}t.modules[a]={n64q:o,n64r:d,n8q:l,n8r:u,pG1gen:F,pG1zero:C,pG1b:p,pG2gen:E,pG2zero:B,pG2b:w,pq:t.modules.f1m.pq,pr:g,pOneT:P,r:n,q:i,prePSize:k,preQSize:R},function(){const e=t.addFunction(I+"_mul1");e.addParam("pA","i32"),e.addParam("pC1","i32"),e.addParam("pR","i32");const a=e.getCodeBuilder(),i=a.getLocal("pA"),n=a.i32_add(a.getLocal("pA"),a.i32_const(2*r)),o=a.i32_add(a.getLocal("pA"),a.i32_const(4*r)),l=a.getLocal("pC1"),s=a.getLocal("pR"),c=a.i32_add(a.getLocal("pR"),a.i32_const(2*r)),d=a.i32_add(a.getLocal("pR"),a.i32_const(4*r)),u=a.i32_const(t.alloc(2*r)),f=a.i32_const(t.alloc(2*r));e.addCode(a.call(m+"_add",i,n,u),a.call(m+"_add",n,o,f),a.call(m+"_mul",n,l,d),a.call(m+"_mul",f,l,s),a.call(m+"_sub",s,d,s),a.call(m+"_mulNR",s,s),a.call(m+"_mul",u,l,c),a.call(m+"_sub",c,d,c))}(),function(){const e=t.addFunction(I+"_mul01");e.addParam("pA","i32"),e.addParam("pC0","i32"),e.addParam("pC1","i32"),e.addParam("pR","i32");const a=e.getCodeBuilder(),i=a.getLocal("pA"),n=a.i32_add(a.getLocal("pA"),a.i32_const(2*r)),o=a.i32_add(a.getLocal("pA"),a.i32_const(4*r)),l=a.getLocal("pC0"),s=a.getLocal("pC1"),c=a.getLocal("pR"),d=a.i32_add(a.getLocal("pR"),a.i32_const(2*r)),u=a.i32_add(a.getLocal("pR"),a.i32_const(4*r)),f=a.i32_const(t.alloc(2*r)),g=a.i32_const(t.alloc(2*r)),h=a.i32_const(t.alloc(2*r)),p=a.i32_const(t.alloc(2*r));e.addCode(a.call(m+"_mul",i,l,f),a.call(m+"_mul",n,s,g),a.call(m+"_add",i,n,h),a.call(m+"_add",i,o,p),a.call(m+"_add",n,o,c),a.call(m+"_mul",c,s,c),a.call(m+"_sub",c,g,c),a.call(m+"_mulNR",c,c),a.call(m+"_add",c,f,c),a.call(m+"_add",l,s,d),a.call(m+"_mul",d,h,d),a.call(m+"_sub",d,f,d),a.call(m+"_sub",d,g,d),a.call(m+"_mul",p,l,u),a.call(m+"_sub",u,f,u),a.call(m+"_add",u,g,u))}(),function(){const e=t.addFunction(T+"_mul014");e.addParam("pA","i32"),e.addParam("pC0","i32"),e.addParam("pC1","i32"),e.addParam("pC4","i32"),e.addParam("pR","i32");const a=e.getCodeBuilder(),i=a.getLocal("pA"),n=a.i32_add(a.getLocal("pA"),a.i32_const(6*r)),o=a.getLocal("pC0"),l=a.getLocal("pC1"),s=a.getLocal("pC4"),c=a.i32_const(t.alloc(6*r)),d=a.i32_const(t.alloc(6*r)),u=a.i32_const(t.alloc(2*r)),f=a.getLocal("pR"),g=a.i32_add(a.getLocal("pR"),a.i32_const(6*r));e.addCode(a.call(I+"_mul01",i,o,l,c),a.call(I+"_mul1",n,s,d),a.call(m+"_add",l,s,u),a.call(I+"_add",n,i,g),a.call(I+"_mul01",g,o,u,g),a.call(I+"_sub",g,c,g),a.call(I+"_sub",g,d,g),a.call(I+"_copy",d,f),a.call(I+"_mulNR",f,f),a.call(I+"_add",f,c,f))}(),function(){const e=t.addFunction(a+"_ell");e.addParam("pP","i32"),e.addParam("pCoefs","i32"),e.addParam("pF","i32");const i=e.getCodeBuilder(),n=i.getLocal("pP"),o=i.i32_add(i.getLocal("pP"),i.i32_const(l)),s=i.getLocal("pF"),c=i.getLocal("pCoefs"),d=i.i32_add(i.getLocal("pCoefs"),i.i32_const(r)),u=i.i32_add(i.getLocal("pCoefs"),i.i32_const(2*r)),f=i.i32_add(i.getLocal("pCoefs"),i.i32_const(3*r)),g=i.i32_add(i.getLocal("pCoefs"),i.i32_const(4*r)),p=t.alloc(2*r),_=i.i32_const(p),m=i.i32_const(p),w=i.i32_const(p+r),L=t.alloc(2*r),b=i.i32_const(L),y=i.i32_const(L),v=i.i32_const(L+r);e.addCode(i.call(h+"_mul",c,o,m),i.call(h+"_mul",d,o,w),i.call(h+"_mul",u,n,y),i.call(h+"_mul",f,n,v),i.call(T+"_mul014",s,g,b,_,s))}();const V=t.alloc(k),W=t.alloc(R);function Z(e){const i=t.addFunction(a+"_pairingEq"+e);for(let t=0;t>8n&0xFFn)),e.push(Number(a>>16n&0xFFn)),e.push(Number(a>>24n&0xFFn)),e}function la(t){const e=function(t){for(var e=[],a=0;a>6,128|63&i):i<55296||i>=57344?e.push(224|i>>12,128|i>>6&63,128|63&i):(a++,i=65536+((1023&i)<<10|1023&t.charCodeAt(a)),e.push(240|i>>18,128|i>>12&63,128|i>>6&63,128|63&i))}return e}(t);return[...ua(e.length),...e]}function ra(t){const e=[];let a=aa(t);if(ia(a))throw new Error("Number cannot be negative");for(;!na(a);)e.push(Number(0x7Fn&a)),a>>=7n;0==e.length&&e.push(0);for(let t=0;t0xFFFFFFFFn)throw new Error("Number too big");if(e>0x7FFFFFFFn&&(e-=0x100000000n),e<-2147483648n)throw new Error("Number too small");return sa(e)}function da(t){let e=aa(t);if(e>0xFFFFFFFFFFFFFFFFn)throw new Error("Number too big");if(e>0x7FFFFFFFFFFFFFFFn&&(e-=0x10000000000000000n),e<-9223372036854775808n)throw new Error("Number too small");return sa(e)}function ua(t){let e=aa(t);if(e>0xFFFFFFFFn)throw new Error("Number too big");return ra(e)}function fa(t){return Array.from(t,(function(t){return("0"+(255&t).toString(16)).slice(-2)})).join("")}class ga{constructor(t){this.func=t,this.functionName=t.functionName,this.module=t.module}setLocal(t,e){const a=this.func.localIdxByName[t];if(void 0===a)throw new Error(`Local Variable not defined: Function: ${this.functionName} local: ${t} `);return[...e,33,...ua(a)]}teeLocal(t,e){const a=this.func.localIdxByName[t];if(void 0===a)throw new Error(`Local Variable not defined: Function: ${this.functionName} local: ${t} `);return[...e,34,...ua(a)]}getLocal(t){const e=this.func.localIdxByName[t];if(void 0===e)throw new Error(`Local Variable not defined: Function: ${this.functionName} local: ${t} `);return[32,...ua(e)]}i64_load8_s(t,e,a){return[...t,48,void 0===a?0:a,...ua(e||0)]}i64_load8_u(t,e,a){return[...t,49,void 0===a?0:a,...ua(e||0)]}i64_load16_s(t,e,a){return[...t,50,void 0===a?1:a,...ua(e||0)]}i64_load16_u(t,e,a){return[...t,51,void 0===a?1:a,...ua(e||0)]}i64_load32_s(t,e,a){return[...t,52,void 0===a?2:a,...ua(e||0)]}i64_load32_u(t,e,a){return[...t,53,void 0===a?2:a,...ua(e||0)]}i64_load(t,e,a){return[...t,41,void 0===a?3:a,...ua(e||0)]}i64_store(t,e,a,i){let n,o,l;return Array.isArray(e)?(n=0,o=3,l=e):Array.isArray(a)?(n=e,o=3,l=a):Array.isArray(i)&&(n=e,o=a,l=i),[...t,...l,55,o,...ua(n)]}i64_store32(t,e,a,i){let n,o,l;return Array.isArray(e)?(n=0,o=2,l=e):Array.isArray(a)?(n=e,o=2,l=a):Array.isArray(i)&&(n=e,o=a,l=i),[...t,...l,62,o,...ua(n)]}i64_store16(t,e,a,i){let n,o,l;return Array.isArray(e)?(n=0,o=1,l=e):Array.isArray(a)?(n=e,o=1,l=a):Array.isArray(i)&&(n=e,o=a,l=i),[...t,...l,61,o,...ua(n)]}i64_store8(t,e,a,i){let n,o,l;return Array.isArray(e)?(n=0,o=0,l=e):Array.isArray(a)?(n=e,o=0,l=a):Array.isArray(i)&&(n=e,o=a,l=i),[...t,...l,60,o,...ua(n)]}i32_load8_s(t,e,a){return[...t,44,void 0===a?0:a,...ua(e||0)]}i32_load8_u(t,e,a){return[...t,45,void 0===a?0:a,...ua(e||0)]}i32_load16_s(t,e,a){return[...t,46,void 0===a?1:a,...ua(e||0)]}i32_load16_u(t,e,a){return[...t,47,void 0===a?1:a,...ua(e||0)]}i32_load(t,e,a){return[...t,40,void 0===a?2:a,...ua(e||0)]}i32_store(t,e,a,i){let n,o,l;return Array.isArray(e)?(n=0,o=2,l=e):Array.isArray(a)?(n=e,o=2,l=a):Array.isArray(i)&&(n=e,o=a,l=i),[...t,...l,54,o,...ua(n)]}i32_store16(t,e,a,i){let n,o,l;return Array.isArray(e)?(n=0,o=1,l=e):Array.isArray(a)?(n=e,o=1,l=a):Array.isArray(i)&&(n=e,o=a,l=i),[...t,...l,59,o,...ua(n)]}i32_store8(t,e,a,i){let n,o,l;return Array.isArray(e)?(n=0,o=0,l=e):Array.isArray(a)?(n=e,o=0,l=a):Array.isArray(i)&&(n=e,o=a,l=i),[...t,...l,58,o,...ua(n)]}call(t,...e){const a=this.module.functionIdxByName[t];if(void 0===a)throw new Error(`Function not defined: Function: ${t}`);return[...[].concat(...e),16,...ua(a)]}call_indirect(t,...e){return[...[].concat(...e),...t,17,0,0]}if(t,e,a){return a?[...t,4,64,...e,5,...a,11]:[...t,4,64,...e,11]}block(t){return[2,64,...t,11]}loop(...t){return[3,64,...[].concat(...t),11]}br_if(t,e){return[...e,13,...ua(t)]}br(t){return[12,...ua(t)]}ret(t){return[...t,15]}drop(t){return[...t,26]}i64_const(t){return[66,...da(t)]}i32_const(t){return[65,...ca(t)]}i64_eqz(t){return[...t,80]}i64_eq(t,e){return[...t,...e,81]}i64_ne(t,e){return[...t,...e,82]}i64_lt_s(t,e){return[...t,...e,83]}i64_lt_u(t,e){return[...t,...e,84]}i64_gt_s(t,e){return[...t,...e,85]}i64_gt_u(t,e){return[...t,...e,86]}i64_le_s(t,e){return[...t,...e,87]}i64_le_u(t,e){return[...t,...e,88]}i64_ge_s(t,e){return[...t,...e,89]}i64_ge_u(t,e){return[...t,...e,90]}i64_add(t,e){return[...t,...e,124]}i64_sub(t,e){return[...t,...e,125]}i64_mul(t,e){return[...t,...e,126]}i64_div_s(t,e){return[...t,...e,127]}i64_div_u(t,e){return[...t,...e,128]}i64_rem_s(t,e){return[...t,...e,129]}i64_rem_u(t,e){return[...t,...e,130]}i64_and(t,e){return[...t,...e,131]}i64_or(t,e){return[...t,...e,132]}i64_xor(t,e){return[...t,...e,133]}i64_shl(t,e){return[...t,...e,134]}i64_shr_s(t,e){return[...t,...e,135]}i64_shr_u(t,e){return[...t,...e,136]}i64_extend_i32_s(t){return[...t,172]}i64_extend_i32_u(t){return[...t,173]}i64_clz(t){return[...t,121]}i64_ctz(t){return[...t,122]}i32_eqz(t){return[...t,69]}i32_eq(t,e){return[...t,...e,70]}i32_ne(t,e){return[...t,...e,71]}i32_lt_s(t,e){return[...t,...e,72]}i32_lt_u(t,e){return[...t,...e,73]}i32_gt_s(t,e){return[...t,...e,74]}i32_gt_u(t,e){return[...t,...e,75]}i32_le_s(t,e){return[...t,...e,76]}i32_le_u(t,e){return[...t,...e,77]}i32_ge_s(t,e){return[...t,...e,78]}i32_ge_u(t,e){return[...t,...e,79]}i32_add(t,e){return[...t,...e,106]}i32_sub(t,e){return[...t,...e,107]}i32_mul(t,e){return[...t,...e,108]}i32_div_s(t,e){return[...t,...e,109]}i32_div_u(t,e){return[...t,...e,110]}i32_rem_s(t,e){return[...t,...e,111]}i32_rem_u(t,e){return[...t,...e,112]}i32_and(t,e){return[...t,...e,113]}i32_or(t,e){return[...t,...e,114]}i32_xor(t,e){return[...t,...e,115]}i32_shl(t,e){return[...t,...e,116]}i32_shr_s(t,e){return[...t,...e,117]}i32_shr_u(t,e){return[...t,...e,118]}i32_rotl(t,e){return[...t,...e,119]}i32_rotr(t,e){return[...t,...e,120]}i32_wrap_i64(t){return[...t,167]}i32_clz(t){return[...t,103]}i32_ctz(t){return[...t,104]}unreachable(){return[0]}current_memory(){return[63,0]}comment(){return[]}}const ha={i32:127,i64:126,f32:125,f64:124,anyfunc:112,func:96,emptyblock:64};class pa{constructor(t,e,a,i,n){if("import"==a)this.fnType="import",this.moduleName=i,this.fieldName=n;else{if("internal"!=a)throw new Error("Invalid function fnType: "+a);this.fnType="internal"}this.module=t,this.fnName=e,this.params=[],this.locals=[],this.localIdxByName={},this.code=[],this.returnType=null,this.nextLocal=0}addParam(t,e){if(this.localIdxByName[t])throw new Error(`param already exists. Function: ${this.fnName}, Param: ${t} `);const a=this.nextLocal++;this.localIdxByName[t]=a,this.params.push({type:e})}addLocal(t,e,a){const i=a||1;if(this.localIdxByName[t])throw new Error(`local already exists. Function: ${this.fnName}, Param: ${t} `);const n=this.nextLocal++;this.localIdxByName[t]=n,this.locals.push({type:e,length:i})}setReturnType(t){if(this.returnType)throw new Error(`returnType already defined. Function: ${this.fnName}`);this.returnType=t}getSignature(){return[96,...[...ua(this.params.length),...this.params.map((t=>ha[t.type]))],...this.returnType?[1,ha[this.returnType]]:[0]]}getBody(){const t=this.locals.map((t=>[...ua(t.length),ha[t.type]])),e=[...ua(this.locals.length),...[].concat(...t),...this.code,11];return[...ua(e.length),...e]}addCode(...t){this.code.push(...[].concat(...t))}getCodeBuilder(){return new ga(this)}}var _a=Object.freeze({__proto__:null,ModuleBuilder:class{constructor(){this.functions=[],this.functionIdxByName={},this.nImportFunctions=0,this.nInternalFunctions=0,this.memory={pagesSize:1,moduleName:"env",fieldName:"memory"},this.free=8,this.datas=[],this.modules={},this.exports=[],this.functionsTable=[]}build(){return this._setSignatures(),new Uint8Array([...oa(1836278016),...oa(1),...this._buildType(),...this._buildImport(),...this._buildFunctionDeclarations(),...this._buildFunctionsTable(),...this._buildExports(),...this._buildElements(),...this._buildCode(),...this._buildData()])}addFunction(t){if(void 0!==this.functionIdxByName[t])throw new Error(`Function already defined: ${t}`);const e=this.functions.length;return this.functionIdxByName[t]=e,this.functions.push(new pa(this,t,"internal")),this.nInternalFunctions++,this.functions[e]}addIimportFunction(t,e,a){if(void 0!==this.functionIdxByName[t])throw new Error(`Function already defined: ${t}`);if(this.functions.length>0&&"internal"==this.functions[this.functions.length-1].type)throw new Error(`Import functions must be declared before internal: ${t}`);let i=a||t;const n=this.functions.length;return this.functionIdxByName[t]=n,this.functions.push(new pa(this,t,"import",e,i)),this.nImportFunctions++,this.functions[n]}setMemory(t,e,a){this.memory={pagesSize:t,moduleName:e||"env",fieldName:a||"memory"}}exportFunction(t,e){const a=e||t;if(void 0===this.functionIdxByName[t])throw new Error(`Function not defined: ${t}`);const i=this.functionIdxByName[t];a!=t&&(this.functionIdxByName[a]=i),this.exports.push({exportName:a,idx:i})}addFunctionToTable(t){const e=this.functionIdxByName[t];this.functionsTable.push(e)}addData(t,e){this.datas.push({offset:t,bytes:e})}alloc(t,e){let a,i;(Array.isArray(t)||ArrayBuffer.isView(t))&&void 0===e?(a=t.length,i=t):(a=t,i=e),a=1+(a-1>>3)<<3;const n=this.free;return this.free+=a,i&&this.addData(n,i),n}allocString(t){const e=(new globalThis.TextEncoder).encode(t);return this.alloc([...e,0])}_setSignatures(){this.signatures=[];const t={};if(this.functionsTable.length>0){const e=this.functions[this.functionsTable[0]].getSignature();t["s_"+fa(e)]=0,this.signatures.push(e)}for(let e=0;e{e.pendingLoads.push({page:t,resolve:a,reject:i})}));return e.__statusPage("After Load request: ",t),a}__statusPage(t,e){const a=[],i=this;if(!i.logHistory)return;a.push("=="+t+" "+e);let n="";for(let t=0;t "+e.history[t][a][i])}_triggerLoad(){const t=this;if(t.reading)return;if(0==t.pendingLoads.length)return;const e=Object.keys(t.pages),a=[];for(let i=0;i0&&(void 0!==t.pages[t.pendingLoads[0].page]||i>0||a.length>0);){const e=t.pendingLoads.shift();if(void 0!==t.pages[e.page]){t.pages[e.page].pendingOps++;const i=a.indexOf(e.page);i>=0&&a.splice(i,1),t.pages[e.page].loading?t.pages[e.page].loading.push(e):e.resolve(),t.__statusPage("After Load (cached): ",e.page)}else{if(i)i--;else{const e=a.shift();t.__statusPage("Before Unload: ",e),t.avBuffs.unshift(t.pages[e]),delete t.pages[e],t.__statusPage("After Unload: ",e)}e.page>=t.totalPages?(t.pages[e.page]=o(),e.resolve(),t.__statusPage("After Load (new): ",e.page)):(t.reading=!0,t.pages[e.page]=o(),t.pages[e.page].loading=[e],n.push(t.fd.read(t.pages[e.page].buff,0,t.pageSize,e.page*t.pageSize).then((a=>{t.pages[e.page].size=a.bytesRead;const i=t.pages[e.page].loading;delete t.pages[e.page].loading;for(let t=0;t{e.reject(t)}))),t.__statusPage("After Load (loading): ",e.page))}}function o(){if(t.avBuffs.length>0){const e=t.avBuffs.shift();return e.dirty=!1,e.pendingOps=1,e.size=0,e}return{dirty:!1,buff:new Uint8Array(t.pageSize),pendingOps:1,size:0}}Promise.all(n).then((()=>{t.reading=!1,t.pendingLoads.length>0&&setImmediate(t._triggerLoad.bind(t)),t._tryClose()}))}_triggerWrite(){const t=this;if(t.writing)return;const e=Object.keys(t.pages),a=[];for(let i=0;i{n.writing=!1}),(e=>{console.log("ERROR Writing: "+e),t.error=e,t._tryClose()}))))}t.writing&&Promise.all(a).then((()=>{t.writing=!1,setImmediate(t._triggerWrite.bind(t)),t._tryClose(),t.pendingLoads.length>0&&setImmediate(t._triggerLoad.bind(t))}))}_getDirtyPage(){for(let t in this.pages)if(this.pages[t].dirty)return t;return-1}async write(t,e){if(0==t.byteLength)return;const a=this;if(void 0===e&&(e=a.pos),a.pos=e+t.byteLength,a.totalSize0;){await o[l-i];const e=r+s>a.pageSize?a.pageSize-r:s,n=t.slice(t.byteLength-s,t.byteLength-s+e);new Uint8Array(a.pages[l].buff.buffer,r,e).set(n),a.pages[l].dirty=!0,a.pages[l].pendingOps--,a.pages[l].size=Math.max(r+e,a.pages[l].size),l>=a.totalPages&&(a.totalPages=l+1),s-=e,l++,r=0,a.writing||setImmediate(a._triggerWrite.bind(a))}}async read(t,e){let a=new Uint8Array(t);return await this.readToBuffer(a,0,t,e),a}async readToBuffer(t,e,a,i){if(0==a)return;const n=this;if(a>n.pageSize*n.maxPagesLoaded*.8){const t=Math.floor(1.1*a);this.maxPagesLoaded=Math.floor(t/n.pageSize)+1}if(void 0===i&&(i=n.pos),n.pos=i+a,n.pendingClose)throw new Error("Reading a closing file");const o=Math.floor(i/n.pageSize),l=Math.floor((i+a-1)/n.pageSize),r=[];for(let t=o;t<=l;t++)r.push(n._loadPage(t));n._triggerLoad();let s=o,c=i%n.pageSize,d=i+a>n.totalSize?a-(i+a-n.totalSize):a;for(;d>0;){await r[s-o],n.__statusPage("After Await (read): ",s);const i=c+d>n.pageSize?n.pageSize-c:d,l=new Uint8Array(n.pages[s].buff.buffer,n.pages[s].buff.byteOffset+c,i);t.set(l,e+a-d),n.pages[s].pendingOps--,n.__statusPage("After Op done: ",s),d-=i,s++,c=0,n.pendingLoads.length>0&&setImmediate(n._triggerLoad.bind(n))}this.pos=i+a}_tryClose(){const t=this;if(!t.pendingClose)return;t.error&&t.pendingCloseReject(t.error);t._getDirtyPage()>=0||t.writing||t.reading||t.pendingLoads.length>0||t.pendingClose()}close(){const t=this;if(t.pendingClose)throw new Error("Closing the file twice");return new Promise(((e,a)=>{t.pendingClose=e,t.pendingCloseReject=a,t._tryClose()})).then((()=>{t.fd.close()}),(e=>{throw t.fd.close(),e}))}async discard(){await this.close(),await ma.promises.unlink(this.fileName)}async writeULE32(t,e){const a=new Uint8Array(4);new DataView(a.buffer).setUint32(0,t,!0),await this.write(a,e)}async writeUBE32(t,e){const a=new Uint8Array(4);new DataView(a.buffer).setUint32(0,t,!1),await this.write(a,e)}async writeULE64(t,e){const a=new Uint8Array(8),i=new DataView(a.buffer);i.setUint32(0,4294967295&t,!0),i.setUint32(4,Math.floor(t/4294967296),!0),await this.write(a,e)}async readULE32(t){const e=await this.read(4,t);return new Uint32Array(e.buffer)[0]}async readUBE32(t){const e=await this.read(4,t);return new DataView(e.buffer).getUint32(0,!1)}async readULE64(t){const e=await this.read(8,t),a=new Uint32Array(e.buffer);return 4294967296*a[1]+a[0]}async readString(t){const e=this;if(e.pendingClose)throw new Error("Reading a closing file");let a=void 0===t?e.pos:t,i=Math.floor(a/e.pageSize),n=!1,o="";for(;!n;){let t=e._loadPage(i);e._triggerLoad(),await t,e.__statusPage("After Await (read): ",i);let l=a%e.pageSize;const r=new Uint8Array(e.pages[i].buff.buffer,e.pages[i].buff.byteOffset+l,e.pageSize-l);let s=r.findIndex((t=>0===t));n=-1!==s,n?(o+=(new TextDecoder).decode(r.slice(0,s)),e.pos=i*this.pageSize+l+s+1):(o+=(new TextDecoder).decode(r),e.pos=i*this.pageSize+l+r.length),e.pages[i].pendingOps--,e.__statusPage("After Op done: ",i),a=e.pos,i++,e.pendingLoads.length>0&&setImmediate(e._triggerLoad.bind(e))}return o}}const ba=new Uint8Array(4),ya=new DataView(ba.buffer),va=new Uint8Array(8),Fa=new DataView(va.buffer);class xa{constructor(){this.pageSize=16384}_resizeIfNeeded(t){if(t>this.allocSize){const e=Math.max(this.allocSize+(1<<20),Math.floor(1.1*this.allocSize),t),a=new Uint8Array(e);a.set(this.o.data),this.o.data=a,this.allocSize=e}}async write(t,e){if(void 0===e&&(e=this.pos),this.readOnly)throw new Error("Writing a read only file");this._resizeIfNeeded(e+t.byteLength),this.o.data.set(t.slice(),e),e+t.byteLength>this.totalSize&&(this.totalSize=e+t.byteLength),this.pos=e+t.byteLength}async readToBuffer(t,e,a,i){if(void 0===i&&(i=this.pos),this.readOnly&&i+a>this.totalSize)throw new Error("Reading out of bounds");this._resizeIfNeeded(i+a);const n=new Uint8Array(this.o.data.buffer,this.o.data.byteOffset+i,a);t.set(n,e),this.pos=i+a}async read(t,e){const a=new Uint8Array(t);return await this.readToBuffer(a,0,t,e),a}close(){this.o.data.byteLength!=this.totalSize&&(this.o.data=this.o.data.slice(0,this.totalSize))}async discard(){}async writeULE32(t,e){ya.setUint32(0,t,!0),await this.write(ba,e)}async writeUBE32(t,e){ya.setUint32(0,t,!1),await this.write(ba,e)}async writeULE64(t,e){Fa.setUint32(0,4294967295&t,!0),Fa.setUint32(4,Math.floor(t/4294967296),!0),await this.write(va,e)}async readULE32(t){const e=await this.read(4,t);return new Uint32Array(e.buffer)[0]}async readUBE32(t){const e=await this.read(4,t);return new DataView(e.buffer).getUint32(0,!1)}async readULE64(t){const e=await this.read(8,t),a=new Uint32Array(e.buffer);return 4294967296*a[1]+a[0]}async readString(t){const e=this;let a=void 0===t?e.pos:t;if(a>this.totalSize){if(this.readOnly)throw new Error("Reading out of bounds");this._resizeIfNeeded(t)}const i=new Uint8Array(e.o.data.buffer,a,this.totalSize-a);let n=i.findIndex((t=>0===t)),o="";return-1!==n?(o=(new TextDecoder).decode(i.slice(0,n)),e.pos=a+n+1):e.pos=a,o}}const Ca=1<<22;const Sa=new Uint8Array(4),Ea=new DataView(Sa.buffer),Aa=new Uint8Array(8),Ba=new DataView(Aa.buffer);class Pa{constructor(){this.pageSize=16384}_resizeIfNeeded(t){if(t<=this.totalSize)return;if(this.readOnly)throw new Error("Reading out of file bounds");const e=Math.floor((t-1)/Ca)+1;for(let a=Math.max(this.o.data.length-1,0);a0;){const e=n+o>Ca?Ca-n:o,l=t.slice(t.byteLength-o,t.byteLength-o+e);new Uint8Array(a.o.data[i].buffer,n,e).set(l),o-=e,i++,n=0}this.pos=e+t.byteLength}async readToBuffer(t,e,a,i){const n=this;if(void 0===i&&(i=n.pos),this.readOnly&&i+a>this.totalSize)throw new Error("Reading out of bounds");this._resizeIfNeeded(i+a);let o=Math.floor(i/Ca),l=i%Ca,r=a;for(;r>0;){const i=l+r>Ca?Ca-l:r,s=new Uint8Array(n.o.data[o].buffer,l,i);t.set(s,e+a-r),r-=i,o++,l=0}this.pos=i+a}async read(t,e){const a=new Uint8Array(t);return await this.readToBuffer(a,0,t,e),a}close(){}async discard(){}async writeULE32(t,e){Ea.setUint32(0,t,!0),await this.write(Sa,e)}async writeUBE32(t,e){Ea.setUint32(0,t,!1),await this.write(Sa,e)}async writeULE64(t,e){Ba.setUint32(0,4294967295&t,!0),Ba.setUint32(4,Math.floor(t/4294967296),!0),await this.write(Aa,e)}async readULE32(t){const e=await this.read(4,t);return new Uint32Array(e.buffer)[0]}async readUBE32(t){const e=await this.read(4,t);return new DataView(e.buffer).getUint32(0,!1)}async readULE64(t){const e=await this.read(8,t),a=new Uint32Array(e.buffer);return 4294967296*a[1]+a[0]}async readString(t){const e=this;let a=void 0===t?e.pos:t;if(a>this.totalSize){if(this.readOnly)throw new Error("Reading out of bounds");this._resizeIfNeeded(t)}let i=!1,n="";for(;!i;){let t=Math.floor(a/Ca),o=a%Ca;if(void 0===e.o.data[t])throw new Error("ERROR");let l=Math.min(2048,e.o.data[t].length-o);const r=new Uint8Array(e.o.data[t].buffer,o,l);let s=r.findIndex((t=>0===t));i=-1!==s,i?(n+=(new TextDecoder).decode(r.slice(0,s)),e.pos=t*Ca+o+s+1):(n+=(new TextDecoder).decode(r),e.pos=t*Ca+o+r.length),a=e.pos}return n}}const{O_TRUNC:za,O_CREAT:Ia,O_RDWR:Ta,O_EXCL:Ga,O_RDONLY:Oa}=e.constants,qa=65536,Ua=8192;async function Ma(t,e,a){if("string"==typeof t&&(t={type:"file",fileName:t,cacheSize:e||qa,pageSize:a||Ua}),"file"==t.type)return await wa(t.fileName,za|Ia|Ta,t.cacheSize,t.pageSize);if("mem"==t.type)return function(t){const e=t.initialSize||1<<20,a=new xa;return a.o=t,a.o.data=new Uint8Array(e),a.allocSize=e,a.totalSize=0,a.readOnly=!1,a.pos=0,a}(t);if("bigMem"==t.type)return function(t){const e=t.initialSize||0,a=new Pa;a.o=t;const i=e?Math.floor((e-1)/Ca)+1:0;a.o.data=[];for(let t=0;ta)throw new Error("Version not supported");const s=await o.readULE32();let c=[];for(let t=0;t1)throw new Error(t.fileName+": Section Duplicated "+a);t.pos=e[a][0].p,t.readingSection=e[a][0]}async function Za(t,e){if(void 0===t.readingSection)throw new Error("Not reading a section");if(!e&&t.pos-t.readingSection.p!=t.readingSection.size)throw new Error("Invalid section size reading");delete t.readingSection}async function Ha(t,e,a,i){const n=new Uint8Array(a);vt.toRprLE(n,0,e,a),await t.write(n,i)}async function Qa(t,e,a){const i=await t.read(e,a);return vt.fromRprLE(i,0,e)}async function Ka(t,e,a,i,n){void 0===n&&(n=e[i][0].size);const o=t.pageSize;await Wa(t,e,i),await Da(a,i);for(let e=0;e=0)a=await wt(i);else{if(!(["BLS12381"].indexOf(n)>=0))throw new Error(`Curve not supported: ${t}`);a=await Lt(i)}return a}var oi=Object.freeze({__proto__:null,getCurveFromR:ai,getCurveFromQ:ii,getCurveFromName:ni});function li(t){if(!Number.isSafeInteger(t)||t<0)throw new Error("positive integer expected, got "+t)}function ri(t,...e){if(!((a=t)instanceof Uint8Array||ArrayBuffer.isView(a)&&"Uint8Array"===a.constructor.name))throw new Error("Uint8Array expected");var a;if(e.length>0&&!e.includes(t.length))throw new Error("Uint8Array expected of length "+e+", got length="+t.length)}function si(t,e=!0){if(t.destroyed)throw new Error("Hash instance has been destroyed");if(e&&t.finished)throw new Error("Hash#digest() has already been called")}function ci(t,e){ri(t);const a=e.outputLen;if(t.length68===new Uint8Array(new Uint32Array([287454020]).buffer)[0])();function fi(t){return t<<24&4278190080|t<<8&16711680|t>>>8&65280|t>>>24&255}const gi=ui?t=>t:t=>fi(t);function hi(t){for(let e=0;et(a).update(pi(e)).digest(),a=t({});return e.outputLen=a.outputLen,e.blockLen=a.blockLen,e.create=e=>t(e),e}const wi=new Uint8Array([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3,11,8,12,0,5,2,15,13,10,14,3,6,7,1,9,4,7,9,3,1,13,12,11,14,2,6,5,10,4,0,15,8,9,0,5,7,2,4,10,15,14,1,11,12,6,8,3,13,2,12,6,10,0,11,8,3,4,13,7,5,15,14,1,9,12,5,1,15,14,13,4,10,0,7,6,3,9,2,8,11,13,11,7,14,12,1,3,9,5,0,15,4,8,6,2,10,6,15,14,9,11,3,0,8,12,2,13,7,1,4,10,5,10,2,8,4,7,6,1,5,15,11,9,14,3,12,13,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3,11,8,12,0,5,2,15,13,10,14,3,6,7,1,9,4,7,9,3,1,13,12,11,14,2,6,5,10,4,0,15,8,9,0,5,7,2,4,10,15,14,1,11,12,6,8,3,13,2,12,6,10,0,11,8,3,4,13,7,5,15,14,1,9]);class Li extends _i{constructor(t,e,a={},i,n,o){if(super(),this.blockLen=t,this.outputLen=e,this.length=0,this.pos=0,this.finished=!1,this.destroyed=!1,li(t),li(e),li(i),e<0||e>i)throw new Error("outputLen bigger than keyLen");if(void 0!==a.key&&(a.key.length<1||a.key.length>i))throw new Error("key length must be undefined or 1.."+i);if(void 0!==a.salt&&a.salt.length!==n)throw new Error("salt must be undefined or "+n);if(void 0!==a.personalization&&a.personalization.length!==o)throw new Error("personalization must be undefined or "+o);this.buffer=new Uint8Array(t),this.buffer32=di(this.buffer)}update(t){si(this);const{blockLen:e,buffer:a,buffer32:i}=this,n=(t=pi(t)).length,o=t.byteOffset,l=t.buffer;for(let r=0;ri[e]=gi(t)))}digest(){const{buffer:t,outputLen:e}=this;this.digestInto(t);const a=t.slice(0,e);return this.destroy(),a}_cloneInto(t){const{buffer:e,length:a,finished:i,destroyed:n,outputLen:o,pos:l}=this;return t||(t=new this.constructor({dkLen:o})),t.set(...this.get()),t.length=a,t.finished=i,t.destroyed=n,t.outputLen=o,t.buffer.set(e),t.pos=l,t}}const bi=BigInt(2**32-1),yi=BigInt(32);function vi(t,e=!1){return e?{h:Number(t&bi),l:Number(t>>yi&bi)}:{h:0|Number(t>>yi&bi),l:0|Number(t&bi)}}function Fi(t,e=!1){let a=new Uint32Array(t.length),i=new Uint32Array(t.length);for(let n=0;nt<>>32-a,Ci=(t,e,a)=>e<>>32-a,Si=(t,e,a)=>e<>>64-a,Ei=(t,e,a)=>t<>>64-a;var Ai={fromBig:vi,split:Fi,toBig:(t,e)=>BigInt(t>>>0)<>>0),shrSH:(t,e,a)=>t>>>a,shrSL:(t,e,a)=>t<<32-a|e>>>a,rotrSH:(t,e,a)=>t>>>a|e<<32-a,rotrSL:(t,e,a)=>t<<32-a|e>>>a,rotrBH:(t,e,a)=>t<<64-a|e>>>a-32,rotrBL:(t,e,a)=>t>>>a-32|e<<64-a,rotr32H:(t,e)=>e,rotr32L:(t,e)=>t,rotlSH:xi,rotlSL:Ci,rotlBH:Si,rotlBL:Ei,add:function(t,e,a,i){const n=(e>>>0)+(i>>>0);return{h:t+a+(n/2**32|0)|0,l:0|n}},add3L:(t,e,a)=>(t>>>0)+(e>>>0)+(a>>>0),add3H:(t,e,a,i)=>e+a+i+(t/2**32|0)|0,add4L:(t,e,a,i)=>(t>>>0)+(e>>>0)+(a>>>0)+(i>>>0),add4H:(t,e,a,i,n)=>e+a+i+n+(t/2**32|0)|0,add5H:(t,e,a,i,n,o)=>e+a+i+n+o+(t/2**32|0)|0,add5L:(t,e,a,i,n)=>(t>>>0)+(e>>>0)+(a>>>0)+(i>>>0)+(n>>>0)};const Bi=new Uint32Array([4089235720,1779033703,2227873595,3144134277,4271175723,1013904242,1595750129,2773480762,2917565137,1359893119,725511199,2600822924,4215389547,528734635,327033209,1541459225]),Pi=new Uint32Array(32);function zi(t,e,a,i,n,o){const l=n[o],r=n[o+1];let s=Pi[2*t],c=Pi[2*t+1],d=Pi[2*e],u=Pi[2*e+1],f=Pi[2*a],g=Pi[2*a+1],h=Pi[2*i],p=Pi[2*i+1],_=Ai.add3L(s,d,l);c=Ai.add3H(_,c,u,r),s=0|_,({Dh:p,Dl:h}={Dh:p^c,Dl:h^s}),({Dh:p,Dl:h}={Dh:Ai.rotr32H(p,h),Dl:Ai.rotr32L(p,h)}),({h:g,l:f}=Ai.add(g,f,p,h)),({Bh:u,Bl:d}={Bh:u^g,Bl:d^f}),({Bh:u,Bl:d}={Bh:Ai.rotrSH(u,d,24),Bl:Ai.rotrSL(u,d,24)}),Pi[2*t]=s,Pi[2*t+1]=c,Pi[2*e]=d,Pi[2*e+1]=u,Pi[2*a]=f,Pi[2*a+1]=g,Pi[2*i]=h,Pi[2*i+1]=p}function Ii(t,e,a,i,n,o){const l=n[o],r=n[o+1];let s=Pi[2*t],c=Pi[2*t+1],d=Pi[2*e],u=Pi[2*e+1],f=Pi[2*a],g=Pi[2*a+1],h=Pi[2*i],p=Pi[2*i+1],_=Ai.add3L(s,d,l);c=Ai.add3H(_,c,u,r),s=0|_,({Dh:p,Dl:h}={Dh:p^c,Dl:h^s}),({Dh:p,Dl:h}={Dh:Ai.rotrSH(p,h,16),Dl:Ai.rotrSL(p,h,16)}),({h:g,l:f}=Ai.add(g,f,p,h)),({Bh:u,Bl:d}={Bh:u^g,Bl:d^f}),({Bh:u,Bl:d}={Bh:Ai.rotrBH(u,d,63),Bl:Ai.rotrBL(u,d,63)}),Pi[2*t]=s,Pi[2*t+1]=c,Pi[2*e]=d,Pi[2*e+1]=u,Pi[2*a]=f,Pi[2*a+1]=g,Pi[2*i]=h,Pi[2*i+1]=p}class Ti extends Li{constructor(t={}){super(128,void 0===t.dkLen?64:t.dkLen,t,64,16,16),this.v0l=0|Bi[0],this.v0h=0|Bi[1],this.v1l=0|Bi[2],this.v1h=0|Bi[3],this.v2l=0|Bi[4],this.v2h=0|Bi[5],this.v3l=0|Bi[6],this.v3h=0|Bi[7],this.v4l=0|Bi[8],this.v4h=0|Bi[9],this.v5l=0|Bi[10],this.v5h=0|Bi[11],this.v6l=0|Bi[12],this.v6h=0|Bi[13],this.v7l=0|Bi[14],this.v7h=0|Bi[15];const e=t.key?t.key.length:0;if(this.v0l^=this.outputLen|e<<8|65536|1<<24,t.salt){const e=di(pi(t.salt));this.v4l^=gi(e[0]),this.v4h^=gi(e[1]),this.v5l^=gi(e[2]),this.v5h^=gi(e[3])}if(t.personalization){const e=di(pi(t.personalization));this.v6l^=gi(e[0]),this.v6h^=gi(e[1]),this.v7l^=gi(e[2]),this.v7h^=gi(e[3])}if(t.key){const e=new Uint8Array(this.blockLen);e.set(pi(t.key)),this.update(e)}}get(){let{v0l:t,v0h:e,v1l:a,v1h:i,v2l:n,v2h:o,v3l:l,v3h:r,v4l:s,v4h:c,v5l:d,v5h:u,v6l:f,v6h:g,v7l:h,v7h:p}=this;return[t,e,a,i,n,o,l,r,s,c,d,u,f,g,h,p]}set(t,e,a,i,n,o,l,r,s,c,d,u,f,g,h,p){this.v0l=0|t,this.v0h=0|e,this.v1l=0|a,this.v1h=0|i,this.v2l=0|n,this.v2h=0|o,this.v3l=0|l,this.v3h=0|r,this.v4l=0|s,this.v4h=0|c,this.v5l=0|d,this.v5h=0|u,this.v6l=0|f,this.v6h=0|g,this.v7l=0|h,this.v7h=0|p}compress(t,e,a){this.get().forEach(((t,e)=>Pi[e]=t)),Pi.set(Bi,16);let{h:i,l:n}=Ai.fromBig(BigInt(this.length));Pi[24]=Bi[8]^n,Pi[25]=Bi[9]^i,a&&(Pi[28]=~Pi[28],Pi[29]=~Pi[29]);let o=0;const l=wi;for(let a=0;a<12;a++)zi(0,4,8,12,t,e+2*l[o++]),Ii(0,4,8,12,t,e+2*l[o++]),zi(1,5,9,13,t,e+2*l[o++]),Ii(1,5,9,13,t,e+2*l[o++]),zi(2,6,10,14,t,e+2*l[o++]),Ii(2,6,10,14,t,e+2*l[o++]),zi(3,7,11,15,t,e+2*l[o++]),Ii(3,7,11,15,t,e+2*l[o++]),zi(0,5,10,15,t,e+2*l[o++]),Ii(0,5,10,15,t,e+2*l[o++]),zi(1,6,11,12,t,e+2*l[o++]),Ii(1,6,11,12,t,e+2*l[o++]),zi(2,7,8,13,t,e+2*l[o++]),Ii(2,7,8,13,t,e+2*l[o++]),zi(3,4,9,14,t,e+2*l[o++]),Ii(3,4,9,14,t,e+2*l[o++]);this.v0l^=Pi[0]^Pi[16],this.v0h^=Pi[1]^Pi[17],this.v1l^=Pi[2]^Pi[18],this.v1h^=Pi[3]^Pi[19],this.v2l^=Pi[4]^Pi[20],this.v2h^=Pi[5]^Pi[21],this.v3l^=Pi[6]^Pi[22],this.v3h^=Pi[7]^Pi[23],this.v4l^=Pi[8]^Pi[24],this.v4h^=Pi[9]^Pi[25],this.v5l^=Pi[10]^Pi[26],this.v5h^=Pi[11]^Pi[27],this.v6l^=Pi[12]^Pi[28],this.v6h^=Pi[13]^Pi[29],this.v7l^=Pi[14]^Pi[30],this.v7h^=Pi[15]^Pi[31],Pi.fill(0)}destroy(){this.destroyed=!0,this.buffer32.fill(0),this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)}}const Gi=mi((t=>new Ti(t)));function Oi(t){return(0!=(4294901760&t)?(t&=4294901760,16):0)|(0!=(4278255360&t)?(t&=4278255360,8):0)|(0!=(4042322160&t)?(t&=4042322160,4):0)|(0!=(3435973836&t)?(t&=3435973836,2):0)|0!=(2863311530&t)}function qi(t,e){const a=new DataView(t.buffer,t.byteOffset,t.byteLength);let i="";for(let t=0;t<4;t++){t>0&&(i+="\n"),i+="\t\t";for(let e=0;e<4;e++)e>0&&(i+=" "),i+=a.getUint32(16*t+4*e).toString(16).padStart(8,"0")}return e&&(i=e+"\n"+i),i}function Ui(t,e){if(t.byteLength!=e.byteLength)return!1;for(var a=new Int8Array(t),i=new Int8Array(e),n=0;n!=t.byteLength;n++)if(a[n]!=i[n])return!1;return!0}function Mi(t){const e=t.subarray(0,128),a=di(t.subarray(128)),i=Gi.create({dkLen:64});i.buffer.set(e),i.v0l=0|a[0],i.v0h=0|a[1],i.v1l=0|a[2],i.v1h=0|a[3],i.v2l=0|a[4],i.v2h=0|a[5],i.v3l=0|a[6],i.v3h=0|a[7],i.v4l=0|a[8],i.v4h=0|a[9],i.v5l=0|a[10],i.v5h=0|a[11],i.v6l=0|a[12],i.v6h=0|a[13],i.v7l=0|a[14],i.v7h=0|a[15];const n=2**32,o=a[16]+a[17]*n,l=a[18]+a[19]*n;return i.length=o+l,i.pos=l,i}function ki(t){const e=new Uint8Array(216),a=di(e.subarray(128));return e.set(t.buffer),a[0]=t.v0l,a[1]=t.v0h,a[2]=t.v1l,a[3]=t.v1h,a[4]=t.v2l,a[5]=t.v2h,a[6]=t.v3l,a[7]=t.v3h,a[8]=t.v4l,a[9]=t.v4h,a[10]=t.v5l,a[11]=t.v5h,a[12]=t.v6l,a[13]=t.v6h,a[14]=t.v7l,a[15]=t.v7h,a[18]=t.pos,a[16]=t.length-t.pos,e}async function Ri(t,e,a,i,n){if(t.G1.isZero(e))return!1;if(t.G1.isZero(a))return!1;if(t.G2.isZero(i))return!1;if(t.G2.isZero(n))return!1;return await t.pairingEq(e,n,t.G1.neg(a),i)}function Ni(t){let e=new Uint8Array(t);return globalThis.crypto.getRandomValues(e),e}async function ji(t){{const e=await globalThis.crypto.subtle.digest("SHA-256",t.buffer);return new Uint8Array(e)}}function Di(t,e){return new DataView(t.buffer).getUint32(e,!1)}async function Vi(t){for(;!t;)t=await window.prompt("Enter a random text. (Entropy): ","");const e=Gi.create(64);e.update(Ni(64));const a=new TextEncoder;e.update(a.encode(t));const i=e.digest(),n=[];for(let t=0;t<8;t++)n[t]=Di(i,4*t);return new M(n)}async function Wi(t,e){let a,i;e<32?(a=1<>>0,i=1):(a=4294967296,i=1<>>0);let n=t;for(let t=0;t{a[i]=Qi(t,e[i])})),a}return"bigint"==typeof e||void 0!==e.eq?e.toString(10):e}const Ki=1,Xi=2,Yi=10,Ji=2,$i=3,tn=4,en=5,an=6,nn=7,on=8,ln=9,rn=10,sn=11,cn=12,dn=13,un=14,fn=15,gn=16,hn=17;async function pn(t,e){await Da(t,1),await t.writeULE32(1),await Va(t);const a=await ii(e.q);await Da(t,2);const i=a.q,n=8*(Math.floor((vt.bitLength(i)-1)/64)+1),o=a.r,l=8*(Math.floor((vt.bitLength(o)-1)/64)+1);await t.writeULE32(n),await Ha(t,i,n),await t.writeULE32(l),await Ha(t,o,l),await t.writeULE32(e.nVars),await t.writeULE32(e.nPublic),await t.writeULE32(e.domainSize),await _n(t,a,e.vk_alpha_1),await _n(t,a,e.vk_beta_1),await mn(t,a,e.vk_beta_2),await mn(t,a,e.vk_gamma_2),await _n(t,a,e.vk_delta_1),await mn(t,a,e.vk_delta_2),await Va(t)}async function _n(t,e,a){const i=new Uint8Array(2*e.G1.F.n8);e.G1.toRprLEM(i,0,a),await t.write(i)}async function mn(t,e,a){const i=new Uint8Array(2*e.G2.F.n8);e.G2.toRprLEM(i,0,a),await t.write(i)}async function wn(t,e,a){const i=await t.read(2*e.G1.F.n8),n=e.G1.fromRprLEM(i,0);return a?e.G1.toObject(n):n}async function Ln(t,e,a){const i=await t.read(2*e.G2.F.n8),n=e.G2.fromRprLEM(i,0);return a?e.G2.toObject(n):n}async function bn(t,e,a,i){await Wa(t,e,1);const n=await t.readULE32();if(await Za(t),n===Ki)return await async function(t,e,a,i){const n={protocol:"groth16"};await Wa(t,e,2);const o=await t.readULE32();n.n8q=o,n.q=await Qa(t,o);const l=await t.readULE32();return n.n8r=l,n.r=await Qa(t,l),n.curve=await ii(n.q,i),n.nVars=await t.readULE32(),n.nPublic=await t.readULE32(),n.domainSize=await t.readULE32(),n.power=Oi(n.domainSize),n.vk_alpha_1=await wn(t,n.curve,a),n.vk_beta_1=await wn(t,n.curve,a),n.vk_beta_2=await Ln(t,n.curve,a),n.vk_gamma_2=await Ln(t,n.curve,a),n.vk_delta_1=await wn(t,n.curve,a),n.vk_delta_2=await Ln(t,n.curve,a),await Za(t),n}(t,e,a,i);if(n===Xi)return await async function(t,e,a,i){const n={protocol:"plonk"};await Wa(t,e,2);const o=await t.readULE32();n.n8q=o,n.q=await Qa(t,o);const l=await t.readULE32();return n.n8r=l,n.r=await Qa(t,l),n.curve=await ii(n.q,i),n.nVars=await t.readULE32(),n.nPublic=await t.readULE32(),n.domainSize=await t.readULE32(),n.power=Oi(n.domainSize),n.nAdditions=await t.readULE32(),n.nConstraints=await t.readULE32(),n.k1=await t.read(l),n.k2=await t.read(l),n.Qm=await wn(t,n.curve,a),n.Ql=await wn(t,n.curve,a),n.Qr=await wn(t,n.curve,a),n.Qo=await wn(t,n.curve,a),n.Qc=await wn(t,n.curve,a),n.S1=await wn(t,n.curve,a),n.S2=await wn(t,n.curve,a),n.S3=await wn(t,n.curve,a),n.X_2=await Ln(t,n.curve,a),await Za(t),n}(t,e,a,i);if(n===Yi)return await async function(t,e,a,i){const n={protocol:"fflonk"};n.protocolId=Yi,await Wa(t,e,Ji);const o=await t.readULE32();n.n8q=o,n.q=await Qa(t,o),n.curve=await ii(n.q,i);const l=await t.readULE32();return n.n8r=l,n.r=await Qa(t,l),n.nVars=await t.readULE32(),n.nPublic=await t.readULE32(),n.domainSize=await t.readULE32(),n.power=Oi(n.domainSize),n.nAdditions=await t.readULE32(),n.nConstraints=await t.readULE32(),n.k1=await t.read(l),n.k2=await t.read(l),n.w3=await t.read(l),n.w4=await t.read(l),n.w8=await t.read(l),n.wr=await t.read(l),n.X_2=await Ln(t,n.curve,a),n.C0=await wn(t,n.curve,a),await Za(t),n}(t,e,a,i);throw new Error("Protocol not supported: ")}async function yn(t,e,a){const i={delta:{}};i.deltaAfter=await wn(t,e,a),i.delta.g1_s=await wn(t,e,a),i.delta.g1_sx=await wn(t,e,a),i.delta.g2_spx=await Ln(t,e,a),i.transcript=await t.read(64),i.type=await t.readULE32();const n=await t.readULE32(),o=t.pos;let l=0;for(;t.pos-o0){const e=new Uint8Array(i);await t.writeULE32(e.byteLength),await t.write(e)}else await t.writeULE32(0)}async function xn(t,e,a){await Da(t,10),await t.write(a.csHash),await t.writeULE32(a.contributions.length);for(let i=0;i{Pn(t)}),e)}(a,50);const{fd:n,sections:o}=await Na(e,"wtns",2),l=await En(n,o),{fd:r,sections:s}=await Na(t,"zkey",2),c=await bn(r,s,void 0,i);if("groth16"!=c.protocol)throw new Error("zkey file is not groth16");if(!vt.eq(c.r,l.q))throw new Error("Curve of the witness does not match the curve of the proving key");if(l.nWitness!=c.nVars)throw new Error(`Invalid witness length. Circuit: ${c.nVars}, witness: ${l.nWitness}`);const d=c.curve,u=d.Fr,f=d.G1,g=d.G2,h=Oi(c.domainSize);a&&a.debug("Reading Wtns");const p=await Xa(n,o,2);let _,m,w,L=async function(){let t,e,n;await async function(){a&&a.debug("Reading Coeffs"),console.time("buildABC_outer");const o=await Xa(r,s,4);a&&a.debug("Building ABC"),(i=i||{})&&"wasm"===i.buildABC?[t,e,n]=await async function(t,e,a,i,n){let o=t.tm.concurrency;const l=12+e.n8r;let r;if(i instanceof et){const t=[],e=i.buffers[0].length;for(let e=0;e65536;)o*=2,s=Math.floor(e.domainSize/o);console.log("@@@ new elementsPerChunk",s);const c=[],d=[];for(let t=0;t1){const e=[];for(let a=0;at?a=i-1:n1){const e=[];for(let a=0;at?a=i-1:n{e.pendingLoads.push({page:t,resolve:a,reject:i})}));return e.__statusPage("After Load request: ",t),a}__statusPage(t,e){const a=[],i=this;if(!i.logHistory)return;a.push("=="+t+" "+e);let n="";for(let t=0;t "+e.history[t][a][i])}_triggerLoad(){const t=this;if(t.reading)return;if(0==t.pendingLoads.length)return;const e=Object.keys(t.pages),a=[];for(let i=0;i0&&(void 0!==t.pages[t.pendingLoads[0].page]||i>0||a.length>0);){const e=t.pendingLoads.shift();if(void 0!==t.pages[e.page]){t.pages[e.page].pendingOps++;const i=a.indexOf(e.page);i>=0&&a.splice(i,1),t.pages[e.page].loading?t.pages[e.page].loading.push(e):e.resolve(),t.__statusPage("After Load (cached): ",e.page)}else{if(i)i--;else{const e=a.shift();t.__statusPage("Before Unload: ",e),t.avBuffs.unshift(t.pages[e]),delete t.pages[e],t.__statusPage("After Unload: ",e)}e.page>=t.totalPages?(t.pages[e.page]=o(),e.resolve(),t.__statusPage("After Load (new): ",e.page)):(t.reading=!0,t.pages[e.page]=o(),t.pages[e.page].loading=[e],n.push(t.fd.read(t.pages[e.page].buff,0,t.pageSize,e.page*t.pageSize).then((a=>{t.pages[e.page].size=a.bytesRead;const i=t.pages[e.page].loading;delete t.pages[e.page].loading;for(let t=0;t{e.reject(t)}))),t.__statusPage("After Load (loading): ",e.page))}}function o(){if(t.avBuffs.length>0){const e=t.avBuffs.shift();return e.dirty=!1,e.pendingOps=1,e.size=0,e}return{dirty:!1,buff:new Uint8Array(t.pageSize),pendingOps:1,size:0}}Promise.all(n).then((()=>{t.reading=!1,t.pendingLoads.length>0&&setImmediate(t._triggerLoad.bind(t)),t._tryClose()}))}_triggerWrite(){const t=this;if(t.writing)return;const e=Object.keys(t.pages),a=[];for(let i=0;i{n.writing=!1}),(e=>{console.log("ERROR Writing: "+e),t.error=e,t._tryClose()}))))}t.writing&&Promise.all(a).then((()=>{t.writing=!1,setImmediate(t._triggerWrite.bind(t)),t._tryClose(),t.pendingLoads.length>0&&setImmediate(t._triggerLoad.bind(t))}))}_getDirtyPage(){for(let t in this.pages)if(this.pages[t].dirty)return t;return-1}async write(t,e){if(0==t.byteLength)return;const a=this;if(void 0===e&&(e=a.pos),a.pos=e+t.byteLength,a.totalSize0;){await o[l-i];const e=r+s>a.pageSize?a.pageSize-r:s,n=t.slice(t.byteLength-s,t.byteLength-s+e);new Uint8Array(a.pages[l].buff.buffer,r,e).set(n),a.pages[l].dirty=!0,a.pages[l].pendingOps--,a.pages[l].size=Math.max(r+e,a.pages[l].size),l>=a.totalPages&&(a.totalPages=l+1),s-=e,l++,r=0,a.writing||setImmediate(a._triggerWrite.bind(a))}}async read(t,e){let a=new Uint8Array(t);return await this.readToBuffer(a,0,t,e),a}async readToBuffer(t,e,a,i){if(0==a)return;const n=this;if(a>n.pageSize*n.maxPagesLoaded*.8){const t=Math.floor(1.1*a);this.maxPagesLoaded=Math.floor(t/n.pageSize)+1}if(void 0===i&&(i=n.pos),n.pos=i+a,n.pendingClose)throw new Error("Reading a closing file");const o=Math.floor(i/n.pageSize),l=Math.floor((i+a-1)/n.pageSize),r=[];for(let t=o;t<=l;t++)r.push(n._loadPage(t));n._triggerLoad();let s=o,c=i%n.pageSize,d=i+a>n.totalSize?a-(i+a-n.totalSize):a;for(;d>0;){await r[s-o],n.__statusPage("After Await (read): ",s);const i=c+d>n.pageSize?n.pageSize-c:d,l=new Uint8Array(n.pages[s].buff.buffer,n.pages[s].buff.byteOffset+c,i);t.set(l,e+a-d),n.pages[s].pendingOps--,n.__statusPage("After Op done: ",s),d-=i,s++,c=0,n.pendingLoads.length>0&&setImmediate(n._triggerLoad.bind(n))}this.pos=i+a}_tryClose(){const t=this;if(!t.pendingClose)return;t.error&&t.pendingCloseReject(t.error);t._getDirtyPage()>=0||t.writing||t.reading||t.pendingLoads.length>0||t.pendingClose()}close(){const t=this;if(t.pendingClose)throw new Error("Closing the file twice");return new Promise(((e,a)=>{t.pendingClose=e,t.pendingCloseReject=a,t._tryClose()})).then((()=>{t.fd.close()}),(e=>{throw t.fd.close(),e}))}async discard(){await this.close(),await ma.promises.unlink(this.fileName)}async writeULE32(t,e){const a=new Uint8Array(4);new DataView(a.buffer).setUint32(0,t,!0),await this.write(a,e)}async writeUBE32(t,e){const a=new Uint8Array(4);new DataView(a.buffer).setUint32(0,t,!1),await this.write(a,e)}async writeULE64(t,e){const a=new Uint8Array(8),i=new DataView(a.buffer);i.setUint32(0,4294967295&t,!0),i.setUint32(4,Math.floor(t/4294967296),!0),await this.write(a,e)}async readULE32(t){const e=await this.read(4,t);return new Uint32Array(e.buffer)[0]}async readUBE32(t){const e=await this.read(4,t);return new DataView(e.buffer).getUint32(0,!1)}async readULE64(t){const e=await this.read(8,t),a=new Uint32Array(e.buffer);return 4294967296*a[1]+a[0]}async readString(t){const e=this;if(e.pendingClose)throw new Error("Reading a closing file");let a=void 0===t?e.pos:t,i=Math.floor(a/e.pageSize),n=!1,o="";for(;!n;){let t=e._loadPage(i);e._triggerLoad(),await t,e.__statusPage("After Await (read): ",i);let l=a%e.pageSize;const r=new Uint8Array(e.pages[i].buff.buffer,e.pages[i].buff.byteOffset+l,e.pageSize-l);let s=r.findIndex((t=>0===t));n=-1!==s,n?(o+=(new TextDecoder).decode(r.slice(0,s)),e.pos=i*this.pageSize+l+s+1):(o+=(new TextDecoder).decode(r),e.pos=i*this.pageSize+l+r.length),e.pages[i].pendingOps--,e.__statusPage("After Op done: ",i),a=e.pos,i++,e.pendingLoads.length>0&&setImmediate(e._triggerLoad.bind(e))}return o}}const Tn=new Uint8Array(4),Gn=new DataView(Tn.buffer),On=new Uint8Array(8),qn=new DataView(On.buffer);class Un{constructor(){this.pageSize=16384}_resizeIfNeeded(t){if(t>this.allocSize){const e=Math.max(this.allocSize+(1<<20),Math.floor(1.1*this.allocSize),t),a=new Uint8Array(e);a.set(this.o.data),this.o.data=a,this.allocSize=e}}async write(t,e){if(void 0===e&&(e=this.pos),this.readOnly)throw new Error("Writing a read only file");this._resizeIfNeeded(e+t.byteLength),this.o.data.set(t.slice(),e),e+t.byteLength>this.totalSize&&(this.totalSize=e+t.byteLength),this.pos=e+t.byteLength}async readToBuffer(t,e,a,i){if(void 0===i&&(i=this.pos),this.readOnly&&i+a>this.totalSize)throw new Error("Reading out of bounds");this._resizeIfNeeded(i+a);const n=new Uint8Array(this.o.data.buffer,this.o.data.byteOffset+i,a);t.set(n,e),this.pos=i+a}async read(t,e){const a=new Uint8Array(t);return await this.readToBuffer(a,0,t,e),a}close(){this.o.data.byteLength!=this.totalSize&&(this.o.data=this.o.data.slice(0,this.totalSize))}async discard(){}async writeULE32(t,e){Gn.setUint32(0,t,!0),await this.write(Tn,e)}async writeUBE32(t,e){Gn.setUint32(0,t,!1),await this.write(Tn,e)}async writeULE64(t,e){qn.setUint32(0,4294967295&t,!0),qn.setUint32(4,Math.floor(t/4294967296),!0),await this.write(On,e)}async readULE32(t){const e=await this.read(4,t);return new Uint32Array(e.buffer)[0]}async readUBE32(t){const e=await this.read(4,t);return new DataView(e.buffer).getUint32(0,!1)}async readULE64(t){const e=await this.read(8,t),a=new Uint32Array(e.buffer);return 4294967296*a[1]+a[0]}async readString(t){const e=this;let a=void 0===t?e.pos:t;if(a>this.totalSize){if(this.readOnly)throw new Error("Reading out of bounds");this._resizeIfNeeded(t)}const i=new Uint8Array(e.o.data.buffer,a,this.totalSize-a);let n=i.findIndex((t=>0===t)),o="";return-1!==n?(o=(new TextDecoder).decode(i.slice(0,n)),e.pos=a+n+1):e.pos=a,o}}const Mn=1<<22;const kn=new Uint8Array(4),Rn=new DataView(kn.buffer),Nn=new Uint8Array(8),jn=new DataView(Nn.buffer);class Dn{constructor(){this.pageSize=16384}_resizeIfNeeded(t){if(t<=this.totalSize)return;if(this.readOnly)throw new Error("Reading out of file bounds");const e=Math.floor((t-1)/Mn)+1;for(let a=Math.max(this.o.data.length-1,0);a0;){const e=n+o>Mn?Mn-n:o,l=t.slice(t.byteLength-o,t.byteLength-o+e);new Uint8Array(a.o.data[i].buffer,n,e).set(l),o-=e,i++,n=0}this.pos=e+t.byteLength}async readToBuffer(t,e,a,i){const n=this;if(void 0===i&&(i=n.pos),this.readOnly&&i+a>this.totalSize)throw new Error("Reading out of bounds");this._resizeIfNeeded(i+a);let o=Math.floor(i/Mn),l=i%Mn,r=a;for(;r>0;){const i=l+r>Mn?Mn-l:r,s=new Uint8Array(n.o.data[o].buffer,l,i);t.set(s,e+a-r),r-=i,o++,l=0}this.pos=i+a}async read(t,e){const a=new Uint8Array(t);return await this.readToBuffer(a,0,t,e),a}close(){}async discard(){}async writeULE32(t,e){Rn.setUint32(0,t,!0),await this.write(kn,e)}async writeUBE32(t,e){Rn.setUint32(0,t,!1),await this.write(kn,e)}async writeULE64(t,e){jn.setUint32(0,4294967295&t,!0),jn.setUint32(4,Math.floor(t/4294967296),!0),await this.write(Nn,e)}async readULE32(t){const e=await this.read(4,t);return new Uint32Array(e.buffer)[0]}async readUBE32(t){const e=await this.read(4,t);return new DataView(e.buffer).getUint32(0,!1)}async readULE64(t){const e=await this.read(8,t),a=new Uint32Array(e.buffer);return 4294967296*a[1]+a[0]}async readString(t){const e=this;let a=void 0===t?e.pos:t;if(a>this.totalSize){if(this.readOnly)throw new Error("Reading out of bounds");this._resizeIfNeeded(t)}let i=!1,n="";for(;!i;){let t=Math.floor(a/Mn),o=a%Mn;if(void 0===e.o.data[t])throw new Error("ERROR");let l=Math.min(2048,e.o.data[t].length-o);const r=new Uint8Array(e.o.data[t].buffer,o,l);let s=r.findIndex((t=>0===t));i=-1!==s,i?(n+=(new TextDecoder).decode(r.slice(0,s)),e.pos=t*Mn+o+s+1):(n+=(new TextDecoder).decode(r),e.pos=t*Mn+o+r.length),a=e.pos}return n}}const Vn=512,Wn=64,Zn=2,Hn=0,Qn=65536,Kn=8192;async function Xn(t,e,a){if("string"==typeof t&&(t={type:"file",fileName:t,cacheSize:e||Qn,pageSize:a||Kn}),"file"==t.type)return await zn(t.fileName,Vn|Wn|Zn,t.cacheSize,t.pageSize);if("mem"==t.type)return function(t){const e=t.initialSize||1<<20,a=new Un;return a.o=t,a.o.data=new Uint8Array(e),a.allocSize=e,a.totalSize=0,a.readOnly=!1,a.pos=0,a}(t);if("bigMem"==t.type)return function(t){const e=t.initialSize||0,a=new Dn;a.o=t;const i=e?Math.floor((e-1)/Mn)+1:0;a.o.data=[];for(let t=0;t0;)a.unshift(0),t--}return a}async function ao(t,e){let a,i,n;e=e||{};let o=1,l=0,r=0,s=!1;if(t instanceof WebAssembly.Instance)a=t,s=!0;else{let s=32767;if(e.memorySize&&(s=parseInt(e.memorySize),s<0))throw new Error("Invalid memory size");let c=!1;for(;!c;)try{n=new WebAssembly.Memory({initial:s}),c=!0}catch(t){if(s<=1)throw t;console.warn("Could not allocate "+1024*s*64+" bytes. This may cause severe instability. Trying with "+1024*s*64/2+" bytes"),s=Math.floor(s/2)}const f=await WebAssembly.compile(t);let g="",h="";a=await WebAssembly.instantiate(f,{env:{memory:n},runtime:{printDebug:function(t){console.log("printDebug:",t)},exceptionHandler:function(t){let e;throw e=1===t?"Signal not found. ":2===t?"Too many signals set. ":3===t?"Signal already set. ":4===t?"Assert Failed. ":5===t?"Not enough memory. ":6===t?"Input signal array access exceeds the size. ":"Unknown error. ",console.error("ERROR: ",t,g),new Error(e+g)},printErrorMessage:function(){g+=d()+"\n"},writeBufferMessage:function(){const t=d();"\n"===t?(console.log(h),h=""):(""!==h&&(h+=" "),h+=t)},showSharedRWMemory:function(){const t=a.exports.getFieldNumLen32(),e=new Uint32Array(t);for(let i=0;i=2&&(l>=1||r>=7)){""!==h&&(h+=" ");const t=vt.fromArray(e,4294967296).toString();h+=t}else console.log(vt.fromArray(e,4294967296))},error:function(t,a,n,o,l,r){let s;throw s=7===t?u(a)+" "+i.getFr(o).toString()+" != "+i.getFr(l).toString()+" "+u(r):9===t?u(a)+" "+i.getFr(o).toString()+" "+u(l):5===t&&e.sym?u(a)+" "+e.sym.labelIdx2Name[l]:u(a)+" "+n+" "+o+" "+l+" "+r,console.log("ERROR: ",t,s),new Error(s)},log:function(t){console.log(i.getFr(t).toString())},logGetSignal:function(t,a){e.logGetSignal&&e.logGetSignal(t,i.getFr(a))},logSetSignal:function(t,a){e.logSetSignal&&e.logSetSignal(t,i.getFr(a))},logStartComponent:function(t){e.logStartComponent&&e.logStartComponent(t)},logFinishComponent:function(t){e.logFinishComponent&&e.logFinishComponent(t)}}})}"function"==typeof a.exports.getVersion&&(o=a.exports.getVersion()),"function"==typeof a.exports.getMinorVersion&&(l=a.exports.getMinorVersion()),"function"==typeof a.exports.getPatchVersion&&(r=a.exports.getPatchVersion());const c=e&&(e.sanityCheck||e.logGetSignal||e.logSetSignal||e.logStartComponent||e.logFinishComponent);if(2===o)i=new no(a,c);else{if(1!==o)throw new Error(`Unsupported circom version: ${o}`);if(s)throw new Error("Loading code from WebAssembly instance is not supported for circom version 1");i=new io(n,a,c)}return i;function d(){let t="",e=a.exports.getMessageChar();for(;0!==e;)t+=String.fromCharCode(e),e=a.exports.getMessageChar();return t}function u(t){const e=new Uint8Array(n.buffer),a=[];for(let i=0;e[t+i]>0;i++)a.push(e[t+i]);return String.fromCharCode.apply(null,a)}}class io{constructor(t,e,a){this.memory=t,this.i32=new Uint32Array(t.buffer),this.instance=e,this.n32=(this.instance.exports.getFrLen()>>2)-2;const i=this.instance.exports.getPRawPrime(),n=new Array(this.n32);for(let t=0;t>2)+t];this.prime=vt.fromArray(n,4294967296),this.Fr=new W(this.prime),this.mask32=vt.fromString("FFFFFFFF",16),this.NVars=this.instance.exports.getNVars(),this.n64=Math.floor((this.Fr.bitLength-1)/64)+1,this.R=this.Fr.e(vt.shiftLeft(1,64*this.n64)),this.RInv=this.Fr.inv(this.R),this.sanityCheck=a}circom_version(){return 1}async _doCalculateWitness(t,e){this.instance.exports.init(this.sanityCheck||e?1:0);const a=this.allocInt(),i=this.allocFr();Object.keys(t).forEach((e=>{const n=to(e),o=parseInt(n.slice(0,8),16),l=parseInt(n.slice(8,16),16);try{this.instance.exports.getSignalOffset32(a,0,o,l)}catch(t){throw new Error(`Signal ${e} is not an input of the circuit.`)}const r=this.getInt(a),s=Jn(t[e]);for(let t=0;t>2]}setInt(t,e){this.i32[t>>2]=e}getFr(t){const e=this,a=t>>2;if(2147483648&e.i32[a+1]){const t=new Array(e.n32);for(let i=0;i>2]=n,void(a.i32[1+(t>>2)]=0)}a.i32[t>>2]=0,a.i32[1+(t>>2)]=2147483648;const o=vt.toArray(e,4294967296);for(let e=0;e>2)+e]=i>=0?o[i]:0}}}class no{constructor(t,e){this.instance=t,this.version=this.instance.exports.getVersion(),this.n32=this.instance.exports.getFieldNumLen32(),this.instance.exports.getRawPrime();const a=new Uint32Array(this.n32);for(let t=0;t{const a=to(e),n=parseInt(a.slice(0,8),16),o=parseInt(a.slice(8,16),16),l=Jn(t[e]);if("function"==typeof this.instance.exports.getInputSignalSize){let t=this.instance.exports.getInputSignalSize(n,o);if(t<0)throw new Error(`Signal ${e} not found\n`);if(l.lengtht)throw new Error(`Too many values for input signal ${e}\n`)}for(let t=0;t1)throw new Error(t.fileName+": File has more than one header");t.pos=e[1][0].p;const a=await t.readULE32(),i=await t.read(a),n=vt.fromRprLE(i),o=await ii(n);if(8*o.F1.n64!=a)throw new Error(t.fileName+": Invalid size");const l=await t.readULE32(),r=await t.readULE32();if(t.pos-e[1][0].p!=e[1][0].size)throw new Error("Invalid PTau header size");return{curve:o,power:l,ceremonyPower:r}}function bo(t,e,a,i){const n={tau:{},alpha:{},beta:{}};return n.tau.g1_s=o(),n.tau.g1_sx=o(),n.alpha.g1_s=o(),n.alpha.g1_sx=o(),n.beta.g1_s=o(),n.beta.g1_sx=o(),n.tau.g2_spx=l(),n.alpha.g2_spx=l(),n.beta.g2_spx=l(),n;function o(){let n;return n=i?a.G1.fromRprLEM(t,e):a.G1.fromRprUncompressed(t,e),e+=2*a.G1.F.n8,n}function l(){let n;return n=i?a.G2.fromRprLEM(t,e):a.G2.fromRprUncompressed(t,e),e+=2*a.G2.F.n8,n}}function yo(t,e,a,i,n){async function o(i){n?a.G1.toRprLEM(t,e,i):a.G1.toRprUncompressed(t,e,i),e+=2*a.F1.n8}async function l(i){n?a.G2.toRprLEM(t,e,i):a.G2.toRprUncompressed(t,e,i),e+=2*a.F2.n8}return o(i.tau.g1_s),o(i.tau.g1_sx),o(i.alpha.g1_s),o(i.alpha.g1_sx),o(i.beta.g1_s),o(i.beta.g1_sx),l(i.tau.g2_spx),l(i.alpha.g2_spx),l(i.beta.g2_spx),t}async function vo(t,e){const a={};a.tauG1=await s(),a.tauG2=await c(),a.alphaG1=await s(),a.betaG1=await s(),a.betaG2=await c(),a.key=await async function(t,e,a){return bo(await t.read(2*e.F1.n8*6+2*e.F2.n8*3),0,e,a)}(t,e,!0),a.partialHash=await t.read(216),a.nextChallenge=await t.read(64),a.type=await t.readULE32();const i=new Uint8Array(2*e.G1.F.n8*6+2*e.G2.F.n8*3);yo(i,0,e,a.key,!1);const n=Mi(a.partialHash);n.update(i),a.responseHash=n.digest();const o=await t.readULE32(),l=t.pos;let r=0;for(;t.pos-l1)throw new Error(t.fileName+": File has more than one contributions section");t.pos=a[7][0].p;const i=await t.readULE32(),n=[];for(let a=0;a0){const e=new Uint8Array(o);await t.writeULE32(e.byteLength),await t.write(e)}else await t.writeULE32(0);async function l(a){e.G1.toRprLEM(i,0,a),await t.write(i)}async function r(a){e.G2.toRprLEM(n,0,a),await t.write(n)}}async function Co(t,e,a){await t.writeULE32(7);const i=t.pos;await t.writeULE64(0),await t.writeULE32(a.length);for(let i=0;i0?u[u.length-1].nextChallenge:So(c,d,o);const L=await ja(a,"ptau",1,n?7:2);await wo(L,c,d);const b=await m.read(64);if(Ui(l,w)&&(w=b,u[u.length-1].nextChallenge=w),!Ui(b,w))throw new Error("Wrong contribution. This contribution is not based on the previous hash");const y=Gi.create({dkLen:64});y.update(b);const v=[];let F;F=await S(m,L,"G1",2,2**d*2-1,[1],"tauG1"),f.tauG1=F[0],F=await S(m,L,"G2",3,2**d,[1],"tauG2"),f.tauG2=F[0],F=await S(m,L,"G1",4,2**d,[0],"alphaG1"),f.alphaG1=F[0],F=await S(m,L,"G1",5,2**d,[0],"betaG1"),f.betaG1=F[0],F=await S(m,L,"G2",6,1,[0],"betaG2"),f.betaG2=F[0],f.partialHash=ki(y);const x=await m.read(2*c.F1.n8*6+2*c.F2.n8*3);f.key=bo(x,0,c,!1),y.update(new Uint8Array(x));const C=y.digest();if(o&&o.info(qi(C,"Contribution Response Hash imported: ")),n){const t=Gi.create({dkLen:64});t.update(C),await E(t,L,"G1",2,2**d*2-1,"tauG1",o),await E(t,L,"G2",3,2**d,"tauG2",o),await E(t,L,"G1",4,2**d,"alphaTauG1",o),await E(t,L,"G1",5,2**d,"betaTauG1",o),await E(t,L,"G2",6,1,"betaG2",o),f.nextChallenge=t.digest(),o&&o.info(qi(f.nextChallenge,"Next Challenge Hash: "))}else f.nextChallenge=l;return u.push(f),await Co(L,c,u),await m.close(),await L.close(),await r.close(),f.nextChallenge;async function S(t,e,a,i,l,r,s){return n?await async function(t,e,a,i,n,l,r){const s=c[a],d=s.F.n8,u=2*s.F.n8,f=[];await Da(e,i);const g=Math.floor((1<<24)/u);v[i]=e.pos;for(let a=0;a=a&&e=e&&n1?s[s.length-2]:c;const u=s[s.length-1];if(e&&e.debug("Validating contribution #"+s[s.length-1].id),!await Bo(o,u,d,e))return!1;const f=Gi.create({dkLen:64});f.update(u.responseHash),e&&e.debug("Verifying powers in tau*G1 section");const g=await b(2,"G1","tauG1",2**l*2-1,[0,1],e);if(a=await Ao(o,g.R1,g.R2,o.G2.g,u.tauG2),!0!==a)return e&&e.error("tauG1 section. Powers do not match"),!1;if(!o.G1.eq(o.G1.g,g.singularPoints[0]))return e&&e.error("First element of tau*G1 section must be the generator"),!1;if(!o.G1.eq(u.tauG1,g.singularPoints[1]))return e&&e.error("Second element of tau*G1 section does not match the one in the contribution section"),!1;e&&e.debug("Verifying powers in tau*G2 section");const h=await b(3,"G2","tauG2",2**l,[0,1],e);if(a=await Ao(o,o.G1.g,u.tauG1,h.R1,h.R2),!0!==a)return e&&e.error("tauG2 section. Powers do not match"),!1;if(!o.G2.eq(o.G2.g,h.singularPoints[0]))return e&&e.error("First element of tau*G2 section must be the generator"),!1;if(!o.G2.eq(u.tauG2,h.singularPoints[1]))return e&&e.error("Second element of tau*G2 section does not match the one in the contribution section"),!1;e&&e.debug("Verifying powers in alpha*tau*G1 section");const p=await b(4,"G1","alphatauG1",2**l,[0],e);if(a=await Ao(o,p.R1,p.R2,o.G2.g,u.tauG2),!0!==a)return e&&e.error("alphaTauG1 section. Powers do not match"),!1;if(!o.G1.eq(u.alphaG1,p.singularPoints[0]))return e&&e.error("First element of alpha*tau*G1 section (alpha*G1) does not match the one in the contribution section"),!1;e&&e.debug("Verifying powers in beta*tau*G1 section");const _=await b(5,"G1","betatauG1",2**l,[0],e);if(a=await Ao(o,_.R1,_.R2,o.G2.g,u.tauG2),!0!==a)return e&&e.error("betaTauG1 section. Powers do not match"),!1;if(!o.G1.eq(u.betaG1,_.singularPoints[0]))return e&&e.error("First element of beta*tau*G1 section (beta*G1) does not match the one in the contribution section"),!1;const m=await async function(t){const e=o.G2,a=2*e.F.n8,l=new Uint8Array(a);if(!n[6])throw t.error("File has no BetaG2 section"),new Error("File has no BetaG2 section");if(n[6].length>1)throw t.error("File has no BetaG2 section"),new Error("File has more than one GetaG2 section");i.pos=n[6][0].p;const r=await i.read(a),s=e.fromRprLEM(r);return e.toRprUncompressed(l,0,s),f.update(l),s}(e);if(!o.G2.eq(u.betaG2,m))return e&&e.error("betaG2 element in betaG2 section does not match the one in the contribution section"),!1;const w=f.digest();if(l==r&&!Ui(w,u.nextChallenge))return e&&e.error("Hash of the values does not match the next challenge of the last contributor in the contributions section"),!1;e&&e.info(qi(w,"Next challenge hash: ")),L(u,d);for(let t=s.length-2;t>=0;t--){const a=s[t],i=t>0?s[t-1]:c;if(!await Bo(o,a,i,e))return!1;L(a,i)}if(e&&e.info("-----------------------------------------------------"),n[12]&&n[13]&&n[14]&&n[15]){let t;if(t=await y("G1",2,12,"tauG1",e),!t)return!1;if(t=await y("G2",3,13,"tauG2",e),!t)return!1;if(t=await y("G1",4,14,"alphaTauG1",e),!t)return!1;if(t=await y("G1",5,15,"betaTauG1",e),!t)return!1}else e&&e.warn('this file does not contain phase2 precalculated values. Please run: \n snarkjs "powersoftau preparephase2" to prepare this file to be used in the phase2 ceremony.');return await i.close(),e&&e.info("Powers of Tau Ok!"),!0;function L(t,a){if(!e)return;e.info("-----------------------------------------------------"),e.info(`Contribution #${t.id}: ${t.name||""}`),e.info(qi(t.nextChallenge,"Next Challenge: "));const i=new Uint8Array(2*o.G1.F.n8*6+2*o.G2.F.n8*3);yo(i,0,o,t.key,!1);const n=Mi(t.partialHash);n.update(i);const l=n.digest();e.info(qi(l,"Response Hash:")),e.info(qi(a.nextChallenge,"Response Hash:")),1==t.type&&(e.info(`Beacon generator: ${Hi(t.beaconHash)}`),e.info(`Beacon iterations Exp: ${t.numIterationsExp}`))}async function b(t,e,a,l,r,s){const c=o[e],d=2*c.F.n8;await Wa(i,n,t);const u=[];let g=c.zero,h=c.zero,p=c.zero;for(let t=0;t0){const t=c.fromRprLEM(n,0),e=Di(Ni(4),0);g=c.add(g,c.timesScalar(p,e)),h=c.add(h,c.timesScalar(t,e))}const m=await c.multiExpAffine(n.slice(0,(e-1)*d),_),w=await c.multiExpAffine(n.slice(d),_);g=c.add(g,m),h=c.add(h,w),p=c.fromRprLEM(n,(e-1)*d);for(let a=0;a=t&&i1;)c/=2,d+=1;if(2**d!=s)throw new Error("Invalid file size");n&&n.debug("Power to tau size: "+d);const u=await Vi(i),f=await Xn(a),g=Gi.create({dkLen:64});for(let t=0;t{n.debug(e+".g1_s: "+t.G1.toString(_[e].g1_s,16)),n.debug(e+".g1_sx: "+t.G1.toString(_[e].g1_sx,16)),n.debug(e+".g2_sp: "+t.G2.toString(_[e].g2_sp,16)),n.debug(e+".g2_spx: "+t.G2.toString(_[e].g2_spx,16)),n.debug("")}));const m=Gi.create({dkLen:64});await f.write(p),m.update(p),await zo(o,f,m,t,"G1",2**d*2-1,t.Fr.one,_.tau.prvKey,"COMPRESSED","tauG1",n),await zo(o,f,m,t,"G2",2**d,t.Fr.one,_.tau.prvKey,"COMPRESSED","tauG2",n),await zo(o,f,m,t,"G1",2**d,_.alpha.prvKey,_.tau.prvKey,"COMPRESSED","alphaTauG1",n),await zo(o,f,m,t,"G1",2**d,_.beta.prvKey,_.tau.prvKey,"COMPRESSED","betaTauG1",n),await zo(o,f,m,t,"G2",1,_.beta.prvKey,_.tau.prvKey,"COMPRESSED","betaTauG2",n);const w=new Uint8Array(2*t.F1.n8*6+2*t.F2.n8*3);yo(w,0,t,_,!1),await f.write(w),m.update(w);const L=m.digest();n&&n.info(qi(L,"Contribution Response Hash: ")),await f.close(),await o.close()},beacon:async function(t,e,a,i,n,o){const l=Zi(i);if(0==l.byteLength||2*l.byteLength!=i.length)return o&&o.error("Invalid Beacon Hash. (It must be a valid hexadecimal sequence)"),!1;if(l.length>=256)return o&&o.error("Maximum length of beacon hash is 255 bytes"),!1;if((n=parseInt(n))<10||n>63)return o&&o.error("Invalid numIterationsExp. (Must be between 10 and 63)"),!1;const{fd:r,sections:s}=await Na(t,"ptau",1),{curve:c,power:d,ceremonyPower:u}=await Lo(r,s);if(d!=u)return o&&o.error("This file has been reduced. You cannot contribute into a reduced file."),!1;s[12]&&o&&o.warn("Contributing into a file that has phase2 calculated. You will have to prepare phase2 again.");const f=await Fo(r,c,s),g={name:a,type:1,numIterationsExp:n,beaconHash:l};let h;h=f.length>0?f[f.length-1].nextChallenge:So(c,d,o),g.key=await Eo(c,h,l,n);const p=Gi.create({dkLen:64});p.update(h);const _=await ja(e,"ptau",1,7);await wo(_,c,d);const m=[];let w;w=await v(2,"G1",2**d*2-1,c.Fr.e(1),g.key.tau.prvKey,"tauG1",o),g.tauG1=w[1],w=await v(3,"G2",2**d,c.Fr.e(1),g.key.tau.prvKey,"tauG2",o),g.tauG2=w[1],w=await v(4,"G1",2**d,g.key.alpha.prvKey,g.key.tau.prvKey,"alphaTauG1",o),g.alphaG1=w[0],w=await v(5,"G1",2**d,g.key.beta.prvKey,g.key.tau.prvKey,"betaTauG1",o),g.betaG1=w[0],w=await v(6,"G2",1,g.key.beta.prvKey,g.key.tau.prvKey,"betaTauG2",o),g.betaG2=w[0],g.partialHash=ki(p);const L=new Uint8Array(2*c.F1.n8*6+2*c.F2.n8*3);yo(L,0,c,g.key,!1),p.update(new Uint8Array(L));const b=p.digest();o&&o.info(qi(b,"Contribution Response Hash imported: "));const y=Gi.create({dkLen:64});return y.update(b),await F(_,"G1",2,2**d*2-1,"tauG1",o),await F(_,"G2",3,2**d,"tauG2",o),await F(_,"G1",4,2**d,"alphaTauG1",o),await F(_,"G1",5,2**d,"betaTauG1",o),await F(_,"G2",6,1,"betaG2",o),g.nextChallenge=y.digest(),o&&o.info(qi(g.nextChallenge,"Next Challenge Hash: ")),f.push(g),await Co(_,c,f),await r.close(),await _.close(),b;async function v(t,e,a,i,n,o,l){const d=[];r.pos=s[t][0].p,await Da(_,t),m[t]=_.pos;const u=c[e],f=2*u.F.n8,g=Math.floor((1<<20)/f);let h=i;for(let t=0;t0?d[d.length-1].nextChallenge:So(r,s,n),u.key=mo(r,f,g);const h=Gi.create({dkLen:64});h.update(f);const p=await ja(e,"ptau",1,7);await wo(p,r,s);const _=[];let m;m=await y(2,"G1",2**s*2-1,r.Fr.e(1),u.key.tau.prvKey,"tauG1"),u.tauG1=m[1],m=await y(3,"G2",2**s,r.Fr.e(1),u.key.tau.prvKey,"tauG2"),u.tauG2=m[1],m=await y(4,"G1",2**s,u.key.alpha.prvKey,u.key.tau.prvKey,"alphaTauG1"),u.alphaG1=m[0],m=await y(5,"G1",2**s,u.key.beta.prvKey,u.key.tau.prvKey,"betaTauG1"),u.betaG1=m[0],m=await y(6,"G2",1,u.key.beta.prvKey,u.key.tau.prvKey,"betaTauG2"),u.betaG2=m[0],u.partialHash=ki(h);const w=new Uint8Array(2*r.F1.n8*6+2*r.F2.n8*3);yo(w,0,r,u.key,!1),h.update(new Uint8Array(w));const L=h.digest();n&&n.info(qi(L,"Contribution Response Hash imported: "));const b=Gi.create({dkLen:64});return b.update(L),await v(p,"G1",2,2**s*2-1,"tauG1"),await v(p,"G2",3,2**s,"tauG2"),await v(p,"G1",4,2**s,"alphaTauG1"),await v(p,"G1",5,2**s,"betaTauG1"),await v(p,"G2",6,1,"betaG2"),u.nextChallenge=b.digest(),n&&n.info(qi(u.nextChallenge,"Next Challenge Hash: ")),d.push(u),await Co(p,r,d),await o.close(),await p.close(),L;async function y(t,e,a,i,s,c){const d=[];o.pos=l[t][0].p,await Da(p,t),_[t]=p.pos;const u=r[e],f=2*u.F.n8,g=Math.floor((1<<20)/f);let m=i;for(let t=0;t=this.length&&(this.length=t+1),!0}getKeys(){const t=new qo;for(let e=0;e{e.pendingLoads.push({page:t,resolve:a,reject:i})}));return e.__statusPage("After Load request: ",t),a}__statusPage(t,e){const a=[],i=this;if(!i.logHistory)return;a.push("=="+t+" "+e);let n="";for(let t=0;t "+e.history[t][a][i])}_triggerLoad(){const t=this;if(t.reading)return;if(0==t.pendingLoads.length)return;const e=Object.keys(t.pages),a=[];for(let i=0;i0&&(void 0!==t.pages[t.pendingLoads[0].page]||i>0||a.length>0);){const e=t.pendingLoads.shift();if(void 0!==t.pages[e.page]){t.pages[e.page].pendingOps++;const i=a.indexOf(e.page);i>=0&&a.splice(i,1),t.pages[e.page].loading?t.pages[e.page].loading.push(e):e.resolve(),t.__statusPage("After Load (cached): ",e.page)}else{if(i)i--;else{const e=a.shift();t.__statusPage("Before Unload: ",e),t.avBuffs.unshift(t.pages[e]),delete t.pages[e],t.__statusPage("After Unload: ",e)}e.page>=t.totalPages?(t.pages[e.page]=o(),e.resolve(),t.__statusPage("After Load (new): ",e.page)):(t.reading=!0,t.pages[e.page]=o(),t.pages[e.page].loading=[e],n.push(t.fd.read(t.pages[e.page].buff,0,t.pageSize,e.page*t.pageSize).then((a=>{t.pages[e.page].size=a.bytesRead;const i=t.pages[e.page].loading;delete t.pages[e.page].loading;for(let t=0;t{e.reject(t)}))),t.__statusPage("After Load (loading): ",e.page))}}function o(){if(t.avBuffs.length>0){const e=t.avBuffs.shift();return e.dirty=!1,e.pendingOps=1,e.size=0,e}return{dirty:!1,buff:new Uint8Array(t.pageSize),pendingOps:1,size:0}}Promise.all(n).then((()=>{t.reading=!1,t.pendingLoads.length>0&&setImmediate(t._triggerLoad.bind(t)),t._tryClose()}))}_triggerWrite(){const t=this;if(t.writing)return;const e=Object.keys(t.pages),a=[];for(let i=0;i{n.writing=!1}),(e=>{console.log("ERROR Writing: "+e),t.error=e,t._tryClose()}))))}t.writing&&Promise.all(a).then((()=>{t.writing=!1,setImmediate(t._triggerWrite.bind(t)),t._tryClose(),t.pendingLoads.length>0&&setImmediate(t._triggerLoad.bind(t))}))}_getDirtyPage(){for(let t in this.pages)if(this.pages[t].dirty)return t;return-1}async write(t,e){if(0==t.byteLength)return;const a=this;if(void 0===e&&(e=a.pos),a.pos=e+t.byteLength,a.totalSize0;){await o[l-i];const e=r+s>a.pageSize?a.pageSize-r:s,n=t.slice(t.byteLength-s,t.byteLength-s+e);new Uint8Array(a.pages[l].buff.buffer,r,e).set(n),a.pages[l].dirty=!0,a.pages[l].pendingOps--,a.pages[l].size=Math.max(r+e,a.pages[l].size),l>=a.totalPages&&(a.totalPages=l+1),s-=e,l++,r=0,a.writing||setImmediate(a._triggerWrite.bind(a))}}async read(t,e){let a=new Uint8Array(t);return await this.readToBuffer(a,0,t,e),a}async readToBuffer(t,e,a,i){if(0==a)return;const n=this;if(a>n.pageSize*n.maxPagesLoaded*.8){const t=Math.floor(1.1*a);this.maxPagesLoaded=Math.floor(t/n.pageSize)+1}if(void 0===i&&(i=n.pos),n.pos=i+a,n.pendingClose)throw new Error("Reading a closing file");const o=Math.floor(i/n.pageSize),l=Math.floor((i+a-1)/n.pageSize),r=[];for(let t=o;t<=l;t++)r.push(n._loadPage(t));n._triggerLoad();let s=o,c=i%n.pageSize,d=i+a>n.totalSize?a-(i+a-n.totalSize):a;for(;d>0;){await r[s-o],n.__statusPage("After Await (read): ",s);const i=c+d>n.pageSize?n.pageSize-c:d,l=new Uint8Array(n.pages[s].buff.buffer,n.pages[s].buff.byteOffset+c,i);t.set(l,e+a-d),n.pages[s].pendingOps--,n.__statusPage("After Op done: ",s),d-=i,s++,c=0,n.pendingLoads.length>0&&setImmediate(n._triggerLoad.bind(n))}this.pos=i+a}_tryClose(){const t=this;if(!t.pendingClose)return;t.error&&t.pendingCloseReject(t.error);t._getDirtyPage()>=0||t.writing||t.reading||t.pendingLoads.length>0||t.pendingClose()}close(){const t=this;if(t.pendingClose)throw new Error("Closing the file twice");return new Promise(((e,a)=>{t.pendingClose=e,t.pendingCloseReject=a,t._tryClose()})).then((()=>{t.fd.close()}),(e=>{throw t.fd.close(),e}))}async discard(){await this.close(),await ma.promises.unlink(this.fileName)}async writeULE32(t,e){const a=new Uint8Array(4);new DataView(a.buffer).setUint32(0,t,!0),await this.write(a,e)}async writeUBE32(t,e){const a=new Uint8Array(4);new DataView(a.buffer).setUint32(0,t,!1),await this.write(a,e)}async writeULE64(t,e){const a=new Uint8Array(8),i=new DataView(a.buffer);i.setUint32(0,4294967295&t,!0),i.setUint32(4,Math.floor(t/4294967296),!0),await this.write(a,e)}async readULE32(t){const e=await this.read(4,t);return new Uint32Array(e.buffer)[0]}async readUBE32(t){const e=await this.read(4,t);return new DataView(e.buffer).getUint32(0,!1)}async readULE64(t){const e=await this.read(8,t),a=new Uint32Array(e.buffer);return 4294967296*a[1]+a[0]}async readString(t){const e=this;if(e.pendingClose)throw new Error("Reading a closing file");let a=void 0===t?e.pos:t,i=Math.floor(a/e.pageSize),n=!1,o="";for(;!n;){let t=e._loadPage(i);e._triggerLoad(),await t,e.__statusPage("After Await (read): ",i);let l=a%e.pageSize;const r=new Uint8Array(e.pages[i].buff.buffer,e.pages[i].buff.byteOffset+l,e.pageSize-l);let s=r.findIndex((t=>0===t));n=-1!==s,n?(o+=(new TextDecoder).decode(r.slice(0,s)),e.pos=i*this.pageSize+l+s+1):(o+=(new TextDecoder).decode(r),e.pos=i*this.pageSize+l+r.length),e.pages[i].pendingOps--,e.__statusPage("After Op done: ",i),a=e.pos,i++,e.pendingLoads.length>0&&setImmediate(e._triggerLoad.bind(e))}return o}}const Mo=new Uint8Array(4),ko=new DataView(Mo.buffer),Ro=new Uint8Array(8),No=new DataView(Ro.buffer);class jo{constructor(){this.pageSize=16384}_resizeIfNeeded(t){if(t>this.allocSize){const e=Math.max(this.allocSize+(1<<20),Math.floor(1.1*this.allocSize),t),a=new Uint8Array(e);a.set(this.o.data),this.o.data=a,this.allocSize=e}}async write(t,e){if(void 0===e&&(e=this.pos),this.readOnly)throw new Error("Writing a read only file");this._resizeIfNeeded(e+t.byteLength),this.o.data.set(t.slice(),e),e+t.byteLength>this.totalSize&&(this.totalSize=e+t.byteLength),this.pos=e+t.byteLength}async readToBuffer(t,e,a,i){if(void 0===i&&(i=this.pos),this.readOnly&&i+a>this.totalSize)throw new Error("Reading out of bounds");this._resizeIfNeeded(i+a);const n=new Uint8Array(this.o.data.buffer,this.o.data.byteOffset+i,a);t.set(n,e),this.pos=i+a}async read(t,e){const a=new Uint8Array(t);return await this.readToBuffer(a,0,t,e),a}close(){this.o.data.byteLength!=this.totalSize&&(this.o.data=this.o.data.slice(0,this.totalSize))}async discard(){}async writeULE32(t,e){ko.setUint32(0,t,!0),await this.write(Mo,e)}async writeUBE32(t,e){ko.setUint32(0,t,!1),await this.write(Mo,e)}async writeULE64(t,e){No.setUint32(0,4294967295&t,!0),No.setUint32(4,Math.floor(t/4294967296),!0),await this.write(Ro,e)}async readULE32(t){const e=await this.read(4,t);return new Uint32Array(e.buffer)[0]}async readUBE32(t){const e=await this.read(4,t);return new DataView(e.buffer).getUint32(0,!1)}async readULE64(t){const e=await this.read(8,t),a=new Uint32Array(e.buffer);return 4294967296*a[1]+a[0]}async readString(t){const e=this;let a=void 0===t?e.pos:t;if(a>this.totalSize){if(this.readOnly)throw new Error("Reading out of bounds");this._resizeIfNeeded(t)}const i=new Uint8Array(e.o.data.buffer,a,this.totalSize-a);let n=i.findIndex((t=>0===t)),o="";return-1!==n?(o=(new TextDecoder).decode(i.slice(0,n)),e.pos=a+n+1):e.pos=a,o}}const Do=1<<22;const Vo=new Uint8Array(4),Wo=new DataView(Vo.buffer),Zo=new Uint8Array(8),Ho=new DataView(Zo.buffer);class Qo{constructor(){this.pageSize=16384}_resizeIfNeeded(t){if(t<=this.totalSize)return;if(this.readOnly)throw new Error("Reading out of file bounds");const e=Math.floor((t-1)/Do)+1;for(let a=Math.max(this.o.data.length-1,0);a0;){const e=n+o>Do?Do-n:o,l=t.slice(t.byteLength-o,t.byteLength-o+e);new Uint8Array(a.o.data[i].buffer,n,e).set(l),o-=e,i++,n=0}this.pos=e+t.byteLength}async readToBuffer(t,e,a,i){const n=this;if(void 0===i&&(i=n.pos),this.readOnly&&i+a>this.totalSize)throw new Error("Reading out of bounds");this._resizeIfNeeded(i+a);let o=Math.floor(i/Do),l=i%Do,r=a;for(;r>0;){const i=l+r>Do?Do-l:r,s=new Uint8Array(n.o.data[o].buffer,l,i);t.set(s,e+a-r),r-=i,o++,l=0}this.pos=i+a}async read(t,e){const a=new Uint8Array(t);return await this.readToBuffer(a,0,t,e),a}close(){}async discard(){}async writeULE32(t,e){Wo.setUint32(0,t,!0),await this.write(Vo,e)}async writeUBE32(t,e){Wo.setUint32(0,t,!1),await this.write(Vo,e)}async writeULE64(t,e){Ho.setUint32(0,4294967295&t,!0),Ho.setUint32(4,Math.floor(t/4294967296),!0),await this.write(Zo,e)}async readULE32(t){const e=await this.read(4,t);return new Uint32Array(e.buffer)[0]}async readUBE32(t){const e=await this.read(4,t);return new DataView(e.buffer).getUint32(0,!1)}async readULE64(t){const e=await this.read(8,t),a=new Uint32Array(e.buffer);return 4294967296*a[1]+a[0]}async readString(t){const e=this;let a=void 0===t?e.pos:t;if(a>this.totalSize){if(this.readOnly)throw new Error("Reading out of bounds");this._resizeIfNeeded(t)}let i=!1,n="";for(;!i;){let t=Math.floor(a/Do),o=a%Do;if(void 0===e.o.data[t])throw new Error("ERROR");let l=Math.min(2048,e.o.data[t].length-o);const r=new Uint8Array(e.o.data[t].buffer,o,l);let s=r.findIndex((t=>0===t));i=-1!==s,i?(n+=(new TextDecoder).decode(r.slice(0,s)),e.pos=t*Do+o+s+1):(n+=(new TextDecoder).decode(r),e.pos=t*Do+o+r.length),a=e.pos}return n}}async function Ko(t,e,a){if(t instanceof Uint8Array&&(t={type:"mem",data:t}),"string"==typeof t){t={type:"mem",data:await fetch(t).then((function(t){return t.arrayBuffer()})).then((function(t){return new Uint8Array(t)}))}}if("file"==t.type)return await async function(t,e,a,i){if(a=a||262144,"number"!=typeof e&&["w+","wx+","r","ax+","a+"].indexOf(e)<0)throw new Error("Invalid open option");const n=await ma.promises.open(t,e),o=await n.stat();return new Uo(n,o,a,i,t)}(t.fileName,Hn,t.cacheSize,t.pageSize);if("mem"==t.type)return await function(t){const e=new jo;return e.o=t,e.allocSize=t.data.byteLength,e.totalSize=t.data.byteLength,e.readOnly=!0,e.pos=0,e}(t);if("bigMem"==t.type)return await function(t){const e=new Qo;return e.o=t,e.totalSize=(t.data.length-1)*Do+t.data[t.data.length-1].byteLength,e.readOnly=!0,e.pos=0,e}(t);throw new Error("Invalid FastFile type: "+t.type)}async function Xo(t,e,a){if(void 0!==t.readingSection)throw new Error("Already reading a section");if(!e[a])throw new Error(t.fileName+": Missing section "+a);if(e[a].length>1)throw new Error(t.fileName+": Section Duplicated "+a);t.pos=e[a][0].p,t.readingSection=e[a][0]}async function Yo(t,e){if(void 0===t.readingSection)throw new Error("Not reading a section");if(!e&&t.pos-t.readingSection.p!=t.readingSection.size)throw new Error("Invalid section size reading");delete t.readingSection}async function Jo(t,e,a,i,n){if((i=void 0===i?0:i)+(n=void 0===n?e[a][0].size-i:n)>e[a][0].size)throw new Error("Reading out of the range of the section");let o;return o=n<1<<30?new Uint8Array(n):new et(n),await t.readToBuffer(o,0,n,e[a][0].p+i),o}const $o=4,tl=5;async function el(t,e,a){let i;i="object"==typeof a?a:void 0===a?{singleThread:!1}:{singleThread:a};const n={};if(await Xo(t,e,1),n.n8=await t.readULE32(),n.prime=await async function(t,e,a){const i=await t.read(e,a);return vt.fromRprLE(i,0,e)}(t,n.n8),i.F){if(i.F.p!=n.prime)throw new Error("Different Prime");n.F=i.F}else if(i.getFieldFromPrime)n.F=await i.getFieldFromPrime(n.prime,i.singleThread);else if(i.getCurveFromPrime)n.curve=await i.getCurveFromPrime(n.prime,i.singleThread),n.F=n.curve.Fr;else try{n.curve=await async function(t,e,a){let i;if(v(t,yt))i=await wt(e,a);else{if(!v(t,bt))throw new Error(`Curve not supported: ${P(t)}`);i=await Lt(e,a)}return i}(n.prime,i.singleThread),n.F=n.curve.Fr}catch(t){n.F=new W(n.prime)}return n.nVars=await t.readULE32(),n.nOutputs=await t.readULE32(),n.nPubInputs=await t.readULE32(),n.nPrvInputs=await t.readULE32(),n.nLabels=await t.readULE64(),n.nConstraints=await t.readULE32(),n.useCustomGates=void 0!==e[$o]&&null!==e[$o]&&void 0!==e[tl]&&null!==e[tl],await Yo(t),n}async function al(t,e,a){if("object"!=typeof a)throw new Error("readR1csFd: options must be an object");a.loadConstraints=!("loadConstraints"in a)||a.loadConstraints,a.loadMap="loadMap"in a&&a.loadMap,a.loadCustomGates=!("loadCustomGates"in a)||a.loadCustomGates;const i=await el(t,e,a);return a.loadConstraints&&(i.constraints=await async function(t,e,a,i,n){let o;o="object"==typeof i?i:void 0===i?{}:{logger:i,loggerCtx:n};const l=await Jo(t,e,2);let r,s=0;r=a.nConstraints>1<<20?new qo:[];for(let t=0;t1<<20?new qo:[];for(let t=0;t1<<20?new qo:[];for(let t=0;ta)throw new Error("Version not supported");const s=await o.readULE32();let c=[];for(let t=0;t{let i="";return Object.keys(a).forEach((n=>{let o=e.varIdx2Name[n];"one"==o&&(o="1");let l=t.curve.Fr.toString(a[n]);"1"==l&&(l=""),"-1"==l&&(l="-"),""!=i&&"-"!=l[0]&&(l="+"+l),""!=i&&(l=" "+l),i=i+l+o})),i},o=`[ ${n(i[0])} ] * [ ${n(i[1])} ] - [ ${n(i[2])} ] = 0`;a&&a.info(o)}},info:async function(t,e){const a=await il(t);return vt.eq(a.prime,ol)?e&&e.info("Curve: bn-128"):vt.eq(a.prime,nl)?e&&e.info("Curve: bls12-381"):e&&e.info(`Unknown Curve. Prime: ${vt.toString(a.prime)}`),e&&e.info(`# of Wires: ${a.nVars}`),e&&e.info(`# of Constraints: ${a.nConstraints}`),e&&e.info(`# of Private Inputs: ${a.nPrvInputs}`),e&&e.info(`# of Public Inputs: ${a.nPubInputs}`),e&&e.info(`# of Labels: ${a.nLabels}`),e&&e.info(`# of Outputs: ${a.nOutputs}`),a},exportJson:async function(t,e){const a=await il(t,!0,!0,!0,e),i=a.curve.Fr;return delete a.curve,delete a.F,Qi(i,a)}});async function rl(t){const e={labelIdx2Name:["one"],varIdx2Name:["one"],componentIdx2Name:[]},a=await Yn(t),i=await a.read(a.totalSize),n=new TextDecoder("utf-8").decode(i).split("\n");for(let t=0;t Reading r1cs file");const{fd:i,sections:n}=await Na(t,"r1cs",1),o=await al(i,n,{loadConstraints:!1,loadCustomGates:!1});a&&a.info("> Reading witness file");const{fd:l,sections:r}=await Na(e,"wtns",2),s=await En(l,r);if(!vt.eq(o.prime,s.q))throw new Error("Curve of the witness does not match the curve of the proving key");const c=await Xa(l,r,2);await l.close();const d=(await ai(o.prime)).Fr,u=d.n8,f=await Xa(i,n,2);a&&(a.info("----------------------------"),a.info(" WITNESS CHECK"),a.info(` Curve: ${o.curve.name}`),a.info(` Vars (wires): ${o.nVars}`),a.info(` Outputs: ${o.nOutputs}`),a.info(` Public Inputs: ${o.nPubInputs}`),a.info(` Private Inputs: ${o.nPrvInputs}`),a.info(` Labels: ${o.nLabels}`),a.info(` Constraints: ${o.nConstraints}`),a.info(` Custom Gates: ${o.useCustomGates}`),a.info("----------------------------")),a&&a.info("> Checking witness correctness");let g=0,h=!0;for(let t=0;t{const i=function(t){return d.fromRprLE(c.slice(t*u,t*u+u))}(a),n=t[a];e=d.add(e,d.mul(i,n))})),e}function _(){const t={},e=f.slice(g,g+4);g+=4;const a=new DataView(e.buffer).getUint32(0,!0),i=f.slice(g,g+(4+o.n8)*a);g+=(4+o.n8)*a;const n=new DataView(i.buffer);for(let e=0;e=this.length&&(this.length=t+1),!0}getKeys(){const t=new gl;for(let e=0;es)return i&&i.error(`circuit too big for this power of tau ceremony. ${u.nConstraints}*2 > 2**${s}`),-1;if(!l[12])return i&&i.error("Powers of tau is not prepared."),-1;const _=u.nOutputs+u.nPubInputs,m=2**p;await Da(f,1),await f.writeULE32(1),await Va(f),await Da(f,2);const w=r.q,L=8*(Math.floor((vt.bitLength(w)-1)/64)+1),b=r.r,y=8*(Math.floor((vt.bitLength(b)-1)/64)+1),v=vt.mod(vt.shl(1,8*y),b),F=r.Fr.e(vt.mod(vt.mul(v,v),b));let x,C,S;await f.writeULE32(L),await Ha(f,w,L),await f.writeULE32(y),await Ha(f,b,y),await f.writeULE32(u.nVars),await f.writeULE32(_),await f.writeULE32(m),x=await o.read(g,l[4][0].p),await f.write(x),x=await r.G1.batchLEMtoU(x),n.update(x),C=await o.read(g,l[5][0].p),await f.write(C),C=await r.G1.batchLEMtoU(C),n.update(C),S=await o.read(h,l[6][0].p),await f.write(S),S=await r.G2.batchLEMtoU(S),n.update(S);const E=new Uint8Array(g);r.G1.toRprLEM(E,0,r.G1.g);const A=new Uint8Array(h);r.G2.toRprLEM(A,0,r.G2.g);const B=new Uint8Array(g);r.G1.toRprUncompressed(B,0,r.G1.g);const P=new Uint8Array(h);r.G2.toRprUncompressed(P,0,r.G2.g),await f.write(A),await f.write(E),await f.write(A),n.update(P),n.update(B),n.update(P),await Va(f),i&&i.info(H()),i&&i.info("Reading r1cs");let z=await Xa(c,d,2);await c.close();let I=new gl(u.nVars),T=new gl(u.nVars),G=new gl(u.nVars),O=new gl(u.nVars-_-1),q=new Array(_+1);i&&i.info(H()),i&&i.info("Reading tauG1");let U=await Xa(o,l,12,(m-1)*g,m*g);i&&i.info("Reading tauG2");let M=await Xa(o,l,13,(m-1)*h,m*h);i&&i.info("Reading alphatauG1");let k=await Xa(o,l,14,(m-1)*g,m*g);i&&i.info("Reading betatauG1");let R=await Xa(o,l,15,(m-1)*g,m*g);i&&i.info(H()),i&&i.info("processConstraints"),await async function(){const t=new Uint8Array(12+r.Fr.n8),e=new DataView(t.buffer),a=new Uint8Array(r.Fr.n8);r.Fr.toRprLE(a,0,r.Fr.e(1));let n=0;function o(){const t=z.slice(n,n+4);n+=4;return new DataView(t.buffer).getUint32(0,!0)}const l=new gl;for(let t=0;t=0?r.Fr.fromRprLE(z.slice(i[3],i[3]+r.Fr.n8),0):r.Fr.fromRprLE(a,0);const o=r.Fr.mul(n,F);r.Fr.toRprLE(t,12,o),s.set(t,d),d+=t.length}await f.write(s),await Va(f)}(),i&&i.info(H()),i&&i.info("composeAndWritePoints"),await j(3,"G1",q,"IC"),q=null,i&&i.info(H()),i&&i.info("writeHs"),await async function(){await Da(f,9);const t=new et(m*g);if(p(i&&i.debug(`Writing points end ${o}: ${d}/${a.length}`),t)))),c+=n,t++}const d=await Promise.all(s);for(let t=0;t32768?(g=new et(p*o),h=new et(p*r.Fr.n8)):(g=new Uint8Array(p*o),h=new Uint8Array(p*r.Fr.n8));let _=0,m=0;const w=[U,M,k,R],L=new Uint8Array(r.Fr.n8);r.Fr.toRprLE(L,0,r.Fr.e(1));let b=0;for(let t=0;t=0?h.set(z.slice(e[t][n][2],e[t][n][2]+r.Fr.n8),b*r.Fr.n8):h.set(L,b*r.Fr.n8),b++;if(e.length>1){const t=[];t.push({cmd:"ALLOCSET",var:0,buff:g}),t.push({cmd:"ALLOCSET",var:1,buff:h}),t.push({cmd:"ALLOC",var:2,len:e.length*l}),_=0,m=0;let a=0;for(let i=0;i=0;t--){const e=d.contributions[t];i&&i.info("-------------------------"),i&&i.info(qi(e.contributionHash,`contribution #${t+1} ${e.name?e.name:""}:`)),1==e.type&&(i&&i.info(`Beacon generator: ${Hi(e.beaconHash)}`),i&&i.info(`Beacon iterations Exp: ${e.numIterationsExp}`))}return i&&i.info("-------------------------"),i&&i.info("ZKey Ok!"),!0;async function w(t,e){const a=2*s.G1.F.n8,i=t.byteLength/a,n=s.tm.concurrency,o=Math.floor(i/n),l=[];for(let a=0;a Detected protocol: "+n.protocol),"groth16"===n.protocol)o=await async function(t,e,a){const i=await ii(t.q),n=2*i.G1.F.n8,o=await i.pairing(t.vk_alpha_1,t.vk_beta_2);let l={protocol:t.protocol,curve:i.name,nPublic:t.nPublic,vk_alpha_1:i.G1.toObject(t.vk_alpha_1),vk_beta_2:i.G2.toObject(t.vk_beta_2),vk_gamma_2:i.G2.toObject(t.vk_gamma_2),vk_delta_2:i.G2.toObject(t.vk_delta_2),vk_alphabeta_12:i.Gt.toObject(o)};await Wa(e,a,3),l.IC=[];for(let a=0;a<=t.nPublic;a++){const t=await e.read(n),a=i.G1.toObject(t);l.IC.push(a)}return await Za(e),l=ml(l),l}(n,a,i);else if("plonk"===n.protocol)o=await async function(t){const e=await ii(t.q);let a={protocol:t.protocol,curve:e.name,nPublic:t.nPublic,power:t.power,k1:e.Fr.toObject(t.k1),k2:e.Fr.toObject(t.k2),Qm:e.G1.toObject(t.Qm),Ql:e.G1.toObject(t.Ql),Qr:e.G1.toObject(t.Qr),Qo:e.G1.toObject(t.Qo),Qc:e.G1.toObject(t.Qc),S1:e.G1.toObject(t.S1),S2:e.G1.toObject(t.S2),S3:e.G1.toObject(t.S3),X_2:e.G2.toObject(t.X_2),w:e.Fr.toObject(e.Fr.w[t.power])};return a=ml(a),a}(n);else{if(!n.protocolId||n.protocolId!==Yi)throw new Error("zkey file protocol unrecognized");o=await async function(t,e){const a=await ii(t.q);let i={protocol:t.protocol,curve:a.name,nPublic:t.nPublic,power:t.power,k1:a.Fr.toObject(t.k1),k2:a.Fr.toObject(t.k2),w:a.Fr.toObject(a.Fr.w[t.power]),w3:a.Fr.toObject(t.w3),w4:a.Fr.toObject(t.w4),w8:a.Fr.toObject(t.w8),wr:a.Fr.toObject(t.wr),X_2:a.G2.toObject(t.X_2),C0:a.G1.toObject(t.C0)};return ml(i)}(n)}return await a.close(),e&&e.info("EXPORT VERIFICATION KEY FINISHED"),o}const{unstringifyBigInts:Ll,stringifyBigInts:bl}=Ft;async function yl(t,e,a){a&&a.info("FFLONK EXPORT SOLIDITY VERIFIER STARTED");const i=await ni(t.curve);let n=d(t.w3);t.w3_2=u(i.Fr.square(n));let o=d(t.w4);t.w4_2=u(i.Fr.square(o)),t.w4_3=u(i.Fr.mul(i.Fr.square(o),o));let l=d(t.w8),r=i.Fr.one;for(let e=1;e<8;e++)r=i.Fr.mul(r,l),t["w8_"+e]=u(r);let s=e[t.protocol];a&&a.info("FFLONK EXPORT SOLIDITY VERIFIER FINISHED");const{default:c}=await Promise.resolve().then((function(){return Cr}));return c.render(s,t);function d(t){const e=Ll(t);return i.Fr.fromObject(e)}function u(t){const e=i.Fr.toObject(t);return bl(e)}}var vl=Object.freeze({__proto__:null,newZKey:hl,exportBellman:async function(t,e,a){const{fd:i,sections:n}=await Na(t,"zkey",2),o=await bn(i,n);if("groth16"!=o.protocol)throw new Error("zkey file is not groth16");const l=await ii(o.q),r=2*l.G1.F.n8,s=2*l.G2.F.n8,c=await vn(i,l,n),d=await Xn(e);let u;await w(o.vk_alpha_1),await w(o.vk_beta_1),await L(o.vk_beta_2),await L(o.vk_gamma_2),await w(o.vk_delta_1),await L(o.vk_delta_2),u=await Xa(i,n,3),u=await l.G1.batchLEMtoU(u),await b("G1",u);const f=await Xa(i,n,9);let g,h,p,_,m;g=await l.G1.fft(f,"affine","jacobian",a),g=await l.G1.batchApplyKey(g,l.Fr.neg(l.Fr.e(2)),l.Fr.w[o.power+1],"jacobian","affine",a),g=g.slice(0,g.byteLength-r),g=await l.G1.batchLEMtoU(g),await b("G1",g),h=await Xa(i,n,8),h=await l.G1.batchLEMtoU(h),await b("G1",h),p=await Xa(i,n,5),p=await l.G1.batchLEMtoU(p),await b("G1",p),_=await Xa(i,n,6),_=await l.G1.batchLEMtoU(_),await b("G1",_),m=await Xa(i,n,7),m=await l.G2.batchLEMtoU(m),await b("G2",m),await d.write(c.csHash),await async function(t){const e=new Uint8Array(4);new DataView(e.buffer,e.byteOffset,e.byteLength).setUint32(0,t,!1),await d.write(e)}(c.contributions.length);for(let t=0;tf.contributions.length)return n&&n.error("The impoerted file does not include new contributions"),!1;for(let t=0;t=256)return o&&o.error("Maximum length of beacon hash is 255 bytes"),!1;if((n=parseInt(n))<10||n>63)return o&&o.error("Invalid numIterationsExp. (Must be between 10 and 63)"),!1;const{fd:r,sections:s}=await Na(t,"zkey",2),c=await bn(r,s);if("groth16"!=c.protocol)throw new Error("zkey file is not groth16");const d=await ii(c.q),u=await vn(r,d,s),f=await ja(e,"zkey",1,10),g=await Wi(l,n),h=Gi.create({dkLen:64});h.update(u.csHash);for(let t=0;t{const i=this.curve.G1.toObject(this.polynomials[a]);t?e.polynomials[a]=i:e[a]=i})),Object.keys(this.evaluations).forEach((a=>{const i=this.curve.Fr.toObject(this.evaluations[a]);t?e.evaluations[a]=i:e[a]=i})),e}fromObjectProof(t){this.resetProof(),Object.keys(t.polynomials).forEach((e=>{this.polynomials[e]=this.curve.G1.fromObject(t.polynomials[e])})),Object.keys(t.evaluations).forEach((e=>{this.evaluations[e]=this.curve.Fr.fromObject(t.evaluations[e])}))}}const xl=[],Cl=[],Sl=[],El=BigInt(0),Al=BigInt(1),Bl=BigInt(2),Pl=BigInt(7),zl=BigInt(256),Il=BigInt(113);for(let t=0,e=Al,a=1,i=0;t<24;t++){[a,i]=[i,(2*a+3*i)%5],xl.push(2*(5*i+a)),Cl.push((t+1)*(t+2)/2%64);let n=El;for(let t=0;t<7;t++)e=(e<>Pl)*Il)%zl,e&Bl&&(n^=Al<<(Al<a>32?Si(t,e,a):xi(t,e,a),ql=(t,e,a)=>a>32?Ei(t,e,a):Ci(t,e,a);class Ul extends _i{constructor(t,e,a,i=!1,n=24){if(super(),this.blockLen=t,this.suffix=e,this.outputLen=a,this.enableXOF=i,this.rounds=n,this.pos=0,this.posOut=0,this.finished=!1,this.destroyed=!1,li(a),0>=this.blockLen||this.blockLen>=200)throw new Error("Sha3 supports only keccak-f1600 function");this.state=new Uint8Array(200),this.state32=di(this.state)}keccak(){ui||hi(this.state32),function(t,e=24){const a=new Uint32Array(10);for(let i=24-e;i<24;i++){for(let e=0;e<10;e++)a[e]=t[e]^t[e+10]^t[e+20]^t[e+30]^t[e+40];for(let e=0;e<10;e+=2){const i=(e+8)%10,n=(e+2)%10,o=a[n],l=a[n+1],r=Ol(o,l,1)^a[i],s=ql(o,l,1)^a[i+1];for(let a=0;a<50;a+=10)t[e+a]^=r,t[e+a+1]^=s}let e=t[2],n=t[3];for(let a=0;a<24;a++){const i=Cl[a],o=Ol(e,n,i),l=ql(e,n,i),r=xl[a];e=t[r],n=t[r+1],t[r]=o,t[r+1]=l}for(let e=0;e<50;e+=10){for(let i=0;i<10;i++)a[i]=t[e+i];for(let i=0;i<10;i++)t[e+i]^=~a[(i+2)%10]&a[(i+4)%10]}t[0]^=Tl[i],t[1]^=Gl[i]}a.fill(0)}(this.state32,this.rounds),ui||hi(this.state32),this.posOut=0,this.pos=0}update(t){si(this);const{blockLen:e,state:a}=this,i=(t=pi(t)).length;for(let n=0;n=a&&this.keccak();const o=Math.min(a-this.posOut,n-i);t.set(e.subarray(this.posOut,this.posOut+o),i),this.posOut+=o,i+=o}return t}xofInto(t){if(!this.enableXOF)throw new Error("XOF is not possible for this instance");return this.writeInto(t)}xof(t){return li(t),this.xofInto(new Uint8Array(t))}digestInto(t){if(ci(t,this),this.finished)throw new Error("digest() was already called");return this.writeInto(t),this.destroy(),t}digest(){return this.digestInto(new Uint8Array(this.outputLen))}destroy(){this.destroyed=!0,this.state.fill(0)}_cloneInto(t){const{blockLen:e,suffix:a,outputLen:i,rounds:n,enableXOF:o}=this;return t||(t=new Ul(e,a,i,o,n)),t.state32.set(this.state32),t.pos=this.pos,t.posOut=this.posOut,t.finished=this.finished,t.rounds=n,t.suffix=a,t.outputLen=i,t.enableXOF=o,t.destroyed=this.destroyed,t}}const Ml=((t,e,a)=>function(t){const e=e=>t().update(pi(e)).digest(),a=t();return e.outputLen=a.outputLen,e.blockLen=a.blockLen,e.create=()=>t(),e}((()=>new Ul(e,t,a))))(1,136,32);class kl{constructor(t){this.G1=t.G1,this.Fr=t.Fr,this.reset()}reset(){this.data=[]}addPolCommitment(t){this.data.push({type:0,data:t})}addScalar(t){this.data.push({type:1,data:t})}getChallenge(){if(0===this.data.length)throw new Error("Keccak256Transcript: No data to generate a transcript");let t=0,e=0;this.data.forEach((a=>0===a.type?t++:e++));let a=new Uint8Array(e*this.Fr.n8+t*this.G1.F.n8*2),i=0;for(let t=0;t32768?new et(t.length*i.n8):new Uint8Array(t.length*i.n8);for(let e=0;e32768?new et(i*n.n8):new Uint8Array(i*n.n8);return o.set(t.coef.slice(),0),new $l(o,e,a)}isEqual(t){const e=this.degree();if(e!==t.degree())return!1;for(let a=0;a32768?new et((this.length()+t.length)*this.Fr.n8):new Uint8Array((this.length()+t.length)*this.Fr.n8);e.set(this.coef,0);for(let a=0;athis.coef.byteLength?this.Fr.zero:this.coef.slice(e,e+this.Fr.n8)}setCoef(t,e){if(t>this.length()-1)throw new Error("Coef index is not available");this.coef.set(e,t*this.Fr.n8)}static async to4T(t,e,a,i){a=a||[];let n=await i.ifft(t);const o=4*e>32768?new et(4*e*i.n8):new Uint8Array(4*e*i.n8);o.set(n,0);const l=await i.fft(o);if(0===a.length)return[n,l];const r=e+a.length>32768?new et((e+a.length)*i.n8):new Uint8Array((e+a.length)*i.n8);r.set(n,0);for(let t=0;t0;t--){const e=t*this.Fr.n8;if(!this.Fr.eq(this.Fr.zero,this.coef.slice(e,e+this.Fr.n8)))return t}return 0}evaluate(t){let e=this.Fr.zero;for(let a=this.degree()+1;a>0;a--){let i=a*this.Fr.n8;const n=this.coef.slice(i-this.Fr.n8,i);e=this.Fr.add(n,this.Fr.mul(e,t))}return e}fastEvaluate(t){const e=this.Fr;let a=this.degree()+1,i=parseInt(a/3),n=a-3*i,o=[],l=[];l[0]=e.one;for(let a=0;a<3;a++){o[a]=e.zero;for(let r=2===a?i+n:i;r>0;r--)o[a]=e.add(this.getCoef(a*i+r-1),e.mul(o[a],t)),0===a&&(l[0]=e.mul(l[0],t))}for(let t=1;t<3;t++)o[0]=e.add(o[0],e.mul(l[t-1],o[t])),l[t]=e.mul(l[t-1],l[0]);return o[0]}add(t,e){let a=!1;t.length()>this.length()&&(a=!0);const i=this.length(),n=t.length();for(let o=0;othis.length()&&(a=!0);const i=this.length(),n=t.length();for(let o=0;o32768?new et(a*e.n8):new Uint8Array(a*e.n8);let n=new $l(i,this.curve,this.logger);n.coef.set(this.coef.slice(0,(a-1)*e.n8),32),this.mulScalar(e.neg(t)),n.add(this),this.coef=n.coef}byXNSubValue(t,e){const a=this.Fr,i=!(this.length()-t-1>=this.degree())?this.length()+t:this.length(),n=i>32768?new et(i*a.n8):new Uint8Array(i*a.n8);let o=new $l(n,this.curve,this.logger);o.coef.set(this.coef.slice(0,32*(this.degree()+1)),32*t),this.mulScalar(e),o.add(this),this.coef=o.coef}divBy(t){const e=this.Fr,a=this.degree(),i=t.degree();let n=new $l(this.coef,this.curve,this.logger);this.coef=this.length()>32768?new et(this.length()*e.n8):new Uint8Array(this.length()*e.n8);for(let o=a-i;o>=0;o--){this.setCoef(o,e.div(n.getCoef(o+i),t.getCoef(i)));for(let a=0;a<=i;a++)n.setCoef(o+a,e.sub(n.getCoef(o+a),e.mul(this.getCoef(o),t.getCoef(a))))}return n}divByMonic(t,e){const a=this.Fr;let i=this.degree(),n=this.length()>32768?new et(this.length()*a.n8):new Uint8Array(this.length()*a.n8),o=new $l(n,this.curve,this.logger),l=[];for(let e=0;e=0&&!(s<0);s-=r){let i=n;l[i]=a.add(this.getCoef(s+t),a.mul(l[i],e)),o.setCoef(s,l[i])}this.coef=o.coef}divByVanishing(t,e){if(this.degree()32768?new et(this.length()*a.n8):new Uint8Array(this.length()*a.n8);for(let n=this.length()-1;n>=t;n--){let o=i.getCoef(n);a.eq(a.zero,o)||(i.setCoef(n,a.zero),i.setCoef(n-t,a.add(i.getCoef(n-t),a.mul(e,o))),this.setCoef(n-t,a.add(this.getCoef(n-t),o)))}return i}divByVanishing2(t,e){if(this.degree()32768?new et(this.length()*a.n8):new Uint8Array(this.length()*a.n8);let n=this.length()-t,o=Math.floor(n/3),l=n-2*o;console.log(n),console.log(o+" "+l);for(let n=0;n<3;n++){console.log("> Thread "+n);for(let r=0===n?l:o;r>0;r--){let s=r-1;0!==n&&(s+=(n-1)*o+l);let c=s+t,d=i.getCoef(c);a.eq(a.zero,d)||(i.setCoef(c,a.zero),i.setCoef(s,a.add(i.getCoef(s),a.mul(e,d))),this.setCoef(s,a.add(this.getCoef(s),d)),console.log(s+" <-- "+c))}}return this.print(),i}fastDivByVanishing(t){const e=this.Fr;for(let a=0;a32768?new et(this.length()*e.n8):new Uint8Array(this.length()*e.n8),this.curve,this.logger),u=this.coef;this.coef=d.coef,d.coef=u;for(let t=0;t0;t--){let a=t-1,n=a*s+c;h[a]=[];for(let l=0;l32768?new et(this.length()*this.Fr.n8):new Uint8Array(this.length()*this.Fr.n8);e.set(this.Fr.zero,(this.length()-1)*this.Fr.n8),e.set(this.coef.slice((this.length()-1)*this.Fr.n8,this.length()*this.Fr.n8),(this.length()-2)*this.Fr.n8);for(let a=this.length()-3;a>=0;a--){let i=a*this.Fr.n8;e.set(this.Fr.add(this.coef.slice(i+this.Fr.n8,i+2*this.Fr.n8),this.Fr.mul(t,e.slice(i+this.Fr.n8,i+2*this.Fr.n8))),a*this.Fr.n8)}if(!this.Fr.eq(this.coef.slice(0,this.Fr.n8),this.Fr.mul(this.Fr.neg(t),e.slice(0,this.Fr.n8))))throw new Error("Polynomial does not divide");this.coef=e}divZh(t,e=4){for(let e=0;et*(e-1)-e&&!this.Fr.isZero(n))throw new Error("Polynomial is not divisible")}return this}divByZerofier(t,e){let a=this.Fr;const i=a.inv(e),n=a.neg(i);let o=a.eq(a.one,n),l=a.eq(a.negone,n);if(!o)for(let e=0;ethis.length()-t-1&&!this.Fr.isZero(s))throw new Error("Polynomial is not divisible")}return this}byX(){const t=this.length()+1>32768?new et(this.coef.byteLength+this.Fr.n8):new Uint8Array(this.coef.byteLength+this.Fr.n8);t.set(this.Fr.zero,0),t.set(this.coef,this.Fr.n8),this.coef=t}static async expX(t,e,a=!1){const i=t.Fr;if(e<1)throw new Error("Compute a new polynomial to a zero or negative number is not allowed");if(1===e)return await $l.fromEvaluations(t.coef,curve,t.logger);const n=a?t.degree():t.length()-1,o=n*e+1>32768?new et((n*e+1)*i.n8):new Uint8Array((n*e+1)*i.n8);o.set(t.getCoef(0),0);for(let a=1;a<=n;a++){const n=a*i.n8,l=t.getCoef(a);o.set(l,n*e)}return new $l(o,t.curve,t.logger)}split(t,e,a){if(t<1)throw new Error(`Polynomials can't be split in ${t} parts`);if(1===t)return[this];if(0!==a.length&&a.length32768?new et(l):new Uint8Array(l);n[e]=new $l(r,this.curve,this.logger);const s=e*i,c=o?this.coef.byteLength:(e+1)*i;if(n[e].coef.set(this.coef.slice(s,c),0),o||n[e].coef.set(a[e],i),0!==e){const t=this.Fr.sub(n[e].coef.slice(0,this.Fr.n8),a[e-1]);n[e].coef.set(t,0)}o&&n[e].truncate()}return n}truncate(){const t=this.degree();if(t+132768?new et((t+1)*this.Fr.n8):new Uint8Array((t+1)*this.Fr.n8);e.set(this.coef.slice(0,(t+1)*this.Fr.n8),0),this.coef=e}}static lagrangePolynomialInterpolation(t,e,a){const i=a.Fr;let n=o(0);for(let e=1;e32768?new et(t.length*i.n8):new Uint8Array(t.length*i.n8);o=new $l(n,a),o.setCoef(0,i.neg(t[e])),o.setCoef(1,i.one)}else o.byXSubValue(t[e]);let l=o.evaluate(t[n]);l=i.inv(l);const r=i.mul(e[n],l);return o.mulScalar(r),o}}static zerofierPolynomial(t,e){const a=e.Fr;let i=t.length+1>32768?new et((t.length+1)*a.n8):new Uint8Array((t.length+1)*a.n8),n=new $l(i,e);n.setCoef(0,a.neg(t[0])),n.setCoef(1,a.one);for(let e=1;e=0;a--){const i=this.getCoef(a);t.eq(t.zero,i)||(t.isNegative(i)?e+=" - ":a!==this.degree()&&(e+=" + "),e+=t.toString(i),a>0&&(e+=a>1?"x^"+a:"x"))}console.log(e)}async multiExponentiation(t,e){const a=this.coef.byteLength/this.Fr.n8,i=t.slice(0,a*this.G1.F.n8*2),n=await this.Fr.batchFromMontgomery(this.coef);let o=await this.G1.multiExpAffine(i,n,this.logger,e);return o=this.G1.toAffine(o),o}}class tr{constructor(t,e,a){this.eval=t,this.curve=e,this.Fr=e.Fr,this.logger=a}static async fromPolynomial(t,e,a,i){const n=new et(t.length()*e*a.Fr.n8);n.set(t.coef,0);const o=await a.Fr.fft(n);return new tr(o,a,i)}getEvaluation(t){const e=t*this.Fr.n8;if(e+this.Fr.n8>this.eval.byteLength)throw new Error("Evaluations.getEvaluation() out of bounds");return this.eval.slice(e,e+this.Fr.n8)}length(){let t=this.eval.byteLength/this.Fr.n8;if(t!==Math.floor(this.eval.byteLength/this.Fr.n8))throw new Error("Polynomial evaluations buffer has incorrect size");return 0===t&&this.logger.warn("Polynomial has length zero"),t}}const{stringifyBigInts:er}=Ft;async function ar(t,e,a,i){const{fd:n,sections:o}=await Na(e,"wtns",2);a&&a.debug("> Reading witness file");const l=await En(n,o);a&&a.debug("> Reading zkey file");const{fd:r,sections:s}=await Na(t,"zkey",2),c=await bn(r,s,void 0,i);if("plonk"!=c.protocol)throw new Error("zkey file is not plonk");if(!vt.eq(c.r,l.q))throw new Error("Curve of the witness does not match the curve of the proving key");if(l.nWitness!=c.nVars-c.nAdditions)throw new Error(`Invalid witness length. Circuit: ${c.nVars}, witness: ${l.nWitness}, ${c.nAdditions}`);const d=c.curve,u=d.Fr,f=d.Fr.n8,g=c.domainSize*f;a&&(a.debug("----------------------------"),a.debug(" PLONK PROVE SETTINGS"),a.debug(` Curve: ${d.name}`),a.debug(` Circuit power: ${c.power}`),a.debug(` Domain size: ${c.domainSize}`),a.debug(` Vars: ${c.nVars}`),a.debug(` Public vars: ${c.nPublic}`),a.debug(` Constraints: ${c.nConstraints}`),a.debug(` Additions: ${c.nAdditions}`),a.debug("----------------------------")),a&&a.debug("> Reading witness file data");const h=await Xa(n,o,2);h.set(u.zero,0);const p=new et(f*c.nAdditions);let _={},m={},w={},L={},b=new Fl(d,a);const y=new kl(d);a&&a.debug(`> Reading Section ${Nl}. Additions`),await async function(){a&&a.debug("··· Computing additions");const t=await Xa(r,s,Nl),e=8+2*f;for(let i=0;i Reading Section ${Xl}. Sigma1, Sigma2 & Sigma 3`),a&&a.debug("··· Reading Sigma polynomials "),m.Sigma1=new $l(new et(g),d,a),m.Sigma2=new $l(new et(g),d,a),m.Sigma3=new $l(new et(g),d,a),await r.readToBuffer(m.Sigma1.coef,0,g,s[Xl][0].p),await r.readToBuffer(m.Sigma2.coef,0,g,s[Xl][0].p+5*g),await r.readToBuffer(m.Sigma3.coef,0,g,s[Xl][0].p+10*g),a&&a.debug("··· Reading Sigma evaluations"),w.Sigma1=new tr(new et(4*g),d,a),w.Sigma2=new tr(new et(4*g),d,a),w.Sigma3=new tr(new et(4*g),d,a),await r.readToBuffer(w.Sigma1.eval,0,4*g,s[Xl][0].p+g),await r.readToBuffer(w.Sigma2.eval,0,4*g,s[Xl][0].p+6*g),await r.readToBuffer(w.Sigma3.eval,0,4*g,s[Xl][0].p+11*g),a&&a.debug(`> Reading Section ${Jl}. Powers of Tau`);const v=await Xa(r,s,Jl);let F=[];for(let t=1;t<=c.nPublic;t++){const e=h.slice(t*u.n8,t*u.n8+u.n8);F.push(vt.fromRprLE(e))}a&&a.debug(""),a&&a.debug("> ROUND 1"),await async function(){L.b=[];for(let t=1;t<=11;t++)L.b[t]=d.Fr.random();a&&a.debug("> Computing A, B, C wire polynomials");await async function(){a&&a.debug("··· Reading data from zkey file");_.A=new et(g),_.B=new et(g),_.C=new et(g);const t=await Xa(r,s,jl),e=await Xa(r,s,Dl),i=await Xa(r,s,Vl);for(let a=0;a=c.domainSize+2)throw new Error("A Polynomial is not well calculated");if(m.B.degree()>=c.domainSize+2)throw new Error("B Polynomial is not well calculated");if(m.C.degree()>=c.domainSize+2)throw new Error("C Polynomial is not well calculated")}(),a&&a.debug("> Computing A, B, C MSM");let t=await m.A.multiExponentiation(v,"A"),e=await m.B.multiExponentiation(v,"B"),i=await m.C.multiExponentiation(v,"C");return b.addPolynomial("A",t),b.addPolynomial("B",e),b.addPolynomial("C",i),0}(),a&&a.debug("> ROUND 2"),await async function(){a&&a.debug("> Computing challenges beta and gamma");y.reset(),y.addPolCommitment(c.Qm),y.addPolCommitment(c.Ql),y.addPolCommitment(c.Qr),y.addPolCommitment(c.Qo),y.addPolCommitment(c.Qc),y.addPolCommitment(c.S1),y.addPolCommitment(c.S2),y.addPolCommitment(c.S3);for(let t=0;t Computing Z polynomial");await async function(){a&&a.debug("··· Computing Z evaluations");let t=new et(g),e=new et(g);t.set(u.one,0),e.set(u.one,0);let i=u.one;for(let a=0;a=c.domainSize+3)throw new Error("Z Polynomial is not well calculated");delete _.Z}(),a&&a.debug("> Computing Z MSM");let t=await m.Z.multiExponentiation(v,"Z");b.addPolynomial("Z",t)}(),a&&a.debug("> ROUND 3"),await async function(){a&&a.debug("> Computing challenge alpha");y.reset(),y.addScalar(L.beta),y.addScalar(L.gamma),y.addPolCommitment(b.getPolynomial("Z")),L.alpha=y.getChallenge(),L.alpha2=u.square(L.alpha),a&&a.debug("··· challenges.alpha: "+u.toString(L.alpha,16));a&&a.debug("> Computing T polynomial");await async function(){a&&a.debug(`··· Reading sections ${Zl}, ${Hl}, ${Wl}, ${Ql}, ${Kl}. Q selectors`);w.QL=new tr(new et(4*g),d,a),w.QR=new tr(new et(4*g),d,a),w.QM=new tr(new et(4*g),d,a),w.QO=new tr(new et(4*g),d,a),w.QC=new tr(new et(4*g),d,a),await r.readToBuffer(w.QL.eval,0,4*g,s[Zl][0].p+g),await r.readToBuffer(w.QR.eval,0,4*g,s[Hl][0].p+g),await r.readToBuffer(w.QM.eval,0,4*g,s[Wl][0].p+g),await r.readToBuffer(w.QO.eval,0,4*g,s[Ql][0].p+g),await r.readToBuffer(w.QC.eval,0,4*g,s[Kl][0].p+g),w.Lagrange=new tr(new et(4*g*c.nPublic),d,a);for(let t=0;t=3*c.domainSize+6)throw new Error("T Polynomial is not well calculated");a&&a.debug("··· Computing T1, T2, T3 polynomials");m.T1=new $l(new et((c.domainSize+1)*f),d,a),m.T2=new $l(new et((c.domainSize+1)*f),d,a),m.T3=new $l(new et((c.domainSize+6)*f),d,a),m.T1.coef.set(m.T.coef.slice(0,g),0),m.T2.coef.set(m.T.coef.slice(g,2*g),0),m.T3.coef.set(m.T.coef.slice(2*g,3*g+6*f),0),m.T1.setCoef(c.domainSize,L.b[10]);const e=u.sub(m.T2.getCoef(0),L.b[10]);m.T2.setCoef(0,e),m.T2.setCoef(c.domainSize,L.b[11]);const i=u.sub(m.T3.getCoef(0),L.b[11]);m.T3.setCoef(0,i)}(),a&&a.debug("> Computing T MSM");let t=await m.T1.multiExponentiation(v,"T1"),e=await m.T2.multiExponentiation(v,"T2"),i=await m.T3.multiExponentiation(v,"T3");b.addPolynomial("T1",t),b.addPolynomial("T2",e),b.addPolynomial("T3",i)}(),a&&a.debug("> ROUND 4"),await async function(){a&&a.debug("> Computing challenge xi");y.reset(),y.addScalar(L.alpha),y.addPolCommitment(b.getPolynomial("T1")),y.addPolCommitment(b.getPolynomial("T2")),y.addPolCommitment(b.getPolynomial("T3")),L.xi=y.getChallenge(),L.xiw=u.mul(L.xi,u.w[c.power]),a&&a.debug("··· challenges.xi: "+u.toString(L.xi,16));b.addEvaluation("eval_a",m.A.evaluate(L.xi)),b.addEvaluation("eval_b",m.B.evaluate(L.xi)),b.addEvaluation("eval_c",m.C.evaluate(L.xi)),b.addEvaluation("eval_s1",m.Sigma1.evaluate(L.xi)),b.addEvaluation("eval_s2",m.Sigma2.evaluate(L.xi)),b.addEvaluation("eval_zw",m.Z.evaluate(L.xiw))}(),a&&a.debug("> ROUND 5"),await async function(){a&&a.debug("> Computing challenge v");y.reset(),y.addScalar(L.xi),y.addScalar(b.getEvaluation("eval_a")),y.addScalar(b.getEvaluation("eval_b")),y.addScalar(b.getEvaluation("eval_c")),y.addScalar(b.getEvaluation("eval_s1")),y.addScalar(b.getEvaluation("eval_s2")),y.addScalar(b.getEvaluation("eval_zw")),L.v=[],L.v[1]=y.getChallenge(),a&&a.debug("··· challenges.v: "+u.toString(L.v[1],16));for(let t=2;t<6;t++)L.v[t]=u.mul(L.v[t-1],L.v[1]);a&&a.debug("> Computing linearisation polynomial R(X)");await async function(){const t=d.Fr;m.QL=new $l(new et(g),d,a),m.QR=new $l(new et(g),d,a),m.QM=new $l(new et(g),d,a),m.QO=new $l(new et(g),d,a),m.QC=new $l(new et(g),d,a),await r.readToBuffer(m.QL.coef,0,g,s[Zl][0].p),await r.readToBuffer(m.QR.coef,0,g,s[Hl][0].p),await r.readToBuffer(m.QM.coef,0,g,s[Wl][0].p),await r.readToBuffer(m.QO.coef,0,g,s[Ql][0].p),await r.readToBuffer(m.QC.coef,0,g,s[Kl][0].p),L.xin=L.xi;for(let e=0;e Computing opening proof polynomial Wxi(X) polynomial");m.Wxi=new $l(new et(g+6*f),d,a),m.Wxi.add(m.R),m.Wxi.add(m.A,L.v[1]),m.Wxi.add(m.B,L.v[2]),m.Wxi.add(m.C,L.v[3]),m.Wxi.add(m.Sigma1,L.v[4]),m.Wxi.add(m.Sigma2,L.v[5]),m.Wxi.subScalar(u.mul(L.v[1],b.evaluations.eval_a)),m.Wxi.subScalar(u.mul(L.v[2],b.evaluations.eval_b)),m.Wxi.subScalar(u.mul(L.v[3],b.evaluations.eval_c)),m.Wxi.subScalar(u.mul(L.v[4],b.evaluations.eval_s1)),m.Wxi.subScalar(u.mul(L.v[5],b.evaluations.eval_s2)),void m.Wxi.divByZerofier(1,L.xi),a&&a.debug("> Computing opening proof polynomial Wxiw(X) polynomial");(async function(){m.Wxiw=$l.fromPolynomial(m.Z,d,a),m.Wxiw.subScalar(b.evaluations.eval_zw),m.Wxiw.divByZerofier(1,L.xiw)})(),a&&a.debug("> Computing Wxi, Wxiw MSM");let t=await m.Wxi.multiExponentiation(v,"Wxi"),e=await m.Wxiw.multiExponentiation(v,"Wxiw");b.addPolynomial("Wxi",t),b.addPolynomial("Wxiw",e)}(),await r.close(),await n.close();let x=b.toObjectProof(!1);return x.protocol="plonk",x.curve=d.name,a&&a.debug("PLONK PROVER FINISHED"),{proof:er(x),publicSignals:er(F)};function C(t,e){const a=t.slice(e,e+4);return new DataView(a.buffer,a.byteOffset,a.byteLength).getUint32(0,!0)}function S(t){return ta;){const e=n.shift(),a=n.shift(),i=e[0],o=a[0],l=w++,r=t.zero,s=t.neg(e[1]),c=t.neg(a[1]),d=t.one,u=t.zero;_.push([i,o,l,r,s,c,d,u]),m.push([i,o,e[1],a[1]]),n.push([l,t.one])}for(let t=0;t0?i.toString():a!=t.zero?"k":"0"}function s(e,a,s){const c=r(e),d=r(a);if("0"===c||"0"===d)i(s),l(s);else if("k"===c){l(n(a,e[0],s))}else if("k"===d){l(n(e,a[0],s))}else!function(e,a,i){const n=o(e,1),l=o(a,1),r=o(i,1),s=n.s[0],c=l.s[0],d=r.s[0],u=t.mul(n.coefs[0],l.coefs[0]),f=t.mul(n.coefs[0],l.k),g=t.mul(n.k,l.coefs[0]),h=t.neg(r.coefs[0]),p=t.sub(t.mul(n.k,l.k),r.k);_.push([s,c,d,u,f,g,h,p])}(e,a,s)}for(let e=1;e<=L;e++){const a=e,i=0,n=0,o=t.zero,l=t.one,r=t.zero,s=t.zero,c=t.zero;_.push([a,i,n,o,l,r,s,c])}for(let t=0;tr)return i&&i.error(`circuit too big for this power of tau ceremony. ${_.length} > 2**${r}`),-1;if(!o[12])return i&&i.error("Powers of tau is not prepared."),-1;const F=new et(v*u),x=o[12][0].p+(2**y-1)*u;await n.readToBuffer(F,0,v*u,x);const[C,S]=function(){let t=h.two;for(;a(t,[],y);)h.add(t,h.one);let e=h.add(t,h.one);for(;a(e,[t],y);)h.add(e,h.one);return[t,e];function a(t,e,a){const i=2**a;let n=h.one;for(let o=0;o0?2:this.Fr.isZero(e)?0:1}normalizeLinearCombination(t){const e=Object.keys(t);for(let a=0;an;){const i=l.shift(),n=l.shift(),o=t.nVars++,r=this.fnGetAdditionConstraint(i[0],n[0],o,this.Fr.neg(i[1]),this.Fr.neg(n[1]),this.Fr.zero,this.Fr.one,this.Fr.zero);e.push(r),a.push([i[0],n[0],i[1],n[1]]),l.push([o,this.Fr.one])}for(let t=0;tthis.n-1)throw new Error("CPolynomial:addPolynomial, cannot add a polynomial to a position greater than n-1");this.polynomials[t]=e}degree(){let t=this.polynomials.map(((t,e)=>void 0===t?0:t.degree()*this.n+e));return Math.max(...t)}getPolynomial(){let t=this.polynomials.map((t=>void 0===t?0:t.degree()));const e=this.degree(),a=2**(Oi(e-1)+1),i=this.Fr.n8;let n=new $l(new et(a*i),this.curve,this.logger);for(let a=0;a Reading witness file");const{fd:n,sections:o}=await Na(e,"wtns",2),l=await En(n,o);a&&a.info("> Reading zkey file");const{fd:r,sections:s}=await Na(t,"zkey",2),c=await bn(r,s,void 0,i);if(c.protocolId!==Yi)throw new Error("zkey file is not fflonk");if(!vt.eq(c.r,l.q))throw new Error("Curve of the witness does not match the curve of the proving key");if(l.nWitness!==c.nVars-c.nAdditions)throw new Error(`Invalid witness length. Circuit: ${c.nVars}, witness: ${l.nWitness}, ${c.nAdditions}`);const d=c.curve,u=d.Fr,f=d.Fr.n8,g=2*d.G1.F.n8,h=c.domainSize*f;a&&(a.info("----------------------------"),a.info(" FFLONK PROVE SETTINGS"),a.info(` Curve: ${d.name}`),a.info(` Circuit power: ${c.power}`),a.info(` Domain size: ${c.domainSize}`),a.info(` Vars: ${c.nVars}`),a.info(` Public vars: ${c.nPublic}`),a.info(` Constraints: ${c.nConstraints}`),a.info(` Additions: ${c.nAdditions}`),a.info("----------------------------")),a&&a.info("> Reading witness file data");const p=await Xa(n,o,2);await n.close(),p.set(u.zero,0);const _=new et(c.nAdditions*f);let m={},w={},L={},b={},y={},v={},F=new Fl(d,a);a&&a.info(`> Reading Section ${$i}. Additions`),await async function(){a&&a.info("··· Computing additions");const t=await Xa(r,s,$i),e=8+2*f;for(let i=0;i Reading Sections ${cn},${dn},${un}. Sigma1, Sigma2 & Sigma 3`),a&&a.info("··· Reading Sigma polynomials "),w.Sigma1=new $l(new et(h),d,a),w.Sigma2=new $l(new et(h),d,a),w.Sigma3=new $l(new et(h),d,a),await r.readToBuffer(w.Sigma1.coef,0,h,s[cn][0].p),await r.readToBuffer(w.Sigma2.coef,0,h,s[dn][0].p),await r.readToBuffer(w.Sigma3.coef,0,h,s[un][0].p),a&&a.info("··· Reading Sigma evaluations"),L.Sigma1=new tr(new et(4*h),d,a),L.Sigma2=new tr(new et(4*h),d,a),L.Sigma3=new tr(new et(4*h),d,a),await r.readToBuffer(L.Sigma1.eval,0,4*h,s[cn][0].p+h),await r.readToBuffer(L.Sigma2.eval,0,4*h,s[dn][0].p+h),await r.readToBuffer(L.Sigma3.eval,0,4*h,s[un][0].p+h),a&&a.info(`> Reading Section ${gn}. Powers of Tau`);const x=new et(16*c.domainSize*g);await r.readToBuffer(x,0,(9*c.domainSize+18)*g,s[gn][0].p),globalThis.gc&&globalThis.gc(),a&&a.info(""),a&&a.info("> ROUND 1"),await async function(){y.b=[];for(let t=1;t<=9;t++)y.b[t]=u.random();a&&a.info("> Computing A, B, C wire polynomials");await async function(){a&&a.info("··· Reading data from zkey file");m.A=new et(h),m.B=new et(h),m.C=new et(h);const t=await Xa(r,s,tn),e=await Xa(r,s,en),i=await Xa(r,s,an);for(let a=0;a=c.domainSize)throw new Error("A Polynomial is not well calculated");if(w.B.degree()>=c.domainSize)throw new Error("B Polynomial is not well calculated");if(w.C.degree()>=c.domainSize)throw new Error("C Polynomial is not well calculated")}(),a&&a.info("> Computing T0 polynomial");await async function(){a&&a.info(`··· Reading sections ${nn}, ${on}, ${ln}, ${rn}, ${sn}. Q selectors`);L.QL=new tr(new et(4*h),d,a),L.QR=new tr(new et(4*h),d,a),L.QM=new tr(new et(4*h),d,a),L.QO=new tr(new et(4*h),d,a),L.QC=new tr(new et(4*h),d,a),await r.readToBuffer(L.QL.eval,0,4*h,s[nn][0].p+h),await r.readToBuffer(L.QR.eval,0,4*h,s[on][0].p+h),await r.readToBuffer(L.QM.eval,0,4*h,s[ln][0].p+h),await r.readToBuffer(L.QO.eval,0,4*h,s[rn][0].p+h),await r.readToBuffer(L.QC.eval,0,4*h,s[sn][0].p+h);const t=await Xa(r,s,fn);L.lagrange1=new tr(t,d,a),m.T0=new et(4*h),a&&a.info("··· Computing T0 evaluations");for(let t=0;t<4*c.domainSize;t++){a&&0!==t&&t%1e5==0&&a.info(` T0 evaluation ${t}/${4*c.domainSize}`);const e=L.A.getEvaluation(t),i=L.B.getEvaluation(t),n=L.C.getEvaluation(t),o=L.QL.getEvaluation(t),l=L.QR.getEvaluation(t),r=L.QM.getEvaluation(t),s=L.QO.getEvaluation(t),d=L.QC.getEvaluation(t);let g=u.zero;for(let e=0;e=2*c.domainSize-2)throw new Error(`T0 Polynomial is not well calculated (degree is ${w.T0.degree()} and must be less than ${2*c.domainSize+2}`);delete m.T0}(),a&&a.info("> Computing C1 polynomial");await async function(){let t=new hr(4,d,a);if(t.addPolynomial(0,w.A),t.addPolynomial(1,w.B),t.addPolynomial(2,w.C),t.addPolynomial(3,w.T0),w.C1=t.getPolynomial(),w.C1.degree()>=8*c.domainSize-8)throw new Error("C1 Polynomial is not well calculated")}(),a&&a.info("> Computing C1 multi exponentiation");let t=await w.C1.multiExponentiation(x,"C1");return F.addPolynomial("C1",t),0}(),delete w.T0,delete L.QL,delete L.QR,delete L.QM,delete L.QO,delete L.QC,globalThis.gc&&globalThis.gc(),a&&a.info("> ROUND 2"),await async function(){a&&a.info("> Computing challenges beta and gamma");const t=new kl(d);t.addPolCommitment(c.C0);for(let e=0;e Computing Z polynomial");await async function(){a&&a.info("··· Computing Z evaluations");let t=new et(h),e=new et(h);t.set(u.one,0),e.set(u.one,0);let i=u.one;for(let n=0;n=c.domainSize+3)throw new Error("Z Polynomial is not well calculated");delete m.Z}(),a&&a.info("> Computing T1 polynomial");await async function(){a&&a.info("··· Computing T1 evaluations");m.T1=new et(2*h),m.T1z=new et(2*h);let t=u.one;for(let e=0;e<2*c.domainSize;e++){a&&0!==e&&e%1e5==0&&a.info(` T1 evaluation ${e}/${4*c.domainSize}`);const i=u.square(t),n=L.Z.getEvaluation(2*e),o=u.add(u.add(u.mul(y.b[7],i),u.mul(y.b[8],t)),y.b[9]),l=L.lagrange1.getEvaluation(c.domainSize+2*e);let r=u.mul(u.sub(n,u.one),l),s=u.mul(o,l);m.T1.set(r,e*f),m.T1z.set(s,e*f),t=u.mul(t,u.w[c.power+1])}a&&a.info("··· Computing T1 ifft");w.T1=await $l.fromEvaluations(m.T1,d,a),w.T1.divByZerofier(c.domainSize,u.one),a&&a.info("··· Computing T1z ifft");if(w.T1z=await $l.fromEvaluations(m.T1z,d,a),w.T1.add(w.T1z),w.T1.degree()>=c.domainSize+2)throw new Error("T1 Polynomial is not well calculated");delete m.T1,delete m.T1z,delete w.T1z}(),a&&a.info("> Computing T2 polynomial");await async function(){a&&a.info("··· Computing T2 evaluations");m.T2=new et(4*h),m.T2z=new et(4*h);let t=u.one;for(let e=0;e<4*c.domainSize;e++){a&&0!==e&&e%1e5==0&&a.info(` T2 evaluation ${e}/${4*c.domainSize}`);const i=u.square(t),n=u.mul(t,u.w[c.power]),o=u.square(n),l=L.A.getEvaluation(e),r=L.B.getEvaluation(e),s=L.C.getEvaluation(e),d=L.Z.getEvaluation(e),g=L.Z.getEvaluation((4*c.domainSize+4+e)%(4*c.domainSize)),h=u.add(u.add(u.mul(y.b[7],i),u.mul(y.b[8],t)),y.b[9]),p=u.add(u.add(u.mul(y.b[7],o),u.mul(y.b[8],n)),y.b[9]),_=L.Sigma1.getEvaluation(e),w=L.Sigma2.getEvaluation(e),b=L.Sigma3.getEvaluation(e),v=u.mul(y.beta,t);let F=u.add(l,v);F=u.add(F,y.gamma);let x=u.add(r,u.mul(v,c.k1));x=u.add(x,y.gamma);let C=u.add(s,u.mul(v,c.k2));C=u.add(C,y.gamma);let S=u.mul(u.mul(u.mul(F,x),C),d),E=u.mul(u.mul(u.mul(F,x),C),h),A=u.add(l,u.mul(y.beta,_));A=u.add(A,y.gamma);let B=u.add(r,u.mul(y.beta,w));B=u.add(B,y.gamma);let P=u.add(s,u.mul(y.beta,b));P=u.add(P,y.gamma);let z=u.mul(u.mul(u.mul(A,B),P),g),I=u.mul(u.mul(u.mul(A,B),P),p),T=u.sub(S,z),G=u.sub(E,I);m.T2.set(T,e*f),m.T2z.set(G,e*f),t=u.mul(t,u.w[c.power+2])}a&&a.info("··· Computing T2 ifft");w.T2=await $l.fromEvaluations(m.T2,d,a),a&&a.info("··· Computing T2 / ZH");w.T2.divByZerofier(c.domainSize,u.one),a&&a.info("··· Computing T2z ifft");if(w.T2z=await $l.fromEvaluations(m.T2z,d,a),w.T2.add(w.T2z),w.T2.degree()>=3*c.domainSize)throw new Error("T2 Polynomial is not well calculated");delete m.T2,delete m.T2z,delete w.T2z}(),a&&a.info("> Computing C2 polynomial");await async function(){let t=new hr(3,d,a);if(t.addPolynomial(0,w.Z),t.addPolynomial(1,w.T1),t.addPolynomial(2,w.T2),w.C2=t.getPolynomial(),w.C2.degree()>=9*c.domainSize)throw new Error("C2 Polynomial is not well calculated")}(),a&&a.info("> Computing C2 multi exponentiation");let e=await w.C2.multiExponentiation(x,"C2");return F.addPolynomial("C2",e),0}(),delete m.A,delete m.B,delete m.C,delete L.A,delete L.B,delete L.C,delete L.Sigma1,delete L.Sigma2,delete L.Sigma3,delete L.lagrange1,delete L.Z,globalThis.gc&&globalThis.gc(),a&&a.info("> ROUND 3"),await async function(){a&&a.info("> Computing challenge xi");const t=new kl(d);t.addScalar(y.gamma),t.addPolCommitment(F.getPolynomial("C2")),y.xiSeed=t.getChallenge();const e=u.square(y.xiSeed);v.w8=[],v.w8[0]=u.one;for(let t=1;t<8;t++)v.w8[t]=u.mul(v.w8[t-1],c.w8);v.w4=[],v.w4[0]=u.one;for(let t=1;t<4;t++)v.w4[t]=u.mul(v.w4[t-1],c.w4);v.w3=[],v.w3[0]=u.one,v.w3[1]=c.w3,v.w3[2]=u.square(c.w3),v.S0={},v.S0.h0w8=[],v.S0.h0w8[0]=u.mul(e,y.xiSeed);for(let t=1;t<8;t++)v.S0.h0w8[t]=u.mul(v.S0.h0w8[0],v.w8[t]);v.S1={},v.S1.h1w4=[],v.S1.h1w4[0]=u.square(v.S0.h0w8[0]);for(let t=1;t<4;t++)v.S1.h1w4[t]=u.mul(v.S1.h1w4[0],v.w4[t]);v.S2={},v.S2.h2w3=[],v.S2.h2w3[0]=u.mul(v.S1.h1w4[0],e),v.S2.h2w3[1]=u.mul(v.S2.h2w3[0],v.w3[1]),v.S2.h2w3[2]=u.mul(v.S2.h2w3[0],v.w3[2]),v.S2.h3w3=[],v.S2.h3w3[0]=u.mul(v.S2.h2w3[0],c.wr),v.S2.h3w3[1]=u.mul(v.S2.h3w3[0],v.w3[1]),v.S2.h3w3[2]=u.mul(v.S2.h3w3[0],v.w3[2]),y.xi=u.mul(u.square(v.S2.h2w3[0]),v.S2.h2w3[0]),a&&a.info("··· challenges.xi: "+u.toString(y.xi));w.QL=new $l(new et(h),d,a),w.QR=new $l(new et(h),d,a),w.QM=new $l(new et(h),d,a),w.QO=new $l(new et(h),d,a),w.QC=new $l(new et(h),d,a),await r.readToBuffer(w.QL.coef,0,h,s[nn][0].p),await r.readToBuffer(w.QR.coef,0,h,s[on][0].p),await r.readToBuffer(w.QM.coef,0,h,s[ln][0].p),await r.readToBuffer(w.QO.coef,0,h,s[rn][0].p),await r.readToBuffer(w.QC.coef,0,h,s[sn][0].p),a&&a.info("··· Computing evaluations");F.addEvaluation("ql",w.QL.evaluate(y.xi)),F.addEvaluation("qr",w.QR.evaluate(y.xi)),F.addEvaluation("qm",w.QM.evaluate(y.xi)),F.addEvaluation("qo",w.QO.evaluate(y.xi)),F.addEvaluation("qc",w.QC.evaluate(y.xi)),F.addEvaluation("s1",w.Sigma1.evaluate(y.xi)),F.addEvaluation("s2",w.Sigma2.evaluate(y.xi)),F.addEvaluation("s3",w.Sigma3.evaluate(y.xi)),F.addEvaluation("a",w.A.evaluate(y.xi)),F.addEvaluation("b",w.B.evaluate(y.xi)),F.addEvaluation("c",w.C.evaluate(y.xi)),F.addEvaluation("z",w.Z.evaluate(y.xi)),y.xiw=u.mul(y.xi,u.w[c.power]),F.addEvaluation("zw",w.Z.evaluate(y.xiw)),F.addEvaluation("t1w",w.T1.evaluate(y.xiw)),F.addEvaluation("t2w",w.T2.evaluate(y.xiw))}(),delete w.A,delete w.B,delete w.C,delete w.Z,delete w.T1,delete w.T2,delete w.Sigma1,delete w.Sigma2,delete w.Sigma3,delete w.QL,delete w.QR,delete w.QM,delete w.QC,delete w.QO,globalThis.gc&&globalThis.gc(),a&&a.info("> ROUND 4"),await async function(){a&&a.info("> Computing challenge alpha");const t=new kl(d);t.addScalar(y.xiSeed),t.addScalar(F.getEvaluation("ql")),t.addScalar(F.getEvaluation("qr")),t.addScalar(F.getEvaluation("qm")),t.addScalar(F.getEvaluation("qo")),t.addScalar(F.getEvaluation("qc")),t.addScalar(F.getEvaluation("s1")),t.addScalar(F.getEvaluation("s2")),t.addScalar(F.getEvaluation("s3")),t.addScalar(F.getEvaluation("a")),t.addScalar(F.getEvaluation("b")),t.addScalar(F.getEvaluation("c")),t.addScalar(F.getEvaluation("z")),t.addScalar(F.getEvaluation("zw")),t.addScalar(F.getEvaluation("t1w")),t.addScalar(F.getEvaluation("t2w")),y.alpha=t.getChallenge(),a&&a.info("··· challenges.alpha: "+u.toString(y.alpha));a&&a.info("> Reading C0 polynomial");w.C0=new $l(new et(8*h),d,a),await r.readToBuffer(w.C0.coef,0,8*h,s[hn][0].p),a&&a.info("> Computing R0 polynomial");(function(){if(w.R0=$l.lagrangePolynomialInterpolation([v.S0.h0w8[0],v.S0.h0w8[1],v.S0.h0w8[2],v.S0.h0w8[3],v.S0.h0w8[4],v.S0.h0w8[5],v.S0.h0w8[6],v.S0.h0w8[7]],[w.C0.evaluate(v.S0.h0w8[0]),w.C0.evaluate(v.S0.h0w8[1]),w.C0.evaluate(v.S0.h0w8[2]),w.C0.evaluate(v.S0.h0w8[3]),w.C0.evaluate(v.S0.h0w8[4]),w.C0.evaluate(v.S0.h0w8[5]),w.C0.evaluate(v.S0.h0w8[6]),w.C0.evaluate(v.S0.h0w8[7])],d),w.R0.degree()>7)throw new Error("R0 Polynomial is not well calculated")})(),a&&a.info("> Computing R1 polynomial");(function(){if(w.R1=$l.lagrangePolynomialInterpolation([v.S1.h1w4[0],v.S1.h1w4[1],v.S1.h1w4[2],v.S1.h1w4[3]],[w.C1.evaluate(v.S1.h1w4[0]),w.C1.evaluate(v.S1.h1w4[1]),w.C1.evaluate(v.S1.h1w4[2]),w.C1.evaluate(v.S1.h1w4[3])],d),w.R1.degree()>3)throw new Error("R1 Polynomial is not well calculated")})(),a&&a.info("> Computing R2 polynomial");(function(){if(w.R2=$l.lagrangePolynomialInterpolation([v.S2.h2w3[0],v.S2.h2w3[1],v.S2.h2w3[2],v.S2.h3w3[0],v.S2.h3w3[1],v.S2.h3w3[2]],[w.C2.evaluate(v.S2.h2w3[0]),w.C2.evaluate(v.S2.h2w3[1]),w.C2.evaluate(v.S2.h2w3[2]),w.C2.evaluate(v.S2.h3w3[0]),w.C2.evaluate(v.S2.h3w3[1]),w.C2.evaluate(v.S2.h3w3[2])],d),w.R2.degree()>5)throw new Error("R2 Polynomial is not well calculated")})(),a&&a.info("> Computing F polynomial");await async function(){a&&a.info("··· Computing F polynomial");w.F=$l.fromPolynomial(w.C0,d,a),w.F.sub(w.R0),w.F.divByZerofier(8,y.xi);let t=$l.fromPolynomial(w.C1,d,a);t.sub(w.R1),t.mulScalar(y.alpha),t.divByZerofier(4,y.xi);let e=$l.fromPolynomial(w.C2,d,a);if(e.sub(w.R2),e.mulScalar(u.square(y.alpha)),e.divByZerofier(3,y.xi),e.divByZerofier(3,y.xiw),w.F.add(t),w.F.add(e),w.F.degree()>=9*c.domainSize-6)throw new Error("F Polynomial is not well calculated")}(),a&&a.info("> Computing W1 multi exponentiation");let e=await w.F.multiExponentiation(x,"W1");return F.addPolynomial("W1",e),0}(),globalThis.gc&&globalThis.gc(),a&&a.info("> ROUND 5"),await async function(){a&&a.info("> Computing challenge y");const t=new kl(d);t.addScalar(y.alpha),t.addPolCommitment(F.getPolynomial("W1")),y.y=t.getChallenge(),a&&a.info("··· challenges.y: "+u.toString(y.y));a&&a.info("> Computing L polynomial");await async function(){a&&a.info("··· Computing L polynomial");const t=w.R0.evaluate(y.y),e=w.R1.evaluate(y.y),i=w.R2.evaluate(y.y);let n=u.sub(y.y,v.S0.h0w8[0]);for(let t=1;t<8;t++)n=u.mul(n,u.sub(y.y,v.S0.h0w8[t]));let o=u.sub(y.y,v.S1.h1w4[0]);for(let t=1;t<4;t++)o=u.mul(o,u.sub(y.y,v.S1.h1w4[t]));let l=u.sub(y.y,v.S2.h2w3[0]);for(let t=1;t<3;t++)l=u.mul(l,u.sub(y.y,v.S2.h2w3[t]));for(let t=0;t<3;t++)l=u.mul(l,u.sub(y.y,v.S2.h3w3[t]));let r=u.mul(o,l),s=u.mul(y.alpha,u.mul(n,l)),f=u.mul(u.square(y.alpha),u.mul(n,o));b.denH1=o,b.denH2=l,w.L=$l.fromPolynomial(w.C0,d,a),w.L.subScalar(t),w.L.mulScalar(r);let g=$l.fromPolynomial(w.C1,d,a);g.subScalar(e),g.mulScalar(s);let h=$l.fromPolynomial(w.C2,d,a);h.subScalar(i),h.mulScalar(f),w.L.add(g),w.L.add(h),a&&a.info("> Computing ZT polynomial");await async function(){w.ZT=$l.zerofierPolynomial([v.S0.h0w8[0],v.S0.h0w8[1],v.S0.h0w8[2],v.S0.h0w8[3],v.S0.h0w8[4],v.S0.h0w8[5],v.S0.h0w8[6],v.S0.h0w8[7],v.S1.h1w4[0],v.S1.h1w4[1],v.S1.h1w4[2],v.S1.h1w4[3],v.S2.h2w3[0],v.S2.h2w3[1],v.S2.h2w3[2],v.S2.h3w3[0],v.S2.h3w3[1],v.S2.h3w3[2]],d)}();const p=w.ZT.evaluate(y.y);if(w.F.mulScalar(p),w.L.sub(w.F),w.L.degree()>=9*c.domainSize)throw new Error("L Polynomial is not well calculated");delete m.L}(),a&&a.info("> Computing ZTS2 polynomial");await async function(){w.ZTS2=$l.zerofierPolynomial([v.S1.h1w4[0],v.S1.h1w4[1],v.S1.h1w4[2],v.S1.h1w4[3],v.S2.h2w3[0],v.S2.h2w3[1],v.S2.h2w3[2],v.S2.h3w3[0],v.S2.h3w3[1],v.S2.h3w3[2]],d)}();let e=w.ZTS2.evaluate(y.y);e=u.inv(e),w.L.mulScalar(e);const i=$l.fromCoefficientsArray([u.neg(y.y),u.one],d);a&&a.info("> Computing W' = L / ZTS2 polynomial");const n=w.L.divBy(i);if(n.degree()>0)throw new Error(`Degree of L(X)/(ZTS2(y)(X-y)) remainder is ${n.degree()} and should be 0`);if(w.L.degree()>=9*c.domainSize-1)throw new Error("Degree of L(X)/(ZTS2(y)(X-y)) is not correct");a&&a.info("> Computing W' multi exponentiation");let o=await w.L.multiExponentiation(x,"W2");return F.addPolynomial("W2",o),0}(),delete w.C0,delete w.C1,delete w.C2,delete w.R1,delete w.R2,delete w.F,delete w.L,delete w.ZT,delete w.ZTS2,await r.close(),globalThis.gc&&globalThis.gc(),F.addEvaluation("inv",function(){let t=y.xi;for(let e=0;e Reading PTau file");const{fd:n,sections:o}=await Na(e,"ptau",1);if(!o[12])throw new Error("Powers of Tau is not well prepared. Section 12 missing.");i&&i.info("> Getting curve from PTau settings");const{curve:l}=await Lo(n,o);i&&i.info("> Reading r1cs file");const{fd:r,sections:s}=await Na(t,"r1cs",1),c=await al(r,s,{loadConstraints:!1,loadCustomGates:!0});if(c.prime!==l.r)throw new Error("r1cs curve does not match powers of tau ceremony curve");const d=l.Fr,u=l.Fr.n8,f=2*l.G1.F.n8,g=2*l.G2.F.n8;let h,p={},_={},m={nVars:c.nVars,nPublic:c.nOutputs+c.nPubInputs};const w=new gl;let L=new gl;if(i&&i.info("> Processing FFlonk constraints"),await async function(t,e,a){for(let e=0;e computing k1 and k2");const[b,y]=function(){let t=d.two;for(;a(t,[],m.cirPower);)d.add(t,d.one);let e=d.add(t,d.one);for(;a(e,[t],m.cirPower);)d.add(e,d.one);return[t,e];function a(t,e,a){const i=2**a;let n=d.one;for(let o=0;o computing w3");const v=function(){let t=d.e(31624),e=vt.div(3648040478639879203707734290876212514758060733402672390616367364429301415936n,vt.e(3));return d.exp(t,e)}();i&&i.info("> computing w4");const F=d.w[2];i&&i.info("> computing w8");const x=d.w[3];i&&i.info("> computing wr");const C=function(t,e){const a=e.e(467799165886069610036046866799264026481344299079011762026774533774345988080n);return e.exp(a,2**(28-t))}(m.cirPower,l.Fr);return await async function(){i&&i.info("> Writing the zkey file");const t=await ja(a,"zkey",1,17,1<<22,1<<24);i&&i.info("··· Writing Section 1. Zkey Header");await async function(t){await Da(t,1),await t.writeULE32(Yi),await Va(t)}(t),i&&i.info(`··· Writing Section ${$i}. Additions`);await async function(t){await Da(t,$i);const e=new Uint8Array(8+2*u),a=new DataView(e.buffer);for(let n=0;n=8*m.domainSize)throw new Error("C0 Polynomial is not well calculated");await Da(t,hn),await t.write(p.C0.coef),await Va(t)}(t),globalThis.gc&&globalThis.gc();i&&i.info(`··· Writing Section ${Ji}. FFlonk Header`);await async function(t){await Da(t,Ji);const e=l.q,a=8*(Math.floor((vt.bitLength(e)-1)/64)+1);await t.writeULE32(a),await Ha(t,e,a);const i=l.r,r=8*(Math.floor((vt.bitLength(i)-1)/64)+1);let s;await t.writeULE32(r),await Ha(t,i,r),await t.writeULE32(m.nVars),await t.writeULE32(m.nPublic),await t.writeULE32(m.domainSize),await t.writeULE32(L.length),await t.writeULE32(w.length),await t.write(b),await t.write(y),await t.write(v),await t.write(F),await t.write(x),await t.write(C),s=await n.read(g,o[3][0].p+g),await t.write(s);let c=await p.C0.multiExponentiation(h,"C0");await t.write(c),await Va(t)}(t),globalThis.gc&&globalThis.gc();i&&i.info("> Writing the zkey file finished");await t.close()}(),await r.close(),await n.close(),i&&i.info("FFLONK SETUP FINISHED"),0;async function S(t,e,a,n){await Da(t,e);for(let e=0;e Checking commitments belong to G1"),!function(t,e,a){const i=t.G1;return i.isValid(e.polynomials.C1)&&i.isValid(e.polynomials.C2)&&i.isValid(e.polynomials.W1)&&i.isValid(e.polynomials.W2)&&i.isValid(a.C0)}(n,l,o))return i&&i.error("Proof commitments are not valid"),!1;if(i&&i.info("> Checking evaluations belong to F"),!function(t,e){return br(t,e.evaluations.ql)&&br(t,e.evaluations.qr)&&br(t,e.evaluations.qm)&&br(t,e.evaluations.qo)&&br(t,e.evaluations.qc)&&br(t,e.evaluations.s1)&&br(t,e.evaluations.s2)&&br(t,e.evaluations.s3)&&br(t,e.evaluations.a)&&br(t,e.evaluations.b)&&br(t,e.evaluations.c)&&br(t,e.evaluations.z)&&br(t,e.evaluations.zw)&&br(t,e.evaluations.t1w)&&br(t,e.evaluations.t2w)}(n,l))return i&&i.error("Proof evaluations are not valid."),!1;if(i&&i.info("> Checking public inputs belong to F"),!function(t,e){for(let a=0;a Computing challenges");const{challenges:c,roots:d}=function(t,e,a,i,n){const o=t.Fr,l={},r={},s=new kl(t);s.addPolCommitment(a.C0);for(let t=0;t Computing Zero polynomial evaluation Z_H(xi)"),c.zh=s.sub(c.xiN,s.one),c.invzh=s.inv(c.zh),i&&i.info("> Computing Lagrange evaluations");const u=await async function(t,e,a){const i=t.Fr,n=Math.max(1,a.nPublic),o=new et(n*i.n8);let l=new et(n*i.n8),r=i.one;for(let t=0;t Computing polynomial identities PI(X)");const f=function(t,e,a){const i=t.Fr;let n=i.zero;for(let t=0;t Computing r0(y)");const g=function(t,e,a,i,n){const o=i.Fr,l=yr(a.S0.h0w8,e.y,e.xi,i);n&&n.info("··· Computing r0(y)");let r=o.zero;for(let e=0;e<8;e++){let i=[];i[1]=a.S0.h0w8[e];for(let t=2;t<8;t++)i[t]=o.mul(i[t-1],a.S0.h0w8[e]);let n=o.add(t.evaluations.ql,o.mul(t.evaluations.qr,i[1]));n=o.add(n,o.mul(t.evaluations.qo,i[2])),n=o.add(n,o.mul(t.evaluations.qm,i[3])),n=o.add(n,o.mul(t.evaluations.qc,i[4])),n=o.add(n,o.mul(t.evaluations.s1,i[5])),n=o.add(n,o.mul(t.evaluations.s2,i[6])),n=o.add(n,o.mul(t.evaluations.s3,i[7])),r=o.add(r,o.mul(n,l[e]))}return r}(l,c,d,n,i);i&&i.info("> Computing r1(y)");const h=function(t,e,a,i,n,o){const l=n.Fr,r=yr(a.S1.h1w4,e.y,e.xi,n);o&&o.info("··· Computing T0(xi)");let s=l.mul(t.evaluations.ql,t.evaluations.a);s=l.add(s,l.mul(t.evaluations.qr,t.evaluations.b)),s=l.add(s,l.mul(t.evaluations.qm,l.mul(t.evaluations.a,t.evaluations.b))),s=l.add(s,l.mul(t.evaluations.qo,t.evaluations.c)),s=l.add(s,t.evaluations.qc),s=l.add(s,i),s=l.mul(s,e.invzh),o&&o.info("··· Computing C1(h_1ω_4^i) values");let c=l.zero;for(let e=0;e<4;e++){let i=t.evaluations.a;i=l.add(i,l.mul(a.S1.h1w4[e],t.evaluations.b));const n=l.square(a.S1.h1w4[e]);i=l.add(i,l.mul(n,t.evaluations.c)),i=l.add(i,l.mul(l.mul(n,a.S1.h1w4[e]),s)),c=l.add(c,l.mul(i,r[e]))}return c}(l,c,d,f,n,i);i&&i.info("> Computing r2(y)");const p=function(t,e,a,i,n,o,l){const r=o.Fr,s=function(t,e,a,i,n){const o=n.Fr,l=[],r=t[0].length,s=r*t.length,c=o.exp(e,s),d=o.mul(o.add(a,i),o.exp(e,r)),u=o.mul(a,i),f=o.add(o.sub(c,d),u);let g=o.mul(o.mul(o.e(r),t[0][0]),o.sub(a,i));for(let a=0;a Computing F");const _=function(t,e,a,i,n){const o=t.G1,l=t.Fr;let r=l.sub(i.y,n.S0.h0w8[0]);for(let t=1;t<8;t++)r=l.mul(r,l.sub(i.y,n.S0.h0w8[t]));i.temp=r;let s=l.sub(i.y,n.S1.h1w4[0]);for(let t=1;t<4;t++)s=l.mul(s,l.sub(i.y,n.S1.h1w4[t]));let c=l.sub(i.y,n.S2.h2w3[0]);for(let t=1;t<3;t++)c=l.mul(c,l.sub(i.y,n.S2.h2w3[t]));for(let t=0;t<3;t++)c=l.mul(c,l.sub(i.y,n.S2.h3w3[t]));i.quotient1=l.mul(i.alpha,l.div(r,s)),i.quotient2=l.mul(l.square(i.alpha),l.div(r,c));let d=o.timesFr(e.polynomials.C1,i.quotient1),u=o.timesFr(e.polynomials.C2,i.quotient2);return o.add(a.C0,o.add(d,u))}(n,l,o,c,d);i&&i.info("> Computing E");const m=function(t,e,a,i,n,o,l){const r=t.G1,s=t.Fr;let c=s.mul(o,a.quotient1),d=s.mul(l,a.quotient2);return r.timesFr(r.one,s.add(n,s.add(c,d)))}(n,0,c,0,g,h,p);i&&i.info("> Computing J");const w=function(t,e,a){const i=t.G1;return i.timesFr(e.polynomials.W1,a.temp)}(n,l,c);i&&i.info("> Validate all evaluations with a pairing");const L=await async function(t,e,a,i,n,o,l){const r=t.G1;let s=r.timesFr(e.polynomials.W2,a.y);s=r.add(r.sub(r.sub(n,o),l),s);const c=t.G2.one,d=e.polynomials.W2,u=i.X_2;return await t.pairingEq(r.neg(s),c,d,u)}(n,l,c,o,_,m,w);return i&&(L?i.info("PROOF VERIFIED SUCCESSFULLY"):i.warn("Invalid Proof")),i&&i.info("FFLONK VERIFIER FINISHED"),L},exportSolidityVerifier:yl,exportSolidityCallData:async function(t,e){const a=vr(e),i=vr(t),n=await ni(a.curve);n.G1,n.Fr;let o="";for(let t=0;t()=>(e&&(t=e(e=0)),t),c=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),l=(e,t)=>{let r={};for(var i in e)n(r,i,{get:e[i],enumerable:!0});return t||n(r,Symbol.toStringTag,{value:`Module`}),r},u=(e,t,a,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=i(t),l=0,u=c.length,d;lt[e]).bind(null,d),enumerable:!(s=r(t,d))||s.enumerable});return e},d=(e,r,i)=>(i=e==null?{}:t(a(e)),u(r||!e||!e.__esModule?n(i,`default`,{value:e,enumerable:!0}):i,e)),f=l({gzipCode:()=>p,n8q:()=>32,n8r:()=>32,pG1b:()=>_,pG1gen:()=>h,pG1zero:()=>g,pG2b:()=>b,pG2gen:()=>v,pG2zero:()=>y,pOneT:()=>x,pq:()=>488,pr:()=>m,prePSize:()=>192,preQSize:()=>S,q:()=>C,r:()=>w}),p,m,h,g,_,v,y,b,x,S,C,w,T=s((()=>{p=`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`,m=1768,h=31432,g=31528,_=3080,v=31624,y=31816,b=12456,x=32008,S=19776,C=`21888242871839275222246405745257275088696311157297823662689037894645226208583`,w=`21888242871839275222246405745257275088548364400416034343698204186575808495617`}));function E(e){return BigInt(e)}function D(e){return e<0n}function O(e){return e===0n}function k(e){return D(e)?e.toString(2).length-1:e.toString(2).length}function A(e){let t=[],n=E(e);return t.push(Number(n&255n)),t.push(Number(n>>8n&255n)),t.push(Number(n>>16n&255n)),t.push(Number(n>>24n&255n)),t}function j(e){for(var t=[],n=0;n>6,128|r&63):r<55296||r>=57344?t.push(224|r>>12,128|r>>6&63,128|r&63):(n++,r=65536+((r&1023)<<10|e.charCodeAt(n)&1023),t.push(240|r>>18,128|r>>12&63,128|r>>6&63,128|r&63))}return t}function M(e){let t=j(e);return[...L(t.length),...t]}function N(e){let t=[],n=E(e);if(D(n))throw Error(`Number cannot be negative`);for(;!O(n);)t.push(Number(n&127n)),n>>=7n;t.length==0&&t.push(0);for(let e=0;e4294967295n)throw Error(`Number too big`);if(t>2147483647n&&(t-=4294967296n),t<-2147483648n)throw Error(`Number too small`);return P(t)}function I(e){let t=E(e);if(t>18446744073709551615n)throw Error(`Number too big`);if(t>9223372036854775807n&&(t-=18446744073709551616n),t<-9223372036854775808n)throw Error(`Number too small`);return P(t)}function L(e){let t=E(e);if(t>4294967295n)throw Error(`Number too big`);return N(t)}function ee(e){return Array.from(e,function(e){return(`0`+(e&255).toString(16)).slice(-2)}).join(``)}function R(e){if(typeof e==`string`){let t=e.split(` +`);for(let e=0;e{})),ne,re=s((()=>{te(),ne=class{constructor(e){this.func=e,this.functionName=e.functionName,this.module=e.module}setLocal(e,t){let n=this.func.localIdxByName[e];if(n===void 0)throw Error(`Local Variable not defined: Function: ${this.functionName} local: ${e} `);return[...t,33,...L(n)]}teeLocal(e,t){let n=this.func.localIdxByName[e];if(n===void 0)throw Error(`Local Variable not defined: Function: ${this.functionName} local: ${e} `);return[...t,34,...L(n)]}getLocal(e){let t=this.func.localIdxByName[e];if(t===void 0)throw Error(`Local Variable not defined: Function: ${this.functionName} local: ${e} `);return[32,...L(t)]}i64_load8_s(e,t,n){let r=t||0,i=n===void 0?0:n;return[...e,48,i,...L(r)]}i64_load8_u(e,t,n){let r=t||0,i=n===void 0?0:n;return[...e,49,i,...L(r)]}i64_load16_s(e,t,n){let r=t||0,i=n===void 0?1:n;return[...e,50,i,...L(r)]}i64_load16_u(e,t,n){let r=t||0,i=n===void 0?1:n;return[...e,51,i,...L(r)]}i64_load32_s(e,t,n){let r=t||0,i=n===void 0?2:n;return[...e,52,i,...L(r)]}i64_load32_u(e,t,n){let r=t||0,i=n===void 0?2:n;return[...e,53,i,...L(r)]}i64_load(e,t,n){let r=t||0,i=n===void 0?3:n;return[...e,41,i,...L(r)]}i64_store(e,t,n,r){let i,a,o;return Array.isArray(t)?(i=0,a=3,o=t):Array.isArray(n)?(i=t,a=3,o=n):Array.isArray(r)&&(i=t,a=n,o=r),[...e,...o,55,a,...L(i)]}i64_store32(e,t,n,r){let i,a,o;return Array.isArray(t)?(i=0,a=2,o=t):Array.isArray(n)?(i=t,a=2,o=n):Array.isArray(r)&&(i=t,a=n,o=r),[...e,...o,62,a,...L(i)]}i64_store16(e,t,n,r){let i,a,o;return Array.isArray(t)?(i=0,a=1,o=t):Array.isArray(n)?(i=t,a=1,o=n):Array.isArray(r)&&(i=t,a=n,o=r),[...e,...o,61,a,...L(i)]}i64_store8(e,t,n,r){let i,a,o;return Array.isArray(t)?(i=0,a=0,o=t):Array.isArray(n)?(i=t,a=0,o=n):Array.isArray(r)&&(i=t,a=n,o=r),[...e,...o,60,a,...L(i)]}i32_load8_s(e,t,n){let r=t||0,i=n===void 0?0:n;return[...e,44,i,...L(r)]}i32_load8_u(e,t,n){let r=t||0,i=n===void 0?0:n;return[...e,45,i,...L(r)]}i32_load16_s(e,t,n){let r=t||0,i=n===void 0?1:n;return[...e,46,i,...L(r)]}i32_load16_u(e,t,n){let r=t||0,i=n===void 0?1:n;return[...e,47,i,...L(r)]}i32_load(e,t,n){let r=t||0,i=n===void 0?2:n;return[...e,40,i,...L(r)]}i32_store(e,t,n,r){let i,a,o;return Array.isArray(t)?(i=0,a=2,o=t):Array.isArray(n)?(i=t,a=2,o=n):Array.isArray(r)&&(i=t,a=n,o=r),[...e,...o,54,a,...L(i)]}i32_store16(e,t,n,r){let i,a,o;return Array.isArray(t)?(i=0,a=1,o=t):Array.isArray(n)?(i=t,a=1,o=n):Array.isArray(r)&&(i=t,a=n,o=r),[...e,...o,59,a,...L(i)]}i32_store8(e,t,n,r){let i,a,o;return Array.isArray(t)?(i=0,a=0,o=t):Array.isArray(n)?(i=t,a=0,o=n):Array.isArray(r)&&(i=t,a=n,o=r),[...e,...o,58,a,...L(i)]}call(e,...t){let n=this.module.functionIdxByName[e];if(n===void 0)throw Error(`Function not defined: Function: ${e}`);return[...[].concat(...t),16,...L(n)]}call_indirect(e,...t){return[...[].concat(...t),...e,17,0,0]}if(e,t,n){return n?[...e,4,64,...t,5,...n,11]:[...e,4,64,...t,11]}block(e){return[2,64,...e,11]}loop(...e){return[3,64,...[].concat(...e),11]}br_if(e,t){return[...t,13,...L(e)]}br(e){return[12,...L(e)]}ret(e){return[...e,15]}drop(e){return[...e,26]}i64_const(e){return[66,...I(e)]}i32_const(e){return[65,...F(e)]}i64_eqz(e){return[...e,80]}i64_eq(e,t){return[...e,...t,81]}i64_ne(e,t){return[...e,...t,82]}i64_lt_s(e,t){return[...e,...t,83]}i64_lt_u(e,t){return[...e,...t,84]}i64_gt_s(e,t){return[...e,...t,85]}i64_gt_u(e,t){return[...e,...t,86]}i64_le_s(e,t){return[...e,...t,87]}i64_le_u(e,t){return[...e,...t,88]}i64_ge_s(e,t){return[...e,...t,89]}i64_ge_u(e,t){return[...e,...t,90]}i64_add(e,t){return[...e,...t,124]}i64_sub(e,t){return[...e,...t,125]}i64_mul(e,t){return[...e,...t,126]}i64_div_s(e,t){return[...e,...t,127]}i64_div_u(e,t){return[...e,...t,128]}i64_rem_s(e,t){return[...e,...t,129]}i64_rem_u(e,t){return[...e,...t,130]}i64_and(e,t){return[...e,...t,131]}i64_or(e,t){return[...e,...t,132]}i64_xor(e,t){return[...e,...t,133]}i64_shl(e,t){return[...e,...t,134]}i64_shr_s(e,t){return[...e,...t,135]}i64_shr_u(e,t){return[...e,...t,136]}i64_extend_i32_s(e){return[...e,172]}i64_extend_i32_u(e){return[...e,173]}i64_clz(e){return[...e,121]}i64_ctz(e){return[...e,122]}i32_eqz(e){return[...e,69]}i32_eq(e,t){return[...e,...t,70]}i32_ne(e,t){return[...e,...t,71]}i32_lt_s(e,t){return[...e,...t,72]}i32_lt_u(e,t){return[...e,...t,73]}i32_gt_s(e,t){return[...e,...t,74]}i32_gt_u(e,t){return[...e,...t,75]}i32_le_s(e,t){return[...e,...t,76]}i32_le_u(e,t){return[...e,...t,77]}i32_ge_s(e,t){return[...e,...t,78]}i32_ge_u(e,t){return[...e,...t,79]}i32_add(e,t){return[...e,...t,106]}i32_sub(e,t){return[...e,...t,107]}i32_mul(e,t){return[...e,...t,108]}i32_div_s(e,t){return[...e,...t,109]}i32_div_u(e,t){return[...e,...t,110]}i32_rem_s(e,t){return[...e,...t,111]}i32_rem_u(e,t){return[...e,...t,112]}i32_and(e,t){return[...e,...t,113]}i32_or(e,t){return[...e,...t,114]}i32_xor(e,t){return[...e,...t,115]}i32_shl(e,t){return[...e,...t,116]}i32_shr_s(e,t){return[...e,...t,117]}i32_shr_u(e,t){return[...e,...t,118]}i32_rotl(e,t){return[...e,...t,119]}i32_rotr(e,t){return[...e,...t,120]}i32_wrap_i64(e){return[...e,167]}i32_clz(e){return[...e,103]}i32_ctz(e){return[...e,104]}unreachable(){return[0]}current_memory(){return[63,0]}comment(){return[]}}})),ie,ae,oe=s((()=>{re(),te(),ie={i32:127,i64:126,f32:125,f64:124,anyfunc:112,func:96,emptyblock:64},ae=class{constructor(e,t,n,r,i){if(n==`import`)this.fnType=`import`,this.moduleName=r,this.fieldName=i;else if(n==`internal`)this.fnType=`internal`;else throw Error(`Invalid function fnType: `+n);this.module=e,this.fnName=t,this.params=[],this.locals=[],this.localIdxByName={},this.code=[],this.returnType=null,this.nextLocal=0}addParam(e,t){if(this.localIdxByName[e])throw Error(`param already exists. Function: ${this.fnName}, Param: ${e} `);let n=this.nextLocal++;this.localIdxByName[e]=n,this.params.push({type:t})}addLocal(e,t,n){let r=n||1;if(this.localIdxByName[e])throw Error(`local already exists. Function: ${this.fnName}, Param: ${e} `);let i=this.nextLocal++;this.localIdxByName[e]=i,this.locals.push({type:t,length:r})}setReturnType(e){if(this.returnType)throw Error(`returnType already defined. Function: ${this.fnName}`);this.returnType=e}getSignature(){let e=[...L(this.params.length),...this.params.map(e=>ie[e.type])],t=this.returnType?[1,ie[this.returnType]]:[0];return[96,...e,...t]}getBody(){let e=this.locals.map(e=>[...L(e.length),ie[e.type]]),t=[...L(this.locals.length),...[].concat(...e),...this.code,11];return[...L(t.length),...t]}addCode(...e){this.code.push(...[].concat(...e))}getCodeBuilder(){return new ne(this)}}})),se,ce=s((()=>{oe(),te(),se=class{constructor(){this.functions=[],this.functionIdxByName={},this.nImportFunctions=0,this.nInternalFunctions=0,this.memory={pagesSize:1,moduleName:`env`,fieldName:`memory`},this.free=8,this.datas=[],this.modules={},this.exports=[],this.functionsTable=[]}build(){return this._setSignatures(),new Uint8Array([...A(1836278016),...A(1),...this._buildType(),...this._buildImport(),...this._buildFunctionDeclarations(),...this._buildFunctionsTable(),...this._buildExports(),...this._buildElements(),...this._buildCode(),...this._buildData()])}addFunction(e){if(this.functionIdxByName[e]!==void 0)throw Error(`Function already defined: ${e}`);let t=this.functions.length;return this.functionIdxByName[e]=t,this.functions.push(new ae(this,e,`internal`)),this.nInternalFunctions++,this.functions[t]}addIimportFunction(e,t,n){if(this.functionIdxByName[e]!==void 0)throw Error(`Function already defined: ${e}`);if(this.functions.length>0&&this.functions[this.functions.length-1].type==`internal`)throw Error(`Import functions must be declared before internal: ${e}`);let r=n||e,i=this.functions.length;return this.functionIdxByName[e]=i,this.functions.push(new ae(this,e,`import`,t,r)),this.nImportFunctions++,this.functions[i]}setMemory(e,t,n){this.memory={pagesSize:e,moduleName:t||`env`,fieldName:n||`memory`}}exportFunction(e,t){let n=t||e;if(this.functionIdxByName[e]===void 0)throw Error(`Function not defined: ${e}`);let r=this.functionIdxByName[e];n!=e&&(this.functionIdxByName[n]=r),this.exports.push({exportName:n,idx:r})}addFunctionToTable(e){let t=this.functionIdxByName[e];this.functionsTable.push(t)}addData(e,t){this.datas.push({offset:e,bytes:t})}alloc(e,t){let n,r;(Array.isArray(e)||ArrayBuffer.isView(e))&&t===void 0?(n=e.length,r=e):(n=e,r=t),n=(n-1>>3)+1<<3;let i=this.free;return this.free+=n,r&&this.addData(i,r),i}allocString(e){let t=new globalThis.TextEncoder().encode(e);return this.alloc([...t,0])}_setSignatures(){this.signatures=[];let e={};if(this.functionsTable.length>0){let t=this.functions[this.functionsTable[0]].getSignature(),n=`s_`+ee(t);e[n]=0,this.signatures.push(t)}for(let t=0;t{te(),le=class{constructor(e){this.func=e,this.functionName=e.functionName,this.module=e.module}setLocal(e,t){if(this.func.localIdxByName[e]===void 0)throw Error(`Local Variable not defined: Function: ${this.functionName} local: ${e} `);return[t,`set_local $${e}`]}teeLocal(e,t){if(this.func.localIdxByName[e]===void 0)throw Error(`Local Variable not defined: Function: ${this.functionName} local: ${e} `);return[t,`tee_local $${e}`]}getLocal(e){if(this.func.localIdxByName[e]===void 0)throw Error(`Local Variable not defined: Function: ${this.functionName} local: ${e} `);return`get_local $${e}`}genLoad(e,t,n,r,i){let a=e,o=r||0;o>0&&(a+=` offset=${o}`);let s=i===void 0?t:i;return s!=t&&(a+=` align=${1<0&&(l+=` offset=${o}`),s!=t&&(l+=` align=${1<{ue(),te(),de=class{constructor(e,t,n,r,i){if(n==`import`)this.fnType=`import`,this.moduleName=r,this.fieldName=i;else if(n==`internal`)this.fnType=`internal`,this.comment=r;else throw Error(`Invalid function fnType: `+n);this.module=e,this.fnName=t,this.params=[],this.locals=[],this.localIdxByName={},this.code=[],this.returnType=null,this.nextLocal=0}addParam(e,t){if(this.localIdxByName[e])throw Error(`param already exists. Function: ${this.fnName}, Param: ${e} `);let n=this.nextLocal++;this.localIdxByName[e]=n,this.params.push({type:t,name:e})}addLocal(e,t,n){if(n!==void 0&&n!=1)throw Error(`Locals greater than 1 not implemented`);if(this.localIdxByName[e])throw Error(`local already exists. Function: ${this.fnName}, Param: ${e} `);let r=this.nextLocal++;this.localIdxByName[e]=r,this.locals.push({type:t,name:e})}setReturnType(e){if(this.returnType)throw Error(`returnType already defined. Function: ${this.fnName}`);this.returnType=e}getSignature(){let e=``;for(let t=0;t{fe(),te(),pe=class{constructor(){this.functions=[],this.functionIdxByName={},this.nImportFunctions=0,this.nInternalFunctions=0,this.memory={pagesSize:1,moduleName:`env`,fieldName:`memory`},this.free=8,this.datas=[],this.modules={},this.exports=[],this.functionsTable=[]}build(){let e=[];return this._setSignatures(),e.push(this._buildType()),e.push(this._buildImport()),this.functionsTable.length>0&&e.push(this._buildFunctionsTable()),this.exports.length>0&&e.push(this._buildExports()),this.functionsTable.length>0&&e.push(this._buildElements()),this.nInternalFunctions>0&&e.push(this._buildFunctions()),e.push(this._buildData()),[`(module`,R(e),`)`]}addFunction(e,t){if(this.functionIdxByName[e]!==void 0)throw Error(`Function already defined: ${e}`);let n=this.functions.length;return this.functionIdxByName[e]=n,this.functions.push(new de(this,e,`internal`,t)),this.nInternalFunctions++,this.functions[n]}addIimportFunction(e,t,n){if(this.functionIdxByName[e]!==void 0)throw Error(`Function already defined: ${e}`);if(this.functions.length>0&&this.functions[this.functions.length-1].type==`internal`)throw Error(`Import functions must be declared before internal: ${e}`);let r=n||e,i=this.functions.length;return this.functionIdxByName[e]=i,this.functions.push(new de(this,e,`import`,t,r)),this.nImportFunctions++,this.functions[i]}setMemory(e,t,n){this.memory={pagesSize:e,moduleName:t||`env`,fieldName:n||`memory`}}exportFunction(e,t){let n=t||e;if(this.functionIdxByName[e]===void 0)throw Error(`Function not defined: ${e}`);let r=this.functionIdxByName[e];n!=e&&(this.functionIdxByName[n]=r),this.exports.push({exportName:n,idx:r})}addFunctionToTable(e){let t=this.functionIdxByName[e];this.functionsTable.push(t)}addData(e,t){this.datas.push({offset:e,bytes:t})}alloc(e,t){let n,r;(Array.isArray(e)||ArrayBuffer.isView(e))&&t===void 0?(n=e.length,r=e):(n=e,r=t),n=(n-1>>3)+1<<3;let i=this.free;return this.free+=n,r&&this.addData(i,r),i}allocString(e){let t=new TextEncoder().encode(e);return this.alloc([...t,0])}_setSignatures(){this.signatures=[];let e={};if(this.functionsTable.length>0){let t=this.functions[this.functionsTable[0]].getSignature(),n=this.functions[this.functionsTable[0]].getSignatureName();e[n]=0,this.signatures.push(t)}for(let t=0;t126||e[n]==34||e[n]==92){let r=e[n].toString(16);for(;r.length<2;)r=`0`+r;t+=`\\`+r}else t+=String.fromCharCode(e[n]);return t+=`"`,t}}}}));async function he(e,t,n){let r=new ge;r.defBytes=t,r.bitsPerBytes=n||32,r.memory=new WebAssembly.Memory({initial:2e4}),r.i32=new Uint32Array(r.memory.buffer),r.i8=new Uint8Array(r.memory.buffer);let i=new se;i.addIimportFunction(`debug_log32`,`debug`,`log32`).addParam(`x`,`i32`);let a=i.addIimportFunction(`debug_log64`,`debug`,`log64`);a.addParam(`x`,`i32`),a.addParam(`y`,`i32`),c(i),l(i),e(i,r);let o=i.build(),s=await WebAssembly.compile(o);return r.log=console.log,r.instance=await WebAssembly.instantiate(s,{env:{memory:r.memory},debug:{log32:function(e){e<0&&(e=4294967296+e);let t=e.toString(16);for(;t.length<8;)t=`0`+t;r.log(t+`: `+e.toString())},log64:function(e,t){e<0&&(e=4294967296+e),t<0&&(t=4294967296+t);let n=BigInt(e)+(BigInt(t)<<32n),i=n.toString(16);for(;i.length<16;)i=`0`+i;r.log(i+`: `+n.toString())}}}),Object.assign(r,r.instance.exports),Object.assign(r,i.modules),r;function c(e){let t=e.addFunction(`log32`);t.addParam(`x`,`i32`);let n=t.getCodeBuilder();t.addCode(n.call(`debug_log32`,n.getLocal(`x`)))}function l(e){let t=e.addFunction(`log64`);t.addParam(`x`,`i64`);let n=t.getCodeBuilder();t.addCode(n.call(`debug_log64`,n.i32_wrap_i64(n.getLocal(`x`)),n.i32_wrap_i64(n.i64_shr_u(n.getLocal(`x`),n.i64_const(32)))))}}var ge,_e=s((()=>{ce(),ge=class{constructor(){}alloc(e){e===void 0&&(e=this.defBytes),e=(e-1>>3)+1<<3;let t=this.i32[0];return this.i32[0]+=e,t}set(e,t,n){Array.isArray(t)||(t=[t]),n===void 0&&(n=this.defBytes);let r=Math.floor((n-1)/4)+1,i=e,a=1n<>2]=Number(t),n=e,i+=4}if(n!==0n)throw Error(`Expected v to be 0`)}return e}get(e,t,n){n===void 0&&(t===void 0?(t=1,n=this.defBytes):(t=n,n=this.defBytes));let r=Math.floor((n-1)/4)+1,i=1n<=0;n--){t*=i;let r=this.i32[(e>>2)+n];this.bitsPerBytes<32&&r&2147483648&&(r-=4294967296),t+=BigInt(r)}a.push(t),e+=r*4}return a.length==1?a[0]:a}}})),ve=l({ModuleBuilder:()=>se,ModuleBuilderWat:()=>pe,buildProtoboard:()=>he}),ye=s((()=>{ce(),me(),_e()}));function z(e,t){let n=Array(t),r=BigInt(e);for(let e=0;e>=8n;return n}var be=s((()=>{}));function xe(e,t,n){let r=n||`int`;if(e.modules[r])return r;e.modules[r]={};let i=t*2,a=t*8;function o(){let n=e.addFunction(r+`_copy`);n.addParam(`px`,`i32`),n.addParam(`pr`,`i32`);let i=n.getCodeBuilder();for(let e=0;e>1&&r>1,e>>1)))),t.addCode(n.setLocal(`c1`,n.i64_add(n.getLocal(`c1`),n.i64_shr_u(n.getLocal(`c0`),n.i64_const(32)))))),e>0&&(t.addCode(n.setLocal(`c0`,n.i64_add(n.i64_and(n.getLocal(`c0`),n.i64_const(4294967295)),n.i64_and(n.getLocal(s),n.i64_const(4294967295))))),t.addCode(n.setLocal(`c1`,n.i64_add(n.i64_add(n.getLocal(`c1`),n.i64_shr_u(n.getLocal(`c0`),n.i64_const(32))),n.getLocal(c))))),t.addCode(n.i64_store32(n.getLocal(`r`),e*4,n.getLocal(`c0`))),t.addCode(n.setLocal(s,n.getLocal(`c1`)),n.setLocal(c,n.i64_shr_u(n.getLocal(s),n.i64_const(32))))}t.addCode(n.i64_store32(n.getLocal(`r`),i*4*2-4,n.getLocal(s)))}function g(){let t=e.addFunction(r+`_squareOld`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let n=t.getCodeBuilder();t.addCode(n.call(r+`_mul`,n.getLocal(`x`),n.getLocal(`x`),n.getLocal(`r`)))}function _(){let t=e.addFunction(r+`__mul1`);t.addParam(`px`,`i32`),t.addParam(`y`,`i64`),t.addParam(`pr`,`i32`),t.addLocal(`c`,`i64`);let n=t.getCodeBuilder();t.addCode(n.setLocal(`c`,n.i64_mul(n.i64_load32_u(n.getLocal(`px`),0,0),n.getLocal(`y`)))),t.addCode(n.i64_store32(n.getLocal(`pr`),0,0,n.getLocal(`c`)));for(let e=1;e{}));function Ce(e,t,n,r,i,a,o){let s=e.addFunction(t);s.addParam(`base`,`i32`),s.addParam(`scalar`,`i32`),s.addParam(`scalarLength`,`i32`),s.addParam(`r`,`i32`),s.addLocal(`i`,`i32`),s.addLocal(`b`,`i32`);let c=s.getCodeBuilder(),l=c.i32_const(e.alloc(n));s.addCode(c.if(c.i32_eqz(c.getLocal(`scalarLength`)),[...c.call(o,c.getLocal(`r`)),...c.ret([])])),s.addCode(c.call(a,c.getLocal(`base`),l)),s.addCode(c.call(o,c.getLocal(`r`))),s.addCode(c.setLocal(`i`,c.getLocal(`scalarLength`))),s.addCode(c.block(c.loop(c.setLocal(`i`,c.i32_sub(c.getLocal(`i`),c.i32_const(1))),c.setLocal(`b`,c.i32_load8_u(c.i32_add(c.getLocal(`scalar`),c.getLocal(`i`)))),...u(),c.br_if(1,c.i32_eqz(c.getLocal(`i`))),c.br(0))));function u(){let e=[];for(let t=0;t<8;t++)e.push(...c.call(i,c.getLocal(`r`),c.getLocal(`r`)),...c.if(c.i32_ge_u(c.getLocal(`b`),c.i32_const(128>>t)),[...c.setLocal(`b`,c.i32_sub(c.getLocal(`b`),c.i32_const(128>>t))),...c.call(r,c.getLocal(`r`),l,c.getLocal(`r`))]));return e}}var we=s((()=>{}));function Te(e,t){let n=e.modules[t].n64*8,r=e.addFunction(t+`_batchInverse`);r.addParam(`pIn`,`i32`),r.addParam(`inStep`,`i32`),r.addParam(`n`,`i32`),r.addParam(`pOut`,`i32`),r.addParam(`outStep`,`i32`),r.addLocal(`itAux`,`i32`),r.addLocal(`itIn`,`i32`),r.addLocal(`itOut`,`i32`),r.addLocal(`i`,`i32`);let i=r.getCodeBuilder(),a=i.i32_const(e.alloc(n));r.addCode(i.setLocal(`itAux`,i.i32_load(i.i32_const(0))),i.i32_store(i.i32_const(0),i.i32_add(i.getLocal(`itAux`),i.i32_mul(i.i32_add(i.getLocal(`n`),i.i32_const(1)),i.i32_const(n))))),r.addCode(i.call(t+`_one`,i.getLocal(`itAux`)),i.setLocal(`itIn`,i.getLocal(`pIn`)),i.setLocal(`itAux`,i.i32_add(i.getLocal(`itAux`),i.i32_const(n))),i.setLocal(`i`,i.i32_const(0)),i.block(i.loop(i.br_if(1,i.i32_eq(i.getLocal(`i`),i.getLocal(`n`))),i.if(i.call(t+`_isZero`,i.getLocal(`itIn`)),i.call(t+`_copy`,i.i32_sub(i.getLocal(`itAux`),i.i32_const(n)),i.getLocal(`itAux`)),i.call(t+`_mul`,i.getLocal(`itIn`),i.i32_sub(i.getLocal(`itAux`),i.i32_const(n)),i.getLocal(`itAux`))),i.setLocal(`itIn`,i.i32_add(i.getLocal(`itIn`),i.getLocal(`inStep`))),i.setLocal(`itAux`,i.i32_add(i.getLocal(`itAux`),i.i32_const(n))),i.setLocal(`i`,i.i32_add(i.getLocal(`i`),i.i32_const(1))),i.br(0))),i.setLocal(`itIn`,i.i32_sub(i.getLocal(`itIn`),i.getLocal(`inStep`))),i.setLocal(`itAux`,i.i32_sub(i.getLocal(`itAux`),i.i32_const(n))),i.setLocal(`itOut`,i.i32_add(i.getLocal(`pOut`),i.i32_mul(i.i32_sub(i.getLocal(`n`),i.i32_const(1)),i.getLocal(`outStep`)))),i.call(t+`_inverse`,i.getLocal(`itAux`),i.getLocal(`itAux`)),i.block(i.loop(i.br_if(1,i.i32_eqz(i.getLocal(`i`))),i.if(i.call(t+`_isZero`,i.getLocal(`itIn`)),[...i.call(t+`_copy`,i.getLocal(`itAux`),i.i32_sub(i.getLocal(`itAux`),i.i32_const(n))),...i.call(t+`_zero`,i.getLocal(`itOut`))],[...i.call(t+`_copy`,i.i32_sub(i.getLocal(`itAux`),i.i32_const(n)),a),...i.call(t+`_mul`,i.getLocal(`itAux`),i.getLocal(`itIn`),i.i32_sub(i.getLocal(`itAux`),i.i32_const(n))),...i.call(t+`_mul`,i.getLocal(`itAux`),a,i.getLocal(`itOut`))]),i.setLocal(`itIn`,i.i32_sub(i.getLocal(`itIn`),i.getLocal(`inStep`))),i.setLocal(`itOut`,i.i32_sub(i.getLocal(`itOut`),i.getLocal(`outStep`))),i.setLocal(`itAux`,i.i32_sub(i.getLocal(`itAux`),i.i32_const(n))),i.setLocal(`i`,i.i32_sub(i.getLocal(`i`),i.i32_const(1))),i.br(0)))),r.addCode(i.i32_store(i.i32_const(0),i.getLocal(`itAux`)))}var Ee,De=s((()=>{Ee=Te}));function Oe(e,t,n,r,i,a){a===void 0&&(a=r{ke=Oe}));function je(e,t,n,r,i,a){a===void 0&&(a=r{Me=je}));function Pe(e,t){return e===t?0:e>t?1:-1}function Fe(e){return e*e}function Ie(e){return e%2n!=0n}function Le(e){return e%2n==0n}function Re(e){return e<0n}function ze(e){return e>0n}function Be(e){return Re(e)?e.toString(2).length-1:e.toString(2).length}function Ve(e){return e<0n?-e:e}function He(e){return Ve(e)===1n}function Ue(e,t){for(var n=0n,r=1n,i=t,a=Ve(e),o,s,c;a!==0n;)o=i/a,s=n,c=i,n=r,i=a,r=s-o*r,a=c-o*a;if(!He(i))throw Error(e.toString()+` and `+t.toString()+` are not co-prime`);return Pe(n,0n)===-1&&(n+=t),Re(e)?-n:n}function We(e,t,n){if(n===0n)throw Error(`Cannot take modPow with modulus 0`);var r=1n,i=e%n;for(Re(t)&&(t*=-1n,i=Ue(i,n));ze(t);){if(i===0n)return 0n;Ie(t)&&(r=r*i%n),t/=2n,i=Fe(i)%n}return r}function Ge(e,t){return e=e>=0n?e:-e,t=t>=0n?t:-t,e===t?0:e>t?1:-1}function Ke(e,t){return t===0n?!1:He(t)?!0:Ge(t,2n)===0?Le(e):e%t===0n}function qe(e){var t=Ve(e);if(He(t))return!1;if(t===2n||t===3n||t===5n)return!0;if(Le(t)||Ke(t,3n)||Ke(t,5n))return!1;if(t<49n)return!0}function Je(e){return e-1n}function Ye(e){switch(Ve(e)){case 21888242871839275222246405745257275088696311157297823662689037894645226208583n:case 21888242871839275222246405745257275088548364400416034343698204186575808495617n:case 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787n:case 52435875175126190479447740508185965837690552500527637822603658699938581184513n:case 41898490967918953402344214791240637128170709919953949071783502921025352812571106773058893763790338921418070971888458477323173057491593855069696241854796396165721416325350064441470418137846398469611935719059908164220784476160001n:return!0}return!1}function Xe(e,t){for(var n=Je(e),r=n,i=0,a,o,s;Le(r);)r/=2n,i++;next:for(o=0;o{}));function $e(e,t,n,r){let i=BigInt(t),a=Math.floor((Be(i-1n)-1)/64)+1,o=a*2,s=a*8,c=n||`f1m`;if(e.modules[c])return c;let l=xe(e,a,r),u=e.alloc(s,z(i,s)),d=e.alloc(z(Fe(1n<>1n,g=e.alloc(s,z(h,s)),_=h+1n,v=e.alloc(s,z(_,s));e.modules[c]={pq:u,pR2:d,n64:a,q:i,pOne:f,pZero:p,pePlusOne:v};function y(){let t=e.addFunction(c+`_one`);t.addParam(`pr`,`i32`);let n=t.getCodeBuilder();t.addCode(n.call(l+`_copy`,n.i32_const(f),n.getLocal(`pr`)))}function b(){let t=e.addFunction(c+`_add`);t.addParam(`x`,`i32`),t.addParam(`y`,`i32`),t.addParam(`r`,`i32`);let n=t.getCodeBuilder();t.addCode(n.if(n.call(l+`_add`,n.getLocal(`x`),n.getLocal(`y`),n.getLocal(`r`)),n.drop(n.call(l+`_sub`,n.getLocal(`r`),n.i32_const(u),n.getLocal(`r`))),n.if(n.call(l+`_gte`,n.getLocal(`r`),n.i32_const(u)),n.drop(n.call(l+`_sub`,n.getLocal(`r`),n.i32_const(u),n.getLocal(`r`))))))}function x(){let t=e.addFunction(c+`_sub`);t.addParam(`x`,`i32`),t.addParam(`y`,`i32`),t.addParam(`r`,`i32`);let n=t.getCodeBuilder();t.addCode(n.if(n.call(l+`_sub`,n.getLocal(`x`),n.getLocal(`y`),n.getLocal(`r`)),n.drop(n.call(l+`_add`,n.getLocal(`r`),n.i32_const(u),n.getLocal(`r`)))))}function S(){let t=e.addFunction(c+`_neg`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let n=t.getCodeBuilder();t.addCode(n.call(c+`_sub`,n.i32_const(p),n.getLocal(`x`),n.getLocal(`r`)))}function C(){let t=e.addFunction(c+`_isNegative`);t.addParam(`x`,`i32`),t.setReturnType(`i32`);let n=t.getCodeBuilder(),r=n.i32_const(e.alloc(s));t.addCode(n.call(c+`_fromMontgomery`,n.getLocal(`x`),r),n.call(l+`_gte`,r,n.i32_const(v)))}function w(){let t=e.addFunction(c+`_sign`);t.addParam(`x`,`i32`),t.setReturnType(`i32`);let n=t.getCodeBuilder(),r=n.i32_const(e.alloc(s));t.addCode(n.if(n.call(l+`_isZero`,n.getLocal(`x`)),n.ret(n.i32_const(0))),n.call(c+`_fromMontgomery`,n.getLocal(`x`),r),n.if(n.call(l+`_gte`,r,n.i32_const(v)),n.ret(n.i32_const(-1))),n.ret(n.i32_const(1)))}function T(){let t=e.alloc(o*o*8),n=e.addFunction(c+`_mReduct`);n.addParam(`t`,`i32`),n.addParam(`r`,`i32`),n.addLocal(`np32`,`i64`),n.addLocal(`c`,`i64`),n.addLocal(`m`,`i64`);let r=n.getCodeBuilder(),a=Number(4294967296n-Ue(i,4294967296n));n.addCode(r.setLocal(`np32`,r.i64_const(a)));for(let e=0;e=o&&t.addCode(n.i64_store32(n.getLocal(`r`),(e-o)*4,n.getLocal(m))),[m,h]=[h,m],t.addCode(n.setLocal(h,n.i64_shr_u(n.getLocal(m),n.i64_const(32))))}t.addCode(n.i64_store32(n.getLocal(`r`),o*4-4,n.getLocal(m))),t.addCode(n.if(n.i32_wrap_i64(n.getLocal(h)),n.drop(n.call(l+`_sub`,n.getLocal(`r`),n.i32_const(u),n.getLocal(`r`))),n.if(n.call(l+`_gte`,n.getLocal(`r`),n.i32_const(u)),n.drop(n.call(l+`_sub`,n.getLocal(`r`),n.i32_const(u),n.getLocal(`r`))))))}function D(){let t=e.addFunction(c+`_square`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`),t.addLocal(`c0`,`i64`),t.addLocal(`c1`,`i64`),t.addLocal(`c0_old`,`i64`),t.addLocal(`c1_old`,`i64`),t.addLocal(`np32`,`i64`);for(let e=0;e>1&&r>1,e>>1)))),t.addCode(n.setLocal(`c1`,n.i64_add(n.getLocal(`c1`),n.i64_shr_u(n.getLocal(`c0`),n.i64_const(32)))))),e>0&&(t.addCode(n.setLocal(`c0`,n.i64_add(n.i64_and(n.getLocal(`c0`),n.i64_const(4294967295)),n.i64_and(n.getLocal(p),n.i64_const(4294967295))))),t.addCode(n.setLocal(`c1`,n.i64_add(n.i64_add(n.getLocal(`c1`),n.i64_shr_u(n.getLocal(`c0`),n.i64_const(32))),n.getLocal(m)))));for(let r=Math.max(1,e-o+1);r<=e&&r=o&&t.addCode(n.i64_store32(n.getLocal(`r`),(e-o)*4,n.getLocal(`c0`))),t.addCode(n.setLocal(p,n.getLocal(`c1`)),n.setLocal(m,n.i64_shr_u(n.getLocal(p),n.i64_const(32))))}t.addCode(n.i64_store32(n.getLocal(`r`),o*4-4,n.getLocal(p))),t.addCode(n.if(n.i32_wrap_i64(n.getLocal(m)),n.drop(n.call(l+`_sub`,n.getLocal(`r`),n.i32_const(u),n.getLocal(`r`))),n.if(n.call(l+`_gte`,n.getLocal(`r`),n.i32_const(u)),n.drop(n.call(l+`_sub`,n.getLocal(`r`),n.i32_const(u),n.getLocal(`r`))))))}function O(){let t=e.addFunction(c+`_squareOld`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let n=t.getCodeBuilder();t.addCode(n.call(c+`_mul`,n.getLocal(`x`),n.getLocal(`x`),n.getLocal(`r`)))}function k(){let t=e.addFunction(c+`_toMontgomery`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let n=t.getCodeBuilder();t.addCode(n.call(c+`_mul`,n.getLocal(`x`),n.i32_const(d),n.getLocal(`r`)))}function A(){let t=e.alloc(s*2),n=e.addFunction(c+`_fromMontgomery`);n.addParam(`x`,`i32`),n.addParam(`r`,`i32`);let r=n.getCodeBuilder();n.addCode(r.call(l+`_copy`,r.getLocal(`x`),r.i32_const(t))),n.addCode(r.call(l+`_zero`,r.i32_const(t+s))),n.addCode(r.call(c+`_mReduct`,r.i32_const(t),r.getLocal(`r`)))}function j(){let t=e.addFunction(c+`_inverse`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let n=t.getCodeBuilder();t.addCode(n.call(c+`_fromMontgomery`,n.getLocal(`x`),n.getLocal(`r`))),t.addCode(n.call(l+`_inverseMod`,n.getLocal(`r`),n.i32_const(u),n.getLocal(`r`))),t.addCode(n.call(c+`_toMontgomery`,n.getLocal(`r`),n.getLocal(`r`)))}let M=2n;if(Ze(i))for(;We(M,h,i)!==m;)M+=1n;let N=0,P=m;for(;!Ie(P)&&P!==0n;)N++,P>>=1n;let F=e.alloc(s,z(P,s)),I=We(M,P,i),L=e.alloc(z((I<>1n,R=e.alloc(s,z(ee,s));function te(){let t=e.addFunction(c+`_sqrt`);t.addParam(`n`,`i32`),t.addParam(`r`,`i32`),t.addLocal(`m`,`i32`),t.addLocal(`i`,`i32`),t.addLocal(`j`,`i32`);let n=t.getCodeBuilder(),r=n.i32_const(f),i=n.i32_const(e.alloc(s)),a=n.i32_const(e.alloc(s)),o=n.i32_const(e.alloc(s)),l=n.i32_const(e.alloc(s)),u=n.i32_const(e.alloc(s));t.addCode(n.if(n.call(c+`_isZero`,n.getLocal(`n`)),n.ret(n.call(c+`_zero`,n.getLocal(`r`)))),n.setLocal(`m`,n.i32_const(N)),n.call(c+`_copy`,n.i32_const(L),i),n.call(c+`_exp`,n.getLocal(`n`),n.i32_const(F),n.i32_const(s),a),n.call(c+`_exp`,n.getLocal(`n`),n.i32_const(R),n.i32_const(s),o),n.block(n.loop(n.br_if(1,n.call(c+`_eq`,a,r)),n.call(c+`_square`,a,l),n.setLocal(`i`,n.i32_const(1)),n.block(n.loop(n.br_if(1,n.call(c+`_eq`,l,r)),n.call(c+`_square`,l,l),n.setLocal(`i`,n.i32_add(n.getLocal(`i`),n.i32_const(1))),n.br(0))),n.call(c+`_copy`,i,u),n.setLocal(`j`,n.i32_sub(n.i32_sub(n.getLocal(`m`),n.getLocal(`i`)),n.i32_const(1))),n.block(n.loop(n.br_if(1,n.i32_eqz(n.getLocal(`j`))),n.call(c+`_square`,u,u),n.setLocal(`j`,n.i32_sub(n.getLocal(`j`),n.i32_const(1))),n.br(0))),n.setLocal(`m`,n.getLocal(`i`)),n.call(c+`_square`,u,i),n.call(c+`_mul`,a,i,a),n.call(c+`_mul`,o,u,o),n.br(0))),n.if(n.call(c+`_isNegative`,o),n.call(c+`_neg`,o,n.getLocal(`r`)),n.call(c+`_copy`,o,n.getLocal(`r`))))}function ne(){let t=e.addFunction(c+`_isSquare`);t.addParam(`n`,`i32`),t.setReturnType(`i32`);let n=t.getCodeBuilder(),r=n.i32_const(f),i=n.i32_const(e.alloc(s));t.addCode(n.if(n.call(c+`_isZero`,n.getLocal(`n`)),n.ret(n.i32_const(1))),n.call(c+`_exp`,n.getLocal(`n`),n.i32_const(g),n.i32_const(s),i),n.call(c+`_eq`,i,r))}function re(){let t=e.addFunction(c+`_load`);t.addParam(`scalar`,`i32`),t.addParam(`scalarLen`,`i32`),t.addParam(`r`,`i32`),t.addLocal(`p`,`i32`),t.addLocal(`l`,`i32`),t.addLocal(`i`,`i32`),t.addLocal(`j`,`i32`);let n=t.getCodeBuilder(),r=n.i32_const(e.alloc(s)),i=e.alloc(s),a=n.i32_const(i);t.addCode(n.call(l+`_zero`,n.getLocal(`r`)),n.setLocal(`i`,n.i32_const(s)),n.setLocal(`p`,n.getLocal(`scalar`)),n.block(n.loop(n.br_if(1,n.i32_gt_u(n.getLocal(`i`),n.getLocal(`scalarLen`))),n.if(n.i32_eq(n.getLocal(`i`),n.i32_const(s)),n.call(c+`_one`,r),n.call(c+`_mul`,r,n.i32_const(d),r)),n.call(c+`_mul`,n.getLocal(`p`),r,a),n.call(c+`_add`,n.getLocal(`r`),a,n.getLocal(`r`)),n.setLocal(`p`,n.i32_add(n.getLocal(`p`),n.i32_const(s))),n.setLocal(`i`,n.i32_add(n.getLocal(`i`),n.i32_const(s))),n.br(0))),n.setLocal(`l`,n.i32_rem_u(n.getLocal(`scalarLen`),n.i32_const(s))),n.if(n.i32_eqz(n.getLocal(`l`)),n.ret([])),n.call(l+`_zero`,a),n.setLocal(`j`,n.i32_const(0)),n.block(n.loop(n.br_if(1,n.i32_eq(n.getLocal(`j`),n.getLocal(`l`))),n.i32_store8(n.getLocal(`j`),i,n.i32_load8_u(n.getLocal(`p`))),n.setLocal(`p`,n.i32_add(n.getLocal(`p`),n.i32_const(1))),n.setLocal(`j`,n.i32_add(n.getLocal(`j`),n.i32_const(1))),n.br(0))),n.if(n.i32_eq(n.getLocal(`i`),n.i32_const(s)),n.call(c+`_one`,r),n.call(c+`_mul`,r,n.i32_const(d),r)),n.call(c+`_mul`,a,r,a),n.call(c+`_add`,n.getLocal(`r`),a,n.getLocal(`r`)))}function ie(){let t=e.addFunction(c+`_timesScalar`);t.addParam(`x`,`i32`),t.addParam(`scalar`,`i32`),t.addParam(`scalarLen`,`i32`),t.addParam(`r`,`i32`);let n=t.getCodeBuilder(),r=n.i32_const(e.alloc(s));t.addCode(n.call(c+`_load`,n.getLocal(`scalar`),n.getLocal(`scalarLen`),r),n.call(c+`_toMontgomery`,r,r),n.call(c+`_mul`,n.getLocal(`x`),r,n.getLocal(`r`)))}function ae(){let t=e.addFunction(c+`_isOne`);t.addParam(`x`,`i32`),t.setReturnType(`i32`);let n=t.getCodeBuilder();t.addCode(n.ret(n.call(l+`_eq`,n.getLocal(`x`),n.i32_const(f))))}return e.exportFunction(l+`_copy`,c+`_copy`),e.exportFunction(l+`_zero`,c+`_zero`),e.exportFunction(l+`_isZero`,c+`_isZero`),e.exportFunction(l+`_eq`,c+`_eq`),ae(),b(),x(),S(),T(),E(),D(),O(),k(),A(),C(),w(),j(),y(),re(),ie(),Ee(e,c),ke(e,c+`_batchToMontgomery`,c+`_toMontgomery`,s,s),ke(e,c+`_batchFromMontgomery`,c+`_fromMontgomery`,s,s),ke(e,c+`_batchNeg`,c+`_neg`,s,s),Me(e,c+`_batchAdd`,c+`_add`,s,s),Me(e,c+`_batchSub`,c+`_sub`,s,s),Me(e,c+`_batchMul`,c+`_mul`,s,s),e.exportFunction(c+`_add`),e.exportFunction(c+`_sub`),e.exportFunction(c+`_neg`),e.exportFunction(c+`_isNegative`),e.exportFunction(c+`_isOne`),e.exportFunction(c+`_sign`),e.exportFunction(c+`_mReduct`),e.exportFunction(c+`_mul`),e.exportFunction(c+`_square`),e.exportFunction(c+`_squareOld`),e.exportFunction(c+`_fromMontgomery`),e.exportFunction(c+`_toMontgomery`),e.exportFunction(c+`_inverse`),e.exportFunction(c+`_one`),e.exportFunction(c+`_load`),e.exportFunction(c+`_timesScalar`),Ce(e,c+`_exp`,s,c+`_mul`,c+`_square`,l+`_copy`,c+`_one`),e.exportFunction(c+`_exp`),e.exportFunction(c+`_batchInverse`),Ze(i)&&(te(),ne(),e.exportFunction(c+`_sqrt`),e.exportFunction(c+`_isSquare`)),e.exportFunction(c+`_batchToMontgomery`),e.exportFunction(c+`_batchFromMontgomery`),c}var et=s((()=>{Se(),be(),we(),De(),Ae(),Ne(),Qe()}));function tt(e,t,n,r,i){let a=BigInt(t),o=Math.floor((Be(a-1n)-1)/64)+1,s=o*8,c=n||`f1`;if(e.modules[c])return c;e.modules[c]={n64:o};let l=i||`int`,u=$e(e,a,r,l),d=e.modules[u].pR2,f=e.modules[u].pq,p=e.modules[u].pePlusOne;function m(){let t=e.alloc(s),n=e.addFunction(c+`_mul`);n.addParam(`x`,`i32`),n.addParam(`y`,`i32`),n.addParam(`r`,`i32`);let r=n.getCodeBuilder();n.addCode(r.call(u+`_mul`,r.getLocal(`x`),r.getLocal(`y`),r.i32_const(t))),n.addCode(r.call(u+`_mul`,r.i32_const(t),r.i32_const(d),r.getLocal(`r`)))}function h(){let t=e.addFunction(c+`_square`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let n=t.getCodeBuilder();t.addCode(n.call(c+`_mul`,n.getLocal(`x`),n.getLocal(`x`),n.getLocal(`r`)))}function g(){let t=e.addFunction(c+`_inverse`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let n=t.getCodeBuilder();t.addCode(n.call(l+`_inverseMod`,n.getLocal(`x`),n.i32_const(f),n.getLocal(`r`)))}function _(){let t=e.addFunction(c+`_isNegative`);t.addParam(`x`,`i32`),t.setReturnType(`i32`);let n=t.getCodeBuilder();t.addCode(n.call(l+`_gte`,n.getLocal(`x`),n.i32_const(p)))}return m(),h(),g(),_(),e.exportFunction(u+`_add`,c+`_add`),e.exportFunction(u+`_sub`,c+`_sub`),e.exportFunction(u+`_neg`,c+`_neg`),e.exportFunction(c+`_mul`),e.exportFunction(c+`_square`),e.exportFunction(c+`_inverse`),e.exportFunction(c+`_isNegative`),e.exportFunction(u+`_copy`,c+`_copy`),e.exportFunction(u+`_zero`,c+`_zero`),e.exportFunction(u+`_one`,c+`_one`),e.exportFunction(u+`_isZero`,c+`_isZero`),e.exportFunction(u+`_eq`,c+`_eq`),c}var nt=s((()=>{et(),Qe()}));function rt(e,t,n,r){if(e.modules[n])return n;let i=e.modules[r].n64*8,a=e.modules[r].q;e.modules[n]={n64:e.modules[r].n64*2};function o(){let t=e.addFunction(n+`_add`);t.addParam(`x`,`i32`),t.addParam(`y`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.getLocal(`y`),l=a.i32_add(a.getLocal(`y`),a.i32_const(i)),u=a.getLocal(`r`),d=a.i32_add(a.getLocal(`r`),a.i32_const(i));t.addCode(a.call(r+`_add`,o,c,u),a.call(r+`_add`,s,l,d))}function s(){let t=e.addFunction(n+`_timesScalar`);t.addParam(`x`,`i32`),t.addParam(`scalar`,`i32`),t.addParam(`scalarLen`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.getLocal(`r`),l=a.i32_add(a.getLocal(`r`),a.i32_const(i));t.addCode(a.call(r+`_timesScalar`,o,a.getLocal(`scalar`),a.getLocal(`scalarLen`),c),a.call(r+`_timesScalar`,s,a.getLocal(`scalar`),a.getLocal(`scalarLen`),l))}function c(){let t=e.addFunction(n+`_sub`);t.addParam(`x`,`i32`),t.addParam(`y`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.getLocal(`y`),l=a.i32_add(a.getLocal(`y`),a.i32_const(i)),u=a.getLocal(`r`),d=a.i32_add(a.getLocal(`r`),a.i32_const(i));t.addCode(a.call(r+`_sub`,o,c,u),a.call(r+`_sub`,s,l,d))}function l(){let t=e.addFunction(n+`_neg`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.getLocal(`r`),l=a.i32_add(a.getLocal(`r`),a.i32_const(i));t.addCode(a.call(r+`_neg`,o,c),a.call(r+`_neg`,s,l))}function u(){let t=e.addFunction(n+`_conjugate`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.getLocal(`r`),l=a.i32_add(a.getLocal(`r`),a.i32_const(i));t.addCode(a.call(r+`_copy`,o,c),a.call(r+`_neg`,s,l))}function d(){let t=e.addFunction(n+`_isNegative`);t.addParam(`x`,`i32`),t.setReturnType(`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i));t.addCode(a.if(a.call(r+`_isZero`,s),a.ret(a.call(r+`_isNegative`,o))),a.ret(a.call(r+`_isNegative`,s)))}function f(){let a=e.addFunction(n+`_mul`);a.addParam(`x`,`i32`),a.addParam(`y`,`i32`),a.addParam(`r`,`i32`);let o=a.getCodeBuilder(),s=o.getLocal(`x`),c=o.i32_add(o.getLocal(`x`),o.i32_const(i)),l=o.getLocal(`y`),u=o.i32_add(o.getLocal(`y`),o.i32_const(i)),d=o.getLocal(`r`),f=o.i32_add(o.getLocal(`r`),o.i32_const(i)),p=o.i32_const(e.alloc(i)),m=o.i32_const(e.alloc(i)),h=o.i32_const(e.alloc(i)),g=o.i32_const(e.alloc(i));a.addCode(o.call(r+`_mul`,s,l,p),o.call(r+`_mul`,c,u,m),o.call(r+`_add`,s,c,h),o.call(r+`_add`,l,u,g),o.call(r+`_mul`,h,g,h),o.call(t,m,d),o.call(r+`_add`,p,d,d),o.call(r+`_add`,p,m,f),o.call(r+`_sub`,h,f,f))}function p(){let t=e.addFunction(n+`_mul1`);t.addParam(`x`,`i32`),t.addParam(`y`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.getLocal(`y`),l=a.getLocal(`r`),u=a.i32_add(a.getLocal(`r`),a.i32_const(i));t.addCode(a.call(r+`_mul`,o,c,l),a.call(r+`_mul`,s,c,u))}function m(){let a=e.addFunction(n+`_square`);a.addParam(`x`,`i32`),a.addParam(`r`,`i32`);let o=a.getCodeBuilder(),s=o.getLocal(`x`),c=o.i32_add(o.getLocal(`x`),o.i32_const(i)),l=o.getLocal(`r`),u=o.i32_add(o.getLocal(`r`),o.i32_const(i)),d=o.i32_const(e.alloc(i)),f=o.i32_const(e.alloc(i)),p=o.i32_const(e.alloc(i)),m=o.i32_const(e.alloc(i));a.addCode(o.call(r+`_mul`,s,c,d),o.call(r+`_add`,s,c,f),o.call(t,c,p),o.call(r+`_add`,s,p,p),o.call(t,d,m),o.call(r+`_add`,m,d,m),o.call(r+`_mul`,f,p,l),o.call(r+`_sub`,l,m,l),o.call(r+`_add`,d,d,u))}function h(){let t=e.addFunction(n+`_toMontgomery`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.getLocal(`r`),l=a.i32_add(a.getLocal(`r`),a.i32_const(i));t.addCode(a.call(r+`_toMontgomery`,o,c),a.call(r+`_toMontgomery`,s,l))}function g(){let t=e.addFunction(n+`_fromMontgomery`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.getLocal(`r`),l=a.i32_add(a.getLocal(`r`),a.i32_const(i));t.addCode(a.call(r+`_fromMontgomery`,o,c),a.call(r+`_fromMontgomery`,s,l))}function _(){let t=e.addFunction(n+`_copy`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.getLocal(`r`),l=a.i32_add(a.getLocal(`r`),a.i32_const(i));t.addCode(a.call(r+`_copy`,o,c),a.call(r+`_copy`,s,l))}function v(){let t=e.addFunction(n+`_zero`);t.addParam(`x`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i));t.addCode(a.call(r+`_zero`,o),a.call(r+`_zero`,s))}function y(){let t=e.addFunction(n+`_one`);t.addParam(`x`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i));t.addCode(a.call(r+`_one`,o),a.call(r+`_zero`,s))}function b(){let t=e.addFunction(n+`_eq`);t.addParam(`x`,`i32`),t.addParam(`y`,`i32`),t.setReturnType(`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.getLocal(`y`),l=a.i32_add(a.getLocal(`y`),a.i32_const(i));t.addCode(a.i32_and(a.call(r+`_eq`,o,c),a.call(r+`_eq`,s,l)))}function x(){let t=e.addFunction(n+`_isZero`);t.addParam(`x`,`i32`),t.setReturnType(`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i));t.addCode(a.i32_and(a.call(r+`_isZero`,o),a.call(r+`_isZero`,s)))}function S(){let a=e.addFunction(n+`_inverse`);a.addParam(`x`,`i32`),a.addParam(`r`,`i32`);let o=a.getCodeBuilder(),s=o.getLocal(`x`),c=o.i32_add(o.getLocal(`x`),o.i32_const(i)),l=o.getLocal(`r`),u=o.i32_add(o.getLocal(`r`),o.i32_const(i)),d=o.i32_const(e.alloc(i)),f=o.i32_const(e.alloc(i)),p=o.i32_const(e.alloc(i)),m=o.i32_const(e.alloc(i));a.addCode(o.call(r+`_square`,s,d),o.call(r+`_square`,c,f),o.call(t,f,p),o.call(r+`_sub`,d,p,p),o.call(r+`_inverse`,p,m),o.call(r+`_mul`,s,m,l),o.call(r+`_mul`,c,m,u),o.call(r+`_neg`,u,u))}function C(){let t=e.addFunction(n+`_sign`);t.addParam(`x`,`i32`),t.addLocal(`s`,`i32`),t.setReturnType(`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i));t.addCode(a.setLocal(`s`,a.call(r+`_sign`,s)),a.if(a.getLocal(`s`),a.ret(a.getLocal(`s`))),a.ret(a.call(r+`_sign`,o)))}function w(){let t=e.addFunction(n+`_isOne`);t.addParam(`x`,`i32`),t.setReturnType(`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i));t.addCode(a.ret(a.i32_and(a.call(r+`_isOne`,o),a.call(r+`_isZero`,s))))}function T(){let t=e.addFunction(n+`_sqrt`);t.addParam(`a`,`i32`),t.addParam(`pr`,`i32`);let o=t.getCodeBuilder(),s=o.i32_const(e.alloc(z((BigInt(a||0)-3n)/4n,i))),c=o.i32_const(e.alloc(z((BigInt(a||0)-1n)/2n,i))),l=o.getLocal(`a`),u=o.i32_const(e.alloc(i*2)),d=o.i32_const(e.alloc(i*2)),f=o.i32_const(e.alloc(i*2)),p=e.alloc(i*2),m=o.i32_const(p),h=o.i32_const(p),g=o.i32_const(p+i),_=o.i32_const(e.alloc(i*2)),v=o.i32_const(e.alloc(i*2));t.addCode(o.call(n+`_one`,m),o.call(n+`_neg`,m,m),o.call(n+`_exp`,l,s,o.i32_const(i),u),o.call(n+`_square`,u,d),o.call(n+`_mul`,l,d,d),o.call(n+`_conjugate`,d,f),o.call(n+`_mul`,f,d,f),o.if(o.call(n+`_eq`,f,m),o.unreachable()),o.call(n+`_mul`,u,l,_),o.if(o.call(n+`_eq`,d,m),[...o.call(r+`_zero`,h),...o.call(r+`_one`,g),...o.call(n+`_mul`,m,_,o.getLocal(`pr`))],[...o.call(n+`_one`,v),...o.call(n+`_add`,v,d,v),...o.call(n+`_exp`,v,c,o.i32_const(i),v),...o.call(n+`_mul`,v,_,o.getLocal(`pr`))]))}function E(){let t=e.addFunction(n+`_isSquare`);t.addParam(`a`,`i32`),t.setReturnType(`i32`);let r=t.getCodeBuilder(),o=r.i32_const(e.alloc(z((BigInt(a||0)-3n)/4n,i))),s=r.getLocal(`a`),c=r.i32_const(e.alloc(i*2)),l=r.i32_const(e.alloc(i*2)),u=r.i32_const(e.alloc(i*2)),d=e.alloc(i*2),f=r.i32_const(d);t.addCode(r.call(n+`_one`,f),r.call(n+`_neg`,f,f),r.call(n+`_exp`,s,o,r.i32_const(i),c),r.call(n+`_square`,c,l),r.call(n+`_mul`,s,l,l),r.call(n+`_conjugate`,l,u),r.call(n+`_mul`,u,l,u),r.if(r.call(n+`_eq`,u,f),r.ret(r.i32_const(0))),r.ret(r.i32_const(1)))}return x(),w(),v(),y(),_(),f(),p(),m(),o(),c(),l(),u(),h(),g(),b(),S(),s(),C(),d(),e.exportFunction(n+`_isZero`),e.exportFunction(n+`_isOne`),e.exportFunction(n+`_zero`),e.exportFunction(n+`_one`),e.exportFunction(n+`_copy`),e.exportFunction(n+`_mul`),e.exportFunction(n+`_mul1`),e.exportFunction(n+`_square`),e.exportFunction(n+`_add`),e.exportFunction(n+`_sub`),e.exportFunction(n+`_neg`),e.exportFunction(n+`_sign`),e.exportFunction(n+`_conjugate`),e.exportFunction(n+`_fromMontgomery`),e.exportFunction(n+`_toMontgomery`),e.exportFunction(n+`_eq`),e.exportFunction(n+`_inverse`),Ee(e,n),Ce(e,n+`_exp`,i*2,n+`_mul`,n+`_square`,n+`_copy`,n+`_one`),T(),E(),e.exportFunction(n+`_exp`),e.exportFunction(n+`_timesScalar`),e.exportFunction(n+`_batchInverse`),e.exportFunction(n+`_sqrt`),e.exportFunction(n+`_isSquare`),e.exportFunction(n+`_isNegative`),n}var it=s((()=>{we(),De(),be()}));function at(e,t,n,r){if(e.modules[n])return n;let i=e.modules[r].n64*8;e.modules[n]={n64:e.modules[r].n64*3};function a(){let t=e.addFunction(n+`_add`);t.addParam(`x`,`i32`),t.addParam(`y`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i)),l=a.getLocal(`y`),u=a.i32_add(a.getLocal(`y`),a.i32_const(i)),d=a.i32_add(a.getLocal(`y`),a.i32_const(2*i)),f=a.getLocal(`r`),p=a.i32_add(a.getLocal(`r`),a.i32_const(i)),m=a.i32_add(a.getLocal(`r`),a.i32_const(2*i));t.addCode(a.call(r+`_add`,o,l,f),a.call(r+`_add`,s,u,p),a.call(r+`_add`,c,d,m))}function o(){let t=e.addFunction(n+`_timesScalar`);t.addParam(`x`,`i32`),t.addParam(`scalar`,`i32`),t.addParam(`scalarLen`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i)),l=a.getLocal(`r`),u=a.i32_add(a.getLocal(`r`),a.i32_const(i)),d=a.i32_add(a.getLocal(`r`),a.i32_const(2*i));t.addCode(a.call(r+`_timesScalar`,o,a.getLocal(`scalar`),a.getLocal(`scalarLen`),l),a.call(r+`_timesScalar`,s,a.getLocal(`scalar`),a.getLocal(`scalarLen`),u),a.call(r+`_timesScalar`,c,a.getLocal(`scalar`),a.getLocal(`scalarLen`),d))}function s(){let t=e.addFunction(n+`_sub`);t.addParam(`x`,`i32`),t.addParam(`y`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i)),l=a.getLocal(`y`),u=a.i32_add(a.getLocal(`y`),a.i32_const(i)),d=a.i32_add(a.getLocal(`y`),a.i32_const(2*i)),f=a.getLocal(`r`),p=a.i32_add(a.getLocal(`r`),a.i32_const(i)),m=a.i32_add(a.getLocal(`r`),a.i32_const(2*i));t.addCode(a.call(r+`_sub`,o,l,f),a.call(r+`_sub`,s,u,p),a.call(r+`_sub`,c,d,m))}function c(){let t=e.addFunction(n+`_neg`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i)),l=a.getLocal(`r`),u=a.i32_add(a.getLocal(`r`),a.i32_const(i)),d=a.i32_add(a.getLocal(`r`),a.i32_const(2*i));t.addCode(a.call(r+`_neg`,o,l),a.call(r+`_neg`,s,u),a.call(r+`_neg`,c,d))}function l(){let t=e.addFunction(n+`_isNegative`);t.addParam(`x`,`i32`),t.setReturnType(`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i));t.addCode(a.if(a.call(r+`_isZero`,c),a.if(a.call(r+`_isZero`,s),a.ret(a.call(r+`_isNegative`,o)),a.ret(a.call(r+`_isNegative`,s)))),a.ret(a.call(r+`_isNegative`,c)))}function u(){let a=e.addFunction(n+`_mul`);a.addParam(`x`,`i32`),a.addParam(`y`,`i32`),a.addParam(`r`,`i32`);let o=a.getCodeBuilder(),s=o.getLocal(`x`),c=o.i32_add(o.getLocal(`x`),o.i32_const(i)),l=o.i32_add(o.getLocal(`x`),o.i32_const(2*i)),u=o.getLocal(`y`),d=o.i32_add(o.getLocal(`y`),o.i32_const(i)),f=o.i32_add(o.getLocal(`y`),o.i32_const(2*i)),p=o.getLocal(`r`),m=o.i32_add(o.getLocal(`r`),o.i32_const(i)),h=o.i32_add(o.getLocal(`r`),o.i32_const(2*i)),g=o.i32_const(e.alloc(i)),_=o.i32_const(e.alloc(i)),v=o.i32_const(e.alloc(i)),y=o.i32_const(e.alloc(i)),b=o.i32_const(e.alloc(i)),x=o.i32_const(e.alloc(i)),S=o.i32_const(e.alloc(i)),C=o.i32_const(e.alloc(i)),w=o.i32_const(e.alloc(i)),T=o.i32_const(e.alloc(i)),E=o.i32_const(e.alloc(i)),D=o.i32_const(e.alloc(i)),O=o.i32_const(e.alloc(i));a.addCode(o.call(r+`_mul`,s,u,g),o.call(r+`_mul`,c,d,_),o.call(r+`_mul`,l,f,v),o.call(r+`_add`,s,c,y),o.call(r+`_add`,u,d,b),o.call(r+`_add`,s,l,x),o.call(r+`_add`,u,f,S),o.call(r+`_add`,c,l,C),o.call(r+`_add`,d,f,w),o.call(r+`_add`,g,_,T),o.call(r+`_add`,g,v,E),o.call(r+`_add`,_,v,D),o.call(r+`_mul`,C,w,p),o.call(r+`_sub`,p,D,p),o.call(t,p,p),o.call(r+`_add`,g,p,p),o.call(r+`_mul`,y,b,m),o.call(r+`_sub`,m,T,m),o.call(t,v,O),o.call(r+`_add`,m,O,m),o.call(r+`_mul`,x,S,h),o.call(r+`_sub`,h,E,h),o.call(r+`_add`,h,_,h))}function d(){let a=e.addFunction(n+`_square`);a.addParam(`x`,`i32`),a.addParam(`r`,`i32`);let o=a.getCodeBuilder(),s=o.getLocal(`x`),c=o.i32_add(o.getLocal(`x`),o.i32_const(i)),l=o.i32_add(o.getLocal(`x`),o.i32_const(2*i)),u=o.getLocal(`r`),d=o.i32_add(o.getLocal(`r`),o.i32_const(i)),f=o.i32_add(o.getLocal(`r`),o.i32_const(2*i)),p=o.i32_const(e.alloc(i)),m=o.i32_const(e.alloc(i)),h=o.i32_const(e.alloc(i)),g=o.i32_const(e.alloc(i)),_=o.i32_const(e.alloc(i)),v=o.i32_const(e.alloc(i)),y=o.i32_const(e.alloc(i));a.addCode(o.call(r+`_square`,s,p),o.call(r+`_mul`,s,c,m),o.call(r+`_add`,m,m,h),o.call(r+`_sub`,s,c,g),o.call(r+`_add`,g,l,g),o.call(r+`_square`,g,g),o.call(r+`_mul`,c,l,_),o.call(r+`_add`,_,_,v),o.call(r+`_square`,l,y),o.call(t,v,u),o.call(r+`_add`,p,u,u),o.call(t,y,d),o.call(r+`_add`,h,d,d),o.call(r+`_add`,p,y,f),o.call(r+`_sub`,v,f,f),o.call(r+`_add`,g,f,f),o.call(r+`_add`,h,f,f))}function f(){let t=e.addFunction(n+`_toMontgomery`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i)),l=a.getLocal(`r`),u=a.i32_add(a.getLocal(`r`),a.i32_const(i)),d=a.i32_add(a.getLocal(`r`),a.i32_const(2*i));t.addCode(a.call(r+`_toMontgomery`,o,l),a.call(r+`_toMontgomery`,s,u),a.call(r+`_toMontgomery`,c,d))}function p(){let t=e.addFunction(n+`_fromMontgomery`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i)),l=a.getLocal(`r`),u=a.i32_add(a.getLocal(`r`),a.i32_const(i)),d=a.i32_add(a.getLocal(`r`),a.i32_const(2*i));t.addCode(a.call(r+`_fromMontgomery`,o,l),a.call(r+`_fromMontgomery`,s,u),a.call(r+`_fromMontgomery`,c,d))}function m(){let t=e.addFunction(n+`_copy`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i)),l=a.getLocal(`r`),u=a.i32_add(a.getLocal(`r`),a.i32_const(i)),d=a.i32_add(a.getLocal(`r`),a.i32_const(2*i));t.addCode(a.call(r+`_copy`,o,l),a.call(r+`_copy`,s,u),a.call(r+`_copy`,c,d))}function h(){let t=e.addFunction(n+`_zero`);t.addParam(`x`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i));t.addCode(a.call(r+`_zero`,o),a.call(r+`_zero`,s),a.call(r+`_zero`,c))}function g(){let t=e.addFunction(n+`_one`);t.addParam(`x`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i));t.addCode(a.call(r+`_one`,o),a.call(r+`_zero`,s),a.call(r+`_zero`,c))}function _(){let t=e.addFunction(n+`_eq`);t.addParam(`x`,`i32`),t.addParam(`y`,`i32`),t.setReturnType(`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i)),l=a.getLocal(`y`),u=a.i32_add(a.getLocal(`y`),a.i32_const(i)),d=a.i32_add(a.getLocal(`y`),a.i32_const(2*i));t.addCode(a.i32_and(a.i32_and(a.call(r+`_eq`,o,l),a.call(r+`_eq`,s,u)),a.call(r+`_eq`,c,d)))}function v(){let t=e.addFunction(n+`_isZero`);t.addParam(`x`,`i32`),t.setReturnType(`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i));t.addCode(a.i32_and(a.i32_and(a.call(r+`_isZero`,o),a.call(r+`_isZero`,s)),a.call(r+`_isZero`,c)))}function y(){let a=e.addFunction(n+`_inverse`);a.addParam(`x`,`i32`),a.addParam(`r`,`i32`);let o=a.getCodeBuilder(),s=o.getLocal(`x`),c=o.i32_add(o.getLocal(`x`),o.i32_const(i)),l=o.i32_add(o.getLocal(`x`),o.i32_const(2*i)),u=o.getLocal(`r`),d=o.i32_add(o.getLocal(`r`),o.i32_const(i)),f=o.i32_add(o.getLocal(`r`),o.i32_const(2*i)),p=o.i32_const(e.alloc(i)),m=o.i32_const(e.alloc(i)),h=o.i32_const(e.alloc(i)),g=o.i32_const(e.alloc(i)),_=o.i32_const(e.alloc(i)),v=o.i32_const(e.alloc(i)),y=o.i32_const(e.alloc(i)),b=o.i32_const(e.alloc(i)),x=o.i32_const(e.alloc(i)),S=o.i32_const(e.alloc(i)),C=o.i32_const(e.alloc(i));a.addCode(o.call(r+`_square`,s,p),o.call(r+`_square`,c,m),o.call(r+`_square`,l,h),o.call(r+`_mul`,s,c,g),o.call(r+`_mul`,s,l,_),o.call(r+`_mul`,c,l,v),o.call(t,v,y),o.call(r+`_sub`,p,y,y),o.call(t,h,b),o.call(r+`_sub`,b,g,b),o.call(r+`_sub`,m,_,x),o.call(r+`_mul`,l,b,S),o.call(r+`_mul`,c,x,C),o.call(r+`_add`,S,C,S),o.call(t,S,S),o.call(r+`_mul`,s,y,C),o.call(r+`_add`,C,S,S),o.call(r+`_inverse`,S,S),o.call(r+`_mul`,S,y,u),o.call(r+`_mul`,S,b,d),o.call(r+`_mul`,S,x,f))}function b(){let t=e.addFunction(n+`_sign`);t.addParam(`x`,`i32`),t.addLocal(`s`,`i32`),t.setReturnType(`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i));t.addCode(a.setLocal(`s`,a.call(r+`_sign`,c)),a.if(a.getLocal(`s`),a.ret(a.getLocal(`s`))),a.setLocal(`s`,a.call(r+`_sign`,s)),a.if(a.getLocal(`s`),a.ret(a.getLocal(`s`))),a.ret(a.call(r+`_sign`,o)))}function x(){let t=e.addFunction(n+`_isOne`);t.addParam(`x`,`i32`),t.setReturnType(`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(i*2));t.addCode(a.ret(a.i32_and(a.i32_and(a.call(r+`_isOne`,o),a.call(r+`_isZero`,s)),a.call(r+`_isZero`,c))))}return v(),x(),h(),g(),m(),u(),d(),a(),s(),c(),b(),f(),p(),_(),y(),o(),l(),e.exportFunction(n+`_isZero`),e.exportFunction(n+`_isOne`),e.exportFunction(n+`_zero`),e.exportFunction(n+`_one`),e.exportFunction(n+`_copy`),e.exportFunction(n+`_mul`),e.exportFunction(n+`_square`),e.exportFunction(n+`_add`),e.exportFunction(n+`_sub`),e.exportFunction(n+`_neg`),e.exportFunction(n+`_sign`),e.exportFunction(n+`_fromMontgomery`),e.exportFunction(n+`_toMontgomery`),e.exportFunction(n+`_eq`),e.exportFunction(n+`_inverse`),Ee(e,n),Ce(e,n+`_exp`,i*3,n+`_mul`,n+`_square`,n+`_copy`,n+`_one`),e.exportFunction(n+`_exp`),e.exportFunction(n+`_timesScalar`),e.exportFunction(n+`_batchInverse`),e.exportFunction(n+`_isNegative`),n}var ot=s((()=>{we(),De()}));function st(e,t,n,r,i,a,o,s){let c=e.addFunction(t);c.addParam(`base`,`i32`),c.addParam(`scalar`,`i32`),c.addParam(`scalarLength`,`i32`),c.addParam(`r`,`i32`),c.addLocal(`old0`,`i32`),c.addLocal(`nbits`,`i32`),c.addLocal(`i`,`i32`),c.addLocal(`last`,`i32`),c.addLocal(`cur`,`i32`),c.addLocal(`carry`,`i32`),c.addLocal(`p`,`i32`);let l=c.getCodeBuilder(),u=l.i32_const(e.alloc(n));function d(e){return l.i32_and(l.i32_shr_u(l.i32_load(l.i32_add(l.getLocal(`scalar`),l.i32_and(l.i32_shr_u(e,l.i32_const(3)),l.i32_const(4294967292)))),l.i32_and(e,l.i32_const(31))),l.i32_const(1))}function f(e){return[...l.i32_store8(l.getLocal(`p`),l.i32_const(e)),...l.setLocal(`p`,l.i32_add(l.getLocal(`p`),l.i32_const(1)))]}c.addCode(l.if(l.i32_eqz(l.getLocal(`scalarLength`)),[...l.call(s,l.getLocal(`r`)),...l.ret([])]),l.setLocal(`nbits`,l.i32_shl(l.getLocal(`scalarLength`),l.i32_const(3))),l.setLocal(`old0`,l.i32_load(l.i32_const(0))),l.setLocal(`p`,l.getLocal(`old0`)),l.i32_store(l.i32_const(0),l.i32_and(l.i32_add(l.i32_add(l.getLocal(`old0`),l.i32_const(32)),l.getLocal(`nbits`)),l.i32_const(4294967288))),l.setLocal(`i`,l.i32_const(1)),l.setLocal(`last`,d(l.i32_const(0))),l.setLocal(`carry`,l.i32_const(0)),l.block(l.loop(l.br_if(1,l.i32_eq(l.getLocal(`i`),l.getLocal(`nbits`))),l.setLocal(`cur`,d(l.getLocal(`i`))),l.if(l.getLocal(`last`),l.if(l.getLocal(`cur`),l.if(l.getLocal(`carry`),[...l.setLocal(`last`,l.i32_const(0)),...l.setLocal(`carry`,l.i32_const(1)),...f(1)],[...l.setLocal(`last`,l.i32_const(0)),...l.setLocal(`carry`,l.i32_const(1)),...f(255)]),l.if(l.getLocal(`carry`),[...l.setLocal(`last`,l.i32_const(0)),...l.setLocal(`carry`,l.i32_const(1)),...f(255)],[...l.setLocal(`last`,l.i32_const(0)),...l.setLocal(`carry`,l.i32_const(0)),...f(1)])),l.if(l.getLocal(`cur`),l.if(l.getLocal(`carry`),[...l.setLocal(`last`,l.i32_const(0)),...l.setLocal(`carry`,l.i32_const(1)),...f(0)],[...l.setLocal(`last`,l.i32_const(1)),...l.setLocal(`carry`,l.i32_const(0)),...f(0)]),l.if(l.getLocal(`carry`),[...l.setLocal(`last`,l.i32_const(1)),...l.setLocal(`carry`,l.i32_const(0)),...f(0)],[...l.setLocal(`last`,l.i32_const(0)),...l.setLocal(`carry`,l.i32_const(0)),...f(0)]))),l.setLocal(`i`,l.i32_add(l.getLocal(`i`),l.i32_const(1))),l.br(0))),l.if(l.getLocal(`last`),l.if(l.getLocal(`carry`),[...f(255),...f(0),...f(1)],[...f(1)]),l.if(l.getLocal(`carry`),[...f(0),...f(1)])),l.setLocal(`p`,l.i32_sub(l.getLocal(`p`),l.i32_const(1))),l.call(o,l.getLocal(`base`),u),l.call(s,l.getLocal(`r`)),l.block(l.loop(l.call(i,l.getLocal(`r`),l.getLocal(`r`)),l.setLocal(`cur`,l.i32_load8_u(l.getLocal(`p`))),l.if(l.getLocal(`cur`),l.if(l.i32_eq(l.getLocal(`cur`),l.i32_const(1)),l.call(r,l.getLocal(`r`),u,l.getLocal(`r`)),l.call(a,l.getLocal(`r`),u,l.getLocal(`r`)))),l.br_if(1,l.i32_eq(l.getLocal(`old0`),l.getLocal(`p`))),l.setLocal(`p`,l.i32_sub(l.getLocal(`p`),l.i32_const(1))),l.br(0))),l.i32_store(l.i32_const(0),l.getLocal(`old0`)))}var ct=s((()=>{}));function lt(e,t,n,r,i){let a=e.modules[t].n64*8;function o(){let t=e.addFunction(n+`_getChunk`);t.addParam(`pScalar`,`i32`),t.addParam(`scalarSize`,`i32`),t.addParam(`startBit`,`i32`),t.addParam(`chunkSize`,`i32`),t.addLocal(`bitsToEnd`,`i32`),t.addLocal(`mask`,`i32`),t.setReturnType(`i32`);let r=t.getCodeBuilder();t.addCode(r.setLocal(`bitsToEnd`,r.i32_sub(r.i32_mul(r.getLocal(`scalarSize`),r.i32_const(8)),r.getLocal(`startBit`))),r.if(r.i32_gt_s(r.getLocal(`chunkSize`),r.getLocal(`bitsToEnd`)),r.setLocal(`mask`,r.i32_sub(r.i32_shl(r.i32_const(1),r.getLocal(`bitsToEnd`)),r.i32_const(1))),r.setLocal(`mask`,r.i32_sub(r.i32_shl(r.i32_const(1),r.getLocal(`chunkSize`)),r.i32_const(1)))),r.i32_and(r.i32_shr_u(r.i32_load(r.i32_add(r.getLocal(`pScalar`),r.i32_shr_u(r.getLocal(`startBit`),r.i32_const(3))),0,0),r.i32_and(r.getLocal(`startBit`),r.i32_const(7))),r.getLocal(`mask`)))}function s(){let o=e.addFunction(n+`_chunk`);o.addParam(`pBases`,`i32`),o.addParam(`pScalars`,`i32`),o.addParam(`scalarSize`,`i32`),o.addParam(`n`,`i32`),o.addParam(`startBit`,`i32`),o.addParam(`chunkSize`,`i32`),o.addParam(`pr`,`i32`),o.addLocal(`nChunks`,`i32`),o.addLocal(`itScalar`,`i32`),o.addLocal(`endScalar`,`i32`),o.addLocal(`itBase`,`i32`),o.addLocal(`i`,`i32`),o.addLocal(`j`,`i32`),o.addLocal(`nTable`,`i32`),o.addLocal(`pTable`,`i32`),o.addLocal(`idx`,`i32`),o.addLocal(`pIdxTable`,`i32`);let s=o.getCodeBuilder();o.addCode(s.if(s.i32_eqz(s.getLocal(`n`)),[...s.call(t+`_zero`,s.getLocal(`pr`)),...s.ret([])]),s.setLocal(`nTable`,s.i32_shl(s.i32_const(1),s.getLocal(`chunkSize`))),s.setLocal(`pTable`,s.i32_load(s.i32_const(0))),s.i32_store(s.i32_const(0),s.i32_add(s.getLocal(`pTable`),s.i32_mul(s.getLocal(`nTable`),s.i32_const(a)))),s.setLocal(`j`,s.i32_const(0)),s.block(s.loop(s.br_if(1,s.i32_eq(s.getLocal(`j`),s.getLocal(`nTable`))),s.call(t+`_zero`,s.i32_add(s.getLocal(`pTable`),s.i32_mul(s.getLocal(`j`),s.i32_const(a)))),s.setLocal(`j`,s.i32_add(s.getLocal(`j`),s.i32_const(1))),s.br(0))),s.setLocal(`itBase`,s.getLocal(`pBases`)),s.setLocal(`itScalar`,s.getLocal(`pScalars`)),s.setLocal(`endScalar`,s.i32_add(s.getLocal(`pScalars`),s.i32_mul(s.getLocal(`n`),s.getLocal(`scalarSize`)))),s.block(s.loop(s.br_if(1,s.i32_eq(s.getLocal(`itScalar`),s.getLocal(`endScalar`))),s.setLocal(`idx`,s.call(n+`_getChunk`,s.getLocal(`itScalar`),s.getLocal(`scalarSize`),s.getLocal(`startBit`),s.getLocal(`chunkSize`))),s.if(s.getLocal(`idx`),[...s.setLocal(`pIdxTable`,s.i32_add(s.getLocal(`pTable`),s.i32_mul(s.i32_sub(s.getLocal(`idx`),s.i32_const(1)),s.i32_const(a)))),...s.call(r,s.getLocal(`pIdxTable`),s.getLocal(`itBase`),s.getLocal(`pIdxTable`))]),s.setLocal(`itScalar`,s.i32_add(s.getLocal(`itScalar`),s.getLocal(`scalarSize`))),s.setLocal(`itBase`,s.i32_add(s.getLocal(`itBase`),s.i32_const(i))),s.br(0))),s.call(n+`_reduceTable`,s.getLocal(`pTable`),s.getLocal(`chunkSize`)),s.call(t+`_copy`,s.getLocal(`pTable`),s.getLocal(`pr`)),s.i32_store(s.i32_const(0),s.getLocal(`pTable`)))}function c(){let r=e.addFunction(n);r.addParam(`pBases`,`i32`),r.addParam(`pScalars`,`i32`),r.addParam(`scalarSize`,`i32`),r.addParam(`n`,`i32`),r.addParam(`pr`,`i32`),r.addLocal(`chunkSize`,`i32`),r.addLocal(`nChunks`,`i32`),r.addLocal(`itScalar`,`i32`),r.addLocal(`endScalar`,`i32`),r.addLocal(`itBase`,`i32`),r.addLocal(`itBit`,`i32`),r.addLocal(`i`,`i32`),r.addLocal(`j`,`i32`),r.addLocal(`nTable`,`i32`),r.addLocal(`pTable`,`i32`),r.addLocal(`idx`,`i32`),r.addLocal(`pIdxTable`,`i32`);let i=r.getCodeBuilder(),o=i.i32_const(e.alloc(a)),s=e.alloc([17,17,17,17,17,17,17,17,17,17,16,16,15,14,13,13,12,11,10,9,8,7,7,6,5,4,3,2,1,1,1,1]);r.addCode(i.call(t+`_zero`,i.getLocal(`pr`)),i.if(i.i32_eqz(i.getLocal(`n`)),i.ret([])),i.setLocal(`chunkSize`,i.i32_load8_u(i.i32_clz(i.getLocal(`n`)),s)),i.setLocal(`nChunks`,i.i32_add(i.i32_div_u(i.i32_sub(i.i32_shl(i.getLocal(`scalarSize`),i.i32_const(3)),i.i32_const(1)),i.getLocal(`chunkSize`)),i.i32_const(1))),i.setLocal(`itBit`,i.i32_mul(i.i32_sub(i.getLocal(`nChunks`),i.i32_const(1)),i.getLocal(`chunkSize`))),i.block(i.loop(i.br_if(1,i.i32_lt_s(i.getLocal(`itBit`),i.i32_const(0))),i.if(i.i32_eqz(i.call(t+`_isZero`,i.getLocal(`pr`))),[...i.setLocal(`j`,i.i32_const(0)),...i.block(i.loop(i.br_if(1,i.i32_eq(i.getLocal(`j`),i.getLocal(`chunkSize`))),i.call(t+`_double`,i.getLocal(`pr`),i.getLocal(`pr`)),i.setLocal(`j`,i.i32_add(i.getLocal(`j`),i.i32_const(1))),i.br(0)))]),i.call(n+`_chunk`,i.getLocal(`pBases`),i.getLocal(`pScalars`),i.getLocal(`scalarSize`),i.getLocal(`n`),i.getLocal(`itBit`),i.getLocal(`chunkSize`),o),i.call(t+`_add`,i.getLocal(`pr`),o,i.getLocal(`pr`)),i.setLocal(`itBit`,i.i32_sub(i.getLocal(`itBit`),i.getLocal(`chunkSize`))),i.br(0))))}function l(){let r=e.addFunction(n+`_reduceTable`);r.addParam(`pTable`,`i32`),r.addParam(`p`,`i32`),r.addLocal(`half`,`i32`),r.addLocal(`it1`,`i32`),r.addLocal(`it2`,`i32`),r.addLocal(`pAcc`,`i32`);let i=r.getCodeBuilder();r.addCode(i.if(i.i32_eq(i.getLocal(`p`),i.i32_const(1)),i.ret([])),i.setLocal(`half`,i.i32_shl(i.i32_const(1),i.i32_sub(i.getLocal(`p`),i.i32_const(1)))),i.setLocal(`it1`,i.getLocal(`pTable`)),i.setLocal(`it2`,i.i32_add(i.getLocal(`pTable`),i.i32_mul(i.getLocal(`half`),i.i32_const(a)))),i.setLocal(`pAcc`,i.i32_sub(i.getLocal(`it2`),i.i32_const(a))),i.block(i.loop(i.br_if(1,i.i32_eq(i.getLocal(`it1`),i.getLocal(`pAcc`))),i.call(t+`_add`,i.getLocal(`it1`),i.getLocal(`it2`),i.getLocal(`it1`)),i.call(t+`_add`,i.getLocal(`pAcc`),i.getLocal(`it2`),i.getLocal(`pAcc`)),i.setLocal(`it1`,i.i32_add(i.getLocal(`it1`),i.i32_const(a))),i.setLocal(`it2`,i.i32_add(i.getLocal(`it2`),i.i32_const(a))),i.br(0))),i.call(n+`_reduceTable`,i.getLocal(`pTable`),i.i32_sub(i.getLocal(`p`),i.i32_const(1))),i.setLocal(`p`,i.i32_sub(i.getLocal(`p`),i.i32_const(1))),i.block(i.loop(i.br_if(1,i.i32_eqz(i.getLocal(`p`))),i.call(t+`_double`,i.getLocal(`pAcc`),i.getLocal(`pAcc`)),i.setLocal(`p`,i.i32_sub(i.getLocal(`p`),i.i32_const(1))),i.br(0))),i.call(t+`_add`,i.getLocal(`pTable`),i.getLocal(`pAcc`),i.getLocal(`pTable`)))}o(),l(),s(),c(),e.exportFunction(n),e.exportFunction(n+`_chunk`)}var ut=s((()=>{}));function dt(e,t,n,r){let i=e.modules[n].n64,a=i*8;if(e.modules[t])return t;e.modules[t]={n64:i*3};function o(){let r=e.addFunction(t+`_isZero`);r.addParam(`p1`,`i32`),r.setReturnType(`i32`);let i=r.getCodeBuilder();r.addCode(i.call(n+`_isZero`,i.i32_add(i.getLocal(`p1`),i.i32_const(a*2))))}function s(){let r=e.addFunction(t+`_isZeroAffine`);r.addParam(`p1`,`i32`),r.setReturnType(`i32`);let i=r.getCodeBuilder();r.addCode(i.i32_and(i.call(n+`_isZero`,i.getLocal(`p1`)),i.call(n+`_isZero`,i.i32_add(i.getLocal(`p1`),i.i32_const(a)))))}function c(){let n=e.addFunction(t+`_copy`);n.addParam(`ps`,`i32`),n.addParam(`pd`,`i32`);let r=n.getCodeBuilder();for(let e=0;e{ct(),Ae(),ut()}));function pt(e,t,n,r,i){let a=e.modules[r].n64*8,o=e.modules[n].n64*8,s=e.modules[r].q,c=s-1n,l=0;for(;!Ie(c);)l++,c>>=1n;let u=2n;for(;We(u,s>>1n,s)===1n;)u+=1n;let d=Array(l+1);d[l]=We(u,c,s);let f=l-1;for(;f>=0;)d[f]=We(d[f+1],2n,s),f--;let p=[],m=(1n<>n);return t}let T=Array(256);for(let e=0;e<256;e++)T[e]=w(e);let E=e.alloc(T);function D(){let n=e.addFunction(t+`__log2`);n.addParam(`n`,`i32`),n.setReturnType(`i32`),n.addLocal(`bits`,`i32`),n.addLocal(`aux`,`i32`);let r=n.getCodeBuilder();n.addCode(r.setLocal(`aux`,r.i32_shr_u(r.getLocal(`n`),r.i32_const(1)))),n.addCode(r.setLocal(`bits`,r.i32_const(0))),n.addCode(r.block(r.loop(r.br_if(1,r.i32_eqz(r.getLocal(`aux`))),r.setLocal(`aux`,r.i32_shr_u(r.getLocal(`aux`),r.i32_const(1))),r.setLocal(`bits`,r.i32_add(r.getLocal(`bits`),r.i32_const(1))),r.br(0)))),n.addCode(r.if(r.i32_ne(r.getLocal(`n`),r.i32_shl(r.i32_const(1),r.getLocal(`bits`))),r.unreachable())),n.addCode(r.if(r.i32_gt_u(r.getLocal(`bits`),r.i32_const(l)),r.unreachable())),n.addCode(r.getLocal(`bits`))}function O(){let n=e.addFunction(t+`_fft`);n.addParam(`px`,`i32`),n.addParam(`n`,`i32`),n.addLocal(`bits`,`i32`);let i=n.getCodeBuilder(),o=i.i32_const(e.alloc(a));n.addCode(i.setLocal(`bits`,i.call(t+`__log2`,i.getLocal(`n`))),i.call(r+`_one`,o),i.call(t+`_rawfft`,i.getLocal(`px`),i.getLocal(`bits`),i.i32_const(0),o))}function k(){let n=e.addFunction(t+`_ifft`);n.addParam(`px`,`i32`),n.addParam(`n`,`i32`),n.addLocal(`bits`,`i32`),n.addLocal(`pInv2`,`i32`);let r=n.getCodeBuilder();n.addCode(r.setLocal(`bits`,r.call(t+`__log2`,r.getLocal(`n`))),r.setLocal(`pInv2`,r.i32_add(r.i32_const(v),r.i32_mul(r.getLocal(`bits`),r.i32_const(a)))),r.call(t+`_rawfft`,r.getLocal(`px`),r.getLocal(`bits`),r.i32_const(1),r.getLocal(`pInv2`)))}function A(){let s=e.addFunction(t+`_rawfft`);s.addParam(`px`,`i32`),s.addParam(`bits`,`i32`),s.addParam(`reverse`,`i32`),s.addParam(`mulFactor`,`i32`),s.addLocal(`s`,`i32`),s.addLocal(`k`,`i32`),s.addLocal(`j`,`i32`),s.addLocal(`m`,`i32`),s.addLocal(`mdiv2`,`i32`),s.addLocal(`n`,`i32`),s.addLocal(`pwm`,`i32`),s.addLocal(`idx1`,`i32`),s.addLocal(`idx2`,`i32`);let c=s.getCodeBuilder(),l=c.i32_const(e.alloc(a)),u=c.i32_const(e.alloc(o)),d=c.i32_const(e.alloc(o));s.addCode(c.call(t+`__reversePermutation`,c.getLocal(`px`),c.getLocal(`bits`)),c.setLocal(`n`,c.i32_shl(c.i32_const(1),c.getLocal(`bits`))),c.setLocal(`s`,c.i32_const(1)),c.block(c.loop(c.br_if(1,c.i32_gt_u(c.getLocal(`s`),c.getLocal(`bits`))),c.setLocal(`m`,c.i32_shl(c.i32_const(1),c.getLocal(`s`))),c.setLocal(`pwm`,c.i32_add(c.i32_const(h),c.i32_mul(c.getLocal(`s`),c.i32_const(a)))),c.setLocal(`k`,c.i32_const(0)),c.block(c.loop(c.br_if(1,c.i32_ge_u(c.getLocal(`k`),c.getLocal(`n`))),c.call(r+`_one`,l),c.setLocal(`mdiv2`,c.i32_shr_u(c.getLocal(`m`),c.i32_const(1))),c.setLocal(`j`,c.i32_const(0)),c.block(c.loop(c.br_if(1,c.i32_ge_u(c.getLocal(`j`),c.getLocal(`mdiv2`))),c.setLocal(`idx1`,c.i32_add(c.getLocal(`px`),c.i32_mul(c.i32_add(c.getLocal(`k`),c.getLocal(`j`)),c.i32_const(o)))),c.setLocal(`idx2`,c.i32_add(c.getLocal(`idx1`),c.i32_mul(c.getLocal(`mdiv2`),c.i32_const(o)))),c.call(i,c.getLocal(`idx2`),l,u),c.call(n+`_copy`,c.getLocal(`idx1`),d),c.call(n+`_add`,d,u,c.getLocal(`idx1`)),c.call(n+`_sub`,d,u,c.getLocal(`idx2`)),c.call(r+`_mul`,l,c.getLocal(`pwm`),l),c.setLocal(`j`,c.i32_add(c.getLocal(`j`),c.i32_const(1))),c.br(0))),c.setLocal(`k`,c.i32_add(c.getLocal(`k`),c.getLocal(`m`))),c.br(0))),c.setLocal(`s`,c.i32_add(c.getLocal(`s`),c.i32_const(1))),c.br(0))),c.call(t+`__fftFinal`,c.getLocal(`px`),c.getLocal(`bits`),c.getLocal(`reverse`),c.getLocal(`mulFactor`)))}function j(){let a=e.addFunction(t+`__fftFinal`);a.addParam(`px`,`i32`),a.addParam(`bits`,`i32`),a.addParam(`reverse`,`i32`),a.addParam(`mulFactor`,`i32`),a.addLocal(`n`,`i32`),a.addLocal(`ndiv2`,`i32`),a.addLocal(`pInv2`,`i32`),a.addLocal(`i`,`i32`),a.addLocal(`mask`,`i32`),a.addLocal(`idx1`,`i32`),a.addLocal(`idx2`,`i32`);let s=a.getCodeBuilder(),c=s.i32_const(e.alloc(o));a.addCode(s.if(s.i32_and(s.i32_eqz(s.getLocal(`reverse`)),s.call(r+`_isOne`,s.getLocal(`mulFactor`))),s.ret([])),s.setLocal(`n`,s.i32_shl(s.i32_const(1),s.getLocal(`bits`))),s.setLocal(`mask`,s.i32_sub(s.getLocal(`n`),s.i32_const(1))),s.setLocal(`i`,s.i32_const(1)),s.setLocal(`ndiv2`,s.i32_shr_u(s.getLocal(`n`),s.i32_const(1))),s.block(s.loop(s.br_if(1,s.i32_ge_u(s.getLocal(`i`),s.getLocal(`ndiv2`))),s.setLocal(`idx1`,s.i32_add(s.getLocal(`px`),s.i32_mul(s.getLocal(`i`),s.i32_const(o)))),s.setLocal(`idx2`,s.i32_add(s.getLocal(`px`),s.i32_mul(s.i32_sub(s.getLocal(`n`),s.getLocal(`i`)),s.i32_const(o)))),s.if(s.getLocal(`reverse`),s.if(s.call(r+`_isOne`,s.getLocal(`mulFactor`)),[...s.call(n+`_copy`,s.getLocal(`idx1`),c),...s.call(n+`_copy`,s.getLocal(`idx2`),s.getLocal(`idx1`)),...s.call(n+`_copy`,c,s.getLocal(`idx2`))],[...s.call(n+`_copy`,s.getLocal(`idx1`),c),...s.call(i,s.getLocal(`idx2`),s.getLocal(`mulFactor`),s.getLocal(`idx1`)),...s.call(i,c,s.getLocal(`mulFactor`),s.getLocal(`idx2`))]),s.if(s.call(r+`_isOne`,s.getLocal(`mulFactor`)),[],[...s.call(i,s.getLocal(`idx1`),s.getLocal(`mulFactor`),s.getLocal(`idx1`)),...s.call(i,s.getLocal(`idx2`),s.getLocal(`mulFactor`),s.getLocal(`idx2`))])),s.setLocal(`i`,s.i32_add(s.getLocal(`i`),s.i32_const(1))),s.br(0))),s.if(s.call(r+`_isOne`,s.getLocal(`mulFactor`)),[],[...s.call(i,s.getLocal(`px`),s.getLocal(`mulFactor`),s.getLocal(`px`)),...s.setLocal(`idx2`,s.i32_add(s.getLocal(`px`),s.i32_mul(s.getLocal(`ndiv2`),s.i32_const(o)))),...s.call(i,s.getLocal(`idx2`),s.getLocal(`mulFactor`),s.getLocal(`idx2`))]))}function M(){let r=e.addFunction(t+`__reversePermutation`);r.addParam(`px`,`i32`),r.addParam(`bits`,`i32`),r.addLocal(`n`,`i32`),r.addLocal(`i`,`i32`),r.addLocal(`ri`,`i32`),r.addLocal(`idx1`,`i32`),r.addLocal(`idx2`,`i32`);let i=r.getCodeBuilder(),a=i.i32_const(e.alloc(o));r.addCode(i.setLocal(`n`,i.i32_shl(i.i32_const(1),i.getLocal(`bits`))),i.setLocal(`i`,i.i32_const(0)),i.block(i.loop(i.br_if(1,i.i32_eq(i.getLocal(`i`),i.getLocal(`n`))),i.setLocal(`idx1`,i.i32_add(i.getLocal(`px`),i.i32_mul(i.getLocal(`i`),i.i32_const(o)))),i.setLocal(`ri`,i.call(t+`__rev`,i.getLocal(`i`),i.getLocal(`bits`))),i.setLocal(`idx2`,i.i32_add(i.getLocal(`px`),i.i32_mul(i.getLocal(`ri`),i.i32_const(o)))),i.if(i.i32_lt_u(i.getLocal(`i`),i.getLocal(`ri`)),[...i.call(n+`_copy`,i.getLocal(`idx1`),a),...i.call(n+`_copy`,i.getLocal(`idx2`),i.getLocal(`idx1`)),...i.call(n+`_copy`,a,i.getLocal(`idx2`))]),i.setLocal(`i`,i.i32_add(i.getLocal(`i`),i.i32_const(1))),i.br(0))))}function N(){let n=e.addFunction(t+`__rev`);n.addParam(`x`,`i32`),n.addParam(`bits`,`i32`),n.setReturnType(`i32`);let r=n.getCodeBuilder();n.addCode(r.i32_rotl(r.i32_add(r.i32_add(r.i32_shl(r.i32_load8_u(r.i32_and(r.getLocal(`x`),r.i32_const(255)),E,0),r.i32_const(24)),r.i32_shl(r.i32_load8_u(r.i32_and(r.i32_shr_u(r.getLocal(`x`),r.i32_const(8)),r.i32_const(255)),E,0),r.i32_const(16))),r.i32_add(r.i32_shl(r.i32_load8_u(r.i32_and(r.i32_shr_u(r.getLocal(`x`),r.i32_const(16)),r.i32_const(255)),E,0),r.i32_const(8)),r.i32_load8_u(r.i32_and(r.i32_shr_u(r.getLocal(`x`),r.i32_const(24)),r.i32_const(255)),E,0))),r.getLocal(`bits`)))}function P(){let s=e.addFunction(t+`_fftJoin`);s.addParam(`pBuff1`,`i32`),s.addParam(`pBuff2`,`i32`),s.addParam(`n`,`i32`),s.addParam(`first`,`i32`),s.addParam(`inc`,`i32`),s.addLocal(`idx1`,`i32`),s.addLocal(`idx2`,`i32`),s.addLocal(`i`,`i32`);let c=s.getCodeBuilder(),l=c.i32_const(e.alloc(a)),u=c.i32_const(e.alloc(o)),d=c.i32_const(e.alloc(o));s.addCode(c.call(r+`_copy`,c.getLocal(`first`),l),c.setLocal(`i`,c.i32_const(0)),c.block(c.loop(c.br_if(1,c.i32_eq(c.getLocal(`i`),c.getLocal(`n`))),c.setLocal(`idx1`,c.i32_add(c.getLocal(`pBuff1`),c.i32_mul(c.getLocal(`i`),c.i32_const(o)))),c.setLocal(`idx2`,c.i32_add(c.getLocal(`pBuff2`),c.i32_mul(c.getLocal(`i`),c.i32_const(o)))),c.call(i,c.getLocal(`idx2`),l,u),c.call(n+`_copy`,c.getLocal(`idx1`),d),c.call(n+`_add`,d,u,c.getLocal(`idx1`)),c.call(n+`_sub`,d,u,c.getLocal(`idx2`)),c.call(r+`_mul`,l,c.getLocal(`inc`),l),c.setLocal(`i`,c.i32_add(c.getLocal(`i`),c.i32_const(1))),c.br(0))))}function F(){let s=e.addFunction(t+`_fftJoinExt`);s.addParam(`pBuff1`,`i32`),s.addParam(`pBuff2`,`i32`),s.addParam(`n`,`i32`),s.addParam(`first`,`i32`),s.addParam(`inc`,`i32`),s.addParam(`totalBits`,`i32`),s.addLocal(`idx1`,`i32`),s.addLocal(`idx2`,`i32`),s.addLocal(`i`,`i32`),s.addLocal(`pShiftToM`,`i32`);let c=s.getCodeBuilder(),l=c.i32_const(e.alloc(a)),u=c.i32_const(e.alloc(o));s.addCode(c.setLocal(`pShiftToM`,c.i32_add(c.i32_const(S),c.i32_mul(c.getLocal(`totalBits`),c.i32_const(a)))),c.call(r+`_copy`,c.getLocal(`first`),l),c.setLocal(`i`,c.i32_const(0)),c.block(c.loop(c.br_if(1,c.i32_eq(c.getLocal(`i`),c.getLocal(`n`))),c.setLocal(`idx1`,c.i32_add(c.getLocal(`pBuff1`),c.i32_mul(c.getLocal(`i`),c.i32_const(o)))),c.setLocal(`idx2`,c.i32_add(c.getLocal(`pBuff2`),c.i32_mul(c.getLocal(`i`),c.i32_const(o)))),c.call(n+`_add`,c.getLocal(`idx1`),c.getLocal(`idx2`),u),c.call(i,c.getLocal(`idx2`),c.getLocal(`pShiftToM`),c.getLocal(`idx2`)),c.call(n+`_add`,c.getLocal(`idx1`),c.getLocal(`idx2`),c.getLocal(`idx2`)),c.call(i,c.getLocal(`idx2`),l,c.getLocal(`idx2`)),c.call(n+`_copy`,u,c.getLocal(`idx1`)),c.call(r+`_mul`,l,c.getLocal(`inc`),l),c.setLocal(`i`,c.i32_add(c.getLocal(`i`),c.i32_const(1))),c.br(0))))}function I(){let s=e.addFunction(t+`_fftJoinExtInv`);s.addParam(`pBuff1`,`i32`),s.addParam(`pBuff2`,`i32`),s.addParam(`n`,`i32`),s.addParam(`first`,`i32`),s.addParam(`inc`,`i32`),s.addParam(`totalBits`,`i32`),s.addLocal(`idx1`,`i32`),s.addLocal(`idx2`,`i32`),s.addLocal(`i`,`i32`),s.addLocal(`pShiftToM`,`i32`),s.addLocal(`pSConst`,`i32`);let c=s.getCodeBuilder(),l=c.i32_const(e.alloc(a)),u=c.i32_const(e.alloc(o));s.addCode(c.setLocal(`pShiftToM`,c.i32_add(c.i32_const(S),c.i32_mul(c.getLocal(`totalBits`),c.i32_const(a)))),c.setLocal(`pSConst`,c.i32_add(c.i32_const(C),c.i32_mul(c.getLocal(`totalBits`),c.i32_const(a)))),c.call(r+`_copy`,c.getLocal(`first`),l),c.setLocal(`i`,c.i32_const(0)),c.block(c.loop(c.br_if(1,c.i32_eq(c.getLocal(`i`),c.getLocal(`n`))),c.setLocal(`idx1`,c.i32_add(c.getLocal(`pBuff1`),c.i32_mul(c.getLocal(`i`),c.i32_const(o)))),c.setLocal(`idx2`,c.i32_add(c.getLocal(`pBuff2`),c.i32_mul(c.getLocal(`i`),c.i32_const(o)))),c.call(i,c.getLocal(`idx2`),l,u),c.call(n+`_sub`,c.getLocal(`idx1`),u,c.getLocal(`idx2`)),c.call(i,c.getLocal(`idx2`),c.getLocal(`pSConst`),c.getLocal(`idx2`)),c.call(i,c.getLocal(`idx1`),c.getLocal(`pShiftToM`),c.getLocal(`idx1`)),c.call(n+`_sub`,u,c.getLocal(`idx1`),c.getLocal(`idx1`)),c.call(i,c.getLocal(`idx1`),c.getLocal(`pSConst`),c.getLocal(`idx1`)),c.call(r+`_mul`,l,c.getLocal(`inc`),l),c.setLocal(`i`,c.i32_add(c.getLocal(`i`),c.i32_const(1))),c.br(0))))}function L(){let s=e.addFunction(t+`_prepareLagrangeEvaluation`);s.addParam(`pBuff1`,`i32`),s.addParam(`pBuff2`,`i32`),s.addParam(`n`,`i32`),s.addParam(`first`,`i32`),s.addParam(`inc`,`i32`),s.addParam(`totalBits`,`i32`),s.addLocal(`idx1`,`i32`),s.addLocal(`idx2`,`i32`),s.addLocal(`i`,`i32`),s.addLocal(`pShiftToM`,`i32`),s.addLocal(`pSConst`,`i32`);let c=s.getCodeBuilder(),l=c.i32_const(e.alloc(a)),u=c.i32_const(e.alloc(o));s.addCode(c.setLocal(`pShiftToM`,c.i32_add(c.i32_const(S),c.i32_mul(c.getLocal(`totalBits`),c.i32_const(a)))),c.setLocal(`pSConst`,c.i32_add(c.i32_const(C),c.i32_mul(c.getLocal(`totalBits`),c.i32_const(a)))),c.call(r+`_copy`,c.getLocal(`first`),l),c.setLocal(`i`,c.i32_const(0)),c.block(c.loop(c.br_if(1,c.i32_eq(c.getLocal(`i`),c.getLocal(`n`))),c.setLocal(`idx1`,c.i32_add(c.getLocal(`pBuff1`),c.i32_mul(c.getLocal(`i`),c.i32_const(o)))),c.setLocal(`idx2`,c.i32_add(c.getLocal(`pBuff2`),c.i32_mul(c.getLocal(`i`),c.i32_const(o)))),c.call(i,c.getLocal(`idx1`),c.getLocal(`pShiftToM`),u),c.call(n+`_sub`,c.getLocal(`idx2`),u,u),c.call(n+`_sub`,c.getLocal(`idx1`),c.getLocal(`idx2`),c.getLocal(`idx2`)),c.call(i,u,c.getLocal(`pSConst`),c.getLocal(`idx1`)),c.call(i,c.getLocal(`idx2`),l,c.getLocal(`idx2`)),c.call(r+`_mul`,l,c.getLocal(`inc`),l),c.setLocal(`i`,c.i32_add(c.getLocal(`i`),c.i32_const(1))),c.br(0))))}function ee(){let s=e.addFunction(t+`_fftMix`);s.addParam(`pBuff`,`i32`),s.addParam(`n`,`i32`),s.addParam(`exp`,`i32`),s.addLocal(`nGroups`,`i32`),s.addLocal(`nPerGroup`,`i32`),s.addLocal(`nPerGroupDiv2`,`i32`),s.addLocal(`pairOffset`,`i32`),s.addLocal(`idx1`,`i32`),s.addLocal(`idx2`,`i32`),s.addLocal(`i`,`i32`),s.addLocal(`j`,`i32`),s.addLocal(`pwm`,`i32`);let c=s.getCodeBuilder(),l=c.i32_const(e.alloc(a)),u=c.i32_const(e.alloc(o)),d=c.i32_const(e.alloc(o));s.addCode(c.setLocal(`nPerGroup`,c.i32_shl(c.i32_const(1),c.getLocal(`exp`))),c.setLocal(`nPerGroupDiv2`,c.i32_shr_u(c.getLocal(`nPerGroup`),c.i32_const(1))),c.setLocal(`nGroups`,c.i32_shr_u(c.getLocal(`n`),c.getLocal(`exp`))),c.setLocal(`pairOffset`,c.i32_mul(c.getLocal(`nPerGroupDiv2`),c.i32_const(o))),c.setLocal(`pwm`,c.i32_add(c.i32_const(h),c.i32_mul(c.getLocal(`exp`),c.i32_const(a)))),c.setLocal(`i`,c.i32_const(0)),c.block(c.loop(c.br_if(1,c.i32_eq(c.getLocal(`i`),c.getLocal(`nGroups`))),c.call(r+`_one`,l),c.setLocal(`j`,c.i32_const(0)),c.block(c.loop(c.br_if(1,c.i32_eq(c.getLocal(`j`),c.getLocal(`nPerGroupDiv2`))),c.setLocal(`idx1`,c.i32_add(c.getLocal(`pBuff`),c.i32_mul(c.i32_add(c.i32_mul(c.getLocal(`i`),c.getLocal(`nPerGroup`)),c.getLocal(`j`)),c.i32_const(o)))),c.setLocal(`idx2`,c.i32_add(c.getLocal(`idx1`),c.getLocal(`pairOffset`))),c.call(i,c.getLocal(`idx2`),l,u),c.call(n+`_copy`,c.getLocal(`idx1`),d),c.call(n+`_add`,d,u,c.getLocal(`idx1`)),c.call(n+`_sub`,d,u,c.getLocal(`idx2`)),c.call(r+`_mul`,l,c.getLocal(`pwm`),l),c.setLocal(`j`,c.i32_add(c.getLocal(`j`),c.i32_const(1))),c.br(0))),c.setLocal(`i`,c.i32_add(c.getLocal(`i`),c.i32_const(1))),c.br(0))))}function R(){let r=e.addFunction(t+`_fftFinal`);r.addParam(`pBuff`,`i32`),r.addParam(`n`,`i32`),r.addParam(`factor`,`i32`),r.addLocal(`idx1`,`i32`),r.addLocal(`idx2`,`i32`),r.addLocal(`i`,`i32`),r.addLocal(`ndiv2`,`i32`);let a=r.getCodeBuilder(),s=a.i32_const(e.alloc(o));r.addCode(a.setLocal(`ndiv2`,a.i32_shr_u(a.getLocal(`n`),a.i32_const(1))),a.if(a.i32_and(a.getLocal(`n`),a.i32_const(1)),a.call(i,a.i32_add(a.getLocal(`pBuff`),a.i32_mul(a.getLocal(`ndiv2`),a.i32_const(o))),a.getLocal(`factor`),a.i32_add(a.getLocal(`pBuff`),a.i32_mul(a.getLocal(`ndiv2`),a.i32_const(o))))),a.setLocal(`i`,a.i32_const(0)),a.block(a.loop(a.br_if(1,a.i32_ge_u(a.getLocal(`i`),a.getLocal(`ndiv2`))),a.setLocal(`idx1`,a.i32_add(a.getLocal(`pBuff`),a.i32_mul(a.getLocal(`i`),a.i32_const(o)))),a.setLocal(`idx2`,a.i32_add(a.getLocal(`pBuff`),a.i32_mul(a.i32_sub(a.i32_sub(a.getLocal(`n`),a.i32_const(1)),a.getLocal(`i`)),a.i32_const(o)))),a.call(i,a.getLocal(`idx2`),a.getLocal(`factor`),s),a.call(i,a.getLocal(`idx1`),a.getLocal(`factor`),a.getLocal(`idx2`)),a.call(n+`_copy`,s,a.getLocal(`idx1`)),a.setLocal(`i`,a.i32_add(a.getLocal(`i`),a.i32_const(1))),a.br(0))))}N(),M(),j(),A(),D(),O(),k(),P(),F(),I(),ee(),R(),L(),e.exportFunction(t+`__reversePermutation`),e.exportFunction(t+`_fft`),e.exportFunction(t+`_ifft`),e.exportFunction(t+`_rawfft`),e.exportFunction(t+`_fftJoin`),e.exportFunction(t+`_fftJoinExt`),e.exportFunction(t+`_fftJoinExtInv`),e.exportFunction(t+`_fftMix`),e.exportFunction(t+`_fftFinal`),e.exportFunction(t+`_prepareLagrangeEvaluation`)}var mt=s((()=>{Qe(),be()}));function ht(e,t,n){let r=e.modules[n].n64*8;function i(){let i=e.addFunction(t+`_zero`);i.addParam(`px`,`i32`),i.addParam(`n`,`i32`),i.addLocal(`lastp`,`i32`),i.addLocal(`p`,`i32`);let a=i.getCodeBuilder();i.addCode(a.setLocal(`p`,a.getLocal(`px`)),a.setLocal(`lastp`,a.i32_add(a.getLocal(`px`),a.i32_mul(a.getLocal(`n`),a.i32_const(r)))),a.block(a.loop(a.br_if(1,a.i32_eq(a.getLocal(`p`),a.getLocal(`lastp`))),a.call(n+`_zero`,a.getLocal(`p`)),a.setLocal(`p`,a.i32_add(a.getLocal(`p`),a.i32_const(r))),a.br(0))))}function a(){let i=e.addFunction(t+`_constructLC`);i.addParam(`ppolynomials`,`i32`),i.addParam(`psignals`,`i32`),i.addParam(`nSignals`,`i32`),i.addParam(`pres`,`i32`),i.addLocal(`i`,`i32`),i.addLocal(`j`,`i32`),i.addLocal(`pp`,`i32`),i.addLocal(`ps`,`i32`),i.addLocal(`pd`,`i32`),i.addLocal(`ncoefs`,`i32`);let a=i.getCodeBuilder(),o=a.i32_const(e.alloc(r));i.addCode(a.setLocal(`i`,a.i32_const(0)),a.setLocal(`pp`,a.getLocal(`ppolynomials`)),a.setLocal(`ps`,a.getLocal(`psignals`)),a.block(a.loop(a.br_if(1,a.i32_eq(a.getLocal(`i`),a.getLocal(`nSignals`))),a.setLocal(`ncoefs`,a.i32_load(a.getLocal(`pp`))),a.setLocal(`pp`,a.i32_add(a.getLocal(`pp`),a.i32_const(4))),a.setLocal(`j`,a.i32_const(0)),a.block(a.loop(a.br_if(1,a.i32_eq(a.getLocal(`j`),a.getLocal(`ncoefs`))),a.setLocal(`pd`,a.i32_add(a.getLocal(`pres`),a.i32_mul(a.i32_load(a.getLocal(`pp`)),a.i32_const(r)))),a.setLocal(`pp`,a.i32_add(a.getLocal(`pp`),a.i32_const(4))),a.call(n+`_mul`,a.getLocal(`ps`),a.getLocal(`pp`),o),a.call(n+`_add`,o,a.getLocal(`pd`),a.getLocal(`pd`)),a.setLocal(`pp`,a.i32_add(a.getLocal(`pp`),a.i32_const(r))),a.setLocal(`j`,a.i32_add(a.getLocal(`j`),a.i32_const(1))),a.br(0))),a.setLocal(`ps`,a.i32_add(a.getLocal(`ps`),a.i32_const(r))),a.setLocal(`i`,a.i32_add(a.getLocal(`i`),a.i32_const(1))),a.br(0))))}return i(),a(),e.exportFunction(t+`_zero`),e.exportFunction(t+`_constructLC`),t}var gt=s((()=>{}));function _t(e,t,n){let r=e.modules[n].n64*8;function i(){let i=e.addFunction(t+`_buildABC`);i.addParam(`pCoefs`,`i32`),i.addParam(`nCoefs`,`i32`),i.addParam(`pWitness`,`i32`),i.addParam(`pA`,`i32`),i.addParam(`pB`,`i32`),i.addParam(`pC`,`i32`),i.addParam(`offsetOut`,`i32`),i.addParam(`nOut`,`i32`),i.addParam(`offsetWitness`,`i32`),i.addParam(`nWitness`,`i32`),i.addLocal(`it`,`i32`),i.addLocal(`ita`,`i32`),i.addLocal(`itb`,`i32`),i.addLocal(`last`,`i32`),i.addLocal(`m`,`i32`),i.addLocal(`c`,`i32`),i.addLocal(`s`,`i32`),i.addLocal(`pOut`,`i32`);let a=i.getCodeBuilder(),o=a.i32_const(e.alloc(r));i.addCode(a.setLocal(`ita`,a.getLocal(`pA`)),a.setLocal(`itb`,a.getLocal(`pB`)),a.setLocal(`last`,a.i32_add(a.getLocal(`pA`),a.i32_mul(a.getLocal(`nOut`),a.i32_const(r)))),a.block(a.loop(a.br_if(1,a.i32_eq(a.getLocal(`ita`),a.getLocal(`last`))),a.call(n+`_zero`,a.getLocal(`ita`)),a.call(n+`_zero`,a.getLocal(`itb`)),a.setLocal(`ita`,a.i32_add(a.getLocal(`ita`),a.i32_const(r))),a.setLocal(`itb`,a.i32_add(a.getLocal(`itb`),a.i32_const(r))),a.br(0))),a.setLocal(`it`,a.getLocal(`pCoefs`)),a.setLocal(`last`,a.i32_add(a.getLocal(`pCoefs`),a.i32_mul(a.getLocal(`nCoefs`),a.i32_const(r+12)))),a.block(a.loop(a.br_if(1,a.i32_eq(a.getLocal(`it`),a.getLocal(`last`))),a.setLocal(`s`,a.i32_load(a.getLocal(`it`),8)),a.if(a.i32_or(a.i32_lt_u(a.getLocal(`s`),a.getLocal(`offsetWitness`)),a.i32_ge_u(a.getLocal(`s`),a.i32_add(a.getLocal(`offsetWitness`),a.getLocal(`nWitness`)))),[...a.setLocal(`it`,a.i32_add(a.getLocal(`it`),a.i32_const(r+12))),...a.br(1)]),a.setLocal(`m`,a.i32_load(a.getLocal(`it`))),a.if(a.i32_eq(a.getLocal(`m`),a.i32_const(0)),a.setLocal(`pOut`,a.getLocal(`pA`)),a.if(a.i32_eq(a.getLocal(`m`),a.i32_const(1)),a.setLocal(`pOut`,a.getLocal(`pB`)),[...a.setLocal(`it`,a.i32_add(a.getLocal(`it`),a.i32_const(r+12))),...a.br(1)])),a.setLocal(`c`,a.i32_load(a.getLocal(`it`),4)),a.if(a.i32_or(a.i32_lt_u(a.getLocal(`c`),a.getLocal(`offsetOut`)),a.i32_ge_u(a.getLocal(`c`),a.i32_add(a.getLocal(`offsetOut`),a.getLocal(`nOut`)))),[...a.setLocal(`it`,a.i32_add(a.getLocal(`it`),a.i32_const(r+12))),...a.br(1)]),a.setLocal(`pOut`,a.i32_add(a.getLocal(`pOut`),a.i32_mul(a.i32_sub(a.getLocal(`c`),a.getLocal(`offsetOut`)),a.i32_const(r)))),a.call(n+`_mul`,a.i32_add(a.getLocal(`pWitness`),a.i32_mul(a.i32_sub(a.getLocal(`s`),a.getLocal(`offsetWitness`)),a.i32_const(r))),a.i32_add(a.getLocal(`it`),a.i32_const(12)),o),a.call(n+`_add`,a.getLocal(`pOut`),o,a.getLocal(`pOut`)),a.setLocal(`it`,a.i32_add(a.getLocal(`it`),a.i32_const(r+12))),a.br(0))),a.setLocal(`ita`,a.getLocal(`pA`)),a.setLocal(`itb`,a.getLocal(`pB`)),a.setLocal(`it`,a.getLocal(`pC`)),a.setLocal(`last`,a.i32_add(a.getLocal(`pA`),a.i32_mul(a.getLocal(`nOut`),a.i32_const(r)))),a.block(a.loop(a.br_if(1,a.i32_eq(a.getLocal(`ita`),a.getLocal(`last`))),a.call(n+`_mul`,a.getLocal(`ita`),a.getLocal(`itb`),a.getLocal(`it`)),a.setLocal(`ita`,a.i32_add(a.getLocal(`ita`),a.i32_const(r))),a.setLocal(`itb`,a.i32_add(a.getLocal(`itb`),a.i32_const(r))),a.setLocal(`it`,a.i32_add(a.getLocal(`it`),a.i32_const(r))),a.br(0))))}function a(){let i=e.addFunction(t+`_joinABC`);i.addParam(`pA`,`i32`),i.addParam(`pB`,`i32`),i.addParam(`pC`,`i32`),i.addParam(`n`,`i32`),i.addParam(`pP`,`i32`),i.addLocal(`ita`,`i32`),i.addLocal(`itb`,`i32`),i.addLocal(`itc`,`i32`),i.addLocal(`itp`,`i32`),i.addLocal(`last`,`i32`);let a=i.getCodeBuilder(),o=a.i32_const(e.alloc(r));i.addCode(a.setLocal(`ita`,a.getLocal(`pA`)),a.setLocal(`itb`,a.getLocal(`pB`)),a.setLocal(`itc`,a.getLocal(`pC`)),a.setLocal(`itp`,a.getLocal(`pP`)),a.setLocal(`last`,a.i32_add(a.getLocal(`pA`),a.i32_mul(a.getLocal(`n`),a.i32_const(r)))),a.block(a.loop(a.br_if(1,a.i32_eq(a.getLocal(`ita`),a.getLocal(`last`))),a.call(n+`_mul`,a.getLocal(`ita`),a.getLocal(`itb`),o),a.call(n+`_sub`,o,a.getLocal(`itc`),a.getLocal(`itp`)),a.setLocal(`ita`,a.i32_add(a.getLocal(`ita`),a.i32_const(r))),a.setLocal(`itb`,a.i32_add(a.getLocal(`itb`),a.i32_const(r))),a.setLocal(`itc`,a.i32_add(a.getLocal(`itc`),a.i32_const(r))),a.setLocal(`itp`,a.i32_add(a.getLocal(`itp`),a.i32_const(r))),a.br(0))))}function o(){let i=e.addFunction(t+`_batchAdd`);i.addParam(`pa`,`i32`),i.addParam(`pb`,`i32`),i.addParam(`n`,`i32`),i.addParam(`pr`,`i32`),i.addLocal(`ita`,`i32`),i.addLocal(`itb`,`i32`),i.addLocal(`itr`,`i32`),i.addLocal(`last`,`i32`);let a=i.getCodeBuilder();i.addCode(a.setLocal(`ita`,a.getLocal(`pa`)),a.setLocal(`itb`,a.getLocal(`pb`)),a.setLocal(`itr`,a.getLocal(`pr`)),a.setLocal(`last`,a.i32_add(a.getLocal(`pa`),a.i32_mul(a.getLocal(`n`),a.i32_const(r)))),a.block(a.loop(a.br_if(1,a.i32_eq(a.getLocal(`ita`),a.getLocal(`last`))),a.call(n+`_add`,a.getLocal(`ita`),a.getLocal(`itb`),a.getLocal(`itr`)),a.setLocal(`ita`,a.i32_add(a.getLocal(`ita`),a.i32_const(r))),a.setLocal(`itb`,a.i32_add(a.getLocal(`itb`),a.i32_const(r))),a.setLocal(`itr`,a.i32_add(a.getLocal(`itr`),a.i32_const(r))),a.br(0))))}return i(),a(),o(),e.exportFunction(t+`_buildABC`),e.exportFunction(t+`_joinABC`),e.exportFunction(t+`_batchAdd`),t}var vt=s((()=>{}));function yt(e,t,n,r,i,a,o,s){let c=e.addFunction(t);c.addParam(`pIn`,`i32`),c.addParam(`n`,`i32`),c.addParam(`pFirst`,`i32`),c.addParam(`pInc`,`i32`),c.addParam(`pOut`,`i32`),c.addLocal(`pOldFree`,`i32`),c.addLocal(`i`,`i32`),c.addLocal(`pFrom`,`i32`),c.addLocal(`pTo`,`i32`);let l=c.getCodeBuilder(),u=l.i32_const(e.alloc(o));c.addCode(l.setLocal(`pFrom`,l.getLocal(`pIn`)),l.setLocal(`pTo`,l.getLocal(`pOut`))),c.addCode(l.call(r+`_copy`,l.getLocal(`pFirst`),u)),c.addCode(l.setLocal(`i`,l.i32_const(0)),l.block(l.loop(l.br_if(1,l.i32_eq(l.getLocal(`i`),l.getLocal(`n`))),l.call(s,l.getLocal(`pFrom`),u,l.getLocal(`pTo`)),l.setLocal(`pFrom`,l.i32_add(l.getLocal(`pFrom`),l.i32_const(i))),l.setLocal(`pTo`,l.i32_add(l.getLocal(`pTo`),l.i32_const(a))),l.call(r+`_mul`,u,l.getLocal(`pInc`),u),l.setLocal(`i`,l.i32_add(l.getLocal(`i`),l.i32_const(1))),l.br(0)))),e.exportFunction(t)}var bt=s((()=>{}));function xt(e,t){let n=t||`bn128`;if(e.modules[n])return n;let r=21888242871839275222246405745257275088696311157297823662689037894645226208583n,i=21888242871839275222246405745257275088548364400416034343698204186575808495617n,a=Math.floor((Be(r-1n)-1)/64)+1,o=a*8,s=o,c=o,l=c*2,u=c*12,d=e.alloc(z(i,s)),f=$e(e,r,`f1m`);tt(e,i,`fr`,`frm`);let p=e.alloc(z(y(3n),c)),m=dt(e,`g1m`,`f1m`,p);pt(e,`frm`,`frm`,`frm`,`frm_mul`),ht(e,`pol`,`frm`),_t(e,`qap`,`frm`);let h=rt(e,`f1m_neg`,`f2m`,`f1m`),g=e.alloc([...z(y(19485874751759354771024239261021720505790618469301721065564631296452457478373n),c),...z(y(266929791119991161246907387137283842545076965332900288569378510910307636690n),c)]),_=dt(e,`g2m`,`f2m`,g);function v(t,n){let r=e.addFunction(t);r.addParam(`pG`,`i32`),r.addParam(`pFr`,`i32`),r.addParam(`pr`,`i32`);let i=r.getCodeBuilder(),a=i.i32_const(e.alloc(o));r.addCode(i.call(`frm_fromMontgomery`,i.getLocal(`pFr`),a),i.call(n,i.getLocal(`pG`),a,i.i32_const(o),i.getLocal(`pr`))),e.exportFunction(t)}v(`g1m_timesFr`,`g1m_timesScalar`),pt(e,`g1m`,`g1m`,`frm`,`g1m_timesFr`),v(`g2m_timesFr`,`g2m_timesScalar`),pt(e,`g2m`,`g2m`,`frm`,`g2m_timesFr`),v(`g1m_timesFrAffine`,`g1m_timesScalarAffine`),v(`g2m_timesFrAffine`,`g2m_timesScalarAffine`),yt(e,`frm_batchApplyKey`,`fmr`,`frm`,o,o,o,`frm_mul`),yt(e,`g1m_batchApplyKey`,`g1m`,`frm`,o*3,o*3,o,`g1m_timesFr`),yt(e,`g1m_batchApplyKeyMixed`,`g1m`,`frm`,o*2,o*3,o,`g1m_timesFrAffine`),yt(e,`g2m_batchApplyKey`,`g2m`,`frm`,o*2*3,o*3*2,o,`g2m_timesFr`),yt(e,`g2m_batchApplyKeyMixed`,`g2m`,`frm`,o*2*2,o*3*2,o,`g2m_timesFrAffine`);function y(e){return BigInt(e)*(1n<e+(t==0?0:1),0)+te+1,re=6*o,ie=3*o*2+ne*R;e.modules[n]={n64:a,pG1gen:x,pG1zero:C,pG1b:p,pG2gen:T,pG2zero:D,pG2b:g,pq:e.modules.f1m.pq,pr:d,pOneT:O,prePSize:re,preQSize:ie,r:`21888242871839275222246405745257275088548364400416034343698204186575808495617`,q:`21888242871839275222246405745257275088696311157297823662689037894645226208583`};function ae(e){let t=e,n=[];for(;t>0n;){if(Ie(t)){let e=2-Number(t%4n);n.push(e),t-=BigInt(e)}else n.push(0);t>>=1n}return n}function oe(e){let t=e,n=[];for(;t>0n;)Ie(t)?n.push(1):n.push(0),t>>=1n;return n}function se(){let t=e.addFunction(n+`_prepareG1`);t.addParam(`pP`,`i32`),t.addParam(`ppreP`,`i32`);let r=t.getCodeBuilder();t.addCode(r.call(m+`_normalize`,r.getLocal(`pP`),r.getLocal(`ppreP`)))}function ce(){let t=e.addFunction(n+`_prepAddStep`);t.addParam(`pQ`,`i32`),t.addParam(`pR`,`i32`),t.addParam(`pCoef`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`pQ`),a=r.i32_add(r.getLocal(`pQ`),r.i32_const(l)),o=r.getLocal(`pR`),s=r.i32_add(r.getLocal(`pR`),r.i32_const(l)),c=r.i32_add(r.getLocal(`pR`),r.i32_const(2*l)),u=r.getLocal(`pCoef`),d=r.i32_add(r.getLocal(`pCoef`),r.i32_const(l)),f=r.i32_add(r.getLocal(`pCoef`),r.i32_const(2*l)),p=d,m=r.i32_const(e.alloc(l)),g=r.i32_const(e.alloc(l)),_=r.i32_const(e.alloc(l)),v=r.i32_const(e.alloc(l)),y=r.i32_const(e.alloc(l)),b=r.i32_const(e.alloc(l)),x=r.i32_const(e.alloc(l));t.addCode(r.call(h+`_mul`,i,c,p),r.call(h+`_sub`,o,p,p),r.call(h+`_mul`,a,c,m),r.call(h+`_sub`,s,m,m),r.call(h+`_square`,p,g),r.call(h+`_square`,m,_),r.call(h+`_mul`,p,g,v),r.call(h+`_mul`,o,g,y),r.call(h+`_add`,y,y,x),r.call(h+`_mul`,c,_,b),r.call(h+`_add`,v,b,b),r.call(h+`_sub`,b,x,b),r.call(h+`_mul`,p,b,o),r.call(h+`_mul`,v,s,s),r.call(h+`_sub`,y,b,x),r.call(h+`_mul`,m,x,x),r.call(h+`_sub`,x,s,s),r.call(h+`_mul`,c,v,c),r.call(h+`_mul`,p,a,x),r.call(h+`_mul`,m,i,u),r.call(h+`_sub`,u,x,u),r.call(h+`_mul`,u,r.i32_const(j),u),r.call(h+`_neg`,m,f))}function le(){let t=e.addFunction(n+`_prepDblStep`);t.addParam(`pR`,`i32`),t.addParam(`pCoef`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`pR`),a=r.i32_add(r.getLocal(`pR`),r.i32_const(l)),o=r.i32_add(r.getLocal(`pR`),r.i32_const(2*l)),s=r.getLocal(`pCoef`),c=r.i32_add(r.getLocal(`pCoef`),r.i32_const(l)),u=r.i32_add(r.getLocal(`pCoef`),r.i32_const(2*l)),d=r.i32_const(e.alloc(l)),f=r.i32_const(e.alloc(l)),p=r.i32_const(e.alloc(l)),m=r.i32_const(e.alloc(l)),g=r.i32_const(e.alloc(l)),_=r.i32_const(e.alloc(l)),v=r.i32_const(e.alloc(l)),y=r.i32_const(e.alloc(l)),b=r.i32_const(e.alloc(l)),x=r.i32_const(e.alloc(l)),S=r.i32_const(e.alloc(l)),C=r.i32_const(e.alloc(l));t.addCode(r.call(h+`_mul`,a,r.i32_const(A),d),r.call(h+`_mul`,i,d,d),r.call(h+`_square`,a,f),r.call(h+`_square`,o,p),r.call(h+`_add`,p,p,m),r.call(h+`_add`,m,p,m),r.call(h+`_mul`,r.i32_const(M),m,g),r.call(h+`_add`,g,g,_),r.call(h+`_add`,g,_,_),r.call(h+`_add`,f,_,v),r.call(h+`_mul`,v,r.i32_const(A),v),r.call(h+`_add`,f,p,C),r.call(h+`_add`,a,o,y),r.call(h+`_square`,y,y),r.call(h+`_sub`,y,C,y),r.call(h+`_sub`,g,f,b),r.call(h+`_square`,i,x),r.call(h+`_square`,g,S),r.call(h+`_sub`,f,_,C),r.call(h+`_mul`,d,C,i),r.call(h+`_add`,S,S,C),r.call(h+`_add`,S,C,C),r.call(h+`_square`,v,a),r.call(h+`_sub`,a,C,a),r.call(h+`_mul`,f,y,o),r.call(h+`_mul`,r.i32_const(j),b,s),r.call(h+`_neg`,y,c),r.call(h+`_add`,x,x,u),r.call(h+`_add`,x,u,u))}function ue(){let t=e.addFunction(n+`_mulByQ`);t.addParam(`p1`,`i32`),t.addParam(`pr`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`p1`),a=r.i32_add(r.getLocal(`p1`),r.i32_const(l)),o=r.i32_add(r.getLocal(`p1`),r.i32_const(l*2)),s=r.getLocal(`pr`),u=r.i32_add(r.getLocal(`pr`),r.i32_const(l)),d=r.i32_add(r.getLocal(`pr`),r.i32_const(l*2)),f=r.i32_const(e.alloc([...z(y(`21575463638280843010398324269430826099269044274347216827212613867836435027261`),c),...z(y(`10307601595873709700152284273816112264069230130616436755625194854815875713954`),c)])),p=r.i32_const(e.alloc([...z(y(`2821565182194536844548159561693502659359617185244120367078079554186484126554`),c),...z(y(`3505843767911556378687030309984248845540243509899259641013678093033130930403`),c)]));t.addCode(r.call(h+`_conjugate`,i,s),r.call(h+`_mul`,f,s,s),r.call(h+`_conjugate`,a,u),r.call(h+`_mul`,p,u,u),r.call(h+`_conjugate`,o,d))}function de(){ue();let t=e.addFunction(n+`_prepareG2`);t.addParam(`pQ`,`i32`),t.addParam(`ppreQ`,`i32`),t.addLocal(`pCoef`,`i32`),t.addLocal(`i`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`pQ`),a=e.alloc(l*3),o=r.i32_const(a),s=r.i32_const(a),c=r.i32_const(a+l),u=r.i32_const(a+2*l),d=r.i32_add(r.getLocal(`ppreQ`),r.i32_const(0)),f=r.i32_add(r.getLocal(`ppreQ`),r.i32_const(l)),p=e.alloc(l*3),m=r.i32_const(p),g=e.alloc(l*3),v=r.i32_const(g),y=r.i32_const(g+l);t.addCode(r.call(_+`_normalize`,i,d),r.call(h+`_copy`,d,s),r.call(h+`_copy`,f,c),r.call(h+`_one`,u)),t.addCode(r.setLocal(`pCoef`,r.i32_add(r.getLocal(`ppreQ`),r.i32_const(l*3))),r.setLocal(`i`,r.i32_const(L.length-2)),r.block(r.loop(r.call(n+`_prepDblStep`,o,r.getLocal(`pCoef`)),r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(R))),r.if(r.i32_load8_s(r.getLocal(`i`),ee),[...r.call(n+`_prepAddStep`,d,o,r.getLocal(`pCoef`)),...r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(R)))]),r.br_if(1,r.i32_eqz(r.getLocal(`i`))),r.setLocal(`i`,r.i32_sub(r.getLocal(`i`),r.i32_const(1))),r.br(0)))),t.addCode(r.call(n+`_mulByQ`,d,m),r.call(n+`_mulByQ`,m,v)),t.addCode(r.call(h+`_neg`,y,y),r.call(n+`_prepAddStep`,m,o,r.getLocal(`pCoef`)),r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(R))),r.call(n+`_prepAddStep`,v,o,r.getLocal(`pCoef`)),r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(R))))}function fe(){let t=e.addFunction(n+`__mulBy024Old`);t.addParam(`pEll0`,`i32`),t.addParam(`pEllVW`,`i32`),t.addParam(`pEllVV`,`i32`),t.addParam(`pR`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`pEll0`),a=r.getLocal(`pEllVV`),o=r.getLocal(`pEllVW`),s=r.getLocal(`pR`),c=e.alloc(u),d=r.i32_const(c),f=r.i32_const(c),p=r.i32_const(c+l),m=r.i32_const(c+l*2),g=r.i32_const(c+l*3),_=r.i32_const(c+l*4),v=r.i32_const(c+l*5);t.addCode(r.call(h+`_copy`,i,f),r.call(h+`_zero`,p),r.call(h+`_copy`,a,m),r.call(h+`_zero`,g),r.call(h+`_copy`,o,_),r.call(h+`_zero`,v),r.call(I+`_mul`,d,s,s))}function pe(){let t=e.addFunction(n+`__mulBy024`);t.addParam(`pEll0`,`i32`),t.addParam(`pEllVW`,`i32`),t.addParam(`pEllVV`,`i32`),t.addParam(`pR`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`pEll0`),a=r.getLocal(`pEllVV`),s=r.getLocal(`pEllVW`),c=r.getLocal(`pR`),u=r.i32_add(r.getLocal(`pR`),r.i32_const(2*o)),d=r.i32_add(r.getLocal(`pR`),r.i32_const(4*o)),f=r.i32_add(r.getLocal(`pR`),r.i32_const(6*o)),p=r.i32_add(r.getLocal(`pR`),r.i32_const(8*o)),m=r.i32_add(r.getLocal(`pR`),r.i32_const(10*o)),g=r.i32_const(e.alloc(l)),_=r.i32_const(e.alloc(l)),v=r.i32_const(e.alloc(l)),y=r.i32_const(e.alloc(l)),b=r.i32_const(e.alloc(l)),x=r.i32_const(e.alloc(l)),S=r.i32_const(e.alloc(l)),C=r.i32_const(e.alloc(l)),w=r.i32_const(e.alloc(l)),T=r.i32_const(e.alloc(l)),E=r.i32_const(e.alloc(l));t.addCode(r.call(h+`_mul`,c,i,S),r.call(h+`_mul`,d,a,C),r.call(h+`_mul`,p,s,w),r.call(h+`_add`,c,p,v),r.call(h+`_add`,c,d,_),r.call(h+`_add`,u,f,y),r.call(h+`_add`,y,m,y),r.call(h+`_mul`,u,a,T),r.call(h+`_add`,T,w,b),r.call(h+`_mul`,r.i32_const(k),b,x),r.call(h+`_add`,x,S,c),r.call(h+`_mul`,m,s,b),r.call(h+`_add`,T,b,T),r.call(h+`_add`,b,C,b),r.call(h+`_mul`,r.i32_const(k),b,x),r.call(h+`_mul`,u,i,b),r.call(h+`_add`,T,b,T),r.call(h+`_add`,x,b,u),r.call(h+`_add`,i,a,g),r.call(h+`_mul`,_,g,b),r.call(h+`_add`,S,C,E),r.call(h+`_sub`,b,E,b),r.call(h+`_mul`,f,s,x),r.call(h+`_add`,T,x,T),r.call(h+`_add`,d,p,g),r.call(h+`_add`,b,x,d),r.call(h+`_add`,a,s,_),r.call(h+`_mul`,_,g,b),r.call(h+`_add`,C,w,E),r.call(h+`_sub`,b,E,b),r.call(h+`_mul`,r.i32_const(k),b,x),r.call(h+`_mul`,f,i,b),r.call(h+`_add`,T,b,T),r.call(h+`_add`,x,b,f),r.call(h+`_mul`,m,a,b),r.call(h+`_add`,T,b,T),r.call(h+`_mul`,r.i32_const(k),b,x),r.call(h+`_add`,i,s,g),r.call(h+`_mul`,v,g,b),r.call(h+`_add`,S,w,E),r.call(h+`_sub`,b,E,b),r.call(h+`_add`,x,b,p),r.call(h+`_add`,i,a,g),r.call(h+`_add`,g,s,g),r.call(h+`_mul`,y,g,b),r.call(h+`_sub`,b,T,m))}function me(){let t=e.addFunction(n+`_millerLoop`);t.addParam(`ppreP`,`i32`),t.addParam(`ppreQ`,`i32`),t.addParam(`r`,`i32`),t.addLocal(`pCoef`,`i32`),t.addLocal(`i`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`ppreP`),a=r.i32_add(r.getLocal(`ppreP`),r.i32_const(c)),o=r.getLocal(`pCoef`),s=r.i32_add(r.getLocal(`pCoef`),r.i32_const(l)),u=r.i32_add(r.getLocal(`pCoef`),r.i32_const(2*l)),d=e.alloc(l),f=r.i32_const(d),p=e.alloc(l),m=r.i32_const(p),g=r.getLocal(`r`);t.addCode(r.call(I+`_one`,g),r.setLocal(`pCoef`,r.i32_add(r.getLocal(`ppreQ`),r.i32_const(l*3))),r.setLocal(`i`,r.i32_const(L.length-2)),r.block(r.loop(r.call(I+`_square`,g,g),r.call(h+`_mul1`,s,a,f),r.call(h+`_mul1`,u,i,m),r.call(n+`__mulBy024`,o,f,m,g),r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(R))),r.if(r.i32_load8_s(r.getLocal(`i`),ee),[...r.call(h+`_mul1`,s,a,f),...r.call(h+`_mul1`,u,i,m),...r.call(n+`__mulBy024`,o,f,m,g),...r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(R)))]),r.br_if(1,r.i32_eqz(r.getLocal(`i`))),r.setLocal(`i`,r.i32_sub(r.getLocal(`i`),r.i32_const(1))),r.br(0)))),t.addCode(r.call(h+`_mul1`,s,a,f),r.call(h+`_mul1`,u,i,m),r.call(n+`__mulBy024`,o,f,m,g),r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(R))),r.call(h+`_mul1`,s,a,f),r.call(h+`_mul1`,u,i,m),r.call(n+`__mulBy024`,o,f,m,g),r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(R))))}function he(t){let i=[[[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n]],[[1n,0n],[8376118865763821496583973867626364092589906065868298776909617916018768340080n,16469823323077808223889137241176536799009286646108169935659301613961712198316n],[21888242871839275220042445260109153167277707414472061641714758635765020556617n,0n],[11697423496358154304825782922584725312912383441159505038794027105778954184319n,303847389135065887422783454877609941456349188919719272345083954437860409601n],[21888242871839275220042445260109153167277707414472061641714758635765020556616n,0n],[3321304630594332808241809054958361220322477375291206261884409189760185844239n,5722266937896532885780051958958348231143373700109372999374820235121374419868n],[21888242871839275222246405745257275088696311157297823662689037894645226208582n,0n],[13512124006075453725662431877630910996106405091429524885779419978626457868503n,5418419548761466998357268504080738289687024511189653727029736280683514010267n],[2203960485148121921418603742825762020974279258880205651966n,0n],[10190819375481120917420622822672549775783927716138318623895010788866272024264n,21584395482704209334823622290379665147239961968378104390343953940207365798982n],[2203960485148121921418603742825762020974279258880205651967n,0n],[18566938241244942414004596690298913868373833782006617400804628704885040364344n,16165975933942742336466353786298926857552937457188450663314217659523851788715n]]],a=[[[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n]],[[1n,0n],[21575463638280843010398324269430826099269044274347216827212613867836435027261n,10307601595873709700152284273816112264069230130616436755625194854815875713954n],[21888242871839275220042445260109153167277707414472061641714758635765020556616n,0n],[3772000881919853776433695186713858239009073593817195771773381919316419345261n,2236595495967245188281701248203181795121068902605861227855261137820944008926n],[2203960485148121921418603742825762020974279258880205651966n,0n],[18429021223477853657660792034369865839114504446431234726392080002137598044644n,9344045779998320333812420223237981029506012124075525679208581902008406485703n]],[[1n,0n],[2581911344467009335267311115468803099551665605076196740867805258568234346338n,19937756971775647987995932169929341994314640652964949448313374472400716661030n],[2203960485148121921418603742825762020974279258880205651966n,0n],[5324479202449903542726783395506214481928257762400643279780343368557297135718n,16208900380737693084919495127334387981393726419856888799917914180988844123039n],[21888242871839275220042445260109153167277707414472061641714758635765020556616n,0n],[13981852324922362344252311234282257507216387789820983642040889267519694726527n,7629828391165209371577384193250820201684255241773809077146787135900891633097n]]],o=e.addFunction(n+`__frobeniusMap`+t);o.addParam(`x`,`i32`),o.addParam(`r`,`i32`);let s=o.getCodeBuilder();for(let n=0;n<6;n++){let r=n==0?s.getLocal(`x`):s.i32_add(s.getLocal(`x`),s.i32_const(n*l)),d=r,p=s.i32_add(s.getLocal(`x`),s.i32_const(n*l+c)),m=n==0?s.getLocal(`r`):s.i32_add(s.getLocal(`r`),s.i32_const(n*l)),g=m,_=s.i32_add(s.getLocal(`r`),s.i32_const(n*l+c)),v=u(i[Math.floor(n/3)][t%12],a[n%3][t%6]),b=e.alloc([...z(y(v[0]),32),...z(y(v[1]),32)]);t%2==1?o.addCode(s.call(f+`_copy`,d,g),s.call(f+`_neg`,p,_),s.call(h+`_mul`,m,s.i32_const(b),m)):o.addCode(s.call(h+`_mul`,r,s.i32_const(b),m))}function u(e,t){let n=BigInt(e[0]),i=BigInt(e[1]),a=BigInt(t[0]),o=BigInt(t[1]),s=[(n*a-i*o)%r,(n*o+i*a)%r];return Re(s[0])&&(s[0]+=r),s}}function ge(){let t=e.addFunction(n+`__finalExponentiationFirstChunk`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`x`),a=i,s=r.i32_add(i,r.i32_const(o*6)),c=r.getLocal(`r`),l=e.alloc(u),d=r.i32_const(l),f=d,p=r.i32_const(l+o*6),m=r.i32_const(e.alloc(u)),h=r.i32_const(e.alloc(u)),g=r.i32_const(e.alloc(u));t.addCode(r.call(P+`_copy`,a,f),r.call(P+`_neg`,s,p),r.call(I+`_inverse`,i,m),r.call(I+`_mul`,d,m,h),r.call(n+`__frobeniusMap2`,h,g),r.call(I+`_mul`,h,g,c))}function _e(){let t=e.addFunction(n+`__cyclotomicSquare`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`x`),a=r.i32_add(r.getLocal(`x`),r.i32_const(l)),o=r.i32_add(r.getLocal(`x`),r.i32_const(2*l)),s=r.i32_add(r.getLocal(`x`),r.i32_const(3*l)),c=r.i32_add(r.getLocal(`x`),r.i32_const(4*l)),u=r.i32_add(r.getLocal(`x`),r.i32_const(5*l)),d=r.getLocal(`r`),f=r.i32_add(r.getLocal(`r`),r.i32_const(l)),p=r.i32_add(r.getLocal(`r`),r.i32_const(2*l)),m=r.i32_add(r.getLocal(`r`),r.i32_const(3*l)),g=r.i32_add(r.getLocal(`r`),r.i32_const(4*l)),_=r.i32_add(r.getLocal(`r`),r.i32_const(5*l)),v=r.i32_const(e.alloc(l)),y=r.i32_const(e.alloc(l)),b=r.i32_const(e.alloc(l)),x=r.i32_const(e.alloc(l)),S=r.i32_const(e.alloc(l)),C=r.i32_const(e.alloc(l)),w=r.i32_const(e.alloc(l)),T=r.i32_const(e.alloc(l));t.addCode(r.call(h+`_mul`,i,c,w),r.call(h+`_mul`,c,r.i32_const(k),v),r.call(h+`_add`,i,v,v),r.call(h+`_add`,i,c,T),r.call(h+`_mul`,T,v,v),r.call(h+`_mul`,r.i32_const(k),w,T),r.call(h+`_add`,w,T,T),r.call(h+`_sub`,v,T,v),r.call(h+`_add`,w,w,y),r.call(h+`_mul`,s,o,w),r.call(h+`_mul`,o,r.i32_const(k),b),r.call(h+`_add`,s,b,b),r.call(h+`_add`,s,o,T),r.call(h+`_mul`,T,b,b),r.call(h+`_mul`,r.i32_const(k),w,T),r.call(h+`_add`,w,T,T),r.call(h+`_sub`,b,T,b),r.call(h+`_add`,w,w,x),r.call(h+`_mul`,a,u,w),r.call(h+`_mul`,u,r.i32_const(k),S),r.call(h+`_add`,a,S,S),r.call(h+`_add`,a,u,T),r.call(h+`_mul`,T,S,S),r.call(h+`_mul`,r.i32_const(k),w,T),r.call(h+`_add`,w,T,T),r.call(h+`_sub`,S,T,S),r.call(h+`_add`,w,w,C),r.call(h+`_sub`,v,i,d),r.call(h+`_add`,d,d,d),r.call(h+`_add`,v,d,d),r.call(h+`_add`,y,c,g),r.call(h+`_add`,g,g,g),r.call(h+`_add`,y,g,g),r.call(h+`_mul`,C,r.i32_const(j),T),r.call(h+`_add`,T,s,m),r.call(h+`_add`,m,m,m),r.call(h+`_add`,T,m,m),r.call(h+`_sub`,S,o,p),r.call(h+`_add`,p,p,p),r.call(h+`_add`,S,p,p),r.call(h+`_sub`,b,a,f),r.call(h+`_add`,f,f,f),r.call(h+`_add`,b,f,f),r.call(h+`_add`,x,u,_),r.call(h+`_add`,_,_,_),r.call(h+`_add`,x,_,_))}function ve(t,r){let i=ae(t).map(e=>e==-1?255:e),a=e.alloc(i),o=e.addFunction(n+`__cyclotomicExp_`+r);o.addParam(`x`,`i32`),o.addParam(`r`,`i32`),o.addLocal(`bit`,`i32`),o.addLocal(`i`,`i32`);let s=o.getCodeBuilder(),c=s.getLocal(`x`),l=s.getLocal(`r`),d=s.i32_const(e.alloc(u));o.addCode(s.call(I+`_conjugate`,c,d),s.call(I+`_one`,l),s.if(s.teeLocal(`bit`,s.i32_load8_s(s.i32_const(i.length-1),a)),s.if(s.i32_eq(s.getLocal(`bit`),s.i32_const(1)),s.call(I+`_mul`,l,c,l),s.call(I+`_mul`,l,d,l))),s.setLocal(`i`,s.i32_const(i.length-2)),s.block(s.loop(s.call(n+`__cyclotomicSquare`,l,l),s.if(s.teeLocal(`bit`,s.i32_load8_s(s.getLocal(`i`),a)),s.if(s.i32_eq(s.getLocal(`bit`),s.i32_const(1)),s.call(I+`_mul`,l,c,l),s.call(I+`_mul`,l,d,l))),s.br_if(1,s.i32_eqz(s.getLocal(`i`))),s.setLocal(`i`,s.i32_sub(s.getLocal(`i`),s.i32_const(1))),s.br(0))))}function ye(){_e(),ve(4965661367192848881n,`w0`);let t=e.addFunction(n+`__finalExponentiationLastChunk`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`x`),a=r.getLocal(`r`),o=r.i32_const(e.alloc(u)),s=r.i32_const(e.alloc(u)),c=r.i32_const(e.alloc(u)),l=r.i32_const(e.alloc(u)),d=r.i32_const(e.alloc(u)),f=r.i32_const(e.alloc(u)),p=r.i32_const(e.alloc(u)),m=r.i32_const(e.alloc(u)),h=r.i32_const(e.alloc(u)),g=r.i32_const(e.alloc(u)),_=r.i32_const(e.alloc(u)),v=r.i32_const(e.alloc(u)),y=r.i32_const(e.alloc(u)),b=r.i32_const(e.alloc(u)),x=r.i32_const(e.alloc(u)),S=r.i32_const(e.alloc(u)),C=r.i32_const(e.alloc(u)),w=r.i32_const(e.alloc(u)),T=r.i32_const(e.alloc(u)),E=r.i32_const(e.alloc(u)),D=r.i32_const(e.alloc(u));t.addCode(r.call(n+`__cyclotomicExp_w0`,i,o),r.call(I+`_conjugate`,o,o),r.call(n+`__cyclotomicSquare`,o,s),r.call(n+`__cyclotomicSquare`,s,c),r.call(I+`_mul`,c,s,l),r.call(n+`__cyclotomicExp_w0`,l,d),r.call(I+`_conjugate`,d,d),r.call(n+`__cyclotomicSquare`,d,f),r.call(n+`__cyclotomicExp_w0`,f,p),r.call(I+`_conjugate`,p,p),r.call(I+`_conjugate`,l,m),r.call(I+`_conjugate`,p,h),r.call(I+`_mul`,h,d,g),r.call(I+`_mul`,g,m,_),r.call(I+`_mul`,_,s,v),r.call(I+`_mul`,_,d,y),r.call(I+`_mul`,y,i,b),r.call(n+`__frobeniusMap1`,v,x),r.call(I+`_mul`,x,b,S),r.call(n+`__frobeniusMap2`,_,C),r.call(I+`_mul`,C,S,w),r.call(I+`_conjugate`,i,T),r.call(I+`_mul`,T,v,E),r.call(n+`__frobeniusMap3`,E,D),r.call(I+`_mul`,D,w,a))}function be(){ge(),ye();let t=e.addFunction(n+`_finalExponentiation`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`x`),a=r.getLocal(`r`),o=r.i32_const(e.alloc(u));t.addCode(r.call(n+`__finalExponentiationFirstChunk`,i,o),r.call(n+`__finalExponentiationLastChunk`,o,a))}function xe(){let t=e.addFunction(n+`_finalExponentiationOld`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let r=e.alloc(z(552484233613224096312617126783173147097382103762957654188882734314196910839907541213974502761540629817009608548654680343627701153829446747810907373256841551006201639677726139946029199968412598804882391702273019083653272047566316584365559776493027495458238373902875937659943504873220554161550525926302303331747463515644711876653177129578303191095900909191624817826566688241804408081892785725967931714097716709526092261278071952560171111444072049229123565057483750161460024353346284167282452756217662335528813519139808291170539072125381230815729071544861602750936964829313608137325426383735122175229541155376346436093930287402089517426973178917569713384748081827255472576937471496195752727188261435633271238710131736096299798168852925540549342330775279877006784354801422249722573783561685179618816480037695005515426162362431072245638324744480n,352)),i=t.getCodeBuilder();t.addCode(i.call(I+`_exp`,i.getLocal(`x`),i.i32_const(r),i.i32_const(352),i.getLocal(`r`)))}let Se=e.alloc(re),Ce=e.alloc(ie);function we(t){let r=e.addFunction(n+`_pairingEq`+t);for(let e=0;e{be(),et(),nt(),it(),ot(),ft(),mt(),gt(),vt(),bt(),Qe()}));function Ct(e,t){let n=t||`bls12381`;if(e.modules[n])return n;let r=4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787n,i=52435875175126190479447740508185965837690552500527637822603658699938581184513n,a=Math.floor((Be(r-1n)-1)/64)+1,o=a*8,s=o,c=s*2,l=s*12,u=Math.floor((Be(i-1n)-1)/64)+1,d=u*8,f=d,p=e.alloc(z(i,f)),m=$e(e,r,`f1m`,`intq`);tt(e,i,`fr`,`frm`,`intr`);let h=e.alloc(z(x(4n),s)),g=dt(e,`g1m`,`f1m`,h);pt(e,`frm`,`frm`,`frm`,`frm_mul`),ht(e,`pol`,`frm`),_t(e,`qap`,`frm`);let _=rt(e,`f1m_neg`,`f2m`,`f1m`),v=e.alloc([...z(x(4n),s),...z(x(4n),s)]),y=dt(e,`g2m`,`f2m`,v);function b(t,n){let r=e.addFunction(t);r.addParam(`pG`,`i32`),r.addParam(`pFr`,`i32`),r.addParam(`pr`,`i32`);let i=r.getCodeBuilder(),a=i.i32_const(e.alloc(d));r.addCode(i.call(`frm_fromMontgomery`,i.getLocal(`pFr`),a),i.call(n,i.getLocal(`pG`),a,i.i32_const(d),i.getLocal(`pr`))),e.exportFunction(t)}b(`g1m_timesFr`,`g1m_timesScalar`),pt(e,`g1m`,`g1m`,`frm`,`g1m_timesFr`),b(`g2m_timesFr`,`g2m_timesScalar`),pt(e,`g2m`,`g2m`,`frm`,`g2m_timesFr`),b(`g1m_timesFrAffine`,`g1m_timesScalarAffine`),b(`g2m_timesFrAffine`,`g2m_timesScalarAffine`),yt(e,`frm_batchApplyKey`,`fmr`,`frm`,d,d,d,`frm_mul`),yt(e,`g1m_batchApplyKey`,`g1m`,`frm`,o*3,o*3,d,`g1m_timesFr`),yt(e,`g1m_batchApplyKeyMixed`,`g1m`,`frm`,o*2,o*3,d,`g1m_timesFrAffine`),yt(e,`g2m_batchApplyKey`,`g2m`,`frm`,o*2*3,o*3*2,d,`g2m_timesFr`),yt(e,`g2m_batchApplyKeyMixed`,`g2m`,`frm`,o*2*2,o*3*2,d,`g2m_timesFrAffine`);function x(e){return BigInt(e)*(1n<e+(t==0?0:1),0)+R+1,ne=6*o,re=3*o*2+te*ee,ie=15132376222941642752n;e.modules[n]={n64q:a,n64r:u,n8q:o,n8r:d,pG1gen:C,pG1zero:T,pG1b:h,pG2gen:D,pG2zero:k,pG2b:v,pq:e.modules.f1m.pq,pr:p,pOneT:A,r:i,q:r,prePSize:ne,preQSize:re};function ae(e){let t=e,n=[];for(;t>0n;){if(Ie(t)){let e=2-Number(t%4n);n.push(e),t-=BigInt(e)}else n.push(0);t>>=1n}return n}function oe(e){let t=e,n=[];for(;t>0n;)Ie(t)?n.push(1):n.push(0),t>>=1n;return n}function se(){let t=e.addFunction(n+`_prepareG1`);t.addParam(`pP`,`i32`),t.addParam(`ppreP`,`i32`);let r=t.getCodeBuilder();t.addCode(r.call(g+`_normalize`,r.getLocal(`pP`),r.getLocal(`ppreP`)))}function ce(){let t=e.addFunction(n+`_prepDblStep`);t.addParam(`R`,`i32`),t.addParam(`r`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`R`),a=r.i32_add(r.getLocal(`R`),r.i32_const(2*o)),s=r.i32_add(r.getLocal(`R`),r.i32_const(4*o)),l=r.getLocal(`r`),u=r.i32_add(r.getLocal(`r`),r.i32_const(2*o)),d=r.i32_add(r.getLocal(`r`),r.i32_const(4*o)),f=r.i32_const(e.alloc(c)),p=r.i32_const(e.alloc(c)),m=r.i32_const(e.alloc(c)),h=r.i32_const(e.alloc(c)),g=r.i32_const(e.alloc(c));t.addCode(r.call(_+`_square`,i,l),r.call(_+`_square`,a,p),r.call(_+`_square`,p,m),r.call(_+`_add`,p,i,u),r.call(_+`_square`,u,u),r.call(_+`_sub`,u,l,u),r.call(_+`_sub`,u,m,u),r.call(_+`_add`,u,u,u),r.call(_+`_add`,l,l,h),r.call(_+`_add`,h,l,h),r.call(_+`_add`,i,h,d),r.call(_+`_square`,h,g),r.call(_+`_square`,s,f),r.call(_+`_sub`,g,u,i),r.call(_+`_sub`,i,u,i),r.call(_+`_add`,s,a,s),r.call(_+`_square`,s,s),r.call(_+`_sub`,s,p,s),r.call(_+`_sub`,s,f,s),r.call(_+`_sub`,u,i,a),r.call(_+`_mul`,a,h,a),r.call(_+`_add`,m,m,m),r.call(_+`_add`,m,m,m),r.call(_+`_add`,m,m,m),r.call(_+`_sub`,a,m,a),r.call(_+`_mul`,h,f,u),r.call(_+`_add`,u,u,u),r.call(_+`_neg`,u,u),r.call(_+`_square`,d,d),r.call(_+`_sub`,d,l,d),r.call(_+`_sub`,d,g,d),r.call(_+`_add`,p,p,p),r.call(_+`_add`,p,p,p),r.call(_+`_sub`,d,p,d),r.call(_+`_mul`,s,f,l),r.call(_+`_add`,l,l,l))}function le(){let t=e.addFunction(n+`_prepAddStep`);t.addParam(`R`,`i32`),t.addParam(`Q`,`i32`),t.addParam(`r`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`R`),a=r.i32_add(r.getLocal(`R`),r.i32_const(2*o)),s=r.i32_add(r.getLocal(`R`),r.i32_const(4*o)),l=r.getLocal(`Q`),u=r.i32_add(r.getLocal(`Q`),r.i32_const(2*o)),d=r.getLocal(`r`),f=r.i32_add(r.getLocal(`r`),r.i32_const(2*o)),p=r.i32_add(r.getLocal(`r`),r.i32_const(4*o)),m=r.i32_const(e.alloc(c)),h=r.i32_const(e.alloc(c)),g=r.i32_const(e.alloc(c)),v=r.i32_const(e.alloc(c)),y=r.i32_const(e.alloc(c)),b=r.i32_const(e.alloc(c)),x=r.i32_const(e.alloc(c)),S=r.i32_const(e.alloc(c)),C=r.i32_const(e.alloc(c)),w=r.i32_const(e.alloc(c)),T=r.i32_const(e.alloc(c));t.addCode(r.call(_+`_square`,s,m),r.call(_+`_square`,u,h),r.call(_+`_mul`,m,l,v),r.call(_+`_add`,u,s,f),r.call(_+`_square`,f,f),r.call(_+`_sub`,f,h,f),r.call(_+`_sub`,f,m,f),r.call(_+`_mul`,f,m,f),r.call(_+`_sub`,v,i,y),r.call(_+`_square`,y,b),r.call(_+`_add`,b,b,x),r.call(_+`_add`,x,x,x),r.call(_+`_mul`,x,y,S),r.call(_+`_sub`,f,a,C),r.call(_+`_sub`,C,a,C),r.call(_+`_mul`,C,l,p),r.call(_+`_mul`,x,i,w),r.call(_+`_square`,C,i),r.call(_+`_sub`,i,S,i),r.call(_+`_sub`,i,w,i),r.call(_+`_sub`,i,w,i),r.call(_+`_add`,s,y,s),r.call(_+`_square`,s,s),r.call(_+`_sub`,s,m,s),r.call(_+`_sub`,s,b,s),r.call(_+`_add`,u,s,d),r.call(_+`_sub`,w,i,T),r.call(_+`_mul`,T,C,T),r.call(_+`_mul`,a,S,v),r.call(_+`_add`,v,v,v),r.call(_+`_sub`,T,v,a),r.call(_+`_square`,d,d),r.call(_+`_sub`,d,h,d),r.call(_+`_square`,s,g),r.call(_+`_sub`,d,g,d),r.call(_+`_add`,p,p,p),r.call(_+`_sub`,p,d,p),r.call(_+`_add`,s,s,d),r.call(_+`_neg`,C,C),r.call(_+`_add`,C,C,f))}function ue(){let t=e.addFunction(n+`_prepareG2`);t.addParam(`pQ`,`i32`),t.addParam(`ppreQ`,`i32`),t.addLocal(`pCoef`,`i32`),t.addLocal(`i`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`pQ`),a=e.alloc(c*3),o=r.i32_const(a),s=r.getLocal(`ppreQ`);t.addCode(r.call(y+`_normalize`,i,s),r.if(r.call(y+`_isZero`,s),r.ret([])),r.call(y+`_copy`,s,o),r.setLocal(`pCoef`,r.i32_add(r.getLocal(`ppreQ`),r.i32_const(c*3)))),t.addCode(r.setLocal(`i`,r.i32_const(I.length-2)),r.block(r.loop(r.call(n+`_prepDblStep`,o,r.getLocal(`pCoef`)),r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(ee))),r.if(r.i32_load8_s(r.getLocal(`i`),L),[...r.call(n+`_prepAddStep`,o,s,r.getLocal(`pCoef`)),...r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(ee)))]),r.br_if(1,r.i32_eqz(r.getLocal(`i`))),r.setLocal(`i`,r.i32_sub(r.getLocal(`i`),r.i32_const(1))),r.br(0))))}function de(){let t=e.addFunction(N+`_mul1`);t.addParam(`pA`,`i32`),t.addParam(`pC1`,`i32`),t.addParam(`pR`,`i32`);let n=t.getCodeBuilder(),r=n.getLocal(`pA`),i=n.i32_add(n.getLocal(`pA`),n.i32_const(s*2)),a=n.i32_add(n.getLocal(`pA`),n.i32_const(s*4)),o=n.getLocal(`pC1`),c=n.getLocal(`pR`),l=n.i32_add(n.getLocal(`pR`),n.i32_const(s*2)),u=n.i32_add(n.getLocal(`pR`),n.i32_const(s*4)),d=n.i32_const(e.alloc(s*2)),f=n.i32_const(e.alloc(s*2));t.addCode(n.call(_+`_add`,r,i,d),n.call(_+`_add`,i,a,f),n.call(_+`_mul`,i,o,u),n.call(_+`_mul`,f,o,c),n.call(_+`_sub`,c,u,c),n.call(_+`_mulNR`,c,c),n.call(_+`_mul`,d,o,l),n.call(_+`_sub`,l,u,l))}de();function fe(){let t=e.addFunction(N+`_mul01`);t.addParam(`pA`,`i32`),t.addParam(`pC0`,`i32`),t.addParam(`pC1`,`i32`),t.addParam(`pR`,`i32`);let n=t.getCodeBuilder(),r=n.getLocal(`pA`),i=n.i32_add(n.getLocal(`pA`),n.i32_const(s*2)),a=n.i32_add(n.getLocal(`pA`),n.i32_const(s*4)),o=n.getLocal(`pC0`),c=n.getLocal(`pC1`),l=n.getLocal(`pR`),u=n.i32_add(n.getLocal(`pR`),n.i32_const(s*2)),d=n.i32_add(n.getLocal(`pR`),n.i32_const(s*4)),f=n.i32_const(e.alloc(s*2)),p=n.i32_const(e.alloc(s*2)),m=n.i32_const(e.alloc(s*2)),h=n.i32_const(e.alloc(s*2));t.addCode(n.call(_+`_mul`,r,o,f),n.call(_+`_mul`,i,c,p),n.call(_+`_add`,r,i,m),n.call(_+`_add`,r,a,h),n.call(_+`_add`,i,a,l),n.call(_+`_mul`,l,c,l),n.call(_+`_sub`,l,p,l),n.call(_+`_mulNR`,l,l),n.call(_+`_add`,l,f,l),n.call(_+`_add`,o,c,u),n.call(_+`_mul`,u,m,u),n.call(_+`_sub`,u,f,u),n.call(_+`_sub`,u,p,u),n.call(_+`_mul`,h,o,d),n.call(_+`_sub`,d,f,d),n.call(_+`_add`,d,p,d))}fe();function pe(){let t=e.addFunction(F+`_mul014`);t.addParam(`pA`,`i32`),t.addParam(`pC0`,`i32`),t.addParam(`pC1`,`i32`),t.addParam(`pC4`,`i32`),t.addParam(`pR`,`i32`);let n=t.getCodeBuilder(),r=n.getLocal(`pA`),i=n.i32_add(n.getLocal(`pA`),n.i32_const(s*6)),a=n.getLocal(`pC0`),o=n.getLocal(`pC1`),c=n.getLocal(`pC4`),l=n.i32_const(e.alloc(s*6)),u=n.i32_const(e.alloc(s*6)),d=n.i32_const(e.alloc(s*2)),f=n.getLocal(`pR`),p=n.i32_add(n.getLocal(`pR`),n.i32_const(s*6));t.addCode(n.call(N+`_mul01`,r,a,o,l),n.call(N+`_mul1`,i,c,u),n.call(_+`_add`,o,c,d),n.call(N+`_add`,i,r,p),n.call(N+`_mul01`,p,a,d,p),n.call(N+`_sub`,p,l,p),n.call(N+`_sub`,p,u,p),n.call(N+`_copy`,u,f),n.call(N+`_mulNR`,f,f),n.call(N+`_add`,f,l,f))}pe();function me(){let t=e.addFunction(n+`_ell`);t.addParam(`pP`,`i32`),t.addParam(`pCoefs`,`i32`),t.addParam(`pF`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`pP`),a=r.i32_add(r.getLocal(`pP`),r.i32_const(o)),c=r.getLocal(`pF`),l=r.getLocal(`pCoefs`),u=r.i32_add(r.getLocal(`pCoefs`),r.i32_const(s)),d=r.i32_add(r.getLocal(`pCoefs`),r.i32_const(s*2)),f=r.i32_add(r.getLocal(`pCoefs`),r.i32_const(s*3)),p=r.i32_add(r.getLocal(`pCoefs`),r.i32_const(s*4)),h=e.alloc(s*2),g=r.i32_const(h),_=r.i32_const(h),v=r.i32_const(h+s),y=e.alloc(s*2),b=r.i32_const(y),x=r.i32_const(y),S=r.i32_const(y+s);t.addCode(r.call(m+`_mul`,l,a,_),r.call(m+`_mul`,u,a,v),r.call(m+`_mul`,d,i,x),r.call(m+`_mul`,f,i,S),r.call(F+`_mul014`,c,p,b,g,c))}me();function he(){let t=e.addFunction(n+`_millerLoop`);t.addParam(`ppreP`,`i32`),t.addParam(`ppreQ`,`i32`),t.addParam(`r`,`i32`),t.addLocal(`pCoef`,`i32`),t.addLocal(`i`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`ppreP`),a=r.getLocal(`pCoef`),o=r.getLocal(`r`);t.addCode(r.call(F+`_one`,o),r.if(r.call(g+`_isZero`,i),r.ret([])),r.if(r.call(g+`_isZero`,r.getLocal(`ppreQ`)),r.ret([])),r.setLocal(`pCoef`,r.i32_add(r.getLocal(`ppreQ`),r.i32_const(c*3))),r.setLocal(`i`,r.i32_const(I.length-2)),r.block(r.loop(r.call(n+`_ell`,i,a,o),r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(ee))),r.if(r.i32_load8_s(r.getLocal(`i`),L),[...r.call(n+`_ell`,i,a,o),...r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(ee)))]),r.call(F+`_square`,o,o),r.br_if(1,r.i32_eq(r.getLocal(`i`),r.i32_const(1))),r.setLocal(`i`,r.i32_sub(r.getLocal(`i`),r.i32_const(1))),r.br(0))),r.call(n+`_ell`,i,a,o)),t.addCode(r.call(F+`_conjugate`,o,o))}function ge(t){let n=[[[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n]],[[1n,0n],[3850754370037169011952147076051364057158807420970682438676050522613628423219637725072182697113062777891589506424760n,151655185184498381465642749684540099398075398968325446656007613510403227271200139370504932015952886146304766135027n],[793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620351n,0n],[2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530n,1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257n],[793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350n,0n],[3125332594171059424908108096204648978570118281977575435832422631601824034463382777937621250592425535493320683825557n,877076961050607968509681729531255177986764537961432449499635504522207616027455086505066378536590128544573588734230n],[4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559786n,0n],[151655185184498381465642749684540099398075398968325446656007613510403227271200139370504932015952886146304766135027n,3850754370037169011952147076051364057158807420970682438676050522613628423219637725072182697113062777891589506424760n],[4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436n,0n],[1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257n,2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530n],[4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437n,0n],[877076961050607968509681729531255177986764537961432449499635504522207616027455086505066378536590128544573588734230n,3125332594171059424908108096204648978570118281977575435832422631601824034463382777937621250592425535493320683825557n]]],i=[[[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n]],[[1n,0n],[0n,4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436n],[793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350n,0n],[0n,1n],[4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436n,0n],[0n,793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350n]],[[1n,0n],[4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437n,0n],[4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436n,0n],[4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559786n,0n],[793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350n,0n],[793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620351n,0n]]],a=e.addFunction(F+`_frobeniusMap`+t);a.addParam(`x`,`i32`),a.addParam(`r`,`i32`);let l=a.getCodeBuilder();for(let r=0;r<6;r++){let d=r==0?l.getLocal(`x`):l.i32_add(l.getLocal(`x`),l.i32_const(r*c)),f=d,p=l.i32_add(l.getLocal(`x`),l.i32_const(r*c+s)),h=r==0?l.getLocal(`r`):l.i32_add(l.getLocal(`r`),l.i32_const(r*c)),g=h,v=l.i32_add(l.getLocal(`r`),l.i32_const(r*c+s)),y=u(n[Math.floor(r/3)][t%12],i[r%3][t%6]),b=e.alloc([...z(x(y[0]),o),...z(x(y[1]),o)]);t%2==1?a.addCode(l.call(m+`_copy`,f,g),l.call(m+`_neg`,p,v),l.call(_+`_mul`,h,l.i32_const(b),h)):a.addCode(l.call(_+`_mul`,d,l.i32_const(b),h))}function u(e,t){let n=e[0],i=e[1],a=t[0],o=t[1],s=[(n*a-i*o)%r,(n*o+i*a)%r];return Re(s[0])&&(s[0]+=r),s}}function _e(){let t=e.addFunction(n+`__cyclotomicSquare`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`x`),a=r.i32_add(r.getLocal(`x`),r.i32_const(c)),o=r.i32_add(r.getLocal(`x`),r.i32_const(2*c)),s=r.i32_add(r.getLocal(`x`),r.i32_const(3*c)),l=r.i32_add(r.getLocal(`x`),r.i32_const(4*c)),u=r.i32_add(r.getLocal(`x`),r.i32_const(5*c)),d=r.getLocal(`r`),f=r.i32_add(r.getLocal(`r`),r.i32_const(c)),p=r.i32_add(r.getLocal(`r`),r.i32_const(2*c)),m=r.i32_add(r.getLocal(`r`),r.i32_const(3*c)),h=r.i32_add(r.getLocal(`r`),r.i32_const(4*c)),g=r.i32_add(r.getLocal(`r`),r.i32_const(5*c)),v=r.i32_const(e.alloc(c)),y=r.i32_const(e.alloc(c)),b=r.i32_const(e.alloc(c)),x=r.i32_const(e.alloc(c)),S=r.i32_const(e.alloc(c)),C=r.i32_const(e.alloc(c)),w=r.i32_const(e.alloc(c)),T=r.i32_const(e.alloc(c));t.addCode(r.call(_+`_mul`,i,l,w),r.call(_+`_mulNR`,l,v),r.call(_+`_add`,i,v,v),r.call(_+`_add`,i,l,T),r.call(_+`_mul`,T,v,v),r.call(_+`_mulNR`,w,T),r.call(_+`_add`,w,T,T),r.call(_+`_sub`,v,T,v),r.call(_+`_add`,w,w,y),r.call(_+`_mul`,s,o,w),r.call(_+`_mulNR`,o,b),r.call(_+`_add`,s,b,b),r.call(_+`_add`,s,o,T),r.call(_+`_mul`,T,b,b),r.call(_+`_mulNR`,w,T),r.call(_+`_add`,w,T,T),r.call(_+`_sub`,b,T,b),r.call(_+`_add`,w,w,x),r.call(_+`_mul`,a,u,w),r.call(_+`_mulNR`,u,S),r.call(_+`_add`,a,S,S),r.call(_+`_add`,a,u,T),r.call(_+`_mul`,T,S,S),r.call(_+`_mulNR`,w,T),r.call(_+`_add`,w,T,T),r.call(_+`_sub`,S,T,S),r.call(_+`_add`,w,w,C),r.call(_+`_sub`,v,i,d),r.call(_+`_add`,d,d,d),r.call(_+`_add`,v,d,d),r.call(_+`_add`,y,l,h),r.call(_+`_add`,h,h,h),r.call(_+`_add`,y,h,h),r.call(_+`_mul`,C,r.i32_const(j),T),r.call(_+`_add`,T,s,m),r.call(_+`_add`,m,m,m),r.call(_+`_add`,T,m,m),r.call(_+`_sub`,S,o,p),r.call(_+`_add`,p,p,p),r.call(_+`_add`,S,p,p),r.call(_+`_sub`,b,a,f),r.call(_+`_add`,f,f,f),r.call(_+`_add`,b,f,f),r.call(_+`_add`,x,u,g),r.call(_+`_add`,g,g,g),r.call(_+`_add`,x,g,g))}function ve(t,r,i){let a=ae(t).map(e=>e==-1?255:e),o=e.alloc(a),s=e.addFunction(n+`__cyclotomicExp_`+i);s.addParam(`x`,`i32`),s.addParam(`r`,`i32`),s.addLocal(`bit`,`i32`),s.addLocal(`i`,`i32`);let c=s.getCodeBuilder(),u=c.getLocal(`x`),d=c.getLocal(`r`),f=c.i32_const(e.alloc(l));s.addCode(c.call(F+`_conjugate`,u,f),c.call(F+`_one`,d),c.if(c.teeLocal(`bit`,c.i32_load8_s(c.i32_const(a.length-1),o)),c.if(c.i32_eq(c.getLocal(`bit`),c.i32_const(1)),c.call(F+`_mul`,d,u,d),c.call(F+`_mul`,d,f,d))),c.setLocal(`i`,c.i32_const(a.length-2)),c.block(c.loop(c.call(n+`__cyclotomicSquare`,d,d),c.if(c.teeLocal(`bit`,c.i32_load8_s(c.getLocal(`i`),o)),c.if(c.i32_eq(c.getLocal(`bit`),c.i32_const(1)),c.call(F+`_mul`,d,u,d),c.call(F+`_mul`,d,f,d))),c.br_if(1,c.i32_eqz(c.getLocal(`i`))),c.setLocal(`i`,c.i32_sub(c.getLocal(`i`),c.i32_const(1))),c.br(0)))),r&&s.addCode(c.call(F+`_conjugate`,d,d))}function ye(){_e(),ve(ie,!0,`w0`);let t=e.addFunction(n+`_finalExponentiation`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`x`),a=r.getLocal(`r`),o=r.i32_const(e.alloc(l)),s=r.i32_const(e.alloc(l)),c=r.i32_const(e.alloc(l)),u=r.i32_const(e.alloc(l)),d=r.i32_const(e.alloc(l)),f=r.i32_const(e.alloc(l)),p=r.i32_const(e.alloc(l));t.addCode(r.call(F+`_frobeniusMap6`,i,o),r.call(F+`_inverse`,i,s),r.call(F+`_mul`,o,s,c),r.call(F+`_copy`,c,s),r.call(F+`_frobeniusMap2`,c,c),r.call(F+`_mul`,c,s,c),r.call(n+`__cyclotomicSquare`,c,s),r.call(F+`_conjugate`,s,s),r.call(n+`__cyclotomicExp_w0`,c,u),r.call(n+`__cyclotomicSquare`,u,d),r.call(F+`_mul`,s,u,f),r.call(n+`__cyclotomicExp_w0`,f,s),r.call(n+`__cyclotomicExp_w0`,s,o),r.call(n+`__cyclotomicExp_w0`,o,p),r.call(F+`_mul`,p,d,p),r.call(n+`__cyclotomicExp_w0`,p,d),r.call(F+`_conjugate`,f,f),r.call(F+`_mul`,d,f,d),r.call(F+`_mul`,d,c,d),r.call(F+`_conjugate`,c,f),r.call(F+`_mul`,s,c,s),r.call(F+`_frobeniusMap3`,s,s),r.call(F+`_mul`,p,f,p),r.call(F+`_frobeniusMap1`,p,p),r.call(F+`_mul`,u,o,u),r.call(F+`_frobeniusMap2`,u,u),r.call(F+`_mul`,u,s,u),r.call(F+`_mul`,u,p,u),r.call(F+`_mul`,u,d,a))}function be(){let t=e.addFunction(n+`_finalExponentiationOld`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let r=e.alloc(z(322277361516934140462891564586510139908379969514828494218366688025288661041104682794998680497580008899973249814104447692778988208376779573819485263026159588510513834876303014016798809919343532899164848730280942609956670917565618115867287399623286813270357901731510188149934363360381614501334086825442271920079363289954510565375378443704372994881406797882676971082200626541916413184642520269678897559532260949334760604962086348898118982248842634379637598665468817769075878555493752214492790122785850202957575200176084204422751485957336465472324810982833638490904279282696134323072515220044451592646885410572234451732790590013479358343841220074174848221722017083597872017638514103174122784843925578370430843522959600095676285723737049438346544753168912974976791528535276317256904336520179281145394686565050419250614107803233314658825463117900250701199181529205942363159325765991819433914303908860460720581408201373164047773794825411011922305820065611121544561808414055302212057471395719432072209245600258134364584636810093520285711072578721435517884103526483832733289802426157301542744476740008494780363354305116978805620671467071400711358839553375340724899735460480144599782014906586543813292157922220645089192130209334926661588737007768565838519456601560804957985667880395221049249803753582637708560n,544)),i=t.getCodeBuilder();t.addCode(i.call(F+`_exp`,i.getLocal(`x`),i.i32_const(r),i.i32_const(544),i.getLocal(`r`)))}let xe=e.alloc(ne),Se=e.alloc(re);function Ce(t){let r=e.addFunction(n+`_pairingEq`+t);for(let e=0;e{be(),et(),nt(),it(),ot(),ft(),mt(),gt(),vt(),bt(),Qe()})),Tt=l({bn128_wasm_gzip:()=>f,buildBls12381:()=>Ct,buildBn128:()=>xt,buildF1m:()=>$e}),Et=s((()=>{T(),St(),wt(),et()}));console.log(`browser esm`);var Dt=Object.create,Ot=Object.defineProperty,kt=Object.getOwnPropertyDescriptor,At=Object.getOwnPropertyNames,jt=Object.getPrototypeOf,Mt=Object.prototype.hasOwnProperty,Nt=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Pt=(e,t)=>{let n={};for(var r in e)Ot(n,r,{get:e[r],enumerable:!0});return t||Ot(n,Symbol.toStringTag,{value:`Module`}),n},Ft=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=At(t),a=0,o=i.length,s;at[e]).bind(null,s),enumerable:!(r=kt(t,s))||r.enumerable});return e},It=(e,t,n)=>(n=e==null?{}:Dt(jt(e)),Ft(t||!e||!e.__esModule?Ot(n,`default`,{value:e,enumerable:!0}):n,e)),Lt=(e=>typeof require<`u`?require:typeof Proxy<`u`?new Proxy(e,{get:(e,t)=>(typeof require<`u`?require:e)[t]}):e)(function(e){if(typeof require<`u`)return require.apply(this,arguments);throw Error('Calling `require` for "'+e+"\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.")}),Rt=Pt({abs:()=>ln,add:()=>tn,band:()=>vn,bitLength:()=>Ut,bits:()=>Qt,bor:()=>yn,bxor:()=>bn,div:()=>un,e:()=>Vt,eq:()=>fn,exp:()=>cn,fromArray:()=>Ht,fromRprBE:()=>Dn,fromRprLE:()=>En,fromString:()=>Bt,geq:()=>_n,gt:()=>hn,isNegative:()=>Wt,isOdd:()=>Xt,isZero:()=>Gt,land:()=>xn,leq:()=>gn,lnot:()=>Cn,lor:()=>Sn,lt:()=>mn,mod:()=>dn,mul:()=>an,naf:()=>Zt,neg:()=>rn,neq:()=>pn,one:()=>jn,pow:()=>sn,shiftLeft:()=>Kt,shiftRight:()=>qt,shl:()=>Jt,shr:()=>Yt,square:()=>on,sub:()=>nn,toArray:()=>en,toLEBuff:()=>kn,toNumber:()=>$t,toRprBE:()=>Tn,toRprLE:()=>wn,toString:()=>On,zero:()=>An}),zt=[0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4];function Bt(e,t){if(!t||t==10)return BigInt(e);if(t==16)return e.slice(0,2)==`0x`?BigInt(e):BigInt(`0x`+e)}var Vt=Bt;function Ht(e,t){let n=BigInt(0);t=BigInt(t);for(let r=0;r>BigInt(t)}var Jt=Kt,Yt=qt;function Xt(e){return(BigInt(e)&BigInt(1))==BigInt(1)}function Zt(e){let t=BigInt(e),n=[];for(;t;){if(t&BigInt(1)){let e=2-Number(t%BigInt(4));n.push(e),t-=BigInt(e)}else n.push(0);t>>=BigInt(1)}return n}function Qt(e){let t=BigInt(e),n=[];for(;t;)t&BigInt(1)?n.push(1):n.push(0),t>>=BigInt(1);return n}function $t(e){if(e>BigInt(2**53-1))throw Error(`Number too big`);return Number(e)}function en(e,t){let n=[],r=BigInt(e);for(t=BigInt(t);r;)n.unshift(Number(r%t)),r/=t;return n}function tn(e,t){return BigInt(e)+BigInt(t)}function nn(e,t){return BigInt(e)-BigInt(t)}function rn(e){return-BigInt(e)}function an(e,t){return BigInt(e)*BigInt(t)}function on(e){return BigInt(e)*BigInt(e)}function sn(e,t){return BigInt(e)**BigInt(t)}function cn(e,t){return BigInt(e)**BigInt(t)}function ln(e){return BigInt(e)>=0?BigInt(e):-BigInt(e)}function un(e,t){return BigInt(e)/BigInt(t)}function dn(e,t){return BigInt(e)%BigInt(t)}function fn(e,t){return BigInt(e)==BigInt(t)}function pn(e,t){return BigInt(e)!=BigInt(t)}function mn(e,t){return BigInt(e)BigInt(t)}function gn(e,t){return BigInt(e)<=BigInt(t)}function _n(e,t){return BigInt(e)>=BigInt(t)}function vn(e,t){return BigInt(e)&BigInt(t)}function yn(e,t){return BigInt(e)|BigInt(t)}function bn(e,t){return BigInt(e)^BigInt(t)}function xn(e,t){return BigInt(e)&&BigInt(t)}function Sn(e,t){return BigInt(e)||BigInt(t)}function Cn(e){return!BigInt(e)}function wn(e,t,n,r){let i=`0000000`+n.toString(16),a=new Uint32Array(e.buffer,e.byteOffset+t,r/4),o=((i.length-7)*4-1>>5)+1;for(let e=0;e>5)+1;for(let e=0;ei[i.length-t-1]=e.toString(16).padStart(8,`0`)),Bt(i.join(``),16)}function Dn(e,t,n){n||=e.byteLength,t||=0;let r=new DataView(e.buffer,e.byteOffset+t,n),i=Array(n/4);for(let e=0;e>=1;return n}function Pn(e,t,n){if(Gt(n))return e.one;let r=Qt(n);if(r.length==0)return e.one;let i=t;for(let n=r.length-2;n>=0;n--)i=e.square(i),r[n]&&(i=e.mul(i,t));return i}function Fn(e){if(e.m%2==1)if(fn(dn(e.p,4),1))if(fn(dn(e.p,8),1))if(fn(dn(e.p,16),1))In(e);else if(fn(dn(e.p,16),9))Ln(e);else throw Error(`Field withot sqrt`);else if(fn(dn(e.p,8),5))Rn(e);else throw Error(`Field withot sqrt`);else fn(dn(e.p,4),3)&&zn(e);else{let t=dn(sn(e.p,e.m/2),4);t==1?Bn(e):t==3?Vn(e):Hn(e)}}function In(e){for(e.sqrt_q=sn(e.p,e.m),e.sqrt_s=0,e.sqrt_t=nn(e.sqrt_q,1);!Xt(e.sqrt_t);)e.sqrt_s+=1,e.sqrt_t=un(e.sqrt_t,2);let t=e.one;for(;e.eq(t,e.one);){let n=e.random();e.sqrt_z=e.pow(n,e.sqrt_t),t=e.pow(e.sqrt_z,2**(e.sqrt_s-1))}e.sqrt_tm1d2=un(nn(e.sqrt_t,1),2),e.sqrt=function(e){let t=this;if(t.isZero(e))return t.zero;let n=t.pow(e,t.sqrt_tm1d2),r=t.pow(t.mul(t.square(n),e),2**(t.sqrt_s-1));if(t.eq(r,t.negone))return null;let i=t.sqrt_s,a=t.mul(e,n),o=t.mul(a,n),s=t.sqrt_z;for(;!t.eq(o,t.one);){let e=t.square(o),r=1;for(;!t.eq(e,t.one);)e=t.square(e),r++;n=s;for(let e=0;e>>0,e[i]=(e[i]^e[t])>>>0,e[i]=(e[i]<<16|e[i]>>>16&65535)>>>0,e[r]=e[r]+e[i]>>>0,e[n]=(e[n]^e[r])>>>0,e[n]=(e[n]<<12|e[n]>>>20&4095)>>>0,e[t]=e[t]+e[n]>>>0,e[i]=(e[i]^e[t])>>>0,e[i]=(e[i]<<8|e[i]>>>24&255)>>>0,e[r]=e[r]+e[i]>>>0,e[n]=(e[n]^e[r])>>>0,e[n]=(e[n]<<7|e[n]>>>25&127)>>>0}function Wn(e){Un(e,0,4,8,12),Un(e,1,5,9,13),Un(e,2,6,10,14),Un(e,3,7,11,15),Un(e,0,5,10,15),Un(e,1,6,11,12),Un(e,2,7,8,13),Un(e,3,4,9,14)}var Gn=class{constructor(e){e||=[0,0,0,0,0,0,0,0],this.state=[1634760805,857760878,2036477234,1797285236,e[0],e[1],e[2],e[3],e[4],e[5],e[6],e[7],0,0,0,0],this.idx=16,this.buff=Array(16)}nextU32(){return this.idx==16&&this.update(),this.buff[this.idx++]}nextU64(){return tn(an(this.nextU32(),4294967296),this.nextU32())}nextBool(){return(this.nextU32()&1)==1}update(){for(let e=0;e<16;e++)this.buff[e]=this.state[e];for(let e=0;e<10;e++)Wn(this.buff);for(let e=0;e<16;e++)this.buff[e]=this.buff[e]+this.state[e]>>>0;this.idx=0,this.state[12]=this.state[12]+1>>>0,this.state[12]==0&&(this.state[13]=this.state[13]+1>>>0,this.state[13]==0&&(this.state[14]=this.state[14]+1>>>0,this.state[14]==0&&(this.state[15]=this.state[15]+1>>>0)))}},Kn=Nt(((e,t)=>{t.exports={}}));function qn(e){let t=new Uint8Array(e);if(globalThis.crypto!==void 0)globalThis.crypto.getRandomValues(t);else if(typeof Lt==`function`)Kn().randomFillSync(t);else throw Error(`No cryptographically secure random source available.`);return t}function Jn(){let e=qn(32),t=new Uint32Array(e.buffer),n=[];for(let e=0;e<8;e++)n.push(t[e]);return n}var Yn=null;function Xn(){return Yn||(Yn=new Gn(Jn()),Yn)}var Zn=class{constructor(e,t,n){this.F=t,this.G=e,this.opMulGF=n;let r=t.sqrt_t||t.t,i=t.sqrt_s||t.s,a=t.one;for(;t.eq(t.pow(a,t.half),t.one);)a=t.add(a,t.one);this.w=Array(i+1),this.wi=Array(i+1),this.w[i]=this.F.pow(a,r),this.wi[i]=this.F.inv(this.w[i]);let o=i-1;for(;o>=0;)this.w[o]=this.F.square(this.w[o+1]),this.wi[o]=this.F.square(this.wi[o+1]),o--;this.roots=[],this._setRoots(Math.min(i,15))}_setRoots(e){for(let t=e;t>=0&&!this.roots[t];t--){let e=this.F.one,n=1<>1,s=$n(e,t,n-1,r,i*2),c=$n(e,t,n-1,r+i,i*2),l=Array(a);for(let t=0;t>this.one,this.bitLength=Ut(this.p),this.mask=(this.one<>this.one;this.nqr=this.two;let n=this.pow(this.nqr,t);for(;!this.eq(n,this.negone);)this.nqr+=this.one,n=this.pow(this.nqr,t);for(this.s=0,this.t=this.negone;(this.t&this.one)==this.zero;)this.s+=1,this.t>>=this.one;this.nqr_to_t=this.pow(this.nqr,this.t),Fn(this),this.FFT=new Zn(this,this,this.mul.bind(this)),this.fft=this.FFT.fft.bind(this.FFT),this.ifft=this.FFT.ifft.bind(this.FFT),this.w=this.FFT.w,this.wi=this.FFT.wi,this.shift=this.square(this.nqr),this.k=this.exp(this.nqr,2**this.s)}e(e,t){let n;if(t?t==16&&(n=BigInt(`0x`+e)):n=BigInt(e),n<0){let e=-n;return e>=this.p&&(e%=this.p),this.p-e}else return n>=this.p?n%this.p:n}add(e,t){let n=e+t;return n>=this.p?n-this.p:n}sub(e,t){return e>=t?e-t:this.p-t+e}neg(e){return e&&this.p-e}mul(e,t){return e*t%this.p}mulScalar(e,t){return e*this.e(t)%this.p}square(e){return e*e%this.p}eq(e,t){return e==t}neq(e,t){return e!=t}lt(e,t){return(e>this.half?e-this.p:e)<(t>this.half?t-this.p:t)}gt(e,t){return(e>this.half?e-this.p:e)>(t>this.half?t-this.p:t)}leq(e,t){return(e>this.half?e-this.p:e)<=(t>this.half?t-this.p:t)}geq(e,t){return(e>this.half?e-this.p:e)>=(t>this.half?t-this.p:t)}div(e,t){return this.mul(e,this.inv(t))}idiv(e,t){if(!t)throw Error(`Division by zero`);return e/t}inv(e){if(!e)throw Error(`Division by zero`);let t=this.zero,n=this.p,r=this.one,i=e%this.p;for(;i;){let e=n/i;[t,r]=[r,t-e*r],[n,i]=[i,n-e*i]}return t=this.p?n-this.p:n}bor(e,t){let n=(e|t)&this.mask;return n>=this.p?n-this.p:n}bxor(e,t){let n=(e^t)&this.mask;return n>=this.p?n-this.p:n}bnot(e){let t=e^this.mask;return t>=this.p?t-this.p:t}shl(e,t){if(Number(t)=this.p?n-this.p:n}else{let n=this.p-t;return Number(n)>n:this.zero}}shr(e,t){if(Number(t)>t;{let n=this.p-t;if(Number(n)=this.p?t-this.p:t}else return 0}}land(e,t){return e&&t?this.one:this.zero}lor(e,t){return e||t?this.one:this.zero}lnot(e){return e?this.zero:this.one}sqrt_old(e){if(e==this.zero)return this.zero;if(this.pow(e,this.negone>>this.one)!=this.one)return null;let t=this.s,n=this.nqr_to_t,r=this.pow(e,this.t),i=this.pow(e,this.add(this.t,this.one)>>this.one);for(;r!=this.one;){let e=this.square(r),a=1;for(;e!=this.one;)a++,e=this.square(e);let o=n;for(let e=0;ethis.p>>this.one&&(i=this.neg(i)),i}normalize(e,t){if(e=BigInt(e,t),e<0){let t=-e;return t>=this.p&&(t%=this.p),this.p-t}else return e>=this.p?e%this.p:e}random(){let e=this.bitLength*2/8,t=this.zero;for(let n=0;nthis.half&&t==10?`-`+(this.p-e).toString(t):e.toString(t),n}isZero(e){return e==this.zero}fromRng(e){let t;do{t=this.zero;for(let n=0;n=this.p);return t=t*this.Ri%this.p,t}fft(e){return this.FFT.fft(e)}ifft(e){return this.FFT.ifft(e)}toRprLE(e,t,n){wn(e,t,n,this.n64*8)}toRprBE(e,t,n){Tn(e,t,n,this.n64*8)}toRprBEM(e,t,n){return this.toRprBE(e,t,this.mul(this.R,n))}toRprLEM(e,t,n){return this.toRprLE(e,t,this.mul(this.R,n))}fromRprLE(e,t){return En(e,t,this.n8)}fromRprBE(e,t){return Dn(e,t,this.n8)}fromRprLEM(e,t){return this.mul(this.fromRprLE(e,t),this.Ri)}fromRprBEM(e,t){return this.mul(this.fromRprBE(e,t),this.Ri)}toObject(e){return e}},tr=Pt({array2buffer:()=>hr,beBuff2int:()=>ir,beInt2Buff:()=>ar,bitReverse:()=>fr,buffReverseBits:()=>mr,buffer2array:()=>gr,leBuff2int:()=>or,leInt2Buff:()=>sr,log2:()=>pr,stringifyBigInts:()=>nr,stringifyFElements:()=>cr,unstringifyBigInts:()=>rr,unstringifyFElements:()=>lr});function nr(e){if(typeof e==`bigint`||e.eq!==void 0)return e.toString(10);if(e instanceof Uint8Array)return En(e,0);if(Array.isArray(e))return e.map(nr);if(typeof e==`object`){let t={};return Object.keys(e).forEach(n=>{t[n]=nr(e[n])}),t}else return e}function rr(e){if(typeof e==`string`&&/^[0-9]+$/.test(e)||typeof e==`string`&&/^0x[0-9a-fA-F]+$/.test(e))return BigInt(e);if(Array.isArray(e))return e.map(rr);if(typeof e==`object`){if(e===null)return null;let t={};return Object.keys(e).forEach(n=>{t[n]=rr(e[n])}),t}else return e}function ir(e){let t=BigInt(0),n=e.length,r=0,i=new DataView(e.buffer,e.byteOffset,e.byteLength);for(;n>0;)n>=4?(n-=4,t+=BigInt(i.getUint32(n))<=2?(n-=2,t+=BigInt(i.getUint16(n))<0;)a-4>=0?(a-=4,i.setUint32(a,Number(n&BigInt(4294967295))),n>>=BigInt(32)):a-2>=0?(a-=2,i.setUint16(a,Number(n&BigInt(65535))),n>>=BigInt(16)):(--a,i.setUint8(a,Number(n&BigInt(255))),n>>=BigInt(8));if(n)throw Error(`Number does not fit in this length`);return r}function or(e){let t=BigInt(0),n=0,r=new DataView(e.buffer,e.byteOffset,e.byteLength);for(;n>=BigInt(32)):a+2<=t?(i.setUint16(a,Number(n&BigInt(65535)),!0),a+=2,n>>=BigInt(16)):(i.setUint8(a,Number(n&BigInt(255)),!0),a+=1,n>>=BigInt(8));if(n)throw Error(`Number does not fit in this length`);return r}function cr(e,t){if(typeof t==`bigint`||t.eq!==void 0)return t.toString(10);if(t instanceof Uint8Array)return e.toString(e.e(t));if(Array.isArray(t))return t.map(cr.bind(this,e));if(typeof t==`object`){let n={};return Object.keys(t).forEach(r=>{n[r]=cr(e,t[r])}),n}else return t}function lr(e,t){if(typeof t==`string`&&/^[0-9]+$/.test(t)||typeof t==`string`&&/^0x[0-9a-fA-F]+$/.test(t))return e.e(t);if(Array.isArray(t))return t.map(lr.bind(this,e));if(typeof t==`object`){if(t===null)return null;let n={};return Object.keys(t).forEach(r=>{n[r]=lr(e,t[r])}),n}else return t}var ur=[];for(let e=0;e<256;e++)ur[e]=dr(e,8);function dr(e,t){let n=0,r=e;for(let e=0;e>=1;return n}function fr(e,t){return(ur[e>>>24]|ur[e>>>16&255]<<8|ur[e>>>8&255]<<16|ur[e&255]<<24)>>>32-t}function pr(e){return(e&4294901760?(e&=4294901760,16):0)|(e&4278255360?(e&=4278255360,8):0)|(e&4042322160?(e&=4042322160,4):0)|(e&3435973836?(e&=3435973836,2):0)|(e&2863311530)!=0}function mr(e,t){let n=e.byteLength/t,r=pr(n);if(n!=1<n){let r=e.slice(i*t,(i+1)*t);e.set(e.slice(n*t,(n+1)*t),i*t),e.set(r,n*t)}}}function hr(e,t){let n=new Uint8Array(t*e.length);for(let r=0;r0;){let t=s+c>_r?_r-s:c,n=new Uint8Array(this.buffers[o].buffer,this.buffers[o].byteOffset+s,t);if(t==r)return n.slice();a||=r<=_r?new Uint8Array(r):new e(r),a.set(n,r-c),c-=t,o++,s=0}return a}set(t,n){n===void 0&&(n=0);let r=t.byteLength;if(r==0)return;let i=Math.floor(n/_r);if(i==Math.floor((n+r-1)/_r))return t instanceof e&&t.buffers.length==1?this.buffers[i].set(t.buffers[0],n%_r):this.buffers[i].set(t,n%_r);let a=i,o=n%_r,s=r;for(;s>0;){let e=o+s>_r?_r-o:s,n=t.slice(r-s,r-s+e);new Uint8Array(this.buffers[a].buffer,this.buffers[a].byteOffset+o,e).set(n),s-=e,a++,o=0}}};function vr(e,t,n,r){return async function(i){let a=Math.floor(i.byteLength/n);if(a*n!==i.byteLength)throw Error(`Invalid buffer size`);let o=Math.floor(a/e.concurrency),s=[];for(let c=0;c=0;e--)this.w[e]=this.square(this.w[e+1]);if(!this.eq(this.w[0],this.one))throw Error(`Error calculating roots of unity`);this.batchToMontgomery=vr(e,t+`_batchToMontgomery`,this.n8,this.n8),this.batchFromMontgomery=vr(e,t+`_batchFromMontgomery`,this.n8,this.n8)}op2(e,t,n){return this.tm.setBuff(this.pOp1,t),this.tm.setBuff(this.pOp2,n),this.tm.instance.exports[this.prefix+e](this.pOp1,this.pOp2,this.pOp3),this.tm.getBuff(this.pOp3,this.n8)}op2Bool(e,t,n){return this.tm.setBuff(this.pOp1,t),this.tm.setBuff(this.pOp2,n),!!this.tm.instance.exports[this.prefix+e](this.pOp1,this.pOp2)}op1(e,t){return this.tm.setBuff(this.pOp1,t),this.tm.instance.exports[this.prefix+e](this.pOp1,this.pOp3),this.tm.getBuff(this.pOp3,this.n8)}op1Bool(e,t){return this.tm.setBuff(this.pOp1,t),!!this.tm.instance.exports[this.prefix+e](this.pOp1,this.pOp3)}add(e,t){return this.op2(`_add`,e,t)}eq(e,t){return this.op2Bool(`_eq`,e,t)}isZero(e){return this.op1Bool(`_isZero`,e)}sub(e,t){return this.op2(`_sub`,e,t)}neg(e){return this.op1(`_neg`,e)}inv(e){return this.op1(`_inverse`,e)}toMontgomery(e){return this.op1(`_toMontgomery`,e)}fromMontgomery(e){return this.op1(`_fromMontgomery`,e)}mul(e,t){return this.op2(`_mul`,e,t)}div(e,t){return this.tm.setBuff(this.pOp1,e),this.tm.setBuff(this.pOp2,t),this.tm.instance.exports[this.prefix+`_inverse`](this.pOp2,this.pOp2),this.tm.instance.exports[this.prefix+`_mul`](this.pOp1,this.pOp2,this.pOp3),this.tm.getBuff(this.pOp3,this.n8)}square(e){return this.op1(`_square`,e)}isSquare(e){return this.op1Bool(`_isSquare`,e)}sqrt(e){return this.op1(`_sqrt`,e)}exp(e,t){return t instanceof Uint8Array||(t=kn(Vt(t))),this.tm.setBuff(this.pOp1,e),this.tm.setBuff(this.pOp2,t),this.tm.instance.exports[this.prefix+`_exp`](this.pOp1,this.pOp2,t.byteLength,this.pOp3),this.tm.getBuff(this.pOp3,this.n8)}isNegative(e){return this.op1Bool(`_isNegative`,e)}e(e,t){if(e instanceof Uint8Array)return e;let n=Vt(e,t);Wt(n)?(n=rn(n),hn(n,this.p)&&(n=dn(n,this.p)),n=nn(this.p,n)):hn(n,this.p)&&(n=dn(n,this.p));let r=sr(n,this.n8);return this.toMontgomery(r)}toString(e,t){return On(En(this.fromMontgomery(e),0),t)}fromRng(e){let t,n=new Uint8Array(this.n8);do{t=An;for(let n=0;nn.buffer.byteLength){let i=n.buffer.byteLength/65536,a=Math.floor((r[0]+t)/65536)+1;a>e&&(a=e),n.grow(a-i)}return i}function l(e){let t=e instanceof Uint8Array?e:new Uint8Array(e),n=c(t.byteLength);return o().set(t,n),n}function u(e,t){return new Uint8Array(n.buffer,e,t)}function d(e,t){o().set(t instanceof Uint8Array?t:new Uint8Array(t),e)}function f(e){if(e[0].cmd===`INIT`)return s(e[0]);let n=[],r=[],i=a()[0];for(let i=0;i{(function(n,r){typeof e==`object`&&t!==void 0?r(e):typeof define==`function`&&define.amd?define([`exports`],r):(n=typeof globalThis<`u`?globalThis:n||self,r(n.workerpool={}))})(e,(function(e){"use strict";var t={},n={exports:{}};(function(e){var t=function(e){return e!==void 0&&e.versions!=null&&e.versions.node!=null&&e+``==`[object process]`};e.exports.isNode=t,e.exports.platform=typeof process<`u`&&t(process)?`node`:`browser`;var n=e.exports.platform===`node`&&Kn();e.exports.isMainThread=e.exports.platform===`node`?(!n||n.isMainThread)&&!process.connected:typeof Window<`u`,e.exports.cpus=e.exports.platform===`browser`?self.navigator.hardwareConcurrency:Kn().cpus().length})(n);var r=n.exports;function i(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:i}}throw TypeError(`Invalid attempt to iterate non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var a,o=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return o=e.done,e},e:function(e){s=!0,a=e},f:function(){try{o||n.return==null||n.return()}finally{if(s)throw a}}}}function d(e,t,n){return(t=x(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function f(e){return f=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},f(e)}function p(e,t){if(typeof t!=`function`&&t!==null)throw TypeError(`Super expression must either be null or a function`);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,`prototype`,{writable:!1}),t&&y(e,t)}function m(e){try{return Function.toString.call(e).indexOf(`[native code]`)!==-1}catch{return typeof e==`function`}}function h(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch{}return(h=function(){return!!e})()}function g(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function _(e){for(var t=1;t= 11.7.0 required`);return e}function re(){if(typeof Worker!=`function`&&((typeof Worker>`u`?`undefined`:S(Worker))!==`object`||typeof Worker.prototype.constructor!=`function`))throw Error(`WorkerPool: Web Workers not supported`)}function ie(){try{return Kn()}catch(e){if(S(e)===`object`&&e!==null&&e.code===`MODULE_NOT_FOUND`)return null;throw e}}function ae(){if(P.platform===`browser`){if(typeof Blob>`u`)throw Error(`Blob not supported by the browser`);if(!window.URL||typeof window.URL.createObjectURL!=`function`)throw Error(`URL.createObjectURL not supported by the browser`);var e=new Blob([M()],{type:`text/javascript`});return window.URL.createObjectURL(e)}else return __dirname+`/worker.js`}function oe(e,t){if(t.workerType===`web`)return re(),se(e,t.workerOpts,Worker);if(t.workerType===`thread`)return n=ne(),ce(e,n,t);if(t.workerType===`process`||!t.workerType)return le(e,ue(t),Kn());if(P.platform===`browser`)return re(),se(e,t.workerOpts,Worker);var n=ie();return n?ce(e,n,t):le(e,ue(t),Kn())}function se(e,t,n){F(t,ee,`workerOpts`);var r=new n(e,t);return r.isBrowserWorker=!0,r.on=function(e,t){this.addEventListener(e,function(e){t(e.data)})},r.send=function(e,t){this.postMessage(e,t)},r}function ce(e,t,n){F(n?.workerThreadOpts,L,`workerThreadOpts`);var r=new t.Worker(e,_({stdout:n?.emitStdStreams??!1,stderr:n?.emitStdStreams??!1},n?.workerThreadOpts));return r.isWorkerThread=!0,r.send=function(e,t){this.postMessage(e,t)},r.kill=function(){return this.terminate(),!0},r.disconnect=function(){this.terminate()},n!=null&&n.emitStdStreams&&(r.stdout.on(`data`,function(e){return r.emit(`stdout`,e)}),r.stderr.on(`data`,function(e){return r.emit(`stderr`,e)})),r}function le(e,t,n){F(t.forkOpts,I,`forkOpts`);var r=n.fork(e,t.forkArgs,t.forkOpts),i=r.send;return r.send=function(e){return i.call(r,e)},t.emitStdStreams&&(r.stdout.on(`data`,function(e){return r.emit(`stdout`,e)}),r.stderr.on(`data`,function(e){return r.emit(`stderr`,e)})),r.isChildProcess=!0,r}function ue(e){e||={};var t=process.execArgv.join(` `),n=t.indexOf(`--inspect`)!==-1,r=t.indexOf(`--debug-brk`)!==-1,i=[];return n&&(i.push(`--inspect=`+e.debugPort),r&&i.push(`--debug-brk`)),process.execArgv.forEach(function(e){e.indexOf(`--max-old-space-size`)>-1&&i.push(e)}),Object.assign({},e,{forkArgs:e.forkArgs,forkOpts:Object.assign({},e.forkOpts,{execArgv:(e.forkOpts&&e.forkOpts.execArgv||[]).concat(i),stdio:e.emitStdStreams?`pipe`:void 0})})}function de(e){for(var t=Error(``),n=Object.keys(e),r=0;r0},pe.prototype.terminate=function(e,t){var n=this;if(e){for(var r in this.processing)this.processing[r]!==void 0&&this.processing[r].resolver.reject(Error(`Worker terminated`));this.processing=Object.create(null)}for(var i=0,a=Object.values(n.tracking);i=e)throw Error(`WorkerPool debug port limit reached: `+t+`>= `+e);return this.ports[t]=!0,this.length++,t},t.prototype.releasePort=function(e){delete this.ports[e],this.length--},z}var Se,Ce;function we(){if(Ce)return Se;Ce=1;var e=O().Promise,t=ge,n=r,i=ye(),a=i.FIFOQueue,o=i.LIFOQueue,s=new(xe());function c(e,r){typeof e==`string`?this.script=e||null:(this.script=null,r=e),this.workers=[],this.taskQueue=this._createQueue(r&&r.queueStrategy||`fifo`),r||={},this.forkArgs=Object.freeze(r.forkArgs||[]),this.forkOpts=Object.freeze(r.forkOpts||{}),this.workerOpts=Object.freeze(r.workerOpts||{}),this.workerThreadOpts=Object.freeze(r.workerThreadOpts||{}),this.debugPortStart=r.debugPortStart||43210,this.nodeWorker=r.nodeWorker,this.workerType=r.workerType||r.nodeWorker||`auto`,this.maxQueueSize=r.maxQueueSize||1/0,this.workerTerminateTimeout=r.workerTerminateTimeout||1e3,this.onCreateWorker=r.onCreateWorker||function(){return null},this.onTerminateWorker=r.onTerminateWorker||function(){return null},this.emitStdStreams=r.emitStdStreams||!1,r&&`maxWorkers`in r?(l(r.maxWorkers),this.maxWorkers=r.maxWorkers):this.maxWorkers=Math.max((n.cpus||4)-1,1),r&&`minWorkers`in r&&(r.minWorkers===`max`?this.minWorkers=this.maxWorkers:(u(r.minWorkers),this.minWorkers=r.minWorkers,this.maxWorkers=Math.max(this.minWorkers,this.maxWorkers)),this._ensureMinWorkers()),this._boundNext=this._next.bind(this),this.workerType===`thread`&&t.ensureWorkerThreads()}c.prototype.exec=function(t,n,r){if(n&&!Array.isArray(n))throw TypeError(`Array expected as argument "params"`);if(typeof t==`string`){var i=e.defer();if(this.taskQueue.size()>=this.maxQueueSize)throw Error(`Max queue size of `+this.maxQueueSize+` reached`);var a={method:t,params:n,resolver:i,timeout:null,options:r};this.taskQueue.push(a);var o=i.promise.timeout,s=this.taskQueue;return i.promise.timeout=function(e){return s.contains(a)?(a.timeout=e,i.promise):o.call(i.promise,e)},this._next(),i.promise}else if(typeof t==`function`)return this.exec(`run`,[String(t),n],r);else throw TypeError(`Function or string expected as argument "method"`)},c.prototype.proxy=function(){if(arguments.length>0)throw Error(`No arguments expected`);var e=this;return this.exec(`methods`).then(function(t){var n={};return t.forEach(function(t){n[t]=function(){return e.exec(t,Array.prototype.slice.call(arguments))}}),n})},c.prototype._next=function(){if(this.taskQueue.size()>0){var e=this._getWorker();if(e){var t=this,n=this.taskQueue.pop();if(n.resolver.promise.pending){var r=e.exec(n.method,n.params,n.resolver,n.options).then(t._boundNext).catch(function(){if(e.terminated)return t._removeWorker(e)}).then(function(){t._next()});typeof n.timeout==`number`&&r.timeout(n.timeout)}else t._next()}}},c.prototype._getWorker=function(){for(var e=this.workers,t=0;t0;){var a=i.pop();if(a)a.resolver.reject(Error(`Pool terminated`));else break}i.clear();var o=function(e){s.releasePort(e.debugPort),this._removeWorkerFromList(e)}.bind(this),c=[];return this.workers.slice().forEach(function(e){var i=e.terminateAndNotify(t,n).then(o).always(function(){r.onTerminateWorker({forkArgs:e.forkArgs,forkOpts:e.forkOpts,workerThreadOpts:e.workerThreadOpts,script:e.script})});c.push(i)}),e.all(c)},c.prototype.stats=function(){var e=this.workers.length,t=this.workers.filter(function(e){return e.busy()}).length;return{totalWorkers:e,busyWorkers:t,idleWorkers:e-t,pendingTasks:this.taskQueue.size(),activeTasks:t}},c.prototype._ensureMinWorkers=function(){if(this.minWorkers)for(var e=this.workers.length;e= 1`)}function u(e){if(!d(e)||!f(e)||e<0)throw TypeError(`Option minWorkers must be an integer number >= 0`)}function d(e){return typeof e==`number`}function f(e){return Math.round(e)==e}return Se=c,Se}var Te={},Ee,De;function Oe(){if(De)return Ee;De=1;function e(e,t){this.message=e,this.transfer=t}return Ee=e,Ee}var ke;function Ae(){return ke?Te:(ke=1,(function(e){var t=Oe(),n=O().Promise,r=`__workerpool-terminate__`,i=`__workerpool-cleanup__`,a=1e3,o={exit:function(){}},s={addAbortListener:function(e){o.abortListeners.push(e)},emit:o.emit};if(typeof self<`u`&&typeof postMessage==`function`&&typeof addEventListener==`function`)o.on=function(e,t){addEventListener(e,function(e){t(e.data)})},o.send=function(e,t){t?postMessage(e,t):postMessage(e)};else if(typeof process<`u`){var c;try{c=Kn()}catch(e){if(!(S(e)===`object`&&e!==null&&e.code===`MODULE_NOT_FOUND`))throw e}if(c&&c.parentPort!==null){var l=c.parentPort;o.send=l.postMessage.bind(l),o.on=l.on.bind(l),o.exit=process.exit.bind(process)}else o.on=process.on.bind(process),o.send=function(e){process.send(e)},o.on(`disconnect`,function(){process.exit(1)}),o.exit=process.exit.bind(process)}else throw Error(`Script must be executed as a worker`);function u(e){return e&&e.toJSON?JSON.parse(JSON.stringify(e)):JSON.parse(JSON.stringify(e,Object.getOwnPropertyNames(e)))}function d(e){return e&&typeof e.then==`function`&&typeof e.catch==`function`}o.methods={},o.methods.run=function(e,t){var n=Function(`return (`+e+`).apply(this, arguments);`);return n.worker=s,n.apply(n,t)},o.methods.methods=function(){return Object.keys(o.methods)},o.terminationHandler=void 0,o.abortListenerTimeout=a,o.abortListeners=[],o.terminateAndExit=function(e){var t=function(){o.exit(e)};if(!o.terminationHandler)return t();var r=o.terminationHandler(e);return d(r)?(r.then(t,t),r):(t(),new n(function(e,t){t(Error(`Worker terminating`))}))},o.cleanup=function(e){if(!o.abortListeners.length)return o.send({id:e,method:i,error:u(Error(`Worker terminating`))}),new n(function(e){e()});var t=function(){o.exit()},r=function(){o.abortListeners.length||(o.abortListeners=[])},a=o.abortListeners.map(function(e){return e()}),s,c=new n(function(e,t){s=setTimeout(function(){t(Error(`Timeout occured waiting for abort handler, killing worker`))},o.abortListenerTimeout)}),l=n.all(a).then(function(){clearTimeout(s),r()},function(){clearTimeout(s),t()});return new n(function(e,t){l.then(e,t),c.then(e,t)}).then(function(){o.send({id:e,method:i,error:null})},function(t){o.send({id:e,method:i,error:t?u(t):null})})};var f=null;o.on(`message`,function(e){if(e===r)return o.terminateAndExit(0);if(e.method===i)return o.cleanup(e.id);try{var n=o.methods[e.method];if(n){f=e.id;var a=n.apply(n,e.params);d(a)?a.then(function(n){n instanceof t?o.send({id:e.id,result:n.message,error:null},n.transfer):o.send({id:e.id,result:n,error:null}),f=null}).catch(function(t){o.send({id:e.id,result:null,error:u(t)}),f=null}):(a instanceof t?o.send({id:e.id,result:a.message,error:null},a.transfer):o.send({id:e.id,result:a,error:null}),f=null)}else throw Error(`Unknown method "`+e.method+`"`)}catch(t){o.send({id:e.id,result:null,error:u(t)})}}),o.register=function(e,t){if(e)for(var n in e)e.hasOwnProperty(n)&&(o.methods[n]=e[n],o.methods[n].worker=s);t&&(o.terminationHandler=t.onTerminate,o.abortListenerTimeout=t.abortListenerTimeout||a),o.send(`ready`)},o.emit=function(e){if(f){if(e instanceof t){o.send({id:f,isEvent:!0,payload:e.message},e.transfer);return}o.send({id:f,isEvent:!0,payload:e})}},e.add=o.register,e.emit=o.emit})(Te),Te)}var je=r.platform,Me=r.isMainThread,Ne=r.cpus,Pe=ge.TerminateError;function Fe(e,t){return new(we())(e,t)}var Ie=t.pool=Fe;function Le(e,t){Ae().add(e,t)}var Re=t.worker=Le;function ze(e){Ae().emit(e)}var Be=t.workerEmit=ze,Ve=t.Promise=O().Promise,He=t.Transfer=Oe(),Ue=t.platform=je,We=t.isMainThread=Me,Ge=t.cpus=Ne,Ke=t.TerminateError=Pe;e.Promise=Ve,e.TerminateError=Ke,e.Transfer=He,e.cpus=Ge,e.default=t,e.isMainThread=We,e.platform=Ue,e.pool=Ie,e.worker=Re,e.workerEmit=Be,Object.defineProperty(e,`__esModule`,{value:!0})}))}))(),1),Tr=`!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e="undefined"!=typeof globalThis?globalThis:e||self).worker=n()}(this,(function(){"use strict";function e(n){return e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e(n)}function n(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var t={};var r=function(e,n){this.message=e,this.transfer=n},o={};function i(e,n){var t=this;if(!(this instanceof i))throw new SyntaxError("Constructor must be called with the new operator");if("function"!=typeof e)throw new SyntaxError("Function parameter handler(resolve, reject) missing");var r=[],o=[];this.resolved=!1,this.rejected=!1,this.pending=!0,this[Symbol.toStringTag]="Promise";var a=function(e,n){r.push(e),o.push(n)};this.then=function(e,n){return new i((function(t,r){var o=e?s(e,t,r):t,i=n?s(n,t,r):r;a(o,i)}),t)};var f=function(e){return t.resolved=!0,t.rejected=!1,t.pending=!1,r.forEach((function(n){n(e)})),a=function(n,t){n(e)},f=d=function(){},t},d=function(e){return t.resolved=!1,t.rejected=!0,t.pending=!1,o.forEach((function(n){n(e)})),a=function(n,t){t(e)},f=d=function(){},t};this.cancel=function(){return n?n.cancel():d(new u),t},this.timeout=function(e){if(n)n.timeout(e);else{var r=setTimeout((function(){d(new c("Promise timed out after "+e+" ms"))}),e);t.always((function(){clearTimeout(r)}))}return t},e((function(e){f(e)}),(function(e){d(e)}))}function s(e,n,t){return function(r){try{var o=e(r);o&&"function"==typeof o.then&&"function"==typeof o.catch?o.then(n,t):n(o)}catch(e){t(e)}}}function u(e){this.message=e||"promise cancelled",this.stack=(new Error).stack}function c(e){this.message=e||"timeout exceeded",this.stack=(new Error).stack}return i.prototype.catch=function(e){return this.then(null,e)},i.prototype.always=function(e){return this.then(e,e)},i.prototype.finally=function(e){var n=this,t=function(){return new i((function(e){return e()})).then(e).then((function(){return n}))};return this.then(t,t)},i.all=function(e){return new i((function(n,t){var r=e.length,o=[];r?e.forEach((function(e,i){e.then((function(e){o[i]=e,0==--r&&n(o)}),(function(e){r=0,t(e)}))})):n(o)}))},i.defer=function(){var e={};return e.promise=new i((function(n,t){e.resolve=n,e.reject=t})),e},u.prototype=new Error,u.prototype.constructor=Error,u.prototype.name="CancellationError",i.CancellationError=u,c.prototype=new Error,c.prototype.constructor=Error,c.prototype.name="TimeoutError",i.TimeoutError=c,o.Promise=i,function(n){var t=r,i=o.Promise,s="__workerpool-cleanup__",u={exit:function(){}},c={addAbortListener:function(e){u.abortListeners.push(e)},emit:u.emit};if("undefined"!=typeof self&&"function"==typeof postMessage&&"function"==typeof addEventListener)u.on=function(e,n){addEventListener(e,(function(e){n(e.data)}))},u.send=function(e,n){n?postMessage(e,n):postMessage(e)};else{if("undefined"==typeof process)throw new Error("Script must be executed as a worker");var a;try{a=require("worker_threads")}catch(n){if("object"!==e(n)||null===n||"MODULE_NOT_FOUND"!==n.code)throw n}if(a&&null!==a.parentPort){var f=a.parentPort;u.send=f.postMessage.bind(f),u.on=f.on.bind(f),u.exit=process.exit.bind(process)}else u.on=process.on.bind(process),u.send=function(e){process.send(e)},u.on("disconnect",(function(){process.exit(1)})),u.exit=process.exit.bind(process)}function d(e){return e&&e.toJSON?JSON.parse(JSON.stringify(e)):JSON.parse(JSON.stringify(e,Object.getOwnPropertyNames(e)))}function l(e){return e&&"function"==typeof e.then&&"function"==typeof e.catch}u.methods={},u.methods.run=function(e,n){var t=new Function("return ("+e+").apply(this, arguments);");return t.worker=c,t.apply(t,n)},u.methods.methods=function(){return Object.keys(u.methods)},u.terminationHandler=void 0,u.abortListenerTimeout=1e3,u.abortListeners=[],u.terminateAndExit=function(e){var n=function(){u.exit(e)};if(!u.terminationHandler)return n();var t=u.terminationHandler(e);return l(t)?(t.then(n,n),t):(n(),new i((function(e,n){n(new Error("Worker terminating"))})))},u.cleanup=function(e){if(!u.abortListeners.length)return u.send({id:e,method:s,error:d(new Error("Worker terminating"))}),new i((function(e){e()}));var n,t=u.abortListeners.map((function(e){return e()})),r=new i((function(e,t){n=setTimeout((function(){t(new Error("Timeout occured waiting for abort handler, killing worker"))}),u.abortListenerTimeout)})),o=i.all(t).then((function(){clearTimeout(n),u.abortListeners.length||(u.abortListeners=[])}),(function(){clearTimeout(n),u.exit()}));return new i((function(e,n){o.then(e,n),r.then(e,n)})).then((function(){u.send({id:e,method:s,error:null})}),(function(n){u.send({id:e,method:s,error:n?d(n):null})}))};var p=null;u.on("message",(function(e){if("__workerpool-terminate__"===e)return u.terminateAndExit(0);if(e.method===s)return u.cleanup(e.id);try{var n=u.methods[e.method];if(!n)throw new Error('Unknown method "'+e.method+'"');p=e.id;var r=n.apply(n,e.params);l(r)?r.then((function(n){n instanceof t?u.send({id:e.id,result:n.message,error:null},n.transfer):u.send({id:e.id,result:n,error:null}),p=null})).catch((function(n){u.send({id:e.id,result:null,error:d(n)}),p=null})):(r instanceof t?u.send({id:e.id,result:r.message,error:null},r.transfer):u.send({id:e.id,result:r,error:null}),p=null)}catch(n){u.send({id:e.id,result:null,error:d(n)})}})),u.register=function(e,n){if(e)for(var t in e)e.hasOwnProperty(t)&&(u.methods[t]=e[t],u.methods[t].worker=c);n&&(u.terminationHandler=n.onTerminate,u.abortListenerTimeout=n.abortListenerTimeout||1e3),u.send("ready")},u.emit=function(e){if(p){if(e instanceof t)return void u.send({id:p,isEvent:!0,payload:e.message},e.transfer);u.send({id:p,isEvent:!0,payload:e})}},n.add=u.register,n.emit=u.emit}(t),n(t)})); + +;(function(){ +var runTask=(function thread() { + const MAXMEM = 32767; + let instance; + let memory; + + // Lazily cached typed-array views over wasm memory. + // Invalidated automatically when memory.grow() replaces memory.buffer. + let _u32 = null; + let _u8 = null; + + function getU32() { + if (_u32 === null || _u32.buffer !== memory.buffer) { + _u32 = new Uint32Array(memory.buffer, 0, 1); + } + return _u32; + } + + function getU8() { + if (_u8 === null || _u8.buffer !== memory.buffer) { + _u8 = new Uint8Array(memory.buffer); + } + return _u8; + } + + async function init(data) { + let wasmModule; + if (data.code instanceof WebAssembly.Module) { + wasmModule = data.code; + } else { + wasmModule = await WebAssembly.compile(new Uint8Array(data.code)); + } + memory = new WebAssembly.Memory({initial: data.init, maximum: MAXMEM}); + // Reset cached views — new memory means new backing buffer. + _u32 = null; + _u8 = null; + instance = await WebAssembly.instantiate(wasmModule, {env: {memory}}); + } + + function alloc(length) { + const u32 = getU32(); + // Align to 4 bytes with a branchless bitmask instead of a loop. + u32[0] = (u32[0] + 3) & ~3; + const res = u32[0]; + u32[0] += length; + if (u32[0] + length > memory.buffer.byteLength) { + const currentPages = memory.buffer.byteLength / 0x10000; + let requiredPages = Math.floor((u32[0] + length) / 0x10000) + 1; + if (requiredPages > MAXMEM) requiredPages = MAXMEM; + memory.grow(requiredPages - currentPages); + // memory.buffer changed — cached views are now stale. + } + return res; + } + + function allocBuffer(buffer) { + const src = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer); + const p = alloc(src.byteLength); + // getU8() handles re-creation if alloc() triggered a grow. + getU8().set(src, p); + return p; + } + + function getBuffer(pointer, length) { + return new Uint8Array(memory.buffer, pointer, length); + } + + function setBuffer(pointer, buffer) { + getU8().set(buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer), pointer); + } + + function runTask(task) { + if (task[0].cmd === "INIT") { + // INIT is the only async path — return a Promise so workerpool + // can await it; all other tasks execute synchronously to prevent + // concurrent execution of tasks within the same worker. + return init(task[0]); + } + const vars = []; + const out = []; + const oldAlloc = getU32()[0]; + for (let i = 0; i < task.length; i++) { + const step = task[i]; + switch (step.cmd) { + case "ALLOCSET": + vars[step.var] = allocBuffer(step.buff); + break; + case "ALLOC": + vars[step.var] = alloc(step.len); + break; + case "SET": + setBuffer(vars[step.var], step.buff); + break; + case "CALL": { + const paramDefs = step.params; + const params = new Array(paramDefs.length); + for (let j = 0; j < paramDefs.length; j++) { + const p = paramDefs[j]; + params[j] = p.var !== undefined + ? vars[p.var] + (p.offset || 0) + : p.val; + } + instance.exports[step.fnName](...params); + break; + } + case "GET": + out[step.out] = getBuffer(vars[step.var], step.len).slice(); + break; + default: + throw new Error("Invalid cmd: " + step.cmd); + } + } + // Reclaim task-local allocations. getU32() handles a post-grow buffer. + getU32()[0] = oldAlloc; + return out; + } + + return runTask; +})(); +worker.add({runTask:runTask}); +})();`;function Er(){return typeof navigator==`object`&&navigator.hardwareConcurrency||2}function Dr(){return`web`}function Or(){return typeof Worker<`u`}var kr=null;function Ar(){if(kr)return kr;let e=new Blob([Tr],{type:`application/javascript`});return kr=(globalThis.URL?globalThis.URL:globalThis.webkitURL).createObjectURL(e),kr}var jr=25;async function Mr(e,t){let n=new Nr;n.memory=new WebAssembly.Memory({initial:jr}),n.u8=new Uint8Array(n.memory.buffer),n.u32=new Uint32Array(n.memory.buffer);let r=await WebAssembly.compile(e.code);if(n.instance=await WebAssembly.instantiate(r,{env:{memory:n.memory}}),Or()||(t=!0),n.singleThread=t,n.initalPFree=n.u32[0],n.pq=e.pq,n.pr=e.pr,n.pG1gen=e.pG1gen,n.pG1zero=e.pG1zero,n.pG2gen=e.pG2gen,n.pG2zero=e.pG2zero,n.pOneT=e.pOneT,n.code=e.code,n.wasmModule=r,t)n.taskManager=Cr(),await n.taskManager([{cmd:`INIT`,init:jr,code:n.code.slice()}]),n.concurrency=1;else{let e=Er(),t=Math.min(Math.max(e,2),64);n.concurrency=t,n.pool=wr.default.pool(Ar(),{maxWorkers:t,workerType:Dr()});let r=[];for(let e=0;e=0;e--){if(!n.isZero(h))for(let e=0;el&&(_=l),_(s&&s.debug(`Multiexp end: ${c}: ${t}/${f}`),e)))}let v=await Promise.all(m),y=n.zero;for(let e=v.length-1;e>=0;e--)y=n.add(y,v[e]);return y}n.multiExp=async function(e,t,n,r){return a(e,t,`jacobian`,n,r)},n.multiExpAffine=async function(e,t,n,r){return a(e,t,`affine`,n,r)}}function Rr(e,t){let n=e[t],r=e.Fr,i=n.tm;async function a(e,a,c,l,u,d){c||=`affine`,l||=`affine`;let f,p,m,h,g,_,v,y,b;t==`G1`?(c==`affine`?(f=n.F.n8*2,h=`g1m_batchToJacobian`):f=n.F.n8*3,p=n.F.n8*3,a&&(y=`g1m_fftFinal`),v=`g1m_fftJoin`,_=`g1m_fftMix`,b=`g1m__reversePermutation`,l==`affine`?(m=n.F.n8*2,g=`g1m_batchToAffine`):m=n.F.n8*3):t==`G2`?(c==`affine`?(f=n.F.n8*2,h=`g2m_batchToJacobian`):f=n.F.n8*3,p=n.F.n8*3,a&&(y=`g2m_fftFinal`),v=`g2m_fftJoin`,_=`g2m_fftMix`,b=`g2m__reversePermutation`,l==`affine`?(m=n.F.n8*2,g=`g2m_batchToAffine`):m=n.F.n8*3):t==`Fr`&&(f=n.n8,p=n.n8,m=n.n8,a&&(y=`frm_fftFinal`),_=`frm_fftMix`,v=`frm_fftJoin`,b=`frm__reversePermutation`);let x=!1;Array.isArray(e)?(e=hr(e,f),x=!0):e=e.slice(0,e.byteLength);let S=e.byteLength/f,C=pr(S);if(1<=16;)O*=2,D/=2;let k=pr(D),A=[];u&&u.debug(`${d}: fft ${C} mix start: ${O}`);for(let t=0;t0;t--)T.set(E[t],e),e+=D*m,delete E[t];T.set(E[0].slice(0,(D-1)*m),e),delete E[0]}else for(let e=0;e1<<28?new B(d[0].byteLength*2):new Uint8Array(d[0].byteLength*2),f.set(d[0]),f.set(d[1],d[0].byteLength),f}async function s(e,t,n,i,o){let s,l;s=e.slice(0,e.byteLength/2),l=e.slice(e.byteLength/2,e.byteLength);let u=[];u.push(a(s,!0,t,`jacobian`,i,o)),u.push(a(l,!0,t,`jacobian`,i,o)),[s,l]=await Promise.all(u);let d=await c(s,l,`fftJoinExtInv`,r.one,r.shiftInv,`jacobian`,n,i,o),f;return f=d[0].byteLength>1<<28?new B(d[0].byteLength*2):new Uint8Array(d[0].byteLength*2),f.set(d[0]),f.set(d[1],d[0].byteLength),f}async function c(e,a,o,s,c,l,u,d,f){let p=65536,m,h,g,_,v,y;if(t==`G1`)l==`affine`?(v=n.F.n8*2,h=`g1m_batchToJacobian`):v=n.F.n8*3,y=n.F.n8*3,m=`g1m_`+o,u==`affine`?(g=`g1m_batchToAffine`,_=n.F.n8*2):_=n.F.n8*3;else if(t==`G2`)l==`affine`?(v=n.F.n8*2,h=`g2m_batchToJacobian`):v=n.F.n8*3,m=`g2m_`+o,y=n.F.n8*3,u==`affine`?(g=`g2m_batchToAffine`,_=n.F.n8*2):_=n.F.n8*3;else if(t==`Fr`)v=r.n8,_=r.n8,y=r.n8,m=`frm_`+o;else throw Error(`Invalid group`);if(e.byteLength!=a.byteLength)throw Error(`Invalid buffer size`);let b=Math.floor(e.byteLength/v);if(b!=1<p&&(x=p);let S=[];for(let t=0;t(d&&d.debug(`${f}: fftJoinExt End: ${t}/${b}`),e)))}let C=await Promise.all(S),w,T;b*_>1<<28?(w=new B(b*_),T=new B(b*_)):(w=new Uint8Array(b*_),T=new Uint8Array(b*_));let E=0;for(let e=0;er.s+1)throw s&&s.error(`lagrangeEvaluations input too big`),Error(`lagrangeEvaluations input too big`);let p=e.slice(0,e.byteLength/2),m=e.slice(e.byteLength/2,e.byteLength),h=r.exp(r.shift,d/2),g=r.inv(r.sub(r.one,h));[p,m]=await c(p,m,`prepareLagrangeEvaluation`,g,r.shiftInv,i,`jacobian`,s,l+` prep`);let _=[];_.push(a(p,!0,`jacobian`,o,s,l+` t0`)),_.push(a(m,!0,`jacobian`,o,s,l+` t1`)),[p,m]=await Promise.all(_);let v;return v=p.byteLength>1<<28?new B(p.byteLength*2):new Uint8Array(p.byteLength*2),v.set(p),v.set(m,p.byteLength),v},n.fftMix=async function(e){let a=n.F.n8*3,o,s;if(t==`G1`)o=`g1m_fftMix`,s=`g1m_fftJoin`;else if(t==`G2`)o=`g2m_fftMix`,s=`g2m_fftJoin`;else if(t==`Fr`)o=`frm_fftMix`,s=`frm_fftJoin`;else throw Error(`Invalid group`);let c=Math.floor(e.byteLength/a),l=pr(c),u=1<=0;e--)p.set(f[e][0],m),m+=f[e][0].byteLength;return p}}async function zr(e){let t=await Mr(e.wasm,e.singleThread),n={};return n.q=Vt(e.wasm.q.toString()),n.r=Vt(e.wasm.r.toString()),n.name=e.name,n.tm=t,n.prePSize=e.wasm.prePSize,n.preQSize=e.wasm.preQSize,n.Fr=new yr(t,`frm`,e.n8r,e.r),n.F1=new yr(t,`f1m`,e.n8q,e.q),n.F2=new br(t,`f2m`,n.F1),n.G1=new Sr(t,`g1m`,n.F1,e.wasm.pG1gen,e.wasm.pG1b,e.cofactorG1),n.G2=new Sr(t,`g2m`,n.F2,e.wasm.pG2gen,e.wasm.pG2b,e.cofactorG2),n.F6=new xr(t,`f6m`,n.F2),n.F12=new br(t,`ftm`,n.F6),n.Gt=n.F12,Pr(n,`G1`),Pr(n,`G2`),Pr(n,`Fr`),Lr(n,`G1`),Lr(n,`G2`),Rr(n,`G1`),Rr(n,`G2`),Rr(n,`Fr`),Fr(n),n.array2buffer=function(e,t){let n=new Uint8Array(t*e.length);for(let r=0;r(ye(),ve)),{buildBn128:r}=await Promise.resolve().then(()=>(Et(),Tt)),i=new e;i.setMemory(25),r(i),t&&t(i),n.code=i.build(),n.pq=i.modules.f1m.pq,n.pr=i.modules.frm.pq,n.pG1gen=i.modules.bn128.pG1gen,n.pG1zero=i.modules.bn128.pG1zero,n.pG1b=i.modules.bn128.pG1b,n.pG2gen=i.modules.bn128.pG2gen,n.pG2zero=i.modules.bn128.pG2zero,n.pG2b=i.modules.bn128.pG2b,n.pOneT=i.modules.bn128.pOneT,n.prePSize=i.modules.bn128.prePSize,n.preQSize=i.modules.bn128.preQSize,n.n8q=32,n.n8r=32,n.q=i.modules.bn128.q,n.r=i.modules.bn128.r}else{console.log(`Using prebuilt bn128 wasm`);let e=await Promise.resolve().then(()=>(T(),f));n.pq=e.pq,n.pr=e.pr,n.pG1gen=e.pG1gen,n.pG1zero=e.pG1zero,n.pG1b=e.pG1b,n.pG2gen=e.pG2gen,n.pG2zero=e.pG2zero,n.pG2b=e.pG2b,n.pOneT=e.pOneT,n.prePSize=e.prePSize,n.preQSize=e.preQSize,n.n8q=32,n.n8r=32,n.q=e.q,n.r=e.r;let t=Uint8Array.from(atob(e.gzipCode),e=>e.charCodeAt(0)),r=new Blob([t]),i=new DecompressionStream(`gzip`),a=r.stream().pipeThrough(i);n.code=await new Response(a).bytes()}let r={name:`bn128`,wasm:n,q:Vt(`21888242871839275222246405745257275088696311157297823662689037894645226208583`),r:Vt(`21888242871839275222246405745257275088548364400416034343698204186575808495617`),n8q:32,n8r:32,cofactorG2:Vt(`30644e72e131a029b85045b68181585e06ceecda572a2489345f2299c0f9fa8d`,16),singleThread:!!e},i=await zr(r);return i.terminate=async function(){r.singleThread||(globalThis.curve_bn128=null,await this.tm.terminate())},e||(globalThis.curve_bn128=i),i}globalThis.curve_bls12381=null;async function Vr(e,t){if(!e&&globalThis.curve_bls12381)return globalThis.curve_bls12381;let{ModuleBuilder:n}=await Promise.resolve().then(()=>(ye(),ve)),{buildBls12381:r}=await Promise.resolve().then(()=>(Et(),Tt)),i=new n;i.setMemory(25),r(i),t&&t(i);let a={};a.code=i.build(),a.pq=i.modules.f1m.pq,a.pr=i.modules.frm.pq,a.pG1gen=i.modules.bls12381.pG1gen,a.pG1zero=i.modules.bls12381.pG1zero,a.pG1b=i.modules.bls12381.pG1b,a.pG2gen=i.modules.bls12381.pG2gen,a.pG2zero=i.modules.bls12381.pG2zero,a.pG2b=i.modules.bls12381.pG2b,a.pOneT=i.modules.bls12381.pOneT,a.prePSize=i.modules.bls12381.prePSize,a.preQSize=i.modules.bls12381.preQSize,a.n8q=48,a.n8r=32,a.q=i.modules.bls12381.q,a.r=i.modules.bls12381.r;let o={name:`bls12381`,wasm:a,q:Vt(`1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab`,16),r:Vt(`73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001`,16),n8q:48,n8r:32,cofactorG1:Vt(`0x396c8c005555e1568c00aaab0000aaab`,16),cofactorG2:Vt(`0x5d543a95414e7f1091d50792876a202cd91de4547085abaa68a205b2e5a7ddfa628f1cb4d9e82ef21537e293a6691ae1616ec6e786f0c70cf1c38e31c7238e5`,16),singleThread:!!e},s=await zr(o);return s.terminate=async function(){o.singleThread||(globalThis.curve_bls12381=null,await this.tm.terminate())},e||(globalThis.curve_bls12381=s),s}var Hr=Vt(`73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001`,16),Ur=Vt(`21888242871839275222246405745257275088548364400416034343698204186575808495617`);Vt(`1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab`,16),Vt(`21888242871839275222246405745257275088696311157297823662689037894645226208583`);async function Wr(e,t,n){let r;if(fn(e,Ur))r=await Br(t,n);else if(fn(e,Hr))r=await Vr(t,n);else throw Error(`Curve not supported: ${On(e)}`);return r}var V=Rt,Gr=tr;function Kr(e){let t=e.initialSize||1<<20,n=new Qr;return n.o=e,n.o.data=new Uint8Array(t),n.allocSize=t,n.totalSize=0,n.readOnly=!1,n.pos=0,n}function qr(e){let t=new Qr;return t.o=e,t.allocSize=e.data.byteLength,t.totalSize=e.data.byteLength,t.readOnly=!0,t.pos=0,t}var Jr=new Uint8Array(4),Yr=new DataView(Jr.buffer),Xr=new Uint8Array(8),Zr=new DataView(Xr.buffer),Qr=class{constructor(){this.pageSize=16384}_resizeIfNeeded(e){if(e>this.allocSize){let t=Math.max(this.allocSize+(1<<20),Math.floor(this.allocSize*1.1),e),n=new Uint8Array(t);n.set(this.o.data),this.o.data=n,this.allocSize=t}}async write(e,t){if(t===void 0&&(t=this.pos),this.readOnly)throw Error(`Writing a read only file`);this._resizeIfNeeded(t+e.byteLength),this.o.data.set(e.slice(),t),t+e.byteLength>this.totalSize&&(this.totalSize=t+e.byteLength),this.pos=t+e.byteLength}async readToBuffer(e,t,n,r){if(r===void 0&&(r=this.pos),this.readOnly&&r+n>this.totalSize)throw Error(`Reading out of bounds`);this._resizeIfNeeded(r+n);let i=new Uint8Array(this.o.data.buffer,this.o.data.byteOffset+r,n);e.set(i,t),this.pos=r+n}async read(e,t){let n=this,r=new Uint8Array(e);return await n.readToBuffer(r,0,e,t),r}close(){this.o.data.byteLength!=this.totalSize&&(this.o.data=this.o.data.slice(0,this.totalSize))}async discard(){}async writeULE32(e,t){let n=this;Yr.setUint32(0,e,!0),await n.write(Jr,t)}async writeUBE32(e,t){let n=this;Yr.setUint32(0,e,!1),await n.write(Jr,t)}async writeULE64(e,t){let n=this;Zr.setUint32(0,e&4294967295,!0),Zr.setUint32(4,Math.floor(e/4294967296),!0),await n.write(Xr,t)}async readULE32(e){let t=await this.read(4,e);return new Uint32Array(t.buffer)[0]}async readUBE32(e){let t=await this.read(4,e);return new DataView(t.buffer).getUint32(0,!1)}async readULE64(e){let t=await this.read(8,e),n=new Uint32Array(t.buffer);return n[1]*4294967296+n[0]}async readString(e){let t=this,n=e===void 0?t.pos:e;if(n>this.totalSize){if(this.readOnly)throw Error(`Reading out of bounds`);this._resizeIfNeeded(e)}let r=new Uint8Array(t.o.data.buffer,n,this.totalSize-n),i=r.findIndex(e=>e===0),a=i!==-1,o=``;return a?(o=new TextDecoder().decode(r.slice(0,i)),t.pos=n+i+1):t.pos=n,o}},$r=1<<22;function ei(e){let t=e.initialSize||0,n=new oi;n.o=e;let r=t?Math.floor((t-1)/$r)+1:0;n.o.data=[];for(let e=0;e0;){let t=i+a>$r?$r-i:a,o=e.slice(e.byteLength-a,e.byteLength-a+t);new Uint8Array(n.o.data[r].buffer,i,t).set(o),a-=t,r++,i=0}this.pos=t+e.byteLength}async readToBuffer(e,t,n,r){let i=this;if(r===void 0&&(r=i.pos),this.readOnly&&r+n>this.totalSize)throw Error(`Reading out of bounds`);this._resizeIfNeeded(r+n);let a=Math.floor(r/$r),o=r%$r,s=n;for(;s>0;){let r=o+s>$r?$r-o:s,c=new Uint8Array(i.o.data[a].buffer,o,r);e.set(c,t+n-s),s-=r,a++,o=0}this.pos=r+n}async read(e,t){let n=this,r=new Uint8Array(e);return await n.readToBuffer(r,0,e,t),r}close(){}async discard(){}async writeULE32(e,t){let n=this;ri.setUint32(0,e,!0),await n.write(ni,t)}async writeUBE32(e,t){let n=this;ri.setUint32(0,e,!1),await n.write(ni,t)}async writeULE64(e,t){let n=this;ai.setUint32(0,e&4294967295,!0),ai.setUint32(4,Math.floor(e/4294967296),!0),await n.write(ii,t)}async readULE32(e){let t=await this.read(4,e);return new Uint32Array(t.buffer)[0]}async readUBE32(e){let t=await this.read(4,e);return new DataView(t.buffer).getUint32(0,!1)}async readULE64(e){let t=await this.read(8,e),n=new Uint32Array(t.buffer);return n[1]*4294967296+n[0]}async readString(e){let t=this,n=e===void 0?t.pos:e;if(n>this.totalSize){if(this.readOnly)throw Error(`Reading out of bounds`);this._resizeIfNeeded(e)}let r=!1,i=``;for(;!r;){let e=Math.floor(n/$r),a=n%$r;if(t.o.data[e]===void 0)throw Error(`ERROR`);let o=Math.min(2048,t.o.data[e].length-a),s=new Uint8Array(t.o.data[e].buffer,a,o),c=s.findIndex(e=>e===0);r=c!==-1,r?(i+=new TextDecoder().decode(s.slice(0,c)),t.pos=e*$r+a+c+1):(i+=new TextDecoder().decode(s),t.pos=e*$r+a+s.length),n=t.pos}return i}},si=65536;function ci(){throw Error(`File I/O is not supported in the browser`)}function li(e,t){return e instanceof Uint8Array?{type:`mem`,data:e}:typeof e==`string`?{type:`mem`,initialSize:t||si}:e}async function ui(e){let t=await fetch(e).then(e=>e.arrayBuffer());return{type:`mem`,data:new Uint8Array(t)}}function di(e,t,n){if(e.type===`file`&&ci(),e.type===`mem`)return t(e);if(e.type===`bigMem`)return n(e);throw Error(`Invalid FastFile type: `+e.type)}function fi(e,t){return di(li(e,t),Kr,ei)}async function pi(e){return e=typeof e==`string`?await ui(e):li(e),di(e,qr,ti)}var mi=typeof Buffer<`u`&&Buffer.constants&&Buffer.constants.MAX_LENGTH?Buffer.constants.MAX_LENGTH:1<<30;async function H(e,t,n,r,i){let a=await pi(e,r,i),o=await a.read(4),s=``;for(let e=0;e<4;e++)s+=String.fromCharCode(o[e]);if(s!=t)throw Error(e+`: Invalid File format`);if(await a.readULE32()>n)throw Error(`Version not supported`);let c=await a.readULE32(),l=[];for(let e=0;e1)throw Error(e.fileName+`: Section Duplicated `+n);e.pos=t[n][0].p,e.readingSection=t[n][0]}async function K(e,t){if(e.readingSection===void 0)throw Error(`Not reading a section`);if(!t&&e.pos-e.readingSection.p!=e.readingSection.size)throw Error(`Invalid section size reading`);delete e.readingSection}async function gi(e,t,n,r){let i=new Uint8Array(n);V.toRprLE(i,0,t,n),await e.write(i,r)}async function _i(e,t,n){let r=await e.read(t,n);return V.fromRprLE(r,0,t)}async function q(e,t,n,r,i){i===void 0&&(i=t[r][0].size);let a=e.pageSize;await G(e,t,r),await U(n,r);for(let t=0;tt[n][0].size)throw Error(`Reading out of the range of the section`);let a;return a=iEi,getCurveFromQ:()=>Ti,getCurveFromR:()=>wi}),bi=V.e(`73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001`,16),xi=V.e(`21888242871839275222246405745257275088548364400416034343698204186575808495617`),Si=V.e(`1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab`,16),Ci=V.e(`21888242871839275222246405745257275088696311157297823662689037894645226208583`);async function wi(e,t){let n,r=t&&t.singleThread;if(V.eq(e,xi))n=await Br(r);else if(V.eq(e,bi))n=await Vr(r);else throw Error(`Curve not supported: ${V.toString(e)}`);return n}async function Ti(e,t){let n,r=t&&t.singleThread;if(V.eq(e,Ci))n=await Br(r);else if(V.eq(e,Si))n=await Vr(r);else throw Error(`Curve not supported: ${V.toString(e)}`);return n}async function Ei(e,t){let n,r=t&&t.singleThread,i=a(e);if([`BN128`,`BN254`,`ALTBN128`].indexOf(i)>=0)n=await Br(r);else if([`BLS12381`].indexOf(i)>=0)n=await Vr(r);else throw Error(`Curve not supported: ${e}`);return n;function a(e){return e.toUpperCase().match(/[A-Za-z0-9]+/g).join(``)}}function Di(e){return e instanceof Uint8Array||ArrayBuffer.isView(e)&&e.constructor.name===`Uint8Array`}function Oi(e,t=``){if(!Number.isSafeInteger(e)||e<0){let n=t&&`"${t}" `;throw Error(`${n}expected integer >= 0, got ${e}`)}}function ki(e,t,n=``){let r=Di(e),i=e?.length,a=t!==void 0;if(!r||a&&i!==t){let o=n&&`"${n}" `,s=a?` of length ${t}`:``,c=r?`length=${i}`:`type=${typeof e}`;throw Error(o+`expected Uint8Array`+s+`, got `+c)}return e}function Ai(e,t=!0){if(e.destroyed)throw Error(`Hash instance has been destroyed`);if(t&&e.finished)throw Error(`Hash#digest() has already been called`)}function ji(e,t){ki(e,void 0,`digestInto() output`);let n=t.outputLen;if(e.length=`+n)}function Mi(e){return new Uint32Array(e.buffer,e.byteOffset,Math.floor(e.byteLength/4))}function Ni(...e){for(let t=0;t>>8&65280|e>>>24&255}var Ii=Pi?e=>e:e=>Fi(e);function Li(e){for(let t=0;te:Li;typeof Uint8Array.from([]).toHex==`function`&&Uint8Array.fromHex;function zi(e,t={}){let n=(t,n)=>e(n).update(t).digest(),r=e(void 0);return n.outputLen=r.outputLen,n.blockLen=r.blockLen,n.create=t=>e(t),Object.assign(n,t),Object.freeze(n)}var Bi=Uint8Array.from([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3,11,8,12,0,5,2,15,13,10,14,3,6,7,1,9,4,7,9,3,1,13,12,11,14,2,6,5,10,4,0,15,8,9,0,5,7,2,4,10,15,14,1,11,12,6,8,3,13,2,12,6,10,0,11,8,3,4,13,7,5,15,14,1,9,12,5,1,15,14,13,4,10,0,7,6,3,9,2,8,11,13,11,7,14,12,1,3,9,5,0,15,4,8,6,2,10,6,15,14,9,11,3,0,8,12,2,13,7,1,4,10,5,10,2,8,4,7,6,1,5,15,11,9,14,3,12,13,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3,11,8,12,0,5,2,15,13,10,14,3,6,7,1,9,4,7,9,3,1,13,12,11,14,2,6,5,10,4,0,15,8,9,0,5,7,2,4,10,15,14,1,11,12,6,8,3,13,2,12,6,10,0,11,8,3,4,13,7,5,15,14,1,9]),Vi=BigInt(2**32-1),Hi=BigInt(32);function Ui(e,t=!1){return t?{h:Number(e&Vi),l:Number(e>>Hi&Vi)}:{h:Number(e>>Hi&Vi)|0,l:Number(e&Vi)|0}}function Wi(e,t=!1){let n=e.length,r=new Uint32Array(n),i=new Uint32Array(n);for(let a=0;ae>>>n|t<<32-n,Ki=(e,t,n)=>e<<32-n|t>>>n,qi=(e,t,n)=>e<<64-n|t>>>n-32,Ji=(e,t,n)=>e>>>n-32|t<<64-n,Yi=(e,t)=>t,Xi=(e,t)=>e,Zi=(e,t,n)=>e<>>32-n,Qi=(e,t,n)=>t<>>32-n,$i=(e,t,n)=>t<>>64-n,ea=(e,t,n)=>e<>>64-n;function ta(e,t,n,r){let i=(t>>>0)+(r>>>0);return{h:e+n+(i/2**32|0)|0,l:i|0}}var na=(e,t,n)=>(e>>>0)+(t>>>0)+(n>>>0),ra=(e,t,n,r)=>t+n+r+(e/2**32|0)|0,ia=Uint32Array.from([4089235720,1779033703,2227873595,3144134277,4271175723,1013904242,1595750129,2773480762,2917565137,1359893119,725511199,2600822924,4215389547,528734635,327033209,1541459225]),Y=new Uint32Array(32);function aa(e,t,n,r,i,a){let o=i[a],s=i[a+1],c=Y[2*e],l=Y[2*e+1],u=Y[2*t],d=Y[2*t+1],f=Y[2*n],p=Y[2*n+1],m=Y[2*r],h=Y[2*r+1],g=na(c,u,o);l=ra(g,l,d,s),c=g|0,{Dh:h,Dl:m}={Dh:h^l,Dl:m^c},{Dh:h,Dl:m}={Dh:Yi(h,m),Dl:Xi(h,m)},{h:p,l:f}=ta(p,f,h,m),{Bh:d,Bl:u}={Bh:d^p,Bl:u^f},{Bh:d,Bl:u}={Bh:Gi(d,u,24),Bl:Ki(d,u,24)},Y[2*e]=c,Y[2*e+1]=l,Y[2*t]=u,Y[2*t+1]=d,Y[2*n]=f,Y[2*n+1]=p,Y[2*r]=m,Y[2*r+1]=h}function oa(e,t,n,r,i,a){let o=i[a],s=i[a+1],c=Y[2*e],l=Y[2*e+1],u=Y[2*t],d=Y[2*t+1],f=Y[2*n],p=Y[2*n+1],m=Y[2*r],h=Y[2*r+1],g=na(c,u,o);l=ra(g,l,d,s),c=g|0,{Dh:h,Dl:m}={Dh:h^l,Dl:m^c},{Dh:h,Dl:m}={Dh:Gi(h,m,16),Dl:Ki(h,m,16)},{h:p,l:f}=ta(p,f,h,m),{Bh:d,Bl:u}={Bh:d^p,Bl:u^f},{Bh:d,Bl:u}={Bh:qi(d,u,63),Bl:Ji(d,u,63)},Y[2*e]=c,Y[2*e+1]=l,Y[2*t]=u,Y[2*t+1]=d,Y[2*n]=f,Y[2*n+1]=p,Y[2*r]=m,Y[2*r+1]=h}function sa(e,t={},n,r,i){if(Oi(n),e<0||e>n)throw Error(`outputLen bigger than keyLen`);let{key:a,salt:o,personalization:s}=t;if(a!==void 0&&(a.length<1||a.length>n))throw Error(`"key" expected to be undefined or of length=1..`+n);o!==void 0&&ki(o,r,`salt`),s!==void 0&&ki(s,i,`personalization`)}var ca=class{buffer;buffer32;finished=!1;destroyed=!1;length=0;pos=0;blockLen;outputLen;constructor(e,t){Oi(e),Oi(t),this.blockLen=e,this.outputLen=t,this.buffer=new Uint8Array(e),this.buffer32=Mi(this.buffer)}update(e){Ai(this),ki(e);let{blockLen:t,buffer:n,buffer32:r}=this,i=e.length,a=e.byteOffset,o=e.buffer;for(let s=0;sr[t]=Ii(e))}digest(){let{buffer:e,outputLen:t}=this;this.digestInto(e);let n=e.slice(0,t);return this.destroy(),n}_cloneInto(e){let{buffer:t,length:n,finished:r,destroyed:i,outputLen:a,pos:o}=this;return e||=new this.constructor({dkLen:a}),e.set(...this.get()),e.buffer.set(t),e.destroyed=i,e.finished=r,e.length=n,e.pos=o,e.outputLen=a,e}clone(){return this._cloneInto()}},la=class extends ca{v0l=ia[0]|0;v0h=ia[1]|0;v1l=ia[2]|0;v1h=ia[3]|0;v2l=ia[4]|0;v2h=ia[5]|0;v3l=ia[6]|0;v3h=ia[7]|0;v4l=ia[8]|0;v4h=ia[9]|0;v5l=ia[10]|0;v5h=ia[11]|0;v6l=ia[12]|0;v6h=ia[13]|0;v7l=ia[14]|0;v7h=ia[15]|0;constructor(e={}){let t=e.dkLen===void 0?64:e.dkLen;super(128,t),sa(t,e,64,16,16);let{key:n,personalization:r,salt:i}=e,a=0;if(n!==void 0&&(ki(n,void 0,`key`),a=n.length),this.v0l^=this.outputLen|a<<8|16842752,i!==void 0){ki(i,void 0,`salt`);let e=Mi(i);this.v4l^=Ii(e[0]),this.v4h^=Ii(e[1]),this.v5l^=Ii(e[2]),this.v5h^=Ii(e[3])}if(r!==void 0){ki(r,void 0,`personalization`);let e=Mi(r);this.v6l^=Ii(e[0]),this.v6h^=Ii(e[1]),this.v7l^=Ii(e[2]),this.v7h^=Ii(e[3])}if(n!==void 0){let e=new Uint8Array(this.blockLen);e.set(n),this.update(e)}}get(){let{v0l:e,v0h:t,v1l:n,v1h:r,v2l:i,v2h:a,v3l:o,v3h:s,v4l:c,v4h:l,v5l:u,v5h:d,v6l:f,v6h:p,v7l:m,v7h:h}=this;return[e,t,n,r,i,a,o,s,c,l,u,d,f,p,m,h]}set(e,t,n,r,i,a,o,s,c,l,u,d,f,p,m,h){this.v0l=e|0,this.v0h=t|0,this.v1l=n|0,this.v1h=r|0,this.v2l=i|0,this.v2h=a|0,this.v3l=o|0,this.v3h=s|0,this.v4l=c|0,this.v4h=l|0,this.v5l=u|0,this.v5h=d|0,this.v6l=f|0,this.v6h=p|0,this.v7l=m|0,this.v7h=h|0}compress(e,t,n){this.get().forEach((e,t)=>Y[t]=e),Y.set(ia,16);let{h:r,l:i}=Ui(BigInt(this.length));Y[24]=ia[8]^i,Y[25]=ia[9]^r,n&&(Y[28]=~Y[28],Y[29]=~Y[29]);let a=0,o=Bi;for(let n=0;n<12;n++)aa(0,4,8,12,e,t+2*o[a++]),oa(0,4,8,12,e,t+2*o[a++]),aa(1,5,9,13,e,t+2*o[a++]),oa(1,5,9,13,e,t+2*o[a++]),aa(2,6,10,14,e,t+2*o[a++]),oa(2,6,10,14,e,t+2*o[a++]),aa(3,7,11,15,e,t+2*o[a++]),oa(3,7,11,15,e,t+2*o[a++]),aa(0,5,10,15,e,t+2*o[a++]),oa(0,5,10,15,e,t+2*o[a++]),aa(1,6,11,12,e,t+2*o[a++]),oa(1,6,11,12,e,t+2*o[a++]),aa(2,7,8,13,e,t+2*o[a++]),oa(2,7,8,13,e,t+2*o[a++]),aa(3,4,9,14,e,t+2*o[a++]),oa(3,4,9,14,e,t+2*o[a++]);this.v0l^=Y[0]^Y[16],this.v0h^=Y[1]^Y[17],this.v1l^=Y[2]^Y[18],this.v1h^=Y[3]^Y[19],this.v2l^=Y[4]^Y[20],this.v2h^=Y[5]^Y[21],this.v3l^=Y[6]^Y[22],this.v3h^=Y[7]^Y[23],this.v4l^=Y[8]^Y[24],this.v4h^=Y[9]^Y[25],this.v5l^=Y[10]^Y[26],this.v5h^=Y[11]^Y[27],this.v6l^=Y[12]^Y[28],this.v6h^=Y[13]^Y[29],this.v7l^=Y[14]^Y[30],this.v7h^=Y[15]^Y[31],Ni(Y)}destroy(){this.destroyed=!0,Ni(this.buffer32),this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)}},ua=zi(e=>new la(e)),da=c(((e,t)=>{t.exports={}}));da();var fa=[];for(let e=0;e<256;e++)fa[e]=pa(e,8);function pa(e,t){let n=0,r=e;for(let e=0;e>=1;return n}function ma(e){return(e&4294901760?(e&=4294901760,16):0)|(e&4278255360?(e&=4278255360,8):0)|(e&4042322160?(e&=4042322160,4):0)|(e&3435973836?(e&=3435973836,2):0)|(e&2863311530)!=0}function ha(e,t){let n=new DataView(e.buffer,e.byteOffset,e.byteLength),r=``;for(let e=0;e<4;e++){e>0&&(r+=` +`),r+=` `;for(let t=0;t<4;t++)t>0&&(r+=` `),r+=n.getUint32(e*16+t*4).toString(16).padStart(8,`0`)}return t&&(r=t+` +`+r),r}function ga(e,t){if(e.byteLength!=t.byteLength)return!1;for(var n=new Int8Array(e),r=new Int8Array(t),i=0;i!=e.byteLength;i++)if(n[i]!=r[i])return!1;return!0}function _a(e){return e.clone()}function va(e){let t=e.subarray(0,128),n=Mi(e.subarray(128)),r=ua.create({dkLen:64});r.buffer.set(t),r.v0l=n[0]|0,r.v0h=n[1]|0,r.v1l=n[2]|0,r.v1h=n[3]|0,r.v2l=n[4]|0,r.v2h=n[5]|0,r.v3l=n[6]|0,r.v3h=n[7]|0,r.v4l=n[8]|0,r.v4h=n[9]|0,r.v5l=n[10]|0,r.v5h=n[11]|0,r.v6l=n[12]|0,r.v6h=n[13]|0,r.v7l=n[14]|0,r.v7h=n[15]|0;let i=2**32,a=n[16]+n[17]*i,o=n[18]+n[19]*i;return r.length=a+o,r.pos=o,r}function ya(e){let t=new Uint8Array(216),n=Mi(t.subarray(128));return t.set(e.buffer),n[0]=e.v0l,n[1]=e.v0h,n[2]=e.v1l,n[3]=e.v1h,n[4]=e.v2l,n[5]=e.v2h,n[6]=e.v3l,n[7]=e.v3h,n[8]=e.v4l,n[9]=e.v4h,n[10]=e.v5l,n[11]=e.v5h,n[12]=e.v6l,n[13]=e.v6h,n[14]=e.v7l,n[15]=e.v7h,n[18]=e.pos,n[16]=e.length-e.pos,t}async function ba(e,t,n,r,i){return e.G1.isZero(t)||e.G1.isZero(n)||e.G2.isZero(r)||e.G2.isZero(i)?!1:await e.pairingEq(t,i,e.G1.neg(n),r)}function xa(){return window.prompt(`Enter a random text. (Entropy): `,``)}function Sa(e){let t=new Uint8Array(e);return globalThis.crypto.getRandomValues(t),t}async function Ca(e){{let t=await globalThis.crypto.subtle.digest(`SHA-256`,e.buffer);return new Uint8Array(t)}}function wa(e,t){return new DataView(e.buffer).getUint32(t,!1)}async function Ta(e){for(;!e;)e=await xa();let t=ua.create(64);t.update(Sa(64));let n=new TextEncoder;t.update(n.encode(e));let r=t.digest(),i=[];for(let e=0;e<8;e++)i[e]=wa(r,e*4);return new Gn(i)}async function Ea(e,t){let n,r;t<32?(n=1<>>0,r=1):(n=4294967296,r=1<>>0);let i=e;for(let e=0;e{n[r]=ka(e,t[r])}),n}else if(typeof t==`bigint`||t.eq!==void 0)return t.toString(10);else return t}async function Aa(e,t){await U(e,1),await e.writeULE32(1),await W(e);let n=await Ti(t.q);await U(e,2);let r=n.q,i=(Math.floor((V.bitLength(r)-1)/64)+1)*8,a=n.r,o=(Math.floor((V.bitLength(a)-1)/64)+1)*8;await e.writeULE32(i),await gi(e,r,i),await e.writeULE32(o),await gi(e,a,o),await e.writeULE32(t.nVars),await e.writeULE32(t.nPublic),await e.writeULE32(t.domainSize),await ja(e,n,t.vk_alpha_1),await ja(e,n,t.vk_beta_1),await Ma(e,n,t.vk_beta_2),await Ma(e,n,t.vk_gamma_2),await ja(e,n,t.vk_delta_1),await Ma(e,n,t.vk_delta_2),await W(e)}async function ja(e,t,n){let r=new Uint8Array(t.G1.F.n8*2);t.G1.toRprLEM(r,0,n),await e.write(r)}async function Ma(e,t,n){let r=new Uint8Array(t.G2.F.n8*2);t.G2.toRprLEM(r,0,n),await e.write(r)}async function Na(e,t,n){let r=await e.read(t.G1.F.n8*2),i=t.G1.fromRprLEM(r,0);return n?t.G1.toObject(i):i}async function Pa(e,t,n){let r=await e.read(t.G2.F.n8*2),i=t.G2.fromRprLEM(r,0);return n?t.G2.toObject(i):i}async function Fa(e,t,n,r){await G(e,t,1);let i=await e.readULE32();if(await K(e),i===1)return await Ia(e,t,n,r);if(i===2)return await La(e,t,n,r);if(i===10)return await Ra(e,t,n,r);throw Error(`Protocol not supported: `)}async function Ia(e,t,n,r){let i={};i.protocol=`groth16`,await G(e,t,2);let a=await e.readULE32();i.n8q=a,i.q=await _i(e,a);let o=await e.readULE32();return i.n8r=o,i.r=await _i(e,o),i.curve=await Ti(i.q,r),i.nVars=await e.readULE32(),i.nPublic=await e.readULE32(),i.domainSize=await e.readULE32(),i.power=ma(i.domainSize),i.vk_alpha_1=await Na(e,i.curve,n),i.vk_beta_1=await Na(e,i.curve,n),i.vk_beta_2=await Pa(e,i.curve,n),i.vk_gamma_2=await Pa(e,i.curve,n),i.vk_delta_1=await Na(e,i.curve,n),i.vk_delta_2=await Pa(e,i.curve,n),await K(e),i}async function La(e,t,n,r){let i={};i.protocol=`plonk`,await G(e,t,2);let a=await e.readULE32();i.n8q=a,i.q=await _i(e,a);let o=await e.readULE32();return i.n8r=o,i.r=await _i(e,o),i.curve=await Ti(i.q,r),i.nVars=await e.readULE32(),i.nPublic=await e.readULE32(),i.domainSize=await e.readULE32(),i.power=ma(i.domainSize),i.nAdditions=await e.readULE32(),i.nConstraints=await e.readULE32(),i.k1=await e.read(o),i.k2=await e.read(o),i.Qm=await Na(e,i.curve,n),i.Ql=await Na(e,i.curve,n),i.Qr=await Na(e,i.curve,n),i.Qo=await Na(e,i.curve,n),i.Qc=await Na(e,i.curve,n),i.S1=await Na(e,i.curve,n),i.S2=await Na(e,i.curve,n),i.S3=await Na(e,i.curve,n),i.X_2=await Pa(e,i.curve,n),await K(e),i}async function Ra(e,t,n,r){let i={};i.protocol=`fflonk`,i.protocolId=10,await G(e,t,2);let a=await e.readULE32();i.n8q=a,i.q=await _i(e,a),i.curve=await Ti(i.q,r);let o=await e.readULE32();return i.n8r=o,i.r=await _i(e,o),i.nVars=await e.readULE32(),i.nPublic=await e.readULE32(),i.domainSize=await e.readULE32(),i.power=ma(i.domainSize),i.nAdditions=await e.readULE32(),i.nConstraints=await e.readULE32(),i.k1=await e.read(o),i.k2=await e.read(o),i.w3=await e.read(o),i.w4=await e.read(o),i.w8=await e.read(o),i.wr=await e.read(o),i.X_2=await Pa(e,i.curve,n),i.C0=await Na(e,i.curve,n),await K(e),i}async function za(e,t){let{fd:n,sections:r}=await H(e,`zkey`,1),i=await Fa(n,r,t),a=new er(i.r),o=V.mod(V.shl(1,i.n8r*8),i.r),s=a.inv(o),c=a.mul(s,s),l=await Ti(i.q);await G(n,r,3),i.IC=[];for(let e=0;e<=i.nPublic;e++){let e=await Na(n,l,t);i.IC.push(e)}await K(n),await G(n,r,4);let u=await n.readULE32();i.ccoefs=[];for(let e=0;e0){let t=new Uint8Array(r);await e.writeULE32(t.byteLength),await e.write(t)}else await e.writeULE32(0)}async function Ua(e,t,n){await U(e,10),await e.write(n.csHash),await e.writeULE32(n.contributions.length);for(let r=0;r2**16;)a*=2,c=Math.floor(t.domainSize/a);console.log(`@@@ new elementsPerChunk`,c);let l=[],u=[];for(let e=0;e1){let t=[];for(let n=0;ne?n=r-1:i1){let t=[];for(let n=0;n<1;n++){let r=[];r.push({cmd:`ALLOC`,var:0,len:d[n][0].byteLength}),r.push({cmd:`ALLOC`,var:1,len:d[n][0].byteLength});for(let t=0;t<3;t++){r.push({cmd:`SET`,var:0,buff:d[n][t]});for(let i=1;ie?n=r-1:i{ro(e)},t)}function ao(e){let t=e.initialSize||1<<20,n=new fo;return n.o=e,n.o.data=new Uint8Array(t),n.allocSize=t,n.totalSize=0,n.readOnly=!1,n.pos=0,n}function oo(e){let t=new fo;return t.o=e,t.allocSize=e.data.byteLength,t.totalSize=e.data.byteLength,t.readOnly=!0,t.pos=0,t}var so=new Uint8Array(4),co=new DataView(so.buffer),lo=new Uint8Array(8),uo=new DataView(lo.buffer),fo=class{constructor(){this.pageSize=16384}_resizeIfNeeded(e){if(e>this.allocSize){let t=Math.max(this.allocSize+(1<<20),Math.floor(this.allocSize*1.1),e),n=new Uint8Array(t);n.set(this.o.data),this.o.data=n,this.allocSize=t}}async write(e,t){if(t===void 0&&(t=this.pos),this.readOnly)throw Error(`Writing a read only file`);this._resizeIfNeeded(t+e.byteLength),this.o.data.set(e.slice(),t),t+e.byteLength>this.totalSize&&(this.totalSize=t+e.byteLength),this.pos=t+e.byteLength}async readToBuffer(e,t,n,r){if(r===void 0&&(r=this.pos),this.readOnly&&r+n>this.totalSize)throw Error(`Reading out of bounds`);this._resizeIfNeeded(r+n);let i=new Uint8Array(this.o.data.buffer,this.o.data.byteOffset+r,n);e.set(i,t),this.pos=r+n}async read(e,t){let n=this,r=new Uint8Array(e);return await n.readToBuffer(r,0,e,t),r}close(){this.o.data.byteLength!=this.totalSize&&(this.o.data=this.o.data.slice(0,this.totalSize))}async discard(){}async writeULE32(e,t){let n=this;co.setUint32(0,e,!0),await n.write(so,t)}async writeUBE32(e,t){let n=this;co.setUint32(0,e,!1),await n.write(so,t)}async writeULE64(e,t){let n=this;uo.setUint32(0,e&4294967295,!0),uo.setUint32(4,Math.floor(e/4294967296),!0),await n.write(lo,t)}async readULE32(e){let t=await this.read(4,e);return new Uint32Array(t.buffer)[0]}async readUBE32(e){let t=await this.read(4,e);return new DataView(t.buffer).getUint32(0,!1)}async readULE64(e){let t=await this.read(8,e),n=new Uint32Array(t.buffer);return n[1]*4294967296+n[0]}async readString(e){let t=this,n=e===void 0?t.pos:e;if(n>this.totalSize){if(this.readOnly)throw Error(`Reading out of bounds`);this._resizeIfNeeded(e)}let r=new Uint8Array(t.o.data.buffer,n,this.totalSize-n),i=r.findIndex(e=>e===0),a=i!==-1,o=``;return a?(o=new TextDecoder().decode(r.slice(0,i)),t.pos=n+i+1):t.pos=n,o}},po=1<<22;function mo(e){let t=e.initialSize||0,n=new bo;n.o=e;let r=t?Math.floor((t-1)/po)+1:0;n.o.data=[];for(let e=0;e0;){let t=i+a>po?po-i:a,o=e.slice(e.byteLength-a,e.byteLength-a+t);new Uint8Array(n.o.data[r].buffer,i,t).set(o),a-=t,r++,i=0}this.pos=t+e.byteLength}async readToBuffer(e,t,n,r){let i=this;if(r===void 0&&(r=i.pos),this.readOnly&&r+n>this.totalSize)throw Error(`Reading out of bounds`);this._resizeIfNeeded(r+n);let a=Math.floor(r/po),o=r%po,s=n;for(;s>0;){let r=o+s>po?po-o:s,c=new Uint8Array(i.o.data[a].buffer,o,r);e.set(c,t+n-s),s-=r,a++,o=0}this.pos=r+n}async read(e,t){let n=this,r=new Uint8Array(e);return await n.readToBuffer(r,0,e,t),r}close(){}async discard(){}async writeULE32(e,t){let n=this;_o.setUint32(0,e,!0),await n.write(go,t)}async writeUBE32(e,t){let n=this;_o.setUint32(0,e,!1),await n.write(go,t)}async writeULE64(e,t){let n=this;yo.setUint32(0,e&4294967295,!0),yo.setUint32(4,Math.floor(e/4294967296),!0),await n.write(vo,t)}async readULE32(e){let t=await this.read(4,e);return new Uint32Array(t.buffer)[0]}async readUBE32(e){let t=await this.read(4,e);return new DataView(t.buffer).getUint32(0,!1)}async readULE64(e){let t=await this.read(8,e),n=new Uint32Array(t.buffer);return n[1]*4294967296+n[0]}async readString(e){let t=this,n=e===void 0?t.pos:e;if(n>this.totalSize){if(this.readOnly)throw Error(`Reading out of bounds`);this._resizeIfNeeded(e)}let r=!1,i=``;for(;!r;){let e=Math.floor(n/po),a=n%po;if(t.o.data[e]===void 0)throw Error(`ERROR`);let o=Math.min(2048,t.o.data[e].length-a),s=new Uint8Array(t.o.data[e].buffer,a,o),c=s.findIndex(e=>e===0);r=c!==-1,r?(i+=new TextDecoder().decode(s.slice(0,c)),t.pos=e*po+a+c+1):(i+=new TextDecoder().decode(s),t.pos=e*po+a+s.length),n=t.pos}return i}},xo=65536;function So(){throw Error(`File I/O is not supported in the browser`)}function Co(e,t){return e instanceof Uint8Array?{type:`mem`,data:e}:typeof e==`string`?{type:`mem`,initialSize:t||xo}:e}async function wo(e){let t=await fetch(e).then(e=>e.arrayBuffer());return{type:`mem`,data:new Uint8Array(t)}}function To(e,t,n){if(e.type===`file`&&So(),e.type===`mem`)return t(e);if(e.type===`bigMem`)return n(e);throw Error(`Invalid FastFile type: `+e.type)}function Eo(e,t){return To(Co(e,t),ao,mo)}async function Do(e){return e=typeof e==`string`?await wo(e):Co(e),To(e,oo,ho)}function Oo(e){let t=[];return n(t,e),t;function n(e,t){if(Array.isArray(t))for(let r=0;r0;)n.unshift(0),e--}return n}async function Mo(e,t){let n,r,i;t||={};let a=1,o=0,s=0,c=!1;if(e instanceof WebAssembly.Instance)n=e,c=!0;else{let c=32767;if(t.memorySize&&(c=parseInt(t.memorySize),c<0))throw Error(`Invalid memory size`);let l=!1;for(;!l;)try{i=new WebAssembly.Memory({initial:c}),l=!0}catch(e){if(c<=1)throw e;console.warn(`Could not allocate `+c*1024*64+` bytes. This may cause severe instability. Trying with `+c*1024*64/2+` bytes`),c=Math.floor(c/2)}let f=await WebAssembly.compile(e),p=``,m=``;n=await WebAssembly.instantiate(f,{env:{memory:i},runtime:{printDebug:function(e){console.log(`printDebug:`,e)},exceptionHandler:function(e){let t;throw t=e===1?`Signal not found. `:e===2?`Too many signals set. `:e===3?`Signal already set. `:e===4?`Assert Failed. `:e===5?`Not enough memory. `:e===6?`Input signal array access exceeds the size. `:`Unknown error. `,console.error(`ERROR: `,e,p),Error(t+p)},printErrorMessage:function(){p+=u()+` +`},writeBufferMessage:function(){let e=u();e===` +`?(console.log(m),m=``):(m!==``&&(m+=` `),m+=e)},showSharedRWMemory:function(){let e=n.exports.getFieldNumLen32(),t=new Uint32Array(e);for(let r=0;r=2&&(o>=1||s>=7)){m!==``&&(m+=` `);let e=V.fromArray(t,4294967296).toString();m+=e}else console.log(V.fromArray(t,4294967296))},error:function(e,n,i,a,o,s){let c;throw c=e===7?d(n)+` `+r.getFr(a).toString()+` != `+r.getFr(o).toString()+` `+d(s):e===9?d(n)+` `+r.getFr(a).toString()+` `+d(o):e===5&&t.sym?d(n)+` `+t.sym.labelIdx2Name[o]:d(n)+` `+i+` `+a+` `+o+` `+s,console.log(`ERROR: `,e,c),Error(c)},log:function(e){console.log(r.getFr(e).toString())},logGetSignal:function(e,n){t.logGetSignal&&t.logGetSignal(e,r.getFr(n))},logSetSignal:function(e,n){t.logSetSignal&&t.logSetSignal(e,r.getFr(n))},logStartComponent:function(e){t.logStartComponent&&t.logStartComponent(e)},logFinishComponent:function(e){t.logFinishComponent&&t.logFinishComponent(e)}}})}typeof n.exports.getVersion==`function`&&(a=n.exports.getVersion()),typeof n.exports.getMinorVersion==`function`&&(o=n.exports.getMinorVersion()),typeof n.exports.getPatchVersion==`function`&&(s=n.exports.getPatchVersion());let l=t&&(t.sanityCheck||t.logGetSignal||t.logSetSignal||t.logStartComponent||t.logFinishComponent);if(a===2)r=new Po(n,l);else if(a===1){if(c)throw Error(`Loading code from WebAssembly instance is not supported for circom version 1`);r=new No(i,n,l)}else throw Error(`Unsupported circom version: ${a}`);return r;function u(){let e=``,t=n.exports.getMessageChar();for(;t!==0;)e+=String.fromCharCode(t),t=n.exports.getMessageChar();return e}function d(e){let t=new Uint8Array(i.buffer),n=[];for(let r=0;t[e+r]>0;r++)n.push(t[e+r]);return String.fromCharCode.apply(null,n)}}var No=class{constructor(e,t,n){this.memory=e,this.i32=new Uint32Array(e.buffer),this.instance=t,this.n32=(this.instance.exports.getFrLen()>>2)-2;let r=this.instance.exports.getPRawPrime(),i=Array(this.n32);for(let e=0;e>2)+e];this.prime=V.fromArray(i,4294967296),this.Fr=new er(this.prime),this.mask32=V.fromString(`FFFFFFFF`,16),this.NVars=this.instance.exports.getNVars(),this.n64=Math.floor((this.Fr.bitLength-1)/64)+1,this.R=this.Fr.e(V.shiftLeft(1,this.n64*64)),this.RInv=this.Fr.inv(this.R),this.sanityCheck=n}circom_version(){return 1}async _doCalculateWitness(e,t){this.instance.exports.init(this.sanityCheck||t?1:0);let n=this.allocInt(),r=this.allocFr();Object.keys(e).forEach(t=>{let i=Ao(t),a=parseInt(i.slice(0,8),16),o=parseInt(i.slice(8,16),16);try{this.instance.exports.getSignalOffset32(n,0,a,o)}catch{throw Error(`Signal ${t} is not an input of the circuit.`)}let s=this.getInt(n),c=Oo(e[t]);for(let e=0;e>2]}setInt(e,t){this.i32[e>>2]=t}getFr(e){let t=this,n=e>>2;if(t.i32[n+1]&2147483648){let e=Array(t.n32);for(let r=0;r>2]=i,n.i32[(e>>2)+1]=0;return}n.i32[e>>2]=0,n.i32[(e>>2)+1]=2147483648;let a=V.toArray(t,4294967296);for(let t=0;t=0?n.i32[(e>>2)+2+t]=a[r]:n.i32[(e>>2)+2+t]=0}}},Po=class{constructor(e,t){this.instance=e,this.version=this.instance.exports.getVersion(),this.n32=this.instance.exports.getFieldNumLen32(),this.instance.exports.getRawPrime();let n=new Uint32Array(this.n32);for(let e=0;e{let n=Ao(t),i=parseInt(n.slice(0,8),16),a=parseInt(n.slice(8,16),16),o=Oo(e[t]);if(typeof this.instance.exports.getInputSignalSize==`function`){let e=this.instance.exports.getInputSignalSize(i,a);if(e<0)throw Error(`Signal ${t} not found\n`);if(o.lengthe)throw Error(`Too many values for input signal ${t}\n`)}for(let e=0;eKo,fullProve:()=>Ro,prove:()=>Qa,verify:()=>Bo});function Jo(e,t){let n=new DataView(t.buffer,t.byteOffset,t.byteLength),r=[];for(let e=0;e<8;e++)r[e]=n.getUint32(e*4);let i=new Gn(r);return e.G2.fromRng(i)}function Yo(e,t,n,r,i){let a=ua.create({dkLen:64}),o=new Uint8Array([t]);a.update(o),a.update(n);let s=e.G1.toUncompressed(r);a.update(s);let c=e.G1.toUncompressed(i);return a.update(c),Jo(e,a.digest())}function Xo(e,t,n,r,i){return e.g1_s=t.G1.toAffine(t.G1.fromRng(i)),e.g1_sx=t.G1.toAffine(t.G1.timesFr(e.g1_s,e.prvKey)),e.g2_sp=t.G2.toAffine(Yo(t,n,r,e.g1_s,e.g1_sx)),e.g2_spx=t.G2.toAffine(t.G2.timesFr(e.g2_sp,e.prvKey)),e}function Zo(e,t,n){let r={tau:{},alpha:{},beta:{}};return r.tau.prvKey=e.Fr.fromRng(n),r.alpha.prvKey=e.Fr.fromRng(n),r.beta.prvKey=e.Fr.fromRng(n),Xo(r.tau,e,0,t,n),Xo(r.alpha,e,1,t,n),Xo(r.beta,e,2,t,n),r}async function Qo(e,t,n,r){r||=n,await e.writeULE32(1);let i=e.pos;await e.writeULE64(0),await e.writeULE32(t.F1.n64*8);let a=new Uint8Array(t.F1.n8);V.toRprLE(a,0,t.q,t.F1.n8),await e.write(a),await e.writeULE32(n),await e.writeULE32(r);let o=e.pos-i-8,s=e.pos;await e.writeULE64(o,i),e.pos=s}async function $o(e,t){if(!t[1])throw Error(e.fileName+`: File has no header`);if(t[1].length>1)throw Error(e.fileName+`: File has more than one header`);e.pos=t[1][0].p;let n=await e.readULE32(),r=await e.read(n),i=await Ti(V.fromRprLE(r));if(i.F1.n64*8!=n)throw Error(e.fileName+`: Invalid size`);let a=await e.readULE32(),o=await e.readULE32();if(e.pos-t[1][0].p!=t[1][0].size)throw Error(`Invalid PTau header size`);return{curve:i,power:a,ceremonyPower:o}}async function es(e,t,n){return ts(await e.read(t.F1.n8*2*6+t.F2.n8*2*3),0,t,n)}function ts(e,t,n,r){let i={tau:{},alpha:{},beta:{}};return i.tau.g1_s=a(),i.tau.g1_sx=a(),i.alpha.g1_s=a(),i.alpha.g1_sx=a(),i.beta.g1_s=a(),i.beta.g1_sx=a(),i.tau.g2_spx=o(),i.alpha.g2_spx=o(),i.beta.g2_spx=o(),i;function a(){let i;return i=r?n.G1.fromRprLEM(e,t):n.G1.fromRprUncompressed(e,t),t+=n.G1.F.n8*2,i}function o(){let i;return i=r?n.G2.fromRprLEM(e,t):n.G2.fromRprUncompressed(e,t),t+=n.G2.F.n8*2,i}}function ns(e,t,n,r,i){a(r.tau.g1_s),a(r.tau.g1_sx),a(r.alpha.g1_s),a(r.alpha.g1_sx),a(r.beta.g1_s),a(r.beta.g1_sx),o(r.tau.g2_spx),o(r.alpha.g2_spx),o(r.beta.g2_spx);async function a(r){i?n.G1.toRprLEM(e,t,r):n.G1.toRprUncompressed(e,t,r),t+=n.F1.n8*2}async function o(r){i?n.G2.toRprLEM(e,t,r):n.G2.toRprUncompressed(e,t,r),t+=n.F2.n8*2}return e}async function rs(e,t,n,r){let i=new Uint8Array(t.F1.n8*2*6+t.F2.n8*2*3);ns(i,0,t,n,r),await e.write(i)}async function is(e,t){let n={};n.tauG1=await c(),n.tauG2=await l(),n.alphaG1=await c(),n.betaG1=await c(),n.betaG2=await l(),n.key=await es(e,t,!0),n.partialHash=await e.read(216),n.nextChallenge=await e.read(64),n.type=await e.readULE32();let r=new Uint8Array(t.G1.F.n8*2*6+t.G2.F.n8*2*3);ns(r,0,t,n.key,!1);let i=va(n.partialHash);i.update(r),n.responseHash=i.digest();let a=await e.readULE32(),o=e.pos,s=0;for(;e.pos-o1)throw Error(e.fileName+`: File has more than one contributions section`);e.pos=n[7][0].p;let r=await e.readULE32(),i=[];for(let n=0;n0){let t=new Uint8Array(a);await e.writeULE32(t.byteLength),await e.write(t)}else await e.writeULE32(0);async function o(n){t.G1.toRprLEM(r,0,n),await e.write(r)}async function s(n){t.G2.toRprLEM(i,0,n),await e.write(i)}}async function ss(e,t,n){await e.writeULE32(7);let r=e.pos;await e.writeULE64(0),await e.writeULE32(n.length);for(let r=0;r0?d[d.length-1].nextChallenge:cs(l,u,a);let y=await hi(n,`ptau`,1,i?7:2);await Qo(y,l,u);let b=await _.read(64);if(ga(o,v)&&(v=b,d[d.length-1].nextChallenge=v),!ga(b,v))throw Error(`Wrong contribution. This contribution is not based on the previous hash`);let x=ua.create({dkLen:64});x.update(b);let S=[],C;C=await E(_,y,`G1`,2,2**u*2-1,[1],`tauG1`),f.tauG1=C[0],C=await E(_,y,`G2`,3,2**u,[1],`tauG2`),f.tauG2=C[0],C=await E(_,y,`G1`,4,2**u,[0],`alphaG1`),f.alphaG1=C[0],C=await E(_,y,`G1`,5,2**u,[0],`betaG1`),f.betaG1=C[0],C=await E(_,y,`G2`,6,1,[0],`betaG2`),f.betaG2=C[0],f.partialHash=ya(x);let w=await _.read(l.F1.n8*2*6+l.F2.n8*2*3);f.key=ts(w,0,l,!1),x.update(new Uint8Array(w));let T=x.digest();if(a&&a.info(ha(T,`Contribution Response Hash imported: `)),i){let e=ua.create({dkLen:64});e.update(T),await k(e,y,`G1`,2,2**u*2-1,`tauG1`,a),await k(e,y,`G2`,3,2**u,`tauG2`,a),await k(e,y,`G1`,4,2**u,`alphaTauG1`,a),await k(e,y,`G1`,5,2**u,`betaTauG1`,a),await k(e,y,`G2`,6,1,`betaG2`,a),f.nextChallenge=e.digest(),a&&a.info(ha(f.nextChallenge,`Next Challenge Hash: `))}else f.nextChallenge=o;return d.push(f),await ss(y,l,d),await _.close(),await y.close(),await s.close(),f.nextChallenge;async function E(e,t,n,r,a,o,s){return i?await D(e,t,n,r,a,o,s):await O(e,t,n,r,a,o,s)}async function D(e,t,n,r,i,o,s){let c=l[n],u=c.F.n8,d=c.F.n8*2,f=[];await U(t,r);let p=Math.floor((1<<24)/d);S[r]=t.pos;for(let n=0;n=n&&t=t&&i1?c[c.length-2]:l;let d=c[c.length-1];if(t&&t.debug(`Validating contribution #`+c[c.length-1].id),!await ms(a,d,u,t))return!1;let f=ua.create({dkLen:64});f.update(d.responseHash),t&&t.debug(`Verifying powers in tau*G1 section`);let p=await x(2,`G1`,`tauG1`,2**o*2-1,[0,1],t);if(n=await ps(a,p.R1,p.R2,a.G2.g,d.tauG2),n!==!0)return t&&t.error(`tauG1 section. Powers do not match`),!1;if(!a.G1.eq(a.G1.g,p.singularPoints[0]))return t&&t.error(`First element of tau*G1 section must be the generator`),!1;if(!a.G1.eq(d.tauG1,p.singularPoints[1]))return t&&t.error(`Second element of tau*G1 section does not match the one in the contribution section`),!1;t&&t.debug(`Verifying powers in tau*G2 section`);let m=await x(3,`G2`,`tauG2`,2**o,[0,1],t);if(n=await ps(a,a.G1.g,d.tauG1,m.R1,m.R2),n!==!0)return t&&t.error(`tauG2 section. Powers do not match`),!1;if(!a.G2.eq(a.G2.g,m.singularPoints[0]))return t&&t.error(`First element of tau*G2 section must be the generator`),!1;if(!a.G2.eq(d.tauG2,m.singularPoints[1]))return t&&t.error(`Second element of tau*G2 section does not match the one in the contribution section`),!1;t&&t.debug(`Verifying powers in alpha*tau*G1 section`);let h=await x(4,`G1`,`alphatauG1`,2**o,[0],t);if(n=await ps(a,h.R1,h.R2,a.G2.g,d.tauG2),n!==!0)return t&&t.error(`alphaTauG1 section. Powers do not match`),!1;if(!a.G1.eq(d.alphaG1,h.singularPoints[0]))return t&&t.error(`First element of alpha*tau*G1 section (alpha*G1) does not match the one in the contribution section`),!1;t&&t.debug(`Verifying powers in beta*tau*G1 section`);let g=await x(5,`G1`,`betatauG1`,2**o,[0],t);if(n=await ps(a,g.R1,g.R2,a.G2.g,d.tauG2),n!==!0)return t&&t.error(`betaTauG1 section. Powers do not match`),!1;if(!a.G1.eq(d.betaG1,g.singularPoints[0]))return t&&t.error(`First element of beta*tau*G1 section (beta*G1) does not match the one in the contribution section`),!1;let _=await b(t);if(!a.G2.eq(d.betaG2,_))return t&&t.error(`betaG2 element in betaG2 section does not match the one in the contribution section`),!1;let v=f.digest();if(o==s&&!ga(v,d.nextChallenge))return t&&t.error(`Hash of the values does not match the next challenge of the last contributor in the contributions section`),!1;t&&t.info(ha(v,`Next challenge hash: `)),y(d,u);for(let e=c.length-2;e>=0;e--){let n=c[e],r=e>0?c[e-1]:l;if(!await ms(a,n,r,t))return!1;y(n,r,t)}if(t&&t.info(`-----------------------------------------------------`),!i[12]||!i[13]||!i[14]||!i[15])t&&t.warn(`this file does not contain phase2 precalculated values. Please run: + snarkjs "powersoftau preparephase2" to prepare this file to be used in the phase2 ceremony.`);else{let e;if(e=await S(`G1`,2,12,`tauG1`,t),!e||(e=await S(`G2`,3,13,`tauG2`,t),!e)||(e=await S(`G1`,4,14,`alphaTauG1`,t),!e)||(e=await S(`G1`,5,15,`betaTauG1`,t),!e))return!1}return await r.close(),t&&t.info(`Powers of Tau Ok!`),!0;function y(e,n){if(!t)return;t.info(`-----------------------------------------------------`),t.info(`Contribution #${e.id}: ${e.name||``}`),t.info(ha(e.nextChallenge,`Next Challenge: `));let r=new Uint8Array(a.G1.F.n8*2*6+a.G2.F.n8*2*3);ns(r,0,a,e.key,!1);let i=va(e.partialHash);i.update(r);let o=i.digest();t.info(ha(o,`Response Hash:`)),t.info(ha(n.nextChallenge,`Response Hash:`)),e.type==1&&(t.info(`Beacon generator: ${Oa(e.beaconHash)}`),t.info(`Beacon iterations Exp: ${e.numIterationsExp}`))}async function b(e){let t=a.G2,n=t.F.n8*2,o=new Uint8Array(n);if(!i[6])throw e.error(`File has no BetaG2 section`),Error(`File has no BetaG2 section`);if(i[6].length>1)throw e.error(`File has no BetaG2 section`),Error(`File has more than one GetaG2 section`);r.pos=i[6][0].p;let s=await r.read(n),c=t.fromRprLEM(s);return t.toRprUncompressed(o,0,c),f.update(o),c}async function x(e,t,n,o,s,c){let l=65536,u=a[t],d=u.F.n8*2;await G(r,i,e);let p=[],m=u.zero,h=u.zero,g=u.zero;for(let e=0;e0){let e=u.fromRprLEM(i,0),t=wa(Sa(4),0);m=u.add(m,u.timesScalar(g,t)),h=u.add(h,u.timesScalar(e,t))}let v=await u.multiExpAffine(i.slice(0,(t-1)*d),_),y=await u.multiExpAffine(i.slice(d),_);m=u.add(m,v),h=u.add(h,y),g=u.fromRprLEM(i,(t-1)*d);for(let n=0;n=e&&r1;)l/=2,u+=1;if(2**u!=c)throw Error(`Invalid file size`);i&&i.debug(`Power to tau size: `+u);let d=await Ta(r),f=await Eo(n),p=ua.create({dkLen:64});for(let e=0;e{i.debug(t+`.g1_s: `+e.G1.toString(g[t].g1_s,16)),i.debug(t+`.g1_sx: `+e.G1.toString(g[t].g1_sx,16)),i.debug(t+`.g2_sp: `+e.G2.toString(g[t].g2_sp,16)),i.debug(t+`.g2_spx: `+e.G2.toString(g[t].g2_spx,16)),i.debug(``)});let _=ua.create({dkLen:64});await f.write(h),_.update(h),await _s(a,f,_,e,`G1`,2**u*2-1,e.Fr.one,g.tau.prvKey,`COMPRESSED`,`tauG1`,i),await _s(a,f,_,e,`G2`,2**u,e.Fr.one,g.tau.prvKey,`COMPRESSED`,`tauG2`,i),await _s(a,f,_,e,`G1`,2**u,g.alpha.prvKey,g.tau.prvKey,`COMPRESSED`,`alphaTauG1`,i),await _s(a,f,_,e,`G1`,2**u,g.beta.prvKey,g.tau.prvKey,`COMPRESSED`,`betaTauG1`,i),await _s(a,f,_,e,`G2`,1,g.beta.prvKey,g.tau.prvKey,`COMPRESSED`,`betaTauG2`,i);let v=new Uint8Array(e.F1.n8*2*6+e.F2.n8*2*3);ns(v,0,e,g,!1),await f.write(v),_.update(v);let y=_.digest();i&&i.info(ha(y,`Contribution Response Hash: `)),await f.close(),await a.close()}async function ys(e,t,n,r,i,a){let o=Da(r);if(o.byteLength==0||o.byteLength*2!=r.length)return a&&a.error(`Invalid Beacon Hash. (It must be a valid hexadecimal sequence)`),!1;if(o.length>=256)return a&&a.error(`Maximum length of beacon hash is 255 bytes`),!1;if(i=parseInt(i),i<10||i>63)return a&&a.error(`Invalid numIterationsExp. (Must be between 10 and 63)`),!1;let{fd:s,sections:c}=await H(e,`ptau`,1),{curve:l,power:u,ceremonyPower:d}=await $o(s,c);if(u!=d)return a&&a.error(`This file has been reduced. You cannot contribute into a reduced file.`),!1;c[12]&&a&&a.warn(`Contributing into a file that has phase2 calculated. You will have to prepare phase2 again.`);let f=await as(s,l,c),p={name:n,type:1,numIterationsExp:i,beaconHash:o},m;m=f.length>0?f[f.length-1].nextChallenge:cs(l,u,a),p.key=await ls(l,m,o,i);let h=ua.create({dkLen:64});h.update(m);let g=await hi(t,`ptau`,1,7);await Qo(g,l,u);let _=[],v;v=await S(2,`G1`,2**u*2-1,l.Fr.e(1),p.key.tau.prvKey,`tauG1`,a),p.tauG1=v[1],v=await S(3,`G2`,2**u,l.Fr.e(1),p.key.tau.prvKey,`tauG2`,a),p.tauG2=v[1],v=await S(4,`G1`,2**u,p.key.alpha.prvKey,p.key.tau.prvKey,`alphaTauG1`,a),p.alphaG1=v[0],v=await S(5,`G1`,2**u,p.key.beta.prvKey,p.key.tau.prvKey,`betaTauG1`,a),p.betaG1=v[0],v=await S(6,`G2`,1,p.key.beta.prvKey,p.key.tau.prvKey,`betaTauG2`,a),p.betaG2=v[0],p.partialHash=ya(h);let y=new Uint8Array(l.F1.n8*2*6+l.F2.n8*2*3);ns(y,0,l,p.key,!1),h.update(new Uint8Array(y));let b=h.digest();a&&a.info(ha(b,`Contribution Response Hash imported: `));let x=ua.create({dkLen:64});return x.update(b),await C(g,`G1`,2,2**u*2-1,`tauG1`,a),await C(g,`G2`,3,2**u,`tauG2`,a),await C(g,`G1`,4,2**u,`alphaTauG1`,a),await C(g,`G1`,5,2**u,`betaTauG1`,a),await C(g,`G2`,6,1,`betaG2`,a),p.nextChallenge=x.digest(),a&&a.info(ha(p.nextChallenge,`Next Challenge Hash: `)),f.push(p),await ss(g,l,f),await s.close(),await g.close(),b;async function S(e,t,n,r,i,a,o){let u=[];s.pos=c[e][0].p,await U(g,e),_[e]=g.pos;let d=l[t],f=d.F.n8*2,p=Math.floor((1<<20)/f),m=r;for(let e=0;e0?u[u.length-1].nextChallenge:cs(s,c,i),d.key=Zo(s,f,p);let m=ua.create({dkLen:64});m.update(f);let h=await hi(t,`ptau`,1,7);await Qo(h,s,c);let g=[],_;_=await x(2,`G1`,2**c*2-1,s.Fr.e(1),d.key.tau.prvKey,`tauG1`),d.tauG1=_[1],_=await x(3,`G2`,2**c,s.Fr.e(1),d.key.tau.prvKey,`tauG2`),d.tauG2=_[1],_=await x(4,`G1`,2**c,d.key.alpha.prvKey,d.key.tau.prvKey,`alphaTauG1`),d.alphaG1=_[0],_=await x(5,`G1`,2**c,d.key.beta.prvKey,d.key.tau.prvKey,`betaTauG1`),d.betaG1=_[0],_=await x(6,`G2`,1,d.key.beta.prvKey,d.key.tau.prvKey,`betaTauG2`),d.betaG2=_[0],d.partialHash=ya(m);let v=new Uint8Array(s.F1.n8*2*6+s.F2.n8*2*3);ns(v,0,s,d.key,!1),m.update(new Uint8Array(v));let y=m.digest();i&&i.info(ha(y,`Contribution Response Hash imported: `));let b=ua.create({dkLen:64});return b.update(y),await S(h,`G1`,2,2**c*2-1,`tauG1`),await S(h,`G2`,3,2**c,`tauG2`),await S(h,`G1`,4,2**c,`alphaTauG1`),await S(h,`G1`,5,2**c,`betaTauG1`),await S(h,`G2`,6,1,`betaG2`),d.nextChallenge=b.digest(),i&&i.info(ha(d.nextChallenge,`Next Challenge Hash: `)),u.push(d),await ss(h,s,u),await a.close(),await h.close(),y;async function x(e,t,n,r,c,l){let u=[];a.pos=o[e][0].p,await U(h,e),g[e]=h.pos;let d=s[t],f=d.F.n8*2,p=Math.floor((1<<20)/f),_=r;for(let e=0;eys,challengeContribute:()=>vs,contribute:()=>bs,convert:()=>Cs,exportChallenge:()=>ds,exportJson:()=>ws,importResponse:()=>fs,newAccumulator:()=>us,preparePhase2:()=>xs,truncate:()=>Ss,verify:()=>hs});function Es(e,t,n){for(let t=0;t{let r=``;return Object.keys(n).forEach(i=>{let a=t.varIdx2Name[i];a==`one`&&(a=`1`);let o=e.curve.Fr.toString(n[i]);o==`1`&&(o=``),o==`-1`&&(o=`-`),r!=``&&o[0]!=`-`&&(o=`+`+o),r!=``&&(o=` `+o),r=r+o+a}),r},a=`[ ${i(r[0])} ] * [ ${i(r[1])} ] - [ ${i(r[2])} ] = 0`;n&&n.info(a)}}var Ds=262144,Os={get:function(e,t){return isNaN(t)?e[t]:e.getElement(t)},set:function(e,t,n){return isNaN(t)?(e[t]=n,!0):e.setElement(t,n)}},ks=class{constructor(e){this.length=e||0,this.arr=Array(Ds);for(let t=0;t=this.length&&(this.length=e+1),!0}getKeys(){let e=new As;for(let t=0;t1<<20?new As:[];for(let e=0;e1<<20?new As:[];for(let e=0;e1<<20?new As:[];for(let e=0;eVs,info:()=>Bs,print:()=>Es});async function Us(e){let t={labelIdx2Name:[`one`],varIdx2Name:[`one`],componentIdx2Name:[]},n=await Do(e),r=await n.read(n.totalSize),i=new TextDecoder(`utf-8`).decode(r).split(` +`);for(let e=0;e `+t.toString())}),i.trigger&&(u||=await Us(r),l.logStartComponent=function(e){a&&a.info(`START: `+u.componentIdx2Name[e])},l.logFinishComponent=function(e){a&&a.info(`FINISH: `+u.componentIdx2Name[e])}),l.sym=u;let d=await Mo(c,l),f=await d.calculateWitness(o,!0),p=await hi(n,`wtns`,2,2);await qa(p,f,d.prime),await p.close()}async function Ks(e){return await Xa(e)}async function qs(e,t,n){n&&n.info(`WITNESS CHECKING STARTED`),n&&n.info(`> Reading r1cs file`);let{fd:r,sections:i}=await H(e,`r1cs`,1,1<<22,1<<24),a=await Ps(r,i,{loadConstraints:!1,loadCustomGates:!1});n&&n.info(`> Reading witness file`);let{fd:o,sections:s}=await H(t,`wtns`,2,1<<22,1<<24),c=await Ya(o,s);if(!V.eq(a.prime,c.q))throw Error(`Curve of the witness does not match the curve of the proving key`);let l=await J(o,s,2);await o.close();let u=(await wi(a.prime)).Fr,d=u.n8,f=await J(r,i,2);n&&(n.info(`----------------------------`),n.info(` WITNESS CHECK`),n.info(` Curve: ${a.curve.name}`),n.info(` Vars (wires): ${a.nVars}`),n.info(` Outputs: ${a.nOutputs}`),n.info(` Public Inputs: ${a.nPubInputs}`),n.info(` Private Inputs: ${a.nPrvInputs}`),n.info(` Labels: ${a.nLabels}`),n.info(` Constraints: ${a.nConstraints}`),n.info(` Custom Gates: ${a.useCustomGates}`),n.info(`----------------------------`)),n&&n.info(`> Checking witness correctness`);let p=0,m=!0;for(let e=0;e{let r=_(n),i=e[n];t=u.add(t,u.mul(r,i))}),t}function g(){let e={},t=f.slice(p,p+4);p+=4;let n=new DataView(t.buffer).getUint32(0,!0),r=f.slice(p,p+(4+a.n8)*n);p+=(4+a.n8)*n;let i=new DataView(r.buffer);for(let t=0;tIo,check:()=>qs,debug:()=>Gs,exportJson:()=>Ks}),Ys=262144,Xs={get:function(e,t){return isNaN(t)?e[t]:e.getElement(t)},set:function(e,t,n){return isNaN(t)?(e[t]=n,!0):e.setElement(t,n)}},Zs=class{constructor(e){this.length=e||0,this.arr=Array(Ys);for(let t=0;t=this.length&&(this.length=e+1),!0}getKeys(){let e=new Qs;for(let t=0;tc)return r&&r.error(`circuit too big for this power of tau ceremony. ${d.nConstraints}*2 > 2**${c}`),-1;if(!o[12])return r&&r.error(`Powers of tau is not prepared.`),-1;let g=d.nOutputs+d.nPubInputs,_=2**h;await U(f,1),await f.writeULE32(1),await W(f),await U(f,2);let v=s.q,y=(Math.floor((V.bitLength(v)-1)/64)+1)*8,b=s.r,x=(Math.floor((V.bitLength(b)-1)/64)+1)*8,S=V.mod(V.shl(1,x*8),b),C=s.Fr.e(V.mod(V.mul(S,S),b));await f.writeULE32(y),await gi(f,v,y),await f.writeULE32(x),await gi(f,b,x),await f.writeULE32(d.nVars),await f.writeULE32(g),await f.writeULE32(_);let w;w=await a.read(p,o[4][0].p),await f.write(w),w=await s.G1.batchLEMtoU(w),i.update(w);let T;T=await a.read(p,o[5][0].p),await f.write(T),T=await s.G1.batchLEMtoU(T),i.update(T);let E;E=await a.read(m,o[6][0].p),await f.write(E),E=await s.G2.batchLEMtoU(E),i.update(E);let D=new Uint8Array(p);s.G1.toRprLEM(D,0,s.G1.g);let O=new Uint8Array(m);s.G2.toRprLEM(O,0,s.G2.g);let k=new Uint8Array(p);s.G1.toRprUncompressed(k,0,s.G1.g);let A=new Uint8Array(m);s.G2.toRprUncompressed(A,0,s.G2.g),await f.write(O),await f.write(D),await f.write(O),i.update(A),i.update(k),i.update(A),await W(f),r&&r.info(de()),r&&r.info(`Reading r1cs`);let j=await J(l,u,2);await l.close();let M=new Qs(d.nVars),N=new Qs(d.nVars),P=new Qs(d.nVars),F=new Qs(d.nVars-g-1),I=Array(g+1);r&&r.info(de()),r&&r.info(`Reading tauG1`);let L=await J(a,o,12,(_-1)*p,_*p);r&&r.info(`Reading tauG2`);let ee=await J(a,o,13,(_-1)*m,_*m);r&&r.info(`Reading alphatauG1`);let R=await J(a,o,14,(_-1)*p,_*p);r&&r.info(`Reading betatauG1`);let te=await J(a,o,15,(_-1)*p,_*p);r&&r.info(de()),r&&r.info(`processConstraints`),await ie(),r&&r.info(de()),r&&r.info(`composeAndWritePoints`),await ae(3,`G1`,I,`IC`),I=null,r&&r.info(de()),r&&r.info(`writeHs`),await re(),r&&r.info(de()),r&&r.info(`hashHPoints`),await se(),r&&r.info(de()),r&&r.info(`composeAndWritePoints 8 G1 C`),await ae(8,`G1`,F,`C`),F=null,r&&r.info(de()),r&&r.info(`composeAndWritePoints 5 G1 A`),await ae(5,`G1`,M,`A`),M=null,r&&r.info(de()),r&&r.info(`composeAndWritePoints 6 G1 B1`),await ae(6,`G1`,N,`B1`),N=null,r&&r.info(de()),r&&r.info(`composeAndWritePoints 7 G2 B2`),await ae(7,`G2`,P,`B2`),P=null,r&&r.info(de()),r&&r.info(`Contributions section`);let ne=i.digest();return await U(f,10),await f.write(ne),await f.writeULE32(0),await W(f),r&&r.info(ha(ne,`Circuit hash: `)),await f.close(),await a.close(),ne;async function re(){await U(f,9);let e=new B(_*p);if(h=0?s.Fr.fromRprLE(j.slice(r[3],r[3]+s.Fr.n8),0):s.Fr.fromRprLE(n,0);let a=s.Fr.mul(i,C);s.Fr.toRprLE(e,12,a),c.set(e,u),u+=e.length}}async function ae(e,t,n,a){let o=32768,c=s[t];ue(n.length),await U(f,e);let l=[],u=0;for(;u(r&&r.debug(`Writing points end ${a}: ${d}/${n.length}`),e))),u+=i,e++}let d=await Promise.all(l);for(let e=0;e32768?(m=new B(p*a),h=new B(p*s.Fr.n8)):(m=new Uint8Array(p*a),h=new Uint8Array(p*s.Fr.n8));let g,_,v=[L,ee,R,te],y=new Uint8Array(s.Fr.n8);s.Fr.toRprLE(y,0,s.Fr.e(1));let b=0;for(let e=0;e=0?h.set(j.slice(t[e][i][2],t[e][i][2]+s.Fr.n8),b*s.Fr.n8):h.set(y,b*s.Fr.n8),b++;if(t.length>1){let e=[];e.push({cmd:`ALLOCSET`,var:0,buff:m}),e.push({cmd:`ALLOCSET`,var:1,buff:h}),e.push({cmd:`ALLOC`,var:2,len:t.length*o}),g=0,_=0;let n=0;for(let r=0;rf.contributions.length)return i&&i.error(`The impoerted file does not include new contributions`),!1;for(let e=0;e=0;e--){let t=u.contributions[e];r&&r.info(`-------------------------`),r&&r.info(ha(t.contributionHash,`contribution #${e+1} ${t.name?t.name:``}:`)),t.type==1&&(r&&r.info(`Beacon generator: ${Oa(t.beaconHash)}`),r&&r.info(`Beacon iterations Exp: ${t.numIterationsExp}`))}return r&&r.info(`-------------------------`),r&&r.info(`ZKey Ok!`),!0;async function v(e,t,n,a,o,s,l,u,d){let f=1<<20,p=c[e],m=p.F.n8*2;await G(t,n,s),await G(a,o,s);let h=p.zero,g=p.zero,_=n[s][0].size/m;for(let e=0;e<_;e+=f){r&&r.debug(`Same ratio check ${d}: ${e}/${_}`);let n=Math.min(_-e,f),i=await t.read(n*m),o=await a.read(n*m),s=Sa(4*n),c=await p.multiExpAffine(i,s),l=await p.multiExpAffine(o,s);h=p.add(h,c),g=p.add(g,l)}return await K(t),await K(a),_==0?!0:(i=await nc(c,h,g,l,u),i===!0)}async function y(){let e=1<<20,n=c.G1,l=c.Fr,u=n.F.n8*2,{fd:d,sections:f}=await H(t,`ptau`,1),p=new B(s.domainSize*s.n8r),m=Array(8);for(let e=0;e<8;e++)m[e]=wa(Sa(4),0);let g=new Gn(m);for(let e=0;e=256)return a&&a.error(`Maximum length of beacon hash is 255 bytes`),!1;if(i=parseInt(i),i<10||i>63)return a&&a.error(`Invalid numIterationsExp. (Must be between 10 and 63)`),!1;let{fd:s,sections:c}=await H(e,`zkey`,2),l=await Fa(s,c);if(l.protocol!=`groth16`)throw Error(`zkey file is not groth16`);let u=await Ti(l.q),d=await Va(s,u,c),f=await hi(t,`zkey`,1,10),p=await Ea(o,i),m=ua.create({dkLen:64});m.update(d.csHash);for(let e=0;e Detected protocol: `+i.protocol);let a;if(i.protocol===`groth16`)a=await dc(i,n,r);else if(i.protocol===`plonk`)a=await fc(i);else if(i.protocolId&&i.protocolId===10)a=await pc(i,t);else throw Error(`zkey file protocol unrecognized`);return await n.close(),t&&t.info(`EXPORT VERIFICATION KEY FINISHED`),a}async function dc(e,t,n){let r=await Ti(e.q),i=r.G1.F.n8*2,a=await r.pairing(e.vk_alpha_1,e.vk_beta_2),o={protocol:e.protocol,curve:r.name,nPublic:e.nPublic,vk_alpha_1:r.G1.toObject(e.vk_alpha_1),vk_beta_2:r.G2.toObject(e.vk_beta_2),vk_gamma_2:r.G2.toObject(e.vk_gamma_2),vk_delta_2:r.G2.toObject(e.vk_delta_2),vk_alphabeta_12:r.Gt.toObject(a)};await G(t,n,3),o.IC=[];for(let n=0;n<=e.nPublic;n++){let e=await t.read(i),n=r.G1.toObject(e);o.IC.push(n)}return await K(t),o=lc(o),o}async function fc(e){let t=await Ti(e.q),n={protocol:e.protocol,curve:t.name,nPublic:e.nPublic,power:e.power,k1:t.Fr.toObject(e.k1),k2:t.Fr.toObject(e.k2),Qm:t.G1.toObject(e.Qm),Ql:t.G1.toObject(e.Ql),Qr:t.G1.toObject(e.Qr),Qo:t.G1.toObject(e.Qo),Qc:t.G1.toObject(e.Qc),S1:t.G1.toObject(e.S1),S2:t.G1.toObject(e.S2),S3:t.G1.toObject(e.S3),X_2:t.G2.toObject(e.X_2),w:t.Fr.toObject(t.Fr.w[e.power])};return n=lc(n),n}async function pc(e,t){let n=await Ti(e.q);return lc({protocol:e.protocol,curve:n.name,nPublic:e.nPublic,power:e.power,k1:n.Fr.toObject(e.k1),k2:n.Fr.toObject(e.k2),w:n.Fr.toObject(n.Fr.w[e.power]),w3:n.Fr.toObject(e.w3),w4:n.Fr.toObject(e.w4),w8:n.Fr.toObject(e.w8),wr:n.Fr.toObject(e.wr),X_2:n.G2.toObject(e.X_2),C0:n.G1.toObject(e.C0)})}function mc(e){return yc[e]||e}function hc(){return Function.prototype.toString.call(this)+`; +`+xc}var X,gc,_c,vc,yc,bc,xc,Sc=s((()=>{X={},gc=/[|\\{}()[\]^$+*?.]/g,_c=Object.prototype.hasOwnProperty,vc=function(e,t){return _c.apply(e,[t])},X.escapeRegExpChars=function(e){return e?String(e).replace(gc,`\\$&`):``},yc={"&":`&`,"<":`<`,">":`>`,'"':`"`,"'":`'`},bc=/[&<>'"]/g,xc=`var _ENCODE_HTML_RULES = { + "&": "&" + , "<": "<" + , ">": ">" + , '"': """ + , "'": "'" + } + , _MATCH_HTML = /[&<>'"]/g; +function encode_char(c) { + return _ENCODE_HTML_RULES[c] || c; +}; +`,X.escapeXML=function(e){return e==null?``:String(e).replace(bc,mc)};try{typeof Object.defineProperty==`function`?Object.defineProperty(X.escapeXML,`toString`,{value:hc}):X.escapeXML.toString=hc}catch{console.warn(`Unable to set escapeXML.toString (is the Function prototype frozen?)`)}X.shallowCopy=function(e,t){if(t||={},e!=null)for(var n in t)vc(t,n)&&(n===`__proto__`||n===`constructor`||(e[n]=t[n]));return e},X.shallowCopyFromList=function(e,t,n){if(n||=[],t||={},e!=null)for(var r=0;rZ});function wc(e,t){let n;if(t.some(function(t){return n=Z.resolveInclude(e,t,!0),Nc.default.existsSync(n)}))return n}function Tc(e,t){let n,r,i=t.views,a=/^[A-Za-z]+:\\|^\//.exec(e);if(a&&a.length)e=e.replace(/^\/*/,``),n=Array.isArray(t.root)?wc(e,t.root):Z.resolveInclude(e,t.root||`/`,!0);else if(t.filename&&(r=Z.resolveInclude(e,t.filename),Nc.default.existsSync(r)&&(n=r)),!n&&Array.isArray(i)&&(n=wc(e,i)),!n&&typeof t.includer!=`function`)throw Error(`Could not find the include file "`+t.escapeFunction(e)+`"`);return n}function Ec(e,t){let n,r=e.filename,i=arguments.length>1;if(e.cache){if(!r)throw Error(`cache option requires a filename`);if(n=Z.cache.get(r),n)return n;i||(t=Oc(r).toString().replace(Uc,``))}else if(!i){if(!r)throw Error(`Internal EJS error: no file name or template provided`);t=Oc(r).toString().replace(Uc,``)}return n=Z.compile(t,e),e.cache&&Z.cache.set(r,n),n}function Dc(e,t,n){let r;if(n){try{r=Ec(e)(t)}catch(e){return n(e)}n(null,r)}else{if(typeof Z.promiseImpl==`function`)return new Z.promiseImpl(function(n,i){try{r=Ec(e)(t),n(r)}catch(e){i(e)}});throw Error(`Please provide a callback function`)}}function Oc(e){return Z.fileLoader(e)}function kc(e,t){let n=X.shallowCopy(X.createNullProtoObjWherePossible(),t);if(n.filename=Tc(e,n),typeof t.includer==`function`){let r=t.includer(e,n.filename);if(r&&(r.filename&&(n.filename=r.filename),r.template))return Ec(n,r.template)}return Ec(n)}function Ac(e,t,n,r,i){let a=t.split(` +`),o=Math.max(r-3,0),s=Math.min(a.length,r+3),c=i(n),l=a.slice(o,s).map(function(e,t){let n=t+o+1;return(n==r?` >> `:` `)+n+`| `+e}).join(` +`);throw e.path=c,e.message=(c||`ejs`)+`:`+r+` +`+l+` + +`+e.message,e}function jc(e){return e.replace(/;(\s*$)/,`$1`)}function Mc(e,t){let n=X.hasOwnOnlyObject(t),r=X.createNullProtoObjWherePossible();this.templateText=e,this.mode=null,this.truncate=!1,this.currentLine=1,this.source=``,r.escapeFunction=n.escape||n.escapeFunction||X.escapeXML,r.compileDebug=n.compileDebug!==!1,r.debug=!!n.debug,r.filename=n.filename,r.openDelimiter=n.openDelimiter||Z.openDelimiter||Ic,r.closeDelimiter=n.closeDelimiter||Z.closeDelimiter||Lc,r.delimiter=n.delimiter||Z.delimiter||Rc,r.strict=n.strict||!1,r.context=n.context,r.cache=n.cache||!1,r.rmWhitespace=n.rmWhitespace,r.root=n.root,r.includer=n.includer,r.outputFunctionName=n.outputFunctionName,r.localsName=n.localsName||Z.localsName||zc,r.views=n.views,r.async=n.async,r.destructuredLocals=n.destructuredLocals,r.legacyInclude=n.legacyInclude===void 0?!0:!!n.legacyInclude,r.strict?r._with=!1:r._with=n._with===void 0?!0:n._with,this.opts=r,this.regex=this.createRegex()}var Nc,Pc,Fc,Z,Ic,Lc,Rc,zc,Bc,Vc,Hc,Uc,Wc,Gc=s((()=>{Nc=d(da()),Pc=d(da()),Sc(),Fc=`let`,Z={},Ic=`<`,Lc=`>`,Rc=`%`,zc=`locals`,Bc=`(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)`,Vc=[`delimiter`,`scope`,`context`,`debug`,`compileDebug`,`_with`,`rmWhitespace`,`strict`,`filename`,`async`],Hc=Vc.concat(`cache`),Uc=/^\uFEFF/,Wc=/^[a-zA-Z_$][0-9a-zA-Z_$]*$/,Z.cache=X.cache,Z.fileLoader=Nc.default.readFileSync,Z.localsName=zc,Z.promiseImpl=Function(`return this;`)().Promise,Z.resolveInclude=function(e,t,n){let r=Pc.default.dirname,i=Pc.default.extname,a=Pc.default.resolve,o=a(n?t:r(t),e);return i(e)||(o+=`.ejs`),o},Z.compile=function(e,t){let n;return t&&t.scope&&(console.warn("`scope` option is deprecated and will be removed in future EJS"),t.context||=t.scope,delete t.scope),n=new Mc(e,t),n.compile()},Z.render=function(e,t,n){let r=t||X.createNullProtoObjWherePossible(),i=n||X.createNullProtoObjWherePossible();return arguments.length==2&&X.shallowCopyFromList(i,r,Vc),Ec(i,e)(r)},Z.renderFile=function(){let e=Array.prototype.slice.call(arguments),t=e.shift(),n,r={filename:t},i,a;return typeof arguments[arguments.length-1]==`function`&&(n=e.pop()),e.length?(i=e.shift(),e.length?X.shallowCopy(r,e.pop()):(i.settings&&(i.settings.views&&(r.views=i.settings.views),i.settings[`view cache`]&&(r.cache=!0),a=i.settings[`view options`],a&&X.shallowCopy(r,a)),X.shallowCopyFromList(r,i,Hc)),r.filename=t):i=X.createNullProtoObjWherePossible(),Dc(r,i,n)},Z.Template=Mc,Z.clearCache=function(){Z.cache.reset()},Mc.modes={EVAL:`eval`,ESCAPED:`escaped`,RAW:`raw`,COMMENT:`comment`,LITERAL:`literal`},Mc.prototype={createRegex:function(){let e=Bc,t=X.escapeRegExpChars(this.opts.delimiter),n=X.escapeRegExpChars(this.opts.openDelimiter),r=X.escapeRegExpChars(this.opts.closeDelimiter);return e=e.replace(/%/g,t).replace(//g,r),new RegExp(e)},compile:function(){let e,t,n=this.opts,r=``,i=``,a=n.escapeFunction,o,s=n.filename?JSON.stringify(n.filename):`undefined`;if(!this.source){if(this.generateSource(),r+=` ${Fc} __output = "";\n function __append(s) { if (s !== undefined && s !== null) __output += s } +`,n.outputFunctionName){if(!Wc.test(n.outputFunctionName))throw Error(`outputFunctionName is not a valid JS identifier.`);r+=` ${Fc} `+n.outputFunctionName+` = __append; +`}if(n.localsName&&!Wc.test(n.localsName))throw Error(`localsName is not a valid JS identifier.`);if(n.destructuredLocals&&n.destructuredLocals.length){let e=` ${Fc} __locals = (`+n.localsName+` || {}), +`;for(let t=0;t0&&(e+=`, + `),e+=r+` = __locals.`+r}r+=e+`; +`}n._with!==!1&&(r+=` with (`+n.localsName+` || {}) { +`,i+=` } +`),i+=` return __output; +`,this.source=r+this.source+i}e=n.compileDebug?`${Fc} __line = 1 + , __lines = `+JSON.stringify(this.templateText)+` + , __filename = `+s+`; +try { +`+this.source+`} catch (e) { + rethrow(e, __lines, __filename, __line, escapeFn); +} +`:this.source,n.strict&&(e=`"use strict"; +`+e),n.debug&&console.log(e),n.compileDebug&&n.filename&&(e=e+` +//# sourceURL=`+s+` +`);try{if(n.async)try{o=Function(`return (async function(){}).constructor;`)()}catch(e){throw e instanceof SyntaxError?Error(`This environment does not support async/await`):e}else o=Function;t=new o(n.localsName+`, escapeFn, include, rethrow`,e)}catch(e){throw e instanceof SyntaxError&&(n.filename&&(e.message+=` in `+n.filename),e.message+=` while compiling ejs + +`,e.message+=`If the above error is not helpful, you may want to try EJS-Lint: +`,e.message+=`https://github.com/RyanZim/EJS-Lint`,n.async||(e.message+=` +`,e.message+="Or, if you meant to create an async function, pass `async: true` as an option.")),e}let c=function(e){return t.apply(n.context,[e||X.createNullProtoObjWherePossible(),a,function(t,r){let i=X.shallowCopy(X.createNullProtoObjWherePossible(),e);return r&&(i=X.shallowCopy(i,r)),kc(t,n)(i)},Ac])};if(n.filename&&typeof Object.defineProperty==`function`){let e=n.filename,t=Pc.default.basename(e,Pc.default.extname(e));try{Object.defineProperty(c,`name`,{value:t,writable:!1,enumerable:!1,configurable:!0})}catch{}}return c},generateSource:function(){this.opts.rmWhitespace&&(this.templateText=this.templateText.replace(/[\r\n]+/g,` +`).replace(/^\s+|\s+$/gm,``));let e=this,t=this.opts.delimiter,n=this.opts.openDelimiter,r=this.opts.closeDelimiter,i=X.escapeRegExpChars(n+t+`_`),a=X.escapeRegExpChars(`_`+t+r),o=n+t+`_`,s=`_`+t+r;this.templateText=this.templateText.replace(RegExp(`[ \\t]*`+i,`gm`),o).replace(RegExp(a+`[ \\t]*`,`gm`),s);let c=this.parseTemplateText();c&&c.length&&c.forEach(function(i,a){let o;if(i.indexOf(n+t)===0&&i.indexOf(n+t+t)!==0&&(o=c[a+2],!(o==t+r||o==`-`+t+r||o==`_`+t+r)))throw Error(`Could not find matching close tag for "`+i+`".`);e.scanLine(i)})},parseTemplateText:function(){let e=this.templateText,t=this.regex,n=t.exec(e),r=[],i;for(;n;)i=n.index,i!==0&&(r.push(e.substring(0,i)),e=e.slice(i)),r.push(n[0]),e=e.slice(n[0].length),n=t.exec(e);return e&&r.push(e),r},_addOutput:function(e){if(this.truncate&&=(e=e.replace(/^(?:\r\n|\r|\n)/,``),!1),!e)return e;e=e.replace(/\\/g,`\\\\`),e=e.replace(/\n/g,`\\n`),e=e.replace(/\r/g,`\\r`),e=e.replace(/"/g,`\\"`),this.source+=` ; __append("`+e+`") +`},scanLine:function(e){let t=this,n=this.opts.delimiter,r=this.opts.openDelimiter,i=this.opts.closeDelimiter,a=0;switch(a=e.split(` +`).length-1,e){case r+n:case r+n+`_`:this.mode=Mc.modes.EVAL;break;case r+n+`=`:this.mode=Mc.modes.ESCAPED;break;case r+n+`-`:this.mode=Mc.modes.RAW;break;case r+n+`#`:this.mode=Mc.modes.COMMENT;break;case r+n+n:this.mode=Mc.modes.LITERAL,this.source+=` ; __append("`+e.replace(r+n+n,r+n)+`") +`;break;case n+n+i:this.mode=Mc.modes.LITERAL,this.source+=` ; __append("`+e.replace(n+n+i,n+i)+`") +`;break;case n+i:case`-`+n+i:case`_`+n+i:this.mode==Mc.modes.LITERAL&&this._addOutput(e),this.mode=null,this.truncate=e.indexOf(`-`)===0||e.indexOf(`_`)===0;break;default:if(this.mode){switch(this.mode){case Mc.modes.EVAL:case Mc.modes.ESCAPED:case Mc.modes.RAW:e.lastIndexOf(`//`)>e.lastIndexOf(` +`)&&(e+=` +`)}switch(this.mode){case Mc.modes.EVAL:this.source+=` ; `+e+` +`;break;case Mc.modes.ESCAPED:this.source+=` ; __append(escapeFn(`+jc(e)+`)) +`;break;case Mc.modes.RAW:this.source+=` ; __append(`+jc(e)+`) +`;break;case Mc.modes.COMMENT:break;case Mc.modes.LITERAL:this._addOutput(e);break}}else this._addOutput(e)}t.opts.compileDebug&&a&&(this.currentLine+=a,this.source+=` ; __line = `+this.currentLine+` +`)}},Z.escapeXML=X.escapeXML,Z.__express=Z.renderFile,typeof window<`u`&&(window.ejs=Z),typeof module<`u`&&(module.exports=Z)})),{unstringifyBigInts:Kc,stringifyBigInts:qc}=Gr;async function Jc(e,t,n){n&&n.info(`FFLONK EXPORT SOLIDITY VERIFIER STARTED`);let r=await Ei(e.curve),i=u(e.w3);e.w3_2=d(r.Fr.square(i));let a=u(e.w4);e.w4_2=d(r.Fr.square(a)),e.w4_3=d(r.Fr.mul(r.Fr.square(a),a));let o=u(e.w8),s=r.Fr.one;for(let t=1;t<8;t++)s=r.Fr.mul(s,o),e[`w8_`+t]=d(s);let c=t[e.protocol];n&&n.info(`FFLONK EXPORT SOLIDITY VERIFIER FINISHED`);let{default:l}=await Promise.resolve().then(()=>(Gc(),Cc));return l.render(c,e);function u(e){let t=Kc(e);return r.Fr.fromObject(t)}function d(e){return qc(r.Fr.toObject(e))}}async function Yc(e,t,n){let r=await uc(e,n);if(r.protocol===`fflonk`)return Jc(r,t,n);let i=t[r.protocol],{default:a}=await Promise.resolve().then(()=>(Gc(),Cc));return a.render(i,r)}var Xc=l({beacon:()=>oc,bellmanContribute:()=>cc,contribute:()=>ac,exportBellman:()=>ec,exportJson:()=>sc,exportSolidityVerifier:()=>Yc,exportVerificationKey:()=>uc,importBellman:()=>tc,newZKey:()=>$s,verifyFromInit:()=>rc,verifyFromR1cs:()=>ic});async function Zc(e,t,n,r){globalThis.gc&&globalThis.gc();let{fd:i,sections:a}=await H(t,`ptau`,1,1<<22,1<<24),{curve:o,power:s}=await $o(i,a),{fd:c,sections:l}=await H(e,`r1cs`,1,1<<22,1<<24),u=await Ps(c,l,{loadConstraints:!0,loadCustomGates:!0}),d=o.G1.F.n8*2,f=o.G1,p=o.G2.F.n8*2,m=o.Fr,h=o.Fr.n8;r&&r.info(`Reading r1cs`),await J(c,l,2);let g=new Qs,_=new Qs,v=u.nVars,y=u.nOutputs+u.nPubInputs;await k(o.Fr,u,r),globalThis.gc&&globalThis.gc();let b=await hi(n,`zkey`,1,14,1<<22,1<<24);if(u.prime!=o.r)return r&&r.error(`r1cs curve does not match powers of tau ceremony curve`),-1;let x=ma(g.length-1)+1;x<3&&(x=3);let S=2**x;if(r&&r.info(`Plonk constraints: `+g.length),x>s)return r&&r.error(`circuit too big for this power of tau ceremony. ${g.length} > 2**${s}`),-1;if(!a[12])return r&&r.error(`Powers of tau is not prepared.`),-1;let C=new B(S*d),w=a[12][0].p+(2**x-1)*d;await i.readToBuffer(C,0,S*d,w);let[T,E]=L(),D={};await N(3,`Additions`),globalThis.gc&&globalThis.gc(),await A(4,0,`Amap`),globalThis.gc&&globalThis.gc(),await A(5,1,`Bmap`),globalThis.gc&&globalThis.gc(),await A(6,2,`Cmap`),globalThis.gc&&globalThis.gc(),await j(7,3,`Qm`),globalThis.gc&&globalThis.gc(),await j(8,4,`Ql`),globalThis.gc&&globalThis.gc(),await j(9,5,`Qr`),globalThis.gc&&globalThis.gc(),await j(10,6,`Qo`),globalThis.gc&&globalThis.gc(),await j(11,7,`Qc`),globalThis.gc&&globalThis.gc(),await P(12,`sigma`),globalThis.gc&&globalThis.gc(),await F(13,`lagrange polynomials`),globalThis.gc&&globalThis.gc(),await U(b,14);let O=new B((S+6)*d);await i.readToBuffer(O,0,(S+6)*d,a[2][0].p),await b.write(O),await W(b),globalThis.gc&&globalThis.gc(),await I(),await b.close(),await c.close(),await i.close(),r&&r.info(`Setup Finished`);return;async function k(e,t,n){function r(e){let t=Object.keys(e);for(let n=0;nn;){let t=i.shift(),n=i.shift(),r=t[0],a=n[0],o=v++,s=e.zero,c=e.neg(t[1]),l=e.neg(n[1]),u=e.one,d=e.zero;g.push([r,a,o,s,c,l,u,d]),_.push([r,a,t[1],n[1]]),i.push([o,e.one])}for(let e=0;e0?r.toString():n==e.zero?`0`:`k`}function l(e,t,n){let a=c(e),l=c(t);a===`0`||l===`0`?(r(n),o(n)):a===`k`?o(i(t,e[0],n)):l===`k`?o(i(e,t[0],n)):s(e,t,n)}for(let t=1;t<=y;t++){let n=t,r=e.zero,i=e.one,a=e.zero,o=e.zero,s=e.zero;g.push([n,0,0,r,i,a,o,s])}for(let e=0;e{let r=this.curve.G1.toObject(this.polynomials[n]);e?t.polynomials[n]=r:t[n]=r}),Object.keys(this.evaluations).forEach(n=>{let r=this.curve.Fr.toObject(this.evaluations[n]);e?t.evaluations[n]=r:t[n]=r}),t}fromObjectProof(e){this.resetProof(),Object.keys(e.polynomials).forEach(t=>{this.polynomials[t]=this.curve.G1.fromObject(e.polynomials[t])}),Object.keys(e.evaluations).forEach(t=>{this.evaluations[t]=this.curve.Fr.fromObject(e.evaluations[t])})}},$c=BigInt(0),el=BigInt(1),tl=BigInt(2),nl=BigInt(7),rl=BigInt(256),il=BigInt(113),al=[],ol=[],sl=[];for(let e=0,t=el,n=1,r=0;e<24;e++){[n,r]=[r,(2*n+3*r)%5],al.push(2*(5*r+n)),ol.push((e+1)*(e+2)/2%64);let i=$c;for(let e=0;e<7;e++)t=(t<>nl)*il)%rl,t&tl&&(i^=el<<(el<n>32?$i(e,t,n):Zi(e,t,n),fl=(e,t,n)=>n>32?ea(e,t,n):Qi(e,t,n);function pl(e,t=24){let n=new Uint32Array(10);for(let r=24-t;r<24;r++){for(let t=0;t<10;t++)n[t]=e[t]^e[t+10]^e[t+20]^e[t+30]^e[t+40];for(let t=0;t<10;t+=2){let r=(t+8)%10,i=(t+2)%10,a=n[i],o=n[i+1],s=dl(a,o,1)^n[r],c=fl(a,o,1)^n[r+1];for(let n=0;n<50;n+=10)e[t+n]^=s,e[t+n+1]^=c}let t=e[2],i=e[3];for(let n=0;n<24;n++){let r=ol[n],a=dl(t,i,r),o=fl(t,i,r),s=al[n];t=e[s],i=e[s+1],e[s]=a,e[s+1]=o}for(let t=0;t<50;t+=10){for(let r=0;r<10;r++)n[r]=e[t+r];for(let r=0;r<10;r++)e[t+r]^=~n[(r+2)%10]&n[(r+4)%10]}e[0]^=ll[r],e[1]^=ul[r]}Ni(n)}var ml=class e{state;pos=0;posOut=0;finished=!1;state32;destroyed=!1;blockLen;suffix;outputLen;enableXOF=!1;rounds;constructor(e,t,n,r=!1,i=24){if(this.blockLen=e,this.suffix=t,this.outputLen=n,this.enableXOF=r,this.rounds=i,Oi(n,`outputLen`),!(0=n&&this.keccak();let a=Math.min(n-this.posOut,i-r);e.set(t.subarray(this.posOut,this.posOut+a),r),this.posOut+=a,r+=a}return e}xofInto(e){if(!this.enableXOF)throw Error(`XOF is not possible for this instance`);return this.writeInto(e)}xof(e){return Oi(e),this.xofInto(new Uint8Array(e))}digestInto(e){if(ji(e,this),this.finished)throw Error(`digest() was already called`);return this.writeInto(e),this.destroy(),e}digest(){return this.digestInto(new Uint8Array(this.outputLen))}destroy(){this.destroyed=!0,Ni(this.state)}_cloneInto(t){let{blockLen:n,suffix:r,outputLen:i,rounds:a,enableXOF:o}=this;return t||=new e(n,r,i,o,a),t.state32.set(this.state32),t.pos=this.pos,t.posOut=this.posOut,t.finished=this.finished,t.rounds=a,t.suffix=r,t.outputLen=i,t.enableXOF=o,t.destroyed=this.destroyed,t}},hl=((e,t,n,r={})=>zi(()=>new ml(t,e,n),r))(1,136,32),gl=0,_l=1,vl=class{constructor(e){this.G1=e.G1,this.Fr=e.Fr,this.reset()}reset(){this.data=[]}addPolCommitment(e){this.data.push({type:gl,data:e})}addScalar(e){this.data.push({type:_l,data:e})}getChallenge(){if(this.data.length===0)throw Error(`Keccak256Transcript: No data to generate a transcript`);let e=0,t=0;this.data.forEach(n=>gl===n.type?e++:t++);let n=new Uint8Array(t*this.Fr.n8+e*this.G1.F.n8*2),r=0;for(let e=0;e32768?new B(t.length*i.n8):new Uint8Array(t.length*i.n8);for(let e=0;e32768?new B(i*a.n8):new Uint8Array(i*a.n8);return o.set(t.coef.slice(),0),new e(o,n,r)}isEqual(e){let t=this.degree();if(t!==e.degree())return!1;for(let n=0;n32768?new B((this.length()+e.length)*this.Fr.n8):new Uint8Array((this.length()+e.length)*this.Fr.n8);t.set(this.coef,0);for(let n=0;nthis.coef.byteLength?this.Fr.zero:this.coef.slice(t,t+this.Fr.n8)}setCoef(e,t){if(e>this.length()-1)throw Error(`Coef index is not available`);this.coef.set(t,e*this.Fr.n8)}static async to4T(e,t,n,r){n||=[];let i=await r.ifft(e),a=t*4>32768?new B(t*4*r.n8):new Uint8Array(t*4*r.n8);a.set(i,0);let o=await r.fft(a);if(n.length===0)return[i,o];let s=t+n.length>32768?new B((t+n.length)*r.n8):new Uint8Array((t+n.length)*r.n8);s.set(i,0);for(let e=0;e0;e--){let t=e*this.Fr.n8;if(!this.Fr.eq(this.Fr.zero,this.coef.slice(t,t+this.Fr.n8)))return e}return 0}evaluate(e){let t=this.Fr.zero;for(let n=this.degree()+1;n>0;n--){let r=n*this.Fr.n8,i=this.coef.slice(r-this.Fr.n8,r);t=this.Fr.add(i,this.Fr.mul(t,e))}return t}fastEvaluate(e){let t=this.Fr,n=this.degree()+1,r=parseInt(n/3),i=n-r*3,a=[],o=[];o[0]=t.one;for(let n=0;n<3;n++){a[n]=t.zero;let s=n===2?r+i:r;for(let i=s;i>0;i--)a[n]=t.add(this.getCoef(n*r+i-1),t.mul(a[n],e)),n===0&&(o[0]=t.mul(o[0],e))}for(let e=1;e<3;e++)a[0]=t.add(a[0],t.mul(o[e-1],a[e])),o[e]=t.mul(o[e-1],o[0]);return a[0]}add(e,t){let n=!1;e.length()>this.length()&&(n=!0);let r=this.length(),i=e.length();for(let a=0;athis.length()&&(n=!0);let r=this.length(),i=e.length();for(let a=0;a32768?new B(r*n.n8):new Uint8Array(r*n.n8),this.curve,this.logger);i.coef.set(this.coef.slice(0,(r-1)*n.n8),32),this.mulScalar(n.neg(t)),i.add(this),this.coef=i.coef}byXNSubValue(t,n){let r=this.Fr,i=this.length()-t-1>=this.degree()?this.length():this.length()+t,a=new e(i>32768?new B(i*r.n8):new Uint8Array(i*r.n8),this.curve,this.logger);a.coef.set(this.coef.slice(0,(this.degree()+1)*32),t*32),this.mulScalar(n),a.add(this),this.coef=a.coef}divBy(t){let n=this.Fr,r=this.degree(),i=t.degree(),a=new e(this.coef,this.curve,this.logger);this.coef=this.length()>32768?new B(this.length()*n.n8):new Uint8Array(this.length()*n.n8);for(let e=r-i;e>=0;e--){this.setCoef(e,n.div(a.getCoef(e+i),t.getCoef(i)));for(let r=0;r<=i;r++)a.setCoef(e+r,n.sub(a.getCoef(e+r),n.mul(this.getCoef(e),t.getCoef(r))))}return a}divByMonic(t,n){let r=this.Fr,i=this.degree(),a=new e(this.length()>32768?new B(this.length()*r.n8):new Uint8Array(this.length()*r.n8),this.curve,this.logger),o=[];for(let e=0;e=0&&!(l<0);l-=s){let i=e;o[i]=r.add(this.getCoef(l+t),r.mul(o[i],n)),a.setCoef(l,o[i]),c=(c+1)%t}this.coef=a.coef}divByVanishing(t,n){if(this.degree()32768?new B(this.length()*r.n8):new Uint8Array(this.length()*r.n8);for(let e=this.length()-1;e>=t;e--){let a=i.getCoef(e);r.eq(r.zero,a)||(i.setCoef(e,r.zero),i.setCoef(e-t,r.add(i.getCoef(e-t),r.mul(n,a))),this.setCoef(e-t,r.add(this.getCoef(e-t),a)))}return i}divByVanishing2(t,n){if(this.degree()32768?new B(this.length()*r.n8):new Uint8Array(this.length()*r.n8);let a=this.length()-t,o=Math.floor(a/3),s=a-2*o;console.log(a),console.log(o+` `+s);for(let e=0;e<3;e++){console.log(`> Thread `+e);for(let a=e===0?s:o;a>0;a--){let c=a-1;e!==0&&(c+=(e-1)*o+s);let l=c+t,u=i.getCoef(l);r.eq(r.zero,u)||(i.setCoef(l,r.zero),i.setCoef(c,r.add(i.getCoef(c),r.mul(n,u))),this.setCoef(c,r.add(this.getCoef(c),u)),console.log(c+` <-- `+l))}}return this.print(),i}fastDivByVanishing(t){let n=this.Fr;for(let r=0;r32768?new B(this.length()*n.n8):new Uint8Array(this.length()*n.n8),this.curve,this.logger),d=this.coef;this.coef=u.coef,u.coef=d;for(let e=0;e<5;e++){let t=(e+1)*c+l;for(let e=0;e0;e--){let t=e-1,r=t*c+l;m[t]=[];for(let a=0;a32768?new B(this.length()*this.Fr.n8):new Uint8Array(this.length()*this.Fr.n8);t.set(this.Fr.zero,(this.length()-1)*this.Fr.n8),t.set(this.coef.slice((this.length()-1)*this.Fr.n8,this.length()*this.Fr.n8),(this.length()-2)*this.Fr.n8);for(let n=this.length()-3;n>=0;n--){let r=n*this.Fr.n8;t.set(this.Fr.add(this.coef.slice(r+this.Fr.n8,r+2*this.Fr.n8),this.Fr.mul(e,t.slice(r+this.Fr.n8,r+2*this.Fr.n8))),n*this.Fr.n8)}if(!this.Fr.eq(this.coef.slice(0,this.Fr.n8),this.Fr.mul(this.Fr.neg(e),t.slice(0,this.Fr.n8))))throw Error(`Polynomial does not divide`);this.coef=t}divZh(e,t=4){for(let t=0;te*(t-1)-t&&!this.Fr.isZero(i))throw Error(`Polynomial is not divisible`)}return this}divByZerofier(e,t){let n=this.Fr,r=n.inv(t),i=n.neg(r),a=n.eq(n.one,i),o=n.eq(n.negone,i);if(!a)for(let t=0;tthis.length()-e-1&&!this.Fr.isZero(c))throw Error(`Polynomial is not divisible`)}return this}byX(){let e=this.length()+1>32768?new B(this.coef.byteLength+this.Fr.n8):new Uint8Array(this.coef.byteLength+this.Fr.n8);e.set(this.Fr.zero,0),e.set(this.coef,this.Fr.n8),this.coef=e}static async expX(t,n,r=!1){let i=t.Fr;if(n<1)throw Error(`Compute a new polynomial to a zero or negative number is not allowed`);if(n===1)return await e.fromEvaluations(t.coef,t.curve,t.logger);let a=r?t.degree():t.length()-1,o=a*n+1>32768?new B((a*n+1)*i.n8):new Uint8Array((a*n+1)*i.n8);o.set(t.getCoef(0),0);for(let e=1;e<=a;e++){let r=e*i.n8,a=t.getCoef(e);o.set(a,r*n)}return new e(o,t.curve,t.logger)}split(t,n,r){if(t<1)throw Error(`Polynomials can't be split in ${t} parts`);if(t===1)return[this];if(r.length!==0&&r.length32768?new B(s):new Uint8Array(s),this.curve,this.logger);let c=n*i,l=o?this.coef.byteLength:(n+1)*i;if(a[n].coef.set(this.coef.slice(c,l),0),o||a[n].coef.set(r[n],i),n!==0){let e=this.Fr.sub(a[n].coef.slice(0,this.Fr.n8),r[n-1]);a[n].coef.set(e,0)}o&&a[n].truncate()}return a}truncate(){let e=this.degree();if(e+132768?new B((e+1)*this.Fr.n8):new Uint8Array((e+1)*this.Fr.n8);t.set(this.coef.slice(0,(e+1)*this.Fr.n8),0),this.coef=t}}static lagrangePolynomialInterpolation(t,n,r){let i=r.Fr,a=o(0);for(let e=1;e32768?new B(t.length*i.n8):new Uint8Array(t.length*i.n8),r),o.setCoef(0,i.neg(t[n])),o.setCoef(1,i.one)):o.byXSubValue(t[n]));let s=o.evaluate(t[a]);s=i.inv(s);let c=i.mul(n[a],s);return o.mulScalar(c),o}}static zerofierPolynomial(t,n){let r=n.Fr,i=new e(t.length+1>32768?new B((t.length+1)*r.n8):new Uint8Array((t.length+1)*r.n8),n);i.setCoef(0,r.neg(t[0])),i.setCoef(1,r.one);for(let e=1;e=0;n--){let r=this.getCoef(n);e.eq(e.zero,r)||(e.isNegative(r)?t+=` - `:n!==this.degree()&&(t+=` + `),t+=e.toString(r),n>0&&(t+=n>1?`x^`+n:`x`))}console.log(t)}async multiExponentiation(e,t){let n=this.coef.byteLength/this.Fr.n8,r=e.slice(0,n*this.G1.F.n8*2),i=await this.Fr.batchFromMontgomery(this.coef),a=await this.G1.multiExpAffine(r,i,this.logger,t);return a=this.G1.toAffine(a),a}},$=class e{constructor(e,t,n){this.eval=e,this.curve=t,this.Fr=t.Fr,this.logger=n}static async fromPolynomial(t,n,r,i){let a=new B(t.length()*n*r.Fr.n8);return a.set(t.coef,0),new e(await r.Fr.fft(a),r,i)}getEvaluation(e){let t=e*this.Fr.n8;if(t+this.Fr.n8>this.eval.byteLength)throw Error(`Evaluations.getEvaluation() out of bounds`);return this.eval.slice(t,t+this.Fr.n8)}length(){let e=this.eval.byteLength/this.Fr.n8;if(e!==Math.floor(this.eval.byteLength/this.Fr.n8))throw Error(`Polynomial evaluations buffer has incorrect size`);return e===0&&this.logger.warn(`Polynomial has length zero`),e}},{stringifyBigInts:bl}=Gr;async function xl(e,t,n,r){let{fd:i,sections:a}=await H(t,`wtns`,2,1<<25,1<<23);n&&n.debug(`> Reading witness file`);let o=await Ya(i,a);n&&n.debug(`> Reading zkey file`);let{fd:s,sections:c}=await H(e,`zkey`,2,1<<25,1<<23),l=await Fa(s,c,void 0,r);if(l.protocol!=`plonk`)throw Error(`zkey file is not plonk`);if(!V.eq(l.r,o.q))throw Error(`Curve of the witness does not match the curve of the proving key`);if(o.nWitness!=l.nVars-l.nAdditions)throw Error(`Invalid witness length. Circuit: ${l.nVars}, witness: ${o.nWitness}, ${l.nAdditions}`);let u=l.curve,d=u.Fr,f=u.Fr.n8,p=l.domainSize*f;n&&(n.debug(`----------------------------`),n.debug(` PLONK PROVE SETTINGS`),n.debug(` Curve: ${u.name}`),n.debug(` Circuit power: ${l.power}`),n.debug(` Domain size: ${l.domainSize}`),n.debug(` Vars: ${l.nVars}`),n.debug(` Public vars: ${l.nPublic}`),n.debug(` Constraints: ${l.nConstraints}`),n.debug(` Additions: ${l.nAdditions}`),n.debug(`----------------------------`)),n&&n.debug(`> Reading witness file data`);let m=await J(i,a,2);m.set(d.zero,0);let h=new B(f*l.nAdditions),g={},_={},v={},y={},b=new Qc(u,n),x=new vl(u);n&&n.debug(`> Reading Section 3. Additions`),await T(),n&&n.debug(`> Reading Section 12. Sigma1, Sigma2 & Sigma 3`),n&&n.debug(`··· Reading Sigma polynomials `),_.Sigma1=new Q(new B(p),u,n),_.Sigma2=new Q(new B(p),u,n),_.Sigma3=new Q(new B(p),u,n),await s.readToBuffer(_.Sigma1.coef,0,p,c[12][0].p),await s.readToBuffer(_.Sigma2.coef,0,p,c[12][0].p+5*p),await s.readToBuffer(_.Sigma3.coef,0,p,c[12][0].p+10*p),n&&n.debug(`··· Reading Sigma evaluations`),v.Sigma1=new $(new B(p*4),u,n),v.Sigma2=new $(new B(p*4),u,n),v.Sigma3=new $(new B(p*4),u,n),await s.readToBuffer(v.Sigma1.eval,0,p*4,c[12][0].p+p),await s.readToBuffer(v.Sigma2.eval,0,p*4,c[12][0].p+6*p),await s.readToBuffer(v.Sigma3.eval,0,p*4,c[12][0].p+11*p),n&&n.debug(`> Reading Section 14. Powers of Tau`);let S=await J(s,c,14),C=[];for(let e=1;e<=l.nPublic;e++){let t=m.slice(e*d.n8,e*d.n8+d.n8);C.push(V.fromRprLE(t))}n&&n.debug(``),n&&n.debug(`> ROUND 1`),await O(),n&&n.debug(`> ROUND 2`),await A(),n&&n.debug(`> ROUND 3`),await M(),n&&n.debug(`> ROUND 4`),await P(),n&&n.debug(`> ROUND 5`),await F(),await s.close(),await i.close();let w=b.toObjectProof(!1);return w.protocol=`plonk`,w.curve=u.name,n&&n.debug(`PLONK PROVER FINISHED`),{proof:bl(w),publicSignals:bl(C)};async function T(){n&&n.debug(`··· Computing additions`);let e=await J(s,c,3),t=8+f*2;for(let r=0;r Computing A, B, C wire polynomials`),await k(),n&&n.debug(`> Computing A, B, C MSM`);let e=await _.A.multiExponentiation(S,`A`),t=await _.B.multiExponentiation(S,`B`),r=await _.C.multiExponentiation(S,`C`);return b.addPolynomial(`A`,e),b.addPolynomial(`B`,t),b.addPolynomial(`C`,r),0}async function k(){n&&n.debug(`··· Reading data from zkey file`),g.A=new B(p),g.B=new B(p),g.C=new B(p);let e=await J(s,c,4),t=await J(s,c,5),r=await J(s,c,6);for(let n=0;n=l.domainSize+2)throw Error(`A Polynomial is not well calculated`);if(_.B.degree()>=l.domainSize+2)throw Error(`B Polynomial is not well calculated`);if(_.C.degree()>=l.domainSize+2)throw Error(`C Polynomial is not well calculated`)}async function A(){n&&n.debug(`> Computing challenges beta and gamma`),x.reset(),x.addPolCommitment(l.Qm),x.addPolCommitment(l.Ql),x.addPolCommitment(l.Qr),x.addPolCommitment(l.Qo),x.addPolCommitment(l.Qc),x.addPolCommitment(l.S1),x.addPolCommitment(l.S2),x.addPolCommitment(l.S3);for(let e=0;e Computing Z polynomial`),await j(),n&&n.debug(`> Computing Z MSM`);let e=await _.Z.multiExponentiation(S,`Z`);b.addPolynomial(`Z`,e)}async function j(){n&&n.debug(`··· Computing Z evaluations`);let e=new B(p),t=new B(p);e.set(d.one,0),t.set(d.one,0);let r=d.one;for(let n=0;n=l.domainSize+3)throw Error(`Z Polynomial is not well calculated`);delete g.Z}async function M(){n&&n.debug(`> Computing challenge alpha`),x.reset(),x.addScalar(y.beta),x.addScalar(y.gamma),x.addPolCommitment(b.getPolynomial(`Z`)),y.alpha=x.getChallenge(),y.alpha2=d.square(y.alpha),n&&n.debug(`··· challenges.alpha: `+d.toString(y.alpha,16)),n&&n.debug(`> Computing T polynomial`),await N(),n&&n.debug(`> Computing T MSM`);let e=await _.T1.multiExponentiation(S,`T1`),t=await _.T2.multiExponentiation(S,`T2`),r=await _.T3.multiExponentiation(S,`T3`);b.addPolynomial(`T1`,e),b.addPolynomial(`T2`,t),b.addPolynomial(`T3`,r)}async function N(){n&&n.debug(`··· Reading sections 8, 9, 7, 10, 11. Q selectors`),v.QL=new $(new B(p*4),u,n),v.QR=new $(new B(p*4),u,n),v.QM=new $(new B(p*4),u,n),v.QO=new $(new B(p*4),u,n),v.QC=new $(new B(p*4),u,n),await s.readToBuffer(v.QL.eval,0,p*4,c[8][0].p+p),await s.readToBuffer(v.QR.eval,0,p*4,c[9][0].p+p),await s.readToBuffer(v.QM.eval,0,p*4,c[7][0].p+p),await s.readToBuffer(v.QO.eval,0,p*4,c[10][0].p+p),await s.readToBuffer(v.QC.eval,0,p*4,c[11][0].p+p),v.Lagrange=new $(new B(p*4*l.nPublic),u,n);for(let e=0;e=l.domainSize*3+6)throw Error(`T Polynomial is not well calculated`);n&&n.debug(`··· Computing T1, T2, T3 polynomials`),_.T1=new Q(new B((l.domainSize+1)*f),u,n),_.T2=new Q(new B((l.domainSize+1)*f),u,n),_.T3=new Q(new B((l.domainSize+6)*f),u,n),_.T1.coef.set(_.T.coef.slice(0,p),0),_.T2.coef.set(_.T.coef.slice(p,p*2),0),_.T3.coef.set(_.T.coef.slice(p*2,p*3+6*f),0),_.T1.setCoef(l.domainSize,y.b[10]);let t=d.sub(_.T2.getCoef(0),y.b[10]);_.T2.setCoef(0,t),_.T2.setCoef(l.domainSize,y.b[11]);let r=d.sub(_.T3.getCoef(0),y.b[11]);_.T3.setCoef(0,r)}async function P(){n&&n.debug(`> Computing challenge xi`),x.reset(),x.addScalar(y.alpha),x.addPolCommitment(b.getPolynomial(`T1`)),x.addPolCommitment(b.getPolynomial(`T2`)),x.addPolCommitment(b.getPolynomial(`T3`)),y.xi=x.getChallenge(),y.xiw=d.mul(y.xi,d.w[l.power]),n&&n.debug(`··· challenges.xi: `+d.toString(y.xi,16)),b.addEvaluation(`eval_a`,_.A.evaluate(y.xi)),b.addEvaluation(`eval_b`,_.B.evaluate(y.xi)),b.addEvaluation(`eval_c`,_.C.evaluate(y.xi)),b.addEvaluation(`eval_s1`,_.Sigma1.evaluate(y.xi)),b.addEvaluation(`eval_s2`,_.Sigma2.evaluate(y.xi)),b.addEvaluation(`eval_zw`,_.Z.evaluate(y.xiw))}async function F(){n&&n.debug(`> Computing challenge v`),x.reset(),x.addScalar(y.xi),x.addScalar(b.getEvaluation(`eval_a`)),x.addScalar(b.getEvaluation(`eval_b`)),x.addScalar(b.getEvaluation(`eval_c`)),x.addScalar(b.getEvaluation(`eval_s1`)),x.addScalar(b.getEvaluation(`eval_s2`)),x.addScalar(b.getEvaluation(`eval_zw`)),y.v=[],y.v[1]=x.getChallenge(),n&&n.debug(`··· challenges.v: `+d.toString(y.v[1],16));for(let e=2;e<6;e++)y.v[e]=d.mul(y.v[e-1],y.v[1]);n&&n.debug(`> Computing linearisation polynomial R(X)`),await I(),n&&n.debug(`> Computing opening proof polynomial Wxi(X) polynomial`),L(),n&&n.debug(`> Computing opening proof polynomial Wxiw(X) polynomial`),ee(),n&&n.debug(`> Computing Wxi, Wxiw MSM`);let e=await _.Wxi.multiExponentiation(S,`Wxi`),t=await _.Wxiw.multiExponentiation(S,`Wxiw`);b.addPolynomial(`Wxi`,e),b.addPolynomial(`Wxiw`,t)}async function I(){let e=u.Fr;_.QL=new Q(new B(p),u,n),_.QR=new Q(new B(p),u,n),_.QM=new Q(new B(p),u,n),_.QO=new Q(new B(p),u,n),_.QC=new Q(new B(p),u,n),await s.readToBuffer(_.QL.coef,0,p,c[8][0].p),await s.readToBuffer(_.QR.coef,0,p,c[9][0].p),await s.readToBuffer(_.QM.coef,0,p,c[7][0].p),await s.readToBuffer(_.QO.coef,0,p,c[10][0].p),await s.readToBuffer(_.QC.coef,0,p,c[11][0].p),y.xin=y.xi;for(let t=0;tUl,fullProve:()=>Cl,prove:()=>xl,setup:()=>Zc,verify:()=>Tl});function Gl(e,t){return[e,0,0,t.one,t.zero,t.zero,t.zero,t.zero]}function Kl(e,t,n,r,i,a,o,s){return[e,t,n,r,i,a,o,s]}function ql(e,t,n,r,i,a,o,s,c){return[e,t,n,r,i,a,o,s]}var Jl=0,Yl=1,Xl=2,Zl=class{constructor(e,t,n,r,i){this.Fr=e,this.logger=i,this.fnGetAdditionConstraint=n,this.fnGetMultiplicationConstraint=r}processR1csConstraint(e,t,n,r){this.normalizeLinearCombination(t),this.normalizeLinearCombination(n),this.normalizeLinearCombination(r);let i=this.getLinearCombinationType(t),a=this.getLinearCombinationType(n);if(i===Jl||a===Jl)return this.processR1csAdditionConstraint(e,r);if(i===Yl){let i=this.joinLinearCombinations(n,r,t[0]);return this.processR1csAdditionConstraint(e,i)}else if(a===Yl){let i=this.joinLinearCombinations(t,r,n[0]);return this.processR1csAdditionConstraint(e,i)}else return this.processR1csMultiplicationConstraint(e,t,n,r)}getLinearCombinationType(e){let t=this.Fr.zero,n=0,r=Object.keys(e);for(let i=0;i0?Xl:this.Fr.isZero(t)?Jl:Yl}normalizeLinearCombination(e){let t=Object.keys(e);for(let n=0;ni;){let r=o.shift(),i=o.shift(),a=e.nVars++,s=this.fnGetAdditionConstraint(r[0],i[0],a,this.Fr.neg(r[1]),this.Fr.neg(i[1]),this.Fr.zero,this.Fr.one,this.Fr.zero);t.push(s),n.push([r[0],i[0],r[1],i[1]]),o.push([a,this.Fr.one])}for(let e=0;ethis.n-1)throw Error(`CPolynomial:addPolynomial, cannot add a polynomial to a position greater than n-1`);this.polynomials[e]=t}degree(){let e=this.polynomials.map((e,t)=>e===void 0?0:e.degree()*this.n+t);return Math.max(...e)}getPolynomial(){let e=this.polynomials.map(e=>e===void 0?0:e.degree()),t=this.degree(),n=2**(ma(t-1)+1),r=this.Fr.n8,i=new Q(new B(n*r),this.curve,this.logger);for(let n=0;n Reading PTau file`);let{fd:i,sections:a}=await H(t,`ptau`,1,1<<22,1<<24);if(!a[12])throw Error(`Powers of Tau is not well prepared. Section 12 missing.`);r&&r.info(`> Getting curve from PTau settings`);let{curve:o}=await $o(i,a);r&&r.info(`> Reading r1cs file`);let{fd:s,sections:c}=await H(e,`r1cs`,1,1<<22,1<<24),l=await Ps(s,c,{loadConstraints:!1,loadCustomGates:!0});if(l.prime!==o.r)throw Error(`r1cs curve does not match powers of tau ceremony curve`);let u=o.Fr,d=o.Fr.n8,f=o.G1.F.n8*2,p=o.G2.F.n8*2,m={},h={},g,_={nVars:l.nVars,nPublic:l.nOutputs+l.nPubInputs},v=new Qs,y=new Qs;if(r&&r.info(`> Processing FFlonk constraints`),await E(o.Fr,l,r),globalThis.gc&&globalThis.gc(),_.cirPower=Math.max(3,ma(v.length+2-1)+1),_.domainSize=2**_.cirPower,a[2][0].size<(_.domainSize*9+18)*f)throw Error(`Powers of Tau is not big enough for this circuit size. Section 2 too small.`);if(a[3][0].size computing k1 and k2`);let[b,x]=ee();r&&r.info(`> computing w3`);let S=R();r&&r.info(`> computing w4`);let C=te();r&&r.info(`> computing w8`);let w=ne();r&&r.info(`> computing wr`);let T=re(_.cirPower,o.Fr);return await D(),await s.close(),await i.close(),r&&r.info(`FFLONK SETUP FINISHED`),0;async function E(e,t,n){for(let t=0;t<_.nPublic;t++)v.push(Gl(t+1,e));let r=new Zl(e,Gl,Kl,ql,n),i=await J(s,c,2),a=0;for(let e=0;e Writing the zkey file`);let e=await hi(n,`zkey`,1,17,1<<22,1<<24);r&&r.info(`··· Writing Section 1. Zkey Header`),await O(e),r&&r.info(`··· Writing Section 3. Additions`),await k(e),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 4. A Map`),await A(e,4,0,`A map`),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 5. B Map`),await A(e,5,1,`B map`),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 6. C Map`),await A(e,6,2,`C map`),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 7. QL`),await j(e,7,3,`QL`),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 8. QR`),await j(e,8,4,`QR`),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 9. QM`),await j(e,9,5,`QM`),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 10. QO`),await j(e,10,6,`QO`),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 11. QC`),await j(e,11,7,`QC`),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Sections 12,13,14. Sigma1, Sigma2 & Sigma 3`),await M(e),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 15. Lagrange Polynomials`),await N(e),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 16. Powers of Tau`),await P(e),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 17. C0`),await F(e),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 2. FFlonk Header`),await I(e),globalThis.gc&&globalThis.gc(),r&&r.info(`> Writing the zkey file finished`),await e.close()}async function O(e){await U(e,1),await e.writeULE32(10),await W(e)}async function k(e){await U(e,3);let t=new Uint8Array(8+2*d),n=new DataView(t.buffer);for(let i=0;i=8*_.domainSize)throw Error(`C0 Polynomial is not well calculated`);await U(e,17),await e.write(m.C0.coef),await W(e)}async function I(e){await U(e,2);let t=o.q,n=(Math.floor((V.bitLength(t)-1)/64)+1)*8;await e.writeULE32(n),await gi(e,t,n);let r=o.r,s=(Math.floor((V.bitLength(r)-1)/64)+1)*8;await e.writeULE32(s),await gi(e,r,s),await e.writeULE32(_.nVars),await e.writeULE32(_.nPublic),await e.writeULE32(_.domainSize),await e.writeULE32(y.length),await e.writeULE32(v.length),await e.write(b),await e.write(x),await e.write(S),await e.write(C),await e.write(w),await e.write(T);let c;c=await i.read(p,a[3][0].p+p),await e.write(c);let l=await m.C0.multiExponentiation(g,`C0`);await e.write(l),await W(e)}async function L(e,t){let[n,r]=await Q.to4T(t,_.domainSize,[],u);return await e.write(n),await e.write(r),[n,r]}function ee(){let e=u.two;for(;n(e,[],_.cirPower);)u.add(e,u.one);let t=u.add(e,u.one);for(;n(t,[e],_.cirPower);)u.add(t,u.one);return[e,t];function n(e,t,n){let r=2**n,i=u.one;for(let a=0;a Reading witness file`);let{fd:i,sections:a}=await H(t,`wtns`,2,1<<25,1<<23),o=await Ya(i,a);n&&n.info(`> Reading zkey file`);let{fd:s,sections:c}=await H(e,`zkey`,2,1<<25,1<<23),l=await Fa(s,c,void 0,r);if(l.protocolId!==10)throw Error(`zkey file is not fflonk`);if(!V.eq(l.r,o.q))throw Error(`Curve of the witness does not match the curve of the proving key`);if(o.nWitness!==l.nVars-l.nAdditions)throw Error(`Invalid witness length. Circuit: ${l.nVars}, witness: ${o.nWitness}, ${l.nAdditions}`);let u=l.curve,d=u.Fr,f=u.Fr.n8,p=u.G1.F.n8*2,m=l.domainSize*f;n&&(n.info(`----------------------------`),n.info(` FFLONK PROVE SETTINGS`),n.info(` Curve: ${u.name}`),n.info(` Circuit power: ${l.power}`),n.info(` Domain size: ${l.domainSize}`),n.info(` Vars: ${l.nVars}`),n.info(` Public vars: ${l.nPublic}`),n.info(` Constraints: ${l.nConstraints}`),n.info(` Additions: ${l.nAdditions}`),n.info(`----------------------------`)),n&&n.info(`> Reading witness file data`);let h=await J(i,a,2);await i.close(),h.set(d.zero,0);let g=new B(l.nAdditions*f),_={},v={},y={},b={},x={},S={},C=new Qc(u,n);n&&n.info(`> Reading Section 3. Additions`),await D(),n&&n.info(`> Reading Sections 12,13,14. Sigma1, Sigma2 & Sigma 3`),n&&n.info(`··· Reading Sigma polynomials `),v.Sigma1=new Q(new B(m),u,n),v.Sigma2=new Q(new B(m),u,n),v.Sigma3=new Q(new B(m),u,n),await s.readToBuffer(v.Sigma1.coef,0,m,c[12][0].p),await s.readToBuffer(v.Sigma2.coef,0,m,c[13][0].p),await s.readToBuffer(v.Sigma3.coef,0,m,c[14][0].p),n&&n.info(`··· Reading Sigma evaluations`),y.Sigma1=new $(new B(m*4),u,n),y.Sigma2=new $(new B(m*4),u,n),y.Sigma3=new $(new B(m*4),u,n),await s.readToBuffer(y.Sigma1.eval,0,m*4,c[12][0].p+m),await s.readToBuffer(y.Sigma2.eval,0,m*4,c[13][0].p+m),await s.readToBuffer(y.Sigma3.eval,0,m*4,c[14][0].p+m),n&&n.info(`> Reading Section 16. Powers of Tau`);let w=new B(l.domainSize*16*p);await s.readToBuffer(w,0,(l.domainSize*9+18)*p,c[16][0].p),globalThis.gc&&globalThis.gc(),n&&n.info(``),n&&n.info(`> ROUND 1`),await A(),delete v.T0,delete y.QL,delete y.QR,delete y.QM,delete y.QO,delete y.QC,globalThis.gc&&globalThis.gc(),n&&n.info(`> ROUND 2`),await j(),delete _.A,delete _.B,delete _.C,delete y.A,delete y.B,delete y.C,delete y.Sigma1,delete y.Sigma2,delete y.Sigma3,delete y.lagrange1,delete y.Z,globalThis.gc&&globalThis.gc(),n&&n.info(`> ROUND 3`),await M(),delete v.A,delete v.B,delete v.C,delete v.Z,delete v.T1,delete v.T2,delete v.Sigma1,delete v.Sigma2,delete v.Sigma3,delete v.QL,delete v.QR,delete v.QM,delete v.QC,delete v.QO,globalThis.gc&&globalThis.gc(),n&&n.info(`> ROUND 4`),await N(),globalThis.gc&&globalThis.gc(),n&&n.info(`> ROUND 5`),await P(),delete v.C0,delete v.C1,delete v.C2,delete v.R1,delete v.R2,delete v.F,delete v.L,delete v.ZT,delete v.ZTS2,await s.close(),globalThis.gc&&globalThis.gc(),C.addEvaluation(`inv`,F());let T=C.toObjectProof();T.protocol=`fflonk`,T.curve=u.name;let E=[];for(let e=1;e<=l.nPublic;e++){let t=e*f,n=h.slice(t,t+f);E.push(V.fromRprLE(n))}return n&&n.info(`FFLONK PROVER FINISHED`),{proof:eu(T),publicSignals:eu(E)};async function D(){n&&n.info(`··· Computing additions`);let e=await J(s,c,3),t=8+f*2;for(let r=0;r Computing A, B, C wire polynomials`),await t(),n&&n.info(`> Computing T0 polynomial`),await r(),n&&n.info(`> Computing C1 polynomial`),await i(),n&&n.info(`> Computing C1 multi exponentiation`);let e=await v.C1.multiExponentiation(w,`C1`);return C.addPolynomial(`C1`,e),0;async function t(){n&&n.info(`··· Reading data from zkey file`),_.A=new B(m),_.B=new B(m),_.C=new B(m);let e=await J(s,c,4),t=await J(s,c,5),r=await J(s,c,6);for(let n=0;n=l.domainSize)throw Error(`A Polynomial is not well calculated`);if(v.B.degree()>=l.domainSize)throw Error(`B Polynomial is not well calculated`);if(v.C.degree()>=l.domainSize)throw Error(`C Polynomial is not well calculated`)}async function r(){n&&n.info(`··· Reading sections 7, 8, 9, 10, 11. Q selectors`),y.QL=new $(new B(m*4),u,n),y.QR=new $(new B(m*4),u,n),y.QM=new $(new B(m*4),u,n),y.QO=new $(new B(m*4),u,n),y.QC=new $(new B(m*4),u,n),await s.readToBuffer(y.QL.eval,0,m*4,c[7][0].p+m),await s.readToBuffer(y.QR.eval,0,m*4,c[8][0].p+m),await s.readToBuffer(y.QM.eval,0,m*4,c[9][0].p+m),await s.readToBuffer(y.QO.eval,0,m*4,c[10][0].p+m),await s.readToBuffer(y.QC.eval,0,m*4,c[11][0].p+m),y.lagrange1=new $(await J(s,c,15),u,n),_.T0=new B(m*4),n&&n.info(`··· Computing T0 evaluations`);for(let e=0;e=2*l.domainSize-2)throw Error(`T0 Polynomial is not well calculated (degree is ${v.T0.degree()} and must be less than ${2*l.domainSize+2}`);delete _.T0}async function i(){let e=new Ql(4,u,n);if(e.addPolynomial(0,v.A),e.addPolynomial(1,v.B),e.addPolynomial(2,v.C),e.addPolynomial(3,v.T0),v.C1=e.getPolynomial(),v.C1.degree()>=8*l.domainSize-8)throw Error(`C1 Polynomial is not well calculated`)}}async function j(){n&&n.info(`> Computing challenges beta and gamma`);let e=new vl(u);e.addPolCommitment(l.C0);for(let t=0;t Computing Z polynomial`),await r(),n&&n.info(`> Computing T1 polynomial`),await i(),n&&n.info(`> Computing T2 polynomial`),await a(),n&&n.info(`> Computing C2 polynomial`),await o(),n&&n.info(`> Computing C2 multi exponentiation`);let t=await v.C2.multiExponentiation(w,`C2`);return C.addPolynomial(`C2`,t),0;async function r(){n&&n.info(`··· Computing Z evaluations`);let e=new B(m),t=new B(m);e.set(d.one,0),t.set(d.one,0);let r=d.one;for(let i=0;i=l.domainSize+3)throw Error(`Z Polynomial is not well calculated`);delete _.Z}async function i(){n&&n.info(`··· Computing T1 evaluations`),_.T1=new B(m*2),_.T1z=new B(m*2);let e=d.one;for(let t=0;t=l.domainSize+2)throw Error(`T1 Polynomial is not well calculated`);delete _.T1,delete _.T1z,delete v.T1z}async function a(){n&&n.info(`··· Computing T2 evaluations`),_.T2=new B(m*4),_.T2z=new B(m*4);let e=d.one;for(let t=0;t=3*l.domainSize)throw Error(`T2 Polynomial is not well calculated`);delete _.T2,delete _.T2z,delete v.T2z}async function o(){let e=new Ql(3,u,n);if(e.addPolynomial(0,v.Z),e.addPolynomial(1,v.T1),e.addPolynomial(2,v.T2),v.C2=e.getPolynomial(),v.C2.degree()>=9*l.domainSize)throw Error(`C2 Polynomial is not well calculated`)}}async function M(){n&&n.info(`> Computing challenge xi`);let e=new vl(u);e.addScalar(x.gamma),e.addPolCommitment(C.getPolynomial(`C2`)),x.xiSeed=e.getChallenge();let t=d.square(x.xiSeed);S.w8=[],S.w8[0]=d.one;for(let e=1;e<8;e++)S.w8[e]=d.mul(S.w8[e-1],l.w8);S.w4=[],S.w4[0]=d.one;for(let e=1;e<4;e++)S.w4[e]=d.mul(S.w4[e-1],l.w4);S.w3=[],S.w3[0]=d.one,S.w3[1]=l.w3,S.w3[2]=d.square(l.w3),S.S0={},S.S0.h0w8=[],S.S0.h0w8[0]=d.mul(t,x.xiSeed);for(let e=1;e<8;e++)S.S0.h0w8[e]=d.mul(S.S0.h0w8[0],S.w8[e]);S.S1={},S.S1.h1w4=[],S.S1.h1w4[0]=d.square(S.S0.h0w8[0]);for(let e=1;e<4;e++)S.S1.h1w4[e]=d.mul(S.S1.h1w4[0],S.w4[e]);S.S2={},S.S2.h2w3=[],S.S2.h2w3[0]=d.mul(S.S1.h1w4[0],t),S.S2.h2w3[1]=d.mul(S.S2.h2w3[0],S.w3[1]),S.S2.h2w3[2]=d.mul(S.S2.h2w3[0],S.w3[2]),S.S2.h3w3=[],S.S2.h3w3[0]=d.mul(S.S2.h2w3[0],l.wr),S.S2.h3w3[1]=d.mul(S.S2.h3w3[0],S.w3[1]),S.S2.h3w3[2]=d.mul(S.S2.h3w3[0],S.w3[2]),x.xi=d.mul(d.square(S.S2.h2w3[0]),S.S2.h2w3[0]),n&&n.info(`··· challenges.xi: `+d.toString(x.xi)),v.QL=new Q(new B(m),u,n),v.QR=new Q(new B(m),u,n),v.QM=new Q(new B(m),u,n),v.QO=new Q(new B(m),u,n),v.QC=new Q(new B(m),u,n),await s.readToBuffer(v.QL.coef,0,m,c[7][0].p),await s.readToBuffer(v.QR.coef,0,m,c[8][0].p),await s.readToBuffer(v.QM.coef,0,m,c[9][0].p),await s.readToBuffer(v.QO.coef,0,m,c[10][0].p),await s.readToBuffer(v.QC.coef,0,m,c[11][0].p),n&&n.info(`··· Computing evaluations`),C.addEvaluation(`ql`,v.QL.evaluate(x.xi)),C.addEvaluation(`qr`,v.QR.evaluate(x.xi)),C.addEvaluation(`qm`,v.QM.evaluate(x.xi)),C.addEvaluation(`qo`,v.QO.evaluate(x.xi)),C.addEvaluation(`qc`,v.QC.evaluate(x.xi)),C.addEvaluation(`s1`,v.Sigma1.evaluate(x.xi)),C.addEvaluation(`s2`,v.Sigma2.evaluate(x.xi)),C.addEvaluation(`s3`,v.Sigma3.evaluate(x.xi)),C.addEvaluation(`a`,v.A.evaluate(x.xi)),C.addEvaluation(`b`,v.B.evaluate(x.xi)),C.addEvaluation(`c`,v.C.evaluate(x.xi)),C.addEvaluation(`z`,v.Z.evaluate(x.xi)),x.xiw=d.mul(x.xi,d.w[l.power]),C.addEvaluation(`zw`,v.Z.evaluate(x.xiw)),C.addEvaluation(`t1w`,v.T1.evaluate(x.xiw)),C.addEvaluation(`t2w`,v.T2.evaluate(x.xiw))}async function N(){n&&n.info(`> Computing challenge alpha`);let e=new vl(u);e.addScalar(x.xiSeed),e.addScalar(C.getEvaluation(`ql`)),e.addScalar(C.getEvaluation(`qr`)),e.addScalar(C.getEvaluation(`qm`)),e.addScalar(C.getEvaluation(`qo`)),e.addScalar(C.getEvaluation(`qc`)),e.addScalar(C.getEvaluation(`s1`)),e.addScalar(C.getEvaluation(`s2`)),e.addScalar(C.getEvaluation(`s3`)),e.addScalar(C.getEvaluation(`a`)),e.addScalar(C.getEvaluation(`b`)),e.addScalar(C.getEvaluation(`c`)),e.addScalar(C.getEvaluation(`z`)),e.addScalar(C.getEvaluation(`zw`)),e.addScalar(C.getEvaluation(`t1w`)),e.addScalar(C.getEvaluation(`t2w`)),x.alpha=e.getChallenge(),n&&n.info(`··· challenges.alpha: `+d.toString(x.alpha)),n&&n.info(`> Reading C0 polynomial`),v.C0=new Q(new B(m*8),u,n),await s.readToBuffer(v.C0.coef,0,m*8,c[17][0].p),n&&n.info(`> Computing R0 polynomial`),r(),n&&n.info(`> Computing R1 polynomial`),i(),n&&n.info(`> Computing R2 polynomial`),a(),n&&n.info(`> Computing F polynomial`),await o(),n&&n.info(`> Computing W1 multi exponentiation`);let t=await v.F.multiExponentiation(w,`W1`);return C.addPolynomial(`W1`,t),0;function r(){if(v.R0=Q.lagrangePolynomialInterpolation([S.S0.h0w8[0],S.S0.h0w8[1],S.S0.h0w8[2],S.S0.h0w8[3],S.S0.h0w8[4],S.S0.h0w8[5],S.S0.h0w8[6],S.S0.h0w8[7]],[v.C0.evaluate(S.S0.h0w8[0]),v.C0.evaluate(S.S0.h0w8[1]),v.C0.evaluate(S.S0.h0w8[2]),v.C0.evaluate(S.S0.h0w8[3]),v.C0.evaluate(S.S0.h0w8[4]),v.C0.evaluate(S.S0.h0w8[5]),v.C0.evaluate(S.S0.h0w8[6]),v.C0.evaluate(S.S0.h0w8[7])],u),v.R0.degree()>7)throw Error(`R0 Polynomial is not well calculated`)}function i(){if(v.R1=Q.lagrangePolynomialInterpolation([S.S1.h1w4[0],S.S1.h1w4[1],S.S1.h1w4[2],S.S1.h1w4[3]],[v.C1.evaluate(S.S1.h1w4[0]),v.C1.evaluate(S.S1.h1w4[1]),v.C1.evaluate(S.S1.h1w4[2]),v.C1.evaluate(S.S1.h1w4[3])],u),v.R1.degree()>3)throw Error(`R1 Polynomial is not well calculated`)}function a(){if(v.R2=Q.lagrangePolynomialInterpolation([S.S2.h2w3[0],S.S2.h2w3[1],S.S2.h2w3[2],S.S2.h3w3[0],S.S2.h3w3[1],S.S2.h3w3[2]],[v.C2.evaluate(S.S2.h2w3[0]),v.C2.evaluate(S.S2.h2w3[1]),v.C2.evaluate(S.S2.h2w3[2]),v.C2.evaluate(S.S2.h3w3[0]),v.C2.evaluate(S.S2.h3w3[1]),v.C2.evaluate(S.S2.h3w3[2])],u),v.R2.degree()>5)throw Error(`R2 Polynomial is not well calculated`)}async function o(){n&&n.info(`··· Computing F polynomial`),v.F=Q.fromPolynomial(v.C0,u,n),v.F.sub(v.R0),v.F.divByZerofier(8,x.xi);let e=Q.fromPolynomial(v.C1,u,n);e.sub(v.R1),e.mulScalar(x.alpha),e.divByZerofier(4,x.xi);let t=Q.fromPolynomial(v.C2,u,n);if(t.sub(v.R2),t.mulScalar(d.square(x.alpha)),t.divByZerofier(3,x.xi),t.divByZerofier(3,x.xiw),v.F.add(e),v.F.add(t),v.F.degree()>=9*l.domainSize-6)throw Error(`F Polynomial is not well calculated`)}}async function P(){n&&n.info(`> Computing challenge y`);let e=new vl(u);e.addScalar(x.alpha),e.addPolCommitment(C.getPolynomial(`W1`)),x.y=e.getChallenge(),n&&n.info(`··· challenges.y: `+d.toString(x.y)),n&&n.info(`> Computing L polynomial`),await o(),n&&n.info(`> Computing ZTS2 polynomial`),await c();let t=v.ZTS2.evaluate(x.y);t=d.inv(t),v.L.mulScalar(t);let r=Q.fromCoefficientsArray([d.neg(x.y),d.one],u);n&&n.info(`> Computing W' = L / ZTS2 polynomial`);let i=v.L.divBy(r);if(i.degree()>0)throw Error(`Degree of L(X)/(ZTS2(y)(X-y)) remainder is ${i.degree()} and should be 0`);if(v.L.degree()>=9*l.domainSize-1)throw Error(`Degree of L(X)/(ZTS2(y)(X-y)) is not correct`);n&&n.info(`> Computing W' multi exponentiation`);let a=await v.L.multiExponentiation(w,`W2`);return C.addPolynomial(`W2`,a),0;async function o(){n&&n.info(`··· Computing L polynomial`);let e=v.R0.evaluate(x.y),t=v.R1.evaluate(x.y),r=v.R2.evaluate(x.y),i=d.sub(x.y,S.S0.h0w8[0]);for(let e=1;e<8;e++)i=d.mul(i,d.sub(x.y,S.S0.h0w8[e]));let a=d.sub(x.y,S.S1.h1w4[0]);for(let e=1;e<4;e++)a=d.mul(a,d.sub(x.y,S.S1.h1w4[e]));let o=d.sub(x.y,S.S2.h2w3[0]);for(let e=1;e<3;e++)o=d.mul(o,d.sub(x.y,S.S2.h2w3[e]));for(let e=0;e<3;e++)o=d.mul(o,d.sub(x.y,S.S2.h3w3[e]));let c=d.mul(a,o),f=d.mul(x.alpha,d.mul(i,o)),p=d.mul(d.square(x.alpha),d.mul(i,a));b.denH1=a,b.denH2=o,v.L=Q.fromPolynomial(v.C0,u,n),v.L.subScalar(e),v.L.mulScalar(c);let m=Q.fromPolynomial(v.C1,u,n);m.subScalar(t),m.mulScalar(f);let h=Q.fromPolynomial(v.C2,u,n);h.subScalar(r),h.mulScalar(p),v.L.add(m),v.L.add(h),n&&n.info(`> Computing ZT polynomial`),await s();let g=v.ZT.evaluate(x.y);if(v.F.mulScalar(g),v.L.sub(v.F),v.L.degree()>=9*l.domainSize)throw Error(`L Polynomial is not well calculated`);delete _.L}async function s(){v.ZT=Q.zerofierPolynomial([S.S0.h0w8[0],S.S0.h0w8[1],S.S0.h0w8[2],S.S0.h0w8[3],S.S0.h0w8[4],S.S0.h0w8[5],S.S0.h0w8[6],S.S0.h0w8[7],S.S1.h1w4[0],S.S1.h1w4[1],S.S1.h1w4[2],S.S1.h1w4[3],S.S2.h2w3[0],S.S2.h2w3[1],S.S2.h2w3[2],S.S2.h3w3[0],S.S2.h3w3[1],S.S2.h3w3[2]],u)}async function c(){v.ZTS2=Q.zerofierPolynomial([S.S1.h1w4[0],S.S1.h1w4[1],S.S1.h1w4[2],S.S1.h1w4[3],S.S2.h2w3[0],S.S2.h2w3[1],S.S2.h2w3[2],S.S2.h3w3[0],S.S2.h3w3[1],S.S2.h3w3[2]],u)}}function F(){let e=x.xi;for(let t=0;t Checking commitments belong to G1`),!su(i,o,a))return r&&r.error(`Proof commitments are not valid`),!1;if(r&&r.info(`> Checking evaluations belong to F`),!uu(i,o))return r&&r.error(`Proof evaluations are not valid.`),!1;if(r&&r.info(`> Checking public inputs belong to F`),!du(i,s))return r&&r.error(`Public inputs are not valid.`),!1;r&&r.info(`> Computing challenges`);let{challenges:l,roots:u}=fu(i,o,a,s,r);r&&r.info(`> Computing Zero polynomial evaluation Z_H(xi)`),l.zh=c.sub(l.xiN,c.one),l.invzh=c.inv(l.zh),r&&r.info(`> Computing Lagrange evaluations`);let d=await pu(i,l,a);r&&r.info(`> Computing polynomial identities PI(X)`);let f=mu(i,s,d);r&&r.info(`> Computing r0(y)`);let p=hu(o,l,u,i,r);r&&r.info(`> Computing r1(y)`);let m=gu(o,l,u,f,i,r);r&&r.info(`> Computing r2(y)`);let h=_u(o,l,u,d[1],a,i,r);r&&r.info(`> Computing F`);let g=vu(i,o,a,l,u);r&&r.info(`> Computing E`);let _=yu(i,o,l,a,p,m,h);r&&r.info(`> Computing J`);let v=bu(i,o,l);r&&r.info(`> Validate all evaluations with a pairing`);let y=await xu(i,o,l,a,g,_,v);return r&&(y?r.info(`PROOF VERIFIED SUCCESSFULLY`):r.warn(`Invalid Proof`)),r&&r.info(`FFLONK VERIFIER FINISHED`),y}function ou(e,t){let n=t;return n.k1=e.Fr.fromObject(t.k1),n.k2=e.Fr.fromObject(t.k2),n.w=e.Fr.fromObject(t.w),n.w3=e.Fr.fromObject(t.w3),n.w4=e.Fr.fromObject(t.w4),n.w8=e.Fr.fromObject(t.w8),n.wr=e.Fr.fromObject(t.wr),n.X_2=e.G2.fromObject(t.X_2),n.C0=e.G1.fromObject(t.C0),n}function su(e,t,n){let r=e.G1;return r.isValid(t.polynomials.C1)&&r.isValid(t.polynomials.C2)&&r.isValid(t.polynomials.W1)&&r.isValid(t.polynomials.W2)&&r.isValid(n.C0)}function cu(e,t){return V.geq(t,0)&&V.lt(t,e.r)}function lu(e,t){return cu(e,V.fromRprLE(t))}function uu(e,t){return lu(e,t.evaluations.ql)&&lu(e,t.evaluations.qr)&&lu(e,t.evaluations.qm)&&lu(e,t.evaluations.qo)&&lu(e,t.evaluations.qc)&&lu(e,t.evaluations.s1)&&lu(e,t.evaluations.s2)&&lu(e,t.evaluations.s3)&&lu(e,t.evaluations.a)&&lu(e,t.evaluations.b)&&lu(e,t.evaluations.c)&&lu(e,t.evaluations.z)&&lu(e,t.evaluations.zw)&&lu(e,t.evaluations.t1w)&&lu(e,t.evaluations.t2w)}function du(e,t){for(let n=0;nEu,exportSolidityVerifier:()=>Jc,fullProve:()=>ru,prove:()=>tu,setup:()=>$l,verify:()=>au});return Object.defineProperty(e,`curves`,{enumerable:!0,get:function(){return yi}}),Object.defineProperty(e,`fflonk`,{enumerable:!0,get:function(){return Du}}),Object.defineProperty(e,`groth16`,{enumerable:!0,get:function(){return qo}}),Object.defineProperty(e,`plonk`,{enumerable:!0,get:function(){return Wl}}),Object.defineProperty(e,`powersOfTau`,{enumerable:!0,get:function(){return Ts}}),Object.defineProperty(e,`r1cs`,{enumerable:!0,get:function(){return Hs}}),Object.defineProperty(e,`wtns`,{enumerable:!0,get:function(){return Js}}),Object.defineProperty(e,`zKey`,{enumerable:!0,get:function(){return Xc}}),e})({}); \ No newline at end of file diff --git a/cli.js b/cli.js index 322e0edc..cc89329e 100755 --- a/cli.js +++ b/cli.js @@ -17,7 +17,7 @@ along with snarkJS. If not, see . */ -/* eslint-disable no-console */ + import fs from "fs"; import url from "url"; diff --git a/config/rollup.browser.esm.config.js b/config/rollup.browser.esm.config.js deleted file mode 100644 index 70597a7e..00000000 --- a/config/rollup.browser.esm.config.js +++ /dev/null @@ -1,53 +0,0 @@ -import { nodeResolve } from "@rollup/plugin-node-resolve"; -import commonJS from "@rollup/plugin-commonjs"; -import virtual from "@rollup/plugin-virtual"; -import replace from "@rollup/plugin-replace"; -// Needed by fastfile -import { O_TRUNC, O_CREAT, O_RDWR, O_EXCL, O_RDONLY } from "constants"; - -const empty = "export default {}"; -// We create a stub with these constants instead of including the entire constants definition -const constants = ` -export const O_TRUNC = ${O_TRUNC}; -export const O_CREAT = ${O_CREAT}; -export const O_RDWR = ${O_RDWR}; -export const O_EXCL = ${O_EXCL}; -export const O_RDONLY = ${O_RDONLY} -`; - -export default { - input: "main.js", - output: { - file: "build/browser.esm.js", - format: "es", - inlineDynamicImports: true, - }, - external: ["ffjavascript"], - plugins: [ - replace({ - // The current default is false, but they are changing it next version - preventAssignment: false, - "process.browser": true, - }), - virtual({ - fs: empty, - os: empty, - crypto: empty, - readline: empty, - ejs: empty, - events: empty, - stream: empty, - util: empty, - constants, - }), - nodeResolve({ - browser: true, - preferBuiltins: false, - exportConditions: ["module"], - }), - commonJS(), - ], - treeshake: { - preset: "smallest", - }, -}; diff --git a/config/rollup.cjs.config.js b/config/rollup.cjs.config.js deleted file mode 100644 index 17648c1d..00000000 --- a/config/rollup.cjs.config.js +++ /dev/null @@ -1,19 +0,0 @@ -import fs from "fs"; -import { builtinModules as builtin } from "module"; - -const pkg = JSON.parse(fs.readFileSync("./package.json")); - -export default { - input: "main.js", - output: { - file: "build/main.cjs", - format: "cjs", - }, - external: [ - "@noble/hashes/blake2b", - "@noble/hashes/utils", - "@noble/hashes/sha3", - ...Object.keys(pkg.dependencies), - ...builtin, - ] -}; diff --git a/config/rollup.cli.config.js b/config/rollup.cli.config.js deleted file mode 100644 index 54fe43db..00000000 --- a/config/rollup.cli.config.js +++ /dev/null @@ -1,20 +0,0 @@ -import fs from "fs"; -import { builtinModules as builtin } from "module"; - -const pkg = JSON.parse(fs.readFileSync("./package.json")); - -export default { - input: "cli.js", - output: { - file: "build/cli.cjs", - format: "cjs", - banner: "#!/usr/bin/node --expose-gc \n", - }, - external: [ - "@noble/hashes/blake2b", - "@noble/hashes/utils", - "@noble/hashes/sha3", - ...Object.keys(pkg.dependencies), - ...builtin, - ] -}; diff --git a/config/rollup.iife.config.js b/config/rollup.iife.config.js deleted file mode 100644 index 443b7eee..00000000 --- a/config/rollup.iife.config.js +++ /dev/null @@ -1,56 +0,0 @@ -import { nodeResolve } from "@rollup/plugin-node-resolve"; -import commonJS from "@rollup/plugin-commonjs"; -import virtual from "@rollup/plugin-virtual"; -import replace from "@rollup/plugin-replace"; -import visualizer from "rollup-plugin-visualizer"; -// Needed by fastfile -import { O_TRUNC, O_CREAT, O_RDWR, O_EXCL, O_RDONLY } from "constants"; - -const empty = "export default {}"; -// We create a stub with these constants instead of including the entire constants definition -const constants = ` -export const O_TRUNC = ${O_TRUNC}; -export const O_CREAT = ${O_CREAT}; -export const O_RDWR = ${O_RDWR}; -export const O_EXCL = ${O_EXCL}; -export const O_RDONLY = ${O_RDONLY} -`; - -export default { - input: "main.js", - output: { - file: "build/snarkjs.js", - format: "iife", - sourcemap: "inline", - globals: { - os: "null" - }, - name: "snarkjs", - inlineDynamicImports: true, - }, - plugins: [ - virtual({ - fs: empty, - os: empty, - crypto: empty, - readline: empty, - ejs: empty, - events: empty, - stream: empty, - util: empty, - constants: constants, - }), - nodeResolve({ - browser: true, - preferBuiltins: false, - exportConditions: ["browser", "default", "module", "require"] - }), - commonJS(), - replace({ - // The current default is false, but they are changing it next version - preventAssignment: false, - "process.browser": !!process.env.BROWSER - }), - visualizer(), - ] -}; diff --git a/config/rollup.iife_min.config.js b/config/rollup.iife_min.config.js deleted file mode 100644 index 0fa4cb4f..00000000 --- a/config/rollup.iife_min.config.js +++ /dev/null @@ -1,15 +0,0 @@ -import config from './rollup.iife.config'; -import { terser } from "rollup-plugin-terser"; - -export default { - ...config, - output: { - ...config.output, - file: "build/snarkjs.min.js", - sourcemap: false, - }, - plugins: [ - ...config.plugins, - terser(), - ] -}; diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 00000000..d7909d77 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,34 @@ +import js from "@eslint/js"; +import globals from "globals"; + +export default [ + { ignores: ["build/**", "templates/**", "credentialAtomicQueryV3OnChain/**", "test/circuit2/**", "smart_contract_tests/**", "scripts/**"] }, + js.configs.recommended, + { + languageOptions: { + ecmaVersion: "latest", + sourceType: "module", + globals: { + ...globals.node, + ...globals.browser, + describe: "readonly", + it: "readonly", + test: "readonly", + expect: "readonly", + beforeAll: "readonly", + afterAll: "readonly", + beforeEach: "readonly", + afterEach: "readonly", + vi: "readonly", + globalThis: "readonly", + }, + }, + rules: { + indent: ["error", 4], + "linebreak-style": ["warn", "unix"], + quotes: ["error", "double"], + semi: ["error", "always"], + "no-unused-vars": ["error", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_", "caughtErrorsIgnorePattern": "^_" }], + }, + }, +]; diff --git a/hardhat.config.js b/hardhat.config.js new file mode 100644 index 00000000..39b8a78b --- /dev/null +++ b/hardhat.config.js @@ -0,0 +1,26 @@ +import hardhatEthersPlugin from "@nomicfoundation/hardhat-ethers"; +import { defineConfig } from "hardhat/config"; +import path from "path"; +import { fileURLToPath } from "url"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +export default defineConfig({ + plugins: [hardhatEthersPlugin], + solidity: { + compilers: [ + { + // All snarkjs verifier templates target >=0.7.0 <0.9.0 + version: "0.8.24", + settings: { + optimizer: { enabled: true, runs: 999999 }, + }, + }, + ], + }, + paths: { + sources: path.resolve(__dirname, "contracts"), + cache: path.resolve(__dirname, "cache"), + artifacts: path.resolve(__dirname, "artifacts"), + }, +}); diff --git a/package-lock.json b/package-lock.json index e0bfbc99..0ff5167c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,1244 +9,2064 @@ "version": "0.7.5", "license": "GPL-3.0", "dependencies": { - "@iden3/binfileutils": "file:../binfileutils", - "@noble/hashes": "^1.7.1", - "bfj": "^9.1.2", + "@iden3/binfileutils": "https://github.com/iden3/binfileutils.git#feat/esm-migration", + "@noble/hashes": "^2.0.1", "circom_runtime": "0.1.28", - "ejs": "^3.1.6", - "fastfile": "0.0.20", - "ffjavascript": "file:../ffjavascript", + "ejs": "^5.0.1", + "fastfile": "https://github.com/iden3/fastfile.git#feat/esm-migration", + "ffjavascript": "https://github.com/iden3/ffjavascript.git#feat/esm-migration", "logplease": "^1.2.15", - "r1csfile": "file:../r1csfile" + "r1csfile": "https://github.com/iden3/r1csfile.git#feat/esm-migration" }, "bin": { "snarkjs": "build/cli.cjs" }, "devDependencies": { - "@rollup/plugin-commonjs": "^22.0.0", - "@rollup/plugin-json": "^4.1.0", - "@rollup/plugin-node-resolve": "^14.0.0", - "@rollup/plugin-replace": "^4.0.0", - "@rollup/plugin-virtual": "^2.0.3", - "eslint": "^8.7.0", - "mocha": "^10.2.0", - "rollup": "^2.36.2", - "rollup-plugin-terser": "^7.0.2", - "rollup-plugin-visualizer": "^5.6.0" - } - }, - "../binfileutils": { - "name": "@iden3/binfileutils", - "version": "0.0.12", - "license": "GPL-3.0", - "dependencies": { - "fastfile": "file:../fastfile", - "ffjavascript": "file:../ffjavascript" - }, - "devDependencies": { - "eslint": "^8.6.0", - "rollup": "^2.20.0" - } - }, - "../ffjavascript": { - "version": "0.3.1", - "license": "GPL-3.0", - "dependencies": { - "wasmbuilder": "0.0.16", - "wasmcurves": "file:../wasmcurves", - "web-worker": "1.5.0" - }, - "devDependencies": { - "@rollup/plugin-commonjs": "^25.0.4", - "@rollup/plugin-node-resolve": "^15.2.1", - "@rollup/plugin-replace": "^5.0.3", - "chai": "^5.1.1", - "eslint": "^9.12.0", - "mocha": "^10.7.3", - "rollup": "^3.29.4" - } - }, - "../r1csfile": { - "version": "0.0.48", - "license": "GPL-3.0", + "@eslint/js": "^10.0.1", + "@nomicfoundation/hardhat-ethers": "^4.0.7", + "@vitest/browser": "^4.1.2", + "@vitest/browser-playwright": "^4.1.2", + "bfj": "^9.1.3", + "eslint": "^10.1.0", + "ethers": "^6.13.5", + "globals": "^17.4.0", + "hardhat": "^3.3.0", + "playwright": "^1.59.0", + "rimraf": "^6.1.3", + "vite": "^8.0.3", + "vitest": "^4.1.2" + } + }, + "node_modules/@adraffy/ens-normalize": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@blazediff/core": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@blazediff/core/-/core-1.9.1.tgz", + "integrity": "sha512-ehg3jIkYKulZh+8om/O25vkvSsXXwC+skXmyA87FFx6A/45eqOkZsBltMw/TVteb0mloiGT8oGRTcjRAz66zaA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "@iden3/bigarray": "0.0.2", - "@iden3/binfileutils": "0.0.12", - "fastfile": "0.0.20", - "ffjavascript": "file:../ffjavascript" - }, - "devDependencies": { - "eslint": "^8.6.0", - "mocha": "^10.0.0", - "rollup": "^2.20.0" + "tslib": "^2.4.0" } }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", + "cpu": [ + "ppc64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "node_modules/@esbuild/android-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" - }, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/@esbuild/android-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=4" + "node": ">=18" } }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/@esbuild/android-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=4" + "node": ">=18" } }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "color-name": "1.1.3" + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", + "cpu": [ + "x64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=0.8.0" + "node": ">=18" } }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", + "cpu": [ + "arm64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=4" + "node": ">=18" } }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=4" + "node": ">=18" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "node_modules/@esbuild/linux-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", + "cpu": [ + "arm" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=4" + "node": ">=18" } }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", + "cpu": [ + "loong64" + ], "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=4" + "node": ">=18" } }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", + "cpu": [ + "mips64el" + ], "dev": true, - "dependencies": { - "color-name": "1.1.3" + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", + "cpu": [ + "ppc64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.8.0" + "node": ">=18" } }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", + "cpu": [ + "riscv64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=4" + "node": ">=18" } }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", + "cpu": [ + "s390x" + ], "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=4" + "node": ">=18" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "node_modules/@esbuild/linux-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=18" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", + "cpu": [ + "arm64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", + "cpu": [ + "x64" + ], "dev": true, - "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" - }, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=18" } }, - "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", + "cpu": [ + "arm64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=18" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=10.10.0" + "node": ">=18" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", + "cpu": [ + "arm64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "node": ">=18" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", - "dev": true - }, - "node_modules/@iden3/binfileutils": { - "resolved": "../binfileutils", - "link": true - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=6.0.0" + "node": ">=18" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", + "cpu": [ + "arm64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.0.0" + "node": ">=18" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", + "cpu": [ + "ia32" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.0.0" + "node": ">=18" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "node_modules/@esbuild/win32-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.21", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.21.tgz", - "integrity": "sha512-SRfKmRe1KvYnxjEMtxEr+J4HIeMX5YBg/qhRHpxEIGjhX1rshcHlnFUE9K0GazhVKWM7B+nARSkV8LuvJdJ5/g==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@noble/hashes": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", - "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", - "license": "MIT", + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": "^14.21.3 || >=16" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://opencollective.com/eslint" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, + "license": "MIT", "engines": { - "node": ">= 8" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@eslint/config-array": { + "version": "0.23.3", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.3.tgz", + "integrity": "sha512-j+eEWmB6YYLwcNOdlwQ6L2OsptI/LO6lNBuLIqe5R7RetD658HLoF+Mn7LzYmAWWNNzdC6cqP+L6r8ujeYXWLw==", "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^3.0.3", + "debug": "^4.3.1", + "minimatch": "^10.2.4" + }, "engines": { - "node": ">= 8" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@eslint/config-helpers": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.3.tgz", + "integrity": "sha512-lzGN0onllOZCGroKJmRwY6QcEHxbjBw1gwB8SgRSqK8YbbtEXMvKynsXc3553ckIEBxsbMBU7oOZXKIPGZNeZw==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "@eslint/core": "^1.1.1" }, "engines": { - "node": ">= 8" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@rollup/plugin-commonjs": { - "version": "22.0.2", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-22.0.2.tgz", - "integrity": "sha512-//NdP6iIwPbMTcazYsiBMbJW7gfmpHom33u1beiIoHDEM0Q9clvtQB1T0efvMqHeKsGohiHo97BCPCkBXdscwg==", + "node_modules/@eslint/core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.1.1.tgz", + "integrity": "sha512-QUPblTtE51/7/Zhfv8BDwO0qkkzQL7P/aWWbqcf4xWLEYn1oKjdO0gglQBB4GAsu7u6wjijbCmzsUTy6mnk6oQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@rollup/pluginutils": "^3.1.0", - "commondir": "^1.0.1", - "estree-walker": "^2.0.1", - "glob": "^7.1.6", - "is-reference": "^1.2.1", - "magic-string": "^0.25.7", - "resolve": "^1.17.0" + "@types/json-schema": "^7.0.15" }, "engines": { - "node": ">= 12.0.0" - }, - "peerDependencies": { - "rollup": "^2.68.0" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@rollup/plugin-json": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-4.1.0.tgz", - "integrity": "sha512-yfLbTdNS6amI/2OpmbiBoW12vngr5NW2jCJVZSBEz+H5KfUJZ2M7sDjk0U6GOOdCWFVScShte29o9NezJ53TPw==", + "node_modules/@eslint/js": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz", + "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==", "dev": true, - "dependencies": { - "@rollup/pluginutils": "^3.0.8" + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" }, "peerDependencies": { - "rollup": "^1.20.0 || ^2.0.0" + "eslint": "^10.0.0" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/@rollup/plugin-node-resolve": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-14.1.0.tgz", - "integrity": "sha512-5G2niJroNCz/1zqwXtk0t9+twOSDlG00k1Wfd7bkbbXmwg8H8dvgHdIWAun53Ps/rckfvOC7scDBjuGFg5OaWw==", + "node_modules/@eslint/object-schema": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.3.tgz", + "integrity": "sha512-iM869Pugn9Nsxbh/YHRqYiqd23AmIbxJOcpUMOuWCVNdoQJ5ZtwL6h3t0bcZzJUlC3Dq9jCFCESBZnX0GTv7iQ==", "dev": true, - "dependencies": { - "@rollup/pluginutils": "^3.1.0", - "@types/resolve": "1.17.1", - "deepmerge": "^4.2.2", - "is-builtin-module": "^3.1.0", - "is-module": "^1.0.0", - "resolve": "^1.19.0" - }, + "license": "Apache-2.0", "engines": { - "node": ">= 10.0.0" - }, - "peerDependencies": { - "rollup": "^2.78.0" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@rollup/plugin-replace": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-4.0.0.tgz", - "integrity": "sha512-+rumQFiaNac9y64OHtkHGmdjm7us9bo1PlbgQfdihQtuNxzjpaB064HbRnewUOggLQxVCCyINfStkgmBeQpv1g==", + "node_modules/@eslint/plugin-kit": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.6.1.tgz", + "integrity": "sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@rollup/pluginutils": "^3.1.0", - "magic-string": "^0.25.7" + "@eslint/core": "^1.1.1", + "levn": "^0.4.1" }, - "peerDependencies": { - "rollup": "^1.20.0 || ^2.0.0" + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@rollup/plugin-virtual": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-virtual/-/plugin-virtual-2.1.0.tgz", - "integrity": "sha512-CPPAtlKT53HFqC8jFHb/V5WErpU8Hrq2TyCR0A7kPQMlF2wNUf0o1xuAc+Qxj8NCZM0Z3Yvl+FbUXfJjVWqDwA==", + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=8.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0" + "node": ">=18.18.0" } }, - "node_modules/@rollup/pluginutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", - "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@types/estree": "0.0.39", - "estree-walker": "^1.0.1", - "picomatch": "^2.2.2" + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" }, "engines": { - "node": ">= 8.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0" + "node": ">=18.18.0" } }, - "node_modules/@rollup/pluginutils/node_modules/estree-walker": { + "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", - "dev": true - }, - "node_modules/@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", - "dev": true - }, - "node_modules/@types/node": { - "version": "20.11.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.0.tgz", - "integrity": "sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "dependencies": { - "undici-types": "~5.26.4" + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@types/resolve": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", - "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, - "dependencies": { - "@types/node": "*" + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true + "node_modules/@iden3/bigarray": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@iden3/bigarray/-/bigarray-0.0.2.tgz", + "integrity": "sha512-Xzdyxqm1bOFF6pdIsiHLLl3HkSLjbhqJHVyqaTxXt3RqXBEnmsUmEW47H7VOi/ak7TdkRpNkxjyK5Zbkm+y52g==", + "license": "GPL-3.0" }, - "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "dev": true, - "peer": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" + "node_modules/@iden3/binfileutils": { + "version": "0.0.12", + "resolved": "git+ssh://git@github.com/iden3/binfileutils.git#a1afdf907cad28915f27abd379846bc478012702", + "license": "GPL-3.0", + "dependencies": { + "fastfile": "https://github.com/iden3/fastfile.git#feat/esm-migration", + "ffjavascript": "https://github.com/iden3/ffjavascript.git#feat/esm-migration" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } + "license": "MIT" }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.2.tgz", + "integrity": "sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw==", "dev": true, + "license": "MIT", + "optional": true, "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" + "@tybys/wasm-util": "^0.10.1" }, "funding": { "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" } }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", "dev": true, - "engines": { - "node": ">=6" + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, + "node_modules/@noble/hashes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz", + "integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==", + "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 20.19.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "node_modules/@nomicfoundation/edr": { + "version": "0.12.0-next.29", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.12.0-next.29.tgz", + "integrity": "sha512-/c1LbBC3EFgOIKRup0lQ2SIqL9MLdqdOHDM9Mta5CyDOk9cQFlBSTpWCGDrh+p1BIsPFpVHqa4yjkBmZyL1aZA==", "dev": true, + "license": "MIT", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "@nomicfoundation/edr-darwin-arm64": "0.12.0-next.29", + "@nomicfoundation/edr-darwin-x64": "0.12.0-next.29", + "@nomicfoundation/edr-linux-arm64-gnu": "0.12.0-next.29", + "@nomicfoundation/edr-linux-arm64-musl": "0.12.0-next.29", + "@nomicfoundation/edr-linux-x64-gnu": "0.12.0-next.29", + "@nomicfoundation/edr-linux-x64-musl": "0.12.0-next.29", + "@nomicfoundation/edr-win32-x64-msvc": "0.12.0-next.29" }, "engines": { - "node": ">= 8" + "node": ">= 20" } }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/async": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/bfj": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/bfj/-/bfj-9.1.2.tgz", - "integrity": "sha512-EetpSUewwznXQ7yRtxHCgE5RLZV718n9cOYXe5BlhYKuNs0UkidHaUOe6Jlgbf+viGTQeg8mYhm5Wr4c2AB3gA==", + "node_modules/@nomicfoundation/edr-darwin-arm64": { + "version": "0.12.0-next.29", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.12.0-next.29.tgz", + "integrity": "sha512-qzVcAkUsrVT2Za9pLzTYL/eNLS09R+JSG+4LpQ56Wg3mkjbwItn/F6C/XbGqMbNiEGfLi5kVvtYOtT7yu04/Tg==", + "dev": true, "license": "MIT", - "dependencies": { - "check-types": "^11.2.3", - "hoopy": "^0.1.4", - "jsonpath": "^1.1.1", - "tryer": "^1.0.1" - }, "engines": { - "node": ">= 18.0.0" + "node": ">= 20" } }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "node_modules/@nomicfoundation/edr-darwin-x64": { + "version": "0.12.0-next.29", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.12.0-next.29.tgz", + "integrity": "sha512-P2BSYLsDoM1dGi/0NO3ps3l76NbvFDAnmCUS5SLLLdG/b8RUvWKHtfZFrQgy1KCPDFiiG5IlwzcmAwsPjsyOVQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 20" } }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "node_modules/@nomicfoundation/edr-linux-arm64-gnu": { + "version": "0.12.0-next.29", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.12.0-next.29.tgz", + "integrity": "sha512-3SKZIaZCCuY6fAHj6GpTYpQPj3S0LFO6YUUZw3aSg1joBmM9FkP9a1IiYQOBZnZqk0Fa+pHy2dHMVWDczQHX7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "node_modules/@nomicfoundation/edr-linux-arm64-musl": { + "version": "0.12.0-next.29", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.12.0-next.29.tgz", + "integrity": "sha512-GGDJX3We8+XQ0L1Yy2i6ulbucQPO7HpQ5IYkxFLKL0H611ErErHLawrGIvfcfaDYfnFrC/3uxWEqMQ4GhrWbBQ==", "dev": true, "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, "engines": { - "node": ">=8" + "node": ">= 20" } }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "node_modules/@nomicfoundation/edr-linux-x64-gnu": { + "version": "0.12.0-next.29", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.12.0-next.29.tgz", + "integrity": "sha512-d92L55iy/EzMlu341RgFG1Pqd6Mpd1MmcYi48Na2VtMs7rqRIcAUGeLgoooScLinM5JqTIb1uYVghehFrx98gA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 20" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/@nomicfoundation/edr-linux-x64-musl": { + "version": "0.12.0-next.29", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.12.0-next.29.tgz", + "integrity": "sha512-oOupaxyR6KUzvhJ0zsVU0yfeepB3hcTKxvowq2lPPwp6cMFzPY8PFe6uck+7+rXwog0dDkEa4R/RPEE9DtUelw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 20" } }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "node_modules/@nomicfoundation/edr-win32-x64-msvc": { + "version": "0.12.0-next.29", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.12.0-next.29.tgz", + "integrity": "sha512-QWvz4tTt1Z5JYKXODtqqdxfIQMiWFPGLVIeVJlXl2HSPJAIWTMU+EiBhlGGxP0qoUotUbdJbe7lpG4gw3yKIcA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 20" } }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@nomicfoundation/hardhat-errors": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-errors/-/hardhat-errors-3.0.10.tgz", + "integrity": "sha512-jfQ75/t21674cIQPbQmzRSY8YdusvQhKMsT+IGEoXlJuAzw+ngWsD7y7nHT8UKQ+liHWgMA+Am2843KwP0KtiA==", + "dev": true, + "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "@nomicfoundation/hardhat-utils": "^4.0.2" } }, - "node_modules/check-types": { - "version": "11.2.3", - "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.3.tgz", - "integrity": "sha512-+67P1GkJRaxQD6PKK0Et9DhwQB+vGg3PM5+aavopCpZT1lj9jeqfvpgTLAWErNj8qApkkmXlu/Ug74kmhagkXg==" - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "node_modules/@nomicfoundation/hardhat-ethers": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-4.0.7.tgz", + "integrity": "sha512-7wT4/ikhnL44fzJpe4Bh+bnsuWN55P02rbULCvhmcOOCbh/vouIrfVd008Te4+gwx+rYmJtL92vthj/I9dUd0g==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "license": "MIT", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.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" - }, - "engines": { - "node": ">= 8.10.0" + "@nomicfoundation/hardhat-errors": "^3.0.10", + "@nomicfoundation/hardhat-utils": "^4.0.2", + "debug": "^4.3.2", + "ethereum-cryptography": "^2.2.1", + "ethers": "^6.14.0" }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "peerDependencies": { + "hardhat": "^3.1.11" } }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/@nomicfoundation/hardhat-utils": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-utils/-/hardhat-utils-4.0.2.tgz", + "integrity": "sha512-6lK0+9ygB7wGDlu11DAmTuZxhnoGbyGZC2aRaKKehW0vDNTS9iT7GUimgVvlO3B23E/HwwRKOOLmSVPC4qmmQw==", "dev": true, + "license": "MIT", "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" + "@streamparser/json-node": "^0.0.22", + "debug": "^4.3.2", + "env-paths": "^2.2.0", + "ethereum-cryptography": "^2.2.1", + "fast-equals": "^5.4.0", + "json-stream-stringify": "^3.1.6", + "rfdc": "^1.3.1", + "undici": "^6.16.1" } }, - "node_modules/circom_runtime": { - "version": "0.1.28", - "resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.1.28.tgz", - "integrity": "sha512-ACagpQ7zBRLKDl5xRZ4KpmYIcZDUjOiNRuxvXLqhnnlLSVY1Dbvh73TI853nqoR0oEbihtWmMSjgc5f+pXf/jQ==", - "license": "Apache-2.0", + "node_modules/@nomicfoundation/hardhat-vendored": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-vendored/-/hardhat-vendored-3.0.1.tgz", + "integrity": "sha512-jBOAqmEAMJ8zdfiQmTLV+c0IaSyySqkDSJ9spTy8Ts/m/mO8w364TClyfn+p4ZpxBjyX4LMa3NfC402hoDtwCg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@nomicfoundation/hardhat-zod-utils": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-zod-utils/-/hardhat-zod-utils-3.0.3.tgz", + "integrity": "sha512-WER4/UKLpm7/nz1asvNR7EKZKKBW+48Hw7GOdcd3Rhdr3VTNuTaeIxCJpl6YxTTg+Eq/sPAWX0mr25+USs6KWw==", + "dev": true, + "license": "MIT", "dependencies": { - "ffjavascript": "0.3.1" + "@nomicfoundation/hardhat-errors": "^3.0.7", + "@nomicfoundation/hardhat-utils": "^4.0.0" }, - "bin": { - "calcwit": "calcwit.js" + "peerDependencies": { + "zod": "^3.23.8" } }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "node_modules/@nomicfoundation/solidity-analyzer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.2.tgz", + "integrity": "sha512-q4n32/FNKIhQ3zQGGw5CvPF6GTvDCpYwIf7bEY/dZTZbgfDsHyjJwURxUJf3VQuuJj+fDIFl4+KkBVbw4Ef6jA==", "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "license": "MIT", + "engines": { + "node": ">= 12" + }, + "optionalDependencies": { + "@nomicfoundation/solidity-analyzer-darwin-arm64": "0.1.2", + "@nomicfoundation/solidity-analyzer-darwin-x64": "0.1.2", + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": "0.1.2", + "@nomicfoundation/solidity-analyzer-linux-arm64-musl": "0.1.2", + "@nomicfoundation/solidity-analyzer-linux-x64-gnu": "0.1.2", + "@nomicfoundation/solidity-analyzer-linux-x64-musl": "0.1.2", + "@nomicfoundation/solidity-analyzer-win32-x64-msvc": "0.1.2" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, + "node_modules/@nomicfoundation/solidity-analyzer-darwin-arm64": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.2.tgz", + "integrity": "sha512-JaqcWPDZENCvm++lFFGjrDd8mxtf+CtLd2MiXvMNTBD33dContTZ9TWETwNFwg7JTJT5Q9HEecH7FA+HTSsIUw==", + "dev": true, + "license": "MIT", + "optional": true, "engines": { - "node": ">=7.0.0" + "node": ">= 12" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "node_modules/@nomicfoundation/solidity-analyzer-darwin-x64": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.2.tgz", + "integrity": "sha512-fZNmVztrSXC03e9RONBT+CiksSeYcxI1wlzqyr0L7hsQlK1fzV+f04g2JtQ1c/Fe74ZwdV6aQBdd6Uwl1052sw==", "dev": true, "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, + "optional": true, "engines": { - "node": ">= 8" + "node": ">= 12" } }, - "node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-gnu": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.2.tgz", + "integrity": "sha512-3d54oc+9ZVBuB6nbp8wHylk4xh0N0Gc+bk+/uJae+rUgbOBwQSfuGIbAZt1wBXs5REkSmynEGcqx6DutoK0tPA==", "dev": true, - "dependencies": { - "ms": "2.1.2" - }, + "license": "MIT", + "optional": true, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">= 12" } }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-musl": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.2.tgz", + "integrity": "sha512-iDJfR2qf55vgsg7BtJa7iPiFAsYf2d0Tv/0B+vhtnI16+wfQeTbP7teookbGvAo0eJo7aLLm0xfS/GTkvHIucA==", "dev": true, + "license": "MIT", + "optional": true, "engines": { - "node": ">=10" + "node": ">= 12" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-gnu": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.2.tgz", + "integrity": "sha512-9dlHMAt5/2cpWyuJ9fQNOUXFB/vgSFORg1jpjX1Mh9hJ/MfZXlDdHQ+DpFCs32Zk5pxRBb07yGvSHk9/fezL+g==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-musl": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.2.tgz", + "integrity": "sha512-GzzVeeJob3lfrSlDKQw2bRJ8rBf6mEYaWY+gW0JnTDHINA0s2gPR4km5RLIj1xeZZOYz4zRw+AEeYgLRqB2NXg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-win32-x64-msvc": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.2.tgz", + "integrity": "sha512-Fdjli4DCcFHb4Zgsz0uEJXZ2K7VEO+w5KVv7HmT7WO10iODdU9csC2az4jrhEsRtiR9Gfd74FlG0NYlw1BMdyA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.122.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.122.0.tgz", + "integrity": "sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.12.tgz", + "integrity": "sha512-pv1y2Fv0JybcykuiiD3qBOBdz6RteYojRFY1d+b95WVuzx211CRh+ytI/+9iVyWQ6koTh5dawe4S/yRfOFjgaA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.12.tgz", + "integrity": "sha512-cFYr6zTG/3PXXF3pUO+umXxt1wkRK/0AYT8lDwuqvRC+LuKYWSAQAQZjCWDQpAH172ZV6ieYrNnFzVVcnSflAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.12.tgz", + "integrity": "sha512-ZCsYknnHzeXYps0lGBz8JrF37GpE9bFVefrlmDrAQhOEi4IOIlcoU1+FwHEtyXGx2VkYAvhu7dyBf75EJQffBw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.12.tgz", + "integrity": "sha512-dMLeprcVsyJsKolRXyoTH3NL6qtsT0Y2xeuEA8WQJquWFXkEC4bcu1rLZZSnZRMtAqwtrF/Ib9Ddtpa/Gkge9Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.12.tgz", + "integrity": "sha512-YqWjAgGC/9M1lz3GR1r1rP79nMgo3mQiiA+Hfo+pvKFK1fAJ1bCi0ZQVh8noOqNacuY1qIcfyVfP6HoyBRZ85Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.12.tgz", + "integrity": "sha512-/I5AS4cIroLpslsmzXfwbe5OmWvSsrFuEw3mwvbQ1kDxJ822hFHIx+vsN/TAzNVyepI/j/GSzrtCIwQPeKCLIg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.12.tgz", + "integrity": "sha512-V6/wZztnBqlx5hJQqNWwFdxIKN0m38p8Jas+VoSfgH54HSj9tKTt1dZvG6JRHcjh6D7TvrJPWFGaY9UBVOaWPw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.12.tgz", + "integrity": "sha512-AP3E9BpcUYliZCxa3w5Kwj9OtEVDYK6sVoUzy4vTOJsjPOgdaJZKFmN4oOlX0Wp0RPV2ETfmIra9x1xuayFB7g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.12.tgz", + "integrity": "sha512-nWwpvUSPkoFmZo0kQazZYOrT7J5DGOJ/+QHHzjvNlooDZED8oH82Yg67HvehPPLAg5fUff7TfWFHQS8IV1n3og==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.12.tgz", + "integrity": "sha512-RNrafz5bcwRy+O9e6P8Z/OCAJW/A+qtBczIqVYwTs14pf4iV1/+eKEjdOUta93q2TsT/FI0XYDP3TCky38LMAg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.12.tgz", + "integrity": "sha512-Jpw/0iwoKWx3LJ2rc1yjFrj+T7iHZn2JDg1Yny1ma0luviFS4mhAIcd1LFNxK3EYu3DHWCps0ydXQ5i/rrJ2ig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.12.tgz", + "integrity": "sha512-vRugONE4yMfVn0+7lUKdKvN4D5YusEiPilaoO2sgUWpCvrncvWgPMzK00ZFFJuiPgLwgFNP5eSiUlv2tfc+lpA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.12.tgz", + "integrity": "sha512-ykGiLr/6kkiHc0XnBfmFJuCjr5ZYKKofkx+chJWDjitX+KsJuAmrzWhwyOMSHzPhzOHOy7u9HlFoa5MoAOJ/Zg==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.1.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.12.tgz", + "integrity": "sha512-5eOND4duWkwx1AzCxadcOrNeighiLwMInEADT0YM7xeEOOFcovWZCq8dadXgcRHSf3Ulh1kFo/qvzoFiCLOL1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.12.tgz", + "integrity": "sha512-PyqoipaswDLAZtot351MLhrlrh6lcZPo2LSYE+VDxbVk24LVKAGOuE4hb8xZQmrPAuEtTZW8E6D2zc5EUZX4Lw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.12.tgz", + "integrity": "sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", + "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.4.0", + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", + "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@sentry/core": { + "version": "9.47.1", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.47.1.tgz", + "integrity": "sha512-KX62+qIt4xgy8eHKHiikfhz2p5fOciXd0Cl+dNzhgPFq8klq4MGMNaf148GB3M/vBqP4nw/eFvRMAayFCgdRQw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@streamparser/json": { + "version": "0.0.22", + "resolved": "https://registry.npmjs.org/@streamparser/json/-/json-0.0.22.tgz", + "integrity": "sha512-b6gTSBjJ8G8SuO3Gbbj+zXbVx8NSs1EbpbMKpzGLWMdkR+98McH9bEjSz3+0mPJf68c5nxa3CrJHp5EQNXM6zQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@streamparser/json-node": { + "version": "0.0.22", + "resolved": "https://registry.npmjs.org/@streamparser/json-node/-/json-node-0.0.22.tgz", + "integrity": "sha512-sJT2ptNRwqB1lIsQrQlCoWk5rF4tif9wDh+7yluAGijJamAhrHGYpFB/Zg3hJeceoZypi74ftXk8DHzwYpbZSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@streamparser/json": "^0.0.22" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vitest/browser": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-4.1.2.tgz", + "integrity": "sha512-CwdIf90LNf1Zitgqy63ciMAzmyb4oIGs8WZ40VGYrWkssQKeEKr32EzO8MKUrDPPcPVHFI9oQ5ni2Hp24NaNRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@blazediff/core": "1.9.1", + "@vitest/mocker": "4.1.2", + "@vitest/utils": "4.1.2", + "magic-string": "^0.30.21", + "pngjs": "^7.0.0", + "sirv": "^3.0.2", + "tinyrainbow": "^3.1.0", + "ws": "^8.19.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": "4.1.2" + } + }, + "node_modules/@vitest/browser-playwright": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/browser-playwright/-/browser-playwright-4.1.2.tgz", + "integrity": "sha512-N0Z2HzMLvMR6k/tWPTS6Q/DaRscrkax/f2f9DIbNQr+Cd1l4W4wTf/I6S983PAMr0tNqqoTL+xNkLh9M5vbkLg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@vitest/browser": "4.1.2", + "@vitest/mocker": "4.1.2", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "playwright": "*", + "vitest": "4.1.2" + }, + "peerDependenciesMeta": { + "playwright": { + "optional": false + } + } + }, + "node_modules/@vitest/expect": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.2.tgz", + "integrity": "sha512-gbu+7B0YgUJ2nkdsRJrFFW6X7NTP44WlhiclHniUhxADQJH5Szt9mZ9hWnJPJ8YwOK5zUOSSlSvyzRf0u1DSBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.2", + "@vitest/utils": "4.1.2", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.2.tgz", + "integrity": "sha512-Ize4iQtEALHDttPRCmN+FKqOl2vxTiNUhzobQFFt/BM1lRUTG7zRCLOykG/6Vo4E4hnUdfVLo5/eqKPukcWW7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.2", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.2.tgz", + "integrity": "sha512-dwQga8aejqeuB+TvXCMzSQemvV9hNEtDDpgUKDzOmNQayl2OG241PSWeJwKRH3CiC+sESrmoFd49rfnq7T4RnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/vitest" } }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + "node_modules/@vitest/runner": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.2.tgz", + "integrity": "sha512-Gr+FQan34CdiYAwpGJmQG8PgkyFVmARK8/xSijia3eTFgVfpcpztWLuP6FttGNfPLJhaZVP/euvujeNYar36OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.2", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "node_modules/@vitest/snapshot": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.2.tgz", + "integrity": "sha512-g7yfUmxYS4mNxk31qbOYsSt2F4m1E02LFqO53Xpzg3zKMhLAPZAjjfyl9e6z7HrW6LvUdTwAQR3HHfLjpko16A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.2", + "@vitest/utils": "4.1.2", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.2.tgz", + "integrity": "sha512-DU4fBnbVCJGNBwVA6xSToNXrkZNSiw59H8tcuUspVMsBDBST4nfvsPsEHDHGtWRRnqBERBQu7TrTKskmjqTXKA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.2.tgz", + "integrity": "sha512-xw2/TiX82lQHA06cgbqRKFb5lCAy3axQ4H4SoUFhUsg+wztiet+co86IAMDtF6Vm1hc7J6j09oh/rgDn+JdKIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.2", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, "engines": { - "node": ">=0.10.0" + "node": ">=0.4.0" } }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/adm-zip": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", + "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.3.0" + } + }, + "node_modules/aes-js": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/ajv": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "dev": true, + "license": "MIT", + "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" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.3.1" + "node": ">=12" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/bfj": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-9.1.3.tgz", + "integrity": "sha512-1ythbcNNAd2UjTYW6M+MAHd9KM/m3g4mQ+3a4Vom16WgmUa4GsisdmXAYfpAjkObY5zdpgzaBh1ctZOEcJipuQ==", "dev": true, + "license": "MIT", "dependencies": { - "esutils": "^2.0.2" + "check-types": "^11.2.3", + "hoopy": "^0.1.4", + "tryer": "^1.0.1" }, "engines": { - "node": ">=6.0.0" + "node": ">= 18.0.0" } }, - "node_modules/ejs": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", - "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", - "license": "Apache-2.0", + "node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "license": "MIT", "dependencies": { - "jake": "^10.8.5" - }, - "bin": { - "ejs": "bin/cli.js" + "balanced-match": "^4.0.2" }, "engines": { - "node": ">=0.10.0" + "node": "18 || 20 || >=22" } }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/check-types": { + "version": "11.2.3", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.3.tgz", + "integrity": "sha512-+67P1GkJRaxQD6PKK0Et9DhwQB+vGg3PM5+aavopCpZT1lj9jeqfvpgTLAWErNj8qApkkmXlu/Ug74kmhagkXg==", + "dev": true, + "license": "MIT" + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, "engines": { - "node": ">=10" + "node": ">= 14.16.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/escodegen": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", - "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "node_modules/circom_runtime": { + "version": "0.1.28", + "resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.1.28.tgz", + "integrity": "sha512-ACagpQ7zBRLKDl5xRZ4KpmYIcZDUjOiNRuxvXLqhnnlLSVY1Dbvh73TI853nqoR0oEbihtWmMSjgc5f+pXf/jQ==", + "license": "Apache-2.0", "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" + "ffjavascript": "0.3.1" }, "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" + "calcwit": "calcwit.js" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": ">=4.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" + "node": ">= 8" } }, - "node_modules/escodegen/node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" }, "engines": { - "node": ">=4" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/escodegen/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=4.0" + "node": ">=8" } }, - "node_modules/escodegen/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "node_modules/ejs": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-5.0.1.tgz", + "integrity": "sha512-COqBPFMxuPTPspXl2DkVYaDS3HtrD1GpzOGkNTJ1IYkifq/r9h8SVEFrjA3D9/VJGOEoMQcrlhpntcSUrM8k6A==", + "license": "Apache-2.0", + "bin": { + "ejs": "bin/cli.js" }, "engines": { - "node": ">= 0.8.0" + "node": ">=0.12.18" } }, - "node_modules/escodegen/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "node_modules/enquirer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dev": true, + "license": "MIT", "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">= 0.8.0" + "node": ">=8.6" } }, - "node_modules/escodegen/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.8.0" + "node": ">=6" } }, - "node_modules/escodegen/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "optional": true, + "node_modules/es-module-lexer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" } }, - "node_modules/escodegen/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dependencies": { - "prelude-ls": "~1.1.2" - }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.1.0.tgz", + "integrity": "sha512-S9jlY/ELKEUwwQnqWDO+f+m6sercqOPSqXM5Go94l7DOmxHVDgmSFGWEzeE/gwgTAr0W103BWt0QLe/7mabIvA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.3", + "@eslint/config-helpers": "^0.5.3", + "@eslint/core": "^1.1.1", + "@eslint/plugin-kit": "^0.6.1", + "@humanfs/node": "^0.16.6", "@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", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "cross-spawn": "^7.0.6", "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", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.2.0", + "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "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", + "minimatch": "^10.2.4", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.16.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^5.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" } }, - "node_modules/esprima": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.2.tgz", - "integrity": "sha512-+JpPZam9w5DuJ3Q67SqsMGtiHKENSMRVoxvArfJZK01/BfLEObtZ6orJa/MtoGNR/rfMgp5837T41PAmTwAv/A==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -1259,6 +2079,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -1271,566 +2092,452 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" - }, - "node_modules/fastfile": { - "version": "0.0.20", - "resolved": "https://registry.npmjs.org/fastfile/-/fastfile-0.0.20.tgz", - "integrity": "sha512-r5ZDbgImvVWCP0lA/cGNgQcZqR+aYdFx3u+CtJqUE510pBUVGMn4ulL/iRTI4tACTYsNJ736uzFxEBXesPAktA==" - }, - "node_modules/fastq": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", - "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", + "node_modules/ethereum-cryptography": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", + "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", "dev": true, + "license": "MIT", "dependencies": { - "reusify": "^1.0.4" + "@noble/curves": "1.4.2", + "@noble/hashes": "1.4.0", + "@scure/bip32": "1.4.0", + "@scure/bip39": "1.3.0" } }, - "node_modules/ffjavascript": { - "resolved": "../ffjavascript", - "link": true - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "node_modules/ethereum-cryptography/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", "dev": true, + "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "@noble/hashes": "1.4.0" }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", - "dependencies": { - "minimatch": "^5.0.1" - } - }, - "node_modules/filelist/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/filelist/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, + "node_modules/ethereum-cryptography/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/ethers": { + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.16.0.tgz", + "integrity": "sha512-U1wulmetNymijEhpSEQ7Ct/P/Jw9/e7R1j5XIbPRydgV2DjLVMsULDlNksq3RQnFgKoLlZf88ijYtWEXcPa07A==", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/ethers-io/" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], "license": "MIT", "dependencies": { - "to-regex-range": "^5.0.1" + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "22.7.5", + "aes-js": "4.0.0-beta.5", + "tslib": "2.7.0", + "ws": "8.17.1" }, "engines": { - "node": ">=8" + "node": ">=14.0.0" } }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/ethers/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">= 16" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "node_modules/ethers/node_modules/@types/node": { + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", "dev": true, + "license": "MIT", "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "undici-types": "~6.19.2" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "node_modules/ethers/node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "license": "MIT" }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "node_modules/ethers/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, + "license": "MIT", "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "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" + "node": ">=10.0.0" }, - "engines": { - "node": "*" + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, + "license": "Apache-2.0", "engines": { - "node": ">=10.13.0" + "node": ">=12.0.0" } }, - "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "license": "MIT" }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/fast-equals": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.4.0.tgz", + "integrity": "sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=6.0.0" } }, - "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } + "license": "MIT" }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, - "bin": { - "he": "bin/he" - } + "license": "MIT" }, - "node_modules/hoopy": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", - "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==", - "engines": { - "node": ">= 6.0.0" - } + "node_modules/fastfile": { + "version": "0.0.20", + "resolved": "git+ssh://git@github.com/iden3/fastfile.git#c78a6c23e1a7dfc83beebc64089139d068b62a9f", + "license": "GPL-3.0" }, - "node_modules/ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "node": ">=12.0.0" }, - "engines": { - "node": ">=6" + "peerDependencies": { + "picomatch": "^3 || ^4" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, + "node_modules/ffjavascript": { + "version": "0.3.1", + "resolved": "git+ssh://git@github.com/iden3/ffjavascript.git#0e949b121f874e50ea854e0ce08316ce6dd7eb59", + "license": "GPL-3.0", "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "wasmbuilder": "0.0.16", + "wasmcurves": "https://github.com/iden3/wasmcurves.git#feat/esm-migration", + "workerpool": "10.0.1" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, + "license": "MIT", "dependencies": { - "binary-extensions": "^2.0.0" + "flat-cache": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=16.0.0" } }, - "node_modules/is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { - "builtin-modules": "^3.3.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, + "license": "MIT", "dependencies": { - "hasown": "^2.0.0" + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=16" } }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true, - "bin": { - "is-docker": "cli.js" - }, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=8" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-tsconfig": { + "version": "4.13.7", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.7.tgz", + "integrity": "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10.13.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/globals": { + "version": "17.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.4.0.tgz", + "integrity": "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/hardhat": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-3.3.0.tgz", + "integrity": "sha512-TtejTl3ZeELwlcProbWtnsnPE2wUP2VDxzsTZp/IAgQ277kz3eQtXMpRnacefNmSve/oUAYYHxZtNQEQvaLzHg==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "is-extglob": "^2.1.1" + "@nomicfoundation/edr": "0.12.0-next.29", + "@nomicfoundation/hardhat-errors": "^3.0.10", + "@nomicfoundation/hardhat-utils": "^4.0.2", + "@nomicfoundation/hardhat-vendored": "^3.0.1", + "@nomicfoundation/hardhat-zod-utils": "^3.0.3", + "@nomicfoundation/solidity-analyzer": "^0.1.1", + "@sentry/core": "^9.4.0", + "adm-zip": "^0.4.16", + "chalk": "^5.3.0", + "chokidar": "^4.0.3", + "debug": "^4.3.2", + "enquirer": "^2.3.0", + "ethereum-cryptography": "^2.2.1", + "micro-eth-signer": "^0.14.0", + "p-map": "^7.0.2", + "resolve.exports": "^2.0.3", + "semver": "^7.6.3", + "tsx": "^4.19.3", + "ws": "^8.18.0", + "zod": "^3.23.8" }, - "engines": { - "node": ">=0.10.0" + "bin": { + "hardhat": "dist/src/cli.js" } }, - "node_modules/is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", - "dev": true - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/hoopy": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", + "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.12.0" + "node": ">= 6.0.0" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 4" } }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" - } - }, - "node_modules/is-reference": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", - "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", - "dev": true, - "dependencies": { - "@types/estree": "*" + "node": ">=0.8.19" } }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { - "is-docker": "^2.0.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/jake": { - "version": "10.8.7", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", - "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", - "dependencies": { - "async": "^3.2.3", - "chalk": "^4.0.2", - "filelist": "^1.0.4", - "minimatch": "^3.1.2" - }, - "bin": { - "jake": "bin/cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jest-worker": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", - "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } + "license": "ISC" }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true + "dev": true, + "license": "MIT" }, - "node_modules/jsonpath": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.1.1.tgz", - "integrity": "sha512-l6Cg7jRpixfbgoWgkrl77dgEj8RPvND0wMH6TwQmi9Qs4TFfS9u5cUFnbeKTwj5ga5Y3BTGGNI28k117LJ009w==", - "dependencies": { - "esprima": "1.2.2", - "static-eval": "2.0.2", - "underscore": "1.12.1" + "node_modules/json-stream-stringify": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/json-stream-stringify/-/json-stream-stringify-3.1.6.tgz", + "integrity": "sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=7.10.1" } }, "node_modules/keyv": { @@ -1838,6 +2545,7 @@ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } @@ -1847,6 +2555,7 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -1855,35 +2564,275 @@ "node": ">= 0.8.0" } }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", "dev": true, + "license": "MPL-2.0", "dependencies": { - "p-locate": "^5.0.0" + "detect-libc": "^2.0.3" }, "engines": { - "node": ">=10" + "node": ">= 12.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" + "p-locate": "^5.0.0" }, "engines": { "node": ">=10" @@ -1895,190 +2844,186 @@ "node_modules/logplease": { "version": "1.2.15", "resolved": "https://registry.npmjs.org/logplease/-/logplease-1.2.15.tgz", - "integrity": "sha512-jLlHnlsPSJjpwUfcNyUxXCl33AYg2cHhIf9QhGL2T4iPT0XPB+xP1LRKFPgIg1M/sg9kAJvy94w9CzBNrfnstA==" + "integrity": "sha512-jLlHnlsPSJjpwUfcNyUxXCl33AYg2cHhIf9QhGL2T4iPT0XPB+xP1LRKFPgIg1M/sg9kAJvy94w9CzBNrfnstA==", + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } }, "node_modules/magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, + "license": "MIT", "dependencies": { - "sourcemap-codec": "^1.4.8" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "node_modules/micro-eth-signer": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/micro-eth-signer/-/micro-eth-signer-0.14.0.tgz", + "integrity": "sha512-5PLLzHiVYPWClEvZIXXFu5yutzpadb73rnQCpUqIHu3No3coFuWQNfE5tkBQJ7djuLYl6aRLaS0MgWJYGoqiBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.8.1", + "@noble/hashes": "~1.7.1", + "micro-packed": "~0.7.2" + } }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/micro-eth-signer/node_modules/@noble/curves": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.2.tgz", + "integrity": "sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g==", + "dev": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "@noble/hashes": "1.7.2" + }, + "engines": { + "node": "^14.21.3 || >=16" }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/micro-eth-signer/node_modules/@noble/hashes": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.2.tgz", + "integrity": "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ==", + "dev": true, + "license": "MIT", "engines": { - "node": "*" + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/mocha": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.3.tgz", - "integrity": "sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A==", + "node_modules/micro-packed": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/micro-packed/-/micro-packed-0.7.3.tgz", + "integrity": "sha512-2Milxs+WNC00TRlem41oRswvw31146GiSaoCT7s3Xi2gMUglW5QBeqlQaZeHr5tJx9nm3i57LNXPqxOOaWtTYg==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-colors": "^4.1.3", - "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", - "debug": "^4.3.5", - "diff": "^5.2.0", - "escape-string-regexp": "^4.0.0", - "find-up": "^5.0.0", - "glob": "^8.1.0", - "he": "^1.2.0", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^5.1.6", - "ms": "^2.1.3", - "serialize-javascript": "^6.0.2", - "strip-json-comments": "^3.1.1", - "supports-color": "^8.1.1", - "workerpool": "^6.5.1", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9", - "yargs-unparser": "^2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" + "@scure/base": "~1.2.5" }, - "engines": { - "node": ">= 14.0.0" + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/micro-packed/node_modules/@scure/base": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", + "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/mocha/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "brace-expansion": "^5.0.5" }, "engines": { - "node": ">=12" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "dev": true, + "license": "MIT", "engines": { "node": ">=10" } }, - "node_modules/mocha/node_modules/ms": { + "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "dev": true, + "license": "MIT" }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, - "dependencies": { - "wrappy": "1" - } + "license": "MIT" }, - "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", "dev": true, - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" }, "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "license": "MIT", "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" + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" @@ -2089,6 +3034,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -2104,6 +3050,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -2114,345 +3061,318 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "node_modules/p-map": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", + "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, "engines": { - "node": ">=8.6" + "node": "18 || 20 || >=22" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/r1csfile": { - "resolved": "../r1csfile", - "link": true - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } + "license": "MIT" }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } + "license": "ISC" }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, + "license": "MIT", + "peer": true, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "node_modules/playwright": { + "version": "1.59.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.59.1.tgz", + "integrity": "sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==", "dev": true, + "license": "Apache-2.0", + "peer": true, "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" + "playwright-core": "1.59.1" }, "bin": { - "resolve": "bin/resolve" + "playwright": "cli.js" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" } }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "node_modules/playwright-core": { + "version": "1.59.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.59.1.tgz", + "integrity": "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==", "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, "engines": { - "node": ">=4" + "node": ">=18" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "node_modules/pngjs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz", + "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==", "dev": true, + "license": "MIT", "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" + "node": ">=14.19.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/postcss": { + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": "^10 || ^12 || >=14" } }, - "node_modules/rollup": { - "version": "2.79.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz", - "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "license": "MIT", - "peer": true, - "bin": { - "rollup": "dist/bin/rollup" - }, "engines": { - "node": ">=10.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "node": ">= 0.8.0" } }, - "node_modules/rollup-plugin-terser": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", - "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", - "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser", + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "jest-worker": "^26.2.1", - "serialize-javascript": "^4.0.0", - "terser": "^5.0.0" - }, - "peerDependencies": { - "rollup": "^2.0.0" + "license": "MIT", + "engines": { + "node": ">=6" } }, - "node_modules/rollup-plugin-terser/node_modules/serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, + "node_modules/r1csfile": { + "version": "0.0.48", + "resolved": "git+ssh://git@github.com/iden3/r1csfile.git#20d8befec24bdce24549014ff5c1f8f487d426c8", + "license": "GPL-3.0", "dependencies": { - "randombytes": "^2.1.0" + "@iden3/bigarray": "0.0.2", + "@iden3/binfileutils": "https://github.com/iden3/binfileutils.git#feat/esm-migration", + "fastfile": "https://github.com/iden3/fastfile.git#feat/esm-migration", + "ffjavascript": "https://github.com/iden3/ffjavascript.git#feat/esm-migration" } }, - "node_modules/rollup-plugin-visualizer": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.12.0.tgz", - "integrity": "sha512-8/NU9jXcHRs7Nnj07PF2o4gjxmm9lXIrZ8r175bT9dK8qoLlvKTwRMArRCMgpMGlq8CTLugRvEmyMeMXIU2pNQ==", + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "dev": true, - "dependencies": { - "open": "^8.4.0", - "picomatch": "^2.3.1", - "source-map": "^0.7.4", - "yargs": "^17.5.1" - }, - "bin": { - "rollup-plugin-visualizer": "dist/bin/cli.js" - }, + "license": "MIT", "engines": { - "node": ">=14" - }, - "peerDependencies": { - "rollup": "2.x || 3.x || 4.x" + "node": ">= 14.18.0" }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, - "node_modules/rollup-plugin-visualizer/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, - "node_modules/rollup-plugin-visualizer/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", "dev": true, - "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" - }, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=10" } }, - "node_modules/rollup-plugin-visualizer/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "dev": true, - "engines": { - "node": ">=12" - } + "license": "MIT" }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "node_modules/rimraf": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz", + "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "license": "BlueOak-1.0.0", "dependencies": { - "queue-microtask": "^1.2.2" + "glob": "^13.0.3", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "node_modules/rimraf/node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "node_modules/rolldown": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.12.tgz", + "integrity": "sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A==", "dev": true, + "license": "MIT", "dependencies": { - "randombytes": "^2.1.0" + "@oxc-project/types": "=0.122.0", + "@rolldown/pluginutils": "1.0.0-rc.12" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.0-rc.12", + "@rolldown/binding-darwin-arm64": "1.0.0-rc.12", + "@rolldown/binding-darwin-x64": "1.0.0-rc.12", + "@rolldown/binding-freebsd-x64": "1.0.0-rc.12", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.12", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.12", + "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.12", + "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.12", + "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.12", + "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.12", + "@rolldown/binding-linux-x64-musl": "1.0.0-rc.12", + "@rolldown/binding-openharmony-arm64": "1.0.0-rc.12", + "@rolldown/binding-wasm32-wasi": "1.0.0-rc.12", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.12", + "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.12" + } + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/shebang-command": { @@ -2460,6 +3380,7 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -2472,72 +3393,63 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true, - "engines": { - "node": ">= 8" - } + "license": "ISC" }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "node_modules/sirv": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", + "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", "dev": true, + "license": "MIT", "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">=18" } }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "deprecated": "Please use @jridgewell/sourcemap-codec instead", - "dev": true - }, - "node_modules/static-eval": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz", - "integrity": "sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==", - "dependencies": { - "escodegen": "^1.8.1" - } + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/std-env": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz", + "integrity": "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==", "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } + "license": "MIT" }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -2545,88 +3457,115 @@ "node": ">=8" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz", + "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18" } }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { - "node": ">=8" + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "node_modules/tinyrainbow": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", + "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=14.0.0" } }, - "node_modules/terser": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.26.0.tgz", - "integrity": "sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ==", + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", "dev": true, - "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" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=6" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "node_modules/tryer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", + "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true, + "license": "0BSD" }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "node_modules/tsx": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", "dev": true, "license": "MIT", "dependencies": { - "is-number": "^7.0.0" + "esbuild": "~0.27.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" }, "engines": { - "node": ">=8.0" + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" } }, - "node_modules/tryer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", - "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==" + "node_modules/tsx/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -2634,139 +3573,286 @@ "node": ">= 0.8.0" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/undici": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.24.1.tgz", + "integrity": "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18.17" } }, - "node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" - }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/vite": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.3.tgz", + "integrity": "sha512-B9ifbFudT1TFhfltfaIPgjo9Z3mDynBTJSUYxTjOQruf/zHH+ezCQKcoqO+h7a9Pw9Nm/OtlXAiGT1axBgwqrQ==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "isexe": "^2.0.0" + "lightningcss": "^1.32.0", + "picomatch": "^4.0.4", + "postcss": "^8.5.8", + "rolldown": "1.0.0-rc.12", + "tinyglobby": "^0.2.15" }, "bin": { - "node-which": "bin/node-which" + "vite": "bin/vite.js" }, "engines": { - "node": ">= 8" + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.1.0", + "esbuild": "^0.27.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } } }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "node_modules/vite/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=0.10.0" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/workerpool": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", - "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/vitest": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.2.tgz", + "integrity": "sha512-xjR1dMTVHlFLh98JE3i/f/WePqJsah4A0FK9cc8Ehp9Udk0AZk6ccpIZhh1qJ/yxVWRZ+Q54ocnD8TXmkhspGg==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "@vitest/expect": "4.1.2", + "@vitest/mocker": "4.1.2", + "@vitest/pretty-format": "4.1.2", + "@vitest/runner": "4.1.2", + "@vitest/snapshot": "4.1.2", + "@vitest/spy": "4.1.2", + "@vitest/utils": "4.1.2", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" }, "engines": { - "node": ">=10" + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.2", + "@vitest/browser-preview": "4.1.2", + "@vitest/browser-webdriverio": "4.1.2", + "@vitest/ui": "4.1.2", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "node_modules/wasmbuilder": { + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/wasmbuilder/-/wasmbuilder-0.0.16.tgz", + "integrity": "sha512-Qx3lEFqaVvp1cEYW7Bfi+ebRJrOiwz2Ieu7ZG2l7YyeSJIok/reEQCQCuicj/Y32ITIJuGIM9xZQppGx5LrQdA==", + "license": "GPL-3.0" + }, + "node_modules/wasmcurves": { + "version": "0.2.2", + "resolved": "git+ssh://git@github.com/iden3/wasmcurves.git#6601f20df1059e29f98ea595ca12e35545c321f1", + "license": "GPL-3.0", + "dependencies": { + "wasmbuilder": "0.0.16" + } }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, "engines": { - "node": ">=10" + "node": ">= 8" } }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", "dev": true, + "license": "MIT", "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" + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "node_modules/workerpool": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-10.0.1.tgz", + "integrity": "sha512-NAnKwZJxWlj/U1cp6ZkEtPE+GQY1S6KtOS3AlCiPfPFLxV3m64giSp7g2LsNJxzYCocDT7TSl+7T0sgrDp3KoQ==", + "license": "Apache-2.0" + }, + "node_modules/ws": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", + "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, "node_modules/yocto-queue": { @@ -2774,12 +3860,24 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "dev": true, + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/package.json b/package.json index fb7b0cd8..b964295e 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "require": "./build/main.cjs" }, "browser": "./build/browser.esm.js", - "umd": "./build/snarkjs.min.js" + "default": "./main.js" } }, "files": [ @@ -25,14 +25,17 @@ "templates/" ], "scripts": { - "test": "mocha", - "testv12": "mocha test/fflonk.test.js test/fullprocess.js test/keypar_test.js test/polynomial.test.js", - "build": "npm run buildcjs && npm run buildcli && npm run buildiife && npm run buildiifemin && npm run buildesm", - "buildcjs": "rollup -c config/rollup.cjs.config.js", - "buildcli": "rollup -c config/rollup.cli.config.js", - "buildiife": "BROWSER=true rollup -c config/rollup.iife.config.js", - "buildiifemin": "BROWSER=true rollup -c config/rollup.iife_min.config.js", - "buildesm": "BROWSER=true rollup -c config/rollup.browser.esm.config" + "lint": "eslint .", + "clean": "rimraf build", + "pretest": "npm run build:node && npm run build:browser && npm run lint", + "test": "vitest run", + "test:node": "vitest run --project node-esm", + "test:watch": "vitest --project node-esm", + "build:node": "vite build", + "build:cli": "vite build --mode cli", + "build:browser": "vite build --mode browser", + "build:iife": "vite build --mode browser-iife", + "build": "npm run clean && npm run build:node && npm run build:cli && npm run build:browser && npm run build:iife" }, "bin": { "snarkjs": "build/cli.cjs" @@ -56,26 +59,28 @@ "url": "https://github.com/iden3/snarkjs.git" }, "dependencies": { - "@iden3/binfileutils": "file:../binfileutils", - "@noble/hashes": "^1.7.1", - "bfj": "^9.1.2", + "@iden3/binfileutils": "https://github.com/iden3/binfileutils.git#feat/esm-migration", + "@noble/hashes": "^2.0.1", "circom_runtime": "0.1.28", - "ejs": "^3.1.6", - "fastfile": "0.0.20", - "ffjavascript": "file:../ffjavascript", + "ejs": "^5.0.1", + "fastfile": "https://github.com/iden3/fastfile.git#feat/esm-migration", + "ffjavascript": "https://github.com/iden3/ffjavascript.git#feat/esm-migration", "logplease": "^1.2.15", - "r1csfile": "file:../r1csfile" + "r1csfile": "https://github.com/iden3/r1csfile.git#feat/esm-migration" }, "devDependencies": { - "@rollup/plugin-commonjs": "^22.0.0", - "@rollup/plugin-json": "^4.1.0", - "@rollup/plugin-node-resolve": "^14.0.0", - "@rollup/plugin-replace": "^4.0.0", - "@rollup/plugin-virtual": "^2.0.3", - "eslint": "^8.7.0", - "mocha": "^10.2.0", - "rollup": "^2.36.2", - "rollup-plugin-terser": "^7.0.2", - "rollup-plugin-visualizer": "^5.6.0" + "@eslint/js": "^10.0.1", + "@nomicfoundation/hardhat-ethers": "^4.0.7", + "@vitest/browser": "^4.1.2", + "@vitest/browser-playwright": "^4.1.2", + "bfj": "^9.1.3", + "eslint": "^10.1.0", + "ethers": "^6.13.5", + "globals": "^17.4.0", + "hardhat": "^3.3.0", + "playwright": "^1.59.0", + "rimraf": "^6.1.3", + "vite": "^8.0.3", + "vitest": "^4.1.2" } } diff --git a/smart_contract_tests/.gitignore b/smart_contract_tests/.gitignore deleted file mode 100644 index 80058e5e..00000000 --- a/smart_contract_tests/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -node_modules -.env -coverage -coverage.json -typechain -typechain-types - -# Hardhat files -cache -artifacts -contracts diff --git a/smart_contract_tests/hardhat.config.cjs b/smart_contract_tests/hardhat.config.cjs deleted file mode 100644 index 6ae7d582..00000000 --- a/smart_contract_tests/hardhat.config.cjs +++ /dev/null @@ -1,39 +0,0 @@ -require("@nomiclabs/hardhat-waffle"); - -/** @type import('hardhat/config').HardhatUserConfig */ -module.exports = { - solidity: { - compilers: [ - { - version: "0.8.17", - settings: { - optimizer: { - enabled: true, - runs: 999999 - } - } - }, - { - version: "0.6.11", - settings: { - optimizer: { - enabled: true, - runs: 999999 - } - } - }, - ] - }, - paths: { - sources: "./contracts", - tests: "./test", - cache: "./cache", - artifacts: "./artifacts" - }, - // gasReporter: { - // enabled: !!process.env.REPORT_GAS, - // outputFile: process.env.REPORT_GAS_FILE ? "./gas_report.md" : null, - // noColors: process.env.REPORT_GAS_FILE ? true : false - // }, - -}; diff --git a/smart_contract_tests/package-lock.json b/smart_contract_tests/package-lock.json deleted file mode 100644 index 3e695300..00000000 --- a/smart_contract_tests/package-lock.json +++ /dev/null @@ -1,7832 +0,0 @@ -{ - "name": "snarkjs-smart-contract-tests", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "snarkjs-smart-contract-tests", - "devDependencies": { - "@nomiclabs/hardhat-ethers": "^2.2.3", - "@nomiclabs/hardhat-waffle": "^2.0.5", - "chai": "^4.3.7", - "ethereum-waffle": "^4.0.10", - "ethers": "^5.7.2", - "ffjavascript": "^0.2.63", - "hardhat": "2.18.3", - "mocha": "^10.2.0", - "snarkjs": "file:.." - } - }, - "..": { - "version": "0.7.5", - "dev": true, - "license": "GPL-3.0", - "dependencies": { - "@iden3/binfileutils": "0.0.12", - "@noble/hashes": "^1.7.1", - "bfj": "^7.0.2", - "circom_runtime": "0.1.28", - "ejs": "^3.1.6", - "fastfile": "0.0.20", - "ffjavascript": "0.3.1", - "logplease": "^1.2.15", - "r1csfile": "0.0.48" - }, - "bin": { - "snarkjs": "build/cli.cjs" - }, - "devDependencies": { - "@rollup/plugin-commonjs": "^22.0.0", - "@rollup/plugin-json": "^4.1.0", - "@rollup/plugin-node-resolve": "^14.0.0", - "@rollup/plugin-replace": "^4.0.0", - "@rollup/plugin-virtual": "^2.0.3", - "eslint": "^8.7.0", - "mocha": "^10.2.0", - "rollup": "^2.36.2", - "rollup-plugin-terser": "^7.0.2", - "rollup-plugin-visualizer": "^5.6.0" - } - }, - "node_modules/@chainsafe/as-sha256": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz", - "integrity": "sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg==", - "dev": true - }, - "node_modules/@chainsafe/persistent-merkle-tree": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.4.2.tgz", - "integrity": "sha512-lLO3ihKPngXLTus/L7WHKaw9PnNJWizlOF1H9NNzHP6Xvh82vzg9F2bzkXhYIFshMZ2gTCEz8tq6STe7r5NDfQ==", - "dev": true, - "dependencies": { - "@chainsafe/as-sha256": "^0.3.1" - } - }, - "node_modules/@chainsafe/ssz": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@chainsafe/ssz/-/ssz-0.9.4.tgz", - "integrity": "sha512-77Qtg2N1ayqs4Bg/wvnWfg5Bta7iy7IRh8XqXh7oNMeP2HBbBwx8m6yTpA8p0EHItWPEBkgZd5S5/LSlp3GXuQ==", - "dev": true, - "dependencies": { - "@chainsafe/as-sha256": "^0.3.1", - "@chainsafe/persistent-merkle-tree": "^0.4.2", - "case": "^1.6.3" - } - }, - "node_modules/@ensdomains/ens": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/@ensdomains/ens/-/ens-0.4.5.tgz", - "integrity": "sha512-JSvpj1iNMFjK6K+uVl4unqMoa9rf5jopb8cya5UGBWz23Nw8hSNT7efgUx4BTlAPAgpNlEioUfeTyQ6J9ZvTVw==", - "deprecated": "Please use @ensdomains/ens-contracts", - "dev": true, - "peer": true, - "dependencies": { - "bluebird": "^3.5.2", - "eth-ens-namehash": "^2.0.8", - "solc": "^0.4.20", - "testrpc": "0.0.1", - "web3-utils": "^1.0.0-beta.31" - } - }, - "node_modules/@ensdomains/ens/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ensdomains/ens/node_modules/camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ensdomains/ens/node_modules/cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==", - "dev": true, - "peer": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "node_modules/@ensdomains/ens/node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ensdomains/ens/node_modules/fs-extra": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", - "integrity": "sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==", - "dev": true, - "peer": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" - } - }, - "node_modules/@ensdomains/ens/node_modules/get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true, - "peer": true - }, - "node_modules/@ensdomains/ens/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", - "dev": true, - "peer": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ensdomains/ens/node_modules/jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", - "dev": true, - "peer": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@ensdomains/ens/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "peer": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@ensdomains/ens/node_modules/solc": { - "version": "0.4.26", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.4.26.tgz", - "integrity": "sha512-o+c6FpkiHd+HPjmjEVpQgH7fqZ14tJpXhho+/bQXlXbliLIS/xjXb42Vxh+qQY1WCSTMQ0+a5vR9vi0MfhU6mA==", - "dev": true, - "peer": true, - "dependencies": { - "fs-extra": "^0.30.0", - "memorystream": "^0.3.1", - "require-from-string": "^1.1.0", - "semver": "^5.3.0", - "yargs": "^4.7.1" - }, - "bin": { - "solcjs": "solcjs" - } - }, - "node_modules/@ensdomains/ens/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", - "dev": true, - "peer": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ensdomains/ens/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dev": true, - "peer": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ensdomains/ens/node_modules/wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==", - "dev": true, - "peer": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ensdomains/ens/node_modules/y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true, - "peer": true - }, - "node_modules/@ensdomains/ens/node_modules/yargs": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", - "integrity": "sha512-LqodLrnIDM3IFT+Hf/5sxBnEGECrfdC1uIbgZeJmESCSo4HoCAaKEus8MylXHAkdacGc0ye+Qa+dpkuom8uVYA==", - "dev": true, - "peer": true, - "dependencies": { - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "lodash.assign": "^4.0.3", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.1", - "which-module": "^1.0.0", - "window-size": "^0.2.0", - "y18n": "^3.2.1", - "yargs-parser": "^2.4.1" - } - }, - "node_modules/@ensdomains/ens/node_modules/yargs-parser": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", - "integrity": "sha512-9pIKIJhnI5tonzG6OnCFlz/yln8xHYcGl+pn3xR0Vzff0vzN1PbNRaelgfgRUwZ3s4i3jvxT9WhmUGL4whnasA==", - "dev": true, - "peer": true, - "dependencies": { - "camelcase": "^3.0.0", - "lodash.assign": "^4.0.6" - } - }, - "node_modules/@ensdomains/resolver": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@ensdomains/resolver/-/resolver-0.2.4.tgz", - "integrity": "sha512-bvaTH34PMCbv6anRa9I/0zjLJgY4EuznbEMgbV77JBCQ9KNC46rzi0avuxpOfu+xDjPEtSFGqVEOr5GlUSGudA==", - "deprecated": "Please use @ensdomains/ens-contracts", - "dev": true, - "peer": true - }, - "node_modules/@ethereum-waffle/chai": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@ethereum-waffle/chai/-/chai-4.0.10.tgz", - "integrity": "sha512-X5RepE7Dn8KQLFO7HHAAe+KeGaX/by14hn90wePGBhzL54tq4Y8JscZFu+/LCwCl6TnkAAy5ebiMoqJ37sFtWw==", - "dev": true, - "dependencies": { - "@ethereum-waffle/provider": "4.0.5", - "debug": "^4.3.4", - "json-bigint": "^1.0.0" - }, - "engines": { - "node": ">=10.0" - }, - "peerDependencies": { - "ethers": "*" - } - }, - "node_modules/@ethereum-waffle/compiler": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@ethereum-waffle/compiler/-/compiler-4.0.3.tgz", - "integrity": "sha512-5x5U52tSvEVJS6dpCeXXKvRKyf8GICDwiTwUvGD3/WD+DpvgvaoHOL82XqpTSUHgV3bBq6ma5/8gKUJUIAnJCw==", - "dev": true, - "dependencies": { - "@resolver-engine/imports": "^0.3.3", - "@resolver-engine/imports-fs": "^0.3.3", - "@typechain/ethers-v5": "^10.0.0", - "@types/mkdirp": "^0.5.2", - "@types/node-fetch": "^2.6.1", - "mkdirp": "^0.5.1", - "node-fetch": "^2.6.7" - }, - "engines": { - "node": ">=10.0" - }, - "peerDependencies": { - "ethers": "*", - "solc": "*", - "typechain": "^8.0.0" - } - }, - "node_modules/@ethereum-waffle/ens": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@ethereum-waffle/ens/-/ens-4.0.3.tgz", - "integrity": "sha512-PVLcdnTbaTfCrfSOrvtlA9Fih73EeDvFS28JQnT5M5P4JMplqmchhcZB1yg/fCtx4cvgHlZXa0+rOCAk2Jk0Jw==", - "dev": true, - "engines": { - "node": ">=10.0" - }, - "peerDependencies": { - "@ensdomains/ens": "^0.4.4", - "@ensdomains/resolver": "^0.2.4", - "ethers": "*" - } - }, - "node_modules/@ethereum-waffle/mock-contract": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@ethereum-waffle/mock-contract/-/mock-contract-4.0.4.tgz", - "integrity": "sha512-LwEj5SIuEe9/gnrXgtqIkWbk2g15imM/qcJcxpLyAkOj981tQxXmtV4XmQMZsdedEsZ/D/rbUAOtZbgwqgUwQA==", - "dev": true, - "engines": { - "node": ">=10.0" - }, - "peerDependencies": { - "ethers": "*" - } - }, - "node_modules/@ethereum-waffle/provider": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@ethereum-waffle/provider/-/provider-4.0.5.tgz", - "integrity": "sha512-40uzfyzcrPh+Gbdzv89JJTMBlZwzya1YLDyim8mVbEqYLP5VRYWoGp0JMyaizgV3hMoUFRqJKVmIUw4v7r3hYw==", - "dev": true, - "dependencies": { - "@ethereum-waffle/ens": "4.0.3", - "@ganache/ethereum-options": "0.1.4", - "debug": "^4.3.4", - "ganache": "7.4.3" - }, - "engines": { - "node": ">=10.0" - }, - "peerDependencies": { - "ethers": "*" - } - }, - "node_modules/@ethereumjs/block": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/@ethereumjs/block/-/block-3.6.3.tgz", - "integrity": "sha512-CegDeryc2DVKnDkg5COQrE0bJfw/p0v3GBk2W5/Dj5dOVfEmb50Ux0GLnSPypooLnfqjwFaorGuT9FokWB3GRg==", - "dev": true, - "dependencies": { - "@ethereumjs/common": "^2.6.5", - "@ethereumjs/tx": "^3.5.2", - "ethereumjs-util": "^7.1.5", - "merkle-patricia-tree": "^4.2.4" - } - }, - "node_modules/@ethereumjs/block/node_modules/@ethereumjs/common": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", - "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", - "dev": true, - "dependencies": { - "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.5" - } - }, - "node_modules/@ethereumjs/block/node_modules/@ethereumjs/tx": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.5.2.tgz", - "integrity": "sha512-gQDNJWKrSDGu2w7w0PzVXVBNMzb7wwdDOmOqczmhNjqFxFuIbhVJDwiGEnxFNC2/b8ifcZzY7MLcluizohRzNw==", - "dev": true, - "dependencies": { - "@ethereumjs/common": "^2.6.4", - "ethereumjs-util": "^7.1.5" - } - }, - "node_modules/@ethereumjs/block/node_modules/ethereumjs-util": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz", - "integrity": "sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==", - "dev": true, - "dependencies": { - "@types/bn.js": "^5.1.0", - "bn.js": "^5.1.2", - "create-hash": "^1.1.2", - "ethereum-cryptography": "^0.1.3", - "rlp": "^2.2.4" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@ethereumjs/blockchain": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/@ethereumjs/blockchain/-/blockchain-5.5.3.tgz", - "integrity": "sha512-bi0wuNJ1gw4ByNCV56H0Z4Q7D+SxUbwyG12Wxzbvqc89PXLRNR20LBcSUZRKpN0+YCPo6m0XZL/JLio3B52LTw==", - "dev": true, - "dependencies": { - "@ethereumjs/block": "^3.6.2", - "@ethereumjs/common": "^2.6.4", - "@ethereumjs/ethash": "^1.1.0", - "debug": "^4.3.3", - "ethereumjs-util": "^7.1.5", - "level-mem": "^5.0.1", - "lru-cache": "^5.1.1", - "semaphore-async-await": "^1.5.1" - } - }, - "node_modules/@ethereumjs/blockchain/node_modules/@ethereumjs/common": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", - "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", - "dev": true, - "dependencies": { - "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.5" - } - }, - "node_modules/@ethereumjs/blockchain/node_modules/ethereumjs-util": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz", - "integrity": "sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==", - "dev": true, - "dependencies": { - "@types/bn.js": "^5.1.0", - "bn.js": "^5.1.2", - "create-hash": "^1.1.2", - "ethereum-cryptography": "^0.1.3", - "rlp": "^2.2.4" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@ethereumjs/common": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.0.tgz", - "integrity": "sha512-Cq2qS0FTu6O2VU1sgg+WyU9Ps0M6j/BEMHN+hRaECXCV/r0aI78u4N6p52QW/BDVhwWZpCdrvG8X7NJdzlpNUA==", - "dev": true, - "dependencies": { - "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.3" - } - }, - "node_modules/@ethereumjs/ethash": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/ethash/-/ethash-1.1.0.tgz", - "integrity": "sha512-/U7UOKW6BzpA+Vt+kISAoeDie1vAvY4Zy2KF5JJb+So7+1yKmJeJEHOGSnQIj330e9Zyl3L5Nae6VZyh2TJnAA==", - "dev": true, - "dependencies": { - "@ethereumjs/block": "^3.5.0", - "@types/levelup": "^4.3.0", - "buffer-xor": "^2.0.1", - "ethereumjs-util": "^7.1.1", - "miller-rabin": "^4.0.0" - } - }, - "node_modules/@ethereumjs/rlp": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz", - "integrity": "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==", - "dev": true, - "peer": true, - "bin": { - "rlp": "bin/rlp" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@ethereumjs/tx": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.4.0.tgz", - "integrity": "sha512-WWUwg1PdjHKZZxPPo274ZuPsJCWV3SqATrEKQP1n2DrVYVP1aZIYpo/mFaA0BDoE0tIQmBeimRCEA0Lgil+yYw==", - "dev": true, - "dependencies": { - "@ethereumjs/common": "^2.6.0", - "ethereumjs-util": "^7.1.3" - } - }, - "node_modules/@ethereumjs/util": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.1.0.tgz", - "integrity": "sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==", - "dev": true, - "peer": true, - "dependencies": { - "@ethereumjs/rlp": "^4.0.1", - "ethereum-cryptography": "^2.0.0", - "micro-ftch": "^0.3.1" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@ethereumjs/util/node_modules/@noble/hashes": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", - "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@ethereumjs/util/node_modules/ethereum-cryptography": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz", - "integrity": "sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==", - "dev": true, - "peer": true, - "dependencies": { - "@noble/curves": "1.3.0", - "@noble/hashes": "1.3.3", - "@scure/bip32": "1.3.3", - "@scure/bip39": "1.2.2" - } - }, - "node_modules/@ethereumjs/vm": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/vm/-/vm-5.6.0.tgz", - "integrity": "sha512-J2m/OgjjiGdWF2P9bj/4LnZQ1zRoZhY8mRNVw/N3tXliGI8ai1sI1mlDPkLpeUUM4vq54gH6n0ZlSpz8U/qlYQ==", - "dev": true, - "dependencies": { - "@ethereumjs/block": "^3.6.0", - "@ethereumjs/blockchain": "^5.5.0", - "@ethereumjs/common": "^2.6.0", - "@ethereumjs/tx": "^3.4.0", - "async-eventemitter": "^0.2.4", - "core-js-pure": "^3.0.1", - "debug": "^2.2.0", - "ethereumjs-util": "^7.1.3", - "functional-red-black-tree": "^1.0.1", - "mcl-wasm": "^0.7.1", - "merkle-patricia-tree": "^4.2.2", - "rustbn.js": "~0.2.0" - } - }, - "node_modules/@ethereumjs/vm/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/@ethereumjs/vm/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/@ethersproject/abi": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", - "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@ethersproject/abstract-provider": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", - "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@ethersproject/abstract-signer": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", - "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@ethersproject/address": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", - "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@ethersproject/base64": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", - "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0" - } - }, - "node_modules/@ethersproject/basex": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz", - "integrity": "sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/properties": "^5.7.0" - } - }, - "node_modules/@ethersproject/bignumber": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", - "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "bn.js": "^5.2.1" - } - }, - "node_modules/@ethersproject/bytes": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", - "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/constants": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", - "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0" - } - }, - "node_modules/@ethersproject/contracts": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz", - "integrity": "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abi": "^5.7.0", - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/transactions": "^5.7.0" - } - }, - "node_modules/@ethersproject/hash": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", - "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@ethersproject/hdnode": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz", - "integrity": "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/basex": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/pbkdf2": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/wordlists": "^5.7.0" - } - }, - "node_modules/@ethersproject/json-wallets": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz", - "integrity": "sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hdnode": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/pbkdf2": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "aes-js": "3.0.0", - "scrypt-js": "3.0.1" - } - }, - "node_modules/@ethersproject/keccak256": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", - "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "js-sha3": "0.8.0" - } - }, - "node_modules/@ethersproject/logger": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", - "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ] - }, - "node_modules/@ethersproject/networks": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", - "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/pbkdf2": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz", - "integrity": "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/sha2": "^5.7.0" - } - }, - "node_modules/@ethersproject/properties": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", - "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/providers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz", - "integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/base64": "^5.7.0", - "@ethersproject/basex": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/networks": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/rlp": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/web": "^5.7.0", - "bech32": "1.1.4", - "ws": "7.4.6" - } - }, - "node_modules/@ethersproject/random": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz", - "integrity": "sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/rlp": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", - "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/sha2": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz", - "integrity": "sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "hash.js": "1.1.7" - } - }, - "node_modules/@ethersproject/signing-key": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", - "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@ethersproject/solidity": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz", - "integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/strings": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", - "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/transactions": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", - "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@ethersproject/units": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz", - "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/wallet": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz", - "integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/hdnode": "^5.7.0", - "@ethersproject/json-wallets": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/wordlists": "^5.7.0" - } - }, - "node_modules/@ethersproject/web": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", - "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@ethersproject/wordlists": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz", - "integrity": "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@ganache/ethereum-address": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@ganache/ethereum-address/-/ethereum-address-0.1.4.tgz", - "integrity": "sha512-sTkU0M9z2nZUzDeHRzzGlW724xhMLXo2LeX1hixbnjHWY1Zg1hkqORywVfl+g5uOO8ht8T0v+34IxNxAhmWlbw==", - "dev": true, - "dependencies": { - "@ganache/utils": "0.1.4" - } - }, - "node_modules/@ganache/ethereum-options": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@ganache/ethereum-options/-/ethereum-options-0.1.4.tgz", - "integrity": "sha512-i4l46taoK2yC41FPkcoDlEVoqHS52wcbHPqJtYETRWqpOaoj9hAg/EJIHLb1t6Nhva2CdTO84bG+qlzlTxjAHw==", - "dev": true, - "dependencies": { - "@ganache/ethereum-address": "0.1.4", - "@ganache/ethereum-utils": "0.1.4", - "@ganache/options": "0.1.4", - "@ganache/utils": "0.1.4", - "bip39": "3.0.4", - "seedrandom": "3.0.5" - } - }, - "node_modules/@ganache/ethereum-utils": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@ganache/ethereum-utils/-/ethereum-utils-0.1.4.tgz", - "integrity": "sha512-FKXF3zcdDrIoCqovJmHLKZLrJ43234Em2sde/3urUT/10gSgnwlpFmrv2LUMAmSbX3lgZhW/aSs8krGhDevDAg==", - "dev": true, - "dependencies": { - "@ethereumjs/common": "2.6.0", - "@ethereumjs/tx": "3.4.0", - "@ethereumjs/vm": "5.6.0", - "@ganache/ethereum-address": "0.1.4", - "@ganache/rlp": "0.1.4", - "@ganache/utils": "0.1.4", - "emittery": "0.10.0", - "ethereumjs-abi": "0.6.8", - "ethereumjs-util": "7.1.3" - } - }, - "node_modules/@ganache/options": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@ganache/options/-/options-0.1.4.tgz", - "integrity": "sha512-zAe/craqNuPz512XQY33MOAG6Si1Xp0hCvfzkBfj2qkuPcbJCq6W/eQ5MB6SbXHrICsHrZOaelyqjuhSEmjXRw==", - "dev": true, - "dependencies": { - "@ganache/utils": "0.1.4", - "bip39": "3.0.4", - "seedrandom": "3.0.5" - } - }, - "node_modules/@ganache/rlp": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@ganache/rlp/-/rlp-0.1.4.tgz", - "integrity": "sha512-Do3D1H6JmhikB+6rHviGqkrNywou/liVeFiKIpOBLynIpvZhRCgn3SEDxyy/JovcaozTo/BynHumfs5R085MFQ==", - "dev": true, - "dependencies": { - "@ganache/utils": "0.1.4", - "rlp": "2.2.6" - } - }, - "node_modules/@ganache/utils": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@ganache/utils/-/utils-0.1.4.tgz", - "integrity": "sha512-oatUueU3XuXbUbUlkyxeLLH3LzFZ4y5aSkNbx6tjSIhVTPeh+AuBKYt4eQ73FFcTB3nj/gZoslgAh5CN7O369w==", - "dev": true, - "dependencies": { - "emittery": "0.10.0", - "keccak": "3.0.1", - "seedrandom": "3.0.5" - }, - "optionalDependencies": { - "@trufflesuite/bigint-buffer": "1.1.9" - } - }, - "node_modules/@metamask/eth-sig-util": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz", - "integrity": "sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==", - "dev": true, - "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" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@metamask/eth-sig-util/node_modules/@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@metamask/eth-sig-util/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/@metamask/eth-sig-util/node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, - "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" - } - }, - "node_modules/@noble/curves": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", - "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", - "dev": true, - "peer": true, - "dependencies": { - "@noble/hashes": "1.3.3" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/curves/node_modules/@noble/hashes": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", - "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/secp256k1": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", - "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] - }, - "node_modules/@nomicfoundation/ethereumjs-block": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.2.tgz", - "integrity": "sha512-hSe6CuHI4SsSiWWjHDIzWhSiAVpzMUcDRpWYzN0T9l8/Rz7xNn3elwVOJ/tAyS0LqL6vitUD78Uk7lQDXZun7Q==", - "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-common": "4.0.2", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "@nomicfoundation/ethereumjs-trie": "6.0.2", - "@nomicfoundation/ethereumjs-tx": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "ethereum-cryptography": "0.1.3", - "ethers": "^5.7.1" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@nomicfoundation/ethereumjs-blockchain": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.2.tgz", - "integrity": "sha512-8UUsSXJs+MFfIIAKdh3cG16iNmWzWC/91P40sazNvrqhhdR/RtGDlFk2iFTGbBAZPs2+klZVzhRX8m2wvuvz3w==", - "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-block": "5.0.2", - "@nomicfoundation/ethereumjs-common": "4.0.2", - "@nomicfoundation/ethereumjs-ethash": "3.0.2", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "@nomicfoundation/ethereumjs-trie": "6.0.2", - "@nomicfoundation/ethereumjs-tx": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "abstract-level": "^1.0.3", - "debug": "^4.3.3", - "ethereum-cryptography": "0.1.3", - "level": "^8.0.0", - "lru-cache": "^5.1.1", - "memory-level": "^1.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@nomicfoundation/ethereumjs-common": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.2.tgz", - "integrity": "sha512-I2WGP3HMGsOoycSdOTSqIaES0ughQTueOsddJ36aYVpI3SN8YSusgRFLwzDJwRFVIYDKx/iJz0sQ5kBHVgdDwg==", - "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-util": "9.0.2", - "crc-32": "^1.2.0" - } - }, - "node_modules/@nomicfoundation/ethereumjs-ethash": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.2.tgz", - "integrity": "sha512-8PfoOQCcIcO9Pylq0Buijuq/O73tmMVURK0OqdjhwqcGHYC2PwhbajDh7GZ55ekB0Px197ajK3PQhpKoiI/UPg==", - "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-block": "5.0.2", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "abstract-level": "^1.0.3", - "bigint-crypto-utils": "^3.0.23", - "ethereum-cryptography": "0.1.3" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@nomicfoundation/ethereumjs-evm": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.2.tgz", - "integrity": "sha512-rBLcUaUfANJxyOx9HIdMX6uXGin6lANCulIm/pjMgRqfiCRMZie3WKYxTSd8ZE/d+qT+zTedBF4+VHTdTSePmQ==", - "dev": true, - "dependencies": { - "@ethersproject/providers": "^5.7.1", - "@nomicfoundation/ethereumjs-common": "4.0.2", - "@nomicfoundation/ethereumjs-tx": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "debug": "^4.3.3", - "ethereum-cryptography": "0.1.3", - "mcl-wasm": "^0.7.1", - "rustbn.js": "~0.2.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@nomicfoundation/ethereumjs-rlp": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.2.tgz", - "integrity": "sha512-QwmemBc+MMsHJ1P1QvPl8R8p2aPvvVcKBbvHnQOKBpBztEo0omN0eaob6FeZS/e3y9NSe+mfu3nNFBHszqkjTA==", - "dev": true, - "bin": { - "rlp": "bin/rlp" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@nomicfoundation/ethereumjs-statemanager": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.2.tgz", - "integrity": "sha512-dlKy5dIXLuDubx8Z74sipciZnJTRSV/uHG48RSijhgm1V7eXYFC567xgKtsKiVZB1ViTP9iFL4B6Je0xD6X2OA==", - "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-common": "4.0.2", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "debug": "^4.3.3", - "ethereum-cryptography": "0.1.3", - "ethers": "^5.7.1", - "js-sdsl": "^4.1.4" - } - }, - "node_modules/@nomicfoundation/ethereumjs-trie": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.2.tgz", - "integrity": "sha512-yw8vg9hBeLYk4YNg5MrSJ5H55TLOv2FSWUTROtDtTMMmDGROsAu+0tBjiNGTnKRi400M6cEzoFfa89Fc5k8NTQ==", - "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "@types/readable-stream": "^2.3.13", - "ethereum-cryptography": "0.1.3", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@nomicfoundation/ethereumjs-tx": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.2.tgz", - "integrity": "sha512-T+l4/MmTp7VhJeNloMkM+lPU3YMUaXdcXgTGCf8+ZFvV9NYZTRLFekRwlG6/JMmVfIfbrW+dRRJ9A6H5Q/Z64g==", - "dev": true, - "dependencies": { - "@chainsafe/ssz": "^0.9.2", - "@ethersproject/providers": "^5.7.2", - "@nomicfoundation/ethereumjs-common": "4.0.2", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "ethereum-cryptography": "0.1.3" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@nomicfoundation/ethereumjs-util": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.2.tgz", - "integrity": "sha512-4Wu9D3LykbSBWZo8nJCnzVIYGvGCuyiYLIJa9XXNVt1q1jUzHdB+sJvx95VGCpPkCT+IbLecW6yfzy3E1bQrwQ==", - "dev": true, - "dependencies": { - "@chainsafe/ssz": "^0.10.0", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "ethereum-cryptography": "0.1.3" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@nomicfoundation/ethereumjs-util/node_modules/@chainsafe/persistent-merkle-tree": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.5.0.tgz", - "integrity": "sha512-l0V1b5clxA3iwQLXP40zYjyZYospQLZXzBVIhhr9kDg/1qHZfzzHw0jj4VPBijfYCArZDlPkRi1wZaV2POKeuw==", - "dev": true, - "dependencies": { - "@chainsafe/as-sha256": "^0.3.1" - } - }, - "node_modules/@nomicfoundation/ethereumjs-util/node_modules/@chainsafe/ssz": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/@chainsafe/ssz/-/ssz-0.10.2.tgz", - "integrity": "sha512-/NL3Lh8K+0q7A3LsiFq09YXS9fPE+ead2rr7vM2QK8PLzrNsw3uqrif9bpRX5UxgeRjM+vYi+boCM3+GM4ovXg==", - "dev": true, - "dependencies": { - "@chainsafe/as-sha256": "^0.3.1", - "@chainsafe/persistent-merkle-tree": "^0.5.0" - } - }, - "node_modules/@nomicfoundation/ethereumjs-vm": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.2.tgz", - "integrity": "sha512-Bj3KZT64j54Tcwr7Qm/0jkeZXJMfdcAtRBedou+Hx0dPOSIgqaIr0vvLwP65TpHbak2DmAq+KJbW2KNtIoFwvA==", - "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-block": "5.0.2", - "@nomicfoundation/ethereumjs-blockchain": "7.0.2", - "@nomicfoundation/ethereumjs-common": "4.0.2", - "@nomicfoundation/ethereumjs-evm": "2.0.2", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "@nomicfoundation/ethereumjs-statemanager": "2.0.2", - "@nomicfoundation/ethereumjs-trie": "6.0.2", - "@nomicfoundation/ethereumjs-tx": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "debug": "^4.3.3", - "ethereum-cryptography": "0.1.3", - "mcl-wasm": "^0.7.1", - "rustbn.js": "~0.2.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.1.tgz", - "integrity": "sha512-1LMtXj1puAxyFusBgUIy5pZk3073cNXYnXUpuNKFghHbIit/xZgbk0AokpUADbNm3gyD6bFWl3LRFh3dhVdREg==", - "dev": true, - "engines": { - "node": ">= 12" - }, - "optionalDependencies": { - "@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" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-darwin-arm64": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.1.tgz", - "integrity": "sha512-KcTodaQw8ivDZyF+D76FokN/HdpgGpfjc/gFCImdLUyqB6eSWVaZPazMbeAjmfhx3R0zm/NYVzxwAokFKgrc0w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-darwin-x64": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.1.tgz", - "integrity": "sha512-XhQG4BaJE6cIbjAVtzGOGbK3sn1BO9W29uhk9J8y8fZF1DYz0Doj8QDMfpMu+A6TjPDs61lbsmeYodIDnfveSA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-freebsd-x64": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-freebsd-x64/-/solidity-analyzer-freebsd-x64-0.1.1.tgz", - "integrity": "sha512-GHF1VKRdHW3G8CndkwdaeLkVBi5A9u2jwtlS7SLhBc8b5U/GcoL39Q+1CSO3hYqePNP+eV5YI7Zgm0ea6kMHoA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-gnu": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.1.tgz", - "integrity": "sha512-g4Cv2fO37ZsUENQ2vwPnZc2zRenHyAxHcyBjKcjaSmmkKrFr64yvzeNO8S3GBFCo90rfochLs99wFVGT/0owpg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-musl": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.1.tgz", - "integrity": "sha512-WJ3CE5Oek25OGE3WwzK7oaopY8xMw9Lhb0mlYuJl/maZVo+WtP36XoQTb7bW/i8aAdHW5Z+BqrHMux23pvxG3w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-gnu": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.1.tgz", - "integrity": "sha512-5WN7leSr5fkUBBjE4f3wKENUy9HQStu7HmWqbtknfXkkil+eNWiBV275IOlpXku7v3uLsXTOKpnnGHJYI2qsdA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-musl": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.1.tgz", - "integrity": "sha512-KdYMkJOq0SYPQMmErv/63CwGwMm5XHenEna9X9aB8mQmhDBrYrlAOSsIPgFCUSL0hjxE3xHP65/EPXR/InD2+w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-win32-arm64-msvc": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-arm64-msvc/-/solidity-analyzer-win32-arm64-msvc-0.1.1.tgz", - "integrity": "sha512-VFZASBfl4qiBYwW5xeY20exWhmv6ww9sWu/krWSesv3q5hA0o1JuzmPHR4LPN6SUZj5vcqci0O6JOL8BPw+APg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-win32-ia32-msvc": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-ia32-msvc/-/solidity-analyzer-win32-ia32-msvc-0.1.1.tgz", - "integrity": "sha512-JnFkYuyCSA70j6Si6cS1A9Gh1aHTEb8kOTBApp/c7NRTFGNMH8eaInKlyuuiIbvYFhlXW4LicqyYuWNNq9hkpQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-win32-x64-msvc": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.1.tgz", - "integrity": "sha512-HrVJr6+WjIXGnw3Q9u6KQcbZCtk0caVWhCdFADySvRyUxJ8PnzlaP+MhwNE8oyT8OZ6ejHBRrrgjSqDCFXGirw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nomiclabs/hardhat-ethers": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.3.tgz", - "integrity": "sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg==", - "dev": true, - "peerDependencies": { - "ethers": "^5.0.0", - "hardhat": "^2.0.0" - } - }, - "node_modules/@nomiclabs/hardhat-waffle": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.6.tgz", - "integrity": "sha512-+Wz0hwmJGSI17B+BhU/qFRZ1l6/xMW82QGXE/Gi+WTmwgJrQefuBs1lIf7hzQ1hLk6hpkvb/zwcNkpVKRYTQYg==", - "dev": true, - "peerDependencies": { - "@nomiclabs/hardhat-ethers": "^2.0.0", - "@types/sinon-chai": "^3.2.3", - "ethereum-waffle": "*", - "ethers": "^5.0.0", - "hardhat": "^2.0.0" - } - }, - "node_modules/@resolver-engine/core": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@resolver-engine/core/-/core-0.3.3.tgz", - "integrity": "sha512-eB8nEbKDJJBi5p5SrvrvILn4a0h42bKtbCTri3ZxCGt6UvoQyp7HnGOfki944bUjBSHKK3RvgfViHn+kqdXtnQ==", - "dev": true, - "dependencies": { - "debug": "^3.1.0", - "is-url": "^1.2.4", - "request": "^2.85.0" - } - }, - "node_modules/@resolver-engine/core/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/@resolver-engine/fs": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@resolver-engine/fs/-/fs-0.3.3.tgz", - "integrity": "sha512-wQ9RhPUcny02Wm0IuJwYMyAG8fXVeKdmhm8xizNByD4ryZlx6PP6kRen+t/haF43cMfmaV7T3Cx6ChOdHEhFUQ==", - "dev": true, - "dependencies": { - "@resolver-engine/core": "^0.3.3", - "debug": "^3.1.0" - } - }, - "node_modules/@resolver-engine/fs/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/@resolver-engine/imports": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@resolver-engine/imports/-/imports-0.3.3.tgz", - "integrity": "sha512-anHpS4wN4sRMwsAbMXhMfOD/y4a4Oo0Cw/5+rue7hSwGWsDOQaAU1ClK1OxjUC35/peazxEl8JaSRRS+Xb8t3Q==", - "dev": true, - "dependencies": { - "@resolver-engine/core": "^0.3.3", - "debug": "^3.1.0", - "hosted-git-info": "^2.6.0", - "path-browserify": "^1.0.0", - "url": "^0.11.0" - } - }, - "node_modules/@resolver-engine/imports-fs": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@resolver-engine/imports-fs/-/imports-fs-0.3.3.tgz", - "integrity": "sha512-7Pjg/ZAZtxpeyCFlZR5zqYkz+Wdo84ugB5LApwriT8XFeQoLwGUj4tZFFvvCuxaNCcqZzCYbonJgmGObYBzyCA==", - "dev": true, - "dependencies": { - "@resolver-engine/fs": "^0.3.3", - "@resolver-engine/imports": "^0.3.3", - "debug": "^3.1.0" - } - }, - "node_modules/@resolver-engine/imports-fs/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/@resolver-engine/imports/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/@scure/base": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.6.tgz", - "integrity": "sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==", - "dev": true, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.3.tgz", - "integrity": "sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ==", - "dev": true, - "peer": true, - "dependencies": { - "@noble/curves": "~1.3.0", - "@noble/hashes": "~1.3.2", - "@scure/base": "~1.1.4" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32/node_modules/@noble/hashes": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", - "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip39": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.2.tgz", - "integrity": "sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA==", - "dev": true, - "peer": true, - "dependencies": { - "@noble/hashes": "~1.3.2", - "@scure/base": "~1.1.4" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip39/node_modules/@noble/hashes": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", - "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@sentry/core": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz", - "integrity": "sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==", - "dev": true, - "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" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/hub": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz", - "integrity": "sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==", - "dev": true, - "dependencies": { - "@sentry/types": "5.30.0", - "@sentry/utils": "5.30.0", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/minimal": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz", - "integrity": "sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==", - "dev": true, - "dependencies": { - "@sentry/hub": "5.30.0", - "@sentry/types": "5.30.0", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/node": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.30.0.tgz", - "integrity": "sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==", - "dev": true, - "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" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/tracing": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz", - "integrity": "sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==", - "dev": true, - "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" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/types": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz", - "integrity": "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/utils": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz", - "integrity": "sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==", - "dev": true, - "dependencies": { - "@sentry/types": "5.30.0", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@trufflesuite/bigint-buffer": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@trufflesuite/bigint-buffer/-/bigint-buffer-1.1.9.tgz", - "integrity": "sha512-bdM5cEGCOhDSwminryHJbRmXc1x7dPKg6Pqns3qyTwFlxsqUgxE29lsERS3PlIW1HTjoIGMUqsk1zQQwST1Yxw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "dependencies": { - "node-gyp-build": "4.3.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@typechain/ethers-v5": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/@typechain/ethers-v5/-/ethers-v5-10.2.1.tgz", - "integrity": "sha512-n3tQmCZjRE6IU4h6lqUGiQ1j866n5MTCBJreNEHHVWXa2u9GJTaeYyU1/k+1qLutkyw+sS6VAN+AbeiTqsxd/A==", - "dev": true, - "dependencies": { - "lodash": "^4.17.15", - "ts-essentials": "^7.0.1" - }, - "peerDependencies": { - "@ethersproject/abi": "^5.0.0", - "@ethersproject/providers": "^5.0.0", - "ethers": "^5.1.3", - "typechain": "^8.1.1", - "typescript": ">=4.3.0" - } - }, - "node_modules/@types/abstract-leveldown": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/@types/abstract-leveldown/-/abstract-leveldown-7.2.5.tgz", - "integrity": "sha512-/2B0nQF4UdupuxeKTJA2+Rj1D+uDemo6P4kMwKCpbfpnzeVaWSELTsAw4Lxn3VJD6APtRrZOCuYo+4nHUQfTfg==", - "dev": true - }, - "node_modules/@types/bn.js": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.5.tgz", - "integrity": "sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/chai": { - "version": "4.3.14", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.14.tgz", - "integrity": "sha512-Wj71sXE4Q4AkGdG9Tvq1u/fquNz9EdG4LIJMwVVII7ashjD/8cf8fyIfJAjRr6YcsXnSE8cOGQPq1gqeR8z+3w==", - "dev": true, - "peer": true - }, - "node_modules/@types/level-errors": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/level-errors/-/level-errors-3.0.2.tgz", - "integrity": "sha512-gyZHbcQ2X5hNXf/9KS2qGEmgDe9EN2WDM3rJ5Ele467C0nA1sLhtmv1bZiPMDYfAYCfPWft0uQIaTvXbASSTRA==", - "dev": true - }, - "node_modules/@types/levelup": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@types/levelup/-/levelup-4.3.3.tgz", - "integrity": "sha512-K+OTIjJcZHVlZQN1HmU64VtrC0jC3dXWQozuEIR9zVvltIk90zaGPM2AgT+fIkChpzHhFE3YnvFLCbLtzAmexA==", - "dev": true, - "dependencies": { - "@types/abstract-leveldown": "*", - "@types/level-errors": "*", - "@types/node": "*" - } - }, - "node_modules/@types/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==", - "dev": true - }, - "node_modules/@types/mkdirp": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-0.5.2.tgz", - "integrity": "sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/node": { - "version": "20.12.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", - "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", - "dev": true, - "dependencies": { - "@types/node": "*", - "form-data": "^4.0.0" - } - }, - "node_modules/@types/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/prettier": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", - "dev": true - }, - "node_modules/@types/readable-stream": { - "version": "2.3.15", - "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.15.tgz", - "integrity": "sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==", - "dev": true, - "dependencies": { - "@types/node": "*", - "safe-buffer": "~5.1.1" - } - }, - "node_modules/@types/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/@types/secp256k1": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.6.tgz", - "integrity": "sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/sinon": { - "version": "17.0.3", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.3.tgz", - "integrity": "sha512-j3uovdn8ewky9kRBG19bOwaZbexJu/XjtkHyjvUgt4xfPFz18dcORIMqnYh66Fx3Powhcr85NT5+er3+oViapw==", - "dev": true, - "peer": true, - "dependencies": { - "@types/sinonjs__fake-timers": "*" - } - }, - "node_modules/@types/sinon-chai": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/@types/sinon-chai/-/sinon-chai-3.2.12.tgz", - "integrity": "sha512-9y0Gflk3b0+NhQZ/oxGtaAJDvRywCa5sIyaVnounqLvmf93yBF4EgIRspePtkMs3Tr844nCclYMlcCNmLCvjuQ==", - "dev": true, - "peer": true, - "dependencies": { - "@types/chai": "*", - "@types/sinon": "*" - } - }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", - "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", - "dev": true, - "peer": true - }, - "node_modules/abstract-level": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/abstract-level/-/abstract-level-1.0.4.tgz", - "integrity": "sha512-eUP/6pbXBkMbXFdx4IH2fVgvB7M0JvR7/lIL33zcs0IBcwjdzSSl31TOJsaCzmKSSDF9h8QYSOJux4Nd4YJqFg==", - "dev": true, - "dependencies": { - "buffer": "^6.0.3", - "catering": "^2.1.0", - "is-buffer": "^2.0.5", - "level-supports": "^4.0.0", - "level-transcoder": "^1.0.1", - "module-error": "^1.0.1", - "queue-microtask": "^1.2.3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/abstract-level/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/abstract-level/node_modules/level-supports": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-4.0.1.tgz", - "integrity": "sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/abstract-leveldown": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.3.0.tgz", - "integrity": "sha512-TU5nlYgta8YrBMNpc9FwQzRbiXsj49gsALsXadbGHt9CROPzX5fB0rWDR5mtdpOOKa5XqRFpbj1QroPAoPzVjQ==", - "dev": true, - "dependencies": { - "buffer": "^5.5.0", - "immediate": "^3.2.3", - "level-concat-iterator": "~2.0.0", - "level-supports": "~1.0.0", - "xtend": "~4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/adm-zip": { - "version": "0.4.16", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", - "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", - "dev": true, - "engines": { - "node": ">=0.3.0" - } - }, - "node_modules/aes-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==", - "dev": true - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "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" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dev": true, - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/async-eventemitter": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/async-eventemitter/-/async-eventemitter-0.2.4.tgz", - "integrity": "sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw==", - "dev": true, - "dependencies": { - "async": "^2.4.0" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", - "dev": true - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dev": true, - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/bcrypt-pbkdf/node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "dev": true - }, - "node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", - "dev": true - }, - "node_modules/bigint-crypto-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/bigint-crypto-utils/-/bigint-crypto-utils-3.3.0.tgz", - "integrity": "sha512-jOTSb+drvEDxEq6OuUybOAv/xxoh3cuYRUIPyu8sSHQNKM303UQ2R1DAo45o1AkcIXw6fzbaFI1+xGGdaXs2lg==", - "dev": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/bignumber.js": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", - "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bip39": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.4.tgz", - "integrity": "sha512-YZKQlb752TrUWqHWj7XAwCSjYEgGAk+/Aas3V7NyjQeZYsztO8JnQUaCWhcnL4T+jL8nvB8typ2jRPzTlgugNw==", - "dev": true, - "dependencies": { - "@types/node": "11.11.6", - "create-hash": "^1.1.0", - "pbkdf2": "^3.0.9", - "randombytes": "^2.0.1" - } - }, - "node_modules/bip39/node_modules/@types/node": { - "version": "11.11.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz", - "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==", - "dev": true - }, - "node_modules/blakejs": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", - "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==", - "dev": true - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true, - "peer": true - }, - "node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", - "dev": true - }, - "node_modules/browser-level": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browser-level/-/browser-level-1.0.1.tgz", - "integrity": "sha512-XECYKJ+Dbzw0lbydyQuJzwNXtOpbMSq737qxJN11sIRTErOMShvDpbzTlgju7orJKvx4epULolZAuJGLzCmWRQ==", - "dev": true, - "dependencies": { - "abstract-level": "^1.0.2", - "catering": "^2.1.1", - "module-error": "^1.0.2", - "run-parallel-limit": "^1.1.0" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "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" - } - }, - "node_modules/browserify-aes/node_modules/buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", - "dev": true - }, - "node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "dev": true, - "dependencies": { - "base-x": "^3.0.2" - } - }, - "node_modules/bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "dev": true, - "dependencies": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/buffer-xor": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-2.0.2.tgz", - "integrity": "sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.1" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/case": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/case/-/case-1.6.3.tgz", - "integrity": "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "dev": true - }, - "node_modules/catering": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/catering/-/catering-2.1.1.tgz", - "integrity": "sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/chai": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", - "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", - "dev": true, - "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" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.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" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/classic-level": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/classic-level/-/classic-level-1.4.1.tgz", - "integrity": "sha512-qGx/KJl3bvtOHrGau2WklEZuXhS3zme+jf+fsu6Ej7W7IP/C49v7KNlWIsT1jZu0YnfzSIYDGcEWpCa1wKGWXQ==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "abstract-level": "^1.0.2", - "catering": "^2.1.0", - "module-error": "^1.0.1", - "napi-macros": "^2.2.2", - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/command-exists": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", - "dev": true - }, - "node_modules/command-line-args": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", - "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", - "dev": true, - "dependencies": { - "array-back": "^3.1.0", - "find-replace": "^3.0.0", - "lodash.camelcase": "^4.3.0", - "typical": "^4.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/command-line-usage": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.3.tgz", - "integrity": "sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==", - "dev": true, - "dependencies": { - "array-back": "^4.0.2", - "chalk": "^2.4.2", - "table-layout": "^1.0.2", - "typical": "^5.2.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/command-line-usage/node_modules/array-back": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", - "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/command-line-usage/node_modules/typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/core-js-pure": { - "version": "3.36.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.36.1.tgz", - "integrity": "sha512-NXCvHvSVYSrewP0L5OhltzXeWFJLo2AL2TYnj6iLV3Bw8mM62wAQMNgUCRI6EBu6hVVpbCxmOPlxh1Ikw2PfUA==", - "dev": true, - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true - }, - "node_modules/crc-32": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", - "dev": true, - "bin": { - "crc32": "bin/crc32.njs" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "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" - } - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-eql": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", - "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", - "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/deferred-leveldown": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-5.3.0.tgz", - "integrity": "sha512-a59VOT+oDy7vtAbLRCZwWgxu2BaCfd5Hk7wxJd48ei7I+nsg8Orlb9CLG0PMZienk9BSUKgeAqkO2+Lw+1+Ukw==", - "dev": true, - "dependencies": { - "abstract-leveldown": "~6.2.1", - "inherits": "^2.0.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/deferred-leveldown/node_modules/abstract-leveldown": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz", - "integrity": "sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==", - "dev": true, - "dependencies": { - "buffer": "^5.5.0", - "immediate": "^3.2.3", - "level-concat-iterator": "~2.0.0", - "level-supports": "~1.0.0", - "xtend": "~4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "dev": true, - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dev": true, - "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" - } - }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/emittery": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.0.tgz", - "integrity": "sha512-AGvFfs+d0JKCJQ4o01ASQLGPmSCxgfU9RFXvzPvZdjKK8oscynksuJhWrSTSw7j7Ep/sZct5b5ZhYCi8S/t0HQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/encoding-down": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-6.3.0.tgz", - "integrity": "sha512-QKrV0iKR6MZVJV08QY0wp1e7vF6QbhnbQhb07bwpEyuz4uZiZgPlEGdkCROuFkUwdxlFaiPIhjyarH1ee/3vhw==", - "dev": true, - "dependencies": { - "abstract-leveldown": "^6.2.1", - "inherits": "^2.0.3", - "level-codec": "^9.0.0", - "level-errors": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/enquirer": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", - "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "dev": true, - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "peer": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/eth-ens-namehash": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz", - "integrity": "sha512-VWEI1+KJfz4Km//dadyvBBoBeSQ0MHTXPvr8UIXiLW6IanxvAV+DmlZAijZwAyggqGUfwQBeHf7tc9wzc1piSw==", - "dev": true, - "peer": true, - "dependencies": { - "idna-uts46-hx": "^2.3.1", - "js-sha3": "^0.5.7" - } - }, - "node_modules/eth-ens-namehash/node_modules/js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g==", - "dev": true, - "peer": true - }, - "node_modules/ethereum-bloom-filters": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.1.0.tgz", - "integrity": "sha512-J1gDRkLpuGNvWYzWslBQR9cDV4nd4kfvVTE/Wy4Kkm4yb3EYRSlyi0eB/inTsSTTVyA0+HyzHgbr95Fn/Z1fSw==", - "dev": true, - "peer": true, - "dependencies": { - "@noble/hashes": "^1.4.0" - } - }, - "node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, - "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" - } - }, - "node_modules/ethereum-waffle": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/ethereum-waffle/-/ethereum-waffle-4.0.10.tgz", - "integrity": "sha512-iw9z1otq7qNkGDNcMoeNeLIATF9yKl1M8AIeu42ElfNBplq0e+5PeasQmm8ybY/elkZ1XyRO0JBQxQdVRb8bqQ==", - "dev": true, - "dependencies": { - "@ethereum-waffle/chai": "4.0.10", - "@ethereum-waffle/compiler": "4.0.3", - "@ethereum-waffle/mock-contract": "4.0.4", - "@ethereum-waffle/provider": "4.0.5", - "solc": "0.8.15", - "typechain": "^8.0.0" - }, - "bin": { - "waffle": "bin/waffle" - }, - "engines": { - "node": ">=10.0" - }, - "peerDependencies": { - "ethers": "*" - } - }, - "node_modules/ethereumjs-abi": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", - "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.8", - "ethereumjs-util": "^6.0.0" - } - }, - "node_modules/ethereumjs-abi/node_modules/@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/ethereumjs-abi/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/ethereumjs-abi/node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, - "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" - } - }, - "node_modules/ethereumjs-util": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.3.tgz", - "integrity": "sha512-y+82tEbyASO0K0X1/SRhbJJoAlfcvq8JbrG4a5cjrOks7HS/36efU/0j2flxCPOUM++HFahk33kr/ZxyC4vNuw==", - "dev": true, - "dependencies": { - "@types/bn.js": "^5.1.0", - "bn.js": "^5.1.2", - "create-hash": "^1.1.2", - "ethereum-cryptography": "^0.1.3", - "rlp": "^2.2.4" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" - } - }, - "node_modules/ethjs-unit": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", - "integrity": "sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==", - "dev": true, - "peer": true, - "dependencies": { - "bn.js": "4.11.6", - "number-to-bn": "1.7.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/ethjs-unit/node_modules/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", - "dev": true, - "peer": true - }, - "node_modules/ethjs-util": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", - "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", - "dev": true, - "dependencies": { - "is-hex-prefixed": "1.0.0", - "strip-hex-prefix": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "dev": true, - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/ffjavascript": { - "version": "0.2.63", - "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.63.tgz", - "integrity": "sha512-dBgdsfGks58b66JnUZeZpGxdMIDQ4QsD3VYlRJyFVrKQHb2kJy4R2gufx5oetrTxXPT+aEjg0dOvOLg1N0on4A==", - "dev": true, - "dependencies": { - "wasmbuilder": "0.0.16", - "wasmcurves": "0.2.2", - "web-worker": "1.2.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-replace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", - "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", - "dev": true, - "dependencies": { - "array-back": "^3.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", - "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fp-ts": { - "version": "1.19.3", - "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz", - "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==", - "dev": true - }, - "node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true - }, - "node_modules/ganache": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/ganache/-/ganache-7.4.3.tgz", - "integrity": "sha512-RpEDUiCkqbouyE7+NMXG26ynZ+7sGiODU84Kz+FVoXUnQ4qQM4M8wif3Y4qUCt+D/eM1RVeGq0my62FPD6Y1KA==", - "bundleDependencies": [ - "@trufflesuite/bigint-buffer", - "emittery", - "keccak", - "leveldown", - "secp256k1", - "@types/bn.js", - "@types/lru-cache", - "@types/seedrandom" - ], - "dev": true, - "hasShrinkwrap": true, - "dependencies": { - "@trufflesuite/bigint-buffer": "1.1.10", - "@types/bn.js": "^5.1.0", - "@types/lru-cache": "5.1.1", - "@types/seedrandom": "3.0.1", - "emittery": "0.10.0", - "keccak": "3.0.2", - "leveldown": "6.1.0", - "secp256k1": "4.0.3" - }, - "bin": { - "ganache": "dist/node/cli.js", - "ganache-cli": "dist/node/cli.js" - }, - "optionalDependencies": { - "bufferutil": "4.0.5", - "utf-8-validate": "5.0.7" - } - }, - "node_modules/ganache/node_modules/@trufflesuite/bigint-buffer": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/@trufflesuite/bigint-buffer/-/bigint-buffer-1.1.10.tgz", - "integrity": "sha512-pYIQC5EcMmID74t26GCC67946mgTJFiLXOT/BYozgrd4UEY2JHEGLhWi9cMiQCt5BSqFEvKkCHNnoj82SRjiEw==", - "dev": true, - "hasInstallScript": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "node-gyp-build": "4.4.0" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/ganache/node_modules/@trufflesuite/bigint-buffer/node_modules/node-gyp-build": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.4.0.tgz", - "integrity": "sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ==", - "dev": true, - "inBundle": true, - "license": "MIT", - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/ganache/node_modules/@types/bn.js": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz", - "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/ganache/node_modules/@types/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache/node_modules/@types/node": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.0.tgz", - "integrity": "sha512-eMhwJXc931Ihh4tkU+Y7GiLzT/y/DBNpNtr4yU9O2w3SYBsr9NaOPhQlLKRmoWtI54uNwuo0IOUFQjVOTZYRvw==", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache/node_modules/@types/seedrandom": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-3.0.1.tgz", - "integrity": "sha512-giB9gzDeiCeloIXDgzFBCgjj1k4WxcDrZtGl6h1IqmUPlxF+Nx8Ve+96QCyDZ/HseB/uvDsKbpib9hU5cU53pw==", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache/node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache/node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "inBundle": true, - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/ganache/node_modules/bufferutil": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.5.tgz", - "integrity": "sha512-HTm14iMQKK2FjFLRTM5lAVcyaUzOnqbPtesFIvREgXpJHdQm8bWS+GkQgIkfaBYRHuCnea7w8UVNfwiAQhlr9A==", - "dev": true, - "optional": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - } - }, - "node_modules/ganache/node_modules/catering": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/catering/-/catering-2.1.0.tgz", - "integrity": "sha512-M5imwzQn6y+ODBfgi+cfgZv2hIUI6oYU/0f35Mdb1ujGeqeoI5tOnl9Q13DTH7LW+7er+NYq8stNOKZD/Z3U/A==", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "queue-tick": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache/node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dev": true, - "inBundle": true, - "license": "MIT", - "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" - } - }, - "node_modules/ganache/node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache/node_modules/emittery": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.0.tgz", - "integrity": "sha512-AGvFfs+d0JKCJQ4o01ASQLGPmSCxgfU9RFXvzPvZdjKK8oscynksuJhWrSTSw7j7Ep/sZct5b5ZhYCi8S/t0HQ==", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/ganache/node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/ganache/node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/ganache/node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "inBundle": true, - "license": "BSD-3-Clause" - }, - "node_modules/ganache/node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/ganache/node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache/node_modules/keccak": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.2.tgz", - "integrity": "sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ==", - "dev": true, - "hasInstallScript": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/ganache/node_modules/leveldown": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-6.1.0.tgz", - "integrity": "sha512-8C7oJDT44JXxh04aSSsfcMI8YiaGRhOFI9/pMEL7nWJLVsWajDPTRxsSHTM2WcTVY5nXM+SuRHzPPi0GbnDX+w==", - "dev": true, - "hasInstallScript": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "abstract-leveldown": "^7.2.0", - "napi-macros": "~2.0.0", - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/ganache/node_modules/leveldown/node_modules/abstract-leveldown": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-7.2.0.tgz", - "integrity": "sha512-DnhQwcFEaYsvYDnACLZhMmCWd3rkOeEvglpa4q5i/5Jlm3UIsWaxVzuXvDLFCSCWRO3yy2/+V/G7FusFgejnfQ==", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "buffer": "^6.0.3", - "catering": "^2.0.0", - "is-buffer": "^2.0.5", - "level-concat-iterator": "^3.0.0", - "level-supports": "^2.0.1", - "queue-microtask": "^1.2.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ganache/node_modules/leveldown/node_modules/level-concat-iterator": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/level-concat-iterator/-/level-concat-iterator-3.1.0.tgz", - "integrity": "sha512-BWRCMHBxbIqPxJ8vHOvKUsaO0v1sLYZtjN3K2iZJsRBYtp+ONsY6Jfi6hy9K3+zolgQRryhIn2NRZjZnWJ9NmQ==", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "catering": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ganache/node_modules/leveldown/node_modules/level-supports": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-2.1.0.tgz", - "integrity": "sha512-E486g1NCjW5cF78KGPrMDRBYzPuueMZ6VBXHT6gC7A8UYWGiM14fGgp+s/L1oFfDWSPV/+SFkYCmZ0SiESkRKA==", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/ganache/node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/ganache/node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache/node_modules/napi-macros": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.0.0.tgz", - "integrity": "sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg==", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache/node_modules/node-addon-api": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache/node_modules/node-gyp-build": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.3.0.tgz", - "integrity": "sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==", - "dev": true, - "inBundle": true, - "license": "MIT", - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/ganache/node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache/node_modules/queue-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.0.tgz", - "integrity": "sha512-ULWhjjE8BmiICGn3G8+1L9wFpERNxkf8ysxkAer4+TFdRefDaXOCV5m92aMB9FtBVmn/8sETXLXY6BfW7hyaWQ==", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/ganache/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache/node_modules/secp256k1": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz", - "integrity": "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==", - "dev": true, - "hasInstallScript": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "elliptic": "^6.5.4", - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/ganache/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/ganache/node_modules/utf-8-validate": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.7.tgz", - "integrity": "sha512-vLt1O5Pp+flcArHGIyKEQq883nBt8nN8tVBcoL0qUXj2XT1n7p70yGIq2VK98I5FdZ1YHc0wk/koOnHjnXWk1Q==", - "dev": true, - "optional": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - } - }, - "node_modules/ganache/node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "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" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dev": true, - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/hardhat": { - "version": "2.18.3", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.18.3.tgz", - "integrity": "sha512-JuYaTG+4ZHVjEHCW5Hn6jCHH3LpO75dtgznZpM/dLv12RcSlw/xHbeQh3FAsGahQr1epKryZcZEMHvztVZHe0g==", - "dev": true, - "dependencies": { - "@ethersproject/abi": "^5.1.2", - "@metamask/eth-sig-util": "^4.0.0", - "@nomicfoundation/ethereumjs-block": "5.0.2", - "@nomicfoundation/ethereumjs-blockchain": "7.0.2", - "@nomicfoundation/ethereumjs-common": "4.0.2", - "@nomicfoundation/ethereumjs-evm": "2.0.2", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "@nomicfoundation/ethereumjs-statemanager": "2.0.2", - "@nomicfoundation/ethereumjs-trie": "6.0.2", - "@nomicfoundation/ethereumjs-tx": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "@nomicfoundation/ethereumjs-vm": "7.0.2", - "@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", - "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.7.3", - "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" - }, - "bin": { - "hardhat": "internal/cli/bootstrap.js" - }, - "peerDependencies": { - "ts-node": "*", - "typescript": "*" - }, - "peerDependenciesMeta": { - "ts-node": { - "optional": true - }, - "typescript": { - "optional": true - } - } - }, - "node_modules/hardhat/node_modules/@noble/hashes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", - "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] - }, - "node_modules/hardhat/node_modules/@scure/bip32": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz", - "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "@noble/hashes": "~1.2.0", - "@noble/secp256k1": "~1.7.0", - "@scure/base": "~1.1.0" - } - }, - "node_modules/hardhat/node_modules/@scure/bip39": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz", - "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "@noble/hashes": "~1.2.0", - "@scure/base": "~1.1.0" - } - }, - "node_modules/hardhat/node_modules/commander": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", - "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", - "dev": true - }, - "node_modules/hardhat/node_modules/ethereum-cryptography": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", - "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", - "dev": true, - "dependencies": { - "@noble/hashes": "1.2.0", - "@noble/secp256k1": "1.7.1", - "@scure/bip32": "1.1.5", - "@scure/bip39": "1.1.1" - } - }, - "node_modules/hardhat/node_modules/jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/hardhat/node_modules/keccak": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", - "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/hardhat/node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/hardhat/node_modules/solc": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.7.3.tgz", - "integrity": "sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==", - "dev": true, - "dependencies": { - "command-exists": "^1.2.8", - "commander": "3.0.2", - "follow-redirects": "^1.12.1", - "fs-extra": "^0.30.0", - "js-sha3": "0.8.0", - "memorystream": "^0.3.1", - "require-from-string": "^2.0.0", - "semver": "^5.5.0", - "tmp": "0.0.33" - }, - "bin": { - "solcjs": "solcjs" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/hardhat/node_modules/solc/node_modules/fs-extra": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", - "integrity": "sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" - } - }, - "node_modules/hardhat/node_modules/solc/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "dev": true, - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/idna-uts46-hx": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz", - "integrity": "sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA==", - "dev": true, - "peer": true, - "dependencies": { - "punycode": "2.1.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/immediate": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.3.0.tgz", - "integrity": "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==", - "dev": true - }, - "node_modules/immutable": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz", - "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==", - "dev": true - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/io-ts": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-1.10.4.tgz", - "integrity": "sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==", - "dev": true, - "dependencies": { - "fp-ts": "^1.0.0" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, - "peer": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "engines": { - "node": ">=4" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-hex-prefixed": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", - "integrity": "sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==", - "dev": true, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", - "dev": true - }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", - "dev": true, - "peer": true - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "dev": true - }, - "node_modules/js-sdsl": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.2.tgz", - "integrity": "sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, - "node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "dev": true - }, - "node_modules/json-bigint": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", - "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", - "dev": true, - "dependencies": { - "bignumber.js": "^9.0.0" - } - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "dev": true, - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/keccak": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", - "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.9" - } - }, - "node_modules/lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw==", - "dev": true, - "peer": true, - "dependencies": { - "invert-kv": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/level": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/level/-/level-8.0.1.tgz", - "integrity": "sha512-oPBGkheysuw7DmzFQYyFe8NAia5jFLAgEnkgWnK3OXAuJr8qFT+xBQIwokAZPME2bhPFzS8hlYcL16m8UZrtwQ==", - "dev": true, - "dependencies": { - "abstract-level": "^1.0.4", - "browser-level": "^1.0.1", - "classic-level": "^1.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/level" - } - }, - "node_modules/level-codec": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.2.tgz", - "integrity": "sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ==", - "dev": true, - "dependencies": { - "buffer": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-concat-iterator": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/level-concat-iterator/-/level-concat-iterator-2.0.1.tgz", - "integrity": "sha512-OTKKOqeav2QWcERMJR7IS9CUo1sHnke2C0gkSmcR7QuEtFNLLzHQAvnMw8ykvEcv0Qtkg0p7FOwP1v9e5Smdcw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz", - "integrity": "sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==", - "dev": true, - "dependencies": { - "errno": "~0.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-iterator-stream": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-4.0.2.tgz", - "integrity": "sha512-ZSthfEqzGSOMWoUGhTXdX9jv26d32XJuHz/5YnuHZzH6wldfWMOVwI9TBtKcya4BKTyTt3XVA0A3cF3q5CY30Q==", - "dev": true, - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.4.0", - "xtend": "^4.0.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-mem": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/level-mem/-/level-mem-5.0.1.tgz", - "integrity": "sha512-qd+qUJHXsGSFoHTziptAKXoLX87QjR7v2KMbqncDXPxQuCdsQlzmyX+gwrEHhlzn08vkf8TyipYyMmiC6Gobzg==", - "dev": true, - "dependencies": { - "level-packager": "^5.0.3", - "memdown": "^5.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-packager": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/level-packager/-/level-packager-5.1.1.tgz", - "integrity": "sha512-HMwMaQPlTC1IlcwT3+swhqf/NUO+ZhXVz6TY1zZIIZlIR0YSn8GtAAWmIvKjNY16ZkEg/JcpAuQskxsXqC0yOQ==", - "dev": true, - "dependencies": { - "encoding-down": "^6.3.0", - "levelup": "^4.3.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-supports": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-1.0.1.tgz", - "integrity": "sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg==", - "dev": true, - "dependencies": { - "xtend": "^4.0.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-transcoder": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/level-transcoder/-/level-transcoder-1.0.1.tgz", - "integrity": "sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w==", - "dev": true, - "dependencies": { - "buffer": "^6.0.3", - "module-error": "^1.0.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/level-transcoder/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/level-ws": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-2.0.0.tgz", - "integrity": "sha512-1iv7VXx0G9ec1isqQZ7y5LmoZo/ewAsyDHNA8EFDW5hqH2Kqovm33nSFkSdnLLAK+I5FlT+lo5Cw9itGe+CpQA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "readable-stream": "^3.1.0", - "xtend": "^4.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/levelup": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/levelup/-/levelup-4.4.0.tgz", - "integrity": "sha512-94++VFO3qN95cM/d6eBXvd894oJE0w3cInq9USsyQzzoJxmiYzPAocNcuGCPGGjoXqDVJcr3C1jzt1TSjyaiLQ==", - "dev": true, - "dependencies": { - "deferred-leveldown": "~5.3.0", - "level-errors": "~2.0.0", - "level-iterator-stream": "~4.0.0", - "level-supports": "~1.0.0", - "xtend": "~4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==", - "dev": true, - "peer": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha512-hFuH8TY+Yji7Eja3mGiuAxBqLagejScbG8GbG0j6o9vzn0YL14My+ktnqtZgFTosKymC9/44wP6s7xyuLfnClw==", - "dev": true, - "peer": true - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/loupe": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", - "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.1" - } - }, - "node_modules/lru_map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", - "dev": true - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/ltgt": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", - "integrity": "sha512-AI2r85+4MquTw9ZYqabu4nMwy9Oftlfa/e/52t9IjtfG+mGBbTNdAoZ3RQKLHR6r0wQnwZnPIEh/Ya6XTWAKNA==", - "dev": true - }, - "node_modules/mcl-wasm": { - "version": "0.7.9", - "resolved": "https://registry.npmjs.org/mcl-wasm/-/mcl-wasm-0.7.9.tgz", - "integrity": "sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ==", - "dev": true, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/memdown": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/memdown/-/memdown-5.1.0.tgz", - "integrity": "sha512-B3J+UizMRAlEArDjWHTMmadet+UKwHd3UjMgGBkZcKAxAYVPS9o0Yeiha4qvz7iGiL2Sb3igUft6p7nbFWctpw==", - "dev": true, - "dependencies": { - "abstract-leveldown": "~6.2.1", - "functional-red-black-tree": "~1.0.1", - "immediate": "~3.2.3", - "inherits": "~2.0.1", - "ltgt": "~2.2.0", - "safe-buffer": "~5.2.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/memdown/node_modules/abstract-leveldown": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz", - "integrity": "sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==", - "dev": true, - "dependencies": { - "buffer": "^5.5.0", - "immediate": "^3.2.3", - "level-concat-iterator": "~2.0.0", - "level-supports": "~1.0.0", - "xtend": "~4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/memdown/node_modules/immediate": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", - "integrity": "sha512-RrGCXRm/fRVqMIhqXrGEX9rRADavPiDFSoMb/k64i9XMk8uH4r/Omi5Ctierj6XzNecwDbO4WuFbDD1zmpl3Tg==", - "dev": true - }, - "node_modules/memory-level": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/memory-level/-/memory-level-1.0.0.tgz", - "integrity": "sha512-UXzwewuWeHBz5krr7EvehKcmLFNoXxGcvuYhC41tRnkrTbJohtS7kVn9akmgirtRygg+f7Yjsfi8Uu5SGSQ4Og==", - "dev": true, - "dependencies": { - "abstract-level": "^1.0.0", - "functional-red-black-tree": "^1.0.1", - "module-error": "^1.0.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", - "dev": true, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/merkle-patricia-tree": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-4.2.4.tgz", - "integrity": "sha512-eHbf/BG6eGNsqqfbLED9rIqbsF4+sykEaBn6OLNs71tjclbMcMOk1tEPmJKcNcNCLkvbpY/lwyOlizWsqPNo8w==", - "dev": true, - "dependencies": { - "@types/levelup": "^4.3.0", - "ethereumjs-util": "^7.1.4", - "level-mem": "^5.0.1", - "level-ws": "^2.0.0", - "readable-stream": "^3.6.0", - "semaphore-async-await": "^1.5.1" - } - }, - "node_modules/merkle-patricia-tree/node_modules/ethereumjs-util": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz", - "integrity": "sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==", - "dev": true, - "dependencies": { - "@types/bn.js": "^5.1.0", - "bn.js": "^5.1.2", - "create-hash": "^1.1.2", - "ethereum-cryptography": "^0.1.3", - "rlp": "^2.2.4" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/micro-ftch": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/micro-ftch/-/micro-ftch-0.3.1.tgz", - "integrity": "sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==", - "dev": true, - "peer": true - }, - "node_modules/miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "dependencies": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "bin": { - "miller-rabin": "bin/miller-rabin" - } - }, - "node_modules/miller-rabin/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", - "dev": true - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mnemonist": { - "version": "0.38.5", - "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz", - "integrity": "sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==", - "dev": true, - "dependencies": { - "obliterator": "^2.0.0" - } - }, - "node_modules/mocha": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz", - "integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==", - "dev": true, - "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": "8.1.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.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" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/mocha/node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.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" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mocha/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/module-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/module-error/-/module-error-1.0.2.tgz", - "integrity": "sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/napi-macros": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.2.2.tgz", - "integrity": "sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g==", - "dev": true - }, - "node_modules/node-addon-api": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", - "dev": true - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-gyp-build": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.3.0.tgz", - "integrity": "sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==", - "dev": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "peer": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "peer": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/number-to-bn": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", - "integrity": "sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==", - "dev": true, - "peer": true, - "dependencies": { - "bn.js": "4.11.6", - "strip-hex-prefix": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/number-to-bn/node_modules/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", - "dev": true, - "peer": true - }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/obliterator": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", - "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==", - "dev": true - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g==", - "dev": true, - "peer": true, - "dependencies": { - "lcid": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", - "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", - "dev": true, - "peer": true, - "dependencies": { - "error-ex": "^1.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true - }, - "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==", - "dev": true, - "peer": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "dev": true, - "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" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", - "dev": true, - "peer": true, - "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", - "dev": true - }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, - "node_modules/punycode": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", - "integrity": "sha512-Yxz2kRwT90aPiWEMHVYnEf4+rhwF1tBmmZ4KepCP+Wkium9JxtWnUm1nqGwpiAHr/tnTSeHqr3wb++jgSkXjhA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==", - "dev": true, - "peer": true, - "dependencies": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==", - "dev": true, - "peer": true, - "dependencies": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==", - "dev": true, - "peer": true, - "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==", - "dev": true, - "peer": true, - "dependencies": { - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/reduce-flatten": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", - "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dev": true, - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request/node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/request/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", - "integrity": "sha512-H7AkJWMobeskkttHyhTVtS0fxpFLjxhbfMa6Bk3wimP7sdPRGL3EyCg3sAQenFfAe+xQ+oAc85Nmtvq0ROM83Q==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==", - "dev": true, - "peer": true - }, - "node_modules/resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "dependencies": { - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/rlp": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.6.tgz", - "integrity": "sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.1" - }, - "bin": { - "rlp": "bin/rlp" - } - }, - "node_modules/rlp/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/run-parallel-limit": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz", - "integrity": "sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rustbn.js": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz", - "integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==", - "dev": true - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/scrypt-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", - "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", - "dev": true - }, - "node_modules/secp256k1": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz", - "integrity": "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "elliptic": "^6.5.4", - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/seedrandom": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", - "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==", - "dev": true - }, - "node_modules/semaphore-async-await": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/semaphore-async-await/-/semaphore-async-await-1.5.1.tgz", - "integrity": "sha512-b/ptP11hETwYWpeilHXXQiV5UJNJl7ZWWooKRE5eBIYWoom6dZ0SluCIdCtKycsMtZgKWE01/qAw6jblw1YVhg==", - "dev": true, - "engines": { - "node": ">=4.1" - } - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true, - "peer": true - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/snarkjs": { - "resolved": "..", - "link": true - }, - "node_modules/solc": { - "version": "0.8.15", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.15.tgz", - "integrity": "sha512-Riv0GNHNk/SddN/JyEuFKwbcWcEeho15iyupTSHw5Np6WuXA5D8kEHbyzDHi6sqmvLzu2l+8b1YmL8Ytple+8w==", - "dev": true, - "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" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/solc/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "peer": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true, - "peer": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "peer": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", - "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", - "dev": true, - "peer": true - }, - "node_modules/sshpk": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", - "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", - "dev": true, - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sshpk/node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "dev": true - }, - "node_modules/stacktrace-parser": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", - "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", - "dev": true, - "dependencies": { - "type-fest": "^0.7.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/stacktrace-parser/node_modules/type-fest": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", - "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-format": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz", - "integrity": "sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==", - "dev": true - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", - "dev": true, - "peer": true, - "dependencies": { - "is-utf8": "^0.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-hex-prefix": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", - "integrity": "sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==", - "dev": true, - "dependencies": { - "is-hex-prefixed": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/table-layout": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz", - "integrity": "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==", - "dev": true, - "dependencies": { - "array-back": "^4.0.1", - "deep-extend": "~0.6.0", - "typical": "^5.2.0", - "wordwrapjs": "^4.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/table-layout/node_modules/array-back": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", - "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/table-layout/node_modules/typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/testrpc": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/testrpc/-/testrpc-0.0.1.tgz", - "integrity": "sha512-afH1hO+SQ/VPlmaLUFj2636QMeDvPCeQMc/9RBMW0IfjNe9gFD9Ra3ShqYkB7py0do1ZcCna/9acHyzTJ+GcNA==", - "deprecated": "testrpc has been renamed to ganache-cli, please use this package from now on.", - "dev": true, - "peer": true - }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tough-cookie/node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, - "node_modules/ts-command-line-args": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz", - "integrity": "sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw==", - "dev": true, - "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" - } - }, - "node_modules/ts-command-line-args/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ts-command-line-args/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ts-command-line-args/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/ts-command-line-args/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/ts-command-line-args/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ts-command-line-args/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ts-essentials": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz", - "integrity": "sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==", - "dev": true, - "peerDependencies": { - "typescript": ">=3.7.0" - } - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tsort": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", - "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==", - "dev": true - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", - "dev": true - }, - "node_modules/tweetnacl-util": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", - "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==", - "dev": true - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typechain": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.3.2.tgz", - "integrity": "sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==", - "dev": true, - "dependencies": { - "@types/prettier": "^2.1.1", - "debug": "^4.3.1", - "fs-extra": "^7.0.0", - "glob": "7.1.7", - "js-sha3": "^0.8.0", - "lodash": "^4.17.15", - "mkdirp": "^1.0.4", - "prettier": "^2.3.1", - "ts-command-line-args": "^2.2.0", - "ts-essentials": "^7.0.1" - }, - "bin": { - "typechain": "dist/cli/cli.js" - }, - "peerDependencies": { - "typescript": ">=4.3.0" - } - }, - "node_modules/typechain/node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, - "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" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/typechain/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/typescript": { - "version": "5.4.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz", - "integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==", - "dev": true, - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/typical": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", - "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/undici": { - "version": "5.28.4", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", - "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", - "dev": true, - "dependencies": { - "@fastify/busboy": "^2.0.0" - }, - "engines": { - "node": ">=14.0" - } - }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz", - "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", - "dev": true, - "dependencies": { - "punycode": "^1.4.1", - "qs": "^6.11.2" - } - }, - "node_modules/url/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true - }, - "node_modules/url/node_modules/qs": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.0.tgz", - "integrity": "sha512-trVZiI6RMOkO476zLGaBIzszOdFPnCCXHPG9kn0yuS1uz6xdVxPfZdB3vUig9pxPFDM9BRAgz/YUIVQ1/vuiUg==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", - "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", - "dev": true, - "peer": true - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "peer": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/wasmbuilder": { - "version": "0.0.16", - "resolved": "https://registry.npmjs.org/wasmbuilder/-/wasmbuilder-0.0.16.tgz", - "integrity": "sha512-Qx3lEFqaVvp1cEYW7Bfi+ebRJrOiwz2Ieu7ZG2l7YyeSJIok/reEQCQCuicj/Y32ITIJuGIM9xZQppGx5LrQdA==", - "dev": true - }, - "node_modules/wasmcurves": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/wasmcurves/-/wasmcurves-0.2.2.tgz", - "integrity": "sha512-JRY908NkmKjFl4ytnTu5ED6AwPD+8VJ9oc94kdq7h5bIwbj0L4TDJ69mG+2aLs2SoCmGfqIesMWTEJjtYsoQXQ==", - "dev": true, - "dependencies": { - "wasmbuilder": "0.0.16" - } - }, - "node_modules/web-worker": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.2.0.tgz", - "integrity": "sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==", - "dev": true - }, - "node_modules/web3-utils": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.10.4.tgz", - "integrity": "sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A==", - "dev": true, - "peer": true, - "dependencies": { - "@ethereumjs/util": "^8.1.0", - "bn.js": "^5.2.1", - "ethereum-bloom-filters": "^1.0.6", - "ethereum-cryptography": "^2.1.2", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-utils/node_modules/@noble/hashes": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", - "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/web3-utils/node_modules/ethereum-cryptography": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz", - "integrity": "sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==", - "dev": true, - "peer": true, - "dependencies": { - "@noble/curves": "1.3.0", - "@noble/hashes": "1.3.3", - "@scure/bip32": "1.3.3", - "@scure/bip39": "1.2.2" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ==", - "dev": true, - "peer": true - }, - "node_modules/window-size": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", - "integrity": "sha512-UD7d8HFA2+PZsbKyaOCEy8gMh1oDtHgJh1LfgjQ4zVXmYjAT/kvz3PueITKuqDiIXQe7yzpPnxX3lNc+AhQMyw==", - "dev": true, - "peer": true, - "bin": { - "window-size": "cli.js" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/wordwrapjs": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz", - "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==", - "dev": true, - "dependencies": { - "reduce-flatten": "^2.0.0", - "typical": "^5.2.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/wordwrapjs/node_modules/typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "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" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/smart_contract_tests/package.json b/smart_contract_tests/package.json deleted file mode 100644 index 1af5f754..00000000 --- a/smart_contract_tests/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "snarkjs-smart-contract-tests", - "private": true, - "type": "module", - "scripts": { - "test": "mocha" - }, - "devDependencies": { - "@nomiclabs/hardhat-ethers": "^2.2.3", - "@nomiclabs/hardhat-waffle": "^2.0.5", - "chai": "^4.3.7", - "ethereum-waffle": "^4.0.10", - "ethers": "^5.7.2", - "ffjavascript": "^0.2.63", - "hardhat": "2.18.3", - "mocha": "^10.2.0", - "snarkjs": "file:.." - } -} diff --git a/smart_contract_tests/test/smart_contracts.test.js b/smart_contract_tests/test/smart_contracts.test.js deleted file mode 100644 index d24f8bcf..00000000 --- a/smart_contract_tests/test/smart_contracts.test.js +++ /dev/null @@ -1,245 +0,0 @@ -import { expect } from "chai"; - -import { buildBn128 } from "ffjavascript"; -import path from "path"; -import hardhat from "hardhat"; -const { ethers, run } = hardhat; - -import * as snarkjs from "snarkjs"; - -import fs from "fs"; - -describe("Smart contracts test suite", function () { - this.timeout(1000000000); - - const ptauFilename = path.join("../test", "plonk_circuit", "powersOfTau15_final.ptau"); - - // Load templates - const templates = {}; - templates.groth16 = fs.readFileSync(path.join("../templates", "verifier_groth16.sol.ejs"), "utf8"); - templates.plonk = fs.readFileSync(path.join("../templates", "verifier_plonk.sol.ejs"), "utf8"); - templates.fflonk = fs.readFileSync(path.join("../templates", "verifier_fflonk.sol.ejs"), "utf8"); - - let verifierContract; - let curve; - - before(async () => { - await fs.promises.mkdir("contracts", {recursive: true}); - curve = await buildBn128(); - }); - - after(async () => { - await curve.terminate(); - }); - - it("Groth16 smart contract 1 input", async () => { - expect(await groth16Verify( - path.join("../test", "groth16", "circuit.r1cs"), - path.join("../test", "groth16", "witness.wtns") - )).to.be.equal(true); - }); - - it("Groth16 smart contract 1 aliased input", async () => { - expect( - await groth16VerifyAliased( - path.join("../test", "groth16", "circuit.r1cs"), - path.join("../test", "groth16", "witness.wtns") - ) - ).to.be.equal(false); - }); - - it("Groth16 smart contract 3 inputs", async () => { - expect(await groth16Verify( - path.join("../test", "circuit2", "circuit.r1cs"), - path.join("../test", "circuit2", "witness.wtns") - )).to.be.equal(true); - }); - - it("Plonk smart contract 1 input", async () => { - expect(await plonkVerify( - path.join("../test", "plonk_circuit", "circuit.r1cs"), - path.join("../test", "plonk_circuit", "witness.wtns") - )).to.be.equal(true); - }); - - it("Plonk smart contract 3 inputs", async () => { - expect(await plonkVerify( - path.join("../test", "circuit2", "circuit.r1cs"), - path.join("../test", "circuit2", "witness.wtns") - )).to.be.equal(true); - }); - - it("Fflonk smart contract 1 input", async () => { - expect(await fflonkVerify( - path.join("../test", "fflonk", "circuit.r1cs"), - path.join("../test", "fflonk", "witness.wtns") - )).to.be.equal(true); - }); - - it("Fflonk smart contract 3 inputs", async () => { - expect(await fflonkVerify( - path.join("../test", "circuit2", "circuit.r1cs"), - path.join("../test", "circuit2", "witness.wtns") - )).to.be.equal(true); - }); - - async function groth16Verify(r1csFilename, wtnsFilename) { - const solidityVerifierFilename = path.join("contracts", "groth16.sol"); - - const zkeyFilename = { type: "mem" }; - - await snarkjs.zKey.newZKey(r1csFilename, ptauFilename, zkeyFilename); - const { proof: proof, publicSignals: publicInputs } = await snarkjs.groth16.prove(zkeyFilename, wtnsFilename); - - const proofA = [proof.pi_a[0], proof.pi_a[1]]; - const proofB = [[proof.pi_b[0][1], proof.pi_b[0][0]], [proof.pi_b[1][1], proof.pi_b[1][0]]]; - const proofC = [proof.pi_c[0], proof.pi_c[1]]; - - // Generate groth16 verifier solidity file from groth16 template + zkey - const verifierCode = await snarkjs.zKey.exportSolidityVerifier(zkeyFilename, templates); - fs.writeFileSync(solidityVerifierFilename, verifierCode, "utf-8"); - - // Compile the groth16 verifier smart contract - await run("compile"); - - // Deploy mock groth16 verifier - const VerifierFactory = await ethers.getContractFactory("Groth16Verifier"); - verifierContract = await VerifierFactory.deploy(); - - return await verifierContract.verifyProof(proofA, proofB, proofC, publicInputs); - } - - async function groth16VerifyAliased(r1csFilename, wtnsFilename) { - const solidityVerifierFilename = path.join("contracts", "groth16.sol"); - - const zkeyFilename = { type: "mem" }; - - await snarkjs.zKey.newZKey(r1csFilename, ptauFilename, zkeyFilename); - const { proof: proof, publicSignals: publicInputs } = await snarkjs.groth16.prove(zkeyFilename, wtnsFilename); - - const proofA = [proof.pi_a[0], proof.pi_a[1]]; - const proofB = [[proof.pi_b[0][1], proof.pi_b[0][0]], [proof.pi_b[1][1], proof.pi_b[1][0]],]; - const proofC = [proof.pi_c[0], proof.pi_c[1]]; - - // Generate groth16 verifier solidity file from groth16 template + zkey - const verifierCode = await snarkjs.zKey.exportSolidityVerifier(zkeyFilename, templates); - fs.writeFileSync(solidityVerifierFilename, verifierCode, "utf-8"); - - // Compile the groth16 verifier smart contract - await run("compile"); - - let pi_with_alias = [...publicInputs]; - pi_with_alias[1] = BigInt(publicInputs[1]) + 21888242871839275222246405745257275088548364400416034343698204186575808495617n; - - // Deploy mock groth16 verifier - const VerifierFactory = await ethers.getContractFactory("Groth16Verifier"); - verifierContract = await VerifierFactory.deploy(); - - return await verifierContract.verifyProof(proofA, proofB, proofC, pi_with_alias); - } - - async function plonkVerify(r1csFilename, wtnsFilename) { - const solidityVerifierFilename = path.join("contracts", "plonk.sol"); - - const zkeyFilename = { type: "mem" }; - - await snarkjs.plonk.setup(r1csFilename, ptauFilename, zkeyFilename); - const { proof: proofJson, publicSignals: publicInputs } = await snarkjs.plonk.prove(zkeyFilename, wtnsFilename); - - // Generate plonk verifier solidity file from plonk template + zkey - const verifierCode = await snarkjs.zKey.exportSolidityVerifier(zkeyFilename, templates); - fs.writeFileSync(solidityVerifierFilename, verifierCode, "utf-8"); - - // Compile the plonk verifier smart contract - await run("compile"); - - // Deploy mock plonk verifier - const VerifierFactory = await ethers.getContractFactory("PlonkVerifier"); - verifierContract = await VerifierFactory.deploy(); - - // Verify the proof in the smart contract - const proof = - [ - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.A[0]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.A[1]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.B[0]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.B[1]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.C[0]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.C[1]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.Z[0]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.Z[1]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.T1[0]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.T1[1]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.T2[0]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.T2[1]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.T3[0]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.T3[1]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.Wxi[0]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.Wxi[1]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.Wxiw[0]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.Wxiw[1]).toHexString(), 32), - - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.eval_a).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.eval_b).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.eval_c).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.eval_s1).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.eval_s2).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(proofJson.eval_zw).toHexString(), 32), - ]; - - return await verifierContract.verifyProof(proof, publicInputs); - }; - - async function fflonkVerify(r1csFilename, wtnsFilename) { - const solidityVerifierFilename = path.join("contracts", "fflonk.sol"); - - const zkeyFilename = { type: "mem" }; - - await snarkjs.fflonk.setup(r1csFilename, ptauFilename, zkeyFilename); - const { proof: proofJson, publicSignals: publicInputs } = await snarkjs.fflonk.prove(zkeyFilename, wtnsFilename); - - // Generate fflonk verifier solidity file from fflonk template + zkey - const verifierCode = await snarkjs.zKey.exportSolidityVerifier(zkeyFilename, templates); - fs.writeFileSync(solidityVerifierFilename, verifierCode, "utf-8"); - - // Compile the fflonk verifier smart contract - await run("compile"); - - // Deploy mock fflonk verifier - const VerifierFactory = await ethers.getContractFactory("FflonkVerifier"); - verifierContract = await VerifierFactory.deploy(); - - // Verify the proof in the smart contract - const { evaluations, polynomials } = proofJson; - - const proof = - [ - ethers.utils.hexZeroPad(ethers.BigNumber.from(polynomials.C1[0]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(polynomials.C1[1]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(polynomials.C2[0]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(polynomials.C2[1]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(polynomials.W1[0]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(polynomials.W1[1]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(polynomials.W2[0]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(polynomials.W2[1]).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(evaluations.ql).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(evaluations.qr).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(evaluations.qm).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(evaluations.qo).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(evaluations.qc).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(evaluations.s1).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(evaluations.s2).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(evaluations.s3).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(evaluations.a).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(evaluations.b).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(evaluations.c).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(evaluations.z).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(evaluations.zw).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(evaluations.t1w).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(evaluations.t2w).toHexString(), 32), - ethers.utils.hexZeroPad(ethers.BigNumber.from(evaluations.inv).toHexString(), 32), - ]; - - return await verifierContract.verifyProof(proof, publicInputs); - }; -}); diff --git a/src/Keccak256Transcript.js b/src/Keccak256Transcript.js index 8c9185c1..5b38e05e 100644 --- a/src/Keccak256Transcript.js +++ b/src/Keccak256Transcript.js @@ -18,7 +18,7 @@ */ import {Scalar} from "ffjavascript"; -import {keccak_256} from "@noble/hashes/sha3"; +import {keccak_256} from "@noble/hashes/sha3.js"; const POLYNOMIAL = 0; const SCALAR = 1; diff --git a/src/clprocessor.js b/src/clprocessor.js index f1561415..43c1619c 100644 --- a/src/clprocessor.js +++ b/src/clprocessor.js @@ -32,7 +32,7 @@ const __dirname = path.dirname(url.fileURLToPath(import.meta.url)); let pkgS; try { pkgS = fs.readFileSync(path.join(__dirname, "package.json")); -} catch (err) { +} catch { pkgS = fs.readFileSync(path.join(__dirname, "..","package.json")); } diff --git a/src/fflonk_export_calldata.js b/src/fflonk_export_calldata.js index 0585e8db..c1397db7 100644 --- a/src/fflonk_export_calldata.js +++ b/src/fflonk_export_calldata.js @@ -22,10 +22,6 @@ import {utils} from "ffjavascript"; const {unstringifyBigInts} = utils; -function i2hex(i) { - return ("0" + i.toString(16)).slice(-2); -} - function p256(n) { let nstr = n.toString(16); while (nstr.length < 64) nstr = "0" + nstr; @@ -37,9 +33,7 @@ export default async function fflonkExportCallData(_pub, _proof) { const proof = unstringifyBigInts(_proof); const pub = unstringifyBigInts(_pub); - const curve = await getCurveFromName(proof.curve); - const G1 = curve.G1; - const Fr = curve.Fr; + await getCurveFromName(proof.curve); let inputs = ""; for (let i = 0; i < pub.length; i++) { diff --git a/src/groth16_prove.js b/src/groth16_prove.js index 5582e138..55b7a1aa 100644 --- a/src/groth16_prove.js +++ b/src/groth16_prove.js @@ -120,8 +120,11 @@ export default async function groth16Prove(zkeyFileName, witnessFileName, logger if (logger) logger.debug("Join ABC"); buffPodd_T = await joinABC(curve, zkey, buffAodd_T, buffBodd_T, buffCodd_T, logger); if (logger) logger.debug("Join ABC finished"); + // eslint-disable-next-line no-useless-assignment buffAodd_T = null; + // eslint-disable-next-line no-useless-assignment buffBodd_T = null; + // eslint-disable-next-line no-useless-assignment buffCodd_T = null; if (globalThis.gc) {globalThis.gc();} @@ -533,7 +536,6 @@ async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { console.log("nGroups", nGroups); - const transfers = []; let result2; if (nGroups > 1) { const promises2 = []; diff --git a/src/keypair.js b/src/keypair.js index f697004f..a8c2a5f3 100644 --- a/src/keypair.js +++ b/src/keypair.js @@ -17,7 +17,7 @@ along with snarkJS. If not, see . */ -import { blake2b } from "@noble/hashes/blake2b"; +import { blake2b } from "@noble/hashes/blake2.js"; import { ChaCha } from "ffjavascript"; diff --git a/src/misc.js b/src/misc.js index 12804fcd..6de4e5cb 100644 --- a/src/misc.js +++ b/src/misc.js @@ -17,9 +17,8 @@ along with snarkJS. If not, see . */ -/* global window */ -import { blake2b } from "@noble/hashes/blake2b"; -import { u32 } from "@noble/hashes/utils"; +import { blake2b } from "@noble/hashes/blake2.js"; +import { u32 } from "@noble/hashes/utils.js"; import readline from "readline"; import { ChaCha } from "ffjavascript"; import crypto from "crypto"; diff --git a/src/plonk_equation.js b/src/plonk_equation.js index c833df71..94737e62 100644 --- a/src/plonk_equation.js +++ b/src/plonk_equation.js @@ -30,6 +30,6 @@ export function getFFlonkAdditionConstraint(signal1, signal2, signalOut, ql, qr, return [signal1, signal2, signalOut, ql, qr, qm, qo, qc]; } -export function getFFlonkMultiplicationConstraint(signal1, signal2, signalOut, ql, qr, qm, qo, qc, Fr) { +export function getFFlonkMultiplicationConstraint(signal1, signal2, signalOut, ql, qr, qm, qo, qc, _Fr) { return [signal1, signal2, signalOut, ql, qr, qm, qo, qc]; } diff --git a/src/plonk_exportsoliditycalldata.js b/src/plonk_exportsoliditycalldata.js index d1bcce37..f07c1312 100644 --- a/src/plonk_exportsoliditycalldata.js +++ b/src/plonk_exportsoliditycalldata.js @@ -21,10 +21,6 @@ import { getCurveFromName } from "./curves.js"; import { utils } from "ffjavascript"; const { unstringifyBigInts} = utils; -function i2hex(i) { - return ("0" + i.toString(16)).slice(-2); -} - function p256(n) { let nstr = n.toString(16); while (nstr.length < 64) nstr = "0"+nstr; @@ -36,9 +32,7 @@ export default async function plonkExportSolidityCallData(_proof, _pub) { const proof = unstringifyBigInts(_proof); const pub = unstringifyBigInts(_pub); - const curve = await getCurveFromName(proof.curve); - const G1 = curve.G1; - const Fr = curve.Fr; + await getCurveFromName(proof.curve); let inputs = ""; for (let i=0; i maxC) { @@ -343,7 +343,7 @@ export default async function plonkSetup(r1csName, ptauName, zkeyName, logger) { // The value is stored in Montgomery. stored = v*R // so when montgomery multiplied by the witness, it's result = v*R*w/R = v*w buffOut.set(addition[2], o); o+= n8r; - buffOut.set(addition[3], o); o+= n8r; + buffOut.set(addition[3], o); await fdZKey.write(buffOut); if ((logger)&&(i%1000000 == 0)) logger.debug(`writing ${name}: ${i}/${plonkAdditions.length}`); } diff --git a/src/polynomial/polynomial.js b/src/polynomial/polynomial.js index fb4b9cb4..110210a8 100644 --- a/src/polynomial/polynomial.js +++ b/src/polynomial/polynomial.js @@ -673,26 +673,26 @@ export class Polynomial { return this; } -// function divideByVanishing(f, n, p) { -// // polynomial division f(X) / (X^n - 1) with remainder -// // very cheap, 0 multiplications -// // strategy: -// // start with q(X) = 0, r(X) = f(X) -// // then start changing q, r while preserving the identity: -// // f(X) = q(X) * (X^n - 1) + r(X) -// // in every step, move highest-degree term of r into the product -// // => r eventually has degree < n and we're done -// let q = Array(f.length).fill(0n); -// let r = [...f]; -// for (let i = f.length - 1; i >= n; i--) { -// let leadingCoeff = r[i]; -// if (leadingCoeff === 0n) continue; -// r[i] = 0n; -// r[i - n] = mod(r[i - n] + leadingCoeff, p); -// q[i - n] = mod(q[i - n] + leadingCoeff, p); -// } -// return [q, r]; -// } + // function divideByVanishing(f, n, p) { + // // polynomial division f(X) / (X^n - 1) with remainder + // // very cheap, 0 multiplications + // // strategy: + // // start with q(X) = 0, r(X) = f(X) + // // then start changing q, r while preserving the identity: + // // f(X) = q(X) * (X^n - 1) + r(X) + // // in every step, move highest-degree term of r into the product + // // => r eventually has degree < n and we're done + // let q = Array(f.length).fill(0n); + // let r = [...f]; + // for (let i = f.length - 1; i >= n; i--) { + // let leadingCoeff = r[i]; + // if (leadingCoeff === 0n) continue; + // r[i] = 0n; + // r[i - n] = mod(r[i - n] + leadingCoeff, p); + // q[i - n] = mod(q[i - n] + leadingCoeff, p); + // } + // return [q, r]; + // } byX() { const coefs = (this.length() + 1) > 2 << 14 ? @@ -703,9 +703,9 @@ export class Polynomial { this.coef = coefs; } -// Compute a new polynomial f(x^n) from f(x) -// f(x) = a_0 + a_1·x + a_2·x^2 + ... + a_j·x^j -// f(x^n) = a_0 + a_1·x^n + a_2·x^2n + ... + a_j·x^jn + // Compute a new polynomial f(x^n) from f(x) + // f(x) = a_0 + a_1·x + a_2·x^2 + ... + a_j·x^j + // f(x^n) = a_0 + a_1·x^n + a_2·x^2n + ... + a_j·x^jn static async expX(polynomial, n, truncate = false) { const Fr = polynomial.Fr; @@ -715,7 +715,7 @@ export class Polynomial { // a zero degree polynomial with a constant coefficient equals to the sum of all the original coefficients throw new Error("Compute a new polynomial to a zero or negative number is not allowed"); } else if (1 === n) { - return await Polynomial.fromEvaluations(polynomial.coef, curve, polynomial.logger); + return await Polynomial.fromEvaluations(polynomial.coef, polynomial.curve, polynomial.logger); } // length is the length of non-constant coefficients @@ -818,69 +818,69 @@ export class Polynomial { // proof.T3 = await expTau(polTHigh, "multiexp T3"); } -// split2(degPols, blindingFactors) { -// let currentDegree = this.degree(); -// const numFilledPols = Math.ceil((currentDegree + 1) / (degPols + 1)); -// -// //blinding factors can be void or must have a length of numPols - 1 -// if (0 !== blindingFactors.length && blindingFactors.length < numFilledPols - 1) { -// throw new Error(`Blinding factors length must be ${numFilledPols - 1}`); -// } -// -// const chunkByteLength = (degPols + 1) * this.Fr.n8; -// -// // Check polynomial can be split in numChunks parts of chunkSize bytes... -// if (this.coef.byteLength / chunkByteLength <= numFilledPols - 1) { -// throw new Error(`Polynomial is short to be split in ${numFilledPols} parts of ${degPols} coefficients each.`); -// } -// -// let res = []; -// for (let i = 0; i < numFilledPols; i++) { -// const isLast = (numFilledPols - 1) === i; -// const byteLength = isLast ? (currentDegree + 1) * this.Fr.n8 - ((numFilledPols - 1) * chunkByteLength) : chunkByteLength + this.Fr.n8; -// -// res[i] = new Polynomial(new BigBuffer(byteLength), this.Fr, this.logger); -// const fr = i * chunkByteLength; -// const to = isLast ? (currentDegree + 1) * this.Fr.n8 : (i + 1) * chunkByteLength; -// res[i].coef.set(this.coef.slice(fr, to), 0); -// -// // Add a blinding factor as higher degree -// if (!isLast) { -// res[i].coef.set(blindingFactors[i], chunkByteLength); -// } -// -// // Sub blinding factor to the lowest degree -// if (0 !== i) { -// const lowestDegree = this.Fr.sub(res[i].coef.slice(0, this.Fr.n8), blindingFactors[i - 1]); -// res[i].coef.set(lowestDegree, 0); -// } -// } -// -// return res; -// } - -// merge(pols, overlap = true) { -// let length = 0; -// for (let i = 0; i < pols.length; i++) { -// length += pols[i].length(); -// } -// -// if (overlap) { -// length -= pols.length - 1; -// } -// -// let res = new Polynomial(new BigBuffer(length * this.Fr.n8)); -// for (let i = 0; i < pols.length; i++) { -// const byteLength = pols[i].coef.byteLength; -// if (0 === i) { -// res.coef.set(pols[i].coef, 0); -// } else { -// -// } -// } -// -// return res; -// } + // split2(degPols, blindingFactors) { + // let currentDegree = this.degree(); + // const numFilledPols = Math.ceil((currentDegree + 1) / (degPols + 1)); + // + // //blinding factors can be void or must have a length of numPols - 1 + // if (0 !== blindingFactors.length && blindingFactors.length < numFilledPols - 1) { + // throw new Error(`Blinding factors length must be ${numFilledPols - 1}`); + // } + // + // const chunkByteLength = (degPols + 1) * this.Fr.n8; + // + // // Check polynomial can be split in numChunks parts of chunkSize bytes... + // if (this.coef.byteLength / chunkByteLength <= numFilledPols - 1) { + // throw new Error(`Polynomial is short to be split in ${numFilledPols} parts of ${degPols} coefficients each.`); + // } + // + // let res = []; + // for (let i = 0; i < numFilledPols; i++) { + // const isLast = (numFilledPols - 1) === i; + // const byteLength = isLast ? (currentDegree + 1) * this.Fr.n8 - ((numFilledPols - 1) * chunkByteLength) : chunkByteLength + this.Fr.n8; + // + // res[i] = new Polynomial(new BigBuffer(byteLength), this.Fr, this.logger); + // const fr = i * chunkByteLength; + // const to = isLast ? (currentDegree + 1) * this.Fr.n8 : (i + 1) * chunkByteLength; + // res[i].coef.set(this.coef.slice(fr, to), 0); + // + // // Add a blinding factor as higher degree + // if (!isLast) { + // res[i].coef.set(blindingFactors[i], chunkByteLength); + // } + // + // // Sub blinding factor to the lowest degree + // if (0 !== i) { + // const lowestDegree = this.Fr.sub(res[i].coef.slice(0, this.Fr.n8), blindingFactors[i - 1]); + // res[i].coef.set(lowestDegree, 0); + // } + // } + // + // return res; + // } + + // merge(pols, overlap = true) { + // let length = 0; + // for (let i = 0; i < pols.length; i++) { + // length += pols[i].length(); + // } + // + // if (overlap) { + // length -= pols.length - 1; + // } + // + // let res = new Polynomial(new BigBuffer(length * this.Fr.n8)); + // for (let i = 0; i < pols.length; i++) { + // const byteLength = pols[i].coef.byteLength; + // if (0 === i) { + // res.coef.set(pols[i].coef, 0); + // } else { + // + // } + // } + // + // return res; + // } truncate() { const deg = this.degree(); diff --git a/src/powersoftau_beacon.js b/src/powersoftau_beacon.js index 5f60c85c..afb70c43 100644 --- a/src/powersoftau_beacon.js +++ b/src/powersoftau_beacon.js @@ -17,7 +17,7 @@ along with snarkJS. If not, see . */ -import { blake2b } from "@noble/hashes/blake2b"; +import { blake2b } from "@noble/hashes/blake2.js"; import * as utils from "./powersoftau_utils.js"; import * as misc from "./misc.js"; import * as binFileUtils from "@iden3/binfileutils"; diff --git a/src/powersoftau_challenge_contribute.js b/src/powersoftau_challenge_contribute.js index 8a06a1c5..4750fe93 100644 --- a/src/powersoftau_challenge_contribute.js +++ b/src/powersoftau_challenge_contribute.js @@ -36,7 +36,7 @@ // G2*up*beta (compressed) import * as fastFile from "fastfile"; -import { blake2b } from "@noble/hashes/blake2b"; +import { blake2b } from "@noble/hashes/blake2.js"; import * as utils from "./powersoftau_utils.js"; import * as misc from "./misc.js"; import { applyKeyToChallengeSection } from "./mpc_applykey.js"; diff --git a/src/powersoftau_contribute.js b/src/powersoftau_contribute.js index cbba8230..3586084f 100644 --- a/src/powersoftau_contribute.js +++ b/src/powersoftau_contribute.js @@ -24,7 +24,7 @@ // 2^N AlphaTauG1 Points (uncompressed) // 2^N BetaTauG1 Points (uncompressed) -import { blake2b } from "@noble/hashes/blake2b"; +import { blake2b } from "@noble/hashes/blake2.js"; import * as utils from "./powersoftau_utils.js"; import * as keyPair from "./keypair.js"; import * as binFileUtils from "@iden3/binfileutils"; diff --git a/src/powersoftau_convert.js b/src/powersoftau_convert.js index cf300a15..352e068b 100644 --- a/src/powersoftau_convert.js +++ b/src/powersoftau_convert.js @@ -19,7 +19,6 @@ import * as binFileUtils from "@iden3/binfileutils"; import * as utils from "./powersoftau_utils.js"; -import * as fastFile from "fastfile"; import {BigBuffer} from "ffjavascript"; export default async function convert(oldPtauFilename, newPTauFilename, logger) { @@ -92,7 +91,7 @@ export default async function convert(oldPtauFilename, newPTauFilename, logger) buff = await G.lagrangeEvaluations(buff, "affine", "affine", logger, sectionName); await fdNew.write(buff); -/* + /* if (p <= curve.Fr.s) { buff = await G.ifft(buff, "affine", "affine", logger, sectionName); await fdNew.write(buff); diff --git a/src/powersoftau_export_challenge.js b/src/powersoftau_export_challenge.js index 37ce011f..677ce68c 100644 --- a/src/powersoftau_export_challenge.js +++ b/src/powersoftau_export_challenge.js @@ -7,7 +7,7 @@ // BetaG2 (uncompressed) import * as fastFile from "fastfile"; -import { blake2b } from "@noble/hashes/blake2b"; +import { blake2b } from "@noble/hashes/blake2.js"; import * as utils from "./powersoftau_utils.js"; import * as binFileUtils from "@iden3/binfileutils"; import * as misc from "./misc.js"; diff --git a/src/powersoftau_import.js b/src/powersoftau_import.js index ee8af2b5..948fd3a6 100644 --- a/src/powersoftau_import.js +++ b/src/powersoftau_import.js @@ -18,7 +18,7 @@ */ import * as fastFile from "fastfile"; -import { blake2b } from "@noble/hashes/blake2b"; +import { blake2b } from "@noble/hashes/blake2.js"; import * as utils from "./powersoftau_utils.js"; import * as binFileUtils from "@iden3/binfileutils"; import * as misc from "./misc.js"; diff --git a/src/powersoftau_new.js b/src/powersoftau_new.js index edbc9c4b..2b399ee6 100644 --- a/src/powersoftau_new.js +++ b/src/powersoftau_new.js @@ -67,7 +67,7 @@ contributions(7) import * as ptauUtils from "./powersoftau_utils.js"; import * as binFileUtils from "@iden3/binfileutils"; -import { blake2b } from "@noble/hashes/blake2b"; +import { blake2b } from "@noble/hashes/blake2.js"; import * as misc from "./misc.js"; export default async function newAccumulator(curve, power, fileName, logger) { diff --git a/src/powersoftau_preparephase2.js b/src/powersoftau_preparephase2.js index a4b7bed9..e671dd43 100644 --- a/src/powersoftau_preparephase2.js +++ b/src/powersoftau_preparephase2.js @@ -67,9 +67,7 @@ export default async function preparePhase2(oldPtauFilename, newPTauFilename, lo async function processSectionPower(p) { const nPoints = 2 ** p; const G = curve[Gstr]; - const Fr = curve.Fr; const sGin = G.F.n8*2; - const sGmid = G.F.n8*3; let buff; buff = new BigBuffer(nPoints*sGin); @@ -87,7 +85,7 @@ export default async function preparePhase2(oldPtauFilename, newPTauFilename, lo buff = await G.lagrangeEvaluations(buff, "affine", "affine", logger, sectionName); await fdNew.write(buff); -/* + /* if (p <= curve.Fr.s) { buff = await G.ifft(buff, "affine", "affine", logger, sectionName); await fdNew.write(buff); diff --git a/src/powersoftau_utils.js b/src/powersoftau_utils.js index cfb06a24..84960da4 100644 --- a/src/powersoftau_utils.js +++ b/src/powersoftau_utils.js @@ -18,7 +18,7 @@ */ import { Scalar } from "ffjavascript"; -import { blake2b } from "@noble/hashes/blake2b"; +import { blake2b } from "@noble/hashes/blake2.js"; import * as keyPair from "./keypair.js"; import * as misc from "./misc.js"; import { getCurveFromQ } from "./curves.js"; diff --git a/src/powersoftau_verify.js b/src/powersoftau_verify.js index 4a6421e0..7b1fdc33 100644 --- a/src/powersoftau_verify.js +++ b/src/powersoftau_verify.js @@ -17,7 +17,7 @@ along with snarkJS. If not, see . */ -import { blake2b } from "@noble/hashes/blake2b"; +import { blake2b } from "@noble/hashes/blake2.js"; import * as utils from "./powersoftau_utils.js"; import * as keyPair from "./keypair.js"; import * as binFileUtils from "@iden3/binfileutils"; diff --git a/src/taskmanager.js b/src/taskmanager.js deleted file mode 100644 index 6b65efec..00000000 --- a/src/taskmanager.js +++ /dev/null @@ -1,232 +0,0 @@ -/* - Copyright 2018 0KIMS association. - - This file is part of snarkJS. - - snarkJS is a free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - snarkJS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with snarkJS. If not, see . -*/ - -const inBrowser = (typeof window !== "undefined"); -let NodeWorker; -if (!inBrowser) { - NodeWorker = require("worker_threads").Worker; -} - -class Deferred { - constructor() { - this.promise = new Promise((resolve, reject)=> { - this.reject = reject; - this.resolve = resolve; - }); - } -} - - -function thread(self, fn, modules) { - - const ctx = { - modules: modules - }; - - self.onmessage = function(e) { - let data; - if (e.data) { - data = e.data; - } else { - data = e; - } - - if (data.cmd == "INIT") { - ctx.processId = data.processId; - } - - - if (data.cmd == "TERMINATE") { - self.postMessage({cmd: "TERMINATE"}); - process.exit(); - return; - } - - let res = fn(ctx, data); - - res = res || {}; - - res.cmd = data.cmd; - - if (res) { - if (res.buff) { - self.postMessage(res, [res.buff.buffer]); - } else { - self.postMessage(res); - } - } - }; - -} - - -async function buildTaskManager(fn, mods, initTask) { - - let concurrency; - if ((typeof(navigator) === "object") && navigator.hardwareConcurrency) { - concurrency = navigator.hardwareConcurrency; - } else { - const os = require("os"); - concurrency = os.cpus().length; - } - - const tm = { - workers: [] - }; - - let S = "{"; - const keys = Object.keys(mods); - for (let i=0; i { - finishTask(); - }); - } else { - finishTask(); - } - }; - } - - function processTask(i, task, asyncCb) { - if (tm.workers[i].state != "READY") - throw new Error("Worker is not ready"); - tm.workers[i].asyncCb = asyncCb; - - tm.workers[i].state = "WORKING"; - if (task.buff) { - tm.workers[i].worker.postMessage(task, [task.buff.buffer]); - } else { - tm.workers[i].worker.postMessage(task); - } - } - - for (let i=0; i { - // const w= await witnessCalculator.calculateWitness(input,0); - // for (let i=0; i< w.length; i++){ - // console.log(w[i]); - // } - const buff= await witnessCalculator.calculateWTNSBin(input,0); - writeFile(process.argv[4], buff, function(err) { + // const w= await witnessCalculator.calculateWitness(input,0); + // for (let i=0; i< w.length; i++){ + // console.log(w[i]); + // } + const buff= await witnessCalculator.calculateWTNSBin(input,0); + writeFile(process.argv[4], buff, function(err) { if (err) throw err; - }); + }); }); } diff --git a/test/circuit2/circuit_js/witness_calculator.cjs b/test/circuit2/circuit_js/witness_calculator.cjs index 20e6e20a..867f0735 100644 --- a/test/circuit2/circuit_js/witness_calculator.cjs +++ b/test/circuit2/circuit_js/witness_calculator.cjs @@ -4,11 +4,11 @@ module.exports = async function builder(code, options) { let wasmModule; try { - wasmModule = await WebAssembly.compile(code); + wasmModule = await WebAssembly.compile(code); } catch (err) { - console.log(err); - console.log("\nTry to run circom --c in order to generate c++ code instead\n"); - throw new Error(err); + console.log(err); + console.log("\nTry to run circom --c in order to generate c++ code instead\n"); + throw new Error(err); } let wc; @@ -19,60 +19,60 @@ module.exports = async function builder(code, options) { const instance = await WebAssembly.instantiate(wasmModule, { runtime: { exceptionHandler : function(code) { - let err; + let err; if (code == 1) { err = "Signal not found.\n"; } else if (code == 2) { err = "Too many signals set.\n"; } else if (code == 3) { err = "Signal already set.\n"; - } else if (code == 4) { + } else if (code == 4) { err = "Assert Failed.\n"; - } else if (code == 5) { + } else if (code == 5) { err = "Not enough memory.\n"; - } else if (code == 6) { + } else if (code == 6) { err = "Input signal array access exceeds the size.\n"; - } else { + } else { err = "Unknown error.\n"; } throw new Error(err + errStr); }, printErrorMessage : function() { - errStr += getMessage() + "\n"; + errStr += getMessage() + "\n"; // console.error(getMessage()); }, writeBufferMessage : function() { - const msg = getMessage(); - // Any calls to `log()` will always end with a `\n`, so that's when we print and reset - if (msg === "\n") { - console.log(msgStr); - msgStr = ""; - } else { - // If we've buffered other content, put a space in between the items - if (msgStr !== "") { - msgStr += " " - } - // Then append the message to the message we are creating - msgStr += msg; - } + const msg = getMessage(); + // Any calls to `log()` will always end with a `\n`, so that's when we print and reset + if (msg === "\n") { + console.log(msgStr); + msgStr = ""; + } else { + // If we've buffered other content, put a space in between the items + if (msgStr !== "") { + msgStr += " "; + } + // Then append the message to the message we are creating + msgStr += msg; + } }, showSharedRWMemory : function() { - printSharedRWMemory (); + printSharedRWMemory (); } } }); const sanityCheck = - options -// options && -// ( -// options.sanityCheck || -// options.logGetSignal || -// options.logSetSignal || -// options.logStartComponent || -// options.logFinishComponent -// ); + options; + // options && + // ( + // options.sanityCheck || + // options.logGetSignal || + // options.logSetSignal || + // options.logStartComponent || + // options.logFinishComponent + // ); wc = new WitnessCalculator(instance, sanityCheck); @@ -80,28 +80,28 @@ module.exports = async function builder(code, options) { function getMessage() { var message = ""; - var c = instance.exports.getMessageChar(); + var c = instance.exports.getMessageChar(); while ( c != 0 ) { message += String.fromCharCode(c); c = instance.exports.getMessageChar(); - } + } return message; } function printSharedRWMemory () { - const shared_rw_memory_size = instance.exports.getFieldNumLen32(); - const arr = new Uint32Array(shared_rw_memory_size); - for (let j=0; j { const h = fnvHash(k); const hMSB = parseInt(h.slice(0,8), 16); @@ -140,32 +140,32 @@ class WitnessCalculator { const fArr = flatArray(input[k]); let signalSize = this.instance.exports.getInputSignalSize(hMSB, hLSB); if (signalSize < 0){ - throw new Error(`Signal ${k} not found\n`); + throw new Error(`Signal ${k} not found\n`); } if (fArr.length < signalSize) { - throw new Error(`Not enough values for input signal ${k}\n`); + throw new Error(`Not enough values for input signal ${k}\n`); } if (fArr.length > signalSize) { - throw new Error(`Too many values for input signal ${k}\n`); + throw new Error(`Too many values for input signal ${k}\n`); } for (let i=0; i0) { + var i = size - res.length; + while (i>0) { res.unshift(0); i--; - } + } } return res; } @@ -317,21 +317,21 @@ function flatArray(a) { } function normalize(n, prime) { - let res = BigInt(n) % prime - if (res < 0) res += prime - return res + let res = BigInt(n) % prime; + if (res < 0) res += prime; + return res; } function fnvHash(str) { const uint64_max = BigInt(2) ** BigInt(64); let hash = BigInt("0xCBF29CE484222325"); for (var i = 0; i < str.length; i++) { - hash ^= BigInt(str[i].charCodeAt()); - hash *= BigInt(0x100000001B3); - hash %= uint64_max; + hash ^= BigInt(str[i].charCodeAt()); + hash *= BigInt(0x100000001B3); + hash %= uint64_max; } let shash = hash.toString(16); let n = 16 - shash.length; - shash = '0'.repeat(n).concat(shash); + shash = "0".repeat(n).concat(shash); return shash; } diff --git a/test/fflonk.test.js b/test/fflonk.test.js index 5081a6b2..ed26c9f6 100644 --- a/test/fflonk.test.js +++ b/test/fflonk.test.js @@ -10,23 +10,23 @@ const { stringifyBigInts } = utils; describe("Fflonk test suite", function () { - const publicInputsFilename = path.join("test", "fflonk", "public.json"); - const proofFilename = path.join("test", "fflonk", "proof.json"); + const _publicInputsFilename = path.join("test", "fflonk", "public.json"); + const _proofFilename = path.join("test", "fflonk", "proof.json"); const r1csFilename = path.join("test", "fflonk", "circuit.r1cs"); const ptauFilename = path.join("test", "plonk_circuit", "powersOfTau15_final.ptau"); const zkeyFilename = path.join("test", "fflonk", "circuit.zkey"); const wtnsFilename = path.join("test", "fflonk", "witness.wtns"); const vkeyFilename = path.join("test", "fflonk", "circuit_vk.json"); - this.timeout(1000000000); + let curve; - before(async () => { + beforeAll(async () => { curve = await getCurveFromName("bn128"); }); - after(async () => { + afterAll(async () => { await curve.terminate(); }); diff --git a/test/fullprocess.js b/test/fullprocess.js index 21b312be..19383bde 100644 --- a/test/fullprocess.js +++ b/test/fullprocess.js @@ -4,7 +4,7 @@ import assert from "assert"; import path from "path"; describe("Full process", function () { - this.timeout(1000000000); + let curve; const ptau_0 = {type: "mem"}; @@ -27,11 +27,11 @@ describe("Full process", function () { let publicSignals; let publicSignalsWithAlias; - before( async () => { + beforeAll(async () => { curve = await getCurveFromName("bn128"); // curve.Fr.s = 10; }); - after( async () => { + afterAll(async () => { await curve.terminate(); // console.log(process._getActiveHandles()); // console.log(process._getActiveRequests()); diff --git a/test/groth16.test.js b/test/groth16.test.js new file mode 100644 index 00000000..67b98844 --- /dev/null +++ b/test/groth16.test.js @@ -0,0 +1,96 @@ +import * as snarkjs from "../main.js"; + +// Vitest browser tests are served from project root via Vite dev server, +// so browser paths need a leading slash; Node tests use CWD-relative paths. +const isBrowser = typeof window !== "undefined"; +const p = (rel) => (isBrowser ? `/${rel}` : rel); + +const r1cs = p("test/groth16/circuit.r1cs"); +const wasm = p("test/groth16/circuit.wasm"); + +describe("Groth16", function () { + let curve; + const ptau_0 = { type: "mem" }; + const ptau_1 = { type: "mem" }; + const ptau_beacon = { type: "mem" }; + const ptau_final = { type: "mem" }; + const zkey_0 = { type: "mem" }; + const zkey_1 = { type: "mem" }; + const zkey_final = { type: "mem" }; + const wtns = { type: "mem" }; + let vKey; + let proof; + let publicSignals; + + beforeAll(async () => { + curve = await snarkjs.curves.getCurveFromName("bn128"); + await snarkjs.powersOfTau.newAccumulator(curve, 11, ptau_0); + await snarkjs.powersOfTau.contribute(ptau_0, ptau_1, "C1", "Entropy1"); + await snarkjs.powersOfTau.beacon( + ptau_1, + ptau_beacon, + "B3", + "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + 10 + ); + await snarkjs.powersOfTau.preparePhase2(ptau_beacon, ptau_final); + }, 300_000); + + afterAll(async () => { + await curve.terminate(); + }); + + it("zkey new", async () => { + await snarkjs.zKey.newZKey(r1cs, ptau_final, zkey_0); + }); + + it("zkey contribute", async () => { + await snarkjs.zKey.contribute(zkey_0, zkey_1, "p2_C1", "pa_Entropy1"); + }); + + it("zkey beacon", async () => { + await snarkjs.zKey.beacon( + zkey_1, + zkey_final, + "B3", + "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + 10 + ); + }); + + it("zkey verify from r1cs", async () => { + const res = await snarkjs.zKey.verifyFromR1cs(r1cs, ptau_final, zkey_final); + expect(res).toBe(true); + }); + + it("zkey verify from init", async () => { + const res = await snarkjs.zKey.verifyFromInit(zkey_0, ptau_final, zkey_final); + expect(res).toBe(true); + }); + + it("zkey export verification key", async () => { + vKey = await snarkjs.zKey.exportVerificationKey(zkey_final); + expect(vKey).toBeTruthy(); + }); + + it("witness calculate", async () => { + await snarkjs.wtns.calculate({ a: 11, b: 2 }, wasm, wtns); + }); + + it("witness check", async () => { + await snarkjs.wtns.check(r1cs, wtns); + }); + + it("groth16 prove", async () => { + const res = await snarkjs.groth16.prove(zkey_final, wtns); + proof = res.proof; + publicSignals = res.publicSignals; + expect(proof).toBeTruthy(); + expect(publicSignals).toBeTruthy(); + }); + + it("groth16 verify", async () => { + const res = await snarkjs.groth16.verify(vKey, publicSignals, proof); + expect(res).toBe(true); + }); +}); diff --git a/test/keypar_test.js b/test/keypar_test.js index 3a7cc236..982436b6 100644 --- a/test/keypar_test.js +++ b/test/keypar_test.js @@ -6,14 +6,14 @@ import { Scalar } from "ffjavascript"; import { getG2sp } from "../src/keypair.js"; describe("keypair", function() { - this.timeout(10000); + let curve; - before( async () => { + beforeAll( async () => { curve = await getCurveFromName("bn128"); }); - after( async () => { + afterAll( async () => { await curve.terminate(); }); diff --git a/test/polynomial.test.js b/test/polynomial.test.js index a131e9a8..bcbd7586 100644 --- a/test/polynomial.test.js +++ b/test/polynomial.test.js @@ -10,17 +10,17 @@ function radomPolynomial(maxDegree, curve) { } describe("snarkjs: Polynomial tests", function () { - this.timeout(150000); + let curve; let sFr; - before(async () => { + beforeAll(async () => { curve = await getCurveFromName("bn128"); sFr = curve.Fr.n8; }); - after(async () => { + afterAll(async () => { await curve.terminate(); }); diff --git a/test/smart_contracts.test.js b/test/smart_contracts.test.js new file mode 100644 index 00000000..83b2696d --- /dev/null +++ b/test/smart_contracts.test.js @@ -0,0 +1,233 @@ +import * as snarkjs from "../main.js"; +import { buildBn128 } from "ffjavascript"; +import path from "path"; +import { fileURLToPath } from "url"; +import fs from "fs"; +import { zeroPadValue, toBeHex } from "ethers"; +import { tasks, network, artifacts } from "hardhat"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const ROOT = path.resolve(__dirname, ".."); +const TEST_DIR = path.join(ROOT, "test"); +const CONTRACTS_DIR = path.join(ROOT, "contracts"); + +const PTAU = path.join(TEST_DIR, "plonk_circuit", "powersOfTau15_final.ptau"); + +// BN128 curve order — used to construct aliased (out-of-range) public inputs +const BN128_ORDER = 21888242871839275222246405745257275088548364400416034343698204186575808495617n; + +// Encode an array of field elements as 32-byte big-endian hex strings (ethers v6) +function encodeFields(fields) { + return fields.map((f) => zeroPadValue(toBeHex(BigInt(f)), 32)); +} + +// -------------------------------------------------------------------------- +// Verifier helpers: generate Solidity verifier, compile, deploy, and verify +// -------------------------------------------------------------------------- + +async function groth16Verify(r1csFilename, wtnsFilename) { + const zkeyFilename = { type: "mem" }; + await snarkjs.zKey.newZKey(r1csFilename, PTAU, zkeyFilename); + + const { proof, publicSignals } = await snarkjs.groth16.prove(zkeyFilename, wtnsFilename); + + const templates = loadTemplates(); + fs.writeFileSync( + path.join(CONTRACTS_DIR, "Groth16Verifier.sol"), + await snarkjs.zKey.exportSolidityVerifier(zkeyFilename, templates), + "utf-8" + ); + + await tasks.getTask("compile").run(); + await artifacts.clearCache(); + const { ethers } = await network.connect(); + const verifier = await (await ethers.getContractFactory("Groth16Verifier")).deploy(); + + return verifier.verifyProof( + [proof.pi_a[0], proof.pi_a[1]], + [[proof.pi_b[0][1], proof.pi_b[0][0]], [proof.pi_b[1][1], proof.pi_b[1][0]]], + [proof.pi_c[0], proof.pi_c[1]], + publicSignals + ); +} + +async function groth16VerifyAliased(r1csFilename, wtnsFilename) { + const zkeyFilename = { type: "mem" }; + await snarkjs.zKey.newZKey(r1csFilename, PTAU, zkeyFilename); + + const { proof, publicSignals } = await snarkjs.groth16.prove(zkeyFilename, wtnsFilename); + + const templates = loadTemplates(); + fs.writeFileSync( + path.join(CONTRACTS_DIR, "Groth16Verifier.sol"), + await snarkjs.zKey.exportSolidityVerifier(zkeyFilename, templates), + "utf-8" + ); + + await tasks.getTask("compile").run(); + await artifacts.clearCache(); + const { ethers } = await network.connect(); + const verifier = await (await ethers.getContractFactory("Groth16Verifier")).deploy(); + + // Shift the second public signal by the curve order — verifier must reject this + const aliasedSignals = [...publicSignals]; + aliasedSignals[1] = BigInt(publicSignals[1]) + BN128_ORDER; + + return verifier.verifyProof( + [proof.pi_a[0], proof.pi_a[1]], + [[proof.pi_b[0][1], proof.pi_b[0][0]], [proof.pi_b[1][1], proof.pi_b[1][0]]], + [proof.pi_c[0], proof.pi_c[1]], + aliasedSignals + ); +} + +async function plonkVerify(r1csFilename, wtnsFilename) { + const zkeyFilename = { type: "mem" }; + await snarkjs.plonk.setup(r1csFilename, PTAU, zkeyFilename); + + const { proof: p, publicSignals } = await snarkjs.plonk.prove(zkeyFilename, wtnsFilename); + + const templates = loadTemplates(); + fs.writeFileSync( + path.join(CONTRACTS_DIR, "PlonkVerifier.sol"), + await snarkjs.zKey.exportSolidityVerifier(zkeyFilename, templates), + "utf-8" + ); + + await tasks.getTask("compile").run(); + await artifacts.clearCache(); + const { ethers } = await network.connect(); + const verifier = await (await ethers.getContractFactory("PlonkVerifier")).deploy(); + + const proof = encodeFields([ + p.A[0], p.A[1], + p.B[0], p.B[1], + p.C[0], p.C[1], + p.Z[0], p.Z[1], + p.T1[0], p.T1[1], + p.T2[0], p.T2[1], + p.T3[0], p.T3[1], + p.Wxi[0], p.Wxi[1], + p.Wxiw[0], p.Wxiw[1], + p.eval_a, p.eval_b, p.eval_c, + p.eval_s1, p.eval_s2, p.eval_zw, + ]); + + return verifier.verifyProof(proof, publicSignals); +} + +async function fflonkVerify(r1csFilename, wtnsFilename) { + const zkeyFilename = { type: "mem" }; + await snarkjs.fflonk.setup(r1csFilename, PTAU, zkeyFilename); + + const { proof: p, publicSignals } = await snarkjs.fflonk.prove(zkeyFilename, wtnsFilename); + + const templates = loadTemplates(); + fs.writeFileSync( + path.join(CONTRACTS_DIR, "FflonkVerifier.sol"), + await snarkjs.zKey.exportSolidityVerifier(zkeyFilename, templates), + "utf-8" + ); + + await tasks.getTask("compile").run(); + await artifacts.clearCache(); + const { ethers } = await network.connect(); + const verifier = await (await ethers.getContractFactory("FflonkVerifier")).deploy(); + + const { evaluations: e, polynomials: poly } = p; + const proof = encodeFields([ + poly.C1[0], poly.C1[1], + poly.C2[0], poly.C2[1], + poly.W1[0], poly.W1[1], + poly.W2[0], poly.W2[1], + e.ql, e.qr, e.qm, e.qo, e.qc, + e.s1, e.s2, e.s3, + e.a, e.b, e.c, + e.z, e.zw, e.t1w, e.t2w, e.inv, + ]); + + return verifier.verifyProof(proof, publicSignals); +} + +function loadTemplates() { + const TMPL = path.join(ROOT, "templates"); + return { + groth16: fs.readFileSync(path.join(TMPL, "verifier_groth16.sol.ejs"), "utf8"), + plonk: fs.readFileSync(path.join(TMPL, "verifier_plonk.sol.ejs"), "utf8"), + fflonk: fs.readFileSync(path.join(TMPL, "verifier_fflonk.sol.ejs"), "utf8"), + }; +} + +// -------------------------------------------------------------------------- +// Test suite +// -------------------------------------------------------------------------- + +describe("Smart contract verifiers", () => { + let curve; + + beforeAll(async () => { + await fs.promises.mkdir(CONTRACTS_DIR, { recursive: true }); + curve = await buildBn128(); + }); + + afterAll(async () => { + await curve.terminate(); + }); + + // ------------------------------------------------------------------ + // Groth16 + // ------------------------------------------------------------------ + describe("Groth16", () => { + it.each([ + ["1 input", "groth16/circuit.r1cs", "groth16/witness.wtns"], + ["3 inputs", "circuit2/circuit.r1cs", "circuit2/witness.wtns"], + ])("verifies proof — %s", async (_, r1csRel, wtnsRel) => { + const result = await groth16Verify( + path.join(TEST_DIR, r1csRel), + path.join(TEST_DIR, wtnsRel) + ); + expect(result).toBe(true); + }); + + it("rejects aliased public input (field wrap-around)", async () => { + const result = await groth16VerifyAliased( + path.join(TEST_DIR, "groth16/circuit.r1cs"), + path.join(TEST_DIR, "groth16/witness.wtns") + ); + expect(result).toBe(false); + }); + }); + + // ------------------------------------------------------------------ + // PLONK + // ------------------------------------------------------------------ + describe("PLONK", () => { + it.each([ + ["1 input", "plonk_circuit/circuit.r1cs", "plonk_circuit/witness.wtns"], + ["3 inputs", "circuit2/circuit.r1cs", "circuit2/witness.wtns"], + ])("verifies proof — %s", async (_, r1csRel, wtnsRel) => { + const result = await plonkVerify( + path.join(TEST_DIR, r1csRel), + path.join(TEST_DIR, wtnsRel) + ); + expect(result).toBe(true); + }); + }); + + // ------------------------------------------------------------------ + // FFlonk + // ------------------------------------------------------------------ + describe("FFlonk", () => { + it.each([ + ["1 input", "fflonk/circuit.r1cs", "fflonk/witness.wtns"], + ["3 inputs", "circuit2/circuit.r1cs", "circuit2/witness.wtns"], + ])("verifies proof — %s", async (_, r1csRel, wtnsRel) => { + const result = await fflonkVerify( + path.join(TEST_DIR, r1csRel), + path.join(TEST_DIR, wtnsRel) + ); + expect(result).toBe(true); + }); + }); +}); diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 00000000..724a8b06 --- /dev/null +++ b/vite.config.js @@ -0,0 +1,162 @@ +import { defineConfig } from "vite"; +import { builtinModules } from "module"; +import { readFileSync } from "fs"; +import { resolve } from "path"; +import { playwright } from "@vitest/browser-playwright"; + +const pkg = JSON.parse(readFileSync(resolve("package.json"), "utf-8")); + +// All declared dependencies + sub-paths treated as external in node/CLI builds +const nodeExternal = [ + ...builtinModules, + ...Object.keys(pkg.dependencies || {}), +]; +const isNodeExternal = (id) => + nodeExternal.includes(id) || nodeExternal.some((e) => id.startsWith(e + "/")); + +// Deps bundled in browser build (everything except these externals) +const browserExternal = ["ffjavascript", "@iden3/binfileutils", "r1csfile", "ejs"]; +const isBrowserExternal = (id) => + browserExternal.includes(id) || browserExternal.some((e) => id.startsWith(e + "/")); + +export default defineConfig(({ mode }) => { + if (mode === "cli") { + return { + plugins: [ + { + name: "fix-import-meta-url-cjs", + renderChunk(code) { + if (!code.includes("{}.url")) return null; + return { + code: code.replace( + /\{\}\.url/g, + "require('url').pathToFileURL(__filename).href" + ), + map: null, + }; + }, + }, + ], + build: { + lib: { + entry: "./cli.js", + formats: ["cjs"], + fileName: () => "cli.cjs", + }, + minify: false, + outDir: "build", + emptyOutDir: false, + rollupOptions: { + external: isNodeExternal, + output: { + banner: "#!/usr/bin/env node", + inlineDynamicImports: true, + }, + }, + }, + }; + } + + if (mode === "browser") { + return { + build: { + lib: { + entry: "./main.js", + name: "snarkjs", + formats: ["es"], + fileName: () => "browser.esm.js", + }, + outDir: "build", + emptyOutDir: false, + rollupOptions: { + external: isBrowserExternal, + }, + }, + define: { "process.browser": "true" }, + resolve: { conditions: ["browser"] }, + }; + } + + if (mode === "browser-iife") { + return { + build: { + lib: { + entry: "./main.js", + name: "snarkjs", + formats: ["iife"], + fileName: () => "snarkjs.min.js", + }, + outDir: "build", + emptyOutDir: false, + minify: true, + }, + define: { "process.browser": "true" }, + resolve: { conditions: ["browser"] }, + }; + } + + // Node (default) + return { + build: { + lib: { + entry: "./main.js", + formats: ["cjs"], + fileName: () => "main.cjs", + }, + outDir: "build", + emptyOutDir: false, + minify: false, + rollupOptions: { + external: isNodeExternal, + output: { + inlineDynamicImports: true, + }, + }, + }, + test: { + projects: [ + { + test: { + name: "node-esm", + include: ["test/**/*.js"], + exclude: ["test/test.utils.js", "test/smart_contracts.test.js"], + environment: "node", + globals: true, + testTimeout: 300_000, + hookTimeout: 300_000, + }, + }, + { + test: { + name: "smart-contracts", + include: ["test/smart_contracts.test.js"], + environment: "node", + globals: true, + // Hardhat compile + zkSNARK proof generation can be slow + testTimeout: 600_000, + hookTimeout: 120_000, + // Run tests sequentially: each case deploys to the same in-process network + sequence: { concurrent: false }, + }, + }, + { + define: { "process.browser": "true" }, + resolve: { conditions: ["browser"] }, + test: { + name: "browser-chromium", + include: ["test/groth16.test.js"], + browser: { + enabled: true, + provider: playwright(), + headless: true, + instances: [{ browser: "chromium" }], + }, + globals: true, + testTimeout: 300_000, + hookTimeout: 300_000, + }, + }, + ], + }, + }; +}); From f32db33057eb854cb4aac92108da9b624e45d32b Mon Sep 17 00:00:00 2001 From: Kolezhniuk Date: Fri, 3 Apr 2026 18:41:13 +0700 Subject: [PATCH 2/8] chore: update dependencies in package-lock.json and remove unused entries --- package-lock.json | 139 ++++++++++++++++++++++++++++------------------ 1 file changed, 85 insertions(+), 54 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0ff5167c..ce09d56a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51,6 +51,31 @@ "dev": true, "license": "MIT" }, + "node_modules/@emnapi/core": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", + "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", + "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@emnapi/wasi-threads": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", @@ -692,7 +717,7 @@ }, "node_modules/@iden3/binfileutils": { "version": "0.0.12", - "resolved": "git+ssh://git@github.com/iden3/binfileutils.git#a1afdf907cad28915f27abd379846bc478012702", + "resolved": "git+ssh://git@github.com/iden3/binfileutils.git#eca16c4827ef30d24b0e2167d03b626de446c4d6", "license": "GPL-3.0", "dependencies": { "fastfile": "https://github.com/iden3/fastfile.git#feat/esm-migration", @@ -726,22 +751,22 @@ } }, "node_modules/@noble/curves": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", - "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", "dev": true, "license": "MIT", "dependencies": { - "@noble/hashes": "1.3.2" + "@noble/hashes": "1.4.0" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@noble/curves/node_modules/@noble/hashes": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", "dev": true, "license": "MIT", "engines": { @@ -1317,19 +1342,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/@scure/bip32/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.4.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@scure/bip32/node_modules/@noble/hashes": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", @@ -1454,6 +1466,18 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/node": { + "version": "25.5.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.2.tgz", + "integrity": "sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "undici-types": "~7.18.0" + } + }, "node_modules/@vitest/browser": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-4.1.2.tgz", @@ -2130,19 +2154,6 @@ "@scure/bip39": "1.3.0" } }, - "node_modules/ethereum-cryptography/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.4.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/ethereum-cryptography/node_modules/@noble/hashes": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", @@ -2185,6 +2196,19 @@ "node": ">=14.0.0" } }, + "node_modules/ethers/node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/ethers/node_modules/@noble/hashes": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", @@ -2280,7 +2304,7 @@ }, "node_modules/fastfile": { "version": "0.0.20", - "resolved": "git+ssh://git@github.com/iden3/fastfile.git#c78a6c23e1a7dfc83beebc64089139d068b62a9f", + "resolved": "git+ssh://git@github.com/iden3/fastfile.git#60a5733f36bba8063258d30c76e55c746fafae87", "license": "GPL-3.0" }, "node_modules/fdir": { @@ -2390,6 +2414,24 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, + "node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -3310,24 +3352,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rimraf/node_modules/glob": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", - "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "minimatch": "^10.2.2", - "minipass": "^7.1.3", - "path-scurry": "^2.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/rolldown": { "version": "1.0.0-rc.12", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.12.tgz", @@ -3583,6 +3607,14 @@ "node": ">=18.17" } }, + "node_modules/undici-types": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "dev": true, + "license": "MIT", + "optional": true + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -3599,7 +3631,6 @@ "integrity": "sha512-B9ifbFudT1TFhfltfaIPgjo9Z3mDynBTJSUYxTjOQruf/zHH+ezCQKcoqO+h7a9Pw9Nm/OtlXAiGT1axBgwqrQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", From 3dad40dc4193c5b53df7c7fedfbf6aafbfb91cc5 Mon Sep 17 00:00:00 2001 From: Kolezhniuk Date: Wed, 8 Apr 2026 19:48:30 +0700 Subject: [PATCH 3/8] bump version to 0.7.6-poc for upcoming features and improvements --- package-lock.json | 399 +++++++++++++++++++++++++--------------------- package.json | 2 +- 2 files changed, 214 insertions(+), 187 deletions(-) diff --git a/package-lock.json b/package-lock.json index ce09d56a..d905cc8f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "snarkjs", - "version": "0.7.5", + "version": "0.7.6-poc", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "snarkjs", - "version": "0.7.5", + "version": "0.7.6-poc", "license": "GPL-3.0", "dependencies": { "@iden3/binfileutils": "https://github.com/iden3/binfileutils.git#feat/esm-migration", @@ -52,22 +52,22 @@ "license": "MIT" }, "node_modules/@emnapi/core": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", - "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.1.tgz", + "integrity": "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==", "dev": true, "license": "MIT", "optional": true, "peer": true, "dependencies": { - "@emnapi/wasi-threads": "1.2.1", + "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" } }, "node_modules/@emnapi/runtime": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", - "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.1.tgz", + "integrity": "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==", "dev": true, "license": "MIT", "optional": true, @@ -77,9 +77,9 @@ } }, "node_modules/@emnapi/wasi-threads": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", - "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.0.tgz", + "integrity": "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==", "dev": true, "license": "MIT", "optional": true, @@ -572,13 +572,13 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.23.3", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.3.tgz", - "integrity": "sha512-j+eEWmB6YYLwcNOdlwQ6L2OsptI/LO6lNBuLIqe5R7RetD658HLoF+Mn7LzYmAWWNNzdC6cqP+L6r8ujeYXWLw==", + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", + "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^3.0.3", + "@eslint/object-schema": "^3.0.5", "debug": "^4.3.1", "minimatch": "^10.2.4" }, @@ -587,22 +587,22 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.3.tgz", - "integrity": "sha512-lzGN0onllOZCGroKJmRwY6QcEHxbjBw1gwB8SgRSqK8YbbtEXMvKynsXc3553ckIEBxsbMBU7oOZXKIPGZNeZw==", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.5.tgz", + "integrity": "sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^1.1.1" + "@eslint/core": "^1.2.1" }, "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/core": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.1.1.tgz", - "integrity": "sha512-QUPblTtE51/7/Zhfv8BDwO0qkkzQL7P/aWWbqcf4xWLEYn1oKjdO0gglQBB4GAsu7u6wjijbCmzsUTy6mnk6oQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", + "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -634,9 +634,9 @@ } }, "node_modules/@eslint/object-schema": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.3.tgz", - "integrity": "sha512-iM869Pugn9Nsxbh/YHRqYiqd23AmIbxJOcpUMOuWCVNdoQJ5ZtwL6h3t0bcZzJUlC3Dq9jCFCESBZnX0GTv7iQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", + "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -644,13 +644,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.6.1.tgz", - "integrity": "sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.1.tgz", + "integrity": "sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^1.1.1", + "@eslint/core": "^1.2.1", "levn": "^0.4.1" }, "engines": { @@ -732,9 +732,9 @@ "license": "MIT" }, "node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.2.tgz", - "integrity": "sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.3.tgz", + "integrity": "sha512-xK9sGVbJWYb08+mTJt3/YV24WxvxpXcXtP6B172paPZ+Ts69Re9dAr7lKwJoeIx8OoeuimEiRZ7umkiUVClmmQ==", "dev": true, "license": "MIT", "optional": true, @@ -1039,9 +1039,9 @@ } }, "node_modules/@oxc-project/types": { - "version": "0.122.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.122.0.tgz", - "integrity": "sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==", + "version": "0.123.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.123.0.tgz", + "integrity": "sha512-YtECP/y8Mj1lSHiUWGSRzy/C6teUKlS87dEfuVKT09LgQbUsBW1rNg+MiJ4buGu3yuADV60gbIvo9/HplA56Ew==", "dev": true, "license": "MIT", "funding": { @@ -1056,9 +1056,9 @@ "license": "MIT" }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.12.tgz", - "integrity": "sha512-pv1y2Fv0JybcykuiiD3qBOBdz6RteYojRFY1d+b95WVuzx211CRh+ytI/+9iVyWQ6koTh5dawe4S/yRfOFjgaA==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.13.tgz", + "integrity": "sha512-5ZiiecKH2DXAVJTNN13gNMUcCDg4Jy8ZjbXEsPnqa248wgOVeYRX0iqXXD5Jz4bI9BFHgKsI2qmyJynstbmr+g==", "cpu": [ "arm64" ], @@ -1073,9 +1073,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.12.tgz", - "integrity": "sha512-cFYr6zTG/3PXXF3pUO+umXxt1wkRK/0AYT8lDwuqvRC+LuKYWSAQAQZjCWDQpAH172ZV6ieYrNnFzVVcnSflAg==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.13.tgz", + "integrity": "sha512-tz/v/8G77seu8zAB3A5sK3UFoOl06zcshEzhUO62sAEtrEuW/H1CcyoupOrD+NbQJytYgA4CppXPzlrmp4JZKA==", "cpu": [ "arm64" ], @@ -1090,9 +1090,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.12.tgz", - "integrity": "sha512-ZCsYknnHzeXYps0lGBz8JrF37GpE9bFVefrlmDrAQhOEi4IOIlcoU1+FwHEtyXGx2VkYAvhu7dyBf75EJQffBw==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.13.tgz", + "integrity": "sha512-8DakphqOz8JrMYWTJmWA+vDJxut6LijZ8Xcdc4flOlAhU7PNVwo2MaWBF9iXjJAPo5rC/IxEFZDhJ3GC7NHvug==", "cpu": [ "x64" ], @@ -1107,9 +1107,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.12.tgz", - "integrity": "sha512-dMLeprcVsyJsKolRXyoTH3NL6qtsT0Y2xeuEA8WQJquWFXkEC4bcu1rLZZSnZRMtAqwtrF/Ib9Ddtpa/Gkge9Q==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.13.tgz", + "integrity": "sha512-4wBQFfjDuXYN/SVI8inBF3Aa+isq40rc6VMFbk5jcpolUBTe5cYnMsHZ51nFWsx3PVyyNN3vgoESki0Hmr/4BA==", "cpu": [ "x64" ], @@ -1124,9 +1124,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.12.tgz", - "integrity": "sha512-YqWjAgGC/9M1lz3GR1r1rP79nMgo3mQiiA+Hfo+pvKFK1fAJ1bCi0ZQVh8noOqNacuY1qIcfyVfP6HoyBRZ85Q==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.13.tgz", + "integrity": "sha512-JW/e4yPIXLms+jmnbwwy5LA/LxVwZUWLN8xug+V200wzaVi5TEGIWQlh8o91gWYFxW609euI98OCCemmWGuPrw==", "cpu": [ "arm" ], @@ -1141,9 +1141,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.12.tgz", - "integrity": "sha512-/I5AS4cIroLpslsmzXfwbe5OmWvSsrFuEw3mwvbQ1kDxJ822hFHIx+vsN/TAzNVyepI/j/GSzrtCIwQPeKCLIg==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.13.tgz", + "integrity": "sha512-ZfKWpXiUymDnavepCaM6KG/uGydJ4l2nBmMxg60Ci4CbeefpqjPWpfaZM7PThOhk2dssqBAcwLc6rAyr0uTdXg==", "cpu": [ "arm64" ], @@ -1158,9 +1158,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.12.tgz", - "integrity": "sha512-V6/wZztnBqlx5hJQqNWwFdxIKN0m38p8Jas+VoSfgH54HSj9tKTt1dZvG6JRHcjh6D7TvrJPWFGaY9UBVOaWPw==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.13.tgz", + "integrity": "sha512-bmRg3O6Z0gq9yodKKWCIpnlH051sEfdVwt+6m5UDffAQMUUqU0xjnQqqAUm+Gu7ofAAly9DqiQDtKu2nPDEABA==", "cpu": [ "arm64" ], @@ -1175,9 +1175,9 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.12.tgz", - "integrity": "sha512-AP3E9BpcUYliZCxa3w5Kwj9OtEVDYK6sVoUzy4vTOJsjPOgdaJZKFmN4oOlX0Wp0RPV2ETfmIra9x1xuayFB7g==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.13.tgz", + "integrity": "sha512-8Wtnbw4k7pMYN9B/mOEAsQ8HOiq7AZ31Ig4M9BKn2So4xRaFEhtCSa4ZJaOutOWq50zpgR4N5+L/opnlaCx8wQ==", "cpu": [ "ppc64" ], @@ -1192,9 +1192,9 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.12.tgz", - "integrity": "sha512-nWwpvUSPkoFmZo0kQazZYOrT7J5DGOJ/+QHHzjvNlooDZED8oH82Yg67HvehPPLAg5fUff7TfWFHQS8IV1n3og==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.13.tgz", + "integrity": "sha512-D/0Nlo8mQuxSMohNJUF2lDXWRsFDsHldfRRgD9bRgktj+EndGPj4DOV37LqDKPYS+osdyhZEH7fTakTAEcW7qg==", "cpu": [ "s390x" ], @@ -1209,9 +1209,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.12.tgz", - "integrity": "sha512-RNrafz5bcwRy+O9e6P8Z/OCAJW/A+qtBczIqVYwTs14pf4iV1/+eKEjdOUta93q2TsT/FI0XYDP3TCky38LMAg==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.13.tgz", + "integrity": "sha512-eRrPvat2YaVQcwwKi/JzOP6MKf1WRnOCr+VaI3cTWz3ZoLcP/654z90lVCJ4dAuMEpPdke0n+qyAqXDZdIC4rA==", "cpu": [ "x64" ], @@ -1226,9 +1226,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.12.tgz", - "integrity": "sha512-Jpw/0iwoKWx3LJ2rc1yjFrj+T7iHZn2JDg1Yny1ma0luviFS4mhAIcd1LFNxK3EYu3DHWCps0ydXQ5i/rrJ2ig==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.13.tgz", + "integrity": "sha512-PsdONiFRp8hR8KgVjTWjZ9s7uA3uueWL0t74/cKHfM4dR5zXYv4AjB8BvA+QDToqxAFg4ZkcVEqeu5F7inoz5w==", "cpu": [ "x64" ], @@ -1243,9 +1243,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.12.tgz", - "integrity": "sha512-vRugONE4yMfVn0+7lUKdKvN4D5YusEiPilaoO2sgUWpCvrncvWgPMzK00ZFFJuiPgLwgFNP5eSiUlv2tfc+lpA==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.13.tgz", + "integrity": "sha512-hCNXgC5dI3TVOLrPT++PKFNZ+1EtS0mLQwfXXXSUD/+rGlB65gZDwN/IDuxLpQP4x8RYYHqGomlUXzpO8aVI2w==", "cpu": [ "arm64" ], @@ -1260,9 +1260,9 @@ } }, "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.12.tgz", - "integrity": "sha512-ykGiLr/6kkiHc0XnBfmFJuCjr5ZYKKofkx+chJWDjitX+KsJuAmrzWhwyOMSHzPhzOHOy7u9HlFoa5MoAOJ/Zg==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.13.tgz", + "integrity": "sha512-viLS5C5et8NFtLWw9Sw3M/w4vvnVkbWkO7wSNh3C+7G1+uCkGpr6PcjNDSFcNtmXY/4trjPBqUfcOL+P3sWy/g==", "cpu": [ "wasm32" ], @@ -1270,16 +1270,18 @@ "license": "MIT", "optional": true, "dependencies": { - "@napi-rs/wasm-runtime": "^1.1.1" + "@emnapi/core": "1.9.1", + "@emnapi/runtime": "1.9.1", + "@napi-rs/wasm-runtime": "^1.1.2" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.12.tgz", - "integrity": "sha512-5eOND4duWkwx1AzCxadcOrNeighiLwMInEADT0YM7xeEOOFcovWZCq8dadXgcRHSf3Ulh1kFo/qvzoFiCLOL1Q==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.13.tgz", + "integrity": "sha512-Fqa3Tlt1xL4wzmAYxGNFV36Hb+VfPc9PYU+E25DAnswXv3ODDu/yyWjQDbXMo5AGWkQVjLgQExuVu8I/UaZhPQ==", "cpu": [ "arm64" ], @@ -1294,9 +1296,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.12.tgz", - "integrity": "sha512-PyqoipaswDLAZtot351MLhrlrh6lcZPo2LSYE+VDxbVk24LVKAGOuE4hb8xZQmrPAuEtTZW8E6D2zc5EUZX4Lw==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.13.tgz", + "integrity": "sha512-/pLI5kPkGEi44TDlnbio3St/5gUFeN51YWNAk/Gnv6mEQBOahRBh52qVFVBpmrnU01n2yysvBML9Ynu7K4kGAQ==", "cpu": [ "x64" ], @@ -1311,9 +1313,9 @@ } }, "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.12.tgz", - "integrity": "sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.13.tgz", + "integrity": "sha512-3ngTAv6F/Py35BsYbeeLeecvhMKdsKm4AoOETVhAA+Qc8nrA2I0kF7oa93mE9qnIurngOSpMnQ0x2nQY2FPviA==", "dev": true, "license": "MIT" }, @@ -1479,15 +1481,15 @@ } }, "node_modules/@vitest/browser": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-4.1.2.tgz", - "integrity": "sha512-CwdIf90LNf1Zitgqy63ciMAzmyb4oIGs8WZ40VGYrWkssQKeEKr32EzO8MKUrDPPcPVHFI9oQ5ni2Hp24NaNRQ==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-4.1.3.tgz", + "integrity": "sha512-CS9KjO2vijuBlbwz0JIgC0YuoI1BuqWI5ziD3Nll6jkpNYtWdjPMVgGynQ9vZovjsECeUqEeNjWrypP414d0CQ==", "dev": true, "license": "MIT", "dependencies": { "@blazediff/core": "1.9.1", - "@vitest/mocker": "4.1.2", - "@vitest/utils": "4.1.2", + "@vitest/mocker": "4.1.3", + "@vitest/utils": "4.1.3", "magic-string": "^0.30.21", "pngjs": "^7.0.0", "sirv": "^3.0.2", @@ -1498,19 +1500,19 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "4.1.2" + "vitest": "4.1.3" } }, "node_modules/@vitest/browser-playwright": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@vitest/browser-playwright/-/browser-playwright-4.1.2.tgz", - "integrity": "sha512-N0Z2HzMLvMR6k/tWPTS6Q/DaRscrkax/f2f9DIbNQr+Cd1l4W4wTf/I6S983PAMr0tNqqoTL+xNkLh9M5vbkLg==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@vitest/browser-playwright/-/browser-playwright-4.1.3.tgz", + "integrity": "sha512-D3Q+YozvSpiFaLPgd6/OMbyqEIZeucSe6AHJJ7VnNJKQhIyBE60TlBZlxzwM8bvjzQE9ZnYWQCPeCw5pnhbiNg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@vitest/browser": "4.1.2", - "@vitest/mocker": "4.1.2", + "@vitest/browser": "4.1.3", + "@vitest/mocker": "4.1.3", "tinyrainbow": "^3.1.0" }, "funding": { @@ -1518,7 +1520,7 @@ }, "peerDependencies": { "playwright": "*", - "vitest": "4.1.2" + "vitest": "4.1.3" }, "peerDependenciesMeta": { "playwright": { @@ -1527,16 +1529,16 @@ } }, "node_modules/@vitest/expect": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.2.tgz", - "integrity": "sha512-gbu+7B0YgUJ2nkdsRJrFFW6X7NTP44WlhiclHniUhxADQJH5Szt9mZ9hWnJPJ8YwOK5zUOSSlSvyzRf0u1DSBQ==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.3.tgz", + "integrity": "sha512-CW8Q9KMtXDGHj0vCsqui0M5KqRsu0zm0GNDW7Gd3U7nZ2RFpPKSCpeCXoT+/+5zr1TNlsoQRDEz+LzZUyq6gnQ==", "dev": true, "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", - "@vitest/spy": "4.1.2", - "@vitest/utils": "4.1.2", + "@vitest/spy": "4.1.3", + "@vitest/utils": "4.1.3", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" }, @@ -1545,13 +1547,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.2.tgz", - "integrity": "sha512-Ize4iQtEALHDttPRCmN+FKqOl2vxTiNUhzobQFFt/BM1lRUTG7zRCLOykG/6Vo4E4hnUdfVLo5/eqKPukcWW7Q==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.3.tgz", + "integrity": "sha512-XN3TrycitDQSzGRnec/YWgoofkYRhouyVQj4YNsJ5r/STCUFqMrP4+oxEv3e7ZbLi4og5kIHrZwekDJgw6hcjw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.1.2", + "@vitest/spy": "4.1.3", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, @@ -1572,9 +1574,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.2.tgz", - "integrity": "sha512-dwQga8aejqeuB+TvXCMzSQemvV9hNEtDDpgUKDzOmNQayl2OG241PSWeJwKRH3CiC+sESrmoFd49rfnq7T4RnA==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.3.tgz", + "integrity": "sha512-hYqqwuMbpkkBodpRh4k4cQSOELxXky1NfMmQvOfKvV8zQHz8x8Dla+2wzElkMkBvSAJX5TRGHJAQvK0TcOafwg==", "dev": true, "license": "MIT", "dependencies": { @@ -1585,13 +1587,13 @@ } }, "node_modules/@vitest/runner": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.2.tgz", - "integrity": "sha512-Gr+FQan34CdiYAwpGJmQG8PgkyFVmARK8/xSijia3eTFgVfpcpztWLuP6FttGNfPLJhaZVP/euvujeNYar36OQ==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.3.tgz", + "integrity": "sha512-VwgOz5MmT0KhlUj40h02LWDpUBVpflZ/b7xZFA25F29AJzIrE+SMuwzFf0b7t4EXdwRNX61C3B6auIXQTR3ttA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.1.2", + "@vitest/utils": "4.1.3", "pathe": "^2.0.3" }, "funding": { @@ -1599,14 +1601,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.2.tgz", - "integrity": "sha512-g7yfUmxYS4mNxk31qbOYsSt2F4m1E02LFqO53Xpzg3zKMhLAPZAjjfyl9e6z7HrW6LvUdTwAQR3HHfLjpko16A==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.3.tgz", + "integrity": "sha512-9l+k/J9KG5wPJDX9BcFFzhhwNjwkRb8RsnYhaT1vPY7OufxmQFc9sZzScRCPTiETzl37mrIWVY9zxzmdVeJwDQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.1.2", - "@vitest/utils": "4.1.2", + "@vitest/pretty-format": "4.1.3", + "@vitest/utils": "4.1.3", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, @@ -1615,9 +1617,9 @@ } }, "node_modules/@vitest/spy": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.2.tgz", - "integrity": "sha512-DU4fBnbVCJGNBwVA6xSToNXrkZNSiw59H8tcuUspVMsBDBST4nfvsPsEHDHGtWRRnqBERBQu7TrTKskmjqTXKA==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.3.tgz", + "integrity": "sha512-ujj5Uwxagg4XUIfAUyRQxAg631BP6e9joRiN99mr48Bg9fRs+5mdUElhOoZ6rP5mBr8Bs3lmrREnkrQWkrsTCw==", "dev": true, "license": "MIT", "funding": { @@ -1625,13 +1627,13 @@ } }, "node_modules/@vitest/utils": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.2.tgz", - "integrity": "sha512-xw2/TiX82lQHA06cgbqRKFb5lCAy3axQ4H4SoUFhUsg+wztiet+co86IAMDtF6Vm1hc7J6j09oh/rgDn+JdKIQ==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.3.tgz", + "integrity": "sha512-Pc/Oexse/khOWsGB+w3q4yzA4te7W4gpZZAvk+fr8qXfTURZUMj5i7kuxsNK5mP/dEB6ao3jfr0rs17fHhbHdw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.1.2", + "@vitest/pretty-format": "4.1.3", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" }, @@ -1823,6 +1825,17 @@ "calcwit": "calcwit.js" } }, + "node_modules/circom_runtime/node_modules/ffjavascript": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.3.1.tgz", + "integrity": "sha512-4PbK1WYodQtuF47D4pRI5KUg3Q392vuP5WjE1THSnceHdXwU3ijaoS0OqxTzLknCtz4Z2TtABzkBdBdMn3B/Aw==", + "license": "GPL-3.0", + "dependencies": { + "wasmbuilder": "0.0.16", + "wasmcurves": "0.2.2", + "web-worker": "1.2.0" + } + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -1979,19 +1992,19 @@ } }, "node_modules/eslint": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.1.0.tgz", - "integrity": "sha512-S9jlY/ELKEUwwQnqWDO+f+m6sercqOPSqXM5Go94l7DOmxHVDgmSFGWEzeE/gwgTAr0W103BWt0QLe/7mabIvA==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.2.0.tgz", + "integrity": "sha512-+L0vBFYGIpSNIt/KWTpFonPrqYvgKw1eUI5Vn7mEogrQcWtWYtNQ7dNqC+px/J0idT3BAkiWrhfS7k+Tum8TUA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", - "@eslint/config-array": "^0.23.3", - "@eslint/config-helpers": "^0.5.3", - "@eslint/core": "^1.1.1", - "@eslint/plugin-kit": "^0.6.1", + "@eslint/config-array": "^0.23.4", + "@eslint/config-helpers": "^0.5.4", + "@eslint/core": "^1.2.0", + "@eslint/plugin-kit": "^0.7.0", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", @@ -2326,8 +2339,8 @@ } }, "node_modules/ffjavascript": { - "version": "0.3.1", - "resolved": "git+ssh://git@github.com/iden3/ffjavascript.git#0e949b121f874e50ea854e0ce08316ce6dd7eb59", + "version": "0.3.1-poc", + "resolved": "git+ssh://git@github.com/iden3/ffjavascript.git#1ff750d476e1508d6511ea0429e9aed9a7dbe1c0", "license": "GPL-3.0", "dependencies": { "wasmbuilder": "0.0.16", @@ -2890,9 +2903,9 @@ "license": "MIT" }, "node_modules/lru-cache": { - "version": "11.2.7", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", - "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.2.tgz", + "integrity": "sha512-wgWa6FWQ3QRRJbIjbsldRJZxdxYngT/dO0I5Ynmlnin8qy7tC6xYzbcJjtN4wHLXtkbVwHzk0C+OejVw1XM+DQ==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -3232,9 +3245,9 @@ } }, "node_modules/postcss": { - "version": "8.5.8", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", - "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", + "version": "8.5.9", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.9.tgz", + "integrity": "sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==", "dev": true, "funding": [ { @@ -3353,14 +3366,14 @@ } }, "node_modules/rolldown": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.12.tgz", - "integrity": "sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A==", + "version": "1.0.0-rc.13", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.13.tgz", + "integrity": "sha512-bvVj8YJmf0rq4pSFmH7laLa6pYrhghv3PRzrCdRAr23g66zOKVJ4wkvFtgohtPLWmthgg8/rkaqRHrpUEh0Zbw==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.122.0", - "@rolldown/pluginutils": "1.0.0-rc.12" + "@oxc-project/types": "=0.123.0", + "@rolldown/pluginutils": "1.0.0-rc.13" }, "bin": { "rolldown": "bin/cli.mjs" @@ -3369,21 +3382,21 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.0-rc.12", - "@rolldown/binding-darwin-arm64": "1.0.0-rc.12", - "@rolldown/binding-darwin-x64": "1.0.0-rc.12", - "@rolldown/binding-freebsd-x64": "1.0.0-rc.12", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.12", - "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.12", - "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.12", - "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.12", - "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.12", - "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.12", - "@rolldown/binding-linux-x64-musl": "1.0.0-rc.12", - "@rolldown/binding-openharmony-arm64": "1.0.0-rc.12", - "@rolldown/binding-wasm32-wasi": "1.0.0-rc.12", - "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.12", - "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.12" + "@rolldown/binding-android-arm64": "1.0.0-rc.13", + "@rolldown/binding-darwin-arm64": "1.0.0-rc.13", + "@rolldown/binding-darwin-x64": "1.0.0-rc.13", + "@rolldown/binding-freebsd-x64": "1.0.0-rc.13", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.13", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.13", + "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.13", + "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.13", + "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.13", + "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.13", + "@rolldown/binding-linux-x64-musl": "1.0.0-rc.13", + "@rolldown/binding-openharmony-arm64": "1.0.0-rc.13", + "@rolldown/binding-wasm32-wasi": "1.0.0-rc.13", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.13", + "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.13" } }, "node_modules/semver": { @@ -3489,9 +3502,9 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz", - "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.1.tgz", + "integrity": "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==", "dev": true, "license": "MIT", "engines": { @@ -3499,14 +3512,14 @@ } }, "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", "dev": true, "license": "MIT", "dependencies": { "fdir": "^6.5.0", - "picomatch": "^4.0.3" + "picomatch": "^4.0.4" }, "engines": { "node": ">=12.0.0" @@ -3626,16 +3639,16 @@ } }, "node_modules/vite": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.3.tgz", - "integrity": "sha512-B9ifbFudT1TFhfltfaIPgjo9Z3mDynBTJSUYxTjOQruf/zHH+ezCQKcoqO+h7a9Pw9Nm/OtlXAiGT1axBgwqrQ==", + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.7.tgz", + "integrity": "sha512-P1PbweD+2/udplnThz3btF4cf6AgPky7kk23RtHUkJIU5BIxwPprhRGmOAHs6FTI7UiGbTNrgNP6jSYD6JaRnw==", "dev": true, "license": "MIT", "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.8", - "rolldown": "1.0.0-rc.12", + "rolldown": "1.0.0-rc.13", "tinyglobby": "^0.2.15" }, "bin": { @@ -3653,7 +3666,7 @@ "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", - "esbuild": "^0.27.0", + "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", @@ -3719,20 +3732,20 @@ } }, "node_modules/vitest": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.2.tgz", - "integrity": "sha512-xjR1dMTVHlFLh98JE3i/f/WePqJsah4A0FK9cc8Ehp9Udk0AZk6ccpIZhh1qJ/yxVWRZ+Q54ocnD8TXmkhspGg==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.3.tgz", + "integrity": "sha512-DBc4Tx0MPNsqb9isoyOq00lHftVx/KIU44QOm2q59npZyLUkENn8TMFsuzuO+4U2FUa9rgbbPt3udrP25GcjXw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@vitest/expect": "4.1.2", - "@vitest/mocker": "4.1.2", - "@vitest/pretty-format": "4.1.2", - "@vitest/runner": "4.1.2", - "@vitest/snapshot": "4.1.2", - "@vitest/spy": "4.1.2", - "@vitest/utils": "4.1.2", + "@vitest/expect": "4.1.3", + "@vitest/mocker": "4.1.3", + "@vitest/pretty-format": "4.1.3", + "@vitest/runner": "4.1.3", + "@vitest/snapshot": "4.1.3", + "@vitest/spy": "4.1.3", + "@vitest/utils": "4.1.3", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", @@ -3760,10 +3773,12 @@ "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.1.2", - "@vitest/browser-preview": "4.1.2", - "@vitest/browser-webdriverio": "4.1.2", - "@vitest/ui": "4.1.2", + "@vitest/browser-playwright": "4.1.3", + "@vitest/browser-preview": "4.1.3", + "@vitest/browser-webdriverio": "4.1.3", + "@vitest/coverage-istanbul": "4.1.3", + "@vitest/coverage-v8": "4.1.3", + "@vitest/ui": "4.1.3", "happy-dom": "*", "jsdom": "*", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -3787,6 +3802,12 @@ "@vitest/browser-webdriverio": { "optional": true }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, "@vitest/ui": { "optional": true }, @@ -3815,6 +3836,12 @@ "wasmbuilder": "0.0.16" } }, + "node_modules/web-worker": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.2.0.tgz", + "integrity": "sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==", + "license": "Apache-2.0" + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index b964295e..86085040 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "snarkjs", "type": "module", - "version": "0.7.5", + "version": "0.7.6-poc", "description": "zkSNARKs implementation in JavaScript", "main": "./build/main.cjs", "module": "./main.js", From 0c34453de43c2c748d328452c28868c98e90ba7b Mon Sep 17 00:00:00 2001 From: Kolezhniuk Date: Wed, 8 Apr 2026 21:31:53 +0700 Subject: [PATCH 4/8] fix: enhance memory usage checks and improve browser build configuration - Updated memory usage functions in `groth16_prove.js` and `zkey_new.js` to handle cases where the process object is undefined, ensuring compatibility in non-Node environments. - Modified `vite.config.js` to exclude certain Node-only files from browser builds, preventing unnecessary dependencies from being included in the bundle. - Added a plugin to stub Node-only modules, allowing for cleaner builds and avoiding errors related to missing modules in the browser context. - Disabled minification in the browser build for easier debugging and added rollup options to manage external dependencies more effectively. --- build/browser.esm.js | 360 +- build/cli.cjs | 3 +- build/main.cjs | 3 +- build/snarkjs.min.js | 9839 +++++++++++++++++++++++++++++++++++++++++- src/groth16_prove.js | 2 +- src/zkey_new.js | 1 + vite.config.js | 23 +- 7 files changed, 9838 insertions(+), 393 deletions(-) diff --git a/build/browser.esm.js b/build/browser.esm.js index 413a3419..0ec1e028 100644 --- a/build/browser.esm.js +++ b/build/browser.esm.js @@ -1305,7 +1305,7 @@ async function ct(e, t, n, r, i, a) { return console.timeEnd("joinABC"), f; } function lt(e) { - if (!e) return; + if (!e || typeof process > "u" || !process.memoryUsage) return; let t = process.memoryUsage(); e.debug(" ", "\x1B[0m Heap:\x1B[32m", `${Math.round(t.heapUsed / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m / \x1B[32m", `${Math.round(t.heapTotal / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m RSS:\x1B[32m", `${Math.round(t.rss / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m External:\x1B[32m", `${Math.round(t.external / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m ArrBuffers:\x1B[32m", `${Math.round(t.arrayBuffers / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m"); } @@ -3089,6 +3089,7 @@ async function qn(e, c, l, d) { new DataView(t.buffer, t.byteOffset, t.byteLength).setUint32(0, e, !1), f.update(t); } function W() { + if (typeof process > "u" || !process.memoryUsage) return {}; let e = process.memoryUsage(); for (let t in e) e[t] = Math.round(e[t] / (1024 * 1024)); return e; @@ -3519,45 +3520,14 @@ async function sr(e, t) { }); } //#endregion -//#region src/fflonk_export_solidity_verifier.js -var { unstringifyBigInts: cr, stringifyBigInts: lr } = p; -async function ur(e, t, n) { - n && n.info("FFLONK EXPORT SOLIDITY VERIFIER STARTED"); - let r = await D(e.curve), i = u(e.w3); - e.w3_2 = d(r.Fr.square(i)); - let a = u(e.w4); - e.w4_2 = d(r.Fr.square(a)), e.w4_3 = d(r.Fr.mul(r.Fr.square(a), a)); - let o = u(e.w8), s = r.Fr.one; - for (let t = 1; t < 8; t++) s = r.Fr.mul(s, o), e["w8_" + t] = d(s); - let c = t[e.protocol]; - n && n.info("FFLONK EXPORT SOLIDITY VERIFIER FINISHED"); - let { default: l } = await import("ejs"); - return l.render(c, e); - function u(e) { - let t = cr(e); - return r.Fr.fromObject(t); - } - function d(e) { - return lr(r.Fr.toObject(e)); - } -} -//#endregion -//#region src/zkey_export_solidityverifier.js -async function dr(e, t, n) { - let r = await ir(e, n); - if (r.protocol === "fflonk") return ur(r, t, n); - let i = t[r.protocol], { default: a } = await import("ejs"); - return a.render(i, r); -} -//#endregion //#region src/zkey.js -var fr = /* @__PURE__ */ y({ +var cr = /* @__PURE__ */ y({ beacon: () => er, bellmanContribute: () => nr, contribute: () => $n, exportBellman: () => Jn, exportJson: () => tr, - exportSolidityVerifier: () => dr, + exportSolidityVerifier: () => null, exportVerificationKey: () => ir, importBellman: () => Yn, newZKey: () => qn, @@ -3566,7 +3536,7 @@ var fr = /* @__PURE__ */ y({ }); //#endregion //#region src/plonk_setup.js -async function pr(e, c, l, d) { +async function lr(e, c, l, d) { globalThis.gc && globalThis.gc(); let { fd: f, sections: p } = await r(c, "ptau", 1, 1 << 22, 1 << 24), { curve: m, power: g } = await rn(f, p), { fd: _, sections: v } = await r(e, "r1cs", 1, 1 << 22, 1 << 24), y = await h(_, v, { loadConstraints: !0, @@ -3756,7 +3726,7 @@ async function pr(e, c, l, d) { } //#endregion //#region src/proof.js -var mr = class { +var ur = class { constructor(e, t) { this.curve = e, this.logger = t, this.resetProof(); } @@ -3795,36 +3765,36 @@ var mr = class { this.evaluations[t] = this.curve.Fr.fromObject(e.evaluations[t]); }); } -}, hr = BigInt(0), gr = BigInt(1), _r = BigInt(2), vr = BigInt(7), yr = BigInt(256), br = BigInt(113), xr = [], Sr = [], Cr = []; -for (let e = 0, t = gr, n = 1, r = 0; e < 24; e++) { - [n, r] = [r, (2 * n + 3 * r) % 5], xr.push(2 * (5 * r + n)), Sr.push((e + 1) * (e + 2) / 2 % 64); - let i = hr; - for (let e = 0; e < 7; e++) t = (t << gr ^ (t >> vr) * br) % yr, t & _r && (i ^= gr << (gr << BigInt(e)) - gr); - Cr.push(i); +}, dr = BigInt(0), fr = BigInt(1), pr = BigInt(2), mr = BigInt(7), hr = BigInt(256), gr = BigInt(113), _r = [], vr = [], yr = []; +for (let e = 0, t = fr, n = 1, r = 0; e < 24; e++) { + [n, r] = [r, (2 * n + 3 * r) % 5], _r.push(2 * (5 * r + n)), vr.push((e + 1) * (e + 2) / 2 % 64); + let i = dr; + for (let e = 0; e < 7; e++) t = (t << fr ^ (t >> mr) * gr) % hr, t & pr && (i ^= fr << (fr << BigInt(e)) - fr); + yr.push(i); } -var wr = U(Cr, !0), Tr = wr[0], Er = wr[1], Dr = (e, t, n) => n > 32 ? ue(e, t, n) : ce(e, t, n), Or = (e, t, n) => n > 32 ? de(e, t, n) : le(e, t, n); -function kr(e, t = 24) { +var br = U(yr, !0), xr = br[0], Sr = br[1], Cr = (e, t, n) => n > 32 ? ue(e, t, n) : ce(e, t, n), wr = (e, t, n) => n > 32 ? de(e, t, n) : le(e, t, n); +function Tr(e, t = 24) { let n = new Uint32Array(10); for (let r = 24 - t; r < 24; r++) { for (let t = 0; t < 10; t++) n[t] = e[t] ^ e[t + 10] ^ e[t + 20] ^ e[t + 30] ^ e[t + 40]; for (let t = 0; t < 10; t += 2) { - let r = (t + 8) % 10, i = (t + 2) % 10, a = n[i], o = n[i + 1], s = Dr(a, o, 1) ^ n[r], c = Or(a, o, 1) ^ n[r + 1]; + let r = (t + 8) % 10, i = (t + 2) % 10, a = n[i], o = n[i + 1], s = Cr(a, o, 1) ^ n[r], c = wr(a, o, 1) ^ n[r + 1]; for (let n = 0; n < 50; n += 10) e[t + n] ^= s, e[t + n + 1] ^= c; } let t = e[2], i = e[3]; for (let n = 0; n < 24; n++) { - let r = Sr[n], a = Dr(t, i, r), o = Or(t, i, r), s = xr[n]; + let r = vr[n], a = Cr(t, i, r), o = wr(t, i, r), s = _r[n]; t = e[s], i = e[s + 1], e[s] = a, e[s + 1] = o; } for (let t = 0; t < 50; t += 10) { for (let r = 0; r < 10; r++) n[r] = e[t + r]; for (let r = 0; r < 10; r++) e[t + r] ^= ~n[(r + 2) % 10] & n[(r + 4) % 10]; } - e[0] ^= Tr[r], e[1] ^= Er[r]; + e[0] ^= xr[r], e[1] ^= Sr[r]; } P(n); } -var Ar = class e { +var Er = class e { state; pos = 0; posOut = 0; @@ -3844,7 +3814,7 @@ var Ar = class e { return this._cloneInto(); } keccak() { - R(this.state32), kr(this.state32, this.rounds), R(this.state32), this.posOut = 0, this.pos = 0; + R(this.state32), Tr(this.state32, this.rounds), R(this.state32), this.posOut = 0, this.pos = 0; } update(e) { j(this), A(e); @@ -3893,7 +3863,7 @@ var Ar = class e { let { blockLen: n, suffix: r, outputLen: i, rounds: a, enableXOF: o } = this; return t ||= new e(n, r, i, o, a), t.state32.set(this.state32), t.pos = this.pos, t.posOut = this.posOut, t.finished = this.finished, t.rounds = a, t.suffix = r, t.outputLen = i, t.enableXOF = o, t.destroyed = this.destroyed, t; } -}, jr = /* @__PURE__ */ ((e, t, n, r = {}) => z(() => new Ar(t, e, n), r))(1, 136, 32), Mr = 0, Nr = 1, Pr = class { +}, Dr = /* @__PURE__ */ ((e, t, n, r = {}) => z(() => new Er(t, e, n), r))(1, 136, 32), Or = 0, kr = 1, Ar = class { constructor(e) { this.G1 = e.G1, this.Fr = e.Fr, this.reset(); } @@ -3902,26 +3872,26 @@ var Ar = class e { } addPolCommitment(e) { this.data.push({ - type: Mr, + type: Or, data: e }); } addScalar(e) { this.data.push({ - type: Nr, + type: kr, data: e }); } getChallenge() { if (this.data.length === 0) throw Error("Keccak256Transcript: No data to generate a transcript"); let e = 0, t = 0; - this.data.forEach((n) => Mr === n.type ? e++ : t++); + this.data.forEach((n) => Or === n.type ? e++ : t++); let n = new Uint8Array(t * this.Fr.n8 + e * this.G1.F.n8 * 2), r = 0; - for (let e = 0; e < this.data.length; e++) Mr === this.data[e].type ? (this.G1.toRprUncompressed(n, r, this.data[e].data), r += this.G1.F.n8 * 2) : (this.Fr.toRprBE(n, r, this.data[e].data), r += this.Fr.n8); - let i = u.fromRprBE(jr(n)); + for (let e = 0; e < this.data.length; e++) Or === this.data[e].type ? (this.G1.toRprUncompressed(n, r, this.data[e].data), r += this.G1.F.n8 * 2) : (this.Fr.toRprBE(n, r, this.data[e].data), r += this.Fr.n8); + let i = u.fromRprBE(Dr(n)); return this.Fr.e(i); } -}, Fr = class { +}, jr = class { static getZ1(e) { return [ e.zero, @@ -4308,8 +4278,8 @@ var Ar = class e { if (e !== Math.floor(this.eval.byteLength / this.Fr.n8)) throw Error("Polynomial evaluations buffer has incorrect size"); return e === 0 && this.logger.warn("Polynomial has length zero"), e; } -}, { stringifyBigInts: Ir } = p; -async function Lr(t, n, r, i) { +}, { stringifyBigInts: Mr } = p; +async function Nr(t, n, r, i) { let { fd: a, sections: o } = await e.readBinFile(n, "wtns", 2, 1 << 25, 1 << 23); r && r.debug("> Reading witness file"); let c = await tt(a, o); @@ -4322,7 +4292,7 @@ async function Lr(t, n, r, i) { r && (r.debug("----------------------------"), r.debug(" PLONK PROVE SETTINGS"), r.debug(` Curve: ${p.name}`), r.debug(` Circuit power: ${f.power}`), r.debug(` Domain size: ${f.domainSize}`), r.debug(` Vars: ${f.nVars}`), r.debug(` Public vars: ${f.nPublic}`), r.debug(` Constraints: ${f.nConstraints}`), r.debug(` Additions: ${f.nAdditions}`), r.debug("----------------------------")), r && r.debug("> Reading witness file data"); let _ = await e.readSection(a, o, 2); _.set(m.zero, 0); - let v = new s(h * f.nAdditions), y = {}, b = {}, x = {}, S = {}, C = new mr(p, r), w = new Pr(p); + let v = new s(h * f.nAdditions), y = {}, b = {}, x = {}, S = {}, C = new ur(p, r), w = new Ar(p); r && r.debug("> Reading Section 3. Additions"), await O(), r && r.debug("> Reading Section 12. Sigma1, Sigma2 & Sigma 3"), r && r.debug("··· Reading Sigma polynomials "), b.Sigma1 = new X(new s(g), p, r), b.Sigma2 = new X(new s(g), p, r), b.Sigma3 = new X(new s(g), p, r), await l.readToBuffer(b.Sigma1.coef, 0, g, d[12][0].p), await l.readToBuffer(b.Sigma2.coef, 0, g, d[12][0].p + 5 * g), await l.readToBuffer(b.Sigma3.coef, 0, g, d[12][0].p + 10 * g), r && r.debug("··· Reading Sigma evaluations"), x.Sigma1 = new Z(new s(g * 4), p, r), x.Sigma2 = new Z(new s(g * 4), p, r), x.Sigma3 = new Z(new s(g * 4), p, r), await l.readToBuffer(x.Sigma1.eval, 0, g * 4, d[12][0].p + g), await l.readToBuffer(x.Sigma2.eval, 0, g * 4, d[12][0].p + 6 * g), await l.readToBuffer(x.Sigma3.eval, 0, g * 4, d[12][0].p + 11 * g), r && r.debug("> Reading Section 14. Powers of Tau"); let T = await e.readSection(l, d, 14), E = []; for (let e = 1; e <= f.nPublic; e++) { @@ -4332,8 +4302,8 @@ async function Lr(t, n, r, i) { r && r.debug(""), r && r.debug("> ROUND 1"), await j(), r && r.debug("> ROUND 2"), await N(), r && r.debug("> ROUND 3"), await F(), r && r.debug("> ROUND 4"), await L(), r && r.debug("> ROUND 5"), await ee(), await l.close(), await a.close(); let D = C.toObjectProof(!1); return D.protocol = "plonk", D.curve = p.name, r && r.debug("PLONK PROVER FINISHED"), { - proof: Ir(D), - publicSignals: Ir(E) + proof: Mr(D), + publicSignals: Mr(E) }; async function O() { r && r.debug("··· Computing additions"); @@ -4437,7 +4407,7 @@ async function Lr(t, n, r, i) { let n = e * 4 * f.domainSize + t, r = x.Lagrange.getEvaluation(n), i = y.A.slice(e * h, (e + 1) * h); A = m.sub(A, m.mul(r, i)); } - let [j, M] = Fr.mul2(n, i, b, C, t % 4, m); + let [j, M] = jr.mul2(n, i, b, C, t % 4, m); j = m.mul(j, c), M = m.mul(M, c), j = m.add(j, m.mul(n, l)), M = m.add(M, m.mul(b, l)), j = m.add(j, m.mul(i, u)), M = m.add(M, m.mul(C, u)), j = m.add(j, m.mul(a, d)), M = m.add(M, m.mul(w, d)), j = m.add(j, A), j = m.add(j, p); let N = m.mul(S.beta, e), P = n; P = m.add(P, N), P = m.add(P, S.gamma); @@ -4445,7 +4415,7 @@ async function Lr(t, n, r, i) { F = m.add(F, m.mul(N, f.k1)), F = m.add(F, S.gamma); let I = a; I = m.add(I, m.mul(N, f.k2)), I = m.add(I, S.gamma); - let L = o, [ee, R] = Fr.mul4(P, F, I, L, b, C, w, E, t % 4, m); + let L = o, [ee, R] = jr.mul4(P, F, I, L, b, C, w, E, t % 4, m); ee = m.mul(ee, S.alpha), R = m.mul(R, S.alpha); let z = n; z = m.add(z, m.mul(S.beta, g)), z = m.add(z, S.gamma); @@ -4453,7 +4423,7 @@ async function Lr(t, n, r, i) { B = m.add(B, m.mul(S.beta, _)), B = m.add(B, S.gamma); let V = a; V = m.add(V, m.mul(S.beta, v)), V = m.add(V, S.gamma); - let te = s, [H, U] = Fr.mul4(z, B, V, te, b, C, w, k, t % 4, m); + let te = s, [H, U] = jr.mul4(z, B, V, te, b, C, w, k, t % 4, m); H = m.mul(H, S.alpha), U = m.mul(U, S.alpha); let ne = m.sub(o, m.one); ne = m.mul(ne, x.Lagrange.getEvaluation(t)), ne = m.mul(ne, S.alpha2); @@ -4525,80 +4495,80 @@ async function Lr(t, n, r, i) { } //#endregion //#region src/plonk_fullprove.js -var { unstringifyBigInts: Rr } = p; -async function zr(e, t, n, r, i, a) { - let o = Rr(e), s = { type: "mem" }; - return await Bt(o, t, s, i), await Lr(n, s, r, a); +var { unstringifyBigInts: Pr } = p; +async function Fr(e, t, n, r, i, a) { + let o = Pr(e), s = { type: "mem" }; + return await Bt(o, t, s, i), await Nr(n, s, r, a); } //#endregion //#region src/plonk_verify.js -var { unstringifyBigInts: Br } = p; -async function Vr(e, t, n, r) { - let i = Br(e); - n = Br(n); - let a = Br(t), o = await D(i.curve), s = o.Fr, c = o.G1; +var { unstringifyBigInts: Ir } = p; +async function Lr(e, t, n, r) { + let i = Ir(e); + n = Ir(n); + let a = Ir(t), o = await D(i.curve), s = o.Fr, c = o.G1; r && r.info("PLONK VERIFIER STARTED"); - let l = Hr(o, n); - if (i = Ur(o, i), !Wr(o, l)) return r.error("Proof commitments are not valid."), !1; + let l = Rr(o, n); + if (i = zr(o, i), !Br(o, l)) return r.error("Proof commitments are not valid."), !1; if (a.length != i.nPublic) return r && r.error("Invalid number of public inputs"), !1; - if (!qr(o, l)) return r && r.error("Proof evaluations are not valid"), !1; - if (!Jr(o, a)) return r && r.error("Public inputs are not valid."), !1; - let u = Yr(o, l, a, i); + if (!Ur(o, l)) return r && r.error("Proof evaluations are not valid"), !1; + if (!Wr(o, a)) return r && r.error("Public inputs are not valid."), !1; + let u = Gr(o, l, a, i); if (r) { r.debug("beta: " + s.toString(u.beta, 16)), r.debug("gamma: " + s.toString(u.gamma, 16)), r.debug("alpha: " + s.toString(u.alpha, 16)), r.debug("xi: " + s.toString(u.xi, 16)); for (let e = 1; e < 6; e++) r && r.debug("v: " + s.toString(u.v[e], 16)); r.debug("u: " + s.toString(u.u, 16)); } - let d = Xr(o, u, i); + let d = Kr(o, u, i); if (r) for (let e = 1; e < d.length; e++) r.debug(`L${e}(xi)=` + s.toString(d[e], 16)); if (a.length != i.nPublic) return r.error("Number of public signals does not match with vk"), !1; - let f = Zr(o, a, d); + let f = qr(o, a, d); r && r.debug("PI(xi): " + s.toString(f, 16)); - let p = Qr(o, l, u, f, d[1]); + let p = Jr(o, l, u, f, d[1]); r && r.debug("r0: " + s.toString(p, 16)); - let m = $r(o, l, u, i, d[1]); + let m = Yr(o, l, u, i, d[1]); r && r.debug("D: " + c.toString(c.toAffine(m), 16)); - let h = ei(o, l, u, i, m); + let h = Xr(o, l, u, i, m); r && r.debug("F: " + c.toString(c.toAffine(h), 16)); - let g = ti(o, l, u, p); + let g = Zr(o, l, u, p); r && r.debug("E: " + c.toString(c.toAffine(g), 16)); - let _ = await ni(o, l, u, i, g, h); + let _ = await Qr(o, l, u, i, g, h); return r && (_ ? r.info("OK!") : r.warn("Invalid Proof")), _; } -function Hr(e, t) { +function Rr(e, t) { let n = e.G1, r = e.Fr, i = {}; return i.A = n.fromObject(t.A), i.B = n.fromObject(t.B), i.C = n.fromObject(t.C), i.Z = n.fromObject(t.Z), i.T1 = n.fromObject(t.T1), i.T2 = n.fromObject(t.T2), i.T3 = n.fromObject(t.T3), i.eval_a = r.fromObject(t.eval_a), i.eval_b = r.fromObject(t.eval_b), i.eval_c = r.fromObject(t.eval_c), i.eval_zw = r.fromObject(t.eval_zw), i.eval_s1 = r.fromObject(t.eval_s1), i.eval_s2 = r.fromObject(t.eval_s2), i.Wxi = n.fromObject(t.Wxi), i.Wxiw = n.fromObject(t.Wxiw), i; } -function Ur(e, t) { +function zr(e, t) { let n = e.G1, r = e.G2, i = e.Fr, a = t; return a.Qm = n.fromObject(t.Qm), a.Ql = n.fromObject(t.Ql), a.Qr = n.fromObject(t.Qr), a.Qo = n.fromObject(t.Qo), a.Qc = n.fromObject(t.Qc), a.S1 = n.fromObject(t.S1), a.S2 = n.fromObject(t.S2), a.S3 = n.fromObject(t.S3), a.k1 = i.fromObject(t.k1), a.k2 = i.fromObject(t.k2), a.X_2 = r.fromObject(t.X_2), a; } -function Wr(e, t) { +function Br(e, t) { let n = e.G1; return !(!n.isValid(t.A) || !n.isValid(t.B) || !n.isValid(t.C) || !n.isValid(t.Z) || !n.isValid(t.T1) || !n.isValid(t.T2) || !n.isValid(t.T3) || !n.isValid(t.Wxi) || !n.isValid(t.Wxiw)); } -function Gr(e, t) { +function Vr(e, t) { return u.geq(t, 0) && u.lt(t, e.r); } -function Kr(e, t) { - return Gr(e, u.fromRprLE(t)); +function Hr(e, t) { + return Vr(e, u.fromRprLE(t)); } -function qr(e, t) { - return Kr(e, t.eval_a) && Kr(e, t.eval_b) && Kr(e, t.eval_c) && Kr(e, t.eval_s1) && Kr(e, t.eval_s2) && Kr(e, t.eval_zw); +function Ur(e, t) { + return Hr(e, t.eval_a) && Hr(e, t.eval_b) && Hr(e, t.eval_c) && Hr(e, t.eval_s1) && Hr(e, t.eval_s2) && Hr(e, t.eval_zw); } -function Jr(e, t) { - for (let n = 0; n < t.length; n++) if (!Gr(e, t[n])) return !1; +function Wr(e, t) { + for (let n = 0; n < t.length; n++) if (!Vr(e, t[n])) return !1; return !0; } -function Yr(e, t, n, r) { - let i = e.Fr, a = {}, o = new Pr(e); +function Gr(e, t, n, r) { + let i = e.Fr, a = {}, o = new Ar(e); o.addPolCommitment(r.Qm), o.addPolCommitment(r.Ql), o.addPolCommitment(r.Qr), o.addPolCommitment(r.Qo), o.addPolCommitment(r.Qc), o.addPolCommitment(r.S1), o.addPolCommitment(r.S2), o.addPolCommitment(r.S3); for (let e = 0; e < n.length; e++) o.addScalar(i.e(n[e])); o.addPolCommitment(t.A), o.addPolCommitment(t.B), o.addPolCommitment(t.C), a.beta = o.getChallenge(), o.reset(), o.addScalar(a.beta), a.gamma = o.getChallenge(), o.reset(), o.addScalar(a.beta), o.addScalar(a.gamma), o.addPolCommitment(t.Z), a.alpha = o.getChallenge(), o.reset(), o.addScalar(a.alpha), o.addPolCommitment(t.T1), o.addPolCommitment(t.T2), o.addPolCommitment(t.T3), a.xi = o.getChallenge(), o.reset(), o.addScalar(a.xi), o.addScalar(t.eval_a), o.addScalar(t.eval_b), o.addScalar(t.eval_c), o.addScalar(t.eval_s1), o.addScalar(t.eval_s2), o.addScalar(t.eval_zw), a.v = [], a.v[1] = o.getChallenge(); for (let e = 2; e < 6; e++) a.v[e] = i.mul(a.v[e - 1], a.v[1]); return o.reset(), o.addPolCommitment(t.Wxi), o.addPolCommitment(t.Wxiw), a.u = o.getChallenge(), a; } -function Xr(e, t, n) { +function Kr(e, t, n) { let r = e.Fr, i = t.xi, a = 1; for (let e = 0; e < n.power; e++) i = r.square(i), a *= 2; t.xin = i, t.zh = r.sub(i, r.one); @@ -4606,7 +4576,7 @@ function Xr(e, t, n) { for (let e = 1; e <= Math.max(1, n.nPublic); e++) o[e] = r.div(r.mul(c, t.zh), r.mul(s, r.sub(t.xi, c))), c = r.mul(c, r.w[n.power]); return o; } -function Zr(e, t, n) { +function qr(e, t, n) { let r = e.Fr, i = r.zero; for (let e = 0; e < t.length; e++) { let a = r.e(t[e]); @@ -4614,7 +4584,7 @@ function Zr(e, t, n) { } return i; } -function Qr(e, t, n, r, i) { +function Jr(e, t, n, r, i) { let a = e.Fr, o = r, s = a.mul(i, a.square(n.alpha)), c = a.add(t.eval_a, a.mul(n.beta, t.eval_s1)); c = a.add(c, n.gamma); let l = a.add(t.eval_b, a.mul(n.beta, t.eval_s2)); @@ -4622,21 +4592,21 @@ function Qr(e, t, n, r, i) { let u = a.add(t.eval_c, n.gamma), d = a.mul(a.mul(c, l), u); return d = a.mul(d, t.eval_zw), d = a.mul(d, n.alpha), a.sub(a.sub(o, s), d); } -function $r(e, t, n, r, i) { +function Yr(e, t, n, r, i) { let a = e.G1, o = e.Fr, s = a.timesFr(r.Qm, o.mul(t.eval_a, t.eval_b)); s = a.add(s, a.timesFr(r.Ql, t.eval_a)), s = a.add(s, a.timesFr(r.Qr, t.eval_b)), s = a.add(s, a.timesFr(r.Qo, t.eval_c)), s = a.add(s, r.Qc); let c = o.mul(n.beta, n.xi), l = o.add(o.add(t.eval_a, c), n.gamma), u = o.add(o.add(t.eval_b, o.mul(c, r.k1)), n.gamma), d = o.add(o.add(t.eval_c, o.mul(c, r.k2)), n.gamma), f = o.mul(o.mul(o.mul(l, u), d), n.alpha), p = o.mul(i, o.square(n.alpha)), m = a.timesFr(t.Z, o.add(o.add(f, p), n.u)), h = o.add(o.add(t.eval_a, o.mul(n.beta, t.eval_s1)), n.gamma), g = o.add(o.add(t.eval_b, o.mul(n.beta, t.eval_s2)), n.gamma), _ = o.mul(o.mul(n.alpha, n.beta), t.eval_zw), v = a.timesFr(r.S3, o.mul(o.mul(h, g), _)), y = t.T1, b = a.timesFr(t.T2, n.xin), x = a.timesFr(t.T3, o.square(n.xin)), S = a.add(y, a.add(b, x)); return S = a.timesFr(S, n.zh), a.sub(a.sub(a.add(s, m), v), S); } -function ei(e, t, n, r, i) { +function Xr(e, t, n, r, i) { let a = e.G1, o = a.add(i, a.timesFr(t.A, n.v[1])); return o = a.add(o, a.timesFr(t.B, n.v[2])), o = a.add(o, a.timesFr(t.C, n.v[3])), o = a.add(o, a.timesFr(r.S1, n.v[4])), o = a.add(o, a.timesFr(r.S2, n.v[5])), o; } -function ti(e, t, n, r) { +function Zr(e, t, n, r) { let i = e.G1, a = e.Fr, o = a.add(a.neg(r), a.mul(n.v[1], t.eval_a)); return o = a.add(o, a.mul(n.v[2], t.eval_b)), o = a.add(o, a.mul(n.v[3], t.eval_c)), o = a.add(o, a.mul(n.v[4], t.eval_s1)), o = a.add(o, a.mul(n.v[5], t.eval_s2)), o = a.add(o, a.mul(n.u, t.eval_zw)), i.timesFr(i.one, o); } -async function ni(e, t, n, r, i, a) { +async function Qr(e, t, n, r, i, a) { let o = e.G1, s = e.Fr, c = t.Wxi; c = o.add(c, o.timesFr(t.Wxiw, n.u)); let l = o.timesFr(t.Wxi, n.xi), u = s.mul(s.mul(n.u, n.xi), s.w[r.power]); @@ -4644,14 +4614,14 @@ async function ni(e, t, n, r, i, a) { } //#endregion //#region src/plonk_exportsoliditycalldata.js -var { unstringifyBigInts: ri } = p; +var { unstringifyBigInts: $r } = p; function Q(e) { let t = e.toString(16); for (; t.length < 64;) t = "0" + t; return t = `"0x${t}"`, t; } -async function ii(e, t) { - let n = ri(e), r = ri(t); +async function ei(e, t) { + let n = $r(e), r = $r(t); await D(n.curve); let i = ""; for (let e = 0; e < r.length; e++) i != "" && (i += ","), i += Q(r[e]); @@ -4659,16 +4629,16 @@ async function ii(e, t) { } //#endregion //#region src/plonk.js -var ai = /* @__PURE__ */ y({ - exportSolidityCallData: () => ii, - fullProve: () => zr, - prove: () => Lr, - setup: () => pr, - verify: () => Vr +var ti = /* @__PURE__ */ y({ + exportSolidityCallData: () => ei, + fullProve: () => Fr, + prove: () => Nr, + setup: () => lr, + verify: () => Lr }); //#endregion //#region src/plonk_equation.js -function oi(e, t) { +function ni(e, t) { return [ e, 0, @@ -4680,7 +4650,7 @@ function oi(e, t) { t.zero ]; } -function si(e, t, n, r, i, a, o, s) { +function ri(e, t, n, r, i, a, o, s) { return [ e, t, @@ -4692,7 +4662,7 @@ function si(e, t, n, r, i, a, o, s) { s ]; } -function ci(e, t, n, r, i, a, o, s, c) { +function ii(e, t, n, r, i, a, o, s, c) { return [ e, t, @@ -4706,18 +4676,18 @@ function ci(e, t, n, r, i, a, o, s, c) { } //#endregion //#region src/r1cs_constraint_processor.js -var li = 0, ui = 1, di = 2, fi = class { +var ai = 0, oi = 1, si = 2, ci = class { constructor(e, t, n, r, i) { this.Fr = e, this.logger = i, this.fnGetAdditionConstraint = n, this.fnGetMultiplicationConstraint = r; } processR1csConstraint(e, t, n, r) { this.normalizeLinearCombination(t), this.normalizeLinearCombination(n), this.normalizeLinearCombination(r); let i = this.getLinearCombinationType(t), a = this.getLinearCombinationType(n); - if (i === li || a === li) return this.processR1csAdditionConstraint(e, r); - if (i === ui) { + if (i === ai || a === ai) return this.processR1csAdditionConstraint(e, r); + if (i === oi) { let i = this.joinLinearCombinations(n, r, t[0]); return this.processR1csAdditionConstraint(e, i); - } else if (a === ui) { + } else if (a === oi) { let i = this.joinLinearCombinations(t, r, n[0]); return this.processR1csAdditionConstraint(e, i); } else return this.processR1csMultiplicationConstraint(e, t, n, r); @@ -4725,7 +4695,7 @@ var li = 0, ui = 1, di = 2, fi = class { getLinearCombinationType(e) { let t = this.Fr.zero, n = 0, r = Object.keys(e); for (let i = 0; i < r.length; i++) e[r[i]] == 0n ? delete e[r[i]] : r[i] == 0 ? t = this.Fr.add(t, e[r[i]]) : n++; - return n > 0 ? di : this.Fr.isZero(t) ? li : ui; + return n > 0 ? si : this.Fr.isZero(t) ? ai : oi; } normalizeLinearCombination(e) { let t = Object.keys(e); @@ -4766,7 +4736,7 @@ var li = 0, ui = 1, di = 2, fi = class { let i = [], a = [], o = this.reduceCoefs(e, i, a, t, 1), s = this.reduceCoefs(e, i, a, n, 1), c = this.reduceCoefs(e, i, a, r, 1), l = this.fnGetMultiplicationConstraint(o.signals[0], s.signals[0], c.signals[0], this.Fr.mul(o.coefs[0], s.k), this.Fr.mul(o.k, s.coefs[0]), this.Fr.mul(o.coefs[0], s.coefs[0]), this.Fr.neg(c.coefs[0]), this.Fr.sub(this.Fr.mul(o.k, s.k), c.k)); return i.push(l), [i, a]; } -}, pi = class { +}, li = class { constructor(e, t, n) { this.n = e, this.polynomials = Array(e).fill(void 0), this.curve = t, this.Fr = t.Fr, this.G1 = t.G1, this.logger = n; } @@ -4793,7 +4763,7 @@ var li = 0, ui = 1, di = 2, fi = class { }; //#endregion //#region src/fflonk_setup.js -async function mi(i, c, l, d) { +async function ui(i, c, l, d) { d && d.info("FFLONK SETUP STARTED"), globalThis.gc && globalThis.gc(), d && d.info("> Reading PTau file"); let { fd: f, sections: p } = await r(c, "ptau", 1, 1 << 22, 1 << 24); if (!p[12]) throw Error("Powers of Tau is not well prepared. Section 12 missing."); @@ -4823,8 +4793,8 @@ async function mi(i, c, l, d) { let P = se(E.cirPower, m.Fr); return await I(), await g.close(), await f.close(), d && d.info("FFLONK SETUP FINISHED"), 0; async function F(t, n, r) { - for (let e = 0; e < E.nPublic; e++) D.push(oi(e + 1, t)); - let i = new fi(t, oi, si, ci, r), a = await e.readSection(g, _, 2), o = 0; + for (let e = 0; e < E.nPublic; e++) D.push(ni(e + 1, t)); + let i = new ci(t, ni, ri, ii, r), a = await e.readSection(g, _, 2), o = 0; for (let e = 0; e < n.nConstraints; e++) { r && e !== 0 && e % 5e5 == 0 && r.info(` processing r1cs constraints ${e}/${n.nConstraints}`); let [t, a] = i.processR1csConstraint(E, ...s()); @@ -4905,7 +4875,7 @@ async function mi(i, c, l, d) { await a(e, 16), T = new s((E.domainSize * 9 + 18) * x), await f.readToBuffer(T, 0, (E.domainSize * 9 + 18) * x, p[2][0].p), await e.write(T), await n(e); } async function H(e) { - let t = new pi(8, m, d); + let t = new li(8, m, d); if (t.addPolynomial(0, C.QL), t.addPolynomial(1, C.QR), t.addPolynomial(2, C.QO), t.addPolynomial(3, C.QM), t.addPolynomial(4, C.QC), t.addPolynomial(5, C.S1), t.addPolynomial(6, C.S2), t.addPolynomial(7, C.S3), C.C0 = t.getPolynomial(), C.C0.degree() >= 8 * E.domainSize) throw Error("C0 Polynomial is not well calculated"); await a(e, 17), await e.write(C.C0.coef), await n(e); } @@ -4957,8 +4927,8 @@ async function mi(i, c, l, d) { } //#endregion //#region src/fflonk_prove.js -var { stringifyBigInts: hi } = p; -async function gi(t, n, r, i) { +var { stringifyBigInts: di } = p; +async function fi(t, n, r, i) { r && r.info("FFLONK PROVER STARTED"), r && r.info("> Reading witness file"); let { fd: a, sections: o } = await e.readBinFile(n, "wtns", 2, 1 << 25, 1 << 23), c = await tt(a, o); r && r.info("> Reading zkey file"); @@ -4970,7 +4940,7 @@ async function gi(t, n, r, i) { r && (r.info("----------------------------"), r.info(" FFLONK PROVE SETTINGS"), r.info(` Curve: ${p.name}`), r.info(` Circuit power: ${f.power}`), r.info(` Domain size: ${f.domainSize}`), r.info(` Vars: ${f.nVars}`), r.info(` Public vars: ${f.nPublic}`), r.info(` Constraints: ${f.nConstraints}`), r.info(` Additions: ${f.nAdditions}`), r.info("----------------------------")), r && r.info("> Reading witness file data"); let v = await e.readSection(a, o, 2); await a.close(), v.set(m.zero, 0); - let y = new s(f.nAdditions * h), b = {}, x = {}, S = {}, C = {}, w = {}, T = {}, E = new mr(p, r); + let y = new s(f.nAdditions * h), b = {}, x = {}, S = {}, C = {}, w = {}, T = {}, E = new ur(p, r); r && r.info("> Reading Section 3. Additions"), await A(), r && r.info("> Reading Sections 12,13,14. Sigma1, Sigma2 & Sigma 3"), r && r.info("··· Reading Sigma polynomials "), x.Sigma1 = new X(new s(_), p, r), x.Sigma2 = new X(new s(_), p, r), x.Sigma3 = new X(new s(_), p, r), await l.readToBuffer(x.Sigma1.coef, 0, _, d[12][0].p), await l.readToBuffer(x.Sigma2.coef, 0, _, d[13][0].p), await l.readToBuffer(x.Sigma3.coef, 0, _, d[14][0].p), r && r.info("··· Reading Sigma evaluations"), S.Sigma1 = new Z(new s(_ * 4), p, r), S.Sigma2 = new Z(new s(_ * 4), p, r), S.Sigma3 = new Z(new s(_ * 4), p, r), await l.readToBuffer(S.Sigma1.eval, 0, _ * 4, d[12][0].p + _), await l.readToBuffer(S.Sigma2.eval, 0, _ * 4, d[13][0].p + _), await l.readToBuffer(S.Sigma3.eval, 0, _ * 4, d[14][0].p + _), r && r.info("> Reading Section 16. Powers of Tau"); let D = new s(f.domainSize * 16 * g); await l.readToBuffer(D, 0, (f.domainSize * 9 + 18) * g, d[16][0].p), globalThis.gc && globalThis.gc(), r && r.info(""), r && r.info("> ROUND 1"), await N(), delete x.T0, delete S.QL, delete S.QR, delete S.QM, delete S.QO, delete S.QC, globalThis.gc && globalThis.gc(), r && r.info("> ROUND 2"), await P(), delete b.A, delete b.B, delete b.C, delete S.A, delete S.B, delete S.C, delete S.Sigma1, delete S.Sigma2, delete S.Sigma3, delete S.lagrange1, delete S.Z, globalThis.gc && globalThis.gc(), r && r.info("> ROUND 3"), await F(), delete x.A, delete x.B, delete x.C, delete x.Z, delete x.T1, delete x.T2, delete x.Sigma1, delete x.Sigma2, delete x.Sigma3, delete x.QL, delete x.QR, delete x.QM, delete x.QC, delete x.QO, globalThis.gc && globalThis.gc(), r && r.info("> ROUND 4"), await I(), globalThis.gc && globalThis.gc(), r && r.info("> ROUND 5"), await L(), delete x.C0, delete x.C1, delete x.C2, delete x.R1, delete x.R2, delete x.F, delete x.L, delete x.ZT, delete x.ZTS2, await l.close(), globalThis.gc && globalThis.gc(), E.addEvaluation("inv", ee()); @@ -4982,8 +4952,8 @@ async function gi(t, n, r, i) { k.push(u.fromRprLE(n)); } return r && r.info("FFLONK PROVER FINISHED"), { - proof: hi(O), - publicSignals: hi(k) + proof: di(O), + publicSignals: di(k) }; async function A() { r && r.info("··· Computing additions"); @@ -5050,13 +5020,13 @@ async function gi(t, n, r, i) { delete b.T0; } async function a() { - let e = new pi(4, p, r); + let e = new li(4, p, r); if (e.addPolynomial(0, x.A), e.addPolynomial(1, x.B), e.addPolynomial(2, x.C), e.addPolynomial(3, x.T0), x.C1 = e.getPolynomial(), x.C1.degree() >= 8 * f.domainSize - 8) throw Error("C1 Polynomial is not well calculated"); } } async function P() { r && r.info("> Computing challenges beta and gamma"); - let e = new Pr(p); + let e = new Ar(p); e.addPolCommitment(f.C0); for (let t = 0; t < f.nPublic; t++) e.addScalar(b.A.slice(t * h, t * h + h)); e.addPolCommitment(E.getPolynomial("C1")), w.beta = e.getChallenge(), r && r.info("··· challenges.beta: " + m.toString(w.beta)), e.reset(), e.addScalar(w.beta), w.gamma = e.getChallenge(), r && r.info("··· challenges.gamma: " + m.toString(w.gamma)), r && r.info("> Computing Z polynomial"), await n(), r && r.info("> Computing T1 polynomial"), await i(), r && r.info("> Computing T2 polynomial"), await a(), r && r.info("> Computing C2 polynomial"), await o(), r && r.info("> Computing C2 multi exponentiation"); @@ -5132,13 +5102,13 @@ async function gi(t, n, r, i) { delete b.T2, delete b.T2z, delete x.T2z; } async function o() { - let e = new pi(3, p, r); + let e = new li(3, p, r); if (e.addPolynomial(0, x.Z), e.addPolynomial(1, x.T1), e.addPolynomial(2, x.T2), x.C2 = e.getPolynomial(), x.C2.degree() >= 9 * f.domainSize) throw Error("C2 Polynomial is not well calculated"); } } async function F() { r && r.info("> Computing challenge xi"); - let e = new Pr(p); + let e = new Ar(p); e.addScalar(w.gamma), e.addPolCommitment(E.getPolynomial("C2")), w.xiSeed = e.getChallenge(); let t = m.square(w.xiSeed); T.w8 = [], T.w8[0] = m.one; @@ -5153,7 +5123,7 @@ async function gi(t, n, r, i) { } async function I() { r && r.info("> Computing challenge alpha"); - let e = new Pr(p); + let e = new Ar(p); e.addScalar(w.xiSeed), e.addScalar(E.getEvaluation("ql")), e.addScalar(E.getEvaluation("qr")), e.addScalar(E.getEvaluation("qm")), e.addScalar(E.getEvaluation("qo")), e.addScalar(E.getEvaluation("qc")), e.addScalar(E.getEvaluation("s1")), e.addScalar(E.getEvaluation("s2")), e.addScalar(E.getEvaluation("s3")), e.addScalar(E.getEvaluation("a")), e.addScalar(E.getEvaluation("b")), e.addScalar(E.getEvaluation("c")), e.addScalar(E.getEvaluation("z")), e.addScalar(E.getEvaluation("zw")), e.addScalar(E.getEvaluation("t1w")), e.addScalar(E.getEvaluation("t2w")), w.alpha = e.getChallenge(), r && r.info("··· challenges.alpha: " + m.toString(w.alpha)), r && r.info("> Reading C0 polynomial"), x.C0 = new X(new s(_ * 8), p, r), await l.readToBuffer(x.C0.coef, 0, _ * 8, d[17][0].p), r && r.info("> Computing R0 polynomial"), n(), r && r.info("> Computing R1 polynomial"), i(), r && r.info("> Computing R2 polynomial"), a(), r && r.info("> Computing F polynomial"), await o(), r && r.info("> Computing W1 multi exponentiation"); let t = await x.F.multiExponentiation(D, "W1"); return E.addPolynomial("W1", t), 0; @@ -5218,7 +5188,7 @@ async function gi(t, n, r, i) { } async function L() { r && r.info("> Computing challenge y"); - let e = new Pr(p); + let e = new Ar(p); e.addScalar(w.alpha), e.addPolCommitment(E.getPolynomial("W1")), w.y = e.getChallenge(), r && r.info("··· challenges.y: " + m.toString(w.y)), r && r.info("> Computing L polynomial"), await o(), r && r.info("> Computing ZTS2 polynomial"), await c(); let t = x.ZTS2.evaluate(w.y); t = m.inv(t), x.L.mulScalar(t); @@ -5330,69 +5300,69 @@ async function gi(t, n, r, i) { } //#endregion //#region src/fflonk_full_prove.js -var { unstringifyBigInts: _i } = p; -async function vi(e, t, n, r, i, a) { - let o = _i(e), s = { type: "mem" }; - return await Bt(o, t, s, i), await gi(n, s, r, a); +var { unstringifyBigInts: pi } = p; +async function mi(e, t, n, r, i, a) { + let o = pi(e), s = { type: "mem" }; + return await Bt(o, t, s, i), await fi(n, s, r, a); } //#endregion //#region src/fflonk_verify.js -var { unstringifyBigInts: yi } = p; -async function bi(e, t, n, r) { - r && r.info("FFLONK VERIFIER STARTED"), e = yi(e), n = yi(n); - let i = await D(e.curve), a = xi(i, e), o = new mr(i, r); +var { unstringifyBigInts: hi } = p; +async function gi(e, t, n, r) { + r && r.info("FFLONK VERIFIER STARTED"), e = hi(e), n = hi(n); + let i = await D(e.curve), a = _i(i, e), o = new ur(i, r); o.fromObjectProof(n); - let s = yi(t); + let s = hi(t); if (s.length !== a.nPublic) return r.error("Number of public signals does not match with vk"), !1; let c = i.Fr; - if (r && (r.info("----------------------------"), r.info(" FFLONK VERIFY SETTINGS"), r.info(` Curve: ${i.name}`), r.info(` Circuit power: ${a.power}`), r.info(` Domain size: ${2 ** a.power}`), r.info(` Public vars: ${a.nPublic}`), r.info("----------------------------")), r && r.info("> Checking commitments belong to G1"), !Si(i, o, a)) return r && r.error("Proof commitments are not valid"), !1; - if (r && r.info("> Checking evaluations belong to F"), !Ti(i, o)) return r && r.error("Proof evaluations are not valid."), !1; - if (r && r.info("> Checking public inputs belong to F"), !Ei(i, s)) return r && r.error("Public inputs are not valid."), !1; + if (r && (r.info("----------------------------"), r.info(" FFLONK VERIFY SETTINGS"), r.info(` Curve: ${i.name}`), r.info(` Circuit power: ${a.power}`), r.info(` Domain size: ${2 ** a.power}`), r.info(` Public vars: ${a.nPublic}`), r.info("----------------------------")), r && r.info("> Checking commitments belong to G1"), !vi(i, o, a)) return r && r.error("Proof commitments are not valid"), !1; + if (r && r.info("> Checking evaluations belong to F"), !xi(i, o)) return r && r.error("Proof evaluations are not valid."), !1; + if (r && r.info("> Checking public inputs belong to F"), !Si(i, s)) return r && r.error("Public inputs are not valid."), !1; r && r.info("> Computing challenges"); - let { challenges: l, roots: u } = Di(i, o, a, s, r); + let { challenges: l, roots: u } = Ci(i, o, a, s, r); r && r.info("> Computing Zero polynomial evaluation Z_H(xi)"), l.zh = c.sub(l.xiN, c.one), l.invzh = c.inv(l.zh), r && r.info("> Computing Lagrange evaluations"); - let d = await Oi(i, l, a); + let d = await wi(i, l, a); r && r.info("> Computing polynomial identities PI(X)"); - let f = ki(i, s, d); + let f = Ti(i, s, d); r && r.info("> Computing r0(y)"); - let p = Ai(o, l, u, i, r); + let p = Ei(o, l, u, i, r); r && r.info("> Computing r1(y)"); - let m = ji(o, l, u, f, i, r); + let m = Di(o, l, u, f, i, r); r && r.info("> Computing r2(y)"); - let h = Mi(o, l, u, d[1], a, i, r); + let h = Oi(o, l, u, d[1], a, i, r); r && r.info("> Computing F"); - let g = Ni(i, o, a, l, u); + let g = ki(i, o, a, l, u); r && r.info("> Computing E"); - let _ = Pi(i, o, l, a, p, m, h); + let _ = Ai(i, o, l, a, p, m, h); r && r.info("> Computing J"); - let v = Fi(i, o, l); + let v = ji(i, o, l); r && r.info("> Validate all evaluations with a pairing"); - let y = await Ii(i, o, l, a, g, _, v); + let y = await Mi(i, o, l, a, g, _, v); return r && (y ? r.info("PROOF VERIFIED SUCCESSFULLY") : r.warn("Invalid Proof")), r && r.info("FFLONK VERIFIER FINISHED"), y; } -function xi(e, t) { +function _i(e, t) { let n = t; return n.k1 = e.Fr.fromObject(t.k1), n.k2 = e.Fr.fromObject(t.k2), n.w = e.Fr.fromObject(t.w), n.w3 = e.Fr.fromObject(t.w3), n.w4 = e.Fr.fromObject(t.w4), n.w8 = e.Fr.fromObject(t.w8), n.wr = e.Fr.fromObject(t.wr), n.X_2 = e.G2.fromObject(t.X_2), n.C0 = e.G1.fromObject(t.C0), n; } -function Si(e, t, n) { +function vi(e, t, n) { let r = e.G1; return r.isValid(t.polynomials.C1) && r.isValid(t.polynomials.C2) && r.isValid(t.polynomials.W1) && r.isValid(t.polynomials.W2) && r.isValid(n.C0); } -function Ci(e, t) { +function yi(e, t) { return u.geq(t, 0) && u.lt(t, e.r); } -function wi(e, t) { - return Ci(e, u.fromRprLE(t)); +function bi(e, t) { + return yi(e, u.fromRprLE(t)); } -function Ti(e, t) { - return wi(e, t.evaluations.ql) && wi(e, t.evaluations.qr) && wi(e, t.evaluations.qm) && wi(e, t.evaluations.qo) && wi(e, t.evaluations.qc) && wi(e, t.evaluations.s1) && wi(e, t.evaluations.s2) && wi(e, t.evaluations.s3) && wi(e, t.evaluations.a) && wi(e, t.evaluations.b) && wi(e, t.evaluations.c) && wi(e, t.evaluations.z) && wi(e, t.evaluations.zw) && wi(e, t.evaluations.t1w) && wi(e, t.evaluations.t2w); +function xi(e, t) { + return bi(e, t.evaluations.ql) && bi(e, t.evaluations.qr) && bi(e, t.evaluations.qm) && bi(e, t.evaluations.qo) && bi(e, t.evaluations.qc) && bi(e, t.evaluations.s1) && bi(e, t.evaluations.s2) && bi(e, t.evaluations.s3) && bi(e, t.evaluations.a) && bi(e, t.evaluations.b) && bi(e, t.evaluations.c) && bi(e, t.evaluations.z) && bi(e, t.evaluations.zw) && bi(e, t.evaluations.t1w) && bi(e, t.evaluations.t2w); } -function Ei(e, t) { - for (let n = 0; n < t.length; n++) if (!Ci(e, t[n])) return !1; +function Si(e, t) { + for (let n = 0; n < t.length; n++) if (!yi(e, t[n])) return !1; return !0; } -function Di(e, t, n, r, i) { - let a = e.Fr, o = {}, s = {}, c = new Pr(e); +function Ci(e, t, n, r, i) { + let a = e.Fr, o = {}, s = {}, c = new Ar(e); c.addPolCommitment(n.C0); for (let e = 0; e < r.length; e++) c.addScalar(a.e(r[e])); c.addPolCommitment(t.polynomials.C1), o.beta = c.getChallenge(), c.reset(), c.addScalar(o.beta), o.gamma = c.getChallenge(), c.reset(), c.addScalar(o.gamma), c.addPolCommitment(t.polynomials.C2); @@ -5412,7 +5382,7 @@ function Di(e, t, n, r, i) { roots: s }; } -async function Oi(e, t, n) { +async function wi(e, t, n) { let r = e.Fr, i = Math.max(1, n.nPublic), a = new s(i * r.n8), o = new s(i * r.n8), c = r.one; for (let e = 0; e < i; e++) { let i = e * r.n8; @@ -5426,7 +5396,7 @@ async function Oi(e, t, n) { } return l; } -function ki(e, t, n) { +function Ti(e, t, n) { let r = e.Fr, i = r.zero; for (let e = 0; e < t.length; e++) { let a = r.e(t[e]); @@ -5434,8 +5404,8 @@ function ki(e, t, n) { } return i; } -function Ai(e, t, n, r, i) { - let a = r.Fr, o = Li(n.S0.h0w8, t.y, t.xi, r); +function Ei(e, t, n, r, i) { + let a = r.Fr, o = Ni(n.S0.h0w8, t.y, t.xi, r); i && i.info("··· Computing r0(y)"); let s = a.zero; for (let t = 0; t < 8; t++) { @@ -5447,8 +5417,8 @@ function Ai(e, t, n, r, i) { } return s; } -function ji(e, t, n, r, i, a) { - let o = i.Fr, s = Li(n.S1.h1w4, t.y, t.xi, i); +function Di(e, t, n, r, i, a) { + let o = i.Fr, s = Ni(n.S1.h1w4, t.y, t.xi, i); a && a.info("··· Computing T0(xi)"); let c = o.mul(e.evaluations.ql, e.evaluations.a); c = o.add(c, o.mul(e.evaluations.qr, e.evaluations.b)), c = o.add(c, o.mul(e.evaluations.qm, o.mul(e.evaluations.a, e.evaluations.b))), c = o.add(c, o.mul(e.evaluations.qo, e.evaluations.c)), c = o.add(c, e.evaluations.qc), c = o.add(c, r), c = o.mul(c, t.invzh), a && a.info("··· Computing C1(h_1ω_4^i) values"); @@ -5461,8 +5431,8 @@ function ji(e, t, n, r, i, a) { } return l; } -function Mi(e, t, n, r, i, a, o) { - let s = a.Fr, c = Ri([n.S2.h2w3, n.S2.h3w3], t.y, t.xi, t.xiw, a); +function Oi(e, t, n, r, i, a, o) { + let s = a.Fr, c = Pi([n.S2.h2w3, n.S2.h3w3], t.y, t.xi, t.xiw, a); o && o.info("··· Computing T1(xi)"); let l = s.sub(e.evaluations.z, s.one); l = s.mul(l, r), l = s.mul(l, t.invzh), o && o.info("··· Computing T2(xi)"); @@ -5480,7 +5450,7 @@ function Mi(e, t, n, r, i, a, o) { } return b; } -function Ni(e, t, n, r, i) { +function ki(e, t, n, r, i) { let a = e.G1, o = e.Fr, s = o.sub(r.y, i.S0.h0w8[0]); for (let e = 1; e < 8; e++) s = o.mul(s, o.sub(r.y, i.S0.h0w8[e])); r.temp = s; @@ -5493,20 +5463,20 @@ function Ni(e, t, n, r, i) { let u = a.timesFr(t.polynomials.C1, r.quotient1), d = a.timesFr(t.polynomials.C2, r.quotient2); return a.add(n.C0, a.add(u, d)); } -function Pi(e, t, n, r, i, a, o) { +function Ai(e, t, n, r, i, a, o) { let s = e.G1, c = e.Fr, l = c.mul(a, n.quotient1), u = c.mul(o, n.quotient2); return s.timesFr(s.one, c.add(i, c.add(l, u))); } -function Fi(e, t, n) { +function ji(e, t, n) { return e.G1.timesFr(t.polynomials.W1, n.temp); } -async function Ii(e, t, n, r, i, a, o) { +async function Mi(e, t, n, r, i, a, o) { let s = e.G1, c = s.timesFr(t.polynomials.W2, n.y); c = s.add(s.sub(s.sub(i, a), o), c); let l = e.G2.one, u = t.polynomials.W2, d = r.X_2; return await e.pairingEq(s.neg(c), l, u, d); } -function Li(e, t, n, r) { +function Ni(e, t, n, r) { let i = r.Fr, a = e.length, o = i.sub(i.exp(t, a), n), s = i.mul(i.e(a), i.exp(e[0], a - 2)), c = []; for (let n = 0; n < a; n++) { let r = e[(a - 1) * n % a], l = i.sub(t, e[n]); @@ -5514,7 +5484,7 @@ function Li(e, t, n, r) { } return c; } -function Ri(e, t, n, r, i) { +function Pi(e, t, n, r, i) { let a = i.Fr, o = [], s = e[0].length, c = s * e.length, l = a.exp(t, c), u = a.mul(a.add(n, r), a.exp(t, s)), d = a.mul(n, r), f = a.add(a.sub(l, u), d), p = a.mul(a.mul(a.e(s), e[0][0]), a.sub(n, r)); for (let n = 0; n < s; n++) { let r = e[0][(s - 1) * n % s], i = a.sub(t, e[0][n]), c = a.mul(p, a.mul(r, i)); @@ -5529,14 +5499,14 @@ function Ri(e, t, n, r, i) { } //#endregion //#region src/fflonk_export_calldata.js -var { unstringifyBigInts: zi } = p; +var { unstringifyBigInts: Fi } = p; function $(e) { let t = e.toString(16); for (; t.length < 64;) t = "0" + t; return t = `0x${t}`, t; } -async function Bi(e, t) { - let n = zi(t), r = zi(e); +async function Ii(e, t) { + let n = Fi(t), r = Fi(e); await D(n.curve); let i = ""; for (let e = 0; e < r.length; e++) i !== "" && (i += ","), i += $(r[e]); @@ -5544,13 +5514,13 @@ async function Bi(e, t) { } //#endregion //#region src/fflonk.js -var Vi = /* @__PURE__ */ y({ - exportSolidityCallData: () => Bi, - exportSolidityVerifier: () => ur, - fullProve: () => vi, - prove: () => gi, - setup: () => mi, - verify: () => bi +var Li = /* @__PURE__ */ y({ + exportSolidityCallData: () => Ii, + exportSolidityVerifier: () => null, + fullProve: () => mi, + prove: () => fi, + setup: () => ui, + verify: () => gi }); //#endregion -export { b as curves, Vi as fflonk, Zt as groth16, ai as plonk, An as powersOfTau, In as r1cs, Hn as wtns, fr as zKey }; +export { b as curves, Li as fflonk, Zt as groth16, ti as plonk, An as powersOfTau, In as r1cs, Hn as wtns, cr as zKey }; diff --git a/build/cli.cjs b/build/cli.cjs index b060d041..de87bc6b 100644 --- a/build/cli.cjs +++ b/build/cli.cjs @@ -2517,6 +2517,7 @@ async function newZKey(r1csName, ptauName, zkeyName, logger) { csHasher.update(buff); } function memUsage() { + if (typeof process === "undefined" || !process.memoryUsage) return {}; let m = process.memoryUsage(); for (const i in m) m[i] = Math.round(m[i] / (1024 * 1024)); return m; @@ -4385,7 +4386,7 @@ async function joinABC(curve, zkey, a, b, c, logger) { return outBuff; } function memUsage(logger) { - if (!logger) return; + if (!logger || typeof process === "undefined" || !process.memoryUsage) return; const used = process.memoryUsage(); logger.debug(" ", "\x1B[0m Heap:\x1B[32m", `${Math.round(used.heapUsed / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m / \x1B[32m", `${Math.round(used.heapTotal / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m RSS:\x1B[32m", `${Math.round(used.rss / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m External:\x1B[32m", `${Math.round(used.external / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m ArrBuffers:\x1B[32m", `${Math.round(used.arrayBuffers / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m"); } diff --git a/build/main.cjs b/build/main.cjs index 98df8cae..87799ad3 100644 --- a/build/main.cjs +++ b/build/main.cjs @@ -1231,7 +1231,7 @@ async function joinABC(curve, zkey, a, b, c, logger) { return outBuff; } function memUsage(logger) { - if (!logger) return; + if (!logger || typeof process === "undefined" || !process.memoryUsage) return; const used = process.memoryUsage(); logger.debug(" ", "\x1B[0m Heap:\x1B[32m", `${Math.round(used.heapUsed / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m / \x1B[32m", `${Math.round(used.heapTotal / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m RSS:\x1B[32m", `${Math.round(used.rss / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m External:\x1B[32m", `${Math.round(used.external / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m ArrBuffers:\x1B[32m", `${Math.round(used.arrayBuffers / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m"); } @@ -3601,6 +3601,7 @@ async function newZKey(r1csName, ptauName, zkeyName, logger) { csHasher.update(buff); } function memUsage() { + if (typeof process === "undefined" || !process.memoryUsage) return {}; let m = process.memoryUsage(); for (const i in m) m[i] = Math.round(m[i] / (1024 * 1024)); return m; diff --git a/build/snarkjs.min.js b/build/snarkjs.min.js index 0c46d146..5f741aa7 100644 --- a/build/snarkjs.min.js +++ b/build/snarkjs.min.js @@ -1,193 +1,9646 @@ -var snarkjs=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=Object.create,n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.getPrototypeOf,o=Object.prototype.hasOwnProperty,s=(e,t)=>()=>(e&&(t=e(e=0)),t),c=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),l=(e,t)=>{let r={};for(var i in e)n(r,i,{get:e[i],enumerable:!0});return t||n(r,Symbol.toStringTag,{value:`Module`}),r},u=(e,t,a,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=i(t),l=0,u=c.length,d;lt[e]).bind(null,d),enumerable:!(s=r(t,d))||s.enumerable});return e},d=(e,r,i)=>(i=e==null?{}:t(a(e)),u(r||!e||!e.__esModule?n(i,`default`,{value:e,enumerable:!0}):i,e)),f=l({gzipCode:()=>p,n8q:()=>32,n8r:()=>32,pG1b:()=>_,pG1gen:()=>h,pG1zero:()=>g,pG2b:()=>b,pG2gen:()=>v,pG2zero:()=>y,pOneT:()=>x,pq:()=>488,pr:()=>m,prePSize:()=>192,preQSize:()=>S,q:()=>C,r:()=>w}),p,m,h,g,_,v,y,b,x,S,C,w,T=s((()=>{p=`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`,m=1768,h=31432,g=31528,_=3080,v=31624,y=31816,b=12456,x=32008,S=19776,C=`21888242871839275222246405745257275088696311157297823662689037894645226208583`,w=`21888242871839275222246405745257275088548364400416034343698204186575808495617`}));function E(e){return BigInt(e)}function D(e){return e<0n}function O(e){return e===0n}function k(e){return D(e)?e.toString(2).length-1:e.toString(2).length}function A(e){let t=[],n=E(e);return t.push(Number(n&255n)),t.push(Number(n>>8n&255n)),t.push(Number(n>>16n&255n)),t.push(Number(n>>24n&255n)),t}function j(e){for(var t=[],n=0;n>6,128|r&63):r<55296||r>=57344?t.push(224|r>>12,128|r>>6&63,128|r&63):(n++,r=65536+((r&1023)<<10|e.charCodeAt(n)&1023),t.push(240|r>>18,128|r>>12&63,128|r>>6&63,128|r&63))}return t}function M(e){let t=j(e);return[...L(t.length),...t]}function N(e){let t=[],n=E(e);if(D(n))throw Error(`Number cannot be negative`);for(;!O(n);)t.push(Number(n&127n)),n>>=7n;t.length==0&&t.push(0);for(let e=0;e4294967295n)throw Error(`Number too big`);if(t>2147483647n&&(t-=4294967296n),t<-2147483648n)throw Error(`Number too small`);return P(t)}function I(e){let t=E(e);if(t>18446744073709551615n)throw Error(`Number too big`);if(t>9223372036854775807n&&(t-=18446744073709551616n),t<-9223372036854775808n)throw Error(`Number too small`);return P(t)}function L(e){let t=E(e);if(t>4294967295n)throw Error(`Number too big`);return N(t)}function ee(e){return Array.from(e,function(e){return(`0`+(e&255).toString(16)).slice(-2)}).join(``)}function R(e){if(typeof e==`string`){let t=e.split(` -`);for(let e=0;e{})),ne,re=s((()=>{te(),ne=class{constructor(e){this.func=e,this.functionName=e.functionName,this.module=e.module}setLocal(e,t){let n=this.func.localIdxByName[e];if(n===void 0)throw Error(`Local Variable not defined: Function: ${this.functionName} local: ${e} `);return[...t,33,...L(n)]}teeLocal(e,t){let n=this.func.localIdxByName[e];if(n===void 0)throw Error(`Local Variable not defined: Function: ${this.functionName} local: ${e} `);return[...t,34,...L(n)]}getLocal(e){let t=this.func.localIdxByName[e];if(t===void 0)throw Error(`Local Variable not defined: Function: ${this.functionName} local: ${e} `);return[32,...L(t)]}i64_load8_s(e,t,n){let r=t||0,i=n===void 0?0:n;return[...e,48,i,...L(r)]}i64_load8_u(e,t,n){let r=t||0,i=n===void 0?0:n;return[...e,49,i,...L(r)]}i64_load16_s(e,t,n){let r=t||0,i=n===void 0?1:n;return[...e,50,i,...L(r)]}i64_load16_u(e,t,n){let r=t||0,i=n===void 0?1:n;return[...e,51,i,...L(r)]}i64_load32_s(e,t,n){let r=t||0,i=n===void 0?2:n;return[...e,52,i,...L(r)]}i64_load32_u(e,t,n){let r=t||0,i=n===void 0?2:n;return[...e,53,i,...L(r)]}i64_load(e,t,n){let r=t||0,i=n===void 0?3:n;return[...e,41,i,...L(r)]}i64_store(e,t,n,r){let i,a,o;return Array.isArray(t)?(i=0,a=3,o=t):Array.isArray(n)?(i=t,a=3,o=n):Array.isArray(r)&&(i=t,a=n,o=r),[...e,...o,55,a,...L(i)]}i64_store32(e,t,n,r){let i,a,o;return Array.isArray(t)?(i=0,a=2,o=t):Array.isArray(n)?(i=t,a=2,o=n):Array.isArray(r)&&(i=t,a=n,o=r),[...e,...o,62,a,...L(i)]}i64_store16(e,t,n,r){let i,a,o;return Array.isArray(t)?(i=0,a=1,o=t):Array.isArray(n)?(i=t,a=1,o=n):Array.isArray(r)&&(i=t,a=n,o=r),[...e,...o,61,a,...L(i)]}i64_store8(e,t,n,r){let i,a,o;return Array.isArray(t)?(i=0,a=0,o=t):Array.isArray(n)?(i=t,a=0,o=n):Array.isArray(r)&&(i=t,a=n,o=r),[...e,...o,60,a,...L(i)]}i32_load8_s(e,t,n){let r=t||0,i=n===void 0?0:n;return[...e,44,i,...L(r)]}i32_load8_u(e,t,n){let r=t||0,i=n===void 0?0:n;return[...e,45,i,...L(r)]}i32_load16_s(e,t,n){let r=t||0,i=n===void 0?1:n;return[...e,46,i,...L(r)]}i32_load16_u(e,t,n){let r=t||0,i=n===void 0?1:n;return[...e,47,i,...L(r)]}i32_load(e,t,n){let r=t||0,i=n===void 0?2:n;return[...e,40,i,...L(r)]}i32_store(e,t,n,r){let i,a,o;return Array.isArray(t)?(i=0,a=2,o=t):Array.isArray(n)?(i=t,a=2,o=n):Array.isArray(r)&&(i=t,a=n,o=r),[...e,...o,54,a,...L(i)]}i32_store16(e,t,n,r){let i,a,o;return Array.isArray(t)?(i=0,a=1,o=t):Array.isArray(n)?(i=t,a=1,o=n):Array.isArray(r)&&(i=t,a=n,o=r),[...e,...o,59,a,...L(i)]}i32_store8(e,t,n,r){let i,a,o;return Array.isArray(t)?(i=0,a=0,o=t):Array.isArray(n)?(i=t,a=0,o=n):Array.isArray(r)&&(i=t,a=n,o=r),[...e,...o,58,a,...L(i)]}call(e,...t){let n=this.module.functionIdxByName[e];if(n===void 0)throw Error(`Function not defined: Function: ${e}`);return[...[].concat(...t),16,...L(n)]}call_indirect(e,...t){return[...[].concat(...t),...e,17,0,0]}if(e,t,n){return n?[...e,4,64,...t,5,...n,11]:[...e,4,64,...t,11]}block(e){return[2,64,...e,11]}loop(...e){return[3,64,...[].concat(...e),11]}br_if(e,t){return[...t,13,...L(e)]}br(e){return[12,...L(e)]}ret(e){return[...e,15]}drop(e){return[...e,26]}i64_const(e){return[66,...I(e)]}i32_const(e){return[65,...F(e)]}i64_eqz(e){return[...e,80]}i64_eq(e,t){return[...e,...t,81]}i64_ne(e,t){return[...e,...t,82]}i64_lt_s(e,t){return[...e,...t,83]}i64_lt_u(e,t){return[...e,...t,84]}i64_gt_s(e,t){return[...e,...t,85]}i64_gt_u(e,t){return[...e,...t,86]}i64_le_s(e,t){return[...e,...t,87]}i64_le_u(e,t){return[...e,...t,88]}i64_ge_s(e,t){return[...e,...t,89]}i64_ge_u(e,t){return[...e,...t,90]}i64_add(e,t){return[...e,...t,124]}i64_sub(e,t){return[...e,...t,125]}i64_mul(e,t){return[...e,...t,126]}i64_div_s(e,t){return[...e,...t,127]}i64_div_u(e,t){return[...e,...t,128]}i64_rem_s(e,t){return[...e,...t,129]}i64_rem_u(e,t){return[...e,...t,130]}i64_and(e,t){return[...e,...t,131]}i64_or(e,t){return[...e,...t,132]}i64_xor(e,t){return[...e,...t,133]}i64_shl(e,t){return[...e,...t,134]}i64_shr_s(e,t){return[...e,...t,135]}i64_shr_u(e,t){return[...e,...t,136]}i64_extend_i32_s(e){return[...e,172]}i64_extend_i32_u(e){return[...e,173]}i64_clz(e){return[...e,121]}i64_ctz(e){return[...e,122]}i32_eqz(e){return[...e,69]}i32_eq(e,t){return[...e,...t,70]}i32_ne(e,t){return[...e,...t,71]}i32_lt_s(e,t){return[...e,...t,72]}i32_lt_u(e,t){return[...e,...t,73]}i32_gt_s(e,t){return[...e,...t,74]}i32_gt_u(e,t){return[...e,...t,75]}i32_le_s(e,t){return[...e,...t,76]}i32_le_u(e,t){return[...e,...t,77]}i32_ge_s(e,t){return[...e,...t,78]}i32_ge_u(e,t){return[...e,...t,79]}i32_add(e,t){return[...e,...t,106]}i32_sub(e,t){return[...e,...t,107]}i32_mul(e,t){return[...e,...t,108]}i32_div_s(e,t){return[...e,...t,109]}i32_div_u(e,t){return[...e,...t,110]}i32_rem_s(e,t){return[...e,...t,111]}i32_rem_u(e,t){return[...e,...t,112]}i32_and(e,t){return[...e,...t,113]}i32_or(e,t){return[...e,...t,114]}i32_xor(e,t){return[...e,...t,115]}i32_shl(e,t){return[...e,...t,116]}i32_shr_s(e,t){return[...e,...t,117]}i32_shr_u(e,t){return[...e,...t,118]}i32_rotl(e,t){return[...e,...t,119]}i32_rotr(e,t){return[...e,...t,120]}i32_wrap_i64(e){return[...e,167]}i32_clz(e){return[...e,103]}i32_ctz(e){return[...e,104]}unreachable(){return[0]}current_memory(){return[63,0]}comment(){return[]}}})),ie,ae,oe=s((()=>{re(),te(),ie={i32:127,i64:126,f32:125,f64:124,anyfunc:112,func:96,emptyblock:64},ae=class{constructor(e,t,n,r,i){if(n==`import`)this.fnType=`import`,this.moduleName=r,this.fieldName=i;else if(n==`internal`)this.fnType=`internal`;else throw Error(`Invalid function fnType: `+n);this.module=e,this.fnName=t,this.params=[],this.locals=[],this.localIdxByName={},this.code=[],this.returnType=null,this.nextLocal=0}addParam(e,t){if(this.localIdxByName[e])throw Error(`param already exists. Function: ${this.fnName}, Param: ${e} `);let n=this.nextLocal++;this.localIdxByName[e]=n,this.params.push({type:t})}addLocal(e,t,n){let r=n||1;if(this.localIdxByName[e])throw Error(`local already exists. Function: ${this.fnName}, Param: ${e} `);let i=this.nextLocal++;this.localIdxByName[e]=i,this.locals.push({type:t,length:r})}setReturnType(e){if(this.returnType)throw Error(`returnType already defined. Function: ${this.fnName}`);this.returnType=e}getSignature(){let e=[...L(this.params.length),...this.params.map(e=>ie[e.type])],t=this.returnType?[1,ie[this.returnType]]:[0];return[96,...e,...t]}getBody(){let e=this.locals.map(e=>[...L(e.length),ie[e.type]]),t=[...L(this.locals.length),...[].concat(...e),...this.code,11];return[...L(t.length),...t]}addCode(...e){this.code.push(...[].concat(...e))}getCodeBuilder(){return new ne(this)}}})),se,ce=s((()=>{oe(),te(),se=class{constructor(){this.functions=[],this.functionIdxByName={},this.nImportFunctions=0,this.nInternalFunctions=0,this.memory={pagesSize:1,moduleName:`env`,fieldName:`memory`},this.free=8,this.datas=[],this.modules={},this.exports=[],this.functionsTable=[]}build(){return this._setSignatures(),new Uint8Array([...A(1836278016),...A(1),...this._buildType(),...this._buildImport(),...this._buildFunctionDeclarations(),...this._buildFunctionsTable(),...this._buildExports(),...this._buildElements(),...this._buildCode(),...this._buildData()])}addFunction(e){if(this.functionIdxByName[e]!==void 0)throw Error(`Function already defined: ${e}`);let t=this.functions.length;return this.functionIdxByName[e]=t,this.functions.push(new ae(this,e,`internal`)),this.nInternalFunctions++,this.functions[t]}addIimportFunction(e,t,n){if(this.functionIdxByName[e]!==void 0)throw Error(`Function already defined: ${e}`);if(this.functions.length>0&&this.functions[this.functions.length-1].type==`internal`)throw Error(`Import functions must be declared before internal: ${e}`);let r=n||e,i=this.functions.length;return this.functionIdxByName[e]=i,this.functions.push(new ae(this,e,`import`,t,r)),this.nImportFunctions++,this.functions[i]}setMemory(e,t,n){this.memory={pagesSize:e,moduleName:t||`env`,fieldName:n||`memory`}}exportFunction(e,t){let n=t||e;if(this.functionIdxByName[e]===void 0)throw Error(`Function not defined: ${e}`);let r=this.functionIdxByName[e];n!=e&&(this.functionIdxByName[n]=r),this.exports.push({exportName:n,idx:r})}addFunctionToTable(e){let t=this.functionIdxByName[e];this.functionsTable.push(t)}addData(e,t){this.datas.push({offset:e,bytes:t})}alloc(e,t){let n,r;(Array.isArray(e)||ArrayBuffer.isView(e))&&t===void 0?(n=e.length,r=e):(n=e,r=t),n=(n-1>>3)+1<<3;let i=this.free;return this.free+=n,r&&this.addData(i,r),i}allocString(e){let t=new globalThis.TextEncoder().encode(e);return this.alloc([...t,0])}_setSignatures(){this.signatures=[];let e={};if(this.functionsTable.length>0){let t=this.functions[this.functionsTable[0]].getSignature(),n=`s_`+ee(t);e[n]=0,this.signatures.push(t)}for(let t=0;t{te(),le=class{constructor(e){this.func=e,this.functionName=e.functionName,this.module=e.module}setLocal(e,t){if(this.func.localIdxByName[e]===void 0)throw Error(`Local Variable not defined: Function: ${this.functionName} local: ${e} `);return[t,`set_local $${e}`]}teeLocal(e,t){if(this.func.localIdxByName[e]===void 0)throw Error(`Local Variable not defined: Function: ${this.functionName} local: ${e} `);return[t,`tee_local $${e}`]}getLocal(e){if(this.func.localIdxByName[e]===void 0)throw Error(`Local Variable not defined: Function: ${this.functionName} local: ${e} `);return`get_local $${e}`}genLoad(e,t,n,r,i){let a=e,o=r||0;o>0&&(a+=` offset=${o}`);let s=i===void 0?t:i;return s!=t&&(a+=` align=${1<0&&(l+=` offset=${o}`),s!=t&&(l+=` align=${1<{ue(),te(),de=class{constructor(e,t,n,r,i){if(n==`import`)this.fnType=`import`,this.moduleName=r,this.fieldName=i;else if(n==`internal`)this.fnType=`internal`,this.comment=r;else throw Error(`Invalid function fnType: `+n);this.module=e,this.fnName=t,this.params=[],this.locals=[],this.localIdxByName={},this.code=[],this.returnType=null,this.nextLocal=0}addParam(e,t){if(this.localIdxByName[e])throw Error(`param already exists. Function: ${this.fnName}, Param: ${e} `);let n=this.nextLocal++;this.localIdxByName[e]=n,this.params.push({type:t,name:e})}addLocal(e,t,n){if(n!==void 0&&n!=1)throw Error(`Locals greater than 1 not implemented`);if(this.localIdxByName[e])throw Error(`local already exists. Function: ${this.fnName}, Param: ${e} `);let r=this.nextLocal++;this.localIdxByName[e]=r,this.locals.push({type:t,name:e})}setReturnType(e){if(this.returnType)throw Error(`returnType already defined. Function: ${this.fnName}`);this.returnType=e}getSignature(){let e=``;for(let t=0;t{fe(),te(),pe=class{constructor(){this.functions=[],this.functionIdxByName={},this.nImportFunctions=0,this.nInternalFunctions=0,this.memory={pagesSize:1,moduleName:`env`,fieldName:`memory`},this.free=8,this.datas=[],this.modules={},this.exports=[],this.functionsTable=[]}build(){let e=[];return this._setSignatures(),e.push(this._buildType()),e.push(this._buildImport()),this.functionsTable.length>0&&e.push(this._buildFunctionsTable()),this.exports.length>0&&e.push(this._buildExports()),this.functionsTable.length>0&&e.push(this._buildElements()),this.nInternalFunctions>0&&e.push(this._buildFunctions()),e.push(this._buildData()),[`(module`,R(e),`)`]}addFunction(e,t){if(this.functionIdxByName[e]!==void 0)throw Error(`Function already defined: ${e}`);let n=this.functions.length;return this.functionIdxByName[e]=n,this.functions.push(new de(this,e,`internal`,t)),this.nInternalFunctions++,this.functions[n]}addIimportFunction(e,t,n){if(this.functionIdxByName[e]!==void 0)throw Error(`Function already defined: ${e}`);if(this.functions.length>0&&this.functions[this.functions.length-1].type==`internal`)throw Error(`Import functions must be declared before internal: ${e}`);let r=n||e,i=this.functions.length;return this.functionIdxByName[e]=i,this.functions.push(new de(this,e,`import`,t,r)),this.nImportFunctions++,this.functions[i]}setMemory(e,t,n){this.memory={pagesSize:e,moduleName:t||`env`,fieldName:n||`memory`}}exportFunction(e,t){let n=t||e;if(this.functionIdxByName[e]===void 0)throw Error(`Function not defined: ${e}`);let r=this.functionIdxByName[e];n!=e&&(this.functionIdxByName[n]=r),this.exports.push({exportName:n,idx:r})}addFunctionToTable(e){let t=this.functionIdxByName[e];this.functionsTable.push(t)}addData(e,t){this.datas.push({offset:e,bytes:t})}alloc(e,t){let n,r;(Array.isArray(e)||ArrayBuffer.isView(e))&&t===void 0?(n=e.length,r=e):(n=e,r=t),n=(n-1>>3)+1<<3;let i=this.free;return this.free+=n,r&&this.addData(i,r),i}allocString(e){let t=new TextEncoder().encode(e);return this.alloc([...t,0])}_setSignatures(){this.signatures=[];let e={};if(this.functionsTable.length>0){let t=this.functions[this.functionsTable[0]].getSignature(),n=this.functions[this.functionsTable[0]].getSignatureName();e[n]=0,this.signatures.push(t)}for(let t=0;t126||e[n]==34||e[n]==92){let r=e[n].toString(16);for(;r.length<2;)r=`0`+r;t+=`\\`+r}else t+=String.fromCharCode(e[n]);return t+=`"`,t}}}}));async function he(e,t,n){let r=new ge;r.defBytes=t,r.bitsPerBytes=n||32,r.memory=new WebAssembly.Memory({initial:2e4}),r.i32=new Uint32Array(r.memory.buffer),r.i8=new Uint8Array(r.memory.buffer);let i=new se;i.addIimportFunction(`debug_log32`,`debug`,`log32`).addParam(`x`,`i32`);let a=i.addIimportFunction(`debug_log64`,`debug`,`log64`);a.addParam(`x`,`i32`),a.addParam(`y`,`i32`),c(i),l(i),e(i,r);let o=i.build(),s=await WebAssembly.compile(o);return r.log=console.log,r.instance=await WebAssembly.instantiate(s,{env:{memory:r.memory},debug:{log32:function(e){e<0&&(e=4294967296+e);let t=e.toString(16);for(;t.length<8;)t=`0`+t;r.log(t+`: `+e.toString())},log64:function(e,t){e<0&&(e=4294967296+e),t<0&&(t=4294967296+t);let n=BigInt(e)+(BigInt(t)<<32n),i=n.toString(16);for(;i.length<16;)i=`0`+i;r.log(i+`: `+n.toString())}}}),Object.assign(r,r.instance.exports),Object.assign(r,i.modules),r;function c(e){let t=e.addFunction(`log32`);t.addParam(`x`,`i32`);let n=t.getCodeBuilder();t.addCode(n.call(`debug_log32`,n.getLocal(`x`)))}function l(e){let t=e.addFunction(`log64`);t.addParam(`x`,`i64`);let n=t.getCodeBuilder();t.addCode(n.call(`debug_log64`,n.i32_wrap_i64(n.getLocal(`x`)),n.i32_wrap_i64(n.i64_shr_u(n.getLocal(`x`),n.i64_const(32)))))}}var ge,_e=s((()=>{ce(),ge=class{constructor(){}alloc(e){e===void 0&&(e=this.defBytes),e=(e-1>>3)+1<<3;let t=this.i32[0];return this.i32[0]+=e,t}set(e,t,n){Array.isArray(t)||(t=[t]),n===void 0&&(n=this.defBytes);let r=Math.floor((n-1)/4)+1,i=e,a=1n<>2]=Number(t),n=e,i+=4}if(n!==0n)throw Error(`Expected v to be 0`)}return e}get(e,t,n){n===void 0&&(t===void 0?(t=1,n=this.defBytes):(t=n,n=this.defBytes));let r=Math.floor((n-1)/4)+1,i=1n<=0;n--){t*=i;let r=this.i32[(e>>2)+n];this.bitsPerBytes<32&&r&2147483648&&(r-=4294967296),t+=BigInt(r)}a.push(t),e+=r*4}return a.length==1?a[0]:a}}})),ve=l({ModuleBuilder:()=>se,ModuleBuilderWat:()=>pe,buildProtoboard:()=>he}),ye=s((()=>{ce(),me(),_e()}));function z(e,t){let n=Array(t),r=BigInt(e);for(let e=0;e>=8n;return n}var be=s((()=>{}));function xe(e,t,n){let r=n||`int`;if(e.modules[r])return r;e.modules[r]={};let i=t*2,a=t*8;function o(){let n=e.addFunction(r+`_copy`);n.addParam(`px`,`i32`),n.addParam(`pr`,`i32`);let i=n.getCodeBuilder();for(let e=0;e>1&&r>1,e>>1)))),t.addCode(n.setLocal(`c1`,n.i64_add(n.getLocal(`c1`),n.i64_shr_u(n.getLocal(`c0`),n.i64_const(32)))))),e>0&&(t.addCode(n.setLocal(`c0`,n.i64_add(n.i64_and(n.getLocal(`c0`),n.i64_const(4294967295)),n.i64_and(n.getLocal(s),n.i64_const(4294967295))))),t.addCode(n.setLocal(`c1`,n.i64_add(n.i64_add(n.getLocal(`c1`),n.i64_shr_u(n.getLocal(`c0`),n.i64_const(32))),n.getLocal(c))))),t.addCode(n.i64_store32(n.getLocal(`r`),e*4,n.getLocal(`c0`))),t.addCode(n.setLocal(s,n.getLocal(`c1`)),n.setLocal(c,n.i64_shr_u(n.getLocal(s),n.i64_const(32))))}t.addCode(n.i64_store32(n.getLocal(`r`),i*4*2-4,n.getLocal(s)))}function g(){let t=e.addFunction(r+`_squareOld`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let n=t.getCodeBuilder();t.addCode(n.call(r+`_mul`,n.getLocal(`x`),n.getLocal(`x`),n.getLocal(`r`)))}function _(){let t=e.addFunction(r+`__mul1`);t.addParam(`px`,`i32`),t.addParam(`y`,`i64`),t.addParam(`pr`,`i32`),t.addLocal(`c`,`i64`);let n=t.getCodeBuilder();t.addCode(n.setLocal(`c`,n.i64_mul(n.i64_load32_u(n.getLocal(`px`),0,0),n.getLocal(`y`)))),t.addCode(n.i64_store32(n.getLocal(`pr`),0,0,n.getLocal(`c`)));for(let e=1;e{}));function Ce(e,t,n,r,i,a,o){let s=e.addFunction(t);s.addParam(`base`,`i32`),s.addParam(`scalar`,`i32`),s.addParam(`scalarLength`,`i32`),s.addParam(`r`,`i32`),s.addLocal(`i`,`i32`),s.addLocal(`b`,`i32`);let c=s.getCodeBuilder(),l=c.i32_const(e.alloc(n));s.addCode(c.if(c.i32_eqz(c.getLocal(`scalarLength`)),[...c.call(o,c.getLocal(`r`)),...c.ret([])])),s.addCode(c.call(a,c.getLocal(`base`),l)),s.addCode(c.call(o,c.getLocal(`r`))),s.addCode(c.setLocal(`i`,c.getLocal(`scalarLength`))),s.addCode(c.block(c.loop(c.setLocal(`i`,c.i32_sub(c.getLocal(`i`),c.i32_const(1))),c.setLocal(`b`,c.i32_load8_u(c.i32_add(c.getLocal(`scalar`),c.getLocal(`i`)))),...u(),c.br_if(1,c.i32_eqz(c.getLocal(`i`))),c.br(0))));function u(){let e=[];for(let t=0;t<8;t++)e.push(...c.call(i,c.getLocal(`r`),c.getLocal(`r`)),...c.if(c.i32_ge_u(c.getLocal(`b`),c.i32_const(128>>t)),[...c.setLocal(`b`,c.i32_sub(c.getLocal(`b`),c.i32_const(128>>t))),...c.call(r,c.getLocal(`r`),l,c.getLocal(`r`))]));return e}}var we=s((()=>{}));function Te(e,t){let n=e.modules[t].n64*8,r=e.addFunction(t+`_batchInverse`);r.addParam(`pIn`,`i32`),r.addParam(`inStep`,`i32`),r.addParam(`n`,`i32`),r.addParam(`pOut`,`i32`),r.addParam(`outStep`,`i32`),r.addLocal(`itAux`,`i32`),r.addLocal(`itIn`,`i32`),r.addLocal(`itOut`,`i32`),r.addLocal(`i`,`i32`);let i=r.getCodeBuilder(),a=i.i32_const(e.alloc(n));r.addCode(i.setLocal(`itAux`,i.i32_load(i.i32_const(0))),i.i32_store(i.i32_const(0),i.i32_add(i.getLocal(`itAux`),i.i32_mul(i.i32_add(i.getLocal(`n`),i.i32_const(1)),i.i32_const(n))))),r.addCode(i.call(t+`_one`,i.getLocal(`itAux`)),i.setLocal(`itIn`,i.getLocal(`pIn`)),i.setLocal(`itAux`,i.i32_add(i.getLocal(`itAux`),i.i32_const(n))),i.setLocal(`i`,i.i32_const(0)),i.block(i.loop(i.br_if(1,i.i32_eq(i.getLocal(`i`),i.getLocal(`n`))),i.if(i.call(t+`_isZero`,i.getLocal(`itIn`)),i.call(t+`_copy`,i.i32_sub(i.getLocal(`itAux`),i.i32_const(n)),i.getLocal(`itAux`)),i.call(t+`_mul`,i.getLocal(`itIn`),i.i32_sub(i.getLocal(`itAux`),i.i32_const(n)),i.getLocal(`itAux`))),i.setLocal(`itIn`,i.i32_add(i.getLocal(`itIn`),i.getLocal(`inStep`))),i.setLocal(`itAux`,i.i32_add(i.getLocal(`itAux`),i.i32_const(n))),i.setLocal(`i`,i.i32_add(i.getLocal(`i`),i.i32_const(1))),i.br(0))),i.setLocal(`itIn`,i.i32_sub(i.getLocal(`itIn`),i.getLocal(`inStep`))),i.setLocal(`itAux`,i.i32_sub(i.getLocal(`itAux`),i.i32_const(n))),i.setLocal(`itOut`,i.i32_add(i.getLocal(`pOut`),i.i32_mul(i.i32_sub(i.getLocal(`n`),i.i32_const(1)),i.getLocal(`outStep`)))),i.call(t+`_inverse`,i.getLocal(`itAux`),i.getLocal(`itAux`)),i.block(i.loop(i.br_if(1,i.i32_eqz(i.getLocal(`i`))),i.if(i.call(t+`_isZero`,i.getLocal(`itIn`)),[...i.call(t+`_copy`,i.getLocal(`itAux`),i.i32_sub(i.getLocal(`itAux`),i.i32_const(n))),...i.call(t+`_zero`,i.getLocal(`itOut`))],[...i.call(t+`_copy`,i.i32_sub(i.getLocal(`itAux`),i.i32_const(n)),a),...i.call(t+`_mul`,i.getLocal(`itAux`),i.getLocal(`itIn`),i.i32_sub(i.getLocal(`itAux`),i.i32_const(n))),...i.call(t+`_mul`,i.getLocal(`itAux`),a,i.getLocal(`itOut`))]),i.setLocal(`itIn`,i.i32_sub(i.getLocal(`itIn`),i.getLocal(`inStep`))),i.setLocal(`itOut`,i.i32_sub(i.getLocal(`itOut`),i.getLocal(`outStep`))),i.setLocal(`itAux`,i.i32_sub(i.getLocal(`itAux`),i.i32_const(n))),i.setLocal(`i`,i.i32_sub(i.getLocal(`i`),i.i32_const(1))),i.br(0)))),r.addCode(i.i32_store(i.i32_const(0),i.getLocal(`itAux`)))}var Ee,De=s((()=>{Ee=Te}));function Oe(e,t,n,r,i,a){a===void 0&&(a=r{ke=Oe}));function je(e,t,n,r,i,a){a===void 0&&(a=r{Me=je}));function Pe(e,t){return e===t?0:e>t?1:-1}function Fe(e){return e*e}function Ie(e){return e%2n!=0n}function Le(e){return e%2n==0n}function Re(e){return e<0n}function ze(e){return e>0n}function Be(e){return Re(e)?e.toString(2).length-1:e.toString(2).length}function Ve(e){return e<0n?-e:e}function He(e){return Ve(e)===1n}function Ue(e,t){for(var n=0n,r=1n,i=t,a=Ve(e),o,s,c;a!==0n;)o=i/a,s=n,c=i,n=r,i=a,r=s-o*r,a=c-o*a;if(!He(i))throw Error(e.toString()+` and `+t.toString()+` are not co-prime`);return Pe(n,0n)===-1&&(n+=t),Re(e)?-n:n}function We(e,t,n){if(n===0n)throw Error(`Cannot take modPow with modulus 0`);var r=1n,i=e%n;for(Re(t)&&(t*=-1n,i=Ue(i,n));ze(t);){if(i===0n)return 0n;Ie(t)&&(r=r*i%n),t/=2n,i=Fe(i)%n}return r}function Ge(e,t){return e=e>=0n?e:-e,t=t>=0n?t:-t,e===t?0:e>t?1:-1}function Ke(e,t){return t===0n?!1:He(t)?!0:Ge(t,2n)===0?Le(e):e%t===0n}function qe(e){var t=Ve(e);if(He(t))return!1;if(t===2n||t===3n||t===5n)return!0;if(Le(t)||Ke(t,3n)||Ke(t,5n))return!1;if(t<49n)return!0}function Je(e){return e-1n}function Ye(e){switch(Ve(e)){case 21888242871839275222246405745257275088696311157297823662689037894645226208583n:case 21888242871839275222246405745257275088548364400416034343698204186575808495617n:case 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787n:case 52435875175126190479447740508185965837690552500527637822603658699938581184513n:case 41898490967918953402344214791240637128170709919953949071783502921025352812571106773058893763790338921418070971888458477323173057491593855069696241854796396165721416325350064441470418137846398469611935719059908164220784476160001n:return!0}return!1}function Xe(e,t){for(var n=Je(e),r=n,i=0,a,o,s;Le(r);)r/=2n,i++;next:for(o=0;o{}));function $e(e,t,n,r){let i=BigInt(t),a=Math.floor((Be(i-1n)-1)/64)+1,o=a*2,s=a*8,c=n||`f1m`;if(e.modules[c])return c;let l=xe(e,a,r),u=e.alloc(s,z(i,s)),d=e.alloc(z(Fe(1n<>1n,g=e.alloc(s,z(h,s)),_=h+1n,v=e.alloc(s,z(_,s));e.modules[c]={pq:u,pR2:d,n64:a,q:i,pOne:f,pZero:p,pePlusOne:v};function y(){let t=e.addFunction(c+`_one`);t.addParam(`pr`,`i32`);let n=t.getCodeBuilder();t.addCode(n.call(l+`_copy`,n.i32_const(f),n.getLocal(`pr`)))}function b(){let t=e.addFunction(c+`_add`);t.addParam(`x`,`i32`),t.addParam(`y`,`i32`),t.addParam(`r`,`i32`);let n=t.getCodeBuilder();t.addCode(n.if(n.call(l+`_add`,n.getLocal(`x`),n.getLocal(`y`),n.getLocal(`r`)),n.drop(n.call(l+`_sub`,n.getLocal(`r`),n.i32_const(u),n.getLocal(`r`))),n.if(n.call(l+`_gte`,n.getLocal(`r`),n.i32_const(u)),n.drop(n.call(l+`_sub`,n.getLocal(`r`),n.i32_const(u),n.getLocal(`r`))))))}function x(){let t=e.addFunction(c+`_sub`);t.addParam(`x`,`i32`),t.addParam(`y`,`i32`),t.addParam(`r`,`i32`);let n=t.getCodeBuilder();t.addCode(n.if(n.call(l+`_sub`,n.getLocal(`x`),n.getLocal(`y`),n.getLocal(`r`)),n.drop(n.call(l+`_add`,n.getLocal(`r`),n.i32_const(u),n.getLocal(`r`)))))}function S(){let t=e.addFunction(c+`_neg`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let n=t.getCodeBuilder();t.addCode(n.call(c+`_sub`,n.i32_const(p),n.getLocal(`x`),n.getLocal(`r`)))}function C(){let t=e.addFunction(c+`_isNegative`);t.addParam(`x`,`i32`),t.setReturnType(`i32`);let n=t.getCodeBuilder(),r=n.i32_const(e.alloc(s));t.addCode(n.call(c+`_fromMontgomery`,n.getLocal(`x`),r),n.call(l+`_gte`,r,n.i32_const(v)))}function w(){let t=e.addFunction(c+`_sign`);t.addParam(`x`,`i32`),t.setReturnType(`i32`);let n=t.getCodeBuilder(),r=n.i32_const(e.alloc(s));t.addCode(n.if(n.call(l+`_isZero`,n.getLocal(`x`)),n.ret(n.i32_const(0))),n.call(c+`_fromMontgomery`,n.getLocal(`x`),r),n.if(n.call(l+`_gte`,r,n.i32_const(v)),n.ret(n.i32_const(-1))),n.ret(n.i32_const(1)))}function T(){let t=e.alloc(o*o*8),n=e.addFunction(c+`_mReduct`);n.addParam(`t`,`i32`),n.addParam(`r`,`i32`),n.addLocal(`np32`,`i64`),n.addLocal(`c`,`i64`),n.addLocal(`m`,`i64`);let r=n.getCodeBuilder(),a=Number(4294967296n-Ue(i,4294967296n));n.addCode(r.setLocal(`np32`,r.i64_const(a)));for(let e=0;e=o&&t.addCode(n.i64_store32(n.getLocal(`r`),(e-o)*4,n.getLocal(m))),[m,h]=[h,m],t.addCode(n.setLocal(h,n.i64_shr_u(n.getLocal(m),n.i64_const(32))))}t.addCode(n.i64_store32(n.getLocal(`r`),o*4-4,n.getLocal(m))),t.addCode(n.if(n.i32_wrap_i64(n.getLocal(h)),n.drop(n.call(l+`_sub`,n.getLocal(`r`),n.i32_const(u),n.getLocal(`r`))),n.if(n.call(l+`_gte`,n.getLocal(`r`),n.i32_const(u)),n.drop(n.call(l+`_sub`,n.getLocal(`r`),n.i32_const(u),n.getLocal(`r`))))))}function D(){let t=e.addFunction(c+`_square`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`),t.addLocal(`c0`,`i64`),t.addLocal(`c1`,`i64`),t.addLocal(`c0_old`,`i64`),t.addLocal(`c1_old`,`i64`),t.addLocal(`np32`,`i64`);for(let e=0;e>1&&r>1,e>>1)))),t.addCode(n.setLocal(`c1`,n.i64_add(n.getLocal(`c1`),n.i64_shr_u(n.getLocal(`c0`),n.i64_const(32)))))),e>0&&(t.addCode(n.setLocal(`c0`,n.i64_add(n.i64_and(n.getLocal(`c0`),n.i64_const(4294967295)),n.i64_and(n.getLocal(p),n.i64_const(4294967295))))),t.addCode(n.setLocal(`c1`,n.i64_add(n.i64_add(n.getLocal(`c1`),n.i64_shr_u(n.getLocal(`c0`),n.i64_const(32))),n.getLocal(m)))));for(let r=Math.max(1,e-o+1);r<=e&&r=o&&t.addCode(n.i64_store32(n.getLocal(`r`),(e-o)*4,n.getLocal(`c0`))),t.addCode(n.setLocal(p,n.getLocal(`c1`)),n.setLocal(m,n.i64_shr_u(n.getLocal(p),n.i64_const(32))))}t.addCode(n.i64_store32(n.getLocal(`r`),o*4-4,n.getLocal(p))),t.addCode(n.if(n.i32_wrap_i64(n.getLocal(m)),n.drop(n.call(l+`_sub`,n.getLocal(`r`),n.i32_const(u),n.getLocal(`r`))),n.if(n.call(l+`_gte`,n.getLocal(`r`),n.i32_const(u)),n.drop(n.call(l+`_sub`,n.getLocal(`r`),n.i32_const(u),n.getLocal(`r`))))))}function O(){let t=e.addFunction(c+`_squareOld`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let n=t.getCodeBuilder();t.addCode(n.call(c+`_mul`,n.getLocal(`x`),n.getLocal(`x`),n.getLocal(`r`)))}function k(){let t=e.addFunction(c+`_toMontgomery`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let n=t.getCodeBuilder();t.addCode(n.call(c+`_mul`,n.getLocal(`x`),n.i32_const(d),n.getLocal(`r`)))}function A(){let t=e.alloc(s*2),n=e.addFunction(c+`_fromMontgomery`);n.addParam(`x`,`i32`),n.addParam(`r`,`i32`);let r=n.getCodeBuilder();n.addCode(r.call(l+`_copy`,r.getLocal(`x`),r.i32_const(t))),n.addCode(r.call(l+`_zero`,r.i32_const(t+s))),n.addCode(r.call(c+`_mReduct`,r.i32_const(t),r.getLocal(`r`)))}function j(){let t=e.addFunction(c+`_inverse`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let n=t.getCodeBuilder();t.addCode(n.call(c+`_fromMontgomery`,n.getLocal(`x`),n.getLocal(`r`))),t.addCode(n.call(l+`_inverseMod`,n.getLocal(`r`),n.i32_const(u),n.getLocal(`r`))),t.addCode(n.call(c+`_toMontgomery`,n.getLocal(`r`),n.getLocal(`r`)))}let M=2n;if(Ze(i))for(;We(M,h,i)!==m;)M+=1n;let N=0,P=m;for(;!Ie(P)&&P!==0n;)N++,P>>=1n;let F=e.alloc(s,z(P,s)),I=We(M,P,i),L=e.alloc(z((I<>1n,R=e.alloc(s,z(ee,s));function te(){let t=e.addFunction(c+`_sqrt`);t.addParam(`n`,`i32`),t.addParam(`r`,`i32`),t.addLocal(`m`,`i32`),t.addLocal(`i`,`i32`),t.addLocal(`j`,`i32`);let n=t.getCodeBuilder(),r=n.i32_const(f),i=n.i32_const(e.alloc(s)),a=n.i32_const(e.alloc(s)),o=n.i32_const(e.alloc(s)),l=n.i32_const(e.alloc(s)),u=n.i32_const(e.alloc(s));t.addCode(n.if(n.call(c+`_isZero`,n.getLocal(`n`)),n.ret(n.call(c+`_zero`,n.getLocal(`r`)))),n.setLocal(`m`,n.i32_const(N)),n.call(c+`_copy`,n.i32_const(L),i),n.call(c+`_exp`,n.getLocal(`n`),n.i32_const(F),n.i32_const(s),a),n.call(c+`_exp`,n.getLocal(`n`),n.i32_const(R),n.i32_const(s),o),n.block(n.loop(n.br_if(1,n.call(c+`_eq`,a,r)),n.call(c+`_square`,a,l),n.setLocal(`i`,n.i32_const(1)),n.block(n.loop(n.br_if(1,n.call(c+`_eq`,l,r)),n.call(c+`_square`,l,l),n.setLocal(`i`,n.i32_add(n.getLocal(`i`),n.i32_const(1))),n.br(0))),n.call(c+`_copy`,i,u),n.setLocal(`j`,n.i32_sub(n.i32_sub(n.getLocal(`m`),n.getLocal(`i`)),n.i32_const(1))),n.block(n.loop(n.br_if(1,n.i32_eqz(n.getLocal(`j`))),n.call(c+`_square`,u,u),n.setLocal(`j`,n.i32_sub(n.getLocal(`j`),n.i32_const(1))),n.br(0))),n.setLocal(`m`,n.getLocal(`i`)),n.call(c+`_square`,u,i),n.call(c+`_mul`,a,i,a),n.call(c+`_mul`,o,u,o),n.br(0))),n.if(n.call(c+`_isNegative`,o),n.call(c+`_neg`,o,n.getLocal(`r`)),n.call(c+`_copy`,o,n.getLocal(`r`))))}function ne(){let t=e.addFunction(c+`_isSquare`);t.addParam(`n`,`i32`),t.setReturnType(`i32`);let n=t.getCodeBuilder(),r=n.i32_const(f),i=n.i32_const(e.alloc(s));t.addCode(n.if(n.call(c+`_isZero`,n.getLocal(`n`)),n.ret(n.i32_const(1))),n.call(c+`_exp`,n.getLocal(`n`),n.i32_const(g),n.i32_const(s),i),n.call(c+`_eq`,i,r))}function re(){let t=e.addFunction(c+`_load`);t.addParam(`scalar`,`i32`),t.addParam(`scalarLen`,`i32`),t.addParam(`r`,`i32`),t.addLocal(`p`,`i32`),t.addLocal(`l`,`i32`),t.addLocal(`i`,`i32`),t.addLocal(`j`,`i32`);let n=t.getCodeBuilder(),r=n.i32_const(e.alloc(s)),i=e.alloc(s),a=n.i32_const(i);t.addCode(n.call(l+`_zero`,n.getLocal(`r`)),n.setLocal(`i`,n.i32_const(s)),n.setLocal(`p`,n.getLocal(`scalar`)),n.block(n.loop(n.br_if(1,n.i32_gt_u(n.getLocal(`i`),n.getLocal(`scalarLen`))),n.if(n.i32_eq(n.getLocal(`i`),n.i32_const(s)),n.call(c+`_one`,r),n.call(c+`_mul`,r,n.i32_const(d),r)),n.call(c+`_mul`,n.getLocal(`p`),r,a),n.call(c+`_add`,n.getLocal(`r`),a,n.getLocal(`r`)),n.setLocal(`p`,n.i32_add(n.getLocal(`p`),n.i32_const(s))),n.setLocal(`i`,n.i32_add(n.getLocal(`i`),n.i32_const(s))),n.br(0))),n.setLocal(`l`,n.i32_rem_u(n.getLocal(`scalarLen`),n.i32_const(s))),n.if(n.i32_eqz(n.getLocal(`l`)),n.ret([])),n.call(l+`_zero`,a),n.setLocal(`j`,n.i32_const(0)),n.block(n.loop(n.br_if(1,n.i32_eq(n.getLocal(`j`),n.getLocal(`l`))),n.i32_store8(n.getLocal(`j`),i,n.i32_load8_u(n.getLocal(`p`))),n.setLocal(`p`,n.i32_add(n.getLocal(`p`),n.i32_const(1))),n.setLocal(`j`,n.i32_add(n.getLocal(`j`),n.i32_const(1))),n.br(0))),n.if(n.i32_eq(n.getLocal(`i`),n.i32_const(s)),n.call(c+`_one`,r),n.call(c+`_mul`,r,n.i32_const(d),r)),n.call(c+`_mul`,a,r,a),n.call(c+`_add`,n.getLocal(`r`),a,n.getLocal(`r`)))}function ie(){let t=e.addFunction(c+`_timesScalar`);t.addParam(`x`,`i32`),t.addParam(`scalar`,`i32`),t.addParam(`scalarLen`,`i32`),t.addParam(`r`,`i32`);let n=t.getCodeBuilder(),r=n.i32_const(e.alloc(s));t.addCode(n.call(c+`_load`,n.getLocal(`scalar`),n.getLocal(`scalarLen`),r),n.call(c+`_toMontgomery`,r,r),n.call(c+`_mul`,n.getLocal(`x`),r,n.getLocal(`r`)))}function ae(){let t=e.addFunction(c+`_isOne`);t.addParam(`x`,`i32`),t.setReturnType(`i32`);let n=t.getCodeBuilder();t.addCode(n.ret(n.call(l+`_eq`,n.getLocal(`x`),n.i32_const(f))))}return e.exportFunction(l+`_copy`,c+`_copy`),e.exportFunction(l+`_zero`,c+`_zero`),e.exportFunction(l+`_isZero`,c+`_isZero`),e.exportFunction(l+`_eq`,c+`_eq`),ae(),b(),x(),S(),T(),E(),D(),O(),k(),A(),C(),w(),j(),y(),re(),ie(),Ee(e,c),ke(e,c+`_batchToMontgomery`,c+`_toMontgomery`,s,s),ke(e,c+`_batchFromMontgomery`,c+`_fromMontgomery`,s,s),ke(e,c+`_batchNeg`,c+`_neg`,s,s),Me(e,c+`_batchAdd`,c+`_add`,s,s),Me(e,c+`_batchSub`,c+`_sub`,s,s),Me(e,c+`_batchMul`,c+`_mul`,s,s),e.exportFunction(c+`_add`),e.exportFunction(c+`_sub`),e.exportFunction(c+`_neg`),e.exportFunction(c+`_isNegative`),e.exportFunction(c+`_isOne`),e.exportFunction(c+`_sign`),e.exportFunction(c+`_mReduct`),e.exportFunction(c+`_mul`),e.exportFunction(c+`_square`),e.exportFunction(c+`_squareOld`),e.exportFunction(c+`_fromMontgomery`),e.exportFunction(c+`_toMontgomery`),e.exportFunction(c+`_inverse`),e.exportFunction(c+`_one`),e.exportFunction(c+`_load`),e.exportFunction(c+`_timesScalar`),Ce(e,c+`_exp`,s,c+`_mul`,c+`_square`,l+`_copy`,c+`_one`),e.exportFunction(c+`_exp`),e.exportFunction(c+`_batchInverse`),Ze(i)&&(te(),ne(),e.exportFunction(c+`_sqrt`),e.exportFunction(c+`_isSquare`)),e.exportFunction(c+`_batchToMontgomery`),e.exportFunction(c+`_batchFromMontgomery`),c}var et=s((()=>{Se(),be(),we(),De(),Ae(),Ne(),Qe()}));function tt(e,t,n,r,i){let a=BigInt(t),o=Math.floor((Be(a-1n)-1)/64)+1,s=o*8,c=n||`f1`;if(e.modules[c])return c;e.modules[c]={n64:o};let l=i||`int`,u=$e(e,a,r,l),d=e.modules[u].pR2,f=e.modules[u].pq,p=e.modules[u].pePlusOne;function m(){let t=e.alloc(s),n=e.addFunction(c+`_mul`);n.addParam(`x`,`i32`),n.addParam(`y`,`i32`),n.addParam(`r`,`i32`);let r=n.getCodeBuilder();n.addCode(r.call(u+`_mul`,r.getLocal(`x`),r.getLocal(`y`),r.i32_const(t))),n.addCode(r.call(u+`_mul`,r.i32_const(t),r.i32_const(d),r.getLocal(`r`)))}function h(){let t=e.addFunction(c+`_square`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let n=t.getCodeBuilder();t.addCode(n.call(c+`_mul`,n.getLocal(`x`),n.getLocal(`x`),n.getLocal(`r`)))}function g(){let t=e.addFunction(c+`_inverse`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let n=t.getCodeBuilder();t.addCode(n.call(l+`_inverseMod`,n.getLocal(`x`),n.i32_const(f),n.getLocal(`r`)))}function _(){let t=e.addFunction(c+`_isNegative`);t.addParam(`x`,`i32`),t.setReturnType(`i32`);let n=t.getCodeBuilder();t.addCode(n.call(l+`_gte`,n.getLocal(`x`),n.i32_const(p)))}return m(),h(),g(),_(),e.exportFunction(u+`_add`,c+`_add`),e.exportFunction(u+`_sub`,c+`_sub`),e.exportFunction(u+`_neg`,c+`_neg`),e.exportFunction(c+`_mul`),e.exportFunction(c+`_square`),e.exportFunction(c+`_inverse`),e.exportFunction(c+`_isNegative`),e.exportFunction(u+`_copy`,c+`_copy`),e.exportFunction(u+`_zero`,c+`_zero`),e.exportFunction(u+`_one`,c+`_one`),e.exportFunction(u+`_isZero`,c+`_isZero`),e.exportFunction(u+`_eq`,c+`_eq`),c}var nt=s((()=>{et(),Qe()}));function rt(e,t,n,r){if(e.modules[n])return n;let i=e.modules[r].n64*8,a=e.modules[r].q;e.modules[n]={n64:e.modules[r].n64*2};function o(){let t=e.addFunction(n+`_add`);t.addParam(`x`,`i32`),t.addParam(`y`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.getLocal(`y`),l=a.i32_add(a.getLocal(`y`),a.i32_const(i)),u=a.getLocal(`r`),d=a.i32_add(a.getLocal(`r`),a.i32_const(i));t.addCode(a.call(r+`_add`,o,c,u),a.call(r+`_add`,s,l,d))}function s(){let t=e.addFunction(n+`_timesScalar`);t.addParam(`x`,`i32`),t.addParam(`scalar`,`i32`),t.addParam(`scalarLen`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.getLocal(`r`),l=a.i32_add(a.getLocal(`r`),a.i32_const(i));t.addCode(a.call(r+`_timesScalar`,o,a.getLocal(`scalar`),a.getLocal(`scalarLen`),c),a.call(r+`_timesScalar`,s,a.getLocal(`scalar`),a.getLocal(`scalarLen`),l))}function c(){let t=e.addFunction(n+`_sub`);t.addParam(`x`,`i32`),t.addParam(`y`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.getLocal(`y`),l=a.i32_add(a.getLocal(`y`),a.i32_const(i)),u=a.getLocal(`r`),d=a.i32_add(a.getLocal(`r`),a.i32_const(i));t.addCode(a.call(r+`_sub`,o,c,u),a.call(r+`_sub`,s,l,d))}function l(){let t=e.addFunction(n+`_neg`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.getLocal(`r`),l=a.i32_add(a.getLocal(`r`),a.i32_const(i));t.addCode(a.call(r+`_neg`,o,c),a.call(r+`_neg`,s,l))}function u(){let t=e.addFunction(n+`_conjugate`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.getLocal(`r`),l=a.i32_add(a.getLocal(`r`),a.i32_const(i));t.addCode(a.call(r+`_copy`,o,c),a.call(r+`_neg`,s,l))}function d(){let t=e.addFunction(n+`_isNegative`);t.addParam(`x`,`i32`),t.setReturnType(`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i));t.addCode(a.if(a.call(r+`_isZero`,s),a.ret(a.call(r+`_isNegative`,o))),a.ret(a.call(r+`_isNegative`,s)))}function f(){let a=e.addFunction(n+`_mul`);a.addParam(`x`,`i32`),a.addParam(`y`,`i32`),a.addParam(`r`,`i32`);let o=a.getCodeBuilder(),s=o.getLocal(`x`),c=o.i32_add(o.getLocal(`x`),o.i32_const(i)),l=o.getLocal(`y`),u=o.i32_add(o.getLocal(`y`),o.i32_const(i)),d=o.getLocal(`r`),f=o.i32_add(o.getLocal(`r`),o.i32_const(i)),p=o.i32_const(e.alloc(i)),m=o.i32_const(e.alloc(i)),h=o.i32_const(e.alloc(i)),g=o.i32_const(e.alloc(i));a.addCode(o.call(r+`_mul`,s,l,p),o.call(r+`_mul`,c,u,m),o.call(r+`_add`,s,c,h),o.call(r+`_add`,l,u,g),o.call(r+`_mul`,h,g,h),o.call(t,m,d),o.call(r+`_add`,p,d,d),o.call(r+`_add`,p,m,f),o.call(r+`_sub`,h,f,f))}function p(){let t=e.addFunction(n+`_mul1`);t.addParam(`x`,`i32`),t.addParam(`y`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.getLocal(`y`),l=a.getLocal(`r`),u=a.i32_add(a.getLocal(`r`),a.i32_const(i));t.addCode(a.call(r+`_mul`,o,c,l),a.call(r+`_mul`,s,c,u))}function m(){let a=e.addFunction(n+`_square`);a.addParam(`x`,`i32`),a.addParam(`r`,`i32`);let o=a.getCodeBuilder(),s=o.getLocal(`x`),c=o.i32_add(o.getLocal(`x`),o.i32_const(i)),l=o.getLocal(`r`),u=o.i32_add(o.getLocal(`r`),o.i32_const(i)),d=o.i32_const(e.alloc(i)),f=o.i32_const(e.alloc(i)),p=o.i32_const(e.alloc(i)),m=o.i32_const(e.alloc(i));a.addCode(o.call(r+`_mul`,s,c,d),o.call(r+`_add`,s,c,f),o.call(t,c,p),o.call(r+`_add`,s,p,p),o.call(t,d,m),o.call(r+`_add`,m,d,m),o.call(r+`_mul`,f,p,l),o.call(r+`_sub`,l,m,l),o.call(r+`_add`,d,d,u))}function h(){let t=e.addFunction(n+`_toMontgomery`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.getLocal(`r`),l=a.i32_add(a.getLocal(`r`),a.i32_const(i));t.addCode(a.call(r+`_toMontgomery`,o,c),a.call(r+`_toMontgomery`,s,l))}function g(){let t=e.addFunction(n+`_fromMontgomery`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.getLocal(`r`),l=a.i32_add(a.getLocal(`r`),a.i32_const(i));t.addCode(a.call(r+`_fromMontgomery`,o,c),a.call(r+`_fromMontgomery`,s,l))}function _(){let t=e.addFunction(n+`_copy`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.getLocal(`r`),l=a.i32_add(a.getLocal(`r`),a.i32_const(i));t.addCode(a.call(r+`_copy`,o,c),a.call(r+`_copy`,s,l))}function v(){let t=e.addFunction(n+`_zero`);t.addParam(`x`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i));t.addCode(a.call(r+`_zero`,o),a.call(r+`_zero`,s))}function y(){let t=e.addFunction(n+`_one`);t.addParam(`x`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i));t.addCode(a.call(r+`_one`,o),a.call(r+`_zero`,s))}function b(){let t=e.addFunction(n+`_eq`);t.addParam(`x`,`i32`),t.addParam(`y`,`i32`),t.setReturnType(`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.getLocal(`y`),l=a.i32_add(a.getLocal(`y`),a.i32_const(i));t.addCode(a.i32_and(a.call(r+`_eq`,o,c),a.call(r+`_eq`,s,l)))}function x(){let t=e.addFunction(n+`_isZero`);t.addParam(`x`,`i32`),t.setReturnType(`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i));t.addCode(a.i32_and(a.call(r+`_isZero`,o),a.call(r+`_isZero`,s)))}function S(){let a=e.addFunction(n+`_inverse`);a.addParam(`x`,`i32`),a.addParam(`r`,`i32`);let o=a.getCodeBuilder(),s=o.getLocal(`x`),c=o.i32_add(o.getLocal(`x`),o.i32_const(i)),l=o.getLocal(`r`),u=o.i32_add(o.getLocal(`r`),o.i32_const(i)),d=o.i32_const(e.alloc(i)),f=o.i32_const(e.alloc(i)),p=o.i32_const(e.alloc(i)),m=o.i32_const(e.alloc(i));a.addCode(o.call(r+`_square`,s,d),o.call(r+`_square`,c,f),o.call(t,f,p),o.call(r+`_sub`,d,p,p),o.call(r+`_inverse`,p,m),o.call(r+`_mul`,s,m,l),o.call(r+`_mul`,c,m,u),o.call(r+`_neg`,u,u))}function C(){let t=e.addFunction(n+`_sign`);t.addParam(`x`,`i32`),t.addLocal(`s`,`i32`),t.setReturnType(`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i));t.addCode(a.setLocal(`s`,a.call(r+`_sign`,s)),a.if(a.getLocal(`s`),a.ret(a.getLocal(`s`))),a.ret(a.call(r+`_sign`,o)))}function w(){let t=e.addFunction(n+`_isOne`);t.addParam(`x`,`i32`),t.setReturnType(`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i));t.addCode(a.ret(a.i32_and(a.call(r+`_isOne`,o),a.call(r+`_isZero`,s))))}function T(){let t=e.addFunction(n+`_sqrt`);t.addParam(`a`,`i32`),t.addParam(`pr`,`i32`);let o=t.getCodeBuilder(),s=o.i32_const(e.alloc(z((BigInt(a||0)-3n)/4n,i))),c=o.i32_const(e.alloc(z((BigInt(a||0)-1n)/2n,i))),l=o.getLocal(`a`),u=o.i32_const(e.alloc(i*2)),d=o.i32_const(e.alloc(i*2)),f=o.i32_const(e.alloc(i*2)),p=e.alloc(i*2),m=o.i32_const(p),h=o.i32_const(p),g=o.i32_const(p+i),_=o.i32_const(e.alloc(i*2)),v=o.i32_const(e.alloc(i*2));t.addCode(o.call(n+`_one`,m),o.call(n+`_neg`,m,m),o.call(n+`_exp`,l,s,o.i32_const(i),u),o.call(n+`_square`,u,d),o.call(n+`_mul`,l,d,d),o.call(n+`_conjugate`,d,f),o.call(n+`_mul`,f,d,f),o.if(o.call(n+`_eq`,f,m),o.unreachable()),o.call(n+`_mul`,u,l,_),o.if(o.call(n+`_eq`,d,m),[...o.call(r+`_zero`,h),...o.call(r+`_one`,g),...o.call(n+`_mul`,m,_,o.getLocal(`pr`))],[...o.call(n+`_one`,v),...o.call(n+`_add`,v,d,v),...o.call(n+`_exp`,v,c,o.i32_const(i),v),...o.call(n+`_mul`,v,_,o.getLocal(`pr`))]))}function E(){let t=e.addFunction(n+`_isSquare`);t.addParam(`a`,`i32`),t.setReturnType(`i32`);let r=t.getCodeBuilder(),o=r.i32_const(e.alloc(z((BigInt(a||0)-3n)/4n,i))),s=r.getLocal(`a`),c=r.i32_const(e.alloc(i*2)),l=r.i32_const(e.alloc(i*2)),u=r.i32_const(e.alloc(i*2)),d=e.alloc(i*2),f=r.i32_const(d);t.addCode(r.call(n+`_one`,f),r.call(n+`_neg`,f,f),r.call(n+`_exp`,s,o,r.i32_const(i),c),r.call(n+`_square`,c,l),r.call(n+`_mul`,s,l,l),r.call(n+`_conjugate`,l,u),r.call(n+`_mul`,u,l,u),r.if(r.call(n+`_eq`,u,f),r.ret(r.i32_const(0))),r.ret(r.i32_const(1)))}return x(),w(),v(),y(),_(),f(),p(),m(),o(),c(),l(),u(),h(),g(),b(),S(),s(),C(),d(),e.exportFunction(n+`_isZero`),e.exportFunction(n+`_isOne`),e.exportFunction(n+`_zero`),e.exportFunction(n+`_one`),e.exportFunction(n+`_copy`),e.exportFunction(n+`_mul`),e.exportFunction(n+`_mul1`),e.exportFunction(n+`_square`),e.exportFunction(n+`_add`),e.exportFunction(n+`_sub`),e.exportFunction(n+`_neg`),e.exportFunction(n+`_sign`),e.exportFunction(n+`_conjugate`),e.exportFunction(n+`_fromMontgomery`),e.exportFunction(n+`_toMontgomery`),e.exportFunction(n+`_eq`),e.exportFunction(n+`_inverse`),Ee(e,n),Ce(e,n+`_exp`,i*2,n+`_mul`,n+`_square`,n+`_copy`,n+`_one`),T(),E(),e.exportFunction(n+`_exp`),e.exportFunction(n+`_timesScalar`),e.exportFunction(n+`_batchInverse`),e.exportFunction(n+`_sqrt`),e.exportFunction(n+`_isSquare`),e.exportFunction(n+`_isNegative`),n}var it=s((()=>{we(),De(),be()}));function at(e,t,n,r){if(e.modules[n])return n;let i=e.modules[r].n64*8;e.modules[n]={n64:e.modules[r].n64*3};function a(){let t=e.addFunction(n+`_add`);t.addParam(`x`,`i32`),t.addParam(`y`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i)),l=a.getLocal(`y`),u=a.i32_add(a.getLocal(`y`),a.i32_const(i)),d=a.i32_add(a.getLocal(`y`),a.i32_const(2*i)),f=a.getLocal(`r`),p=a.i32_add(a.getLocal(`r`),a.i32_const(i)),m=a.i32_add(a.getLocal(`r`),a.i32_const(2*i));t.addCode(a.call(r+`_add`,o,l,f),a.call(r+`_add`,s,u,p),a.call(r+`_add`,c,d,m))}function o(){let t=e.addFunction(n+`_timesScalar`);t.addParam(`x`,`i32`),t.addParam(`scalar`,`i32`),t.addParam(`scalarLen`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i)),l=a.getLocal(`r`),u=a.i32_add(a.getLocal(`r`),a.i32_const(i)),d=a.i32_add(a.getLocal(`r`),a.i32_const(2*i));t.addCode(a.call(r+`_timesScalar`,o,a.getLocal(`scalar`),a.getLocal(`scalarLen`),l),a.call(r+`_timesScalar`,s,a.getLocal(`scalar`),a.getLocal(`scalarLen`),u),a.call(r+`_timesScalar`,c,a.getLocal(`scalar`),a.getLocal(`scalarLen`),d))}function s(){let t=e.addFunction(n+`_sub`);t.addParam(`x`,`i32`),t.addParam(`y`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i)),l=a.getLocal(`y`),u=a.i32_add(a.getLocal(`y`),a.i32_const(i)),d=a.i32_add(a.getLocal(`y`),a.i32_const(2*i)),f=a.getLocal(`r`),p=a.i32_add(a.getLocal(`r`),a.i32_const(i)),m=a.i32_add(a.getLocal(`r`),a.i32_const(2*i));t.addCode(a.call(r+`_sub`,o,l,f),a.call(r+`_sub`,s,u,p),a.call(r+`_sub`,c,d,m))}function c(){let t=e.addFunction(n+`_neg`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i)),l=a.getLocal(`r`),u=a.i32_add(a.getLocal(`r`),a.i32_const(i)),d=a.i32_add(a.getLocal(`r`),a.i32_const(2*i));t.addCode(a.call(r+`_neg`,o,l),a.call(r+`_neg`,s,u),a.call(r+`_neg`,c,d))}function l(){let t=e.addFunction(n+`_isNegative`);t.addParam(`x`,`i32`),t.setReturnType(`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i));t.addCode(a.if(a.call(r+`_isZero`,c),a.if(a.call(r+`_isZero`,s),a.ret(a.call(r+`_isNegative`,o)),a.ret(a.call(r+`_isNegative`,s)))),a.ret(a.call(r+`_isNegative`,c)))}function u(){let a=e.addFunction(n+`_mul`);a.addParam(`x`,`i32`),a.addParam(`y`,`i32`),a.addParam(`r`,`i32`);let o=a.getCodeBuilder(),s=o.getLocal(`x`),c=o.i32_add(o.getLocal(`x`),o.i32_const(i)),l=o.i32_add(o.getLocal(`x`),o.i32_const(2*i)),u=o.getLocal(`y`),d=o.i32_add(o.getLocal(`y`),o.i32_const(i)),f=o.i32_add(o.getLocal(`y`),o.i32_const(2*i)),p=o.getLocal(`r`),m=o.i32_add(o.getLocal(`r`),o.i32_const(i)),h=o.i32_add(o.getLocal(`r`),o.i32_const(2*i)),g=o.i32_const(e.alloc(i)),_=o.i32_const(e.alloc(i)),v=o.i32_const(e.alloc(i)),y=o.i32_const(e.alloc(i)),b=o.i32_const(e.alloc(i)),x=o.i32_const(e.alloc(i)),S=o.i32_const(e.alloc(i)),C=o.i32_const(e.alloc(i)),w=o.i32_const(e.alloc(i)),T=o.i32_const(e.alloc(i)),E=o.i32_const(e.alloc(i)),D=o.i32_const(e.alloc(i)),O=o.i32_const(e.alloc(i));a.addCode(o.call(r+`_mul`,s,u,g),o.call(r+`_mul`,c,d,_),o.call(r+`_mul`,l,f,v),o.call(r+`_add`,s,c,y),o.call(r+`_add`,u,d,b),o.call(r+`_add`,s,l,x),o.call(r+`_add`,u,f,S),o.call(r+`_add`,c,l,C),o.call(r+`_add`,d,f,w),o.call(r+`_add`,g,_,T),o.call(r+`_add`,g,v,E),o.call(r+`_add`,_,v,D),o.call(r+`_mul`,C,w,p),o.call(r+`_sub`,p,D,p),o.call(t,p,p),o.call(r+`_add`,g,p,p),o.call(r+`_mul`,y,b,m),o.call(r+`_sub`,m,T,m),o.call(t,v,O),o.call(r+`_add`,m,O,m),o.call(r+`_mul`,x,S,h),o.call(r+`_sub`,h,E,h),o.call(r+`_add`,h,_,h))}function d(){let a=e.addFunction(n+`_square`);a.addParam(`x`,`i32`),a.addParam(`r`,`i32`);let o=a.getCodeBuilder(),s=o.getLocal(`x`),c=o.i32_add(o.getLocal(`x`),o.i32_const(i)),l=o.i32_add(o.getLocal(`x`),o.i32_const(2*i)),u=o.getLocal(`r`),d=o.i32_add(o.getLocal(`r`),o.i32_const(i)),f=o.i32_add(o.getLocal(`r`),o.i32_const(2*i)),p=o.i32_const(e.alloc(i)),m=o.i32_const(e.alloc(i)),h=o.i32_const(e.alloc(i)),g=o.i32_const(e.alloc(i)),_=o.i32_const(e.alloc(i)),v=o.i32_const(e.alloc(i)),y=o.i32_const(e.alloc(i));a.addCode(o.call(r+`_square`,s,p),o.call(r+`_mul`,s,c,m),o.call(r+`_add`,m,m,h),o.call(r+`_sub`,s,c,g),o.call(r+`_add`,g,l,g),o.call(r+`_square`,g,g),o.call(r+`_mul`,c,l,_),o.call(r+`_add`,_,_,v),o.call(r+`_square`,l,y),o.call(t,v,u),o.call(r+`_add`,p,u,u),o.call(t,y,d),o.call(r+`_add`,h,d,d),o.call(r+`_add`,p,y,f),o.call(r+`_sub`,v,f,f),o.call(r+`_add`,g,f,f),o.call(r+`_add`,h,f,f))}function f(){let t=e.addFunction(n+`_toMontgomery`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i)),l=a.getLocal(`r`),u=a.i32_add(a.getLocal(`r`),a.i32_const(i)),d=a.i32_add(a.getLocal(`r`),a.i32_const(2*i));t.addCode(a.call(r+`_toMontgomery`,o,l),a.call(r+`_toMontgomery`,s,u),a.call(r+`_toMontgomery`,c,d))}function p(){let t=e.addFunction(n+`_fromMontgomery`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i)),l=a.getLocal(`r`),u=a.i32_add(a.getLocal(`r`),a.i32_const(i)),d=a.i32_add(a.getLocal(`r`),a.i32_const(2*i));t.addCode(a.call(r+`_fromMontgomery`,o,l),a.call(r+`_fromMontgomery`,s,u),a.call(r+`_fromMontgomery`,c,d))}function m(){let t=e.addFunction(n+`_copy`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i)),l=a.getLocal(`r`),u=a.i32_add(a.getLocal(`r`),a.i32_const(i)),d=a.i32_add(a.getLocal(`r`),a.i32_const(2*i));t.addCode(a.call(r+`_copy`,o,l),a.call(r+`_copy`,s,u),a.call(r+`_copy`,c,d))}function h(){let t=e.addFunction(n+`_zero`);t.addParam(`x`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i));t.addCode(a.call(r+`_zero`,o),a.call(r+`_zero`,s),a.call(r+`_zero`,c))}function g(){let t=e.addFunction(n+`_one`);t.addParam(`x`,`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i));t.addCode(a.call(r+`_one`,o),a.call(r+`_zero`,s),a.call(r+`_zero`,c))}function _(){let t=e.addFunction(n+`_eq`);t.addParam(`x`,`i32`),t.addParam(`y`,`i32`),t.setReturnType(`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i)),l=a.getLocal(`y`),u=a.i32_add(a.getLocal(`y`),a.i32_const(i)),d=a.i32_add(a.getLocal(`y`),a.i32_const(2*i));t.addCode(a.i32_and(a.i32_and(a.call(r+`_eq`,o,l),a.call(r+`_eq`,s,u)),a.call(r+`_eq`,c,d)))}function v(){let t=e.addFunction(n+`_isZero`);t.addParam(`x`,`i32`),t.setReturnType(`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i));t.addCode(a.i32_and(a.i32_and(a.call(r+`_isZero`,o),a.call(r+`_isZero`,s)),a.call(r+`_isZero`,c)))}function y(){let a=e.addFunction(n+`_inverse`);a.addParam(`x`,`i32`),a.addParam(`r`,`i32`);let o=a.getCodeBuilder(),s=o.getLocal(`x`),c=o.i32_add(o.getLocal(`x`),o.i32_const(i)),l=o.i32_add(o.getLocal(`x`),o.i32_const(2*i)),u=o.getLocal(`r`),d=o.i32_add(o.getLocal(`r`),o.i32_const(i)),f=o.i32_add(o.getLocal(`r`),o.i32_const(2*i)),p=o.i32_const(e.alloc(i)),m=o.i32_const(e.alloc(i)),h=o.i32_const(e.alloc(i)),g=o.i32_const(e.alloc(i)),_=o.i32_const(e.alloc(i)),v=o.i32_const(e.alloc(i)),y=o.i32_const(e.alloc(i)),b=o.i32_const(e.alloc(i)),x=o.i32_const(e.alloc(i)),S=o.i32_const(e.alloc(i)),C=o.i32_const(e.alloc(i));a.addCode(o.call(r+`_square`,s,p),o.call(r+`_square`,c,m),o.call(r+`_square`,l,h),o.call(r+`_mul`,s,c,g),o.call(r+`_mul`,s,l,_),o.call(r+`_mul`,c,l,v),o.call(t,v,y),o.call(r+`_sub`,p,y,y),o.call(t,h,b),o.call(r+`_sub`,b,g,b),o.call(r+`_sub`,m,_,x),o.call(r+`_mul`,l,b,S),o.call(r+`_mul`,c,x,C),o.call(r+`_add`,S,C,S),o.call(t,S,S),o.call(r+`_mul`,s,y,C),o.call(r+`_add`,C,S,S),o.call(r+`_inverse`,S,S),o.call(r+`_mul`,S,y,u),o.call(r+`_mul`,S,b,d),o.call(r+`_mul`,S,x,f))}function b(){let t=e.addFunction(n+`_sign`);t.addParam(`x`,`i32`),t.addLocal(`s`,`i32`),t.setReturnType(`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(2*i));t.addCode(a.setLocal(`s`,a.call(r+`_sign`,c)),a.if(a.getLocal(`s`),a.ret(a.getLocal(`s`))),a.setLocal(`s`,a.call(r+`_sign`,s)),a.if(a.getLocal(`s`),a.ret(a.getLocal(`s`))),a.ret(a.call(r+`_sign`,o)))}function x(){let t=e.addFunction(n+`_isOne`);t.addParam(`x`,`i32`),t.setReturnType(`i32`);let a=t.getCodeBuilder(),o=a.getLocal(`x`),s=a.i32_add(a.getLocal(`x`),a.i32_const(i)),c=a.i32_add(a.getLocal(`x`),a.i32_const(i*2));t.addCode(a.ret(a.i32_and(a.i32_and(a.call(r+`_isOne`,o),a.call(r+`_isZero`,s)),a.call(r+`_isZero`,c))))}return v(),x(),h(),g(),m(),u(),d(),a(),s(),c(),b(),f(),p(),_(),y(),o(),l(),e.exportFunction(n+`_isZero`),e.exportFunction(n+`_isOne`),e.exportFunction(n+`_zero`),e.exportFunction(n+`_one`),e.exportFunction(n+`_copy`),e.exportFunction(n+`_mul`),e.exportFunction(n+`_square`),e.exportFunction(n+`_add`),e.exportFunction(n+`_sub`),e.exportFunction(n+`_neg`),e.exportFunction(n+`_sign`),e.exportFunction(n+`_fromMontgomery`),e.exportFunction(n+`_toMontgomery`),e.exportFunction(n+`_eq`),e.exportFunction(n+`_inverse`),Ee(e,n),Ce(e,n+`_exp`,i*3,n+`_mul`,n+`_square`,n+`_copy`,n+`_one`),e.exportFunction(n+`_exp`),e.exportFunction(n+`_timesScalar`),e.exportFunction(n+`_batchInverse`),e.exportFunction(n+`_isNegative`),n}var ot=s((()=>{we(),De()}));function st(e,t,n,r,i,a,o,s){let c=e.addFunction(t);c.addParam(`base`,`i32`),c.addParam(`scalar`,`i32`),c.addParam(`scalarLength`,`i32`),c.addParam(`r`,`i32`),c.addLocal(`old0`,`i32`),c.addLocal(`nbits`,`i32`),c.addLocal(`i`,`i32`),c.addLocal(`last`,`i32`),c.addLocal(`cur`,`i32`),c.addLocal(`carry`,`i32`),c.addLocal(`p`,`i32`);let l=c.getCodeBuilder(),u=l.i32_const(e.alloc(n));function d(e){return l.i32_and(l.i32_shr_u(l.i32_load(l.i32_add(l.getLocal(`scalar`),l.i32_and(l.i32_shr_u(e,l.i32_const(3)),l.i32_const(4294967292)))),l.i32_and(e,l.i32_const(31))),l.i32_const(1))}function f(e){return[...l.i32_store8(l.getLocal(`p`),l.i32_const(e)),...l.setLocal(`p`,l.i32_add(l.getLocal(`p`),l.i32_const(1)))]}c.addCode(l.if(l.i32_eqz(l.getLocal(`scalarLength`)),[...l.call(s,l.getLocal(`r`)),...l.ret([])]),l.setLocal(`nbits`,l.i32_shl(l.getLocal(`scalarLength`),l.i32_const(3))),l.setLocal(`old0`,l.i32_load(l.i32_const(0))),l.setLocal(`p`,l.getLocal(`old0`)),l.i32_store(l.i32_const(0),l.i32_and(l.i32_add(l.i32_add(l.getLocal(`old0`),l.i32_const(32)),l.getLocal(`nbits`)),l.i32_const(4294967288))),l.setLocal(`i`,l.i32_const(1)),l.setLocal(`last`,d(l.i32_const(0))),l.setLocal(`carry`,l.i32_const(0)),l.block(l.loop(l.br_if(1,l.i32_eq(l.getLocal(`i`),l.getLocal(`nbits`))),l.setLocal(`cur`,d(l.getLocal(`i`))),l.if(l.getLocal(`last`),l.if(l.getLocal(`cur`),l.if(l.getLocal(`carry`),[...l.setLocal(`last`,l.i32_const(0)),...l.setLocal(`carry`,l.i32_const(1)),...f(1)],[...l.setLocal(`last`,l.i32_const(0)),...l.setLocal(`carry`,l.i32_const(1)),...f(255)]),l.if(l.getLocal(`carry`),[...l.setLocal(`last`,l.i32_const(0)),...l.setLocal(`carry`,l.i32_const(1)),...f(255)],[...l.setLocal(`last`,l.i32_const(0)),...l.setLocal(`carry`,l.i32_const(0)),...f(1)])),l.if(l.getLocal(`cur`),l.if(l.getLocal(`carry`),[...l.setLocal(`last`,l.i32_const(0)),...l.setLocal(`carry`,l.i32_const(1)),...f(0)],[...l.setLocal(`last`,l.i32_const(1)),...l.setLocal(`carry`,l.i32_const(0)),...f(0)]),l.if(l.getLocal(`carry`),[...l.setLocal(`last`,l.i32_const(1)),...l.setLocal(`carry`,l.i32_const(0)),...f(0)],[...l.setLocal(`last`,l.i32_const(0)),...l.setLocal(`carry`,l.i32_const(0)),...f(0)]))),l.setLocal(`i`,l.i32_add(l.getLocal(`i`),l.i32_const(1))),l.br(0))),l.if(l.getLocal(`last`),l.if(l.getLocal(`carry`),[...f(255),...f(0),...f(1)],[...f(1)]),l.if(l.getLocal(`carry`),[...f(0),...f(1)])),l.setLocal(`p`,l.i32_sub(l.getLocal(`p`),l.i32_const(1))),l.call(o,l.getLocal(`base`),u),l.call(s,l.getLocal(`r`)),l.block(l.loop(l.call(i,l.getLocal(`r`),l.getLocal(`r`)),l.setLocal(`cur`,l.i32_load8_u(l.getLocal(`p`))),l.if(l.getLocal(`cur`),l.if(l.i32_eq(l.getLocal(`cur`),l.i32_const(1)),l.call(r,l.getLocal(`r`),u,l.getLocal(`r`)),l.call(a,l.getLocal(`r`),u,l.getLocal(`r`)))),l.br_if(1,l.i32_eq(l.getLocal(`old0`),l.getLocal(`p`))),l.setLocal(`p`,l.i32_sub(l.getLocal(`p`),l.i32_const(1))),l.br(0))),l.i32_store(l.i32_const(0),l.getLocal(`old0`)))}var ct=s((()=>{}));function lt(e,t,n,r,i){let a=e.modules[t].n64*8;function o(){let t=e.addFunction(n+`_getChunk`);t.addParam(`pScalar`,`i32`),t.addParam(`scalarSize`,`i32`),t.addParam(`startBit`,`i32`),t.addParam(`chunkSize`,`i32`),t.addLocal(`bitsToEnd`,`i32`),t.addLocal(`mask`,`i32`),t.setReturnType(`i32`);let r=t.getCodeBuilder();t.addCode(r.setLocal(`bitsToEnd`,r.i32_sub(r.i32_mul(r.getLocal(`scalarSize`),r.i32_const(8)),r.getLocal(`startBit`))),r.if(r.i32_gt_s(r.getLocal(`chunkSize`),r.getLocal(`bitsToEnd`)),r.setLocal(`mask`,r.i32_sub(r.i32_shl(r.i32_const(1),r.getLocal(`bitsToEnd`)),r.i32_const(1))),r.setLocal(`mask`,r.i32_sub(r.i32_shl(r.i32_const(1),r.getLocal(`chunkSize`)),r.i32_const(1)))),r.i32_and(r.i32_shr_u(r.i32_load(r.i32_add(r.getLocal(`pScalar`),r.i32_shr_u(r.getLocal(`startBit`),r.i32_const(3))),0,0),r.i32_and(r.getLocal(`startBit`),r.i32_const(7))),r.getLocal(`mask`)))}function s(){let o=e.addFunction(n+`_chunk`);o.addParam(`pBases`,`i32`),o.addParam(`pScalars`,`i32`),o.addParam(`scalarSize`,`i32`),o.addParam(`n`,`i32`),o.addParam(`startBit`,`i32`),o.addParam(`chunkSize`,`i32`),o.addParam(`pr`,`i32`),o.addLocal(`nChunks`,`i32`),o.addLocal(`itScalar`,`i32`),o.addLocal(`endScalar`,`i32`),o.addLocal(`itBase`,`i32`),o.addLocal(`i`,`i32`),o.addLocal(`j`,`i32`),o.addLocal(`nTable`,`i32`),o.addLocal(`pTable`,`i32`),o.addLocal(`idx`,`i32`),o.addLocal(`pIdxTable`,`i32`);let s=o.getCodeBuilder();o.addCode(s.if(s.i32_eqz(s.getLocal(`n`)),[...s.call(t+`_zero`,s.getLocal(`pr`)),...s.ret([])]),s.setLocal(`nTable`,s.i32_shl(s.i32_const(1),s.getLocal(`chunkSize`))),s.setLocal(`pTable`,s.i32_load(s.i32_const(0))),s.i32_store(s.i32_const(0),s.i32_add(s.getLocal(`pTable`),s.i32_mul(s.getLocal(`nTable`),s.i32_const(a)))),s.setLocal(`j`,s.i32_const(0)),s.block(s.loop(s.br_if(1,s.i32_eq(s.getLocal(`j`),s.getLocal(`nTable`))),s.call(t+`_zero`,s.i32_add(s.getLocal(`pTable`),s.i32_mul(s.getLocal(`j`),s.i32_const(a)))),s.setLocal(`j`,s.i32_add(s.getLocal(`j`),s.i32_const(1))),s.br(0))),s.setLocal(`itBase`,s.getLocal(`pBases`)),s.setLocal(`itScalar`,s.getLocal(`pScalars`)),s.setLocal(`endScalar`,s.i32_add(s.getLocal(`pScalars`),s.i32_mul(s.getLocal(`n`),s.getLocal(`scalarSize`)))),s.block(s.loop(s.br_if(1,s.i32_eq(s.getLocal(`itScalar`),s.getLocal(`endScalar`))),s.setLocal(`idx`,s.call(n+`_getChunk`,s.getLocal(`itScalar`),s.getLocal(`scalarSize`),s.getLocal(`startBit`),s.getLocal(`chunkSize`))),s.if(s.getLocal(`idx`),[...s.setLocal(`pIdxTable`,s.i32_add(s.getLocal(`pTable`),s.i32_mul(s.i32_sub(s.getLocal(`idx`),s.i32_const(1)),s.i32_const(a)))),...s.call(r,s.getLocal(`pIdxTable`),s.getLocal(`itBase`),s.getLocal(`pIdxTable`))]),s.setLocal(`itScalar`,s.i32_add(s.getLocal(`itScalar`),s.getLocal(`scalarSize`))),s.setLocal(`itBase`,s.i32_add(s.getLocal(`itBase`),s.i32_const(i))),s.br(0))),s.call(n+`_reduceTable`,s.getLocal(`pTable`),s.getLocal(`chunkSize`)),s.call(t+`_copy`,s.getLocal(`pTable`),s.getLocal(`pr`)),s.i32_store(s.i32_const(0),s.getLocal(`pTable`)))}function c(){let r=e.addFunction(n);r.addParam(`pBases`,`i32`),r.addParam(`pScalars`,`i32`),r.addParam(`scalarSize`,`i32`),r.addParam(`n`,`i32`),r.addParam(`pr`,`i32`),r.addLocal(`chunkSize`,`i32`),r.addLocal(`nChunks`,`i32`),r.addLocal(`itScalar`,`i32`),r.addLocal(`endScalar`,`i32`),r.addLocal(`itBase`,`i32`),r.addLocal(`itBit`,`i32`),r.addLocal(`i`,`i32`),r.addLocal(`j`,`i32`),r.addLocal(`nTable`,`i32`),r.addLocal(`pTable`,`i32`),r.addLocal(`idx`,`i32`),r.addLocal(`pIdxTable`,`i32`);let i=r.getCodeBuilder(),o=i.i32_const(e.alloc(a)),s=e.alloc([17,17,17,17,17,17,17,17,17,17,16,16,15,14,13,13,12,11,10,9,8,7,7,6,5,4,3,2,1,1,1,1]);r.addCode(i.call(t+`_zero`,i.getLocal(`pr`)),i.if(i.i32_eqz(i.getLocal(`n`)),i.ret([])),i.setLocal(`chunkSize`,i.i32_load8_u(i.i32_clz(i.getLocal(`n`)),s)),i.setLocal(`nChunks`,i.i32_add(i.i32_div_u(i.i32_sub(i.i32_shl(i.getLocal(`scalarSize`),i.i32_const(3)),i.i32_const(1)),i.getLocal(`chunkSize`)),i.i32_const(1))),i.setLocal(`itBit`,i.i32_mul(i.i32_sub(i.getLocal(`nChunks`),i.i32_const(1)),i.getLocal(`chunkSize`))),i.block(i.loop(i.br_if(1,i.i32_lt_s(i.getLocal(`itBit`),i.i32_const(0))),i.if(i.i32_eqz(i.call(t+`_isZero`,i.getLocal(`pr`))),[...i.setLocal(`j`,i.i32_const(0)),...i.block(i.loop(i.br_if(1,i.i32_eq(i.getLocal(`j`),i.getLocal(`chunkSize`))),i.call(t+`_double`,i.getLocal(`pr`),i.getLocal(`pr`)),i.setLocal(`j`,i.i32_add(i.getLocal(`j`),i.i32_const(1))),i.br(0)))]),i.call(n+`_chunk`,i.getLocal(`pBases`),i.getLocal(`pScalars`),i.getLocal(`scalarSize`),i.getLocal(`n`),i.getLocal(`itBit`),i.getLocal(`chunkSize`),o),i.call(t+`_add`,i.getLocal(`pr`),o,i.getLocal(`pr`)),i.setLocal(`itBit`,i.i32_sub(i.getLocal(`itBit`),i.getLocal(`chunkSize`))),i.br(0))))}function l(){let r=e.addFunction(n+`_reduceTable`);r.addParam(`pTable`,`i32`),r.addParam(`p`,`i32`),r.addLocal(`half`,`i32`),r.addLocal(`it1`,`i32`),r.addLocal(`it2`,`i32`),r.addLocal(`pAcc`,`i32`);let i=r.getCodeBuilder();r.addCode(i.if(i.i32_eq(i.getLocal(`p`),i.i32_const(1)),i.ret([])),i.setLocal(`half`,i.i32_shl(i.i32_const(1),i.i32_sub(i.getLocal(`p`),i.i32_const(1)))),i.setLocal(`it1`,i.getLocal(`pTable`)),i.setLocal(`it2`,i.i32_add(i.getLocal(`pTable`),i.i32_mul(i.getLocal(`half`),i.i32_const(a)))),i.setLocal(`pAcc`,i.i32_sub(i.getLocal(`it2`),i.i32_const(a))),i.block(i.loop(i.br_if(1,i.i32_eq(i.getLocal(`it1`),i.getLocal(`pAcc`))),i.call(t+`_add`,i.getLocal(`it1`),i.getLocal(`it2`),i.getLocal(`it1`)),i.call(t+`_add`,i.getLocal(`pAcc`),i.getLocal(`it2`),i.getLocal(`pAcc`)),i.setLocal(`it1`,i.i32_add(i.getLocal(`it1`),i.i32_const(a))),i.setLocal(`it2`,i.i32_add(i.getLocal(`it2`),i.i32_const(a))),i.br(0))),i.call(n+`_reduceTable`,i.getLocal(`pTable`),i.i32_sub(i.getLocal(`p`),i.i32_const(1))),i.setLocal(`p`,i.i32_sub(i.getLocal(`p`),i.i32_const(1))),i.block(i.loop(i.br_if(1,i.i32_eqz(i.getLocal(`p`))),i.call(t+`_double`,i.getLocal(`pAcc`),i.getLocal(`pAcc`)),i.setLocal(`p`,i.i32_sub(i.getLocal(`p`),i.i32_const(1))),i.br(0))),i.call(t+`_add`,i.getLocal(`pTable`),i.getLocal(`pAcc`),i.getLocal(`pTable`)))}o(),l(),s(),c(),e.exportFunction(n),e.exportFunction(n+`_chunk`)}var ut=s((()=>{}));function dt(e,t,n,r){let i=e.modules[n].n64,a=i*8;if(e.modules[t])return t;e.modules[t]={n64:i*3};function o(){let r=e.addFunction(t+`_isZero`);r.addParam(`p1`,`i32`),r.setReturnType(`i32`);let i=r.getCodeBuilder();r.addCode(i.call(n+`_isZero`,i.i32_add(i.getLocal(`p1`),i.i32_const(a*2))))}function s(){let r=e.addFunction(t+`_isZeroAffine`);r.addParam(`p1`,`i32`),r.setReturnType(`i32`);let i=r.getCodeBuilder();r.addCode(i.i32_and(i.call(n+`_isZero`,i.getLocal(`p1`)),i.call(n+`_isZero`,i.i32_add(i.getLocal(`p1`),i.i32_const(a)))))}function c(){let n=e.addFunction(t+`_copy`);n.addParam(`ps`,`i32`),n.addParam(`pd`,`i32`);let r=n.getCodeBuilder();for(let e=0;e{ct(),Ae(),ut()}));function pt(e,t,n,r,i){let a=e.modules[r].n64*8,o=e.modules[n].n64*8,s=e.modules[r].q,c=s-1n,l=0;for(;!Ie(c);)l++,c>>=1n;let u=2n;for(;We(u,s>>1n,s)===1n;)u+=1n;let d=Array(l+1);d[l]=We(u,c,s);let f=l-1;for(;f>=0;)d[f]=We(d[f+1],2n,s),f--;let p=[],m=(1n<>n);return t}let T=Array(256);for(let e=0;e<256;e++)T[e]=w(e);let E=e.alloc(T);function D(){let n=e.addFunction(t+`__log2`);n.addParam(`n`,`i32`),n.setReturnType(`i32`),n.addLocal(`bits`,`i32`),n.addLocal(`aux`,`i32`);let r=n.getCodeBuilder();n.addCode(r.setLocal(`aux`,r.i32_shr_u(r.getLocal(`n`),r.i32_const(1)))),n.addCode(r.setLocal(`bits`,r.i32_const(0))),n.addCode(r.block(r.loop(r.br_if(1,r.i32_eqz(r.getLocal(`aux`))),r.setLocal(`aux`,r.i32_shr_u(r.getLocal(`aux`),r.i32_const(1))),r.setLocal(`bits`,r.i32_add(r.getLocal(`bits`),r.i32_const(1))),r.br(0)))),n.addCode(r.if(r.i32_ne(r.getLocal(`n`),r.i32_shl(r.i32_const(1),r.getLocal(`bits`))),r.unreachable())),n.addCode(r.if(r.i32_gt_u(r.getLocal(`bits`),r.i32_const(l)),r.unreachable())),n.addCode(r.getLocal(`bits`))}function O(){let n=e.addFunction(t+`_fft`);n.addParam(`px`,`i32`),n.addParam(`n`,`i32`),n.addLocal(`bits`,`i32`);let i=n.getCodeBuilder(),o=i.i32_const(e.alloc(a));n.addCode(i.setLocal(`bits`,i.call(t+`__log2`,i.getLocal(`n`))),i.call(r+`_one`,o),i.call(t+`_rawfft`,i.getLocal(`px`),i.getLocal(`bits`),i.i32_const(0),o))}function k(){let n=e.addFunction(t+`_ifft`);n.addParam(`px`,`i32`),n.addParam(`n`,`i32`),n.addLocal(`bits`,`i32`),n.addLocal(`pInv2`,`i32`);let r=n.getCodeBuilder();n.addCode(r.setLocal(`bits`,r.call(t+`__log2`,r.getLocal(`n`))),r.setLocal(`pInv2`,r.i32_add(r.i32_const(v),r.i32_mul(r.getLocal(`bits`),r.i32_const(a)))),r.call(t+`_rawfft`,r.getLocal(`px`),r.getLocal(`bits`),r.i32_const(1),r.getLocal(`pInv2`)))}function A(){let s=e.addFunction(t+`_rawfft`);s.addParam(`px`,`i32`),s.addParam(`bits`,`i32`),s.addParam(`reverse`,`i32`),s.addParam(`mulFactor`,`i32`),s.addLocal(`s`,`i32`),s.addLocal(`k`,`i32`),s.addLocal(`j`,`i32`),s.addLocal(`m`,`i32`),s.addLocal(`mdiv2`,`i32`),s.addLocal(`n`,`i32`),s.addLocal(`pwm`,`i32`),s.addLocal(`idx1`,`i32`),s.addLocal(`idx2`,`i32`);let c=s.getCodeBuilder(),l=c.i32_const(e.alloc(a)),u=c.i32_const(e.alloc(o)),d=c.i32_const(e.alloc(o));s.addCode(c.call(t+`__reversePermutation`,c.getLocal(`px`),c.getLocal(`bits`)),c.setLocal(`n`,c.i32_shl(c.i32_const(1),c.getLocal(`bits`))),c.setLocal(`s`,c.i32_const(1)),c.block(c.loop(c.br_if(1,c.i32_gt_u(c.getLocal(`s`),c.getLocal(`bits`))),c.setLocal(`m`,c.i32_shl(c.i32_const(1),c.getLocal(`s`))),c.setLocal(`pwm`,c.i32_add(c.i32_const(h),c.i32_mul(c.getLocal(`s`),c.i32_const(a)))),c.setLocal(`k`,c.i32_const(0)),c.block(c.loop(c.br_if(1,c.i32_ge_u(c.getLocal(`k`),c.getLocal(`n`))),c.call(r+`_one`,l),c.setLocal(`mdiv2`,c.i32_shr_u(c.getLocal(`m`),c.i32_const(1))),c.setLocal(`j`,c.i32_const(0)),c.block(c.loop(c.br_if(1,c.i32_ge_u(c.getLocal(`j`),c.getLocal(`mdiv2`))),c.setLocal(`idx1`,c.i32_add(c.getLocal(`px`),c.i32_mul(c.i32_add(c.getLocal(`k`),c.getLocal(`j`)),c.i32_const(o)))),c.setLocal(`idx2`,c.i32_add(c.getLocal(`idx1`),c.i32_mul(c.getLocal(`mdiv2`),c.i32_const(o)))),c.call(i,c.getLocal(`idx2`),l,u),c.call(n+`_copy`,c.getLocal(`idx1`),d),c.call(n+`_add`,d,u,c.getLocal(`idx1`)),c.call(n+`_sub`,d,u,c.getLocal(`idx2`)),c.call(r+`_mul`,l,c.getLocal(`pwm`),l),c.setLocal(`j`,c.i32_add(c.getLocal(`j`),c.i32_const(1))),c.br(0))),c.setLocal(`k`,c.i32_add(c.getLocal(`k`),c.getLocal(`m`))),c.br(0))),c.setLocal(`s`,c.i32_add(c.getLocal(`s`),c.i32_const(1))),c.br(0))),c.call(t+`__fftFinal`,c.getLocal(`px`),c.getLocal(`bits`),c.getLocal(`reverse`),c.getLocal(`mulFactor`)))}function j(){let a=e.addFunction(t+`__fftFinal`);a.addParam(`px`,`i32`),a.addParam(`bits`,`i32`),a.addParam(`reverse`,`i32`),a.addParam(`mulFactor`,`i32`),a.addLocal(`n`,`i32`),a.addLocal(`ndiv2`,`i32`),a.addLocal(`pInv2`,`i32`),a.addLocal(`i`,`i32`),a.addLocal(`mask`,`i32`),a.addLocal(`idx1`,`i32`),a.addLocal(`idx2`,`i32`);let s=a.getCodeBuilder(),c=s.i32_const(e.alloc(o));a.addCode(s.if(s.i32_and(s.i32_eqz(s.getLocal(`reverse`)),s.call(r+`_isOne`,s.getLocal(`mulFactor`))),s.ret([])),s.setLocal(`n`,s.i32_shl(s.i32_const(1),s.getLocal(`bits`))),s.setLocal(`mask`,s.i32_sub(s.getLocal(`n`),s.i32_const(1))),s.setLocal(`i`,s.i32_const(1)),s.setLocal(`ndiv2`,s.i32_shr_u(s.getLocal(`n`),s.i32_const(1))),s.block(s.loop(s.br_if(1,s.i32_ge_u(s.getLocal(`i`),s.getLocal(`ndiv2`))),s.setLocal(`idx1`,s.i32_add(s.getLocal(`px`),s.i32_mul(s.getLocal(`i`),s.i32_const(o)))),s.setLocal(`idx2`,s.i32_add(s.getLocal(`px`),s.i32_mul(s.i32_sub(s.getLocal(`n`),s.getLocal(`i`)),s.i32_const(o)))),s.if(s.getLocal(`reverse`),s.if(s.call(r+`_isOne`,s.getLocal(`mulFactor`)),[...s.call(n+`_copy`,s.getLocal(`idx1`),c),...s.call(n+`_copy`,s.getLocal(`idx2`),s.getLocal(`idx1`)),...s.call(n+`_copy`,c,s.getLocal(`idx2`))],[...s.call(n+`_copy`,s.getLocal(`idx1`),c),...s.call(i,s.getLocal(`idx2`),s.getLocal(`mulFactor`),s.getLocal(`idx1`)),...s.call(i,c,s.getLocal(`mulFactor`),s.getLocal(`idx2`))]),s.if(s.call(r+`_isOne`,s.getLocal(`mulFactor`)),[],[...s.call(i,s.getLocal(`idx1`),s.getLocal(`mulFactor`),s.getLocal(`idx1`)),...s.call(i,s.getLocal(`idx2`),s.getLocal(`mulFactor`),s.getLocal(`idx2`))])),s.setLocal(`i`,s.i32_add(s.getLocal(`i`),s.i32_const(1))),s.br(0))),s.if(s.call(r+`_isOne`,s.getLocal(`mulFactor`)),[],[...s.call(i,s.getLocal(`px`),s.getLocal(`mulFactor`),s.getLocal(`px`)),...s.setLocal(`idx2`,s.i32_add(s.getLocal(`px`),s.i32_mul(s.getLocal(`ndiv2`),s.i32_const(o)))),...s.call(i,s.getLocal(`idx2`),s.getLocal(`mulFactor`),s.getLocal(`idx2`))]))}function M(){let r=e.addFunction(t+`__reversePermutation`);r.addParam(`px`,`i32`),r.addParam(`bits`,`i32`),r.addLocal(`n`,`i32`),r.addLocal(`i`,`i32`),r.addLocal(`ri`,`i32`),r.addLocal(`idx1`,`i32`),r.addLocal(`idx2`,`i32`);let i=r.getCodeBuilder(),a=i.i32_const(e.alloc(o));r.addCode(i.setLocal(`n`,i.i32_shl(i.i32_const(1),i.getLocal(`bits`))),i.setLocal(`i`,i.i32_const(0)),i.block(i.loop(i.br_if(1,i.i32_eq(i.getLocal(`i`),i.getLocal(`n`))),i.setLocal(`idx1`,i.i32_add(i.getLocal(`px`),i.i32_mul(i.getLocal(`i`),i.i32_const(o)))),i.setLocal(`ri`,i.call(t+`__rev`,i.getLocal(`i`),i.getLocal(`bits`))),i.setLocal(`idx2`,i.i32_add(i.getLocal(`px`),i.i32_mul(i.getLocal(`ri`),i.i32_const(o)))),i.if(i.i32_lt_u(i.getLocal(`i`),i.getLocal(`ri`)),[...i.call(n+`_copy`,i.getLocal(`idx1`),a),...i.call(n+`_copy`,i.getLocal(`idx2`),i.getLocal(`idx1`)),...i.call(n+`_copy`,a,i.getLocal(`idx2`))]),i.setLocal(`i`,i.i32_add(i.getLocal(`i`),i.i32_const(1))),i.br(0))))}function N(){let n=e.addFunction(t+`__rev`);n.addParam(`x`,`i32`),n.addParam(`bits`,`i32`),n.setReturnType(`i32`);let r=n.getCodeBuilder();n.addCode(r.i32_rotl(r.i32_add(r.i32_add(r.i32_shl(r.i32_load8_u(r.i32_and(r.getLocal(`x`),r.i32_const(255)),E,0),r.i32_const(24)),r.i32_shl(r.i32_load8_u(r.i32_and(r.i32_shr_u(r.getLocal(`x`),r.i32_const(8)),r.i32_const(255)),E,0),r.i32_const(16))),r.i32_add(r.i32_shl(r.i32_load8_u(r.i32_and(r.i32_shr_u(r.getLocal(`x`),r.i32_const(16)),r.i32_const(255)),E,0),r.i32_const(8)),r.i32_load8_u(r.i32_and(r.i32_shr_u(r.getLocal(`x`),r.i32_const(24)),r.i32_const(255)),E,0))),r.getLocal(`bits`)))}function P(){let s=e.addFunction(t+`_fftJoin`);s.addParam(`pBuff1`,`i32`),s.addParam(`pBuff2`,`i32`),s.addParam(`n`,`i32`),s.addParam(`first`,`i32`),s.addParam(`inc`,`i32`),s.addLocal(`idx1`,`i32`),s.addLocal(`idx2`,`i32`),s.addLocal(`i`,`i32`);let c=s.getCodeBuilder(),l=c.i32_const(e.alloc(a)),u=c.i32_const(e.alloc(o)),d=c.i32_const(e.alloc(o));s.addCode(c.call(r+`_copy`,c.getLocal(`first`),l),c.setLocal(`i`,c.i32_const(0)),c.block(c.loop(c.br_if(1,c.i32_eq(c.getLocal(`i`),c.getLocal(`n`))),c.setLocal(`idx1`,c.i32_add(c.getLocal(`pBuff1`),c.i32_mul(c.getLocal(`i`),c.i32_const(o)))),c.setLocal(`idx2`,c.i32_add(c.getLocal(`pBuff2`),c.i32_mul(c.getLocal(`i`),c.i32_const(o)))),c.call(i,c.getLocal(`idx2`),l,u),c.call(n+`_copy`,c.getLocal(`idx1`),d),c.call(n+`_add`,d,u,c.getLocal(`idx1`)),c.call(n+`_sub`,d,u,c.getLocal(`idx2`)),c.call(r+`_mul`,l,c.getLocal(`inc`),l),c.setLocal(`i`,c.i32_add(c.getLocal(`i`),c.i32_const(1))),c.br(0))))}function F(){let s=e.addFunction(t+`_fftJoinExt`);s.addParam(`pBuff1`,`i32`),s.addParam(`pBuff2`,`i32`),s.addParam(`n`,`i32`),s.addParam(`first`,`i32`),s.addParam(`inc`,`i32`),s.addParam(`totalBits`,`i32`),s.addLocal(`idx1`,`i32`),s.addLocal(`idx2`,`i32`),s.addLocal(`i`,`i32`),s.addLocal(`pShiftToM`,`i32`);let c=s.getCodeBuilder(),l=c.i32_const(e.alloc(a)),u=c.i32_const(e.alloc(o));s.addCode(c.setLocal(`pShiftToM`,c.i32_add(c.i32_const(S),c.i32_mul(c.getLocal(`totalBits`),c.i32_const(a)))),c.call(r+`_copy`,c.getLocal(`first`),l),c.setLocal(`i`,c.i32_const(0)),c.block(c.loop(c.br_if(1,c.i32_eq(c.getLocal(`i`),c.getLocal(`n`))),c.setLocal(`idx1`,c.i32_add(c.getLocal(`pBuff1`),c.i32_mul(c.getLocal(`i`),c.i32_const(o)))),c.setLocal(`idx2`,c.i32_add(c.getLocal(`pBuff2`),c.i32_mul(c.getLocal(`i`),c.i32_const(o)))),c.call(n+`_add`,c.getLocal(`idx1`),c.getLocal(`idx2`),u),c.call(i,c.getLocal(`idx2`),c.getLocal(`pShiftToM`),c.getLocal(`idx2`)),c.call(n+`_add`,c.getLocal(`idx1`),c.getLocal(`idx2`),c.getLocal(`idx2`)),c.call(i,c.getLocal(`idx2`),l,c.getLocal(`idx2`)),c.call(n+`_copy`,u,c.getLocal(`idx1`)),c.call(r+`_mul`,l,c.getLocal(`inc`),l),c.setLocal(`i`,c.i32_add(c.getLocal(`i`),c.i32_const(1))),c.br(0))))}function I(){let s=e.addFunction(t+`_fftJoinExtInv`);s.addParam(`pBuff1`,`i32`),s.addParam(`pBuff2`,`i32`),s.addParam(`n`,`i32`),s.addParam(`first`,`i32`),s.addParam(`inc`,`i32`),s.addParam(`totalBits`,`i32`),s.addLocal(`idx1`,`i32`),s.addLocal(`idx2`,`i32`),s.addLocal(`i`,`i32`),s.addLocal(`pShiftToM`,`i32`),s.addLocal(`pSConst`,`i32`);let c=s.getCodeBuilder(),l=c.i32_const(e.alloc(a)),u=c.i32_const(e.alloc(o));s.addCode(c.setLocal(`pShiftToM`,c.i32_add(c.i32_const(S),c.i32_mul(c.getLocal(`totalBits`),c.i32_const(a)))),c.setLocal(`pSConst`,c.i32_add(c.i32_const(C),c.i32_mul(c.getLocal(`totalBits`),c.i32_const(a)))),c.call(r+`_copy`,c.getLocal(`first`),l),c.setLocal(`i`,c.i32_const(0)),c.block(c.loop(c.br_if(1,c.i32_eq(c.getLocal(`i`),c.getLocal(`n`))),c.setLocal(`idx1`,c.i32_add(c.getLocal(`pBuff1`),c.i32_mul(c.getLocal(`i`),c.i32_const(o)))),c.setLocal(`idx2`,c.i32_add(c.getLocal(`pBuff2`),c.i32_mul(c.getLocal(`i`),c.i32_const(o)))),c.call(i,c.getLocal(`idx2`),l,u),c.call(n+`_sub`,c.getLocal(`idx1`),u,c.getLocal(`idx2`)),c.call(i,c.getLocal(`idx2`),c.getLocal(`pSConst`),c.getLocal(`idx2`)),c.call(i,c.getLocal(`idx1`),c.getLocal(`pShiftToM`),c.getLocal(`idx1`)),c.call(n+`_sub`,u,c.getLocal(`idx1`),c.getLocal(`idx1`)),c.call(i,c.getLocal(`idx1`),c.getLocal(`pSConst`),c.getLocal(`idx1`)),c.call(r+`_mul`,l,c.getLocal(`inc`),l),c.setLocal(`i`,c.i32_add(c.getLocal(`i`),c.i32_const(1))),c.br(0))))}function L(){let s=e.addFunction(t+`_prepareLagrangeEvaluation`);s.addParam(`pBuff1`,`i32`),s.addParam(`pBuff2`,`i32`),s.addParam(`n`,`i32`),s.addParam(`first`,`i32`),s.addParam(`inc`,`i32`),s.addParam(`totalBits`,`i32`),s.addLocal(`idx1`,`i32`),s.addLocal(`idx2`,`i32`),s.addLocal(`i`,`i32`),s.addLocal(`pShiftToM`,`i32`),s.addLocal(`pSConst`,`i32`);let c=s.getCodeBuilder(),l=c.i32_const(e.alloc(a)),u=c.i32_const(e.alloc(o));s.addCode(c.setLocal(`pShiftToM`,c.i32_add(c.i32_const(S),c.i32_mul(c.getLocal(`totalBits`),c.i32_const(a)))),c.setLocal(`pSConst`,c.i32_add(c.i32_const(C),c.i32_mul(c.getLocal(`totalBits`),c.i32_const(a)))),c.call(r+`_copy`,c.getLocal(`first`),l),c.setLocal(`i`,c.i32_const(0)),c.block(c.loop(c.br_if(1,c.i32_eq(c.getLocal(`i`),c.getLocal(`n`))),c.setLocal(`idx1`,c.i32_add(c.getLocal(`pBuff1`),c.i32_mul(c.getLocal(`i`),c.i32_const(o)))),c.setLocal(`idx2`,c.i32_add(c.getLocal(`pBuff2`),c.i32_mul(c.getLocal(`i`),c.i32_const(o)))),c.call(i,c.getLocal(`idx1`),c.getLocal(`pShiftToM`),u),c.call(n+`_sub`,c.getLocal(`idx2`),u,u),c.call(n+`_sub`,c.getLocal(`idx1`),c.getLocal(`idx2`),c.getLocal(`idx2`)),c.call(i,u,c.getLocal(`pSConst`),c.getLocal(`idx1`)),c.call(i,c.getLocal(`idx2`),l,c.getLocal(`idx2`)),c.call(r+`_mul`,l,c.getLocal(`inc`),l),c.setLocal(`i`,c.i32_add(c.getLocal(`i`),c.i32_const(1))),c.br(0))))}function ee(){let s=e.addFunction(t+`_fftMix`);s.addParam(`pBuff`,`i32`),s.addParam(`n`,`i32`),s.addParam(`exp`,`i32`),s.addLocal(`nGroups`,`i32`),s.addLocal(`nPerGroup`,`i32`),s.addLocal(`nPerGroupDiv2`,`i32`),s.addLocal(`pairOffset`,`i32`),s.addLocal(`idx1`,`i32`),s.addLocal(`idx2`,`i32`),s.addLocal(`i`,`i32`),s.addLocal(`j`,`i32`),s.addLocal(`pwm`,`i32`);let c=s.getCodeBuilder(),l=c.i32_const(e.alloc(a)),u=c.i32_const(e.alloc(o)),d=c.i32_const(e.alloc(o));s.addCode(c.setLocal(`nPerGroup`,c.i32_shl(c.i32_const(1),c.getLocal(`exp`))),c.setLocal(`nPerGroupDiv2`,c.i32_shr_u(c.getLocal(`nPerGroup`),c.i32_const(1))),c.setLocal(`nGroups`,c.i32_shr_u(c.getLocal(`n`),c.getLocal(`exp`))),c.setLocal(`pairOffset`,c.i32_mul(c.getLocal(`nPerGroupDiv2`),c.i32_const(o))),c.setLocal(`pwm`,c.i32_add(c.i32_const(h),c.i32_mul(c.getLocal(`exp`),c.i32_const(a)))),c.setLocal(`i`,c.i32_const(0)),c.block(c.loop(c.br_if(1,c.i32_eq(c.getLocal(`i`),c.getLocal(`nGroups`))),c.call(r+`_one`,l),c.setLocal(`j`,c.i32_const(0)),c.block(c.loop(c.br_if(1,c.i32_eq(c.getLocal(`j`),c.getLocal(`nPerGroupDiv2`))),c.setLocal(`idx1`,c.i32_add(c.getLocal(`pBuff`),c.i32_mul(c.i32_add(c.i32_mul(c.getLocal(`i`),c.getLocal(`nPerGroup`)),c.getLocal(`j`)),c.i32_const(o)))),c.setLocal(`idx2`,c.i32_add(c.getLocal(`idx1`),c.getLocal(`pairOffset`))),c.call(i,c.getLocal(`idx2`),l,u),c.call(n+`_copy`,c.getLocal(`idx1`),d),c.call(n+`_add`,d,u,c.getLocal(`idx1`)),c.call(n+`_sub`,d,u,c.getLocal(`idx2`)),c.call(r+`_mul`,l,c.getLocal(`pwm`),l),c.setLocal(`j`,c.i32_add(c.getLocal(`j`),c.i32_const(1))),c.br(0))),c.setLocal(`i`,c.i32_add(c.getLocal(`i`),c.i32_const(1))),c.br(0))))}function R(){let r=e.addFunction(t+`_fftFinal`);r.addParam(`pBuff`,`i32`),r.addParam(`n`,`i32`),r.addParam(`factor`,`i32`),r.addLocal(`idx1`,`i32`),r.addLocal(`idx2`,`i32`),r.addLocal(`i`,`i32`),r.addLocal(`ndiv2`,`i32`);let a=r.getCodeBuilder(),s=a.i32_const(e.alloc(o));r.addCode(a.setLocal(`ndiv2`,a.i32_shr_u(a.getLocal(`n`),a.i32_const(1))),a.if(a.i32_and(a.getLocal(`n`),a.i32_const(1)),a.call(i,a.i32_add(a.getLocal(`pBuff`),a.i32_mul(a.getLocal(`ndiv2`),a.i32_const(o))),a.getLocal(`factor`),a.i32_add(a.getLocal(`pBuff`),a.i32_mul(a.getLocal(`ndiv2`),a.i32_const(o))))),a.setLocal(`i`,a.i32_const(0)),a.block(a.loop(a.br_if(1,a.i32_ge_u(a.getLocal(`i`),a.getLocal(`ndiv2`))),a.setLocal(`idx1`,a.i32_add(a.getLocal(`pBuff`),a.i32_mul(a.getLocal(`i`),a.i32_const(o)))),a.setLocal(`idx2`,a.i32_add(a.getLocal(`pBuff`),a.i32_mul(a.i32_sub(a.i32_sub(a.getLocal(`n`),a.i32_const(1)),a.getLocal(`i`)),a.i32_const(o)))),a.call(i,a.getLocal(`idx2`),a.getLocal(`factor`),s),a.call(i,a.getLocal(`idx1`),a.getLocal(`factor`),a.getLocal(`idx2`)),a.call(n+`_copy`,s,a.getLocal(`idx1`)),a.setLocal(`i`,a.i32_add(a.getLocal(`i`),a.i32_const(1))),a.br(0))))}N(),M(),j(),A(),D(),O(),k(),P(),F(),I(),ee(),R(),L(),e.exportFunction(t+`__reversePermutation`),e.exportFunction(t+`_fft`),e.exportFunction(t+`_ifft`),e.exportFunction(t+`_rawfft`),e.exportFunction(t+`_fftJoin`),e.exportFunction(t+`_fftJoinExt`),e.exportFunction(t+`_fftJoinExtInv`),e.exportFunction(t+`_fftMix`),e.exportFunction(t+`_fftFinal`),e.exportFunction(t+`_prepareLagrangeEvaluation`)}var mt=s((()=>{Qe(),be()}));function ht(e,t,n){let r=e.modules[n].n64*8;function i(){let i=e.addFunction(t+`_zero`);i.addParam(`px`,`i32`),i.addParam(`n`,`i32`),i.addLocal(`lastp`,`i32`),i.addLocal(`p`,`i32`);let a=i.getCodeBuilder();i.addCode(a.setLocal(`p`,a.getLocal(`px`)),a.setLocal(`lastp`,a.i32_add(a.getLocal(`px`),a.i32_mul(a.getLocal(`n`),a.i32_const(r)))),a.block(a.loop(a.br_if(1,a.i32_eq(a.getLocal(`p`),a.getLocal(`lastp`))),a.call(n+`_zero`,a.getLocal(`p`)),a.setLocal(`p`,a.i32_add(a.getLocal(`p`),a.i32_const(r))),a.br(0))))}function a(){let i=e.addFunction(t+`_constructLC`);i.addParam(`ppolynomials`,`i32`),i.addParam(`psignals`,`i32`),i.addParam(`nSignals`,`i32`),i.addParam(`pres`,`i32`),i.addLocal(`i`,`i32`),i.addLocal(`j`,`i32`),i.addLocal(`pp`,`i32`),i.addLocal(`ps`,`i32`),i.addLocal(`pd`,`i32`),i.addLocal(`ncoefs`,`i32`);let a=i.getCodeBuilder(),o=a.i32_const(e.alloc(r));i.addCode(a.setLocal(`i`,a.i32_const(0)),a.setLocal(`pp`,a.getLocal(`ppolynomials`)),a.setLocal(`ps`,a.getLocal(`psignals`)),a.block(a.loop(a.br_if(1,a.i32_eq(a.getLocal(`i`),a.getLocal(`nSignals`))),a.setLocal(`ncoefs`,a.i32_load(a.getLocal(`pp`))),a.setLocal(`pp`,a.i32_add(a.getLocal(`pp`),a.i32_const(4))),a.setLocal(`j`,a.i32_const(0)),a.block(a.loop(a.br_if(1,a.i32_eq(a.getLocal(`j`),a.getLocal(`ncoefs`))),a.setLocal(`pd`,a.i32_add(a.getLocal(`pres`),a.i32_mul(a.i32_load(a.getLocal(`pp`)),a.i32_const(r)))),a.setLocal(`pp`,a.i32_add(a.getLocal(`pp`),a.i32_const(4))),a.call(n+`_mul`,a.getLocal(`ps`),a.getLocal(`pp`),o),a.call(n+`_add`,o,a.getLocal(`pd`),a.getLocal(`pd`)),a.setLocal(`pp`,a.i32_add(a.getLocal(`pp`),a.i32_const(r))),a.setLocal(`j`,a.i32_add(a.getLocal(`j`),a.i32_const(1))),a.br(0))),a.setLocal(`ps`,a.i32_add(a.getLocal(`ps`),a.i32_const(r))),a.setLocal(`i`,a.i32_add(a.getLocal(`i`),a.i32_const(1))),a.br(0))))}return i(),a(),e.exportFunction(t+`_zero`),e.exportFunction(t+`_constructLC`),t}var gt=s((()=>{}));function _t(e,t,n){let r=e.modules[n].n64*8;function i(){let i=e.addFunction(t+`_buildABC`);i.addParam(`pCoefs`,`i32`),i.addParam(`nCoefs`,`i32`),i.addParam(`pWitness`,`i32`),i.addParam(`pA`,`i32`),i.addParam(`pB`,`i32`),i.addParam(`pC`,`i32`),i.addParam(`offsetOut`,`i32`),i.addParam(`nOut`,`i32`),i.addParam(`offsetWitness`,`i32`),i.addParam(`nWitness`,`i32`),i.addLocal(`it`,`i32`),i.addLocal(`ita`,`i32`),i.addLocal(`itb`,`i32`),i.addLocal(`last`,`i32`),i.addLocal(`m`,`i32`),i.addLocal(`c`,`i32`),i.addLocal(`s`,`i32`),i.addLocal(`pOut`,`i32`);let a=i.getCodeBuilder(),o=a.i32_const(e.alloc(r));i.addCode(a.setLocal(`ita`,a.getLocal(`pA`)),a.setLocal(`itb`,a.getLocal(`pB`)),a.setLocal(`last`,a.i32_add(a.getLocal(`pA`),a.i32_mul(a.getLocal(`nOut`),a.i32_const(r)))),a.block(a.loop(a.br_if(1,a.i32_eq(a.getLocal(`ita`),a.getLocal(`last`))),a.call(n+`_zero`,a.getLocal(`ita`)),a.call(n+`_zero`,a.getLocal(`itb`)),a.setLocal(`ita`,a.i32_add(a.getLocal(`ita`),a.i32_const(r))),a.setLocal(`itb`,a.i32_add(a.getLocal(`itb`),a.i32_const(r))),a.br(0))),a.setLocal(`it`,a.getLocal(`pCoefs`)),a.setLocal(`last`,a.i32_add(a.getLocal(`pCoefs`),a.i32_mul(a.getLocal(`nCoefs`),a.i32_const(r+12)))),a.block(a.loop(a.br_if(1,a.i32_eq(a.getLocal(`it`),a.getLocal(`last`))),a.setLocal(`s`,a.i32_load(a.getLocal(`it`),8)),a.if(a.i32_or(a.i32_lt_u(a.getLocal(`s`),a.getLocal(`offsetWitness`)),a.i32_ge_u(a.getLocal(`s`),a.i32_add(a.getLocal(`offsetWitness`),a.getLocal(`nWitness`)))),[...a.setLocal(`it`,a.i32_add(a.getLocal(`it`),a.i32_const(r+12))),...a.br(1)]),a.setLocal(`m`,a.i32_load(a.getLocal(`it`))),a.if(a.i32_eq(a.getLocal(`m`),a.i32_const(0)),a.setLocal(`pOut`,a.getLocal(`pA`)),a.if(a.i32_eq(a.getLocal(`m`),a.i32_const(1)),a.setLocal(`pOut`,a.getLocal(`pB`)),[...a.setLocal(`it`,a.i32_add(a.getLocal(`it`),a.i32_const(r+12))),...a.br(1)])),a.setLocal(`c`,a.i32_load(a.getLocal(`it`),4)),a.if(a.i32_or(a.i32_lt_u(a.getLocal(`c`),a.getLocal(`offsetOut`)),a.i32_ge_u(a.getLocal(`c`),a.i32_add(a.getLocal(`offsetOut`),a.getLocal(`nOut`)))),[...a.setLocal(`it`,a.i32_add(a.getLocal(`it`),a.i32_const(r+12))),...a.br(1)]),a.setLocal(`pOut`,a.i32_add(a.getLocal(`pOut`),a.i32_mul(a.i32_sub(a.getLocal(`c`),a.getLocal(`offsetOut`)),a.i32_const(r)))),a.call(n+`_mul`,a.i32_add(a.getLocal(`pWitness`),a.i32_mul(a.i32_sub(a.getLocal(`s`),a.getLocal(`offsetWitness`)),a.i32_const(r))),a.i32_add(a.getLocal(`it`),a.i32_const(12)),o),a.call(n+`_add`,a.getLocal(`pOut`),o,a.getLocal(`pOut`)),a.setLocal(`it`,a.i32_add(a.getLocal(`it`),a.i32_const(r+12))),a.br(0))),a.setLocal(`ita`,a.getLocal(`pA`)),a.setLocal(`itb`,a.getLocal(`pB`)),a.setLocal(`it`,a.getLocal(`pC`)),a.setLocal(`last`,a.i32_add(a.getLocal(`pA`),a.i32_mul(a.getLocal(`nOut`),a.i32_const(r)))),a.block(a.loop(a.br_if(1,a.i32_eq(a.getLocal(`ita`),a.getLocal(`last`))),a.call(n+`_mul`,a.getLocal(`ita`),a.getLocal(`itb`),a.getLocal(`it`)),a.setLocal(`ita`,a.i32_add(a.getLocal(`ita`),a.i32_const(r))),a.setLocal(`itb`,a.i32_add(a.getLocal(`itb`),a.i32_const(r))),a.setLocal(`it`,a.i32_add(a.getLocal(`it`),a.i32_const(r))),a.br(0))))}function a(){let i=e.addFunction(t+`_joinABC`);i.addParam(`pA`,`i32`),i.addParam(`pB`,`i32`),i.addParam(`pC`,`i32`),i.addParam(`n`,`i32`),i.addParam(`pP`,`i32`),i.addLocal(`ita`,`i32`),i.addLocal(`itb`,`i32`),i.addLocal(`itc`,`i32`),i.addLocal(`itp`,`i32`),i.addLocal(`last`,`i32`);let a=i.getCodeBuilder(),o=a.i32_const(e.alloc(r));i.addCode(a.setLocal(`ita`,a.getLocal(`pA`)),a.setLocal(`itb`,a.getLocal(`pB`)),a.setLocal(`itc`,a.getLocal(`pC`)),a.setLocal(`itp`,a.getLocal(`pP`)),a.setLocal(`last`,a.i32_add(a.getLocal(`pA`),a.i32_mul(a.getLocal(`n`),a.i32_const(r)))),a.block(a.loop(a.br_if(1,a.i32_eq(a.getLocal(`ita`),a.getLocal(`last`))),a.call(n+`_mul`,a.getLocal(`ita`),a.getLocal(`itb`),o),a.call(n+`_sub`,o,a.getLocal(`itc`),a.getLocal(`itp`)),a.setLocal(`ita`,a.i32_add(a.getLocal(`ita`),a.i32_const(r))),a.setLocal(`itb`,a.i32_add(a.getLocal(`itb`),a.i32_const(r))),a.setLocal(`itc`,a.i32_add(a.getLocal(`itc`),a.i32_const(r))),a.setLocal(`itp`,a.i32_add(a.getLocal(`itp`),a.i32_const(r))),a.br(0))))}function o(){let i=e.addFunction(t+`_batchAdd`);i.addParam(`pa`,`i32`),i.addParam(`pb`,`i32`),i.addParam(`n`,`i32`),i.addParam(`pr`,`i32`),i.addLocal(`ita`,`i32`),i.addLocal(`itb`,`i32`),i.addLocal(`itr`,`i32`),i.addLocal(`last`,`i32`);let a=i.getCodeBuilder();i.addCode(a.setLocal(`ita`,a.getLocal(`pa`)),a.setLocal(`itb`,a.getLocal(`pb`)),a.setLocal(`itr`,a.getLocal(`pr`)),a.setLocal(`last`,a.i32_add(a.getLocal(`pa`),a.i32_mul(a.getLocal(`n`),a.i32_const(r)))),a.block(a.loop(a.br_if(1,a.i32_eq(a.getLocal(`ita`),a.getLocal(`last`))),a.call(n+`_add`,a.getLocal(`ita`),a.getLocal(`itb`),a.getLocal(`itr`)),a.setLocal(`ita`,a.i32_add(a.getLocal(`ita`),a.i32_const(r))),a.setLocal(`itb`,a.i32_add(a.getLocal(`itb`),a.i32_const(r))),a.setLocal(`itr`,a.i32_add(a.getLocal(`itr`),a.i32_const(r))),a.br(0))))}return i(),a(),o(),e.exportFunction(t+`_buildABC`),e.exportFunction(t+`_joinABC`),e.exportFunction(t+`_batchAdd`),t}var vt=s((()=>{}));function yt(e,t,n,r,i,a,o,s){let c=e.addFunction(t);c.addParam(`pIn`,`i32`),c.addParam(`n`,`i32`),c.addParam(`pFirst`,`i32`),c.addParam(`pInc`,`i32`),c.addParam(`pOut`,`i32`),c.addLocal(`pOldFree`,`i32`),c.addLocal(`i`,`i32`),c.addLocal(`pFrom`,`i32`),c.addLocal(`pTo`,`i32`);let l=c.getCodeBuilder(),u=l.i32_const(e.alloc(o));c.addCode(l.setLocal(`pFrom`,l.getLocal(`pIn`)),l.setLocal(`pTo`,l.getLocal(`pOut`))),c.addCode(l.call(r+`_copy`,l.getLocal(`pFirst`),u)),c.addCode(l.setLocal(`i`,l.i32_const(0)),l.block(l.loop(l.br_if(1,l.i32_eq(l.getLocal(`i`),l.getLocal(`n`))),l.call(s,l.getLocal(`pFrom`),u,l.getLocal(`pTo`)),l.setLocal(`pFrom`,l.i32_add(l.getLocal(`pFrom`),l.i32_const(i))),l.setLocal(`pTo`,l.i32_add(l.getLocal(`pTo`),l.i32_const(a))),l.call(r+`_mul`,u,l.getLocal(`pInc`),u),l.setLocal(`i`,l.i32_add(l.getLocal(`i`),l.i32_const(1))),l.br(0)))),e.exportFunction(t)}var bt=s((()=>{}));function xt(e,t){let n=t||`bn128`;if(e.modules[n])return n;let r=21888242871839275222246405745257275088696311157297823662689037894645226208583n,i=21888242871839275222246405745257275088548364400416034343698204186575808495617n,a=Math.floor((Be(r-1n)-1)/64)+1,o=a*8,s=o,c=o,l=c*2,u=c*12,d=e.alloc(z(i,s)),f=$e(e,r,`f1m`);tt(e,i,`fr`,`frm`);let p=e.alloc(z(y(3n),c)),m=dt(e,`g1m`,`f1m`,p);pt(e,`frm`,`frm`,`frm`,`frm_mul`),ht(e,`pol`,`frm`),_t(e,`qap`,`frm`);let h=rt(e,`f1m_neg`,`f2m`,`f1m`),g=e.alloc([...z(y(19485874751759354771024239261021720505790618469301721065564631296452457478373n),c),...z(y(266929791119991161246907387137283842545076965332900288569378510910307636690n),c)]),_=dt(e,`g2m`,`f2m`,g);function v(t,n){let r=e.addFunction(t);r.addParam(`pG`,`i32`),r.addParam(`pFr`,`i32`),r.addParam(`pr`,`i32`);let i=r.getCodeBuilder(),a=i.i32_const(e.alloc(o));r.addCode(i.call(`frm_fromMontgomery`,i.getLocal(`pFr`),a),i.call(n,i.getLocal(`pG`),a,i.i32_const(o),i.getLocal(`pr`))),e.exportFunction(t)}v(`g1m_timesFr`,`g1m_timesScalar`),pt(e,`g1m`,`g1m`,`frm`,`g1m_timesFr`),v(`g2m_timesFr`,`g2m_timesScalar`),pt(e,`g2m`,`g2m`,`frm`,`g2m_timesFr`),v(`g1m_timesFrAffine`,`g1m_timesScalarAffine`),v(`g2m_timesFrAffine`,`g2m_timesScalarAffine`),yt(e,`frm_batchApplyKey`,`fmr`,`frm`,o,o,o,`frm_mul`),yt(e,`g1m_batchApplyKey`,`g1m`,`frm`,o*3,o*3,o,`g1m_timesFr`),yt(e,`g1m_batchApplyKeyMixed`,`g1m`,`frm`,o*2,o*3,o,`g1m_timesFrAffine`),yt(e,`g2m_batchApplyKey`,`g2m`,`frm`,o*2*3,o*3*2,o,`g2m_timesFr`),yt(e,`g2m_batchApplyKeyMixed`,`g2m`,`frm`,o*2*2,o*3*2,o,`g2m_timesFrAffine`);function y(e){return BigInt(e)*(1n<e+(t==0?0:1),0)+te+1,re=6*o,ie=3*o*2+ne*R;e.modules[n]={n64:a,pG1gen:x,pG1zero:C,pG1b:p,pG2gen:T,pG2zero:D,pG2b:g,pq:e.modules.f1m.pq,pr:d,pOneT:O,prePSize:re,preQSize:ie,r:`21888242871839275222246405745257275088548364400416034343698204186575808495617`,q:`21888242871839275222246405745257275088696311157297823662689037894645226208583`};function ae(e){let t=e,n=[];for(;t>0n;){if(Ie(t)){let e=2-Number(t%4n);n.push(e),t-=BigInt(e)}else n.push(0);t>>=1n}return n}function oe(e){let t=e,n=[];for(;t>0n;)Ie(t)?n.push(1):n.push(0),t>>=1n;return n}function se(){let t=e.addFunction(n+`_prepareG1`);t.addParam(`pP`,`i32`),t.addParam(`ppreP`,`i32`);let r=t.getCodeBuilder();t.addCode(r.call(m+`_normalize`,r.getLocal(`pP`),r.getLocal(`ppreP`)))}function ce(){let t=e.addFunction(n+`_prepAddStep`);t.addParam(`pQ`,`i32`),t.addParam(`pR`,`i32`),t.addParam(`pCoef`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`pQ`),a=r.i32_add(r.getLocal(`pQ`),r.i32_const(l)),o=r.getLocal(`pR`),s=r.i32_add(r.getLocal(`pR`),r.i32_const(l)),c=r.i32_add(r.getLocal(`pR`),r.i32_const(2*l)),u=r.getLocal(`pCoef`),d=r.i32_add(r.getLocal(`pCoef`),r.i32_const(l)),f=r.i32_add(r.getLocal(`pCoef`),r.i32_const(2*l)),p=d,m=r.i32_const(e.alloc(l)),g=r.i32_const(e.alloc(l)),_=r.i32_const(e.alloc(l)),v=r.i32_const(e.alloc(l)),y=r.i32_const(e.alloc(l)),b=r.i32_const(e.alloc(l)),x=r.i32_const(e.alloc(l));t.addCode(r.call(h+`_mul`,i,c,p),r.call(h+`_sub`,o,p,p),r.call(h+`_mul`,a,c,m),r.call(h+`_sub`,s,m,m),r.call(h+`_square`,p,g),r.call(h+`_square`,m,_),r.call(h+`_mul`,p,g,v),r.call(h+`_mul`,o,g,y),r.call(h+`_add`,y,y,x),r.call(h+`_mul`,c,_,b),r.call(h+`_add`,v,b,b),r.call(h+`_sub`,b,x,b),r.call(h+`_mul`,p,b,o),r.call(h+`_mul`,v,s,s),r.call(h+`_sub`,y,b,x),r.call(h+`_mul`,m,x,x),r.call(h+`_sub`,x,s,s),r.call(h+`_mul`,c,v,c),r.call(h+`_mul`,p,a,x),r.call(h+`_mul`,m,i,u),r.call(h+`_sub`,u,x,u),r.call(h+`_mul`,u,r.i32_const(j),u),r.call(h+`_neg`,m,f))}function le(){let t=e.addFunction(n+`_prepDblStep`);t.addParam(`pR`,`i32`),t.addParam(`pCoef`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`pR`),a=r.i32_add(r.getLocal(`pR`),r.i32_const(l)),o=r.i32_add(r.getLocal(`pR`),r.i32_const(2*l)),s=r.getLocal(`pCoef`),c=r.i32_add(r.getLocal(`pCoef`),r.i32_const(l)),u=r.i32_add(r.getLocal(`pCoef`),r.i32_const(2*l)),d=r.i32_const(e.alloc(l)),f=r.i32_const(e.alloc(l)),p=r.i32_const(e.alloc(l)),m=r.i32_const(e.alloc(l)),g=r.i32_const(e.alloc(l)),_=r.i32_const(e.alloc(l)),v=r.i32_const(e.alloc(l)),y=r.i32_const(e.alloc(l)),b=r.i32_const(e.alloc(l)),x=r.i32_const(e.alloc(l)),S=r.i32_const(e.alloc(l)),C=r.i32_const(e.alloc(l));t.addCode(r.call(h+`_mul`,a,r.i32_const(A),d),r.call(h+`_mul`,i,d,d),r.call(h+`_square`,a,f),r.call(h+`_square`,o,p),r.call(h+`_add`,p,p,m),r.call(h+`_add`,m,p,m),r.call(h+`_mul`,r.i32_const(M),m,g),r.call(h+`_add`,g,g,_),r.call(h+`_add`,g,_,_),r.call(h+`_add`,f,_,v),r.call(h+`_mul`,v,r.i32_const(A),v),r.call(h+`_add`,f,p,C),r.call(h+`_add`,a,o,y),r.call(h+`_square`,y,y),r.call(h+`_sub`,y,C,y),r.call(h+`_sub`,g,f,b),r.call(h+`_square`,i,x),r.call(h+`_square`,g,S),r.call(h+`_sub`,f,_,C),r.call(h+`_mul`,d,C,i),r.call(h+`_add`,S,S,C),r.call(h+`_add`,S,C,C),r.call(h+`_square`,v,a),r.call(h+`_sub`,a,C,a),r.call(h+`_mul`,f,y,o),r.call(h+`_mul`,r.i32_const(j),b,s),r.call(h+`_neg`,y,c),r.call(h+`_add`,x,x,u),r.call(h+`_add`,x,u,u))}function ue(){let t=e.addFunction(n+`_mulByQ`);t.addParam(`p1`,`i32`),t.addParam(`pr`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`p1`),a=r.i32_add(r.getLocal(`p1`),r.i32_const(l)),o=r.i32_add(r.getLocal(`p1`),r.i32_const(l*2)),s=r.getLocal(`pr`),u=r.i32_add(r.getLocal(`pr`),r.i32_const(l)),d=r.i32_add(r.getLocal(`pr`),r.i32_const(l*2)),f=r.i32_const(e.alloc([...z(y(`21575463638280843010398324269430826099269044274347216827212613867836435027261`),c),...z(y(`10307601595873709700152284273816112264069230130616436755625194854815875713954`),c)])),p=r.i32_const(e.alloc([...z(y(`2821565182194536844548159561693502659359617185244120367078079554186484126554`),c),...z(y(`3505843767911556378687030309984248845540243509899259641013678093033130930403`),c)]));t.addCode(r.call(h+`_conjugate`,i,s),r.call(h+`_mul`,f,s,s),r.call(h+`_conjugate`,a,u),r.call(h+`_mul`,p,u,u),r.call(h+`_conjugate`,o,d))}function de(){ue();let t=e.addFunction(n+`_prepareG2`);t.addParam(`pQ`,`i32`),t.addParam(`ppreQ`,`i32`),t.addLocal(`pCoef`,`i32`),t.addLocal(`i`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`pQ`),a=e.alloc(l*3),o=r.i32_const(a),s=r.i32_const(a),c=r.i32_const(a+l),u=r.i32_const(a+2*l),d=r.i32_add(r.getLocal(`ppreQ`),r.i32_const(0)),f=r.i32_add(r.getLocal(`ppreQ`),r.i32_const(l)),p=e.alloc(l*3),m=r.i32_const(p),g=e.alloc(l*3),v=r.i32_const(g),y=r.i32_const(g+l);t.addCode(r.call(_+`_normalize`,i,d),r.call(h+`_copy`,d,s),r.call(h+`_copy`,f,c),r.call(h+`_one`,u)),t.addCode(r.setLocal(`pCoef`,r.i32_add(r.getLocal(`ppreQ`),r.i32_const(l*3))),r.setLocal(`i`,r.i32_const(L.length-2)),r.block(r.loop(r.call(n+`_prepDblStep`,o,r.getLocal(`pCoef`)),r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(R))),r.if(r.i32_load8_s(r.getLocal(`i`),ee),[...r.call(n+`_prepAddStep`,d,o,r.getLocal(`pCoef`)),...r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(R)))]),r.br_if(1,r.i32_eqz(r.getLocal(`i`))),r.setLocal(`i`,r.i32_sub(r.getLocal(`i`),r.i32_const(1))),r.br(0)))),t.addCode(r.call(n+`_mulByQ`,d,m),r.call(n+`_mulByQ`,m,v)),t.addCode(r.call(h+`_neg`,y,y),r.call(n+`_prepAddStep`,m,o,r.getLocal(`pCoef`)),r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(R))),r.call(n+`_prepAddStep`,v,o,r.getLocal(`pCoef`)),r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(R))))}function fe(){let t=e.addFunction(n+`__mulBy024Old`);t.addParam(`pEll0`,`i32`),t.addParam(`pEllVW`,`i32`),t.addParam(`pEllVV`,`i32`),t.addParam(`pR`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`pEll0`),a=r.getLocal(`pEllVV`),o=r.getLocal(`pEllVW`),s=r.getLocal(`pR`),c=e.alloc(u),d=r.i32_const(c),f=r.i32_const(c),p=r.i32_const(c+l),m=r.i32_const(c+l*2),g=r.i32_const(c+l*3),_=r.i32_const(c+l*4),v=r.i32_const(c+l*5);t.addCode(r.call(h+`_copy`,i,f),r.call(h+`_zero`,p),r.call(h+`_copy`,a,m),r.call(h+`_zero`,g),r.call(h+`_copy`,o,_),r.call(h+`_zero`,v),r.call(I+`_mul`,d,s,s))}function pe(){let t=e.addFunction(n+`__mulBy024`);t.addParam(`pEll0`,`i32`),t.addParam(`pEllVW`,`i32`),t.addParam(`pEllVV`,`i32`),t.addParam(`pR`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`pEll0`),a=r.getLocal(`pEllVV`),s=r.getLocal(`pEllVW`),c=r.getLocal(`pR`),u=r.i32_add(r.getLocal(`pR`),r.i32_const(2*o)),d=r.i32_add(r.getLocal(`pR`),r.i32_const(4*o)),f=r.i32_add(r.getLocal(`pR`),r.i32_const(6*o)),p=r.i32_add(r.getLocal(`pR`),r.i32_const(8*o)),m=r.i32_add(r.getLocal(`pR`),r.i32_const(10*o)),g=r.i32_const(e.alloc(l)),_=r.i32_const(e.alloc(l)),v=r.i32_const(e.alloc(l)),y=r.i32_const(e.alloc(l)),b=r.i32_const(e.alloc(l)),x=r.i32_const(e.alloc(l)),S=r.i32_const(e.alloc(l)),C=r.i32_const(e.alloc(l)),w=r.i32_const(e.alloc(l)),T=r.i32_const(e.alloc(l)),E=r.i32_const(e.alloc(l));t.addCode(r.call(h+`_mul`,c,i,S),r.call(h+`_mul`,d,a,C),r.call(h+`_mul`,p,s,w),r.call(h+`_add`,c,p,v),r.call(h+`_add`,c,d,_),r.call(h+`_add`,u,f,y),r.call(h+`_add`,y,m,y),r.call(h+`_mul`,u,a,T),r.call(h+`_add`,T,w,b),r.call(h+`_mul`,r.i32_const(k),b,x),r.call(h+`_add`,x,S,c),r.call(h+`_mul`,m,s,b),r.call(h+`_add`,T,b,T),r.call(h+`_add`,b,C,b),r.call(h+`_mul`,r.i32_const(k),b,x),r.call(h+`_mul`,u,i,b),r.call(h+`_add`,T,b,T),r.call(h+`_add`,x,b,u),r.call(h+`_add`,i,a,g),r.call(h+`_mul`,_,g,b),r.call(h+`_add`,S,C,E),r.call(h+`_sub`,b,E,b),r.call(h+`_mul`,f,s,x),r.call(h+`_add`,T,x,T),r.call(h+`_add`,d,p,g),r.call(h+`_add`,b,x,d),r.call(h+`_add`,a,s,_),r.call(h+`_mul`,_,g,b),r.call(h+`_add`,C,w,E),r.call(h+`_sub`,b,E,b),r.call(h+`_mul`,r.i32_const(k),b,x),r.call(h+`_mul`,f,i,b),r.call(h+`_add`,T,b,T),r.call(h+`_add`,x,b,f),r.call(h+`_mul`,m,a,b),r.call(h+`_add`,T,b,T),r.call(h+`_mul`,r.i32_const(k),b,x),r.call(h+`_add`,i,s,g),r.call(h+`_mul`,v,g,b),r.call(h+`_add`,S,w,E),r.call(h+`_sub`,b,E,b),r.call(h+`_add`,x,b,p),r.call(h+`_add`,i,a,g),r.call(h+`_add`,g,s,g),r.call(h+`_mul`,y,g,b),r.call(h+`_sub`,b,T,m))}function me(){let t=e.addFunction(n+`_millerLoop`);t.addParam(`ppreP`,`i32`),t.addParam(`ppreQ`,`i32`),t.addParam(`r`,`i32`),t.addLocal(`pCoef`,`i32`),t.addLocal(`i`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`ppreP`),a=r.i32_add(r.getLocal(`ppreP`),r.i32_const(c)),o=r.getLocal(`pCoef`),s=r.i32_add(r.getLocal(`pCoef`),r.i32_const(l)),u=r.i32_add(r.getLocal(`pCoef`),r.i32_const(2*l)),d=e.alloc(l),f=r.i32_const(d),p=e.alloc(l),m=r.i32_const(p),g=r.getLocal(`r`);t.addCode(r.call(I+`_one`,g),r.setLocal(`pCoef`,r.i32_add(r.getLocal(`ppreQ`),r.i32_const(l*3))),r.setLocal(`i`,r.i32_const(L.length-2)),r.block(r.loop(r.call(I+`_square`,g,g),r.call(h+`_mul1`,s,a,f),r.call(h+`_mul1`,u,i,m),r.call(n+`__mulBy024`,o,f,m,g),r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(R))),r.if(r.i32_load8_s(r.getLocal(`i`),ee),[...r.call(h+`_mul1`,s,a,f),...r.call(h+`_mul1`,u,i,m),...r.call(n+`__mulBy024`,o,f,m,g),...r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(R)))]),r.br_if(1,r.i32_eqz(r.getLocal(`i`))),r.setLocal(`i`,r.i32_sub(r.getLocal(`i`),r.i32_const(1))),r.br(0)))),t.addCode(r.call(h+`_mul1`,s,a,f),r.call(h+`_mul1`,u,i,m),r.call(n+`__mulBy024`,o,f,m,g),r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(R))),r.call(h+`_mul1`,s,a,f),r.call(h+`_mul1`,u,i,m),r.call(n+`__mulBy024`,o,f,m,g),r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(R))))}function he(t){let i=[[[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n]],[[1n,0n],[8376118865763821496583973867626364092589906065868298776909617916018768340080n,16469823323077808223889137241176536799009286646108169935659301613961712198316n],[21888242871839275220042445260109153167277707414472061641714758635765020556617n,0n],[11697423496358154304825782922584725312912383441159505038794027105778954184319n,303847389135065887422783454877609941456349188919719272345083954437860409601n],[21888242871839275220042445260109153167277707414472061641714758635765020556616n,0n],[3321304630594332808241809054958361220322477375291206261884409189760185844239n,5722266937896532885780051958958348231143373700109372999374820235121374419868n],[21888242871839275222246405745257275088696311157297823662689037894645226208582n,0n],[13512124006075453725662431877630910996106405091429524885779419978626457868503n,5418419548761466998357268504080738289687024511189653727029736280683514010267n],[2203960485148121921418603742825762020974279258880205651966n,0n],[10190819375481120917420622822672549775783927716138318623895010788866272024264n,21584395482704209334823622290379665147239961968378104390343953940207365798982n],[2203960485148121921418603742825762020974279258880205651967n,0n],[18566938241244942414004596690298913868373833782006617400804628704885040364344n,16165975933942742336466353786298926857552937457188450663314217659523851788715n]]],a=[[[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n]],[[1n,0n],[21575463638280843010398324269430826099269044274347216827212613867836435027261n,10307601595873709700152284273816112264069230130616436755625194854815875713954n],[21888242871839275220042445260109153167277707414472061641714758635765020556616n,0n],[3772000881919853776433695186713858239009073593817195771773381919316419345261n,2236595495967245188281701248203181795121068902605861227855261137820944008926n],[2203960485148121921418603742825762020974279258880205651966n,0n],[18429021223477853657660792034369865839114504446431234726392080002137598044644n,9344045779998320333812420223237981029506012124075525679208581902008406485703n]],[[1n,0n],[2581911344467009335267311115468803099551665605076196740867805258568234346338n,19937756971775647987995932169929341994314640652964949448313374472400716661030n],[2203960485148121921418603742825762020974279258880205651966n,0n],[5324479202449903542726783395506214481928257762400643279780343368557297135718n,16208900380737693084919495127334387981393726419856888799917914180988844123039n],[21888242871839275220042445260109153167277707414472061641714758635765020556616n,0n],[13981852324922362344252311234282257507216387789820983642040889267519694726527n,7629828391165209371577384193250820201684255241773809077146787135900891633097n]]],o=e.addFunction(n+`__frobeniusMap`+t);o.addParam(`x`,`i32`),o.addParam(`r`,`i32`);let s=o.getCodeBuilder();for(let n=0;n<6;n++){let r=n==0?s.getLocal(`x`):s.i32_add(s.getLocal(`x`),s.i32_const(n*l)),d=r,p=s.i32_add(s.getLocal(`x`),s.i32_const(n*l+c)),m=n==0?s.getLocal(`r`):s.i32_add(s.getLocal(`r`),s.i32_const(n*l)),g=m,_=s.i32_add(s.getLocal(`r`),s.i32_const(n*l+c)),v=u(i[Math.floor(n/3)][t%12],a[n%3][t%6]),b=e.alloc([...z(y(v[0]),32),...z(y(v[1]),32)]);t%2==1?o.addCode(s.call(f+`_copy`,d,g),s.call(f+`_neg`,p,_),s.call(h+`_mul`,m,s.i32_const(b),m)):o.addCode(s.call(h+`_mul`,r,s.i32_const(b),m))}function u(e,t){let n=BigInt(e[0]),i=BigInt(e[1]),a=BigInt(t[0]),o=BigInt(t[1]),s=[(n*a-i*o)%r,(n*o+i*a)%r];return Re(s[0])&&(s[0]+=r),s}}function ge(){let t=e.addFunction(n+`__finalExponentiationFirstChunk`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`x`),a=i,s=r.i32_add(i,r.i32_const(o*6)),c=r.getLocal(`r`),l=e.alloc(u),d=r.i32_const(l),f=d,p=r.i32_const(l+o*6),m=r.i32_const(e.alloc(u)),h=r.i32_const(e.alloc(u)),g=r.i32_const(e.alloc(u));t.addCode(r.call(P+`_copy`,a,f),r.call(P+`_neg`,s,p),r.call(I+`_inverse`,i,m),r.call(I+`_mul`,d,m,h),r.call(n+`__frobeniusMap2`,h,g),r.call(I+`_mul`,h,g,c))}function _e(){let t=e.addFunction(n+`__cyclotomicSquare`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`x`),a=r.i32_add(r.getLocal(`x`),r.i32_const(l)),o=r.i32_add(r.getLocal(`x`),r.i32_const(2*l)),s=r.i32_add(r.getLocal(`x`),r.i32_const(3*l)),c=r.i32_add(r.getLocal(`x`),r.i32_const(4*l)),u=r.i32_add(r.getLocal(`x`),r.i32_const(5*l)),d=r.getLocal(`r`),f=r.i32_add(r.getLocal(`r`),r.i32_const(l)),p=r.i32_add(r.getLocal(`r`),r.i32_const(2*l)),m=r.i32_add(r.getLocal(`r`),r.i32_const(3*l)),g=r.i32_add(r.getLocal(`r`),r.i32_const(4*l)),_=r.i32_add(r.getLocal(`r`),r.i32_const(5*l)),v=r.i32_const(e.alloc(l)),y=r.i32_const(e.alloc(l)),b=r.i32_const(e.alloc(l)),x=r.i32_const(e.alloc(l)),S=r.i32_const(e.alloc(l)),C=r.i32_const(e.alloc(l)),w=r.i32_const(e.alloc(l)),T=r.i32_const(e.alloc(l));t.addCode(r.call(h+`_mul`,i,c,w),r.call(h+`_mul`,c,r.i32_const(k),v),r.call(h+`_add`,i,v,v),r.call(h+`_add`,i,c,T),r.call(h+`_mul`,T,v,v),r.call(h+`_mul`,r.i32_const(k),w,T),r.call(h+`_add`,w,T,T),r.call(h+`_sub`,v,T,v),r.call(h+`_add`,w,w,y),r.call(h+`_mul`,s,o,w),r.call(h+`_mul`,o,r.i32_const(k),b),r.call(h+`_add`,s,b,b),r.call(h+`_add`,s,o,T),r.call(h+`_mul`,T,b,b),r.call(h+`_mul`,r.i32_const(k),w,T),r.call(h+`_add`,w,T,T),r.call(h+`_sub`,b,T,b),r.call(h+`_add`,w,w,x),r.call(h+`_mul`,a,u,w),r.call(h+`_mul`,u,r.i32_const(k),S),r.call(h+`_add`,a,S,S),r.call(h+`_add`,a,u,T),r.call(h+`_mul`,T,S,S),r.call(h+`_mul`,r.i32_const(k),w,T),r.call(h+`_add`,w,T,T),r.call(h+`_sub`,S,T,S),r.call(h+`_add`,w,w,C),r.call(h+`_sub`,v,i,d),r.call(h+`_add`,d,d,d),r.call(h+`_add`,v,d,d),r.call(h+`_add`,y,c,g),r.call(h+`_add`,g,g,g),r.call(h+`_add`,y,g,g),r.call(h+`_mul`,C,r.i32_const(j),T),r.call(h+`_add`,T,s,m),r.call(h+`_add`,m,m,m),r.call(h+`_add`,T,m,m),r.call(h+`_sub`,S,o,p),r.call(h+`_add`,p,p,p),r.call(h+`_add`,S,p,p),r.call(h+`_sub`,b,a,f),r.call(h+`_add`,f,f,f),r.call(h+`_add`,b,f,f),r.call(h+`_add`,x,u,_),r.call(h+`_add`,_,_,_),r.call(h+`_add`,x,_,_))}function ve(t,r){let i=ae(t).map(e=>e==-1?255:e),a=e.alloc(i),o=e.addFunction(n+`__cyclotomicExp_`+r);o.addParam(`x`,`i32`),o.addParam(`r`,`i32`),o.addLocal(`bit`,`i32`),o.addLocal(`i`,`i32`);let s=o.getCodeBuilder(),c=s.getLocal(`x`),l=s.getLocal(`r`),d=s.i32_const(e.alloc(u));o.addCode(s.call(I+`_conjugate`,c,d),s.call(I+`_one`,l),s.if(s.teeLocal(`bit`,s.i32_load8_s(s.i32_const(i.length-1),a)),s.if(s.i32_eq(s.getLocal(`bit`),s.i32_const(1)),s.call(I+`_mul`,l,c,l),s.call(I+`_mul`,l,d,l))),s.setLocal(`i`,s.i32_const(i.length-2)),s.block(s.loop(s.call(n+`__cyclotomicSquare`,l,l),s.if(s.teeLocal(`bit`,s.i32_load8_s(s.getLocal(`i`),a)),s.if(s.i32_eq(s.getLocal(`bit`),s.i32_const(1)),s.call(I+`_mul`,l,c,l),s.call(I+`_mul`,l,d,l))),s.br_if(1,s.i32_eqz(s.getLocal(`i`))),s.setLocal(`i`,s.i32_sub(s.getLocal(`i`),s.i32_const(1))),s.br(0))))}function ye(){_e(),ve(4965661367192848881n,`w0`);let t=e.addFunction(n+`__finalExponentiationLastChunk`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`x`),a=r.getLocal(`r`),o=r.i32_const(e.alloc(u)),s=r.i32_const(e.alloc(u)),c=r.i32_const(e.alloc(u)),l=r.i32_const(e.alloc(u)),d=r.i32_const(e.alloc(u)),f=r.i32_const(e.alloc(u)),p=r.i32_const(e.alloc(u)),m=r.i32_const(e.alloc(u)),h=r.i32_const(e.alloc(u)),g=r.i32_const(e.alloc(u)),_=r.i32_const(e.alloc(u)),v=r.i32_const(e.alloc(u)),y=r.i32_const(e.alloc(u)),b=r.i32_const(e.alloc(u)),x=r.i32_const(e.alloc(u)),S=r.i32_const(e.alloc(u)),C=r.i32_const(e.alloc(u)),w=r.i32_const(e.alloc(u)),T=r.i32_const(e.alloc(u)),E=r.i32_const(e.alloc(u)),D=r.i32_const(e.alloc(u));t.addCode(r.call(n+`__cyclotomicExp_w0`,i,o),r.call(I+`_conjugate`,o,o),r.call(n+`__cyclotomicSquare`,o,s),r.call(n+`__cyclotomicSquare`,s,c),r.call(I+`_mul`,c,s,l),r.call(n+`__cyclotomicExp_w0`,l,d),r.call(I+`_conjugate`,d,d),r.call(n+`__cyclotomicSquare`,d,f),r.call(n+`__cyclotomicExp_w0`,f,p),r.call(I+`_conjugate`,p,p),r.call(I+`_conjugate`,l,m),r.call(I+`_conjugate`,p,h),r.call(I+`_mul`,h,d,g),r.call(I+`_mul`,g,m,_),r.call(I+`_mul`,_,s,v),r.call(I+`_mul`,_,d,y),r.call(I+`_mul`,y,i,b),r.call(n+`__frobeniusMap1`,v,x),r.call(I+`_mul`,x,b,S),r.call(n+`__frobeniusMap2`,_,C),r.call(I+`_mul`,C,S,w),r.call(I+`_conjugate`,i,T),r.call(I+`_mul`,T,v,E),r.call(n+`__frobeniusMap3`,E,D),r.call(I+`_mul`,D,w,a))}function be(){ge(),ye();let t=e.addFunction(n+`_finalExponentiation`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`x`),a=r.getLocal(`r`),o=r.i32_const(e.alloc(u));t.addCode(r.call(n+`__finalExponentiationFirstChunk`,i,o),r.call(n+`__finalExponentiationLastChunk`,o,a))}function xe(){let t=e.addFunction(n+`_finalExponentiationOld`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let r=e.alloc(z(552484233613224096312617126783173147097382103762957654188882734314196910839907541213974502761540629817009608548654680343627701153829446747810907373256841551006201639677726139946029199968412598804882391702273019083653272047566316584365559776493027495458238373902875937659943504873220554161550525926302303331747463515644711876653177129578303191095900909191624817826566688241804408081892785725967931714097716709526092261278071952560171111444072049229123565057483750161460024353346284167282452756217662335528813519139808291170539072125381230815729071544861602750936964829313608137325426383735122175229541155376346436093930287402089517426973178917569713384748081827255472576937471496195752727188261435633271238710131736096299798168852925540549342330775279877006784354801422249722573783561685179618816480037695005515426162362431072245638324744480n,352)),i=t.getCodeBuilder();t.addCode(i.call(I+`_exp`,i.getLocal(`x`),i.i32_const(r),i.i32_const(352),i.getLocal(`r`)))}let Se=e.alloc(re),Ce=e.alloc(ie);function we(t){let r=e.addFunction(n+`_pairingEq`+t);for(let e=0;e{be(),et(),nt(),it(),ot(),ft(),mt(),gt(),vt(),bt(),Qe()}));function Ct(e,t){let n=t||`bls12381`;if(e.modules[n])return n;let r=4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787n,i=52435875175126190479447740508185965837690552500527637822603658699938581184513n,a=Math.floor((Be(r-1n)-1)/64)+1,o=a*8,s=o,c=s*2,l=s*12,u=Math.floor((Be(i-1n)-1)/64)+1,d=u*8,f=d,p=e.alloc(z(i,f)),m=$e(e,r,`f1m`,`intq`);tt(e,i,`fr`,`frm`,`intr`);let h=e.alloc(z(x(4n),s)),g=dt(e,`g1m`,`f1m`,h);pt(e,`frm`,`frm`,`frm`,`frm_mul`),ht(e,`pol`,`frm`),_t(e,`qap`,`frm`);let _=rt(e,`f1m_neg`,`f2m`,`f1m`),v=e.alloc([...z(x(4n),s),...z(x(4n),s)]),y=dt(e,`g2m`,`f2m`,v);function b(t,n){let r=e.addFunction(t);r.addParam(`pG`,`i32`),r.addParam(`pFr`,`i32`),r.addParam(`pr`,`i32`);let i=r.getCodeBuilder(),a=i.i32_const(e.alloc(d));r.addCode(i.call(`frm_fromMontgomery`,i.getLocal(`pFr`),a),i.call(n,i.getLocal(`pG`),a,i.i32_const(d),i.getLocal(`pr`))),e.exportFunction(t)}b(`g1m_timesFr`,`g1m_timesScalar`),pt(e,`g1m`,`g1m`,`frm`,`g1m_timesFr`),b(`g2m_timesFr`,`g2m_timesScalar`),pt(e,`g2m`,`g2m`,`frm`,`g2m_timesFr`),b(`g1m_timesFrAffine`,`g1m_timesScalarAffine`),b(`g2m_timesFrAffine`,`g2m_timesScalarAffine`),yt(e,`frm_batchApplyKey`,`fmr`,`frm`,d,d,d,`frm_mul`),yt(e,`g1m_batchApplyKey`,`g1m`,`frm`,o*3,o*3,d,`g1m_timesFr`),yt(e,`g1m_batchApplyKeyMixed`,`g1m`,`frm`,o*2,o*3,d,`g1m_timesFrAffine`),yt(e,`g2m_batchApplyKey`,`g2m`,`frm`,o*2*3,o*3*2,d,`g2m_timesFr`),yt(e,`g2m_batchApplyKeyMixed`,`g2m`,`frm`,o*2*2,o*3*2,d,`g2m_timesFrAffine`);function x(e){return BigInt(e)*(1n<e+(t==0?0:1),0)+R+1,ne=6*o,re=3*o*2+te*ee,ie=15132376222941642752n;e.modules[n]={n64q:a,n64r:u,n8q:o,n8r:d,pG1gen:C,pG1zero:T,pG1b:h,pG2gen:D,pG2zero:k,pG2b:v,pq:e.modules.f1m.pq,pr:p,pOneT:A,r:i,q:r,prePSize:ne,preQSize:re};function ae(e){let t=e,n=[];for(;t>0n;){if(Ie(t)){let e=2-Number(t%4n);n.push(e),t-=BigInt(e)}else n.push(0);t>>=1n}return n}function oe(e){let t=e,n=[];for(;t>0n;)Ie(t)?n.push(1):n.push(0),t>>=1n;return n}function se(){let t=e.addFunction(n+`_prepareG1`);t.addParam(`pP`,`i32`),t.addParam(`ppreP`,`i32`);let r=t.getCodeBuilder();t.addCode(r.call(g+`_normalize`,r.getLocal(`pP`),r.getLocal(`ppreP`)))}function ce(){let t=e.addFunction(n+`_prepDblStep`);t.addParam(`R`,`i32`),t.addParam(`r`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`R`),a=r.i32_add(r.getLocal(`R`),r.i32_const(2*o)),s=r.i32_add(r.getLocal(`R`),r.i32_const(4*o)),l=r.getLocal(`r`),u=r.i32_add(r.getLocal(`r`),r.i32_const(2*o)),d=r.i32_add(r.getLocal(`r`),r.i32_const(4*o)),f=r.i32_const(e.alloc(c)),p=r.i32_const(e.alloc(c)),m=r.i32_const(e.alloc(c)),h=r.i32_const(e.alloc(c)),g=r.i32_const(e.alloc(c));t.addCode(r.call(_+`_square`,i,l),r.call(_+`_square`,a,p),r.call(_+`_square`,p,m),r.call(_+`_add`,p,i,u),r.call(_+`_square`,u,u),r.call(_+`_sub`,u,l,u),r.call(_+`_sub`,u,m,u),r.call(_+`_add`,u,u,u),r.call(_+`_add`,l,l,h),r.call(_+`_add`,h,l,h),r.call(_+`_add`,i,h,d),r.call(_+`_square`,h,g),r.call(_+`_square`,s,f),r.call(_+`_sub`,g,u,i),r.call(_+`_sub`,i,u,i),r.call(_+`_add`,s,a,s),r.call(_+`_square`,s,s),r.call(_+`_sub`,s,p,s),r.call(_+`_sub`,s,f,s),r.call(_+`_sub`,u,i,a),r.call(_+`_mul`,a,h,a),r.call(_+`_add`,m,m,m),r.call(_+`_add`,m,m,m),r.call(_+`_add`,m,m,m),r.call(_+`_sub`,a,m,a),r.call(_+`_mul`,h,f,u),r.call(_+`_add`,u,u,u),r.call(_+`_neg`,u,u),r.call(_+`_square`,d,d),r.call(_+`_sub`,d,l,d),r.call(_+`_sub`,d,g,d),r.call(_+`_add`,p,p,p),r.call(_+`_add`,p,p,p),r.call(_+`_sub`,d,p,d),r.call(_+`_mul`,s,f,l),r.call(_+`_add`,l,l,l))}function le(){let t=e.addFunction(n+`_prepAddStep`);t.addParam(`R`,`i32`),t.addParam(`Q`,`i32`),t.addParam(`r`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`R`),a=r.i32_add(r.getLocal(`R`),r.i32_const(2*o)),s=r.i32_add(r.getLocal(`R`),r.i32_const(4*o)),l=r.getLocal(`Q`),u=r.i32_add(r.getLocal(`Q`),r.i32_const(2*o)),d=r.getLocal(`r`),f=r.i32_add(r.getLocal(`r`),r.i32_const(2*o)),p=r.i32_add(r.getLocal(`r`),r.i32_const(4*o)),m=r.i32_const(e.alloc(c)),h=r.i32_const(e.alloc(c)),g=r.i32_const(e.alloc(c)),v=r.i32_const(e.alloc(c)),y=r.i32_const(e.alloc(c)),b=r.i32_const(e.alloc(c)),x=r.i32_const(e.alloc(c)),S=r.i32_const(e.alloc(c)),C=r.i32_const(e.alloc(c)),w=r.i32_const(e.alloc(c)),T=r.i32_const(e.alloc(c));t.addCode(r.call(_+`_square`,s,m),r.call(_+`_square`,u,h),r.call(_+`_mul`,m,l,v),r.call(_+`_add`,u,s,f),r.call(_+`_square`,f,f),r.call(_+`_sub`,f,h,f),r.call(_+`_sub`,f,m,f),r.call(_+`_mul`,f,m,f),r.call(_+`_sub`,v,i,y),r.call(_+`_square`,y,b),r.call(_+`_add`,b,b,x),r.call(_+`_add`,x,x,x),r.call(_+`_mul`,x,y,S),r.call(_+`_sub`,f,a,C),r.call(_+`_sub`,C,a,C),r.call(_+`_mul`,C,l,p),r.call(_+`_mul`,x,i,w),r.call(_+`_square`,C,i),r.call(_+`_sub`,i,S,i),r.call(_+`_sub`,i,w,i),r.call(_+`_sub`,i,w,i),r.call(_+`_add`,s,y,s),r.call(_+`_square`,s,s),r.call(_+`_sub`,s,m,s),r.call(_+`_sub`,s,b,s),r.call(_+`_add`,u,s,d),r.call(_+`_sub`,w,i,T),r.call(_+`_mul`,T,C,T),r.call(_+`_mul`,a,S,v),r.call(_+`_add`,v,v,v),r.call(_+`_sub`,T,v,a),r.call(_+`_square`,d,d),r.call(_+`_sub`,d,h,d),r.call(_+`_square`,s,g),r.call(_+`_sub`,d,g,d),r.call(_+`_add`,p,p,p),r.call(_+`_sub`,p,d,p),r.call(_+`_add`,s,s,d),r.call(_+`_neg`,C,C),r.call(_+`_add`,C,C,f))}function ue(){let t=e.addFunction(n+`_prepareG2`);t.addParam(`pQ`,`i32`),t.addParam(`ppreQ`,`i32`),t.addLocal(`pCoef`,`i32`),t.addLocal(`i`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`pQ`),a=e.alloc(c*3),o=r.i32_const(a),s=r.getLocal(`ppreQ`);t.addCode(r.call(y+`_normalize`,i,s),r.if(r.call(y+`_isZero`,s),r.ret([])),r.call(y+`_copy`,s,o),r.setLocal(`pCoef`,r.i32_add(r.getLocal(`ppreQ`),r.i32_const(c*3)))),t.addCode(r.setLocal(`i`,r.i32_const(I.length-2)),r.block(r.loop(r.call(n+`_prepDblStep`,o,r.getLocal(`pCoef`)),r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(ee))),r.if(r.i32_load8_s(r.getLocal(`i`),L),[...r.call(n+`_prepAddStep`,o,s,r.getLocal(`pCoef`)),...r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(ee)))]),r.br_if(1,r.i32_eqz(r.getLocal(`i`))),r.setLocal(`i`,r.i32_sub(r.getLocal(`i`),r.i32_const(1))),r.br(0))))}function de(){let t=e.addFunction(N+`_mul1`);t.addParam(`pA`,`i32`),t.addParam(`pC1`,`i32`),t.addParam(`pR`,`i32`);let n=t.getCodeBuilder(),r=n.getLocal(`pA`),i=n.i32_add(n.getLocal(`pA`),n.i32_const(s*2)),a=n.i32_add(n.getLocal(`pA`),n.i32_const(s*4)),o=n.getLocal(`pC1`),c=n.getLocal(`pR`),l=n.i32_add(n.getLocal(`pR`),n.i32_const(s*2)),u=n.i32_add(n.getLocal(`pR`),n.i32_const(s*4)),d=n.i32_const(e.alloc(s*2)),f=n.i32_const(e.alloc(s*2));t.addCode(n.call(_+`_add`,r,i,d),n.call(_+`_add`,i,a,f),n.call(_+`_mul`,i,o,u),n.call(_+`_mul`,f,o,c),n.call(_+`_sub`,c,u,c),n.call(_+`_mulNR`,c,c),n.call(_+`_mul`,d,o,l),n.call(_+`_sub`,l,u,l))}de();function fe(){let t=e.addFunction(N+`_mul01`);t.addParam(`pA`,`i32`),t.addParam(`pC0`,`i32`),t.addParam(`pC1`,`i32`),t.addParam(`pR`,`i32`);let n=t.getCodeBuilder(),r=n.getLocal(`pA`),i=n.i32_add(n.getLocal(`pA`),n.i32_const(s*2)),a=n.i32_add(n.getLocal(`pA`),n.i32_const(s*4)),o=n.getLocal(`pC0`),c=n.getLocal(`pC1`),l=n.getLocal(`pR`),u=n.i32_add(n.getLocal(`pR`),n.i32_const(s*2)),d=n.i32_add(n.getLocal(`pR`),n.i32_const(s*4)),f=n.i32_const(e.alloc(s*2)),p=n.i32_const(e.alloc(s*2)),m=n.i32_const(e.alloc(s*2)),h=n.i32_const(e.alloc(s*2));t.addCode(n.call(_+`_mul`,r,o,f),n.call(_+`_mul`,i,c,p),n.call(_+`_add`,r,i,m),n.call(_+`_add`,r,a,h),n.call(_+`_add`,i,a,l),n.call(_+`_mul`,l,c,l),n.call(_+`_sub`,l,p,l),n.call(_+`_mulNR`,l,l),n.call(_+`_add`,l,f,l),n.call(_+`_add`,o,c,u),n.call(_+`_mul`,u,m,u),n.call(_+`_sub`,u,f,u),n.call(_+`_sub`,u,p,u),n.call(_+`_mul`,h,o,d),n.call(_+`_sub`,d,f,d),n.call(_+`_add`,d,p,d))}fe();function pe(){let t=e.addFunction(F+`_mul014`);t.addParam(`pA`,`i32`),t.addParam(`pC0`,`i32`),t.addParam(`pC1`,`i32`),t.addParam(`pC4`,`i32`),t.addParam(`pR`,`i32`);let n=t.getCodeBuilder(),r=n.getLocal(`pA`),i=n.i32_add(n.getLocal(`pA`),n.i32_const(s*6)),a=n.getLocal(`pC0`),o=n.getLocal(`pC1`),c=n.getLocal(`pC4`),l=n.i32_const(e.alloc(s*6)),u=n.i32_const(e.alloc(s*6)),d=n.i32_const(e.alloc(s*2)),f=n.getLocal(`pR`),p=n.i32_add(n.getLocal(`pR`),n.i32_const(s*6));t.addCode(n.call(N+`_mul01`,r,a,o,l),n.call(N+`_mul1`,i,c,u),n.call(_+`_add`,o,c,d),n.call(N+`_add`,i,r,p),n.call(N+`_mul01`,p,a,d,p),n.call(N+`_sub`,p,l,p),n.call(N+`_sub`,p,u,p),n.call(N+`_copy`,u,f),n.call(N+`_mulNR`,f,f),n.call(N+`_add`,f,l,f))}pe();function me(){let t=e.addFunction(n+`_ell`);t.addParam(`pP`,`i32`),t.addParam(`pCoefs`,`i32`),t.addParam(`pF`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`pP`),a=r.i32_add(r.getLocal(`pP`),r.i32_const(o)),c=r.getLocal(`pF`),l=r.getLocal(`pCoefs`),u=r.i32_add(r.getLocal(`pCoefs`),r.i32_const(s)),d=r.i32_add(r.getLocal(`pCoefs`),r.i32_const(s*2)),f=r.i32_add(r.getLocal(`pCoefs`),r.i32_const(s*3)),p=r.i32_add(r.getLocal(`pCoefs`),r.i32_const(s*4)),h=e.alloc(s*2),g=r.i32_const(h),_=r.i32_const(h),v=r.i32_const(h+s),y=e.alloc(s*2),b=r.i32_const(y),x=r.i32_const(y),S=r.i32_const(y+s);t.addCode(r.call(m+`_mul`,l,a,_),r.call(m+`_mul`,u,a,v),r.call(m+`_mul`,d,i,x),r.call(m+`_mul`,f,i,S),r.call(F+`_mul014`,c,p,b,g,c))}me();function he(){let t=e.addFunction(n+`_millerLoop`);t.addParam(`ppreP`,`i32`),t.addParam(`ppreQ`,`i32`),t.addParam(`r`,`i32`),t.addLocal(`pCoef`,`i32`),t.addLocal(`i`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`ppreP`),a=r.getLocal(`pCoef`),o=r.getLocal(`r`);t.addCode(r.call(F+`_one`,o),r.if(r.call(g+`_isZero`,i),r.ret([])),r.if(r.call(g+`_isZero`,r.getLocal(`ppreQ`)),r.ret([])),r.setLocal(`pCoef`,r.i32_add(r.getLocal(`ppreQ`),r.i32_const(c*3))),r.setLocal(`i`,r.i32_const(I.length-2)),r.block(r.loop(r.call(n+`_ell`,i,a,o),r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(ee))),r.if(r.i32_load8_s(r.getLocal(`i`),L),[...r.call(n+`_ell`,i,a,o),...r.setLocal(`pCoef`,r.i32_add(r.getLocal(`pCoef`),r.i32_const(ee)))]),r.call(F+`_square`,o,o),r.br_if(1,r.i32_eq(r.getLocal(`i`),r.i32_const(1))),r.setLocal(`i`,r.i32_sub(r.getLocal(`i`),r.i32_const(1))),r.br(0))),r.call(n+`_ell`,i,a,o)),t.addCode(r.call(F+`_conjugate`,o,o))}function ge(t){let n=[[[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n]],[[1n,0n],[3850754370037169011952147076051364057158807420970682438676050522613628423219637725072182697113062777891589506424760n,151655185184498381465642749684540099398075398968325446656007613510403227271200139370504932015952886146304766135027n],[793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620351n,0n],[2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530n,1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257n],[793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350n,0n],[3125332594171059424908108096204648978570118281977575435832422631601824034463382777937621250592425535493320683825557n,877076961050607968509681729531255177986764537961432449499635504522207616027455086505066378536590128544573588734230n],[4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559786n,0n],[151655185184498381465642749684540099398075398968325446656007613510403227271200139370504932015952886146304766135027n,3850754370037169011952147076051364057158807420970682438676050522613628423219637725072182697113062777891589506424760n],[4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436n,0n],[1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257n,2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530n],[4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437n,0n],[877076961050607968509681729531255177986764537961432449499635504522207616027455086505066378536590128544573588734230n,3125332594171059424908108096204648978570118281977575435832422631601824034463382777937621250592425535493320683825557n]]],i=[[[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n],[1n,0n]],[[1n,0n],[0n,4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436n],[793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350n,0n],[0n,1n],[4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436n,0n],[0n,793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350n]],[[1n,0n],[4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437n,0n],[4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436n,0n],[4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559786n,0n],[793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350n,0n],[793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620351n,0n]]],a=e.addFunction(F+`_frobeniusMap`+t);a.addParam(`x`,`i32`),a.addParam(`r`,`i32`);let l=a.getCodeBuilder();for(let r=0;r<6;r++){let d=r==0?l.getLocal(`x`):l.i32_add(l.getLocal(`x`),l.i32_const(r*c)),f=d,p=l.i32_add(l.getLocal(`x`),l.i32_const(r*c+s)),h=r==0?l.getLocal(`r`):l.i32_add(l.getLocal(`r`),l.i32_const(r*c)),g=h,v=l.i32_add(l.getLocal(`r`),l.i32_const(r*c+s)),y=u(n[Math.floor(r/3)][t%12],i[r%3][t%6]),b=e.alloc([...z(x(y[0]),o),...z(x(y[1]),o)]);t%2==1?a.addCode(l.call(m+`_copy`,f,g),l.call(m+`_neg`,p,v),l.call(_+`_mul`,h,l.i32_const(b),h)):a.addCode(l.call(_+`_mul`,d,l.i32_const(b),h))}function u(e,t){let n=e[0],i=e[1],a=t[0],o=t[1],s=[(n*a-i*o)%r,(n*o+i*a)%r];return Re(s[0])&&(s[0]+=r),s}}function _e(){let t=e.addFunction(n+`__cyclotomicSquare`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`x`),a=r.i32_add(r.getLocal(`x`),r.i32_const(c)),o=r.i32_add(r.getLocal(`x`),r.i32_const(2*c)),s=r.i32_add(r.getLocal(`x`),r.i32_const(3*c)),l=r.i32_add(r.getLocal(`x`),r.i32_const(4*c)),u=r.i32_add(r.getLocal(`x`),r.i32_const(5*c)),d=r.getLocal(`r`),f=r.i32_add(r.getLocal(`r`),r.i32_const(c)),p=r.i32_add(r.getLocal(`r`),r.i32_const(2*c)),m=r.i32_add(r.getLocal(`r`),r.i32_const(3*c)),h=r.i32_add(r.getLocal(`r`),r.i32_const(4*c)),g=r.i32_add(r.getLocal(`r`),r.i32_const(5*c)),v=r.i32_const(e.alloc(c)),y=r.i32_const(e.alloc(c)),b=r.i32_const(e.alloc(c)),x=r.i32_const(e.alloc(c)),S=r.i32_const(e.alloc(c)),C=r.i32_const(e.alloc(c)),w=r.i32_const(e.alloc(c)),T=r.i32_const(e.alloc(c));t.addCode(r.call(_+`_mul`,i,l,w),r.call(_+`_mulNR`,l,v),r.call(_+`_add`,i,v,v),r.call(_+`_add`,i,l,T),r.call(_+`_mul`,T,v,v),r.call(_+`_mulNR`,w,T),r.call(_+`_add`,w,T,T),r.call(_+`_sub`,v,T,v),r.call(_+`_add`,w,w,y),r.call(_+`_mul`,s,o,w),r.call(_+`_mulNR`,o,b),r.call(_+`_add`,s,b,b),r.call(_+`_add`,s,o,T),r.call(_+`_mul`,T,b,b),r.call(_+`_mulNR`,w,T),r.call(_+`_add`,w,T,T),r.call(_+`_sub`,b,T,b),r.call(_+`_add`,w,w,x),r.call(_+`_mul`,a,u,w),r.call(_+`_mulNR`,u,S),r.call(_+`_add`,a,S,S),r.call(_+`_add`,a,u,T),r.call(_+`_mul`,T,S,S),r.call(_+`_mulNR`,w,T),r.call(_+`_add`,w,T,T),r.call(_+`_sub`,S,T,S),r.call(_+`_add`,w,w,C),r.call(_+`_sub`,v,i,d),r.call(_+`_add`,d,d,d),r.call(_+`_add`,v,d,d),r.call(_+`_add`,y,l,h),r.call(_+`_add`,h,h,h),r.call(_+`_add`,y,h,h),r.call(_+`_mul`,C,r.i32_const(j),T),r.call(_+`_add`,T,s,m),r.call(_+`_add`,m,m,m),r.call(_+`_add`,T,m,m),r.call(_+`_sub`,S,o,p),r.call(_+`_add`,p,p,p),r.call(_+`_add`,S,p,p),r.call(_+`_sub`,b,a,f),r.call(_+`_add`,f,f,f),r.call(_+`_add`,b,f,f),r.call(_+`_add`,x,u,g),r.call(_+`_add`,g,g,g),r.call(_+`_add`,x,g,g))}function ve(t,r,i){let a=ae(t).map(e=>e==-1?255:e),o=e.alloc(a),s=e.addFunction(n+`__cyclotomicExp_`+i);s.addParam(`x`,`i32`),s.addParam(`r`,`i32`),s.addLocal(`bit`,`i32`),s.addLocal(`i`,`i32`);let c=s.getCodeBuilder(),u=c.getLocal(`x`),d=c.getLocal(`r`),f=c.i32_const(e.alloc(l));s.addCode(c.call(F+`_conjugate`,u,f),c.call(F+`_one`,d),c.if(c.teeLocal(`bit`,c.i32_load8_s(c.i32_const(a.length-1),o)),c.if(c.i32_eq(c.getLocal(`bit`),c.i32_const(1)),c.call(F+`_mul`,d,u,d),c.call(F+`_mul`,d,f,d))),c.setLocal(`i`,c.i32_const(a.length-2)),c.block(c.loop(c.call(n+`__cyclotomicSquare`,d,d),c.if(c.teeLocal(`bit`,c.i32_load8_s(c.getLocal(`i`),o)),c.if(c.i32_eq(c.getLocal(`bit`),c.i32_const(1)),c.call(F+`_mul`,d,u,d),c.call(F+`_mul`,d,f,d))),c.br_if(1,c.i32_eqz(c.getLocal(`i`))),c.setLocal(`i`,c.i32_sub(c.getLocal(`i`),c.i32_const(1))),c.br(0)))),r&&s.addCode(c.call(F+`_conjugate`,d,d))}function ye(){_e(),ve(ie,!0,`w0`);let t=e.addFunction(n+`_finalExponentiation`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let r=t.getCodeBuilder(),i=r.getLocal(`x`),a=r.getLocal(`r`),o=r.i32_const(e.alloc(l)),s=r.i32_const(e.alloc(l)),c=r.i32_const(e.alloc(l)),u=r.i32_const(e.alloc(l)),d=r.i32_const(e.alloc(l)),f=r.i32_const(e.alloc(l)),p=r.i32_const(e.alloc(l));t.addCode(r.call(F+`_frobeniusMap6`,i,o),r.call(F+`_inverse`,i,s),r.call(F+`_mul`,o,s,c),r.call(F+`_copy`,c,s),r.call(F+`_frobeniusMap2`,c,c),r.call(F+`_mul`,c,s,c),r.call(n+`__cyclotomicSquare`,c,s),r.call(F+`_conjugate`,s,s),r.call(n+`__cyclotomicExp_w0`,c,u),r.call(n+`__cyclotomicSquare`,u,d),r.call(F+`_mul`,s,u,f),r.call(n+`__cyclotomicExp_w0`,f,s),r.call(n+`__cyclotomicExp_w0`,s,o),r.call(n+`__cyclotomicExp_w0`,o,p),r.call(F+`_mul`,p,d,p),r.call(n+`__cyclotomicExp_w0`,p,d),r.call(F+`_conjugate`,f,f),r.call(F+`_mul`,d,f,d),r.call(F+`_mul`,d,c,d),r.call(F+`_conjugate`,c,f),r.call(F+`_mul`,s,c,s),r.call(F+`_frobeniusMap3`,s,s),r.call(F+`_mul`,p,f,p),r.call(F+`_frobeniusMap1`,p,p),r.call(F+`_mul`,u,o,u),r.call(F+`_frobeniusMap2`,u,u),r.call(F+`_mul`,u,s,u),r.call(F+`_mul`,u,p,u),r.call(F+`_mul`,u,d,a))}function be(){let t=e.addFunction(n+`_finalExponentiationOld`);t.addParam(`x`,`i32`),t.addParam(`r`,`i32`);let r=e.alloc(z(322277361516934140462891564586510139908379969514828494218366688025288661041104682794998680497580008899973249814104447692778988208376779573819485263026159588510513834876303014016798809919343532899164848730280942609956670917565618115867287399623286813270357901731510188149934363360381614501334086825442271920079363289954510565375378443704372994881406797882676971082200626541916413184642520269678897559532260949334760604962086348898118982248842634379637598665468817769075878555493752214492790122785850202957575200176084204422751485957336465472324810982833638490904279282696134323072515220044451592646885410572234451732790590013479358343841220074174848221722017083597872017638514103174122784843925578370430843522959600095676285723737049438346544753168912974976791528535276317256904336520179281145394686565050419250614107803233314658825463117900250701199181529205942363159325765991819433914303908860460720581408201373164047773794825411011922305820065611121544561808414055302212057471395719432072209245600258134364584636810093520285711072578721435517884103526483832733289802426157301542744476740008494780363354305116978805620671467071400711358839553375340724899735460480144599782014906586543813292157922220645089192130209334926661588737007768565838519456601560804957985667880395221049249803753582637708560n,544)),i=t.getCodeBuilder();t.addCode(i.call(F+`_exp`,i.getLocal(`x`),i.i32_const(r),i.i32_const(544),i.getLocal(`r`)))}let xe=e.alloc(ne),Se=e.alloc(re);function Ce(t){let r=e.addFunction(n+`_pairingEq`+t);for(let e=0;e{be(),et(),nt(),it(),ot(),ft(),mt(),gt(),vt(),bt(),Qe()})),Tt=l({bn128_wasm_gzip:()=>f,buildBls12381:()=>Ct,buildBn128:()=>xt,buildF1m:()=>$e}),Et=s((()=>{T(),St(),wt(),et()}));console.log(`browser esm`);var Dt=Object.create,Ot=Object.defineProperty,kt=Object.getOwnPropertyDescriptor,At=Object.getOwnPropertyNames,jt=Object.getPrototypeOf,Mt=Object.prototype.hasOwnProperty,Nt=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Pt=(e,t)=>{let n={};for(var r in e)Ot(n,r,{get:e[r],enumerable:!0});return t||Ot(n,Symbol.toStringTag,{value:`Module`}),n},Ft=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=At(t),a=0,o=i.length,s;at[e]).bind(null,s),enumerable:!(r=kt(t,s))||r.enumerable});return e},It=(e,t,n)=>(n=e==null?{}:Dt(jt(e)),Ft(t||!e||!e.__esModule?Ot(n,`default`,{value:e,enumerable:!0}):n,e)),Lt=(e=>typeof require<`u`?require:typeof Proxy<`u`?new Proxy(e,{get:(e,t)=>(typeof require<`u`?require:e)[t]}):e)(function(e){if(typeof require<`u`)return require.apply(this,arguments);throw Error('Calling `require` for "'+e+"\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.")}),Rt=Pt({abs:()=>ln,add:()=>tn,band:()=>vn,bitLength:()=>Ut,bits:()=>Qt,bor:()=>yn,bxor:()=>bn,div:()=>un,e:()=>Vt,eq:()=>fn,exp:()=>cn,fromArray:()=>Ht,fromRprBE:()=>Dn,fromRprLE:()=>En,fromString:()=>Bt,geq:()=>_n,gt:()=>hn,isNegative:()=>Wt,isOdd:()=>Xt,isZero:()=>Gt,land:()=>xn,leq:()=>gn,lnot:()=>Cn,lor:()=>Sn,lt:()=>mn,mod:()=>dn,mul:()=>an,naf:()=>Zt,neg:()=>rn,neq:()=>pn,one:()=>jn,pow:()=>sn,shiftLeft:()=>Kt,shiftRight:()=>qt,shl:()=>Jt,shr:()=>Yt,square:()=>on,sub:()=>nn,toArray:()=>en,toLEBuff:()=>kn,toNumber:()=>$t,toRprBE:()=>Tn,toRprLE:()=>wn,toString:()=>On,zero:()=>An}),zt=[0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4];function Bt(e,t){if(!t||t==10)return BigInt(e);if(t==16)return e.slice(0,2)==`0x`?BigInt(e):BigInt(`0x`+e)}var Vt=Bt;function Ht(e,t){let n=BigInt(0);t=BigInt(t);for(let r=0;r>BigInt(t)}var Jt=Kt,Yt=qt;function Xt(e){return(BigInt(e)&BigInt(1))==BigInt(1)}function Zt(e){let t=BigInt(e),n=[];for(;t;){if(t&BigInt(1)){let e=2-Number(t%BigInt(4));n.push(e),t-=BigInt(e)}else n.push(0);t>>=BigInt(1)}return n}function Qt(e){let t=BigInt(e),n=[];for(;t;)t&BigInt(1)?n.push(1):n.push(0),t>>=BigInt(1);return n}function $t(e){if(e>BigInt(2**53-1))throw Error(`Number too big`);return Number(e)}function en(e,t){let n=[],r=BigInt(e);for(t=BigInt(t);r;)n.unshift(Number(r%t)),r/=t;return n}function tn(e,t){return BigInt(e)+BigInt(t)}function nn(e,t){return BigInt(e)-BigInt(t)}function rn(e){return-BigInt(e)}function an(e,t){return BigInt(e)*BigInt(t)}function on(e){return BigInt(e)*BigInt(e)}function sn(e,t){return BigInt(e)**BigInt(t)}function cn(e,t){return BigInt(e)**BigInt(t)}function ln(e){return BigInt(e)>=0?BigInt(e):-BigInt(e)}function un(e,t){return BigInt(e)/BigInt(t)}function dn(e,t){return BigInt(e)%BigInt(t)}function fn(e,t){return BigInt(e)==BigInt(t)}function pn(e,t){return BigInt(e)!=BigInt(t)}function mn(e,t){return BigInt(e)BigInt(t)}function gn(e,t){return BigInt(e)<=BigInt(t)}function _n(e,t){return BigInt(e)>=BigInt(t)}function vn(e,t){return BigInt(e)&BigInt(t)}function yn(e,t){return BigInt(e)|BigInt(t)}function bn(e,t){return BigInt(e)^BigInt(t)}function xn(e,t){return BigInt(e)&&BigInt(t)}function Sn(e,t){return BigInt(e)||BigInt(t)}function Cn(e){return!BigInt(e)}function wn(e,t,n,r){let i=`0000000`+n.toString(16),a=new Uint32Array(e.buffer,e.byteOffset+t,r/4),o=((i.length-7)*4-1>>5)+1;for(let e=0;e>5)+1;for(let e=0;ei[i.length-t-1]=e.toString(16).padStart(8,`0`)),Bt(i.join(``),16)}function Dn(e,t,n){n||=e.byteLength,t||=0;let r=new DataView(e.buffer,e.byteOffset+t,n),i=Array(n/4);for(let e=0;e>=1;return n}function Pn(e,t,n){if(Gt(n))return e.one;let r=Qt(n);if(r.length==0)return e.one;let i=t;for(let n=r.length-2;n>=0;n--)i=e.square(i),r[n]&&(i=e.mul(i,t));return i}function Fn(e){if(e.m%2==1)if(fn(dn(e.p,4),1))if(fn(dn(e.p,8),1))if(fn(dn(e.p,16),1))In(e);else if(fn(dn(e.p,16),9))Ln(e);else throw Error(`Field withot sqrt`);else if(fn(dn(e.p,8),5))Rn(e);else throw Error(`Field withot sqrt`);else fn(dn(e.p,4),3)&&zn(e);else{let t=dn(sn(e.p,e.m/2),4);t==1?Bn(e):t==3?Vn(e):Hn(e)}}function In(e){for(e.sqrt_q=sn(e.p,e.m),e.sqrt_s=0,e.sqrt_t=nn(e.sqrt_q,1);!Xt(e.sqrt_t);)e.sqrt_s+=1,e.sqrt_t=un(e.sqrt_t,2);let t=e.one;for(;e.eq(t,e.one);){let n=e.random();e.sqrt_z=e.pow(n,e.sqrt_t),t=e.pow(e.sqrt_z,2**(e.sqrt_s-1))}e.sqrt_tm1d2=un(nn(e.sqrt_t,1),2),e.sqrt=function(e){let t=this;if(t.isZero(e))return t.zero;let n=t.pow(e,t.sqrt_tm1d2),r=t.pow(t.mul(t.square(n),e),2**(t.sqrt_s-1));if(t.eq(r,t.negone))return null;let i=t.sqrt_s,a=t.mul(e,n),o=t.mul(a,n),s=t.sqrt_z;for(;!t.eq(o,t.one);){let e=t.square(o),r=1;for(;!t.eq(e,t.one);)e=t.square(e),r++;n=s;for(let e=0;e>>0,e[i]=(e[i]^e[t])>>>0,e[i]=(e[i]<<16|e[i]>>>16&65535)>>>0,e[r]=e[r]+e[i]>>>0,e[n]=(e[n]^e[r])>>>0,e[n]=(e[n]<<12|e[n]>>>20&4095)>>>0,e[t]=e[t]+e[n]>>>0,e[i]=(e[i]^e[t])>>>0,e[i]=(e[i]<<8|e[i]>>>24&255)>>>0,e[r]=e[r]+e[i]>>>0,e[n]=(e[n]^e[r])>>>0,e[n]=(e[n]<<7|e[n]>>>25&127)>>>0}function Wn(e){Un(e,0,4,8,12),Un(e,1,5,9,13),Un(e,2,6,10,14),Un(e,3,7,11,15),Un(e,0,5,10,15),Un(e,1,6,11,12),Un(e,2,7,8,13),Un(e,3,4,9,14)}var Gn=class{constructor(e){e||=[0,0,0,0,0,0,0,0],this.state=[1634760805,857760878,2036477234,1797285236,e[0],e[1],e[2],e[3],e[4],e[5],e[6],e[7],0,0,0,0],this.idx=16,this.buff=Array(16)}nextU32(){return this.idx==16&&this.update(),this.buff[this.idx++]}nextU64(){return tn(an(this.nextU32(),4294967296),this.nextU32())}nextBool(){return(this.nextU32()&1)==1}update(){for(let e=0;e<16;e++)this.buff[e]=this.state[e];for(let e=0;e<10;e++)Wn(this.buff);for(let e=0;e<16;e++)this.buff[e]=this.buff[e]+this.state[e]>>>0;this.idx=0,this.state[12]=this.state[12]+1>>>0,this.state[12]==0&&(this.state[13]=this.state[13]+1>>>0,this.state[13]==0&&(this.state[14]=this.state[14]+1>>>0,this.state[14]==0&&(this.state[15]=this.state[15]+1>>>0)))}},Kn=Nt(((e,t)=>{t.exports={}}));function qn(e){let t=new Uint8Array(e);if(globalThis.crypto!==void 0)globalThis.crypto.getRandomValues(t);else if(typeof Lt==`function`)Kn().randomFillSync(t);else throw Error(`No cryptographically secure random source available.`);return t}function Jn(){let e=qn(32),t=new Uint32Array(e.buffer),n=[];for(let e=0;e<8;e++)n.push(t[e]);return n}var Yn=null;function Xn(){return Yn||(Yn=new Gn(Jn()),Yn)}var Zn=class{constructor(e,t,n){this.F=t,this.G=e,this.opMulGF=n;let r=t.sqrt_t||t.t,i=t.sqrt_s||t.s,a=t.one;for(;t.eq(t.pow(a,t.half),t.one);)a=t.add(a,t.one);this.w=Array(i+1),this.wi=Array(i+1),this.w[i]=this.F.pow(a,r),this.wi[i]=this.F.inv(this.w[i]);let o=i-1;for(;o>=0;)this.w[o]=this.F.square(this.w[o+1]),this.wi[o]=this.F.square(this.wi[o+1]),o--;this.roots=[],this._setRoots(Math.min(i,15))}_setRoots(e){for(let t=e;t>=0&&!this.roots[t];t--){let e=this.F.one,n=1<>1,s=$n(e,t,n-1,r,i*2),c=$n(e,t,n-1,r+i,i*2),l=Array(a);for(let t=0;t>this.one,this.bitLength=Ut(this.p),this.mask=(this.one<>this.one;this.nqr=this.two;let n=this.pow(this.nqr,t);for(;!this.eq(n,this.negone);)this.nqr+=this.one,n=this.pow(this.nqr,t);for(this.s=0,this.t=this.negone;(this.t&this.one)==this.zero;)this.s+=1,this.t>>=this.one;this.nqr_to_t=this.pow(this.nqr,this.t),Fn(this),this.FFT=new Zn(this,this,this.mul.bind(this)),this.fft=this.FFT.fft.bind(this.FFT),this.ifft=this.FFT.ifft.bind(this.FFT),this.w=this.FFT.w,this.wi=this.FFT.wi,this.shift=this.square(this.nqr),this.k=this.exp(this.nqr,2**this.s)}e(e,t){let n;if(t?t==16&&(n=BigInt(`0x`+e)):n=BigInt(e),n<0){let e=-n;return e>=this.p&&(e%=this.p),this.p-e}else return n>=this.p?n%this.p:n}add(e,t){let n=e+t;return n>=this.p?n-this.p:n}sub(e,t){return e>=t?e-t:this.p-t+e}neg(e){return e&&this.p-e}mul(e,t){return e*t%this.p}mulScalar(e,t){return e*this.e(t)%this.p}square(e){return e*e%this.p}eq(e,t){return e==t}neq(e,t){return e!=t}lt(e,t){return(e>this.half?e-this.p:e)<(t>this.half?t-this.p:t)}gt(e,t){return(e>this.half?e-this.p:e)>(t>this.half?t-this.p:t)}leq(e,t){return(e>this.half?e-this.p:e)<=(t>this.half?t-this.p:t)}geq(e,t){return(e>this.half?e-this.p:e)>=(t>this.half?t-this.p:t)}div(e,t){return this.mul(e,this.inv(t))}idiv(e,t){if(!t)throw Error(`Division by zero`);return e/t}inv(e){if(!e)throw Error(`Division by zero`);let t=this.zero,n=this.p,r=this.one,i=e%this.p;for(;i;){let e=n/i;[t,r]=[r,t-e*r],[n,i]=[i,n-e*i]}return t=this.p?n-this.p:n}bor(e,t){let n=(e|t)&this.mask;return n>=this.p?n-this.p:n}bxor(e,t){let n=(e^t)&this.mask;return n>=this.p?n-this.p:n}bnot(e){let t=e^this.mask;return t>=this.p?t-this.p:t}shl(e,t){if(Number(t)=this.p?n-this.p:n}else{let n=this.p-t;return Number(n)>n:this.zero}}shr(e,t){if(Number(t)>t;{let n=this.p-t;if(Number(n)=this.p?t-this.p:t}else return 0}}land(e,t){return e&&t?this.one:this.zero}lor(e,t){return e||t?this.one:this.zero}lnot(e){return e?this.zero:this.one}sqrt_old(e){if(e==this.zero)return this.zero;if(this.pow(e,this.negone>>this.one)!=this.one)return null;let t=this.s,n=this.nqr_to_t,r=this.pow(e,this.t),i=this.pow(e,this.add(this.t,this.one)>>this.one);for(;r!=this.one;){let e=this.square(r),a=1;for(;e!=this.one;)a++,e=this.square(e);let o=n;for(let e=0;ethis.p>>this.one&&(i=this.neg(i)),i}normalize(e,t){if(e=BigInt(e,t),e<0){let t=-e;return t>=this.p&&(t%=this.p),this.p-t}else return e>=this.p?e%this.p:e}random(){let e=this.bitLength*2/8,t=this.zero;for(let n=0;nthis.half&&t==10?`-`+(this.p-e).toString(t):e.toString(t),n}isZero(e){return e==this.zero}fromRng(e){let t;do{t=this.zero;for(let n=0;n=this.p);return t=t*this.Ri%this.p,t}fft(e){return this.FFT.fft(e)}ifft(e){return this.FFT.ifft(e)}toRprLE(e,t,n){wn(e,t,n,this.n64*8)}toRprBE(e,t,n){Tn(e,t,n,this.n64*8)}toRprBEM(e,t,n){return this.toRprBE(e,t,this.mul(this.R,n))}toRprLEM(e,t,n){return this.toRprLE(e,t,this.mul(this.R,n))}fromRprLE(e,t){return En(e,t,this.n8)}fromRprBE(e,t){return Dn(e,t,this.n8)}fromRprLEM(e,t){return this.mul(this.fromRprLE(e,t),this.Ri)}fromRprBEM(e,t){return this.mul(this.fromRprBE(e,t),this.Ri)}toObject(e){return e}},tr=Pt({array2buffer:()=>hr,beBuff2int:()=>ir,beInt2Buff:()=>ar,bitReverse:()=>fr,buffReverseBits:()=>mr,buffer2array:()=>gr,leBuff2int:()=>or,leInt2Buff:()=>sr,log2:()=>pr,stringifyBigInts:()=>nr,stringifyFElements:()=>cr,unstringifyBigInts:()=>rr,unstringifyFElements:()=>lr});function nr(e){if(typeof e==`bigint`||e.eq!==void 0)return e.toString(10);if(e instanceof Uint8Array)return En(e,0);if(Array.isArray(e))return e.map(nr);if(typeof e==`object`){let t={};return Object.keys(e).forEach(n=>{t[n]=nr(e[n])}),t}else return e}function rr(e){if(typeof e==`string`&&/^[0-9]+$/.test(e)||typeof e==`string`&&/^0x[0-9a-fA-F]+$/.test(e))return BigInt(e);if(Array.isArray(e))return e.map(rr);if(typeof e==`object`){if(e===null)return null;let t={};return Object.keys(e).forEach(n=>{t[n]=rr(e[n])}),t}else return e}function ir(e){let t=BigInt(0),n=e.length,r=0,i=new DataView(e.buffer,e.byteOffset,e.byteLength);for(;n>0;)n>=4?(n-=4,t+=BigInt(i.getUint32(n))<=2?(n-=2,t+=BigInt(i.getUint16(n))<0;)a-4>=0?(a-=4,i.setUint32(a,Number(n&BigInt(4294967295))),n>>=BigInt(32)):a-2>=0?(a-=2,i.setUint16(a,Number(n&BigInt(65535))),n>>=BigInt(16)):(--a,i.setUint8(a,Number(n&BigInt(255))),n>>=BigInt(8));if(n)throw Error(`Number does not fit in this length`);return r}function or(e){let t=BigInt(0),n=0,r=new DataView(e.buffer,e.byteOffset,e.byteLength);for(;n>=BigInt(32)):a+2<=t?(i.setUint16(a,Number(n&BigInt(65535)),!0),a+=2,n>>=BigInt(16)):(i.setUint8(a,Number(n&BigInt(255)),!0),a+=1,n>>=BigInt(8));if(n)throw Error(`Number does not fit in this length`);return r}function cr(e,t){if(typeof t==`bigint`||t.eq!==void 0)return t.toString(10);if(t instanceof Uint8Array)return e.toString(e.e(t));if(Array.isArray(t))return t.map(cr.bind(this,e));if(typeof t==`object`){let n={};return Object.keys(t).forEach(r=>{n[r]=cr(e,t[r])}),n}else return t}function lr(e,t){if(typeof t==`string`&&/^[0-9]+$/.test(t)||typeof t==`string`&&/^0x[0-9a-fA-F]+$/.test(t))return e.e(t);if(Array.isArray(t))return t.map(lr.bind(this,e));if(typeof t==`object`){if(t===null)return null;let n={};return Object.keys(t).forEach(r=>{n[r]=lr(e,t[r])}),n}else return t}var ur=[];for(let e=0;e<256;e++)ur[e]=dr(e,8);function dr(e,t){let n=0,r=e;for(let e=0;e>=1;return n}function fr(e,t){return(ur[e>>>24]|ur[e>>>16&255]<<8|ur[e>>>8&255]<<16|ur[e&255]<<24)>>>32-t}function pr(e){return(e&4294901760?(e&=4294901760,16):0)|(e&4278255360?(e&=4278255360,8):0)|(e&4042322160?(e&=4042322160,4):0)|(e&3435973836?(e&=3435973836,2):0)|(e&2863311530)!=0}function mr(e,t){let n=e.byteLength/t,r=pr(n);if(n!=1<n){let r=e.slice(i*t,(i+1)*t);e.set(e.slice(n*t,(n+1)*t),i*t),e.set(r,n*t)}}}function hr(e,t){let n=new Uint8Array(t*e.length);for(let r=0;r0;){let t=s+c>_r?_r-s:c,n=new Uint8Array(this.buffers[o].buffer,this.buffers[o].byteOffset+s,t);if(t==r)return n.slice();a||=r<=_r?new Uint8Array(r):new e(r),a.set(n,r-c),c-=t,o++,s=0}return a}set(t,n){n===void 0&&(n=0);let r=t.byteLength;if(r==0)return;let i=Math.floor(n/_r);if(i==Math.floor((n+r-1)/_r))return t instanceof e&&t.buffers.length==1?this.buffers[i].set(t.buffers[0],n%_r):this.buffers[i].set(t,n%_r);let a=i,o=n%_r,s=r;for(;s>0;){let e=o+s>_r?_r-o:s,n=t.slice(r-s,r-s+e);new Uint8Array(this.buffers[a].buffer,this.buffers[a].byteOffset+o,e).set(n),s-=e,a++,o=0}}};function vr(e,t,n,r){return async function(i){let a=Math.floor(i.byteLength/n);if(a*n!==i.byteLength)throw Error(`Invalid buffer size`);let o=Math.floor(a/e.concurrency),s=[];for(let c=0;c=0;e--)this.w[e]=this.square(this.w[e+1]);if(!this.eq(this.w[0],this.one))throw Error(`Error calculating roots of unity`);this.batchToMontgomery=vr(e,t+`_batchToMontgomery`,this.n8,this.n8),this.batchFromMontgomery=vr(e,t+`_batchFromMontgomery`,this.n8,this.n8)}op2(e,t,n){return this.tm.setBuff(this.pOp1,t),this.tm.setBuff(this.pOp2,n),this.tm.instance.exports[this.prefix+e](this.pOp1,this.pOp2,this.pOp3),this.tm.getBuff(this.pOp3,this.n8)}op2Bool(e,t,n){return this.tm.setBuff(this.pOp1,t),this.tm.setBuff(this.pOp2,n),!!this.tm.instance.exports[this.prefix+e](this.pOp1,this.pOp2)}op1(e,t){return this.tm.setBuff(this.pOp1,t),this.tm.instance.exports[this.prefix+e](this.pOp1,this.pOp3),this.tm.getBuff(this.pOp3,this.n8)}op1Bool(e,t){return this.tm.setBuff(this.pOp1,t),!!this.tm.instance.exports[this.prefix+e](this.pOp1,this.pOp3)}add(e,t){return this.op2(`_add`,e,t)}eq(e,t){return this.op2Bool(`_eq`,e,t)}isZero(e){return this.op1Bool(`_isZero`,e)}sub(e,t){return this.op2(`_sub`,e,t)}neg(e){return this.op1(`_neg`,e)}inv(e){return this.op1(`_inverse`,e)}toMontgomery(e){return this.op1(`_toMontgomery`,e)}fromMontgomery(e){return this.op1(`_fromMontgomery`,e)}mul(e,t){return this.op2(`_mul`,e,t)}div(e,t){return this.tm.setBuff(this.pOp1,e),this.tm.setBuff(this.pOp2,t),this.tm.instance.exports[this.prefix+`_inverse`](this.pOp2,this.pOp2),this.tm.instance.exports[this.prefix+`_mul`](this.pOp1,this.pOp2,this.pOp3),this.tm.getBuff(this.pOp3,this.n8)}square(e){return this.op1(`_square`,e)}isSquare(e){return this.op1Bool(`_isSquare`,e)}sqrt(e){return this.op1(`_sqrt`,e)}exp(e,t){return t instanceof Uint8Array||(t=kn(Vt(t))),this.tm.setBuff(this.pOp1,e),this.tm.setBuff(this.pOp2,t),this.tm.instance.exports[this.prefix+`_exp`](this.pOp1,this.pOp2,t.byteLength,this.pOp3),this.tm.getBuff(this.pOp3,this.n8)}isNegative(e){return this.op1Bool(`_isNegative`,e)}e(e,t){if(e instanceof Uint8Array)return e;let n=Vt(e,t);Wt(n)?(n=rn(n),hn(n,this.p)&&(n=dn(n,this.p)),n=nn(this.p,n)):hn(n,this.p)&&(n=dn(n,this.p));let r=sr(n,this.n8);return this.toMontgomery(r)}toString(e,t){return On(En(this.fromMontgomery(e),0),t)}fromRng(e){let t,n=new Uint8Array(this.n8);do{t=An;for(let n=0;nn.buffer.byteLength){let i=n.buffer.byteLength/65536,a=Math.floor((r[0]+t)/65536)+1;a>e&&(a=e),n.grow(a-i)}return i}function l(e){let t=e instanceof Uint8Array?e:new Uint8Array(e),n=c(t.byteLength);return o().set(t,n),n}function u(e,t){return new Uint8Array(n.buffer,e,t)}function d(e,t){o().set(t instanceof Uint8Array?t:new Uint8Array(t),e)}function f(e){if(e[0].cmd===`INIT`)return s(e[0]);let n=[],r=[],i=a()[0];for(let i=0;i{(function(n,r){typeof e==`object`&&t!==void 0?r(e):typeof define==`function`&&define.amd?define([`exports`],r):(n=typeof globalThis<`u`?globalThis:n||self,r(n.workerpool={}))})(e,(function(e){"use strict";var t={},n={exports:{}};(function(e){var t=function(e){return e!==void 0&&e.versions!=null&&e.versions.node!=null&&e+``==`[object process]`};e.exports.isNode=t,e.exports.platform=typeof process<`u`&&t(process)?`node`:`browser`;var n=e.exports.platform===`node`&&Kn();e.exports.isMainThread=e.exports.platform===`node`?(!n||n.isMainThread)&&!process.connected:typeof Window<`u`,e.exports.cpus=e.exports.platform===`browser`?self.navigator.hardwareConcurrency:Kn().cpus().length})(n);var r=n.exports;function i(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:i}}throw TypeError(`Invalid attempt to iterate non-iterable instance. -In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var a,o=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return o=e.done,e},e:function(e){s=!0,a=e},f:function(){try{o||n.return==null||n.return()}finally{if(s)throw a}}}}function d(e,t,n){return(t=x(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function f(e){return f=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},f(e)}function p(e,t){if(typeof t!=`function`&&t!==null)throw TypeError(`Super expression must either be null or a function`);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,`prototype`,{writable:!1}),t&&y(e,t)}function m(e){try{return Function.toString.call(e).indexOf(`[native code]`)!==-1}catch{return typeof e==`function`}}function h(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch{}return(h=function(){return!!e})()}function g(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function _(e){for(var t=1;t= 11.7.0 required`);return e}function re(){if(typeof Worker!=`function`&&((typeof Worker>`u`?`undefined`:S(Worker))!==`object`||typeof Worker.prototype.constructor!=`function`))throw Error(`WorkerPool: Web Workers not supported`)}function ie(){try{return Kn()}catch(e){if(S(e)===`object`&&e!==null&&e.code===`MODULE_NOT_FOUND`)return null;throw e}}function ae(){if(P.platform===`browser`){if(typeof Blob>`u`)throw Error(`Blob not supported by the browser`);if(!window.URL||typeof window.URL.createObjectURL!=`function`)throw Error(`URL.createObjectURL not supported by the browser`);var e=new Blob([M()],{type:`text/javascript`});return window.URL.createObjectURL(e)}else return __dirname+`/worker.js`}function oe(e,t){if(t.workerType===`web`)return re(),se(e,t.workerOpts,Worker);if(t.workerType===`thread`)return n=ne(),ce(e,n,t);if(t.workerType===`process`||!t.workerType)return le(e,ue(t),Kn());if(P.platform===`browser`)return re(),se(e,t.workerOpts,Worker);var n=ie();return n?ce(e,n,t):le(e,ue(t),Kn())}function se(e,t,n){F(t,ee,`workerOpts`);var r=new n(e,t);return r.isBrowserWorker=!0,r.on=function(e,t){this.addEventListener(e,function(e){t(e.data)})},r.send=function(e,t){this.postMessage(e,t)},r}function ce(e,t,n){F(n?.workerThreadOpts,L,`workerThreadOpts`);var r=new t.Worker(e,_({stdout:n?.emitStdStreams??!1,stderr:n?.emitStdStreams??!1},n?.workerThreadOpts));return r.isWorkerThread=!0,r.send=function(e,t){this.postMessage(e,t)},r.kill=function(){return this.terminate(),!0},r.disconnect=function(){this.terminate()},n!=null&&n.emitStdStreams&&(r.stdout.on(`data`,function(e){return r.emit(`stdout`,e)}),r.stderr.on(`data`,function(e){return r.emit(`stderr`,e)})),r}function le(e,t,n){F(t.forkOpts,I,`forkOpts`);var r=n.fork(e,t.forkArgs,t.forkOpts),i=r.send;return r.send=function(e){return i.call(r,e)},t.emitStdStreams&&(r.stdout.on(`data`,function(e){return r.emit(`stdout`,e)}),r.stderr.on(`data`,function(e){return r.emit(`stderr`,e)})),r.isChildProcess=!0,r}function ue(e){e||={};var t=process.execArgv.join(` `),n=t.indexOf(`--inspect`)!==-1,r=t.indexOf(`--debug-brk`)!==-1,i=[];return n&&(i.push(`--inspect=`+e.debugPort),r&&i.push(`--debug-brk`)),process.execArgv.forEach(function(e){e.indexOf(`--max-old-space-size`)>-1&&i.push(e)}),Object.assign({},e,{forkArgs:e.forkArgs,forkOpts:Object.assign({},e.forkOpts,{execArgv:(e.forkOpts&&e.forkOpts.execArgv||[]).concat(i),stdio:e.emitStdStreams?`pipe`:void 0})})}function de(e){for(var t=Error(``),n=Object.keys(e),r=0;r0},pe.prototype.terminate=function(e,t){var n=this;if(e){for(var r in this.processing)this.processing[r]!==void 0&&this.processing[r].resolver.reject(Error(`Worker terminated`));this.processing=Object.create(null)}for(var i=0,a=Object.values(n.tracking);i=e)throw Error(`WorkerPool debug port limit reached: `+t+`>= `+e);return this.ports[t]=!0,this.length++,t},t.prototype.releasePort=function(e){delete this.ports[e],this.length--},z}var Se,Ce;function we(){if(Ce)return Se;Ce=1;var e=O().Promise,t=ge,n=r,i=ye(),a=i.FIFOQueue,o=i.LIFOQueue,s=new(xe());function c(e,r){typeof e==`string`?this.script=e||null:(this.script=null,r=e),this.workers=[],this.taskQueue=this._createQueue(r&&r.queueStrategy||`fifo`),r||={},this.forkArgs=Object.freeze(r.forkArgs||[]),this.forkOpts=Object.freeze(r.forkOpts||{}),this.workerOpts=Object.freeze(r.workerOpts||{}),this.workerThreadOpts=Object.freeze(r.workerThreadOpts||{}),this.debugPortStart=r.debugPortStart||43210,this.nodeWorker=r.nodeWorker,this.workerType=r.workerType||r.nodeWorker||`auto`,this.maxQueueSize=r.maxQueueSize||1/0,this.workerTerminateTimeout=r.workerTerminateTimeout||1e3,this.onCreateWorker=r.onCreateWorker||function(){return null},this.onTerminateWorker=r.onTerminateWorker||function(){return null},this.emitStdStreams=r.emitStdStreams||!1,r&&`maxWorkers`in r?(l(r.maxWorkers),this.maxWorkers=r.maxWorkers):this.maxWorkers=Math.max((n.cpus||4)-1,1),r&&`minWorkers`in r&&(r.minWorkers===`max`?this.minWorkers=this.maxWorkers:(u(r.minWorkers),this.minWorkers=r.minWorkers,this.maxWorkers=Math.max(this.minWorkers,this.maxWorkers)),this._ensureMinWorkers()),this._boundNext=this._next.bind(this),this.workerType===`thread`&&t.ensureWorkerThreads()}c.prototype.exec=function(t,n,r){if(n&&!Array.isArray(n))throw TypeError(`Array expected as argument "params"`);if(typeof t==`string`){var i=e.defer();if(this.taskQueue.size()>=this.maxQueueSize)throw Error(`Max queue size of `+this.maxQueueSize+` reached`);var a={method:t,params:n,resolver:i,timeout:null,options:r};this.taskQueue.push(a);var o=i.promise.timeout,s=this.taskQueue;return i.promise.timeout=function(e){return s.contains(a)?(a.timeout=e,i.promise):o.call(i.promise,e)},this._next(),i.promise}else if(typeof t==`function`)return this.exec(`run`,[String(t),n],r);else throw TypeError(`Function or string expected as argument "method"`)},c.prototype.proxy=function(){if(arguments.length>0)throw Error(`No arguments expected`);var e=this;return this.exec(`methods`).then(function(t){var n={};return t.forEach(function(t){n[t]=function(){return e.exec(t,Array.prototype.slice.call(arguments))}}),n})},c.prototype._next=function(){if(this.taskQueue.size()>0){var e=this._getWorker();if(e){var t=this,n=this.taskQueue.pop();if(n.resolver.promise.pending){var r=e.exec(n.method,n.params,n.resolver,n.options).then(t._boundNext).catch(function(){if(e.terminated)return t._removeWorker(e)}).then(function(){t._next()});typeof n.timeout==`number`&&r.timeout(n.timeout)}else t._next()}}},c.prototype._getWorker=function(){for(var e=this.workers,t=0;t0;){var a=i.pop();if(a)a.resolver.reject(Error(`Pool terminated`));else break}i.clear();var o=function(e){s.releasePort(e.debugPort),this._removeWorkerFromList(e)}.bind(this),c=[];return this.workers.slice().forEach(function(e){var i=e.terminateAndNotify(t,n).then(o).always(function(){r.onTerminateWorker({forkArgs:e.forkArgs,forkOpts:e.forkOpts,workerThreadOpts:e.workerThreadOpts,script:e.script})});c.push(i)}),e.all(c)},c.prototype.stats=function(){var e=this.workers.length,t=this.workers.filter(function(e){return e.busy()}).length;return{totalWorkers:e,busyWorkers:t,idleWorkers:e-t,pendingTasks:this.taskQueue.size(),activeTasks:t}},c.prototype._ensureMinWorkers=function(){if(this.minWorkers)for(var e=this.workers.length;e= 1`)}function u(e){if(!d(e)||!f(e)||e<0)throw TypeError(`Option minWorkers must be an integer number >= 0`)}function d(e){return typeof e==`number`}function f(e){return Math.round(e)==e}return Se=c,Se}var Te={},Ee,De;function Oe(){if(De)return Ee;De=1;function e(e,t){this.message=e,this.transfer=t}return Ee=e,Ee}var ke;function Ae(){return ke?Te:(ke=1,(function(e){var t=Oe(),n=O().Promise,r=`__workerpool-terminate__`,i=`__workerpool-cleanup__`,a=1e3,o={exit:function(){}},s={addAbortListener:function(e){o.abortListeners.push(e)},emit:o.emit};if(typeof self<`u`&&typeof postMessage==`function`&&typeof addEventListener==`function`)o.on=function(e,t){addEventListener(e,function(e){t(e.data)})},o.send=function(e,t){t?postMessage(e,t):postMessage(e)};else if(typeof process<`u`){var c;try{c=Kn()}catch(e){if(!(S(e)===`object`&&e!==null&&e.code===`MODULE_NOT_FOUND`))throw e}if(c&&c.parentPort!==null){var l=c.parentPort;o.send=l.postMessage.bind(l),o.on=l.on.bind(l),o.exit=process.exit.bind(process)}else o.on=process.on.bind(process),o.send=function(e){process.send(e)},o.on(`disconnect`,function(){process.exit(1)}),o.exit=process.exit.bind(process)}else throw Error(`Script must be executed as a worker`);function u(e){return e&&e.toJSON?JSON.parse(JSON.stringify(e)):JSON.parse(JSON.stringify(e,Object.getOwnPropertyNames(e)))}function d(e){return e&&typeof e.then==`function`&&typeof e.catch==`function`}o.methods={},o.methods.run=function(e,t){var n=Function(`return (`+e+`).apply(this, arguments);`);return n.worker=s,n.apply(n,t)},o.methods.methods=function(){return Object.keys(o.methods)},o.terminationHandler=void 0,o.abortListenerTimeout=a,o.abortListeners=[],o.terminateAndExit=function(e){var t=function(){o.exit(e)};if(!o.terminationHandler)return t();var r=o.terminationHandler(e);return d(r)?(r.then(t,t),r):(t(),new n(function(e,t){t(Error(`Worker terminating`))}))},o.cleanup=function(e){if(!o.abortListeners.length)return o.send({id:e,method:i,error:u(Error(`Worker terminating`))}),new n(function(e){e()});var t=function(){o.exit()},r=function(){o.abortListeners.length||(o.abortListeners=[])},a=o.abortListeners.map(function(e){return e()}),s,c=new n(function(e,t){s=setTimeout(function(){t(Error(`Timeout occured waiting for abort handler, killing worker`))},o.abortListenerTimeout)}),l=n.all(a).then(function(){clearTimeout(s),r()},function(){clearTimeout(s),t()});return new n(function(e,t){l.then(e,t),c.then(e,t)}).then(function(){o.send({id:e,method:i,error:null})},function(t){o.send({id:e,method:i,error:t?u(t):null})})};var f=null;o.on(`message`,function(e){if(e===r)return o.terminateAndExit(0);if(e.method===i)return o.cleanup(e.id);try{var n=o.methods[e.method];if(n){f=e.id;var a=n.apply(n,e.params);d(a)?a.then(function(n){n instanceof t?o.send({id:e.id,result:n.message,error:null},n.transfer):o.send({id:e.id,result:n,error:null}),f=null}).catch(function(t){o.send({id:e.id,result:null,error:u(t)}),f=null}):(a instanceof t?o.send({id:e.id,result:a.message,error:null},a.transfer):o.send({id:e.id,result:a,error:null}),f=null)}else throw Error(`Unknown method "`+e.method+`"`)}catch(t){o.send({id:e.id,result:null,error:u(t)})}}),o.register=function(e,t){if(e)for(var n in e)e.hasOwnProperty(n)&&(o.methods[n]=e[n],o.methods[n].worker=s);t&&(o.terminationHandler=t.onTerminate,o.abortListenerTimeout=t.abortListenerTimeout||a),o.send(`ready`)},o.emit=function(e){if(f){if(e instanceof t){o.send({id:f,isEvent:!0,payload:e.message},e.transfer);return}o.send({id:f,isEvent:!0,payload:e})}},e.add=o.register,e.emit=o.emit})(Te),Te)}var je=r.platform,Me=r.isMainThread,Ne=r.cpus,Pe=ge.TerminateError;function Fe(e,t){return new(we())(e,t)}var Ie=t.pool=Fe;function Le(e,t){Ae().add(e,t)}var Re=t.worker=Le;function ze(e){Ae().emit(e)}var Be=t.workerEmit=ze,Ve=t.Promise=O().Promise,He=t.Transfer=Oe(),Ue=t.platform=je,We=t.isMainThread=Me,Ge=t.cpus=Ne,Ke=t.TerminateError=Pe;e.Promise=Ve,e.TerminateError=Ke,e.Transfer=He,e.cpus=Ge,e.default=t,e.isMainThread=We,e.platform=Ue,e.pool=Ie,e.worker=Re,e.workerEmit=Be,Object.defineProperty(e,`__esModule`,{value:!0})}))}))(),1),Tr=`!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e="undefined"!=typeof globalThis?globalThis:e||self).worker=n()}(this,(function(){"use strict";function e(n){return e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e(n)}function n(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var t={};var r=function(e,n){this.message=e,this.transfer=n},o={};function i(e,n){var t=this;if(!(this instanceof i))throw new SyntaxError("Constructor must be called with the new operator");if("function"!=typeof e)throw new SyntaxError("Function parameter handler(resolve, reject) missing");var r=[],o=[];this.resolved=!1,this.rejected=!1,this.pending=!0,this[Symbol.toStringTag]="Promise";var a=function(e,n){r.push(e),o.push(n)};this.then=function(e,n){return new i((function(t,r){var o=e?s(e,t,r):t,i=n?s(n,t,r):r;a(o,i)}),t)};var f=function(e){return t.resolved=!0,t.rejected=!1,t.pending=!1,r.forEach((function(n){n(e)})),a=function(n,t){n(e)},f=d=function(){},t},d=function(e){return t.resolved=!1,t.rejected=!0,t.pending=!1,o.forEach((function(n){n(e)})),a=function(n,t){t(e)},f=d=function(){},t};this.cancel=function(){return n?n.cancel():d(new u),t},this.timeout=function(e){if(n)n.timeout(e);else{var r=setTimeout((function(){d(new c("Promise timed out after "+e+" ms"))}),e);t.always((function(){clearTimeout(r)}))}return t},e((function(e){f(e)}),(function(e){d(e)}))}function s(e,n,t){return function(r){try{var o=e(r);o&&"function"==typeof o.then&&"function"==typeof o.catch?o.then(n,t):n(o)}catch(e){t(e)}}}function u(e){this.message=e||"promise cancelled",this.stack=(new Error).stack}function c(e){this.message=e||"timeout exceeded",this.stack=(new Error).stack}return i.prototype.catch=function(e){return this.then(null,e)},i.prototype.always=function(e){return this.then(e,e)},i.prototype.finally=function(e){var n=this,t=function(){return new i((function(e){return e()})).then(e).then((function(){return n}))};return this.then(t,t)},i.all=function(e){return new i((function(n,t){var r=e.length,o=[];r?e.forEach((function(e,i){e.then((function(e){o[i]=e,0==--r&&n(o)}),(function(e){r=0,t(e)}))})):n(o)}))},i.defer=function(){var e={};return e.promise=new i((function(n,t){e.resolve=n,e.reject=t})),e},u.prototype=new Error,u.prototype.constructor=Error,u.prototype.name="CancellationError",i.CancellationError=u,c.prototype=new Error,c.prototype.constructor=Error,c.prototype.name="TimeoutError",i.TimeoutError=c,o.Promise=i,function(n){var t=r,i=o.Promise,s="__workerpool-cleanup__",u={exit:function(){}},c={addAbortListener:function(e){u.abortListeners.push(e)},emit:u.emit};if("undefined"!=typeof self&&"function"==typeof postMessage&&"function"==typeof addEventListener)u.on=function(e,n){addEventListener(e,(function(e){n(e.data)}))},u.send=function(e,n){n?postMessage(e,n):postMessage(e)};else{if("undefined"==typeof process)throw new Error("Script must be executed as a worker");var a;try{a=require("worker_threads")}catch(n){if("object"!==e(n)||null===n||"MODULE_NOT_FOUND"!==n.code)throw n}if(a&&null!==a.parentPort){var f=a.parentPort;u.send=f.postMessage.bind(f),u.on=f.on.bind(f),u.exit=process.exit.bind(process)}else u.on=process.on.bind(process),u.send=function(e){process.send(e)},u.on("disconnect",(function(){process.exit(1)})),u.exit=process.exit.bind(process)}function d(e){return e&&e.toJSON?JSON.parse(JSON.stringify(e)):JSON.parse(JSON.stringify(e,Object.getOwnPropertyNames(e)))}function l(e){return e&&"function"==typeof e.then&&"function"==typeof e.catch}u.methods={},u.methods.run=function(e,n){var t=new Function("return ("+e+").apply(this, arguments);");return t.worker=c,t.apply(t,n)},u.methods.methods=function(){return Object.keys(u.methods)},u.terminationHandler=void 0,u.abortListenerTimeout=1e3,u.abortListeners=[],u.terminateAndExit=function(e){var n=function(){u.exit(e)};if(!u.terminationHandler)return n();var t=u.terminationHandler(e);return l(t)?(t.then(n,n),t):(n(),new i((function(e,n){n(new Error("Worker terminating"))})))},u.cleanup=function(e){if(!u.abortListeners.length)return u.send({id:e,method:s,error:d(new Error("Worker terminating"))}),new i((function(e){e()}));var n,t=u.abortListeners.map((function(e){return e()})),r=new i((function(e,t){n=setTimeout((function(){t(new Error("Timeout occured waiting for abort handler, killing worker"))}),u.abortListenerTimeout)})),o=i.all(t).then((function(){clearTimeout(n),u.abortListeners.length||(u.abortListeners=[])}),(function(){clearTimeout(n),u.exit()}));return new i((function(e,n){o.then(e,n),r.then(e,n)})).then((function(){u.send({id:e,method:s,error:null})}),(function(n){u.send({id:e,method:s,error:n?d(n):null})}))};var p=null;u.on("message",(function(e){if("__workerpool-terminate__"===e)return u.terminateAndExit(0);if(e.method===s)return u.cleanup(e.id);try{var n=u.methods[e.method];if(!n)throw new Error('Unknown method "'+e.method+'"');p=e.id;var r=n.apply(n,e.params);l(r)?r.then((function(n){n instanceof t?u.send({id:e.id,result:n.message,error:null},n.transfer):u.send({id:e.id,result:n,error:null}),p=null})).catch((function(n){u.send({id:e.id,result:null,error:d(n)}),p=null})):(r instanceof t?u.send({id:e.id,result:r.message,error:null},r.transfer):u.send({id:e.id,result:r,error:null}),p=null)}catch(n){u.send({id:e.id,result:null,error:d(n)})}})),u.register=function(e,n){if(e)for(var t in e)e.hasOwnProperty(t)&&(u.methods[t]=e[t],u.methods[t].worker=c);n&&(u.terminationHandler=n.onTerminate,u.abortListenerTimeout=n.abortListenerTimeout||1e3),u.send("ready")},u.emit=function(e){if(p){if(e instanceof t)return void u.send({id:p,isEvent:!0,payload:e.message},e.transfer);u.send({id:p,isEvent:!0,payload:e})}},n.add=u.register,n.emit=u.emit}(t),n(t)})); - -;(function(){ -var runTask=(function thread() { - const MAXMEM = 32767; - let instance; - let memory; - - // Lazily cached typed-array views over wasm memory. - // Invalidated automatically when memory.grow() replaces memory.buffer. - let _u32 = null; - let _u8 = null; - - function getU32() { - if (_u32 === null || _u32.buffer !== memory.buffer) { - _u32 = new Uint32Array(memory.buffer, 0, 1); - } - return _u32; - } - - function getU8() { - if (_u8 === null || _u8.buffer !== memory.buffer) { - _u8 = new Uint8Array(memory.buffer); - } - return _u8; - } - - async function init(data) { - let wasmModule; - if (data.code instanceof WebAssembly.Module) { - wasmModule = data.code; - } else { - wasmModule = await WebAssembly.compile(new Uint8Array(data.code)); - } - memory = new WebAssembly.Memory({initial: data.init, maximum: MAXMEM}); - // Reset cached views — new memory means new backing buffer. - _u32 = null; - _u8 = null; - instance = await WebAssembly.instantiate(wasmModule, {env: {memory}}); - } - - function alloc(length) { - const u32 = getU32(); - // Align to 4 bytes with a branchless bitmask instead of a loop. - u32[0] = (u32[0] + 3) & ~3; - const res = u32[0]; - u32[0] += length; - if (u32[0] + length > memory.buffer.byteLength) { - const currentPages = memory.buffer.byteLength / 0x10000; - let requiredPages = Math.floor((u32[0] + length) / 0x10000) + 1; - if (requiredPages > MAXMEM) requiredPages = MAXMEM; - memory.grow(requiredPages - currentPages); - // memory.buffer changed — cached views are now stale. - } - return res; - } - - function allocBuffer(buffer) { - const src = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer); - const p = alloc(src.byteLength); - // getU8() handles re-creation if alloc() triggered a grow. - getU8().set(src, p); - return p; - } - - function getBuffer(pointer, length) { - return new Uint8Array(memory.buffer, pointer, length); - } - - function setBuffer(pointer, buffer) { - getU8().set(buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer), pointer); - } - - function runTask(task) { - if (task[0].cmd === "INIT") { - // INIT is the only async path — return a Promise so workerpool - // can await it; all other tasks execute synchronously to prevent - // concurrent execution of tasks within the same worker. - return init(task[0]); - } - const vars = []; - const out = []; - const oldAlloc = getU32()[0]; - for (let i = 0; i < task.length; i++) { - const step = task[i]; - switch (step.cmd) { - case "ALLOCSET": - vars[step.var] = allocBuffer(step.buff); - break; - case "ALLOC": - vars[step.var] = alloc(step.len); - break; - case "SET": - setBuffer(vars[step.var], step.buff); - break; - case "CALL": { - const paramDefs = step.params; - const params = new Array(paramDefs.length); - for (let j = 0; j < paramDefs.length; j++) { - const p = paramDefs[j]; - params[j] = p.var !== undefined - ? vars[p.var] + (p.offset || 0) - : p.val; - } - instance.exports[step.fnName](...params); - break; - } - case "GET": - out[step.out] = getBuffer(vars[step.var], step.len).slice(); - break; - default: - throw new Error("Invalid cmd: " + step.cmd); - } - } - // Reclaim task-local allocations. getU32() handles a post-grow buffer. - getU32()[0] = oldAlloc; - return out; - } - - return runTask; -})(); -worker.add({runTask:runTask}); -})();`;function Er(){return typeof navigator==`object`&&navigator.hardwareConcurrency||2}function Dr(){return`web`}function Or(){return typeof Worker<`u`}var kr=null;function Ar(){if(kr)return kr;let e=new Blob([Tr],{type:`application/javascript`});return kr=(globalThis.URL?globalThis.URL:globalThis.webkitURL).createObjectURL(e),kr}var jr=25;async function Mr(e,t){let n=new Nr;n.memory=new WebAssembly.Memory({initial:jr}),n.u8=new Uint8Array(n.memory.buffer),n.u32=new Uint32Array(n.memory.buffer);let r=await WebAssembly.compile(e.code);if(n.instance=await WebAssembly.instantiate(r,{env:{memory:n.memory}}),Or()||(t=!0),n.singleThread=t,n.initalPFree=n.u32[0],n.pq=e.pq,n.pr=e.pr,n.pG1gen=e.pG1gen,n.pG1zero=e.pG1zero,n.pG2gen=e.pG2gen,n.pG2zero=e.pG2zero,n.pOneT=e.pOneT,n.code=e.code,n.wasmModule=r,t)n.taskManager=Cr(),await n.taskManager([{cmd:`INIT`,init:jr,code:n.code.slice()}]),n.concurrency=1;else{let e=Er(),t=Math.min(Math.max(e,2),64);n.concurrency=t,n.pool=wr.default.pool(Ar(),{maxWorkers:t,workerType:Dr()});let r=[];for(let e=0;e=0;e--){if(!n.isZero(h))for(let e=0;el&&(_=l),_(s&&s.debug(`Multiexp end: ${c}: ${t}/${f}`),e)))}let v=await Promise.all(m),y=n.zero;for(let e=v.length-1;e>=0;e--)y=n.add(y,v[e]);return y}n.multiExp=async function(e,t,n,r){return a(e,t,`jacobian`,n,r)},n.multiExpAffine=async function(e,t,n,r){return a(e,t,`affine`,n,r)}}function Rr(e,t){let n=e[t],r=e.Fr,i=n.tm;async function a(e,a,c,l,u,d){c||=`affine`,l||=`affine`;let f,p,m,h,g,_,v,y,b;t==`G1`?(c==`affine`?(f=n.F.n8*2,h=`g1m_batchToJacobian`):f=n.F.n8*3,p=n.F.n8*3,a&&(y=`g1m_fftFinal`),v=`g1m_fftJoin`,_=`g1m_fftMix`,b=`g1m__reversePermutation`,l==`affine`?(m=n.F.n8*2,g=`g1m_batchToAffine`):m=n.F.n8*3):t==`G2`?(c==`affine`?(f=n.F.n8*2,h=`g2m_batchToJacobian`):f=n.F.n8*3,p=n.F.n8*3,a&&(y=`g2m_fftFinal`),v=`g2m_fftJoin`,_=`g2m_fftMix`,b=`g2m__reversePermutation`,l==`affine`?(m=n.F.n8*2,g=`g2m_batchToAffine`):m=n.F.n8*3):t==`Fr`&&(f=n.n8,p=n.n8,m=n.n8,a&&(y=`frm_fftFinal`),_=`frm_fftMix`,v=`frm_fftJoin`,b=`frm__reversePermutation`);let x=!1;Array.isArray(e)?(e=hr(e,f),x=!0):e=e.slice(0,e.byteLength);let S=e.byteLength/f,C=pr(S);if(1<=16;)O*=2,D/=2;let k=pr(D),A=[];u&&u.debug(`${d}: fft ${C} mix start: ${O}`);for(let t=0;t0;t--)T.set(E[t],e),e+=D*m,delete E[t];T.set(E[0].slice(0,(D-1)*m),e),delete E[0]}else for(let e=0;e1<<28?new B(d[0].byteLength*2):new Uint8Array(d[0].byteLength*2),f.set(d[0]),f.set(d[1],d[0].byteLength),f}async function s(e,t,n,i,o){let s,l;s=e.slice(0,e.byteLength/2),l=e.slice(e.byteLength/2,e.byteLength);let u=[];u.push(a(s,!0,t,`jacobian`,i,o)),u.push(a(l,!0,t,`jacobian`,i,o)),[s,l]=await Promise.all(u);let d=await c(s,l,`fftJoinExtInv`,r.one,r.shiftInv,`jacobian`,n,i,o),f;return f=d[0].byteLength>1<<28?new B(d[0].byteLength*2):new Uint8Array(d[0].byteLength*2),f.set(d[0]),f.set(d[1],d[0].byteLength),f}async function c(e,a,o,s,c,l,u,d,f){let p=65536,m,h,g,_,v,y;if(t==`G1`)l==`affine`?(v=n.F.n8*2,h=`g1m_batchToJacobian`):v=n.F.n8*3,y=n.F.n8*3,m=`g1m_`+o,u==`affine`?(g=`g1m_batchToAffine`,_=n.F.n8*2):_=n.F.n8*3;else if(t==`G2`)l==`affine`?(v=n.F.n8*2,h=`g2m_batchToJacobian`):v=n.F.n8*3,m=`g2m_`+o,y=n.F.n8*3,u==`affine`?(g=`g2m_batchToAffine`,_=n.F.n8*2):_=n.F.n8*3;else if(t==`Fr`)v=r.n8,_=r.n8,y=r.n8,m=`frm_`+o;else throw Error(`Invalid group`);if(e.byteLength!=a.byteLength)throw Error(`Invalid buffer size`);let b=Math.floor(e.byteLength/v);if(b!=1<p&&(x=p);let S=[];for(let t=0;t(d&&d.debug(`${f}: fftJoinExt End: ${t}/${b}`),e)))}let C=await Promise.all(S),w,T;b*_>1<<28?(w=new B(b*_),T=new B(b*_)):(w=new Uint8Array(b*_),T=new Uint8Array(b*_));let E=0;for(let e=0;er.s+1)throw s&&s.error(`lagrangeEvaluations input too big`),Error(`lagrangeEvaluations input too big`);let p=e.slice(0,e.byteLength/2),m=e.slice(e.byteLength/2,e.byteLength),h=r.exp(r.shift,d/2),g=r.inv(r.sub(r.one,h));[p,m]=await c(p,m,`prepareLagrangeEvaluation`,g,r.shiftInv,i,`jacobian`,s,l+` prep`);let _=[];_.push(a(p,!0,`jacobian`,o,s,l+` t0`)),_.push(a(m,!0,`jacobian`,o,s,l+` t1`)),[p,m]=await Promise.all(_);let v;return v=p.byteLength>1<<28?new B(p.byteLength*2):new Uint8Array(p.byteLength*2),v.set(p),v.set(m,p.byteLength),v},n.fftMix=async function(e){let a=n.F.n8*3,o,s;if(t==`G1`)o=`g1m_fftMix`,s=`g1m_fftJoin`;else if(t==`G2`)o=`g2m_fftMix`,s=`g2m_fftJoin`;else if(t==`Fr`)o=`frm_fftMix`,s=`frm_fftJoin`;else throw Error(`Invalid group`);let c=Math.floor(e.byteLength/a),l=pr(c),u=1<=0;e--)p.set(f[e][0],m),m+=f[e][0].byteLength;return p}}async function zr(e){let t=await Mr(e.wasm,e.singleThread),n={};return n.q=Vt(e.wasm.q.toString()),n.r=Vt(e.wasm.r.toString()),n.name=e.name,n.tm=t,n.prePSize=e.wasm.prePSize,n.preQSize=e.wasm.preQSize,n.Fr=new yr(t,`frm`,e.n8r,e.r),n.F1=new yr(t,`f1m`,e.n8q,e.q),n.F2=new br(t,`f2m`,n.F1),n.G1=new Sr(t,`g1m`,n.F1,e.wasm.pG1gen,e.wasm.pG1b,e.cofactorG1),n.G2=new Sr(t,`g2m`,n.F2,e.wasm.pG2gen,e.wasm.pG2b,e.cofactorG2),n.F6=new xr(t,`f6m`,n.F2),n.F12=new br(t,`ftm`,n.F6),n.Gt=n.F12,Pr(n,`G1`),Pr(n,`G2`),Pr(n,`Fr`),Lr(n,`G1`),Lr(n,`G2`),Rr(n,`G1`),Rr(n,`G2`),Rr(n,`Fr`),Fr(n),n.array2buffer=function(e,t){let n=new Uint8Array(t*e.length);for(let r=0;r(ye(),ve)),{buildBn128:r}=await Promise.resolve().then(()=>(Et(),Tt)),i=new e;i.setMemory(25),r(i),t&&t(i),n.code=i.build(),n.pq=i.modules.f1m.pq,n.pr=i.modules.frm.pq,n.pG1gen=i.modules.bn128.pG1gen,n.pG1zero=i.modules.bn128.pG1zero,n.pG1b=i.modules.bn128.pG1b,n.pG2gen=i.modules.bn128.pG2gen,n.pG2zero=i.modules.bn128.pG2zero,n.pG2b=i.modules.bn128.pG2b,n.pOneT=i.modules.bn128.pOneT,n.prePSize=i.modules.bn128.prePSize,n.preQSize=i.modules.bn128.preQSize,n.n8q=32,n.n8r=32,n.q=i.modules.bn128.q,n.r=i.modules.bn128.r}else{console.log(`Using prebuilt bn128 wasm`);let e=await Promise.resolve().then(()=>(T(),f));n.pq=e.pq,n.pr=e.pr,n.pG1gen=e.pG1gen,n.pG1zero=e.pG1zero,n.pG1b=e.pG1b,n.pG2gen=e.pG2gen,n.pG2zero=e.pG2zero,n.pG2b=e.pG2b,n.pOneT=e.pOneT,n.prePSize=e.prePSize,n.preQSize=e.preQSize,n.n8q=32,n.n8r=32,n.q=e.q,n.r=e.r;let t=Uint8Array.from(atob(e.gzipCode),e=>e.charCodeAt(0)),r=new Blob([t]),i=new DecompressionStream(`gzip`),a=r.stream().pipeThrough(i);n.code=await new Response(a).bytes()}let r={name:`bn128`,wasm:n,q:Vt(`21888242871839275222246405745257275088696311157297823662689037894645226208583`),r:Vt(`21888242871839275222246405745257275088548364400416034343698204186575808495617`),n8q:32,n8r:32,cofactorG2:Vt(`30644e72e131a029b85045b68181585e06ceecda572a2489345f2299c0f9fa8d`,16),singleThread:!!e},i=await zr(r);return i.terminate=async function(){r.singleThread||(globalThis.curve_bn128=null,await this.tm.terminate())},e||(globalThis.curve_bn128=i),i}globalThis.curve_bls12381=null;async function Vr(e,t){if(!e&&globalThis.curve_bls12381)return globalThis.curve_bls12381;let{ModuleBuilder:n}=await Promise.resolve().then(()=>(ye(),ve)),{buildBls12381:r}=await Promise.resolve().then(()=>(Et(),Tt)),i=new n;i.setMemory(25),r(i),t&&t(i);let a={};a.code=i.build(),a.pq=i.modules.f1m.pq,a.pr=i.modules.frm.pq,a.pG1gen=i.modules.bls12381.pG1gen,a.pG1zero=i.modules.bls12381.pG1zero,a.pG1b=i.modules.bls12381.pG1b,a.pG2gen=i.modules.bls12381.pG2gen,a.pG2zero=i.modules.bls12381.pG2zero,a.pG2b=i.modules.bls12381.pG2b,a.pOneT=i.modules.bls12381.pOneT,a.prePSize=i.modules.bls12381.prePSize,a.preQSize=i.modules.bls12381.preQSize,a.n8q=48,a.n8r=32,a.q=i.modules.bls12381.q,a.r=i.modules.bls12381.r;let o={name:`bls12381`,wasm:a,q:Vt(`1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab`,16),r:Vt(`73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001`,16),n8q:48,n8r:32,cofactorG1:Vt(`0x396c8c005555e1568c00aaab0000aaab`,16),cofactorG2:Vt(`0x5d543a95414e7f1091d50792876a202cd91de4547085abaa68a205b2e5a7ddfa628f1cb4d9e82ef21537e293a6691ae1616ec6e786f0c70cf1c38e31c7238e5`,16),singleThread:!!e},s=await zr(o);return s.terminate=async function(){o.singleThread||(globalThis.curve_bls12381=null,await this.tm.terminate())},e||(globalThis.curve_bls12381=s),s}var Hr=Vt(`73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001`,16),Ur=Vt(`21888242871839275222246405745257275088548364400416034343698204186575808495617`);Vt(`1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab`,16),Vt(`21888242871839275222246405745257275088696311157297823662689037894645226208583`);async function Wr(e,t,n){let r;if(fn(e,Ur))r=await Br(t,n);else if(fn(e,Hr))r=await Vr(t,n);else throw Error(`Curve not supported: ${On(e)}`);return r}var V=Rt,Gr=tr;function Kr(e){let t=e.initialSize||1<<20,n=new Qr;return n.o=e,n.o.data=new Uint8Array(t),n.allocSize=t,n.totalSize=0,n.readOnly=!1,n.pos=0,n}function qr(e){let t=new Qr;return t.o=e,t.allocSize=e.data.byteLength,t.totalSize=e.data.byteLength,t.readOnly=!0,t.pos=0,t}var Jr=new Uint8Array(4),Yr=new DataView(Jr.buffer),Xr=new Uint8Array(8),Zr=new DataView(Xr.buffer),Qr=class{constructor(){this.pageSize=16384}_resizeIfNeeded(e){if(e>this.allocSize){let t=Math.max(this.allocSize+(1<<20),Math.floor(this.allocSize*1.1),e),n=new Uint8Array(t);n.set(this.o.data),this.o.data=n,this.allocSize=t}}async write(e,t){if(t===void 0&&(t=this.pos),this.readOnly)throw Error(`Writing a read only file`);this._resizeIfNeeded(t+e.byteLength),this.o.data.set(e.slice(),t),t+e.byteLength>this.totalSize&&(this.totalSize=t+e.byteLength),this.pos=t+e.byteLength}async readToBuffer(e,t,n,r){if(r===void 0&&(r=this.pos),this.readOnly&&r+n>this.totalSize)throw Error(`Reading out of bounds`);this._resizeIfNeeded(r+n);let i=new Uint8Array(this.o.data.buffer,this.o.data.byteOffset+r,n);e.set(i,t),this.pos=r+n}async read(e,t){let n=this,r=new Uint8Array(e);return await n.readToBuffer(r,0,e,t),r}close(){this.o.data.byteLength!=this.totalSize&&(this.o.data=this.o.data.slice(0,this.totalSize))}async discard(){}async writeULE32(e,t){let n=this;Yr.setUint32(0,e,!0),await n.write(Jr,t)}async writeUBE32(e,t){let n=this;Yr.setUint32(0,e,!1),await n.write(Jr,t)}async writeULE64(e,t){let n=this;Zr.setUint32(0,e&4294967295,!0),Zr.setUint32(4,Math.floor(e/4294967296),!0),await n.write(Xr,t)}async readULE32(e){let t=await this.read(4,e);return new Uint32Array(t.buffer)[0]}async readUBE32(e){let t=await this.read(4,e);return new DataView(t.buffer).getUint32(0,!1)}async readULE64(e){let t=await this.read(8,e),n=new Uint32Array(t.buffer);return n[1]*4294967296+n[0]}async readString(e){let t=this,n=e===void 0?t.pos:e;if(n>this.totalSize){if(this.readOnly)throw Error(`Reading out of bounds`);this._resizeIfNeeded(e)}let r=new Uint8Array(t.o.data.buffer,n,this.totalSize-n),i=r.findIndex(e=>e===0),a=i!==-1,o=``;return a?(o=new TextDecoder().decode(r.slice(0,i)),t.pos=n+i+1):t.pos=n,o}},$r=1<<22;function ei(e){let t=e.initialSize||0,n=new oi;n.o=e;let r=t?Math.floor((t-1)/$r)+1:0;n.o.data=[];for(let e=0;e0;){let t=i+a>$r?$r-i:a,o=e.slice(e.byteLength-a,e.byteLength-a+t);new Uint8Array(n.o.data[r].buffer,i,t).set(o),a-=t,r++,i=0}this.pos=t+e.byteLength}async readToBuffer(e,t,n,r){let i=this;if(r===void 0&&(r=i.pos),this.readOnly&&r+n>this.totalSize)throw Error(`Reading out of bounds`);this._resizeIfNeeded(r+n);let a=Math.floor(r/$r),o=r%$r,s=n;for(;s>0;){let r=o+s>$r?$r-o:s,c=new Uint8Array(i.o.data[a].buffer,o,r);e.set(c,t+n-s),s-=r,a++,o=0}this.pos=r+n}async read(e,t){let n=this,r=new Uint8Array(e);return await n.readToBuffer(r,0,e,t),r}close(){}async discard(){}async writeULE32(e,t){let n=this;ri.setUint32(0,e,!0),await n.write(ni,t)}async writeUBE32(e,t){let n=this;ri.setUint32(0,e,!1),await n.write(ni,t)}async writeULE64(e,t){let n=this;ai.setUint32(0,e&4294967295,!0),ai.setUint32(4,Math.floor(e/4294967296),!0),await n.write(ii,t)}async readULE32(e){let t=await this.read(4,e);return new Uint32Array(t.buffer)[0]}async readUBE32(e){let t=await this.read(4,e);return new DataView(t.buffer).getUint32(0,!1)}async readULE64(e){let t=await this.read(8,e),n=new Uint32Array(t.buffer);return n[1]*4294967296+n[0]}async readString(e){let t=this,n=e===void 0?t.pos:e;if(n>this.totalSize){if(this.readOnly)throw Error(`Reading out of bounds`);this._resizeIfNeeded(e)}let r=!1,i=``;for(;!r;){let e=Math.floor(n/$r),a=n%$r;if(t.o.data[e]===void 0)throw Error(`ERROR`);let o=Math.min(2048,t.o.data[e].length-a),s=new Uint8Array(t.o.data[e].buffer,a,o),c=s.findIndex(e=>e===0);r=c!==-1,r?(i+=new TextDecoder().decode(s.slice(0,c)),t.pos=e*$r+a+c+1):(i+=new TextDecoder().decode(s),t.pos=e*$r+a+s.length),n=t.pos}return i}},si=65536;function ci(){throw Error(`File I/O is not supported in the browser`)}function li(e,t){return e instanceof Uint8Array?{type:`mem`,data:e}:typeof e==`string`?{type:`mem`,initialSize:t||si}:e}async function ui(e){let t=await fetch(e).then(e=>e.arrayBuffer());return{type:`mem`,data:new Uint8Array(t)}}function di(e,t,n){if(e.type===`file`&&ci(),e.type===`mem`)return t(e);if(e.type===`bigMem`)return n(e);throw Error(`Invalid FastFile type: `+e.type)}function fi(e,t){return di(li(e,t),Kr,ei)}async function pi(e){return e=typeof e==`string`?await ui(e):li(e),di(e,qr,ti)}var mi=typeof Buffer<`u`&&Buffer.constants&&Buffer.constants.MAX_LENGTH?Buffer.constants.MAX_LENGTH:1<<30;async function H(e,t,n,r,i){let a=await pi(e,r,i),o=await a.read(4),s=``;for(let e=0;e<4;e++)s+=String.fromCharCode(o[e]);if(s!=t)throw Error(e+`: Invalid File format`);if(await a.readULE32()>n)throw Error(`Version not supported`);let c=await a.readULE32(),l=[];for(let e=0;e1)throw Error(e.fileName+`: Section Duplicated `+n);e.pos=t[n][0].p,e.readingSection=t[n][0]}async function K(e,t){if(e.readingSection===void 0)throw Error(`Not reading a section`);if(!t&&e.pos-e.readingSection.p!=e.readingSection.size)throw Error(`Invalid section size reading`);delete e.readingSection}async function gi(e,t,n,r){let i=new Uint8Array(n);V.toRprLE(i,0,t,n),await e.write(i,r)}async function _i(e,t,n){let r=await e.read(t,n);return V.fromRprLE(r,0,t)}async function q(e,t,n,r,i){i===void 0&&(i=t[r][0].size);let a=e.pageSize;await G(e,t,r),await U(n,r);for(let t=0;tt[n][0].size)throw Error(`Reading out of the range of the section`);let a;return a=iEi,getCurveFromQ:()=>Ti,getCurveFromR:()=>wi}),bi=V.e(`73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001`,16),xi=V.e(`21888242871839275222246405745257275088548364400416034343698204186575808495617`),Si=V.e(`1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab`,16),Ci=V.e(`21888242871839275222246405745257275088696311157297823662689037894645226208583`);async function wi(e,t){let n,r=t&&t.singleThread;if(V.eq(e,xi))n=await Br(r);else if(V.eq(e,bi))n=await Vr(r);else throw Error(`Curve not supported: ${V.toString(e)}`);return n}async function Ti(e,t){let n,r=t&&t.singleThread;if(V.eq(e,Ci))n=await Br(r);else if(V.eq(e,Si))n=await Vr(r);else throw Error(`Curve not supported: ${V.toString(e)}`);return n}async function Ei(e,t){let n,r=t&&t.singleThread,i=a(e);if([`BN128`,`BN254`,`ALTBN128`].indexOf(i)>=0)n=await Br(r);else if([`BLS12381`].indexOf(i)>=0)n=await Vr(r);else throw Error(`Curve not supported: ${e}`);return n;function a(e){return e.toUpperCase().match(/[A-Za-z0-9]+/g).join(``)}}function Di(e){return e instanceof Uint8Array||ArrayBuffer.isView(e)&&e.constructor.name===`Uint8Array`}function Oi(e,t=``){if(!Number.isSafeInteger(e)||e<0){let n=t&&`"${t}" `;throw Error(`${n}expected integer >= 0, got ${e}`)}}function ki(e,t,n=``){let r=Di(e),i=e?.length,a=t!==void 0;if(!r||a&&i!==t){let o=n&&`"${n}" `,s=a?` of length ${t}`:``,c=r?`length=${i}`:`type=${typeof e}`;throw Error(o+`expected Uint8Array`+s+`, got `+c)}return e}function Ai(e,t=!0){if(e.destroyed)throw Error(`Hash instance has been destroyed`);if(t&&e.finished)throw Error(`Hash#digest() has already been called`)}function ji(e,t){ki(e,void 0,`digestInto() output`);let n=t.outputLen;if(e.length=`+n)}function Mi(e){return new Uint32Array(e.buffer,e.byteOffset,Math.floor(e.byteLength/4))}function Ni(...e){for(let t=0;t>>8&65280|e>>>24&255}var Ii=Pi?e=>e:e=>Fi(e);function Li(e){for(let t=0;te:Li;typeof Uint8Array.from([]).toHex==`function`&&Uint8Array.fromHex;function zi(e,t={}){let n=(t,n)=>e(n).update(t).digest(),r=e(void 0);return n.outputLen=r.outputLen,n.blockLen=r.blockLen,n.create=t=>e(t),Object.assign(n,t),Object.freeze(n)}var Bi=Uint8Array.from([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3,11,8,12,0,5,2,15,13,10,14,3,6,7,1,9,4,7,9,3,1,13,12,11,14,2,6,5,10,4,0,15,8,9,0,5,7,2,4,10,15,14,1,11,12,6,8,3,13,2,12,6,10,0,11,8,3,4,13,7,5,15,14,1,9,12,5,1,15,14,13,4,10,0,7,6,3,9,2,8,11,13,11,7,14,12,1,3,9,5,0,15,4,8,6,2,10,6,15,14,9,11,3,0,8,12,2,13,7,1,4,10,5,10,2,8,4,7,6,1,5,15,11,9,14,3,12,13,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3,11,8,12,0,5,2,15,13,10,14,3,6,7,1,9,4,7,9,3,1,13,12,11,14,2,6,5,10,4,0,15,8,9,0,5,7,2,4,10,15,14,1,11,12,6,8,3,13,2,12,6,10,0,11,8,3,4,13,7,5,15,14,1,9]),Vi=BigInt(2**32-1),Hi=BigInt(32);function Ui(e,t=!1){return t?{h:Number(e&Vi),l:Number(e>>Hi&Vi)}:{h:Number(e>>Hi&Vi)|0,l:Number(e&Vi)|0}}function Wi(e,t=!1){let n=e.length,r=new Uint32Array(n),i=new Uint32Array(n);for(let a=0;ae>>>n|t<<32-n,Ki=(e,t,n)=>e<<32-n|t>>>n,qi=(e,t,n)=>e<<64-n|t>>>n-32,Ji=(e,t,n)=>e>>>n-32|t<<64-n,Yi=(e,t)=>t,Xi=(e,t)=>e,Zi=(e,t,n)=>e<>>32-n,Qi=(e,t,n)=>t<>>32-n,$i=(e,t,n)=>t<>>64-n,ea=(e,t,n)=>e<>>64-n;function ta(e,t,n,r){let i=(t>>>0)+(r>>>0);return{h:e+n+(i/2**32|0)|0,l:i|0}}var na=(e,t,n)=>(e>>>0)+(t>>>0)+(n>>>0),ra=(e,t,n,r)=>t+n+r+(e/2**32|0)|0,ia=Uint32Array.from([4089235720,1779033703,2227873595,3144134277,4271175723,1013904242,1595750129,2773480762,2917565137,1359893119,725511199,2600822924,4215389547,528734635,327033209,1541459225]),Y=new Uint32Array(32);function aa(e,t,n,r,i,a){let o=i[a],s=i[a+1],c=Y[2*e],l=Y[2*e+1],u=Y[2*t],d=Y[2*t+1],f=Y[2*n],p=Y[2*n+1],m=Y[2*r],h=Y[2*r+1],g=na(c,u,o);l=ra(g,l,d,s),c=g|0,{Dh:h,Dl:m}={Dh:h^l,Dl:m^c},{Dh:h,Dl:m}={Dh:Yi(h,m),Dl:Xi(h,m)},{h:p,l:f}=ta(p,f,h,m),{Bh:d,Bl:u}={Bh:d^p,Bl:u^f},{Bh:d,Bl:u}={Bh:Gi(d,u,24),Bl:Ki(d,u,24)},Y[2*e]=c,Y[2*e+1]=l,Y[2*t]=u,Y[2*t+1]=d,Y[2*n]=f,Y[2*n+1]=p,Y[2*r]=m,Y[2*r+1]=h}function oa(e,t,n,r,i,a){let o=i[a],s=i[a+1],c=Y[2*e],l=Y[2*e+1],u=Y[2*t],d=Y[2*t+1],f=Y[2*n],p=Y[2*n+1],m=Y[2*r],h=Y[2*r+1],g=na(c,u,o);l=ra(g,l,d,s),c=g|0,{Dh:h,Dl:m}={Dh:h^l,Dl:m^c},{Dh:h,Dl:m}={Dh:Gi(h,m,16),Dl:Ki(h,m,16)},{h:p,l:f}=ta(p,f,h,m),{Bh:d,Bl:u}={Bh:d^p,Bl:u^f},{Bh:d,Bl:u}={Bh:qi(d,u,63),Bl:Ji(d,u,63)},Y[2*e]=c,Y[2*e+1]=l,Y[2*t]=u,Y[2*t+1]=d,Y[2*n]=f,Y[2*n+1]=p,Y[2*r]=m,Y[2*r+1]=h}function sa(e,t={},n,r,i){if(Oi(n),e<0||e>n)throw Error(`outputLen bigger than keyLen`);let{key:a,salt:o,personalization:s}=t;if(a!==void 0&&(a.length<1||a.length>n))throw Error(`"key" expected to be undefined or of length=1..`+n);o!==void 0&&ki(o,r,`salt`),s!==void 0&&ki(s,i,`personalization`)}var ca=class{buffer;buffer32;finished=!1;destroyed=!1;length=0;pos=0;blockLen;outputLen;constructor(e,t){Oi(e),Oi(t),this.blockLen=e,this.outputLen=t,this.buffer=new Uint8Array(e),this.buffer32=Mi(this.buffer)}update(e){Ai(this),ki(e);let{blockLen:t,buffer:n,buffer32:r}=this,i=e.length,a=e.byteOffset,o=e.buffer;for(let s=0;sr[t]=Ii(e))}digest(){let{buffer:e,outputLen:t}=this;this.digestInto(e);let n=e.slice(0,t);return this.destroy(),n}_cloneInto(e){let{buffer:t,length:n,finished:r,destroyed:i,outputLen:a,pos:o}=this;return e||=new this.constructor({dkLen:a}),e.set(...this.get()),e.buffer.set(t),e.destroyed=i,e.finished=r,e.length=n,e.pos=o,e.outputLen=a,e}clone(){return this._cloneInto()}},la=class extends ca{v0l=ia[0]|0;v0h=ia[1]|0;v1l=ia[2]|0;v1h=ia[3]|0;v2l=ia[4]|0;v2h=ia[5]|0;v3l=ia[6]|0;v3h=ia[7]|0;v4l=ia[8]|0;v4h=ia[9]|0;v5l=ia[10]|0;v5h=ia[11]|0;v6l=ia[12]|0;v6h=ia[13]|0;v7l=ia[14]|0;v7h=ia[15]|0;constructor(e={}){let t=e.dkLen===void 0?64:e.dkLen;super(128,t),sa(t,e,64,16,16);let{key:n,personalization:r,salt:i}=e,a=0;if(n!==void 0&&(ki(n,void 0,`key`),a=n.length),this.v0l^=this.outputLen|a<<8|16842752,i!==void 0){ki(i,void 0,`salt`);let e=Mi(i);this.v4l^=Ii(e[0]),this.v4h^=Ii(e[1]),this.v5l^=Ii(e[2]),this.v5h^=Ii(e[3])}if(r!==void 0){ki(r,void 0,`personalization`);let e=Mi(r);this.v6l^=Ii(e[0]),this.v6h^=Ii(e[1]),this.v7l^=Ii(e[2]),this.v7h^=Ii(e[3])}if(n!==void 0){let e=new Uint8Array(this.blockLen);e.set(n),this.update(e)}}get(){let{v0l:e,v0h:t,v1l:n,v1h:r,v2l:i,v2h:a,v3l:o,v3h:s,v4l:c,v4h:l,v5l:u,v5h:d,v6l:f,v6h:p,v7l:m,v7h:h}=this;return[e,t,n,r,i,a,o,s,c,l,u,d,f,p,m,h]}set(e,t,n,r,i,a,o,s,c,l,u,d,f,p,m,h){this.v0l=e|0,this.v0h=t|0,this.v1l=n|0,this.v1h=r|0,this.v2l=i|0,this.v2h=a|0,this.v3l=o|0,this.v3h=s|0,this.v4l=c|0,this.v4h=l|0,this.v5l=u|0,this.v5h=d|0,this.v6l=f|0,this.v6h=p|0,this.v7l=m|0,this.v7h=h|0}compress(e,t,n){this.get().forEach((e,t)=>Y[t]=e),Y.set(ia,16);let{h:r,l:i}=Ui(BigInt(this.length));Y[24]=ia[8]^i,Y[25]=ia[9]^r,n&&(Y[28]=~Y[28],Y[29]=~Y[29]);let a=0,o=Bi;for(let n=0;n<12;n++)aa(0,4,8,12,e,t+2*o[a++]),oa(0,4,8,12,e,t+2*o[a++]),aa(1,5,9,13,e,t+2*o[a++]),oa(1,5,9,13,e,t+2*o[a++]),aa(2,6,10,14,e,t+2*o[a++]),oa(2,6,10,14,e,t+2*o[a++]),aa(3,7,11,15,e,t+2*o[a++]),oa(3,7,11,15,e,t+2*o[a++]),aa(0,5,10,15,e,t+2*o[a++]),oa(0,5,10,15,e,t+2*o[a++]),aa(1,6,11,12,e,t+2*o[a++]),oa(1,6,11,12,e,t+2*o[a++]),aa(2,7,8,13,e,t+2*o[a++]),oa(2,7,8,13,e,t+2*o[a++]),aa(3,4,9,14,e,t+2*o[a++]),oa(3,4,9,14,e,t+2*o[a++]);this.v0l^=Y[0]^Y[16],this.v0h^=Y[1]^Y[17],this.v1l^=Y[2]^Y[18],this.v1h^=Y[3]^Y[19],this.v2l^=Y[4]^Y[20],this.v2h^=Y[5]^Y[21],this.v3l^=Y[6]^Y[22],this.v3h^=Y[7]^Y[23],this.v4l^=Y[8]^Y[24],this.v4h^=Y[9]^Y[25],this.v5l^=Y[10]^Y[26],this.v5h^=Y[11]^Y[27],this.v6l^=Y[12]^Y[28],this.v6h^=Y[13]^Y[29],this.v7l^=Y[14]^Y[30],this.v7h^=Y[15]^Y[31],Ni(Y)}destroy(){this.destroyed=!0,Ni(this.buffer32),this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)}},ua=zi(e=>new la(e)),da=c(((e,t)=>{t.exports={}}));da();var fa=[];for(let e=0;e<256;e++)fa[e]=pa(e,8);function pa(e,t){let n=0,r=e;for(let e=0;e>=1;return n}function ma(e){return(e&4294901760?(e&=4294901760,16):0)|(e&4278255360?(e&=4278255360,8):0)|(e&4042322160?(e&=4042322160,4):0)|(e&3435973836?(e&=3435973836,2):0)|(e&2863311530)!=0}function ha(e,t){let n=new DataView(e.buffer,e.byteOffset,e.byteLength),r=``;for(let e=0;e<4;e++){e>0&&(r+=` -`),r+=` `;for(let t=0;t<4;t++)t>0&&(r+=` `),r+=n.getUint32(e*16+t*4).toString(16).padStart(8,`0`)}return t&&(r=t+` -`+r),r}function ga(e,t){if(e.byteLength!=t.byteLength)return!1;for(var n=new Int8Array(e),r=new Int8Array(t),i=0;i!=e.byteLength;i++)if(n[i]!=r[i])return!1;return!0}function _a(e){return e.clone()}function va(e){let t=e.subarray(0,128),n=Mi(e.subarray(128)),r=ua.create({dkLen:64});r.buffer.set(t),r.v0l=n[0]|0,r.v0h=n[1]|0,r.v1l=n[2]|0,r.v1h=n[3]|0,r.v2l=n[4]|0,r.v2h=n[5]|0,r.v3l=n[6]|0,r.v3h=n[7]|0,r.v4l=n[8]|0,r.v4h=n[9]|0,r.v5l=n[10]|0,r.v5h=n[11]|0,r.v6l=n[12]|0,r.v6h=n[13]|0,r.v7l=n[14]|0,r.v7h=n[15]|0;let i=2**32,a=n[16]+n[17]*i,o=n[18]+n[19]*i;return r.length=a+o,r.pos=o,r}function ya(e){let t=new Uint8Array(216),n=Mi(t.subarray(128));return t.set(e.buffer),n[0]=e.v0l,n[1]=e.v0h,n[2]=e.v1l,n[3]=e.v1h,n[4]=e.v2l,n[5]=e.v2h,n[6]=e.v3l,n[7]=e.v3h,n[8]=e.v4l,n[9]=e.v4h,n[10]=e.v5l,n[11]=e.v5h,n[12]=e.v6l,n[13]=e.v6h,n[14]=e.v7l,n[15]=e.v7h,n[18]=e.pos,n[16]=e.length-e.pos,t}async function ba(e,t,n,r,i){return e.G1.isZero(t)||e.G1.isZero(n)||e.G2.isZero(r)||e.G2.isZero(i)?!1:await e.pairingEq(t,i,e.G1.neg(n),r)}function xa(){return window.prompt(`Enter a random text. (Entropy): `,``)}function Sa(e){let t=new Uint8Array(e);return globalThis.crypto.getRandomValues(t),t}async function Ca(e){{let t=await globalThis.crypto.subtle.digest(`SHA-256`,e.buffer);return new Uint8Array(t)}}function wa(e,t){return new DataView(e.buffer).getUint32(t,!1)}async function Ta(e){for(;!e;)e=await xa();let t=ua.create(64);t.update(Sa(64));let n=new TextEncoder;t.update(n.encode(e));let r=t.digest(),i=[];for(let e=0;e<8;e++)i[e]=wa(r,e*4);return new Gn(i)}async function Ea(e,t){let n,r;t<32?(n=1<>>0,r=1):(n=4294967296,r=1<>>0);let i=e;for(let e=0;e{n[r]=ka(e,t[r])}),n}else if(typeof t==`bigint`||t.eq!==void 0)return t.toString(10);else return t}async function Aa(e,t){await U(e,1),await e.writeULE32(1),await W(e);let n=await Ti(t.q);await U(e,2);let r=n.q,i=(Math.floor((V.bitLength(r)-1)/64)+1)*8,a=n.r,o=(Math.floor((V.bitLength(a)-1)/64)+1)*8;await e.writeULE32(i),await gi(e,r,i),await e.writeULE32(o),await gi(e,a,o),await e.writeULE32(t.nVars),await e.writeULE32(t.nPublic),await e.writeULE32(t.domainSize),await ja(e,n,t.vk_alpha_1),await ja(e,n,t.vk_beta_1),await Ma(e,n,t.vk_beta_2),await Ma(e,n,t.vk_gamma_2),await ja(e,n,t.vk_delta_1),await Ma(e,n,t.vk_delta_2),await W(e)}async function ja(e,t,n){let r=new Uint8Array(t.G1.F.n8*2);t.G1.toRprLEM(r,0,n),await e.write(r)}async function Ma(e,t,n){let r=new Uint8Array(t.G2.F.n8*2);t.G2.toRprLEM(r,0,n),await e.write(r)}async function Na(e,t,n){let r=await e.read(t.G1.F.n8*2),i=t.G1.fromRprLEM(r,0);return n?t.G1.toObject(i):i}async function Pa(e,t,n){let r=await e.read(t.G2.F.n8*2),i=t.G2.fromRprLEM(r,0);return n?t.G2.toObject(i):i}async function Fa(e,t,n,r){await G(e,t,1);let i=await e.readULE32();if(await K(e),i===1)return await Ia(e,t,n,r);if(i===2)return await La(e,t,n,r);if(i===10)return await Ra(e,t,n,r);throw Error(`Protocol not supported: `)}async function Ia(e,t,n,r){let i={};i.protocol=`groth16`,await G(e,t,2);let a=await e.readULE32();i.n8q=a,i.q=await _i(e,a);let o=await e.readULE32();return i.n8r=o,i.r=await _i(e,o),i.curve=await Ti(i.q,r),i.nVars=await e.readULE32(),i.nPublic=await e.readULE32(),i.domainSize=await e.readULE32(),i.power=ma(i.domainSize),i.vk_alpha_1=await Na(e,i.curve,n),i.vk_beta_1=await Na(e,i.curve,n),i.vk_beta_2=await Pa(e,i.curve,n),i.vk_gamma_2=await Pa(e,i.curve,n),i.vk_delta_1=await Na(e,i.curve,n),i.vk_delta_2=await Pa(e,i.curve,n),await K(e),i}async function La(e,t,n,r){let i={};i.protocol=`plonk`,await G(e,t,2);let a=await e.readULE32();i.n8q=a,i.q=await _i(e,a);let o=await e.readULE32();return i.n8r=o,i.r=await _i(e,o),i.curve=await Ti(i.q,r),i.nVars=await e.readULE32(),i.nPublic=await e.readULE32(),i.domainSize=await e.readULE32(),i.power=ma(i.domainSize),i.nAdditions=await e.readULE32(),i.nConstraints=await e.readULE32(),i.k1=await e.read(o),i.k2=await e.read(o),i.Qm=await Na(e,i.curve,n),i.Ql=await Na(e,i.curve,n),i.Qr=await Na(e,i.curve,n),i.Qo=await Na(e,i.curve,n),i.Qc=await Na(e,i.curve,n),i.S1=await Na(e,i.curve,n),i.S2=await Na(e,i.curve,n),i.S3=await Na(e,i.curve,n),i.X_2=await Pa(e,i.curve,n),await K(e),i}async function Ra(e,t,n,r){let i={};i.protocol=`fflonk`,i.protocolId=10,await G(e,t,2);let a=await e.readULE32();i.n8q=a,i.q=await _i(e,a),i.curve=await Ti(i.q,r);let o=await e.readULE32();return i.n8r=o,i.r=await _i(e,o),i.nVars=await e.readULE32(),i.nPublic=await e.readULE32(),i.domainSize=await e.readULE32(),i.power=ma(i.domainSize),i.nAdditions=await e.readULE32(),i.nConstraints=await e.readULE32(),i.k1=await e.read(o),i.k2=await e.read(o),i.w3=await e.read(o),i.w4=await e.read(o),i.w8=await e.read(o),i.wr=await e.read(o),i.X_2=await Pa(e,i.curve,n),i.C0=await Na(e,i.curve,n),await K(e),i}async function za(e,t){let{fd:n,sections:r}=await H(e,`zkey`,1),i=await Fa(n,r,t),a=new er(i.r),o=V.mod(V.shl(1,i.n8r*8),i.r),s=a.inv(o),c=a.mul(s,s),l=await Ti(i.q);await G(n,r,3),i.IC=[];for(let e=0;e<=i.nPublic;e++){let e=await Na(n,l,t);i.IC.push(e)}await K(n),await G(n,r,4);let u=await n.readULE32();i.ccoefs=[];for(let e=0;e0){let t=new Uint8Array(r);await e.writeULE32(t.byteLength),await e.write(t)}else await e.writeULE32(0)}async function Ua(e,t,n){await U(e,10),await e.write(n.csHash),await e.writeULE32(n.contributions.length);for(let r=0;r2**16;)a*=2,c=Math.floor(t.domainSize/a);console.log(`@@@ new elementsPerChunk`,c);let l=[],u=[];for(let e=0;e1){let t=[];for(let n=0;ne?n=r-1:i1){let t=[];for(let n=0;n<1;n++){let r=[];r.push({cmd:`ALLOC`,var:0,len:d[n][0].byteLength}),r.push({cmd:`ALLOC`,var:1,len:d[n][0].byteLength});for(let t=0;t<3;t++){r.push({cmd:`SET`,var:0,buff:d[n][t]});for(let i=1;ie?n=r-1:i{ro(e)},t)}function ao(e){let t=e.initialSize||1<<20,n=new fo;return n.o=e,n.o.data=new Uint8Array(t),n.allocSize=t,n.totalSize=0,n.readOnly=!1,n.pos=0,n}function oo(e){let t=new fo;return t.o=e,t.allocSize=e.data.byteLength,t.totalSize=e.data.byteLength,t.readOnly=!0,t.pos=0,t}var so=new Uint8Array(4),co=new DataView(so.buffer),lo=new Uint8Array(8),uo=new DataView(lo.buffer),fo=class{constructor(){this.pageSize=16384}_resizeIfNeeded(e){if(e>this.allocSize){let t=Math.max(this.allocSize+(1<<20),Math.floor(this.allocSize*1.1),e),n=new Uint8Array(t);n.set(this.o.data),this.o.data=n,this.allocSize=t}}async write(e,t){if(t===void 0&&(t=this.pos),this.readOnly)throw Error(`Writing a read only file`);this._resizeIfNeeded(t+e.byteLength),this.o.data.set(e.slice(),t),t+e.byteLength>this.totalSize&&(this.totalSize=t+e.byteLength),this.pos=t+e.byteLength}async readToBuffer(e,t,n,r){if(r===void 0&&(r=this.pos),this.readOnly&&r+n>this.totalSize)throw Error(`Reading out of bounds`);this._resizeIfNeeded(r+n);let i=new Uint8Array(this.o.data.buffer,this.o.data.byteOffset+r,n);e.set(i,t),this.pos=r+n}async read(e,t){let n=this,r=new Uint8Array(e);return await n.readToBuffer(r,0,e,t),r}close(){this.o.data.byteLength!=this.totalSize&&(this.o.data=this.o.data.slice(0,this.totalSize))}async discard(){}async writeULE32(e,t){let n=this;co.setUint32(0,e,!0),await n.write(so,t)}async writeUBE32(e,t){let n=this;co.setUint32(0,e,!1),await n.write(so,t)}async writeULE64(e,t){let n=this;uo.setUint32(0,e&4294967295,!0),uo.setUint32(4,Math.floor(e/4294967296),!0),await n.write(lo,t)}async readULE32(e){let t=await this.read(4,e);return new Uint32Array(t.buffer)[0]}async readUBE32(e){let t=await this.read(4,e);return new DataView(t.buffer).getUint32(0,!1)}async readULE64(e){let t=await this.read(8,e),n=new Uint32Array(t.buffer);return n[1]*4294967296+n[0]}async readString(e){let t=this,n=e===void 0?t.pos:e;if(n>this.totalSize){if(this.readOnly)throw Error(`Reading out of bounds`);this._resizeIfNeeded(e)}let r=new Uint8Array(t.o.data.buffer,n,this.totalSize-n),i=r.findIndex(e=>e===0),a=i!==-1,o=``;return a?(o=new TextDecoder().decode(r.slice(0,i)),t.pos=n+i+1):t.pos=n,o}},po=1<<22;function mo(e){let t=e.initialSize||0,n=new bo;n.o=e;let r=t?Math.floor((t-1)/po)+1:0;n.o.data=[];for(let e=0;e0;){let t=i+a>po?po-i:a,o=e.slice(e.byteLength-a,e.byteLength-a+t);new Uint8Array(n.o.data[r].buffer,i,t).set(o),a-=t,r++,i=0}this.pos=t+e.byteLength}async readToBuffer(e,t,n,r){let i=this;if(r===void 0&&(r=i.pos),this.readOnly&&r+n>this.totalSize)throw Error(`Reading out of bounds`);this._resizeIfNeeded(r+n);let a=Math.floor(r/po),o=r%po,s=n;for(;s>0;){let r=o+s>po?po-o:s,c=new Uint8Array(i.o.data[a].buffer,o,r);e.set(c,t+n-s),s-=r,a++,o=0}this.pos=r+n}async read(e,t){let n=this,r=new Uint8Array(e);return await n.readToBuffer(r,0,e,t),r}close(){}async discard(){}async writeULE32(e,t){let n=this;_o.setUint32(0,e,!0),await n.write(go,t)}async writeUBE32(e,t){let n=this;_o.setUint32(0,e,!1),await n.write(go,t)}async writeULE64(e,t){let n=this;yo.setUint32(0,e&4294967295,!0),yo.setUint32(4,Math.floor(e/4294967296),!0),await n.write(vo,t)}async readULE32(e){let t=await this.read(4,e);return new Uint32Array(t.buffer)[0]}async readUBE32(e){let t=await this.read(4,e);return new DataView(t.buffer).getUint32(0,!1)}async readULE64(e){let t=await this.read(8,e),n=new Uint32Array(t.buffer);return n[1]*4294967296+n[0]}async readString(e){let t=this,n=e===void 0?t.pos:e;if(n>this.totalSize){if(this.readOnly)throw Error(`Reading out of bounds`);this._resizeIfNeeded(e)}let r=!1,i=``;for(;!r;){let e=Math.floor(n/po),a=n%po;if(t.o.data[e]===void 0)throw Error(`ERROR`);let o=Math.min(2048,t.o.data[e].length-a),s=new Uint8Array(t.o.data[e].buffer,a,o),c=s.findIndex(e=>e===0);r=c!==-1,r?(i+=new TextDecoder().decode(s.slice(0,c)),t.pos=e*po+a+c+1):(i+=new TextDecoder().decode(s),t.pos=e*po+a+s.length),n=t.pos}return i}},xo=65536;function So(){throw Error(`File I/O is not supported in the browser`)}function Co(e,t){return e instanceof Uint8Array?{type:`mem`,data:e}:typeof e==`string`?{type:`mem`,initialSize:t||xo}:e}async function wo(e){let t=await fetch(e).then(e=>e.arrayBuffer());return{type:`mem`,data:new Uint8Array(t)}}function To(e,t,n){if(e.type===`file`&&So(),e.type===`mem`)return t(e);if(e.type===`bigMem`)return n(e);throw Error(`Invalid FastFile type: `+e.type)}function Eo(e,t){return To(Co(e,t),ao,mo)}async function Do(e){return e=typeof e==`string`?await wo(e):Co(e),To(e,oo,ho)}function Oo(e){let t=[];return n(t,e),t;function n(e,t){if(Array.isArray(t))for(let r=0;r0;)n.unshift(0),e--}return n}async function Mo(e,t){let n,r,i;t||={};let a=1,o=0,s=0,c=!1;if(e instanceof WebAssembly.Instance)n=e,c=!0;else{let c=32767;if(t.memorySize&&(c=parseInt(t.memorySize),c<0))throw Error(`Invalid memory size`);let l=!1;for(;!l;)try{i=new WebAssembly.Memory({initial:c}),l=!0}catch(e){if(c<=1)throw e;console.warn(`Could not allocate `+c*1024*64+` bytes. This may cause severe instability. Trying with `+c*1024*64/2+` bytes`),c=Math.floor(c/2)}let f=await WebAssembly.compile(e),p=``,m=``;n=await WebAssembly.instantiate(f,{env:{memory:i},runtime:{printDebug:function(e){console.log(`printDebug:`,e)},exceptionHandler:function(e){let t;throw t=e===1?`Signal not found. `:e===2?`Too many signals set. `:e===3?`Signal already set. `:e===4?`Assert Failed. `:e===5?`Not enough memory. `:e===6?`Input signal array access exceeds the size. `:`Unknown error. `,console.error(`ERROR: `,e,p),Error(t+p)},printErrorMessage:function(){p+=u()+` -`},writeBufferMessage:function(){let e=u();e===` -`?(console.log(m),m=``):(m!==``&&(m+=` `),m+=e)},showSharedRWMemory:function(){let e=n.exports.getFieldNumLen32(),t=new Uint32Array(e);for(let r=0;r=2&&(o>=1||s>=7)){m!==``&&(m+=` `);let e=V.fromArray(t,4294967296).toString();m+=e}else console.log(V.fromArray(t,4294967296))},error:function(e,n,i,a,o,s){let c;throw c=e===7?d(n)+` `+r.getFr(a).toString()+` != `+r.getFr(o).toString()+` `+d(s):e===9?d(n)+` `+r.getFr(a).toString()+` `+d(o):e===5&&t.sym?d(n)+` `+t.sym.labelIdx2Name[o]:d(n)+` `+i+` `+a+` `+o+` `+s,console.log(`ERROR: `,e,c),Error(c)},log:function(e){console.log(r.getFr(e).toString())},logGetSignal:function(e,n){t.logGetSignal&&t.logGetSignal(e,r.getFr(n))},logSetSignal:function(e,n){t.logSetSignal&&t.logSetSignal(e,r.getFr(n))},logStartComponent:function(e){t.logStartComponent&&t.logStartComponent(e)},logFinishComponent:function(e){t.logFinishComponent&&t.logFinishComponent(e)}}})}typeof n.exports.getVersion==`function`&&(a=n.exports.getVersion()),typeof n.exports.getMinorVersion==`function`&&(o=n.exports.getMinorVersion()),typeof n.exports.getPatchVersion==`function`&&(s=n.exports.getPatchVersion());let l=t&&(t.sanityCheck||t.logGetSignal||t.logSetSignal||t.logStartComponent||t.logFinishComponent);if(a===2)r=new Po(n,l);else if(a===1){if(c)throw Error(`Loading code from WebAssembly instance is not supported for circom version 1`);r=new No(i,n,l)}else throw Error(`Unsupported circom version: ${a}`);return r;function u(){let e=``,t=n.exports.getMessageChar();for(;t!==0;)e+=String.fromCharCode(t),t=n.exports.getMessageChar();return e}function d(e){let t=new Uint8Array(i.buffer),n=[];for(let r=0;t[e+r]>0;r++)n.push(t[e+r]);return String.fromCharCode.apply(null,n)}}var No=class{constructor(e,t,n){this.memory=e,this.i32=new Uint32Array(e.buffer),this.instance=t,this.n32=(this.instance.exports.getFrLen()>>2)-2;let r=this.instance.exports.getPRawPrime(),i=Array(this.n32);for(let e=0;e>2)+e];this.prime=V.fromArray(i,4294967296),this.Fr=new er(this.prime),this.mask32=V.fromString(`FFFFFFFF`,16),this.NVars=this.instance.exports.getNVars(),this.n64=Math.floor((this.Fr.bitLength-1)/64)+1,this.R=this.Fr.e(V.shiftLeft(1,this.n64*64)),this.RInv=this.Fr.inv(this.R),this.sanityCheck=n}circom_version(){return 1}async _doCalculateWitness(e,t){this.instance.exports.init(this.sanityCheck||t?1:0);let n=this.allocInt(),r=this.allocFr();Object.keys(e).forEach(t=>{let i=Ao(t),a=parseInt(i.slice(0,8),16),o=parseInt(i.slice(8,16),16);try{this.instance.exports.getSignalOffset32(n,0,a,o)}catch{throw Error(`Signal ${t} is not an input of the circuit.`)}let s=this.getInt(n),c=Oo(e[t]);for(let e=0;e>2]}setInt(e,t){this.i32[e>>2]=t}getFr(e){let t=this,n=e>>2;if(t.i32[n+1]&2147483648){let e=Array(t.n32);for(let r=0;r>2]=i,n.i32[(e>>2)+1]=0;return}n.i32[e>>2]=0,n.i32[(e>>2)+1]=2147483648;let a=V.toArray(t,4294967296);for(let t=0;t=0?n.i32[(e>>2)+2+t]=a[r]:n.i32[(e>>2)+2+t]=0}}},Po=class{constructor(e,t){this.instance=e,this.version=this.instance.exports.getVersion(),this.n32=this.instance.exports.getFieldNumLen32(),this.instance.exports.getRawPrime();let n=new Uint32Array(this.n32);for(let e=0;e{let n=Ao(t),i=parseInt(n.slice(0,8),16),a=parseInt(n.slice(8,16),16),o=Oo(e[t]);if(typeof this.instance.exports.getInputSignalSize==`function`){let e=this.instance.exports.getInputSignalSize(i,a);if(e<0)throw Error(`Signal ${t} not found\n`);if(o.lengthe)throw Error(`Too many values for input signal ${t}\n`)}for(let e=0;eKo,fullProve:()=>Ro,prove:()=>Qa,verify:()=>Bo});function Jo(e,t){let n=new DataView(t.buffer,t.byteOffset,t.byteLength),r=[];for(let e=0;e<8;e++)r[e]=n.getUint32(e*4);let i=new Gn(r);return e.G2.fromRng(i)}function Yo(e,t,n,r,i){let a=ua.create({dkLen:64}),o=new Uint8Array([t]);a.update(o),a.update(n);let s=e.G1.toUncompressed(r);a.update(s);let c=e.G1.toUncompressed(i);return a.update(c),Jo(e,a.digest())}function Xo(e,t,n,r,i){return e.g1_s=t.G1.toAffine(t.G1.fromRng(i)),e.g1_sx=t.G1.toAffine(t.G1.timesFr(e.g1_s,e.prvKey)),e.g2_sp=t.G2.toAffine(Yo(t,n,r,e.g1_s,e.g1_sx)),e.g2_spx=t.G2.toAffine(t.G2.timesFr(e.g2_sp,e.prvKey)),e}function Zo(e,t,n){let r={tau:{},alpha:{},beta:{}};return r.tau.prvKey=e.Fr.fromRng(n),r.alpha.prvKey=e.Fr.fromRng(n),r.beta.prvKey=e.Fr.fromRng(n),Xo(r.tau,e,0,t,n),Xo(r.alpha,e,1,t,n),Xo(r.beta,e,2,t,n),r}async function Qo(e,t,n,r){r||=n,await e.writeULE32(1);let i=e.pos;await e.writeULE64(0),await e.writeULE32(t.F1.n64*8);let a=new Uint8Array(t.F1.n8);V.toRprLE(a,0,t.q,t.F1.n8),await e.write(a),await e.writeULE32(n),await e.writeULE32(r);let o=e.pos-i-8,s=e.pos;await e.writeULE64(o,i),e.pos=s}async function $o(e,t){if(!t[1])throw Error(e.fileName+`: File has no header`);if(t[1].length>1)throw Error(e.fileName+`: File has more than one header`);e.pos=t[1][0].p;let n=await e.readULE32(),r=await e.read(n),i=await Ti(V.fromRprLE(r));if(i.F1.n64*8!=n)throw Error(e.fileName+`: Invalid size`);let a=await e.readULE32(),o=await e.readULE32();if(e.pos-t[1][0].p!=t[1][0].size)throw Error(`Invalid PTau header size`);return{curve:i,power:a,ceremonyPower:o}}async function es(e,t,n){return ts(await e.read(t.F1.n8*2*6+t.F2.n8*2*3),0,t,n)}function ts(e,t,n,r){let i={tau:{},alpha:{},beta:{}};return i.tau.g1_s=a(),i.tau.g1_sx=a(),i.alpha.g1_s=a(),i.alpha.g1_sx=a(),i.beta.g1_s=a(),i.beta.g1_sx=a(),i.tau.g2_spx=o(),i.alpha.g2_spx=o(),i.beta.g2_spx=o(),i;function a(){let i;return i=r?n.G1.fromRprLEM(e,t):n.G1.fromRprUncompressed(e,t),t+=n.G1.F.n8*2,i}function o(){let i;return i=r?n.G2.fromRprLEM(e,t):n.G2.fromRprUncompressed(e,t),t+=n.G2.F.n8*2,i}}function ns(e,t,n,r,i){a(r.tau.g1_s),a(r.tau.g1_sx),a(r.alpha.g1_s),a(r.alpha.g1_sx),a(r.beta.g1_s),a(r.beta.g1_sx),o(r.tau.g2_spx),o(r.alpha.g2_spx),o(r.beta.g2_spx);async function a(r){i?n.G1.toRprLEM(e,t,r):n.G1.toRprUncompressed(e,t,r),t+=n.F1.n8*2}async function o(r){i?n.G2.toRprLEM(e,t,r):n.G2.toRprUncompressed(e,t,r),t+=n.F2.n8*2}return e}async function rs(e,t,n,r){let i=new Uint8Array(t.F1.n8*2*6+t.F2.n8*2*3);ns(i,0,t,n,r),await e.write(i)}async function is(e,t){let n={};n.tauG1=await c(),n.tauG2=await l(),n.alphaG1=await c(),n.betaG1=await c(),n.betaG2=await l(),n.key=await es(e,t,!0),n.partialHash=await e.read(216),n.nextChallenge=await e.read(64),n.type=await e.readULE32();let r=new Uint8Array(t.G1.F.n8*2*6+t.G2.F.n8*2*3);ns(r,0,t,n.key,!1);let i=va(n.partialHash);i.update(r),n.responseHash=i.digest();let a=await e.readULE32(),o=e.pos,s=0;for(;e.pos-o1)throw Error(e.fileName+`: File has more than one contributions section`);e.pos=n[7][0].p;let r=await e.readULE32(),i=[];for(let n=0;n0){let t=new Uint8Array(a);await e.writeULE32(t.byteLength),await e.write(t)}else await e.writeULE32(0);async function o(n){t.G1.toRprLEM(r,0,n),await e.write(r)}async function s(n){t.G2.toRprLEM(i,0,n),await e.write(i)}}async function ss(e,t,n){await e.writeULE32(7);let r=e.pos;await e.writeULE64(0),await e.writeULE32(n.length);for(let r=0;r0?d[d.length-1].nextChallenge:cs(l,u,a);let y=await hi(n,`ptau`,1,i?7:2);await Qo(y,l,u);let b=await _.read(64);if(ga(o,v)&&(v=b,d[d.length-1].nextChallenge=v),!ga(b,v))throw Error(`Wrong contribution. This contribution is not based on the previous hash`);let x=ua.create({dkLen:64});x.update(b);let S=[],C;C=await E(_,y,`G1`,2,2**u*2-1,[1],`tauG1`),f.tauG1=C[0],C=await E(_,y,`G2`,3,2**u,[1],`tauG2`),f.tauG2=C[0],C=await E(_,y,`G1`,4,2**u,[0],`alphaG1`),f.alphaG1=C[0],C=await E(_,y,`G1`,5,2**u,[0],`betaG1`),f.betaG1=C[0],C=await E(_,y,`G2`,6,1,[0],`betaG2`),f.betaG2=C[0],f.partialHash=ya(x);let w=await _.read(l.F1.n8*2*6+l.F2.n8*2*3);f.key=ts(w,0,l,!1),x.update(new Uint8Array(w));let T=x.digest();if(a&&a.info(ha(T,`Contribution Response Hash imported: `)),i){let e=ua.create({dkLen:64});e.update(T),await k(e,y,`G1`,2,2**u*2-1,`tauG1`,a),await k(e,y,`G2`,3,2**u,`tauG2`,a),await k(e,y,`G1`,4,2**u,`alphaTauG1`,a),await k(e,y,`G1`,5,2**u,`betaTauG1`,a),await k(e,y,`G2`,6,1,`betaG2`,a),f.nextChallenge=e.digest(),a&&a.info(ha(f.nextChallenge,`Next Challenge Hash: `))}else f.nextChallenge=o;return d.push(f),await ss(y,l,d),await _.close(),await y.close(),await s.close(),f.nextChallenge;async function E(e,t,n,r,a,o,s){return i?await D(e,t,n,r,a,o,s):await O(e,t,n,r,a,o,s)}async function D(e,t,n,r,i,o,s){let c=l[n],u=c.F.n8,d=c.F.n8*2,f=[];await U(t,r);let p=Math.floor((1<<24)/d);S[r]=t.pos;for(let n=0;n=n&&t=t&&i1?c[c.length-2]:l;let d=c[c.length-1];if(t&&t.debug(`Validating contribution #`+c[c.length-1].id),!await ms(a,d,u,t))return!1;let f=ua.create({dkLen:64});f.update(d.responseHash),t&&t.debug(`Verifying powers in tau*G1 section`);let p=await x(2,`G1`,`tauG1`,2**o*2-1,[0,1],t);if(n=await ps(a,p.R1,p.R2,a.G2.g,d.tauG2),n!==!0)return t&&t.error(`tauG1 section. Powers do not match`),!1;if(!a.G1.eq(a.G1.g,p.singularPoints[0]))return t&&t.error(`First element of tau*G1 section must be the generator`),!1;if(!a.G1.eq(d.tauG1,p.singularPoints[1]))return t&&t.error(`Second element of tau*G1 section does not match the one in the contribution section`),!1;t&&t.debug(`Verifying powers in tau*G2 section`);let m=await x(3,`G2`,`tauG2`,2**o,[0,1],t);if(n=await ps(a,a.G1.g,d.tauG1,m.R1,m.R2),n!==!0)return t&&t.error(`tauG2 section. Powers do not match`),!1;if(!a.G2.eq(a.G2.g,m.singularPoints[0]))return t&&t.error(`First element of tau*G2 section must be the generator`),!1;if(!a.G2.eq(d.tauG2,m.singularPoints[1]))return t&&t.error(`Second element of tau*G2 section does not match the one in the contribution section`),!1;t&&t.debug(`Verifying powers in alpha*tau*G1 section`);let h=await x(4,`G1`,`alphatauG1`,2**o,[0],t);if(n=await ps(a,h.R1,h.R2,a.G2.g,d.tauG2),n!==!0)return t&&t.error(`alphaTauG1 section. Powers do not match`),!1;if(!a.G1.eq(d.alphaG1,h.singularPoints[0]))return t&&t.error(`First element of alpha*tau*G1 section (alpha*G1) does not match the one in the contribution section`),!1;t&&t.debug(`Verifying powers in beta*tau*G1 section`);let g=await x(5,`G1`,`betatauG1`,2**o,[0],t);if(n=await ps(a,g.R1,g.R2,a.G2.g,d.tauG2),n!==!0)return t&&t.error(`betaTauG1 section. Powers do not match`),!1;if(!a.G1.eq(d.betaG1,g.singularPoints[0]))return t&&t.error(`First element of beta*tau*G1 section (beta*G1) does not match the one in the contribution section`),!1;let _=await b(t);if(!a.G2.eq(d.betaG2,_))return t&&t.error(`betaG2 element in betaG2 section does not match the one in the contribution section`),!1;let v=f.digest();if(o==s&&!ga(v,d.nextChallenge))return t&&t.error(`Hash of the values does not match the next challenge of the last contributor in the contributions section`),!1;t&&t.info(ha(v,`Next challenge hash: `)),y(d,u);for(let e=c.length-2;e>=0;e--){let n=c[e],r=e>0?c[e-1]:l;if(!await ms(a,n,r,t))return!1;y(n,r,t)}if(t&&t.info(`-----------------------------------------------------`),!i[12]||!i[13]||!i[14]||!i[15])t&&t.warn(`this file does not contain phase2 precalculated values. Please run: - snarkjs "powersoftau preparephase2" to prepare this file to be used in the phase2 ceremony.`);else{let e;if(e=await S(`G1`,2,12,`tauG1`,t),!e||(e=await S(`G2`,3,13,`tauG2`,t),!e)||(e=await S(`G1`,4,14,`alphaTauG1`,t),!e)||(e=await S(`G1`,5,15,`betaTauG1`,t),!e))return!1}return await r.close(),t&&t.info(`Powers of Tau Ok!`),!0;function y(e,n){if(!t)return;t.info(`-----------------------------------------------------`),t.info(`Contribution #${e.id}: ${e.name||``}`),t.info(ha(e.nextChallenge,`Next Challenge: `));let r=new Uint8Array(a.G1.F.n8*2*6+a.G2.F.n8*2*3);ns(r,0,a,e.key,!1);let i=va(e.partialHash);i.update(r);let o=i.digest();t.info(ha(o,`Response Hash:`)),t.info(ha(n.nextChallenge,`Response Hash:`)),e.type==1&&(t.info(`Beacon generator: ${Oa(e.beaconHash)}`),t.info(`Beacon iterations Exp: ${e.numIterationsExp}`))}async function b(e){let t=a.G2,n=t.F.n8*2,o=new Uint8Array(n);if(!i[6])throw e.error(`File has no BetaG2 section`),Error(`File has no BetaG2 section`);if(i[6].length>1)throw e.error(`File has no BetaG2 section`),Error(`File has more than one GetaG2 section`);r.pos=i[6][0].p;let s=await r.read(n),c=t.fromRprLEM(s);return t.toRprUncompressed(o,0,c),f.update(o),c}async function x(e,t,n,o,s,c){let l=65536,u=a[t],d=u.F.n8*2;await G(r,i,e);let p=[],m=u.zero,h=u.zero,g=u.zero;for(let e=0;e0){let e=u.fromRprLEM(i,0),t=wa(Sa(4),0);m=u.add(m,u.timesScalar(g,t)),h=u.add(h,u.timesScalar(e,t))}let v=await u.multiExpAffine(i.slice(0,(t-1)*d),_),y=await u.multiExpAffine(i.slice(d),_);m=u.add(m,v),h=u.add(h,y),g=u.fromRprLEM(i,(t-1)*d);for(let n=0;n=e&&r1;)l/=2,u+=1;if(2**u!=c)throw Error(`Invalid file size`);i&&i.debug(`Power to tau size: `+u);let d=await Ta(r),f=await Eo(n),p=ua.create({dkLen:64});for(let e=0;e{i.debug(t+`.g1_s: `+e.G1.toString(g[t].g1_s,16)),i.debug(t+`.g1_sx: `+e.G1.toString(g[t].g1_sx,16)),i.debug(t+`.g2_sp: `+e.G2.toString(g[t].g2_sp,16)),i.debug(t+`.g2_spx: `+e.G2.toString(g[t].g2_spx,16)),i.debug(``)});let _=ua.create({dkLen:64});await f.write(h),_.update(h),await _s(a,f,_,e,`G1`,2**u*2-1,e.Fr.one,g.tau.prvKey,`COMPRESSED`,`tauG1`,i),await _s(a,f,_,e,`G2`,2**u,e.Fr.one,g.tau.prvKey,`COMPRESSED`,`tauG2`,i),await _s(a,f,_,e,`G1`,2**u,g.alpha.prvKey,g.tau.prvKey,`COMPRESSED`,`alphaTauG1`,i),await _s(a,f,_,e,`G1`,2**u,g.beta.prvKey,g.tau.prvKey,`COMPRESSED`,`betaTauG1`,i),await _s(a,f,_,e,`G2`,1,g.beta.prvKey,g.tau.prvKey,`COMPRESSED`,`betaTauG2`,i);let v=new Uint8Array(e.F1.n8*2*6+e.F2.n8*2*3);ns(v,0,e,g,!1),await f.write(v),_.update(v);let y=_.digest();i&&i.info(ha(y,`Contribution Response Hash: `)),await f.close(),await a.close()}async function ys(e,t,n,r,i,a){let o=Da(r);if(o.byteLength==0||o.byteLength*2!=r.length)return a&&a.error(`Invalid Beacon Hash. (It must be a valid hexadecimal sequence)`),!1;if(o.length>=256)return a&&a.error(`Maximum length of beacon hash is 255 bytes`),!1;if(i=parseInt(i),i<10||i>63)return a&&a.error(`Invalid numIterationsExp. (Must be between 10 and 63)`),!1;let{fd:s,sections:c}=await H(e,`ptau`,1),{curve:l,power:u,ceremonyPower:d}=await $o(s,c);if(u!=d)return a&&a.error(`This file has been reduced. You cannot contribute into a reduced file.`),!1;c[12]&&a&&a.warn(`Contributing into a file that has phase2 calculated. You will have to prepare phase2 again.`);let f=await as(s,l,c),p={name:n,type:1,numIterationsExp:i,beaconHash:o},m;m=f.length>0?f[f.length-1].nextChallenge:cs(l,u,a),p.key=await ls(l,m,o,i);let h=ua.create({dkLen:64});h.update(m);let g=await hi(t,`ptau`,1,7);await Qo(g,l,u);let _=[],v;v=await S(2,`G1`,2**u*2-1,l.Fr.e(1),p.key.tau.prvKey,`tauG1`,a),p.tauG1=v[1],v=await S(3,`G2`,2**u,l.Fr.e(1),p.key.tau.prvKey,`tauG2`,a),p.tauG2=v[1],v=await S(4,`G1`,2**u,p.key.alpha.prvKey,p.key.tau.prvKey,`alphaTauG1`,a),p.alphaG1=v[0],v=await S(5,`G1`,2**u,p.key.beta.prvKey,p.key.tau.prvKey,`betaTauG1`,a),p.betaG1=v[0],v=await S(6,`G2`,1,p.key.beta.prvKey,p.key.tau.prvKey,`betaTauG2`,a),p.betaG2=v[0],p.partialHash=ya(h);let y=new Uint8Array(l.F1.n8*2*6+l.F2.n8*2*3);ns(y,0,l,p.key,!1),h.update(new Uint8Array(y));let b=h.digest();a&&a.info(ha(b,`Contribution Response Hash imported: `));let x=ua.create({dkLen:64});return x.update(b),await C(g,`G1`,2,2**u*2-1,`tauG1`,a),await C(g,`G2`,3,2**u,`tauG2`,a),await C(g,`G1`,4,2**u,`alphaTauG1`,a),await C(g,`G1`,5,2**u,`betaTauG1`,a),await C(g,`G2`,6,1,`betaG2`,a),p.nextChallenge=x.digest(),a&&a.info(ha(p.nextChallenge,`Next Challenge Hash: `)),f.push(p),await ss(g,l,f),await s.close(),await g.close(),b;async function S(e,t,n,r,i,a,o){let u=[];s.pos=c[e][0].p,await U(g,e),_[e]=g.pos;let d=l[t],f=d.F.n8*2,p=Math.floor((1<<20)/f),m=r;for(let e=0;e0?u[u.length-1].nextChallenge:cs(s,c,i),d.key=Zo(s,f,p);let m=ua.create({dkLen:64});m.update(f);let h=await hi(t,`ptau`,1,7);await Qo(h,s,c);let g=[],_;_=await x(2,`G1`,2**c*2-1,s.Fr.e(1),d.key.tau.prvKey,`tauG1`),d.tauG1=_[1],_=await x(3,`G2`,2**c,s.Fr.e(1),d.key.tau.prvKey,`tauG2`),d.tauG2=_[1],_=await x(4,`G1`,2**c,d.key.alpha.prvKey,d.key.tau.prvKey,`alphaTauG1`),d.alphaG1=_[0],_=await x(5,`G1`,2**c,d.key.beta.prvKey,d.key.tau.prvKey,`betaTauG1`),d.betaG1=_[0],_=await x(6,`G2`,1,d.key.beta.prvKey,d.key.tau.prvKey,`betaTauG2`),d.betaG2=_[0],d.partialHash=ya(m);let v=new Uint8Array(s.F1.n8*2*6+s.F2.n8*2*3);ns(v,0,s,d.key,!1),m.update(new Uint8Array(v));let y=m.digest();i&&i.info(ha(y,`Contribution Response Hash imported: `));let b=ua.create({dkLen:64});return b.update(y),await S(h,`G1`,2,2**c*2-1,`tauG1`),await S(h,`G2`,3,2**c,`tauG2`),await S(h,`G1`,4,2**c,`alphaTauG1`),await S(h,`G1`,5,2**c,`betaTauG1`),await S(h,`G2`,6,1,`betaG2`),d.nextChallenge=b.digest(),i&&i.info(ha(d.nextChallenge,`Next Challenge Hash: `)),u.push(d),await ss(h,s,u),await a.close(),await h.close(),y;async function x(e,t,n,r,c,l){let u=[];a.pos=o[e][0].p,await U(h,e),g[e]=h.pos;let d=s[t],f=d.F.n8*2,p=Math.floor((1<<20)/f),_=r;for(let e=0;eys,challengeContribute:()=>vs,contribute:()=>bs,convert:()=>Cs,exportChallenge:()=>ds,exportJson:()=>ws,importResponse:()=>fs,newAccumulator:()=>us,preparePhase2:()=>xs,truncate:()=>Ss,verify:()=>hs});function Es(e,t,n){for(let t=0;t{let r=``;return Object.keys(n).forEach(i=>{let a=t.varIdx2Name[i];a==`one`&&(a=`1`);let o=e.curve.Fr.toString(n[i]);o==`1`&&(o=``),o==`-1`&&(o=`-`),r!=``&&o[0]!=`-`&&(o=`+`+o),r!=``&&(o=` `+o),r=r+o+a}),r},a=`[ ${i(r[0])} ] * [ ${i(r[1])} ] - [ ${i(r[2])} ] = 0`;n&&n.info(a)}}var Ds=262144,Os={get:function(e,t){return isNaN(t)?e[t]:e.getElement(t)},set:function(e,t,n){return isNaN(t)?(e[t]=n,!0):e.setElement(t,n)}},ks=class{constructor(e){this.length=e||0,this.arr=Array(Ds);for(let t=0;t=this.length&&(this.length=e+1),!0}getKeys(){let e=new As;for(let t=0;t1<<20?new As:[];for(let e=0;e1<<20?new As:[];for(let e=0;e1<<20?new As:[];for(let e=0;eVs,info:()=>Bs,print:()=>Es});async function Us(e){let t={labelIdx2Name:[`one`],varIdx2Name:[`one`],componentIdx2Name:[]},n=await Do(e),r=await n.read(n.totalSize),i=new TextDecoder(`utf-8`).decode(r).split(` -`);for(let e=0;e `+t.toString())}),i.trigger&&(u||=await Us(r),l.logStartComponent=function(e){a&&a.info(`START: `+u.componentIdx2Name[e])},l.logFinishComponent=function(e){a&&a.info(`FINISH: `+u.componentIdx2Name[e])}),l.sym=u;let d=await Mo(c,l),f=await d.calculateWitness(o,!0),p=await hi(n,`wtns`,2,2);await qa(p,f,d.prime),await p.close()}async function Ks(e){return await Xa(e)}async function qs(e,t,n){n&&n.info(`WITNESS CHECKING STARTED`),n&&n.info(`> Reading r1cs file`);let{fd:r,sections:i}=await H(e,`r1cs`,1,1<<22,1<<24),a=await Ps(r,i,{loadConstraints:!1,loadCustomGates:!1});n&&n.info(`> Reading witness file`);let{fd:o,sections:s}=await H(t,`wtns`,2,1<<22,1<<24),c=await Ya(o,s);if(!V.eq(a.prime,c.q))throw Error(`Curve of the witness does not match the curve of the proving key`);let l=await J(o,s,2);await o.close();let u=(await wi(a.prime)).Fr,d=u.n8,f=await J(r,i,2);n&&(n.info(`----------------------------`),n.info(` WITNESS CHECK`),n.info(` Curve: ${a.curve.name}`),n.info(` Vars (wires): ${a.nVars}`),n.info(` Outputs: ${a.nOutputs}`),n.info(` Public Inputs: ${a.nPubInputs}`),n.info(` Private Inputs: ${a.nPrvInputs}`),n.info(` Labels: ${a.nLabels}`),n.info(` Constraints: ${a.nConstraints}`),n.info(` Custom Gates: ${a.useCustomGates}`),n.info(`----------------------------`)),n&&n.info(`> Checking witness correctness`);let p=0,m=!0;for(let e=0;e{let r=_(n),i=e[n];t=u.add(t,u.mul(r,i))}),t}function g(){let e={},t=f.slice(p,p+4);p+=4;let n=new DataView(t.buffer).getUint32(0,!0),r=f.slice(p,p+(4+a.n8)*n);p+=(4+a.n8)*n;let i=new DataView(r.buffer);for(let t=0;tIo,check:()=>qs,debug:()=>Gs,exportJson:()=>Ks}),Ys=262144,Xs={get:function(e,t){return isNaN(t)?e[t]:e.getElement(t)},set:function(e,t,n){return isNaN(t)?(e[t]=n,!0):e.setElement(t,n)}},Zs=class{constructor(e){this.length=e||0,this.arr=Array(Ys);for(let t=0;t=this.length&&(this.length=e+1),!0}getKeys(){let e=new Qs;for(let t=0;tc)return r&&r.error(`circuit too big for this power of tau ceremony. ${d.nConstraints}*2 > 2**${c}`),-1;if(!o[12])return r&&r.error(`Powers of tau is not prepared.`),-1;let g=d.nOutputs+d.nPubInputs,_=2**h;await U(f,1),await f.writeULE32(1),await W(f),await U(f,2);let v=s.q,y=(Math.floor((V.bitLength(v)-1)/64)+1)*8,b=s.r,x=(Math.floor((V.bitLength(b)-1)/64)+1)*8,S=V.mod(V.shl(1,x*8),b),C=s.Fr.e(V.mod(V.mul(S,S),b));await f.writeULE32(y),await gi(f,v,y),await f.writeULE32(x),await gi(f,b,x),await f.writeULE32(d.nVars),await f.writeULE32(g),await f.writeULE32(_);let w;w=await a.read(p,o[4][0].p),await f.write(w),w=await s.G1.batchLEMtoU(w),i.update(w);let T;T=await a.read(p,o[5][0].p),await f.write(T),T=await s.G1.batchLEMtoU(T),i.update(T);let E;E=await a.read(m,o[6][0].p),await f.write(E),E=await s.G2.batchLEMtoU(E),i.update(E);let D=new Uint8Array(p);s.G1.toRprLEM(D,0,s.G1.g);let O=new Uint8Array(m);s.G2.toRprLEM(O,0,s.G2.g);let k=new Uint8Array(p);s.G1.toRprUncompressed(k,0,s.G1.g);let A=new Uint8Array(m);s.G2.toRprUncompressed(A,0,s.G2.g),await f.write(O),await f.write(D),await f.write(O),i.update(A),i.update(k),i.update(A),await W(f),r&&r.info(de()),r&&r.info(`Reading r1cs`);let j=await J(l,u,2);await l.close();let M=new Qs(d.nVars),N=new Qs(d.nVars),P=new Qs(d.nVars),F=new Qs(d.nVars-g-1),I=Array(g+1);r&&r.info(de()),r&&r.info(`Reading tauG1`);let L=await J(a,o,12,(_-1)*p,_*p);r&&r.info(`Reading tauG2`);let ee=await J(a,o,13,(_-1)*m,_*m);r&&r.info(`Reading alphatauG1`);let R=await J(a,o,14,(_-1)*p,_*p);r&&r.info(`Reading betatauG1`);let te=await J(a,o,15,(_-1)*p,_*p);r&&r.info(de()),r&&r.info(`processConstraints`),await ie(),r&&r.info(de()),r&&r.info(`composeAndWritePoints`),await ae(3,`G1`,I,`IC`),I=null,r&&r.info(de()),r&&r.info(`writeHs`),await re(),r&&r.info(de()),r&&r.info(`hashHPoints`),await se(),r&&r.info(de()),r&&r.info(`composeAndWritePoints 8 G1 C`),await ae(8,`G1`,F,`C`),F=null,r&&r.info(de()),r&&r.info(`composeAndWritePoints 5 G1 A`),await ae(5,`G1`,M,`A`),M=null,r&&r.info(de()),r&&r.info(`composeAndWritePoints 6 G1 B1`),await ae(6,`G1`,N,`B1`),N=null,r&&r.info(de()),r&&r.info(`composeAndWritePoints 7 G2 B2`),await ae(7,`G2`,P,`B2`),P=null,r&&r.info(de()),r&&r.info(`Contributions section`);let ne=i.digest();return await U(f,10),await f.write(ne),await f.writeULE32(0),await W(f),r&&r.info(ha(ne,`Circuit hash: `)),await f.close(),await a.close(),ne;async function re(){await U(f,9);let e=new B(_*p);if(h=0?s.Fr.fromRprLE(j.slice(r[3],r[3]+s.Fr.n8),0):s.Fr.fromRprLE(n,0);let a=s.Fr.mul(i,C);s.Fr.toRprLE(e,12,a),c.set(e,u),u+=e.length}}async function ae(e,t,n,a){let o=32768,c=s[t];ue(n.length),await U(f,e);let l=[],u=0;for(;u(r&&r.debug(`Writing points end ${a}: ${d}/${n.length}`),e))),u+=i,e++}let d=await Promise.all(l);for(let e=0;e32768?(m=new B(p*a),h=new B(p*s.Fr.n8)):(m=new Uint8Array(p*a),h=new Uint8Array(p*s.Fr.n8));let g,_,v=[L,ee,R,te],y=new Uint8Array(s.Fr.n8);s.Fr.toRprLE(y,0,s.Fr.e(1));let b=0;for(let e=0;e=0?h.set(j.slice(t[e][i][2],t[e][i][2]+s.Fr.n8),b*s.Fr.n8):h.set(y,b*s.Fr.n8),b++;if(t.length>1){let e=[];e.push({cmd:`ALLOCSET`,var:0,buff:m}),e.push({cmd:`ALLOCSET`,var:1,buff:h}),e.push({cmd:`ALLOC`,var:2,len:t.length*o}),g=0,_=0;let n=0;for(let r=0;rf.contributions.length)return i&&i.error(`The impoerted file does not include new contributions`),!1;for(let e=0;e=0;e--){let t=u.contributions[e];r&&r.info(`-------------------------`),r&&r.info(ha(t.contributionHash,`contribution #${e+1} ${t.name?t.name:``}:`)),t.type==1&&(r&&r.info(`Beacon generator: ${Oa(t.beaconHash)}`),r&&r.info(`Beacon iterations Exp: ${t.numIterationsExp}`))}return r&&r.info(`-------------------------`),r&&r.info(`ZKey Ok!`),!0;async function v(e,t,n,a,o,s,l,u,d){let f=1<<20,p=c[e],m=p.F.n8*2;await G(t,n,s),await G(a,o,s);let h=p.zero,g=p.zero,_=n[s][0].size/m;for(let e=0;e<_;e+=f){r&&r.debug(`Same ratio check ${d}: ${e}/${_}`);let n=Math.min(_-e,f),i=await t.read(n*m),o=await a.read(n*m),s=Sa(4*n),c=await p.multiExpAffine(i,s),l=await p.multiExpAffine(o,s);h=p.add(h,c),g=p.add(g,l)}return await K(t),await K(a),_==0?!0:(i=await nc(c,h,g,l,u),i===!0)}async function y(){let e=1<<20,n=c.G1,l=c.Fr,u=n.F.n8*2,{fd:d,sections:f}=await H(t,`ptau`,1),p=new B(s.domainSize*s.n8r),m=Array(8);for(let e=0;e<8;e++)m[e]=wa(Sa(4),0);let g=new Gn(m);for(let e=0;e=256)return a&&a.error(`Maximum length of beacon hash is 255 bytes`),!1;if(i=parseInt(i),i<10||i>63)return a&&a.error(`Invalid numIterationsExp. (Must be between 10 and 63)`),!1;let{fd:s,sections:c}=await H(e,`zkey`,2),l=await Fa(s,c);if(l.protocol!=`groth16`)throw Error(`zkey file is not groth16`);let u=await Ti(l.q),d=await Va(s,u,c),f=await hi(t,`zkey`,1,10),p=await Ea(o,i),m=ua.create({dkLen:64});m.update(d.csHash);for(let e=0;e Detected protocol: `+i.protocol);let a;if(i.protocol===`groth16`)a=await dc(i,n,r);else if(i.protocol===`plonk`)a=await fc(i);else if(i.protocolId&&i.protocolId===10)a=await pc(i,t);else throw Error(`zkey file protocol unrecognized`);return await n.close(),t&&t.info(`EXPORT VERIFICATION KEY FINISHED`),a}async function dc(e,t,n){let r=await Ti(e.q),i=r.G1.F.n8*2,a=await r.pairing(e.vk_alpha_1,e.vk_beta_2),o={protocol:e.protocol,curve:r.name,nPublic:e.nPublic,vk_alpha_1:r.G1.toObject(e.vk_alpha_1),vk_beta_2:r.G2.toObject(e.vk_beta_2),vk_gamma_2:r.G2.toObject(e.vk_gamma_2),vk_delta_2:r.G2.toObject(e.vk_delta_2),vk_alphabeta_12:r.Gt.toObject(a)};await G(t,n,3),o.IC=[];for(let n=0;n<=e.nPublic;n++){let e=await t.read(i),n=r.G1.toObject(e);o.IC.push(n)}return await K(t),o=lc(o),o}async function fc(e){let t=await Ti(e.q),n={protocol:e.protocol,curve:t.name,nPublic:e.nPublic,power:e.power,k1:t.Fr.toObject(e.k1),k2:t.Fr.toObject(e.k2),Qm:t.G1.toObject(e.Qm),Ql:t.G1.toObject(e.Ql),Qr:t.G1.toObject(e.Qr),Qo:t.G1.toObject(e.Qo),Qc:t.G1.toObject(e.Qc),S1:t.G1.toObject(e.S1),S2:t.G1.toObject(e.S2),S3:t.G1.toObject(e.S3),X_2:t.G2.toObject(e.X_2),w:t.Fr.toObject(t.Fr.w[e.power])};return n=lc(n),n}async function pc(e,t){let n=await Ti(e.q);return lc({protocol:e.protocol,curve:n.name,nPublic:e.nPublic,power:e.power,k1:n.Fr.toObject(e.k1),k2:n.Fr.toObject(e.k2),w:n.Fr.toObject(n.Fr.w[e.power]),w3:n.Fr.toObject(e.w3),w4:n.Fr.toObject(e.w4),w8:n.Fr.toObject(e.w8),wr:n.Fr.toObject(e.wr),X_2:n.G2.toObject(e.X_2),C0:n.G1.toObject(e.C0)})}function mc(e){return yc[e]||e}function hc(){return Function.prototype.toString.call(this)+`; -`+xc}var X,gc,_c,vc,yc,bc,xc,Sc=s((()=>{X={},gc=/[|\\{}()[\]^$+*?.]/g,_c=Object.prototype.hasOwnProperty,vc=function(e,t){return _c.apply(e,[t])},X.escapeRegExpChars=function(e){return e?String(e).replace(gc,`\\$&`):``},yc={"&":`&`,"<":`<`,">":`>`,'"':`"`,"'":`'`},bc=/[&<>'"]/g,xc=`var _ENCODE_HTML_RULES = { - "&": "&" - , "<": "<" - , ">": ">" - , '"': """ - , "'": "'" - } - , _MATCH_HTML = /[&<>'"]/g; -function encode_char(c) { - return _ENCODE_HTML_RULES[c] || c; -}; -`,X.escapeXML=function(e){return e==null?``:String(e).replace(bc,mc)};try{typeof Object.defineProperty==`function`?Object.defineProperty(X.escapeXML,`toString`,{value:hc}):X.escapeXML.toString=hc}catch{console.warn(`Unable to set escapeXML.toString (is the Function prototype frozen?)`)}X.shallowCopy=function(e,t){if(t||={},e!=null)for(var n in t)vc(t,n)&&(n===`__proto__`||n===`constructor`||(e[n]=t[n]));return e},X.shallowCopyFromList=function(e,t,n){if(n||=[],t||={},e!=null)for(var r=0;rZ});function wc(e,t){let n;if(t.some(function(t){return n=Z.resolveInclude(e,t,!0),Nc.default.existsSync(n)}))return n}function Tc(e,t){let n,r,i=t.views,a=/^[A-Za-z]+:\\|^\//.exec(e);if(a&&a.length)e=e.replace(/^\/*/,``),n=Array.isArray(t.root)?wc(e,t.root):Z.resolveInclude(e,t.root||`/`,!0);else if(t.filename&&(r=Z.resolveInclude(e,t.filename),Nc.default.existsSync(r)&&(n=r)),!n&&Array.isArray(i)&&(n=wc(e,i)),!n&&typeof t.includer!=`function`)throw Error(`Could not find the include file "`+t.escapeFunction(e)+`"`);return n}function Ec(e,t){let n,r=e.filename,i=arguments.length>1;if(e.cache){if(!r)throw Error(`cache option requires a filename`);if(n=Z.cache.get(r),n)return n;i||(t=Oc(r).toString().replace(Uc,``))}else if(!i){if(!r)throw Error(`Internal EJS error: no file name or template provided`);t=Oc(r).toString().replace(Uc,``)}return n=Z.compile(t,e),e.cache&&Z.cache.set(r,n),n}function Dc(e,t,n){let r;if(n){try{r=Ec(e)(t)}catch(e){return n(e)}n(null,r)}else{if(typeof Z.promiseImpl==`function`)return new Z.promiseImpl(function(n,i){try{r=Ec(e)(t),n(r)}catch(e){i(e)}});throw Error(`Please provide a callback function`)}}function Oc(e){return Z.fileLoader(e)}function kc(e,t){let n=X.shallowCopy(X.createNullProtoObjWherePossible(),t);if(n.filename=Tc(e,n),typeof t.includer==`function`){let r=t.includer(e,n.filename);if(r&&(r.filename&&(n.filename=r.filename),r.template))return Ec(n,r.template)}return Ec(n)}function Ac(e,t,n,r,i){let a=t.split(` -`),o=Math.max(r-3,0),s=Math.min(a.length,r+3),c=i(n),l=a.slice(o,s).map(function(e,t){let n=t+o+1;return(n==r?` >> `:` `)+n+`| `+e}).join(` -`);throw e.path=c,e.message=(c||`ejs`)+`:`+r+` -`+l+` - -`+e.message,e}function jc(e){return e.replace(/;(\s*$)/,`$1`)}function Mc(e,t){let n=X.hasOwnOnlyObject(t),r=X.createNullProtoObjWherePossible();this.templateText=e,this.mode=null,this.truncate=!1,this.currentLine=1,this.source=``,r.escapeFunction=n.escape||n.escapeFunction||X.escapeXML,r.compileDebug=n.compileDebug!==!1,r.debug=!!n.debug,r.filename=n.filename,r.openDelimiter=n.openDelimiter||Z.openDelimiter||Ic,r.closeDelimiter=n.closeDelimiter||Z.closeDelimiter||Lc,r.delimiter=n.delimiter||Z.delimiter||Rc,r.strict=n.strict||!1,r.context=n.context,r.cache=n.cache||!1,r.rmWhitespace=n.rmWhitespace,r.root=n.root,r.includer=n.includer,r.outputFunctionName=n.outputFunctionName,r.localsName=n.localsName||Z.localsName||zc,r.views=n.views,r.async=n.async,r.destructuredLocals=n.destructuredLocals,r.legacyInclude=n.legacyInclude===void 0?!0:!!n.legacyInclude,r.strict?r._with=!1:r._with=n._with===void 0?!0:n._with,this.opts=r,this.regex=this.createRegex()}var Nc,Pc,Fc,Z,Ic,Lc,Rc,zc,Bc,Vc,Hc,Uc,Wc,Gc=s((()=>{Nc=d(da()),Pc=d(da()),Sc(),Fc=`let`,Z={},Ic=`<`,Lc=`>`,Rc=`%`,zc=`locals`,Bc=`(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)`,Vc=[`delimiter`,`scope`,`context`,`debug`,`compileDebug`,`_with`,`rmWhitespace`,`strict`,`filename`,`async`],Hc=Vc.concat(`cache`),Uc=/^\uFEFF/,Wc=/^[a-zA-Z_$][0-9a-zA-Z_$]*$/,Z.cache=X.cache,Z.fileLoader=Nc.default.readFileSync,Z.localsName=zc,Z.promiseImpl=Function(`return this;`)().Promise,Z.resolveInclude=function(e,t,n){let r=Pc.default.dirname,i=Pc.default.extname,a=Pc.default.resolve,o=a(n?t:r(t),e);return i(e)||(o+=`.ejs`),o},Z.compile=function(e,t){let n;return t&&t.scope&&(console.warn("`scope` option is deprecated and will be removed in future EJS"),t.context||=t.scope,delete t.scope),n=new Mc(e,t),n.compile()},Z.render=function(e,t,n){let r=t||X.createNullProtoObjWherePossible(),i=n||X.createNullProtoObjWherePossible();return arguments.length==2&&X.shallowCopyFromList(i,r,Vc),Ec(i,e)(r)},Z.renderFile=function(){let e=Array.prototype.slice.call(arguments),t=e.shift(),n,r={filename:t},i,a;return typeof arguments[arguments.length-1]==`function`&&(n=e.pop()),e.length?(i=e.shift(),e.length?X.shallowCopy(r,e.pop()):(i.settings&&(i.settings.views&&(r.views=i.settings.views),i.settings[`view cache`]&&(r.cache=!0),a=i.settings[`view options`],a&&X.shallowCopy(r,a)),X.shallowCopyFromList(r,i,Hc)),r.filename=t):i=X.createNullProtoObjWherePossible(),Dc(r,i,n)},Z.Template=Mc,Z.clearCache=function(){Z.cache.reset()},Mc.modes={EVAL:`eval`,ESCAPED:`escaped`,RAW:`raw`,COMMENT:`comment`,LITERAL:`literal`},Mc.prototype={createRegex:function(){let e=Bc,t=X.escapeRegExpChars(this.opts.delimiter),n=X.escapeRegExpChars(this.opts.openDelimiter),r=X.escapeRegExpChars(this.opts.closeDelimiter);return e=e.replace(/%/g,t).replace(//g,r),new RegExp(e)},compile:function(){let e,t,n=this.opts,r=``,i=``,a=n.escapeFunction,o,s=n.filename?JSON.stringify(n.filename):`undefined`;if(!this.source){if(this.generateSource(),r+=` ${Fc} __output = "";\n function __append(s) { if (s !== undefined && s !== null) __output += s } -`,n.outputFunctionName){if(!Wc.test(n.outputFunctionName))throw Error(`outputFunctionName is not a valid JS identifier.`);r+=` ${Fc} `+n.outputFunctionName+` = __append; -`}if(n.localsName&&!Wc.test(n.localsName))throw Error(`localsName is not a valid JS identifier.`);if(n.destructuredLocals&&n.destructuredLocals.length){let e=` ${Fc} __locals = (`+n.localsName+` || {}), -`;for(let t=0;t0&&(e+=`, - `),e+=r+` = __locals.`+r}r+=e+`; -`}n._with!==!1&&(r+=` with (`+n.localsName+` || {}) { -`,i+=` } -`),i+=` return __output; -`,this.source=r+this.source+i}e=n.compileDebug?`${Fc} __line = 1 - , __lines = `+JSON.stringify(this.templateText)+` - , __filename = `+s+`; -try { -`+this.source+`} catch (e) { - rethrow(e, __lines, __filename, __line, escapeFn); -} -`:this.source,n.strict&&(e=`"use strict"; -`+e),n.debug&&console.log(e),n.compileDebug&&n.filename&&(e=e+` -//# sourceURL=`+s+` -`);try{if(n.async)try{o=Function(`return (async function(){}).constructor;`)()}catch(e){throw e instanceof SyntaxError?Error(`This environment does not support async/await`):e}else o=Function;t=new o(n.localsName+`, escapeFn, include, rethrow`,e)}catch(e){throw e instanceof SyntaxError&&(n.filename&&(e.message+=` in `+n.filename),e.message+=` while compiling ejs - -`,e.message+=`If the above error is not helpful, you may want to try EJS-Lint: -`,e.message+=`https://github.com/RyanZim/EJS-Lint`,n.async||(e.message+=` -`,e.message+="Or, if you meant to create an async function, pass `async: true` as an option.")),e}let c=function(e){return t.apply(n.context,[e||X.createNullProtoObjWherePossible(),a,function(t,r){let i=X.shallowCopy(X.createNullProtoObjWherePossible(),e);return r&&(i=X.shallowCopy(i,r)),kc(t,n)(i)},Ac])};if(n.filename&&typeof Object.defineProperty==`function`){let e=n.filename,t=Pc.default.basename(e,Pc.default.extname(e));try{Object.defineProperty(c,`name`,{value:t,writable:!1,enumerable:!1,configurable:!0})}catch{}}return c},generateSource:function(){this.opts.rmWhitespace&&(this.templateText=this.templateText.replace(/[\r\n]+/g,` -`).replace(/^\s+|\s+$/gm,``));let e=this,t=this.opts.delimiter,n=this.opts.openDelimiter,r=this.opts.closeDelimiter,i=X.escapeRegExpChars(n+t+`_`),a=X.escapeRegExpChars(`_`+t+r),o=n+t+`_`,s=`_`+t+r;this.templateText=this.templateText.replace(RegExp(`[ \\t]*`+i,`gm`),o).replace(RegExp(a+`[ \\t]*`,`gm`),s);let c=this.parseTemplateText();c&&c.length&&c.forEach(function(i,a){let o;if(i.indexOf(n+t)===0&&i.indexOf(n+t+t)!==0&&(o=c[a+2],!(o==t+r||o==`-`+t+r||o==`_`+t+r)))throw Error(`Could not find matching close tag for "`+i+`".`);e.scanLine(i)})},parseTemplateText:function(){let e=this.templateText,t=this.regex,n=t.exec(e),r=[],i;for(;n;)i=n.index,i!==0&&(r.push(e.substring(0,i)),e=e.slice(i)),r.push(n[0]),e=e.slice(n[0].length),n=t.exec(e);return e&&r.push(e),r},_addOutput:function(e){if(this.truncate&&=(e=e.replace(/^(?:\r\n|\r|\n)/,``),!1),!e)return e;e=e.replace(/\\/g,`\\\\`),e=e.replace(/\n/g,`\\n`),e=e.replace(/\r/g,`\\r`),e=e.replace(/"/g,`\\"`),this.source+=` ; __append("`+e+`") -`},scanLine:function(e){let t=this,n=this.opts.delimiter,r=this.opts.openDelimiter,i=this.opts.closeDelimiter,a=0;switch(a=e.split(` -`).length-1,e){case r+n:case r+n+`_`:this.mode=Mc.modes.EVAL;break;case r+n+`=`:this.mode=Mc.modes.ESCAPED;break;case r+n+`-`:this.mode=Mc.modes.RAW;break;case r+n+`#`:this.mode=Mc.modes.COMMENT;break;case r+n+n:this.mode=Mc.modes.LITERAL,this.source+=` ; __append("`+e.replace(r+n+n,r+n)+`") -`;break;case n+n+i:this.mode=Mc.modes.LITERAL,this.source+=` ; __append("`+e.replace(n+n+i,n+i)+`") -`;break;case n+i:case`-`+n+i:case`_`+n+i:this.mode==Mc.modes.LITERAL&&this._addOutput(e),this.mode=null,this.truncate=e.indexOf(`-`)===0||e.indexOf(`_`)===0;break;default:if(this.mode){switch(this.mode){case Mc.modes.EVAL:case Mc.modes.ESCAPED:case Mc.modes.RAW:e.lastIndexOf(`//`)>e.lastIndexOf(` -`)&&(e+=` -`)}switch(this.mode){case Mc.modes.EVAL:this.source+=` ; `+e+` -`;break;case Mc.modes.ESCAPED:this.source+=` ; __append(escapeFn(`+jc(e)+`)) -`;break;case Mc.modes.RAW:this.source+=` ; __append(`+jc(e)+`) -`;break;case Mc.modes.COMMENT:break;case Mc.modes.LITERAL:this._addOutput(e);break}}else this._addOutput(e)}t.opts.compileDebug&&a&&(this.currentLine+=a,this.source+=` ; __line = `+this.currentLine+` -`)}},Z.escapeXML=X.escapeXML,Z.__express=Z.renderFile,typeof window<`u`&&(window.ejs=Z),typeof module<`u`&&(module.exports=Z)})),{unstringifyBigInts:Kc,stringifyBigInts:qc}=Gr;async function Jc(e,t,n){n&&n.info(`FFLONK EXPORT SOLIDITY VERIFIER STARTED`);let r=await Ei(e.curve),i=u(e.w3);e.w3_2=d(r.Fr.square(i));let a=u(e.w4);e.w4_2=d(r.Fr.square(a)),e.w4_3=d(r.Fr.mul(r.Fr.square(a),a));let o=u(e.w8),s=r.Fr.one;for(let t=1;t<8;t++)s=r.Fr.mul(s,o),e[`w8_`+t]=d(s);let c=t[e.protocol];n&&n.info(`FFLONK EXPORT SOLIDITY VERIFIER FINISHED`);let{default:l}=await Promise.resolve().then(()=>(Gc(),Cc));return l.render(c,e);function u(e){let t=Kc(e);return r.Fr.fromObject(t)}function d(e){return qc(r.Fr.toObject(e))}}async function Yc(e,t,n){let r=await uc(e,n);if(r.protocol===`fflonk`)return Jc(r,t,n);let i=t[r.protocol],{default:a}=await Promise.resolve().then(()=>(Gc(),Cc));return a.render(i,r)}var Xc=l({beacon:()=>oc,bellmanContribute:()=>cc,contribute:()=>ac,exportBellman:()=>ec,exportJson:()=>sc,exportSolidityVerifier:()=>Yc,exportVerificationKey:()=>uc,importBellman:()=>tc,newZKey:()=>$s,verifyFromInit:()=>rc,verifyFromR1cs:()=>ic});async function Zc(e,t,n,r){globalThis.gc&&globalThis.gc();let{fd:i,sections:a}=await H(t,`ptau`,1,1<<22,1<<24),{curve:o,power:s}=await $o(i,a),{fd:c,sections:l}=await H(e,`r1cs`,1,1<<22,1<<24),u=await Ps(c,l,{loadConstraints:!0,loadCustomGates:!0}),d=o.G1.F.n8*2,f=o.G1,p=o.G2.F.n8*2,m=o.Fr,h=o.Fr.n8;r&&r.info(`Reading r1cs`),await J(c,l,2);let g=new Qs,_=new Qs,v=u.nVars,y=u.nOutputs+u.nPubInputs;await k(o.Fr,u,r),globalThis.gc&&globalThis.gc();let b=await hi(n,`zkey`,1,14,1<<22,1<<24);if(u.prime!=o.r)return r&&r.error(`r1cs curve does not match powers of tau ceremony curve`),-1;let x=ma(g.length-1)+1;x<3&&(x=3);let S=2**x;if(r&&r.info(`Plonk constraints: `+g.length),x>s)return r&&r.error(`circuit too big for this power of tau ceremony. ${g.length} > 2**${s}`),-1;if(!a[12])return r&&r.error(`Powers of tau is not prepared.`),-1;let C=new B(S*d),w=a[12][0].p+(2**x-1)*d;await i.readToBuffer(C,0,S*d,w);let[T,E]=L(),D={};await N(3,`Additions`),globalThis.gc&&globalThis.gc(),await A(4,0,`Amap`),globalThis.gc&&globalThis.gc(),await A(5,1,`Bmap`),globalThis.gc&&globalThis.gc(),await A(6,2,`Cmap`),globalThis.gc&&globalThis.gc(),await j(7,3,`Qm`),globalThis.gc&&globalThis.gc(),await j(8,4,`Ql`),globalThis.gc&&globalThis.gc(),await j(9,5,`Qr`),globalThis.gc&&globalThis.gc(),await j(10,6,`Qo`),globalThis.gc&&globalThis.gc(),await j(11,7,`Qc`),globalThis.gc&&globalThis.gc(),await P(12,`sigma`),globalThis.gc&&globalThis.gc(),await F(13,`lagrange polynomials`),globalThis.gc&&globalThis.gc(),await U(b,14);let O=new B((S+6)*d);await i.readToBuffer(O,0,(S+6)*d,a[2][0].p),await b.write(O),await W(b),globalThis.gc&&globalThis.gc(),await I(),await b.close(),await c.close(),await i.close(),r&&r.info(`Setup Finished`);return;async function k(e,t,n){function r(e){let t=Object.keys(e);for(let n=0;nn;){let t=i.shift(),n=i.shift(),r=t[0],a=n[0],o=v++,s=e.zero,c=e.neg(t[1]),l=e.neg(n[1]),u=e.one,d=e.zero;g.push([r,a,o,s,c,l,u,d]),_.push([r,a,t[1],n[1]]),i.push([o,e.one])}for(let e=0;e0?r.toString():n==e.zero?`0`:`k`}function l(e,t,n){let a=c(e),l=c(t);a===`0`||l===`0`?(r(n),o(n)):a===`k`?o(i(t,e[0],n)):l===`k`?o(i(e,t[0],n)):s(e,t,n)}for(let t=1;t<=y;t++){let n=t,r=e.zero,i=e.one,a=e.zero,o=e.zero,s=e.zero;g.push([n,0,0,r,i,a,o,s])}for(let e=0;e{let r=this.curve.G1.toObject(this.polynomials[n]);e?t.polynomials[n]=r:t[n]=r}),Object.keys(this.evaluations).forEach(n=>{let r=this.curve.Fr.toObject(this.evaluations[n]);e?t.evaluations[n]=r:t[n]=r}),t}fromObjectProof(e){this.resetProof(),Object.keys(e.polynomials).forEach(t=>{this.polynomials[t]=this.curve.G1.fromObject(e.polynomials[t])}),Object.keys(e.evaluations).forEach(t=>{this.evaluations[t]=this.curve.Fr.fromObject(e.evaluations[t])})}},$c=BigInt(0),el=BigInt(1),tl=BigInt(2),nl=BigInt(7),rl=BigInt(256),il=BigInt(113),al=[],ol=[],sl=[];for(let e=0,t=el,n=1,r=0;e<24;e++){[n,r]=[r,(2*n+3*r)%5],al.push(2*(5*r+n)),ol.push((e+1)*(e+2)/2%64);let i=$c;for(let e=0;e<7;e++)t=(t<>nl)*il)%rl,t&tl&&(i^=el<<(el<n>32?$i(e,t,n):Zi(e,t,n),fl=(e,t,n)=>n>32?ea(e,t,n):Qi(e,t,n);function pl(e,t=24){let n=new Uint32Array(10);for(let r=24-t;r<24;r++){for(let t=0;t<10;t++)n[t]=e[t]^e[t+10]^e[t+20]^e[t+30]^e[t+40];for(let t=0;t<10;t+=2){let r=(t+8)%10,i=(t+2)%10,a=n[i],o=n[i+1],s=dl(a,o,1)^n[r],c=fl(a,o,1)^n[r+1];for(let n=0;n<50;n+=10)e[t+n]^=s,e[t+n+1]^=c}let t=e[2],i=e[3];for(let n=0;n<24;n++){let r=ol[n],a=dl(t,i,r),o=fl(t,i,r),s=al[n];t=e[s],i=e[s+1],e[s]=a,e[s+1]=o}for(let t=0;t<50;t+=10){for(let r=0;r<10;r++)n[r]=e[t+r];for(let r=0;r<10;r++)e[t+r]^=~n[(r+2)%10]&n[(r+4)%10]}e[0]^=ll[r],e[1]^=ul[r]}Ni(n)}var ml=class e{state;pos=0;posOut=0;finished=!1;state32;destroyed=!1;blockLen;suffix;outputLen;enableXOF=!1;rounds;constructor(e,t,n,r=!1,i=24){if(this.blockLen=e,this.suffix=t,this.outputLen=n,this.enableXOF=r,this.rounds=i,Oi(n,`outputLen`),!(0=n&&this.keccak();let a=Math.min(n-this.posOut,i-r);e.set(t.subarray(this.posOut,this.posOut+a),r),this.posOut+=a,r+=a}return e}xofInto(e){if(!this.enableXOF)throw Error(`XOF is not possible for this instance`);return this.writeInto(e)}xof(e){return Oi(e),this.xofInto(new Uint8Array(e))}digestInto(e){if(ji(e,this),this.finished)throw Error(`digest() was already called`);return this.writeInto(e),this.destroy(),e}digest(){return this.digestInto(new Uint8Array(this.outputLen))}destroy(){this.destroyed=!0,Ni(this.state)}_cloneInto(t){let{blockLen:n,suffix:r,outputLen:i,rounds:a,enableXOF:o}=this;return t||=new e(n,r,i,o,a),t.state32.set(this.state32),t.pos=this.pos,t.posOut=this.posOut,t.finished=this.finished,t.rounds=a,t.suffix=r,t.outputLen=i,t.enableXOF=o,t.destroyed=this.destroyed,t}},hl=((e,t,n,r={})=>zi(()=>new ml(t,e,n),r))(1,136,32),gl=0,_l=1,vl=class{constructor(e){this.G1=e.G1,this.Fr=e.Fr,this.reset()}reset(){this.data=[]}addPolCommitment(e){this.data.push({type:gl,data:e})}addScalar(e){this.data.push({type:_l,data:e})}getChallenge(){if(this.data.length===0)throw Error(`Keccak256Transcript: No data to generate a transcript`);let e=0,t=0;this.data.forEach(n=>gl===n.type?e++:t++);let n=new Uint8Array(t*this.Fr.n8+e*this.G1.F.n8*2),r=0;for(let e=0;e32768?new B(t.length*i.n8):new Uint8Array(t.length*i.n8);for(let e=0;e32768?new B(i*a.n8):new Uint8Array(i*a.n8);return o.set(t.coef.slice(),0),new e(o,n,r)}isEqual(e){let t=this.degree();if(t!==e.degree())return!1;for(let n=0;n32768?new B((this.length()+e.length)*this.Fr.n8):new Uint8Array((this.length()+e.length)*this.Fr.n8);t.set(this.coef,0);for(let n=0;nthis.coef.byteLength?this.Fr.zero:this.coef.slice(t,t+this.Fr.n8)}setCoef(e,t){if(e>this.length()-1)throw Error(`Coef index is not available`);this.coef.set(t,e*this.Fr.n8)}static async to4T(e,t,n,r){n||=[];let i=await r.ifft(e),a=t*4>32768?new B(t*4*r.n8):new Uint8Array(t*4*r.n8);a.set(i,0);let o=await r.fft(a);if(n.length===0)return[i,o];let s=t+n.length>32768?new B((t+n.length)*r.n8):new Uint8Array((t+n.length)*r.n8);s.set(i,0);for(let e=0;e0;e--){let t=e*this.Fr.n8;if(!this.Fr.eq(this.Fr.zero,this.coef.slice(t,t+this.Fr.n8)))return e}return 0}evaluate(e){let t=this.Fr.zero;for(let n=this.degree()+1;n>0;n--){let r=n*this.Fr.n8,i=this.coef.slice(r-this.Fr.n8,r);t=this.Fr.add(i,this.Fr.mul(t,e))}return t}fastEvaluate(e){let t=this.Fr,n=this.degree()+1,r=parseInt(n/3),i=n-r*3,a=[],o=[];o[0]=t.one;for(let n=0;n<3;n++){a[n]=t.zero;let s=n===2?r+i:r;for(let i=s;i>0;i--)a[n]=t.add(this.getCoef(n*r+i-1),t.mul(a[n],e)),n===0&&(o[0]=t.mul(o[0],e))}for(let e=1;e<3;e++)a[0]=t.add(a[0],t.mul(o[e-1],a[e])),o[e]=t.mul(o[e-1],o[0]);return a[0]}add(e,t){let n=!1;e.length()>this.length()&&(n=!0);let r=this.length(),i=e.length();for(let a=0;athis.length()&&(n=!0);let r=this.length(),i=e.length();for(let a=0;a32768?new B(r*n.n8):new Uint8Array(r*n.n8),this.curve,this.logger);i.coef.set(this.coef.slice(0,(r-1)*n.n8),32),this.mulScalar(n.neg(t)),i.add(this),this.coef=i.coef}byXNSubValue(t,n){let r=this.Fr,i=this.length()-t-1>=this.degree()?this.length():this.length()+t,a=new e(i>32768?new B(i*r.n8):new Uint8Array(i*r.n8),this.curve,this.logger);a.coef.set(this.coef.slice(0,(this.degree()+1)*32),t*32),this.mulScalar(n),a.add(this),this.coef=a.coef}divBy(t){let n=this.Fr,r=this.degree(),i=t.degree(),a=new e(this.coef,this.curve,this.logger);this.coef=this.length()>32768?new B(this.length()*n.n8):new Uint8Array(this.length()*n.n8);for(let e=r-i;e>=0;e--){this.setCoef(e,n.div(a.getCoef(e+i),t.getCoef(i)));for(let r=0;r<=i;r++)a.setCoef(e+r,n.sub(a.getCoef(e+r),n.mul(this.getCoef(e),t.getCoef(r))))}return a}divByMonic(t,n){let r=this.Fr,i=this.degree(),a=new e(this.length()>32768?new B(this.length()*r.n8):new Uint8Array(this.length()*r.n8),this.curve,this.logger),o=[];for(let e=0;e=0&&!(l<0);l-=s){let i=e;o[i]=r.add(this.getCoef(l+t),r.mul(o[i],n)),a.setCoef(l,o[i]),c=(c+1)%t}this.coef=a.coef}divByVanishing(t,n){if(this.degree()32768?new B(this.length()*r.n8):new Uint8Array(this.length()*r.n8);for(let e=this.length()-1;e>=t;e--){let a=i.getCoef(e);r.eq(r.zero,a)||(i.setCoef(e,r.zero),i.setCoef(e-t,r.add(i.getCoef(e-t),r.mul(n,a))),this.setCoef(e-t,r.add(this.getCoef(e-t),a)))}return i}divByVanishing2(t,n){if(this.degree()32768?new B(this.length()*r.n8):new Uint8Array(this.length()*r.n8);let a=this.length()-t,o=Math.floor(a/3),s=a-2*o;console.log(a),console.log(o+` `+s);for(let e=0;e<3;e++){console.log(`> Thread `+e);for(let a=e===0?s:o;a>0;a--){let c=a-1;e!==0&&(c+=(e-1)*o+s);let l=c+t,u=i.getCoef(l);r.eq(r.zero,u)||(i.setCoef(l,r.zero),i.setCoef(c,r.add(i.getCoef(c),r.mul(n,u))),this.setCoef(c,r.add(this.getCoef(c),u)),console.log(c+` <-- `+l))}}return this.print(),i}fastDivByVanishing(t){let n=this.Fr;for(let r=0;r32768?new B(this.length()*n.n8):new Uint8Array(this.length()*n.n8),this.curve,this.logger),d=this.coef;this.coef=u.coef,u.coef=d;for(let e=0;e<5;e++){let t=(e+1)*c+l;for(let e=0;e0;e--){let t=e-1,r=t*c+l;m[t]=[];for(let a=0;a32768?new B(this.length()*this.Fr.n8):new Uint8Array(this.length()*this.Fr.n8);t.set(this.Fr.zero,(this.length()-1)*this.Fr.n8),t.set(this.coef.slice((this.length()-1)*this.Fr.n8,this.length()*this.Fr.n8),(this.length()-2)*this.Fr.n8);for(let n=this.length()-3;n>=0;n--){let r=n*this.Fr.n8;t.set(this.Fr.add(this.coef.slice(r+this.Fr.n8,r+2*this.Fr.n8),this.Fr.mul(e,t.slice(r+this.Fr.n8,r+2*this.Fr.n8))),n*this.Fr.n8)}if(!this.Fr.eq(this.coef.slice(0,this.Fr.n8),this.Fr.mul(this.Fr.neg(e),t.slice(0,this.Fr.n8))))throw Error(`Polynomial does not divide`);this.coef=t}divZh(e,t=4){for(let t=0;te*(t-1)-t&&!this.Fr.isZero(i))throw Error(`Polynomial is not divisible`)}return this}divByZerofier(e,t){let n=this.Fr,r=n.inv(t),i=n.neg(r),a=n.eq(n.one,i),o=n.eq(n.negone,i);if(!a)for(let t=0;tthis.length()-e-1&&!this.Fr.isZero(c))throw Error(`Polynomial is not divisible`)}return this}byX(){let e=this.length()+1>32768?new B(this.coef.byteLength+this.Fr.n8):new Uint8Array(this.coef.byteLength+this.Fr.n8);e.set(this.Fr.zero,0),e.set(this.coef,this.Fr.n8),this.coef=e}static async expX(t,n,r=!1){let i=t.Fr;if(n<1)throw Error(`Compute a new polynomial to a zero or negative number is not allowed`);if(n===1)return await e.fromEvaluations(t.coef,t.curve,t.logger);let a=r?t.degree():t.length()-1,o=a*n+1>32768?new B((a*n+1)*i.n8):new Uint8Array((a*n+1)*i.n8);o.set(t.getCoef(0),0);for(let e=1;e<=a;e++){let r=e*i.n8,a=t.getCoef(e);o.set(a,r*n)}return new e(o,t.curve,t.logger)}split(t,n,r){if(t<1)throw Error(`Polynomials can't be split in ${t} parts`);if(t===1)return[this];if(r.length!==0&&r.length32768?new B(s):new Uint8Array(s),this.curve,this.logger);let c=n*i,l=o?this.coef.byteLength:(n+1)*i;if(a[n].coef.set(this.coef.slice(c,l),0),o||a[n].coef.set(r[n],i),n!==0){let e=this.Fr.sub(a[n].coef.slice(0,this.Fr.n8),r[n-1]);a[n].coef.set(e,0)}o&&a[n].truncate()}return a}truncate(){let e=this.degree();if(e+132768?new B((e+1)*this.Fr.n8):new Uint8Array((e+1)*this.Fr.n8);t.set(this.coef.slice(0,(e+1)*this.Fr.n8),0),this.coef=t}}static lagrangePolynomialInterpolation(t,n,r){let i=r.Fr,a=o(0);for(let e=1;e32768?new B(t.length*i.n8):new Uint8Array(t.length*i.n8),r),o.setCoef(0,i.neg(t[n])),o.setCoef(1,i.one)):o.byXSubValue(t[n]));let s=o.evaluate(t[a]);s=i.inv(s);let c=i.mul(n[a],s);return o.mulScalar(c),o}}static zerofierPolynomial(t,n){let r=n.Fr,i=new e(t.length+1>32768?new B((t.length+1)*r.n8):new Uint8Array((t.length+1)*r.n8),n);i.setCoef(0,r.neg(t[0])),i.setCoef(1,r.one);for(let e=1;e=0;n--){let r=this.getCoef(n);e.eq(e.zero,r)||(e.isNegative(r)?t+=` - `:n!==this.degree()&&(t+=` + `),t+=e.toString(r),n>0&&(t+=n>1?`x^`+n:`x`))}console.log(t)}async multiExponentiation(e,t){let n=this.coef.byteLength/this.Fr.n8,r=e.slice(0,n*this.G1.F.n8*2),i=await this.Fr.batchFromMontgomery(this.coef),a=await this.G1.multiExpAffine(r,i,this.logger,t);return a=this.G1.toAffine(a),a}},$=class e{constructor(e,t,n){this.eval=e,this.curve=t,this.Fr=t.Fr,this.logger=n}static async fromPolynomial(t,n,r,i){let a=new B(t.length()*n*r.Fr.n8);return a.set(t.coef,0),new e(await r.Fr.fft(a),r,i)}getEvaluation(e){let t=e*this.Fr.n8;if(t+this.Fr.n8>this.eval.byteLength)throw Error(`Evaluations.getEvaluation() out of bounds`);return this.eval.slice(t,t+this.Fr.n8)}length(){let e=this.eval.byteLength/this.Fr.n8;if(e!==Math.floor(this.eval.byteLength/this.Fr.n8))throw Error(`Polynomial evaluations buffer has incorrect size`);return e===0&&this.logger.warn(`Polynomial has length zero`),e}},{stringifyBigInts:bl}=Gr;async function xl(e,t,n,r){let{fd:i,sections:a}=await H(t,`wtns`,2,1<<25,1<<23);n&&n.debug(`> Reading witness file`);let o=await Ya(i,a);n&&n.debug(`> Reading zkey file`);let{fd:s,sections:c}=await H(e,`zkey`,2,1<<25,1<<23),l=await Fa(s,c,void 0,r);if(l.protocol!=`plonk`)throw Error(`zkey file is not plonk`);if(!V.eq(l.r,o.q))throw Error(`Curve of the witness does not match the curve of the proving key`);if(o.nWitness!=l.nVars-l.nAdditions)throw Error(`Invalid witness length. Circuit: ${l.nVars}, witness: ${o.nWitness}, ${l.nAdditions}`);let u=l.curve,d=u.Fr,f=u.Fr.n8,p=l.domainSize*f;n&&(n.debug(`----------------------------`),n.debug(` PLONK PROVE SETTINGS`),n.debug(` Curve: ${u.name}`),n.debug(` Circuit power: ${l.power}`),n.debug(` Domain size: ${l.domainSize}`),n.debug(` Vars: ${l.nVars}`),n.debug(` Public vars: ${l.nPublic}`),n.debug(` Constraints: ${l.nConstraints}`),n.debug(` Additions: ${l.nAdditions}`),n.debug(`----------------------------`)),n&&n.debug(`> Reading witness file data`);let m=await J(i,a,2);m.set(d.zero,0);let h=new B(f*l.nAdditions),g={},_={},v={},y={},b=new Qc(u,n),x=new vl(u);n&&n.debug(`> Reading Section 3. Additions`),await T(),n&&n.debug(`> Reading Section 12. Sigma1, Sigma2 & Sigma 3`),n&&n.debug(`··· Reading Sigma polynomials `),_.Sigma1=new Q(new B(p),u,n),_.Sigma2=new Q(new B(p),u,n),_.Sigma3=new Q(new B(p),u,n),await s.readToBuffer(_.Sigma1.coef,0,p,c[12][0].p),await s.readToBuffer(_.Sigma2.coef,0,p,c[12][0].p+5*p),await s.readToBuffer(_.Sigma3.coef,0,p,c[12][0].p+10*p),n&&n.debug(`··· Reading Sigma evaluations`),v.Sigma1=new $(new B(p*4),u,n),v.Sigma2=new $(new B(p*4),u,n),v.Sigma3=new $(new B(p*4),u,n),await s.readToBuffer(v.Sigma1.eval,0,p*4,c[12][0].p+p),await s.readToBuffer(v.Sigma2.eval,0,p*4,c[12][0].p+6*p),await s.readToBuffer(v.Sigma3.eval,0,p*4,c[12][0].p+11*p),n&&n.debug(`> Reading Section 14. Powers of Tau`);let S=await J(s,c,14),C=[];for(let e=1;e<=l.nPublic;e++){let t=m.slice(e*d.n8,e*d.n8+d.n8);C.push(V.fromRprLE(t))}n&&n.debug(``),n&&n.debug(`> ROUND 1`),await O(),n&&n.debug(`> ROUND 2`),await A(),n&&n.debug(`> ROUND 3`),await M(),n&&n.debug(`> ROUND 4`),await P(),n&&n.debug(`> ROUND 5`),await F(),await s.close(),await i.close();let w=b.toObjectProof(!1);return w.protocol=`plonk`,w.curve=u.name,n&&n.debug(`PLONK PROVER FINISHED`),{proof:bl(w),publicSignals:bl(C)};async function T(){n&&n.debug(`··· Computing additions`);let e=await J(s,c,3),t=8+f*2;for(let r=0;r Computing A, B, C wire polynomials`),await k(),n&&n.debug(`> Computing A, B, C MSM`);let e=await _.A.multiExponentiation(S,`A`),t=await _.B.multiExponentiation(S,`B`),r=await _.C.multiExponentiation(S,`C`);return b.addPolynomial(`A`,e),b.addPolynomial(`B`,t),b.addPolynomial(`C`,r),0}async function k(){n&&n.debug(`··· Reading data from zkey file`),g.A=new B(p),g.B=new B(p),g.C=new B(p);let e=await J(s,c,4),t=await J(s,c,5),r=await J(s,c,6);for(let n=0;n=l.domainSize+2)throw Error(`A Polynomial is not well calculated`);if(_.B.degree()>=l.domainSize+2)throw Error(`B Polynomial is not well calculated`);if(_.C.degree()>=l.domainSize+2)throw Error(`C Polynomial is not well calculated`)}async function A(){n&&n.debug(`> Computing challenges beta and gamma`),x.reset(),x.addPolCommitment(l.Qm),x.addPolCommitment(l.Ql),x.addPolCommitment(l.Qr),x.addPolCommitment(l.Qo),x.addPolCommitment(l.Qc),x.addPolCommitment(l.S1),x.addPolCommitment(l.S2),x.addPolCommitment(l.S3);for(let e=0;e Computing Z polynomial`),await j(),n&&n.debug(`> Computing Z MSM`);let e=await _.Z.multiExponentiation(S,`Z`);b.addPolynomial(`Z`,e)}async function j(){n&&n.debug(`··· Computing Z evaluations`);let e=new B(p),t=new B(p);e.set(d.one,0),t.set(d.one,0);let r=d.one;for(let n=0;n=l.domainSize+3)throw Error(`Z Polynomial is not well calculated`);delete g.Z}async function M(){n&&n.debug(`> Computing challenge alpha`),x.reset(),x.addScalar(y.beta),x.addScalar(y.gamma),x.addPolCommitment(b.getPolynomial(`Z`)),y.alpha=x.getChallenge(),y.alpha2=d.square(y.alpha),n&&n.debug(`··· challenges.alpha: `+d.toString(y.alpha,16)),n&&n.debug(`> Computing T polynomial`),await N(),n&&n.debug(`> Computing T MSM`);let e=await _.T1.multiExponentiation(S,`T1`),t=await _.T2.multiExponentiation(S,`T2`),r=await _.T3.multiExponentiation(S,`T3`);b.addPolynomial(`T1`,e),b.addPolynomial(`T2`,t),b.addPolynomial(`T3`,r)}async function N(){n&&n.debug(`··· Reading sections 8, 9, 7, 10, 11. Q selectors`),v.QL=new $(new B(p*4),u,n),v.QR=new $(new B(p*4),u,n),v.QM=new $(new B(p*4),u,n),v.QO=new $(new B(p*4),u,n),v.QC=new $(new B(p*4),u,n),await s.readToBuffer(v.QL.eval,0,p*4,c[8][0].p+p),await s.readToBuffer(v.QR.eval,0,p*4,c[9][0].p+p),await s.readToBuffer(v.QM.eval,0,p*4,c[7][0].p+p),await s.readToBuffer(v.QO.eval,0,p*4,c[10][0].p+p),await s.readToBuffer(v.QC.eval,0,p*4,c[11][0].p+p),v.Lagrange=new $(new B(p*4*l.nPublic),u,n);for(let e=0;e=l.domainSize*3+6)throw Error(`T Polynomial is not well calculated`);n&&n.debug(`··· Computing T1, T2, T3 polynomials`),_.T1=new Q(new B((l.domainSize+1)*f),u,n),_.T2=new Q(new B((l.domainSize+1)*f),u,n),_.T3=new Q(new B((l.domainSize+6)*f),u,n),_.T1.coef.set(_.T.coef.slice(0,p),0),_.T2.coef.set(_.T.coef.slice(p,p*2),0),_.T3.coef.set(_.T.coef.slice(p*2,p*3+6*f),0),_.T1.setCoef(l.domainSize,y.b[10]);let t=d.sub(_.T2.getCoef(0),y.b[10]);_.T2.setCoef(0,t),_.T2.setCoef(l.domainSize,y.b[11]);let r=d.sub(_.T3.getCoef(0),y.b[11]);_.T3.setCoef(0,r)}async function P(){n&&n.debug(`> Computing challenge xi`),x.reset(),x.addScalar(y.alpha),x.addPolCommitment(b.getPolynomial(`T1`)),x.addPolCommitment(b.getPolynomial(`T2`)),x.addPolCommitment(b.getPolynomial(`T3`)),y.xi=x.getChallenge(),y.xiw=d.mul(y.xi,d.w[l.power]),n&&n.debug(`··· challenges.xi: `+d.toString(y.xi,16)),b.addEvaluation(`eval_a`,_.A.evaluate(y.xi)),b.addEvaluation(`eval_b`,_.B.evaluate(y.xi)),b.addEvaluation(`eval_c`,_.C.evaluate(y.xi)),b.addEvaluation(`eval_s1`,_.Sigma1.evaluate(y.xi)),b.addEvaluation(`eval_s2`,_.Sigma2.evaluate(y.xi)),b.addEvaluation(`eval_zw`,_.Z.evaluate(y.xiw))}async function F(){n&&n.debug(`> Computing challenge v`),x.reset(),x.addScalar(y.xi),x.addScalar(b.getEvaluation(`eval_a`)),x.addScalar(b.getEvaluation(`eval_b`)),x.addScalar(b.getEvaluation(`eval_c`)),x.addScalar(b.getEvaluation(`eval_s1`)),x.addScalar(b.getEvaluation(`eval_s2`)),x.addScalar(b.getEvaluation(`eval_zw`)),y.v=[],y.v[1]=x.getChallenge(),n&&n.debug(`··· challenges.v: `+d.toString(y.v[1],16));for(let e=2;e<6;e++)y.v[e]=d.mul(y.v[e-1],y.v[1]);n&&n.debug(`> Computing linearisation polynomial R(X)`),await I(),n&&n.debug(`> Computing opening proof polynomial Wxi(X) polynomial`),L(),n&&n.debug(`> Computing opening proof polynomial Wxiw(X) polynomial`),ee(),n&&n.debug(`> Computing Wxi, Wxiw MSM`);let e=await _.Wxi.multiExponentiation(S,`Wxi`),t=await _.Wxiw.multiExponentiation(S,`Wxiw`);b.addPolynomial(`Wxi`,e),b.addPolynomial(`Wxiw`,t)}async function I(){let e=u.Fr;_.QL=new Q(new B(p),u,n),_.QR=new Q(new B(p),u,n),_.QM=new Q(new B(p),u,n),_.QO=new Q(new B(p),u,n),_.QC=new Q(new B(p),u,n),await s.readToBuffer(_.QL.coef,0,p,c[8][0].p),await s.readToBuffer(_.QR.coef,0,p,c[9][0].p),await s.readToBuffer(_.QM.coef,0,p,c[7][0].p),await s.readToBuffer(_.QO.coef,0,p,c[10][0].p),await s.readToBuffer(_.QC.coef,0,p,c[11][0].p),y.xin=y.xi;for(let t=0;tUl,fullProve:()=>Cl,prove:()=>xl,setup:()=>Zc,verify:()=>Tl});function Gl(e,t){return[e,0,0,t.one,t.zero,t.zero,t.zero,t.zero]}function Kl(e,t,n,r,i,a,o,s){return[e,t,n,r,i,a,o,s]}function ql(e,t,n,r,i,a,o,s,c){return[e,t,n,r,i,a,o,s]}var Jl=0,Yl=1,Xl=2,Zl=class{constructor(e,t,n,r,i){this.Fr=e,this.logger=i,this.fnGetAdditionConstraint=n,this.fnGetMultiplicationConstraint=r}processR1csConstraint(e,t,n,r){this.normalizeLinearCombination(t),this.normalizeLinearCombination(n),this.normalizeLinearCombination(r);let i=this.getLinearCombinationType(t),a=this.getLinearCombinationType(n);if(i===Jl||a===Jl)return this.processR1csAdditionConstraint(e,r);if(i===Yl){let i=this.joinLinearCombinations(n,r,t[0]);return this.processR1csAdditionConstraint(e,i)}else if(a===Yl){let i=this.joinLinearCombinations(t,r,n[0]);return this.processR1csAdditionConstraint(e,i)}else return this.processR1csMultiplicationConstraint(e,t,n,r)}getLinearCombinationType(e){let t=this.Fr.zero,n=0,r=Object.keys(e);for(let i=0;i0?Xl:this.Fr.isZero(t)?Jl:Yl}normalizeLinearCombination(e){let t=Object.keys(e);for(let n=0;ni;){let r=o.shift(),i=o.shift(),a=e.nVars++,s=this.fnGetAdditionConstraint(r[0],i[0],a,this.Fr.neg(r[1]),this.Fr.neg(i[1]),this.Fr.zero,this.Fr.one,this.Fr.zero);t.push(s),n.push([r[0],i[0],r[1],i[1]]),o.push([a,this.Fr.one])}for(let e=0;ethis.n-1)throw Error(`CPolynomial:addPolynomial, cannot add a polynomial to a position greater than n-1`);this.polynomials[e]=t}degree(){let e=this.polynomials.map((e,t)=>e===void 0?0:e.degree()*this.n+t);return Math.max(...e)}getPolynomial(){let e=this.polynomials.map(e=>e===void 0?0:e.degree()),t=this.degree(),n=2**(ma(t-1)+1),r=this.Fr.n8,i=new Q(new B(n*r),this.curve,this.logger);for(let n=0;n Reading PTau file`);let{fd:i,sections:a}=await H(t,`ptau`,1,1<<22,1<<24);if(!a[12])throw Error(`Powers of Tau is not well prepared. Section 12 missing.`);r&&r.info(`> Getting curve from PTau settings`);let{curve:o}=await $o(i,a);r&&r.info(`> Reading r1cs file`);let{fd:s,sections:c}=await H(e,`r1cs`,1,1<<22,1<<24),l=await Ps(s,c,{loadConstraints:!1,loadCustomGates:!0});if(l.prime!==o.r)throw Error(`r1cs curve does not match powers of tau ceremony curve`);let u=o.Fr,d=o.Fr.n8,f=o.G1.F.n8*2,p=o.G2.F.n8*2,m={},h={},g,_={nVars:l.nVars,nPublic:l.nOutputs+l.nPubInputs},v=new Qs,y=new Qs;if(r&&r.info(`> Processing FFlonk constraints`),await E(o.Fr,l,r),globalThis.gc&&globalThis.gc(),_.cirPower=Math.max(3,ma(v.length+2-1)+1),_.domainSize=2**_.cirPower,a[2][0].size<(_.domainSize*9+18)*f)throw Error(`Powers of Tau is not big enough for this circuit size. Section 2 too small.`);if(a[3][0].size computing k1 and k2`);let[b,x]=ee();r&&r.info(`> computing w3`);let S=R();r&&r.info(`> computing w4`);let C=te();r&&r.info(`> computing w8`);let w=ne();r&&r.info(`> computing wr`);let T=re(_.cirPower,o.Fr);return await D(),await s.close(),await i.close(),r&&r.info(`FFLONK SETUP FINISHED`),0;async function E(e,t,n){for(let t=0;t<_.nPublic;t++)v.push(Gl(t+1,e));let r=new Zl(e,Gl,Kl,ql,n),i=await J(s,c,2),a=0;for(let e=0;e Writing the zkey file`);let e=await hi(n,`zkey`,1,17,1<<22,1<<24);r&&r.info(`··· Writing Section 1. Zkey Header`),await O(e),r&&r.info(`··· Writing Section 3. Additions`),await k(e),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 4. A Map`),await A(e,4,0,`A map`),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 5. B Map`),await A(e,5,1,`B map`),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 6. C Map`),await A(e,6,2,`C map`),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 7. QL`),await j(e,7,3,`QL`),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 8. QR`),await j(e,8,4,`QR`),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 9. QM`),await j(e,9,5,`QM`),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 10. QO`),await j(e,10,6,`QO`),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 11. QC`),await j(e,11,7,`QC`),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Sections 12,13,14. Sigma1, Sigma2 & Sigma 3`),await M(e),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 15. Lagrange Polynomials`),await N(e),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 16. Powers of Tau`),await P(e),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 17. C0`),await F(e),globalThis.gc&&globalThis.gc(),r&&r.info(`··· Writing Section 2. FFlonk Header`),await I(e),globalThis.gc&&globalThis.gc(),r&&r.info(`> Writing the zkey file finished`),await e.close()}async function O(e){await U(e,1),await e.writeULE32(10),await W(e)}async function k(e){await U(e,3);let t=new Uint8Array(8+2*d),n=new DataView(t.buffer);for(let i=0;i=8*_.domainSize)throw Error(`C0 Polynomial is not well calculated`);await U(e,17),await e.write(m.C0.coef),await W(e)}async function I(e){await U(e,2);let t=o.q,n=(Math.floor((V.bitLength(t)-1)/64)+1)*8;await e.writeULE32(n),await gi(e,t,n);let r=o.r,s=(Math.floor((V.bitLength(r)-1)/64)+1)*8;await e.writeULE32(s),await gi(e,r,s),await e.writeULE32(_.nVars),await e.writeULE32(_.nPublic),await e.writeULE32(_.domainSize),await e.writeULE32(y.length),await e.writeULE32(v.length),await e.write(b),await e.write(x),await e.write(S),await e.write(C),await e.write(w),await e.write(T);let c;c=await i.read(p,a[3][0].p+p),await e.write(c);let l=await m.C0.multiExponentiation(g,`C0`);await e.write(l),await W(e)}async function L(e,t){let[n,r]=await Q.to4T(t,_.domainSize,[],u);return await e.write(n),await e.write(r),[n,r]}function ee(){let e=u.two;for(;n(e,[],_.cirPower);)u.add(e,u.one);let t=u.add(e,u.one);for(;n(t,[e],_.cirPower);)u.add(t,u.one);return[e,t];function n(e,t,n){let r=2**n,i=u.one;for(let a=0;a Reading witness file`);let{fd:i,sections:a}=await H(t,`wtns`,2,1<<25,1<<23),o=await Ya(i,a);n&&n.info(`> Reading zkey file`);let{fd:s,sections:c}=await H(e,`zkey`,2,1<<25,1<<23),l=await Fa(s,c,void 0,r);if(l.protocolId!==10)throw Error(`zkey file is not fflonk`);if(!V.eq(l.r,o.q))throw Error(`Curve of the witness does not match the curve of the proving key`);if(o.nWitness!==l.nVars-l.nAdditions)throw Error(`Invalid witness length. Circuit: ${l.nVars}, witness: ${o.nWitness}, ${l.nAdditions}`);let u=l.curve,d=u.Fr,f=u.Fr.n8,p=u.G1.F.n8*2,m=l.domainSize*f;n&&(n.info(`----------------------------`),n.info(` FFLONK PROVE SETTINGS`),n.info(` Curve: ${u.name}`),n.info(` Circuit power: ${l.power}`),n.info(` Domain size: ${l.domainSize}`),n.info(` Vars: ${l.nVars}`),n.info(` Public vars: ${l.nPublic}`),n.info(` Constraints: ${l.nConstraints}`),n.info(` Additions: ${l.nAdditions}`),n.info(`----------------------------`)),n&&n.info(`> Reading witness file data`);let h=await J(i,a,2);await i.close(),h.set(d.zero,0);let g=new B(l.nAdditions*f),_={},v={},y={},b={},x={},S={},C=new Qc(u,n);n&&n.info(`> Reading Section 3. Additions`),await D(),n&&n.info(`> Reading Sections 12,13,14. Sigma1, Sigma2 & Sigma 3`),n&&n.info(`··· Reading Sigma polynomials `),v.Sigma1=new Q(new B(m),u,n),v.Sigma2=new Q(new B(m),u,n),v.Sigma3=new Q(new B(m),u,n),await s.readToBuffer(v.Sigma1.coef,0,m,c[12][0].p),await s.readToBuffer(v.Sigma2.coef,0,m,c[13][0].p),await s.readToBuffer(v.Sigma3.coef,0,m,c[14][0].p),n&&n.info(`··· Reading Sigma evaluations`),y.Sigma1=new $(new B(m*4),u,n),y.Sigma2=new $(new B(m*4),u,n),y.Sigma3=new $(new B(m*4),u,n),await s.readToBuffer(y.Sigma1.eval,0,m*4,c[12][0].p+m),await s.readToBuffer(y.Sigma2.eval,0,m*4,c[13][0].p+m),await s.readToBuffer(y.Sigma3.eval,0,m*4,c[14][0].p+m),n&&n.info(`> Reading Section 16. Powers of Tau`);let w=new B(l.domainSize*16*p);await s.readToBuffer(w,0,(l.domainSize*9+18)*p,c[16][0].p),globalThis.gc&&globalThis.gc(),n&&n.info(``),n&&n.info(`> ROUND 1`),await A(),delete v.T0,delete y.QL,delete y.QR,delete y.QM,delete y.QO,delete y.QC,globalThis.gc&&globalThis.gc(),n&&n.info(`> ROUND 2`),await j(),delete _.A,delete _.B,delete _.C,delete y.A,delete y.B,delete y.C,delete y.Sigma1,delete y.Sigma2,delete y.Sigma3,delete y.lagrange1,delete y.Z,globalThis.gc&&globalThis.gc(),n&&n.info(`> ROUND 3`),await M(),delete v.A,delete v.B,delete v.C,delete v.Z,delete v.T1,delete v.T2,delete v.Sigma1,delete v.Sigma2,delete v.Sigma3,delete v.QL,delete v.QR,delete v.QM,delete v.QC,delete v.QO,globalThis.gc&&globalThis.gc(),n&&n.info(`> ROUND 4`),await N(),globalThis.gc&&globalThis.gc(),n&&n.info(`> ROUND 5`),await P(),delete v.C0,delete v.C1,delete v.C2,delete v.R1,delete v.R2,delete v.F,delete v.L,delete v.ZT,delete v.ZTS2,await s.close(),globalThis.gc&&globalThis.gc(),C.addEvaluation(`inv`,F());let T=C.toObjectProof();T.protocol=`fflonk`,T.curve=u.name;let E=[];for(let e=1;e<=l.nPublic;e++){let t=e*f,n=h.slice(t,t+f);E.push(V.fromRprLE(n))}return n&&n.info(`FFLONK PROVER FINISHED`),{proof:eu(T),publicSignals:eu(E)};async function D(){n&&n.info(`··· Computing additions`);let e=await J(s,c,3),t=8+f*2;for(let r=0;r Computing A, B, C wire polynomials`),await t(),n&&n.info(`> Computing T0 polynomial`),await r(),n&&n.info(`> Computing C1 polynomial`),await i(),n&&n.info(`> Computing C1 multi exponentiation`);let e=await v.C1.multiExponentiation(w,`C1`);return C.addPolynomial(`C1`,e),0;async function t(){n&&n.info(`··· Reading data from zkey file`),_.A=new B(m),_.B=new B(m),_.C=new B(m);let e=await J(s,c,4),t=await J(s,c,5),r=await J(s,c,6);for(let n=0;n=l.domainSize)throw Error(`A Polynomial is not well calculated`);if(v.B.degree()>=l.domainSize)throw Error(`B Polynomial is not well calculated`);if(v.C.degree()>=l.domainSize)throw Error(`C Polynomial is not well calculated`)}async function r(){n&&n.info(`··· Reading sections 7, 8, 9, 10, 11. Q selectors`),y.QL=new $(new B(m*4),u,n),y.QR=new $(new B(m*4),u,n),y.QM=new $(new B(m*4),u,n),y.QO=new $(new B(m*4),u,n),y.QC=new $(new B(m*4),u,n),await s.readToBuffer(y.QL.eval,0,m*4,c[7][0].p+m),await s.readToBuffer(y.QR.eval,0,m*4,c[8][0].p+m),await s.readToBuffer(y.QM.eval,0,m*4,c[9][0].p+m),await s.readToBuffer(y.QO.eval,0,m*4,c[10][0].p+m),await s.readToBuffer(y.QC.eval,0,m*4,c[11][0].p+m),y.lagrange1=new $(await J(s,c,15),u,n),_.T0=new B(m*4),n&&n.info(`··· Computing T0 evaluations`);for(let e=0;e=2*l.domainSize-2)throw Error(`T0 Polynomial is not well calculated (degree is ${v.T0.degree()} and must be less than ${2*l.domainSize+2}`);delete _.T0}async function i(){let e=new Ql(4,u,n);if(e.addPolynomial(0,v.A),e.addPolynomial(1,v.B),e.addPolynomial(2,v.C),e.addPolynomial(3,v.T0),v.C1=e.getPolynomial(),v.C1.degree()>=8*l.domainSize-8)throw Error(`C1 Polynomial is not well calculated`)}}async function j(){n&&n.info(`> Computing challenges beta and gamma`);let e=new vl(u);e.addPolCommitment(l.C0);for(let t=0;t Computing Z polynomial`),await r(),n&&n.info(`> Computing T1 polynomial`),await i(),n&&n.info(`> Computing T2 polynomial`),await a(),n&&n.info(`> Computing C2 polynomial`),await o(),n&&n.info(`> Computing C2 multi exponentiation`);let t=await v.C2.multiExponentiation(w,`C2`);return C.addPolynomial(`C2`,t),0;async function r(){n&&n.info(`··· Computing Z evaluations`);let e=new B(m),t=new B(m);e.set(d.one,0),t.set(d.one,0);let r=d.one;for(let i=0;i=l.domainSize+3)throw Error(`Z Polynomial is not well calculated`);delete _.Z}async function i(){n&&n.info(`··· Computing T1 evaluations`),_.T1=new B(m*2),_.T1z=new B(m*2);let e=d.one;for(let t=0;t=l.domainSize+2)throw Error(`T1 Polynomial is not well calculated`);delete _.T1,delete _.T1z,delete v.T1z}async function a(){n&&n.info(`··· Computing T2 evaluations`),_.T2=new B(m*4),_.T2z=new B(m*4);let e=d.one;for(let t=0;t=3*l.domainSize)throw Error(`T2 Polynomial is not well calculated`);delete _.T2,delete _.T2z,delete v.T2z}async function o(){let e=new Ql(3,u,n);if(e.addPolynomial(0,v.Z),e.addPolynomial(1,v.T1),e.addPolynomial(2,v.T2),v.C2=e.getPolynomial(),v.C2.degree()>=9*l.domainSize)throw Error(`C2 Polynomial is not well calculated`)}}async function M(){n&&n.info(`> Computing challenge xi`);let e=new vl(u);e.addScalar(x.gamma),e.addPolCommitment(C.getPolynomial(`C2`)),x.xiSeed=e.getChallenge();let t=d.square(x.xiSeed);S.w8=[],S.w8[0]=d.one;for(let e=1;e<8;e++)S.w8[e]=d.mul(S.w8[e-1],l.w8);S.w4=[],S.w4[0]=d.one;for(let e=1;e<4;e++)S.w4[e]=d.mul(S.w4[e-1],l.w4);S.w3=[],S.w3[0]=d.one,S.w3[1]=l.w3,S.w3[2]=d.square(l.w3),S.S0={},S.S0.h0w8=[],S.S0.h0w8[0]=d.mul(t,x.xiSeed);for(let e=1;e<8;e++)S.S0.h0w8[e]=d.mul(S.S0.h0w8[0],S.w8[e]);S.S1={},S.S1.h1w4=[],S.S1.h1w4[0]=d.square(S.S0.h0w8[0]);for(let e=1;e<4;e++)S.S1.h1w4[e]=d.mul(S.S1.h1w4[0],S.w4[e]);S.S2={},S.S2.h2w3=[],S.S2.h2w3[0]=d.mul(S.S1.h1w4[0],t),S.S2.h2w3[1]=d.mul(S.S2.h2w3[0],S.w3[1]),S.S2.h2w3[2]=d.mul(S.S2.h2w3[0],S.w3[2]),S.S2.h3w3=[],S.S2.h3w3[0]=d.mul(S.S2.h2w3[0],l.wr),S.S2.h3w3[1]=d.mul(S.S2.h3w3[0],S.w3[1]),S.S2.h3w3[2]=d.mul(S.S2.h3w3[0],S.w3[2]),x.xi=d.mul(d.square(S.S2.h2w3[0]),S.S2.h2w3[0]),n&&n.info(`··· challenges.xi: `+d.toString(x.xi)),v.QL=new Q(new B(m),u,n),v.QR=new Q(new B(m),u,n),v.QM=new Q(new B(m),u,n),v.QO=new Q(new B(m),u,n),v.QC=new Q(new B(m),u,n),await s.readToBuffer(v.QL.coef,0,m,c[7][0].p),await s.readToBuffer(v.QR.coef,0,m,c[8][0].p),await s.readToBuffer(v.QM.coef,0,m,c[9][0].p),await s.readToBuffer(v.QO.coef,0,m,c[10][0].p),await s.readToBuffer(v.QC.coef,0,m,c[11][0].p),n&&n.info(`··· Computing evaluations`),C.addEvaluation(`ql`,v.QL.evaluate(x.xi)),C.addEvaluation(`qr`,v.QR.evaluate(x.xi)),C.addEvaluation(`qm`,v.QM.evaluate(x.xi)),C.addEvaluation(`qo`,v.QO.evaluate(x.xi)),C.addEvaluation(`qc`,v.QC.evaluate(x.xi)),C.addEvaluation(`s1`,v.Sigma1.evaluate(x.xi)),C.addEvaluation(`s2`,v.Sigma2.evaluate(x.xi)),C.addEvaluation(`s3`,v.Sigma3.evaluate(x.xi)),C.addEvaluation(`a`,v.A.evaluate(x.xi)),C.addEvaluation(`b`,v.B.evaluate(x.xi)),C.addEvaluation(`c`,v.C.evaluate(x.xi)),C.addEvaluation(`z`,v.Z.evaluate(x.xi)),x.xiw=d.mul(x.xi,d.w[l.power]),C.addEvaluation(`zw`,v.Z.evaluate(x.xiw)),C.addEvaluation(`t1w`,v.T1.evaluate(x.xiw)),C.addEvaluation(`t2w`,v.T2.evaluate(x.xiw))}async function N(){n&&n.info(`> Computing challenge alpha`);let e=new vl(u);e.addScalar(x.xiSeed),e.addScalar(C.getEvaluation(`ql`)),e.addScalar(C.getEvaluation(`qr`)),e.addScalar(C.getEvaluation(`qm`)),e.addScalar(C.getEvaluation(`qo`)),e.addScalar(C.getEvaluation(`qc`)),e.addScalar(C.getEvaluation(`s1`)),e.addScalar(C.getEvaluation(`s2`)),e.addScalar(C.getEvaluation(`s3`)),e.addScalar(C.getEvaluation(`a`)),e.addScalar(C.getEvaluation(`b`)),e.addScalar(C.getEvaluation(`c`)),e.addScalar(C.getEvaluation(`z`)),e.addScalar(C.getEvaluation(`zw`)),e.addScalar(C.getEvaluation(`t1w`)),e.addScalar(C.getEvaluation(`t2w`)),x.alpha=e.getChallenge(),n&&n.info(`··· challenges.alpha: `+d.toString(x.alpha)),n&&n.info(`> Reading C0 polynomial`),v.C0=new Q(new B(m*8),u,n),await s.readToBuffer(v.C0.coef,0,m*8,c[17][0].p),n&&n.info(`> Computing R0 polynomial`),r(),n&&n.info(`> Computing R1 polynomial`),i(),n&&n.info(`> Computing R2 polynomial`),a(),n&&n.info(`> Computing F polynomial`),await o(),n&&n.info(`> Computing W1 multi exponentiation`);let t=await v.F.multiExponentiation(w,`W1`);return C.addPolynomial(`W1`,t),0;function r(){if(v.R0=Q.lagrangePolynomialInterpolation([S.S0.h0w8[0],S.S0.h0w8[1],S.S0.h0w8[2],S.S0.h0w8[3],S.S0.h0w8[4],S.S0.h0w8[5],S.S0.h0w8[6],S.S0.h0w8[7]],[v.C0.evaluate(S.S0.h0w8[0]),v.C0.evaluate(S.S0.h0w8[1]),v.C0.evaluate(S.S0.h0w8[2]),v.C0.evaluate(S.S0.h0w8[3]),v.C0.evaluate(S.S0.h0w8[4]),v.C0.evaluate(S.S0.h0w8[5]),v.C0.evaluate(S.S0.h0w8[6]),v.C0.evaluate(S.S0.h0w8[7])],u),v.R0.degree()>7)throw Error(`R0 Polynomial is not well calculated`)}function i(){if(v.R1=Q.lagrangePolynomialInterpolation([S.S1.h1w4[0],S.S1.h1w4[1],S.S1.h1w4[2],S.S1.h1w4[3]],[v.C1.evaluate(S.S1.h1w4[0]),v.C1.evaluate(S.S1.h1w4[1]),v.C1.evaluate(S.S1.h1w4[2]),v.C1.evaluate(S.S1.h1w4[3])],u),v.R1.degree()>3)throw Error(`R1 Polynomial is not well calculated`)}function a(){if(v.R2=Q.lagrangePolynomialInterpolation([S.S2.h2w3[0],S.S2.h2w3[1],S.S2.h2w3[2],S.S2.h3w3[0],S.S2.h3w3[1],S.S2.h3w3[2]],[v.C2.evaluate(S.S2.h2w3[0]),v.C2.evaluate(S.S2.h2w3[1]),v.C2.evaluate(S.S2.h2w3[2]),v.C2.evaluate(S.S2.h3w3[0]),v.C2.evaluate(S.S2.h3w3[1]),v.C2.evaluate(S.S2.h3w3[2])],u),v.R2.degree()>5)throw Error(`R2 Polynomial is not well calculated`)}async function o(){n&&n.info(`··· Computing F polynomial`),v.F=Q.fromPolynomial(v.C0,u,n),v.F.sub(v.R0),v.F.divByZerofier(8,x.xi);let e=Q.fromPolynomial(v.C1,u,n);e.sub(v.R1),e.mulScalar(x.alpha),e.divByZerofier(4,x.xi);let t=Q.fromPolynomial(v.C2,u,n);if(t.sub(v.R2),t.mulScalar(d.square(x.alpha)),t.divByZerofier(3,x.xi),t.divByZerofier(3,x.xiw),v.F.add(e),v.F.add(t),v.F.degree()>=9*l.domainSize-6)throw Error(`F Polynomial is not well calculated`)}}async function P(){n&&n.info(`> Computing challenge y`);let e=new vl(u);e.addScalar(x.alpha),e.addPolCommitment(C.getPolynomial(`W1`)),x.y=e.getChallenge(),n&&n.info(`··· challenges.y: `+d.toString(x.y)),n&&n.info(`> Computing L polynomial`),await o(),n&&n.info(`> Computing ZTS2 polynomial`),await c();let t=v.ZTS2.evaluate(x.y);t=d.inv(t),v.L.mulScalar(t);let r=Q.fromCoefficientsArray([d.neg(x.y),d.one],u);n&&n.info(`> Computing W' = L / ZTS2 polynomial`);let i=v.L.divBy(r);if(i.degree()>0)throw Error(`Degree of L(X)/(ZTS2(y)(X-y)) remainder is ${i.degree()} and should be 0`);if(v.L.degree()>=9*l.domainSize-1)throw Error(`Degree of L(X)/(ZTS2(y)(X-y)) is not correct`);n&&n.info(`> Computing W' multi exponentiation`);let a=await v.L.multiExponentiation(w,`W2`);return C.addPolynomial(`W2`,a),0;async function o(){n&&n.info(`··· Computing L polynomial`);let e=v.R0.evaluate(x.y),t=v.R1.evaluate(x.y),r=v.R2.evaluate(x.y),i=d.sub(x.y,S.S0.h0w8[0]);for(let e=1;e<8;e++)i=d.mul(i,d.sub(x.y,S.S0.h0w8[e]));let a=d.sub(x.y,S.S1.h1w4[0]);for(let e=1;e<4;e++)a=d.mul(a,d.sub(x.y,S.S1.h1w4[e]));let o=d.sub(x.y,S.S2.h2w3[0]);for(let e=1;e<3;e++)o=d.mul(o,d.sub(x.y,S.S2.h2w3[e]));for(let e=0;e<3;e++)o=d.mul(o,d.sub(x.y,S.S2.h3w3[e]));let c=d.mul(a,o),f=d.mul(x.alpha,d.mul(i,o)),p=d.mul(d.square(x.alpha),d.mul(i,a));b.denH1=a,b.denH2=o,v.L=Q.fromPolynomial(v.C0,u,n),v.L.subScalar(e),v.L.mulScalar(c);let m=Q.fromPolynomial(v.C1,u,n);m.subScalar(t),m.mulScalar(f);let h=Q.fromPolynomial(v.C2,u,n);h.subScalar(r),h.mulScalar(p),v.L.add(m),v.L.add(h),n&&n.info(`> Computing ZT polynomial`),await s();let g=v.ZT.evaluate(x.y);if(v.F.mulScalar(g),v.L.sub(v.F),v.L.degree()>=9*l.domainSize)throw Error(`L Polynomial is not well calculated`);delete _.L}async function s(){v.ZT=Q.zerofierPolynomial([S.S0.h0w8[0],S.S0.h0w8[1],S.S0.h0w8[2],S.S0.h0w8[3],S.S0.h0w8[4],S.S0.h0w8[5],S.S0.h0w8[6],S.S0.h0w8[7],S.S1.h1w4[0],S.S1.h1w4[1],S.S1.h1w4[2],S.S1.h1w4[3],S.S2.h2w3[0],S.S2.h2w3[1],S.S2.h2w3[2],S.S2.h3w3[0],S.S2.h3w3[1],S.S2.h3w3[2]],u)}async function c(){v.ZTS2=Q.zerofierPolynomial([S.S1.h1w4[0],S.S1.h1w4[1],S.S1.h1w4[2],S.S1.h1w4[3],S.S2.h2w3[0],S.S2.h2w3[1],S.S2.h2w3[2],S.S2.h3w3[0],S.S2.h3w3[1],S.S2.h3w3[2]],u)}}function F(){let e=x.xi;for(let t=0;t Checking commitments belong to G1`),!su(i,o,a))return r&&r.error(`Proof commitments are not valid`),!1;if(r&&r.info(`> Checking evaluations belong to F`),!uu(i,o))return r&&r.error(`Proof evaluations are not valid.`),!1;if(r&&r.info(`> Checking public inputs belong to F`),!du(i,s))return r&&r.error(`Public inputs are not valid.`),!1;r&&r.info(`> Computing challenges`);let{challenges:l,roots:u}=fu(i,o,a,s,r);r&&r.info(`> Computing Zero polynomial evaluation Z_H(xi)`),l.zh=c.sub(l.xiN,c.one),l.invzh=c.inv(l.zh),r&&r.info(`> Computing Lagrange evaluations`);let d=await pu(i,l,a);r&&r.info(`> Computing polynomial identities PI(X)`);let f=mu(i,s,d);r&&r.info(`> Computing r0(y)`);let p=hu(o,l,u,i,r);r&&r.info(`> Computing r1(y)`);let m=gu(o,l,u,f,i,r);r&&r.info(`> Computing r2(y)`);let h=_u(o,l,u,d[1],a,i,r);r&&r.info(`> Computing F`);let g=vu(i,o,a,l,u);r&&r.info(`> Computing E`);let _=yu(i,o,l,a,p,m,h);r&&r.info(`> Computing J`);let v=bu(i,o,l);r&&r.info(`> Validate all evaluations with a pairing`);let y=await xu(i,o,l,a,g,_,v);return r&&(y?r.info(`PROOF VERIFIED SUCCESSFULLY`):r.warn(`Invalid Proof`)),r&&r.info(`FFLONK VERIFIER FINISHED`),y}function ou(e,t){let n=t;return n.k1=e.Fr.fromObject(t.k1),n.k2=e.Fr.fromObject(t.k2),n.w=e.Fr.fromObject(t.w),n.w3=e.Fr.fromObject(t.w3),n.w4=e.Fr.fromObject(t.w4),n.w8=e.Fr.fromObject(t.w8),n.wr=e.Fr.fromObject(t.wr),n.X_2=e.G2.fromObject(t.X_2),n.C0=e.G1.fromObject(t.C0),n}function su(e,t,n){let r=e.G1;return r.isValid(t.polynomials.C1)&&r.isValid(t.polynomials.C2)&&r.isValid(t.polynomials.W1)&&r.isValid(t.polynomials.W2)&&r.isValid(n.C0)}function cu(e,t){return V.geq(t,0)&&V.lt(t,e.r)}function lu(e,t){return cu(e,V.fromRprLE(t))}function uu(e,t){return lu(e,t.evaluations.ql)&&lu(e,t.evaluations.qr)&&lu(e,t.evaluations.qm)&&lu(e,t.evaluations.qo)&&lu(e,t.evaluations.qc)&&lu(e,t.evaluations.s1)&&lu(e,t.evaluations.s2)&&lu(e,t.evaluations.s3)&&lu(e,t.evaluations.a)&&lu(e,t.evaluations.b)&&lu(e,t.evaluations.c)&&lu(e,t.evaluations.z)&&lu(e,t.evaluations.zw)&&lu(e,t.evaluations.t1w)&&lu(e,t.evaluations.t2w)}function du(e,t){for(let n=0;nEu,exportSolidityVerifier:()=>Jc,fullProve:()=>ru,prove:()=>tu,setup:()=>$l,verify:()=>au});return Object.defineProperty(e,`curves`,{enumerable:!0,get:function(){return yi}}),Object.defineProperty(e,`fflonk`,{enumerable:!0,get:function(){return Du}}),Object.defineProperty(e,`groth16`,{enumerable:!0,get:function(){return qo}}),Object.defineProperty(e,`plonk`,{enumerable:!0,get:function(){return Wl}}),Object.defineProperty(e,`powersOfTau`,{enumerable:!0,get:function(){return Ts}}),Object.defineProperty(e,`r1cs`,{enumerable:!0,get:function(){return Hs}}),Object.defineProperty(e,`wtns`,{enumerable:!0,get:function(){return Js}}),Object.defineProperty(e,`zKey`,{enumerable:!0,get:function(){return Xc}}),e})({}); \ No newline at end of file +var snarkjs = (function(exports, _iden3_binfileutils, ffjavascript, r1csfile) { + Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); + //#region \0rolldown/runtime.js + var __create = Object.create; + var __defProp = Object.defineProperty; + var __getOwnPropDesc = Object.getOwnPropertyDescriptor; + var __getOwnPropNames = Object.getOwnPropertyNames; + var __getProtoOf = Object.getPrototypeOf; + var __hasOwnProp = Object.prototype.hasOwnProperty; + var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports); + var __exportAll = (all, no_symbols) => { + let target = {}; + for (var name in all) __defProp(target, name, { + get: all[name], + enumerable: true + }); + if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" }); + return target; + }; + var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { + key = keys[i]; + if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { + get: ((k) => from[k]).bind(null, key), + enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable + }); + } + return to; + }; + var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { + value: mod, + enumerable: true + }) : target, mod)); + //#endregion + _iden3_binfileutils = __toESM(_iden3_binfileutils); + //#region src/curves.js + var curves_exports = /* @__PURE__ */ __exportAll({ + getCurveFromName: () => getCurveFromName, + getCurveFromQ: () => getCurveFromQ, + getCurveFromR: () => getCurveFromR + }); + var bls12381r$1 = ffjavascript.Scalar.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16); + var bn128r$1 = ffjavascript.Scalar.e("21888242871839275222246405745257275088548364400416034343698204186575808495617"); + var bls12381q = ffjavascript.Scalar.e("1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", 16); + var bn128q = ffjavascript.Scalar.e("21888242871839275222246405745257275088696311157297823662689037894645226208583"); + async function getCurveFromR(r, options) { + let curve; + let singleThread = options && options.singleThread; + if (ffjavascript.Scalar.eq(r, bn128r$1)) curve = await (0, ffjavascript.buildBn128)(singleThread); + else if (ffjavascript.Scalar.eq(r, bls12381r$1)) curve = await (0, ffjavascript.buildBls12381)(singleThread); + else throw new Error(`Curve not supported: ${ffjavascript.Scalar.toString(r)}`); + return curve; + } + async function getCurveFromQ(q, options) { + let curve; + let singleThread = options && options.singleThread; + if (ffjavascript.Scalar.eq(q, bn128q)) curve = await (0, ffjavascript.buildBn128)(singleThread); + else if (ffjavascript.Scalar.eq(q, bls12381q)) curve = await (0, ffjavascript.buildBls12381)(singleThread); + else throw new Error(`Curve not supported: ${ffjavascript.Scalar.toString(q)}`); + return curve; + } + async function getCurveFromName(name, options) { + let curve; + let singleThread = options && options.singleThread; + const normName = normalizeName(name); + if ([ + "BN128", + "BN254", + "ALTBN128" + ].indexOf(normName) >= 0) curve = await (0, ffjavascript.buildBn128)(singleThread); + else if (["BLS12381"].indexOf(normName) >= 0) curve = await (0, ffjavascript.buildBls12381)(singleThread); + else throw new Error(`Curve not supported: ${name}`); + return curve; + function normalizeName(n) { + return n.toUpperCase().match(/[A-Za-z0-9]+/g).join(""); + } + } + //#endregion + //#region node_modules/@noble/hashes/utils.js + /** + * Utilities for hex, bytes, CSPRNG. + * @module + */ + /*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */ + /** Checks if something is Uint8Array. Be careful: nodejs Buffer will return true. */ + function isBytes(a) { + return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array"; + } + /** Asserts something is positive integer. */ + function anumber(n, title = "") { + if (!Number.isSafeInteger(n) || n < 0) { + const prefix = title && `"${title}" `; + throw new Error(`${prefix}expected integer >= 0, got ${n}`); + } + } + /** Asserts something is Uint8Array. */ + function abytes(value, length, title = "") { + const bytes = isBytes(value); + const len = value?.length; + const needsLen = length !== void 0; + if (!bytes || needsLen && len !== length) { + const prefix = title && `"${title}" `; + const ofLen = needsLen ? ` of length ${length}` : ""; + const got = bytes ? `length=${len}` : `type=${typeof value}`; + throw new Error(prefix + "expected Uint8Array" + ofLen + ", got " + got); + } + return value; + } + /** Asserts a hash instance has not been destroyed / finished */ + function aexists(instance, checkFinished = true) { + if (instance.destroyed) throw new Error("Hash instance has been destroyed"); + if (checkFinished && instance.finished) throw new Error("Hash#digest() has already been called"); + } + /** Asserts output is properly-sized byte array */ + function aoutput(out, instance) { + abytes(out, void 0, "digestInto() output"); + const min = instance.outputLen; + if (out.length < min) throw new Error("\"digestInto() output\" expected to be of length >=" + min); + } + /** Cast u8 / u16 / u32 to u32. */ + function u32(arr) { + return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4)); + } + /** Zeroize a byte array. Warning: JS provides no guarantees. */ + function clean(...arrays) { + for (let i = 0; i < arrays.length; i++) arrays[i].fill(0); + } + /** Is current platform little-endian? Most are. Big-Endian platform: IBM */ + var isLE = new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68; + /** The byte swap operation for uint32 */ + function byteSwap(word) { + return word << 24 & 4278190080 | word << 8 & 16711680 | word >>> 8 & 65280 | word >>> 24 & 255; + } + /** Conditionally byte swap if on a big-endian platform */ + var swap8IfBE = isLE ? (n) => n : (n) => byteSwap(n); + /** In place byte swap for Uint32Array */ + function byteSwap32(arr) { + for (let i = 0; i < arr.length; i++) arr[i] = byteSwap(arr[i]); + return arr; + } + var swap32IfBE = isLE ? (u) => u : byteSwap32; + typeof Uint8Array.from([]).toHex === "function" && Uint8Array.fromHex; + /** Creates function with outputLen, blockLen, create properties from a class constructor. */ + function createHasher(hashCons, info = {}) { + const hashC = (msg, opts) => hashCons(opts).update(msg).digest(); + const tmp = hashCons(void 0); + hashC.outputLen = tmp.outputLen; + hashC.blockLen = tmp.blockLen; + hashC.create = (opts) => hashCons(opts); + Object.assign(hashC, info); + return Object.freeze(hashC); + } + //#endregion + //#region node_modules/@noble/hashes/_blake.js + /** + * Internal blake variable. + * For BLAKE2b, the two extra permutations for rounds 10 and 11 are SIGMA[10..11] = SIGMA[0..1]. + */ + var BSIGMA = /* @__PURE__ */ Uint8Array.from([ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 14, + 10, + 4, + 8, + 9, + 15, + 13, + 6, + 1, + 12, + 0, + 2, + 11, + 7, + 5, + 3, + 11, + 8, + 12, + 0, + 5, + 2, + 15, + 13, + 10, + 14, + 3, + 6, + 7, + 1, + 9, + 4, + 7, + 9, + 3, + 1, + 13, + 12, + 11, + 14, + 2, + 6, + 5, + 10, + 4, + 0, + 15, + 8, + 9, + 0, + 5, + 7, + 2, + 4, + 10, + 15, + 14, + 1, + 11, + 12, + 6, + 8, + 3, + 13, + 2, + 12, + 6, + 10, + 0, + 11, + 8, + 3, + 4, + 13, + 7, + 5, + 15, + 14, + 1, + 9, + 12, + 5, + 1, + 15, + 14, + 13, + 4, + 10, + 0, + 7, + 6, + 3, + 9, + 2, + 8, + 11, + 13, + 11, + 7, + 14, + 12, + 1, + 3, + 9, + 5, + 0, + 15, + 4, + 8, + 6, + 2, + 10, + 6, + 15, + 14, + 9, + 11, + 3, + 0, + 8, + 12, + 2, + 13, + 7, + 1, + 4, + 10, + 5, + 10, + 2, + 8, + 4, + 7, + 6, + 1, + 5, + 15, + 11, + 9, + 14, + 3, + 12, + 13, + 0, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 14, + 10, + 4, + 8, + 9, + 15, + 13, + 6, + 1, + 12, + 0, + 2, + 11, + 7, + 5, + 3, + 11, + 8, + 12, + 0, + 5, + 2, + 15, + 13, + 10, + 14, + 3, + 6, + 7, + 1, + 9, + 4, + 7, + 9, + 3, + 1, + 13, + 12, + 11, + 14, + 2, + 6, + 5, + 10, + 4, + 0, + 15, + 8, + 9, + 0, + 5, + 7, + 2, + 4, + 10, + 15, + 14, + 1, + 11, + 12, + 6, + 8, + 3, + 13, + 2, + 12, + 6, + 10, + 0, + 11, + 8, + 3, + 4, + 13, + 7, + 5, + 15, + 14, + 1, + 9 + ]); + //#endregion + //#region node_modules/@noble/hashes/_u64.js + /** + * Internal helpers for u64. BigUint64Array is too slow as per 2025, so we implement it using Uint32Array. + * @todo re-check https://issues.chromium.org/issues/42212588 + * @module + */ + var U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1); + var _32n = /* @__PURE__ */ BigInt(32); + function fromBig(n, le = false) { + if (le) return { + h: Number(n & U32_MASK64), + l: Number(n >> _32n & U32_MASK64) + }; + return { + h: Number(n >> _32n & U32_MASK64) | 0, + l: Number(n & U32_MASK64) | 0 + }; + } + function split(lst, le = false) { + const len = lst.length; + let Ah = new Uint32Array(len); + let Al = new Uint32Array(len); + for (let i = 0; i < len; i++) { + const { h, l } = fromBig(lst[i], le); + [Ah[i], Al[i]] = [h, l]; + } + return [Ah, Al]; + } + var rotrSH = (h, l, s) => h >>> s | l << 32 - s; + var rotrSL = (h, l, s) => h << 32 - s | l >>> s; + var rotrBH = (h, l, s) => h << 64 - s | l >>> s - 32; + var rotrBL = (h, l, s) => h >>> s - 32 | l << 64 - s; + var rotr32H = (_h, l) => l; + var rotr32L = (h, _l) => h; + var rotlSH = (h, l, s) => h << s | l >>> 32 - s; + var rotlSL = (h, l, s) => l << s | h >>> 32 - s; + var rotlBH = (h, l, s) => l << s - 32 | h >>> 64 - s; + var rotlBL = (h, l, s) => h << s - 32 | l >>> 64 - s; + function add(Ah, Al, Bh, Bl) { + const l = (Al >>> 0) + (Bl >>> 0); + return { + h: Ah + Bh + (l / 2 ** 32 | 0) | 0, + l: l | 0 + }; + } + var add3L = (Al, Bl, Cl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0); + var add3H = (low, Ah, Bh, Ch) => Ah + Bh + Ch + (low / 2 ** 32 | 0) | 0; + //#endregion + //#region node_modules/@noble/hashes/blake2.js + /** + * blake2b (64-bit) & blake2s (8 to 32-bit) hash functions. + * b could have been faster, but there is no fast u64 in js, so s is 1.5x faster. + * @module + */ + var B2B_IV = /* @__PURE__ */ Uint32Array.from([ + 4089235720, + 1779033703, + 2227873595, + 3144134277, + 4271175723, + 1013904242, + 1595750129, + 2773480762, + 2917565137, + 1359893119, + 725511199, + 2600822924, + 4215389547, + 528734635, + 327033209, + 1541459225 + ]); + var BBUF = /* @__PURE__ */ new Uint32Array(32); + function G1b(a, b, c, d, msg, x) { + const Xl = msg[x], Xh = msg[x + 1]; + let Al = BBUF[2 * a], Ah = BBUF[2 * a + 1]; + let Bl = BBUF[2 * b], Bh = BBUF[2 * b + 1]; + let Cl = BBUF[2 * c], Ch = BBUF[2 * c + 1]; + let Dl = BBUF[2 * d], Dh = BBUF[2 * d + 1]; + let ll = add3L(Al, Bl, Xl); + Ah = add3H(ll, Ah, Bh, Xh); + Al = ll | 0; + ({Dh, Dl} = { + Dh: Dh ^ Ah, + Dl: Dl ^ Al + }); + ({Dh, Dl} = { + Dh: rotr32H(Dh, Dl), + Dl: rotr32L(Dh, Dl) + }); + ({h: Ch, l: Cl} = add(Ch, Cl, Dh, Dl)); + ({Bh, Bl} = { + Bh: Bh ^ Ch, + Bl: Bl ^ Cl + }); + ({Bh, Bl} = { + Bh: rotrSH(Bh, Bl, 24), + Bl: rotrSL(Bh, Bl, 24) + }); + BBUF[2 * a] = Al, BBUF[2 * a + 1] = Ah; + BBUF[2 * b] = Bl, BBUF[2 * b + 1] = Bh; + BBUF[2 * c] = Cl, BBUF[2 * c + 1] = Ch; + BBUF[2 * d] = Dl, BBUF[2 * d + 1] = Dh; + } + function G2b(a, b, c, d, msg, x) { + const Xl = msg[x], Xh = msg[x + 1]; + let Al = BBUF[2 * a], Ah = BBUF[2 * a + 1]; + let Bl = BBUF[2 * b], Bh = BBUF[2 * b + 1]; + let Cl = BBUF[2 * c], Ch = BBUF[2 * c + 1]; + let Dl = BBUF[2 * d], Dh = BBUF[2 * d + 1]; + let ll = add3L(Al, Bl, Xl); + Ah = add3H(ll, Ah, Bh, Xh); + Al = ll | 0; + ({Dh, Dl} = { + Dh: Dh ^ Ah, + Dl: Dl ^ Al + }); + ({Dh, Dl} = { + Dh: rotrSH(Dh, Dl, 16), + Dl: rotrSL(Dh, Dl, 16) + }); + ({h: Ch, l: Cl} = add(Ch, Cl, Dh, Dl)); + ({Bh, Bl} = { + Bh: Bh ^ Ch, + Bl: Bl ^ Cl + }); + ({Bh, Bl} = { + Bh: rotrBH(Bh, Bl, 63), + Bl: rotrBL(Bh, Bl, 63) + }); + BBUF[2 * a] = Al, BBUF[2 * a + 1] = Ah; + BBUF[2 * b] = Bl, BBUF[2 * b + 1] = Bh; + BBUF[2 * c] = Cl, BBUF[2 * c + 1] = Ch; + BBUF[2 * d] = Dl, BBUF[2 * d + 1] = Dh; + } + function checkBlake2Opts(outputLen, opts = {}, keyLen, saltLen, persLen) { + anumber(keyLen); + if (outputLen < 0 || outputLen > keyLen) throw new Error("outputLen bigger than keyLen"); + const { key, salt, personalization } = opts; + if (key !== void 0 && (key.length < 1 || key.length > keyLen)) throw new Error("\"key\" expected to be undefined or of length=1.." + keyLen); + if (salt !== void 0) abytes(salt, saltLen, "salt"); + if (personalization !== void 0) abytes(personalization, persLen, "personalization"); + } + /** Internal base class for BLAKE2. */ + var _BLAKE2 = class { + buffer; + buffer32; + finished = false; + destroyed = false; + length = 0; + pos = 0; + blockLen; + outputLen; + constructor(blockLen, outputLen) { + anumber(blockLen); + anumber(outputLen); + this.blockLen = blockLen; + this.outputLen = outputLen; + this.buffer = new Uint8Array(blockLen); + this.buffer32 = u32(this.buffer); + } + update(data) { + aexists(this); + abytes(data); + const { blockLen, buffer, buffer32 } = this; + const len = data.length; + const offset = data.byteOffset; + const buf = data.buffer; + for (let pos = 0; pos < len;) { + if (this.pos === blockLen) { + swap32IfBE(buffer32); + this.compress(buffer32, 0, false); + swap32IfBE(buffer32); + this.pos = 0; + } + const take = Math.min(blockLen - this.pos, len - pos); + const dataOffset = offset + pos; + if (take === blockLen && !(dataOffset % 4) && pos + take < len) { + const data32 = new Uint32Array(buf, dataOffset, Math.floor((len - pos) / 4)); + swap32IfBE(data32); + for (let pos32 = 0; pos + blockLen < len; pos32 += buffer32.length, pos += blockLen) { + this.length += blockLen; + this.compress(data32, pos32, false); + } + swap32IfBE(data32); + continue; + } + buffer.set(data.subarray(pos, pos + take), this.pos); + this.pos += take; + this.length += take; + pos += take; + } + return this; + } + digestInto(out) { + aexists(this); + aoutput(out, this); + const { pos, buffer32 } = this; + this.finished = true; + clean(this.buffer.subarray(pos)); + swap32IfBE(buffer32); + this.compress(buffer32, 0, true); + swap32IfBE(buffer32); + const out32 = u32(out); + this.get().forEach((v, i) => out32[i] = swap8IfBE(v)); + } + digest() { + const { buffer, outputLen } = this; + this.digestInto(buffer); + const res = buffer.slice(0, outputLen); + this.destroy(); + return res; + } + _cloneInto(to) { + const { buffer, length, finished, destroyed, outputLen, pos } = this; + to ||= new this.constructor({ dkLen: outputLen }); + to.set(...this.get()); + to.buffer.set(buffer); + to.destroyed = destroyed; + to.finished = finished; + to.length = length; + to.pos = pos; + to.outputLen = outputLen; + return to; + } + clone() { + return this._cloneInto(); + } + }; + /** Internal blake2b hash class. */ + var _BLAKE2b = class extends _BLAKE2 { + v0l = B2B_IV[0] | 0; + v0h = B2B_IV[1] | 0; + v1l = B2B_IV[2] | 0; + v1h = B2B_IV[3] | 0; + v2l = B2B_IV[4] | 0; + v2h = B2B_IV[5] | 0; + v3l = B2B_IV[6] | 0; + v3h = B2B_IV[7] | 0; + v4l = B2B_IV[8] | 0; + v4h = B2B_IV[9] | 0; + v5l = B2B_IV[10] | 0; + v5h = B2B_IV[11] | 0; + v6l = B2B_IV[12] | 0; + v6h = B2B_IV[13] | 0; + v7l = B2B_IV[14] | 0; + v7h = B2B_IV[15] | 0; + constructor(opts = {}) { + const olen = opts.dkLen === void 0 ? 64 : opts.dkLen; + super(128, olen); + checkBlake2Opts(olen, opts, 64, 16, 16); + let { key, personalization, salt } = opts; + let keyLength = 0; + if (key !== void 0) { + abytes(key, void 0, "key"); + keyLength = key.length; + } + this.v0l ^= this.outputLen | keyLength << 8 | 16842752; + if (salt !== void 0) { + abytes(salt, void 0, "salt"); + const slt = u32(salt); + this.v4l ^= swap8IfBE(slt[0]); + this.v4h ^= swap8IfBE(slt[1]); + this.v5l ^= swap8IfBE(slt[2]); + this.v5h ^= swap8IfBE(slt[3]); + } + if (personalization !== void 0) { + abytes(personalization, void 0, "personalization"); + const pers = u32(personalization); + this.v6l ^= swap8IfBE(pers[0]); + this.v6h ^= swap8IfBE(pers[1]); + this.v7l ^= swap8IfBE(pers[2]); + this.v7h ^= swap8IfBE(pers[3]); + } + if (key !== void 0) { + const tmp = new Uint8Array(this.blockLen); + tmp.set(key); + this.update(tmp); + } + } + get() { + let { v0l, v0h, v1l, v1h, v2l, v2h, v3l, v3h, v4l, v4h, v5l, v5h, v6l, v6h, v7l, v7h } = this; + return [ + v0l, + v0h, + v1l, + v1h, + v2l, + v2h, + v3l, + v3h, + v4l, + v4h, + v5l, + v5h, + v6l, + v6h, + v7l, + v7h + ]; + } + set(v0l, v0h, v1l, v1h, v2l, v2h, v3l, v3h, v4l, v4h, v5l, v5h, v6l, v6h, v7l, v7h) { + this.v0l = v0l | 0; + this.v0h = v0h | 0; + this.v1l = v1l | 0; + this.v1h = v1h | 0; + this.v2l = v2l | 0; + this.v2h = v2h | 0; + this.v3l = v3l | 0; + this.v3h = v3h | 0; + this.v4l = v4l | 0; + this.v4h = v4h | 0; + this.v5l = v5l | 0; + this.v5h = v5h | 0; + this.v6l = v6l | 0; + this.v6h = v6h | 0; + this.v7l = v7l | 0; + this.v7h = v7h | 0; + } + compress(msg, offset, isLast) { + this.get().forEach((v, i) => BBUF[i] = v); + BBUF.set(B2B_IV, 16); + let { h, l } = fromBig(BigInt(this.length)); + BBUF[24] = B2B_IV[8] ^ l; + BBUF[25] = B2B_IV[9] ^ h; + if (isLast) { + BBUF[28] = ~BBUF[28]; + BBUF[29] = ~BBUF[29]; + } + let j = 0; + const s = BSIGMA; + for (let i = 0; i < 12; i++) { + G1b(0, 4, 8, 12, msg, offset + 2 * s[j++]); + G2b(0, 4, 8, 12, msg, offset + 2 * s[j++]); + G1b(1, 5, 9, 13, msg, offset + 2 * s[j++]); + G2b(1, 5, 9, 13, msg, offset + 2 * s[j++]); + G1b(2, 6, 10, 14, msg, offset + 2 * s[j++]); + G2b(2, 6, 10, 14, msg, offset + 2 * s[j++]); + G1b(3, 7, 11, 15, msg, offset + 2 * s[j++]); + G2b(3, 7, 11, 15, msg, offset + 2 * s[j++]); + G1b(0, 5, 10, 15, msg, offset + 2 * s[j++]); + G2b(0, 5, 10, 15, msg, offset + 2 * s[j++]); + G1b(1, 6, 11, 12, msg, offset + 2 * s[j++]); + G2b(1, 6, 11, 12, msg, offset + 2 * s[j++]); + G1b(2, 7, 8, 13, msg, offset + 2 * s[j++]); + G2b(2, 7, 8, 13, msg, offset + 2 * s[j++]); + G1b(3, 4, 9, 14, msg, offset + 2 * s[j++]); + G2b(3, 4, 9, 14, msg, offset + 2 * s[j++]); + } + this.v0l ^= BBUF[0] ^ BBUF[16]; + this.v0h ^= BBUF[1] ^ BBUF[17]; + this.v1l ^= BBUF[2] ^ BBUF[18]; + this.v1h ^= BBUF[3] ^ BBUF[19]; + this.v2l ^= BBUF[4] ^ BBUF[20]; + this.v2h ^= BBUF[5] ^ BBUF[21]; + this.v3l ^= BBUF[6] ^ BBUF[22]; + this.v3h ^= BBUF[7] ^ BBUF[23]; + this.v4l ^= BBUF[8] ^ BBUF[24]; + this.v4h ^= BBUF[9] ^ BBUF[25]; + this.v5l ^= BBUF[10] ^ BBUF[26]; + this.v5h ^= BBUF[11] ^ BBUF[27]; + this.v6l ^= BBUF[12] ^ BBUF[28]; + this.v6h ^= BBUF[13] ^ BBUF[29]; + this.v7l ^= BBUF[14] ^ BBUF[30]; + this.v7h ^= BBUF[15] ^ BBUF[31]; + clean(BBUF); + } + destroy() { + this.destroyed = true; + clean(this.buffer32); + this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + } + }; + /** + * Blake2b hash function. 64-bit. 1.5x slower than blake2s in JS. + * @param msg - message that would be hashed + * @param opts - dkLen output length, key for MAC mode, salt, personalization + */ + var blake2b = /* @__PURE__ */ createHasher((opts) => new _BLAKE2b(opts)); + (/* @__PURE__ */ __commonJSMin(((exports, module) => { + module.exports = {}; + })))(); + var _revTable = []; + for (let i = 0; i < 256; i++) _revTable[i] = _revSlow(i, 8); + function _revSlow(idx, bits) { + let res = 0; + let a = idx; + for (let i = 0; i < bits; i++) { + res <<= 1; + res = res | a & 1; + a >>= 1; + } + return res; + } + function log2(V) { + return ((V & 4294901760) !== 0 ? (V &= 4294901760, 16) : 0) | ((V & 4278255360) !== 0 ? (V &= 4278255360, 8) : 0) | ((V & 4042322160) !== 0 ? (V &= 4042322160, 4) : 0) | ((V & 3435973836) !== 0 ? (V &= 3435973836, 2) : 0) | (V & 2863311530) !== 0; + } + function formatHash(b, title) { + const a = new DataView(b.buffer, b.byteOffset, b.byteLength); + let S = ""; + for (let i = 0; i < 4; i++) { + if (i > 0) S += "\n"; + S += " "; + for (let j = 0; j < 4; j++) { + if (j > 0) S += " "; + S += a.getUint32(i * 16 + j * 4).toString(16).padStart(8, "0"); + } + } + if (title) S = title + "\n" + S; + return S; + } + function hashIsEqual(h1, h2) { + if (h1.byteLength != h2.byteLength) return false; + var dv1 = new Int8Array(h1); + var dv2 = new Int8Array(h2); + for (var i = 0; i != h1.byteLength; i++) if (dv1[i] != dv2[i]) return false; + return true; + } + function cloneHasher(h) { + return h.clone(); + } + function fromPartialHash(partial) { + const buf = partial.subarray(0, 128); + const rest = u32(partial.subarray(128)); + const res = blake2b.create({ dkLen: 64 }); + res.buffer.set(buf); + res.v0l = rest[0] | 0, res.v0h = rest[1] | 0; + res.v1l = rest[2] | 0, res.v1h = rest[3] | 0; + res.v2l = rest[4] | 0, res.v2h = rest[5] | 0; + res.v3l = rest[6] | 0, res.v3h = rest[7] | 0; + res.v4l = rest[8] | 0, res.v4h = rest[9] | 0; + res.v5l = rest[10] | 0, res.v5h = rest[11] | 0; + res.v6l = rest[12] | 0, res.v6h = rest[13] | 0; + res.v7l = rest[14] | 0, res.v7h = rest[15] | 0; + const shift = 2 ** 32; + const len = rest[16] + rest[17] * shift; + const pos = rest[18] + rest[19] * shift; + res.length = len + pos; + res.pos = pos; + return res; + } + function toPartialHash(hash) { + const res = new Uint8Array(216); + const res32 = u32(res.subarray(128)); + res.set(hash.buffer); + res32[0] = hash.v0l, res32[1] = hash.v0h; + res32[2] = hash.v1l, res32[3] = hash.v1h; + res32[4] = hash.v2l, res32[5] = hash.v2h; + res32[6] = hash.v3l, res32[7] = hash.v3h; + res32[8] = hash.v4l, res32[9] = hash.v4h; + res32[10] = hash.v5l, res32[11] = hash.v5h; + res32[12] = hash.v6l, res32[13] = hash.v6h; + res32[14] = hash.v7l, res32[15] = hash.v7h; + res32[18] = hash.pos; + res32[16] = hash.length - hash.pos; + return res; + } + async function sameRatio$2(curve, g1s, g1sx, g2s, g2sx) { + if (curve.G1.isZero(g1s)) return false; + if (curve.G1.isZero(g1sx)) return false; + if (curve.G2.isZero(g2s)) return false; + if (curve.G2.isZero(g2sx)) return false; + return await curve.pairingEq(g1s, g2sx, curve.G1.neg(g1sx), g2s); + } + function askEntropy() { + return window.prompt("Enter a random text. (Entropy): ", ""); + } + function getRandomBytes(n) { + let array = new Uint8Array(n); + globalThis.crypto.getRandomValues(array); + return array; + } + async function sha256digest(data) { + { + const buffer = await globalThis.crypto.subtle.digest("SHA-256", data.buffer); + return new Uint8Array(buffer); + } + } + /** + * @param {Uint8Array} data + * @param {number} offset + */ + function readUInt32BE(data, offset) { + return new DataView(data.buffer).getUint32(offset, false); + } + async function getRandomRng(entropy) { + while (!entropy) entropy = await askEntropy(); + const hasher = blake2b.create(64); + hasher.update(getRandomBytes(64)); + const enc = new TextEncoder(); + hasher.update(enc.encode(entropy)); + const hash = hasher.digest(); + const seed = []; + for (let i = 0; i < 8; i++) seed[i] = readUInt32BE(hash, i * 4); + return new ffjavascript.ChaCha(seed); + } + async function rngFromBeaconParams(beaconHash, numIterationsExp) { + let nIterationsInner; + let nIterationsOuter; + if (numIterationsExp < 32) { + nIterationsInner = 1 << numIterationsExp >>> 0; + nIterationsOuter = 1; + } else { + nIterationsInner = 4294967296; + nIterationsOuter = 1 << numIterationsExp - 32 >>> 0; + } + let curHash = beaconHash; + for (let i = 0; i < nIterationsOuter; i++) for (let j = 0; j < nIterationsInner; j++) curHash = await sha256digest(curHash); + const curHashV = new DataView(curHash.buffer, curHash.byteOffset, curHash.byteLength); + const seed = []; + for (let i = 0; i < 8; i++) seed[i] = curHashV.getUint32(i * 4, false); + return new ffjavascript.ChaCha(seed); + } + function hex2ByteArray(s) { + if (s instanceof Uint8Array) return s; + if (s.slice(0, 2) == "0x") s = s.slice(2); + return new Uint8Array(s.match(/[\da-f]{2}/gi).map(function(h) { + return parseInt(h, 16); + })); + } + function byteArray2hex(byteArray) { + return Array.prototype.map.call(byteArray, function(byte) { + return ("0" + (byte & 255).toString(16)).slice(-2); + }).join(""); + } + function stringifyBigIntsWithField(Fr, o) { + if (o instanceof Uint8Array) return Fr.toString(o); + else if (Array.isArray(o)) return o.map(stringifyBigIntsWithField.bind(null, Fr)); + else if (typeof o == "object") { + const res = {}; + Object.keys(o).forEach((k) => { + res[k] = stringifyBigIntsWithField(Fr, o[k]); + }); + return res; + } else if (typeof o == "bigint" || o.eq !== void 0) return o.toString(10); + else return o; + } + //#endregion + //#region src/zkey_utils.js + async function writeHeader(fd, zkey) { + await _iden3_binfileutils.startWriteSection(fd, 1); + await fd.writeULE32(1); + await _iden3_binfileutils.endWriteSection(fd); + const curve = await getCurveFromQ(zkey.q); + await _iden3_binfileutils.startWriteSection(fd, 2); + const primeQ = curve.q; + const n8q = (Math.floor((ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) + 1) * 8; + const primeR = curve.r; + const n8r = (Math.floor((ffjavascript.Scalar.bitLength(primeR) - 1) / 64) + 1) * 8; + await fd.writeULE32(n8q); + await _iden3_binfileutils.writeBigInt(fd, primeQ, n8q); + await fd.writeULE32(n8r); + await _iden3_binfileutils.writeBigInt(fd, primeR, n8r); + await fd.writeULE32(zkey.nVars); + await fd.writeULE32(zkey.nPublic); + await fd.writeULE32(zkey.domainSize); + await writeG1(fd, curve, zkey.vk_alpha_1); + await writeG1(fd, curve, zkey.vk_beta_1); + await writeG2(fd, curve, zkey.vk_beta_2); + await writeG2(fd, curve, zkey.vk_gamma_2); + await writeG1(fd, curve, zkey.vk_delta_1); + await writeG2(fd, curve, zkey.vk_delta_2); + await _iden3_binfileutils.endWriteSection(fd); + } + async function writeG1(fd, curve, p) { + const buff = new Uint8Array(curve.G1.F.n8 * 2); + curve.G1.toRprLEM(buff, 0, p); + await fd.write(buff); + } + async function writeG2(fd, curve, p) { + const buff = new Uint8Array(curve.G2.F.n8 * 2); + curve.G2.toRprLEM(buff, 0, p); + await fd.write(buff); + } + async function readG1(fd, curve, toObject) { + const buff = await fd.read(curve.G1.F.n8 * 2); + const res = curve.G1.fromRprLEM(buff, 0); + return toObject ? curve.G1.toObject(res) : res; + } + async function readG2(fd, curve, toObject) { + const buff = await fd.read(curve.G2.F.n8 * 2); + const res = curve.G2.fromRprLEM(buff, 0); + return toObject ? curve.G2.toObject(res) : res; + } + async function readHeader$1(fd, sections, toObject, options) { + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 1); + const protocolId = await fd.readULE32(); + await _iden3_binfileutils.endReadSection(fd); + if (protocolId === 1) return await readHeaderGroth16(fd, sections, toObject, options); + else if (protocolId === 2) return await readHeaderPlonk(fd, sections, toObject, options); + else if (protocolId === 10) return await readHeaderFFlonk(fd, sections, toObject, options); + else throw new Error("Protocol not supported: "); + } + async function readHeaderGroth16(fd, sections, toObject, options) { + const zkey = {}; + zkey.protocol = "groth16"; + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 2); + const n8q = await fd.readULE32(); + zkey.n8q = n8q; + zkey.q = await _iden3_binfileutils.readBigInt(fd, n8q); + const n8r = await fd.readULE32(); + zkey.n8r = n8r; + zkey.r = await _iden3_binfileutils.readBigInt(fd, n8r); + zkey.curve = await getCurveFromQ(zkey.q, options); + zkey.nVars = await fd.readULE32(); + zkey.nPublic = await fd.readULE32(); + zkey.domainSize = await fd.readULE32(); + zkey.power = log2(zkey.domainSize); + zkey.vk_alpha_1 = await readG1(fd, zkey.curve, toObject); + zkey.vk_beta_1 = await readG1(fd, zkey.curve, toObject); + zkey.vk_beta_2 = await readG2(fd, zkey.curve, toObject); + zkey.vk_gamma_2 = await readG2(fd, zkey.curve, toObject); + zkey.vk_delta_1 = await readG1(fd, zkey.curve, toObject); + zkey.vk_delta_2 = await readG2(fd, zkey.curve, toObject); + await _iden3_binfileutils.endReadSection(fd); + return zkey; + } + async function readHeaderPlonk(fd, sections, toObject, options) { + const zkey = {}; + zkey.protocol = "plonk"; + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 2); + const n8q = await fd.readULE32(); + zkey.n8q = n8q; + zkey.q = await _iden3_binfileutils.readBigInt(fd, n8q); + const n8r = await fd.readULE32(); + zkey.n8r = n8r; + zkey.r = await _iden3_binfileutils.readBigInt(fd, n8r); + zkey.curve = await getCurveFromQ(zkey.q, options); + zkey.nVars = await fd.readULE32(); + zkey.nPublic = await fd.readULE32(); + zkey.domainSize = await fd.readULE32(); + zkey.power = log2(zkey.domainSize); + zkey.nAdditions = await fd.readULE32(); + zkey.nConstraints = await fd.readULE32(); + zkey.k1 = await fd.read(n8r); + zkey.k2 = await fd.read(n8r); + zkey.Qm = await readG1(fd, zkey.curve, toObject); + zkey.Ql = await readG1(fd, zkey.curve, toObject); + zkey.Qr = await readG1(fd, zkey.curve, toObject); + zkey.Qo = await readG1(fd, zkey.curve, toObject); + zkey.Qc = await readG1(fd, zkey.curve, toObject); + zkey.S1 = await readG1(fd, zkey.curve, toObject); + zkey.S2 = await readG1(fd, zkey.curve, toObject); + zkey.S3 = await readG1(fd, zkey.curve, toObject); + zkey.X_2 = await readG2(fd, zkey.curve, toObject); + await _iden3_binfileutils.endReadSection(fd); + return zkey; + } + async function readHeaderFFlonk(fd, sections, toObject, options) { + const zkey = {}; + zkey.protocol = "fflonk"; + zkey.protocolId = 10; + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 2); + const n8q = await fd.readULE32(); + zkey.n8q = n8q; + zkey.q = await _iden3_binfileutils.readBigInt(fd, n8q); + zkey.curve = await getCurveFromQ(zkey.q, options); + const n8r = await fd.readULE32(); + zkey.n8r = n8r; + zkey.r = await _iden3_binfileutils.readBigInt(fd, n8r); + zkey.nVars = await fd.readULE32(); + zkey.nPublic = await fd.readULE32(); + zkey.domainSize = await fd.readULE32(); + zkey.power = log2(zkey.domainSize); + zkey.nAdditions = await fd.readULE32(); + zkey.nConstraints = await fd.readULE32(); + zkey.k1 = await fd.read(n8r); + zkey.k2 = await fd.read(n8r); + zkey.w3 = await fd.read(n8r); + zkey.w4 = await fd.read(n8r); + zkey.w8 = await fd.read(n8r); + zkey.wr = await fd.read(n8r); + zkey.X_2 = await readG2(fd, zkey.curve, toObject); + zkey.C0 = await readG1(fd, zkey.curve, toObject); + await _iden3_binfileutils.endReadSection(fd); + return zkey; + } + async function readZKey(fileName, toObject) { + const { fd, sections } = await _iden3_binfileutils.readBinFile(fileName, "zkey", 1); + const zkey = await readHeader$1(fd, sections, toObject); + const Fr = new ffjavascript.F1Field(zkey.r); + const Rr = ffjavascript.Scalar.mod(ffjavascript.Scalar.shl(1, zkey.n8r * 8), zkey.r); + const Rri = Fr.inv(Rr); + const Rri2 = Fr.mul(Rri, Rri); + let curve = await getCurveFromQ(zkey.q); + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 3); + zkey.IC = []; + for (let i = 0; i <= zkey.nPublic; i++) { + const P = await readG1(fd, curve, toObject); + zkey.IC.push(P); + } + await _iden3_binfileutils.endReadSection(fd); + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 4); + const nCCoefs = await fd.readULE32(); + zkey.ccoefs = []; + for (let i = 0; i < nCCoefs; i++) { + const m = await fd.readULE32(); + const c = await fd.readULE32(); + const s = await fd.readULE32(); + const v = await readFr2(toObject); + zkey.ccoefs.push({ + matrix: m, + constraint: c, + signal: s, + value: v + }); + } + await _iden3_binfileutils.endReadSection(fd); + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 5); + zkey.A = []; + for (let i = 0; i < zkey.nVars; i++) { + const A = await readG1(fd, curve, toObject); + zkey.A[i] = A; + } + await _iden3_binfileutils.endReadSection(fd); + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 6); + zkey.B1 = []; + for (let i = 0; i < zkey.nVars; i++) { + const B1 = await readG1(fd, curve, toObject); + zkey.B1[i] = B1; + } + await _iden3_binfileutils.endReadSection(fd); + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 7); + zkey.B2 = []; + for (let i = 0; i < zkey.nVars; i++) { + const B2 = await readG2(fd, curve, toObject); + zkey.B2[i] = B2; + } + await _iden3_binfileutils.endReadSection(fd); + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 8); + zkey.C = []; + for (let i = zkey.nPublic + 1; i < zkey.nVars; i++) { + const C = await readG1(fd, curve, toObject); + zkey.C[i] = C; + } + await _iden3_binfileutils.endReadSection(fd); + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 9); + zkey.hExps = []; + for (let i = 0; i < zkey.domainSize; i++) { + const H = await readG1(fd, curve, toObject); + zkey.hExps.push(H); + } + await _iden3_binfileutils.endReadSection(fd); + await fd.close(); + return zkey; + async function readFr2() { + const n = await _iden3_binfileutils.readBigInt(fd, zkey.n8r); + return Fr.mul(n, Rri2); + } + } + async function readContribution$1(fd, curve, toObject) { + const c = { delta: {} }; + c.deltaAfter = await readG1(fd, curve, toObject); + c.delta.g1_s = await readG1(fd, curve, toObject); + c.delta.g1_sx = await readG1(fd, curve, toObject); + c.delta.g2_spx = await readG2(fd, curve, toObject); + c.transcript = await fd.read(64); + c.type = await fd.readULE32(); + const paramLength = await fd.readULE32(); + const curPos = fd.pos; + let lastType = 0; + while (fd.pos - curPos < paramLength) { + const buffType = await fd.read(1); + if (buffType[0] <= lastType) throw new Error("Parameters in the contribution must be sorted"); + lastType = buffType[0]; + if (buffType[0] == 1) { + const buffLen = await fd.read(1); + const buffStr = await fd.read(buffLen[0]); + c.name = new TextDecoder().decode(buffStr); + } else if (buffType[0] == 2) c.numIterationsExp = (await fd.read(1))[0]; + else if (buffType[0] == 3) { + const buffLen = await fd.read(1); + c.beaconHash = await fd.read(buffLen[0]); + } else throw new Error("Parameter not recognized"); + } + if (fd.pos != curPos + paramLength) throw new Error("Parameters do not match"); + return c; + } + async function readMPCParams(fd, curve, sections) { + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 10); + const res = { contributions: [] }; + res.csHash = await fd.read(64); + const n = await fd.readULE32(); + for (let i = 0; i < n; i++) { + const c = await readContribution$1(fd, curve); + res.contributions.push(c); + } + await _iden3_binfileutils.endReadSection(fd); + return res; + } + async function writeContribution$1(fd, curve, c) { + await writeG1(fd, curve, c.deltaAfter); + await writeG1(fd, curve, c.delta.g1_s); + await writeG1(fd, curve, c.delta.g1_sx); + await writeG2(fd, curve, c.delta.g2_spx); + await fd.write(c.transcript); + await fd.writeULE32(c.type || 0); + const params = []; + if (c.name) { + params.push(1); + const nameData = new TextEncoder("utf-8").encode(c.name.substring(0, 64)); + params.push(nameData.byteLength); + for (let i = 0; i < nameData.byteLength; i++) params.push(nameData[i]); + } + if (c.type == 1) { + params.push(2); + params.push(c.numIterationsExp); + params.push(3); + params.push(c.beaconHash.byteLength); + for (let i = 0; i < c.beaconHash.byteLength; i++) params.push(c.beaconHash[i]); + } + if (params.length > 0) { + const paramsBuff = new Uint8Array(params); + await fd.writeULE32(paramsBuff.byteLength); + await fd.write(paramsBuff); + } else await fd.writeULE32(0); + } + async function writeMPCParams(fd, curve, mpcParams) { + await _iden3_binfileutils.startWriteSection(fd, 10); + await fd.write(mpcParams.csHash); + await fd.writeULE32(mpcParams.contributions.length); + for (let i = 0; i < mpcParams.contributions.length; i++) await writeContribution$1(fd, curve, mpcParams.contributions[i]); + await _iden3_binfileutils.endWriteSection(fd); + } + function hashG1(hasher, curve, p) { + const buff = new Uint8Array(curve.G1.F.n8 * 2); + curve.G1.toRprUncompressed(buff, 0, p); + hasher.update(buff); + } + function hashG2(hasher, curve, p) { + const buff = new Uint8Array(curve.G2.F.n8 * 2); + curve.G2.toRprUncompressed(buff, 0, p); + hasher.update(buff); + } + function hashPubKey(hasher, curve, c) { + hashG1(hasher, curve, c.deltaAfter); + hashG1(hasher, curve, c.delta.g1_s); + hashG1(hasher, curve, c.delta.g1_sx); + hashG2(hasher, curve, c.delta.g2_spx); + hasher.update(c.transcript); + } + //#endregion + //#region src/wtns_utils.js + async function write(fd, witness, prime) { + await _iden3_binfileutils.startWriteSection(fd, 1); + const n8 = (Math.floor((ffjavascript.Scalar.bitLength(prime) - 1) / 64) + 1) * 8; + await fd.writeULE32(n8); + await _iden3_binfileutils.writeBigInt(fd, prime, n8); + await fd.writeULE32(witness.length); + await _iden3_binfileutils.endWriteSection(fd); + await _iden3_binfileutils.startWriteSection(fd, 2); + for (let i = 0; i < witness.length; i++) await _iden3_binfileutils.writeBigInt(fd, witness[i], n8); + await _iden3_binfileutils.endWriteSection(fd, 2); + } + async function writeBin(fd, witnessBin, prime) { + await _iden3_binfileutils.startWriteSection(fd, 1); + const n8 = (Math.floor((ffjavascript.Scalar.bitLength(prime) - 1) / 64) + 1) * 8; + await fd.writeULE32(n8); + await _iden3_binfileutils.writeBigInt(fd, prime, n8); + if (witnessBin.byteLength % n8 != 0) throw new Error("Invalid witness length"); + await fd.writeULE32(witnessBin.byteLength / n8); + await _iden3_binfileutils.endWriteSection(fd); + await _iden3_binfileutils.startWriteSection(fd, 2); + await fd.write(witnessBin); + await _iden3_binfileutils.endWriteSection(fd); + } + async function readHeader(fd, sections) { + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 1); + const n8 = await fd.readULE32(); + const q = await _iden3_binfileutils.readBigInt(fd, n8); + const nWitness = await fd.readULE32(); + await _iden3_binfileutils.endReadSection(fd); + return { + n8, + q, + nWitness + }; + } + async function read(fileName) { + const { fd, sections } = await _iden3_binfileutils.readBinFile(fileName, "wtns", 2); + const { n8, nWitness } = await readHeader(fd, sections); + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 2); + const res = []; + for (let i = 0; i < nWitness; i++) { + const v = await _iden3_binfileutils.readBigInt(fd, n8); + res.push(v); + } + await _iden3_binfileutils.endReadSection(fd); + await fd.close(); + return res; + } + //#endregion + //#region src/groth16_prove.js + var { stringifyBigInts: stringifyBigInts$3 } = ffjavascript.utils; + async function groth16Prove(zkeyFileName, witnessFileName, logger, options) { + if (logger) monitorMemoryUsage(logger, 50); + const { fd: fdWtns, sections: sectionsWtns } = await _iden3_binfileutils.readBinFile(witnessFileName, "wtns", 2, 1 << 25, 1 << 23); + const wtns = await readHeader(fdWtns, sectionsWtns); + const { fd: fdZKey, sections: sectionsZKey } = await _iden3_binfileutils.readBinFile(zkeyFileName, "zkey", 2, 1 << 25, 1 << 23); + const zkey = await readHeader$1(fdZKey, sectionsZKey, void 0, options); + if (zkey.protocol != "groth16") throw new Error("zkey file is not groth16"); + if (!ffjavascript.Scalar.eq(zkey.r, wtns.q)) throw new Error("Curve of the witness does not match the curve of the proving key"); + if (wtns.nWitness != zkey.nVars) throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}`); + const curve = zkey.curve; + const Fr = curve.Fr; + const G1 = curve.G1; + const G2 = curve.G2; + const power = log2(zkey.domainSize); + if (logger) logger.debug("Reading Wtns"); + const buffWitness = await _iden3_binfileutils.readSection(fdWtns, sectionsWtns, 2); + let resH; + let resHPromise; + let buffPodd_T; + let abcPromise = (async function() { + let buffA_T, buffB_T, buffC_T; + await (async function() { + if (logger) logger.debug("Reading Coeffs"); + console.time("buildABC_outer"); + const buffCoeffs = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 4); + if (logger) logger.debug("Building ABC"); + options = options || {}; + if (options && options.buildABC === "wasm") [buffA_T, buffB_T, buffC_T] = await buildABC(curve, zkey, buffWitness, buffCoeffs, logger); + else if (options && options.buildABC === "wasm1") [buffA_T, buffB_T, buffC_T] = await buildABCWASM1(curve, zkey, buffWitness, buffCoeffs, logger); + else [buffA_T, buffB_T, buffC_T] = await buildABC1(curve, zkey, buffWitness, buffCoeffs, logger); + console.timeEnd("buildABC_outer"); + })(); + console.time("abcPromise"); + if (globalThis.gc) globalThis.gc(); + const inc = power === Fr.s ? curve.Fr.shift : curve.Fr.w[power + 1]; + let buffAodd_T; + await (async function() { + let buffA = await Fr.ifft(buffA_T, "", "", logger, "IFFT_A"); + buffA_T = null; + const buffAodd = await Fr.batchApplyKey(buffA, Fr.e(1), inc); + buffAodd_T = await Fr.fft(buffAodd, "", "", logger, "FFT_A"); + })(); + let buffBodd_T; + await (async function() { + const buffB = await Fr.ifft(buffB_T, "", "", logger, "IFFT_B"); + buffB_T = null; + const buffBodd = await Fr.batchApplyKey(buffB, Fr.e(1), inc); + buffBodd_T = await Fr.fft(buffBodd, "", "", logger, "FFT_B"); + })(); + let buffCodd_T; + await (async function() { + const buffC = await Fr.ifft(buffC_T, "", "", logger, "IFFT_C"); + buffC_T = null; + const buffCodd = await Fr.batchApplyKey(buffC, Fr.e(1), inc); + buffCodd_T = await Fr.fft(buffCodd, "", "", logger, "FFT_C"); + })(); + if (logger) logger.debug("Join ABC"); + buffPodd_T = await joinABC(curve, zkey, buffAodd_T, buffBodd_T, buffCodd_T, logger); + if (logger) logger.debug("Join ABC finished"); + buffAodd_T = null; + buffBodd_T = null; + buffCodd_T = null; + if (globalThis.gc) globalThis.gc(); + console.timeEnd("abcPromise"); + })(); + let proof = {}; + async function calcPiA() { + if (logger) logger.debug("Reading A Points"); + const buffBasesA = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 5); + console.time("Calculate PiA"); + proof.pi_a = await curve.G1.multiExpAffine(buffBasesA, buffWitness, logger, "multiexp A"); + console.timeEnd("Calculate PiA"); + } + let piaPromise = calcPiA(); + let pib1; + async function calcPiB1() { + if (logger) logger.debug("Reading B1 Points"); + const buffBasesB1 = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 6); + console.time("Calculate PiB1"); + pib1 = await curve.G1.multiExpAffine(buffBasesB1, buffWitness, logger, "multiexp B1"); + console.timeEnd("Calculate PiB1"); + } + let pib1Promise = calcPiB1(); + async function calcPiB() { + if (logger) logger.debug("Reading B2 Points"); + const buffBasesB2 = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 7); + console.time("Calculate PiB"); + proof.pi_b = await curve.G2.multiExpAffine(buffBasesB2, buffWitness, logger, "multiexp B2"); + console.timeEnd("Calculate PiB"); + } + let pibPromise = calcPiB(); + let picPromise = (async function() { + if (logger) logger.debug("Reading C Points"); + const buffBasesC = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 8); + console.time("Calculate PiC"); + proof.pi_c = await curve.G1.multiExpAffine(buffBasesC, buffWitness.slice((zkey.nPublic + 1) * curve.Fr.n8), logger, "multiexp C"); + console.timeEnd("Calculate PiC"); + })(); + resHPromise = (async function() { + if (logger) logger.debug("Reading H Points"); + await abcPromise; + console.time("resHPromise"); + const buffBasesH = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 9); + resH = await curve.G1.multiExpAffine(buffBasesH, buffPodd_T, logger, "multiexp H"); + console.timeEnd("resHPromise"); + })(); + const r = curve.Fr.random(); + const s = curve.Fr.random(); + await piaPromise; + proof.pi_a = G1.add(proof.pi_a, zkey.vk_alpha_1); + proof.pi_a = G1.add(proof.pi_a, G1.timesFr(zkey.vk_delta_1, r)); + await pibPromise; + proof.pi_b = G2.add(proof.pi_b, zkey.vk_beta_2); + proof.pi_b = G2.add(proof.pi_b, G2.timesFr(zkey.vk_delta_2, s)); + await pib1Promise; + pib1 = G1.add(pib1, zkey.vk_beta_1); + pib1 = G1.add(pib1, G1.timesFr(zkey.vk_delta_1, s)); + await Promise.all([picPromise, resHPromise]); + proof.pi_c = G1.add(proof.pi_c, resH); + proof.pi_c = G1.add(proof.pi_c, G1.timesFr(proof.pi_a, s)); + proof.pi_c = G1.add(proof.pi_c, G1.timesFr(pib1, r)); + proof.pi_c = G1.add(proof.pi_c, G1.timesFr(zkey.vk_delta_1, Fr.neg(Fr.mul(r, s)))); + let publicSignals = []; + for (let i = 1; i <= zkey.nPublic; i++) { + const b = buffWitness.slice(i * Fr.n8, i * Fr.n8 + Fr.n8); + publicSignals.push(ffjavascript.Scalar.fromRprLE(b)); + } + proof.pi_a = G1.toObject(G1.toAffine(proof.pi_a)); + proof.pi_b = G2.toObject(G2.toAffine(proof.pi_b)); + proof.pi_c = G1.toObject(G1.toAffine(proof.pi_c)); + proof.protocol = "groth16"; + proof.curve = curve.name; + await fdZKey.close(); + await fdWtns.close(); + proof = stringifyBigInts$3(proof); + publicSignals = stringifyBigInts$3(publicSignals); + return { + proof, + publicSignals + }; + } + async function buildABC1(curve, zkey, witness, coeffs, logger) { + const n8 = curve.Fr.n8; + const sCoef = 12 + zkey.n8r; + const nCoef = (coeffs.byteLength - 4) / sCoef; + const outBuffA = new ffjavascript.BigBuffer(zkey.domainSize * n8); + const outBuffB = new ffjavascript.BigBuffer(zkey.domainSize * n8); + const outBuffC = new ffjavascript.BigBuffer(zkey.domainSize * n8); + const outBuf = [outBuffA, outBuffB]; + for (let i = 0; i < nCoef; i++) { + if (logger && i % 1e6 == 0) logger.debug(`QAP AB: ${i}/${nCoef}`); + let buffCoefV, coef; + if (coeffs.buffer) { + const coeffOffset = 4 + i * sCoef; + buffCoefV = new DataView(coeffs.buffer, coeffs.byteOffset + coeffOffset, sCoef); + coef = new Uint8Array(coeffs.buffer, coeffs.byteOffset + coeffOffset + 12, n8); + } else { + const buffCoef = coeffs.slice(4 + i * sCoef, 4 + i * sCoef + sCoef); + buffCoefV = new DataView(buffCoef.buffer); + coef = buffCoef.slice(12, 12 + n8); + } + const m = buffCoefV.getUint32(0, true); + const c = buffCoefV.getUint32(4, true); + const s = buffCoefV.getUint32(8, true); + outBuf[m].set(curve.Fr.add(outBuf[m].slice(c * n8, c * n8 + n8), curve.Fr.mul(coef, witness.slice(s * n8, s * n8 + n8))), c * n8); + if (i % 1e6 == 0 && logger) memUsage(logger); + } + for (let i = 0; i < zkey.domainSize; i++) { + if (logger && i % 1e6 == 0) logger.debug(`QAP C: ${i}/${zkey.domainSize}`); + outBuffC.set(curve.Fr.mul(outBuffA.slice(i * n8, i * n8 + n8), outBuffB.slice(i * n8, i * n8 + n8)), i * n8); + } + return [ + outBuffA, + outBuffB, + outBuffC + ]; + } + async function buildABC(curve, zkey, witness, coeffs, logger) { + let concurrency = curve.tm.concurrency; + const sCoef = 12 + zkey.n8r; + let getUint32; + if (coeffs instanceof ffjavascript.BigBuffer) { + const coeffsDV = []; + const PAGE_LEN = coeffs.buffers[0].length; + for (let i = 0; i < coeffs.buffers.length; i++) coeffsDV.push(new DataView(coeffs.buffers[i].buffer)); + getUint32 = function(pos) { + return coeffsDV[Math.floor(pos / PAGE_LEN)].getUint32(pos % PAGE_LEN, true); + }; + } else { + const coeffsDV = new DataView(coeffs.buffer, coeffs.byteOffset, coeffs.byteLength); + getUint32 = function(pos) { + return coeffsDV.getUint32(pos, true); + }; + } + let elementsPerChunk = Math.floor(zkey.domainSize / concurrency); + console.log("@@@ elementsPerChunk", elementsPerChunk); + while (elementsPerChunk > 2 ** 16) { + concurrency *= 2; + elementsPerChunk = Math.floor(zkey.domainSize / concurrency); + } + console.log("@@@ new elementsPerChunk", elementsPerChunk); + const promises = []; + const cutPoints = []; + for (let i = 0; i < concurrency; i++) cutPoints.push(getCutPoint(Math.floor(i * elementsPerChunk))); + cutPoints.push(coeffs.byteLength); + const chunkSize = 2 ** 26; + for (let s = 0; s < zkey.nVars; s += chunkSize) { + if (logger) logger.debug(`QAP ${s}: ${s}/${zkey.nVars}`); + const ns = Math.min(zkey.nVars - s, chunkSize); + for (let i = 0; i < concurrency; i++) { + let n; + if (i < concurrency - 1) n = elementsPerChunk; + else n = zkey.domainSize - i * elementsPerChunk; + if (n == 0) continue; + const task = []; + task.push({ + cmd: "ALLOCSET", + var: 0, + buff: coeffs.slice(cutPoints[i], cutPoints[i + 1]) + }); + task.push({ + cmd: "ALLOCSET", + var: 1, + buff: witness.slice(s * curve.Fr.n8, (s + ns) * curve.Fr.n8) + }); + task.push({ + cmd: "ALLOC", + var: 2, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "ALLOC", + var: 3, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "ALLOC", + var: 4, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "CALL", + fnName: "qap_buildABC", + params: [ + { var: 0 }, + { val: (cutPoints[i + 1] - cutPoints[i]) / sCoef }, + { var: 1 }, + { var: 2 }, + { var: 3 }, + { var: 4 }, + { val: i * elementsPerChunk }, + { val: n }, + { val: s }, + { val: ns } + ] + }); + task.push({ + cmd: "GET", + out: 0, + var: 2, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "GET", + out: 1, + var: 3, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "GET", + out: 2, + var: 4, + len: n * curve.Fr.n8 + }); + promises.push(curve.tm.queueAction(task)); + } + } + let result = await Promise.all(promises); + const nGroups = result.length / concurrency; + if (nGroups > 1) { + const promises2 = []; + for (let i = 0; i < concurrency; i++) { + const task = []; + task.push({ + cmd: "ALLOC", + var: 0, + len: result[i][0].byteLength + }); + task.push({ + cmd: "ALLOC", + var: 1, + len: result[i][0].byteLength + }); + for (let m = 0; m < 3; m++) { + task.push({ + cmd: "SET", + var: 0, + buff: result[i][m] + }); + for (let s = 1; s < nGroups; s++) { + task.push({ + cmd: "SET", + var: 1, + buff: result[s * concurrency + i][m] + }); + task.push({ + cmd: "CALL", + fnName: "qap_batchAdd", + params: [ + { var: 0 }, + { var: 1 }, + { val: result[i][m].length / curve.Fr.n8 }, + { var: 0 } + ] + }); + } + task.push({ + cmd: "GET", + out: m, + var: 0, + len: result[i][m].length + }); + } + promises2.push(curve.tm.queueAction(task)); + } + result = await Promise.all(promises2); + } + const outBuffA = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); + const outBuffB = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); + const outBuffC = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); + let p = 0; + for (let i = 0; i < result.length; i++) { + outBuffA.set(result[i][0], p); + outBuffB.set(result[i][1], p); + outBuffC.set(result[i][2], p); + p += result[i][0].byteLength; + } + return [ + outBuffA, + outBuffB, + outBuffC + ]; + function getCutPoint(v) { + let m = 0; + let n = getUint32(0); + while (m < n) { + var k = Math.floor((n + m) / 2); + const va = getUint32(4 + k * sCoef + 4); + if (va > v) n = k - 1; + else if (va < v) m = k + 1; + else n = k; + } + return 4 + m * sCoef; + } + } + async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { + console.time("buildABC"); + const concurrency = 1; + const sCoef = 12 + zkey.n8r; + let getUint32; + if (coeffs instanceof ffjavascript.BigBuffer) { + const coeffsDV = []; + const PAGE_LEN = coeffs.buffers[0].length; + for (let i = 0; i < coeffs.buffers.length; i++) coeffsDV.push(new DataView(coeffs.buffers[i].buffer)); + getUint32 = function(pos) { + return coeffsDV[Math.floor(pos / PAGE_LEN)].getUint32(pos % PAGE_LEN, true); + }; + } else { + const coeffsDV = new DataView(coeffs.buffer, coeffs.byteOffset, coeffs.byteLength); + getUint32 = function(pos) { + return coeffsDV.getUint32(pos, true); + }; + } + const elementsPerChunk = Math.floor((zkey.domainSize - 1) / concurrency) + 1; + const promises = []; + const cutPoints = []; + for (let i = 0; i < concurrency; i++) cutPoints.push(getCutPoint(Math.floor(i * elementsPerChunk))); + cutPoints.push(coeffs.byteLength); + const chunkSize = elementsPerChunk; + console.log("zkey.domainSize", zkey.domainSize); + console.log("concurrency", concurrency); + console.log("elementsPerChunk", elementsPerChunk); + console.log("chunkSize", chunkSize); + for (let s = 0; s < zkey.nVars; s += chunkSize) { + if (logger) logger.debug(`QAP: ${s}/${zkey.nVars}`); + const ns = Math.min(zkey.nVars - s, chunkSize); + console.log("ns", ns); + for (let i = 0; i < concurrency; i++) { + let n; + if (i < concurrency - 1) n = elementsPerChunk; + else n = zkey.domainSize - i * elementsPerChunk; + if (n === 0) continue; + const task = []; + const coeffsBuff = coeffs.slice(cutPoints[i], cutPoints[i + 1]); + const witnessBuff = witness.slice(s * curve.Fr.n8, (s + ns) * curve.Fr.n8); + task.push({ + cmd: "ALLOCSET", + var: 0, + buff: coeffsBuff + }); + task.push({ + cmd: "ALLOCSET", + var: 1, + buff: witnessBuff + }); + task.push({ + cmd: "ALLOC", + var: 2, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "ALLOC", + var: 3, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "ALLOC", + var: 4, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "CALL", + fnName: "qap_buildABC", + params: [ + { var: 0 }, + { val: (cutPoints[i + 1] - cutPoints[i]) / sCoef }, + { var: 1 }, + { var: 2 }, + { var: 3 }, + { var: 4 }, + { val: i * elementsPerChunk }, + { val: n }, + { val: s }, + { val: ns } + ] + }); + task.push({ + cmd: "GET", + out: 0, + var: 2, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "GET", + out: 1, + var: 3, + len: n * curve.Fr.n8 + }); + task.push({ + cmd: "GET", + out: 2, + var: 4, + len: n * curve.Fr.n8 + }); + promises.push(curve.tm.queueAction(task, [coeffsBuff.buffer, witnessBuff.buffer])); + } + } + let result = await Promise.all(promises); + console.log("result.length", result.length); + console.log("result", result); + const nGroups = result.length / concurrency; + console.log("nGroups", nGroups); + let result2; + if (nGroups > 1) { + const promises2 = []; + for (let i = 0; i < concurrency; i++) { + const task = []; + task.push({ + cmd: "ALLOC", + var: 0, + len: result[i][0].byteLength + }); + task.push({ + cmd: "ALLOC", + var: 1, + len: result[i][0].byteLength + }); + for (let m = 0; m < 3; m++) { + task.push({ + cmd: "SET", + var: 0, + buff: result[i][m] + }); + for (let s = 1; s < nGroups; s++) { + task.push({ + cmd: "SET", + var: 1, + buff: result[s * concurrency + i][m] + }); + task.push({ + cmd: "CALL", + fnName: "qap_batchAdd", + params: [ + { var: 0 }, + { var: 1 }, + { val: result[i][m].length / curve.Fr.n8 }, + { var: 0 } + ] + }); + } + task.push({ + cmd: "GET", + out: m, + var: 0, + len: result[i][m].length + }); + } + console.log("task.length", task.length); + promises2.push(curve.tm.queueAction(task, result.buffer)); + } + console.log("promises2.length", promises2.length); + result2 = await Promise.all(promises2); + result = result2; + } + const outBuffA = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); + const outBuffB = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); + const outBuffC = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); + let p = 0; + for (let i = 0; i < result.length; i++) { + outBuffA.set(result[i][0], p); + outBuffB.set(result[i][1], p); + outBuffC.set(result[i][2], p); + p += result[i][0].byteLength; + } + console.timeEnd("buildABC"); + return [ + outBuffA, + outBuffB, + outBuffC + ]; + function getCutPoint(v) { + let m = 0; + let n = getUint32(0); + while (m < n) { + let k = Math.floor((n + m) / 2); + const va = getUint32(4 + k * sCoef + 4); + if (va > v) n = k - 1; + else if (va < v) m = k + 1; + else n = k; + } + return 4 + m * sCoef; + } + } + async function joinABC(curve, zkey, a, b, c, logger) { + console.time("joinABC"); + const MAX_CHUNK_SIZE = 65536; + const n8 = curve.Fr.n8; + const nElements = Math.floor(a.byteLength / curve.Fr.n8); + const promises = []; + for (let i = 0; i < nElements; i += MAX_CHUNK_SIZE) { + if (logger) logger.debug(`JoinABC: ${i}/${nElements}`); + const n = Math.min(nElements - i, MAX_CHUNK_SIZE); + const task = []; + const aChunk = a.slice(i * n8, (i + n) * n8); + const bChunk = b.slice(i * n8, (i + n) * n8); + const cChunk = c.slice(i * n8, (i + n) * n8); + task.push({ + cmd: "ALLOCSET", + var: 0, + buff: aChunk + }); + task.push({ + cmd: "ALLOCSET", + var: 1, + buff: bChunk + }); + task.push({ + cmd: "ALLOCSET", + var: 2, + buff: cChunk + }); + task.push({ + cmd: "ALLOC", + var: 3, + len: n * n8 + }); + task.push({ + cmd: "CALL", + fnName: "qap_joinABC", + params: [ + { var: 0 }, + { var: 1 }, + { var: 2 }, + { val: n }, + { var: 3 } + ] + }); + task.push({ + cmd: "CALL", + fnName: "frm_batchFromMontgomery", + params: [ + { var: 3 }, + { val: n }, + { var: 3 } + ] + }); + task.push({ + cmd: "GET", + out: 0, + var: 3, + len: n * n8 + }); + promises.push(curve.tm.queueAction(task, [ + aChunk.buffer, + bChunk.buffer, + cChunk.buffer + ])); + } + const result = await Promise.all(promises); + let outBuff; + if (a instanceof ffjavascript.BigBuffer) outBuff = new ffjavascript.BigBuffer(a.byteLength); + else outBuff = new Uint8Array(a.byteLength); + let p = 0; + for (let i = 0; i < result.length; i++) { + outBuff.set(result[i][0], p); + p += result[i][0].byteLength; + } + console.timeEnd("joinABC"); + return outBuff; + } + function memUsage(logger) { + if (!logger || typeof process === "undefined" || !process.memoryUsage) return; + const used = process.memoryUsage(); + logger.debug(" ", "\x1B[0m Heap:\x1B[32m", `${Math.round(used.heapUsed / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m / \x1B[32m", `${Math.round(used.heapTotal / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m RSS:\x1B[32m", `${Math.round(used.rss / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m External:\x1B[32m", `${Math.round(used.external / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m ArrBuffers:\x1B[32m", `${Math.round(used.arrayBuffers / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m"); + } + function monitorMemoryUsage(logger, interval = 5e3) { + return setInterval(() => { + memUsage(logger); + }, interval); + } + //#endregion + //#region node_modules/fastfile/build/browser/browser.esm.js + function e(e) { + let t = e.initialSize || 1 << 20, n = new s(); + return n.o = e, n.o.data = new Uint8Array(t), n.allocSize = t, n.totalSize = 0, n.readOnly = !1, n.pos = 0, n; + } + function t(e) { + let t = new s(); + return t.o = e, t.allocSize = e.data.byteLength, t.totalSize = e.data.byteLength, t.readOnly = !0, t.pos = 0, t; + } + var r = new Uint8Array(4), i = new DataView(r.buffer), a = new Uint8Array(8), o = new DataView(a.buffer), s = class { + constructor() { + this.pageSize = 16384; + } + _resizeIfNeeded(e) { + if (e > this.allocSize) { + let t = Math.max(this.allocSize + (1 << 20), Math.floor(this.allocSize * 1.1), e), n = new Uint8Array(t); + n.set(this.o.data), this.o.data = n, this.allocSize = t; + } + } + async write(e, t) { + if (t === void 0 && (t = this.pos), this.readOnly) throw Error("Writing a read only file"); + this._resizeIfNeeded(t + e.byteLength), this.o.data.set(e.slice(), t), t + e.byteLength > this.totalSize && (this.totalSize = t + e.byteLength), this.pos = t + e.byteLength; + } + async readToBuffer(e, t, n, r) { + if (r === void 0 && (r = this.pos), this.readOnly && r + n > this.totalSize) throw Error("Reading out of bounds"); + this._resizeIfNeeded(r + n); + let i = new Uint8Array(this.o.data.buffer, this.o.data.byteOffset + r, n); + e.set(i, t), this.pos = r + n; + } + async read(e, t) { + let n = this, r = new Uint8Array(e); + return await n.readToBuffer(r, 0, e, t), r; + } + close() { + this.o.data.byteLength != this.totalSize && (this.o.data = this.o.data.slice(0, this.totalSize)); + } + async discard() {} + async writeULE32(e, t) { + let n = this; + i.setUint32(0, e, !0), await n.write(r, t); + } + async writeUBE32(e, t) { + let n = this; + i.setUint32(0, e, !1), await n.write(r, t); + } + async writeULE64(e, t) { + let n = this; + o.setUint32(0, e & 4294967295, !0), o.setUint32(4, Math.floor(e / 4294967296), !0), await n.write(a, t); + } + async readULE32(e) { + let t = await this.read(4, e); + return new Uint32Array(t.buffer)[0]; + } + async readUBE32(e) { + let t = await this.read(4, e); + return new DataView(t.buffer).getUint32(0, !1); + } + async readULE64(e) { + let t = await this.read(8, e), n = new Uint32Array(t.buffer); + return n[1] * 4294967296 + n[0]; + } + async readString(e) { + let t = this, n = e === void 0 ? t.pos : e; + if (n > this.totalSize) { + if (this.readOnly) throw Error("Reading out of bounds"); + this._resizeIfNeeded(e); + } + let r = new Uint8Array(t.o.data.buffer, n, this.totalSize - n), i = r.findIndex((e) => e === 0), a = i !== -1, o = ""; + return a ? (o = new TextDecoder().decode(r.slice(0, i)), t.pos = n + i + 1) : t.pos = n, o; + } + }, c = 1 << 22; + function l(e) { + let t = e.initialSize || 0, n = new g(); + n.o = e; + let r = t ? Math.floor((t - 1) / c) + 1 : 0; + n.o.data = []; + for (let e = 0; e < r - 1; e++) n.o.data.push(new Uint8Array(c)); + return r && n.o.data.push(new Uint8Array(t - c * (r - 1))), n.totalSize = 0, n.readOnly = !1, n.pos = 0, n; + } + function u(e) { + let t = new g(); + return t.o = e, t.totalSize = (e.data.length - 1) * c + e.data[e.data.length - 1].byteLength, t.readOnly = !0, t.pos = 0, t; + } + var f = new Uint8Array(4), p = new DataView(f.buffer), m = new Uint8Array(8), h = new DataView(m.buffer), g = class { + constructor() { + this.pageSize = 16384; + } + _resizeIfNeeded(e) { + if (e <= this.totalSize) return; + if (this.readOnly) throw Error("Reading out of file bounds"); + let t = Math.floor((e - 1) / c) + 1; + for (let n = Math.max(this.o.data.length - 1, 0); n < t; n++) { + let r = n < t - 1 ? c : e - (t - 1) * c, i = new Uint8Array(r); + n == this.o.data.length - 1 && i.set(this.o.data[n]), this.o.data[n] = i; + } + this.totalSize = e; + } + async write(e, t) { + let n = this; + if (t === void 0 && (t = n.pos), this.readOnly) throw Error("Writing a read only file"); + this._resizeIfNeeded(t + e.byteLength); + let r = Math.floor(t / c), i = t % c, a = e.byteLength; + for (; a > 0;) { + let t = i + a > c ? c - i : a, o = e.slice(e.byteLength - a, e.byteLength - a + t); + new Uint8Array(n.o.data[r].buffer, i, t).set(o), a -= t, r++, i = 0; + } + this.pos = t + e.byteLength; + } + async readToBuffer(e, t, n, r) { + let i = this; + if (r === void 0 && (r = i.pos), this.readOnly && r + n > this.totalSize) throw Error("Reading out of bounds"); + this._resizeIfNeeded(r + n); + let a = Math.floor(r / c), o = r % c, s = n; + for (; s > 0;) { + let r = o + s > c ? c - o : s, l = new Uint8Array(i.o.data[a].buffer, o, r); + e.set(l, t + n - s), s -= r, a++, o = 0; + } + this.pos = r + n; + } + async read(e, t) { + let n = this, r = new Uint8Array(e); + return await n.readToBuffer(r, 0, e, t), r; + } + close() {} + async discard() {} + async writeULE32(e, t) { + let n = this; + p.setUint32(0, e, !0), await n.write(f, t); + } + async writeUBE32(e, t) { + let n = this; + p.setUint32(0, e, !1), await n.write(f, t); + } + async writeULE64(e, t) { + let n = this; + h.setUint32(0, e & 4294967295, !0), h.setUint32(4, Math.floor(e / 4294967296), !0), await n.write(m, t); + } + async readULE32(e) { + let t = await this.read(4, e); + return new Uint32Array(t.buffer)[0]; + } + async readUBE32(e) { + let t = await this.read(4, e); + return new DataView(t.buffer).getUint32(0, !1); + } + async readULE64(e) { + let t = await this.read(8, e), n = new Uint32Array(t.buffer); + return n[1] * 4294967296 + n[0]; + } + async readString(e) { + let t = this, n = e === void 0 ? t.pos : e; + if (n > this.totalSize) { + if (this.readOnly) throw Error("Reading out of bounds"); + this._resizeIfNeeded(e); + } + let r = !1, i = ""; + for (; !r;) { + let e = Math.floor(n / c), a = n % c; + if (t.o.data[e] === void 0) throw Error("ERROR"); + let o = Math.min(2048, t.o.data[e].length - a), s = new Uint8Array(t.o.data[e].buffer, a, o), l = s.findIndex((e) => e === 0); + r = l !== -1, r ? (i += new TextDecoder().decode(s.slice(0, l)), t.pos = e * c + a + l + 1) : (i += new TextDecoder().decode(s), t.pos = e * c + a + s.length), n = t.pos; + } + return i; + } + }, _ = 65536; + function v() { + throw Error("File I/O is not supported in the browser"); + } + function y(e, t) { + return e instanceof Uint8Array ? { + type: "mem", + data: e + } : typeof e == "string" ? { + type: "mem", + initialSize: t || _ + } : e; + } + async function b(e) { + let t = await fetch(e).then((e) => e.arrayBuffer()); + return { + type: "mem", + data: new Uint8Array(t) + }; + } + function x(e, t, n) { + if (e.type === "file" && v(), e.type === "mem") return t(e); + if (e.type === "bigMem") return n(e); + throw Error("Invalid FastFile type: " + e.type); + } + function S(t, n) { + return x(y(t, n), e, l); + } + async function w(e) { + return e = typeof e == "string" ? await b(e) : y(e), x(e, t, u); + } + //#endregion + //#region node_modules/circom_runtime/js/utils.js + function flatArray(a) { + let res = []; + fillArray(res, a); + return res; + function fillArray(res, a) { + if (Array.isArray(a)) for (let i = 0; i < a.length; i++) fillArray(res, a[i]); + else res.push(a); + } + } + function normalize(n, prime) { + let res = BigInt(n) % prime; + if (res < 0) res += prime; + return res; + } + function fnvHash(str) { + const uint64_max = BigInt(2) ** BigInt(64); + let hash = BigInt("0xCBF29CE484222325"); + for (let i = 0; i < str.length; i++) { + hash ^= BigInt(str[i].charCodeAt(0)); + hash *= BigInt(1099511628211); + hash %= uint64_max; + } + let shash = hash.toString(16); + let n = 16 - shash.length; + shash = "0".repeat(n).concat(shash); + return shash; + } + function toArray32(s, size) { + const res = []; + let rem = BigInt(s); + const radix = BigInt(4294967296); + while (rem) { + res.unshift(Number(rem % radix)); + rem = rem / radix; + } + if (size) { + let i = size - res.length; + while (i > 0) { + res.unshift(0); + i--; + } + } + return res; + } + //#endregion + //#region node_modules/circom_runtime/js/witness_calculator.js + async function builder(code, options) { + let instance; + let wc; + let memory; + options = options || {}; + let majorVersion = 1; + let minorVersion = 0; + let patchVersion = 0; + let codeIsWebAssemblyInstance = false; + if (code instanceof WebAssembly.Instance) { + instance = code; + codeIsWebAssemblyInstance = true; + } else { + let memorySize = 32767; + if (options.memorySize) { + memorySize = parseInt(options.memorySize); + if (memorySize < 0) throw new Error("Invalid memory size"); + } + let memoryAllocated = false; + while (!memoryAllocated) try { + memory = new WebAssembly.Memory({ initial: memorySize }); + memoryAllocated = true; + } catch (err) { + if (memorySize <= 1) throw err; + console.warn("Could not allocate " + memorySize * 1024 * 64 + " bytes. This may cause severe instability. Trying with " + memorySize * 1024 * 64 / 2 + " bytes"); + memorySize = Math.floor(memorySize / 2); + } + const wasmModule = await WebAssembly.compile(code); + let errStr = ""; + let msgStr = ""; + instance = await WebAssembly.instantiate(wasmModule, { + env: { "memory": memory }, + runtime: { + printDebug: function(value) { + console.log("printDebug:", value); + }, + exceptionHandler: function(code) { + let err; + if (code === 1) err = "Signal not found. "; + else if (code === 2) err = "Too many signals set. "; + else if (code === 3) err = "Signal already set. "; + else if (code === 4) err = "Assert Failed. "; + else if (code === 5) err = "Not enough memory. "; + else if (code === 6) err = "Input signal array access exceeds the size. "; + else err = "Unknown error. "; + console.error("ERROR: ", code, errStr); + throw new Error(err + errStr); + }, + printErrorMessage: function() { + errStr += getMessage() + "\n"; + }, + writeBufferMessage: function() { + const msg = getMessage(); + if (msg === "\n") { + console.log(msgStr); + msgStr = ""; + } else { + if (msgStr !== "") msgStr += " "; + msgStr += msg; + } + }, + showSharedRWMemory: function() { + const shared_rw_memory_size = instance.exports.getFieldNumLen32(); + const arr = new Uint32Array(shared_rw_memory_size); + for (let j = 0; j < shared_rw_memory_size; j++) arr[shared_rw_memory_size - 1 - j] = instance.exports.readSharedRWMemory(j); + if (majorVersion >= 2 && (minorVersion >= 1 || patchVersion >= 7)) { + if (msgStr !== "") msgStr += " "; + const msg = ffjavascript.Scalar.fromArray(arr, 4294967296).toString(); + msgStr += msg; + } else console.log(ffjavascript.Scalar.fromArray(arr, 4294967296)); + }, + error: function(code, pstr, a, b, c, d) { + let errStr; + if (code === 7) errStr = p2str(pstr) + " " + wc.getFr(b).toString() + " != " + wc.getFr(c).toString() + " " + p2str(d); + else if (code === 9) errStr = p2str(pstr) + " " + wc.getFr(b).toString() + " " + p2str(c); + else if (code === 5 && options.sym) errStr = p2str(pstr) + " " + options.sym.labelIdx2Name[c]; + else errStr = p2str(pstr) + " " + a + " " + b + " " + c + " " + d; + console.log("ERROR: ", code, errStr); + throw new Error(errStr); + }, + log: function(a) { + console.log(wc.getFr(a).toString()); + }, + logGetSignal: function(signal, pVal) { + if (options.logGetSignal) options.logGetSignal(signal, wc.getFr(pVal)); + }, + logSetSignal: function(signal, pVal) { + if (options.logSetSignal) options.logSetSignal(signal, wc.getFr(pVal)); + }, + logStartComponent: function(cIdx) { + if (options.logStartComponent) options.logStartComponent(cIdx); + }, + logFinishComponent: function(cIdx) { + if (options.logFinishComponent) options.logFinishComponent(cIdx); + } + } + }); + } + if (typeof instance.exports.getVersion == "function") majorVersion = instance.exports.getVersion(); + if (typeof instance.exports.getMinorVersion == "function") minorVersion = instance.exports.getMinorVersion(); + if (typeof instance.exports.getPatchVersion == "function") patchVersion = instance.exports.getPatchVersion(); + const sanityCheck = options && (options.sanityCheck || options.logGetSignal || options.logSetSignal || options.logStartComponent || options.logFinishComponent); + if (majorVersion === 2) wc = new WitnessCalculatorCircom2(instance, sanityCheck); + else if (majorVersion === 1) { + if (codeIsWebAssemblyInstance) throw new Error("Loading code from WebAssembly instance is not supported for circom version 1"); + wc = new WitnessCalculatorCircom1(memory, instance, sanityCheck); + } else throw new Error(`Unsupported circom version: ${majorVersion}`); + return wc; + function getMessage() { + let message = ""; + let c = instance.exports.getMessageChar(); + while (c !== 0) { + message += String.fromCharCode(c); + c = instance.exports.getMessageChar(); + } + return message; + } + function p2str(p) { + const i8 = new Uint8Array(memory.buffer); + const bytes = []; + for (let i = 0; i8[p + i] > 0; i++) bytes.push(i8[p + i]); + return String.fromCharCode.apply(null, bytes); + } + } + var WitnessCalculatorCircom1 = class { + constructor(memory, instance, sanityCheck) { + this.memory = memory; + this.i32 = new Uint32Array(memory.buffer); + this.instance = instance; + this.n32 = (this.instance.exports.getFrLen() >> 2) - 2; + const pRawPrime = this.instance.exports.getPRawPrime(); + const arr = new Array(this.n32); + for (let i = 0; i < this.n32; i++) arr[this.n32 - 1 - i] = this.i32[(pRawPrime >> 2) + i]; + this.prime = ffjavascript.Scalar.fromArray(arr, 4294967296); + this.Fr = new ffjavascript.F1Field(this.prime); + this.mask32 = ffjavascript.Scalar.fromString("FFFFFFFF", 16); + this.NVars = this.instance.exports.getNVars(); + this.n64 = Math.floor((this.Fr.bitLength - 1) / 64) + 1; + this.R = this.Fr.e(ffjavascript.Scalar.shiftLeft(1, this.n64 * 64)); + this.RInv = this.Fr.inv(this.R); + this.sanityCheck = sanityCheck; + } + circom_version() { + return 1; + } + async _doCalculateWitness(input, sanityCheck) { + this.instance.exports.init(this.sanityCheck || sanityCheck ? 1 : 0); + const pSigOffset = this.allocInt(); + const pFr = this.allocFr(); + Object.keys(input).forEach((k) => { + const h = fnvHash(k); + const hMSB = parseInt(h.slice(0, 8), 16); + const hLSB = parseInt(h.slice(8, 16), 16); + try { + this.instance.exports.getSignalOffset32(pSigOffset, 0, hMSB, hLSB); + } catch (err) { + throw new Error(`Signal ${k} is not an input of the circuit.`); + } + const sigOffset = this.getInt(pSigOffset); + const fArr = flatArray(input[k]); + for (let i = 0; i < fArr.length; i++) { + this.setFr(pFr, fArr[i]); + this.instance.exports.setSignal(0, 0, sigOffset + i, pFr); + } + }); + } + async calculateWitness(input, sanityCheck) { + const self = this; + const old0 = self.i32[0]; + const w = []; + await self._doCalculateWitness(input, sanityCheck); + for (let i = 0; i < self.NVars; i++) { + const pWitness = self.instance.exports.getPWitness(i); + w.push(self.getFr(pWitness)); + } + self.i32[0] = old0; + return w; + } + async calculateBinWitness(input, sanityCheck) { + const self = this; + const old0 = self.i32[0]; + await self._doCalculateWitness(input, sanityCheck); + const pWitnessBuffer = self.instance.exports.getWitnessBuffer(); + self.i32[0] = old0; + const buff = self.memory.buffer.slice(pWitnessBuffer, pWitnessBuffer + self.NVars * self.n64 * 8); + return new Uint8Array(buff); + } + allocInt() { + const p = this.i32[0]; + this.i32[0] = p + 8; + return p; + } + allocFr() { + const p = this.i32[0]; + this.i32[0] = p + this.n32 * 4 + 8; + return p; + } + getInt(p) { + return this.i32[p >> 2]; + } + setInt(p, v) { + this.i32[p >> 2] = v; + } + getFr(p) { + const self = this; + const idx = p >> 2; + if (self.i32[idx + 1] & 2147483648) { + const arr = new Array(self.n32); + for (let i = 0; i < self.n32; i++) arr[self.n32 - 1 - i] = self.i32[idx + 2 + i]; + const res = self.Fr.e(ffjavascript.Scalar.fromArray(arr, 4294967296)); + if (self.i32[idx + 1] & 1073741824) return fromMontgomery(res); + else return res; + } else if (self.i32[idx] & 2147483648) return self.Fr.e(self.i32[idx] - 4294967296); + else return self.Fr.e(self.i32[idx]); + function fromMontgomery(n) { + return self.Fr.mul(self.RInv, n); + } + } + setFr(p, v) { + const self = this; + v = self.Fr.e(v); + const minShort = self.Fr.neg(self.Fr.e("80000000", 16)); + const maxShort = self.Fr.e("7FFFFFFF", 16); + if (self.Fr.geq(v, minShort) && self.Fr.leq(v, maxShort)) { + let a; + if (self.Fr.geq(v, self.Fr.zero)) a = ffjavascript.Scalar.toNumber(v); + else { + a = ffjavascript.Scalar.toNumber(self.Fr.sub(v, minShort)); + a = a - 2147483648; + a = 4294967296 + a; + } + self.i32[p >> 2] = a; + self.i32[(p >> 2) + 1] = 0; + return; + } + self.i32[p >> 2] = 0; + self.i32[(p >> 2) + 1] = 2147483648; + const arr = ffjavascript.Scalar.toArray(v, 4294967296); + for (let i = 0; i < self.n32; i++) { + const idx = arr.length - 1 - i; + if (idx >= 0) self.i32[(p >> 2) + 2 + i] = arr[idx]; + else self.i32[(p >> 2) + 2 + i] = 0; + } + } + }; + var WitnessCalculatorCircom2 = class { + constructor(instance, sanityCheck) { + this.instance = instance; + this.version = this.instance.exports.getVersion(); + this.n32 = this.instance.exports.getFieldNumLen32(); + this.instance.exports.getRawPrime(); + const arr = new Uint32Array(this.n32); + for (let i = 0; i < this.n32; i++) arr[this.n32 - 1 - i] = this.instance.exports.readSharedRWMemory(i); + this.prime = ffjavascript.Scalar.fromArray(arr, 4294967296); + this.witnessSize = this.instance.exports.getWitnessSize(); + this.sanityCheck = sanityCheck; + } + circom_version() { + return this.instance.exports.getVersion(); + } + async _doCalculateWitness(input, sanityCheck) { + this.instance.exports.init(this.sanityCheck || sanityCheck ? 1 : 0); + const keys = Object.keys(input); + let input_counter = 0; + keys.forEach((k) => { + const h = fnvHash(k); + const hMSB = parseInt(h.slice(0, 8), 16); + const hLSB = parseInt(h.slice(8, 16), 16); + const fArr = flatArray(input[k]); + if (typeof this.instance.exports.getInputSignalSize === "function") { + let signalSize = this.instance.exports.getInputSignalSize(hMSB, hLSB); + if (signalSize < 0) throw new Error(`Signal ${k} not found\n`); + if (fArr.length < signalSize) throw new Error(`Not enough values for input signal ${k}\n`); + if (fArr.length > signalSize) throw new Error(`Too many values for input signal ${k}\n`); + } + for (let i = 0; i < fArr.length; i++) { + const arrFr = toArray32(normalize(fArr[i], this.prime), this.n32); + for (let j = 0; j < this.n32; j++) this.instance.exports.writeSharedRWMemory(j, arrFr[this.n32 - 1 - j]); + try { + this.instance.exports.setInputSignal(hMSB, hLSB, i); + input_counter++; + } catch (err) { + throw new Error(err); + } + } + }); + if (input_counter < this.instance.exports.getInputSize()) throw new Error(`Not all inputs have been set. Only ${input_counter} out of ${this.instance.exports.getInputSize()}`); + } + async calculateWitness(input, sanityCheck) { + const w = []; + await this._doCalculateWitness(input, sanityCheck); + for (let i = 0; i < this.witnessSize; i++) { + this.instance.exports.getWitness(i); + const arr = new Uint32Array(this.n32); + for (let j = 0; j < this.n32; j++) arr[this.n32 - 1 - j] = this.instance.exports.readSharedRWMemory(j); + w.push(ffjavascript.Scalar.fromArray(arr, 4294967296)); + } + return w; + } + async calculateWTNSBin(input, sanityCheck) { + const buff32 = new Uint32Array(this.witnessSize * this.n32 + this.n32 + 11); + const buff = new Uint8Array(buff32.buffer); + await this._doCalculateWitness(input, sanityCheck); + buff[0] = "w".charCodeAt(0); + buff[1] = "t".charCodeAt(0); + buff[2] = "n".charCodeAt(0); + buff[3] = "s".charCodeAt(0); + buff32[1] = 2; + buff32[2] = 2; + buff32[3] = 1; + const n8 = this.n32 * 4; + const idSection1lengthHex = (8 + n8).toString(16); + buff32[4] = parseInt(idSection1lengthHex.slice(0, 8), 16); + buff32[5] = parseInt(idSection1lengthHex.slice(8, 16), 16); + buff32[6] = n8; + this.instance.exports.getRawPrime(); + let pos = 7; + for (let j = 0; j < this.n32; j++) buff32[pos + j] = this.instance.exports.readSharedRWMemory(j); + pos += this.n32; + buff32[pos] = this.witnessSize; + pos++; + buff32[pos] = 2; + pos++; + const idSection2lengthHex = (n8 * this.witnessSize).toString(16); + buff32[pos] = parseInt(idSection2lengthHex.slice(0, 8), 16); + buff32[pos + 1] = parseInt(idSection2lengthHex.slice(8, 16), 16); + pos += 2; + for (let i = 0; i < this.witnessSize; i++) { + this.instance.exports.getWitness(i); + for (let j = 0; j < this.n32; j++) buff32[pos + j] = this.instance.exports.readSharedRWMemory(j); + pos += this.n32; + } + return buff; + } + }; + //#endregion + //#region src/wtns_calculate.js + var { unstringifyBigInts: unstringifyBigInts$10 } = ffjavascript.utils; + async function wtnsCalculate(_input, wasmFileName, wtnsFileName, options) { + const input = unstringifyBigInts$10(_input); + const fdWasm = await w(wasmFileName); + const wasm = await fdWasm.read(fdWasm.totalSize); + await fdWasm.close(); + const wc = await builder(wasm, options); + if (wc.circom_version() === 1) { + const w = await wc.calculateBinWitness(input); + const fdWtns = await _iden3_binfileutils.createBinFile(wtnsFileName, "wtns", 2, 2); + await writeBin(fdWtns, w, wc.prime); + await fdWtns.close(); + } else { + const fdWtns = await S(wtnsFileName); + const w = await wc.calculateWTNSBin(input); + await fdWtns.write(w); + await fdWtns.close(); + } + } + //#endregion + //#region src/groth16_fullprove.js + var { unstringifyBigInts: unstringifyBigInts$9 } = ffjavascript.utils; + async function groth16FullProve(_input, wasmFile, zkeyFileName, logger, wtnsCalcOptions, proverOptions) { + const input = unstringifyBigInts$9(_input); + const wtns = { type: "mem" }; + await wtnsCalculate(input, wasmFile, wtns, wtnsCalcOptions); + return await groth16Prove(zkeyFileName, wtns, logger, proverOptions); + } + //#endregion + //#region src/groth16_verify.js + var { unstringifyBigInts: unstringifyBigInts$8 } = ffjavascript.utils; + async function groth16Verify(_vk_verifier, _publicSignals, _proof, logger) { + const vk_verifier = unstringifyBigInts$8(_vk_verifier); + const proof = unstringifyBigInts$8(_proof); + const publicSignals = unstringifyBigInts$8(_publicSignals); + const curve = await getCurveFromName(vk_verifier.curve); + const IC0 = curve.G1.fromObject(vk_verifier.IC[0]); + const IC = new Uint8Array(curve.G1.F.n8 * 2 * publicSignals.length); + const w = new Uint8Array(curve.Fr.n8 * publicSignals.length); + if (!publicInputsAreValid$2(curve, publicSignals)) { + if (logger) logger.error("Public inputs are not valid."); + return false; + } + for (let i = 0; i < publicSignals.length; i++) { + const buffP = curve.G1.fromObject(vk_verifier.IC[i + 1]); + IC.set(buffP, i * curve.G1.F.n8 * 2); + ffjavascript.Scalar.toRprLE(w, curve.Fr.n8 * i, publicSignals[i], curve.Fr.n8); + } + let cpub = await curve.G1.multiExpAffine(IC, w); + cpub = curve.G1.add(cpub, IC0); + const pi_a = curve.G1.fromObject(proof.pi_a); + const pi_b = curve.G2.fromObject(proof.pi_b); + const pi_c = curve.G1.fromObject(proof.pi_c); + if (!isWellConstructed$1(curve, { + pi_a, + pi_b, + pi_c + })) { + if (logger) logger.error("Proof commitments are not valid."); + return false; + } + const vk_gamma_2 = curve.G2.fromObject(vk_verifier.vk_gamma_2); + const vk_delta_2 = curve.G2.fromObject(vk_verifier.vk_delta_2); + const vk_alpha_1 = curve.G1.fromObject(vk_verifier.vk_alpha_1); + const vk_beta_2 = curve.G2.fromObject(vk_verifier.vk_beta_2); + if (!await curve.pairingEq(curve.G1.neg(pi_a), pi_b, cpub, vk_gamma_2, pi_c, vk_delta_2, vk_alpha_1, vk_beta_2)) { + if (logger) logger.error("Invalid proof"); + return false; + } + if (logger) logger.info("OK!"); + return true; + } + function isWellConstructed$1(curve, proof) { + const G1 = curve.G1; + const G2 = curve.G2; + return G1.isValid(proof.pi_a) && G2.isValid(proof.pi_b) && G1.isValid(proof.pi_c); + } + function checkValueBelongToField$2(curve, value) { + return ffjavascript.Scalar.geq(value, 0) && ffjavascript.Scalar.lt(value, curve.r); + } + function publicInputsAreValid$2(curve, publicInputs) { + for (let i = 0; i < publicInputs.length; i++) if (!checkValueBelongToField$2(curve, publicInputs[i])) return false; + return true; + } + //#endregion + //#region src/groth16_exportsoliditycalldata.js + var { unstringifyBigInts: unstringifyBigInts$7 } = ffjavascript.utils; + function p256$2(n) { + let nstr = n.toString(16); + while (nstr.length < 64) nstr = "0" + nstr; + nstr = `"0x${nstr}"`; + return nstr; + } + async function groth16ExportSolidityCallData(_proof, _pub) { + const proof = unstringifyBigInts$7(_proof); + const pub = unstringifyBigInts$7(_pub); + let inputs = ""; + for (let i = 0; i < pub.length; i++) { + if (inputs != "") inputs = inputs + ","; + inputs = inputs + p256$2(pub[i]); + } + let S; + S = `[${p256$2(proof.pi_a[0])}, ${p256$2(proof.pi_a[1])}],[[${p256$2(proof.pi_b[0][1])}, ${p256$2(proof.pi_b[0][0])}],[${p256$2(proof.pi_b[1][1])}, ${p256$2(proof.pi_b[1][0])}]],[${p256$2(proof.pi_c[0])}, ${p256$2(proof.pi_c[1])}],[${inputs}]`; + return S; + } + //#endregion + //#region src/groth16.js + var groth16_exports = /* @__PURE__ */ __exportAll({ + exportSolidityCallData: () => groth16ExportSolidityCallData, + fullProve: () => groth16FullProve, + prove: () => groth16Prove, + verify: () => groth16Verify + }); + //#endregion + //#region src/keypair.js + function hashToG2(curve, hash) { + const hashV = new DataView(hash.buffer, hash.byteOffset, hash.byteLength); + const seed = []; + for (let i = 0; i < 8; i++) seed[i] = hashV.getUint32(i * 4); + const rng = new ffjavascript.ChaCha(seed); + return curve.G2.fromRng(rng); + } + function getG2sp(curve, persinalization, challenge, g1s, g1sx) { + const h = blake2b.create({ dkLen: 64 }); + const b1 = new Uint8Array([persinalization]); + h.update(b1); + h.update(challenge); + const b3 = curve.G1.toUncompressed(g1s); + h.update(b3); + const b4 = curve.G1.toUncompressed(g1sx); + h.update(b4); + return hashToG2(curve, h.digest()); + } + function calculatePubKey(k, curve, personalization, challengeHash, rng) { + k.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); + k.g1_sx = curve.G1.toAffine(curve.G1.timesFr(k.g1_s, k.prvKey)); + k.g2_sp = curve.G2.toAffine(getG2sp(curve, personalization, challengeHash, k.g1_s, k.g1_sx)); + k.g2_spx = curve.G2.toAffine(curve.G2.timesFr(k.g2_sp, k.prvKey)); + return k; + } + function createPTauKey(curve, challengeHash, rng) { + const key = { + tau: {}, + alpha: {}, + beta: {} + }; + key.tau.prvKey = curve.Fr.fromRng(rng); + key.alpha.prvKey = curve.Fr.fromRng(rng); + key.beta.prvKey = curve.Fr.fromRng(rng); + calculatePubKey(key.tau, curve, 0, challengeHash, rng); + calculatePubKey(key.alpha, curve, 1, challengeHash, rng); + calculatePubKey(key.beta, curve, 2, challengeHash, rng); + return key; + } + //#endregion + //#region src/powersoftau_utils.js + async function writePTauHeader(fd, curve, power, ceremonyPower) { + if (!ceremonyPower) ceremonyPower = power; + await fd.writeULE32(1); + const pHeaderSize = fd.pos; + await fd.writeULE64(0); + await fd.writeULE32(curve.F1.n64 * 8); + const buff = new Uint8Array(curve.F1.n8); + ffjavascript.Scalar.toRprLE(buff, 0, curve.q, curve.F1.n8); + await fd.write(buff); + await fd.writeULE32(power); + await fd.writeULE32(ceremonyPower); + const headerSize = fd.pos - pHeaderSize - 8; + const oldPos = fd.pos; + await fd.writeULE64(headerSize, pHeaderSize); + fd.pos = oldPos; + } + async function readPTauHeader(fd, sections) { + if (!sections[1]) throw new Error(fd.fileName + ": File has no header"); + if (sections[1].length > 1) throw new Error(fd.fileName + ": File has more than one header"); + fd.pos = sections[1][0].p; + const n8 = await fd.readULE32(); + const buff = await fd.read(n8); + const curve = await getCurveFromQ(ffjavascript.Scalar.fromRprLE(buff)); + if (curve.F1.n64 * 8 != n8) throw new Error(fd.fileName + ": Invalid size"); + const power = await fd.readULE32(); + const ceremonyPower = await fd.readULE32(); + if (fd.pos - sections[1][0].p != sections[1][0].size) throw new Error("Invalid PTau header size"); + return { + curve, + power, + ceremonyPower + }; + } + async function readPtauPubKey(fd, curve, montgomery) { + return fromPtauPubKeyRpr(await fd.read(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3), 0, curve, montgomery); + } + function fromPtauPubKeyRpr(buff, pos, curve, montgomery) { + const key = { + tau: {}, + alpha: {}, + beta: {} + }; + key.tau.g1_s = readG1(); + key.tau.g1_sx = readG1(); + key.alpha.g1_s = readG1(); + key.alpha.g1_sx = readG1(); + key.beta.g1_s = readG1(); + key.beta.g1_sx = readG1(); + key.tau.g2_spx = readG2(); + key.alpha.g2_spx = readG2(); + key.beta.g2_spx = readG2(); + return key; + function readG1() { + let p; + if (montgomery) p = curve.G1.fromRprLEM(buff, pos); + else p = curve.G1.fromRprUncompressed(buff, pos); + pos += curve.G1.F.n8 * 2; + return p; + } + function readG2() { + let p; + if (montgomery) p = curve.G2.fromRprLEM(buff, pos); + else p = curve.G2.fromRprUncompressed(buff, pos); + pos += curve.G2.F.n8 * 2; + return p; + } + } + function toPtauPubKeyRpr(buff, pos, curve, key, montgomery) { + writeG1(key.tau.g1_s); + writeG1(key.tau.g1_sx); + writeG1(key.alpha.g1_s); + writeG1(key.alpha.g1_sx); + writeG1(key.beta.g1_s); + writeG1(key.beta.g1_sx); + writeG2(key.tau.g2_spx); + writeG2(key.alpha.g2_spx); + writeG2(key.beta.g2_spx); + async function writeG1(p) { + if (montgomery) curve.G1.toRprLEM(buff, pos, p); + else curve.G1.toRprUncompressed(buff, pos, p); + pos += curve.F1.n8 * 2; + } + async function writeG2(p) { + if (montgomery) curve.G2.toRprLEM(buff, pos, p); + else curve.G2.toRprUncompressed(buff, pos, p); + pos += curve.F2.n8 * 2; + } + return buff; + } + async function writePtauPubKey(fd, curve, key, montgomery) { + const buff = new Uint8Array(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3); + toPtauPubKeyRpr(buff, 0, curve, key, montgomery); + await fd.write(buff); + } + async function readContribution(fd, curve) { + const c = {}; + c.tauG1 = await readG1(); + c.tauG2 = await readG2(); + c.alphaG1 = await readG1(); + c.betaG1 = await readG1(); + c.betaG2 = await readG2(); + c.key = await readPtauPubKey(fd, curve, true); + c.partialHash = await fd.read(216); + c.nextChallenge = await fd.read(64); + c.type = await fd.readULE32(); + const buffV = new Uint8Array(curve.G1.F.n8 * 2 * 6 + curve.G2.F.n8 * 2 * 3); + toPtauPubKeyRpr(buffV, 0, curve, c.key, false); + const responseHasher = fromPartialHash(c.partialHash); + responseHasher.update(buffV); + c.responseHash = responseHasher.digest(); + const paramLength = await fd.readULE32(); + const curPos = fd.pos; + let lastType = 0; + while (fd.pos - curPos < paramLength) { + const buffType = await readDV(1); + if (buffType[0] <= lastType) throw new Error("Parameters in the contribution must be sorted"); + lastType = buffType[0]; + if (buffType[0] == 1) { + const buffStr = await readDV((await readDV(1))[0]); + c.name = new TextDecoder().decode(buffStr); + } else if (buffType[0] == 2) c.numIterationsExp = (await readDV(1))[0]; + else if (buffType[0] == 3) c.beaconHash = await readDV((await readDV(1))[0]); + else throw new Error("Parameter not recognized"); + } + if (fd.pos != curPos + paramLength) throw new Error("Parameters do not match"); + return c; + async function readG1() { + const pBuff = await fd.read(curve.G1.F.n8 * 2); + return curve.G1.fromRprLEM(pBuff); + } + async function readG2() { + const pBuff = await fd.read(curve.G2.F.n8 * 2); + return curve.G2.fromRprLEM(pBuff); + } + async function readDV(n) { + const b = await fd.read(n); + return new Uint8Array(b); + } + } + async function readContributions(fd, curve, sections) { + if (!sections[7]) throw new Error(fd.fileName + ": File has no contributions"); + if (sections[7][0].length > 1) throw new Error(fd.fileName + ": File has more than one contributions section"); + fd.pos = sections[7][0].p; + const nContributions = await fd.readULE32(); + const contributions = []; + for (let i = 0; i < nContributions; i++) { + const c = await readContribution(fd, curve); + c.id = i + 1; + contributions.push(c); + } + if (fd.pos - sections[7][0].p != sections[7][0].size) throw new Error("Invalid contribution section size"); + return contributions; + } + async function writeContribution(fd, curve, contribution) { + const buffG1 = new Uint8Array(curve.F1.n8 * 2); + const buffG2 = new Uint8Array(curve.F2.n8 * 2); + await writeG1(contribution.tauG1); + await writeG2(contribution.tauG2); + await writeG1(contribution.alphaG1); + await writeG1(contribution.betaG1); + await writeG2(contribution.betaG2); + await writePtauPubKey(fd, curve, contribution.key, true); + await fd.write(contribution.partialHash); + await fd.write(contribution.nextChallenge); + await fd.writeULE32(contribution.type || 0); + const params = []; + if (contribution.name) { + params.push(1); + const nameData = new TextEncoder("utf-8").encode(contribution.name.substring(0, 64)); + params.push(nameData.byteLength); + for (let i = 0; i < nameData.byteLength; i++) params.push(nameData[i]); + } + if (contribution.type == 1) { + params.push(2); + params.push(contribution.numIterationsExp); + params.push(3); + params.push(contribution.beaconHash.byteLength); + for (let i = 0; i < contribution.beaconHash.byteLength; i++) params.push(contribution.beaconHash[i]); + } + if (params.length > 0) { + const paramsBuff = new Uint8Array(params); + await fd.writeULE32(paramsBuff.byteLength); + await fd.write(paramsBuff); + } else await fd.writeULE32(0); + async function writeG1(p) { + curve.G1.toRprLEM(buffG1, 0, p); + await fd.write(buffG1); + } + async function writeG2(p) { + curve.G2.toRprLEM(buffG2, 0, p); + await fd.write(buffG2); + } + } + async function writeContributions(fd, curve, contributions) { + await fd.writeULE32(7); + const pContributionsSize = fd.pos; + await fd.writeULE64(0); + await fd.writeULE32(contributions.length); + for (let i = 0; i < contributions.length; i++) await writeContribution(fd, curve, contributions[i]); + const contributionsSize = fd.pos - pContributionsSize - 8; + const oldPos = fd.pos; + await fd.writeULE64(contributionsSize, pContributionsSize); + fd.pos = oldPos; + } + function calculateFirstChallengeHash(curve, power, logger) { + if (logger) logger.debug("Calculating First Challenge Hash"); + const hasher = blake2b.create({ dkLen: 64 }); + const vG1 = new Uint8Array(curve.G1.F.n8 * 2); + const vG2 = new Uint8Array(curve.G2.F.n8 * 2); + curve.G1.toRprUncompressed(vG1, 0, curve.G1.g); + curve.G2.toRprUncompressed(vG2, 0, curve.G2.g); + hasher.update(blake2b.create({ dkLen: 64 }).digest()); + let n; + n = 2 ** power * 2 - 1; + if (logger) logger.debug("Calculate Initial Hash: tauG1"); + hashBlock(vG1, n); + n = 2 ** power; + if (logger) logger.debug("Calculate Initial Hash: tauG2"); + hashBlock(vG2, n); + if (logger) logger.debug("Calculate Initial Hash: alphaTauG1"); + hashBlock(vG1, n); + if (logger) logger.debug("Calculate Initial Hash: betaTauG1"); + hashBlock(vG1, n); + hasher.update(vG2); + return hasher.digest(); + function hashBlock(buff, n) { + const blockSize = 341e3; + const nBlocks = Math.floor(n / blockSize); + const rem = n % blockSize; + const bigBuff = new Uint8Array(blockSize * buff.byteLength); + for (let i = 0; i < blockSize; i++) bigBuff.set(buff, i * buff.byteLength); + for (let i = 0; i < nBlocks; i++) { + hasher.update(bigBuff); + if (logger) logger.debug("Initial hash: " + i * blockSize); + } + for (let i = 0; i < rem; i++) hasher.update(buff); + } + } + async function keyFromBeacon(curve, challengeHash, beaconHash, numIterationsExp) { + return createPTauKey(curve, challengeHash, await rngFromBeaconParams(beaconHash, numIterationsExp)); + } + //#endregion + //#region src/powersoftau_new.js + async function newAccumulator(curve, power, fileName, logger) { + const fd = await _iden3_binfileutils.createBinFile(fileName, "ptau", 1, 7); + await writePTauHeader(fd, curve, power, 0); + const buffG1 = curve.G1.oneAffine; + const buffG2 = curve.G2.oneAffine; + await _iden3_binfileutils.startWriteSection(fd, 2); + const nTauG1 = 2 ** power * 2 - 1; + for (let i = 0; i < nTauG1; i++) { + await fd.write(buffG1); + if (logger && i % 1e5 == 0 && i) logger.log("tauG1: " + i); + } + await _iden3_binfileutils.endWriteSection(fd); + await _iden3_binfileutils.startWriteSection(fd, 3); + const nTauG2 = 2 ** power; + for (let i = 0; i < nTauG2; i++) { + await fd.write(buffG2); + if (logger && i % 1e5 == 0 && i) logger.log("tauG2: " + i); + } + await _iden3_binfileutils.endWriteSection(fd); + await _iden3_binfileutils.startWriteSection(fd, 4); + const nAlfaTauG1 = 2 ** power; + for (let i = 0; i < nAlfaTauG1; i++) { + await fd.write(buffG1); + if (logger && i % 1e5 == 0 && i) logger.log("alphaTauG1: " + i); + } + await _iden3_binfileutils.endWriteSection(fd); + await _iden3_binfileutils.startWriteSection(fd, 5); + const nBetaTauG1 = 2 ** power; + for (let i = 0; i < nBetaTauG1; i++) { + await fd.write(buffG1); + if (logger && i % 1e5 == 0 && i) logger.log("betaTauG1: " + i); + } + await _iden3_binfileutils.endWriteSection(fd); + await _iden3_binfileutils.startWriteSection(fd, 6); + await fd.write(buffG2); + await _iden3_binfileutils.endWriteSection(fd); + await _iden3_binfileutils.startWriteSection(fd, 7); + await fd.writeULE32(0); + await _iden3_binfileutils.endWriteSection(fd); + await fd.close(); + const firstChallengeHash = calculateFirstChallengeHash(curve, power, logger); + if (logger) logger.debug(formatHash(blake2b.create({ dkLen: 64 }).digest(), "Blank Contribution Hash:")); + if (logger) logger.info(formatHash(firstChallengeHash, "First Contribution Hash:")); + return firstChallengeHash; + } + //#endregion + //#region src/powersoftau_export_challenge.js + async function exportChallenge(pTauFilename, challengeFilename, logger) { + const { fd: fdFrom, sections } = await _iden3_binfileutils.readBinFile(pTauFilename, "ptau", 1); + const { curve, power } = await readPTauHeader(fdFrom, sections); + const contributions = await readContributions(fdFrom, curve, sections); + let lastResponseHash, curChallengeHash; + if (contributions.length == 0) { + lastResponseHash = blake2b.create({ dkLen: 64 }).digest(); + curChallengeHash = calculateFirstChallengeHash(curve, power); + } else { + lastResponseHash = contributions[contributions.length - 1].responseHash; + curChallengeHash = contributions[contributions.length - 1].nextChallenge; + } + if (logger) logger.info(formatHash(lastResponseHash, "Last Response Hash: ")); + if (logger) logger.info(formatHash(curChallengeHash, "New Challenge Hash: ")); + const fdTo = await S(challengeFilename); + const toHash = blake2b.create({ dkLen: 64 }); + await fdTo.write(lastResponseHash); + toHash.update(lastResponseHash); + await exportSection(2, "G1", 2 ** power * 2 - 1, "tauG1"); + await exportSection(3, "G2", 2 ** power, "tauG2"); + await exportSection(4, "G1", 2 ** power, "alphaTauG1"); + await exportSection(5, "G1", 2 ** power, "betaTauG1"); + await exportSection(6, "G2", 1, "betaG2"); + await fdFrom.close(); + await fdTo.close(); + const calcCurChallengeHash = toHash.digest(); + if (!hashIsEqual(curChallengeHash, calcCurChallengeHash)) { + if (logger) logger.info(formatHash(calcCurChallengeHash, "Calc Curret Challenge Hash: ")); + if (logger) logger.error("PTau file is corrupted. Calculated new challenge hash does not match with the eclared one"); + throw new Error("PTau file is corrupted. Calculated new challenge hash does not match with the eclared one"); + } + return curChallengeHash; + async function exportSection(sectionId, groupName, nPoints, sectionName) { + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const nPointsChunk = Math.floor((1 << 24) / sG); + await _iden3_binfileutils.startReadUniqueSection(fdFrom, sections, sectionId); + for (let i = 0; i < nPoints; i += nPointsChunk) { + if (logger) logger.debug(`Exporting ${sectionName}: ${i}/${nPoints}`); + const n = Math.min(nPoints - i, nPointsChunk); + let buff; + buff = await fdFrom.read(n * sG); + buff = await G.batchLEMtoU(buff); + await fdTo.write(buff); + toHash.update(buff); + } + await _iden3_binfileutils.endReadSection(fdFrom); + } + } + //#endregion + //#region src/powersoftau_import.js + async function importResponse(oldPtauFilename, contributionFilename, newPTauFilename, name, importPoints, logger) { + const noHash = new Uint8Array(64); + for (let i = 0; i < 64; i++) noHash[i] = 255; + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(oldPtauFilename, "ptau", 1); + const { curve, power } = await readPTauHeader(fdOld, sections); + const contributions = await readContributions(fdOld, curve, sections); + const currentContribution = {}; + if (name) currentContribution.name = name; + const sG1 = curve.F1.n8 * 2; + const scG1 = curve.F1.n8; + const sG2 = curve.F2.n8 * 2; + const scG2 = curve.F2.n8; + const fdResponse = await w(contributionFilename); + if (fdResponse.totalSize != 64 + (2 ** power * 2 - 1) * scG1 + 2 ** power * scG2 + 2 ** power * scG1 + 2 ** power * scG1 + scG2 + sG1 * 6 + sG2 * 3) throw new Error("Size of the contribution is invalid"); + let lastChallengeHash; + if (contributions.length > 0) lastChallengeHash = contributions[contributions.length - 1].nextChallenge; + else lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); + const fdNew = await _iden3_binfileutils.createBinFile(newPTauFilename, "ptau", 1, importPoints ? 7 : 2); + await writePTauHeader(fdNew, curve, power); + const contributionPreviousHash = await fdResponse.read(64); + if (hashIsEqual(noHash, lastChallengeHash)) { + lastChallengeHash = contributionPreviousHash; + contributions[contributions.length - 1].nextChallenge = lastChallengeHash; + } + if (!hashIsEqual(contributionPreviousHash, lastChallengeHash)) throw new Error("Wrong contribution. This contribution is not based on the previous hash"); + const hasherResponse = blake2b.create({ dkLen: 64 }); + hasherResponse.update(contributionPreviousHash); + const startSections = []; + let res; + res = await processSection(fdResponse, fdNew, "G1", 2, 2 ** power * 2 - 1, [1], "tauG1"); + currentContribution.tauG1 = res[0]; + res = await processSection(fdResponse, fdNew, "G2", 3, 2 ** power, [1], "tauG2"); + currentContribution.tauG2 = res[0]; + res = await processSection(fdResponse, fdNew, "G1", 4, 2 ** power, [0], "alphaG1"); + currentContribution.alphaG1 = res[0]; + res = await processSection(fdResponse, fdNew, "G1", 5, 2 ** power, [0], "betaG1"); + currentContribution.betaG1 = res[0]; + res = await processSection(fdResponse, fdNew, "G2", 6, 1, [0], "betaG2"); + currentContribution.betaG2 = res[0]; + currentContribution.partialHash = toPartialHash(hasherResponse); + const buffKey = await fdResponse.read(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3); + currentContribution.key = fromPtauPubKeyRpr(buffKey, 0, curve, false); + hasherResponse.update(new Uint8Array(buffKey)); + const hashResponse = hasherResponse.digest(); + if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); + if (importPoints) { + const nextChallengeHasher = blake2b.create({ dkLen: 64 }); + nextChallengeHasher.update(hashResponse); + await hashSection(nextChallengeHasher, fdNew, "G1", 2, 2 ** power * 2 - 1, "tauG1", logger); + await hashSection(nextChallengeHasher, fdNew, "G2", 3, 2 ** power, "tauG2", logger); + await hashSection(nextChallengeHasher, fdNew, "G1", 4, 2 ** power, "alphaTauG1", logger); + await hashSection(nextChallengeHasher, fdNew, "G1", 5, 2 ** power, "betaTauG1", logger); + await hashSection(nextChallengeHasher, fdNew, "G2", 6, 1, "betaG2", logger); + currentContribution.nextChallenge = nextChallengeHasher.digest(); + if (logger) logger.info(formatHash(currentContribution.nextChallenge, "Next Challenge Hash: ")); + } else currentContribution.nextChallenge = noHash; + contributions.push(currentContribution); + await writeContributions(fdNew, curve, contributions); + await fdResponse.close(); + await fdNew.close(); + await fdOld.close(); + return currentContribution.nextChallenge; + async function processSection(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { + if (importPoints) return await processSectionImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName); + else return await processSectionNoImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName); + } + async function processSectionImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { + const G = curve[groupName]; + const scG = G.F.n8; + const sG = G.F.n8 * 2; + const singularPoints = []; + await _iden3_binfileutils.startWriteSection(fdTo, sectionId); + const nPointsChunk = Math.floor((1 << 24) / sG); + startSections[sectionId] = fdTo.pos; + for (let i = 0; i < nPoints; i += nPointsChunk) { + if (logger) logger.debug(`Importing ${sectionName}: ${i}/${nPoints}`); + const n = Math.min(nPoints - i, nPointsChunk); + const buffC = await fdFrom.read(n * scG); + hasherResponse.update(buffC); + const buffLEM = await G.batchCtoLEM(buffC); + await fdTo.write(buffLEM); + for (let j = 0; j < singularPointIndexes.length; j++) { + const sp = singularPointIndexes[j]; + if (sp >= i && sp < i + n) { + const P = G.fromRprLEM(buffLEM, (sp - i) * sG); + singularPoints.push(P); + } + } + } + await _iden3_binfileutils.endWriteSection(fdTo); + return singularPoints; + } + async function processSectionNoImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { + const G = curve[groupName]; + const scG = G.F.n8; + const singularPoints = []; + const nPointsChunk = Math.floor((1 << 24) / scG); + for (let i = 0; i < nPoints; i += nPointsChunk) { + if (logger) logger.debug(`Importing ${sectionName}: ${i}/${nPoints}`); + const n = Math.min(nPoints - i, nPointsChunk); + const buffC = await fdFrom.read(n * scG); + hasherResponse.update(buffC); + for (let j = 0; j < singularPointIndexes.length; j++) { + const sp = singularPointIndexes[j]; + if (sp >= i && sp < i + n) { + const P = G.fromRprCompressed(buffC, (sp - i) * scG); + singularPoints.push(P); + } + } + } + return singularPoints; + } + async function hashSection(nextChallengeHasher, fdTo, groupName, sectionId, nPoints, sectionName, logger) { + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const nPointsChunk = Math.floor((1 << 24) / sG); + const oldPos = fdTo.pos; + fdTo.pos = startSections[sectionId]; + for (let i = 0; i < nPoints; i += nPointsChunk) { + if (logger) logger.debug(`Hashing ${sectionName}: ${i}/${nPoints}`); + const n = Math.min(nPoints - i, nPointsChunk); + const buffLEM = await fdTo.read(n * sG); + const buffU = await G.batchLEMtoU(buffLEM); + nextChallengeHasher.update(buffU); + } + fdTo.pos = oldPos; + } + } + //#endregion + //#region src/powersoftau_verify.js + var sameRatio$1 = sameRatio$2; + async function verifyContribution(curve, cur, prev, logger) { + let sr; + if (cur.type == 1) { + const beaconKey = await keyFromBeacon(curve, prev.nextChallenge, cur.beaconHash, cur.numIterationsExp); + if (!curve.G1.eq(cur.key.tau.g1_s, beaconKey.tau.g1_s)) { + if (logger) logger.error(`BEACON key (tauG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G1.eq(cur.key.tau.g1_sx, beaconKey.tau.g1_sx)) { + if (logger) logger.error(`BEACON key (tauG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G2.eq(cur.key.tau.g2_spx, beaconKey.tau.g2_spx)) { + if (logger) logger.error(`BEACON key (tauG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G1.eq(cur.key.alpha.g1_s, beaconKey.alpha.g1_s)) { + if (logger) logger.error(`BEACON key (alphaG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G1.eq(cur.key.alpha.g1_sx, beaconKey.alpha.g1_sx)) { + if (logger) logger.error(`BEACON key (alphaG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G2.eq(cur.key.alpha.g2_spx, beaconKey.alpha.g2_spx)) { + if (logger) logger.error(`BEACON key (alphaG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G1.eq(cur.key.beta.g1_s, beaconKey.beta.g1_s)) { + if (logger) logger.error(`BEACON key (betaG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G1.eq(cur.key.beta.g1_sx, beaconKey.beta.g1_sx)) { + if (logger) logger.error(`BEACON key (betaG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + if (!curve.G2.eq(cur.key.beta.g2_spx, beaconKey.beta.g2_spx)) { + if (logger) logger.error(`BEACON key (betaG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); + return false; + } + } + cur.key.tau.g2_sp = curve.G2.toAffine(getG2sp(curve, 0, prev.nextChallenge, cur.key.tau.g1_s, cur.key.tau.g1_sx)); + cur.key.alpha.g2_sp = curve.G2.toAffine(getG2sp(curve, 1, prev.nextChallenge, cur.key.alpha.g1_s, cur.key.alpha.g1_sx)); + cur.key.beta.g2_sp = curve.G2.toAffine(getG2sp(curve, 2, prev.nextChallenge, cur.key.beta.g1_s, cur.key.beta.g1_sx)); + sr = await sameRatio$1(curve, cur.key.tau.g1_s, cur.key.tau.g1_sx, cur.key.tau.g2_sp, cur.key.tau.g2_spx); + if (sr !== true) { + if (logger) logger.error("INVALID key (tau) in challenge #" + cur.id); + return false; + } + sr = await sameRatio$1(curve, cur.key.alpha.g1_s, cur.key.alpha.g1_sx, cur.key.alpha.g2_sp, cur.key.alpha.g2_spx); + if (sr !== true) { + if (logger) logger.error("INVALID key (alpha) in challenge #" + cur.id); + return false; + } + sr = await sameRatio$1(curve, cur.key.beta.g1_s, cur.key.beta.g1_sx, cur.key.beta.g2_sp, cur.key.beta.g2_spx); + if (sr !== true) { + if (logger) logger.error("INVALID key (beta) in challenge #" + cur.id); + return false; + } + sr = await sameRatio$1(curve, prev.tauG1, cur.tauG1, cur.key.tau.g2_sp, cur.key.tau.g2_spx); + if (sr !== true) { + if (logger) logger.error("INVALID tau*G1. challenge #" + cur.id + " It does not follow the previous contribution"); + return false; + } + sr = await sameRatio$1(curve, cur.key.tau.g1_s, cur.key.tau.g1_sx, prev.tauG2, cur.tauG2); + if (sr !== true) { + if (logger) logger.error("INVALID tau*G2. challenge #" + cur.id + " It does not follow the previous contribution"); + return false; + } + sr = await sameRatio$1(curve, prev.alphaG1, cur.alphaG1, cur.key.alpha.g2_sp, cur.key.alpha.g2_spx); + if (sr !== true) { + if (logger) logger.error("INVALID alpha*G1. challenge #" + cur.id + " It does not follow the previous contribution"); + return false; + } + sr = await sameRatio$1(curve, prev.betaG1, cur.betaG1, cur.key.beta.g2_sp, cur.key.beta.g2_spx); + if (sr !== true) { + if (logger) logger.error("INVALID beta*G1. challenge #" + cur.id + " It does not follow the previous contribution"); + return false; + } + sr = await sameRatio$1(curve, cur.key.beta.g1_s, cur.key.beta.g1_sx, prev.betaG2, cur.betaG2); + if (sr !== true) { + if (logger) logger.error("INVALID beta*G2. challenge #" + cur.id + "It does not follow the previous contribution"); + return false; + } + if (logger) logger.info("Powers Of tau file OK!"); + return true; + } + async function verify(tauFilename, logger) { + let sr; + const { fd, sections } = await _iden3_binfileutils.readBinFile(tauFilename, "ptau", 1); + const { curve, power, ceremonyPower } = await readPTauHeader(fd, sections); + const contrs = await readContributions(fd, curve, sections); + if (logger) logger.debug("power: 2**" + power); + if (logger) logger.debug("Computing initial contribution hash"); + const initialContribution = { + tauG1: curve.G1.g, + tauG2: curve.G2.g, + alphaG1: curve.G1.g, + betaG1: curve.G1.g, + betaG2: curve.G2.g, + nextChallenge: calculateFirstChallengeHash(curve, ceremonyPower, logger), + responseHash: blake2b.create({ dkLen: 64 }).digest() + }; + if (contrs.length == 0) { + if (logger) logger.error("This file has no contribution! It cannot be used in production"); + return false; + } + let prevContr; + if (contrs.length > 1) prevContr = contrs[contrs.length - 2]; + else prevContr = initialContribution; + const curContr = contrs[contrs.length - 1]; + if (logger) logger.debug("Validating contribution #" + contrs[contrs.length - 1].id); + if (!await verifyContribution(curve, curContr, prevContr, logger)) return false; + const nextContributionHasher = blake2b.create({ dkLen: 64 }); + nextContributionHasher.update(curContr.responseHash); + if (logger) logger.debug("Verifying powers in tau*G1 section"); + const rTau1 = await processSection(2, "G1", "tauG1", 2 ** power * 2 - 1, [0, 1], logger); + sr = await sameRatio$1(curve, rTau1.R1, rTau1.R2, curve.G2.g, curContr.tauG2); + if (sr !== true) { + if (logger) logger.error("tauG1 section. Powers do not match"); + return false; + } + if (!curve.G1.eq(curve.G1.g, rTau1.singularPoints[0])) { + if (logger) logger.error("First element of tau*G1 section must be the generator"); + return false; + } + if (!curve.G1.eq(curContr.tauG1, rTau1.singularPoints[1])) { + if (logger) logger.error("Second element of tau*G1 section does not match the one in the contribution section"); + return false; + } + if (logger) logger.debug("Verifying powers in tau*G2 section"); + const rTau2 = await processSection(3, "G2", "tauG2", 2 ** power, [0, 1], logger); + sr = await sameRatio$1(curve, curve.G1.g, curContr.tauG1, rTau2.R1, rTau2.R2); + if (sr !== true) { + if (logger) logger.error("tauG2 section. Powers do not match"); + return false; + } + if (!curve.G2.eq(curve.G2.g, rTau2.singularPoints[0])) { + if (logger) logger.error("First element of tau*G2 section must be the generator"); + return false; + } + if (!curve.G2.eq(curContr.tauG2, rTau2.singularPoints[1])) { + if (logger) logger.error("Second element of tau*G2 section does not match the one in the contribution section"); + return false; + } + if (logger) logger.debug("Verifying powers in alpha*tau*G1 section"); + const rAlphaTauG1 = await processSection(4, "G1", "alphatauG1", 2 ** power, [0], logger); + sr = await sameRatio$1(curve, rAlphaTauG1.R1, rAlphaTauG1.R2, curve.G2.g, curContr.tauG2); + if (sr !== true) { + if (logger) logger.error("alphaTauG1 section. Powers do not match"); + return false; + } + if (!curve.G1.eq(curContr.alphaG1, rAlphaTauG1.singularPoints[0])) { + if (logger) logger.error("First element of alpha*tau*G1 section (alpha*G1) does not match the one in the contribution section"); + return false; + } + if (logger) logger.debug("Verifying powers in beta*tau*G1 section"); + const rBetaTauG1 = await processSection(5, "G1", "betatauG1", 2 ** power, [0], logger); + sr = await sameRatio$1(curve, rBetaTauG1.R1, rBetaTauG1.R2, curve.G2.g, curContr.tauG2); + if (sr !== true) { + if (logger) logger.error("betaTauG1 section. Powers do not match"); + return false; + } + if (!curve.G1.eq(curContr.betaG1, rBetaTauG1.singularPoints[0])) { + if (logger) logger.error("First element of beta*tau*G1 section (beta*G1) does not match the one in the contribution section"); + return false; + } + const betaG2 = await processSectionBetaG2(logger); + if (!curve.G2.eq(curContr.betaG2, betaG2)) { + if (logger) logger.error("betaG2 element in betaG2 section does not match the one in the contribution section"); + return false; + } + const nextContributionHash = nextContributionHasher.digest(); + if (power == ceremonyPower) { + if (!hashIsEqual(nextContributionHash, curContr.nextChallenge)) { + if (logger) logger.error("Hash of the values does not match the next challenge of the last contributor in the contributions section"); + return false; + } + } + if (logger) logger.info(formatHash(nextContributionHash, "Next challenge hash: ")); + printContribution(curContr, prevContr); + for (let i = contrs.length - 2; i >= 0; i--) { + const curContr = contrs[i]; + const prevContr = i > 0 ? contrs[i - 1] : initialContribution; + if (!await verifyContribution(curve, curContr, prevContr, logger)) return false; + printContribution(curContr, prevContr, logger); + } + if (logger) logger.info("-----------------------------------------------------"); + if (!sections[12] || !sections[13] || !sections[14] || !sections[15]) { + if (logger) logger.warn("this file does not contain phase2 precalculated values. Please run: \n snarkjs \"powersoftau preparephase2\" to prepare this file to be used in the phase2 ceremony."); + } else { + let res; + res = await verifyLagrangeEvaluations("G1", 2, 12, "tauG1", logger); + if (!res) return false; + res = await verifyLagrangeEvaluations("G2", 3, 13, "tauG2", logger); + if (!res) return false; + res = await verifyLagrangeEvaluations("G1", 4, 14, "alphaTauG1", logger); + if (!res) return false; + res = await verifyLagrangeEvaluations("G1", 5, 15, "betaTauG1", logger); + if (!res) return false; + } + await fd.close(); + if (logger) logger.info("Powers of Tau Ok!"); + return true; + function printContribution(curContr, prevContr) { + if (!logger) return; + logger.info("-----------------------------------------------------"); + logger.info(`Contribution #${curContr.id}: ${curContr.name || ""}`); + logger.info(formatHash(curContr.nextChallenge, "Next Challenge: ")); + const buffV = new Uint8Array(curve.G1.F.n8 * 2 * 6 + curve.G2.F.n8 * 2 * 3); + toPtauPubKeyRpr(buffV, 0, curve, curContr.key, false); + const responseHasher = fromPartialHash(curContr.partialHash); + responseHasher.update(buffV); + const responseHash = responseHasher.digest(); + logger.info(formatHash(responseHash, "Response Hash:")); + logger.info(formatHash(prevContr.nextChallenge, "Response Hash:")); + if (curContr.type == 1) { + logger.info(`Beacon generator: ${byteArray2hex(curContr.beaconHash)}`); + logger.info(`Beacon iterations Exp: ${curContr.numIterationsExp}`); + } + } + async function processSectionBetaG2(logger) { + const G = curve.G2; + const sG = G.F.n8 * 2; + const buffUv = new Uint8Array(sG); + if (!sections[6]) { + logger.error("File has no BetaG2 section"); + throw new Error("File has no BetaG2 section"); + } + if (sections[6].length > 1) { + logger.error("File has no BetaG2 section"); + throw new Error("File has more than one GetaG2 section"); + } + fd.pos = sections[6][0].p; + const buff = await fd.read(sG); + const P = G.fromRprLEM(buff); + G.toRprUncompressed(buffUv, 0, P); + nextContributionHasher.update(buffUv); + return P; + } + async function processSection(idSection, groupName, sectionName, nPoints, singularPointIndexes, logger) { + const MAX_CHUNK_SIZE = 65536; + const G = curve[groupName]; + const sG = G.F.n8 * 2; + await _iden3_binfileutils.startReadUniqueSection(fd, sections, idSection); + const singularPoints = []; + let R1 = G.zero; + let R2 = G.zero; + let lastBase = G.zero; + for (let i = 0; i < nPoints; i += MAX_CHUNK_SIZE) { + if (logger) logger.debug(`points relations: ${sectionName}: ${i}/${nPoints} `); + const n = Math.min(nPoints - i, MAX_CHUNK_SIZE); + const bases = await fd.read(n * sG); + const basesU = await G.batchLEMtoU(bases); + nextContributionHasher.update(basesU); + const scalars = getRandomBytes(4 * (n - 1)); + if (i > 0) { + const firstBase = G.fromRprLEM(bases, 0); + const r = readUInt32BE(getRandomBytes(4), 0); + R1 = G.add(R1, G.timesScalar(lastBase, r)); + R2 = G.add(R2, G.timesScalar(firstBase, r)); + } + const r1 = await G.multiExpAffine(bases.slice(0, (n - 1) * sG), scalars); + const r2 = await G.multiExpAffine(bases.slice(sG), scalars); + R1 = G.add(R1, r1); + R2 = G.add(R2, r2); + lastBase = G.fromRprLEM(bases, (n - 1) * sG); + for (let j = 0; j < singularPointIndexes.length; j++) { + const sp = singularPointIndexes[j]; + if (sp >= i && sp < i + n) { + const P = G.fromRprLEM(bases, (sp - i) * sG); + singularPoints.push(P); + } + } + } + await _iden3_binfileutils.endReadSection(fd); + return { + R1, + R2, + singularPoints + }; + } + async function verifyLagrangeEvaluations(gName, tauSection, lagrangeSection, sectionName, logger) { + if (logger) logger.debug(`Verifying phase2 calculated values ${sectionName}...`); + const G = curve[gName]; + const sG = G.F.n8 * 2; + const seed = new Array(8); + for (let i = 0; i < 8; i++) seed[i] = readUInt32BE(getRandomBytes(4), 0); + for (let p = 0; p <= power; p++) if (!await verifyPower(p)) return false; + if (tauSection == 2) { + if (!await verifyPower(power + 1)) return false; + } + return true; + async function verifyPower(p) { + if (logger) logger.debug(`Power ${p}...`); + const n8r = curve.Fr.n8; + const nPoints = 2 ** p; + let buff_r = new Uint32Array(nPoints); + let buffG; + let rng = new ffjavascript.ChaCha(seed); + if (logger) logger.debug(`Creating random numbers Powers${p}...`); + for (let i = 0; i < nPoints; i++) if (p == power + 1 && i == nPoints - 1) buff_r[i] = 0; + else buff_r[i] = rng.nextU32(); + buff_r = new Uint8Array(buff_r.buffer, buff_r.byteOffset, buff_r.byteLength); + if (logger) logger.debug(`reading points Powers${p}...`); + await _iden3_binfileutils.startReadUniqueSection(fd, sections, tauSection); + buffG = new ffjavascript.BigBuffer(nPoints * sG); + if (p == power + 1) { + await fd.readToBuffer(buffG, 0, (nPoints - 1) * sG); + buffG.set(curve.G1.zeroAffine, (nPoints - 1) * sG); + } else await fd.readToBuffer(buffG, 0, nPoints * sG); + await _iden3_binfileutils.endReadSection(fd, true); + const resTau = await G.multiExpAffine(buffG, buff_r, logger, sectionName + "_" + p); + buff_r = new ffjavascript.BigBuffer(nPoints * n8r); + rng = new ffjavascript.ChaCha(seed); + const buff4 = new Uint8Array(4); + const buff4V = new DataView(buff4.buffer); + if (logger) logger.debug(`Creating random numbers Powers${p}...`); + for (let i = 0; i < nPoints; i++) if (i != nPoints - 1 || p != power + 1) { + buff4V.setUint32(0, rng.nextU32(), true); + buff_r.set(buff4, i * n8r); + } + if (logger) logger.debug(`batchToMontgomery ${p}...`); + buff_r = await curve.Fr.batchToMontgomery(buff_r); + if (logger) logger.debug(`fft ${p}...`); + buff_r = await curve.Fr.fft(buff_r); + if (logger) logger.debug(`batchFromMontgomery ${p}...`); + buff_r = await curve.Fr.batchFromMontgomery(buff_r); + if (logger) logger.debug(`reading points Lagrange${p}...`); + await _iden3_binfileutils.startReadUniqueSection(fd, sections, lagrangeSection); + fd.pos += sG * (2 ** p - 1); + await fd.readToBuffer(buffG, 0, nPoints * sG); + await _iden3_binfileutils.endReadSection(fd, true); + const resLagrange = await G.multiExpAffine(buffG, buff_r, logger, sectionName + "_" + p + "_transformed"); + if (!G.eq(resTau, resLagrange)) { + if (logger) logger.error("Phase2 caclutation does not match with powers of tau"); + return false; + } + return true; + } + } + } + //#endregion + //#region src/mpc_applykey.js + async function applyKeyToSection(fdOld, sections, fdNew, idSection, curve, groupName, first, inc, sectionName, logger) { + const MAX_CHUNK_SIZE = 65536; + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const nPoints = sections[idSection][0].size / sG; + await _iden3_binfileutils.startReadUniqueSection(fdOld, sections, idSection); + await _iden3_binfileutils.startWriteSection(fdNew, idSection); + let t = first; + for (let i = 0; i < nPoints; i += MAX_CHUNK_SIZE) { + if (logger) logger.debug(`Applying key: ${sectionName}: ${i}/${nPoints}`); + const n = Math.min(nPoints - i, MAX_CHUNK_SIZE); + let buff; + buff = await fdOld.read(n * sG); + buff = await G.batchApplyKey(buff, t, inc); + await fdNew.write(buff); + t = curve.Fr.mul(t, curve.Fr.exp(inc, n)); + } + await _iden3_binfileutils.endWriteSection(fdNew); + await _iden3_binfileutils.endReadSection(fdOld); + } + async function applyKeyToChallengeSection(fdOld, fdNew, responseHasher, curve, groupName, nPoints, first, inc, formatOut, sectionName, logger) { + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const chunkSize = Math.floor((1 << 20) / sG); + let t = first; + for (let i = 0; i < nPoints; i += chunkSize) { + if (logger) logger.debug(`Applying key ${sectionName}: ${i}/${nPoints}`); + const n = Math.min(nPoints - i, chunkSize); + const buffInU = await fdOld.read(n * sG); + const buffInLEM = await G.batchUtoLEM(buffInU); + const buffOutLEM = await G.batchApplyKey(buffInLEM, t, inc); + let buffOut; + if (formatOut == "COMPRESSED") buffOut = await G.batchLEMtoC(buffOutLEM); + else buffOut = await G.batchLEMtoU(buffOutLEM); + if (responseHasher) responseHasher.update(buffOut); + await fdNew.write(buffOut); + t = curve.Fr.mul(t, curve.Fr.exp(inc, n)); + } + } + //#endregion + //#region src/powersoftau_challenge_contribute.js + async function challengeContribute(curve, challengeFilename, responseFileName, entropy, logger) { + const fdFrom = await w(challengeFilename); + const sG1 = curve.F1.n64 * 8 * 2; + const sG2 = curve.F2.n64 * 8 * 2; + const domainSize = (fdFrom.totalSize + sG1 - 64 - sG2) / (4 * sG1 + sG2); + let e = domainSize; + let power = 0; + while (e > 1) { + e = e / 2; + power += 1; + } + if (2 ** power != domainSize) throw new Error("Invalid file size"); + if (logger) logger.debug("Power to tau size: " + power); + const rng = await getRandomRng(entropy); + const fdTo = await S(responseFileName); + const challengeHasher = blake2b.create({ dkLen: 64 }); + for (let i = 0; i < fdFrom.totalSize; i += fdFrom.pageSize) { + if (logger) logger.debug(`Hashing challenge ${i}/${fdFrom.totalSize}`); + const s = Math.min(fdFrom.totalSize - i, fdFrom.pageSize); + const buff = await fdFrom.read(s); + challengeHasher.update(buff); + } + const claimedHash = await fdFrom.read(64, 0); + if (logger) logger.info(formatHash(claimedHash, "Claimed Previous Response Hash: ")); + const challengeHash = challengeHasher.digest(); + if (logger) logger.info(formatHash(challengeHash, "Current Challenge Hash: ")); + const key = createPTauKey(curve, challengeHash, rng); + if (logger) [ + "tau", + "alpha", + "beta" + ].forEach((k) => { + logger.debug(k + ".g1_s: " + curve.G1.toString(key[k].g1_s, 16)); + logger.debug(k + ".g1_sx: " + curve.G1.toString(key[k].g1_sx, 16)); + logger.debug(k + ".g2_sp: " + curve.G2.toString(key[k].g2_sp, 16)); + logger.debug(k + ".g2_spx: " + curve.G2.toString(key[k].g2_spx, 16)); + logger.debug(""); + }); + const responseHasher = blake2b.create({ dkLen: 64 }); + await fdTo.write(challengeHash); + responseHasher.update(challengeHash); + await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", 2 ** power * 2 - 1, curve.Fr.one, key.tau.prvKey, "COMPRESSED", "tauG1", logger); + await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G2", 2 ** power, curve.Fr.one, key.tau.prvKey, "COMPRESSED", "tauG2", logger); + await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", 2 ** power, key.alpha.prvKey, key.tau.prvKey, "COMPRESSED", "alphaTauG1", logger); + await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", 2 ** power, key.beta.prvKey, key.tau.prvKey, "COMPRESSED", "betaTauG1", logger); + await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G2", 1, key.beta.prvKey, key.tau.prvKey, "COMPRESSED", "betaTauG2", logger); + const buffKey = new Uint8Array(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3); + toPtauPubKeyRpr(buffKey, 0, curve, key, false); + await fdTo.write(buffKey); + responseHasher.update(buffKey); + const responseHash = responseHasher.digest(); + if (logger) logger.info(formatHash(responseHash, "Contribution Response Hash: ")); + await fdTo.close(); + await fdFrom.close(); + } + //#endregion + //#region src/powersoftau_beacon.js + async function beacon$1(oldPtauFilename, newPTauFilename, name, beaconHashStr, numIterationsExp, logger) { + const beaconHash = hex2ByteArray(beaconHashStr); + if (beaconHash.byteLength == 0 || beaconHash.byteLength * 2 != beaconHashStr.length) { + if (logger) logger.error("Invalid Beacon Hash. (It must be a valid hexadecimal sequence)"); + return false; + } + if (beaconHash.length >= 256) { + if (logger) logger.error("Maximum length of beacon hash is 255 bytes"); + return false; + } + numIterationsExp = parseInt(numIterationsExp); + if (numIterationsExp < 10 || numIterationsExp > 63) { + if (logger) logger.error("Invalid numIterationsExp. (Must be between 10 and 63)"); + return false; + } + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(oldPtauFilename, "ptau", 1); + const { curve, power, ceremonyPower } = await readPTauHeader(fdOld, sections); + if (power != ceremonyPower) { + if (logger) logger.error("This file has been reduced. You cannot contribute into a reduced file."); + return false; + } + if (sections[12]) { + if (logger) logger.warn("Contributing into a file that has phase2 calculated. You will have to prepare phase2 again."); + } + const contributions = await readContributions(fdOld, curve, sections); + const curContribution = { + name, + type: 1, + numIterationsExp, + beaconHash + }; + let lastChallengeHash; + if (contributions.length > 0) lastChallengeHash = contributions[contributions.length - 1].nextChallenge; + else lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); + curContribution.key = await keyFromBeacon(curve, lastChallengeHash, beaconHash, numIterationsExp); + const responseHasher = blake2b.create({ dkLen: 64 }); + responseHasher.update(lastChallengeHash); + const fdNew = await _iden3_binfileutils.createBinFile(newPTauFilename, "ptau", 1, 7); + await writePTauHeader(fdNew, curve, power); + const startSections = []; + let firstPoints; + firstPoints = await processSection(2, "G1", 2 ** power * 2 - 1, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG1", logger); + curContribution.tauG1 = firstPoints[1]; + firstPoints = await processSection(3, "G2", 2 ** power, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG2", logger); + curContribution.tauG2 = firstPoints[1]; + firstPoints = await processSection(4, "G1", 2 ** power, curContribution.key.alpha.prvKey, curContribution.key.tau.prvKey, "alphaTauG1", logger); + curContribution.alphaG1 = firstPoints[0]; + firstPoints = await processSection(5, "G1", 2 ** power, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG1", logger); + curContribution.betaG1 = firstPoints[0]; + firstPoints = await processSection(6, "G2", 1, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG2", logger); + curContribution.betaG2 = firstPoints[0]; + curContribution.partialHash = toPartialHash(responseHasher); + const buffKey = new Uint8Array(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3); + toPtauPubKeyRpr(buffKey, 0, curve, curContribution.key, false); + responseHasher.update(new Uint8Array(buffKey)); + const hashResponse = responseHasher.digest(); + if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); + const nextChallengeHasher = blake2b.create({ dkLen: 64 }); + nextChallengeHasher.update(hashResponse); + await hashSection(fdNew, "G1", 2, 2 ** power * 2 - 1, "tauG1", logger); + await hashSection(fdNew, "G2", 3, 2 ** power, "tauG2", logger); + await hashSection(fdNew, "G1", 4, 2 ** power, "alphaTauG1", logger); + await hashSection(fdNew, "G1", 5, 2 ** power, "betaTauG1", logger); + await hashSection(fdNew, "G2", 6, 1, "betaG2", logger); + curContribution.nextChallenge = nextChallengeHasher.digest(); + if (logger) logger.info(formatHash(curContribution.nextChallenge, "Next Challenge Hash: ")); + contributions.push(curContribution); + await writeContributions(fdNew, curve, contributions); + await fdOld.close(); + await fdNew.close(); + return hashResponse; + async function processSection(sectionId, groupName, NPoints, first, inc, sectionName, logger) { + const res = []; + fdOld.pos = sections[sectionId][0].p; + await _iden3_binfileutils.startWriteSection(fdNew, sectionId); + startSections[sectionId] = fdNew.pos; + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const chunkSize = Math.floor((1 << 20) / sG); + let t = first; + for (let i = 0; i < NPoints; i += chunkSize) { + if (logger) logger.debug(`applying key${sectionName}: ${i}/${NPoints}`); + const n = Math.min(NPoints - i, chunkSize); + const buffIn = await fdOld.read(n * sG); + const buffOutLEM = await G.batchApplyKey(buffIn, t, inc); + const promiseWrite = fdNew.write(buffOutLEM); + const buffOutC = await G.batchLEMtoC(buffOutLEM); + responseHasher.update(buffOutC); + await promiseWrite; + if (i == 0) for (let j = 0; j < Math.min(2, NPoints); j++) res.push(G.fromRprLEM(buffOutLEM, j * sG)); + t = curve.Fr.mul(t, curve.Fr.exp(inc, n)); + } + await _iden3_binfileutils.endWriteSection(fdNew); + return res; + } + async function hashSection(fdTo, groupName, sectionId, nPoints, sectionName, logger) { + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const nPointsChunk = Math.floor((1 << 24) / sG); + const oldPos = fdTo.pos; + fdTo.pos = startSections[sectionId]; + for (let i = 0; i < nPoints; i += nPointsChunk) { + if (logger) logger.debug(`Hashing ${sectionName}: ${i}/${nPoints}`); + const n = Math.min(nPoints - i, nPointsChunk); + const buffLEM = await fdTo.read(n * sG); + const buffU = await G.batchLEMtoU(buffLEM); + nextChallengeHasher.update(buffU); + } + fdTo.pos = oldPos; + } + } + //#endregion + //#region src/powersoftau_contribute.js + async function contribute(oldPtauFilename, newPTauFilename, name, entropy, logger) { + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(oldPtauFilename, "ptau", 1); + const { curve, power, ceremonyPower } = await readPTauHeader(fdOld, sections); + if (power != ceremonyPower) { + if (logger) logger.error("This file has been reduced. You cannot contribute into a reduced file."); + throw new Error("This file has been reduced. You cannot contribute into a reduced file."); + } + if (sections[12]) { + if (logger) logger.warn("WARNING: Contributing into a file that has phase2 calculated. You will have to prepare phase2 again."); + } + const contributions = await readContributions(fdOld, curve, sections); + const curContribution = { + name, + type: 0 + }; + let lastChallengeHash; + const rng = await getRandomRng(entropy); + if (contributions.length > 0) lastChallengeHash = contributions[contributions.length - 1].nextChallenge; + else lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); + curContribution.key = createPTauKey(curve, lastChallengeHash, rng); + const responseHasher = blake2b.create({ dkLen: 64 }); + responseHasher.update(lastChallengeHash); + const fdNew = await _iden3_binfileutils.createBinFile(newPTauFilename, "ptau", 1, 7); + await writePTauHeader(fdNew, curve, power); + const startSections = []; + let firstPoints; + firstPoints = await processSection(2, "G1", 2 ** power * 2 - 1, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG1"); + curContribution.tauG1 = firstPoints[1]; + firstPoints = await processSection(3, "G2", 2 ** power, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG2"); + curContribution.tauG2 = firstPoints[1]; + firstPoints = await processSection(4, "G1", 2 ** power, curContribution.key.alpha.prvKey, curContribution.key.tau.prvKey, "alphaTauG1"); + curContribution.alphaG1 = firstPoints[0]; + firstPoints = await processSection(5, "G1", 2 ** power, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG1"); + curContribution.betaG1 = firstPoints[0]; + firstPoints = await processSection(6, "G2", 1, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG2"); + curContribution.betaG2 = firstPoints[0]; + curContribution.partialHash = toPartialHash(responseHasher); + const buffKey = new Uint8Array(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3); + toPtauPubKeyRpr(buffKey, 0, curve, curContribution.key, false); + responseHasher.update(new Uint8Array(buffKey)); + const hashResponse = responseHasher.digest(); + if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); + const nextChallengeHasher = blake2b.create({ dkLen: 64 }); + nextChallengeHasher.update(hashResponse); + await hashSection(fdNew, "G1", 2, 2 ** power * 2 - 1, "tauG1"); + await hashSection(fdNew, "G2", 3, 2 ** power, "tauG2"); + await hashSection(fdNew, "G1", 4, 2 ** power, "alphaTauG1"); + await hashSection(fdNew, "G1", 5, 2 ** power, "betaTauG1"); + await hashSection(fdNew, "G2", 6, 1, "betaG2"); + curContribution.nextChallenge = nextChallengeHasher.digest(); + if (logger) logger.info(formatHash(curContribution.nextChallenge, "Next Challenge Hash: ")); + contributions.push(curContribution); + await writeContributions(fdNew, curve, contributions); + await fdOld.close(); + await fdNew.close(); + return hashResponse; + async function processSection(sectionId, groupName, NPoints, first, inc, sectionName) { + const res = []; + fdOld.pos = sections[sectionId][0].p; + await _iden3_binfileutils.startWriteSection(fdNew, sectionId); + startSections[sectionId] = fdNew.pos; + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const chunkSize = Math.floor((1 << 20) / sG); + let t = first; + for (let i = 0; i < NPoints; i += chunkSize) { + if (logger) logger.debug(`processing: ${sectionName}: ${i}/${NPoints}`); + const n = Math.min(NPoints - i, chunkSize); + const buffIn = await fdOld.read(n * sG); + const buffOutLEM = await G.batchApplyKey(buffIn, t, inc); + const promiseWrite = fdNew.write(buffOutLEM); + const buffOutC = await G.batchLEMtoC(buffOutLEM); + responseHasher.update(buffOutC); + await promiseWrite; + if (i == 0) for (let j = 0; j < Math.min(2, NPoints); j++) res.push(G.fromRprLEM(buffOutLEM, j * sG)); + t = curve.Fr.mul(t, curve.Fr.exp(inc, n)); + } + await _iden3_binfileutils.endWriteSection(fdNew); + return res; + } + async function hashSection(fdTo, groupName, sectionId, nPoints, sectionName) { + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const nPointsChunk = Math.floor((1 << 24) / sG); + const oldPos = fdTo.pos; + fdTo.pos = startSections[sectionId]; + for (let i = 0; i < nPoints; i += nPointsChunk) { + if (logger && i) logger.debug(`Hashing ${sectionName}: ` + i); + const n = Math.min(nPoints - i, nPointsChunk); + const buffLEM = await fdTo.read(n * sG); + const buffU = await G.batchLEMtoU(buffLEM); + nextChallengeHasher.update(buffU); + } + fdTo.pos = oldPos; + } + } + //#endregion + //#region src/powersoftau_preparephase2.js + async function preparePhase2(oldPtauFilename, newPTauFilename, logger) { + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(oldPtauFilename, "ptau", 1); + const { curve, power } = await readPTauHeader(fdOld, sections); + const fdNew = await _iden3_binfileutils.createBinFile(newPTauFilename, "ptau", 1, 11); + await writePTauHeader(fdNew, curve, power); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 2); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 3); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 4); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 5); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 6); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 7); + await processSection(2, 12, "G1", "tauG1"); + await processSection(3, 13, "G2", "tauG2"); + await processSection(4, 14, "G1", "alphaTauG1"); + await processSection(5, 15, "G1", "betaTauG1"); + await fdOld.close(); + await fdNew.close(); + return; + async function processSection(oldSectionId, newSectionId, Gstr, sectionName) { + if (logger) logger.debug("Starting section: " + sectionName); + await _iden3_binfileutils.startWriteSection(fdNew, newSectionId); + for (let p = 0; p <= power; p++) await processSectionPower(p); + if (oldSectionId == 2) await processSectionPower(power + 1); + await _iden3_binfileutils.endWriteSection(fdNew); + async function processSectionPower(p) { + const nPoints = 2 ** p; + const G = curve[Gstr]; + const sGin = G.F.n8 * 2; + let buff; + buff = new ffjavascript.BigBuffer(nPoints * sGin); + await _iden3_binfileutils.startReadUniqueSection(fdOld, sections, oldSectionId); + if (oldSectionId == 2 && p == power + 1) { + await fdOld.readToBuffer(buff, 0, (nPoints - 1) * sGin); + buff.set(curve.G1.zeroAffine, (nPoints - 1) * sGin); + } else await fdOld.readToBuffer(buff, 0, nPoints * sGin); + await _iden3_binfileutils.endReadSection(fdOld, true); + buff = await G.lagrangeEvaluations(buff, "affine", "affine", logger, sectionName); + await fdNew.write(buff); + } + } + } + //#endregion + //#region src/powersoftau_truncate.js + async function truncate(ptauFilename, template, logger) { + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(ptauFilename, "ptau", 1); + const { curve, power, ceremonyPower } = await readPTauHeader(fdOld, sections); + const sG1 = curve.G1.F.n8 * 2; + const sG2 = curve.G2.F.n8 * 2; + for (let p = 1; p < power; p++) await generateTruncate(p); + await fdOld.close(); + return true; + async function generateTruncate(p) { + let sP = p.toString(); + while (sP.length < 2) sP = "0" + sP; + if (logger) logger.debug("Writing Power: " + sP); + const fdNew = await _iden3_binfileutils.createBinFile(template + sP + ".ptau", "ptau", 1, 11); + await writePTauHeader(fdNew, curve, p, ceremonyPower); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 2, (2 ** p * 2 - 1) * sG1); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 3, 2 ** p * sG2); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 4, 2 ** p * sG1); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 5, 2 ** p * sG1); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 6, sG2); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 7); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 12, (2 ** (p + 1) * 2 - 1) * sG1); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 13, (2 ** p * 2 - 1) * sG2); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 14, (2 ** p * 2 - 1) * sG1); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 15, (2 ** p * 2 - 1) * sG1); + await fdNew.close(); + } + } + //#endregion + //#region src/powersoftau_convert.js + async function convert(oldPtauFilename, newPTauFilename, logger) { + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(oldPtauFilename, "ptau", 1); + const { curve, power } = await readPTauHeader(fdOld, sections); + const fdNew = await _iden3_binfileutils.createBinFile(newPTauFilename, "ptau", 1, 11); + await writePTauHeader(fdNew, curve, power); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 2); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 3); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 4); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 5); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 6); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 7); + await processSection(2, 12, "G1", "tauG1"); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 13); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 14); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 15); + await fdOld.close(); + await fdNew.close(); + return; + async function processSection(oldSectionId, newSectionId, Gstr, sectionName) { + if (logger) logger.debug("Starting section: " + sectionName); + await _iden3_binfileutils.startWriteSection(fdNew, newSectionId); + const size = sections[newSectionId][0].size; + const chunkSize = fdOld.pageSize; + await _iden3_binfileutils.startReadUniqueSection(fdOld, sections, newSectionId); + for (let p = 0; p < size; p += chunkSize) { + const l = Math.min(size - p, chunkSize); + const buff = await fdOld.read(l); + await fdNew.write(buff); + } + await _iden3_binfileutils.endReadSection(fdOld); + if (oldSectionId == 2) await processSectionPower(power + 1); + await _iden3_binfileutils.endWriteSection(fdNew); + async function processSectionPower(p) { + const nPoints = 2 ** p; + const G = curve[Gstr]; + const sGin = G.F.n8 * 2; + let buff; + buff = new ffjavascript.BigBuffer(nPoints * sGin); + await _iden3_binfileutils.startReadUniqueSection(fdOld, sections, oldSectionId); + if (oldSectionId == 2 && p == power + 1) { + await fdOld.readToBuffer(buff, 0, (nPoints - 1) * sGin); + buff.set(curve.G1.zeroAffine, (nPoints - 1) * sGin); + } else await fdOld.readToBuffer(buff, 0, nPoints * sGin); + await _iden3_binfileutils.endReadSection(fdOld, true); + buff = await G.lagrangeEvaluations(buff, "affine", "affine", logger, sectionName); + await fdNew.write(buff); + } + } + } + //#endregion + //#region src/powersoftau_export_json.js + async function exportJson(pTauFilename, verbose) { + const { fd, sections } = await _iden3_binfileutils.readBinFile(pTauFilename, "ptau", 1); + const { curve, power } = await readPTauHeader(fd, sections); + const pTau = {}; + pTau.q = curve.q; + pTau.power = power; + pTau.contributions = await readContributions(fd, curve, sections); + pTau.tauG1 = await exportSection(2, "G1", 2 ** power * 2 - 1, "tauG1"); + pTau.tauG2 = await exportSection(3, "G2", 2 ** power, "tauG2"); + pTau.alphaTauG1 = await exportSection(4, "G1", 2 ** power, "alphaTauG1"); + pTau.betaTauG1 = await exportSection(5, "G1", 2 ** power, "betaTauG1"); + pTau.betaG2 = await exportSection(6, "G2", 1, "betaG2"); + pTau.lTauG1 = await exportLagrange(12, "G1", "lTauG1"); + pTau.lTauG2 = await exportLagrange(13, "G2", "lTauG2"); + pTau.lAlphaTauG1 = await exportLagrange(14, "G1", "lAlphaTauG2"); + pTau.lBetaTauG1 = await exportLagrange(15, "G1", "lBetaTauG2"); + await fd.close(); + return stringifyBigIntsWithField(curve.Fr, pTau); + async function exportSection(sectionId, groupName, nPoints, sectionName) { + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const res = []; + await _iden3_binfileutils.startReadUniqueSection(fd, sections, sectionId); + for (let i = 0; i < nPoints; i++) { + if (verbose && i && i % 1e4 == 0) console.log(`${sectionName}: ` + i); + const buff = await fd.read(sG); + res.push(G.fromRprLEM(buff, 0)); + } + await _iden3_binfileutils.endReadSection(fd); + return res; + } + async function exportLagrange(sectionId, groupName, sectionName) { + const G = curve[groupName]; + const sG = G.F.n8 * 2; + const res = []; + await _iden3_binfileutils.startReadUniqueSection(fd, sections, sectionId); + for (let p = 0; p <= power; p++) { + if (verbose) console.log(`${sectionName}: Power: ${p}`); + res[p] = []; + const nPoints = 2 ** p; + for (let i = 0; i < nPoints; i++) { + if (verbose && i && i % 1e4 == 0) console.log(`${sectionName}: ${i}/${nPoints}`); + const buff = await fd.read(sG); + res[p].push(G.fromRprLEM(buff, 0)); + } + } + await _iden3_binfileutils.endReadSection(fd, true); + return res; + } + } + //#endregion + //#region src/powersoftau.js + var powersoftau_exports = /* @__PURE__ */ __exportAll({ + beacon: () => beacon$1, + challengeContribute: () => challengeContribute, + contribute: () => contribute, + convert: () => convert, + exportChallenge: () => exportChallenge, + exportJson: () => exportJson, + importResponse: () => importResponse, + newAccumulator: () => newAccumulator, + preparePhase2: () => preparePhase2, + truncate: () => truncate, + verify: () => verify + }); + //#endregion + //#region src/r1cs_print.js + function r1csPrint(r1cs, syms, logger) { + for (let i = 0; i < r1cs.constraints.length; i++) printCostraint(r1cs.constraints[i]); + function printCostraint(c) { + const lc2str = (lc) => { + let S = ""; + Object.keys(lc).forEach((k) => { + let name = syms.varIdx2Name[k]; + if (name == "one") name = "1"; + let vs = r1cs.curve.Fr.toString(lc[k]); + if (vs == "1") vs = ""; + if (vs == "-1") vs = "-"; + if (S != "" && vs[0] != "-") vs = "+" + vs; + if (S != "") vs = " " + vs; + S = S + vs + name; + }); + return S; + }; + const S = `[ ${lc2str(c[0])} ] * [ ${lc2str(c[1])} ] - [ ${lc2str(c[2])} ] = 0`; + if (logger) logger.info(S); + } + } + //#endregion + //#region src/r1cs_info.js + var bls12381r = ffjavascript.Scalar.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16); + var bn128r = ffjavascript.Scalar.e("21888242871839275222246405745257275088548364400416034343698204186575808495617"); + async function r1csInfo(r1csName, logger) { + const cir = await (0, r1csfile.readR1cs)(r1csName); + if (ffjavascript.Scalar.eq(cir.prime, bn128r)) { + if (logger) logger.info("Curve: bn-128"); + } else if (ffjavascript.Scalar.eq(cir.prime, bls12381r)) { + if (logger) logger.info("Curve: bls12-381"); + } else if (logger) logger.info(`Unknown Curve. Prime: ${ffjavascript.Scalar.toString(cir.prime)}`); + if (logger) logger.info(`# of Wires: ${cir.nVars}`); + if (logger) logger.info(`# of Constraints: ${cir.nConstraints}`); + if (logger) logger.info(`# of Private Inputs: ${cir.nPrvInputs}`); + if (logger) logger.info(`# of Public Inputs: ${cir.nPubInputs}`); + if (logger) logger.info(`# of Labels: ${cir.nLabels}`); + if (logger) logger.info(`# of Outputs: ${cir.nOutputs}`); + return cir; + } + //#endregion + //#region src/r1cs_export_json.js + async function r1csExportJson(r1csFileName, logger) { + const cir = await (0, r1csfile.readR1cs)(r1csFileName, true, true, true, logger); + const Fr = cir.curve.Fr; + delete cir.curve; + delete cir.F; + return stringifyBigIntsWithField(Fr, cir); + } + //#endregion + //#region src/r1cs.js + var r1cs_exports = /* @__PURE__ */ __exportAll({ + exportJson: () => r1csExportJson, + info: () => r1csInfo, + print: () => r1csPrint + }); + //#endregion + //#region src/loadsyms.js + async function loadSymbols(symFileName) { + const sym = { + labelIdx2Name: ["one"], + varIdx2Name: ["one"], + componentIdx2Name: [] + }; + const fd = await w(symFileName); + const buff = await fd.read(fd.totalSize); + const lines = new TextDecoder("utf-8").decode(buff).split("\n"); + for (let i = 0; i < lines.length; i++) { + const arr = lines[i].split(","); + if (arr.length != 4) continue; + if (sym.varIdx2Name[arr[1]]) sym.varIdx2Name[arr[1]] += "|" + arr[3]; + else sym.varIdx2Name[arr[1]] = arr[3]; + sym.labelIdx2Name[arr[0]] = arr[3]; + if (!sym.componentIdx2Name[arr[2]]) sym.componentIdx2Name[arr[2]] = extractComponent(arr[3]); + } + await fd.close(); + return sym; + function extractComponent(name) { + const arr = name.split("."); + arr.pop(); + return arr.join("."); + } + } + //#endregion + //#region src/wtns_debug.js + var { unstringifyBigInts: unstringifyBigInts$6 } = ffjavascript.utils; + async function wtnsDebug(_input, wasmFileName, wtnsFileName, symName, options, logger) { + const input = unstringifyBigInts$6(_input); + const fdWasm = await w(wasmFileName); + const wasm = await fdWasm.read(fdWasm.totalSize); + await fdWasm.close(); + const wcOps = { + ...options, + sanityCheck: true + }; + let sym = await loadSymbols(symName); + if (options.set) { + if (!sym) sym = await loadSymbols(symName); + wcOps.logSetSignal = function(labelIdx, value) { + if (logger) logger.info("SET " + sym.labelIdx2Name[labelIdx] + " <-- " + value.toString()); + }; + } + if (options.get) { + if (!sym) sym = await loadSymbols(symName); + wcOps.logGetSignal = function(varIdx, value) { + if (logger) logger.info("GET " + sym.labelIdx2Name[varIdx] + " --> " + value.toString()); + }; + } + if (options.trigger) { + if (!sym) sym = await loadSymbols(symName); + wcOps.logStartComponent = function(cIdx) { + if (logger) logger.info("START: " + sym.componentIdx2Name[cIdx]); + }; + wcOps.logFinishComponent = function(cIdx) { + if (logger) logger.info("FINISH: " + sym.componentIdx2Name[cIdx]); + }; + } + wcOps.sym = sym; + const wc = await builder(wasm, wcOps); + const w$1 = await wc.calculateWitness(input, true); + const fdWtns = await _iden3_binfileutils.createBinFile(wtnsFileName, "wtns", 2, 2); + await write(fdWtns, w$1, wc.prime); + await fdWtns.close(); + } + //#endregion + //#region src/wtns_export_json.js + async function wtnsExportJson(wtnsFileName) { + return await read(wtnsFileName); + } + //#endregion + //#region src/wtns_check.js + async function wtnsCheck(r1csFilename, wtnsFilename, logger) { + if (logger) logger.info("WITNESS CHECKING STARTED"); + if (logger) logger.info("> Reading r1cs file"); + const { fd: fdR1cs, sections: sectionsR1cs } = await _iden3_binfileutils.readBinFile(r1csFilename, "r1cs", 1, 1 << 22, 1 << 24); + const r1cs = await (0, r1csfile.readR1csFd)(fdR1cs, sectionsR1cs, { + loadConstraints: false, + loadCustomGates: false + }); + if (logger) logger.info("> Reading witness file"); + const { fd: fdWtns, sections: wtnsSections } = await _iden3_binfileutils.readBinFile(wtnsFilename, "wtns", 2, 1 << 22, 1 << 24); + const wtnsHeader = await readHeader(fdWtns, wtnsSections); + if (!ffjavascript.Scalar.eq(r1cs.prime, wtnsHeader.q)) throw new Error("Curve of the witness does not match the curve of the proving key"); + const buffWitness = await _iden3_binfileutils.readSection(fdWtns, wtnsSections, 2); + await fdWtns.close(); + const Fr = (await getCurveFromR(r1cs.prime)).Fr; + const sFr = Fr.n8; + const bR1cs = await _iden3_binfileutils.readSection(fdR1cs, sectionsR1cs, 2); + if (logger) { + logger.info("----------------------------"); + logger.info(" WITNESS CHECK"); + logger.info(` Curve: ${r1cs.curve.name}`); + logger.info(` Vars (wires): ${r1cs.nVars}`); + logger.info(` Outputs: ${r1cs.nOutputs}`); + logger.info(` Public Inputs: ${r1cs.nPubInputs}`); + logger.info(` Private Inputs: ${r1cs.nPrvInputs}`); + logger.info(` Labels: ${r1cs.nLabels}`); + logger.info(` Constraints: ${r1cs.nConstraints}`); + logger.info(` Custom Gates: ${r1cs.useCustomGates}`); + logger.info("----------------------------"); + } + if (logger) logger.info("> Checking witness correctness"); + let bR1csPos = 0; + let res = true; + for (let i = 0; i < r1cs.nConstraints; i++) { + if (logger && i !== 0 && i % 5e5 === 0) logger.info(`··· processing r1cs constraints ${i}/${r1cs.nConstraints}`); + const lcA = readLC(); + const lcB = readLC(); + const lcC = readLC(); + const evalA = EvaluateLinearCombination(lcA); + const evalB = EvaluateLinearCombination(lcB); + const evalC = EvaluateLinearCombination(lcC); + if (!Fr.eq(Fr.sub(Fr.mul(evalA, evalB), evalC), Fr.zero)) { + logger.warn("··· aborting checking process at constraint " + i); + res = false; + break; + } + } + fdR1cs.close(); + if (logger) if (res) { + logger.info("WITNESS IS CORRECT"); + logger.info("WITNESS CHECKING FINISHED SUCCESSFULLY"); + } else { + logger.warn("WITNESS IS NOT CORRECT"); + logger.warn("WITNESS CHECKING FINISHED UNSUCCESSFULLY"); + } + return res; + function EvaluateLinearCombination(lc) { + let res = Fr.zero; + Object.keys(lc).forEach((signalId) => { + const signalValue = getWitnessValue(signalId); + const signalFactor = lc[signalId]; + res = Fr.add(res, Fr.mul(signalValue, signalFactor)); + }); + return res; + } + function readLC() { + const lc = {}; + const buffUL32 = bR1cs.slice(bR1csPos, bR1csPos + 4); + bR1csPos += 4; + const nIdx = new DataView(buffUL32.buffer).getUint32(0, true); + const buff = bR1cs.slice(bR1csPos, bR1csPos + (4 + r1cs.n8) * nIdx); + bR1csPos += (4 + r1cs.n8) * nIdx; + const buffV = new DataView(buff.buffer); + for (let i = 0; i < nIdx; i++) { + const idx = buffV.getUint32(i * (4 + r1cs.n8), true); + lc[idx] = r1cs.F.fromRprLE(buff, i * (4 + r1cs.n8) + 4); + } + return lc; + } + function getWitnessValue(signalId) { + return Fr.fromRprLE(buffWitness.slice(signalId * sFr, signalId * sFr + sFr)); + } + } + //#endregion + //#region src/wtns.js + var wtns_exports = /* @__PURE__ */ __exportAll({ + calculate: () => wtnsCalculate, + check: () => wtnsCheck, + debug: () => wtnsDebug, + exportJson: () => wtnsExportJson + }); + //#endregion + //#region src/bigarray.js + var SUBARRAY_SIZE = 262144; + var BigArrayHandler = { + get: function(obj, prop) { + if (!isNaN(prop)) return obj.getElement(prop); + else return obj[prop]; + }, + set: function(obj, prop, value) { + if (!isNaN(prop)) return obj.setElement(prop, value); + else { + obj[prop] = value; + return true; + } + } + }; + var _BigArray = class { + constructor(initSize) { + this.length = initSize || 0; + this.arr = new Array(SUBARRAY_SIZE); + for (let i = 0; i < initSize; i += SUBARRAY_SIZE) this.arr[i / SUBARRAY_SIZE] = new Array(Math.min(SUBARRAY_SIZE, initSize - i)); + return this; + } + push() { + for (let i = 0; i < arguments.length; i++) this.setElement(this.length, arguments[i]); + } + slice(f, t) { + const arr = new Array(t - f); + for (let i = f; i < t; i++) arr[i - f] = this.getElement(i); + return arr; + } + getElement(idx) { + idx = parseInt(idx); + const idx1 = Math.floor(idx / SUBARRAY_SIZE); + const idx2 = idx % SUBARRAY_SIZE; + return this.arr[idx1] ? this.arr[idx1][idx2] : void 0; + } + setElement(idx, value) { + idx = parseInt(idx); + const idx1 = Math.floor(idx / SUBARRAY_SIZE); + if (!this.arr[idx1]) this.arr[idx1] = new Array(SUBARRAY_SIZE); + const idx2 = idx % SUBARRAY_SIZE; + this.arr[idx1][idx2] = value; + if (idx >= this.length) this.length = idx + 1; + return true; + } + getKeys() { + const newA = new BigArray(); + for (let i = 0; i < this.arr.length; i++) if (this.arr[i]) { + for (let j = 0; j < this.arr[i].length; j++) if (typeof this.arr[i][j] !== "undefined") newA.push(i * SUBARRAY_SIZE + j); + } + return newA; + } + }; + var BigArray = class { + constructor(initSize) { + const obj = new _BigArray(initSize); + return new Proxy(obj, BigArrayHandler); + } + }; + //#endregion + //#region src/zkey_new.js + async function newZKey(r1csName, ptauName, zkeyName, logger) { + const TAU_G1 = 0; + const TAU_G2 = 1; + const ALPHATAU_G1 = 2; + const BETATAU_G1 = 3; + const csHasher = blake2b.create({ dkLen: 64 }); + const { fd: fdPTau, sections: sectionsPTau } = await (0, _iden3_binfileutils.readBinFile)(ptauName, "ptau", 1, 1 << 22, 1 << 24); + const { curve, power } = await readPTauHeader(fdPTau, sectionsPTau); + const { fd: fdR1cs, sections: sectionsR1cs } = await (0, _iden3_binfileutils.readBinFile)(r1csName, "r1cs", 1, 1 << 22, 1 << 24); + const r1cs = await (0, r1csfile.readR1csHeader)(fdR1cs, sectionsR1cs, false); + const fdZKey = await (0, _iden3_binfileutils.createBinFile)(zkeyName, "zkey", 1, 10, 1 << 22, 1 << 24); + const sG1 = curve.G1.F.n8 * 2; + const sG2 = curve.G2.F.n8 * 2; + if (r1cs.prime != curve.r) { + if (logger) logger.error("r1cs curve does not match powers of tau ceremony curve"); + return -1; + } + const cirPower = log2(r1cs.nConstraints + r1cs.nPubInputs + r1cs.nOutputs + 1 - 1) + 1; + if (cirPower > power) { + if (logger) logger.error(`circuit too big for this power of tau ceremony. ${r1cs.nConstraints}*2 > 2**${power}`); + return -1; + } + if (!sectionsPTau[12]) { + if (logger) logger.error("Powers of tau is not prepared."); + return -1; + } + const nPublic = r1cs.nOutputs + r1cs.nPubInputs; + const domainSize = 2 ** cirPower; + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 1); + await fdZKey.writeULE32(1); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 2); + const primeQ = curve.q; + const n8q = (Math.floor((ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) + 1) * 8; + const primeR = curve.r; + const n8r = (Math.floor((ffjavascript.Scalar.bitLength(primeR) - 1) / 64) + 1) * 8; + const Rr = ffjavascript.Scalar.mod(ffjavascript.Scalar.shl(1, n8r * 8), primeR); + const R2r = curve.Fr.e(ffjavascript.Scalar.mod(ffjavascript.Scalar.mul(Rr, Rr), primeR)); + await fdZKey.writeULE32(n8q); + await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeQ, n8q); + await fdZKey.writeULE32(n8r); + await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeR, n8r); + await fdZKey.writeULE32(r1cs.nVars); + await fdZKey.writeULE32(nPublic); + await fdZKey.writeULE32(domainSize); + let bAlpha1; + bAlpha1 = await fdPTau.read(sG1, sectionsPTau[4][0].p); + await fdZKey.write(bAlpha1); + bAlpha1 = await curve.G1.batchLEMtoU(bAlpha1); + csHasher.update(bAlpha1); + let bBeta1; + bBeta1 = await fdPTau.read(sG1, sectionsPTau[5][0].p); + await fdZKey.write(bBeta1); + bBeta1 = await curve.G1.batchLEMtoU(bBeta1); + csHasher.update(bBeta1); + let bBeta2; + bBeta2 = await fdPTau.read(sG2, sectionsPTau[6][0].p); + await fdZKey.write(bBeta2); + bBeta2 = await curve.G2.batchLEMtoU(bBeta2); + csHasher.update(bBeta2); + const bg1 = new Uint8Array(sG1); + curve.G1.toRprLEM(bg1, 0, curve.G1.g); + const bg2 = new Uint8Array(sG2); + curve.G2.toRprLEM(bg2, 0, curve.G2.g); + const bg1U = new Uint8Array(sG1); + curve.G1.toRprUncompressed(bg1U, 0, curve.G1.g); + const bg2U = new Uint8Array(sG2); + curve.G2.toRprUncompressed(bg2U, 0, curve.G2.g); + await fdZKey.write(bg2); + await fdZKey.write(bg1); + await fdZKey.write(bg2); + csHasher.update(bg2U); + csHasher.update(bg1U); + csHasher.update(bg2U); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + if (logger) logger.info(memUsage()); + if (logger) logger.info("Reading r1cs"); + let sR1cs = await (0, _iden3_binfileutils.readSection)(fdR1cs, sectionsR1cs, 2); + await fdR1cs.close(); + let A = new BigArray(r1cs.nVars); + let B1 = new BigArray(r1cs.nVars); + let B2 = new BigArray(r1cs.nVars); + let C = new BigArray(r1cs.nVars - nPublic - 1); + let IC = new Array(nPublic + 1); + if (logger) logger.info(memUsage()); + if (logger) logger.info("Reading tauG1"); + let sTauG1 = await (0, _iden3_binfileutils.readSection)(fdPTau, sectionsPTau, 12, (domainSize - 1) * sG1, domainSize * sG1); + if (logger) logger.info("Reading tauG2"); + let sTauG2 = await (0, _iden3_binfileutils.readSection)(fdPTau, sectionsPTau, 13, (domainSize - 1) * sG2, domainSize * sG2); + if (logger) logger.info("Reading alphatauG1"); + let sAlphaTauG1 = await (0, _iden3_binfileutils.readSection)(fdPTau, sectionsPTau, 14, (domainSize - 1) * sG1, domainSize * sG1); + if (logger) logger.info("Reading betatauG1"); + let sBetaTauG1 = await (0, _iden3_binfileutils.readSection)(fdPTau, sectionsPTau, 15, (domainSize - 1) * sG1, domainSize * sG1); + if (logger) logger.info(memUsage()); + if (logger) logger.info("processConstraints"); + await processConstraints(); + if (logger) logger.info(memUsage()); + if (logger) logger.info("composeAndWritePoints"); + await composeAndWritePoints(3, "G1", IC, "IC"); + IC = null; + if (logger) logger.info(memUsage()); + if (logger) logger.info("writeHs"); + await writeHs(); + if (logger) logger.info(memUsage()); + if (logger) logger.info("hashHPoints"); + await hashHPoints(); + if (logger) logger.info(memUsage()); + if (logger) logger.info("composeAndWritePoints 8 G1 C"); + await composeAndWritePoints(8, "G1", C, "C"); + C = null; + if (logger) logger.info(memUsage()); + if (logger) logger.info("composeAndWritePoints 5 G1 A"); + await composeAndWritePoints(5, "G1", A, "A"); + A = null; + if (logger) logger.info(memUsage()); + if (logger) logger.info("composeAndWritePoints 6 G1 B1"); + await composeAndWritePoints(6, "G1", B1, "B1"); + B1 = null; + if (logger) logger.info(memUsage()); + if (logger) logger.info("composeAndWritePoints 7 G2 B2"); + await composeAndWritePoints(7, "G2", B2, "B2"); + B2 = null; + if (logger) logger.info(memUsage()); + if (logger) logger.info("Contributions section"); + const csHash = csHasher.digest(); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 10); + await fdZKey.write(csHash); + await fdZKey.writeULE32(0); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + if (logger) logger.info(formatHash(csHash, "Circuit hash: ")); + await fdZKey.close(); + await fdPTau.close(); + return csHash; + async function writeHs() { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 9); + const buffOut = new ffjavascript.BigBuffer(domainSize * sG1); + if (cirPower < curve.Fr.s) { + let sTauG1 = await (0, _iden3_binfileutils.readSection)(fdPTau, sectionsPTau, 12, (domainSize * 2 - 1) * sG1, domainSize * 2 * sG1); + for (let i = 0; i < domainSize; i++) { + if (logger && i % 1e4 == 0) logger.debug(`splitting buffer: ${i}/${domainSize}`); + const buff = sTauG1.slice((i * 2 + 1) * sG1, (i * 2 + 1) * sG1 + sG1); + buffOut.set(buff, i * sG1); + } + } else if (cirPower == curve.Fr.s) { + const o = sectionsPTau[12][0].p + (2 ** (cirPower + 1) - 1) * sG1; + await fdPTau.readToBuffer(buffOut, 0, domainSize * sG1, o + domainSize * sG1); + } else { + if (logger) logger.error("Circuit too big"); + throw new Error("Circuit too big for this curve"); + } + await fdZKey.write(buffOut); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function processConstraints() { + const buffCoeff = new Uint8Array(12 + curve.Fr.n8); + const buffCoeffV = new DataView(buffCoeff.buffer); + const bOne = new Uint8Array(curve.Fr.n8); + curve.Fr.toRprLE(bOne, 0, curve.Fr.e(1)); + let r1csPos = 0; + function r1cs_readULE32() { + const buff = sR1cs.slice(r1csPos, r1csPos + 4); + r1csPos += 4; + return new DataView(buff.buffer).getUint32(0, true); + } + const coefs = new BigArray(); + for (let c = 0; c < r1cs.nConstraints; c++) { + if (logger && c % 1e4 == 0) logger.debug(`processing constraints: ${c}/${r1cs.nConstraints}`); + const nA = r1cs_readULE32(); + for (let i = 0; i < nA; i++) { + const s = r1cs_readULE32(); + const coefp = r1csPos; + r1csPos += curve.Fr.n8; + const l1t = TAU_G1; + const l1 = sG1 * c; + const l2t = BETATAU_G1; + const l2 = sG1 * c; + if (typeof A[s] === "undefined") A[s] = []; + A[s].push([ + l1t, + l1, + coefp + ]); + if (s <= nPublic) { + if (typeof IC[s] === "undefined") IC[s] = []; + IC[s].push([ + l2t, + l2, + coefp + ]); + } else { + if (typeof C[s - nPublic - 1] === "undefined") C[s - nPublic - 1] = []; + C[s - nPublic - 1].push([ + l2t, + l2, + coefp + ]); + } + coefs.push([ + 0, + c, + s, + coefp + ]); + } + const nB = r1cs_readULE32(); + for (let i = 0; i < nB; i++) { + const s = r1cs_readULE32(); + const coefp = r1csPos; + r1csPos += curve.Fr.n8; + const l1t = TAU_G1; + const l1 = sG1 * c; + const l2t = TAU_G2; + const l2 = sG2 * c; + const l3t = ALPHATAU_G1; + const l3 = sG1 * c; + if (typeof B1[s] === "undefined") B1[s] = []; + B1[s].push([ + l1t, + l1, + coefp + ]); + if (typeof B2[s] === "undefined") B2[s] = []; + B2[s].push([ + l2t, + l2, + coefp + ]); + if (s <= nPublic) { + if (typeof IC[s] === "undefined") IC[s] = []; + IC[s].push([ + l3t, + l3, + coefp + ]); + } else { + if (typeof C[s - nPublic - 1] === "undefined") C[s - nPublic - 1] = []; + C[s - nPublic - 1].push([ + l3t, + l3, + coefp + ]); + } + coefs.push([ + 1, + c, + s, + coefp + ]); + } + const nC = r1cs_readULE32(); + for (let i = 0; i < nC; i++) { + const s = r1cs_readULE32(); + const coefp = r1csPos; + r1csPos += curve.Fr.n8; + const l1t = TAU_G1; + const l1 = sG1 * c; + if (s <= nPublic) { + if (typeof IC[s] === "undefined") IC[s] = []; + IC[s].push([ + l1t, + l1, + coefp + ]); + } else { + if (typeof C[s - nPublic - 1] === "undefined") C[s - nPublic - 1] = []; + C[s - nPublic - 1].push([ + l1t, + l1, + coefp + ]); + } + } + } + for (let s = 0; s <= nPublic; s++) { + const l1t = TAU_G1; + const l1 = sG1 * (r1cs.nConstraints + s); + const l2t = BETATAU_G1; + const l2 = sG1 * (r1cs.nConstraints + s); + if (typeof A[s] === "undefined") A[s] = []; + A[s].push([ + l1t, + l1, + -1 + ]); + if (typeof IC[s] === "undefined") IC[s] = []; + IC[s].push([ + l2t, + l2, + -1 + ]); + coefs.push([ + 0, + r1cs.nConstraints + s, + s, + -1 + ]); + } + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 4); + const buffSection = new ffjavascript.BigBuffer(coefs.length * (12 + curve.Fr.n8) + 4); + const buff4 = new Uint8Array(4); + new DataView(buff4.buffer).setUint32(0, coefs.length, true); + buffSection.set(buff4); + let coefsPos = 4; + for (let i = 0; i < coefs.length; i++) { + if (logger && i % 1e5 == 0) logger.debug(`writing coeffs: ${i}/${coefs.length}`); + writeCoef(coefs[i]); + } + await fdZKey.write(buffSection); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + function writeCoef(c) { + buffCoeffV.setUint32(0, c[0], true); + buffCoeffV.setUint32(4, c[1], true); + buffCoeffV.setUint32(8, c[2], true); + let n; + if (c[3] >= 0) n = curve.Fr.fromRprLE(sR1cs.slice(c[3], c[3] + curve.Fr.n8), 0); + else n = curve.Fr.fromRprLE(bOne, 0); + const nR2 = curve.Fr.mul(n, R2r); + curve.Fr.toRprLE(buffCoeff, 12, nR2); + buffSection.set(buffCoeff, coefsPos); + coefsPos += buffCoeff.length; + } + } + async function composeAndWritePoints(idSection, groupName, arr, sectionName) { + const CHUNK_SIZE = 32768; + const G = curve[groupName]; + hashU32(arr.length); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, idSection); + let opPromises = []; + let i = 0; + while (i < arr.length) { + let t = 0; + while (i < arr.length && t < curve.tm.concurrency) { + if (logger) logger.debug(`Writing points start ${sectionName}: ${i}/${arr.length}`); + let n = 1; + let nP = arr[i] ? arr[i].length : 0; + while (i + n < arr.length && nP + (arr[i + n] ? arr[i + n].length : 0) < CHUNK_SIZE && n < CHUNK_SIZE) { + nP += arr[i + n] ? arr[i + n].length : 0; + n++; + } + if (logger) logger.info("before slice:"); + if (logger) logger.info(memUsage()); + const subArr = arr.slice(i, i + n); + if (logger) logger.info("after slice:"); + if (logger) logger.info(memUsage()); + const _i = i; + opPromises.push(composeAndWritePointsThread(groupName, subArr, logger, sectionName).then((r) => { + if (logger) logger.debug(`Writing points end ${sectionName}: ${_i}/${arr.length}`); + return r; + })); + i += n; + t++; + } + const result = await Promise.all(opPromises); + for (let k = 0; k < result.length; k++) { + await fdZKey.write(result[k][0]); + const buff = await G.batchLEMtoU(result[k][0]); + csHasher.update(buff); + } + opPromises = []; + } + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function composeAndWritePointsThread(groupName, arr, logger, sectionName) { + const G = curve[groupName]; + const sGin = G.F.n8 * 2; + const sGmid = G.F.n8 * 3; + const sGout = G.F.n8 * 2; + let fnExp, fnMultiExp, fnBatchToAffine, fnZero; + if (groupName == "G1") { + fnExp = "g1m_timesScalarAffine"; + fnMultiExp = "g1m_multiexpAffine"; + fnBatchToAffine = "g1m_batchToAffine"; + fnZero = "g1m_zero"; + } else if (groupName == "G2") { + fnExp = "g2m_timesScalarAffine"; + fnMultiExp = "g2m_multiexpAffine"; + fnBatchToAffine = "g2m_batchToAffine"; + fnZero = "g2m_zero"; + } else throw new Error("Invalid group"); + let acc = 0; + for (let i = 0; i < arr.length; i++) acc += arr[i] ? arr[i].length : 0; + let bBases, bScalars; + if (acc > 32768) { + bBases = new ffjavascript.BigBuffer(acc * sGin); + bScalars = new ffjavascript.BigBuffer(acc * curve.Fr.n8); + } else { + bBases = new Uint8Array(acc * sGin); + bScalars = new Uint8Array(acc * curve.Fr.n8); + } + let pB; + let pS; + const sBuffs = [ + sTauG1, + sTauG2, + sAlphaTauG1, + sBetaTauG1 + ]; + const bOne = new Uint8Array(curve.Fr.n8); + curve.Fr.toRprLE(bOne, 0, curve.Fr.e(1)); + let offset = 0; + for (let i = 0; i < arr.length; i++) { + if (!arr[i]) continue; + for (let j = 0; j < arr[i].length; j++) { + if (logger && j && j % 1e4 == 0) logger.debug(`Configuring big array ${sectionName}: ${j}/${arr[i].length}`); + bBases.set(sBuffs[arr[i][j][0]].slice(arr[i][j][1], arr[i][j][1] + sGin), offset * sGin); + if (arr[i][j][2] >= 0) bScalars.set(sR1cs.slice(arr[i][j][2], arr[i][j][2] + curve.Fr.n8), offset * curve.Fr.n8); + else bScalars.set(bOne, offset * curve.Fr.n8); + offset++; + } + } + if (arr.length > 1) { + const task = []; + task.push({ + cmd: "ALLOCSET", + var: 0, + buff: bBases + }); + task.push({ + cmd: "ALLOCSET", + var: 1, + buff: bScalars + }); + task.push({ + cmd: "ALLOC", + var: 2, + len: arr.length * sGmid + }); + pB = 0; + pS = 0; + let pD = 0; + for (let i = 0; i < arr.length; i++) { + if (!arr[i]) { + task.push({ + cmd: "CALL", + fnName: fnZero, + params: [{ + var: 2, + offset: pD + }] + }); + pD += sGmid; + continue; + } + if (arr[i].length == 1) task.push({ + cmd: "CALL", + fnName: fnExp, + params: [ + { + var: 0, + offset: pB + }, + { + var: 1, + offset: pS + }, + { val: curve.Fr.n8 }, + { + var: 2, + offset: pD + } + ] + }); + else task.push({ + cmd: "CALL", + fnName: fnMultiExp, + params: [ + { + var: 0, + offset: pB + }, + { + var: 1, + offset: pS + }, + { val: curve.Fr.n8 }, + { val: arr[i].length }, + { + var: 2, + offset: pD + } + ] + }); + pB += sGin * arr[i].length; + pS += curve.Fr.n8 * arr[i].length; + pD += sGmid; + } + task.push({ + cmd: "CALL", + fnName: fnBatchToAffine, + params: [ + { var: 2 }, + { val: arr.length }, + { var: 2 } + ] + }); + task.push({ + cmd: "GET", + out: 0, + var: 2, + len: arr.length * sGout + }); + return await curve.tm.queueAction(task); + } else { + let res = await G.multiExpAffine(bBases, bScalars, logger, sectionName); + res = [G.toAffine(res)]; + return res; + } + } + async function hashHPoints() { + const CHUNK_SIZE = 16384; + hashU32(domainSize - 1); + for (let i = 0; i < domainSize - 1; i += CHUNK_SIZE) { + if (logger) logger.debug(`HashingHPoints: ${i}/${domainSize}`); + const n = Math.min(domainSize - 1, CHUNK_SIZE); + await hashHPointsChunk(i, n); + } + } + async function hashHPointsChunk(offset, nPoints) { + const buff1 = await fdPTau.read(nPoints * sG1, sectionsPTau[2][0].p + (offset + domainSize) * sG1); + const buff2 = await fdPTau.read(nPoints * sG1, sectionsPTau[2][0].p + offset * sG1); + const concurrency = curve.tm.concurrency; + const nPointsPerThread = Math.floor(nPoints / concurrency); + const opPromises = []; + for (let i = 0; i < concurrency; i++) { + let n; + if (i < concurrency - 1) n = nPointsPerThread; + else n = nPoints - i * nPointsPerThread; + if (n == 0) continue; + const subBuff1 = buff1.slice(i * nPointsPerThread * sG1, (i * nPointsPerThread + n) * sG1); + const subBuff2 = buff2.slice(i * nPointsPerThread * sG1, (i * nPointsPerThread + n) * sG1); + opPromises.push(hashHPointsThread(subBuff1, subBuff2)); + } + const result = await Promise.all(opPromises); + for (let i = 0; i < result.length; i++) csHasher.update(result[i][0]); + } + async function hashHPointsThread(buff1, buff2) { + const nPoints = buff1.byteLength / sG1; + const sGmid = curve.G1.F.n8 * 3; + const task = []; + task.push({ + cmd: "ALLOCSET", + var: 0, + buff: buff1 + }); + task.push({ + cmd: "ALLOCSET", + var: 1, + buff: buff2 + }); + task.push({ + cmd: "ALLOC", + var: 2, + len: nPoints * sGmid + }); + for (let i = 0; i < nPoints; i++) task.push({ + cmd: "CALL", + fnName: "g1m_subAffine", + params: [ + { + var: 0, + offset: i * sG1 + }, + { + var: 1, + offset: i * sG1 + }, + { + var: 2, + offset: i * sGmid + } + ] + }); + task.push({ + cmd: "CALL", + fnName: "g1m_batchToAffine", + params: [ + { var: 2 }, + { val: nPoints }, + { var: 2 } + ] + }); + task.push({ + cmd: "CALL", + fnName: "g1m_batchLEMtoU", + params: [ + { var: 2 }, + { val: nPoints }, + { var: 2 } + ] + }); + task.push({ + cmd: "GET", + out: 0, + var: 2, + len: nPoints * sG1 + }); + return await curve.tm.queueAction(task); + } + function hashU32(n) { + const buff = new Uint8Array(4); + new DataView(buff.buffer, buff.byteOffset, buff.byteLength).setUint32(0, n, false); + csHasher.update(buff); + } + function memUsage() { + if (typeof process === "undefined" || !process.memoryUsage) return {}; + let m = process.memoryUsage(); + for (const i in m) m[i] = Math.round(m[i] / (1024 * 1024)); + return m; + } + } + //#endregion + //#region src/zkey_export_bellman.js + async function phase2exportMPCParams(zkeyName, mpcparamsName, logger) { + const { fd: fdZKey, sections: sectionsZKey } = await _iden3_binfileutils.readBinFile(zkeyName, "zkey", 2); + const zkey = await readHeader$1(fdZKey, sectionsZKey); + if (zkey.protocol != "groth16") throw new Error("zkey file is not groth16"); + const curve = await getCurveFromQ(zkey.q); + const sG1 = curve.G1.F.n8 * 2; + const sG2 = curve.G2.F.n8 * 2; + const mpcParams = await readMPCParams(fdZKey, curve, sectionsZKey); + const fdMPCParams = await S(mpcparamsName); + await writeG1(zkey.vk_alpha_1); + await writeG1(zkey.vk_beta_1); + await writeG2(zkey.vk_beta_2); + await writeG2(zkey.vk_gamma_2); + await writeG1(zkey.vk_delta_1); + await writeG2(zkey.vk_delta_2); + let buffBasesIC; + buffBasesIC = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 3); + buffBasesIC = await curve.G1.batchLEMtoU(buffBasesIC); + await writePointArray("G1", buffBasesIC); + const buffBasesH_Lodd = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 9); + let buffBasesH_Tau; + buffBasesH_Tau = await curve.G1.fft(buffBasesH_Lodd, "affine", "jacobian", logger); + buffBasesH_Tau = await curve.G1.batchApplyKey(buffBasesH_Tau, curve.Fr.neg(curve.Fr.e(2)), curve.Fr.w[zkey.power + 1], "jacobian", "affine", logger); + buffBasesH_Tau = buffBasesH_Tau.slice(0, buffBasesH_Tau.byteLength - sG1); + buffBasesH_Tau = await curve.G1.batchLEMtoU(buffBasesH_Tau); + await writePointArray("G1", buffBasesH_Tau); + let buffBasesC; + buffBasesC = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 8); + buffBasesC = await curve.G1.batchLEMtoU(buffBasesC); + await writePointArray("G1", buffBasesC); + let buffBasesA; + buffBasesA = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 5); + buffBasesA = await curve.G1.batchLEMtoU(buffBasesA); + await writePointArray("G1", buffBasesA); + let buffBasesB1; + buffBasesB1 = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 6); + buffBasesB1 = await curve.G1.batchLEMtoU(buffBasesB1); + await writePointArray("G1", buffBasesB1); + let buffBasesB2; + buffBasesB2 = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 7); + buffBasesB2 = await curve.G2.batchLEMtoU(buffBasesB2); + await writePointArray("G2", buffBasesB2); + await fdMPCParams.write(mpcParams.csHash); + await writeU32(mpcParams.contributions.length); + for (let i = 0; i < mpcParams.contributions.length; i++) { + const c = mpcParams.contributions[i]; + await writeG1(c.deltaAfter); + await writeG1(c.delta.g1_s); + await writeG1(c.delta.g1_sx); + await writeG2(c.delta.g2_spx); + await fdMPCParams.write(c.transcript); + } + await fdZKey.close(); + await fdMPCParams.close(); + async function writeG1(P) { + const buff = new Uint8Array(sG1); + curve.G1.toRprUncompressed(buff, 0, P); + await fdMPCParams.write(buff); + } + async function writeG2(P) { + const buff = new Uint8Array(sG2); + curve.G2.toRprUncompressed(buff, 0, P); + await fdMPCParams.write(buff); + } + async function writePointArray(groupName, buff) { + let sG; + if (groupName == "G1") sG = sG1; + else sG = sG2; + const buffSize = new Uint8Array(4); + new DataView(buffSize.buffer, buffSize.byteOffset, buffSize.byteLength).setUint32(0, buff.byteLength / sG, false); + await fdMPCParams.write(buffSize); + await fdMPCParams.write(buff); + } + async function writeU32(n) { + const buffSize = new Uint8Array(4); + new DataView(buffSize.buffer, buffSize.byteOffset, buffSize.byteLength).setUint32(0, n, false); + await fdMPCParams.write(buffSize); + } + } + //#endregion + //#region src/zkey_import_bellman.js + async function phase2importMPCParams(zkeyNameOld, mpcparamsName, zkeyNameNew, name, logger) { + const { fd: fdZKeyOld, sections: sectionsZKeyOld } = await _iden3_binfileutils.readBinFile(zkeyNameOld, "zkey", 2); + const zkeyHeader = await readHeader$1(fdZKeyOld, sectionsZKeyOld, false); + if (zkeyHeader.protocol != "groth16") throw new Error("zkey file is not groth16"); + const curve = await getCurveFromQ(zkeyHeader.q); + const sG1 = curve.G1.F.n8 * 2; + const sG2 = curve.G2.F.n8 * 2; + const oldMPCParams = await readMPCParams(fdZKeyOld, curve, sectionsZKeyOld); + const newMPCParams = {}; + const fdMPCParams = await w(mpcparamsName); + fdMPCParams.pos = sG1 * 3 + sG2 * 3 + 8 + sG1 * zkeyHeader.nVars + 4 + sG1 * (zkeyHeader.domainSize - 1) + 4 + sG1 * zkeyHeader.nVars + 4 + sG1 * zkeyHeader.nVars + 4 + sG2 * zkeyHeader.nVars; + newMPCParams.csHash = await fdMPCParams.read(64); + const nContributions = await fdMPCParams.readUBE32(); + newMPCParams.contributions = []; + for (let i = 0; i < nContributions; i++) { + const c = { delta: {} }; + c.deltaAfter = await readG1(fdMPCParams); + c.delta.g1_s = await readG1(fdMPCParams); + c.delta.g1_sx = await readG1(fdMPCParams); + c.delta.g2_spx = await readG2(fdMPCParams); + c.transcript = await fdMPCParams.read(64); + if (i < oldMPCParams.contributions.length) { + c.type = oldMPCParams.contributions[i].type; + if (c.type == 1) { + c.beaconHash = oldMPCParams.contributions[i].beaconHash; + c.numIterationsExp = oldMPCParams.contributions[i].numIterationsExp; + } + if (oldMPCParams.contributions[i].name) c.name = oldMPCParams.contributions[i].name; + } + newMPCParams.contributions.push(c); + } + if (!hashIsEqual(newMPCParams.csHash, oldMPCParams.csHash)) { + if (logger) logger.error("Hash of the original circuit does not match with the MPC one"); + return false; + } + if (oldMPCParams.contributions.length > newMPCParams.contributions.length) { + if (logger) logger.error("The impoerted file does not include new contributions"); + return false; + } + for (let i = 0; i < oldMPCParams.contributions.length; i++) if (!contributionIsEqual(oldMPCParams.contributions[i], newMPCParams.contributions[i])) { + if (logger) logger.error(`Previous contribution ${i} does not match`); + return false; + } + if (name) for (let i = oldMPCParams.contributions.length; i < newMPCParams.contributions.length; i++) newMPCParams.contributions[i].name = name; + const fdZKeyNew = await _iden3_binfileutils.createBinFile(zkeyNameNew, "zkey", 1, 10); + fdMPCParams.pos = 0; + fdMPCParams.pos += sG1; + fdMPCParams.pos += sG1; + fdMPCParams.pos += sG2; + fdMPCParams.pos += sG2; + zkeyHeader.vk_delta_1 = await readG1(fdMPCParams); + zkeyHeader.vk_delta_2 = await readG2(fdMPCParams); + await writeHeader(fdZKeyNew, zkeyHeader); + if (await fdMPCParams.readUBE32() != zkeyHeader.nPublic + 1) { + if (logger) logger.error("Invalid number of points in IC"); + await fdZKeyNew.discard(); + return false; + } + fdMPCParams.pos += sG1 * (zkeyHeader.nPublic + 1); + await _iden3_binfileutils.copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 3); + await _iden3_binfileutils.copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 4); + if (await fdMPCParams.readUBE32() != zkeyHeader.domainSize - 1) { + if (logger) logger.error("Invalid number of points in H"); + await fdZKeyNew.discard(); + return false; + } + let buffH; + const buffTauU = await fdMPCParams.read(sG1 * (zkeyHeader.domainSize - 1)); + const buffTauLEM = await curve.G1.batchUtoLEM(buffTauU); + buffH = new Uint8Array(zkeyHeader.domainSize * sG1); + buffH.set(buffTauLEM); + curve.G1.toRprLEM(buffH, sG1 * (zkeyHeader.domainSize - 1), curve.G1.zeroAffine); + const n2Inv = curve.Fr.neg(curve.Fr.inv(curve.Fr.e(2))); + const wInv = curve.Fr.inv(curve.Fr.w[zkeyHeader.power + 1]); + buffH = await curve.G1.batchApplyKey(buffH, n2Inv, wInv, "affine", "jacobian", logger); + buffH = await curve.G1.ifft(buffH, "jacobian", "affine", logger); + await _iden3_binfileutils.startWriteSection(fdZKeyNew, 9); + await fdZKeyNew.write(buffH); + await _iden3_binfileutils.endWriteSection(fdZKeyNew); + if (await fdMPCParams.readUBE32() != zkeyHeader.nVars - zkeyHeader.nPublic - 1) { + if (logger) logger.error("Invalid number of points in L"); + await fdZKeyNew.discard(); + return false; + } + let buffL; + buffL = await fdMPCParams.read(sG1 * (zkeyHeader.nVars - zkeyHeader.nPublic - 1)); + buffL = await curve.G1.batchUtoLEM(buffL); + await _iden3_binfileutils.startWriteSection(fdZKeyNew, 8); + await fdZKeyNew.write(buffL); + await _iden3_binfileutils.endWriteSection(fdZKeyNew); + if (await fdMPCParams.readUBE32() != zkeyHeader.nVars) { + if (logger) logger.error("Invalid number of points in A"); + await fdZKeyNew.discard(); + return false; + } + fdMPCParams.pos += sG1 * zkeyHeader.nVars; + await _iden3_binfileutils.copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 5); + if (await fdMPCParams.readUBE32() != zkeyHeader.nVars) { + if (logger) logger.error("Invalid number of points in B1"); + await fdZKeyNew.discard(); + return false; + } + fdMPCParams.pos += sG1 * zkeyHeader.nVars; + await _iden3_binfileutils.copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 6); + if (await fdMPCParams.readUBE32() != zkeyHeader.nVars) { + if (logger) logger.error("Invalid number of points in B2"); + await fdZKeyNew.discard(); + return false; + } + fdMPCParams.pos += sG2 * zkeyHeader.nVars; + await _iden3_binfileutils.copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 7); + await writeMPCParams(fdZKeyNew, curve, newMPCParams); + await fdMPCParams.close(); + await fdZKeyNew.close(); + await fdZKeyOld.close(); + return true; + async function readG1(fd) { + const buff = await fd.read(curve.G1.F.n8 * 2); + return curve.G1.fromRprUncompressed(buff, 0); + } + async function readG2(fd) { + const buff = await fd.read(curve.G2.F.n8 * 2); + return curve.G2.fromRprUncompressed(buff, 0); + } + function contributionIsEqual(c1, c2) { + if (!curve.G1.eq(c1.deltaAfter, c2.deltaAfter)) return false; + if (!curve.G1.eq(c1.delta.g1_s, c2.delta.g1_s)) return false; + if (!curve.G1.eq(c1.delta.g1_sx, c2.delta.g1_sx)) return false; + if (!curve.G2.eq(c1.delta.g2_spx, c2.delta.g2_spx)) return false; + if (!hashIsEqual(c1.transcript, c2.transcript)) return false; + return true; + } + } + //#endregion + //#region src/zkey_verify_frominit.js + var sameRatio = sameRatio$2; + async function phase2verifyFromInit(initFileName, pTauFileName, zkeyFileName, logger) { + let sr; + const { fd, sections } = await _iden3_binfileutils.readBinFile(zkeyFileName, "zkey", 2); + const zkey = await readHeader$1(fd, sections, false); + if (zkey.protocol != "groth16") throw new Error("zkey file is not groth16"); + const curve = await getCurveFromQ(zkey.q); + const sG1 = curve.G1.F.n8 * 2; + const mpcParams = await readMPCParams(fd, curve, sections); + const accumulatedHasher = blake2b.create({ dkLen: 64 }); + accumulatedHasher.update(mpcParams.csHash); + let curDelta = curve.G1.g; + for (let i = 0; i < mpcParams.contributions.length; i++) { + const c = mpcParams.contributions[i]; + const ourHasher = cloneHasher(accumulatedHasher); + hashG1(ourHasher, curve, c.delta.g1_s); + hashG1(ourHasher, curve, c.delta.g1_sx); + if (!hashIsEqual(ourHasher.digest(), c.transcript)) { + console.log(`INVALID(${i}): Inconsistent transcript `); + return false; + } + const delta_g2_sp = hashToG2(curve, c.transcript); + sr = await sameRatio(curve, c.delta.g1_s, c.delta.g1_sx, delta_g2_sp, c.delta.g2_spx); + if (sr !== true) { + console.log(`INVALID(${i}): public key G1 and G2 do not have the same ration `); + return false; + } + sr = await sameRatio(curve, curDelta, c.deltaAfter, delta_g2_sp, c.delta.g2_spx); + if (sr !== true) { + console.log(`INVALID(${i}): deltaAfter does not fillow the public key `); + return false; + } + if (c.type == 1) { + const rng = await rngFromBeaconParams(c.beaconHash, c.numIterationsExp); + const expected_prvKey = curve.Fr.fromRng(rng); + const expected_g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); + const expected_g1_sx = curve.G1.toAffine(curve.G1.timesFr(expected_g1_s, expected_prvKey)); + if (curve.G1.eq(expected_g1_s, c.delta.g1_s) !== true) { + console.log(`INVALID(${i}): Key of the beacon does not match. g1_s `); + return false; + } + if (curve.G1.eq(expected_g1_sx, c.delta.g1_sx) !== true) { + console.log(`INVALID(${i}): Key of the beacon does not match. g1_sx `); + return false; + } + } + hashPubKey(accumulatedHasher, curve, c); + const contributionHasher = blake2b.create({ dkLen: 64 }); + hashPubKey(contributionHasher, curve, c); + c.contributionHash = contributionHasher.digest(); + curDelta = c.deltaAfter; + } + const { fd: fdInit, sections: sectionsInit } = await _iden3_binfileutils.readBinFile(initFileName, "zkey", 2); + const zkeyInit = await readHeader$1(fdInit, sectionsInit, false); + if (zkeyInit.protocol != "groth16") throw new Error("zkeyinit file is not groth16"); + if (!ffjavascript.Scalar.eq(zkeyInit.q, zkey.q) || !ffjavascript.Scalar.eq(zkeyInit.r, zkey.r) || zkeyInit.n8q != zkey.n8q || zkeyInit.n8r != zkey.n8r) { + if (logger) logger.error("INVALID: Different curves"); + return false; + } + if (zkeyInit.nVars != zkey.nVars || zkeyInit.nPublic != zkey.nPublic || zkeyInit.domainSize != zkey.domainSize) { + if (logger) logger.error("INVALID: Different circuit parameters"); + return false; + } + if (!curve.G1.eq(zkey.vk_alpha_1, zkeyInit.vk_alpha_1)) { + if (logger) logger.error("INVALID: Invalid alpha1"); + return false; + } + if (!curve.G1.eq(zkey.vk_beta_1, zkeyInit.vk_beta_1)) { + if (logger) logger.error("INVALID: Invalid beta1"); + return false; + } + if (!curve.G2.eq(zkey.vk_beta_2, zkeyInit.vk_beta_2)) { + if (logger) logger.error("INVALID: Invalid beta2"); + return false; + } + if (!curve.G2.eq(zkey.vk_gamma_2, zkeyInit.vk_gamma_2)) { + if (logger) logger.error("INVALID: Invalid gamma2"); + return false; + } + if (!curve.G1.eq(zkey.vk_delta_1, curDelta)) { + if (logger) logger.error("INVALID: Invalid delta1"); + return false; + } + sr = await sameRatio(curve, curve.G1.g, curDelta, curve.G2.g, zkey.vk_delta_2); + if (sr !== true) { + if (logger) logger.error("INVALID: Invalid delta2"); + return false; + } + const mpcParamsInit = await readMPCParams(fdInit, curve, sectionsInit); + if (!hashIsEqual(mpcParams.csHash, mpcParamsInit.csHash)) { + if (logger) logger.error("INVALID: Circuit does not match"); + return false; + } + if (sections[8][0].size != sG1 * (zkey.nVars - zkey.nPublic - 1)) { + if (logger) logger.error("INVALID: Invalid L section size"); + return false; + } + if (sections[9][0].size != sG1 * zkey.domainSize) { + if (logger) logger.error("INVALID: Invalid H section size"); + return false; + } + let ss; + ss = await _iden3_binfileutils.sectionIsEqual(fd, sections, fdInit, sectionsInit, 3); + if (!ss) { + if (logger) logger.error("INVALID: IC section is not identical"); + return false; + } + ss = await _iden3_binfileutils.sectionIsEqual(fd, sections, fdInit, sectionsInit, 4); + if (!ss) { + if (logger) logger.error("Coeffs section is not identical"); + return false; + } + ss = await _iden3_binfileutils.sectionIsEqual(fd, sections, fdInit, sectionsInit, 5); + if (!ss) { + if (logger) logger.error("A section is not identical"); + return false; + } + ss = await _iden3_binfileutils.sectionIsEqual(fd, sections, fdInit, sectionsInit, 6); + if (!ss) { + if (logger) logger.error("B1 section is not identical"); + return false; + } + ss = await _iden3_binfileutils.sectionIsEqual(fd, sections, fdInit, sectionsInit, 7); + if (!ss) { + if (logger) logger.error("B2 section is not identical"); + return false; + } + sr = await sectionHasSameRatio("G1", fdInit, sectionsInit, fd, sections, 8, zkey.vk_delta_2, zkeyInit.vk_delta_2, "L section"); + if (sr !== true) { + if (logger) logger.error("L section does not match"); + return false; + } + sr = await sameRatioH(); + if (sr !== true) { + if (logger) logger.error("H section does not match"); + return false; + } + if (logger) logger.info(formatHash(mpcParams.csHash, "Circuit Hash: ")); + await fd.close(); + await fdInit.close(); + for (let i = mpcParams.contributions.length - 1; i >= 0; i--) { + const c = mpcParams.contributions[i]; + if (logger) logger.info("-------------------------"); + if (logger) logger.info(formatHash(c.contributionHash, `contribution #${i + 1} ${c.name ? c.name : ""}:`)); + if (c.type == 1) { + if (logger) logger.info(`Beacon generator: ${byteArray2hex(c.beaconHash)}`); + if (logger) logger.info(`Beacon iterations Exp: ${c.numIterationsExp}`); + } + } + if (logger) logger.info("-------------------------"); + if (logger) logger.info("ZKey Ok!"); + return true; + async function sectionHasSameRatio(groupName, fd1, sections1, fd2, sections2, idSection, g2sp, g2spx, sectionName) { + const MAX_CHUNK_SIZE = 1 << 20; + const G = curve[groupName]; + const sG = G.F.n8 * 2; + await _iden3_binfileutils.startReadUniqueSection(fd1, sections1, idSection); + await _iden3_binfileutils.startReadUniqueSection(fd2, sections2, idSection); + let R1 = G.zero; + let R2 = G.zero; + const nPoints = sections1[idSection][0].size / sG; + for (let i = 0; i < nPoints; i += MAX_CHUNK_SIZE) { + if (logger) logger.debug(`Same ratio check ${sectionName}: ${i}/${nPoints}`); + const n = Math.min(nPoints - i, MAX_CHUNK_SIZE); + const bases1 = await fd1.read(n * sG); + const bases2 = await fd2.read(n * sG); + const scalars = getRandomBytes(4 * n); + const r1 = await G.multiExpAffine(bases1, scalars); + const r2 = await G.multiExpAffine(bases2, scalars); + R1 = G.add(R1, r1); + R2 = G.add(R2, r2); + } + await _iden3_binfileutils.endReadSection(fd1); + await _iden3_binfileutils.endReadSection(fd2); + if (nPoints == 0) return true; + sr = await sameRatio(curve, R1, R2, g2sp, g2spx); + if (sr !== true) return false; + return true; + } + async function sameRatioH() { + const MAX_CHUNK_SIZE = 1 << 20; + const G = curve.G1; + const Fr = curve.Fr; + const sG = G.F.n8 * 2; + const { fd: fdPTau, sections: sectionsPTau } = await _iden3_binfileutils.readBinFile(pTauFileName, "ptau", 1); + let buff_r = new ffjavascript.BigBuffer(zkey.domainSize * zkey.n8r); + const seed = new Array(8); + for (let i = 0; i < 8; i++) seed[i] = readUInt32BE(getRandomBytes(4), 0); + const rng = new ffjavascript.ChaCha(seed); + for (let i = 0; i < zkey.domainSize - 1; i++) { + const e = Fr.fromRng(rng); + Fr.toRprLE(buff_r, i * zkey.n8r, e); + } + Fr.toRprLE(buff_r, (zkey.domainSize - 1) * zkey.n8r, Fr.zero); + let R1 = G.zero; + for (let i = 0; i < zkey.domainSize; i += MAX_CHUNK_SIZE) { + if (logger) logger.debug(`H Verification(tau): ${i}/${zkey.domainSize}`); + const n = Math.min(zkey.domainSize - i, MAX_CHUNK_SIZE); + const buffB = await batchSubtract(await fdPTau.read(sG * n, sectionsPTau[2][0].p + zkey.domainSize * sG + i * sG), await fdPTau.read(sG * n, sectionsPTau[2][0].p + i * sG)); + const buffS = buff_r.slice(i * zkey.n8r, (i + n) * zkey.n8r); + const r = await G.multiExpAffine(buffB, buffS); + R1 = G.add(R1, r); + } + buff_r = await Fr.batchToMontgomery(buff_r); + let first; + if (zkey.power < Fr.s) first = Fr.neg(Fr.e(2)); + else { + const small_m = 2 ** Fr.s; + const shift_to_small_m = Fr.exp(Fr.shift, small_m); + first = Fr.sub(shift_to_small_m, Fr.one); + } + const inc = zkey.power < Fr.s ? Fr.w[zkey.power + 1] : Fr.shift; + buff_r = await Fr.batchApplyKey(buff_r, first, inc); + buff_r = await Fr.fft(buff_r); + buff_r = await Fr.batchFromMontgomery(buff_r); + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 9); + let R2 = G.zero; + for (let i = 0; i < zkey.domainSize; i += MAX_CHUNK_SIZE) { + if (logger) logger.debug(`H Verification(lagrange): ${i}/${zkey.domainSize}`); + const n = Math.min(zkey.domainSize - i, MAX_CHUNK_SIZE); + const buff = await fd.read(sG * n); + const buffS = buff_r.slice(i * zkey.n8r, (i + n) * zkey.n8r); + const r = await G.multiExpAffine(buff, buffS); + R2 = G.add(R2, r); + } + await _iden3_binfileutils.endReadSection(fd); + sr = await sameRatio(curve, R1, R2, zkey.vk_delta_2, zkeyInit.vk_delta_2); + if (sr !== true) return false; + return true; + } + async function batchSubtract(buff1, buff2) { + const sG = curve.G1.F.n8 * 2; + const nPoints = buff1.byteLength / sG; + const concurrency = curve.tm.concurrency; + const nPointsPerThread = Math.floor(nPoints / concurrency); + const opPromises = []; + for (let i = 0; i < concurrency; i++) { + let n; + if (i < concurrency - 1) n = nPointsPerThread; + else n = nPoints - i * nPointsPerThread; + if (n == 0) continue; + const subBuff1 = buff1.slice(i * nPointsPerThread * sG1, (i * nPointsPerThread + n) * sG1); + const subBuff2 = buff2.slice(i * nPointsPerThread * sG1, (i * nPointsPerThread + n) * sG1); + opPromises.push(batchSubtractThread(subBuff1, subBuff2)); + } + const result = await Promise.all(opPromises); + const fullBuffOut = new Uint8Array(nPoints * sG); + let p = 0; + for (let i = 0; i < result.length; i++) { + fullBuffOut.set(result[i][0], p); + p += result[i][0].byteLength; + } + return fullBuffOut; + } + async function batchSubtractThread(buff1, buff2) { + const sG1 = curve.G1.F.n8 * 2; + const sGmid = curve.G1.F.n8 * 3; + const nPoints = buff1.byteLength / sG1; + const task = []; + task.push({ + cmd: "ALLOCSET", + var: 0, + buff: buff1 + }); + task.push({ + cmd: "ALLOCSET", + var: 1, + buff: buff2 + }); + task.push({ + cmd: "ALLOC", + var: 2, + len: nPoints * sGmid + }); + for (let i = 0; i < nPoints; i++) task.push({ + cmd: "CALL", + fnName: "g1m_subAffine", + params: [ + { + var: 0, + offset: i * sG1 + }, + { + var: 1, + offset: i * sG1 + }, + { + var: 2, + offset: i * sGmid + } + ] + }); + task.push({ + cmd: "CALL", + fnName: "g1m_batchToAffine", + params: [ + { var: 2 }, + { val: nPoints }, + { var: 2 } + ] + }); + task.push({ + cmd: "GET", + out: 0, + var: 2, + len: nPoints * sG1 + }); + return await curve.tm.queueAction(task); + } + } + //#endregion + //#region src/zkey_verify_fromr1cs.js + async function phase2verifyFromR1cs(r1csFileName, pTauFileName, zkeyFileName, logger) { + const initFileName = { type: "bigMem" }; + await newZKey(r1csFileName, pTauFileName, initFileName, logger); + return await phase2verifyFromInit(initFileName, pTauFileName, zkeyFileName, logger); + } + //#endregion + //#region src/zkey_contribute.js + async function phase2contribute(zkeyNameOld, zkeyNameNew, name, entropy, logger) { + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(zkeyNameOld, "zkey", 2); + const zkey = await readHeader$1(fdOld, sections); + if (zkey.protocol != "groth16") throw new Error("zkey file is not groth16"); + const curve = await getCurveFromQ(zkey.q); + const mpcParams = await readMPCParams(fdOld, curve, sections); + const fdNew = await _iden3_binfileutils.createBinFile(zkeyNameNew, "zkey", 1, 10); + const rng = await getRandomRng(entropy); + const transcriptHasher = blake2b.create({ dkLen: 64 }); + transcriptHasher.update(mpcParams.csHash); + for (let i = 0; i < mpcParams.contributions.length; i++) hashPubKey(transcriptHasher, curve, mpcParams.contributions[i]); + const curContribution = {}; + curContribution.delta = {}; + curContribution.delta.prvKey = curve.Fr.fromRng(rng); + curContribution.delta.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); + curContribution.delta.g1_sx = curve.G1.toAffine(curve.G1.timesFr(curContribution.delta.g1_s, curContribution.delta.prvKey)); + hashG1(transcriptHasher, curve, curContribution.delta.g1_s); + hashG1(transcriptHasher, curve, curContribution.delta.g1_sx); + curContribution.transcript = transcriptHasher.digest(); + curContribution.delta.g2_sp = hashToG2(curve, curContribution.transcript); + curContribution.delta.g2_spx = curve.G2.toAffine(curve.G2.timesFr(curContribution.delta.g2_sp, curContribution.delta.prvKey)); + zkey.vk_delta_1 = curve.G1.timesFr(zkey.vk_delta_1, curContribution.delta.prvKey); + zkey.vk_delta_2 = curve.G2.timesFr(zkey.vk_delta_2, curContribution.delta.prvKey); + curContribution.deltaAfter = zkey.vk_delta_1; + curContribution.type = 0; + if (name) curContribution.name = name; + mpcParams.contributions.push(curContribution); + await writeHeader(fdNew, zkey); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 3); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 4); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 5); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 6); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 7); + const invDelta = curve.Fr.inv(curContribution.delta.prvKey); + await applyKeyToSection(fdOld, sections, fdNew, 8, curve, "G1", invDelta, curve.Fr.e(1), "L Section", logger); + await applyKeyToSection(fdOld, sections, fdNew, 9, curve, "G1", invDelta, curve.Fr.e(1), "H Section", logger); + await writeMPCParams(fdNew, curve, mpcParams); + await fdOld.close(); + await fdNew.close(); + const contributionHasher = blake2b.create({ dkLen: 64 }); + hashPubKey(contributionHasher, curve, curContribution); + const contributionHash = contributionHasher.digest(); + if (logger) logger.info(formatHash(mpcParams.csHash, "Circuit Hash: ")); + if (logger) logger.info(formatHash(contributionHash, "Contribution Hash: ")); + return contributionHash; + } + //#endregion + //#region src/zkey_beacon.js + async function beacon(zkeyNameOld, zkeyNameNew, name, beaconHashStr, numIterationsExp, logger) { + const beaconHash = hex2ByteArray(beaconHashStr); + if (beaconHash.byteLength == 0 || beaconHash.byteLength * 2 != beaconHashStr.length) { + if (logger) logger.error("Invalid Beacon Hash. (It must be a valid hexadecimal sequence)"); + return false; + } + if (beaconHash.length >= 256) { + if (logger) logger.error("Maximum length of beacon hash is 255 bytes"); + return false; + } + numIterationsExp = parseInt(numIterationsExp); + if (numIterationsExp < 10 || numIterationsExp > 63) { + if (logger) logger.error("Invalid numIterationsExp. (Must be between 10 and 63)"); + return false; + } + const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(zkeyNameOld, "zkey", 2); + const zkey = await readHeader$1(fdOld, sections); + if (zkey.protocol != "groth16") throw new Error("zkey file is not groth16"); + const curve = await getCurveFromQ(zkey.q); + const mpcParams = await readMPCParams(fdOld, curve, sections); + const fdNew = await _iden3_binfileutils.createBinFile(zkeyNameNew, "zkey", 1, 10); + const rng = await rngFromBeaconParams(beaconHash, numIterationsExp); + const transcriptHasher = blake2b.create({ dkLen: 64 }); + transcriptHasher.update(mpcParams.csHash); + for (let i = 0; i < mpcParams.contributions.length; i++) hashPubKey(transcriptHasher, curve, mpcParams.contributions[i]); + const curContribution = {}; + curContribution.delta = {}; + curContribution.delta.prvKey = curve.Fr.fromRng(rng); + curContribution.delta.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); + curContribution.delta.g1_sx = curve.G1.toAffine(curve.G1.timesFr(curContribution.delta.g1_s, curContribution.delta.prvKey)); + hashG1(transcriptHasher, curve, curContribution.delta.g1_s); + hashG1(transcriptHasher, curve, curContribution.delta.g1_sx); + curContribution.transcript = transcriptHasher.digest(); + curContribution.delta.g2_sp = hashToG2(curve, curContribution.transcript); + curContribution.delta.g2_spx = curve.G2.toAffine(curve.G2.timesFr(curContribution.delta.g2_sp, curContribution.delta.prvKey)); + zkey.vk_delta_1 = curve.G1.timesFr(zkey.vk_delta_1, curContribution.delta.prvKey); + zkey.vk_delta_2 = curve.G2.timesFr(zkey.vk_delta_2, curContribution.delta.prvKey); + curContribution.deltaAfter = zkey.vk_delta_1; + curContribution.type = 1; + curContribution.numIterationsExp = numIterationsExp; + curContribution.beaconHash = beaconHash; + if (name) curContribution.name = name; + mpcParams.contributions.push(curContribution); + await writeHeader(fdNew, zkey); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 3); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 4); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 5); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 6); + await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 7); + const invDelta = curve.Fr.inv(curContribution.delta.prvKey); + await applyKeyToSection(fdOld, sections, fdNew, 8, curve, "G1", invDelta, curve.Fr.e(1), "L Section", logger); + await applyKeyToSection(fdOld, sections, fdNew, 9, curve, "G1", invDelta, curve.Fr.e(1), "H Section", logger); + await writeMPCParams(fdNew, curve, mpcParams); + await fdOld.close(); + await fdNew.close(); + const contributionHasher = blake2b.create({ dkLen: 64 }); + hashPubKey(contributionHasher, curve, curContribution); + const contributionHash = contributionHasher.digest(); + if (logger) logger.info(formatHash(contributionHash, "Contribution Hash: ")); + return contributionHash; + } + //#endregion + //#region src/zkey_export_json.js + async function zkeyExportJson(zkeyFileName) { + const zKey = await readZKey(zkeyFileName, true); + delete zKey.curve; + delete zKey.F; + return ffjavascript.utils.stringifyBigInts(zKey); + } + //#endregion + //#region src/zkey_bellman_contribute.js + async function bellmanContribute(curve, challengeFilename, responseFileName, entropy, logger) { + const rng = await getRandomRng(entropy); + const delta = curve.Fr.fromRng(rng); + const invDelta = curve.Fr.inv(delta); + const sG1 = curve.G1.F.n8 * 2; + const sG2 = curve.G2.F.n8 * 2; + const fdFrom = await w(challengeFilename); + const fdTo = await S(responseFileName); + await copy(sG1); + await copy(sG1); + await copy(sG2); + await copy(sG2); + const oldDelta1 = await readG1(); + const delta1 = curve.G1.timesFr(oldDelta1, delta); + await writeG1(delta1); + const oldDelta2 = await readG2(); + await writeG2(curve.G2.timesFr(oldDelta2, delta)); + const nIC = await fdFrom.readUBE32(); + await fdTo.writeUBE32(nIC); + await copy(nIC * sG1); + const nH = await fdFrom.readUBE32(); + await fdTo.writeUBE32(nH); + await applyKeyToChallengeSection(fdFrom, fdTo, null, curve, "G1", nH, invDelta, curve.Fr.e(1), "UNCOMPRESSED", "H", logger); + const nL = await fdFrom.readUBE32(); + await fdTo.writeUBE32(nL); + await applyKeyToChallengeSection(fdFrom, fdTo, null, curve, "G1", nL, invDelta, curve.Fr.e(1), "UNCOMPRESSED", "L", logger); + const nA = await fdFrom.readUBE32(); + await fdTo.writeUBE32(nA); + await copy(nA * sG1); + const nB1 = await fdFrom.readUBE32(); + await fdTo.writeUBE32(nB1); + await copy(nB1 * sG1); + const nB2 = await fdFrom.readUBE32(); + await fdTo.writeUBE32(nB2); + await copy(nB2 * sG2); + const transcriptHasher = blake2b.create({ dkLen: 64 }); + const mpcParams = {}; + mpcParams.csHash = await fdFrom.read(64); + transcriptHasher.update(mpcParams.csHash); + const nContributions = await fdFrom.readUBE32(); + mpcParams.contributions = []; + for (let i = 0; i < nContributions; i++) { + const c = { delta: {} }; + c.deltaAfter = await readG1(); + c.delta.g1_s = await readG1(); + c.delta.g1_sx = await readG1(); + c.delta.g2_spx = await readG2(); + c.transcript = await fdFrom.read(64); + mpcParams.contributions.push(c); + hashPubKey(transcriptHasher, curve, c); + } + const curContribution = {}; + curContribution.delta = {}; + curContribution.delta.prvKey = delta; + curContribution.delta.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); + curContribution.delta.g1_sx = curve.G1.toAffine(curve.G1.timesFr(curContribution.delta.g1_s, delta)); + hashG1(transcriptHasher, curve, curContribution.delta.g1_s); + hashG1(transcriptHasher, curve, curContribution.delta.g1_sx); + curContribution.transcript = transcriptHasher.digest(); + curContribution.delta.g2_sp = hashToG2(curve, curContribution.transcript); + curContribution.delta.g2_spx = curve.G2.toAffine(curve.G2.timesFr(curContribution.delta.g2_sp, delta)); + curContribution.deltaAfter = delta1; + curContribution.type = 0; + mpcParams.contributions.push(curContribution); + await fdTo.write(mpcParams.csHash); + await fdTo.writeUBE32(mpcParams.contributions.length); + for (let i = 0; i < mpcParams.contributions.length; i++) { + const c = mpcParams.contributions[i]; + await writeG1(c.deltaAfter); + await writeG1(c.delta.g1_s); + await writeG1(c.delta.g1_sx); + await writeG2(c.delta.g2_spx); + await fdTo.write(c.transcript); + } + const contributionHasher = blake2b.create({ dkLen: 64 }); + hashPubKey(contributionHasher, curve, curContribution); + const contributionHash = contributionHasher.digest(); + if (logger) logger.info(formatHash(contributionHash, "Contribution Hash: ")); + await fdTo.close(); + await fdFrom.close(); + return contributionHash; + async function copy(nBytes) { + const CHUNK_SIZE = fdFrom.pageSize * 2; + for (let i = 0; i < nBytes; i += CHUNK_SIZE) { + const n = Math.min(nBytes - i, CHUNK_SIZE); + const buff = await fdFrom.read(n); + await fdTo.write(buff); + } + } + async function readG1() { + const buff = await fdFrom.read(curve.G1.F.n8 * 2); + return curve.G1.fromRprUncompressed(buff, 0); + } + async function readG2() { + const buff = await fdFrom.read(curve.G2.F.n8 * 2); + return curve.G2.fromRprUncompressed(buff, 0); + } + async function writeG1(P) { + const buff = new Uint8Array(sG1); + curve.G1.toRprUncompressed(buff, 0, P); + await fdTo.write(buff); + } + async function writeG2(P) { + const buff = new Uint8Array(sG2); + curve.G2.toRprUncompressed(buff, 0, P); + await fdTo.write(buff); + } + } + //#endregion + //#region src/zkey_export_verificationkey.js + var { stringifyBigInts: stringifyBigInts$2 } = ffjavascript.utils; + async function zkeyExportVerificationKey(zkeyName, logger) { + if (logger) logger.info("EXPORT VERIFICATION KEY STARTED"); + const { fd, sections } = await _iden3_binfileutils.readBinFile(zkeyName, "zkey", 2); + const zkey = await readHeader$1(fd, sections); + if (logger) logger.info("> Detected protocol: " + zkey.protocol); + let res; + if (zkey.protocol === "groth16") res = await groth16Vk(zkey, fd, sections); + else if (zkey.protocol === "plonk") res = await plonkVk(zkey); + else if (zkey.protocolId && zkey.protocolId === 10) res = await exportFFlonkVk(zkey, logger); + else throw new Error("zkey file protocol unrecognized"); + await fd.close(); + if (logger) logger.info("EXPORT VERIFICATION KEY FINISHED"); + return res; + } + async function groth16Vk(zkey, fd, sections) { + const curve = await getCurveFromQ(zkey.q); + const sG1 = curve.G1.F.n8 * 2; + const alphaBeta = await curve.pairing(zkey.vk_alpha_1, zkey.vk_beta_2); + let vKey = { + protocol: zkey.protocol, + curve: curve.name, + nPublic: zkey.nPublic, + vk_alpha_1: curve.G1.toObject(zkey.vk_alpha_1), + vk_beta_2: curve.G2.toObject(zkey.vk_beta_2), + vk_gamma_2: curve.G2.toObject(zkey.vk_gamma_2), + vk_delta_2: curve.G2.toObject(zkey.vk_delta_2), + vk_alphabeta_12: curve.Gt.toObject(alphaBeta) + }; + await _iden3_binfileutils.startReadUniqueSection(fd, sections, 3); + vKey.IC = []; + for (let i = 0; i <= zkey.nPublic; i++) { + const buff = await fd.read(sG1); + const P = curve.G1.toObject(buff); + vKey.IC.push(P); + } + await _iden3_binfileutils.endReadSection(fd); + vKey = stringifyBigInts$2(vKey); + return vKey; + } + async function plonkVk(zkey) { + const curve = await getCurveFromQ(zkey.q); + let vKey = { + protocol: zkey.protocol, + curve: curve.name, + nPublic: zkey.nPublic, + power: zkey.power, + k1: curve.Fr.toObject(zkey.k1), + k2: curve.Fr.toObject(zkey.k2), + Qm: curve.G1.toObject(zkey.Qm), + Ql: curve.G1.toObject(zkey.Ql), + Qr: curve.G1.toObject(zkey.Qr), + Qo: curve.G1.toObject(zkey.Qo), + Qc: curve.G1.toObject(zkey.Qc), + S1: curve.G1.toObject(zkey.S1), + S2: curve.G1.toObject(zkey.S2), + S3: curve.G1.toObject(zkey.S3), + X_2: curve.G2.toObject(zkey.X_2), + w: curve.Fr.toObject(curve.Fr.w[zkey.power]) + }; + vKey = stringifyBigInts$2(vKey); + return vKey; + } + async function exportFFlonkVk(zkey, _logger) { + const curve = await getCurveFromQ(zkey.q); + return stringifyBigInts$2({ + protocol: zkey.protocol, + curve: curve.name, + nPublic: zkey.nPublic, + power: zkey.power, + k1: curve.Fr.toObject(zkey.k1), + k2: curve.Fr.toObject(zkey.k2), + w: curve.Fr.toObject(curve.Fr.w[zkey.power]), + w3: curve.Fr.toObject(zkey.w3), + w4: curve.Fr.toObject(zkey.w4), + w8: curve.Fr.toObject(zkey.w8), + wr: curve.Fr.toObject(zkey.wr), + X_2: curve.G2.toObject(zkey.X_2), + C0: curve.G1.toObject(zkey.C0) + }); + } + //#endregion + //#region src/zkey.js + var zkey_exports = /* @__PURE__ */ __exportAll({ + beacon: () => beacon, + bellmanContribute: () => bellmanContribute, + contribute: () => phase2contribute, + exportBellman: () => phase2exportMPCParams, + exportJson: () => zkeyExportJson, + exportSolidityVerifier: () => null, + exportVerificationKey: () => zkeyExportVerificationKey, + importBellman: () => phase2importMPCParams, + newZKey: () => newZKey, + verifyFromInit: () => phase2verifyFromInit, + verifyFromR1cs: () => phase2verifyFromR1cs + }); + //#endregion + //#region src/plonk_setup.js + async function plonkSetup(r1csName, ptauName, zkeyName, logger) { + if (globalThis.gc) globalThis.gc(); + const { fd: fdPTau, sections: sectionsPTau } = await (0, _iden3_binfileutils.readBinFile)(ptauName, "ptau", 1, 1 << 22, 1 << 24); + const { curve, power } = await readPTauHeader(fdPTau, sectionsPTau); + const { fd: fdR1cs, sections: sectionsR1cs } = await (0, _iden3_binfileutils.readBinFile)(r1csName, "r1cs", 1, 1 << 22, 1 << 24); + const r1cs = await (0, r1csfile.readR1csFd)(fdR1cs, sectionsR1cs, { + loadConstraints: true, + loadCustomGates: true + }); + const sG1 = curve.G1.F.n8 * 2; + const G1 = curve.G1; + const sG2 = curve.G2.F.n8 * 2; + const Fr = curve.Fr; + const n8r = curve.Fr.n8; + if (logger) logger.info("Reading r1cs"); + await (0, _iden3_binfileutils.readSection)(fdR1cs, sectionsR1cs, 2); + const plonkConstraints = new BigArray(); + const plonkAdditions = new BigArray(); + let plonkNVars = r1cs.nVars; + const nPublic = r1cs.nOutputs + r1cs.nPubInputs; + await processConstraints(curve.Fr, r1cs, logger); + if (globalThis.gc) globalThis.gc(); + const fdZKey = await (0, _iden3_binfileutils.createBinFile)(zkeyName, "zkey", 1, 14, 1 << 22, 1 << 24); + if (r1cs.prime != curve.r) { + if (logger) logger.error("r1cs curve does not match powers of tau ceremony curve"); + return -1; + } + let cirPower = log2(plonkConstraints.length - 1) + 1; + if (cirPower < 3) cirPower = 3; + const domainSize = 2 ** cirPower; + if (logger) logger.info("Plonk constraints: " + plonkConstraints.length); + if (cirPower > power) { + if (logger) logger.error(`circuit too big for this power of tau ceremony. ${plonkConstraints.length} > 2**${power}`); + return -1; + } + if (!sectionsPTau[12]) { + if (logger) logger.error("Powers of tau is not prepared."); + return -1; + } + const LPoints = new ffjavascript.BigBuffer(domainSize * sG1); + const o = sectionsPTau[12][0].p + (2 ** cirPower - 1) * sG1; + await fdPTau.readToBuffer(LPoints, 0, domainSize * sG1, o); + const [k1, k2] = getK1K2(); + const vk = {}; + await writeAdditions(3, "Additions"); + if (globalThis.gc) globalThis.gc(); + await writeWitnessMap(4, 0, "Amap"); + if (globalThis.gc) globalThis.gc(); + await writeWitnessMap(5, 1, "Bmap"); + if (globalThis.gc) globalThis.gc(); + await writeWitnessMap(6, 2, "Cmap"); + if (globalThis.gc) globalThis.gc(); + await writeQMap(7, 3, "Qm"); + if (globalThis.gc) globalThis.gc(); + await writeQMap(8, 4, "Ql"); + if (globalThis.gc) globalThis.gc(); + await writeQMap(9, 5, "Qr"); + if (globalThis.gc) globalThis.gc(); + await writeQMap(10, 6, "Qo"); + if (globalThis.gc) globalThis.gc(); + await writeQMap(11, 7, "Qc"); + if (globalThis.gc) globalThis.gc(); + await writeSigma(12, "sigma"); + if (globalThis.gc) globalThis.gc(); + await writeLs(13, "lagrange polynomials"); + if (globalThis.gc) globalThis.gc(); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 14); + const buffOut = new ffjavascript.BigBuffer((domainSize + 6) * sG1); + await fdPTau.readToBuffer(buffOut, 0, (domainSize + 6) * sG1, sectionsPTau[2][0].p); + await fdZKey.write(buffOut); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + if (globalThis.gc) globalThis.gc(); + await writeHeaders(); + await fdZKey.close(); + await fdR1cs.close(); + await fdPTau.close(); + if (logger) logger.info("Setup Finished"); + return; + async function processConstraints(Fr, r1cs, logger) { + function normalize(linearComb) { + const ss = Object.keys(linearComb); + for (let i = 0; i < ss.length; i++) if (linearComb[ss[i]] == 0n) delete linearComb[ss[i]]; + } + function join(linearComb1, k, linearComb2) { + const res = {}; + for (let s in linearComb1) if (typeof res[s] == "undefined") res[s] = Fr.mul(k, linearComb1[s]); + else res[s] = Fr.add(res[s], Fr.mul(k, linearComb1[s])); + for (let s in linearComb2) if (typeof res[s] == "undefined") res[s] = linearComb2[s]; + else res[s] = Fr.add(res[s], linearComb2[s]); + normalize(res); + return res; + } + function reduceCoefs(linearComb, maxC) { + const res = { + k: Fr.zero, + s: [], + coefs: [] + }; + const cs = []; + for (let s in linearComb) if (s == 0) res.k = Fr.add(res.k, linearComb[s]); + else if (linearComb[s] != 0n) cs.push([Number(s), linearComb[s]]); + while (cs.length > maxC) { + const c1 = cs.shift(); + const c2 = cs.shift(); + const sl = c1[0]; + const sr = c2[0]; + const so = plonkNVars++; + const qm = Fr.zero; + const ql = Fr.neg(c1[1]); + const qr = Fr.neg(c2[1]); + const qo = Fr.one; + const qc = Fr.zero; + plonkConstraints.push([ + sl, + sr, + so, + qm, + ql, + qr, + qo, + qc + ]); + plonkAdditions.push([ + sl, + sr, + c1[1], + c2[1] + ]); + cs.push([so, Fr.one]); + } + for (let i = 0; i < cs.length; i++) { + res.s[i] = cs[i][0]; + res.coefs[i] = cs[i][1]; + } + while (res.coefs.length < maxC) { + res.s.push(0); + res.coefs.push(Fr.zero); + } + return res; + } + function addConstraintSum(lc) { + const C = reduceCoefs(lc, 3); + const sl = C.s[0]; + const sr = C.s[1]; + const so = C.s[2]; + const qm = Fr.zero; + const ql = C.coefs[0]; + const qr = C.coefs[1]; + const qo = C.coefs[2]; + const qc = C.k; + plonkConstraints.push([ + sl, + sr, + so, + qm, + ql, + qr, + qo, + qc + ]); + } + function addConstraintMul(lcA, lcB, lcC) { + const A = reduceCoefs(lcA, 1); + const B = reduceCoefs(lcB, 1); + const C = reduceCoefs(lcC, 1); + const sl = A.s[0]; + const sr = B.s[0]; + const so = C.s[0]; + const qm = Fr.mul(A.coefs[0], B.coefs[0]); + const ql = Fr.mul(A.coefs[0], B.k); + const qr = Fr.mul(A.k, B.coefs[0]); + const qo = Fr.neg(C.coefs[0]); + const qc = Fr.sub(Fr.mul(A.k, B.k), C.k); + plonkConstraints.push([ + sl, + sr, + so, + qm, + ql, + qr, + qo, + qc + ]); + } + function getLinearCombinationType(lc) { + let k = Fr.zero; + let n = 0; + const ss = Object.keys(lc); + for (let i = 0; i < ss.length; i++) if (lc[ss[i]] == 0n) delete lc[ss[i]]; + else if (ss[i] == 0) k = Fr.add(k, lc[ss[i]]); + else n++; + if (n > 0) return n.toString(); + if (k != Fr.zero) return "k"; + return "0"; + } + function process(lcA, lcB, lcC) { + const lctA = getLinearCombinationType(lcA); + const lctB = getLinearCombinationType(lcB); + if (lctA === "0" || lctB === "0") { + normalize(lcC); + addConstraintSum(lcC); + } else if (lctA === "k") addConstraintSum(join(lcB, lcA[0], lcC)); + else if (lctB === "k") addConstraintSum(join(lcA, lcB[0], lcC)); + else addConstraintMul(lcA, lcB, lcC); + } + for (let s = 1; s <= nPublic; s++) { + const sl = s; + const sr = 0; + const so = 0; + const qm = Fr.zero; + const ql = Fr.one; + const qr = Fr.zero; + const qo = Fr.zero; + const qc = Fr.zero; + plonkConstraints.push([ + sl, + sr, + so, + qm, + ql, + qr, + qo, + qc + ]); + } + for (let c = 0; c < r1cs.constraints.length; c++) { + if (logger && c % 1e4 === 0) logger.debug(`processing constraints: ${c}/${r1cs.nConstraints}`); + process(...r1cs.constraints[c]); + } + } + async function writeWitnessMap(sectionNum, posConstraint, name) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); + for (let i = 0; i < plonkConstraints.length; i++) { + await fdZKey.writeULE32(plonkConstraints[i][posConstraint]); + if (logger && i % 1e6 == 0) logger.debug(`writing ${name}: ${i}/${plonkConstraints.length}`); + } + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeQMap(sectionNum, posConstraint, name) { + let Q = new ffjavascript.BigBuffer(domainSize * n8r); + for (let i = 0; i < plonkConstraints.length; i++) { + Q.set(plonkConstraints[i][posConstraint], i * n8r); + if (logger && i % 1e6 == 0) logger.debug(`writing ${name}: ${i}/${plonkConstraints.length}`); + } + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); + await writeP4(Q); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + Q = await Fr.batchFromMontgomery(Q); + vk[name] = await curve.G1.multiExpAffine(LPoints, Q, logger, "multiexp " + name); + } + async function writeP4(buff) { + const q = await Fr.ifft(buff); + const q4 = new ffjavascript.BigBuffer(domainSize * n8r * 4); + q4.set(q, 0); + const Q4 = await Fr.fft(q4); + await fdZKey.write(q); + await fdZKey.write(Q4); + } + async function writeAdditions(sectionNum, name) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); + const buffOut = new Uint8Array(8 + 2 * n8r); + const buffOutV = new DataView(buffOut.buffer); + for (let i = 0; i < plonkAdditions.length; i++) { + const addition = plonkAdditions[i]; + let o = 0; + buffOutV.setUint32(o, addition[0], true); + o += 4; + buffOutV.setUint32(o, addition[1], true); + o += 4; + buffOut.set(addition[2], o); + o += n8r; + buffOut.set(addition[3], o); + await fdZKey.write(buffOut); + if (logger && i % 1e6 == 0) logger.debug(`writing ${name}: ${i}/${plonkAdditions.length}`); + } + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeSigma(sectionNum, name) { + const sigma = new ffjavascript.BigBuffer(n8r * domainSize * 3); + const lastAparence = new BigArray(plonkNVars); + const firstPos = new BigArray(plonkNVars); + let w = Fr.one; + for (let i = 0; i < domainSize; i++) { + if (i < plonkConstraints.length) { + buildSigma(plonkConstraints[i][0], i); + buildSigma(plonkConstraints[i][1], domainSize + i); + buildSigma(plonkConstraints[i][2], domainSize * 2 + i); + } else { + buildSigma(0, i); + buildSigma(0, domainSize + i); + buildSigma(0, domainSize * 2 + i); + } + w = Fr.mul(w, Fr.w[cirPower]); + if (logger && i % 1e6 == 0) logger.debug(`writing ${name} phase1: ${i}/${plonkConstraints.length}`); + } + for (let s = 0; s < plonkNVars; s++) { + if (typeof firstPos[s] !== "undefined") sigma.set(lastAparence[s], firstPos[s] * n8r); + else console.log("Variable not used"); + if (logger && s % 1e6 == 0) logger.debug(`writing ${name} phase2: ${s}/${plonkNVars}`); + } + if (globalThis.gc) globalThis.gc(); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); + let S1 = sigma.slice(0, domainSize * n8r); + await writeP4(S1); + if (globalThis.gc) globalThis.gc(); + let S2 = sigma.slice(domainSize * n8r, domainSize * n8r * 2); + await writeP4(S2); + if (globalThis.gc) globalThis.gc(); + let S3 = sigma.slice(domainSize * n8r * 2, domainSize * n8r * 3); + await writeP4(S3); + if (globalThis.gc) globalThis.gc(); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + S1 = await Fr.batchFromMontgomery(S1); + S2 = await Fr.batchFromMontgomery(S2); + S3 = await Fr.batchFromMontgomery(S3); + vk.S1 = await curve.G1.multiExpAffine(LPoints, S1, logger, "multiexp S1"); + if (globalThis.gc) globalThis.gc(); + vk.S2 = await curve.G1.multiExpAffine(LPoints, S2, logger, "multiexp S2"); + if (globalThis.gc) globalThis.gc(); + vk.S3 = await curve.G1.multiExpAffine(LPoints, S3, logger, "multiexp S3"); + if (globalThis.gc) globalThis.gc(); + function buildSigma(s, p) { + if (typeof lastAparence[s] === "undefined") firstPos[s] = p; + else sigma.set(lastAparence[s], p * n8r); + let v; + if (p < domainSize) v = w; + else if (p < 2 * domainSize) v = Fr.mul(w, k1); + else v = Fr.mul(w, k2); + lastAparence[s] = v; + } + } + async function writeLs(sectionNum, name) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); + const l = Math.max(nPublic, 1); + for (let i = 0; i < l; i++) { + let buff = new ffjavascript.BigBuffer(domainSize * n8r); + buff.set(Fr.one, i * n8r); + await writeP4(buff); + if (logger) logger.debug(`writing ${name} ${i}/${l}`); + } + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeHeaders() { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 1); + await fdZKey.writeULE32(2); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 2); + const primeQ = curve.q; + const n8q = (Math.floor((ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) + 1) * 8; + const primeR = curve.r; + const n8r = (Math.floor((ffjavascript.Scalar.bitLength(primeR) - 1) / 64) + 1) * 8; + await fdZKey.writeULE32(n8q); + await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeQ, n8q); + await fdZKey.writeULE32(n8r); + await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeR, n8r); + await fdZKey.writeULE32(plonkNVars); + await fdZKey.writeULE32(nPublic); + await fdZKey.writeULE32(domainSize); + await fdZKey.writeULE32(plonkAdditions.length); + await fdZKey.writeULE32(plonkConstraints.length); + await fdZKey.write(k1); + await fdZKey.write(k2); + await fdZKey.write(G1.toAffine(vk.Qm)); + await fdZKey.write(G1.toAffine(vk.Ql)); + await fdZKey.write(G1.toAffine(vk.Qr)); + await fdZKey.write(G1.toAffine(vk.Qo)); + await fdZKey.write(G1.toAffine(vk.Qc)); + await fdZKey.write(G1.toAffine(vk.S1)); + await fdZKey.write(G1.toAffine(vk.S2)); + await fdZKey.write(G1.toAffine(vk.S3)); + let bX_2; + bX_2 = await fdPTau.read(sG2, sectionsPTau[3][0].p + sG2); + await fdZKey.write(bX_2); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + function getK1K2() { + let k1 = Fr.two; + while (isIncluded(k1, [], cirPower)) Fr.add(k1, Fr.one); + let k2 = Fr.add(k1, Fr.one); + while (isIncluded(k2, [k1], cirPower)) Fr.add(k2, Fr.one); + return [k1, k2]; + function isIncluded(k, kArr, pow) { + const domainSize = 2 ** pow; + let w = Fr.one; + for (let i = 0; i < domainSize; i++) { + if (Fr.eq(k, w)) return true; + for (let j = 0; j < kArr.length; j++) if (Fr.eq(k, Fr.mul(kArr[j], w))) return true; + w = Fr.mul(w, Fr.w[pow]); + } + return false; + } + } + } + //#endregion + //#region src/proof.js + var Proof = class { + constructor(curve, logger) { + this.curve = curve; + this.logger = logger; + this.resetProof(); + } + resetProof() { + this.polynomials = {}; + this.evaluations = {}; + } + addPolynomial(key, polynomial) { + if (key in this.polynomials) this.logger.warn(`proof: polynomial.${key} already exist in proof`); + this.polynomials[key] = polynomial; + } + getPolynomial(key) { + if (!(key in this.polynomials)) this.logger.warn(`proof: polynomial ${key} does not exist in proof`); + return this.polynomials[key]; + } + addEvaluation(key, evaluation) { + if (key in this.evaluations) this.logger.warn(`proof: evaluations.${key} already exist in proof`); + this.evaluations[key] = evaluation; + } + getEvaluation(key) { + if (!(key in this.evaluations)) this.logger.warn(`proof: evaluation ${key} does not exist in proof`); + return this.evaluations[key]; + } + toObjectProof(splitFields = true) { + let res = splitFields ? { + polynomials: {}, + evaluations: {} + } : {}; + Object.keys(this.polynomials).forEach((key) => { + const value = this.curve.G1.toObject(this.polynomials[key]); + if (splitFields) res.polynomials[key] = value; + else res[key] = value; + }); + Object.keys(this.evaluations).forEach((key) => { + const value = this.curve.Fr.toObject(this.evaluations[key]); + if (splitFields) res.evaluations[key] = value; + else res[key] = value; + }); + return res; + } + fromObjectProof(objectProof) { + this.resetProof(); + Object.keys(objectProof.polynomials).forEach((key) => { + this.polynomials[key] = this.curve.G1.fromObject(objectProof.polynomials[key]); + }); + Object.keys(objectProof.evaluations).forEach((key) => { + this.evaluations[key] = this.curve.Fr.fromObject(objectProof.evaluations[key]); + }); + } + }; + //#endregion + //#region node_modules/@noble/hashes/sha3.js + /** + * SHA3 (keccak) hash function, based on a new "Sponge function" design. + * Different from older hashes, the internal state is bigger than output size. + * + * Check out [FIPS-202](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf), + * [Website](https://keccak.team/keccak.html), + * [the differences between SHA-3 and Keccak](https://crypto.stackexchange.com/questions/15727/what-are-the-key-differences-between-the-draft-sha-3-standard-and-the-keccak-sub). + * + * Check out `sha3-addons` module for cSHAKE, k12, and others. + * @module + */ + var _0n = BigInt(0); + var _1n = BigInt(1); + var _2n = BigInt(2); + var _7n = BigInt(7); + var _256n = BigInt(256); + var _0x71n = BigInt(113); + var SHA3_PI = []; + var SHA3_ROTL = []; + var _SHA3_IOTA = []; + for (let round = 0, R = _1n, x = 1, y = 0; round < 24; round++) { + [x, y] = [y, (2 * x + 3 * y) % 5]; + SHA3_PI.push(2 * (5 * y + x)); + SHA3_ROTL.push((round + 1) * (round + 2) / 2 % 64); + let t = _0n; + for (let j = 0; j < 7; j++) { + R = (R << _1n ^ (R >> _7n) * _0x71n) % _256n; + if (R & _2n) t ^= _1n << (_1n << BigInt(j)) - _1n; + } + _SHA3_IOTA.push(t); + } + var IOTAS = split(_SHA3_IOTA, true); + var SHA3_IOTA_H = IOTAS[0]; + var SHA3_IOTA_L = IOTAS[1]; + var rotlH = (h, l, s) => s > 32 ? rotlBH(h, l, s) : rotlSH(h, l, s); + var rotlL = (h, l, s) => s > 32 ? rotlBL(h, l, s) : rotlSL(h, l, s); + /** `keccakf1600` internal function, additionally allows to adjust round count. */ + function keccakP(s, rounds = 24) { + const B = new Uint32Array(10); + for (let round = 24 - rounds; round < 24; round++) { + for (let x = 0; x < 10; x++) B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40]; + for (let x = 0; x < 10; x += 2) { + const idx1 = (x + 8) % 10; + const idx0 = (x + 2) % 10; + const B0 = B[idx0]; + const B1 = B[idx0 + 1]; + const Th = rotlH(B0, B1, 1) ^ B[idx1]; + const Tl = rotlL(B0, B1, 1) ^ B[idx1 + 1]; + for (let y = 0; y < 50; y += 10) { + s[x + y] ^= Th; + s[x + y + 1] ^= Tl; + } + } + let curH = s[2]; + let curL = s[3]; + for (let t = 0; t < 24; t++) { + const shift = SHA3_ROTL[t]; + const Th = rotlH(curH, curL, shift); + const Tl = rotlL(curH, curL, shift); + const PI = SHA3_PI[t]; + curH = s[PI]; + curL = s[PI + 1]; + s[PI] = Th; + s[PI + 1] = Tl; + } + for (let y = 0; y < 50; y += 10) { + for (let x = 0; x < 10; x++) B[x] = s[y + x]; + for (let x = 0; x < 10; x++) s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10]; + } + s[0] ^= SHA3_IOTA_H[round]; + s[1] ^= SHA3_IOTA_L[round]; + } + clean(B); + } + /** Keccak sponge function. */ + var Keccak = class Keccak { + state; + pos = 0; + posOut = 0; + finished = false; + state32; + destroyed = false; + blockLen; + suffix; + outputLen; + enableXOF = false; + rounds; + constructor(blockLen, suffix, outputLen, enableXOF = false, rounds = 24) { + this.blockLen = blockLen; + this.suffix = suffix; + this.outputLen = outputLen; + this.enableXOF = enableXOF; + this.rounds = rounds; + anumber(outputLen, "outputLen"); + if (!(0 < blockLen && blockLen < 200)) throw new Error("only keccak-f1600 function is supported"); + this.state = new Uint8Array(200); + this.state32 = u32(this.state); + } + clone() { + return this._cloneInto(); + } + keccak() { + swap32IfBE(this.state32); + keccakP(this.state32, this.rounds); + swap32IfBE(this.state32); + this.posOut = 0; + this.pos = 0; + } + update(data) { + aexists(this); + abytes(data); + const { blockLen, state } = this; + const len = data.length; + for (let pos = 0; pos < len;) { + const take = Math.min(blockLen - this.pos, len - pos); + for (let i = 0; i < take; i++) state[this.pos++] ^= data[pos++]; + if (this.pos === blockLen) this.keccak(); + } + return this; + } + finish() { + if (this.finished) return; + this.finished = true; + const { state, suffix, pos, blockLen } = this; + state[pos] ^= suffix; + if ((suffix & 128) !== 0 && pos === blockLen - 1) this.keccak(); + state[blockLen - 1] ^= 128; + this.keccak(); + } + writeInto(out) { + aexists(this, false); + abytes(out); + this.finish(); + const bufferOut = this.state; + const { blockLen } = this; + for (let pos = 0, len = out.length; pos < len;) { + if (this.posOut >= blockLen) this.keccak(); + const take = Math.min(blockLen - this.posOut, len - pos); + out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos); + this.posOut += take; + pos += take; + } + return out; + } + xofInto(out) { + if (!this.enableXOF) throw new Error("XOF is not possible for this instance"); + return this.writeInto(out); + } + xof(bytes) { + anumber(bytes); + return this.xofInto(new Uint8Array(bytes)); + } + digestInto(out) { + aoutput(out, this); + if (this.finished) throw new Error("digest() was already called"); + this.writeInto(out); + this.destroy(); + return out; + } + digest() { + return this.digestInto(new Uint8Array(this.outputLen)); + } + destroy() { + this.destroyed = true; + clean(this.state); + } + _cloneInto(to) { + const { blockLen, suffix, outputLen, rounds, enableXOF } = this; + to ||= new Keccak(blockLen, suffix, outputLen, enableXOF, rounds); + to.state32.set(this.state32); + to.pos = this.pos; + to.posOut = this.posOut; + to.finished = this.finished; + to.rounds = rounds; + to.suffix = suffix; + to.outputLen = outputLen; + to.enableXOF = enableXOF; + to.destroyed = this.destroyed; + return to; + } + }; + var genKeccak = (suffix, blockLen, outputLen, info = {}) => createHasher(() => new Keccak(blockLen, suffix, outputLen), info); + /** keccak-256 hash function. Different from SHA3-256. */ + var keccak_256 = /* @__PURE__ */ genKeccak(1, 136, 32); + //#endregion + //#region src/Keccak256Transcript.js + var POLYNOMIAL = 0; + var SCALAR = 1; + var Keccak256Transcript = class { + constructor(curve) { + this.G1 = curve.G1; + this.Fr = curve.Fr; + this.reset(); + } + reset() { + this.data = []; + } + addPolCommitment(polynomialCommitment) { + this.data.push({ + type: POLYNOMIAL, + data: polynomialCommitment + }); + } + addScalar(scalar) { + this.data.push({ + type: SCALAR, + data: scalar + }); + } + getChallenge() { + if (0 === this.data.length) throw new Error("Keccak256Transcript: No data to generate a transcript"); + let nPolynomials = 0; + let nScalars = 0; + this.data.forEach((element) => POLYNOMIAL === element.type ? nPolynomials++ : nScalars++); + let buffer = new Uint8Array(nScalars * this.Fr.n8 + nPolynomials * this.G1.F.n8 * 2); + let offset = 0; + for (let i = 0; i < this.data.length; i++) if (POLYNOMIAL === this.data[i].type) { + this.G1.toRprUncompressed(buffer, offset, this.data[i].data); + offset += this.G1.F.n8 * 2; + } else { + this.Fr.toRprBE(buffer, offset, this.data[i].data); + offset += this.Fr.n8; + } + const value = ffjavascript.Scalar.fromRprBE(keccak_256(buffer)); + return this.Fr.e(value); + } + }; + //#endregion + //#region src/mul_z.js + var MulZ = class { + static getZ1(Fr) { + return [ + Fr.zero, + Fr.add(Fr.e(-1), Fr.w[2]), + Fr.e(-2), + Fr.sub(Fr.e(-1), Fr.w[2]) + ]; + } + static getZ2(Fr) { + return [ + Fr.zero, + Fr.add(Fr.zero, Fr.mul(Fr.e(-2), Fr.w[2])), + Fr.e(4), + Fr.sub(Fr.zero, Fr.mul(Fr.e(-2), Fr.w[2])) + ]; + } + static getZ3(Fr) { + return [ + Fr.zero, + Fr.add(Fr.e(2), Fr.mul(Fr.e(2), Fr.w[2])), + Fr.e(-8), + Fr.sub(Fr.e(2), Fr.mul(Fr.e(2), Fr.w[2])) + ]; + } + static mul2(a, b, ap, bp, p, Fr) { + const Z1 = this.getZ1(Fr); + let r, rz; + const a_b = Fr.mul(a, b); + const a_bp = Fr.mul(a, bp); + const ap_b = Fr.mul(ap, b); + const ap_bp = Fr.mul(ap, bp); + r = a_b; + let a0 = Fr.add(a_bp, ap_b); + let a1 = ap_bp; + rz = a0; + if (p) rz = Fr.add(rz, Fr.mul(Z1[p], a1)); + return [r, rz]; + } + static mul3(a, b, c, ap, bp, cp, p, Fr) { + const Z1 = this.getZ1(Fr); + const Z2 = this.getZ2(Fr); + let r, rz; + const a_b = Fr.mul(a, b); + const a_bp = Fr.mul(a, bp); + const ap_b = Fr.mul(ap, b); + const ap_bp = Fr.mul(ap, bp); + r = Fr.mul(a_b, c); + let a0 = Fr.mul(ap_b, c); + a0 = Fr.add(a0, Fr.mul(a_bp, c)); + a0 = Fr.add(a0, Fr.mul(a_b, cp)); + let a1 = Fr.mul(ap_bp, c); + a1 = Fr.add(a1, Fr.mul(a_bp, cp)); + a1 = Fr.add(a1, Fr.mul(ap_b, cp)); + rz = a0; + if (p) { + const a2 = Fr.mul(ap_bp, cp); + rz = Fr.add(rz, Fr.mul(Z1[p], a1)); + rz = Fr.add(rz, Fr.mul(Z2[p], a2)); + } + return [r, rz]; + } + static mul4(a, b, c, d, ap, bp, cp, dp, p, Fr) { + const Z1 = this.getZ1(Fr); + const Z2 = this.getZ2(Fr); + const Z3 = this.getZ3(Fr); + let r, rz; + const a_b = Fr.mul(a, b); + const a_bp = Fr.mul(a, bp); + const ap_b = Fr.mul(ap, b); + const ap_bp = Fr.mul(ap, bp); + const c_d = Fr.mul(c, d); + const c_dp = Fr.mul(c, dp); + const cp_d = Fr.mul(cp, d); + const cp_dp = Fr.mul(cp, dp); + r = Fr.mul(a_b, c_d); + let a0 = Fr.mul(ap_b, c_d); + a0 = Fr.add(a0, Fr.mul(a_bp, c_d)); + a0 = Fr.add(a0, Fr.mul(a_b, cp_d)); + a0 = Fr.add(a0, Fr.mul(a_b, c_dp)); + let a1 = Fr.mul(ap_bp, c_d); + a1 = Fr.add(a1, Fr.mul(ap_b, cp_d)); + a1 = Fr.add(a1, Fr.mul(ap_b, c_dp)); + a1 = Fr.add(a1, Fr.mul(a_bp, cp_d)); + a1 = Fr.add(a1, Fr.mul(a_bp, c_dp)); + a1 = Fr.add(a1, Fr.mul(a_b, cp_dp)); + let a2 = Fr.mul(a_bp, cp_dp); + a2 = Fr.add(a2, Fr.mul(ap_b, cp_dp)); + a2 = Fr.add(a2, Fr.mul(ap_bp, c_dp)); + a2 = Fr.add(a2, Fr.mul(ap_bp, cp_d)); + let a3 = Fr.mul(ap_bp, cp_dp); + rz = a0; + if (p) { + rz = Fr.add(rz, Fr.mul(Z1[p], a1)); + rz = Fr.add(rz, Fr.mul(Z2[p], a2)); + rz = Fr.add(rz, Fr.mul(Z3[p], a3)); + } + return [r, rz]; + } + }; + //#endregion + //#region src/polynomial/polynomial.js + var Polynomial = class Polynomial { + constructor(coefficients, curve, logger) { + this.coef = coefficients; + this.curve = curve; + this.Fr = curve.Fr; + this.G1 = curve.G1; + this.logger = logger; + } + static async fromEvaluations(buffer, curve, logger) { + return new Polynomial(await curve.Fr.ifft(buffer), curve, logger); + } + static fromCoefficientsArray(array, curve, logger) { + const Fr = curve.Fr; + let buff = array.length > 32768 ? new ffjavascript.BigBuffer(array.length * Fr.n8) : new Uint8Array(array.length * Fr.n8); + for (let i = 0; i < array.length; i++) buff.set(array[i], i * Fr.n8); + return new Polynomial(buff, curve, logger); + } + static fromPolynomial(polynomial, curve, logger) { + let length = polynomial.length(); + let Fr = curve.Fr; + let buff = length > 32768 ? new ffjavascript.BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8); + buff.set(polynomial.coef.slice(), 0); + return new Polynomial(buff, curve, logger); + } + isEqual(polynomial) { + const degree = this.degree(); + if (degree !== polynomial.degree()) return false; + for (let i = 0; i < degree + 1; i++) if (!this.Fr.eq(this.getCoef(i), polynomial.getCoef(i))) return false; + return true; + } + blindCoefficients(blindingFactors) { + blindingFactors = blindingFactors || []; + const blindedCoefficients = this.length() + blindingFactors.length > 32768 ? new ffjavascript.BigBuffer((this.length() + blindingFactors.length) * this.Fr.n8) : new Uint8Array((this.length() + blindingFactors.length) * this.Fr.n8); + blindedCoefficients.set(this.coef, 0); + for (let i = 0; i < blindingFactors.length; i++) { + blindedCoefficients.set(this.Fr.add(blindedCoefficients.slice((this.length() + i) * this.Fr.n8, (this.length() + i + 1) * this.Fr.n8), blindingFactors[i]), (this.length() + i) * this.Fr.n8); + blindedCoefficients.set(this.Fr.sub(blindedCoefficients.slice(i * this.Fr.n8, (i + 1) * this.Fr.n8), blindingFactors[i]), i * this.Fr.n8); + } + this.coef = blindedCoefficients; + } + getCoef(index) { + const i_n8 = index * this.Fr.n8; + if (i_n8 + this.Fr.n8 > this.coef.byteLength) return this.Fr.zero; + return this.coef.slice(i_n8, i_n8 + this.Fr.n8); + } + setCoef(index, value) { + if (index > this.length() - 1) throw new Error("Coef index is not available"); + this.coef.set(value, index * this.Fr.n8); + } + static async to4T(buffer, domainSize, blindingFactors, Fr) { + blindingFactors = blindingFactors || []; + let a = await Fr.ifft(buffer); + const a4 = domainSize * 4 > 32768 ? new ffjavascript.BigBuffer(domainSize * 4 * Fr.n8) : new Uint8Array(domainSize * 4 * Fr.n8); + a4.set(a, 0); + const A4 = await Fr.fft(a4); + if (blindingFactors.length === 0) return [a, A4]; + const a1 = domainSize + blindingFactors.length > 32768 ? new ffjavascript.BigBuffer((domainSize + blindingFactors.length) * Fr.n8) : new Uint8Array((domainSize + blindingFactors.length) * Fr.n8); + a1.set(a, 0); + for (let i = 0; i < blindingFactors.length; i++) { + a1.set(Fr.add(a1.slice((domainSize + i) * Fr.n8, (domainSize + i + 1) * Fr.n8), blindingFactors[i]), (domainSize + i) * Fr.n8); + a1.set(Fr.sub(a1.slice(i * Fr.n8, (i + 1) * Fr.n8), blindingFactors[i]), i * Fr.n8); + } + return [a1, A4]; + } + length() { + let length = this.coef.byteLength / this.Fr.n8; + if (length !== Math.floor(this.coef.byteLength / this.Fr.n8)) throw new Error("Polynomial coefficients buffer has incorrect size"); + if (0 === length) { + if (this.logger) this.logger.warn("Polynomial has length zero"); + } + return length; + } + degree() { + for (let i = this.length() - 1; i > 0; i--) { + const i_n8 = i * this.Fr.n8; + if (!this.Fr.eq(this.Fr.zero, this.coef.slice(i_n8, i_n8 + this.Fr.n8))) return i; + } + return 0; + } + evaluate(point) { + let res = this.Fr.zero; + for (let i = this.degree() + 1; i > 0; i--) { + let i_n8 = i * this.Fr.n8; + const currentCoefficient = this.coef.slice(i_n8 - this.Fr.n8, i_n8); + res = this.Fr.add(currentCoefficient, this.Fr.mul(res, point)); + } + return res; + } + fastEvaluate(point) { + const Fr = this.Fr; + let nThreads = 3; + let nCoefs = this.degree() + 1; + let coefsThread = parseInt(nCoefs / nThreads); + let residualCoefs = nCoefs - coefsThread * nThreads; + let res = []; + let xN = []; + xN[0] = Fr.one; + for (let i = 0; i < nThreads; i++) { + res[i] = Fr.zero; + let nCoefs = i === nThreads - 1 ? coefsThread + residualCoefs : coefsThread; + for (let j = nCoefs; j > 0; j--) { + res[i] = Fr.add(this.getCoef(i * coefsThread + j - 1), Fr.mul(res[i], point)); + if (i === 0) xN[0] = Fr.mul(xN[0], point); + } + } + for (let i = 1; i < nThreads; i++) { + res[0] = Fr.add(res[0], Fr.mul(xN[i - 1], res[i])); + xN[i] = Fr.mul(xN[i - 1], xN[0]); + } + return res[0]; + } + add(polynomial, blindingValue) { + let other = false; + if (polynomial.length() > this.length()) other = true; + const thisLength = this.length(); + const polyLength = polynomial.length(); + for (let i = 0; i < Math.max(thisLength, polyLength); i++) { + const i_n8 = i * this.Fr.n8; + const a = i < thisLength ? this.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; + let b = i < polyLength ? polynomial.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; + if (blindingValue !== void 0) b = this.Fr.mul(b, blindingValue); + if (other) polynomial.coef.set(this.Fr.add(a, b), i_n8); + else this.coef.set(this.Fr.add(a, b), i_n8); + } + if (other) { + delete this.coef; + this.coef = polynomial.coef; + } + } + sub(polynomial, blindingValue) { + let other = false; + if (polynomial.length() > this.length()) other = true; + const thisLength = this.length(); + const polyLength = polynomial.length(); + for (let i = 0; i < Math.max(thisLength, polyLength); i++) { + const i_n8 = i * this.Fr.n8; + const a = i < thisLength ? this.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; + let b = i < polyLength ? polynomial.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; + if (blindingValue !== void 0) b = this.Fr.mul(b, blindingValue); + if (other) polynomial.coef.set(this.Fr.sub(a, b), i_n8); + else this.coef.set(this.Fr.sub(a, b), i_n8); + } + if (other) { + delete this.coef; + this.coef = polynomial.coef; + } + } + mulScalar(value) { + for (let i = 0; i < this.length(); i++) { + const i_n8 = i * this.Fr.n8; + this.coef.set(this.Fr.mul(this.coef.slice(i_n8, i_n8 + this.Fr.n8), value), i_n8); + } + } + addScalar(value) { + const currentValue = 0 === this.length() ? this.Fr.zero : this.coef.slice(0, this.Fr.n8); + this.coef.set(this.Fr.add(currentValue, value), 0); + } + subScalar(value) { + const currentValue = 0 === this.length() ? this.Fr.zero : this.coef.slice(0, this.Fr.n8); + this.coef.set(this.Fr.sub(currentValue, value), 0); + } + byXSubValue(value) { + const Fr = this.Fr; + const length = !Fr.eq(Fr.zero, this.getCoef(this.length() - 1)) ? this.length() + 1 : this.length(); + let pol = new Polynomial(length > 32768 ? new ffjavascript.BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8), this.curve, this.logger); + pol.coef.set(this.coef.slice(0, (length - 1) * Fr.n8), 32); + this.mulScalar(Fr.neg(value)); + pol.add(this); + this.coef = pol.coef; + } + byXNSubValue(n, value) { + const Fr = this.Fr; + const length = !(this.length() - n - 1 >= this.degree()) ? this.length() + n : this.length(); + let pol = new Polynomial(length > 32768 ? new ffjavascript.BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8), this.curve, this.logger); + pol.coef.set(this.coef.slice(0, (this.degree() + 1) * 32), n * 32); + this.mulScalar(value); + pol.add(this); + this.coef = pol.coef; + } + divBy(polynomial) { + const Fr = this.Fr; + const degreeA = this.degree(); + const degreeB = polynomial.degree(); + let polR = new Polynomial(this.coef, this.curve, this.logger); + this.coef = this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); + for (let i = degreeA - degreeB; i >= 0; i--) { + this.setCoef(i, Fr.div(polR.getCoef(i + degreeB), polynomial.getCoef(degreeB))); + for (let j = 0; j <= degreeB; j++) polR.setCoef(i + j, Fr.sub(polR.getCoef(i + j), Fr.mul(this.getCoef(i), polynomial.getCoef(j)))); + } + return polR; + } + divByMonic(m, beta) { + const Fr = this.Fr; + let d = this.degree(); + let quotient = new Polynomial(this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8), this.curve, this.logger); + let bArr = []; + for (let i = 0; i < m; i++) { + quotient.setCoef(d - i - m, this.getCoef(d - i)); + bArr[i] = this.getCoef(d - i); + } + let nThreads = m; + let j = 0; + for (let k = 0; k < nThreads; k++) for (let i = d - 2 * m - k; i >= 0; i = i - nThreads) { + if (i < 0) break; + let idx = k; + bArr[idx] = Fr.add(this.getCoef(i + m), Fr.mul(bArr[idx], beta)); + quotient.setCoef(i, bArr[idx]); + j = (j + 1) % m; + } + this.coef = quotient.coef; + } + divByVanishing(n, beta) { + if (this.degree() < n) throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); + const Fr = this.Fr; + let polR = new Polynomial(this.coef, this.curve, this.logger); + this.coef = this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); + for (let i = this.length() - 1; i >= n; i--) { + let leadingCoef = polR.getCoef(i); + if (Fr.eq(Fr.zero, leadingCoef)) continue; + polR.setCoef(i, Fr.zero); + polR.setCoef(i - n, Fr.add(polR.getCoef(i - n), Fr.mul(beta, leadingCoef))); + this.setCoef(i - n, Fr.add(this.getCoef(i - n), leadingCoef)); + } + return polR; + } + divByVanishing2(m, beta) { + if (this.degree() < m) throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); + const Fr = this.Fr; + let polR = new Polynomial(this.coef, this.curve, this.logger); + this.coef = this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); + let nThreads = 3; + let nTotal = this.length() - m; + let nElementsChunk = Math.floor(nTotal / nThreads); + let nElementsLast = nTotal - (nThreads - 1) * nElementsChunk; + console.log(nTotal); + console.log(nElementsChunk + " " + nElementsLast); + for (let k = 0; k < nThreads; k++) { + console.log("> Thread " + k); + for (let i = k === 0 ? nElementsLast : nElementsChunk; i > 0; i--) { + let idxDst = i - 1; + if (k !== 0) idxDst += (k - 1) * nElementsChunk + nElementsLast; + let idxSrc = idxDst + m; + let leadingCoef = polR.getCoef(idxSrc); + if (Fr.eq(Fr.zero, leadingCoef)) continue; + polR.setCoef(idxSrc, Fr.zero); + polR.setCoef(idxDst, Fr.add(polR.getCoef(idxDst), Fr.mul(beta, leadingCoef))); + this.setCoef(idxDst, Fr.add(this.getCoef(idxDst), leadingCoef)); + console.log(idxDst + " <-- " + idxSrc); + } + } + this.print(); + return polR; + } + fastDivByVanishing(data) { + const Fr = this.Fr; + for (let i = 0; i < data.length; i++) { + let m = data[i][0]; + let beta = data[i][1]; + if (this.degree() < m) throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); + let nThreads = 5; + let nElements = this.length() - m; + let nElementsBucket = Math.floor(nElements / nThreads / m); + let nElementsChunk = nElementsBucket * m; + let nElementsLast = nElements - nThreads * nElementsChunk; + let polTmp = new Polynomial(this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8), this.curve, this.logger); + let ptr = this.coef; + this.coef = polTmp.coef; + polTmp.coef = ptr; + for (let k = 0; k < nThreads; k++) { + let idx0 = (k + 1) * nElementsChunk + nElementsLast; + for (let i = 0; i < m; i++) this.setCoef(idx0 + i - m, polTmp.getCoef(idx0 + i)); + for (let i = 0; i < nElementsChunk - m; i++) { + let offset = idx0 - i - 1; + let val = Fr.add(polTmp.getCoef(offset), Fr.mul(beta, this.getCoef(offset))); + this.setCoef(offset - m, val); + } + } + let idx0 = nElementsLast; + let pending = nElementsLast; + for (let i = 0; i < m && pending; i++) { + this.setCoef(idx0 - i - 1, polTmp.getCoef(idx0 + m - i - 1)); + pending--; + } + for (let i = 0; i < pending; i++) { + let offset = idx0 - i - 1; + let val = Fr.add(polTmp.getCoef(offset), Fr.mul(beta, this.getCoef(offset))); + this.setCoef(offset - m, val); + } + let acc = []; + let betaPow = Fr.one; + for (let i = 0; i < nElementsBucket; i++) betaPow = Fr.mul(betaPow, beta); + let currentBeta = Fr.one; + for (let k = nThreads; k > 0; k--) { + let idThread = k - 1; + let idx0 = idThread * nElementsChunk + nElementsLast; + acc[idThread] = []; + for (let i = 0; i < m; i++) { + acc[idThread][i] = this.getCoef(idx0 + i); + if (k !== nThreads) acc[idThread][i] = Fr.add(acc[idThread][i], Fr.mul(betaPow, acc[idThread + 1][i])); + } + currentBeta = Fr.mul(currentBeta, betaPow); + } + for (let k = 0; k < nThreads; k++) { + let idx0 = k * nElementsChunk + nElementsLast; + let currentBeta = beta; + let currentM = m - 1; + let limit = k === 0 ? nElementsLast : nElementsChunk; + for (let i = 0; i < limit; i++) { + let offset = idx0 - i - 1; + let val = Fr.add(this.getCoef(offset), Fr.mul(currentBeta, acc[k][currentM])); + this.setCoef(offset, val); + if (currentM === 0) { + currentM = m - 1; + currentBeta = Fr.mul(currentBeta, beta); + } else currentM--; + } + } + } + } + divByXSubValue(value) { + const coefs = this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * this.Fr.n8) : new Uint8Array(this.length() * this.Fr.n8); + coefs.set(this.Fr.zero, (this.length() - 1) * this.Fr.n8); + coefs.set(this.coef.slice((this.length() - 1) * this.Fr.n8, this.length() * this.Fr.n8), (this.length() - 2) * this.Fr.n8); + for (let i = this.length() - 3; i >= 0; i--) { + let i_n8 = i * this.Fr.n8; + coefs.set(this.Fr.add(this.coef.slice(i_n8 + this.Fr.n8, i_n8 + 2 * this.Fr.n8), this.Fr.mul(value, coefs.slice(i_n8 + this.Fr.n8, i_n8 + 2 * this.Fr.n8))), i * this.Fr.n8); + } + if (!this.Fr.eq(this.coef.slice(0, this.Fr.n8), this.Fr.mul(this.Fr.neg(value), coefs.slice(0, this.Fr.n8)))) throw new Error("Polynomial does not divide"); + this.coef = coefs; + } + divZh(domainSize, extensions = 4) { + for (let i = 0; i < domainSize; i++) { + const i_n8 = i * this.Fr.n8; + this.coef.set(this.Fr.neg(this.coef.slice(i_n8, i_n8 + this.Fr.n8)), i_n8); + } + const upperBound = this.coef.byteLength / this.Fr.n8; + for (let i = domainSize; i < upperBound; i++) { + const i_n8 = i * this.Fr.n8; + const a = this.Fr.sub(this.coef.slice((i - domainSize) * this.Fr.n8, (i - domainSize) * this.Fr.n8 + this.Fr.n8), this.coef.slice(i_n8, i_n8 + this.Fr.n8)); + this.coef.set(a, i_n8); + if (i > domainSize * (extensions - 1) - extensions) { + if (!this.Fr.isZero(a)) throw new Error("Polynomial is not divisible"); + } + } + return this; + } + divByZerofier(n, beta) { + let Fr = this.Fr; + const invBeta = Fr.inv(beta); + const invBetaNeg = Fr.neg(invBeta); + let isOne = Fr.eq(Fr.one, invBetaNeg); + let isNegOne = Fr.eq(Fr.negone, invBetaNeg); + if (!isOne) for (let i = 0; i < n; i++) { + const i_n8 = i * this.Fr.n8; + let element; + if (isNegOne) element = Fr.neg(this.coef.slice(i_n8, i_n8 + this.Fr.n8)); + else element = Fr.mul(invBetaNeg, this.coef.slice(i_n8, i_n8 + this.Fr.n8)); + this.coef.set(element, i_n8); + } + isOne = Fr.eq(Fr.one, invBeta); + isNegOne = Fr.eq(Fr.negone, invBeta); + for (let i = n; i < this.length(); i++) { + const i_n8 = i * this.Fr.n8; + const i_prev_n8 = (i - n) * this.Fr.n8; + let element = this.Fr.sub(this.coef.slice(i_prev_n8, i_prev_n8 + this.Fr.n8), this.coef.slice(i_n8, i_n8 + this.Fr.n8)); + if (!isOne) if (isNegOne) element = Fr.neg(element); + else element = Fr.mul(invBeta, element); + this.coef.set(element, i_n8); + if (i > this.length() - n - 1) { + if (!this.Fr.isZero(element)) throw new Error("Polynomial is not divisible"); + } + } + return this; + } + byX() { + const coefs = this.length() + 1 > 32768 ? new ffjavascript.BigBuffer(this.coef.byteLength + this.Fr.n8) : new Uint8Array(this.coef.byteLength + this.Fr.n8); + coefs.set(this.Fr.zero, 0); + coefs.set(this.coef, this.Fr.n8); + this.coef = coefs; + } + static async expX(polynomial, n, truncate = false) { + const Fr = polynomial.Fr; + if (n < 1) throw new Error("Compute a new polynomial to a zero or negative number is not allowed"); + else if (1 === n) return await Polynomial.fromEvaluations(polynomial.coef, polynomial.curve, polynomial.logger); + const length = truncate ? polynomial.degree() : polynomial.length() - 1; + const bufferDst = length * n + 1 > 32768 ? new ffjavascript.BigBuffer((length * n + 1) * Fr.n8) : new Uint8Array((length * n + 1) * Fr.n8); + bufferDst.set(polynomial.getCoef(0), 0); + for (let i = 1; i <= length; i++) { + const i_sFr = i * Fr.n8; + const coef = polynomial.getCoef(i); + bufferDst.set(coef, i_sFr * n); + } + return new Polynomial(bufferDst, polynomial.curve, polynomial.logger); + } + split(numPols, degPols, blindingFactors) { + if (numPols < 1) throw new Error(`Polynomials can't be split in ${numPols} parts`); + else if (1 === numPols) return [this]; + if (0 !== blindingFactors.length && blindingFactors.length < numPols - 1) throw new Error(`Blinding factors length must be ${numPols - 1}`); + const chunkByteLength = (degPols + 1) * this.Fr.n8; + let res = []; + const numRealPols = Math.ceil((this.degree() + 1) * this.Fr.n8 / chunkByteLength); + if (numRealPols < numPols) for (let i = numRealPols; i < numPols; i++) res[i] = new Polynomial(new Uint8Array(this.Fr.n8), this.curve, this.logger); + numPols = Math.min(numPols, numRealPols); + for (let i = 0; i < numPols; i++) { + const isLast = numPols - 1 === i; + const byteLength = isLast ? this.coef.byteLength - (numPols - 1) * chunkByteLength : chunkByteLength + this.Fr.n8; + res[i] = new Polynomial(byteLength / this.Fr.n8 > 32768 ? new ffjavascript.BigBuffer(byteLength) : new Uint8Array(byteLength), this.curve, this.logger); + const fr = i * chunkByteLength; + const to = isLast ? this.coef.byteLength : (i + 1) * chunkByteLength; + res[i].coef.set(this.coef.slice(fr, to), 0); + if (!isLast) res[i].coef.set(blindingFactors[i], chunkByteLength); + if (0 !== i) { + const lowestDegree = this.Fr.sub(res[i].coef.slice(0, this.Fr.n8), blindingFactors[i - 1]); + res[i].coef.set(lowestDegree, 0); + } + if (isLast) res[i].truncate(); + } + return res; + } + truncate() { + const deg = this.degree(); + if (deg + 1 < this.coef.byteLength / this.Fr.n8) { + const newCoefs = deg + 1 > 32768 ? new ffjavascript.BigBuffer((deg + 1) * this.Fr.n8) : new Uint8Array((deg + 1) * this.Fr.n8); + newCoefs.set(this.coef.slice(0, (deg + 1) * this.Fr.n8), 0); + this.coef = newCoefs; + } + } + static lagrangePolynomialInterpolation(xArr, yArr, curve) { + const Fr = curve.Fr; + let polynomial = computeLagrangePolynomial(0); + for (let i = 1; i < xArr.length; i++) polynomial.add(computeLagrangePolynomial(i)); + return polynomial; + function computeLagrangePolynomial(i) { + let polynomial; + for (let j = 0; j < xArr.length; j++) { + if (j === i) continue; + if (polynomial === void 0) { + polynomial = new Polynomial(xArr.length > 32768 ? new ffjavascript.BigBuffer(xArr.length * Fr.n8) : new Uint8Array(xArr.length * Fr.n8), curve); + polynomial.setCoef(0, Fr.neg(xArr[j])); + polynomial.setCoef(1, Fr.one); + } else polynomial.byXSubValue(xArr[j]); + } + let denominator = polynomial.evaluate(xArr[i]); + denominator = Fr.inv(denominator); + const mulFactor = Fr.mul(yArr[i], denominator); + polynomial.mulScalar(mulFactor); + return polynomial; + } + } + static zerofierPolynomial(xArr, curve) { + const Fr = curve.Fr; + let polynomial = new Polynomial(xArr.length + 1 > 32768 ? new ffjavascript.BigBuffer((xArr.length + 1) * Fr.n8) : new Uint8Array((xArr.length + 1) * Fr.n8), curve); + polynomial.setCoef(0, Fr.neg(xArr[0])); + polynomial.setCoef(1, Fr.one); + for (let i = 1; i < xArr.length; i++) polynomial.byXSubValue(xArr[i]); + return polynomial; + } + print() { + const Fr = this.Fr; + let res = ""; + for (let i = this.degree(); i >= 0; i--) { + const coef = this.getCoef(i); + if (!Fr.eq(Fr.zero, coef)) { + if (Fr.isNegative(coef)) res += " - "; + else if (i !== this.degree()) res += " + "; + res += Fr.toString(coef); + if (i > 0) res += i > 1 ? "x^" + i : "x"; + } + } + console.log(res); + } + async multiExponentiation(PTau, name) { + const n = this.coef.byteLength / this.Fr.n8; + const PTauN = PTau.slice(0, n * this.G1.F.n8 * 2); + const bm = await this.Fr.batchFromMontgomery(this.coef); + let res = await this.G1.multiExpAffine(PTauN, bm, this.logger, name); + res = this.G1.toAffine(res); + return res; + } + }; + //#endregion + //#region src/polynomial/evaluations.js + var Evaluations = class Evaluations { + constructor(evaluations, curve, logger) { + this.eval = evaluations; + this.curve = curve; + this.Fr = curve.Fr; + this.logger = logger; + } + static async fromPolynomial(polynomial, extension, curve, logger) { + const coefficientsN = new ffjavascript.BigBuffer(polynomial.length() * extension * curve.Fr.n8); + coefficientsN.set(polynomial.coef, 0); + return new Evaluations(await curve.Fr.fft(coefficientsN), curve, logger); + } + getEvaluation(index) { + const i_n8 = index * this.Fr.n8; + if (i_n8 + this.Fr.n8 > this.eval.byteLength) throw new Error("Evaluations.getEvaluation() out of bounds"); + return this.eval.slice(i_n8, i_n8 + this.Fr.n8); + } + length() { + let length = this.eval.byteLength / this.Fr.n8; + if (length !== Math.floor(this.eval.byteLength / this.Fr.n8)) throw new Error("Polynomial evaluations buffer has incorrect size"); + if (0 === length) this.logger.warn("Polynomial has length zero"); + return length; + } + }; + //#endregion + //#region src/plonk_prove.js + var { stringifyBigInts: stringifyBigInts$1 } = ffjavascript.utils; + async function plonk16Prove(zkeyFileName, witnessFileName, logger, options) { + const { fd: fdWtns, sections: sectionsWtns } = await _iden3_binfileutils.readBinFile(witnessFileName, "wtns", 2, 1 << 25, 1 << 23); + if (logger) logger.debug("> Reading witness file"); + const wtns = await readHeader(fdWtns, sectionsWtns); + if (logger) logger.debug("> Reading zkey file"); + const { fd: fdZKey, sections: zkeySections } = await _iden3_binfileutils.readBinFile(zkeyFileName, "zkey", 2, 1 << 25, 1 << 23); + const zkey = await readHeader$1(fdZKey, zkeySections, void 0, options); + if (zkey.protocol != "plonk") throw new Error("zkey file is not plonk"); + if (!ffjavascript.Scalar.eq(zkey.r, wtns.q)) throw new Error("Curve of the witness does not match the curve of the proving key"); + if (wtns.nWitness != zkey.nVars - zkey.nAdditions) throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}, ${zkey.nAdditions}`); + const curve = zkey.curve; + const Fr = curve.Fr; + const n8r = curve.Fr.n8; + const sDomain = zkey.domainSize * n8r; + if (logger) { + logger.debug("----------------------------"); + logger.debug(" PLONK PROVE SETTINGS"); + logger.debug(` Curve: ${curve.name}`); + logger.debug(` Circuit power: ${zkey.power}`); + logger.debug(` Domain size: ${zkey.domainSize}`); + logger.debug(` Vars: ${zkey.nVars}`); + logger.debug(` Public vars: ${zkey.nPublic}`); + logger.debug(` Constraints: ${zkey.nConstraints}`); + logger.debug(` Additions: ${zkey.nAdditions}`); + logger.debug("----------------------------"); + } + if (logger) logger.debug("> Reading witness file data"); + const buffWitness = await _iden3_binfileutils.readSection(fdWtns, sectionsWtns, 2); + buffWitness.set(Fr.zero, 0); + const buffInternalWitness = new ffjavascript.BigBuffer(n8r * zkey.nAdditions); + let buffers = {}; + let polynomials = {}; + let evaluations = {}; + let challenges = {}; + let proof = new Proof(curve, logger); + const transcript = new Keccak256Transcript(curve); + if (logger) logger.debug(`> Reading Section 3. Additions`); + await calculateAdditions(); + if (logger) logger.debug(`> Reading Section 12. Sigma1, Sigma2 & Sigma 3`); + if (logger) logger.debug("··· Reading Sigma polynomials "); + polynomials.Sigma1 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.Sigma2 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.Sigma3 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + await fdZKey.readToBuffer(polynomials.Sigma1.coef, 0, sDomain, zkeySections[12][0].p); + await fdZKey.readToBuffer(polynomials.Sigma2.coef, 0, sDomain, zkeySections[12][0].p + 5 * sDomain); + await fdZKey.readToBuffer(polynomials.Sigma3.coef, 0, sDomain, zkeySections[12][0].p + 10 * sDomain); + if (logger) logger.debug("··· Reading Sigma evaluations"); + evaluations.Sigma1 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.Sigma2 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.Sigma3 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + await fdZKey.readToBuffer(evaluations.Sigma1.eval, 0, sDomain * 4, zkeySections[12][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.Sigma2.eval, 0, sDomain * 4, zkeySections[12][0].p + 6 * sDomain); + await fdZKey.readToBuffer(evaluations.Sigma3.eval, 0, sDomain * 4, zkeySections[12][0].p + 11 * sDomain); + if (logger) logger.debug(`> Reading Section 14. Powers of Tau`); + const PTau = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 14); + let publicSignals = []; + for (let i = 1; i <= zkey.nPublic; i++) { + const pub = buffWitness.slice(i * Fr.n8, i * Fr.n8 + Fr.n8); + publicSignals.push(ffjavascript.Scalar.fromRprLE(pub)); + } + if (logger) logger.debug(""); + if (logger) logger.debug("> ROUND 1"); + await round1(); + if (logger) logger.debug("> ROUND 2"); + await round2(); + if (logger) logger.debug("> ROUND 3"); + await round3(); + if (logger) logger.debug("> ROUND 4"); + await round4(); + if (logger) logger.debug("> ROUND 5"); + await round5(); + await fdZKey.close(); + await fdWtns.close(); + let _proof = proof.toObjectProof(false); + _proof.protocol = "plonk"; + _proof.curve = curve.name; + if (logger) logger.debug("PLONK PROVER FINISHED"); + return { + proof: stringifyBigInts$1(_proof), + publicSignals: stringifyBigInts$1(publicSignals) + }; + async function calculateAdditions() { + if (logger) logger.debug("··· Computing additions"); + const additionsBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 3); + const sSum = 8 + n8r * 2; + for (let i = 0; i < zkey.nAdditions; i++) { + if (logger && 0 !== i && i % 1e5 === 0) logger.debug(` addition ${i}/${zkey.nAdditions}`); + let offset = i * sSum; + const signalId1 = readUInt32(additionsBuff, offset); + offset += 4; + const signalId2 = readUInt32(additionsBuff, offset); + offset += 4; + const factor1 = additionsBuff.slice(offset, offset + n8r); + offset += n8r; + const factor2 = additionsBuff.slice(offset, offset + n8r); + const witness1 = getWitness(signalId1); + const witness2 = getWitness(signalId2); + const result = Fr.add(Fr.mul(factor1, witness1), Fr.mul(factor2, witness2)); + buffInternalWitness.set(result, n8r * i); + } + } + function readUInt32(b, o) { + const buff = b.slice(o, o + 4); + return new DataView(buff.buffer, buff.byteOffset, buff.byteLength).getUint32(0, true); + } + function getWitness(idx) { + if (idx < zkey.nVars - zkey.nAdditions) return buffWitness.slice(idx * n8r, idx * n8r + n8r); + else if (idx < zkey.nVars) return buffInternalWitness.slice((idx - (zkey.nVars - zkey.nAdditions)) * n8r, (idx - (zkey.nVars - zkey.nAdditions)) * n8r + n8r); + else return curve.Fr.zero; + } + async function round1() { + challenges.b = []; + for (let i = 1; i <= 11; i++) challenges.b[i] = curve.Fr.random(); + if (logger) logger.debug("> Computing A, B, C wire polynomials"); + await computeWirePolynomials(); + if (logger) logger.debug("> Computing A, B, C MSM"); + let commitA = await polynomials.A.multiExponentiation(PTau, "A"); + let commitB = await polynomials.B.multiExponentiation(PTau, "B"); + let commitC = await polynomials.C.multiExponentiation(PTau, "C"); + proof.addPolynomial("A", commitA); + proof.addPolynomial("B", commitB); + proof.addPolynomial("C", commitC); + return 0; + } + async function computeWirePolynomials() { + if (logger) logger.debug("··· Reading data from zkey file"); + buffers.A = new ffjavascript.BigBuffer(sDomain); + buffers.B = new ffjavascript.BigBuffer(sDomain); + buffers.C = new ffjavascript.BigBuffer(sDomain); + const aMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 4); + const bMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 5); + const cMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 6); + for (let i = 0; i < zkey.nConstraints; i++) { + const i_sFr = i * n8r; + const offset = i * 4; + const signalIdA = readUInt32(aMapBuff, offset); + buffers.A.set(getWitness(signalIdA), i_sFr); + const signalIdB = readUInt32(bMapBuff, offset); + buffers.B.set(getWitness(signalIdB), i_sFr); + const signalIdC = readUInt32(cMapBuff, offset); + buffers.C.set(getWitness(signalIdC), i_sFr); + } + buffers.A = await Fr.batchToMontgomery(buffers.A); + buffers.B = await Fr.batchToMontgomery(buffers.B); + buffers.C = await Fr.batchToMontgomery(buffers.C); + if (logger) logger.debug("··· Computing A ifft"); + polynomials.A = await Polynomial.fromEvaluations(buffers.A, curve, logger); + if (logger) logger.debug("··· Computing B ifft"); + polynomials.B = await Polynomial.fromEvaluations(buffers.B, curve, logger); + if (logger) logger.debug("··· Computing C ifft"); + polynomials.C = await Polynomial.fromEvaluations(buffers.C, curve, logger); + if (logger) logger.debug("··· Computing A fft"); + evaluations.A = await Evaluations.fromPolynomial(polynomials.A, 4, curve, logger); + if (logger) logger.debug("··· Computing B fft"); + evaluations.B = await Evaluations.fromPolynomial(polynomials.B, 4, curve, logger); + if (logger) logger.debug("··· Computing C fft"); + evaluations.C = await Evaluations.fromPolynomial(polynomials.C, 4, curve, logger); + polynomials.A.blindCoefficients([challenges.b[2], challenges.b[1]]); + polynomials.B.blindCoefficients([challenges.b[4], challenges.b[3]]); + polynomials.C.blindCoefficients([challenges.b[6], challenges.b[5]]); + if (polynomials.A.degree() >= zkey.domainSize + 2) throw new Error("A Polynomial is not well calculated"); + if (polynomials.B.degree() >= zkey.domainSize + 2) throw new Error("B Polynomial is not well calculated"); + if (polynomials.C.degree() >= zkey.domainSize + 2) throw new Error("C Polynomial is not well calculated"); + } + async function round2() { + if (logger) logger.debug("> Computing challenges beta and gamma"); + transcript.reset(); + transcript.addPolCommitment(zkey.Qm); + transcript.addPolCommitment(zkey.Ql); + transcript.addPolCommitment(zkey.Qr); + transcript.addPolCommitment(zkey.Qo); + transcript.addPolCommitment(zkey.Qc); + transcript.addPolCommitment(zkey.S1); + transcript.addPolCommitment(zkey.S2); + transcript.addPolCommitment(zkey.S3); + for (let i = 0; i < zkey.nPublic; i++) transcript.addScalar(buffers.A.slice(i * n8r, i * n8r + n8r)); + transcript.addPolCommitment(proof.getPolynomial("A")); + transcript.addPolCommitment(proof.getPolynomial("B")); + transcript.addPolCommitment(proof.getPolynomial("C")); + challenges.beta = transcript.getChallenge(); + if (logger) logger.debug("··· challenges.beta: " + Fr.toString(challenges.beta, 16)); + transcript.reset(); + transcript.addScalar(challenges.beta); + challenges.gamma = transcript.getChallenge(); + if (logger) logger.debug("··· challenges.gamma: " + Fr.toString(challenges.gamma, 16)); + if (logger) logger.debug("> Computing Z polynomial"); + await computeZ(); + if (logger) logger.debug("> Computing Z MSM"); + let commitZ = await polynomials.Z.multiExponentiation(PTau, "Z"); + proof.addPolynomial("Z", commitZ); + } + async function computeZ() { + if (logger) logger.debug("··· Computing Z evaluations"); + let numArr = new ffjavascript.BigBuffer(sDomain); + let denArr = new ffjavascript.BigBuffer(sDomain); + numArr.set(Fr.one, 0); + denArr.set(Fr.one, 0); + let w = Fr.one; + for (let i = 0; i < zkey.domainSize; i++) { + const i_n8r = i * n8r; + const a = buffers.A.slice(i_n8r, i_n8r + n8r); + const b = buffers.B.slice(i_n8r, i_n8r + n8r); + const c = buffers.C.slice(i_n8r, i_n8r + n8r); + const betaw = Fr.mul(challenges.beta, w); + let n1 = Fr.add(a, betaw); + n1 = Fr.add(n1, challenges.gamma); + let n2 = Fr.add(b, Fr.mul(zkey.k1, betaw)); + n2 = Fr.add(n2, challenges.gamma); + let n3 = Fr.add(c, Fr.mul(zkey.k2, betaw)); + n3 = Fr.add(n3, challenges.gamma); + let num = Fr.mul(n1, Fr.mul(n2, n3)); + let d1 = Fr.add(a, Fr.mul(evaluations.Sigma1.getEvaluation(i * 4), challenges.beta)); + d1 = Fr.add(d1, challenges.gamma); + let d2 = Fr.add(b, Fr.mul(evaluations.Sigma2.getEvaluation(i * 4), challenges.beta)); + d2 = Fr.add(d2, challenges.gamma); + let d3 = Fr.add(c, Fr.mul(evaluations.Sigma3.getEvaluation(i * 4), challenges.beta)); + d3 = Fr.add(d3, challenges.gamma); + let den = Fr.mul(d1, Fr.mul(d2, d3)); + num = Fr.mul(numArr.slice(i_n8r, i_n8r + n8r), num); + numArr.set(num, (i + 1) % zkey.domainSize * n8r); + den = Fr.mul(denArr.slice(i_n8r, i_n8r + n8r), den); + denArr.set(den, (i + 1) % zkey.domainSize * n8r); + w = Fr.mul(w, Fr.w[zkey.power]); + } + denArr = await Fr.batchInverse(denArr); + for (let i = 0; i < zkey.domainSize; i++) { + const i_sFr = i * n8r; + const z = Fr.mul(numArr.slice(i_sFr, i_sFr + n8r), denArr.slice(i_sFr, i_sFr + n8r)); + numArr.set(z, i_sFr); + } + buffers.Z = numArr; + if (!Fr.eq(numArr.slice(0, n8r), Fr.one)) throw new Error("Copy constraints does not match"); + if (logger) logger.debug("··· Computing Z ifft"); + polynomials.Z = await Polynomial.fromEvaluations(buffers.Z, curve, logger); + if (logger) logger.debug("··· Computing Z fft"); + evaluations.Z = await Evaluations.fromPolynomial(polynomials.Z, 4, curve, logger); + polynomials.Z.blindCoefficients([ + challenges.b[9], + challenges.b[8], + challenges.b[7] + ]); + if (polynomials.Z.degree() >= zkey.domainSize + 3) throw new Error("Z Polynomial is not well calculated"); + delete buffers.Z; + } + async function round3() { + if (logger) logger.debug("> Computing challenge alpha"); + transcript.reset(); + transcript.addScalar(challenges.beta); + transcript.addScalar(challenges.gamma); + transcript.addPolCommitment(proof.getPolynomial("Z")); + challenges.alpha = transcript.getChallenge(); + challenges.alpha2 = Fr.square(challenges.alpha); + if (logger) logger.debug("··· challenges.alpha: " + Fr.toString(challenges.alpha, 16)); + if (logger) logger.debug("> Computing T polynomial"); + await computeT(); + if (logger) logger.debug("> Computing T MSM"); + let commitT1 = await polynomials.T1.multiExponentiation(PTau, "T1"); + let commitT2 = await polynomials.T2.multiExponentiation(PTau, "T2"); + let commitT3 = await polynomials.T3.multiExponentiation(PTau, "T3"); + proof.addPolynomial("T1", commitT1); + proof.addPolynomial("T2", commitT2); + proof.addPolynomial("T3", commitT3); + } + async function computeT() { + if (logger) logger.debug(`··· Reading sections 8, 9, 7, 10, 11. Q selectors`); + evaluations.QL = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QR = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QM = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QO = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QC = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + await fdZKey.readToBuffer(evaluations.QL.eval, 0, sDomain * 4, zkeySections[8][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QR.eval, 0, sDomain * 4, zkeySections[9][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QM.eval, 0, sDomain * 4, zkeySections[7][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QO.eval, 0, sDomain * 4, zkeySections[10][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QC.eval, 0, sDomain * 4, zkeySections[11][0].p + sDomain); + evaluations.Lagrange = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4 * zkey.nPublic), curve, logger); + for (let i = 0; i < zkey.nPublic; i++) await fdZKey.readToBuffer(evaluations.Lagrange.eval, i * sDomain * 4, sDomain * 4, zkeySections[13][0].p + i * 5 * sDomain + sDomain); + buffers.T = new ffjavascript.BigBuffer(sDomain * 4); + buffers.Tz = new ffjavascript.BigBuffer(sDomain * 4); + if (logger) logger.debug("··· Computing T evaluations"); + let w = Fr.one; + for (let i = 0; i < zkey.domainSize * 4; i++) { + if (logger && 0 !== i && i % 1e5 === 0) logger.debug(` T evaluation ${i}/${zkey.domainSize * 4}`); + const a = evaluations.A.getEvaluation(i); + const b = evaluations.B.getEvaluation(i); + const c = evaluations.C.getEvaluation(i); + const z = evaluations.Z.getEvaluation(i); + const zw = evaluations.Z.getEvaluation((zkey.domainSize * 4 + 4 + i) % (zkey.domainSize * 4)); + const qm = evaluations.QM.getEvaluation(i); + const ql = evaluations.QL.getEvaluation(i); + const qr = evaluations.QR.getEvaluation(i); + const qo = evaluations.QO.getEvaluation(i); + const qc = evaluations.QC.getEvaluation(i); + const s1 = evaluations.Sigma1.getEvaluation(i); + const s2 = evaluations.Sigma2.getEvaluation(i); + const s3 = evaluations.Sigma3.getEvaluation(i); + const ap = Fr.add(challenges.b[2], Fr.mul(challenges.b[1], w)); + const bp = Fr.add(challenges.b[4], Fr.mul(challenges.b[3], w)); + const cp = Fr.add(challenges.b[6], Fr.mul(challenges.b[5], w)); + const w2 = Fr.square(w); + const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], w2), Fr.mul(challenges.b[8], w)), challenges.b[9]); + const wW = Fr.mul(w, Fr.w[zkey.power]); + const wW2 = Fr.square(wW); + const zWp = Fr.add(Fr.add(Fr.mul(challenges.b[7], wW2), Fr.mul(challenges.b[8], wW)), challenges.b[9]); + let pi = Fr.zero; + for (let j = 0; j < zkey.nPublic; j++) { + const offset = j * 4 * zkey.domainSize + i; + const lPol = evaluations.Lagrange.getEvaluation(offset); + const aVal = buffers.A.slice(j * n8r, (j + 1) * n8r); + pi = Fr.sub(pi, Fr.mul(lPol, aVal)); + } + let [e1, e1z] = MulZ.mul2(a, b, ap, bp, i % 4, Fr); + e1 = Fr.mul(e1, qm); + e1z = Fr.mul(e1z, qm); + e1 = Fr.add(e1, Fr.mul(a, ql)); + e1z = Fr.add(e1z, Fr.mul(ap, ql)); + e1 = Fr.add(e1, Fr.mul(b, qr)); + e1z = Fr.add(e1z, Fr.mul(bp, qr)); + e1 = Fr.add(e1, Fr.mul(c, qo)); + e1z = Fr.add(e1z, Fr.mul(cp, qo)); + e1 = Fr.add(e1, pi); + e1 = Fr.add(e1, qc); + const betaw = Fr.mul(challenges.beta, w); + let e2a = a; + e2a = Fr.add(e2a, betaw); + e2a = Fr.add(e2a, challenges.gamma); + let e2b = b; + e2b = Fr.add(e2b, Fr.mul(betaw, zkey.k1)); + e2b = Fr.add(e2b, challenges.gamma); + let e2c = c; + e2c = Fr.add(e2c, Fr.mul(betaw, zkey.k2)); + e2c = Fr.add(e2c, challenges.gamma); + let e2d = z; + let [e2, e2z] = MulZ.mul4(e2a, e2b, e2c, e2d, ap, bp, cp, zp, i % 4, Fr); + e2 = Fr.mul(e2, challenges.alpha); + e2z = Fr.mul(e2z, challenges.alpha); + let e3a = a; + e3a = Fr.add(e3a, Fr.mul(challenges.beta, s1)); + e3a = Fr.add(e3a, challenges.gamma); + let e3b = b; + e3b = Fr.add(e3b, Fr.mul(challenges.beta, s2)); + e3b = Fr.add(e3b, challenges.gamma); + let e3c = c; + e3c = Fr.add(e3c, Fr.mul(challenges.beta, s3)); + e3c = Fr.add(e3c, challenges.gamma); + let e3d = zw; + let [e3, e3z] = MulZ.mul4(e3a, e3b, e3c, e3d, ap, bp, cp, zWp, i % 4, Fr); + e3 = Fr.mul(e3, challenges.alpha); + e3z = Fr.mul(e3z, challenges.alpha); + let e4 = Fr.sub(z, Fr.one); + e4 = Fr.mul(e4, evaluations.Lagrange.getEvaluation(i)); + e4 = Fr.mul(e4, challenges.alpha2); + let e4z = Fr.mul(zp, evaluations.Lagrange.getEvaluation(i)); + e4z = Fr.mul(e4z, challenges.alpha2); + let t = Fr.add(Fr.sub(Fr.add(e1, e2), e3), e4); + let tz = Fr.add(Fr.sub(Fr.add(e1z, e2z), e3z), e4z); + buffers.T.set(t, i * n8r); + buffers.Tz.set(tz, i * n8r); + w = Fr.mul(w, Fr.w[zkey.power + 2]); + } + if (logger) logger.debug("··· Computing T ifft"); + polynomials.T = await Polynomial.fromEvaluations(buffers.T, curve, logger); + if (logger) logger.debug("··· Computing T / ZH"); + polynomials.T.divZh(zkey.domainSize, 4); + if (logger) logger.debug("··· Computing Tz ifft"); + polynomials.Tz = await Polynomial.fromEvaluations(buffers.Tz, curve, logger); + polynomials.T.add(polynomials.Tz); + if (polynomials.T.degree() >= zkey.domainSize * 3 + 6) throw new Error("T Polynomial is not well calculated"); + if (logger) logger.debug("··· Computing T1, T2, T3 polynomials"); + polynomials.T1 = new Polynomial(new ffjavascript.BigBuffer((zkey.domainSize + 1) * n8r), curve, logger); + polynomials.T2 = new Polynomial(new ffjavascript.BigBuffer((zkey.domainSize + 1) * n8r), curve, logger); + polynomials.T3 = new Polynomial(new ffjavascript.BigBuffer((zkey.domainSize + 6) * n8r), curve, logger); + polynomials.T1.coef.set(polynomials.T.coef.slice(0, sDomain), 0); + polynomials.T2.coef.set(polynomials.T.coef.slice(sDomain, sDomain * 2), 0); + polynomials.T3.coef.set(polynomials.T.coef.slice(sDomain * 2, sDomain * 3 + 6 * n8r), 0); + polynomials.T1.setCoef(zkey.domainSize, challenges.b[10]); + const lowestMid = Fr.sub(polynomials.T2.getCoef(0), challenges.b[10]); + polynomials.T2.setCoef(0, lowestMid); + polynomials.T2.setCoef(zkey.domainSize, challenges.b[11]); + const lowestHigh = Fr.sub(polynomials.T3.getCoef(0), challenges.b[11]); + polynomials.T3.setCoef(0, lowestHigh); + } + async function round4() { + if (logger) logger.debug("> Computing challenge xi"); + transcript.reset(); + transcript.addScalar(challenges.alpha); + transcript.addPolCommitment(proof.getPolynomial("T1")); + transcript.addPolCommitment(proof.getPolynomial("T2")); + transcript.addPolCommitment(proof.getPolynomial("T3")); + challenges.xi = transcript.getChallenge(); + challenges.xiw = Fr.mul(challenges.xi, Fr.w[zkey.power]); + if (logger) logger.debug("··· challenges.xi: " + Fr.toString(challenges.xi, 16)); + proof.addEvaluation("eval_a", polynomials.A.evaluate(challenges.xi)); + proof.addEvaluation("eval_b", polynomials.B.evaluate(challenges.xi)); + proof.addEvaluation("eval_c", polynomials.C.evaluate(challenges.xi)); + proof.addEvaluation("eval_s1", polynomials.Sigma1.evaluate(challenges.xi)); + proof.addEvaluation("eval_s2", polynomials.Sigma2.evaluate(challenges.xi)); + proof.addEvaluation("eval_zw", polynomials.Z.evaluate(challenges.xiw)); + } + async function round5() { + if (logger) logger.debug("> Computing challenge v"); + transcript.reset(); + transcript.addScalar(challenges.xi); + transcript.addScalar(proof.getEvaluation("eval_a")); + transcript.addScalar(proof.getEvaluation("eval_b")); + transcript.addScalar(proof.getEvaluation("eval_c")); + transcript.addScalar(proof.getEvaluation("eval_s1")); + transcript.addScalar(proof.getEvaluation("eval_s2")); + transcript.addScalar(proof.getEvaluation("eval_zw")); + challenges.v = []; + challenges.v[1] = transcript.getChallenge(); + if (logger) logger.debug("··· challenges.v: " + Fr.toString(challenges.v[1], 16)); + for (let i = 2; i < 6; i++) challenges.v[i] = Fr.mul(challenges.v[i - 1], challenges.v[1]); + if (logger) logger.debug("> Computing linearisation polynomial R(X)"); + await computeR(); + if (logger) logger.debug("> Computing opening proof polynomial Wxi(X) polynomial"); + computeWxi(); + if (logger) logger.debug("> Computing opening proof polynomial Wxiw(X) polynomial"); + computeWxiw(); + if (logger) logger.debug("> Computing Wxi, Wxiw MSM"); + let commitWxi = await polynomials.Wxi.multiExponentiation(PTau, "Wxi"); + let commitWxiw = await polynomials.Wxiw.multiExponentiation(PTau, "Wxiw"); + proof.addPolynomial("Wxi", commitWxi); + proof.addPolynomial("Wxiw", commitWxiw); + } + async function computeR() { + const Fr = curve.Fr; + polynomials.QL = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QR = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QM = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QO = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QC = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + await fdZKey.readToBuffer(polynomials.QL.coef, 0, sDomain, zkeySections[8][0].p); + await fdZKey.readToBuffer(polynomials.QR.coef, 0, sDomain, zkeySections[9][0].p); + await fdZKey.readToBuffer(polynomials.QM.coef, 0, sDomain, zkeySections[7][0].p); + await fdZKey.readToBuffer(polynomials.QO.coef, 0, sDomain, zkeySections[10][0].p); + await fdZKey.readToBuffer(polynomials.QC.coef, 0, sDomain, zkeySections[11][0].p); + challenges.xin = challenges.xi; + for (let i = 0; i < zkey.power; i++) challenges.xin = Fr.square(challenges.xin); + challenges.zh = Fr.sub(challenges.xin, Fr.one); + const L = []; + const n = Fr.e(zkey.domainSize); + let w = Fr.one; + for (let i = 1; i <= Math.max(1, zkey.nPublic); i++) { + L[i] = Fr.div(Fr.mul(w, challenges.zh), Fr.mul(n, Fr.sub(challenges.xi, w))); + w = Fr.mul(w, Fr.w[zkey.power]); + } + const eval_l1 = Fr.div(Fr.sub(challenges.xin, Fr.one), Fr.mul(n, Fr.sub(challenges.xi, Fr.one))); + if (logger) { + logger.debug("Lagrange Evaluations: "); + for (let i = 1; i < L.length; i++) logger.debug(`L${i}(xi)=` + Fr.toString(L[i], 16)); + } + let eval_pi = Fr.zero; + for (let i = 0; i < publicSignals.length; i++) { + const w = Fr.e(publicSignals[i]); + eval_pi = Fr.sub(eval_pi, Fr.mul(w, L[i + 1])); + } + if (logger) logger.debug("PI: " + Fr.toString(eval_pi, 16)); + const coef_ab = Fr.mul(proof.evaluations.eval_a, proof.evaluations.eval_b); + let e2a = proof.evaluations.eval_a; + const betaxi = Fr.mul(challenges.beta, challenges.xi); + e2a = Fr.add(e2a, betaxi); + e2a = Fr.add(e2a, challenges.gamma); + let e2b = proof.evaluations.eval_b; + e2b = Fr.add(e2b, Fr.mul(betaxi, zkey.k1)); + e2b = Fr.add(e2b, challenges.gamma); + let e2c = proof.evaluations.eval_c; + e2c = Fr.add(e2c, Fr.mul(betaxi, zkey.k2)); + e2c = Fr.add(e2c, challenges.gamma); + const e2 = Fr.mul(Fr.mul(Fr.mul(e2a, e2b), e2c), challenges.alpha); + let e3a = proof.evaluations.eval_a; + e3a = Fr.add(e3a, Fr.mul(challenges.beta, proof.evaluations.eval_s1)); + e3a = Fr.add(e3a, challenges.gamma); + let e3b = proof.evaluations.eval_b; + e3b = Fr.add(e3b, Fr.mul(challenges.beta, proof.evaluations.eval_s2)); + e3b = Fr.add(e3b, challenges.gamma); + let e3 = Fr.mul(e3a, e3b); + e3 = Fr.mul(e3, proof.evaluations.eval_zw); + e3 = Fr.mul(e3, challenges.alpha); + const e4 = Fr.mul(eval_l1, challenges.alpha2); + polynomials.R = new Polynomial(new ffjavascript.BigBuffer((zkey.domainSize + 6) * n8r), curve, logger); + polynomials.R.add(polynomials.QM, coef_ab); + polynomials.R.add(polynomials.QL, proof.evaluations.eval_a); + polynomials.R.add(polynomials.QR, proof.evaluations.eval_b); + polynomials.R.add(polynomials.QO, proof.evaluations.eval_c); + polynomials.R.add(polynomials.QC); + polynomials.R.add(polynomials.Z, e2); + polynomials.R.sub(polynomials.Sigma3, Fr.mul(e3, challenges.beta)); + polynomials.R.add(polynomials.Z, e4); + let tmp = Polynomial.fromPolynomial(polynomials.T3, curve, logger); + tmp.mulScalar(Fr.square(challenges.xin)); + tmp.add(polynomials.T2, challenges.xin); + tmp.add(polynomials.T1); + tmp.mulScalar(challenges.zh); + polynomials.R.sub(tmp); + let r0 = Fr.sub(eval_pi, Fr.mul(e3, Fr.add(proof.evaluations.eval_c, challenges.gamma))); + r0 = Fr.sub(r0, e4); + if (logger) logger.debug("r0: " + Fr.toString(r0, 16)); + polynomials.R.addScalar(r0); + } + function computeWxi() { + polynomials.Wxi = new Polynomial(new ffjavascript.BigBuffer(sDomain + 6 * n8r), curve, logger); + polynomials.Wxi.add(polynomials.R); + polynomials.Wxi.add(polynomials.A, challenges.v[1]); + polynomials.Wxi.add(polynomials.B, challenges.v[2]); + polynomials.Wxi.add(polynomials.C, challenges.v[3]); + polynomials.Wxi.add(polynomials.Sigma1, challenges.v[4]); + polynomials.Wxi.add(polynomials.Sigma2, challenges.v[5]); + polynomials.Wxi.subScalar(Fr.mul(challenges.v[1], proof.evaluations.eval_a)); + polynomials.Wxi.subScalar(Fr.mul(challenges.v[2], proof.evaluations.eval_b)); + polynomials.Wxi.subScalar(Fr.mul(challenges.v[3], proof.evaluations.eval_c)); + polynomials.Wxi.subScalar(Fr.mul(challenges.v[4], proof.evaluations.eval_s1)); + polynomials.Wxi.subScalar(Fr.mul(challenges.v[5], proof.evaluations.eval_s2)); + polynomials.Wxi.divByZerofier(1, challenges.xi); + } + async function computeWxiw() { + polynomials.Wxiw = Polynomial.fromPolynomial(polynomials.Z, curve, logger); + polynomials.Wxiw.subScalar(proof.evaluations.eval_zw); + polynomials.Wxiw.divByZerofier(1, challenges.xiw); + } + } + //#endregion + //#region src/plonk_fullprove.js + var { unstringifyBigInts: unstringifyBigInts$5 } = ffjavascript.utils; + async function plonkFullProve(_input, wasmFile, zkeyFileName, logger, wtnsCalcOptions, proverOptions) { + const input = unstringifyBigInts$5(_input); + const wtns = { type: "mem" }; + await wtnsCalculate(input, wasmFile, wtns, wtnsCalcOptions); + return await plonk16Prove(zkeyFileName, wtns, logger, proverOptions); + } + //#endregion + //#region src/plonk_verify.js + var { unstringifyBigInts: unstringifyBigInts$4 } = ffjavascript.utils; + async function plonkVerify(_vk_verifier, _publicSignals, _proof, logger) { + let vk_verifier = unstringifyBigInts$4(_vk_verifier); + _proof = unstringifyBigInts$4(_proof); + let publicSignals = unstringifyBigInts$4(_publicSignals); + const curve = await getCurveFromName(vk_verifier.curve); + const Fr = curve.Fr; + const G1 = curve.G1; + if (logger) logger.info("PLONK VERIFIER STARTED"); + let proof = fromObjectProof(curve, _proof); + vk_verifier = fromObjectVk$1(curve, vk_verifier); + if (!isWellConstructed(curve, proof)) { + logger.error("Proof commitments are not valid."); + return false; + } + if (publicSignals.length != vk_verifier.nPublic) { + if (logger) logger.error("Invalid number of public inputs"); + return false; + } + if (!evaluationsAreValid$1(curve, proof)) { + if (logger) logger.error("Proof evaluations are not valid"); + return false; + } + if (!publicInputsAreValid$1(curve, publicSignals)) { + if (logger) logger.error("Public inputs are not valid."); + return false; + } + const challenges = calculatechallenges(curve, proof, publicSignals, vk_verifier); + if (logger) { + logger.debug("beta: " + Fr.toString(challenges.beta, 16)); + logger.debug("gamma: " + Fr.toString(challenges.gamma, 16)); + logger.debug("alpha: " + Fr.toString(challenges.alpha, 16)); + logger.debug("xi: " + Fr.toString(challenges.xi, 16)); + for (let i = 1; i < 6; i++) if (logger) logger.debug("v: " + Fr.toString(challenges.v[i], 16)); + logger.debug("u: " + Fr.toString(challenges.u, 16)); + } + const L = calculateLagrangeEvaluations(curve, challenges, vk_verifier); + if (logger) for (let i = 1; i < L.length; i++) logger.debug(`L${i}(xi)=` + Fr.toString(L[i], 16)); + if (publicSignals.length != vk_verifier.nPublic) { + logger.error("Number of public signals does not match with vk"); + return false; + } + const pi = calculatePI$1(curve, publicSignals, L); + if (logger) logger.debug("PI(xi): " + Fr.toString(pi, 16)); + const r0 = calculateR0(curve, proof, challenges, pi, L[1]); + if (logger) logger.debug("r0: " + Fr.toString(r0, 16)); + const D = calculateD(curve, proof, challenges, vk_verifier, L[1]); + if (logger) logger.debug("D: " + G1.toString(G1.toAffine(D), 16)); + const F = calculateF(curve, proof, challenges, vk_verifier, D); + if (logger) logger.debug("F: " + G1.toString(G1.toAffine(F), 16)); + const E = calculateE(curve, proof, challenges, r0); + if (logger) logger.debug("E: " + G1.toString(G1.toAffine(E), 16)); + const res = await isValidPairing$1(curve, proof, challenges, vk_verifier, E, F); + if (logger) if (res) logger.info("OK!"); + else logger.warn("Invalid Proof"); + return res; + } + function fromObjectProof(curve, proof) { + const G1 = curve.G1; + const Fr = curve.Fr; + const res = {}; + res.A = G1.fromObject(proof.A); + res.B = G1.fromObject(proof.B); + res.C = G1.fromObject(proof.C); + res.Z = G1.fromObject(proof.Z); + res.T1 = G1.fromObject(proof.T1); + res.T2 = G1.fromObject(proof.T2); + res.T3 = G1.fromObject(proof.T3); + res.eval_a = Fr.fromObject(proof.eval_a); + res.eval_b = Fr.fromObject(proof.eval_b); + res.eval_c = Fr.fromObject(proof.eval_c); + res.eval_zw = Fr.fromObject(proof.eval_zw); + res.eval_s1 = Fr.fromObject(proof.eval_s1); + res.eval_s2 = Fr.fromObject(proof.eval_s2); + res.Wxi = G1.fromObject(proof.Wxi); + res.Wxiw = G1.fromObject(proof.Wxiw); + return res; + } + function fromObjectVk$1(curve, vk) { + const G1 = curve.G1; + const G2 = curve.G2; + const Fr = curve.Fr; + const res = vk; + res.Qm = G1.fromObject(vk.Qm); + res.Ql = G1.fromObject(vk.Ql); + res.Qr = G1.fromObject(vk.Qr); + res.Qo = G1.fromObject(vk.Qo); + res.Qc = G1.fromObject(vk.Qc); + res.S1 = G1.fromObject(vk.S1); + res.S2 = G1.fromObject(vk.S2); + res.S3 = G1.fromObject(vk.S3); + res.k1 = Fr.fromObject(vk.k1); + res.k2 = Fr.fromObject(vk.k2); + res.X_2 = G2.fromObject(vk.X_2); + return res; + } + function isWellConstructed(curve, proof) { + const G1 = curve.G1; + if (!G1.isValid(proof.A)) return false; + if (!G1.isValid(proof.B)) return false; + if (!G1.isValid(proof.C)) return false; + if (!G1.isValid(proof.Z)) return false; + if (!G1.isValid(proof.T1)) return false; + if (!G1.isValid(proof.T2)) return false; + if (!G1.isValid(proof.T3)) return false; + if (!G1.isValid(proof.Wxi)) return false; + if (!G1.isValid(proof.Wxiw)) return false; + return true; + } + function checkValueBelongToField$1(curve, value) { + return ffjavascript.Scalar.geq(value, 0) && ffjavascript.Scalar.lt(value, curve.r); + } + function checkEvaluationIsValid$1(curve, evaluation) { + return checkValueBelongToField$1(curve, ffjavascript.Scalar.fromRprLE(evaluation)); + } + function evaluationsAreValid$1(curve, proof) { + return checkEvaluationIsValid$1(curve, proof.eval_a) && checkEvaluationIsValid$1(curve, proof.eval_b) && checkEvaluationIsValid$1(curve, proof.eval_c) && checkEvaluationIsValid$1(curve, proof.eval_s1) && checkEvaluationIsValid$1(curve, proof.eval_s2) && checkEvaluationIsValid$1(curve, proof.eval_zw); + } + function publicInputsAreValid$1(curve, publicInputs) { + for (let i = 0; i < publicInputs.length; i++) if (!checkValueBelongToField$1(curve, publicInputs[i])) return false; + return true; + } + function calculatechallenges(curve, proof, publicSignals, vk) { + const Fr = curve.Fr; + const res = {}; + const transcript = new Keccak256Transcript(curve); + transcript.addPolCommitment(vk.Qm); + transcript.addPolCommitment(vk.Ql); + transcript.addPolCommitment(vk.Qr); + transcript.addPolCommitment(vk.Qo); + transcript.addPolCommitment(vk.Qc); + transcript.addPolCommitment(vk.S1); + transcript.addPolCommitment(vk.S2); + transcript.addPolCommitment(vk.S3); + for (let i = 0; i < publicSignals.length; i++) transcript.addScalar(Fr.e(publicSignals[i])); + transcript.addPolCommitment(proof.A); + transcript.addPolCommitment(proof.B); + transcript.addPolCommitment(proof.C); + res.beta = transcript.getChallenge(); + transcript.reset(); + transcript.addScalar(res.beta); + res.gamma = transcript.getChallenge(); + transcript.reset(); + transcript.addScalar(res.beta); + transcript.addScalar(res.gamma); + transcript.addPolCommitment(proof.Z); + res.alpha = transcript.getChallenge(); + transcript.reset(); + transcript.addScalar(res.alpha); + transcript.addPolCommitment(proof.T1); + transcript.addPolCommitment(proof.T2); + transcript.addPolCommitment(proof.T3); + res.xi = transcript.getChallenge(); + transcript.reset(); + transcript.addScalar(res.xi); + transcript.addScalar(proof.eval_a); + transcript.addScalar(proof.eval_b); + transcript.addScalar(proof.eval_c); + transcript.addScalar(proof.eval_s1); + transcript.addScalar(proof.eval_s2); + transcript.addScalar(proof.eval_zw); + res.v = []; + res.v[1] = transcript.getChallenge(); + for (let i = 2; i < 6; i++) res.v[i] = Fr.mul(res.v[i - 1], res.v[1]); + transcript.reset(); + transcript.addPolCommitment(proof.Wxi); + transcript.addPolCommitment(proof.Wxiw); + res.u = transcript.getChallenge(); + return res; + } + function calculateLagrangeEvaluations(curve, challenges, vk) { + const Fr = curve.Fr; + let xin = challenges.xi; + let domainSize = 1; + for (let i = 0; i < vk.power; i++) { + xin = Fr.square(xin); + domainSize *= 2; + } + challenges.xin = xin; + challenges.zh = Fr.sub(xin, Fr.one); + const L = []; + const n = Fr.e(domainSize); + let w = Fr.one; + for (let i = 1; i <= Math.max(1, vk.nPublic); i++) { + L[i] = Fr.div(Fr.mul(w, challenges.zh), Fr.mul(n, Fr.sub(challenges.xi, w))); + w = Fr.mul(w, Fr.w[vk.power]); + } + return L; + } + function calculatePI$1(curve, publicSignals, L) { + const Fr = curve.Fr; + let pi = Fr.zero; + for (let i = 0; i < publicSignals.length; i++) { + const w = Fr.e(publicSignals[i]); + pi = Fr.sub(pi, Fr.mul(w, L[i + 1])); + } + return pi; + } + function calculateR0(curve, proof, challenges, pi, l1) { + const Fr = curve.Fr; + const e1 = pi; + const e2 = Fr.mul(l1, Fr.square(challenges.alpha)); + let e3a = Fr.add(proof.eval_a, Fr.mul(challenges.beta, proof.eval_s1)); + e3a = Fr.add(e3a, challenges.gamma); + let e3b = Fr.add(proof.eval_b, Fr.mul(challenges.beta, proof.eval_s2)); + e3b = Fr.add(e3b, challenges.gamma); + let e3c = Fr.add(proof.eval_c, challenges.gamma); + let e3 = Fr.mul(Fr.mul(e3a, e3b), e3c); + e3 = Fr.mul(e3, proof.eval_zw); + e3 = Fr.mul(e3, challenges.alpha); + return Fr.sub(Fr.sub(e1, e2), e3); + } + function calculateD(curve, proof, challenges, vk, l1) { + const G1 = curve.G1; + const Fr = curve.Fr; + let d1 = G1.timesFr(vk.Qm, Fr.mul(proof.eval_a, proof.eval_b)); + d1 = G1.add(d1, G1.timesFr(vk.Ql, proof.eval_a)); + d1 = G1.add(d1, G1.timesFr(vk.Qr, proof.eval_b)); + d1 = G1.add(d1, G1.timesFr(vk.Qo, proof.eval_c)); + d1 = G1.add(d1, vk.Qc); + const betaxi = Fr.mul(challenges.beta, challenges.xi); + const d2a1 = Fr.add(Fr.add(proof.eval_a, betaxi), challenges.gamma); + const d2a2 = Fr.add(Fr.add(proof.eval_b, Fr.mul(betaxi, vk.k1)), challenges.gamma); + const d2a3 = Fr.add(Fr.add(proof.eval_c, Fr.mul(betaxi, vk.k2)), challenges.gamma); + const d2a = Fr.mul(Fr.mul(Fr.mul(d2a1, d2a2), d2a3), challenges.alpha); + const d2b = Fr.mul(l1, Fr.square(challenges.alpha)); + const d2 = G1.timesFr(proof.Z, Fr.add(Fr.add(d2a, d2b), challenges.u)); + const d3a = Fr.add(Fr.add(proof.eval_a, Fr.mul(challenges.beta, proof.eval_s1)), challenges.gamma); + const d3b = Fr.add(Fr.add(proof.eval_b, Fr.mul(challenges.beta, proof.eval_s2)), challenges.gamma); + const d3c = Fr.mul(Fr.mul(challenges.alpha, challenges.beta), proof.eval_zw); + const d3 = G1.timesFr(vk.S3, Fr.mul(Fr.mul(d3a, d3b), d3c)); + const d4low = proof.T1; + const d4mid = G1.timesFr(proof.T2, challenges.xin); + const d4high = G1.timesFr(proof.T3, Fr.square(challenges.xin)); + let d4 = G1.add(d4low, G1.add(d4mid, d4high)); + d4 = G1.timesFr(d4, challenges.zh); + return G1.sub(G1.sub(G1.add(d1, d2), d3), d4); + } + function calculateF(curve, proof, challenges, vk, D) { + const G1 = curve.G1; + let res = G1.add(D, G1.timesFr(proof.A, challenges.v[1])); + res = G1.add(res, G1.timesFr(proof.B, challenges.v[2])); + res = G1.add(res, G1.timesFr(proof.C, challenges.v[3])); + res = G1.add(res, G1.timesFr(vk.S1, challenges.v[4])); + res = G1.add(res, G1.timesFr(vk.S2, challenges.v[5])); + return res; + } + function calculateE(curve, proof, challenges, r0) { + const G1 = curve.G1; + const Fr = curve.Fr; + let e = Fr.add(Fr.neg(r0), Fr.mul(challenges.v[1], proof.eval_a)); + e = Fr.add(e, Fr.mul(challenges.v[2], proof.eval_b)); + e = Fr.add(e, Fr.mul(challenges.v[3], proof.eval_c)); + e = Fr.add(e, Fr.mul(challenges.v[4], proof.eval_s1)); + e = Fr.add(e, Fr.mul(challenges.v[5], proof.eval_s2)); + e = Fr.add(e, Fr.mul(challenges.u, proof.eval_zw)); + return G1.timesFr(G1.one, e); + } + async function isValidPairing$1(curve, proof, challenges, vk, E, F) { + const G1 = curve.G1; + const Fr = curve.Fr; + let A1 = proof.Wxi; + A1 = G1.add(A1, G1.timesFr(proof.Wxiw, challenges.u)); + let B1 = G1.timesFr(proof.Wxi, challenges.xi); + const s = Fr.mul(Fr.mul(challenges.u, challenges.xi), Fr.w[vk.power]); + B1 = G1.add(B1, G1.timesFr(proof.Wxiw, s)); + B1 = G1.add(B1, F); + B1 = G1.sub(B1, E); + return await curve.pairingEq(G1.neg(A1), vk.X_2, B1, curve.G2.one); + } + //#endregion + //#region src/plonk_exportsoliditycalldata.js + var { unstringifyBigInts: unstringifyBigInts$3 } = ffjavascript.utils; + function p256$1(n) { + let nstr = n.toString(16); + while (nstr.length < 64) nstr = "0" + nstr; + nstr = `"0x${nstr}"`; + return nstr; + } + async function plonkExportSolidityCallData(_proof, _pub) { + const proof = unstringifyBigInts$3(_proof); + const pub = unstringifyBigInts$3(_pub); + await getCurveFromName(proof.curve); + let inputs = ""; + for (let i = 0; i < pub.length; i++) { + if (inputs != "") inputs = inputs + ","; + inputs = inputs + p256$1(pub[i]); + } + return `[${p256$1(proof.A[0])}, ${p256$1(proof.A[1])},${p256$1(proof.B[0])},${p256$1(proof.B[1])},${p256$1(proof.C[0])},${p256$1(proof.C[1])},${p256$1(proof.Z[0])},${p256$1(proof.Z[1])},${p256$1(proof.T1[0])},${p256$1(proof.T1[1])},${p256$1(proof.T2[0])},${p256$1(proof.T2[1])},${p256$1(proof.T3[0])},${p256$1(proof.T3[1])},${p256$1(proof.Wxi[0])},${p256$1(proof.Wxi[1])},${p256$1(proof.Wxiw[0])},${p256$1(proof.Wxiw[1])},${p256$1(proof.eval_a)},${p256$1(proof.eval_b)},${p256$1(proof.eval_c)},${p256$1(proof.eval_s1)},${p256$1(proof.eval_s2)},${p256$1(proof.eval_zw)}][${inputs}]`; + } + //#endregion + //#region src/plonk.js + var plonk_exports = /* @__PURE__ */ __exportAll({ + exportSolidityCallData: () => plonkExportSolidityCallData, + fullProve: () => plonkFullProve, + prove: () => plonk16Prove, + setup: () => plonkSetup, + verify: () => plonkVerify + }); + //#endregion + //#region src/plonk_equation.js + function getFFlonkConstantConstraint(signal1, Fr) { + return [ + signal1, + 0, + 0, + Fr.one, + Fr.zero, + Fr.zero, + Fr.zero, + Fr.zero + ]; + } + function getFFlonkAdditionConstraint(signal1, signal2, signalOut, ql, qr, qm, qo, qc) { + return [ + signal1, + signal2, + signalOut, + ql, + qr, + qm, + qo, + qc + ]; + } + function getFFlonkMultiplicationConstraint(signal1, signal2, signalOut, ql, qr, qm, qo, qc, _Fr) { + return [ + signal1, + signal2, + signalOut, + ql, + qr, + qm, + qo, + qc + ]; + } + //#endregion + //#region src/r1cs_constraint_processor.js + var LINEAR_COMBINATION_NULLABLE = 0; + var LINEAR_COMBINATION_CONSTANT = 1; + var LINEAR_COMBINATION_VARIABLE = 2; + var r1csConstraintProcessor = class { + constructor(Fr, fnGetConstantConstraint, fnGetAdditionConstraint, fnGetMultiplicationConstraint, logger) { + this.Fr = Fr; + this.logger = logger; + this.fnGetAdditionConstraint = fnGetAdditionConstraint; + this.fnGetMultiplicationConstraint = fnGetMultiplicationConstraint; + } + processR1csConstraint(settings, lcA, lcB, lcC) { + this.normalizeLinearCombination(lcA); + this.normalizeLinearCombination(lcB); + this.normalizeLinearCombination(lcC); + const lctA = this.getLinearCombinationType(lcA); + const lctB = this.getLinearCombinationType(lcB); + if (lctA === LINEAR_COMBINATION_NULLABLE || lctB === LINEAR_COMBINATION_NULLABLE) return this.processR1csAdditionConstraint(settings, lcC); + else if (lctA === LINEAR_COMBINATION_CONSTANT) { + const lcCC = this.joinLinearCombinations(lcB, lcC, lcA[0]); + return this.processR1csAdditionConstraint(settings, lcCC); + } else if (lctB === LINEAR_COMBINATION_CONSTANT) { + const lcCC = this.joinLinearCombinations(lcA, lcC, lcB[0]); + return this.processR1csAdditionConstraint(settings, lcCC); + } else return this.processR1csMultiplicationConstraint(settings, lcA, lcB, lcC); + } + getLinearCombinationType(linCom) { + let k = this.Fr.zero; + let n = 0; + const ss = Object.keys(linCom); + for (let i = 0; i < ss.length; i++) if (linCom[ss[i]] == 0n) delete linCom[ss[i]]; + else if (ss[i] == 0) k = this.Fr.add(k, linCom[ss[i]]); + else n++; + if (n > 0) return LINEAR_COMBINATION_VARIABLE; + if (!this.Fr.isZero(k)) return LINEAR_COMBINATION_CONSTANT; + return LINEAR_COMBINATION_NULLABLE; + } + normalizeLinearCombination(linCom) { + const signalIds = Object.keys(linCom); + for (let i = 0; i < signalIds.length; i++) if (this.Fr.isZero(linCom[signalIds[i]])) delete linCom[signalIds[i]]; + return linCom; + } + joinLinearCombinations(linCom1, linCom2, k) { + const res = {}; + for (let s in linCom1) if (typeof res[s] == "undefined") res[s] = this.Fr.mul(k, linCom1[s]); + else res[s] = this.Fr.add(res[s], this.Fr.mul(k, linCom1[s])); + for (let s in linCom2) if (typeof res[s] == "undefined") res[s] = linCom2[s]; + else res[s] = this.Fr.add(res[s], linCom2[s]); + return this.normalizeLinearCombination(res); + } + reduceCoefs(settings, constraintsArr, additionsArr, linCom, maxC) { + const res = { + k: this.Fr.zero, + signals: [], + coefs: [] + }; + const cs = []; + for (let signalId in linCom) if (signalId == 0) res.k = this.Fr.add(res.k, linCom[signalId]); + else if (linCom[signalId] != 0n) cs.push([Number(signalId), linCom[signalId]]); + while (cs.length > maxC) { + const c1 = cs.shift(); + const c2 = cs.shift(); + const so = settings.nVars++; + const constraints = this.fnGetAdditionConstraint(c1[0], c2[0], so, this.Fr.neg(c1[1]), this.Fr.neg(c2[1]), this.Fr.zero, this.Fr.one, this.Fr.zero); + constraintsArr.push(constraints); + additionsArr.push([ + c1[0], + c2[0], + c1[1], + c2[1] + ]); + cs.push([so, this.Fr.one]); + } + for (let i = 0; i < cs.length; i++) { + res.signals[i] = cs[i][0]; + res.coefs[i] = cs[i][1]; + } + while (res.coefs.length < maxC) { + res.signals.push(0); + res.coefs.push(this.Fr.zero); + } + return res; + } + processR1csAdditionConstraint(settings, linCom) { + const constraintsArr = []; + const additionsArr = []; + const C = this.reduceCoefs(settings, constraintsArr, additionsArr, linCom, 3); + const constraints = this.fnGetAdditionConstraint(C.signals[0], C.signals[1], C.signals[2], C.coefs[0], C.coefs[1], this.Fr.zero, C.coefs[2], C.k); + constraintsArr.push(constraints); + return [constraintsArr, additionsArr]; + } + processR1csMultiplicationConstraint(settings, lcA, lcB, lcC) { + const constraintsArr = []; + const additionsArr = []; + const A = this.reduceCoefs(settings, constraintsArr, additionsArr, lcA, 1); + const B = this.reduceCoefs(settings, constraintsArr, additionsArr, lcB, 1); + const C = this.reduceCoefs(settings, constraintsArr, additionsArr, lcC, 1); + const constraints = this.fnGetMultiplicationConstraint(A.signals[0], B.signals[0], C.signals[0], this.Fr.mul(A.coefs[0], B.k), this.Fr.mul(A.k, B.coefs[0]), this.Fr.mul(A.coefs[0], B.coefs[0]), this.Fr.neg(C.coefs[0]), this.Fr.sub(this.Fr.mul(A.k, B.k), C.k)); + constraintsArr.push(constraints); + return [constraintsArr, additionsArr]; + } + }; + //#endregion + //#region src/polynomial/cpolynomial.js + var CPolynomial = class { + constructor(n, curve, logger) { + this.n = n; + this.polynomials = Array(n).fill(void 0); + this.curve = curve; + this.Fr = curve.Fr; + this.G1 = curve.G1; + this.logger = logger; + } + addPolynomial(position, polynomial) { + if (position > this.n - 1) throw new Error("CPolynomial:addPolynomial, cannot add a polynomial to a position greater than n-1"); + this.polynomials[position] = polynomial; + } + degree() { + let degrees = this.polynomials.map((polynomial, index) => polynomial === void 0 ? 0 : polynomial.degree() * this.n + index); + return Math.max(...degrees); + } + getPolynomial() { + let degrees = this.polynomials.map((polynomial) => polynomial === void 0 ? 0 : polynomial.degree()); + const maxDegree = this.degree(); + const lengthBuffer = 2 ** (log2(maxDegree - 1) + 1); + const sFr = this.Fr.n8; + let polynomial = new Polynomial(new ffjavascript.BigBuffer(lengthBuffer * sFr), this.curve, this.logger); + for (let i = 0; i < maxDegree; i++) { + const i_n8 = i * sFr; + const i_sFr = i_n8 * this.n; + for (let j = 0; j < this.n; j++) if (this.polynomials[j] !== void 0) { + if (i <= degrees[j]) polynomial.coef.set(this.polynomials[j].coef.slice(i_n8, i_n8 + sFr), i_sFr + j * sFr); + } + } + return polynomial; + } + async multiExponentiation(PTau, name) { + let polynomial = this.getPolynomial(); + const n = polynomial.coef.byteLength / this.Fr.n8; + const PTauN = PTau.slice(0, n * this.G1.F.n8 * 2); + const bm = await this.Fr.batchFromMontgomery(polynomial.coef); + let res = await this.G1.multiExpAffine(PTauN, bm, this.logger, name); + res = this.G1.toAffine(res); + return res; + } + }; + //#endregion + //#region src/fflonk_setup.js + async function fflonkSetup(r1csFilename, ptauFilename, zkeyFilename, logger) { + if (logger) logger.info("FFLONK SETUP STARTED"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info("> Reading PTau file"); + const { fd: fdPTau, sections: pTauSections } = await (0, _iden3_binfileutils.readBinFile)(ptauFilename, "ptau", 1, 1 << 22, 1 << 24); + if (!pTauSections[12]) throw new Error("Powers of Tau is not well prepared. Section 12 missing."); + if (logger) logger.info("> Getting curve from PTau settings"); + const { curve } = await readPTauHeader(fdPTau, pTauSections); + if (logger) logger.info("> Reading r1cs file"); + const { fd: fdR1cs, sections: sectionsR1cs } = await (0, _iden3_binfileutils.readBinFile)(r1csFilename, "r1cs", 1, 1 << 22, 1 << 24); + const r1cs = await (0, r1csfile.readR1csFd)(fdR1cs, sectionsR1cs, { + loadConstraints: false, + loadCustomGates: true + }); + if (r1cs.prime !== curve.r) throw new Error("r1cs curve does not match powers of tau ceremony curve"); + const Fr = curve.Fr; + const sFr = curve.Fr.n8; + const sG1 = curve.G1.F.n8 * 2; + const sG2 = curve.G2.F.n8 * 2; + let polynomials = {}; + let evaluations = {}; + let PTau; + let settings = { + nVars: r1cs.nVars, + nPublic: r1cs.nOutputs + r1cs.nPubInputs + }; + const plonkConstraints = new BigArray(); + let plonkAdditions = new BigArray(); + if (logger) logger.info("> Processing FFlonk constraints"); + await computeFFConstraints(curve.Fr, r1cs, logger); + if (globalThis.gc) globalThis.gc(); + settings.cirPower = Math.max(3, log2(plonkConstraints.length + 2 - 1) + 1); + settings.domainSize = 2 ** settings.cirPower; + if (pTauSections[2][0].size < (settings.domainSize * 9 + 18) * sG1) throw new Error("Powers of Tau is not big enough for this circuit size. Section 2 too small."); + if (pTauSections[3][0].size < sG2) throw new Error("Powers of Tau is not well prepared. Section 3 too small."); + if (logger) { + logger.info("----------------------------"); + logger.info(" FFLONK SETUP SETTINGS"); + logger.info(` Curve: ${curve.name}`); + logger.info(` Circuit power: ${settings.cirPower}`); + logger.info(` Domain size: ${settings.domainSize}`); + logger.info(` Vars: ${settings.nVars}`); + logger.info(` Public vars: ${settings.nPublic}`); + logger.info(` Constraints: ${plonkConstraints.length}`); + logger.info(` Additions: ${plonkAdditions.length}`); + logger.info("----------------------------"); + } + if (logger) logger.info("> computing k1 and k2"); + const [k1, k2] = computeK1K2(); + if (logger) logger.info("> computing w3"); + const w3 = computeW3(); + if (logger) logger.info("> computing w4"); + const w4 = computeW4(); + if (logger) logger.info("> computing w8"); + const w8 = computeW8(); + if (logger) logger.info("> computing wr"); + const wr = getOmegaCubicRoot(settings.cirPower, curve.Fr); + await writeZkeyFile(); + await fdR1cs.close(); + await fdPTau.close(); + if (logger) logger.info("FFLONK SETUP FINISHED"); + return 0; + async function computeFFConstraints(Fr, r1cs, logger) { + for (let i = 0; i < settings.nPublic; i++) plonkConstraints.push(getFFlonkConstantConstraint(i + 1, Fr)); + const r1csProcessor = new r1csConstraintProcessor(Fr, getFFlonkConstantConstraint, getFFlonkAdditionConstraint, getFFlonkMultiplicationConstraint, logger); + const bR1cs = await _iden3_binfileutils.readSection(fdR1cs, sectionsR1cs, 2); + let bR1csPos = 0; + for (let i = 0; i < r1cs.nConstraints; i++) { + if (logger && i !== 0 && i % 5e5 === 0) logger.info(` processing r1cs constraints ${i}/${r1cs.nConstraints}`); + const [constraints, additions] = r1csProcessor.processR1csConstraint(settings, ...readConstraint()); + plonkConstraints.push(...constraints); + plonkAdditions.push(...additions); + } + function readConstraint() { + const c = []; + c[0] = readLC(); + c[1] = readLC(); + c[2] = readLC(); + return c; + } + function readLC() { + const lc = {}; + const buffUL32 = bR1cs.slice(bR1csPos, bR1csPos + 4); + bR1csPos += 4; + const nIdx = new DataView(buffUL32.buffer).getUint32(0, true); + const buff = bR1cs.slice(bR1csPos, bR1csPos + (4 + r1cs.n8) * nIdx); + bR1csPos += (4 + r1cs.n8) * nIdx; + const buffV = new DataView(buff.buffer); + for (let i = 0; i < nIdx; i++) { + const idx = buffV.getUint32(i * (4 + r1cs.n8), true); + lc[idx] = r1cs.F.fromRprLE(buff, i * (4 + r1cs.n8) + 4); + } + return lc; + } + return 0; + } + async function writeZkeyFile() { + if (logger) logger.info("> Writing the zkey file"); + const fdZKey = await (0, _iden3_binfileutils.createBinFile)(zkeyFilename, "zkey", 1, 17, 1 << 22, 1 << 24); + if (logger) logger.info(`··· Writing Section 1. Zkey Header`); + await writeZkeyHeader(fdZKey); + if (logger) logger.info(`··· Writing Section 3. Additions`); + await writeAdditions(fdZKey); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 4. A Map`); + await writeWitnessMap(fdZKey, 4, 0, "A map"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 5. B Map`); + await writeWitnessMap(fdZKey, 5, 1, "B map"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 6. C Map`); + await writeWitnessMap(fdZKey, 6, 2, "C map"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 7. QL`); + await writeQMap(fdZKey, 7, 3, "QL"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 8. QR`); + await writeQMap(fdZKey, 8, 4, "QR"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 9. QM`); + await writeQMap(fdZKey, 9, 5, "QM"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 10. QO`); + await writeQMap(fdZKey, 10, 6, "QO"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 11. QC`); + await writeQMap(fdZKey, 11, 7, "QC"); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Sections 12,13,14. Sigma1, Sigma2 & Sigma 3`); + await writeSigma(fdZKey); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 15. Lagrange Polynomials`); + await writeLagrangePolynomials(fdZKey); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 16. Powers of Tau`); + await writePtau(fdZKey); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 17. C0`); + await writeC0(fdZKey); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(`··· Writing Section 2. FFlonk Header`); + await writeFFlonkHeader(fdZKey); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info("> Writing the zkey file finished"); + await fdZKey.close(); + } + async function writeZkeyHeader(fdZKey) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 1); + await fdZKey.writeULE32(10); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeAdditions(fdZKey) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 3); + const buffOut = new Uint8Array(8 + 2 * sFr); + const buffOutV = new DataView(buffOut.buffer); + for (let i = 0; i < plonkAdditions.length; i++) { + if (logger && i !== 0 && i % 5e5 === 0) logger.info(` writing Additions: ${i}/${plonkAdditions.length}`); + const addition = plonkAdditions[i]; + buffOutV.setUint32(0, addition[0], true); + buffOutV.setUint32(4, addition[1], true); + buffOut.set(addition[2], 8); + buffOut.set(addition[3], 8 + sFr); + await fdZKey.write(buffOut); + } + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeWitnessMap(fdZKey, sectionNum, posConstraint, name) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); + for (let i = 0; i < plonkConstraints.length; i++) { + if (logger && i !== 0 && i % 5e5 === 0) logger.info(` writing witness ${name}: ${i}/${plonkConstraints.length}`); + await fdZKey.writeULE32(plonkConstraints[i][posConstraint]); + } + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeQMap(fdZKey, sectionNum, posConstraint, name) { + let Q = new ffjavascript.BigBuffer(settings.domainSize * sFr); + for (let i = 0; i < plonkConstraints.length; i++) { + Q.set(plonkConstraints[i][posConstraint], i * sFr); + if (logger && i !== 0 && i % 5e5 === 0) logger.info(` writing ${name}: ${i}/${plonkConstraints.length}`); + } + polynomials[name] = await Polynomial.fromEvaluations(Q, curve, logger); + evaluations[name] = await Evaluations.fromPolynomial(polynomials[name], 4, curve, logger); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); + await fdZKey.write(polynomials[name].coef); + await fdZKey.write(evaluations[name].eval); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeSigma(fdZKey) { + const sigma = new ffjavascript.BigBuffer(sFr * settings.domainSize * 3); + const lastSeen = new BigArray(settings.nVars); + const firstPos = new BigArray(settings.nVars); + let w = Fr.one; + for (let i = 0; i < settings.domainSize; i++) { + if (i < plonkConstraints.length) { + buildSigma(plonkConstraints[i][0], i); + buildSigma(plonkConstraints[i][1], settings.domainSize + i); + buildSigma(plonkConstraints[i][2], settings.domainSize * 2 + i); + } else if (i < settings.domainSize - 2) { + buildSigma(0, i); + buildSigma(0, settings.domainSize + i); + buildSigma(0, settings.domainSize * 2 + i); + } else { + sigma.set(w, i * sFr); + sigma.set(Fr.mul(w, k1), (settings.domainSize + i) * sFr); + sigma.set(Fr.mul(w, k2), (settings.domainSize * 2 + i) * sFr); + } + w = Fr.mul(w, Fr.w[settings.cirPower]); + if (logger && i !== 0 && i % 5e5 === 0) logger.info(` writing sigma phase1: ${i}/${plonkConstraints.length}`); + } + for (let i = 0; i < settings.nVars; i++) { + if (typeof firstPos[i] !== "undefined") sigma.set(lastSeen[i], firstPos[i] * sFr); + else console.log("Variable not used"); + if (logger && i !== 0 && i % 5e5 === 0) logger.info(` writing sigma phase2: ${i}/${settings.nVars}`); + } + if (globalThis.gc) globalThis.gc(); + for (let i = 0; i < 3; i++) { + const sectionId = 0 === i ? 12 : 1 === i ? 13 : 14; + let name = "S" + (i + 1); + polynomials[name] = await Polynomial.fromEvaluations(sigma.slice(settings.domainSize * sFr * i, settings.domainSize * sFr * (i + 1)), curve, logger); + evaluations[name] = await Evaluations.fromPolynomial(polynomials[name], 4, curve, logger); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionId); + await fdZKey.write(polynomials[name].coef); + await fdZKey.write(evaluations[name].eval); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + if (globalThis.gc) globalThis.gc(); + } + return 0; + function buildSigma(signalId, idx) { + if (typeof lastSeen[signalId] === "undefined") firstPos[signalId] = idx; + else sigma.set(lastSeen[signalId], idx * sFr); + let v; + if (idx < settings.domainSize) v = w; + else if (idx < 2 * settings.domainSize) v = Fr.mul(w, k1); + else v = Fr.mul(w, k2); + lastSeen[signalId] = v; + } + } + async function writeLagrangePolynomials(fdZKey) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 15); + const l = Math.max(settings.nPublic, 1); + for (let i = 0; i < l; i++) { + let buff = new ffjavascript.BigBuffer(settings.domainSize * sFr); + buff.set(Fr.one, i * sFr); + await writeP4(fdZKey, buff); + } + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writePtau(fdZKey) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 16); + PTau = new ffjavascript.BigBuffer((settings.domainSize * 9 + 18) * sG1); + await fdPTau.readToBuffer(PTau, 0, (settings.domainSize * 9 + 18) * sG1, pTauSections[2][0].p); + await fdZKey.write(PTau); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeC0(fdZKey) { + let C0 = new CPolynomial(8, curve, logger); + C0.addPolynomial(0, polynomials.QL); + C0.addPolynomial(1, polynomials.QR); + C0.addPolynomial(2, polynomials.QO); + C0.addPolynomial(3, polynomials.QM); + C0.addPolynomial(4, polynomials.QC); + C0.addPolynomial(5, polynomials.S1); + C0.addPolynomial(6, polynomials.S2); + C0.addPolynomial(7, polynomials.S3); + polynomials.C0 = C0.getPolynomial(); + if (polynomials.C0.degree() >= 8 * settings.domainSize) throw new Error("C0 Polynomial is not well calculated"); + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 17); + await fdZKey.write(polynomials.C0.coef); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeFFlonkHeader(fdZKey) { + await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 2); + const primeQ = curve.q; + const n8q = (Math.floor((ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) + 1) * 8; + await fdZKey.writeULE32(n8q); + await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeQ, n8q); + const primeR = curve.r; + const n8r = (Math.floor((ffjavascript.Scalar.bitLength(primeR) - 1) / 64) + 1) * 8; + await fdZKey.writeULE32(n8r); + await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeR, n8r); + await fdZKey.writeULE32(settings.nVars); + await fdZKey.writeULE32(settings.nPublic); + await fdZKey.writeULE32(settings.domainSize); + await fdZKey.writeULE32(plonkAdditions.length); + await fdZKey.writeULE32(plonkConstraints.length); + await fdZKey.write(k1); + await fdZKey.write(k2); + await fdZKey.write(w3); + await fdZKey.write(w4); + await fdZKey.write(w8); + await fdZKey.write(wr); + let bX_2; + bX_2 = await fdPTau.read(sG2, pTauSections[3][0].p + sG2); + await fdZKey.write(bX_2); + let commitC0 = await polynomials.C0.multiExponentiation(PTau, "C0"); + await fdZKey.write(commitC0); + await (0, _iden3_binfileutils.endWriteSection)(fdZKey); + } + async function writeP4(fdZKey, buff) { + const [coefficients, evaluations4] = await Polynomial.to4T(buff, settings.domainSize, [], Fr); + await fdZKey.write(coefficients); + await fdZKey.write(evaluations4); + return [coefficients, evaluations4]; + } + function computeK1K2() { + let k1 = Fr.two; + while (isIncluded(k1, [], settings.cirPower)) Fr.add(k1, Fr.one); + let k2 = Fr.add(k1, Fr.one); + while (isIncluded(k2, [k1], settings.cirPower)) Fr.add(k2, Fr.one); + return [k1, k2]; + function isIncluded(k, kArr, pow) { + const domainSize = 2 ** pow; + let w = Fr.one; + for (let i = 0; i < domainSize; i++) { + if (Fr.eq(k, w)) return true; + for (let j = 0; j < kArr.length; j++) if (Fr.eq(k, Fr.mul(kArr[j], w))) return true; + w = Fr.mul(w, Fr.w[pow]); + } + return false; + } + } + function computeW3() { + let generator = Fr.e(31624); + let exponent = ffjavascript.Scalar.div(3648040478639879203707734290876212514758060733402672390616367364429301415936n, ffjavascript.Scalar.e(3)); + return Fr.exp(generator, exponent); + } + function computeW4() { + return Fr.w[2]; + } + function computeW8() { + return Fr.w[3]; + } + function getOmegaCubicRoot(power, Fr) { + const firstRoot = Fr.e(467799165886069610036046866799264026481344299079011762026774533774345988080n); + return Fr.exp(firstRoot, 2 ** (28 - power)); + } + } + //#endregion + //#region src/fflonk_prove.js + var { stringifyBigInts } = ffjavascript.utils; + async function fflonkProve(zkeyFileName, witnessFileName, logger, options) { + if (logger) logger.info("FFLONK PROVER STARTED"); + if (logger) logger.info("> Reading witness file"); + const { fd: fdWtns, sections: wtnsSections } = await _iden3_binfileutils.readBinFile(witnessFileName, "wtns", 2, 1 << 25, 1 << 23); + const wtns = await readHeader(fdWtns, wtnsSections); + if (logger) logger.info("> Reading zkey file"); + const { fd: fdZKey, sections: zkeySections } = await _iden3_binfileutils.readBinFile(zkeyFileName, "zkey", 2, 1 << 25, 1 << 23); + const zkey = await readHeader$1(fdZKey, zkeySections, void 0, options); + if (zkey.protocolId !== 10) throw new Error("zkey file is not fflonk"); + if (!ffjavascript.Scalar.eq(zkey.r, wtns.q)) throw new Error("Curve of the witness does not match the curve of the proving key"); + if (wtns.nWitness !== zkey.nVars - zkey.nAdditions) throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}, ${zkey.nAdditions}`); + const curve = zkey.curve; + const Fr = curve.Fr; + const sFr = curve.Fr.n8; + const sG1 = curve.G1.F.n8 * 2; + const sDomain = zkey.domainSize * sFr; + if (logger) { + logger.info("----------------------------"); + logger.info(" FFLONK PROVE SETTINGS"); + logger.info(` Curve: ${curve.name}`); + logger.info(` Circuit power: ${zkey.power}`); + logger.info(` Domain size: ${zkey.domainSize}`); + logger.info(` Vars: ${zkey.nVars}`); + logger.info(` Public vars: ${zkey.nPublic}`); + logger.info(` Constraints: ${zkey.nConstraints}`); + logger.info(` Additions: ${zkey.nAdditions}`); + logger.info("----------------------------"); + } + if (logger) logger.info("> Reading witness file data"); + const buffWitness = await _iden3_binfileutils.readSection(fdWtns, wtnsSections, 2); + await fdWtns.close(); + buffWitness.set(Fr.zero, 0); + const buffInternalWitness = new ffjavascript.BigBuffer(zkey.nAdditions * sFr); + let buffers = {}; + let polynomials = {}; + let evaluations = {}; + let toInverse = {}; + let challenges = {}; + let roots = {}; + let proof = new Proof(curve, logger); + if (logger) logger.info(`> Reading Section 3. Additions`); + await calculateAdditions(); + if (logger) logger.info(`> Reading Sections 12,13,14. Sigma1, Sigma2 & Sigma 3`); + if (logger) logger.info("··· Reading Sigma polynomials "); + polynomials.Sigma1 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.Sigma2 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.Sigma3 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + await fdZKey.readToBuffer(polynomials.Sigma1.coef, 0, sDomain, zkeySections[12][0].p); + await fdZKey.readToBuffer(polynomials.Sigma2.coef, 0, sDomain, zkeySections[13][0].p); + await fdZKey.readToBuffer(polynomials.Sigma3.coef, 0, sDomain, zkeySections[14][0].p); + if (logger) logger.info("··· Reading Sigma evaluations"); + evaluations.Sigma1 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.Sigma2 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.Sigma3 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + await fdZKey.readToBuffer(evaluations.Sigma1.eval, 0, sDomain * 4, zkeySections[12][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.Sigma2.eval, 0, sDomain * 4, zkeySections[13][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.Sigma3.eval, 0, sDomain * 4, zkeySections[14][0].p + sDomain); + if (logger) logger.info(`> Reading Section 16. Powers of Tau`); + const PTau = new ffjavascript.BigBuffer(zkey.domainSize * 16 * sG1); + await fdZKey.readToBuffer(PTau, 0, (zkey.domainSize * 9 + 18) * sG1, zkeySections[16][0].p); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info(""); + if (logger) logger.info("> ROUND 1"); + await round1(); + delete polynomials.T0; + delete evaluations.QL; + delete evaluations.QR; + delete evaluations.QM; + delete evaluations.QO; + delete evaluations.QC; + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info("> ROUND 2"); + await round2(); + delete buffers.A; + delete buffers.B; + delete buffers.C; + delete evaluations.A; + delete evaluations.B; + delete evaluations.C; + delete evaluations.Sigma1; + delete evaluations.Sigma2; + delete evaluations.Sigma3; + delete evaluations.lagrange1; + delete evaluations.Z; + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info("> ROUND 3"); + await round3(); + delete polynomials.A; + delete polynomials.B; + delete polynomials.C; + delete polynomials.Z; + delete polynomials.T1; + delete polynomials.T2; + delete polynomials.Sigma1; + delete polynomials.Sigma2; + delete polynomials.Sigma3; + delete polynomials.QL; + delete polynomials.QR; + delete polynomials.QM; + delete polynomials.QC; + delete polynomials.QO; + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info("> ROUND 4"); + await round4(); + if (globalThis.gc) globalThis.gc(); + if (logger) logger.info("> ROUND 5"); + await round5(); + delete polynomials.C0; + delete polynomials.C1; + delete polynomials.C2; + delete polynomials.R1; + delete polynomials.R2; + delete polynomials.F; + delete polynomials.L; + delete polynomials.ZT; + delete polynomials.ZTS2; + await fdZKey.close(); + if (globalThis.gc) globalThis.gc(); + proof.addEvaluation("inv", getMontgomeryBatchedInverse()); + let _proof = proof.toObjectProof(); + _proof.protocol = "fflonk"; + _proof.curve = curve.name; + let publicSignals = []; + for (let i = 1; i <= zkey.nPublic; i++) { + const i_sFr = i * sFr; + const pub = buffWitness.slice(i_sFr, i_sFr + sFr); + publicSignals.push(ffjavascript.Scalar.fromRprLE(pub)); + } + if (logger) logger.info("FFLONK PROVER FINISHED"); + return { + proof: stringifyBigInts(_proof), + publicSignals: stringifyBigInts(publicSignals) + }; + async function calculateAdditions() { + if (logger) logger.info("··· Computing additions"); + const additionsBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 3); + const sSum = 8 + sFr * 2; + for (let i = 0; i < zkey.nAdditions; i++) { + if (logger && 0 !== i && i % 1e5 === 0) logger.info(` addition ${i}/${zkey.nAdditions}`); + let offset = i * sSum; + const signalId1 = readUInt32(additionsBuff, offset); + offset += 4; + const signalId2 = readUInt32(additionsBuff, offset); + offset += 4; + const factor1 = additionsBuff.slice(offset, offset + sFr); + offset += sFr; + const factor2 = additionsBuff.slice(offset, offset + sFr); + const witness1 = getWitness(signalId1); + const witness2 = getWitness(signalId2); + const result = Fr.add(Fr.mul(factor1, witness1), Fr.mul(factor2, witness2)); + buffInternalWitness.set(result, sFr * i); + } + } + function readUInt32(b, o) { + const buff = b.slice(o, o + 4); + return new DataView(buff.buffer, buff.byteOffset, buff.byteLength).getUint32(0, true); + } + function getWitness(idx) { + let diff = zkey.nVars - zkey.nAdditions; + if (idx < diff) return buffWitness.slice(idx * sFr, idx * sFr + sFr); + else if (idx < zkey.nVars) { + const offset = (idx - diff) * sFr; + return buffInternalWitness.slice(offset, offset + sFr); + } + return Fr.zero; + } + async function round1() { + challenges.b = []; + for (let i = 1; i <= 9; i++) challenges.b[i] = Fr.random(); + if (logger) logger.info("> Computing A, B, C wire polynomials"); + await computeWirePolynomials(); + if (logger) logger.info("> Computing T0 polynomial"); + await computeT0(); + if (logger) logger.info("> Computing C1 polynomial"); + await computeC1(); + if (logger) logger.info("> Computing C1 multi exponentiation"); + let commitC1 = await polynomials.C1.multiExponentiation(PTau, "C1"); + proof.addPolynomial("C1", commitC1); + return 0; + async function computeWirePolynomials() { + if (logger) logger.info("··· Reading data from zkey file"); + buffers.A = new ffjavascript.BigBuffer(sDomain); + buffers.B = new ffjavascript.BigBuffer(sDomain); + buffers.C = new ffjavascript.BigBuffer(sDomain); + const aMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 4); + const bMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 5); + const cMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 6); + for (let i = 0; i < zkey.nConstraints; i++) { + const i_sFr = i * sFr; + const offset = i * 4; + const signalIdA = readUInt32(aMapBuff, offset); + buffers.A.set(getWitness(signalIdA), i_sFr); + const signalIdB = readUInt32(bMapBuff, offset); + buffers.B.set(getWitness(signalIdB), i_sFr); + const signalIdC = readUInt32(cMapBuff, offset); + buffers.C.set(getWitness(signalIdC), i_sFr); + } + buffers.A.set(challenges.b[1], sDomain - 64); + buffers.A.set(challenges.b[2], sDomain - 32); + buffers.B.set(challenges.b[3], sDomain - 64); + buffers.B.set(challenges.b[4], sDomain - 32); + buffers.C.set(challenges.b[5], sDomain - 64); + buffers.C.set(challenges.b[6], sDomain - 32); + buffers.A = await Fr.batchToMontgomery(buffers.A); + buffers.B = await Fr.batchToMontgomery(buffers.B); + buffers.C = await Fr.batchToMontgomery(buffers.C); + if (logger) logger.info("··· Computing A ifft"); + polynomials.A = await Polynomial.fromEvaluations(buffers.A, curve, logger); + if (logger) logger.info("··· Computing B ifft"); + polynomials.B = await Polynomial.fromEvaluations(buffers.B, curve, logger); + if (logger) logger.info("··· Computing C ifft"); + polynomials.C = await Polynomial.fromEvaluations(buffers.C, curve, logger); + if (logger) logger.info("··· Computing A fft"); + evaluations.A = await Evaluations.fromPolynomial(polynomials.A, 4, curve, logger); + if (logger) logger.info("··· Computing B fft"); + evaluations.B = await Evaluations.fromPolynomial(polynomials.B, 4, curve, logger); + if (logger) logger.info("··· Computing C fft"); + evaluations.C = await Evaluations.fromPolynomial(polynomials.C, 4, curve, logger); + if (polynomials.A.degree() >= zkey.domainSize) throw new Error("A Polynomial is not well calculated"); + if (polynomials.B.degree() >= zkey.domainSize) throw new Error("B Polynomial is not well calculated"); + if (polynomials.C.degree() >= zkey.domainSize) throw new Error("C Polynomial is not well calculated"); + } + async function computeT0() { + if (logger) logger.info(`··· Reading sections 7, 8, 9, 10, 11. Q selectors`); + evaluations.QL = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QR = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QM = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QO = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + evaluations.QC = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); + await fdZKey.readToBuffer(evaluations.QL.eval, 0, sDomain * 4, zkeySections[7][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QR.eval, 0, sDomain * 4, zkeySections[8][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QM.eval, 0, sDomain * 4, zkeySections[9][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QO.eval, 0, sDomain * 4, zkeySections[10][0].p + sDomain); + await fdZKey.readToBuffer(evaluations.QC.eval, 0, sDomain * 4, zkeySections[11][0].p + sDomain); + evaluations.lagrange1 = new Evaluations(await _iden3_binfileutils.readSection(fdZKey, zkeySections, 15), curve, logger); + buffers.T0 = new ffjavascript.BigBuffer(sDomain * 4); + if (logger) logger.info("··· Computing T0 evaluations"); + for (let i = 0; i < zkey.domainSize * 4; i++) { + if (logger && 0 !== i && i % 1e5 === 0) logger.info(` T0 evaluation ${i}/${zkey.domainSize * 4}`); + const a = evaluations.A.getEvaluation(i); + const b = evaluations.B.getEvaluation(i); + const c = evaluations.C.getEvaluation(i); + const ql = evaluations.QL.getEvaluation(i); + const qr = evaluations.QR.getEvaluation(i); + const qm = evaluations.QM.getEvaluation(i); + const qo = evaluations.QO.getEvaluation(i); + const qc = evaluations.QC.getEvaluation(i); + let pi = Fr.zero; + for (let j = 0; j < zkey.nPublic; j++) { + const offset = j * 5 * zkey.domainSize + zkey.domainSize + i; + const lPol = evaluations.lagrange1.getEvaluation(offset); + const aVal = buffers.A.slice(j * sFr, (j + 1) * sFr); + pi = Fr.sub(pi, Fr.mul(lPol, aVal)); + } + const e1 = Fr.mul(a, ql); + const e2 = Fr.mul(b, qr); + const e3 = Fr.mul(Fr.mul(a, b), qm); + const e4 = Fr.mul(c, qo); + const t0 = Fr.add(e1, Fr.add(e2, Fr.add(e3, Fr.add(e4, Fr.add(qc, pi))))); + buffers.T0.set(t0, i * sFr); + } + if (logger) logger.info("buffer T0: " + buffers.T0.byteLength / sFr); + if (logger) logger.info("··· Computing T0 ifft"); + polynomials.T0 = await Polynomial.fromEvaluations(buffers.T0, curve, logger); + if (logger) logger.info("T0 length: " + polynomials.T0.length()); + if (logger) logger.info("T0 degree: " + polynomials.T0.degree()); + if (logger) logger.info("··· Computing T0 / ZH"); + polynomials.T0.divByZerofier(zkey.domainSize, Fr.one); + if (polynomials.T0.degree() >= 2 * zkey.domainSize - 2) throw new Error(`T0 Polynomial is not well calculated (degree is ${polynomials.T0.degree()} and must be less than ${2 * zkey.domainSize + 2}`); + delete buffers.T0; + } + async function computeC1() { + let C1 = new CPolynomial(4, curve, logger); + C1.addPolynomial(0, polynomials.A); + C1.addPolynomial(1, polynomials.B); + C1.addPolynomial(2, polynomials.C); + C1.addPolynomial(3, polynomials.T0); + polynomials.C1 = C1.getPolynomial(); + if (polynomials.C1.degree() >= 8 * zkey.domainSize - 8) throw new Error("C1 Polynomial is not well calculated"); + } + } + async function round2() { + if (logger) logger.info("> Computing challenges beta and gamma"); + const transcript = new Keccak256Transcript(curve); + transcript.addPolCommitment(zkey.C0); + for (let i = 0; i < zkey.nPublic; i++) transcript.addScalar(buffers.A.slice(i * sFr, i * sFr + sFr)); + transcript.addPolCommitment(proof.getPolynomial("C1")); + challenges.beta = transcript.getChallenge(); + if (logger) logger.info("··· challenges.beta: " + Fr.toString(challenges.beta)); + transcript.reset(); + transcript.addScalar(challenges.beta); + challenges.gamma = transcript.getChallenge(); + if (logger) logger.info("··· challenges.gamma: " + Fr.toString(challenges.gamma)); + if (logger) logger.info("> Computing Z polynomial"); + await computeZ(); + if (logger) logger.info("> Computing T1 polynomial"); + await computeT1(); + if (logger) logger.info("> Computing T2 polynomial"); + await computeT2(); + if (logger) logger.info("> Computing C2 polynomial"); + await computeC2(); + if (logger) logger.info("> Computing C2 multi exponentiation"); + let commitC2 = await polynomials.C2.multiExponentiation(PTau, "C2"); + proof.addPolynomial("C2", commitC2); + return 0; + async function computeZ() { + if (logger) logger.info("··· Computing Z evaluations"); + let numArr = new ffjavascript.BigBuffer(sDomain); + let denArr = new ffjavascript.BigBuffer(sDomain); + numArr.set(Fr.one, 0); + denArr.set(Fr.one, 0); + let w = Fr.one; + for (let i = 0; i < zkey.domainSize; i++) { + if (logger && 0 !== i && i % 1e5 === 0) logger.info(` Z evaluation ${i}/${zkey.domainSize}`); + const i_sFr = i * sFr; + const betaw = Fr.mul(challenges.beta, w); + let num1 = buffers.A.slice(i_sFr, i_sFr + sFr); + num1 = Fr.add(num1, betaw); + num1 = Fr.add(num1, challenges.gamma); + let num2 = buffers.B.slice(i_sFr, i_sFr + sFr); + num2 = Fr.add(num2, Fr.mul(zkey.k1, betaw)); + num2 = Fr.add(num2, challenges.gamma); + let num3 = buffers.C.slice(i_sFr, i_sFr + sFr); + num3 = Fr.add(num3, Fr.mul(zkey.k2, betaw)); + num3 = Fr.add(num3, challenges.gamma); + let num = Fr.mul(num1, Fr.mul(num2, num3)); + let den1 = buffers.A.slice(i_sFr, i_sFr + sFr); + den1 = Fr.add(den1, Fr.mul(challenges.beta, evaluations.Sigma1.getEvaluation(i * 4))); + den1 = Fr.add(den1, challenges.gamma); + let den2 = buffers.B.slice(i_sFr, i_sFr + sFr); + den2 = Fr.add(den2, Fr.mul(challenges.beta, evaluations.Sigma2.getEvaluation(i * 4))); + den2 = Fr.add(den2, challenges.gamma); + let den3 = buffers.C.slice(i_sFr, i_sFr + sFr); + den3 = Fr.add(den3, Fr.mul(challenges.beta, evaluations.Sigma3.getEvaluation(i * 4))); + den3 = Fr.add(den3, challenges.gamma); + let den = Fr.mul(den1, Fr.mul(den2, den3)); + num = Fr.mul(numArr.slice(i_sFr, i_sFr + sFr), num); + numArr.set(num, (i + 1) % zkey.domainSize * sFr); + den = Fr.mul(denArr.slice(i_sFr, i_sFr + sFr), den); + denArr.set(den, (i + 1) % zkey.domainSize * sFr); + w = Fr.mul(w, Fr.w[zkey.power]); + } + denArr = await Fr.batchInverse(denArr); + for (let i = 0; i < zkey.domainSize; i++) { + const i_sFr = i * sFr; + const z = Fr.mul(numArr.slice(i_sFr, i_sFr + sFr), denArr.slice(i_sFr, i_sFr + sFr)); + numArr.set(z, i_sFr); + } + buffers.Z = numArr; + if (!Fr.eq(numArr.slice(0, sFr), Fr.one)) throw new Error("Copy constraints does not match"); + if (logger) logger.info("··· Computing Z ifft"); + polynomials.Z = await Polynomial.fromEvaluations(buffers.Z, curve, logger); + if (logger) logger.info("··· Computing Z fft"); + evaluations.Z = await Evaluations.fromPolynomial(polynomials.Z, 4, curve, logger); + polynomials.Z.blindCoefficients([ + challenges.b[9], + challenges.b[8], + challenges.b[7] + ]); + if (polynomials.Z.degree() >= zkey.domainSize + 3) throw new Error("Z Polynomial is not well calculated"); + delete buffers.Z; + } + async function computeT1() { + if (logger) logger.info("··· Computing T1 evaluations"); + buffers.T1 = new ffjavascript.BigBuffer(sDomain * 2); + buffers.T1z = new ffjavascript.BigBuffer(sDomain * 2); + let omega = Fr.one; + for (let i = 0; i < zkey.domainSize * 2; i++) { + if (logger && 0 !== i && i % 1e5 === 0) logger.info(` T1 evaluation ${i}/${zkey.domainSize * 4}`); + const omega2 = Fr.square(omega); + const z = evaluations.Z.getEvaluation(i * 2); + const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omega2), Fr.mul(challenges.b[8], omega)), challenges.b[9]); + const lagrange1 = evaluations.lagrange1.getEvaluation(zkey.domainSize + i * 2); + let t1 = Fr.mul(Fr.sub(z, Fr.one), lagrange1); + let t1z = Fr.mul(zp, lagrange1); + buffers.T1.set(t1, i * sFr); + buffers.T1z.set(t1z, i * sFr); + omega = Fr.mul(omega, Fr.w[zkey.power + 1]); + } + if (logger) logger.info("··· Computing T1 ifft"); + polynomials.T1 = await Polynomial.fromEvaluations(buffers.T1, curve, logger); + polynomials.T1.divByZerofier(zkey.domainSize, Fr.one); + if (logger) logger.info("··· Computing T1z ifft"); + polynomials.T1z = await Polynomial.fromEvaluations(buffers.T1z, curve, logger); + polynomials.T1.add(polynomials.T1z); + if (polynomials.T1.degree() >= zkey.domainSize + 2) throw new Error("T1 Polynomial is not well calculated"); + delete buffers.T1; + delete buffers.T1z; + delete polynomials.T1z; + } + async function computeT2() { + if (logger) logger.info("··· Computing T2 evaluations"); + buffers.T2 = new ffjavascript.BigBuffer(sDomain * 4); + buffers.T2z = new ffjavascript.BigBuffer(sDomain * 4); + let omega = Fr.one; + for (let i = 0; i < zkey.domainSize * 4; i++) { + if (logger && 0 !== i && i % 1e5 === 0) logger.info(` T2 evaluation ${i}/${zkey.domainSize * 4}`); + const omega2 = Fr.square(omega); + const omegaW = Fr.mul(omega, Fr.w[zkey.power]); + const omegaW2 = Fr.square(omegaW); + const a = evaluations.A.getEvaluation(i); + const b = evaluations.B.getEvaluation(i); + const c = evaluations.C.getEvaluation(i); + const z = evaluations.Z.getEvaluation(i); + const zW = evaluations.Z.getEvaluation((zkey.domainSize * 4 + 4 + i) % (zkey.domainSize * 4)); + const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omega2), Fr.mul(challenges.b[8], omega)), challenges.b[9]); + const zWp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omegaW2), Fr.mul(challenges.b[8], omegaW)), challenges.b[9]); + const sigma1 = evaluations.Sigma1.getEvaluation(i); + const sigma2 = evaluations.Sigma2.getEvaluation(i); + const sigma3 = evaluations.Sigma3.getEvaluation(i); + const betaX = Fr.mul(challenges.beta, omega); + let e11 = Fr.add(a, betaX); + e11 = Fr.add(e11, challenges.gamma); + let e12 = Fr.add(b, Fr.mul(betaX, zkey.k1)); + e12 = Fr.add(e12, challenges.gamma); + let e13 = Fr.add(c, Fr.mul(betaX, zkey.k2)); + e13 = Fr.add(e13, challenges.gamma); + let e1 = Fr.mul(Fr.mul(Fr.mul(e11, e12), e13), z); + let e1z = Fr.mul(Fr.mul(Fr.mul(e11, e12), e13), zp); + let e21 = Fr.add(a, Fr.mul(challenges.beta, sigma1)); + e21 = Fr.add(e21, challenges.gamma); + let e22 = Fr.add(b, Fr.mul(challenges.beta, sigma2)); + e22 = Fr.add(e22, challenges.gamma); + let e23 = Fr.add(c, Fr.mul(challenges.beta, sigma3)); + e23 = Fr.add(e23, challenges.gamma); + let e2 = Fr.mul(Fr.mul(Fr.mul(e21, e22), e23), zW); + let e2z = Fr.mul(Fr.mul(Fr.mul(e21, e22), e23), zWp); + let t2 = Fr.sub(e1, e2); + let t2z = Fr.sub(e1z, e2z); + buffers.T2.set(t2, i * sFr); + buffers.T2z.set(t2z, i * sFr); + omega = Fr.mul(omega, Fr.w[zkey.power + 2]); + } + if (logger) logger.info("··· Computing T2 ifft"); + polynomials.T2 = await Polynomial.fromEvaluations(buffers.T2, curve, logger); + if (logger) logger.info("··· Computing T2 / ZH"); + polynomials.T2.divByZerofier(zkey.domainSize, Fr.one); + if (logger) logger.info("··· Computing T2z ifft"); + polynomials.T2z = await Polynomial.fromEvaluations(buffers.T2z, curve, logger); + polynomials.T2.add(polynomials.T2z); + if (polynomials.T2.degree() >= 3 * zkey.domainSize) throw new Error("T2 Polynomial is not well calculated"); + delete buffers.T2; + delete buffers.T2z; + delete polynomials.T2z; + } + async function computeC2() { + let C2 = new CPolynomial(3, curve, logger); + C2.addPolynomial(0, polynomials.Z); + C2.addPolynomial(1, polynomials.T1); + C2.addPolynomial(2, polynomials.T2); + polynomials.C2 = C2.getPolynomial(); + if (polynomials.C2.degree() >= 9 * zkey.domainSize) throw new Error("C2 Polynomial is not well calculated"); + } + } + async function round3() { + if (logger) logger.info("> Computing challenge xi"); + const transcript = new Keccak256Transcript(curve); + transcript.addScalar(challenges.gamma); + transcript.addPolCommitment(proof.getPolynomial("C2")); + challenges.xiSeed = transcript.getChallenge(); + const xiSeed2 = Fr.square(challenges.xiSeed); + roots.w8 = []; + roots.w8[0] = Fr.one; + for (let i = 1; i < 8; i++) roots.w8[i] = Fr.mul(roots.w8[i - 1], zkey.w8); + roots.w4 = []; + roots.w4[0] = Fr.one; + for (let i = 1; i < 4; i++) roots.w4[i] = Fr.mul(roots.w4[i - 1], zkey.w4); + roots.w3 = []; + roots.w3[0] = Fr.one; + roots.w3[1] = zkey.w3; + roots.w3[2] = Fr.square(zkey.w3); + roots.S0 = {}; + roots.S0.h0w8 = []; + roots.S0.h0w8[0] = Fr.mul(xiSeed2, challenges.xiSeed); + for (let i = 1; i < 8; i++) roots.S0.h0w8[i] = Fr.mul(roots.S0.h0w8[0], roots.w8[i]); + roots.S1 = {}; + roots.S1.h1w4 = []; + roots.S1.h1w4[0] = Fr.square(roots.S0.h0w8[0]); + for (let i = 1; i < 4; i++) roots.S1.h1w4[i] = Fr.mul(roots.S1.h1w4[0], roots.w4[i]); + roots.S2 = {}; + roots.S2.h2w3 = []; + roots.S2.h2w3[0] = Fr.mul(roots.S1.h1w4[0], xiSeed2); + roots.S2.h2w3[1] = Fr.mul(roots.S2.h2w3[0], roots.w3[1]); + roots.S2.h2w3[2] = Fr.mul(roots.S2.h2w3[0], roots.w3[2]); + roots.S2.h3w3 = []; + roots.S2.h3w3[0] = Fr.mul(roots.S2.h2w3[0], zkey.wr); + roots.S2.h3w3[1] = Fr.mul(roots.S2.h3w3[0], roots.w3[1]); + roots.S2.h3w3[2] = Fr.mul(roots.S2.h3w3[0], roots.w3[2]); + challenges.xi = Fr.mul(Fr.square(roots.S2.h2w3[0]), roots.S2.h2w3[0]); + if (logger) logger.info("··· challenges.xi: " + Fr.toString(challenges.xi)); + polynomials.QL = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QR = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QM = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QO = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + polynomials.QC = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); + await fdZKey.readToBuffer(polynomials.QL.coef, 0, sDomain, zkeySections[7][0].p); + await fdZKey.readToBuffer(polynomials.QR.coef, 0, sDomain, zkeySections[8][0].p); + await fdZKey.readToBuffer(polynomials.QM.coef, 0, sDomain, zkeySections[9][0].p); + await fdZKey.readToBuffer(polynomials.QO.coef, 0, sDomain, zkeySections[10][0].p); + await fdZKey.readToBuffer(polynomials.QC.coef, 0, sDomain, zkeySections[11][0].p); + if (logger) logger.info("··· Computing evaluations"); + proof.addEvaluation("ql", polynomials.QL.evaluate(challenges.xi)); + proof.addEvaluation("qr", polynomials.QR.evaluate(challenges.xi)); + proof.addEvaluation("qm", polynomials.QM.evaluate(challenges.xi)); + proof.addEvaluation("qo", polynomials.QO.evaluate(challenges.xi)); + proof.addEvaluation("qc", polynomials.QC.evaluate(challenges.xi)); + proof.addEvaluation("s1", polynomials.Sigma1.evaluate(challenges.xi)); + proof.addEvaluation("s2", polynomials.Sigma2.evaluate(challenges.xi)); + proof.addEvaluation("s3", polynomials.Sigma3.evaluate(challenges.xi)); + proof.addEvaluation("a", polynomials.A.evaluate(challenges.xi)); + proof.addEvaluation("b", polynomials.B.evaluate(challenges.xi)); + proof.addEvaluation("c", polynomials.C.evaluate(challenges.xi)); + proof.addEvaluation("z", polynomials.Z.evaluate(challenges.xi)); + challenges.xiw = Fr.mul(challenges.xi, Fr.w[zkey.power]); + proof.addEvaluation("zw", polynomials.Z.evaluate(challenges.xiw)); + proof.addEvaluation("t1w", polynomials.T1.evaluate(challenges.xiw)); + proof.addEvaluation("t2w", polynomials.T2.evaluate(challenges.xiw)); + } + async function round4() { + if (logger) logger.info("> Computing challenge alpha"); + const transcript = new Keccak256Transcript(curve); + transcript.addScalar(challenges.xiSeed); + transcript.addScalar(proof.getEvaluation("ql")); + transcript.addScalar(proof.getEvaluation("qr")); + transcript.addScalar(proof.getEvaluation("qm")); + transcript.addScalar(proof.getEvaluation("qo")); + transcript.addScalar(proof.getEvaluation("qc")); + transcript.addScalar(proof.getEvaluation("s1")); + transcript.addScalar(proof.getEvaluation("s2")); + transcript.addScalar(proof.getEvaluation("s3")); + transcript.addScalar(proof.getEvaluation("a")); + transcript.addScalar(proof.getEvaluation("b")); + transcript.addScalar(proof.getEvaluation("c")); + transcript.addScalar(proof.getEvaluation("z")); + transcript.addScalar(proof.getEvaluation("zw")); + transcript.addScalar(proof.getEvaluation("t1w")); + transcript.addScalar(proof.getEvaluation("t2w")); + challenges.alpha = transcript.getChallenge(); + if (logger) logger.info("··· challenges.alpha: " + Fr.toString(challenges.alpha)); + if (logger) logger.info("> Reading C0 polynomial"); + polynomials.C0 = new Polynomial(new ffjavascript.BigBuffer(sDomain * 8), curve, logger); + await fdZKey.readToBuffer(polynomials.C0.coef, 0, sDomain * 8, zkeySections[17][0].p); + if (logger) logger.info("> Computing R0 polynomial"); + computeR0(); + if (logger) logger.info("> Computing R1 polynomial"); + computeR1(); + if (logger) logger.info("> Computing R2 polynomial"); + computeR2(); + if (logger) logger.info("> Computing F polynomial"); + await computeF(); + if (logger) logger.info("> Computing W1 multi exponentiation"); + let commitW1 = await polynomials.F.multiExponentiation(PTau, "W1"); + proof.addPolynomial("W1", commitW1); + return 0; + function computeR0() { + polynomials.R0 = Polynomial.lagrangePolynomialInterpolation([ + roots.S0.h0w8[0], + roots.S0.h0w8[1], + roots.S0.h0w8[2], + roots.S0.h0w8[3], + roots.S0.h0w8[4], + roots.S0.h0w8[5], + roots.S0.h0w8[6], + roots.S0.h0w8[7] + ], [ + polynomials.C0.evaluate(roots.S0.h0w8[0]), + polynomials.C0.evaluate(roots.S0.h0w8[1]), + polynomials.C0.evaluate(roots.S0.h0w8[2]), + polynomials.C0.evaluate(roots.S0.h0w8[3]), + polynomials.C0.evaluate(roots.S0.h0w8[4]), + polynomials.C0.evaluate(roots.S0.h0w8[5]), + polynomials.C0.evaluate(roots.S0.h0w8[6]), + polynomials.C0.evaluate(roots.S0.h0w8[7]) + ], curve); + if (polynomials.R0.degree() > 7) throw new Error("R0 Polynomial is not well calculated"); + } + function computeR1() { + polynomials.R1 = Polynomial.lagrangePolynomialInterpolation([ + roots.S1.h1w4[0], + roots.S1.h1w4[1], + roots.S1.h1w4[2], + roots.S1.h1w4[3] + ], [ + polynomials.C1.evaluate(roots.S1.h1w4[0]), + polynomials.C1.evaluate(roots.S1.h1w4[1]), + polynomials.C1.evaluate(roots.S1.h1w4[2]), + polynomials.C1.evaluate(roots.S1.h1w4[3]) + ], curve); + if (polynomials.R1.degree() > 3) throw new Error("R1 Polynomial is not well calculated"); + } + function computeR2() { + polynomials.R2 = Polynomial.lagrangePolynomialInterpolation([ + roots.S2.h2w3[0], + roots.S2.h2w3[1], + roots.S2.h2w3[2], + roots.S2.h3w3[0], + roots.S2.h3w3[1], + roots.S2.h3w3[2] + ], [ + polynomials.C2.evaluate(roots.S2.h2w3[0]), + polynomials.C2.evaluate(roots.S2.h2w3[1]), + polynomials.C2.evaluate(roots.S2.h2w3[2]), + polynomials.C2.evaluate(roots.S2.h3w3[0]), + polynomials.C2.evaluate(roots.S2.h3w3[1]), + polynomials.C2.evaluate(roots.S2.h3w3[2]) + ], curve); + if (polynomials.R2.degree() > 5) throw new Error("R2 Polynomial is not well calculated"); + } + async function computeF() { + if (logger) logger.info("··· Computing F polynomial"); + polynomials.F = Polynomial.fromPolynomial(polynomials.C0, curve, logger); + polynomials.F.sub(polynomials.R0); + polynomials.F.divByZerofier(8, challenges.xi); + let f2 = Polynomial.fromPolynomial(polynomials.C1, curve, logger); + f2.sub(polynomials.R1); + f2.mulScalar(challenges.alpha); + f2.divByZerofier(4, challenges.xi); + let f3 = Polynomial.fromPolynomial(polynomials.C2, curve, logger); + f3.sub(polynomials.R2); + f3.mulScalar(Fr.square(challenges.alpha)); + f3.divByZerofier(3, challenges.xi); + f3.divByZerofier(3, challenges.xiw); + polynomials.F.add(f2); + polynomials.F.add(f3); + if (polynomials.F.degree() >= 9 * zkey.domainSize - 6) throw new Error("F Polynomial is not well calculated"); + } + } + async function round5() { + if (logger) logger.info("> Computing challenge y"); + const transcript = new Keccak256Transcript(curve); + transcript.addScalar(challenges.alpha); + transcript.addPolCommitment(proof.getPolynomial("W1")); + challenges.y = transcript.getChallenge(); + if (logger) logger.info("··· challenges.y: " + Fr.toString(challenges.y)); + if (logger) logger.info("> Computing L polynomial"); + await computeL(); + if (logger) logger.info("> Computing ZTS2 polynomial"); + await computeZTS2(); + let ZTS2Y = polynomials.ZTS2.evaluate(challenges.y); + ZTS2Y = Fr.inv(ZTS2Y); + polynomials.L.mulScalar(ZTS2Y); + const polDividend = Polynomial.fromCoefficientsArray([Fr.neg(challenges.y), Fr.one], curve); + if (logger) logger.info("> Computing W' = L / ZTS2 polynomial"); + const polRemainder = polynomials.L.divBy(polDividend); + if (polRemainder.degree() > 0) throw new Error(`Degree of L(X)/(ZTS2(y)(X-y)) remainder is ${polRemainder.degree()} and should be 0`); + if (polynomials.L.degree() >= 9 * zkey.domainSize - 1) throw new Error("Degree of L(X)/(ZTS2(y)(X-y)) is not correct"); + if (logger) logger.info("> Computing W' multi exponentiation"); + let commitW2 = await polynomials.L.multiExponentiation(PTau, "W2"); + proof.addPolynomial("W2", commitW2); + return 0; + async function computeL() { + if (logger) logger.info("··· Computing L polynomial"); + const evalR0Y = polynomials.R0.evaluate(challenges.y); + const evalR1Y = polynomials.R1.evaluate(challenges.y); + const evalR2Y = polynomials.R2.evaluate(challenges.y); + let mulL0 = Fr.sub(challenges.y, roots.S0.h0w8[0]); + for (let i = 1; i < 8; i++) mulL0 = Fr.mul(mulL0, Fr.sub(challenges.y, roots.S0.h0w8[i])); + let mulL1 = Fr.sub(challenges.y, roots.S1.h1w4[0]); + for (let i = 1; i < 4; i++) mulL1 = Fr.mul(mulL1, Fr.sub(challenges.y, roots.S1.h1w4[i])); + let mulL2 = Fr.sub(challenges.y, roots.S2.h2w3[0]); + for (let i = 1; i < 3; i++) mulL2 = Fr.mul(mulL2, Fr.sub(challenges.y, roots.S2.h2w3[i])); + for (let i = 0; i < 3; i++) mulL2 = Fr.mul(mulL2, Fr.sub(challenges.y, roots.S2.h3w3[i])); + let preL0 = Fr.mul(mulL1, mulL2); + let preL1 = Fr.mul(challenges.alpha, Fr.mul(mulL0, mulL2)); + let preL2 = Fr.mul(Fr.square(challenges.alpha), Fr.mul(mulL0, mulL1)); + toInverse["denH1"] = mulL1; + toInverse["denH2"] = mulL2; + polynomials.L = Polynomial.fromPolynomial(polynomials.C0, curve, logger); + polynomials.L.subScalar(evalR0Y); + polynomials.L.mulScalar(preL0); + let l2 = Polynomial.fromPolynomial(polynomials.C1, curve, logger); + l2.subScalar(evalR1Y); + l2.mulScalar(preL1); + let l3 = Polynomial.fromPolynomial(polynomials.C2, curve, logger); + l3.subScalar(evalR2Y); + l3.mulScalar(preL2); + polynomials.L.add(l2); + polynomials.L.add(l3); + if (logger) logger.info("> Computing ZT polynomial"); + await computeZT(); + const evalZTY = polynomials.ZT.evaluate(challenges.y); + polynomials.F.mulScalar(evalZTY); + polynomials.L.sub(polynomials.F); + if (polynomials.L.degree() >= 9 * zkey.domainSize) throw new Error("L Polynomial is not well calculated"); + delete buffers.L; + } + async function computeZT() { + polynomials.ZT = Polynomial.zerofierPolynomial([ + roots.S0.h0w8[0], + roots.S0.h0w8[1], + roots.S0.h0w8[2], + roots.S0.h0w8[3], + roots.S0.h0w8[4], + roots.S0.h0w8[5], + roots.S0.h0w8[6], + roots.S0.h0w8[7], + roots.S1.h1w4[0], + roots.S1.h1w4[1], + roots.S1.h1w4[2], + roots.S1.h1w4[3], + roots.S2.h2w3[0], + roots.S2.h2w3[1], + roots.S2.h2w3[2], + roots.S2.h3w3[0], + roots.S2.h3w3[1], + roots.S2.h3w3[2] + ], curve); + } + async function computeZTS2() { + polynomials.ZTS2 = Polynomial.zerofierPolynomial([ + roots.S1.h1w4[0], + roots.S1.h1w4[1], + roots.S1.h1w4[2], + roots.S1.h1w4[3], + roots.S2.h2w3[0], + roots.S2.h2w3[1], + roots.S2.h2w3[2], + roots.S2.h3w3[0], + roots.S2.h3w3[1], + roots.S2.h3w3[2] + ], curve); + } + } + function getMontgomeryBatchedInverse() { + let xiN = challenges.xi; + for (let i = 0; i < zkey.power; i++) xiN = Fr.square(xiN); + toInverse["zh"] = Fr.sub(xiN, Fr.one); + computeLiS0(toInverse, roots.S0.h0w8, challenges.y, curve); + computeLiS1(toInverse, roots.S1.h1w4, challenges.y, curve); + computeLiS2(toInverse, roots.S2.h2w3, roots.S2.h3w3, challenges.y, challenges.xi, challenges.xiw, curve); + const size = Math.max(1, zkey.nPublic); + let w = Fr.one; + for (let i = 0; i < size; i++) { + toInverse["Li_" + (i + 1)] = Fr.mul(Fr.e(zkey.domainSize), Fr.sub(challenges.xi, w)); + w = Fr.mul(w, Fr.w[zkey.power]); + } + let mulAccumulator = Fr.one; + for (const element of Object.values(toInverse)) if (Array.isArray(element)) for (const subElement of element) mulAccumulator = Fr.mul(mulAccumulator, subElement); + else mulAccumulator = Fr.mul(mulAccumulator, element); + return Fr.inv(mulAccumulator); + function computeLiS0(toInverse, roots, x, curve) { + const Fr = curve.Fr; + const len = roots.length; + const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); + const Li = []; + for (let i = 0; i < len; i++) { + const den2 = roots[(len - 1) * i % len]; + const den3 = Fr.sub(x, roots[i]); + toInverse[["LiS0_" + (i + 1)]] = Fr.mul(Fr.mul(den1, den2), den3); + } + return Li; + } + function computeLiS1(toInverse, roots, x, curve) { + const Fr = curve.Fr; + const len = roots.length; + const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); + const Li = []; + for (let i = 0; i < len; i++) { + const den2 = roots[(len - 1) * i % len]; + const den3 = Fr.sub(x, roots[i]); + toInverse[["LiS1_" + (i + 1)]] = Fr.mul(Fr.mul(den1, den2), den3); + } + return Li; + } + function computeLiS2(toInverse, S2, S2p, value, xi, xiw, curve) { + const Fr = curve.Fr; + const Li = []; + const _3h2 = Fr.mul(Fr.e(3), S2[0]); + const xisubxiw = Fr.sub(xi, xiw); + let den1 = Fr.mul(_3h2, xisubxiw); + for (let i = 0; i < 3; i++) { + const den2 = S2[2 * i % 3]; + const den3 = Fr.sub(value, S2[i]); + toInverse[["LiS2_" + (i + 1)]] = Fr.mul(den1, Fr.mul(den2, den3)); + } + const _3h3 = Fr.mul(Fr.e(3), S2p[0]); + const xiwsubxi = Fr.sub(xiw, xi); + den1 = Fr.mul(_3h3, xiwsubxi); + for (let i = 0; i < 3; i++) { + const den2 = S2p[2 * i % 3]; + const den3 = Fr.sub(value, S2p[i]); + toInverse[["LiS2_" + (i + 1 + 3)]] = Fr.mul(den1, Fr.mul(den2, den3)); + } + return Li; + } + } + } + //#endregion + //#region src/fflonk_full_prove.js + var { unstringifyBigInts: unstringifyBigInts$2 } = ffjavascript.utils; + async function fflonkFullProve(_input, wasmFilename, zkeyFilename, logger, wtnsCalcOptions, proverOptions) { + const input = unstringifyBigInts$2(_input); + const wtns = { type: "mem" }; + await wtnsCalculate(input, wasmFilename, wtns, wtnsCalcOptions); + return await fflonkProve(zkeyFilename, wtns, logger, proverOptions); + } + //#endregion + //#region src/fflonk_verify.js + var { unstringifyBigInts: unstringifyBigInts$1 } = ffjavascript.utils; + async function fflonkVerify(_vk_verifier, _publicSignals, _proof, logger) { + if (logger) logger.info("FFLONK VERIFIER STARTED"); + _vk_verifier = unstringifyBigInts$1(_vk_verifier); + _proof = unstringifyBigInts$1(_proof); + const curve = await getCurveFromName(_vk_verifier.curve); + const vk = fromObjectVk(curve, _vk_verifier); + const proof = new Proof(curve, logger); + proof.fromObjectProof(_proof); + const publicSignals = unstringifyBigInts$1(_publicSignals); + if (publicSignals.length !== vk.nPublic) { + logger.error("Number of public signals does not match with vk"); + return false; + } + const Fr = curve.Fr; + if (logger) { + logger.info("----------------------------"); + logger.info(" FFLONK VERIFY SETTINGS"); + logger.info(` Curve: ${curve.name}`); + logger.info(` Circuit power: ${vk.power}`); + logger.info(` Domain size: ${2 ** vk.power}`); + logger.info(` Public vars: ${vk.nPublic}`); + logger.info("----------------------------"); + } + if (logger) logger.info("> Checking commitments belong to G1"); + if (!commitmentsBelongToG1(curve, proof, vk)) { + if (logger) logger.error("Proof commitments are not valid"); + return false; + } + if (logger) logger.info("> Checking evaluations belong to F"); + if (!evaluationsAreValid(curve, proof)) { + if (logger) logger.error("Proof evaluations are not valid."); + return false; + } + if (logger) logger.info("> Checking public inputs belong to F"); + if (!publicInputsAreValid(curve, publicSignals)) { + if (logger) logger.error("Public inputs are not valid."); + return false; + } + if (logger) logger.info("> Computing challenges"); + const { challenges, roots } = computeChallenges(curve, proof, vk, publicSignals, logger); + if (logger) logger.info("> Computing Zero polynomial evaluation Z_H(xi)"); + challenges.zh = Fr.sub(challenges.xiN, Fr.one); + challenges.invzh = Fr.inv(challenges.zh); + if (logger) logger.info("> Computing Lagrange evaluations"); + const lagrangeEvals = await computeLagrangeEvaluations(curve, challenges, vk); + if (logger) logger.info("> Computing polynomial identities PI(X)"); + const pi = calculatePI(curve, publicSignals, lagrangeEvals); + if (logger) logger.info("> Computing r0(y)"); + const r0 = computeR0(proof, challenges, roots, curve, logger); + if (logger) logger.info("> Computing r1(y)"); + const r1 = computeR1(proof, challenges, roots, pi, curve, logger); + if (logger) logger.info("> Computing r2(y)"); + const r2 = computeR2(proof, challenges, roots, lagrangeEvals[1], vk, curve, logger); + if (logger) logger.info("> Computing F"); + const F = computeF(curve, proof, vk, challenges, roots); + if (logger) logger.info("> Computing E"); + const E = computeE(curve, proof, challenges, vk, r0, r1, r2); + if (logger) logger.info("> Computing J"); + const J = computeJ(curve, proof, challenges); + if (logger) logger.info("> Validate all evaluations with a pairing"); + const res = await isValidPairing(curve, proof, challenges, vk, F, E, J); + if (logger) if (res) logger.info("PROOF VERIFIED SUCCESSFULLY"); + else logger.warn("Invalid Proof"); + if (logger) logger.info("FFLONK VERIFIER FINISHED"); + return res; + } + function fromObjectVk(curve, vk) { + const res = vk; + res.k1 = curve.Fr.fromObject(vk.k1); + res.k2 = curve.Fr.fromObject(vk.k2); + res.w = curve.Fr.fromObject(vk.w); + res.w3 = curve.Fr.fromObject(vk.w3); + res.w4 = curve.Fr.fromObject(vk.w4); + res.w8 = curve.Fr.fromObject(vk.w8); + res.wr = curve.Fr.fromObject(vk.wr); + res.X_2 = curve.G2.fromObject(vk.X_2); + res.C0 = curve.G1.fromObject(vk.C0); + return res; + } + function commitmentsBelongToG1(curve, proof, vk) { + const G1 = curve.G1; + return G1.isValid(proof.polynomials.C1) && G1.isValid(proof.polynomials.C2) && G1.isValid(proof.polynomials.W1) && G1.isValid(proof.polynomials.W2) && G1.isValid(vk.C0); + } + function checkValueBelongToField(curve, value) { + return ffjavascript.Scalar.geq(value, 0) && ffjavascript.Scalar.lt(value, curve.r); + } + function checkEvaluationIsValid(curve, evaluation) { + return checkValueBelongToField(curve, ffjavascript.Scalar.fromRprLE(evaluation)); + } + function evaluationsAreValid(curve, proof) { + return checkEvaluationIsValid(curve, proof.evaluations.ql) && checkEvaluationIsValid(curve, proof.evaluations.qr) && checkEvaluationIsValid(curve, proof.evaluations.qm) && checkEvaluationIsValid(curve, proof.evaluations.qo) && checkEvaluationIsValid(curve, proof.evaluations.qc) && checkEvaluationIsValid(curve, proof.evaluations.s1) && checkEvaluationIsValid(curve, proof.evaluations.s2) && checkEvaluationIsValid(curve, proof.evaluations.s3) && checkEvaluationIsValid(curve, proof.evaluations.a) && checkEvaluationIsValid(curve, proof.evaluations.b) && checkEvaluationIsValid(curve, proof.evaluations.c) && checkEvaluationIsValid(curve, proof.evaluations.z) && checkEvaluationIsValid(curve, proof.evaluations.zw) && checkEvaluationIsValid(curve, proof.evaluations.t1w) && checkEvaluationIsValid(curve, proof.evaluations.t2w); + } + function publicInputsAreValid(curve, publicInputs) { + for (let i = 0; i < publicInputs.length; i++) if (!checkValueBelongToField(curve, publicInputs[i])) return false; + return true; + } + function computeChallenges(curve, proof, vk, publicSignals, logger) { + const Fr = curve.Fr; + const challenges = {}; + const roots = {}; + const transcript = new Keccak256Transcript(curve); + transcript.addPolCommitment(vk.C0); + for (let i = 0; i < publicSignals.length; i++) transcript.addScalar(Fr.e(publicSignals[i])); + transcript.addPolCommitment(proof.polynomials.C1); + challenges.beta = transcript.getChallenge(); + transcript.reset(); + transcript.addScalar(challenges.beta); + challenges.gamma = transcript.getChallenge(); + transcript.reset(); + transcript.addScalar(challenges.gamma); + transcript.addPolCommitment(proof.polynomials.C2); + const xiSeed = transcript.getChallenge(); + const xiSeed2 = Fr.square(xiSeed); + let w8 = []; + w8[1] = vk.w8; + w8[2] = Fr.square(vk.w8); + w8[3] = Fr.mul(w8[2], vk.w8); + w8[4] = Fr.mul(w8[3], vk.w8); + w8[5] = Fr.mul(w8[4], vk.w8); + w8[6] = Fr.mul(w8[5], vk.w8); + w8[7] = Fr.mul(w8[6], vk.w8); + let w4 = []; + w4[1] = vk.w4; + w4[2] = Fr.square(vk.w4); + w4[3] = Fr.mul(w4[2], vk.w4); + let w3 = []; + w3[1] = vk.w3; + w3[2] = Fr.square(vk.w3); + roots.S0 = {}; + roots.S0.h0w8 = []; + roots.S0.h0w8[0] = Fr.mul(xiSeed2, xiSeed); + for (let i = 1; i < 8; i++) roots.S0.h0w8[i] = Fr.mul(roots.S0.h0w8[0], w8[i]); + roots.S1 = {}; + roots.S1.h1w4 = []; + roots.S1.h1w4[0] = Fr.square(roots.S0.h0w8[0]); + for (let i = 1; i < 4; i++) roots.S1.h1w4[i] = Fr.mul(roots.S1.h1w4[0], w4[i]); + roots.S2 = {}; + roots.S2.h2w3 = []; + roots.S2.h2w3[0] = Fr.mul(roots.S1.h1w4[0], xiSeed2); + roots.S2.h2w3[1] = Fr.mul(roots.S2.h2w3[0], w3[1]); + roots.S2.h2w3[2] = Fr.mul(roots.S2.h2w3[0], w3[2]); + roots.S2.h3w3 = []; + roots.S2.h3w3[0] = Fr.mul(roots.S2.h2w3[0], vk.wr); + roots.S2.h3w3[1] = Fr.mul(roots.S2.h3w3[0], w3[1]); + roots.S2.h3w3[2] = Fr.mul(roots.S2.h3w3[0], w3[2]); + challenges.xi = Fr.mul(Fr.square(roots.S2.h2w3[0]), roots.S2.h2w3[0]); + challenges.xiw = Fr.mul(challenges.xi, Fr.w[vk.power]); + challenges.xiN = challenges.xi; + vk.domainSize = 1; + for (let i = 0; i < vk.power; i++) { + challenges.xiN = Fr.square(challenges.xiN); + vk.domainSize *= 2; + } + transcript.reset(); + transcript.addScalar(xiSeed); + transcript.addScalar(proof.evaluations.ql); + transcript.addScalar(proof.evaluations.qr); + transcript.addScalar(proof.evaluations.qm); + transcript.addScalar(proof.evaluations.qo); + transcript.addScalar(proof.evaluations.qc); + transcript.addScalar(proof.evaluations.s1); + transcript.addScalar(proof.evaluations.s2); + transcript.addScalar(proof.evaluations.s3); + transcript.addScalar(proof.evaluations.a); + transcript.addScalar(proof.evaluations.b); + transcript.addScalar(proof.evaluations.c); + transcript.addScalar(proof.evaluations.z); + transcript.addScalar(proof.evaluations.zw); + transcript.addScalar(proof.evaluations.t1w); + transcript.addScalar(proof.evaluations.t2w); + challenges.alpha = transcript.getChallenge(); + transcript.reset(); + transcript.addScalar(challenges.alpha); + transcript.addPolCommitment(proof.polynomials.W1); + challenges.y = transcript.getChallenge(); + if (logger) { + logger.info("··· challenges.beta: " + Fr.toString(challenges.beta)); + logger.info("··· challenges.gamma: " + Fr.toString(challenges.gamma)); + logger.info("··· challenges.xi: " + Fr.toString(challenges.xi)); + logger.info("··· challenges.alpha: " + Fr.toString(challenges.alpha)); + logger.info("··· challenges.y: " + Fr.toString(challenges.y)); + } + return { + challenges, + roots + }; + } + async function computeLagrangeEvaluations(curve, challenges, vk) { + const Fr = curve.Fr; + const size = Math.max(1, vk.nPublic); + const numArr = new ffjavascript.BigBuffer(size * Fr.n8); + let denArr = new ffjavascript.BigBuffer(size * Fr.n8); + let w = Fr.one; + for (let i = 0; i < size; i++) { + const i_sFr = i * Fr.n8; + numArr.set(Fr.mul(w, challenges.zh), i_sFr); + denArr.set(Fr.mul(Fr.e(vk.domainSize), Fr.sub(challenges.xi, w)), i_sFr); + w = Fr.mul(w, vk.w); + } + denArr = await Fr.batchInverse(denArr); + let L = []; + for (let i = 0; i < size; i++) { + const i_sFr = i * Fr.n8; + L[i + 1] = Fr.mul(numArr.slice(i_sFr, i_sFr + Fr.n8), denArr.slice(i_sFr, i_sFr + Fr.n8)); + } + return L; + } + function calculatePI(curve, publicSignals, lagrangeEvals) { + const Fr = curve.Fr; + let pi = Fr.zero; + for (let i = 0; i < publicSignals.length; i++) { + const w = Fr.e(publicSignals[i]); + pi = Fr.sub(pi, Fr.mul(w, lagrangeEvals[i + 1])); + } + return pi; + } + function computeR0(proof, challenges, roots, curve, logger) { + const Fr = curve.Fr; + const Li = computeLagrangeLiSi(roots.S0.h0w8, challenges.y, challenges.xi, curve); + if (logger) logger.info("··· Computing r0(y)"); + let res = Fr.zero; + for (let i = 0; i < 8; i++) { + let coefValues = []; + coefValues[1] = roots.S0.h0w8[i]; + for (let j = 2; j < 8; j++) coefValues[j] = Fr.mul(coefValues[j - 1], roots.S0.h0w8[i]); + let c0 = Fr.add(proof.evaluations.ql, Fr.mul(proof.evaluations.qr, coefValues[1])); + c0 = Fr.add(c0, Fr.mul(proof.evaluations.qo, coefValues[2])); + c0 = Fr.add(c0, Fr.mul(proof.evaluations.qm, coefValues[3])); + c0 = Fr.add(c0, Fr.mul(proof.evaluations.qc, coefValues[4])); + c0 = Fr.add(c0, Fr.mul(proof.evaluations.s1, coefValues[5])); + c0 = Fr.add(c0, Fr.mul(proof.evaluations.s2, coefValues[6])); + c0 = Fr.add(c0, Fr.mul(proof.evaluations.s3, coefValues[7])); + res = Fr.add(res, Fr.mul(c0, Li[i])); + } + return res; + } + function computeR1(proof, challenges, roots, pi, curve, logger) { + const Fr = curve.Fr; + const Li = computeLagrangeLiSi(roots.S1.h1w4, challenges.y, challenges.xi, curve); + if (logger) logger.info("··· Computing T0(xi)"); + let t0 = Fr.mul(proof.evaluations.ql, proof.evaluations.a); + t0 = Fr.add(t0, Fr.mul(proof.evaluations.qr, proof.evaluations.b)); + t0 = Fr.add(t0, Fr.mul(proof.evaluations.qm, Fr.mul(proof.evaluations.a, proof.evaluations.b))); + t0 = Fr.add(t0, Fr.mul(proof.evaluations.qo, proof.evaluations.c)); + t0 = Fr.add(t0, proof.evaluations.qc); + t0 = Fr.add(t0, pi); + t0 = Fr.mul(t0, challenges.invzh); + if (logger) logger.info("··· Computing C1(h_1ω_4^i) values"); + let res = Fr.zero; + for (let i = 0; i < 4; i++) { + let c1 = proof.evaluations.a; + c1 = Fr.add(c1, Fr.mul(roots.S1.h1w4[i], proof.evaluations.b)); + const h1w4Squared = Fr.square(roots.S1.h1w4[i]); + c1 = Fr.add(c1, Fr.mul(h1w4Squared, proof.evaluations.c)); + c1 = Fr.add(c1, Fr.mul(Fr.mul(h1w4Squared, roots.S1.h1w4[i]), t0)); + res = Fr.add(res, Fr.mul(c1, Li[i])); + } + return res; + } + function computeR2(proof, challenges, roots, lagrange1, vk, curve, logger) { + const Fr = curve.Fr; + const LiS2 = computeLagrangeLiS2([roots.S2.h2w3, roots.S2.h3w3], challenges.y, challenges.xi, challenges.xiw, curve); + if (logger) logger.info("··· Computing T1(xi)"); + let t1 = Fr.sub(proof.evaluations.z, Fr.one); + t1 = Fr.mul(t1, lagrange1); + t1 = Fr.mul(t1, challenges.invzh); + if (logger) logger.info("··· Computing T2(xi)"); + const betaxi = Fr.mul(challenges.beta, challenges.xi); + const t211 = Fr.add(proof.evaluations.a, Fr.add(betaxi, challenges.gamma)); + const t212 = Fr.add(proof.evaluations.b, Fr.add(Fr.mul(betaxi, vk.k1), challenges.gamma)); + const t213 = Fr.add(proof.evaluations.c, Fr.add(Fr.mul(betaxi, vk.k2), challenges.gamma)); + const t21 = Fr.mul(t211, Fr.mul(t212, Fr.mul(t213, proof.evaluations.z))); + const t221 = Fr.add(proof.evaluations.a, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s1), challenges.gamma)); + const t222 = Fr.add(proof.evaluations.b, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s2), challenges.gamma)); + const t223 = Fr.add(proof.evaluations.c, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s3), challenges.gamma)); + const t22 = Fr.mul(t221, Fr.mul(t222, Fr.mul(t223, proof.evaluations.zw))); + let t2 = Fr.sub(t21, t22); + t2 = Fr.mul(t2, challenges.invzh); + if (logger) logger.info("··· Computing C2(h_2ω_3^i) values"); + let res = Fr.zero; + for (let i = 0; i < 3; i++) { + let c2 = Fr.add(proof.evaluations.z, Fr.mul(roots.S2.h2w3[i], t1)); + c2 = Fr.add(c2, Fr.mul(Fr.square(roots.S2.h2w3[i]), t2)); + res = Fr.add(res, Fr.mul(c2, LiS2[i])); + } + if (logger) logger.info("··· Computing C2(h_3ω_3^i) values"); + for (let i = 0; i < 3; i++) { + let c2 = Fr.add(proof.evaluations.zw, Fr.mul(roots.S2.h3w3[i], proof.evaluations.t1w)); + c2 = Fr.add(c2, Fr.mul(Fr.square(roots.S2.h3w3[i]), proof.evaluations.t2w)); + res = Fr.add(res, Fr.mul(c2, LiS2[i + 3])); + } + return res; + } + function computeF(curve, proof, vk, challenges, roots) { + const G1 = curve.G1; + const Fr = curve.Fr; + let mulH0 = Fr.sub(challenges.y, roots.S0.h0w8[0]); + for (let i = 1; i < 8; i++) mulH0 = Fr.mul(mulH0, Fr.sub(challenges.y, roots.S0.h0w8[i])); + challenges.temp = mulH0; + let mulH1 = Fr.sub(challenges.y, roots.S1.h1w4[0]); + for (let i = 1; i < 4; i++) mulH1 = Fr.mul(mulH1, Fr.sub(challenges.y, roots.S1.h1w4[i])); + let mulH2 = Fr.sub(challenges.y, roots.S2.h2w3[0]); + for (let i = 1; i < 3; i++) mulH2 = Fr.mul(mulH2, Fr.sub(challenges.y, roots.S2.h2w3[i])); + for (let i = 0; i < 3; i++) mulH2 = Fr.mul(mulH2, Fr.sub(challenges.y, roots.S2.h3w3[i])); + challenges.quotient1 = Fr.mul(challenges.alpha, Fr.div(mulH0, mulH1)); + challenges.quotient2 = Fr.mul(Fr.square(challenges.alpha), Fr.div(mulH0, mulH2)); + let F2 = G1.timesFr(proof.polynomials.C1, challenges.quotient1); + let F3 = G1.timesFr(proof.polynomials.C2, challenges.quotient2); + return G1.add(vk.C0, G1.add(F2, F3)); + } + function computeE(curve, proof, challenges, vk, r0, r1, r2) { + const G1 = curve.G1; + const Fr = curve.Fr; + let E2 = Fr.mul(r1, challenges.quotient1); + let E3 = Fr.mul(r2, challenges.quotient2); + return G1.timesFr(G1.one, Fr.add(r0, Fr.add(E2, E3))); + } + function computeJ(curve, proof, challenges) { + return curve.G1.timesFr(proof.polynomials.W1, challenges.temp); + } + async function isValidPairing(curve, proof, challenges, vk, F, E, J) { + const G1 = curve.G1; + let A1 = G1.timesFr(proof.polynomials.W2, challenges.y); + A1 = G1.add(G1.sub(G1.sub(F, E), J), A1); + const A2 = curve.G2.one; + const B1 = proof.polynomials.W2; + const B2 = vk.X_2; + return await curve.pairingEq(G1.neg(A1), A2, B1, B2); + } + function computeLagrangeLiSi(roots, x, xi, curve) { + const Fr = curve.Fr; + const len = roots.length; + const num = Fr.sub(Fr.exp(x, len), xi); + const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); + const Li = []; + for (let i = 0; i < len; i++) { + const den2 = roots[(len - 1) * i % len]; + const den3 = Fr.sub(x, roots[i]); + Li[i] = Fr.div(num, Fr.mul(Fr.mul(den1, den2), den3)); + } + return Li; + } + function computeLagrangeLiS2(roots, value, xi0, xi1, curve) { + const Fr = curve.Fr; + const Li = []; + const len = roots[0].length; + const n = len * roots.length; + const num1 = Fr.exp(value, n); + const num2 = Fr.mul(Fr.add(xi0, xi1), Fr.exp(value, len)); + const num3 = Fr.mul(xi0, xi1); + const num = Fr.add(Fr.sub(num1, num2), num3); + let den1 = Fr.mul(Fr.mul(Fr.e(len), roots[0][0]), Fr.sub(xi0, xi1)); + for (let i = 0; i < len; i++) { + const den2 = roots[0][(len - 1) * i % len]; + const den3 = Fr.sub(value, roots[0][i]); + const den = Fr.mul(den1, Fr.mul(den2, den3)); + Li[i] = Fr.div(num, den); + } + den1 = Fr.mul(Fr.mul(Fr.e(len), roots[1][0]), Fr.sub(xi1, xi0)); + for (let i = 0; i < len; i++) { + const den2 = roots[1][(len - 1) * i % len]; + const den3 = Fr.sub(value, roots[1][i]); + const den = Fr.mul(den1, Fr.mul(den2, den3)); + Li[i + len] = Fr.div(num, den); + } + return Li; + } + //#endregion + //#region src/fflonk_export_calldata.js + var { unstringifyBigInts } = ffjavascript.utils; + function p256(n) { + let nstr = n.toString(16); + while (nstr.length < 64) nstr = "0" + nstr; + nstr = `0x${nstr}`; + return nstr; + } + async function fflonkExportCallData(_pub, _proof) { + const proof = unstringifyBigInts(_proof); + const pub = unstringifyBigInts(_pub); + await getCurveFromName(proof.curve); + let inputs = ""; + for (let i = 0; i < pub.length; i++) { + if (inputs !== "") inputs = inputs + ","; + inputs = inputs + p256(pub[i]); + } + return `[${p256(proof.polynomials.C1[0])}, ${p256(proof.polynomials.C1[1])},${p256(proof.polynomials.C2[0])},${p256(proof.polynomials.C2[1])},${p256(proof.polynomials.W1[0])},${p256(proof.polynomials.W1[1])},${p256(proof.polynomials.W2[0])},${p256(proof.polynomials.W2[1])},${p256(proof.evaluations.ql)},${p256(proof.evaluations.qr)},${p256(proof.evaluations.qm)},${p256(proof.evaluations.qo)},${p256(proof.evaluations.qc)},${p256(proof.evaluations.s1)},${p256(proof.evaluations.s2)},${p256(proof.evaluations.s3)},${p256(proof.evaluations.a)},${p256(proof.evaluations.b)},${p256(proof.evaluations.c)},${p256(proof.evaluations.z)},${p256(proof.evaluations.zw)},${p256(proof.evaluations.t1w)},${p256(proof.evaluations.t2w)},${p256(proof.evaluations.inv)}],[${inputs}]`; + } + //#endregion + //#region src/fflonk.js + var fflonk_exports = /* @__PURE__ */ __exportAll({ + exportSolidityCallData: () => fflonkExportCallData, + exportSolidityVerifier: () => null, + fullProve: () => fflonkFullProve, + prove: () => fflonkProve, + setup: () => fflonkSetup, + verify: () => fflonkVerify + }); + //#endregion + Object.defineProperty(exports, "curves", { + enumerable: true, + get: function() { + return curves_exports; + } + }); + Object.defineProperty(exports, "fflonk", { + enumerable: true, + get: function() { + return fflonk_exports; + } + }); + Object.defineProperty(exports, "groth16", { + enumerable: true, + get: function() { + return groth16_exports; + } + }); + Object.defineProperty(exports, "plonk", { + enumerable: true, + get: function() { + return plonk_exports; + } + }); + Object.defineProperty(exports, "powersOfTau", { + enumerable: true, + get: function() { + return powersoftau_exports; + } + }); + Object.defineProperty(exports, "r1cs", { + enumerable: true, + get: function() { + return r1cs_exports; + } + }); + Object.defineProperty(exports, "wtns", { + enumerable: true, + get: function() { + return wtns_exports; + } + }); + Object.defineProperty(exports, "zKey", { + enumerable: true, + get: function() { + return zkey_exports; + } + }); + return exports; +})({}, _iden3_binfileutils, ffjavascript, r1csfile); diff --git a/src/groth16_prove.js b/src/groth16_prove.js index 55b7a1aa..773139ce 100644 --- a/src/groth16_prove.js +++ b/src/groth16_prove.js @@ -667,7 +667,7 @@ async function joinABC(curve, zkey, a, b, c, logger) { } function memUsage(logger) { - if (!logger) return; + if (!logger || typeof process === "undefined" || !process.memoryUsage) return; const used = process.memoryUsage(); logger.debug( " ", diff --git a/src/zkey_new.js b/src/zkey_new.js index 2fa7c9a1..8db17b5c 100644 --- a/src/zkey_new.js +++ b/src/zkey_new.js @@ -627,6 +627,7 @@ export default async function newZKey(r1csName, ptauName, zkeyName, logger) { } function memUsage() { + if (typeof process === "undefined" || !process.memoryUsage) return {}; let m = process.memoryUsage(); for (const i in m) { m[i] = Math.round(m[i] / (1024*1024)); diff --git a/vite.config.js b/vite.config.js index 724a8b06..c4faa711 100644 --- a/vite.config.js +++ b/vite.config.js @@ -15,10 +15,24 @@ const isNodeExternal = (id) => nodeExternal.includes(id) || nodeExternal.some((e) => id.startsWith(e + "/")); // Deps bundled in browser build (everything except these externals) -const browserExternal = ["ffjavascript", "@iden3/binfileutils", "r1csfile", "ejs"]; +const browserExternal = ["ffjavascript", "@iden3/binfileutils", "r1csfile"]; const isBrowserExternal = (id) => browserExternal.includes(id) || browserExternal.some((e) => id.startsWith(e + "/")); +// Node-only source files excluded from browser builds (Solidity exporter requires ejs + fs). +// Rollup's load hook intercepts these by resolved absolute path and returns an empty stub +// so neither the files nor their transitive deps (ejs, r1csfile, etc.) enter the bundle. +const nodeOnlyFiles = new Set([ + resolve("src/zkey_export_solidityverifier.js"), + resolve("src/fflonk_export_solidity_verifier.js"), +]); +const stubNodeOnlyModules = { + name: "stub-node-only-modules", + load(id) { + if (nodeOnlyFiles.has(id)) return "export default null;"; + }, +}; + export default defineConfig(({ mode }) => { if (mode === "cli") { return { @@ -59,6 +73,7 @@ export default defineConfig(({ mode }) => { if (mode === "browser") { return { + plugins: [stubNodeOnlyModules], build: { lib: { entry: "./main.js", @@ -79,6 +94,7 @@ export default defineConfig(({ mode }) => { if (mode === "browser-iife") { return { + plugins: [stubNodeOnlyModules], build: { lib: { entry: "./main.js", @@ -88,7 +104,10 @@ export default defineConfig(({ mode }) => { }, outDir: "build", emptyOutDir: false, - minify: true, + minify: false, + rollupOptions: { + external: isBrowserExternal, + }, }, define: { "process.browser": "true" }, resolve: { conditions: ["browser"] }, From f8a13c72a089e0f89dde3772a6e8575efc4ae817 Mon Sep 17 00:00:00 2001 From: Kolezhniuk Date: Mon, 13 Apr 2026 10:02:53 +0700 Subject: [PATCH 5/8] Add output globals for external libraries in Vite configuration --- build/browser.esm.js | 46 +++--- build/cli.cjs | 16 +-- build/main.cjs | 8 +- build/snarkjs.min.js | 290 +++++++++++++++++++++++++++++++------ package-lock.json | 332 +++++++++++++++++++++---------------------- vite.config.js | 7 + 6 files changed, 461 insertions(+), 238 deletions(-) diff --git a/build/browser.esm.js b/build/browser.esm.js index 0ec1e028..d8561f0e 100644 --- a/build/browser.esm.js +++ b/build/browser.esm.js @@ -46,19 +46,23 @@ async function D(e, t) { //#endregion //#region node_modules/@noble/hashes/utils.js function O(e) { - return e instanceof Uint8Array || ArrayBuffer.isView(e) && e.constructor.name === "Uint8Array"; + return e instanceof Uint8Array || ArrayBuffer.isView(e) && e.constructor.name === "Uint8Array" && "BYTES_PER_ELEMENT" in e && e.BYTES_PER_ELEMENT === 1; } function k(e, t = "") { + if (typeof e != "number") { + let n = t && `"${t}" `; + throw TypeError(`${n}expected number, got ${typeof e}`); + } if (!Number.isSafeInteger(e) || e < 0) { let n = t && `"${t}" `; - throw Error(`${n}expected integer >= 0, got ${e}`); + throw RangeError(`${n}expected integer >= 0, got ${e}`); } } function A(e, t, n = "") { let r = O(e), i = e?.length, a = t !== void 0; if (!r || a && i !== t) { - let o = n && `"${n}" `, s = a ? ` of length ${t}` : "", c = r ? `length=${i}` : `type=${typeof e}`; - throw Error(o + "expected Uint8Array" + s + ", got " + c); + let o = n && `"${n}" `, s = a ? ` of length ${t}` : "", c = r ? `length=${i}` : `type=${typeof e}`, l = o + "expected Uint8Array" + s + ", got " + c; + throw r ? RangeError(l) : TypeError(l); } return e; } @@ -69,7 +73,7 @@ function j(e, t = !0) { function M(e, t) { A(e, void 0, "digestInto() output"); let n = t.outputLen; - if (e.length < n) throw Error("\"digestInto() output\" expected to be of length >=" + n); + if (e.length < n) throw RangeError("\"digestInto() output\" expected to be of length >=" + n); } function N(e) { return new Uint32Array(e.buffer, e.byteOffset, Math.floor(e.byteLength / 4)); @@ -81,7 +85,7 @@ var F = new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68; function I(e) { return e << 24 & 4278190080 | e << 8 & 16711680 | e >>> 8 & 65280 | e >>> 24 & 255; } -var L = F ? (e) => e : (e) => I(e); +var L = F ? (e) => e : (e) => I(e) >>> 0; function ee(e) { for (let t = 0; t < e.length; t++) e[t] = I(e[t]); return e; @@ -90,7 +94,7 @@ var R = F ? (e) => e : ee; typeof Uint8Array.from([]).toHex == "function" && Uint8Array.fromHex; function z(e, t = {}) { let n = (t, n) => e(n).update(t).digest(), r = e(void 0); - return n.outputLen = r.outputLen, n.blockLen = r.blockLen, n.create = (t) => e(t), Object.assign(n, t), Object.freeze(n); + return n.outputLen = r.outputLen, n.blockLen = r.blockLen, n.canXOF = r.canXOF, n.create = (t) => e(t), Object.assign(n, t), Object.freeze(n); } //#endregion //#region node_modules/@noble/hashes/_blake.js @@ -428,7 +432,7 @@ function ge(e, t, n, r, i, a) { }, G[2 * e] = c, G[2 * e + 1] = l, G[2 * t] = u, G[2 * t + 1] = d, G[2 * n] = f, G[2 * n + 1] = p, G[2 * r] = m, G[2 * r + 1] = h; } function _e(e, t = {}, n, r, i) { - if (k(n), e < 0 || e > n) throw Error("outputLen bigger than keyLen"); + if (k(n), e <= 0 || e > n) throw Error("outputLen bigger than keyLen"); let { key: a, salt: o, personalization: s } = t; if (a !== void 0 && (a.length < 1 || a.length > n)) throw Error("\"key\" expected to be undefined or of length=1.." + n); o !== void 0 && A(o, r, "salt"), s !== void 0 && A(s, i, "personalization"); @@ -442,6 +446,7 @@ var ve = class { pos = 0; blockLen; outputLen; + canXOF = !1; constructor(e, t) { k(e), k(t), this.blockLen = e, this.outputLen = t, this.buffer = new Uint8Array(e), this.buffer32 = N(this.buffer); } @@ -465,9 +470,13 @@ var ve = class { digestInto(e) { j(this), M(e, this); let { pos: t, buffer32: n } = this; - this.finished = !0, P(this.buffer.subarray(t)), R(n), this.compress(n, 0, !0), R(n); - let r = N(e); - this.get().forEach((e, t) => r[t] = L(e)); + if (this.finished = !0, P(this.buffer.subarray(t)), R(n), this.compress(n, 0, !0), R(n), e.byteOffset & 3) throw RangeError("\"digestInto() output\" expected 4-byte aligned byteOffset, got " + e.byteOffset); + let r = this.get(), i = N(e), a = Math.floor(this.outputLen / 4); + for (let e = 0; e < a; e++) i[e] = L(r[e]); + let o = this.outputLen % 4; + if (!o) return; + let s = a * 4, c = r[a]; + for (let t = 0; t < o; t++) e[s + t] = c >>> 8 * t; } digest() { let { buffer: e, outputLen: t } = this; @@ -3774,6 +3783,7 @@ for (let e = 0, t = fr, n = 1, r = 0; e < 24; e++) { } var br = U(yr, !0), xr = br[0], Sr = br[1], Cr = (e, t, n) => n > 32 ? ue(e, t, n) : ce(e, t, n), wr = (e, t, n) => n > 32 ? de(e, t, n) : le(e, t, n); function Tr(e, t = 24) { + if (k(t, "rounds"), t < 1 || t > 24) throw Error("\"rounds\" expected integer 1..24"); let n = new Uint32Array(10); for (let r = 24 - t; r < 24; r++) { for (let t = 0; t < 10; t++) n[t] = e[t] ^ e[t + 10] ^ e[t + 20] ^ e[t + 30] ^ e[t + 40]; @@ -3787,8 +3797,8 @@ function Tr(e, t = 24) { t = e[s], i = e[s + 1], e[s] = a, e[s + 1] = o; } for (let t = 0; t < 50; t += 10) { - for (let r = 0; r < 10; r++) n[r] = e[t + r]; - for (let r = 0; r < 10; r++) e[t + r] ^= ~n[(r + 2) % 10] & n[(r + 4) % 10]; + let n = e[t], r = e[t + 1], i = e[t + 2], a = e[t + 3]; + e[t] ^= ~e[t + 2] & e[t + 4], e[t + 1] ^= ~e[t + 3] & e[t + 5], e[t + 2] ^= ~e[t + 4] & e[t + 6], e[t + 3] ^= ~e[t + 5] & e[t + 7], e[t + 4] ^= ~e[t + 6] & e[t + 8], e[t + 5] ^= ~e[t + 7] & e[t + 9], e[t + 6] ^= ~e[t + 8] & n, e[t + 7] ^= ~e[t + 9] & r, e[t + 8] ^= ~n & i, e[t + 9] ^= ~r & a; } e[0] ^= xr[r], e[1] ^= Sr[r]; } @@ -3804,10 +3814,11 @@ var Er = class e { blockLen; suffix; outputLen; + canXOF; enableXOF = !1; rounds; constructor(e, t, n, r = !1, i = 24) { - if (this.blockLen = e, this.suffix = t, this.outputLen = n, this.enableXOF = r, this.rounds = i, k(n, "outputLen"), !(0 < e && e < 200)) throw Error("only keccak-f1600 function is supported"); + if (this.blockLen = e, this.suffix = t, this.outputLen = n, this.enableXOF = r, this.canXOF = r, this.rounds = i, k(n, "outputLen"), !(0 < e && e < 200)) throw Error("only keccak-f1600 function is supported"); this.state = new Uint8Array(200), this.state32 = N(this.state); } clone() { @@ -3851,17 +3862,18 @@ var Er = class e { } digestInto(e) { if (M(e, this), this.finished) throw Error("digest() was already called"); - return this.writeInto(e), this.destroy(), e; + this.writeInto(e.subarray(0, this.outputLen)), this.destroy(); } digest() { - return this.digestInto(new Uint8Array(this.outputLen)); + let e = new Uint8Array(this.outputLen); + return this.digestInto(e), e; } destroy() { this.destroyed = !0, P(this.state); } _cloneInto(t) { let { blockLen: n, suffix: r, outputLen: i, rounds: a, enableXOF: o } = this; - return t ||= new e(n, r, i, o, a), t.state32.set(this.state32), t.pos = this.pos, t.posOut = this.posOut, t.finished = this.finished, t.rounds = a, t.suffix = r, t.outputLen = i, t.enableXOF = o, t.destroyed = this.destroyed, t; + return t ||= new e(n, r, i, o, a), t.blockLen = n, t.state32.set(this.state32), t.pos = this.pos, t.posOut = this.posOut, t.finished = this.finished, t.rounds = a, t.suffix = r, t.outputLen = i, t.enableXOF = o, t.canXOF = this.canXOF, t.destroyed = this.destroyed, t; } }, Dr = /* @__PURE__ */ ((e, t, n, r = {}) => z(() => new Er(t, e, n), r))(1, 136, 32), Or = 0, kr = 1, Ar = class { constructor(e) { diff --git a/build/cli.cjs b/build/cli.cjs index de87bc6b..5f53a9c1 100644 --- a/build/cli.cjs +++ b/build/cli.cjs @@ -23,27 +23,27 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge }) : target, mod)); //#endregion let fs = require("fs"); -fs = __toESM(fs); +fs = __toESM(fs, 1); let url = require("url"); -url = __toESM(url); +url = __toESM(url, 1); let r1csfile = require("r1csfile"); let fastfile = require("fastfile"); -fastfile = __toESM(fastfile); +fastfile = __toESM(fastfile, 1); let ffjavascript = require("ffjavascript"); let _noble_hashes_blake2_js = require("@noble/hashes/blake2.js"); let _noble_hashes_utils_js = require("@noble/hashes/utils.js"); let readline = require("readline"); -readline = __toESM(readline); +readline = __toESM(readline, 1); let crypto = require("crypto"); -crypto = __toESM(crypto); +crypto = __toESM(crypto, 1); let path = require("path"); -path = __toESM(path); +path = __toESM(path, 1); let _iden3_binfileutils = require("@iden3/binfileutils"); -_iden3_binfileutils = __toESM(_iden3_binfileutils); +_iden3_binfileutils = __toESM(_iden3_binfileutils, 1); let circom_runtime = require("circom_runtime"); let _noble_hashes_sha3_js = require("@noble/hashes/sha3.js"); let logplease = require("logplease"); -logplease = __toESM(logplease); +logplease = __toESM(logplease, 1); let v8 = require("v8"); //#region src/loadsyms.js async function loadSymbols(symFileName) { diff --git a/build/main.cjs b/build/main.cjs index 87799ad3..cb8ff0fa 100644 --- a/build/main.cjs +++ b/build/main.cjs @@ -31,16 +31,16 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge }) : target, mod)); //#endregion let _iden3_binfileutils = require("@iden3/binfileutils"); -_iden3_binfileutils = __toESM(_iden3_binfileutils); +_iden3_binfileutils = __toESM(_iden3_binfileutils, 1); let ffjavascript = require("ffjavascript"); let _noble_hashes_blake2_js = require("@noble/hashes/blake2.js"); let _noble_hashes_utils_js = require("@noble/hashes/utils.js"); let readline = require("readline"); -readline = __toESM(readline); +readline = __toESM(readline, 1); let crypto = require("crypto"); -crypto = __toESM(crypto); +crypto = __toESM(crypto, 1); let fastfile = require("fastfile"); -fastfile = __toESM(fastfile); +fastfile = __toESM(fastfile, 1); let circom_runtime = require("circom_runtime"); let r1csfile = require("r1csfile"); let _noble_hashes_sha3_js = require("@noble/hashes/sha3.js"); diff --git a/build/snarkjs.min.js b/build/snarkjs.min.js index 5f741aa7..f580dce3 100644 --- a/build/snarkjs.min.js +++ b/build/snarkjs.min.js @@ -32,7 +32,7 @@ var snarkjs = (function(exports, _iden3_binfileutils, ffjavascript, r1csfile) { enumerable: true }) : target, mod)); //#endregion - _iden3_binfileutils = __toESM(_iden3_binfileutils); + _iden3_binfileutils = __toESM(_iden3_binfileutils, 1); //#region src/curves.js var curves_exports = /* @__PURE__ */ __exportAll({ getCurveFromName: () => getCurveFromName, @@ -78,22 +78,54 @@ var snarkjs = (function(exports, _iden3_binfileutils, ffjavascript, r1csfile) { //#endregion //#region node_modules/@noble/hashes/utils.js /** - * Utilities for hex, bytes, CSPRNG. - * @module + * Checks if something is Uint8Array. Be careful: nodejs Buffer will return true. + * @param a - value to test + * @returns `true` when the value is a Uint8Array-compatible view. + * @example + * Check whether a value is a Uint8Array-compatible view. + * ```ts + * isBytes(new Uint8Array([1, 2, 3])); + * ``` */ - /*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */ - /** Checks if something is Uint8Array. Be careful: nodejs Buffer will return true. */ function isBytes(a) { - return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array"; + return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array" && "BYTES_PER_ELEMENT" in a && a.BYTES_PER_ELEMENT === 1; } - /** Asserts something is positive integer. */ + /** + * Asserts something is a non-negative integer. + * @param n - number to validate + * @param title - label included in thrown errors + * @throws On wrong argument types. {@link TypeError} + * @throws On wrong argument ranges or values. {@link RangeError} + * @example + * Validate a non-negative integer option. + * ```ts + * anumber(32, 'length'); + * ``` + */ function anumber(n, title = "") { + if (typeof n !== "number") { + const prefix = title && `"${title}" `; + throw new TypeError(`${prefix}expected number, got ${typeof n}`); + } if (!Number.isSafeInteger(n) || n < 0) { const prefix = title && `"${title}" `; - throw new Error(`${prefix}expected integer >= 0, got ${n}`); + throw new RangeError(`${prefix}expected integer >= 0, got ${n}`); } } - /** Asserts something is Uint8Array. */ + /** + * Asserts something is Uint8Array. + * @param value - value to validate + * @param length - optional exact length constraint + * @param title - label included in thrown errors + * @returns The validated byte array. + * @throws On wrong argument types. {@link TypeError} + * @throws On wrong argument ranges or values. {@link RangeError} + * @example + * Validate that a value is a byte array. + * ```ts + * abytes(new Uint8Array([1, 2, 3])); + * ``` + */ function abytes(value, length, title = "") { const bytes = isBytes(value); const len = value?.length; @@ -102,50 +134,154 @@ var snarkjs = (function(exports, _iden3_binfileutils, ffjavascript, r1csfile) { const prefix = title && `"${title}" `; const ofLen = needsLen ? ` of length ${length}` : ""; const got = bytes ? `length=${len}` : `type=${typeof value}`; - throw new Error(prefix + "expected Uint8Array" + ofLen + ", got " + got); + const message = prefix + "expected Uint8Array" + ofLen + ", got " + got; + if (!bytes) throw new TypeError(message); + throw new RangeError(message); } return value; } - /** Asserts a hash instance has not been destroyed / finished */ + /** + * Asserts a hash instance has not been destroyed or finished. + * @param instance - hash instance to validate + * @param checkFinished - whether to reject finalized instances + * @throws If the hash instance has already been destroyed or finalized. {@link Error} + * @example + * Validate that a hash instance is still usable. + * ```ts + * import { aexists } from '@noble/hashes/utils.js'; + * import { sha256 } from '@noble/hashes/sha2.js'; + * const hash = sha256.create(); + * aexists(hash); + * ``` + */ function aexists(instance, checkFinished = true) { if (instance.destroyed) throw new Error("Hash instance has been destroyed"); if (checkFinished && instance.finished) throw new Error("Hash#digest() has already been called"); } - /** Asserts output is properly-sized byte array */ + /** + * Asserts output is a sufficiently-sized byte array. + * @param out - destination buffer + * @param instance - hash instance providing output length + * Oversized buffers are allowed; downstream code only promises to fill the first `outputLen` bytes. + * @throws On wrong argument types. {@link TypeError} + * @throws On wrong argument ranges or values. {@link RangeError} + * @example + * Validate a caller-provided digest buffer. + * ```ts + * import { aoutput } from '@noble/hashes/utils.js'; + * import { sha256 } from '@noble/hashes/sha2.js'; + * const hash = sha256.create(); + * aoutput(new Uint8Array(hash.outputLen), hash); + * ``` + */ function aoutput(out, instance) { abytes(out, void 0, "digestInto() output"); const min = instance.outputLen; - if (out.length < min) throw new Error("\"digestInto() output\" expected to be of length >=" + min); + if (out.length < min) throw new RangeError("\"digestInto() output\" expected to be of length >=" + min); } - /** Cast u8 / u16 / u32 to u32. */ + /** + * Casts a typed array view to Uint32Array. + * `arr.byteOffset` must already be 4-byte aligned or the platform + * Uint32Array constructor will throw. + * @param arr - source typed array + * @returns Uint32Array view over the same buffer. + * @example + * Reinterpret a byte array as 32-bit words. + * ```ts + * u32(new Uint8Array(8)); + * ``` + */ function u32(arr) { return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4)); } - /** Zeroize a byte array. Warning: JS provides no guarantees. */ + /** + * Zeroizes typed arrays in place. Warning: JS provides no guarantees. + * @param arrays - arrays to overwrite with zeros + * @example + * Zeroize sensitive buffers in place. + * ```ts + * clean(new Uint8Array([1, 2, 3])); + * ``` + */ function clean(...arrays) { for (let i = 0; i < arrays.length; i++) arrays[i].fill(0); } - /** Is current platform little-endian? Most are. Big-Endian platform: IBM */ + /** Whether the current platform is little-endian. */ var isLE = new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68; - /** The byte swap operation for uint32 */ + /** + * Byte-swap operation for uint32 values. + * @param word - source word + * @returns Word with reversed byte order. + * @example + * Reverse the byte order of a 32-bit word. + * ```ts + * byteSwap(0x11223344); + * ``` + */ function byteSwap(word) { return word << 24 & 4278190080 | word << 8 & 16711680 | word >>> 8 & 65280 | word >>> 24 & 255; } - /** Conditionally byte swap if on a big-endian platform */ - var swap8IfBE = isLE ? (n) => n : (n) => byteSwap(n); - /** In place byte swap for Uint32Array */ + /** + * Conditionally byte-swaps one 32-bit word on big-endian platforms. + * @param n - source word + * @returns Original or byte-swapped word depending on platform endianness. + * @example + * Normalize a 32-bit word for host endianness. + * ```ts + * swap8IfBE(0x11223344); + * ``` + */ + var swap8IfBE = isLE ? (n) => n : (n) => byteSwap(n) >>> 0; + /** + * Byte-swaps every word of a Uint32Array in place. + * @param arr - array to mutate + * @returns The same array after mutation; callers pass live state arrays here. + * @example + * Reverse the byte order of every word in place. + * ```ts + * byteSwap32(new Uint32Array([0x11223344])); + * ``` + */ function byteSwap32(arr) { for (let i = 0; i < arr.length; i++) arr[i] = byteSwap(arr[i]); return arr; } + /** + * Conditionally byte-swaps a Uint32Array on big-endian platforms. + * @param u - array to normalize for host endianness + * @returns Original or byte-swapped array depending on platform endianness. + * On big-endian runtimes this mutates `u` in place via `byteSwap32(...)`. + * @example + * Normalize a word array for host endianness. + * ```ts + * swap32IfBE(new Uint32Array([0x11223344])); + * ``` + */ var swap32IfBE = isLE ? (u) => u : byteSwap32; typeof Uint8Array.from([]).toHex === "function" && Uint8Array.fromHex; - /** Creates function with outputLen, blockLen, create properties from a class constructor. */ + /** + * Creates a callable hash function from a stateful class constructor. + * @param hashCons - hash constructor or factory + * @param info - optional metadata such as DER OID + * @returns Frozen callable hash wrapper with `.create()`. + * Wrapper construction eagerly calls `hashCons(undefined)` once to read + * `outputLen` / `blockLen`, so constructor side effects happen at module + * init time. + * @example + * Wrap a stateful hash constructor into a callable helper. + * ```ts + * import { createHasher } from '@noble/hashes/utils.js'; + * import { sha256 } from '@noble/hashes/sha2.js'; + * const wrapped = createHasher(sha256.create, { oid: sha256.oid }); + * wrapped(new Uint8Array([1])); + * ``` + */ function createHasher(hashCons, info = {}) { const hashC = (msg, opts) => hashCons(opts).update(msg).digest(); const tmp = hashCons(void 0); hashC.outputLen = tmp.outputLen; hashC.blockLen = tmp.blockLen; + hashC.canXOF = tmp.canXOF; hashC.create = (opts) => hashCons(opts); Object.assign(hashC, info); return Object.freeze(hashC); @@ -153,8 +289,10 @@ var snarkjs = (function(exports, _iden3_binfileutils, ffjavascript, r1csfile) { //#endregion //#region node_modules/@noble/hashes/_blake.js /** - * Internal blake variable. - * For BLAKE2b, the two extra permutations for rounds 10 and 11 are SIGMA[10..11] = SIGMA[0..1]. + * Internal blake permutation table. + * Rows `0..9` serve BLAKE2s, rows `0..11` serve BLAKE2b with `10..11 = 0..1`, and Blake1 also + * reuses the later rows shown below. Blake1 expands rounds `10..15` as `SIGMA[i % 10]`, so rows + * `10..15` intentionally repeat rows `0..5` for the 14-round (256) and 16-round (512) variants. */ var BSIGMA = /* @__PURE__ */ Uint8Array.from([ 0, @@ -416,11 +554,6 @@ var snarkjs = (function(exports, _iden3_binfileutils, ffjavascript, r1csfile) { ]); //#endregion //#region node_modules/@noble/hashes/_u64.js - /** - * Internal helpers for u64. BigUint64Array is too slow as per 2025, so we implement it using Uint32Array. - * @todo re-check https://issues.chromium.org/issues/42212588 - * @module - */ var U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1); var _32n = /* @__PURE__ */ BigInt(32); function fromBig(n, le = false) { @@ -552,7 +685,7 @@ var snarkjs = (function(exports, _iden3_binfileutils, ffjavascript, r1csfile) { } function checkBlake2Opts(outputLen, opts = {}, keyLen, saltLen, persLen) { anumber(keyLen); - if (outputLen < 0 || outputLen > keyLen) throw new Error("outputLen bigger than keyLen"); + if (outputLen <= 0 || outputLen > keyLen) throw new Error("outputLen bigger than keyLen"); const { key, salt, personalization } = opts; if (key !== void 0 && (key.length < 1 || key.length > keyLen)) throw new Error("\"key\" expected to be undefined or of length=1.." + keyLen); if (salt !== void 0) abytes(salt, saltLen, "salt"); @@ -568,6 +701,7 @@ var snarkjs = (function(exports, _iden3_binfileutils, ffjavascript, r1csfile) { pos = 0; blockLen; outputLen; + canXOF = false; constructor(blockLen, outputLen) { anumber(blockLen); anumber(outputLen); @@ -618,8 +752,16 @@ var snarkjs = (function(exports, _iden3_binfileutils, ffjavascript, r1csfile) { swap32IfBE(buffer32); this.compress(buffer32, 0, true); swap32IfBE(buffer32); + if (out.byteOffset & 3) throw new RangeError("\"digestInto() output\" expected 4-byte aligned byteOffset, got " + out.byteOffset); + const state = this.get(); const out32 = u32(out); - this.get().forEach((v, i) => out32[i] = swap8IfBE(v)); + const full = Math.floor(this.outputLen / 4); + for (let i = 0; i < full; i++) out32[i] = swap8IfBE(state[i]); + const tail = this.outputLen % 4; + if (!tail) return; + const off = full * 4; + const word = state[full]; + for (let i = 0; i < tail; i++) out[off + i] = word >>> 8 * i; } digest() { const { buffer, outputLen } = this; @@ -644,7 +786,7 @@ var snarkjs = (function(exports, _iden3_binfileutils, ffjavascript, r1csfile) { return this._cloneInto(); } }; - /** Internal blake2b hash class. */ + /** Internal blake2b hash class with state stored as LE u32 low/high halves. */ var _BLAKE2b = class extends _BLAKE2 { v0l = B2B_IV[0] | 0; v0h = B2B_IV[1] | 0; @@ -791,7 +933,15 @@ var snarkjs = (function(exports, _iden3_binfileutils, ffjavascript, r1csfile) { /** * Blake2b hash function. 64-bit. 1.5x slower than blake2s in JS. * @param msg - message that would be hashed - * @param opts - dkLen output length, key for MAC mode, salt, personalization + * @param opts - Optional output, MAC, salt, and personalization settings. + * `dkLen` must be 1..64 bytes; `salt` and `personalization`, if present, + * must be 16 bytes each. See {@link Blake2Opts}. + * @returns Digest bytes. + * @example + * Hash a message with Blake2b. + * ```ts + * blake2b(new Uint8Array([97, 98, 99])); + * ``` */ var blake2b = /* @__PURE__ */ createHasher((opts) => new _BLAKE2b(opts)); (/* @__PURE__ */ __commonJSMin(((exports, module) => { @@ -6203,9 +6353,11 @@ var snarkjs = (function(exports, _iden3_binfileutils, ffjavascript, r1csfile) { * SHA3 (keccak) hash function, based on a new "Sponge function" design. * Different from older hashes, the internal state is bigger than output size. * - * Check out [FIPS-202](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf), - * [Website](https://keccak.team/keccak.html), - * [the differences between SHA-3 and Keccak](https://crypto.stackexchange.com/questions/15727/what-are-the-key-differences-between-the-draft-sha-3-standard-and-the-keccak-sub). + * Check out + * {@link https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf | FIPS-202}, + * {@link https://keccak.team/keccak.html | Website}, and + * {@link https://crypto.stackexchange.com/q/15727 | the differences between + * SHA-3 and Keccak}. * * Check out `sha3-addons` module for cSHAKE, k12, and others. * @module @@ -6235,8 +6387,21 @@ var snarkjs = (function(exports, _iden3_binfileutils, ffjavascript, r1csfile) { var SHA3_IOTA_L = IOTAS[1]; var rotlH = (h, l, s) => s > 32 ? rotlBH(h, l, s) : rotlSH(h, l, s); var rotlL = (h, l, s) => s > 32 ? rotlBL(h, l, s) : rotlSL(h, l, s); - /** `keccakf1600` internal function, additionally allows to adjust round count. */ + /** + * `keccakf1600` internal permutation, additionally allows adjusting the round count. + * @param s - 5x5 Keccak state encoded as 25 lanes split into 50 uint32 words + * in this file's local little-endian lane-word order + * @param rounds - number of rounds to execute + * @throws If `rounds` is outside the supported `1..24` range. {@link Error} + * @example + * Permute a Keccak state with the default 24 rounds. + * ```ts + * keccakP(new Uint32Array(50)); + * ``` + */ function keccakP(s, rounds = 24) { + anumber(rounds, "rounds"); + if (rounds < 1 || rounds > 24) throw new Error("\"rounds\" expected integer 1..24"); const B = new Uint32Array(10); for (let round = 24 - rounds; round < 24; round++) { for (let x = 0; x < 10; x++) B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40]; @@ -6265,15 +6430,40 @@ var snarkjs = (function(exports, _iden3_binfileutils, ffjavascript, r1csfile) { s[PI + 1] = Tl; } for (let y = 0; y < 50; y += 10) { - for (let x = 0; x < 10; x++) B[x] = s[y + x]; - for (let x = 0; x < 10; x++) s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10]; + const b0 = s[y], b1 = s[y + 1], b2 = s[y + 2], b3 = s[y + 3]; + s[y] ^= ~s[y + 2] & s[y + 4]; + s[y + 1] ^= ~s[y + 3] & s[y + 5]; + s[y + 2] ^= ~s[y + 4] & s[y + 6]; + s[y + 3] ^= ~s[y + 5] & s[y + 7]; + s[y + 4] ^= ~s[y + 6] & s[y + 8]; + s[y + 5] ^= ~s[y + 7] & s[y + 9]; + s[y + 6] ^= ~s[y + 8] & b0; + s[y + 7] ^= ~s[y + 9] & b1; + s[y + 8] ^= ~b0 & b2; + s[y + 9] ^= ~b1 & b3; } s[0] ^= SHA3_IOTA_H[round]; s[1] ^= SHA3_IOTA_L[round]; } clean(B); } - /** Keccak sponge function. */ + /** + * Keccak sponge function. + * @param blockLen - absorb/squeeze rate in bytes + * @param suffix - domain separation suffix byte + * @param outputLen - default digest length in bytes. This base sponge only + * requires a non-negative integer; wrappers that need positive output + * lengths must enforce that themselves. + * @param enableXOF - whether XOF output is allowed + * @param rounds - number of Keccak-f rounds + * @example + * Build a sponge state, absorb bytes, then finalize a digest. + * ```ts + * const hash = new Keccak(136, 0x06, 32); + * hash.update(new Uint8Array([1, 2, 3])); + * hash.digest(); + * ``` + */ var Keccak = class Keccak { state; pos = 0; @@ -6284,6 +6474,7 @@ var snarkjs = (function(exports, _iden3_binfileutils, ffjavascript, r1csfile) { blockLen; suffix; outputLen; + canXOF; enableXOF = false; rounds; constructor(blockLen, suffix, outputLen, enableXOF = false, rounds = 24) { @@ -6291,6 +6482,7 @@ var snarkjs = (function(exports, _iden3_binfileutils, ffjavascript, r1csfile) { this.suffix = suffix; this.outputLen = outputLen; this.enableXOF = enableXOF; + this.canXOF = enableXOF; this.rounds = rounds; anumber(outputLen, "outputLen"); if (!(0 < blockLen && blockLen < 200)) throw new Error("only keccak-f1600 function is supported"); @@ -6354,12 +6546,13 @@ var snarkjs = (function(exports, _iden3_binfileutils, ffjavascript, r1csfile) { digestInto(out) { aoutput(out, this); if (this.finished) throw new Error("digest() was already called"); - this.writeInto(out); + this.writeInto(out.subarray(0, this.outputLen)); this.destroy(); - return out; } digest() { - return this.digestInto(new Uint8Array(this.outputLen)); + const out = new Uint8Array(this.outputLen); + this.digestInto(out); + return out; } destroy() { this.destroyed = true; @@ -6368,6 +6561,7 @@ var snarkjs = (function(exports, _iden3_binfileutils, ffjavascript, r1csfile) { _cloneInto(to) { const { blockLen, suffix, outputLen, rounds, enableXOF } = this; to ||= new Keccak(blockLen, suffix, outputLen, enableXOF, rounds); + to.blockLen = blockLen; to.state32.set(this.state32); to.pos = this.pos; to.posOut = this.posOut; @@ -6376,12 +6570,22 @@ var snarkjs = (function(exports, _iden3_binfileutils, ffjavascript, r1csfile) { to.suffix = suffix; to.outputLen = outputLen; to.enableXOF = enableXOF; + to.canXOF = this.canXOF; to.destroyed = this.destroyed; return to; } }; var genKeccak = (suffix, blockLen, outputLen, info = {}) => createHasher(() => new Keccak(blockLen, suffix, outputLen), info); - /** keccak-256 hash function. Different from SHA3-256. */ + /** + * Keccak-256 hash function. Different from SHA3-256. + * @param msg - message bytes to hash + * @returns Digest bytes. + * @example + * Hash a message with Keccak-256. + * ```ts + * keccak_256(new Uint8Array([97, 98, 99])); + * ``` + */ var keccak_256 = /* @__PURE__ */ genKeccak(1, 136, 32); //#endregion //#region src/Keccak256Transcript.js diff --git a/package-lock.json b/package-lock.json index d905cc8f..50188892 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52,22 +52,22 @@ "license": "MIT" }, "node_modules/@emnapi/core": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.1.tgz", - "integrity": "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", + "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", "dev": true, "license": "MIT", "optional": true, "peer": true, "dependencies": { - "@emnapi/wasi-threads": "1.2.0", + "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "node_modules/@emnapi/runtime": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.1.tgz", - "integrity": "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", + "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", "dev": true, "license": "MIT", "optional": true, @@ -77,9 +77,9 @@ } }, "node_modules/@emnapi/wasi-threads": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.0.tgz", - "integrity": "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", "dev": true, "license": "MIT", "optional": true, @@ -717,7 +717,7 @@ }, "node_modules/@iden3/binfileutils": { "version": "0.0.12", - "resolved": "git+ssh://git@github.com/iden3/binfileutils.git#eca16c4827ef30d24b0e2167d03b626de446c4d6", + "resolved": "git+ssh://git@github.com/iden3/binfileutils.git#c0de22052590168d7c28fee62dc4042bac4c96bf", "license": "GPL-3.0", "dependencies": { "fastfile": "https://github.com/iden3/fastfile.git#feat/esm-migration", @@ -777,9 +777,9 @@ } }, "node_modules/@noble/hashes": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz", - "integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.2.0.tgz", + "integrity": "sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg==", "license": "MIT", "engines": { "node": ">= 20.19.0" @@ -1039,9 +1039,9 @@ } }, "node_modules/@oxc-project/types": { - "version": "0.123.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.123.0.tgz", - "integrity": "sha512-YtECP/y8Mj1lSHiUWGSRzy/C6teUKlS87dEfuVKT09LgQbUsBW1rNg+MiJ4buGu3yuADV60gbIvo9/HplA56Ew==", + "version": "0.124.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.124.0.tgz", + "integrity": "sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==", "dev": true, "license": "MIT", "funding": { @@ -1056,9 +1056,9 @@ "license": "MIT" }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.0-rc.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.13.tgz", - "integrity": "sha512-5ZiiecKH2DXAVJTNN13gNMUcCDg4Jy8ZjbXEsPnqa248wgOVeYRX0iqXXD5Jz4bI9BFHgKsI2qmyJynstbmr+g==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.15.tgz", + "integrity": "sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA==", "cpu": [ "arm64" ], @@ -1073,9 +1073,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.0-rc.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.13.tgz", - "integrity": "sha512-tz/v/8G77seu8zAB3A5sK3UFoOl06zcshEzhUO62sAEtrEuW/H1CcyoupOrD+NbQJytYgA4CppXPzlrmp4JZKA==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.15.tgz", + "integrity": "sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg==", "cpu": [ "arm64" ], @@ -1090,9 +1090,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.0-rc.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.13.tgz", - "integrity": "sha512-8DakphqOz8JrMYWTJmWA+vDJxut6LijZ8Xcdc4flOlAhU7PNVwo2MaWBF9iXjJAPo5rC/IxEFZDhJ3GC7NHvug==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.15.tgz", + "integrity": "sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw==", "cpu": [ "x64" ], @@ -1107,9 +1107,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.0-rc.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.13.tgz", - "integrity": "sha512-4wBQFfjDuXYN/SVI8inBF3Aa+isq40rc6VMFbk5jcpolUBTe5cYnMsHZ51nFWsx3PVyyNN3vgoESki0Hmr/4BA==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.15.tgz", + "integrity": "sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw==", "cpu": [ "x64" ], @@ -1124,9 +1124,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.0-rc.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.13.tgz", - "integrity": "sha512-JW/e4yPIXLms+jmnbwwy5LA/LxVwZUWLN8xug+V200wzaVi5TEGIWQlh8o91gWYFxW609euI98OCCemmWGuPrw==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.15.tgz", + "integrity": "sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA==", "cpu": [ "arm" ], @@ -1141,9 +1141,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.0-rc.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.13.tgz", - "integrity": "sha512-ZfKWpXiUymDnavepCaM6KG/uGydJ4l2nBmMxg60Ci4CbeefpqjPWpfaZM7PThOhk2dssqBAcwLc6rAyr0uTdXg==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.15.tgz", + "integrity": "sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w==", "cpu": [ "arm64" ], @@ -1158,9 +1158,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.0-rc.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.13.tgz", - "integrity": "sha512-bmRg3O6Z0gq9yodKKWCIpnlH051sEfdVwt+6m5UDffAQMUUqU0xjnQqqAUm+Gu7ofAAly9DqiQDtKu2nPDEABA==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.15.tgz", + "integrity": "sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ==", "cpu": [ "arm64" ], @@ -1175,9 +1175,9 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.0.0-rc.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.13.tgz", - "integrity": "sha512-8Wtnbw4k7pMYN9B/mOEAsQ8HOiq7AZ31Ig4M9BKn2So4xRaFEhtCSa4ZJaOutOWq50zpgR4N5+L/opnlaCx8wQ==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.15.tgz", + "integrity": "sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ==", "cpu": [ "ppc64" ], @@ -1192,9 +1192,9 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.0.0-rc.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.13.tgz", - "integrity": "sha512-D/0Nlo8mQuxSMohNJUF2lDXWRsFDsHldfRRgD9bRgktj+EndGPj4DOV37LqDKPYS+osdyhZEH7fTakTAEcW7qg==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.15.tgz", + "integrity": "sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ==", "cpu": [ "s390x" ], @@ -1209,9 +1209,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.0-rc.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.13.tgz", - "integrity": "sha512-eRrPvat2YaVQcwwKi/JzOP6MKf1WRnOCr+VaI3cTWz3ZoLcP/654z90lVCJ4dAuMEpPdke0n+qyAqXDZdIC4rA==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.15.tgz", + "integrity": "sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA==", "cpu": [ "x64" ], @@ -1226,9 +1226,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.0-rc.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.13.tgz", - "integrity": "sha512-PsdONiFRp8hR8KgVjTWjZ9s7uA3uueWL0t74/cKHfM4dR5zXYv4AjB8BvA+QDToqxAFg4ZkcVEqeu5F7inoz5w==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.15.tgz", + "integrity": "sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw==", "cpu": [ "x64" ], @@ -1243,9 +1243,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.0-rc.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.13.tgz", - "integrity": "sha512-hCNXgC5dI3TVOLrPT++PKFNZ+1EtS0mLQwfXXXSUD/+rGlB65gZDwN/IDuxLpQP4x8RYYHqGomlUXzpO8aVI2w==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.15.tgz", + "integrity": "sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg==", "cpu": [ "arm64" ], @@ -1260,9 +1260,9 @@ } }, "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.0-rc.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.13.tgz", - "integrity": "sha512-viLS5C5et8NFtLWw9Sw3M/w4vvnVkbWkO7wSNh3C+7G1+uCkGpr6PcjNDSFcNtmXY/4trjPBqUfcOL+P3sWy/g==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.15.tgz", + "integrity": "sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q==", "cpu": [ "wasm32" ], @@ -1270,18 +1270,18 @@ "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "1.9.1", - "@emnapi/runtime": "1.9.1", - "@napi-rs/wasm-runtime": "^1.1.2" + "@emnapi/core": "1.9.2", + "@emnapi/runtime": "1.9.2", + "@napi-rs/wasm-runtime": "^1.1.3" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.0-rc.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.13.tgz", - "integrity": "sha512-Fqa3Tlt1xL4wzmAYxGNFV36Hb+VfPc9PYU+E25DAnswXv3ODDu/yyWjQDbXMo5AGWkQVjLgQExuVu8I/UaZhPQ==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.15.tgz", + "integrity": "sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA==", "cpu": [ "arm64" ], @@ -1296,9 +1296,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.0-rc.13", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.13.tgz", - "integrity": "sha512-/pLI5kPkGEi44TDlnbio3St/5gUFeN51YWNAk/Gnv6mEQBOahRBh52qVFVBpmrnU01n2yysvBML9Ynu7K4kGAQ==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.15.tgz", + "integrity": "sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g==", "cpu": [ "x64" ], @@ -1313,9 +1313,9 @@ } }, "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-rc.13", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.13.tgz", - "integrity": "sha512-3ngTAv6F/Py35BsYbeeLeecvhMKdsKm4AoOETVhAA+Qc8nrA2I0kF7oa93mE9qnIurngOSpMnQ0x2nQY2FPviA==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.15.tgz", + "integrity": "sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g==", "dev": true, "license": "MIT" }, @@ -1469,27 +1469,27 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "25.5.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.2.tgz", - "integrity": "sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg==", + "version": "25.6.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.0.tgz", + "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==", "dev": true, "license": "MIT", "optional": true, "peer": true, "dependencies": { - "undici-types": "~7.18.0" + "undici-types": "~7.19.0" } }, "node_modules/@vitest/browser": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-4.1.3.tgz", - "integrity": "sha512-CS9KjO2vijuBlbwz0JIgC0YuoI1BuqWI5ziD3Nll6jkpNYtWdjPMVgGynQ9vZovjsECeUqEeNjWrypP414d0CQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-4.1.4.tgz", + "integrity": "sha512-TrNaY/yVOwxtrxNsDUC/wQ56xSwplpytTeRAqF/197xV/ZddxxulBsxR6TrhVMyniJmp9in8d5u0AcDaNRY30w==", "dev": true, "license": "MIT", "dependencies": { "@blazediff/core": "1.9.1", - "@vitest/mocker": "4.1.3", - "@vitest/utils": "4.1.3", + "@vitest/mocker": "4.1.4", + "@vitest/utils": "4.1.4", "magic-string": "^0.30.21", "pngjs": "^7.0.0", "sirv": "^3.0.2", @@ -1500,19 +1500,19 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "4.1.3" + "vitest": "4.1.4" } }, "node_modules/@vitest/browser-playwright": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@vitest/browser-playwright/-/browser-playwright-4.1.3.tgz", - "integrity": "sha512-D3Q+YozvSpiFaLPgd6/OMbyqEIZeucSe6AHJJ7VnNJKQhIyBE60TlBZlxzwM8bvjzQE9ZnYWQCPeCw5pnhbiNg==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@vitest/browser-playwright/-/browser-playwright-4.1.4.tgz", + "integrity": "sha512-q3PchVhZINX23Pv+RERgAtDlp6wzVkID/smOPnZ5YGWpeWUe3jMNYppeVh15j4il3G7JIJty1d1Kicpm0HSMig==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@vitest/browser": "4.1.3", - "@vitest/mocker": "4.1.3", + "@vitest/browser": "4.1.4", + "@vitest/mocker": "4.1.4", "tinyrainbow": "^3.1.0" }, "funding": { @@ -1520,7 +1520,7 @@ }, "peerDependencies": { "playwright": "*", - "vitest": "4.1.3" + "vitest": "4.1.4" }, "peerDependenciesMeta": { "playwright": { @@ -1529,16 +1529,16 @@ } }, "node_modules/@vitest/expect": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.3.tgz", - "integrity": "sha512-CW8Q9KMtXDGHj0vCsqui0M5KqRsu0zm0GNDW7Gd3U7nZ2RFpPKSCpeCXoT+/+5zr1TNlsoQRDEz+LzZUyq6gnQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.4.tgz", + "integrity": "sha512-iPBpra+VDuXmBFI3FMKHSFXp3Gx5HfmSCE8X67Dn+bwephCnQCaB7qWK2ldHa+8ncN8hJU8VTMcxjPpyMkUjww==", "dev": true, "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", - "@vitest/spy": "4.1.3", - "@vitest/utils": "4.1.3", + "@vitest/spy": "4.1.4", + "@vitest/utils": "4.1.4", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" }, @@ -1547,13 +1547,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.3.tgz", - "integrity": "sha512-XN3TrycitDQSzGRnec/YWgoofkYRhouyVQj4YNsJ5r/STCUFqMrP4+oxEv3e7ZbLi4og5kIHrZwekDJgw6hcjw==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.4.tgz", + "integrity": "sha512-R9HTZBhW6yCSGbGQnDnH3QHfJxokKN4KB+Yvk9Q1le7eQNYwiCyKxmLmurSpFy6BzJanSLuEUDrD+j97Q+ZLPg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.1.3", + "@vitest/spy": "4.1.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, @@ -1574,9 +1574,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.3.tgz", - "integrity": "sha512-hYqqwuMbpkkBodpRh4k4cQSOELxXky1NfMmQvOfKvV8zQHz8x8Dla+2wzElkMkBvSAJX5TRGHJAQvK0TcOafwg==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.4.tgz", + "integrity": "sha512-ddmDHU0gjEUyEVLxtZa7xamrpIefdEETu3nZjWtHeZX4QxqJ7tRxSteHVXJOcr8jhiLoGAhkK4WJ3WqBpjx42A==", "dev": true, "license": "MIT", "dependencies": { @@ -1587,13 +1587,13 @@ } }, "node_modules/@vitest/runner": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.3.tgz", - "integrity": "sha512-VwgOz5MmT0KhlUj40h02LWDpUBVpflZ/b7xZFA25F29AJzIrE+SMuwzFf0b7t4EXdwRNX61C3B6auIXQTR3ttA==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.4.tgz", + "integrity": "sha512-xTp7VZ5aXP5ZJrn15UtJUWlx6qXLnGtF6jNxHepdPHpMfz/aVPx+htHtgcAL2mDXJgKhpoo2e9/hVJsIeFbytQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.1.3", + "@vitest/utils": "4.1.4", "pathe": "^2.0.3" }, "funding": { @@ -1601,14 +1601,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.3.tgz", - "integrity": "sha512-9l+k/J9KG5wPJDX9BcFFzhhwNjwkRb8RsnYhaT1vPY7OufxmQFc9sZzScRCPTiETzl37mrIWVY9zxzmdVeJwDQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.4.tgz", + "integrity": "sha512-MCjCFgaS8aZz+m5nTcEcgk/xhWv0rEH4Yl53PPlMXOZ1/Ka2VcZU6CJ+MgYCZbcJvzGhQRjVrGQNZqkGPttIKw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.1.3", - "@vitest/utils": "4.1.3", + "@vitest/pretty-format": "4.1.4", + "@vitest/utils": "4.1.4", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, @@ -1617,9 +1617,9 @@ } }, "node_modules/@vitest/spy": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.3.tgz", - "integrity": "sha512-ujj5Uwxagg4XUIfAUyRQxAg631BP6e9joRiN99mr48Bg9fRs+5mdUElhOoZ6rP5mBr8Bs3lmrREnkrQWkrsTCw==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.4.tgz", + "integrity": "sha512-XxNdAsKW7C+FLydqFJLb5KhJtl3PGCMmYwFRfhvIgxJvLSXhhVI1zM8f1qD3Zg7RCjTSzDVyct6sghs9UEgBEQ==", "dev": true, "license": "MIT", "funding": { @@ -1627,13 +1627,13 @@ } }, "node_modules/@vitest/utils": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.3.tgz", - "integrity": "sha512-Pc/Oexse/khOWsGB+w3q4yzA4te7W4gpZZAvk+fr8qXfTURZUMj5i7kuxsNK5mP/dEB6ao3jfr0rs17fHhbHdw==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.4.tgz", + "integrity": "sha512-13QMT+eysM5uVGa1rG4kegGYNp6cnQcsTc67ELFbhNLQO+vgsygtYJx2khvdt4gVQqSSpC/KT5FZZxUpP3Oatw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.1.3", + "@vitest/pretty-format": "4.1.4", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" }, @@ -1894,9 +1894,9 @@ } }, "node_modules/ejs": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-5.0.1.tgz", - "integrity": "sha512-COqBPFMxuPTPspXl2DkVYaDS3HtrD1GpzOGkNTJ1IYkifq/r9h8SVEFrjA3D9/VJGOEoMQcrlhpntcSUrM8k6A==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-5.0.2.tgz", + "integrity": "sha512-IpbUaI/CAW86l3f+T8zN0iggSc0LmMZLcIW5eRVStLVNCoTXkE0YlncbbH50fp8Cl6zHIky0sW2uUbhBqGw0Jw==", "license": "Apache-2.0", "bin": { "ejs": "bin/cli.js" @@ -2340,7 +2340,7 @@ }, "node_modules/ffjavascript": { "version": "0.3.1-poc", - "resolved": "git+ssh://git@github.com/iden3/ffjavascript.git#1ff750d476e1508d6511ea0429e9aed9a7dbe1c0", + "resolved": "git+ssh://git@github.com/iden3/ffjavascript.git#cc5321961623a9bf1c05aab6a3236e8b06233a46", "license": "GPL-3.0", "dependencies": { "wasmbuilder": "0.0.16", @@ -2459,9 +2459,9 @@ } }, "node_modules/globals": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-17.4.0.tgz", - "integrity": "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw==", + "version": "17.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.5.0.tgz", + "integrity": "sha512-qoV+HK2yFl/366t2/Cb3+xxPUo5BuMynomoDmiaZBIdbs+0pYbjfZU+twLhGKp4uCZ/+NbtpVepH5bGCxRyy2g==", "dev": true, "license": "MIT", "engines": { @@ -2903,9 +2903,9 @@ "license": "MIT" }, "node_modules/lru-cache": { - "version": "11.3.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.2.tgz", - "integrity": "sha512-wgWa6FWQ3QRRJbIjbsldRJZxdxYngT/dO0I5Ynmlnin8qy7tC6xYzbcJjtN4wHLXtkbVwHzk0C+OejVw1XM+DQ==", + "version": "11.3.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.3.tgz", + "integrity": "sha512-JvNw9Y81y33E+BEYPr0U7omo+U9AySnsMsEiXgwT6yqd31VQWTLNQqmT4ou5eqPFUrTfIDFta2wKhB1hyohtAQ==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -3295,7 +3295,7 @@ }, "node_modules/r1csfile": { "version": "0.0.48", - "resolved": "git+ssh://git@github.com/iden3/r1csfile.git#20d8befec24bdce24549014ff5c1f8f487d426c8", + "resolved": "git+ssh://git@github.com/iden3/r1csfile.git#9af98fb578157010a02fb302bde8628bebcef87e", "license": "GPL-3.0", "dependencies": { "@iden3/bigarray": "0.0.2", @@ -3366,14 +3366,14 @@ } }, "node_modules/rolldown": { - "version": "1.0.0-rc.13", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.13.tgz", - "integrity": "sha512-bvVj8YJmf0rq4pSFmH7laLa6pYrhghv3PRzrCdRAr23g66zOKVJ4wkvFtgohtPLWmthgg8/rkaqRHrpUEh0Zbw==", + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.15.tgz", + "integrity": "sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.123.0", - "@rolldown/pluginutils": "1.0.0-rc.13" + "@oxc-project/types": "=0.124.0", + "@rolldown/pluginutils": "1.0.0-rc.15" }, "bin": { "rolldown": "bin/cli.mjs" @@ -3382,21 +3382,21 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.0-rc.13", - "@rolldown/binding-darwin-arm64": "1.0.0-rc.13", - "@rolldown/binding-darwin-x64": "1.0.0-rc.13", - "@rolldown/binding-freebsd-x64": "1.0.0-rc.13", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.13", - "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.13", - "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.13", - "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.13", - "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.13", - "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.13", - "@rolldown/binding-linux-x64-musl": "1.0.0-rc.13", - "@rolldown/binding-openharmony-arm64": "1.0.0-rc.13", - "@rolldown/binding-wasm32-wasi": "1.0.0-rc.13", - "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.13", - "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.13" + "@rolldown/binding-android-arm64": "1.0.0-rc.15", + "@rolldown/binding-darwin-arm64": "1.0.0-rc.15", + "@rolldown/binding-darwin-x64": "1.0.0-rc.15", + "@rolldown/binding-freebsd-x64": "1.0.0-rc.15", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.15", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.15", + "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.15", + "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.15", + "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.15", + "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.15", + "@rolldown/binding-linux-x64-musl": "1.0.0-rc.15", + "@rolldown/binding-openharmony-arm64": "1.0.0-rc.15", + "@rolldown/binding-wasm32-wasi": "1.0.0-rc.15", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.15", + "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.15" } }, "node_modules/semver": { @@ -3621,9 +3621,9 @@ } }, "node_modules/undici-types": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", - "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "version": "7.19.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz", + "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==", "dev": true, "license": "MIT", "optional": true @@ -3639,16 +3639,16 @@ } }, "node_modules/vite": { - "version": "8.0.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.7.tgz", - "integrity": "sha512-P1PbweD+2/udplnThz3btF4cf6AgPky7kk23RtHUkJIU5BIxwPprhRGmOAHs6FTI7UiGbTNrgNP6jSYD6JaRnw==", + "version": "8.0.8", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.8.tgz", + "integrity": "sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw==", "dev": true, "license": "MIT", "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.8", - "rolldown": "1.0.0-rc.13", + "rolldown": "1.0.0-rc.15", "tinyglobby": "^0.2.15" }, "bin": { @@ -3732,20 +3732,20 @@ } }, "node_modules/vitest": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.3.tgz", - "integrity": "sha512-DBc4Tx0MPNsqb9isoyOq00lHftVx/KIU44QOm2q59npZyLUkENn8TMFsuzuO+4U2FUa9rgbbPt3udrP25GcjXw==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.4.tgz", + "integrity": "sha512-tFuJqTxKb8AvfyqMfnavXdzfy3h3sWZRWwfluGbkeR7n0HUev+FmNgZ8SDrRBTVrVCjgH5cA21qGbCffMNtWvg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@vitest/expect": "4.1.3", - "@vitest/mocker": "4.1.3", - "@vitest/pretty-format": "4.1.3", - "@vitest/runner": "4.1.3", - "@vitest/snapshot": "4.1.3", - "@vitest/spy": "4.1.3", - "@vitest/utils": "4.1.3", + "@vitest/expect": "4.1.4", + "@vitest/mocker": "4.1.4", + "@vitest/pretty-format": "4.1.4", + "@vitest/runner": "4.1.4", + "@vitest/snapshot": "4.1.4", + "@vitest/spy": "4.1.4", + "@vitest/utils": "4.1.4", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", @@ -3773,12 +3773,12 @@ "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.1.3", - "@vitest/browser-preview": "4.1.3", - "@vitest/browser-webdriverio": "4.1.3", - "@vitest/coverage-istanbul": "4.1.3", - "@vitest/coverage-v8": "4.1.3", - "@vitest/ui": "4.1.3", + "@vitest/browser-playwright": "4.1.4", + "@vitest/browser-preview": "4.1.4", + "@vitest/browser-webdriverio": "4.1.4", + "@vitest/coverage-istanbul": "4.1.4", + "@vitest/coverage-v8": "4.1.4", + "@vitest/ui": "4.1.4", "happy-dom": "*", "jsdom": "*", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" diff --git a/vite.config.js b/vite.config.js index c4faa711..171956f0 100644 --- a/vite.config.js +++ b/vite.config.js @@ -107,6 +107,13 @@ export default defineConfig(({ mode }) => { minify: false, rollupOptions: { external: isBrowserExternal, + output: { + globals: { + "ffjavascript": "ffjavascript", + "@iden3/binfileutils": "_iden3_binfileutils", + "r1csfile": "r1csfile", + }, + }, }, }, define: { "process.browser": "true" }, From 381b9ddae08e25ce4899bb61132d81df0ccc4142 Mon Sep 17 00:00:00 2001 From: d5k9 Date: Fri, 5 Jun 2026 11:57:16 +0700 Subject: [PATCH 6/8] feat: add benchmarking scripts and improve contract factory paths - Added new benchmarking scripts in package.json for various operations including prove, verify, and compare. - Updated smart contract test file to reference the correct paths for Groth16, Plonk, and Fflonk verifiers. - Enabled minification in vite.config.js for production builds. --- build/browser.esm.js | 3 +- build/cli.cjs | 2 +- build/snarkjs.min.js | 9857 +--------------------------------- package-lock.json | 873 ++- test/smart_contracts.test.js | 8 +- vite.config.js | 2 +- 6 files changed, 440 insertions(+), 10305 deletions(-) diff --git a/build/browser.esm.js b/build/browser.esm.js index d8561f0e..855aade6 100644 --- a/build/browser.esm.js +++ b/build/browser.esm.js @@ -3,7 +3,7 @@ import { createBinFile as t, endWriteSection as n, readBinFile as r, readSection import { BigBuffer as s, ChaCha as c, F1Field as l, Scalar as u, buildBls12381 as d, buildBn128 as f, utils as p } from "ffjavascript"; import { readR1cs as m, readR1csFd as h, readR1csHeader as g } from "r1csfile"; //#region \0rolldown/runtime.js -var _ = Object.defineProperty, v = (e, t) => () => (t || e((t = { exports: {} }).exports, t), t.exports), y = (e, t) => { +var _ = Object.defineProperty, v = (e, t) => () => (t || (e((t = { exports: {} }).exports, t), e = null), t.exports), y = (e, t) => { let n = {}; for (var r in e) _(n, r, { get: e[r], @@ -91,7 +91,6 @@ function ee(e) { return e; } var R = F ? (e) => e : ee; -typeof Uint8Array.from([]).toHex == "function" && Uint8Array.fromHex; function z(e, t = {}) { let n = (t, n) => e(n).update(t).digest(), r = e(void 0); return n.outputLen = r.outputLen, n.blockLen = r.blockLen, n.canXOF = r.canXOF, n.create = (t) => e(t), Object.assign(n, t), Object.freeze(n); diff --git a/build/cli.cjs b/build/cli.cjs index 5f53a9c1..ca2c0468 100644 --- a/build/cli.cjs +++ b/build/cli.cjs @@ -6,7 +6,7 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; -var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports); +var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports); var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { key = keys[i]; diff --git a/build/snarkjs.min.js b/build/snarkjs.min.js index f580dce3..f2e6a35d 100644 --- a/build/snarkjs.min.js +++ b/build/snarkjs.min.js @@ -1,9850 +1,7 @@ -var snarkjs = (function(exports, _iden3_binfileutils, ffjavascript, r1csfile) { - Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); - //#region \0rolldown/runtime.js - var __create = Object.create; - var __defProp = Object.defineProperty; - var __getOwnPropDesc = Object.getOwnPropertyDescriptor; - var __getOwnPropNames = Object.getOwnPropertyNames; - var __getProtoOf = Object.getPrototypeOf; - var __hasOwnProp = Object.prototype.hasOwnProperty; - var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports); - var __exportAll = (all, no_symbols) => { - let target = {}; - for (var name in all) __defProp(target, name, { - get: all[name], - enumerable: true - }); - if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" }); - return target; - }; - var __copyProps = (to, from, except, desc) => { - if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { - key = keys[i]; - if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { - get: ((k) => from[k]).bind(null, key), - enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable - }); - } - return to; - }; - var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { - value: mod, - enumerable: true - }) : target, mod)); - //#endregion - _iden3_binfileutils = __toESM(_iden3_binfileutils, 1); - //#region src/curves.js - var curves_exports = /* @__PURE__ */ __exportAll({ - getCurveFromName: () => getCurveFromName, - getCurveFromQ: () => getCurveFromQ, - getCurveFromR: () => getCurveFromR - }); - var bls12381r$1 = ffjavascript.Scalar.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16); - var bn128r$1 = ffjavascript.Scalar.e("21888242871839275222246405745257275088548364400416034343698204186575808495617"); - var bls12381q = ffjavascript.Scalar.e("1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", 16); - var bn128q = ffjavascript.Scalar.e("21888242871839275222246405745257275088696311157297823662689037894645226208583"); - async function getCurveFromR(r, options) { - let curve; - let singleThread = options && options.singleThread; - if (ffjavascript.Scalar.eq(r, bn128r$1)) curve = await (0, ffjavascript.buildBn128)(singleThread); - else if (ffjavascript.Scalar.eq(r, bls12381r$1)) curve = await (0, ffjavascript.buildBls12381)(singleThread); - else throw new Error(`Curve not supported: ${ffjavascript.Scalar.toString(r)}`); - return curve; - } - async function getCurveFromQ(q, options) { - let curve; - let singleThread = options && options.singleThread; - if (ffjavascript.Scalar.eq(q, bn128q)) curve = await (0, ffjavascript.buildBn128)(singleThread); - else if (ffjavascript.Scalar.eq(q, bls12381q)) curve = await (0, ffjavascript.buildBls12381)(singleThread); - else throw new Error(`Curve not supported: ${ffjavascript.Scalar.toString(q)}`); - return curve; - } - async function getCurveFromName(name, options) { - let curve; - let singleThread = options && options.singleThread; - const normName = normalizeName(name); - if ([ - "BN128", - "BN254", - "ALTBN128" - ].indexOf(normName) >= 0) curve = await (0, ffjavascript.buildBn128)(singleThread); - else if (["BLS12381"].indexOf(normName) >= 0) curve = await (0, ffjavascript.buildBls12381)(singleThread); - else throw new Error(`Curve not supported: ${name}`); - return curve; - function normalizeName(n) { - return n.toUpperCase().match(/[A-Za-z0-9]+/g).join(""); - } - } - //#endregion - //#region node_modules/@noble/hashes/utils.js - /** - * Checks if something is Uint8Array. Be careful: nodejs Buffer will return true. - * @param a - value to test - * @returns `true` when the value is a Uint8Array-compatible view. - * @example - * Check whether a value is a Uint8Array-compatible view. - * ```ts - * isBytes(new Uint8Array([1, 2, 3])); - * ``` - */ - function isBytes(a) { - return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array" && "BYTES_PER_ELEMENT" in a && a.BYTES_PER_ELEMENT === 1; - } - /** - * Asserts something is a non-negative integer. - * @param n - number to validate - * @param title - label included in thrown errors - * @throws On wrong argument types. {@link TypeError} - * @throws On wrong argument ranges or values. {@link RangeError} - * @example - * Validate a non-negative integer option. - * ```ts - * anumber(32, 'length'); - * ``` - */ - function anumber(n, title = "") { - if (typeof n !== "number") { - const prefix = title && `"${title}" `; - throw new TypeError(`${prefix}expected number, got ${typeof n}`); - } - if (!Number.isSafeInteger(n) || n < 0) { - const prefix = title && `"${title}" `; - throw new RangeError(`${prefix}expected integer >= 0, got ${n}`); - } - } - /** - * Asserts something is Uint8Array. - * @param value - value to validate - * @param length - optional exact length constraint - * @param title - label included in thrown errors - * @returns The validated byte array. - * @throws On wrong argument types. {@link TypeError} - * @throws On wrong argument ranges or values. {@link RangeError} - * @example - * Validate that a value is a byte array. - * ```ts - * abytes(new Uint8Array([1, 2, 3])); - * ``` - */ - function abytes(value, length, title = "") { - const bytes = isBytes(value); - const len = value?.length; - const needsLen = length !== void 0; - if (!bytes || needsLen && len !== length) { - const prefix = title && `"${title}" `; - const ofLen = needsLen ? ` of length ${length}` : ""; - const got = bytes ? `length=${len}` : `type=${typeof value}`; - const message = prefix + "expected Uint8Array" + ofLen + ", got " + got; - if (!bytes) throw new TypeError(message); - throw new RangeError(message); - } - return value; - } - /** - * Asserts a hash instance has not been destroyed or finished. - * @param instance - hash instance to validate - * @param checkFinished - whether to reject finalized instances - * @throws If the hash instance has already been destroyed or finalized. {@link Error} - * @example - * Validate that a hash instance is still usable. - * ```ts - * import { aexists } from '@noble/hashes/utils.js'; - * import { sha256 } from '@noble/hashes/sha2.js'; - * const hash = sha256.create(); - * aexists(hash); - * ``` - */ - function aexists(instance, checkFinished = true) { - if (instance.destroyed) throw new Error("Hash instance has been destroyed"); - if (checkFinished && instance.finished) throw new Error("Hash#digest() has already been called"); - } - /** - * Asserts output is a sufficiently-sized byte array. - * @param out - destination buffer - * @param instance - hash instance providing output length - * Oversized buffers are allowed; downstream code only promises to fill the first `outputLen` bytes. - * @throws On wrong argument types. {@link TypeError} - * @throws On wrong argument ranges or values. {@link RangeError} - * @example - * Validate a caller-provided digest buffer. - * ```ts - * import { aoutput } from '@noble/hashes/utils.js'; - * import { sha256 } from '@noble/hashes/sha2.js'; - * const hash = sha256.create(); - * aoutput(new Uint8Array(hash.outputLen), hash); - * ``` - */ - function aoutput(out, instance) { - abytes(out, void 0, "digestInto() output"); - const min = instance.outputLen; - if (out.length < min) throw new RangeError("\"digestInto() output\" expected to be of length >=" + min); - } - /** - * Casts a typed array view to Uint32Array. - * `arr.byteOffset` must already be 4-byte aligned or the platform - * Uint32Array constructor will throw. - * @param arr - source typed array - * @returns Uint32Array view over the same buffer. - * @example - * Reinterpret a byte array as 32-bit words. - * ```ts - * u32(new Uint8Array(8)); - * ``` - */ - function u32(arr) { - return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4)); - } - /** - * Zeroizes typed arrays in place. Warning: JS provides no guarantees. - * @param arrays - arrays to overwrite with zeros - * @example - * Zeroize sensitive buffers in place. - * ```ts - * clean(new Uint8Array([1, 2, 3])); - * ``` - */ - function clean(...arrays) { - for (let i = 0; i < arrays.length; i++) arrays[i].fill(0); - } - /** Whether the current platform is little-endian. */ - var isLE = new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68; - /** - * Byte-swap operation for uint32 values. - * @param word - source word - * @returns Word with reversed byte order. - * @example - * Reverse the byte order of a 32-bit word. - * ```ts - * byteSwap(0x11223344); - * ``` - */ - function byteSwap(word) { - return word << 24 & 4278190080 | word << 8 & 16711680 | word >>> 8 & 65280 | word >>> 24 & 255; - } - /** - * Conditionally byte-swaps one 32-bit word on big-endian platforms. - * @param n - source word - * @returns Original or byte-swapped word depending on platform endianness. - * @example - * Normalize a 32-bit word for host endianness. - * ```ts - * swap8IfBE(0x11223344); - * ``` - */ - var swap8IfBE = isLE ? (n) => n : (n) => byteSwap(n) >>> 0; - /** - * Byte-swaps every word of a Uint32Array in place. - * @param arr - array to mutate - * @returns The same array after mutation; callers pass live state arrays here. - * @example - * Reverse the byte order of every word in place. - * ```ts - * byteSwap32(new Uint32Array([0x11223344])); - * ``` - */ - function byteSwap32(arr) { - for (let i = 0; i < arr.length; i++) arr[i] = byteSwap(arr[i]); - return arr; - } - /** - * Conditionally byte-swaps a Uint32Array on big-endian platforms. - * @param u - array to normalize for host endianness - * @returns Original or byte-swapped array depending on platform endianness. - * On big-endian runtimes this mutates `u` in place via `byteSwap32(...)`. - * @example - * Normalize a word array for host endianness. - * ```ts - * swap32IfBE(new Uint32Array([0x11223344])); - * ``` - */ - var swap32IfBE = isLE ? (u) => u : byteSwap32; - typeof Uint8Array.from([]).toHex === "function" && Uint8Array.fromHex; - /** - * Creates a callable hash function from a stateful class constructor. - * @param hashCons - hash constructor or factory - * @param info - optional metadata such as DER OID - * @returns Frozen callable hash wrapper with `.create()`. - * Wrapper construction eagerly calls `hashCons(undefined)` once to read - * `outputLen` / `blockLen`, so constructor side effects happen at module - * init time. - * @example - * Wrap a stateful hash constructor into a callable helper. - * ```ts - * import { createHasher } from '@noble/hashes/utils.js'; - * import { sha256 } from '@noble/hashes/sha2.js'; - * const wrapped = createHasher(sha256.create, { oid: sha256.oid }); - * wrapped(new Uint8Array([1])); - * ``` - */ - function createHasher(hashCons, info = {}) { - const hashC = (msg, opts) => hashCons(opts).update(msg).digest(); - const tmp = hashCons(void 0); - hashC.outputLen = tmp.outputLen; - hashC.blockLen = tmp.blockLen; - hashC.canXOF = tmp.canXOF; - hashC.create = (opts) => hashCons(opts); - Object.assign(hashC, info); - return Object.freeze(hashC); - } - //#endregion - //#region node_modules/@noble/hashes/_blake.js - /** - * Internal blake permutation table. - * Rows `0..9` serve BLAKE2s, rows `0..11` serve BLAKE2b with `10..11 = 0..1`, and Blake1 also - * reuses the later rows shown below. Blake1 expands rounds `10..15` as `SIGMA[i % 10]`, so rows - * `10..15` intentionally repeat rows `0..5` for the 14-round (256) and 16-round (512) variants. - */ - var BSIGMA = /* @__PURE__ */ Uint8Array.from([ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 14, - 10, - 4, - 8, - 9, - 15, - 13, - 6, - 1, - 12, - 0, - 2, - 11, - 7, - 5, - 3, - 11, - 8, - 12, - 0, - 5, - 2, - 15, - 13, - 10, - 14, - 3, - 6, - 7, - 1, - 9, - 4, - 7, - 9, - 3, - 1, - 13, - 12, - 11, - 14, - 2, - 6, - 5, - 10, - 4, - 0, - 15, - 8, - 9, - 0, - 5, - 7, - 2, - 4, - 10, - 15, - 14, - 1, - 11, - 12, - 6, - 8, - 3, - 13, - 2, - 12, - 6, - 10, - 0, - 11, - 8, - 3, - 4, - 13, - 7, - 5, - 15, - 14, - 1, - 9, - 12, - 5, - 1, - 15, - 14, - 13, - 4, - 10, - 0, - 7, - 6, - 3, - 9, - 2, - 8, - 11, - 13, - 11, - 7, - 14, - 12, - 1, - 3, - 9, - 5, - 0, - 15, - 4, - 8, - 6, - 2, - 10, - 6, - 15, - 14, - 9, - 11, - 3, - 0, - 8, - 12, - 2, - 13, - 7, - 1, - 4, - 10, - 5, - 10, - 2, - 8, - 4, - 7, - 6, - 1, - 5, - 15, - 11, - 9, - 14, - 3, - 12, - 13, - 0, - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 14, - 10, - 4, - 8, - 9, - 15, - 13, - 6, - 1, - 12, - 0, - 2, - 11, - 7, - 5, - 3, - 11, - 8, - 12, - 0, - 5, - 2, - 15, - 13, - 10, - 14, - 3, - 6, - 7, - 1, - 9, - 4, - 7, - 9, - 3, - 1, - 13, - 12, - 11, - 14, - 2, - 6, - 5, - 10, - 4, - 0, - 15, - 8, - 9, - 0, - 5, - 7, - 2, - 4, - 10, - 15, - 14, - 1, - 11, - 12, - 6, - 8, - 3, - 13, - 2, - 12, - 6, - 10, - 0, - 11, - 8, - 3, - 4, - 13, - 7, - 5, - 15, - 14, - 1, - 9 - ]); - //#endregion - //#region node_modules/@noble/hashes/_u64.js - var U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1); - var _32n = /* @__PURE__ */ BigInt(32); - function fromBig(n, le = false) { - if (le) return { - h: Number(n & U32_MASK64), - l: Number(n >> _32n & U32_MASK64) - }; - return { - h: Number(n >> _32n & U32_MASK64) | 0, - l: Number(n & U32_MASK64) | 0 - }; - } - function split(lst, le = false) { - const len = lst.length; - let Ah = new Uint32Array(len); - let Al = new Uint32Array(len); - for (let i = 0; i < len; i++) { - const { h, l } = fromBig(lst[i], le); - [Ah[i], Al[i]] = [h, l]; - } - return [Ah, Al]; - } - var rotrSH = (h, l, s) => h >>> s | l << 32 - s; - var rotrSL = (h, l, s) => h << 32 - s | l >>> s; - var rotrBH = (h, l, s) => h << 64 - s | l >>> s - 32; - var rotrBL = (h, l, s) => h >>> s - 32 | l << 64 - s; - var rotr32H = (_h, l) => l; - var rotr32L = (h, _l) => h; - var rotlSH = (h, l, s) => h << s | l >>> 32 - s; - var rotlSL = (h, l, s) => l << s | h >>> 32 - s; - var rotlBH = (h, l, s) => l << s - 32 | h >>> 64 - s; - var rotlBL = (h, l, s) => h << s - 32 | l >>> 64 - s; - function add(Ah, Al, Bh, Bl) { - const l = (Al >>> 0) + (Bl >>> 0); - return { - h: Ah + Bh + (l / 2 ** 32 | 0) | 0, - l: l | 0 - }; - } - var add3L = (Al, Bl, Cl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0); - var add3H = (low, Ah, Bh, Ch) => Ah + Bh + Ch + (low / 2 ** 32 | 0) | 0; - //#endregion - //#region node_modules/@noble/hashes/blake2.js - /** - * blake2b (64-bit) & blake2s (8 to 32-bit) hash functions. - * b could have been faster, but there is no fast u64 in js, so s is 1.5x faster. - * @module - */ - var B2B_IV = /* @__PURE__ */ Uint32Array.from([ - 4089235720, - 1779033703, - 2227873595, - 3144134277, - 4271175723, - 1013904242, - 1595750129, - 2773480762, - 2917565137, - 1359893119, - 725511199, - 2600822924, - 4215389547, - 528734635, - 327033209, - 1541459225 - ]); - var BBUF = /* @__PURE__ */ new Uint32Array(32); - function G1b(a, b, c, d, msg, x) { - const Xl = msg[x], Xh = msg[x + 1]; - let Al = BBUF[2 * a], Ah = BBUF[2 * a + 1]; - let Bl = BBUF[2 * b], Bh = BBUF[2 * b + 1]; - let Cl = BBUF[2 * c], Ch = BBUF[2 * c + 1]; - let Dl = BBUF[2 * d], Dh = BBUF[2 * d + 1]; - let ll = add3L(Al, Bl, Xl); - Ah = add3H(ll, Ah, Bh, Xh); - Al = ll | 0; - ({Dh, Dl} = { - Dh: Dh ^ Ah, - Dl: Dl ^ Al - }); - ({Dh, Dl} = { - Dh: rotr32H(Dh, Dl), - Dl: rotr32L(Dh, Dl) - }); - ({h: Ch, l: Cl} = add(Ch, Cl, Dh, Dl)); - ({Bh, Bl} = { - Bh: Bh ^ Ch, - Bl: Bl ^ Cl - }); - ({Bh, Bl} = { - Bh: rotrSH(Bh, Bl, 24), - Bl: rotrSL(Bh, Bl, 24) - }); - BBUF[2 * a] = Al, BBUF[2 * a + 1] = Ah; - BBUF[2 * b] = Bl, BBUF[2 * b + 1] = Bh; - BBUF[2 * c] = Cl, BBUF[2 * c + 1] = Ch; - BBUF[2 * d] = Dl, BBUF[2 * d + 1] = Dh; - } - function G2b(a, b, c, d, msg, x) { - const Xl = msg[x], Xh = msg[x + 1]; - let Al = BBUF[2 * a], Ah = BBUF[2 * a + 1]; - let Bl = BBUF[2 * b], Bh = BBUF[2 * b + 1]; - let Cl = BBUF[2 * c], Ch = BBUF[2 * c + 1]; - let Dl = BBUF[2 * d], Dh = BBUF[2 * d + 1]; - let ll = add3L(Al, Bl, Xl); - Ah = add3H(ll, Ah, Bh, Xh); - Al = ll | 0; - ({Dh, Dl} = { - Dh: Dh ^ Ah, - Dl: Dl ^ Al - }); - ({Dh, Dl} = { - Dh: rotrSH(Dh, Dl, 16), - Dl: rotrSL(Dh, Dl, 16) - }); - ({h: Ch, l: Cl} = add(Ch, Cl, Dh, Dl)); - ({Bh, Bl} = { - Bh: Bh ^ Ch, - Bl: Bl ^ Cl - }); - ({Bh, Bl} = { - Bh: rotrBH(Bh, Bl, 63), - Bl: rotrBL(Bh, Bl, 63) - }); - BBUF[2 * a] = Al, BBUF[2 * a + 1] = Ah; - BBUF[2 * b] = Bl, BBUF[2 * b + 1] = Bh; - BBUF[2 * c] = Cl, BBUF[2 * c + 1] = Ch; - BBUF[2 * d] = Dl, BBUF[2 * d + 1] = Dh; - } - function checkBlake2Opts(outputLen, opts = {}, keyLen, saltLen, persLen) { - anumber(keyLen); - if (outputLen <= 0 || outputLen > keyLen) throw new Error("outputLen bigger than keyLen"); - const { key, salt, personalization } = opts; - if (key !== void 0 && (key.length < 1 || key.length > keyLen)) throw new Error("\"key\" expected to be undefined or of length=1.." + keyLen); - if (salt !== void 0) abytes(salt, saltLen, "salt"); - if (personalization !== void 0) abytes(personalization, persLen, "personalization"); - } - /** Internal base class for BLAKE2. */ - var _BLAKE2 = class { - buffer; - buffer32; - finished = false; - destroyed = false; - length = 0; - pos = 0; - blockLen; - outputLen; - canXOF = false; - constructor(blockLen, outputLen) { - anumber(blockLen); - anumber(outputLen); - this.blockLen = blockLen; - this.outputLen = outputLen; - this.buffer = new Uint8Array(blockLen); - this.buffer32 = u32(this.buffer); - } - update(data) { - aexists(this); - abytes(data); - const { blockLen, buffer, buffer32 } = this; - const len = data.length; - const offset = data.byteOffset; - const buf = data.buffer; - for (let pos = 0; pos < len;) { - if (this.pos === blockLen) { - swap32IfBE(buffer32); - this.compress(buffer32, 0, false); - swap32IfBE(buffer32); - this.pos = 0; - } - const take = Math.min(blockLen - this.pos, len - pos); - const dataOffset = offset + pos; - if (take === blockLen && !(dataOffset % 4) && pos + take < len) { - const data32 = new Uint32Array(buf, dataOffset, Math.floor((len - pos) / 4)); - swap32IfBE(data32); - for (let pos32 = 0; pos + blockLen < len; pos32 += buffer32.length, pos += blockLen) { - this.length += blockLen; - this.compress(data32, pos32, false); - } - swap32IfBE(data32); - continue; - } - buffer.set(data.subarray(pos, pos + take), this.pos); - this.pos += take; - this.length += take; - pos += take; - } - return this; - } - digestInto(out) { - aexists(this); - aoutput(out, this); - const { pos, buffer32 } = this; - this.finished = true; - clean(this.buffer.subarray(pos)); - swap32IfBE(buffer32); - this.compress(buffer32, 0, true); - swap32IfBE(buffer32); - if (out.byteOffset & 3) throw new RangeError("\"digestInto() output\" expected 4-byte aligned byteOffset, got " + out.byteOffset); - const state = this.get(); - const out32 = u32(out); - const full = Math.floor(this.outputLen / 4); - for (let i = 0; i < full; i++) out32[i] = swap8IfBE(state[i]); - const tail = this.outputLen % 4; - if (!tail) return; - const off = full * 4; - const word = state[full]; - for (let i = 0; i < tail; i++) out[off + i] = word >>> 8 * i; - } - digest() { - const { buffer, outputLen } = this; - this.digestInto(buffer); - const res = buffer.slice(0, outputLen); - this.destroy(); - return res; - } - _cloneInto(to) { - const { buffer, length, finished, destroyed, outputLen, pos } = this; - to ||= new this.constructor({ dkLen: outputLen }); - to.set(...this.get()); - to.buffer.set(buffer); - to.destroyed = destroyed; - to.finished = finished; - to.length = length; - to.pos = pos; - to.outputLen = outputLen; - return to; - } - clone() { - return this._cloneInto(); - } - }; - /** Internal blake2b hash class with state stored as LE u32 low/high halves. */ - var _BLAKE2b = class extends _BLAKE2 { - v0l = B2B_IV[0] | 0; - v0h = B2B_IV[1] | 0; - v1l = B2B_IV[2] | 0; - v1h = B2B_IV[3] | 0; - v2l = B2B_IV[4] | 0; - v2h = B2B_IV[5] | 0; - v3l = B2B_IV[6] | 0; - v3h = B2B_IV[7] | 0; - v4l = B2B_IV[8] | 0; - v4h = B2B_IV[9] | 0; - v5l = B2B_IV[10] | 0; - v5h = B2B_IV[11] | 0; - v6l = B2B_IV[12] | 0; - v6h = B2B_IV[13] | 0; - v7l = B2B_IV[14] | 0; - v7h = B2B_IV[15] | 0; - constructor(opts = {}) { - const olen = opts.dkLen === void 0 ? 64 : opts.dkLen; - super(128, olen); - checkBlake2Opts(olen, opts, 64, 16, 16); - let { key, personalization, salt } = opts; - let keyLength = 0; - if (key !== void 0) { - abytes(key, void 0, "key"); - keyLength = key.length; - } - this.v0l ^= this.outputLen | keyLength << 8 | 16842752; - if (salt !== void 0) { - abytes(salt, void 0, "salt"); - const slt = u32(salt); - this.v4l ^= swap8IfBE(slt[0]); - this.v4h ^= swap8IfBE(slt[1]); - this.v5l ^= swap8IfBE(slt[2]); - this.v5h ^= swap8IfBE(slt[3]); - } - if (personalization !== void 0) { - abytes(personalization, void 0, "personalization"); - const pers = u32(personalization); - this.v6l ^= swap8IfBE(pers[0]); - this.v6h ^= swap8IfBE(pers[1]); - this.v7l ^= swap8IfBE(pers[2]); - this.v7h ^= swap8IfBE(pers[3]); - } - if (key !== void 0) { - const tmp = new Uint8Array(this.blockLen); - tmp.set(key); - this.update(tmp); - } - } - get() { - let { v0l, v0h, v1l, v1h, v2l, v2h, v3l, v3h, v4l, v4h, v5l, v5h, v6l, v6h, v7l, v7h } = this; - return [ - v0l, - v0h, - v1l, - v1h, - v2l, - v2h, - v3l, - v3h, - v4l, - v4h, - v5l, - v5h, - v6l, - v6h, - v7l, - v7h - ]; - } - set(v0l, v0h, v1l, v1h, v2l, v2h, v3l, v3h, v4l, v4h, v5l, v5h, v6l, v6h, v7l, v7h) { - this.v0l = v0l | 0; - this.v0h = v0h | 0; - this.v1l = v1l | 0; - this.v1h = v1h | 0; - this.v2l = v2l | 0; - this.v2h = v2h | 0; - this.v3l = v3l | 0; - this.v3h = v3h | 0; - this.v4l = v4l | 0; - this.v4h = v4h | 0; - this.v5l = v5l | 0; - this.v5h = v5h | 0; - this.v6l = v6l | 0; - this.v6h = v6h | 0; - this.v7l = v7l | 0; - this.v7h = v7h | 0; - } - compress(msg, offset, isLast) { - this.get().forEach((v, i) => BBUF[i] = v); - BBUF.set(B2B_IV, 16); - let { h, l } = fromBig(BigInt(this.length)); - BBUF[24] = B2B_IV[8] ^ l; - BBUF[25] = B2B_IV[9] ^ h; - if (isLast) { - BBUF[28] = ~BBUF[28]; - BBUF[29] = ~BBUF[29]; - } - let j = 0; - const s = BSIGMA; - for (let i = 0; i < 12; i++) { - G1b(0, 4, 8, 12, msg, offset + 2 * s[j++]); - G2b(0, 4, 8, 12, msg, offset + 2 * s[j++]); - G1b(1, 5, 9, 13, msg, offset + 2 * s[j++]); - G2b(1, 5, 9, 13, msg, offset + 2 * s[j++]); - G1b(2, 6, 10, 14, msg, offset + 2 * s[j++]); - G2b(2, 6, 10, 14, msg, offset + 2 * s[j++]); - G1b(3, 7, 11, 15, msg, offset + 2 * s[j++]); - G2b(3, 7, 11, 15, msg, offset + 2 * s[j++]); - G1b(0, 5, 10, 15, msg, offset + 2 * s[j++]); - G2b(0, 5, 10, 15, msg, offset + 2 * s[j++]); - G1b(1, 6, 11, 12, msg, offset + 2 * s[j++]); - G2b(1, 6, 11, 12, msg, offset + 2 * s[j++]); - G1b(2, 7, 8, 13, msg, offset + 2 * s[j++]); - G2b(2, 7, 8, 13, msg, offset + 2 * s[j++]); - G1b(3, 4, 9, 14, msg, offset + 2 * s[j++]); - G2b(3, 4, 9, 14, msg, offset + 2 * s[j++]); - } - this.v0l ^= BBUF[0] ^ BBUF[16]; - this.v0h ^= BBUF[1] ^ BBUF[17]; - this.v1l ^= BBUF[2] ^ BBUF[18]; - this.v1h ^= BBUF[3] ^ BBUF[19]; - this.v2l ^= BBUF[4] ^ BBUF[20]; - this.v2h ^= BBUF[5] ^ BBUF[21]; - this.v3l ^= BBUF[6] ^ BBUF[22]; - this.v3h ^= BBUF[7] ^ BBUF[23]; - this.v4l ^= BBUF[8] ^ BBUF[24]; - this.v4h ^= BBUF[9] ^ BBUF[25]; - this.v5l ^= BBUF[10] ^ BBUF[26]; - this.v5h ^= BBUF[11] ^ BBUF[27]; - this.v6l ^= BBUF[12] ^ BBUF[28]; - this.v6h ^= BBUF[13] ^ BBUF[29]; - this.v7l ^= BBUF[14] ^ BBUF[30]; - this.v7h ^= BBUF[15] ^ BBUF[31]; - clean(BBUF); - } - destroy() { - this.destroyed = true; - clean(this.buffer32); - this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - } - }; - /** - * Blake2b hash function. 64-bit. 1.5x slower than blake2s in JS. - * @param msg - message that would be hashed - * @param opts - Optional output, MAC, salt, and personalization settings. - * `dkLen` must be 1..64 bytes; `salt` and `personalization`, if present, - * must be 16 bytes each. See {@link Blake2Opts}. - * @returns Digest bytes. - * @example - * Hash a message with Blake2b. - * ```ts - * blake2b(new Uint8Array([97, 98, 99])); - * ``` - */ - var blake2b = /* @__PURE__ */ createHasher((opts) => new _BLAKE2b(opts)); - (/* @__PURE__ */ __commonJSMin(((exports, module) => { - module.exports = {}; - })))(); - var _revTable = []; - for (let i = 0; i < 256; i++) _revTable[i] = _revSlow(i, 8); - function _revSlow(idx, bits) { - let res = 0; - let a = idx; - for (let i = 0; i < bits; i++) { - res <<= 1; - res = res | a & 1; - a >>= 1; - } - return res; - } - function log2(V) { - return ((V & 4294901760) !== 0 ? (V &= 4294901760, 16) : 0) | ((V & 4278255360) !== 0 ? (V &= 4278255360, 8) : 0) | ((V & 4042322160) !== 0 ? (V &= 4042322160, 4) : 0) | ((V & 3435973836) !== 0 ? (V &= 3435973836, 2) : 0) | (V & 2863311530) !== 0; - } - function formatHash(b, title) { - const a = new DataView(b.buffer, b.byteOffset, b.byteLength); - let S = ""; - for (let i = 0; i < 4; i++) { - if (i > 0) S += "\n"; - S += " "; - for (let j = 0; j < 4; j++) { - if (j > 0) S += " "; - S += a.getUint32(i * 16 + j * 4).toString(16).padStart(8, "0"); - } - } - if (title) S = title + "\n" + S; - return S; - } - function hashIsEqual(h1, h2) { - if (h1.byteLength != h2.byteLength) return false; - var dv1 = new Int8Array(h1); - var dv2 = new Int8Array(h2); - for (var i = 0; i != h1.byteLength; i++) if (dv1[i] != dv2[i]) return false; - return true; - } - function cloneHasher(h) { - return h.clone(); - } - function fromPartialHash(partial) { - const buf = partial.subarray(0, 128); - const rest = u32(partial.subarray(128)); - const res = blake2b.create({ dkLen: 64 }); - res.buffer.set(buf); - res.v0l = rest[0] | 0, res.v0h = rest[1] | 0; - res.v1l = rest[2] | 0, res.v1h = rest[3] | 0; - res.v2l = rest[4] | 0, res.v2h = rest[5] | 0; - res.v3l = rest[6] | 0, res.v3h = rest[7] | 0; - res.v4l = rest[8] | 0, res.v4h = rest[9] | 0; - res.v5l = rest[10] | 0, res.v5h = rest[11] | 0; - res.v6l = rest[12] | 0, res.v6h = rest[13] | 0; - res.v7l = rest[14] | 0, res.v7h = rest[15] | 0; - const shift = 2 ** 32; - const len = rest[16] + rest[17] * shift; - const pos = rest[18] + rest[19] * shift; - res.length = len + pos; - res.pos = pos; - return res; - } - function toPartialHash(hash) { - const res = new Uint8Array(216); - const res32 = u32(res.subarray(128)); - res.set(hash.buffer); - res32[0] = hash.v0l, res32[1] = hash.v0h; - res32[2] = hash.v1l, res32[3] = hash.v1h; - res32[4] = hash.v2l, res32[5] = hash.v2h; - res32[6] = hash.v3l, res32[7] = hash.v3h; - res32[8] = hash.v4l, res32[9] = hash.v4h; - res32[10] = hash.v5l, res32[11] = hash.v5h; - res32[12] = hash.v6l, res32[13] = hash.v6h; - res32[14] = hash.v7l, res32[15] = hash.v7h; - res32[18] = hash.pos; - res32[16] = hash.length - hash.pos; - return res; - } - async function sameRatio$2(curve, g1s, g1sx, g2s, g2sx) { - if (curve.G1.isZero(g1s)) return false; - if (curve.G1.isZero(g1sx)) return false; - if (curve.G2.isZero(g2s)) return false; - if (curve.G2.isZero(g2sx)) return false; - return await curve.pairingEq(g1s, g2sx, curve.G1.neg(g1sx), g2s); - } - function askEntropy() { - return window.prompt("Enter a random text. (Entropy): ", ""); - } - function getRandomBytes(n) { - let array = new Uint8Array(n); - globalThis.crypto.getRandomValues(array); - return array; - } - async function sha256digest(data) { - { - const buffer = await globalThis.crypto.subtle.digest("SHA-256", data.buffer); - return new Uint8Array(buffer); - } - } - /** - * @param {Uint8Array} data - * @param {number} offset - */ - function readUInt32BE(data, offset) { - return new DataView(data.buffer).getUint32(offset, false); - } - async function getRandomRng(entropy) { - while (!entropy) entropy = await askEntropy(); - const hasher = blake2b.create(64); - hasher.update(getRandomBytes(64)); - const enc = new TextEncoder(); - hasher.update(enc.encode(entropy)); - const hash = hasher.digest(); - const seed = []; - for (let i = 0; i < 8; i++) seed[i] = readUInt32BE(hash, i * 4); - return new ffjavascript.ChaCha(seed); - } - async function rngFromBeaconParams(beaconHash, numIterationsExp) { - let nIterationsInner; - let nIterationsOuter; - if (numIterationsExp < 32) { - nIterationsInner = 1 << numIterationsExp >>> 0; - nIterationsOuter = 1; - } else { - nIterationsInner = 4294967296; - nIterationsOuter = 1 << numIterationsExp - 32 >>> 0; - } - let curHash = beaconHash; - for (let i = 0; i < nIterationsOuter; i++) for (let j = 0; j < nIterationsInner; j++) curHash = await sha256digest(curHash); - const curHashV = new DataView(curHash.buffer, curHash.byteOffset, curHash.byteLength); - const seed = []; - for (let i = 0; i < 8; i++) seed[i] = curHashV.getUint32(i * 4, false); - return new ffjavascript.ChaCha(seed); - } - function hex2ByteArray(s) { - if (s instanceof Uint8Array) return s; - if (s.slice(0, 2) == "0x") s = s.slice(2); - return new Uint8Array(s.match(/[\da-f]{2}/gi).map(function(h) { - return parseInt(h, 16); - })); - } - function byteArray2hex(byteArray) { - return Array.prototype.map.call(byteArray, function(byte) { - return ("0" + (byte & 255).toString(16)).slice(-2); - }).join(""); - } - function stringifyBigIntsWithField(Fr, o) { - if (o instanceof Uint8Array) return Fr.toString(o); - else if (Array.isArray(o)) return o.map(stringifyBigIntsWithField.bind(null, Fr)); - else if (typeof o == "object") { - const res = {}; - Object.keys(o).forEach((k) => { - res[k] = stringifyBigIntsWithField(Fr, o[k]); - }); - return res; - } else if (typeof o == "bigint" || o.eq !== void 0) return o.toString(10); - else return o; - } - //#endregion - //#region src/zkey_utils.js - async function writeHeader(fd, zkey) { - await _iden3_binfileutils.startWriteSection(fd, 1); - await fd.writeULE32(1); - await _iden3_binfileutils.endWriteSection(fd); - const curve = await getCurveFromQ(zkey.q); - await _iden3_binfileutils.startWriteSection(fd, 2); - const primeQ = curve.q; - const n8q = (Math.floor((ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) + 1) * 8; - const primeR = curve.r; - const n8r = (Math.floor((ffjavascript.Scalar.bitLength(primeR) - 1) / 64) + 1) * 8; - await fd.writeULE32(n8q); - await _iden3_binfileutils.writeBigInt(fd, primeQ, n8q); - await fd.writeULE32(n8r); - await _iden3_binfileutils.writeBigInt(fd, primeR, n8r); - await fd.writeULE32(zkey.nVars); - await fd.writeULE32(zkey.nPublic); - await fd.writeULE32(zkey.domainSize); - await writeG1(fd, curve, zkey.vk_alpha_1); - await writeG1(fd, curve, zkey.vk_beta_1); - await writeG2(fd, curve, zkey.vk_beta_2); - await writeG2(fd, curve, zkey.vk_gamma_2); - await writeG1(fd, curve, zkey.vk_delta_1); - await writeG2(fd, curve, zkey.vk_delta_2); - await _iden3_binfileutils.endWriteSection(fd); - } - async function writeG1(fd, curve, p) { - const buff = new Uint8Array(curve.G1.F.n8 * 2); - curve.G1.toRprLEM(buff, 0, p); - await fd.write(buff); - } - async function writeG2(fd, curve, p) { - const buff = new Uint8Array(curve.G2.F.n8 * 2); - curve.G2.toRprLEM(buff, 0, p); - await fd.write(buff); - } - async function readG1(fd, curve, toObject) { - const buff = await fd.read(curve.G1.F.n8 * 2); - const res = curve.G1.fromRprLEM(buff, 0); - return toObject ? curve.G1.toObject(res) : res; - } - async function readG2(fd, curve, toObject) { - const buff = await fd.read(curve.G2.F.n8 * 2); - const res = curve.G2.fromRprLEM(buff, 0); - return toObject ? curve.G2.toObject(res) : res; - } - async function readHeader$1(fd, sections, toObject, options) { - await _iden3_binfileutils.startReadUniqueSection(fd, sections, 1); - const protocolId = await fd.readULE32(); - await _iden3_binfileutils.endReadSection(fd); - if (protocolId === 1) return await readHeaderGroth16(fd, sections, toObject, options); - else if (protocolId === 2) return await readHeaderPlonk(fd, sections, toObject, options); - else if (protocolId === 10) return await readHeaderFFlonk(fd, sections, toObject, options); - else throw new Error("Protocol not supported: "); - } - async function readHeaderGroth16(fd, sections, toObject, options) { - const zkey = {}; - zkey.protocol = "groth16"; - await _iden3_binfileutils.startReadUniqueSection(fd, sections, 2); - const n8q = await fd.readULE32(); - zkey.n8q = n8q; - zkey.q = await _iden3_binfileutils.readBigInt(fd, n8q); - const n8r = await fd.readULE32(); - zkey.n8r = n8r; - zkey.r = await _iden3_binfileutils.readBigInt(fd, n8r); - zkey.curve = await getCurveFromQ(zkey.q, options); - zkey.nVars = await fd.readULE32(); - zkey.nPublic = await fd.readULE32(); - zkey.domainSize = await fd.readULE32(); - zkey.power = log2(zkey.domainSize); - zkey.vk_alpha_1 = await readG1(fd, zkey.curve, toObject); - zkey.vk_beta_1 = await readG1(fd, zkey.curve, toObject); - zkey.vk_beta_2 = await readG2(fd, zkey.curve, toObject); - zkey.vk_gamma_2 = await readG2(fd, zkey.curve, toObject); - zkey.vk_delta_1 = await readG1(fd, zkey.curve, toObject); - zkey.vk_delta_2 = await readG2(fd, zkey.curve, toObject); - await _iden3_binfileutils.endReadSection(fd); - return zkey; - } - async function readHeaderPlonk(fd, sections, toObject, options) { - const zkey = {}; - zkey.protocol = "plonk"; - await _iden3_binfileutils.startReadUniqueSection(fd, sections, 2); - const n8q = await fd.readULE32(); - zkey.n8q = n8q; - zkey.q = await _iden3_binfileutils.readBigInt(fd, n8q); - const n8r = await fd.readULE32(); - zkey.n8r = n8r; - zkey.r = await _iden3_binfileutils.readBigInt(fd, n8r); - zkey.curve = await getCurveFromQ(zkey.q, options); - zkey.nVars = await fd.readULE32(); - zkey.nPublic = await fd.readULE32(); - zkey.domainSize = await fd.readULE32(); - zkey.power = log2(zkey.domainSize); - zkey.nAdditions = await fd.readULE32(); - zkey.nConstraints = await fd.readULE32(); - zkey.k1 = await fd.read(n8r); - zkey.k2 = await fd.read(n8r); - zkey.Qm = await readG1(fd, zkey.curve, toObject); - zkey.Ql = await readG1(fd, zkey.curve, toObject); - zkey.Qr = await readG1(fd, zkey.curve, toObject); - zkey.Qo = await readG1(fd, zkey.curve, toObject); - zkey.Qc = await readG1(fd, zkey.curve, toObject); - zkey.S1 = await readG1(fd, zkey.curve, toObject); - zkey.S2 = await readG1(fd, zkey.curve, toObject); - zkey.S3 = await readG1(fd, zkey.curve, toObject); - zkey.X_2 = await readG2(fd, zkey.curve, toObject); - await _iden3_binfileutils.endReadSection(fd); - return zkey; - } - async function readHeaderFFlonk(fd, sections, toObject, options) { - const zkey = {}; - zkey.protocol = "fflonk"; - zkey.protocolId = 10; - await _iden3_binfileutils.startReadUniqueSection(fd, sections, 2); - const n8q = await fd.readULE32(); - zkey.n8q = n8q; - zkey.q = await _iden3_binfileutils.readBigInt(fd, n8q); - zkey.curve = await getCurveFromQ(zkey.q, options); - const n8r = await fd.readULE32(); - zkey.n8r = n8r; - zkey.r = await _iden3_binfileutils.readBigInt(fd, n8r); - zkey.nVars = await fd.readULE32(); - zkey.nPublic = await fd.readULE32(); - zkey.domainSize = await fd.readULE32(); - zkey.power = log2(zkey.domainSize); - zkey.nAdditions = await fd.readULE32(); - zkey.nConstraints = await fd.readULE32(); - zkey.k1 = await fd.read(n8r); - zkey.k2 = await fd.read(n8r); - zkey.w3 = await fd.read(n8r); - zkey.w4 = await fd.read(n8r); - zkey.w8 = await fd.read(n8r); - zkey.wr = await fd.read(n8r); - zkey.X_2 = await readG2(fd, zkey.curve, toObject); - zkey.C0 = await readG1(fd, zkey.curve, toObject); - await _iden3_binfileutils.endReadSection(fd); - return zkey; - } - async function readZKey(fileName, toObject) { - const { fd, sections } = await _iden3_binfileutils.readBinFile(fileName, "zkey", 1); - const zkey = await readHeader$1(fd, sections, toObject); - const Fr = new ffjavascript.F1Field(zkey.r); - const Rr = ffjavascript.Scalar.mod(ffjavascript.Scalar.shl(1, zkey.n8r * 8), zkey.r); - const Rri = Fr.inv(Rr); - const Rri2 = Fr.mul(Rri, Rri); - let curve = await getCurveFromQ(zkey.q); - await _iden3_binfileutils.startReadUniqueSection(fd, sections, 3); - zkey.IC = []; - for (let i = 0; i <= zkey.nPublic; i++) { - const P = await readG1(fd, curve, toObject); - zkey.IC.push(P); - } - await _iden3_binfileutils.endReadSection(fd); - await _iden3_binfileutils.startReadUniqueSection(fd, sections, 4); - const nCCoefs = await fd.readULE32(); - zkey.ccoefs = []; - for (let i = 0; i < nCCoefs; i++) { - const m = await fd.readULE32(); - const c = await fd.readULE32(); - const s = await fd.readULE32(); - const v = await readFr2(toObject); - zkey.ccoefs.push({ - matrix: m, - constraint: c, - signal: s, - value: v - }); - } - await _iden3_binfileutils.endReadSection(fd); - await _iden3_binfileutils.startReadUniqueSection(fd, sections, 5); - zkey.A = []; - for (let i = 0; i < zkey.nVars; i++) { - const A = await readG1(fd, curve, toObject); - zkey.A[i] = A; - } - await _iden3_binfileutils.endReadSection(fd); - await _iden3_binfileutils.startReadUniqueSection(fd, sections, 6); - zkey.B1 = []; - for (let i = 0; i < zkey.nVars; i++) { - const B1 = await readG1(fd, curve, toObject); - zkey.B1[i] = B1; - } - await _iden3_binfileutils.endReadSection(fd); - await _iden3_binfileutils.startReadUniqueSection(fd, sections, 7); - zkey.B2 = []; - for (let i = 0; i < zkey.nVars; i++) { - const B2 = await readG2(fd, curve, toObject); - zkey.B2[i] = B2; - } - await _iden3_binfileutils.endReadSection(fd); - await _iden3_binfileutils.startReadUniqueSection(fd, sections, 8); - zkey.C = []; - for (let i = zkey.nPublic + 1; i < zkey.nVars; i++) { - const C = await readG1(fd, curve, toObject); - zkey.C[i] = C; - } - await _iden3_binfileutils.endReadSection(fd); - await _iden3_binfileutils.startReadUniqueSection(fd, sections, 9); - zkey.hExps = []; - for (let i = 0; i < zkey.domainSize; i++) { - const H = await readG1(fd, curve, toObject); - zkey.hExps.push(H); - } - await _iden3_binfileutils.endReadSection(fd); - await fd.close(); - return zkey; - async function readFr2() { - const n = await _iden3_binfileutils.readBigInt(fd, zkey.n8r); - return Fr.mul(n, Rri2); - } - } - async function readContribution$1(fd, curve, toObject) { - const c = { delta: {} }; - c.deltaAfter = await readG1(fd, curve, toObject); - c.delta.g1_s = await readG1(fd, curve, toObject); - c.delta.g1_sx = await readG1(fd, curve, toObject); - c.delta.g2_spx = await readG2(fd, curve, toObject); - c.transcript = await fd.read(64); - c.type = await fd.readULE32(); - const paramLength = await fd.readULE32(); - const curPos = fd.pos; - let lastType = 0; - while (fd.pos - curPos < paramLength) { - const buffType = await fd.read(1); - if (buffType[0] <= lastType) throw new Error("Parameters in the contribution must be sorted"); - lastType = buffType[0]; - if (buffType[0] == 1) { - const buffLen = await fd.read(1); - const buffStr = await fd.read(buffLen[0]); - c.name = new TextDecoder().decode(buffStr); - } else if (buffType[0] == 2) c.numIterationsExp = (await fd.read(1))[0]; - else if (buffType[0] == 3) { - const buffLen = await fd.read(1); - c.beaconHash = await fd.read(buffLen[0]); - } else throw new Error("Parameter not recognized"); - } - if (fd.pos != curPos + paramLength) throw new Error("Parameters do not match"); - return c; - } - async function readMPCParams(fd, curve, sections) { - await _iden3_binfileutils.startReadUniqueSection(fd, sections, 10); - const res = { contributions: [] }; - res.csHash = await fd.read(64); - const n = await fd.readULE32(); - for (let i = 0; i < n; i++) { - const c = await readContribution$1(fd, curve); - res.contributions.push(c); - } - await _iden3_binfileutils.endReadSection(fd); - return res; - } - async function writeContribution$1(fd, curve, c) { - await writeG1(fd, curve, c.deltaAfter); - await writeG1(fd, curve, c.delta.g1_s); - await writeG1(fd, curve, c.delta.g1_sx); - await writeG2(fd, curve, c.delta.g2_spx); - await fd.write(c.transcript); - await fd.writeULE32(c.type || 0); - const params = []; - if (c.name) { - params.push(1); - const nameData = new TextEncoder("utf-8").encode(c.name.substring(0, 64)); - params.push(nameData.byteLength); - for (let i = 0; i < nameData.byteLength; i++) params.push(nameData[i]); - } - if (c.type == 1) { - params.push(2); - params.push(c.numIterationsExp); - params.push(3); - params.push(c.beaconHash.byteLength); - for (let i = 0; i < c.beaconHash.byteLength; i++) params.push(c.beaconHash[i]); - } - if (params.length > 0) { - const paramsBuff = new Uint8Array(params); - await fd.writeULE32(paramsBuff.byteLength); - await fd.write(paramsBuff); - } else await fd.writeULE32(0); - } - async function writeMPCParams(fd, curve, mpcParams) { - await _iden3_binfileutils.startWriteSection(fd, 10); - await fd.write(mpcParams.csHash); - await fd.writeULE32(mpcParams.contributions.length); - for (let i = 0; i < mpcParams.contributions.length; i++) await writeContribution$1(fd, curve, mpcParams.contributions[i]); - await _iden3_binfileutils.endWriteSection(fd); - } - function hashG1(hasher, curve, p) { - const buff = new Uint8Array(curve.G1.F.n8 * 2); - curve.G1.toRprUncompressed(buff, 0, p); - hasher.update(buff); - } - function hashG2(hasher, curve, p) { - const buff = new Uint8Array(curve.G2.F.n8 * 2); - curve.G2.toRprUncompressed(buff, 0, p); - hasher.update(buff); - } - function hashPubKey(hasher, curve, c) { - hashG1(hasher, curve, c.deltaAfter); - hashG1(hasher, curve, c.delta.g1_s); - hashG1(hasher, curve, c.delta.g1_sx); - hashG2(hasher, curve, c.delta.g2_spx); - hasher.update(c.transcript); - } - //#endregion - //#region src/wtns_utils.js - async function write(fd, witness, prime) { - await _iden3_binfileutils.startWriteSection(fd, 1); - const n8 = (Math.floor((ffjavascript.Scalar.bitLength(prime) - 1) / 64) + 1) * 8; - await fd.writeULE32(n8); - await _iden3_binfileutils.writeBigInt(fd, prime, n8); - await fd.writeULE32(witness.length); - await _iden3_binfileutils.endWriteSection(fd); - await _iden3_binfileutils.startWriteSection(fd, 2); - for (let i = 0; i < witness.length; i++) await _iden3_binfileutils.writeBigInt(fd, witness[i], n8); - await _iden3_binfileutils.endWriteSection(fd, 2); - } - async function writeBin(fd, witnessBin, prime) { - await _iden3_binfileutils.startWriteSection(fd, 1); - const n8 = (Math.floor((ffjavascript.Scalar.bitLength(prime) - 1) / 64) + 1) * 8; - await fd.writeULE32(n8); - await _iden3_binfileutils.writeBigInt(fd, prime, n8); - if (witnessBin.byteLength % n8 != 0) throw new Error("Invalid witness length"); - await fd.writeULE32(witnessBin.byteLength / n8); - await _iden3_binfileutils.endWriteSection(fd); - await _iden3_binfileutils.startWriteSection(fd, 2); - await fd.write(witnessBin); - await _iden3_binfileutils.endWriteSection(fd); - } - async function readHeader(fd, sections) { - await _iden3_binfileutils.startReadUniqueSection(fd, sections, 1); - const n8 = await fd.readULE32(); - const q = await _iden3_binfileutils.readBigInt(fd, n8); - const nWitness = await fd.readULE32(); - await _iden3_binfileutils.endReadSection(fd); - return { - n8, - q, - nWitness - }; - } - async function read(fileName) { - const { fd, sections } = await _iden3_binfileutils.readBinFile(fileName, "wtns", 2); - const { n8, nWitness } = await readHeader(fd, sections); - await _iden3_binfileutils.startReadUniqueSection(fd, sections, 2); - const res = []; - for (let i = 0; i < nWitness; i++) { - const v = await _iden3_binfileutils.readBigInt(fd, n8); - res.push(v); - } - await _iden3_binfileutils.endReadSection(fd); - await fd.close(); - return res; - } - //#endregion - //#region src/groth16_prove.js - var { stringifyBigInts: stringifyBigInts$3 } = ffjavascript.utils; - async function groth16Prove(zkeyFileName, witnessFileName, logger, options) { - if (logger) monitorMemoryUsage(logger, 50); - const { fd: fdWtns, sections: sectionsWtns } = await _iden3_binfileutils.readBinFile(witnessFileName, "wtns", 2, 1 << 25, 1 << 23); - const wtns = await readHeader(fdWtns, sectionsWtns); - const { fd: fdZKey, sections: sectionsZKey } = await _iden3_binfileutils.readBinFile(zkeyFileName, "zkey", 2, 1 << 25, 1 << 23); - const zkey = await readHeader$1(fdZKey, sectionsZKey, void 0, options); - if (zkey.protocol != "groth16") throw new Error("zkey file is not groth16"); - if (!ffjavascript.Scalar.eq(zkey.r, wtns.q)) throw new Error("Curve of the witness does not match the curve of the proving key"); - if (wtns.nWitness != zkey.nVars) throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}`); - const curve = zkey.curve; - const Fr = curve.Fr; - const G1 = curve.G1; - const G2 = curve.G2; - const power = log2(zkey.domainSize); - if (logger) logger.debug("Reading Wtns"); - const buffWitness = await _iden3_binfileutils.readSection(fdWtns, sectionsWtns, 2); - let resH; - let resHPromise; - let buffPodd_T; - let abcPromise = (async function() { - let buffA_T, buffB_T, buffC_T; - await (async function() { - if (logger) logger.debug("Reading Coeffs"); - console.time("buildABC_outer"); - const buffCoeffs = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 4); - if (logger) logger.debug("Building ABC"); - options = options || {}; - if (options && options.buildABC === "wasm") [buffA_T, buffB_T, buffC_T] = await buildABC(curve, zkey, buffWitness, buffCoeffs, logger); - else if (options && options.buildABC === "wasm1") [buffA_T, buffB_T, buffC_T] = await buildABCWASM1(curve, zkey, buffWitness, buffCoeffs, logger); - else [buffA_T, buffB_T, buffC_T] = await buildABC1(curve, zkey, buffWitness, buffCoeffs, logger); - console.timeEnd("buildABC_outer"); - })(); - console.time("abcPromise"); - if (globalThis.gc) globalThis.gc(); - const inc = power === Fr.s ? curve.Fr.shift : curve.Fr.w[power + 1]; - let buffAodd_T; - await (async function() { - let buffA = await Fr.ifft(buffA_T, "", "", logger, "IFFT_A"); - buffA_T = null; - const buffAodd = await Fr.batchApplyKey(buffA, Fr.e(1), inc); - buffAodd_T = await Fr.fft(buffAodd, "", "", logger, "FFT_A"); - })(); - let buffBodd_T; - await (async function() { - const buffB = await Fr.ifft(buffB_T, "", "", logger, "IFFT_B"); - buffB_T = null; - const buffBodd = await Fr.batchApplyKey(buffB, Fr.e(1), inc); - buffBodd_T = await Fr.fft(buffBodd, "", "", logger, "FFT_B"); - })(); - let buffCodd_T; - await (async function() { - const buffC = await Fr.ifft(buffC_T, "", "", logger, "IFFT_C"); - buffC_T = null; - const buffCodd = await Fr.batchApplyKey(buffC, Fr.e(1), inc); - buffCodd_T = await Fr.fft(buffCodd, "", "", logger, "FFT_C"); - })(); - if (logger) logger.debug("Join ABC"); - buffPodd_T = await joinABC(curve, zkey, buffAodd_T, buffBodd_T, buffCodd_T, logger); - if (logger) logger.debug("Join ABC finished"); - buffAodd_T = null; - buffBodd_T = null; - buffCodd_T = null; - if (globalThis.gc) globalThis.gc(); - console.timeEnd("abcPromise"); - })(); - let proof = {}; - async function calcPiA() { - if (logger) logger.debug("Reading A Points"); - const buffBasesA = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 5); - console.time("Calculate PiA"); - proof.pi_a = await curve.G1.multiExpAffine(buffBasesA, buffWitness, logger, "multiexp A"); - console.timeEnd("Calculate PiA"); - } - let piaPromise = calcPiA(); - let pib1; - async function calcPiB1() { - if (logger) logger.debug("Reading B1 Points"); - const buffBasesB1 = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 6); - console.time("Calculate PiB1"); - pib1 = await curve.G1.multiExpAffine(buffBasesB1, buffWitness, logger, "multiexp B1"); - console.timeEnd("Calculate PiB1"); - } - let pib1Promise = calcPiB1(); - async function calcPiB() { - if (logger) logger.debug("Reading B2 Points"); - const buffBasesB2 = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 7); - console.time("Calculate PiB"); - proof.pi_b = await curve.G2.multiExpAffine(buffBasesB2, buffWitness, logger, "multiexp B2"); - console.timeEnd("Calculate PiB"); - } - let pibPromise = calcPiB(); - let picPromise = (async function() { - if (logger) logger.debug("Reading C Points"); - const buffBasesC = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 8); - console.time("Calculate PiC"); - proof.pi_c = await curve.G1.multiExpAffine(buffBasesC, buffWitness.slice((zkey.nPublic + 1) * curve.Fr.n8), logger, "multiexp C"); - console.timeEnd("Calculate PiC"); - })(); - resHPromise = (async function() { - if (logger) logger.debug("Reading H Points"); - await abcPromise; - console.time("resHPromise"); - const buffBasesH = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 9); - resH = await curve.G1.multiExpAffine(buffBasesH, buffPodd_T, logger, "multiexp H"); - console.timeEnd("resHPromise"); - })(); - const r = curve.Fr.random(); - const s = curve.Fr.random(); - await piaPromise; - proof.pi_a = G1.add(proof.pi_a, zkey.vk_alpha_1); - proof.pi_a = G1.add(proof.pi_a, G1.timesFr(zkey.vk_delta_1, r)); - await pibPromise; - proof.pi_b = G2.add(proof.pi_b, zkey.vk_beta_2); - proof.pi_b = G2.add(proof.pi_b, G2.timesFr(zkey.vk_delta_2, s)); - await pib1Promise; - pib1 = G1.add(pib1, zkey.vk_beta_1); - pib1 = G1.add(pib1, G1.timesFr(zkey.vk_delta_1, s)); - await Promise.all([picPromise, resHPromise]); - proof.pi_c = G1.add(proof.pi_c, resH); - proof.pi_c = G1.add(proof.pi_c, G1.timesFr(proof.pi_a, s)); - proof.pi_c = G1.add(proof.pi_c, G1.timesFr(pib1, r)); - proof.pi_c = G1.add(proof.pi_c, G1.timesFr(zkey.vk_delta_1, Fr.neg(Fr.mul(r, s)))); - let publicSignals = []; - for (let i = 1; i <= zkey.nPublic; i++) { - const b = buffWitness.slice(i * Fr.n8, i * Fr.n8 + Fr.n8); - publicSignals.push(ffjavascript.Scalar.fromRprLE(b)); - } - proof.pi_a = G1.toObject(G1.toAffine(proof.pi_a)); - proof.pi_b = G2.toObject(G2.toAffine(proof.pi_b)); - proof.pi_c = G1.toObject(G1.toAffine(proof.pi_c)); - proof.protocol = "groth16"; - proof.curve = curve.name; - await fdZKey.close(); - await fdWtns.close(); - proof = stringifyBigInts$3(proof); - publicSignals = stringifyBigInts$3(publicSignals); - return { - proof, - publicSignals - }; - } - async function buildABC1(curve, zkey, witness, coeffs, logger) { - const n8 = curve.Fr.n8; - const sCoef = 12 + zkey.n8r; - const nCoef = (coeffs.byteLength - 4) / sCoef; - const outBuffA = new ffjavascript.BigBuffer(zkey.domainSize * n8); - const outBuffB = new ffjavascript.BigBuffer(zkey.domainSize * n8); - const outBuffC = new ffjavascript.BigBuffer(zkey.domainSize * n8); - const outBuf = [outBuffA, outBuffB]; - for (let i = 0; i < nCoef; i++) { - if (logger && i % 1e6 == 0) logger.debug(`QAP AB: ${i}/${nCoef}`); - let buffCoefV, coef; - if (coeffs.buffer) { - const coeffOffset = 4 + i * sCoef; - buffCoefV = new DataView(coeffs.buffer, coeffs.byteOffset + coeffOffset, sCoef); - coef = new Uint8Array(coeffs.buffer, coeffs.byteOffset + coeffOffset + 12, n8); - } else { - const buffCoef = coeffs.slice(4 + i * sCoef, 4 + i * sCoef + sCoef); - buffCoefV = new DataView(buffCoef.buffer); - coef = buffCoef.slice(12, 12 + n8); - } - const m = buffCoefV.getUint32(0, true); - const c = buffCoefV.getUint32(4, true); - const s = buffCoefV.getUint32(8, true); - outBuf[m].set(curve.Fr.add(outBuf[m].slice(c * n8, c * n8 + n8), curve.Fr.mul(coef, witness.slice(s * n8, s * n8 + n8))), c * n8); - if (i % 1e6 == 0 && logger) memUsage(logger); - } - for (let i = 0; i < zkey.domainSize; i++) { - if (logger && i % 1e6 == 0) logger.debug(`QAP C: ${i}/${zkey.domainSize}`); - outBuffC.set(curve.Fr.mul(outBuffA.slice(i * n8, i * n8 + n8), outBuffB.slice(i * n8, i * n8 + n8)), i * n8); - } - return [ - outBuffA, - outBuffB, - outBuffC - ]; - } - async function buildABC(curve, zkey, witness, coeffs, logger) { - let concurrency = curve.tm.concurrency; - const sCoef = 12 + zkey.n8r; - let getUint32; - if (coeffs instanceof ffjavascript.BigBuffer) { - const coeffsDV = []; - const PAGE_LEN = coeffs.buffers[0].length; - for (let i = 0; i < coeffs.buffers.length; i++) coeffsDV.push(new DataView(coeffs.buffers[i].buffer)); - getUint32 = function(pos) { - return coeffsDV[Math.floor(pos / PAGE_LEN)].getUint32(pos % PAGE_LEN, true); - }; - } else { - const coeffsDV = new DataView(coeffs.buffer, coeffs.byteOffset, coeffs.byteLength); - getUint32 = function(pos) { - return coeffsDV.getUint32(pos, true); - }; - } - let elementsPerChunk = Math.floor(zkey.domainSize / concurrency); - console.log("@@@ elementsPerChunk", elementsPerChunk); - while (elementsPerChunk > 2 ** 16) { - concurrency *= 2; - elementsPerChunk = Math.floor(zkey.domainSize / concurrency); - } - console.log("@@@ new elementsPerChunk", elementsPerChunk); - const promises = []; - const cutPoints = []; - for (let i = 0; i < concurrency; i++) cutPoints.push(getCutPoint(Math.floor(i * elementsPerChunk))); - cutPoints.push(coeffs.byteLength); - const chunkSize = 2 ** 26; - for (let s = 0; s < zkey.nVars; s += chunkSize) { - if (logger) logger.debug(`QAP ${s}: ${s}/${zkey.nVars}`); - const ns = Math.min(zkey.nVars - s, chunkSize); - for (let i = 0; i < concurrency; i++) { - let n; - if (i < concurrency - 1) n = elementsPerChunk; - else n = zkey.domainSize - i * elementsPerChunk; - if (n == 0) continue; - const task = []; - task.push({ - cmd: "ALLOCSET", - var: 0, - buff: coeffs.slice(cutPoints[i], cutPoints[i + 1]) - }); - task.push({ - cmd: "ALLOCSET", - var: 1, - buff: witness.slice(s * curve.Fr.n8, (s + ns) * curve.Fr.n8) - }); - task.push({ - cmd: "ALLOC", - var: 2, - len: n * curve.Fr.n8 - }); - task.push({ - cmd: "ALLOC", - var: 3, - len: n * curve.Fr.n8 - }); - task.push({ - cmd: "ALLOC", - var: 4, - len: n * curve.Fr.n8 - }); - task.push({ - cmd: "CALL", - fnName: "qap_buildABC", - params: [ - { var: 0 }, - { val: (cutPoints[i + 1] - cutPoints[i]) / sCoef }, - { var: 1 }, - { var: 2 }, - { var: 3 }, - { var: 4 }, - { val: i * elementsPerChunk }, - { val: n }, - { val: s }, - { val: ns } - ] - }); - task.push({ - cmd: "GET", - out: 0, - var: 2, - len: n * curve.Fr.n8 - }); - task.push({ - cmd: "GET", - out: 1, - var: 3, - len: n * curve.Fr.n8 - }); - task.push({ - cmd: "GET", - out: 2, - var: 4, - len: n * curve.Fr.n8 - }); - promises.push(curve.tm.queueAction(task)); - } - } - let result = await Promise.all(promises); - const nGroups = result.length / concurrency; - if (nGroups > 1) { - const promises2 = []; - for (let i = 0; i < concurrency; i++) { - const task = []; - task.push({ - cmd: "ALLOC", - var: 0, - len: result[i][0].byteLength - }); - task.push({ - cmd: "ALLOC", - var: 1, - len: result[i][0].byteLength - }); - for (let m = 0; m < 3; m++) { - task.push({ - cmd: "SET", - var: 0, - buff: result[i][m] - }); - for (let s = 1; s < nGroups; s++) { - task.push({ - cmd: "SET", - var: 1, - buff: result[s * concurrency + i][m] - }); - task.push({ - cmd: "CALL", - fnName: "qap_batchAdd", - params: [ - { var: 0 }, - { var: 1 }, - { val: result[i][m].length / curve.Fr.n8 }, - { var: 0 } - ] - }); - } - task.push({ - cmd: "GET", - out: m, - var: 0, - len: result[i][m].length - }); - } - promises2.push(curve.tm.queueAction(task)); - } - result = await Promise.all(promises2); - } - const outBuffA = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); - const outBuffB = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); - const outBuffC = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); - let p = 0; - for (let i = 0; i < result.length; i++) { - outBuffA.set(result[i][0], p); - outBuffB.set(result[i][1], p); - outBuffC.set(result[i][2], p); - p += result[i][0].byteLength; - } - return [ - outBuffA, - outBuffB, - outBuffC - ]; - function getCutPoint(v) { - let m = 0; - let n = getUint32(0); - while (m < n) { - var k = Math.floor((n + m) / 2); - const va = getUint32(4 + k * sCoef + 4); - if (va > v) n = k - 1; - else if (va < v) m = k + 1; - else n = k; - } - return 4 + m * sCoef; - } - } - async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { - console.time("buildABC"); - const concurrency = 1; - const sCoef = 12 + zkey.n8r; - let getUint32; - if (coeffs instanceof ffjavascript.BigBuffer) { - const coeffsDV = []; - const PAGE_LEN = coeffs.buffers[0].length; - for (let i = 0; i < coeffs.buffers.length; i++) coeffsDV.push(new DataView(coeffs.buffers[i].buffer)); - getUint32 = function(pos) { - return coeffsDV[Math.floor(pos / PAGE_LEN)].getUint32(pos % PAGE_LEN, true); - }; - } else { - const coeffsDV = new DataView(coeffs.buffer, coeffs.byteOffset, coeffs.byteLength); - getUint32 = function(pos) { - return coeffsDV.getUint32(pos, true); - }; - } - const elementsPerChunk = Math.floor((zkey.domainSize - 1) / concurrency) + 1; - const promises = []; - const cutPoints = []; - for (let i = 0; i < concurrency; i++) cutPoints.push(getCutPoint(Math.floor(i * elementsPerChunk))); - cutPoints.push(coeffs.byteLength); - const chunkSize = elementsPerChunk; - console.log("zkey.domainSize", zkey.domainSize); - console.log("concurrency", concurrency); - console.log("elementsPerChunk", elementsPerChunk); - console.log("chunkSize", chunkSize); - for (let s = 0; s < zkey.nVars; s += chunkSize) { - if (logger) logger.debug(`QAP: ${s}/${zkey.nVars}`); - const ns = Math.min(zkey.nVars - s, chunkSize); - console.log("ns", ns); - for (let i = 0; i < concurrency; i++) { - let n; - if (i < concurrency - 1) n = elementsPerChunk; - else n = zkey.domainSize - i * elementsPerChunk; - if (n === 0) continue; - const task = []; - const coeffsBuff = coeffs.slice(cutPoints[i], cutPoints[i + 1]); - const witnessBuff = witness.slice(s * curve.Fr.n8, (s + ns) * curve.Fr.n8); - task.push({ - cmd: "ALLOCSET", - var: 0, - buff: coeffsBuff - }); - task.push({ - cmd: "ALLOCSET", - var: 1, - buff: witnessBuff - }); - task.push({ - cmd: "ALLOC", - var: 2, - len: n * curve.Fr.n8 - }); - task.push({ - cmd: "ALLOC", - var: 3, - len: n * curve.Fr.n8 - }); - task.push({ - cmd: "ALLOC", - var: 4, - len: n * curve.Fr.n8 - }); - task.push({ - cmd: "CALL", - fnName: "qap_buildABC", - params: [ - { var: 0 }, - { val: (cutPoints[i + 1] - cutPoints[i]) / sCoef }, - { var: 1 }, - { var: 2 }, - { var: 3 }, - { var: 4 }, - { val: i * elementsPerChunk }, - { val: n }, - { val: s }, - { val: ns } - ] - }); - task.push({ - cmd: "GET", - out: 0, - var: 2, - len: n * curve.Fr.n8 - }); - task.push({ - cmd: "GET", - out: 1, - var: 3, - len: n * curve.Fr.n8 - }); - task.push({ - cmd: "GET", - out: 2, - var: 4, - len: n * curve.Fr.n8 - }); - promises.push(curve.tm.queueAction(task, [coeffsBuff.buffer, witnessBuff.buffer])); - } - } - let result = await Promise.all(promises); - console.log("result.length", result.length); - console.log("result", result); - const nGroups = result.length / concurrency; - console.log("nGroups", nGroups); - let result2; - if (nGroups > 1) { - const promises2 = []; - for (let i = 0; i < concurrency; i++) { - const task = []; - task.push({ - cmd: "ALLOC", - var: 0, - len: result[i][0].byteLength - }); - task.push({ - cmd: "ALLOC", - var: 1, - len: result[i][0].byteLength - }); - for (let m = 0; m < 3; m++) { - task.push({ - cmd: "SET", - var: 0, - buff: result[i][m] - }); - for (let s = 1; s < nGroups; s++) { - task.push({ - cmd: "SET", - var: 1, - buff: result[s * concurrency + i][m] - }); - task.push({ - cmd: "CALL", - fnName: "qap_batchAdd", - params: [ - { var: 0 }, - { var: 1 }, - { val: result[i][m].length / curve.Fr.n8 }, - { var: 0 } - ] - }); - } - task.push({ - cmd: "GET", - out: m, - var: 0, - len: result[i][m].length - }); - } - console.log("task.length", task.length); - promises2.push(curve.tm.queueAction(task, result.buffer)); - } - console.log("promises2.length", promises2.length); - result2 = await Promise.all(promises2); - result = result2; - } - const outBuffA = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); - const outBuffB = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); - const outBuffC = new ffjavascript.BigBuffer(zkey.domainSize * curve.Fr.n8); - let p = 0; - for (let i = 0; i < result.length; i++) { - outBuffA.set(result[i][0], p); - outBuffB.set(result[i][1], p); - outBuffC.set(result[i][2], p); - p += result[i][0].byteLength; - } - console.timeEnd("buildABC"); - return [ - outBuffA, - outBuffB, - outBuffC - ]; - function getCutPoint(v) { - let m = 0; - let n = getUint32(0); - while (m < n) { - let k = Math.floor((n + m) / 2); - const va = getUint32(4 + k * sCoef + 4); - if (va > v) n = k - 1; - else if (va < v) m = k + 1; - else n = k; - } - return 4 + m * sCoef; - } - } - async function joinABC(curve, zkey, a, b, c, logger) { - console.time("joinABC"); - const MAX_CHUNK_SIZE = 65536; - const n8 = curve.Fr.n8; - const nElements = Math.floor(a.byteLength / curve.Fr.n8); - const promises = []; - for (let i = 0; i < nElements; i += MAX_CHUNK_SIZE) { - if (logger) logger.debug(`JoinABC: ${i}/${nElements}`); - const n = Math.min(nElements - i, MAX_CHUNK_SIZE); - const task = []; - const aChunk = a.slice(i * n8, (i + n) * n8); - const bChunk = b.slice(i * n8, (i + n) * n8); - const cChunk = c.slice(i * n8, (i + n) * n8); - task.push({ - cmd: "ALLOCSET", - var: 0, - buff: aChunk - }); - task.push({ - cmd: "ALLOCSET", - var: 1, - buff: bChunk - }); - task.push({ - cmd: "ALLOCSET", - var: 2, - buff: cChunk - }); - task.push({ - cmd: "ALLOC", - var: 3, - len: n * n8 - }); - task.push({ - cmd: "CALL", - fnName: "qap_joinABC", - params: [ - { var: 0 }, - { var: 1 }, - { var: 2 }, - { val: n }, - { var: 3 } - ] - }); - task.push({ - cmd: "CALL", - fnName: "frm_batchFromMontgomery", - params: [ - { var: 3 }, - { val: n }, - { var: 3 } - ] - }); - task.push({ - cmd: "GET", - out: 0, - var: 3, - len: n * n8 - }); - promises.push(curve.tm.queueAction(task, [ - aChunk.buffer, - bChunk.buffer, - cChunk.buffer - ])); - } - const result = await Promise.all(promises); - let outBuff; - if (a instanceof ffjavascript.BigBuffer) outBuff = new ffjavascript.BigBuffer(a.byteLength); - else outBuff = new Uint8Array(a.byteLength); - let p = 0; - for (let i = 0; i < result.length; i++) { - outBuff.set(result[i][0], p); - p += result[i][0].byteLength; - } - console.timeEnd("joinABC"); - return outBuff; - } - function memUsage(logger) { - if (!logger || typeof process === "undefined" || !process.memoryUsage) return; - const used = process.memoryUsage(); - logger.debug(" ", "\x1B[0m Heap:\x1B[32m", `${Math.round(used.heapUsed / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m / \x1B[32m", `${Math.round(used.heapTotal / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m RSS:\x1B[32m", `${Math.round(used.rss / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m External:\x1B[32m", `${Math.round(used.external / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m ArrBuffers:\x1B[32m", `${Math.round(used.arrayBuffers / 1024 / 1024 * 100) / 100} MB`.padEnd(12), "\x1B[0m"); - } - function monitorMemoryUsage(logger, interval = 5e3) { - return setInterval(() => { - memUsage(logger); - }, interval); - } - //#endregion - //#region node_modules/fastfile/build/browser/browser.esm.js - function e(e) { - let t = e.initialSize || 1 << 20, n = new s(); - return n.o = e, n.o.data = new Uint8Array(t), n.allocSize = t, n.totalSize = 0, n.readOnly = !1, n.pos = 0, n; - } - function t(e) { - let t = new s(); - return t.o = e, t.allocSize = e.data.byteLength, t.totalSize = e.data.byteLength, t.readOnly = !0, t.pos = 0, t; - } - var r = new Uint8Array(4), i = new DataView(r.buffer), a = new Uint8Array(8), o = new DataView(a.buffer), s = class { - constructor() { - this.pageSize = 16384; - } - _resizeIfNeeded(e) { - if (e > this.allocSize) { - let t = Math.max(this.allocSize + (1 << 20), Math.floor(this.allocSize * 1.1), e), n = new Uint8Array(t); - n.set(this.o.data), this.o.data = n, this.allocSize = t; - } - } - async write(e, t) { - if (t === void 0 && (t = this.pos), this.readOnly) throw Error("Writing a read only file"); - this._resizeIfNeeded(t + e.byteLength), this.o.data.set(e.slice(), t), t + e.byteLength > this.totalSize && (this.totalSize = t + e.byteLength), this.pos = t + e.byteLength; - } - async readToBuffer(e, t, n, r) { - if (r === void 0 && (r = this.pos), this.readOnly && r + n > this.totalSize) throw Error("Reading out of bounds"); - this._resizeIfNeeded(r + n); - let i = new Uint8Array(this.o.data.buffer, this.o.data.byteOffset + r, n); - e.set(i, t), this.pos = r + n; - } - async read(e, t) { - let n = this, r = new Uint8Array(e); - return await n.readToBuffer(r, 0, e, t), r; - } - close() { - this.o.data.byteLength != this.totalSize && (this.o.data = this.o.data.slice(0, this.totalSize)); - } - async discard() {} - async writeULE32(e, t) { - let n = this; - i.setUint32(0, e, !0), await n.write(r, t); - } - async writeUBE32(e, t) { - let n = this; - i.setUint32(0, e, !1), await n.write(r, t); - } - async writeULE64(e, t) { - let n = this; - o.setUint32(0, e & 4294967295, !0), o.setUint32(4, Math.floor(e / 4294967296), !0), await n.write(a, t); - } - async readULE32(e) { - let t = await this.read(4, e); - return new Uint32Array(t.buffer)[0]; - } - async readUBE32(e) { - let t = await this.read(4, e); - return new DataView(t.buffer).getUint32(0, !1); - } - async readULE64(e) { - let t = await this.read(8, e), n = new Uint32Array(t.buffer); - return n[1] * 4294967296 + n[0]; - } - async readString(e) { - let t = this, n = e === void 0 ? t.pos : e; - if (n > this.totalSize) { - if (this.readOnly) throw Error("Reading out of bounds"); - this._resizeIfNeeded(e); - } - let r = new Uint8Array(t.o.data.buffer, n, this.totalSize - n), i = r.findIndex((e) => e === 0), a = i !== -1, o = ""; - return a ? (o = new TextDecoder().decode(r.slice(0, i)), t.pos = n + i + 1) : t.pos = n, o; - } - }, c = 1 << 22; - function l(e) { - let t = e.initialSize || 0, n = new g(); - n.o = e; - let r = t ? Math.floor((t - 1) / c) + 1 : 0; - n.o.data = []; - for (let e = 0; e < r - 1; e++) n.o.data.push(new Uint8Array(c)); - return r && n.o.data.push(new Uint8Array(t - c * (r - 1))), n.totalSize = 0, n.readOnly = !1, n.pos = 0, n; - } - function u(e) { - let t = new g(); - return t.o = e, t.totalSize = (e.data.length - 1) * c + e.data[e.data.length - 1].byteLength, t.readOnly = !0, t.pos = 0, t; - } - var f = new Uint8Array(4), p = new DataView(f.buffer), m = new Uint8Array(8), h = new DataView(m.buffer), g = class { - constructor() { - this.pageSize = 16384; - } - _resizeIfNeeded(e) { - if (e <= this.totalSize) return; - if (this.readOnly) throw Error("Reading out of file bounds"); - let t = Math.floor((e - 1) / c) + 1; - for (let n = Math.max(this.o.data.length - 1, 0); n < t; n++) { - let r = n < t - 1 ? c : e - (t - 1) * c, i = new Uint8Array(r); - n == this.o.data.length - 1 && i.set(this.o.data[n]), this.o.data[n] = i; - } - this.totalSize = e; - } - async write(e, t) { - let n = this; - if (t === void 0 && (t = n.pos), this.readOnly) throw Error("Writing a read only file"); - this._resizeIfNeeded(t + e.byteLength); - let r = Math.floor(t / c), i = t % c, a = e.byteLength; - for (; a > 0;) { - let t = i + a > c ? c - i : a, o = e.slice(e.byteLength - a, e.byteLength - a + t); - new Uint8Array(n.o.data[r].buffer, i, t).set(o), a -= t, r++, i = 0; - } - this.pos = t + e.byteLength; - } - async readToBuffer(e, t, n, r) { - let i = this; - if (r === void 0 && (r = i.pos), this.readOnly && r + n > this.totalSize) throw Error("Reading out of bounds"); - this._resizeIfNeeded(r + n); - let a = Math.floor(r / c), o = r % c, s = n; - for (; s > 0;) { - let r = o + s > c ? c - o : s, l = new Uint8Array(i.o.data[a].buffer, o, r); - e.set(l, t + n - s), s -= r, a++, o = 0; - } - this.pos = r + n; - } - async read(e, t) { - let n = this, r = new Uint8Array(e); - return await n.readToBuffer(r, 0, e, t), r; - } - close() {} - async discard() {} - async writeULE32(e, t) { - let n = this; - p.setUint32(0, e, !0), await n.write(f, t); - } - async writeUBE32(e, t) { - let n = this; - p.setUint32(0, e, !1), await n.write(f, t); - } - async writeULE64(e, t) { - let n = this; - h.setUint32(0, e & 4294967295, !0), h.setUint32(4, Math.floor(e / 4294967296), !0), await n.write(m, t); - } - async readULE32(e) { - let t = await this.read(4, e); - return new Uint32Array(t.buffer)[0]; - } - async readUBE32(e) { - let t = await this.read(4, e); - return new DataView(t.buffer).getUint32(0, !1); - } - async readULE64(e) { - let t = await this.read(8, e), n = new Uint32Array(t.buffer); - return n[1] * 4294967296 + n[0]; - } - async readString(e) { - let t = this, n = e === void 0 ? t.pos : e; - if (n > this.totalSize) { - if (this.readOnly) throw Error("Reading out of bounds"); - this._resizeIfNeeded(e); - } - let r = !1, i = ""; - for (; !r;) { - let e = Math.floor(n / c), a = n % c; - if (t.o.data[e] === void 0) throw Error("ERROR"); - let o = Math.min(2048, t.o.data[e].length - a), s = new Uint8Array(t.o.data[e].buffer, a, o), l = s.findIndex((e) => e === 0); - r = l !== -1, r ? (i += new TextDecoder().decode(s.slice(0, l)), t.pos = e * c + a + l + 1) : (i += new TextDecoder().decode(s), t.pos = e * c + a + s.length), n = t.pos; - } - return i; - } - }, _ = 65536; - function v() { - throw Error("File I/O is not supported in the browser"); - } - function y(e, t) { - return e instanceof Uint8Array ? { - type: "mem", - data: e - } : typeof e == "string" ? { - type: "mem", - initialSize: t || _ - } : e; - } - async function b(e) { - let t = await fetch(e).then((e) => e.arrayBuffer()); - return { - type: "mem", - data: new Uint8Array(t) - }; - } - function x(e, t, n) { - if (e.type === "file" && v(), e.type === "mem") return t(e); - if (e.type === "bigMem") return n(e); - throw Error("Invalid FastFile type: " + e.type); - } - function S(t, n) { - return x(y(t, n), e, l); - } - async function w(e) { - return e = typeof e == "string" ? await b(e) : y(e), x(e, t, u); - } - //#endregion - //#region node_modules/circom_runtime/js/utils.js - function flatArray(a) { - let res = []; - fillArray(res, a); - return res; - function fillArray(res, a) { - if (Array.isArray(a)) for (let i = 0; i < a.length; i++) fillArray(res, a[i]); - else res.push(a); - } - } - function normalize(n, prime) { - let res = BigInt(n) % prime; - if (res < 0) res += prime; - return res; - } - function fnvHash(str) { - const uint64_max = BigInt(2) ** BigInt(64); - let hash = BigInt("0xCBF29CE484222325"); - for (let i = 0; i < str.length; i++) { - hash ^= BigInt(str[i].charCodeAt(0)); - hash *= BigInt(1099511628211); - hash %= uint64_max; - } - let shash = hash.toString(16); - let n = 16 - shash.length; - shash = "0".repeat(n).concat(shash); - return shash; - } - function toArray32(s, size) { - const res = []; - let rem = BigInt(s); - const radix = BigInt(4294967296); - while (rem) { - res.unshift(Number(rem % radix)); - rem = rem / radix; - } - if (size) { - let i = size - res.length; - while (i > 0) { - res.unshift(0); - i--; - } - } - return res; - } - //#endregion - //#region node_modules/circom_runtime/js/witness_calculator.js - async function builder(code, options) { - let instance; - let wc; - let memory; - options = options || {}; - let majorVersion = 1; - let minorVersion = 0; - let patchVersion = 0; - let codeIsWebAssemblyInstance = false; - if (code instanceof WebAssembly.Instance) { - instance = code; - codeIsWebAssemblyInstance = true; - } else { - let memorySize = 32767; - if (options.memorySize) { - memorySize = parseInt(options.memorySize); - if (memorySize < 0) throw new Error("Invalid memory size"); - } - let memoryAllocated = false; - while (!memoryAllocated) try { - memory = new WebAssembly.Memory({ initial: memorySize }); - memoryAllocated = true; - } catch (err) { - if (memorySize <= 1) throw err; - console.warn("Could not allocate " + memorySize * 1024 * 64 + " bytes. This may cause severe instability. Trying with " + memorySize * 1024 * 64 / 2 + " bytes"); - memorySize = Math.floor(memorySize / 2); - } - const wasmModule = await WebAssembly.compile(code); - let errStr = ""; - let msgStr = ""; - instance = await WebAssembly.instantiate(wasmModule, { - env: { "memory": memory }, - runtime: { - printDebug: function(value) { - console.log("printDebug:", value); - }, - exceptionHandler: function(code) { - let err; - if (code === 1) err = "Signal not found. "; - else if (code === 2) err = "Too many signals set. "; - else if (code === 3) err = "Signal already set. "; - else if (code === 4) err = "Assert Failed. "; - else if (code === 5) err = "Not enough memory. "; - else if (code === 6) err = "Input signal array access exceeds the size. "; - else err = "Unknown error. "; - console.error("ERROR: ", code, errStr); - throw new Error(err + errStr); - }, - printErrorMessage: function() { - errStr += getMessage() + "\n"; - }, - writeBufferMessage: function() { - const msg = getMessage(); - if (msg === "\n") { - console.log(msgStr); - msgStr = ""; - } else { - if (msgStr !== "") msgStr += " "; - msgStr += msg; - } - }, - showSharedRWMemory: function() { - const shared_rw_memory_size = instance.exports.getFieldNumLen32(); - const arr = new Uint32Array(shared_rw_memory_size); - for (let j = 0; j < shared_rw_memory_size; j++) arr[shared_rw_memory_size - 1 - j] = instance.exports.readSharedRWMemory(j); - if (majorVersion >= 2 && (minorVersion >= 1 || patchVersion >= 7)) { - if (msgStr !== "") msgStr += " "; - const msg = ffjavascript.Scalar.fromArray(arr, 4294967296).toString(); - msgStr += msg; - } else console.log(ffjavascript.Scalar.fromArray(arr, 4294967296)); - }, - error: function(code, pstr, a, b, c, d) { - let errStr; - if (code === 7) errStr = p2str(pstr) + " " + wc.getFr(b).toString() + " != " + wc.getFr(c).toString() + " " + p2str(d); - else if (code === 9) errStr = p2str(pstr) + " " + wc.getFr(b).toString() + " " + p2str(c); - else if (code === 5 && options.sym) errStr = p2str(pstr) + " " + options.sym.labelIdx2Name[c]; - else errStr = p2str(pstr) + " " + a + " " + b + " " + c + " " + d; - console.log("ERROR: ", code, errStr); - throw new Error(errStr); - }, - log: function(a) { - console.log(wc.getFr(a).toString()); - }, - logGetSignal: function(signal, pVal) { - if (options.logGetSignal) options.logGetSignal(signal, wc.getFr(pVal)); - }, - logSetSignal: function(signal, pVal) { - if (options.logSetSignal) options.logSetSignal(signal, wc.getFr(pVal)); - }, - logStartComponent: function(cIdx) { - if (options.logStartComponent) options.logStartComponent(cIdx); - }, - logFinishComponent: function(cIdx) { - if (options.logFinishComponent) options.logFinishComponent(cIdx); - } - } - }); - } - if (typeof instance.exports.getVersion == "function") majorVersion = instance.exports.getVersion(); - if (typeof instance.exports.getMinorVersion == "function") minorVersion = instance.exports.getMinorVersion(); - if (typeof instance.exports.getPatchVersion == "function") patchVersion = instance.exports.getPatchVersion(); - const sanityCheck = options && (options.sanityCheck || options.logGetSignal || options.logSetSignal || options.logStartComponent || options.logFinishComponent); - if (majorVersion === 2) wc = new WitnessCalculatorCircom2(instance, sanityCheck); - else if (majorVersion === 1) { - if (codeIsWebAssemblyInstance) throw new Error("Loading code from WebAssembly instance is not supported for circom version 1"); - wc = new WitnessCalculatorCircom1(memory, instance, sanityCheck); - } else throw new Error(`Unsupported circom version: ${majorVersion}`); - return wc; - function getMessage() { - let message = ""; - let c = instance.exports.getMessageChar(); - while (c !== 0) { - message += String.fromCharCode(c); - c = instance.exports.getMessageChar(); - } - return message; - } - function p2str(p) { - const i8 = new Uint8Array(memory.buffer); - const bytes = []; - for (let i = 0; i8[p + i] > 0; i++) bytes.push(i8[p + i]); - return String.fromCharCode.apply(null, bytes); - } - } - var WitnessCalculatorCircom1 = class { - constructor(memory, instance, sanityCheck) { - this.memory = memory; - this.i32 = new Uint32Array(memory.buffer); - this.instance = instance; - this.n32 = (this.instance.exports.getFrLen() >> 2) - 2; - const pRawPrime = this.instance.exports.getPRawPrime(); - const arr = new Array(this.n32); - for (let i = 0; i < this.n32; i++) arr[this.n32 - 1 - i] = this.i32[(pRawPrime >> 2) + i]; - this.prime = ffjavascript.Scalar.fromArray(arr, 4294967296); - this.Fr = new ffjavascript.F1Field(this.prime); - this.mask32 = ffjavascript.Scalar.fromString("FFFFFFFF", 16); - this.NVars = this.instance.exports.getNVars(); - this.n64 = Math.floor((this.Fr.bitLength - 1) / 64) + 1; - this.R = this.Fr.e(ffjavascript.Scalar.shiftLeft(1, this.n64 * 64)); - this.RInv = this.Fr.inv(this.R); - this.sanityCheck = sanityCheck; - } - circom_version() { - return 1; - } - async _doCalculateWitness(input, sanityCheck) { - this.instance.exports.init(this.sanityCheck || sanityCheck ? 1 : 0); - const pSigOffset = this.allocInt(); - const pFr = this.allocFr(); - Object.keys(input).forEach((k) => { - const h = fnvHash(k); - const hMSB = parseInt(h.slice(0, 8), 16); - const hLSB = parseInt(h.slice(8, 16), 16); - try { - this.instance.exports.getSignalOffset32(pSigOffset, 0, hMSB, hLSB); - } catch (err) { - throw new Error(`Signal ${k} is not an input of the circuit.`); - } - const sigOffset = this.getInt(pSigOffset); - const fArr = flatArray(input[k]); - for (let i = 0; i < fArr.length; i++) { - this.setFr(pFr, fArr[i]); - this.instance.exports.setSignal(0, 0, sigOffset + i, pFr); - } - }); - } - async calculateWitness(input, sanityCheck) { - const self = this; - const old0 = self.i32[0]; - const w = []; - await self._doCalculateWitness(input, sanityCheck); - for (let i = 0; i < self.NVars; i++) { - const pWitness = self.instance.exports.getPWitness(i); - w.push(self.getFr(pWitness)); - } - self.i32[0] = old0; - return w; - } - async calculateBinWitness(input, sanityCheck) { - const self = this; - const old0 = self.i32[0]; - await self._doCalculateWitness(input, sanityCheck); - const pWitnessBuffer = self.instance.exports.getWitnessBuffer(); - self.i32[0] = old0; - const buff = self.memory.buffer.slice(pWitnessBuffer, pWitnessBuffer + self.NVars * self.n64 * 8); - return new Uint8Array(buff); - } - allocInt() { - const p = this.i32[0]; - this.i32[0] = p + 8; - return p; - } - allocFr() { - const p = this.i32[0]; - this.i32[0] = p + this.n32 * 4 + 8; - return p; - } - getInt(p) { - return this.i32[p >> 2]; - } - setInt(p, v) { - this.i32[p >> 2] = v; - } - getFr(p) { - const self = this; - const idx = p >> 2; - if (self.i32[idx + 1] & 2147483648) { - const arr = new Array(self.n32); - for (let i = 0; i < self.n32; i++) arr[self.n32 - 1 - i] = self.i32[idx + 2 + i]; - const res = self.Fr.e(ffjavascript.Scalar.fromArray(arr, 4294967296)); - if (self.i32[idx + 1] & 1073741824) return fromMontgomery(res); - else return res; - } else if (self.i32[idx] & 2147483648) return self.Fr.e(self.i32[idx] - 4294967296); - else return self.Fr.e(self.i32[idx]); - function fromMontgomery(n) { - return self.Fr.mul(self.RInv, n); - } - } - setFr(p, v) { - const self = this; - v = self.Fr.e(v); - const minShort = self.Fr.neg(self.Fr.e("80000000", 16)); - const maxShort = self.Fr.e("7FFFFFFF", 16); - if (self.Fr.geq(v, minShort) && self.Fr.leq(v, maxShort)) { - let a; - if (self.Fr.geq(v, self.Fr.zero)) a = ffjavascript.Scalar.toNumber(v); - else { - a = ffjavascript.Scalar.toNumber(self.Fr.sub(v, minShort)); - a = a - 2147483648; - a = 4294967296 + a; - } - self.i32[p >> 2] = a; - self.i32[(p >> 2) + 1] = 0; - return; - } - self.i32[p >> 2] = 0; - self.i32[(p >> 2) + 1] = 2147483648; - const arr = ffjavascript.Scalar.toArray(v, 4294967296); - for (let i = 0; i < self.n32; i++) { - const idx = arr.length - 1 - i; - if (idx >= 0) self.i32[(p >> 2) + 2 + i] = arr[idx]; - else self.i32[(p >> 2) + 2 + i] = 0; - } - } - }; - var WitnessCalculatorCircom2 = class { - constructor(instance, sanityCheck) { - this.instance = instance; - this.version = this.instance.exports.getVersion(); - this.n32 = this.instance.exports.getFieldNumLen32(); - this.instance.exports.getRawPrime(); - const arr = new Uint32Array(this.n32); - for (let i = 0; i < this.n32; i++) arr[this.n32 - 1 - i] = this.instance.exports.readSharedRWMemory(i); - this.prime = ffjavascript.Scalar.fromArray(arr, 4294967296); - this.witnessSize = this.instance.exports.getWitnessSize(); - this.sanityCheck = sanityCheck; - } - circom_version() { - return this.instance.exports.getVersion(); - } - async _doCalculateWitness(input, sanityCheck) { - this.instance.exports.init(this.sanityCheck || sanityCheck ? 1 : 0); - const keys = Object.keys(input); - let input_counter = 0; - keys.forEach((k) => { - const h = fnvHash(k); - const hMSB = parseInt(h.slice(0, 8), 16); - const hLSB = parseInt(h.slice(8, 16), 16); - const fArr = flatArray(input[k]); - if (typeof this.instance.exports.getInputSignalSize === "function") { - let signalSize = this.instance.exports.getInputSignalSize(hMSB, hLSB); - if (signalSize < 0) throw new Error(`Signal ${k} not found\n`); - if (fArr.length < signalSize) throw new Error(`Not enough values for input signal ${k}\n`); - if (fArr.length > signalSize) throw new Error(`Too many values for input signal ${k}\n`); - } - for (let i = 0; i < fArr.length; i++) { - const arrFr = toArray32(normalize(fArr[i], this.prime), this.n32); - for (let j = 0; j < this.n32; j++) this.instance.exports.writeSharedRWMemory(j, arrFr[this.n32 - 1 - j]); - try { - this.instance.exports.setInputSignal(hMSB, hLSB, i); - input_counter++; - } catch (err) { - throw new Error(err); - } - } - }); - if (input_counter < this.instance.exports.getInputSize()) throw new Error(`Not all inputs have been set. Only ${input_counter} out of ${this.instance.exports.getInputSize()}`); - } - async calculateWitness(input, sanityCheck) { - const w = []; - await this._doCalculateWitness(input, sanityCheck); - for (let i = 0; i < this.witnessSize; i++) { - this.instance.exports.getWitness(i); - const arr = new Uint32Array(this.n32); - for (let j = 0; j < this.n32; j++) arr[this.n32 - 1 - j] = this.instance.exports.readSharedRWMemory(j); - w.push(ffjavascript.Scalar.fromArray(arr, 4294967296)); - } - return w; - } - async calculateWTNSBin(input, sanityCheck) { - const buff32 = new Uint32Array(this.witnessSize * this.n32 + this.n32 + 11); - const buff = new Uint8Array(buff32.buffer); - await this._doCalculateWitness(input, sanityCheck); - buff[0] = "w".charCodeAt(0); - buff[1] = "t".charCodeAt(0); - buff[2] = "n".charCodeAt(0); - buff[3] = "s".charCodeAt(0); - buff32[1] = 2; - buff32[2] = 2; - buff32[3] = 1; - const n8 = this.n32 * 4; - const idSection1lengthHex = (8 + n8).toString(16); - buff32[4] = parseInt(idSection1lengthHex.slice(0, 8), 16); - buff32[5] = parseInt(idSection1lengthHex.slice(8, 16), 16); - buff32[6] = n8; - this.instance.exports.getRawPrime(); - let pos = 7; - for (let j = 0; j < this.n32; j++) buff32[pos + j] = this.instance.exports.readSharedRWMemory(j); - pos += this.n32; - buff32[pos] = this.witnessSize; - pos++; - buff32[pos] = 2; - pos++; - const idSection2lengthHex = (n8 * this.witnessSize).toString(16); - buff32[pos] = parseInt(idSection2lengthHex.slice(0, 8), 16); - buff32[pos + 1] = parseInt(idSection2lengthHex.slice(8, 16), 16); - pos += 2; - for (let i = 0; i < this.witnessSize; i++) { - this.instance.exports.getWitness(i); - for (let j = 0; j < this.n32; j++) buff32[pos + j] = this.instance.exports.readSharedRWMemory(j); - pos += this.n32; - } - return buff; - } - }; - //#endregion - //#region src/wtns_calculate.js - var { unstringifyBigInts: unstringifyBigInts$10 } = ffjavascript.utils; - async function wtnsCalculate(_input, wasmFileName, wtnsFileName, options) { - const input = unstringifyBigInts$10(_input); - const fdWasm = await w(wasmFileName); - const wasm = await fdWasm.read(fdWasm.totalSize); - await fdWasm.close(); - const wc = await builder(wasm, options); - if (wc.circom_version() === 1) { - const w = await wc.calculateBinWitness(input); - const fdWtns = await _iden3_binfileutils.createBinFile(wtnsFileName, "wtns", 2, 2); - await writeBin(fdWtns, w, wc.prime); - await fdWtns.close(); - } else { - const fdWtns = await S(wtnsFileName); - const w = await wc.calculateWTNSBin(input); - await fdWtns.write(w); - await fdWtns.close(); - } - } - //#endregion - //#region src/groth16_fullprove.js - var { unstringifyBigInts: unstringifyBigInts$9 } = ffjavascript.utils; - async function groth16FullProve(_input, wasmFile, zkeyFileName, logger, wtnsCalcOptions, proverOptions) { - const input = unstringifyBigInts$9(_input); - const wtns = { type: "mem" }; - await wtnsCalculate(input, wasmFile, wtns, wtnsCalcOptions); - return await groth16Prove(zkeyFileName, wtns, logger, proverOptions); - } - //#endregion - //#region src/groth16_verify.js - var { unstringifyBigInts: unstringifyBigInts$8 } = ffjavascript.utils; - async function groth16Verify(_vk_verifier, _publicSignals, _proof, logger) { - const vk_verifier = unstringifyBigInts$8(_vk_verifier); - const proof = unstringifyBigInts$8(_proof); - const publicSignals = unstringifyBigInts$8(_publicSignals); - const curve = await getCurveFromName(vk_verifier.curve); - const IC0 = curve.G1.fromObject(vk_verifier.IC[0]); - const IC = new Uint8Array(curve.G1.F.n8 * 2 * publicSignals.length); - const w = new Uint8Array(curve.Fr.n8 * publicSignals.length); - if (!publicInputsAreValid$2(curve, publicSignals)) { - if (logger) logger.error("Public inputs are not valid."); - return false; - } - for (let i = 0; i < publicSignals.length; i++) { - const buffP = curve.G1.fromObject(vk_verifier.IC[i + 1]); - IC.set(buffP, i * curve.G1.F.n8 * 2); - ffjavascript.Scalar.toRprLE(w, curve.Fr.n8 * i, publicSignals[i], curve.Fr.n8); - } - let cpub = await curve.G1.multiExpAffine(IC, w); - cpub = curve.G1.add(cpub, IC0); - const pi_a = curve.G1.fromObject(proof.pi_a); - const pi_b = curve.G2.fromObject(proof.pi_b); - const pi_c = curve.G1.fromObject(proof.pi_c); - if (!isWellConstructed$1(curve, { - pi_a, - pi_b, - pi_c - })) { - if (logger) logger.error("Proof commitments are not valid."); - return false; - } - const vk_gamma_2 = curve.G2.fromObject(vk_verifier.vk_gamma_2); - const vk_delta_2 = curve.G2.fromObject(vk_verifier.vk_delta_2); - const vk_alpha_1 = curve.G1.fromObject(vk_verifier.vk_alpha_1); - const vk_beta_2 = curve.G2.fromObject(vk_verifier.vk_beta_2); - if (!await curve.pairingEq(curve.G1.neg(pi_a), pi_b, cpub, vk_gamma_2, pi_c, vk_delta_2, vk_alpha_1, vk_beta_2)) { - if (logger) logger.error("Invalid proof"); - return false; - } - if (logger) logger.info("OK!"); - return true; - } - function isWellConstructed$1(curve, proof) { - const G1 = curve.G1; - const G2 = curve.G2; - return G1.isValid(proof.pi_a) && G2.isValid(proof.pi_b) && G1.isValid(proof.pi_c); - } - function checkValueBelongToField$2(curve, value) { - return ffjavascript.Scalar.geq(value, 0) && ffjavascript.Scalar.lt(value, curve.r); - } - function publicInputsAreValid$2(curve, publicInputs) { - for (let i = 0; i < publicInputs.length; i++) if (!checkValueBelongToField$2(curve, publicInputs[i])) return false; - return true; - } - //#endregion - //#region src/groth16_exportsoliditycalldata.js - var { unstringifyBigInts: unstringifyBigInts$7 } = ffjavascript.utils; - function p256$2(n) { - let nstr = n.toString(16); - while (nstr.length < 64) nstr = "0" + nstr; - nstr = `"0x${nstr}"`; - return nstr; - } - async function groth16ExportSolidityCallData(_proof, _pub) { - const proof = unstringifyBigInts$7(_proof); - const pub = unstringifyBigInts$7(_pub); - let inputs = ""; - for (let i = 0; i < pub.length; i++) { - if (inputs != "") inputs = inputs + ","; - inputs = inputs + p256$2(pub[i]); - } - let S; - S = `[${p256$2(proof.pi_a[0])}, ${p256$2(proof.pi_a[1])}],[[${p256$2(proof.pi_b[0][1])}, ${p256$2(proof.pi_b[0][0])}],[${p256$2(proof.pi_b[1][1])}, ${p256$2(proof.pi_b[1][0])}]],[${p256$2(proof.pi_c[0])}, ${p256$2(proof.pi_c[1])}],[${inputs}]`; - return S; - } - //#endregion - //#region src/groth16.js - var groth16_exports = /* @__PURE__ */ __exportAll({ - exportSolidityCallData: () => groth16ExportSolidityCallData, - fullProve: () => groth16FullProve, - prove: () => groth16Prove, - verify: () => groth16Verify - }); - //#endregion - //#region src/keypair.js - function hashToG2(curve, hash) { - const hashV = new DataView(hash.buffer, hash.byteOffset, hash.byteLength); - const seed = []; - for (let i = 0; i < 8; i++) seed[i] = hashV.getUint32(i * 4); - const rng = new ffjavascript.ChaCha(seed); - return curve.G2.fromRng(rng); - } - function getG2sp(curve, persinalization, challenge, g1s, g1sx) { - const h = blake2b.create({ dkLen: 64 }); - const b1 = new Uint8Array([persinalization]); - h.update(b1); - h.update(challenge); - const b3 = curve.G1.toUncompressed(g1s); - h.update(b3); - const b4 = curve.G1.toUncompressed(g1sx); - h.update(b4); - return hashToG2(curve, h.digest()); - } - function calculatePubKey(k, curve, personalization, challengeHash, rng) { - k.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); - k.g1_sx = curve.G1.toAffine(curve.G1.timesFr(k.g1_s, k.prvKey)); - k.g2_sp = curve.G2.toAffine(getG2sp(curve, personalization, challengeHash, k.g1_s, k.g1_sx)); - k.g2_spx = curve.G2.toAffine(curve.G2.timesFr(k.g2_sp, k.prvKey)); - return k; - } - function createPTauKey(curve, challengeHash, rng) { - const key = { - tau: {}, - alpha: {}, - beta: {} - }; - key.tau.prvKey = curve.Fr.fromRng(rng); - key.alpha.prvKey = curve.Fr.fromRng(rng); - key.beta.prvKey = curve.Fr.fromRng(rng); - calculatePubKey(key.tau, curve, 0, challengeHash, rng); - calculatePubKey(key.alpha, curve, 1, challengeHash, rng); - calculatePubKey(key.beta, curve, 2, challengeHash, rng); - return key; - } - //#endregion - //#region src/powersoftau_utils.js - async function writePTauHeader(fd, curve, power, ceremonyPower) { - if (!ceremonyPower) ceremonyPower = power; - await fd.writeULE32(1); - const pHeaderSize = fd.pos; - await fd.writeULE64(0); - await fd.writeULE32(curve.F1.n64 * 8); - const buff = new Uint8Array(curve.F1.n8); - ffjavascript.Scalar.toRprLE(buff, 0, curve.q, curve.F1.n8); - await fd.write(buff); - await fd.writeULE32(power); - await fd.writeULE32(ceremonyPower); - const headerSize = fd.pos - pHeaderSize - 8; - const oldPos = fd.pos; - await fd.writeULE64(headerSize, pHeaderSize); - fd.pos = oldPos; - } - async function readPTauHeader(fd, sections) { - if (!sections[1]) throw new Error(fd.fileName + ": File has no header"); - if (sections[1].length > 1) throw new Error(fd.fileName + ": File has more than one header"); - fd.pos = sections[1][0].p; - const n8 = await fd.readULE32(); - const buff = await fd.read(n8); - const curve = await getCurveFromQ(ffjavascript.Scalar.fromRprLE(buff)); - if (curve.F1.n64 * 8 != n8) throw new Error(fd.fileName + ": Invalid size"); - const power = await fd.readULE32(); - const ceremonyPower = await fd.readULE32(); - if (fd.pos - sections[1][0].p != sections[1][0].size) throw new Error("Invalid PTau header size"); - return { - curve, - power, - ceremonyPower - }; - } - async function readPtauPubKey(fd, curve, montgomery) { - return fromPtauPubKeyRpr(await fd.read(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3), 0, curve, montgomery); - } - function fromPtauPubKeyRpr(buff, pos, curve, montgomery) { - const key = { - tau: {}, - alpha: {}, - beta: {} - }; - key.tau.g1_s = readG1(); - key.tau.g1_sx = readG1(); - key.alpha.g1_s = readG1(); - key.alpha.g1_sx = readG1(); - key.beta.g1_s = readG1(); - key.beta.g1_sx = readG1(); - key.tau.g2_spx = readG2(); - key.alpha.g2_spx = readG2(); - key.beta.g2_spx = readG2(); - return key; - function readG1() { - let p; - if (montgomery) p = curve.G1.fromRprLEM(buff, pos); - else p = curve.G1.fromRprUncompressed(buff, pos); - pos += curve.G1.F.n8 * 2; - return p; - } - function readG2() { - let p; - if (montgomery) p = curve.G2.fromRprLEM(buff, pos); - else p = curve.G2.fromRprUncompressed(buff, pos); - pos += curve.G2.F.n8 * 2; - return p; - } - } - function toPtauPubKeyRpr(buff, pos, curve, key, montgomery) { - writeG1(key.tau.g1_s); - writeG1(key.tau.g1_sx); - writeG1(key.alpha.g1_s); - writeG1(key.alpha.g1_sx); - writeG1(key.beta.g1_s); - writeG1(key.beta.g1_sx); - writeG2(key.tau.g2_spx); - writeG2(key.alpha.g2_spx); - writeG2(key.beta.g2_spx); - async function writeG1(p) { - if (montgomery) curve.G1.toRprLEM(buff, pos, p); - else curve.G1.toRprUncompressed(buff, pos, p); - pos += curve.F1.n8 * 2; - } - async function writeG2(p) { - if (montgomery) curve.G2.toRprLEM(buff, pos, p); - else curve.G2.toRprUncompressed(buff, pos, p); - pos += curve.F2.n8 * 2; - } - return buff; - } - async function writePtauPubKey(fd, curve, key, montgomery) { - const buff = new Uint8Array(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3); - toPtauPubKeyRpr(buff, 0, curve, key, montgomery); - await fd.write(buff); - } - async function readContribution(fd, curve) { - const c = {}; - c.tauG1 = await readG1(); - c.tauG2 = await readG2(); - c.alphaG1 = await readG1(); - c.betaG1 = await readG1(); - c.betaG2 = await readG2(); - c.key = await readPtauPubKey(fd, curve, true); - c.partialHash = await fd.read(216); - c.nextChallenge = await fd.read(64); - c.type = await fd.readULE32(); - const buffV = new Uint8Array(curve.G1.F.n8 * 2 * 6 + curve.G2.F.n8 * 2 * 3); - toPtauPubKeyRpr(buffV, 0, curve, c.key, false); - const responseHasher = fromPartialHash(c.partialHash); - responseHasher.update(buffV); - c.responseHash = responseHasher.digest(); - const paramLength = await fd.readULE32(); - const curPos = fd.pos; - let lastType = 0; - while (fd.pos - curPos < paramLength) { - const buffType = await readDV(1); - if (buffType[0] <= lastType) throw new Error("Parameters in the contribution must be sorted"); - lastType = buffType[0]; - if (buffType[0] == 1) { - const buffStr = await readDV((await readDV(1))[0]); - c.name = new TextDecoder().decode(buffStr); - } else if (buffType[0] == 2) c.numIterationsExp = (await readDV(1))[0]; - else if (buffType[0] == 3) c.beaconHash = await readDV((await readDV(1))[0]); - else throw new Error("Parameter not recognized"); - } - if (fd.pos != curPos + paramLength) throw new Error("Parameters do not match"); - return c; - async function readG1() { - const pBuff = await fd.read(curve.G1.F.n8 * 2); - return curve.G1.fromRprLEM(pBuff); - } - async function readG2() { - const pBuff = await fd.read(curve.G2.F.n8 * 2); - return curve.G2.fromRprLEM(pBuff); - } - async function readDV(n) { - const b = await fd.read(n); - return new Uint8Array(b); - } - } - async function readContributions(fd, curve, sections) { - if (!sections[7]) throw new Error(fd.fileName + ": File has no contributions"); - if (sections[7][0].length > 1) throw new Error(fd.fileName + ": File has more than one contributions section"); - fd.pos = sections[7][0].p; - const nContributions = await fd.readULE32(); - const contributions = []; - for (let i = 0; i < nContributions; i++) { - const c = await readContribution(fd, curve); - c.id = i + 1; - contributions.push(c); - } - if (fd.pos - sections[7][0].p != sections[7][0].size) throw new Error("Invalid contribution section size"); - return contributions; - } - async function writeContribution(fd, curve, contribution) { - const buffG1 = new Uint8Array(curve.F1.n8 * 2); - const buffG2 = new Uint8Array(curve.F2.n8 * 2); - await writeG1(contribution.tauG1); - await writeG2(contribution.tauG2); - await writeG1(contribution.alphaG1); - await writeG1(contribution.betaG1); - await writeG2(contribution.betaG2); - await writePtauPubKey(fd, curve, contribution.key, true); - await fd.write(contribution.partialHash); - await fd.write(contribution.nextChallenge); - await fd.writeULE32(contribution.type || 0); - const params = []; - if (contribution.name) { - params.push(1); - const nameData = new TextEncoder("utf-8").encode(contribution.name.substring(0, 64)); - params.push(nameData.byteLength); - for (let i = 0; i < nameData.byteLength; i++) params.push(nameData[i]); - } - if (contribution.type == 1) { - params.push(2); - params.push(contribution.numIterationsExp); - params.push(3); - params.push(contribution.beaconHash.byteLength); - for (let i = 0; i < contribution.beaconHash.byteLength; i++) params.push(contribution.beaconHash[i]); - } - if (params.length > 0) { - const paramsBuff = new Uint8Array(params); - await fd.writeULE32(paramsBuff.byteLength); - await fd.write(paramsBuff); - } else await fd.writeULE32(0); - async function writeG1(p) { - curve.G1.toRprLEM(buffG1, 0, p); - await fd.write(buffG1); - } - async function writeG2(p) { - curve.G2.toRprLEM(buffG2, 0, p); - await fd.write(buffG2); - } - } - async function writeContributions(fd, curve, contributions) { - await fd.writeULE32(7); - const pContributionsSize = fd.pos; - await fd.writeULE64(0); - await fd.writeULE32(contributions.length); - for (let i = 0; i < contributions.length; i++) await writeContribution(fd, curve, contributions[i]); - const contributionsSize = fd.pos - pContributionsSize - 8; - const oldPos = fd.pos; - await fd.writeULE64(contributionsSize, pContributionsSize); - fd.pos = oldPos; - } - function calculateFirstChallengeHash(curve, power, logger) { - if (logger) logger.debug("Calculating First Challenge Hash"); - const hasher = blake2b.create({ dkLen: 64 }); - const vG1 = new Uint8Array(curve.G1.F.n8 * 2); - const vG2 = new Uint8Array(curve.G2.F.n8 * 2); - curve.G1.toRprUncompressed(vG1, 0, curve.G1.g); - curve.G2.toRprUncompressed(vG2, 0, curve.G2.g); - hasher.update(blake2b.create({ dkLen: 64 }).digest()); - let n; - n = 2 ** power * 2 - 1; - if (logger) logger.debug("Calculate Initial Hash: tauG1"); - hashBlock(vG1, n); - n = 2 ** power; - if (logger) logger.debug("Calculate Initial Hash: tauG2"); - hashBlock(vG2, n); - if (logger) logger.debug("Calculate Initial Hash: alphaTauG1"); - hashBlock(vG1, n); - if (logger) logger.debug("Calculate Initial Hash: betaTauG1"); - hashBlock(vG1, n); - hasher.update(vG2); - return hasher.digest(); - function hashBlock(buff, n) { - const blockSize = 341e3; - const nBlocks = Math.floor(n / blockSize); - const rem = n % blockSize; - const bigBuff = new Uint8Array(blockSize * buff.byteLength); - for (let i = 0; i < blockSize; i++) bigBuff.set(buff, i * buff.byteLength); - for (let i = 0; i < nBlocks; i++) { - hasher.update(bigBuff); - if (logger) logger.debug("Initial hash: " + i * blockSize); - } - for (let i = 0; i < rem; i++) hasher.update(buff); - } - } - async function keyFromBeacon(curve, challengeHash, beaconHash, numIterationsExp) { - return createPTauKey(curve, challengeHash, await rngFromBeaconParams(beaconHash, numIterationsExp)); - } - //#endregion - //#region src/powersoftau_new.js - async function newAccumulator(curve, power, fileName, logger) { - const fd = await _iden3_binfileutils.createBinFile(fileName, "ptau", 1, 7); - await writePTauHeader(fd, curve, power, 0); - const buffG1 = curve.G1.oneAffine; - const buffG2 = curve.G2.oneAffine; - await _iden3_binfileutils.startWriteSection(fd, 2); - const nTauG1 = 2 ** power * 2 - 1; - for (let i = 0; i < nTauG1; i++) { - await fd.write(buffG1); - if (logger && i % 1e5 == 0 && i) logger.log("tauG1: " + i); - } - await _iden3_binfileutils.endWriteSection(fd); - await _iden3_binfileutils.startWriteSection(fd, 3); - const nTauG2 = 2 ** power; - for (let i = 0; i < nTauG2; i++) { - await fd.write(buffG2); - if (logger && i % 1e5 == 0 && i) logger.log("tauG2: " + i); - } - await _iden3_binfileutils.endWriteSection(fd); - await _iden3_binfileutils.startWriteSection(fd, 4); - const nAlfaTauG1 = 2 ** power; - for (let i = 0; i < nAlfaTauG1; i++) { - await fd.write(buffG1); - if (logger && i % 1e5 == 0 && i) logger.log("alphaTauG1: " + i); - } - await _iden3_binfileutils.endWriteSection(fd); - await _iden3_binfileutils.startWriteSection(fd, 5); - const nBetaTauG1 = 2 ** power; - for (let i = 0; i < nBetaTauG1; i++) { - await fd.write(buffG1); - if (logger && i % 1e5 == 0 && i) logger.log("betaTauG1: " + i); - } - await _iden3_binfileutils.endWriteSection(fd); - await _iden3_binfileutils.startWriteSection(fd, 6); - await fd.write(buffG2); - await _iden3_binfileutils.endWriteSection(fd); - await _iden3_binfileutils.startWriteSection(fd, 7); - await fd.writeULE32(0); - await _iden3_binfileutils.endWriteSection(fd); - await fd.close(); - const firstChallengeHash = calculateFirstChallengeHash(curve, power, logger); - if (logger) logger.debug(formatHash(blake2b.create({ dkLen: 64 }).digest(), "Blank Contribution Hash:")); - if (logger) logger.info(formatHash(firstChallengeHash, "First Contribution Hash:")); - return firstChallengeHash; - } - //#endregion - //#region src/powersoftau_export_challenge.js - async function exportChallenge(pTauFilename, challengeFilename, logger) { - const { fd: fdFrom, sections } = await _iden3_binfileutils.readBinFile(pTauFilename, "ptau", 1); - const { curve, power } = await readPTauHeader(fdFrom, sections); - const contributions = await readContributions(fdFrom, curve, sections); - let lastResponseHash, curChallengeHash; - if (contributions.length == 0) { - lastResponseHash = blake2b.create({ dkLen: 64 }).digest(); - curChallengeHash = calculateFirstChallengeHash(curve, power); - } else { - lastResponseHash = contributions[contributions.length - 1].responseHash; - curChallengeHash = contributions[contributions.length - 1].nextChallenge; - } - if (logger) logger.info(formatHash(lastResponseHash, "Last Response Hash: ")); - if (logger) logger.info(formatHash(curChallengeHash, "New Challenge Hash: ")); - const fdTo = await S(challengeFilename); - const toHash = blake2b.create({ dkLen: 64 }); - await fdTo.write(lastResponseHash); - toHash.update(lastResponseHash); - await exportSection(2, "G1", 2 ** power * 2 - 1, "tauG1"); - await exportSection(3, "G2", 2 ** power, "tauG2"); - await exportSection(4, "G1", 2 ** power, "alphaTauG1"); - await exportSection(5, "G1", 2 ** power, "betaTauG1"); - await exportSection(6, "G2", 1, "betaG2"); - await fdFrom.close(); - await fdTo.close(); - const calcCurChallengeHash = toHash.digest(); - if (!hashIsEqual(curChallengeHash, calcCurChallengeHash)) { - if (logger) logger.info(formatHash(calcCurChallengeHash, "Calc Curret Challenge Hash: ")); - if (logger) logger.error("PTau file is corrupted. Calculated new challenge hash does not match with the eclared one"); - throw new Error("PTau file is corrupted. Calculated new challenge hash does not match with the eclared one"); - } - return curChallengeHash; - async function exportSection(sectionId, groupName, nPoints, sectionName) { - const G = curve[groupName]; - const sG = G.F.n8 * 2; - const nPointsChunk = Math.floor((1 << 24) / sG); - await _iden3_binfileutils.startReadUniqueSection(fdFrom, sections, sectionId); - for (let i = 0; i < nPoints; i += nPointsChunk) { - if (logger) logger.debug(`Exporting ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints - i, nPointsChunk); - let buff; - buff = await fdFrom.read(n * sG); - buff = await G.batchLEMtoU(buff); - await fdTo.write(buff); - toHash.update(buff); - } - await _iden3_binfileutils.endReadSection(fdFrom); - } - } - //#endregion - //#region src/powersoftau_import.js - async function importResponse(oldPtauFilename, contributionFilename, newPTauFilename, name, importPoints, logger) { - const noHash = new Uint8Array(64); - for (let i = 0; i < 64; i++) noHash[i] = 255; - const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(oldPtauFilename, "ptau", 1); - const { curve, power } = await readPTauHeader(fdOld, sections); - const contributions = await readContributions(fdOld, curve, sections); - const currentContribution = {}; - if (name) currentContribution.name = name; - const sG1 = curve.F1.n8 * 2; - const scG1 = curve.F1.n8; - const sG2 = curve.F2.n8 * 2; - const scG2 = curve.F2.n8; - const fdResponse = await w(contributionFilename); - if (fdResponse.totalSize != 64 + (2 ** power * 2 - 1) * scG1 + 2 ** power * scG2 + 2 ** power * scG1 + 2 ** power * scG1 + scG2 + sG1 * 6 + sG2 * 3) throw new Error("Size of the contribution is invalid"); - let lastChallengeHash; - if (contributions.length > 0) lastChallengeHash = contributions[contributions.length - 1].nextChallenge; - else lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); - const fdNew = await _iden3_binfileutils.createBinFile(newPTauFilename, "ptau", 1, importPoints ? 7 : 2); - await writePTauHeader(fdNew, curve, power); - const contributionPreviousHash = await fdResponse.read(64); - if (hashIsEqual(noHash, lastChallengeHash)) { - lastChallengeHash = contributionPreviousHash; - contributions[contributions.length - 1].nextChallenge = lastChallengeHash; - } - if (!hashIsEqual(contributionPreviousHash, lastChallengeHash)) throw new Error("Wrong contribution. This contribution is not based on the previous hash"); - const hasherResponse = blake2b.create({ dkLen: 64 }); - hasherResponse.update(contributionPreviousHash); - const startSections = []; - let res; - res = await processSection(fdResponse, fdNew, "G1", 2, 2 ** power * 2 - 1, [1], "tauG1"); - currentContribution.tauG1 = res[0]; - res = await processSection(fdResponse, fdNew, "G2", 3, 2 ** power, [1], "tauG2"); - currentContribution.tauG2 = res[0]; - res = await processSection(fdResponse, fdNew, "G1", 4, 2 ** power, [0], "alphaG1"); - currentContribution.alphaG1 = res[0]; - res = await processSection(fdResponse, fdNew, "G1", 5, 2 ** power, [0], "betaG1"); - currentContribution.betaG1 = res[0]; - res = await processSection(fdResponse, fdNew, "G2", 6, 1, [0], "betaG2"); - currentContribution.betaG2 = res[0]; - currentContribution.partialHash = toPartialHash(hasherResponse); - const buffKey = await fdResponse.read(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3); - currentContribution.key = fromPtauPubKeyRpr(buffKey, 0, curve, false); - hasherResponse.update(new Uint8Array(buffKey)); - const hashResponse = hasherResponse.digest(); - if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); - if (importPoints) { - const nextChallengeHasher = blake2b.create({ dkLen: 64 }); - nextChallengeHasher.update(hashResponse); - await hashSection(nextChallengeHasher, fdNew, "G1", 2, 2 ** power * 2 - 1, "tauG1", logger); - await hashSection(nextChallengeHasher, fdNew, "G2", 3, 2 ** power, "tauG2", logger); - await hashSection(nextChallengeHasher, fdNew, "G1", 4, 2 ** power, "alphaTauG1", logger); - await hashSection(nextChallengeHasher, fdNew, "G1", 5, 2 ** power, "betaTauG1", logger); - await hashSection(nextChallengeHasher, fdNew, "G2", 6, 1, "betaG2", logger); - currentContribution.nextChallenge = nextChallengeHasher.digest(); - if (logger) logger.info(formatHash(currentContribution.nextChallenge, "Next Challenge Hash: ")); - } else currentContribution.nextChallenge = noHash; - contributions.push(currentContribution); - await writeContributions(fdNew, curve, contributions); - await fdResponse.close(); - await fdNew.close(); - await fdOld.close(); - return currentContribution.nextChallenge; - async function processSection(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { - if (importPoints) return await processSectionImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName); - else return await processSectionNoImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName); - } - async function processSectionImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { - const G = curve[groupName]; - const scG = G.F.n8; - const sG = G.F.n8 * 2; - const singularPoints = []; - await _iden3_binfileutils.startWriteSection(fdTo, sectionId); - const nPointsChunk = Math.floor((1 << 24) / sG); - startSections[sectionId] = fdTo.pos; - for (let i = 0; i < nPoints; i += nPointsChunk) { - if (logger) logger.debug(`Importing ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints - i, nPointsChunk); - const buffC = await fdFrom.read(n * scG); - hasherResponse.update(buffC); - const buffLEM = await G.batchCtoLEM(buffC); - await fdTo.write(buffLEM); - for (let j = 0; j < singularPointIndexes.length; j++) { - const sp = singularPointIndexes[j]; - if (sp >= i && sp < i + n) { - const P = G.fromRprLEM(buffLEM, (sp - i) * sG); - singularPoints.push(P); - } - } - } - await _iden3_binfileutils.endWriteSection(fdTo); - return singularPoints; - } - async function processSectionNoImportPoints(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) { - const G = curve[groupName]; - const scG = G.F.n8; - const singularPoints = []; - const nPointsChunk = Math.floor((1 << 24) / scG); - for (let i = 0; i < nPoints; i += nPointsChunk) { - if (logger) logger.debug(`Importing ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints - i, nPointsChunk); - const buffC = await fdFrom.read(n * scG); - hasherResponse.update(buffC); - for (let j = 0; j < singularPointIndexes.length; j++) { - const sp = singularPointIndexes[j]; - if (sp >= i && sp < i + n) { - const P = G.fromRprCompressed(buffC, (sp - i) * scG); - singularPoints.push(P); - } - } - } - return singularPoints; - } - async function hashSection(nextChallengeHasher, fdTo, groupName, sectionId, nPoints, sectionName, logger) { - const G = curve[groupName]; - const sG = G.F.n8 * 2; - const nPointsChunk = Math.floor((1 << 24) / sG); - const oldPos = fdTo.pos; - fdTo.pos = startSections[sectionId]; - for (let i = 0; i < nPoints; i += nPointsChunk) { - if (logger) logger.debug(`Hashing ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints - i, nPointsChunk); - const buffLEM = await fdTo.read(n * sG); - const buffU = await G.batchLEMtoU(buffLEM); - nextChallengeHasher.update(buffU); - } - fdTo.pos = oldPos; - } - } - //#endregion - //#region src/powersoftau_verify.js - var sameRatio$1 = sameRatio$2; - async function verifyContribution(curve, cur, prev, logger) { - let sr; - if (cur.type == 1) { - const beaconKey = await keyFromBeacon(curve, prev.nextChallenge, cur.beaconHash, cur.numIterationsExp); - if (!curve.G1.eq(cur.key.tau.g1_s, beaconKey.tau.g1_s)) { - if (logger) logger.error(`BEACON key (tauG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); - return false; - } - if (!curve.G1.eq(cur.key.tau.g1_sx, beaconKey.tau.g1_sx)) { - if (logger) logger.error(`BEACON key (tauG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); - return false; - } - if (!curve.G2.eq(cur.key.tau.g2_spx, beaconKey.tau.g2_spx)) { - if (logger) logger.error(`BEACON key (tauG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); - return false; - } - if (!curve.G1.eq(cur.key.alpha.g1_s, beaconKey.alpha.g1_s)) { - if (logger) logger.error(`BEACON key (alphaG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); - return false; - } - if (!curve.G1.eq(cur.key.alpha.g1_sx, beaconKey.alpha.g1_sx)) { - if (logger) logger.error(`BEACON key (alphaG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); - return false; - } - if (!curve.G2.eq(cur.key.alpha.g2_spx, beaconKey.alpha.g2_spx)) { - if (logger) logger.error(`BEACON key (alphaG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); - return false; - } - if (!curve.G1.eq(cur.key.beta.g1_s, beaconKey.beta.g1_s)) { - if (logger) logger.error(`BEACON key (betaG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); - return false; - } - if (!curve.G1.eq(cur.key.beta.g1_sx, beaconKey.beta.g1_sx)) { - if (logger) logger.error(`BEACON key (betaG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); - return false; - } - if (!curve.G2.eq(cur.key.beta.g2_spx, beaconKey.beta.g2_spx)) { - if (logger) logger.error(`BEACON key (betaG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}`); - return false; - } - } - cur.key.tau.g2_sp = curve.G2.toAffine(getG2sp(curve, 0, prev.nextChallenge, cur.key.tau.g1_s, cur.key.tau.g1_sx)); - cur.key.alpha.g2_sp = curve.G2.toAffine(getG2sp(curve, 1, prev.nextChallenge, cur.key.alpha.g1_s, cur.key.alpha.g1_sx)); - cur.key.beta.g2_sp = curve.G2.toAffine(getG2sp(curve, 2, prev.nextChallenge, cur.key.beta.g1_s, cur.key.beta.g1_sx)); - sr = await sameRatio$1(curve, cur.key.tau.g1_s, cur.key.tau.g1_sx, cur.key.tau.g2_sp, cur.key.tau.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID key (tau) in challenge #" + cur.id); - return false; - } - sr = await sameRatio$1(curve, cur.key.alpha.g1_s, cur.key.alpha.g1_sx, cur.key.alpha.g2_sp, cur.key.alpha.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID key (alpha) in challenge #" + cur.id); - return false; - } - sr = await sameRatio$1(curve, cur.key.beta.g1_s, cur.key.beta.g1_sx, cur.key.beta.g2_sp, cur.key.beta.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID key (beta) in challenge #" + cur.id); - return false; - } - sr = await sameRatio$1(curve, prev.tauG1, cur.tauG1, cur.key.tau.g2_sp, cur.key.tau.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID tau*G1. challenge #" + cur.id + " It does not follow the previous contribution"); - return false; - } - sr = await sameRatio$1(curve, cur.key.tau.g1_s, cur.key.tau.g1_sx, prev.tauG2, cur.tauG2); - if (sr !== true) { - if (logger) logger.error("INVALID tau*G2. challenge #" + cur.id + " It does not follow the previous contribution"); - return false; - } - sr = await sameRatio$1(curve, prev.alphaG1, cur.alphaG1, cur.key.alpha.g2_sp, cur.key.alpha.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID alpha*G1. challenge #" + cur.id + " It does not follow the previous contribution"); - return false; - } - sr = await sameRatio$1(curve, prev.betaG1, cur.betaG1, cur.key.beta.g2_sp, cur.key.beta.g2_spx); - if (sr !== true) { - if (logger) logger.error("INVALID beta*G1. challenge #" + cur.id + " It does not follow the previous contribution"); - return false; - } - sr = await sameRatio$1(curve, cur.key.beta.g1_s, cur.key.beta.g1_sx, prev.betaG2, cur.betaG2); - if (sr !== true) { - if (logger) logger.error("INVALID beta*G2. challenge #" + cur.id + "It does not follow the previous contribution"); - return false; - } - if (logger) logger.info("Powers Of tau file OK!"); - return true; - } - async function verify(tauFilename, logger) { - let sr; - const { fd, sections } = await _iden3_binfileutils.readBinFile(tauFilename, "ptau", 1); - const { curve, power, ceremonyPower } = await readPTauHeader(fd, sections); - const contrs = await readContributions(fd, curve, sections); - if (logger) logger.debug("power: 2**" + power); - if (logger) logger.debug("Computing initial contribution hash"); - const initialContribution = { - tauG1: curve.G1.g, - tauG2: curve.G2.g, - alphaG1: curve.G1.g, - betaG1: curve.G1.g, - betaG2: curve.G2.g, - nextChallenge: calculateFirstChallengeHash(curve, ceremonyPower, logger), - responseHash: blake2b.create({ dkLen: 64 }).digest() - }; - if (contrs.length == 0) { - if (logger) logger.error("This file has no contribution! It cannot be used in production"); - return false; - } - let prevContr; - if (contrs.length > 1) prevContr = contrs[contrs.length - 2]; - else prevContr = initialContribution; - const curContr = contrs[contrs.length - 1]; - if (logger) logger.debug("Validating contribution #" + contrs[contrs.length - 1].id); - if (!await verifyContribution(curve, curContr, prevContr, logger)) return false; - const nextContributionHasher = blake2b.create({ dkLen: 64 }); - nextContributionHasher.update(curContr.responseHash); - if (logger) logger.debug("Verifying powers in tau*G1 section"); - const rTau1 = await processSection(2, "G1", "tauG1", 2 ** power * 2 - 1, [0, 1], logger); - sr = await sameRatio$1(curve, rTau1.R1, rTau1.R2, curve.G2.g, curContr.tauG2); - if (sr !== true) { - if (logger) logger.error("tauG1 section. Powers do not match"); - return false; - } - if (!curve.G1.eq(curve.G1.g, rTau1.singularPoints[0])) { - if (logger) logger.error("First element of tau*G1 section must be the generator"); - return false; - } - if (!curve.G1.eq(curContr.tauG1, rTau1.singularPoints[1])) { - if (logger) logger.error("Second element of tau*G1 section does not match the one in the contribution section"); - return false; - } - if (logger) logger.debug("Verifying powers in tau*G2 section"); - const rTau2 = await processSection(3, "G2", "tauG2", 2 ** power, [0, 1], logger); - sr = await sameRatio$1(curve, curve.G1.g, curContr.tauG1, rTau2.R1, rTau2.R2); - if (sr !== true) { - if (logger) logger.error("tauG2 section. Powers do not match"); - return false; - } - if (!curve.G2.eq(curve.G2.g, rTau2.singularPoints[0])) { - if (logger) logger.error("First element of tau*G2 section must be the generator"); - return false; - } - if (!curve.G2.eq(curContr.tauG2, rTau2.singularPoints[1])) { - if (logger) logger.error("Second element of tau*G2 section does not match the one in the contribution section"); - return false; - } - if (logger) logger.debug("Verifying powers in alpha*tau*G1 section"); - const rAlphaTauG1 = await processSection(4, "G1", "alphatauG1", 2 ** power, [0], logger); - sr = await sameRatio$1(curve, rAlphaTauG1.R1, rAlphaTauG1.R2, curve.G2.g, curContr.tauG2); - if (sr !== true) { - if (logger) logger.error("alphaTauG1 section. Powers do not match"); - return false; - } - if (!curve.G1.eq(curContr.alphaG1, rAlphaTauG1.singularPoints[0])) { - if (logger) logger.error("First element of alpha*tau*G1 section (alpha*G1) does not match the one in the contribution section"); - return false; - } - if (logger) logger.debug("Verifying powers in beta*tau*G1 section"); - const rBetaTauG1 = await processSection(5, "G1", "betatauG1", 2 ** power, [0], logger); - sr = await sameRatio$1(curve, rBetaTauG1.R1, rBetaTauG1.R2, curve.G2.g, curContr.tauG2); - if (sr !== true) { - if (logger) logger.error("betaTauG1 section. Powers do not match"); - return false; - } - if (!curve.G1.eq(curContr.betaG1, rBetaTauG1.singularPoints[0])) { - if (logger) logger.error("First element of beta*tau*G1 section (beta*G1) does not match the one in the contribution section"); - return false; - } - const betaG2 = await processSectionBetaG2(logger); - if (!curve.G2.eq(curContr.betaG2, betaG2)) { - if (logger) logger.error("betaG2 element in betaG2 section does not match the one in the contribution section"); - return false; - } - const nextContributionHash = nextContributionHasher.digest(); - if (power == ceremonyPower) { - if (!hashIsEqual(nextContributionHash, curContr.nextChallenge)) { - if (logger) logger.error("Hash of the values does not match the next challenge of the last contributor in the contributions section"); - return false; - } - } - if (logger) logger.info(formatHash(nextContributionHash, "Next challenge hash: ")); - printContribution(curContr, prevContr); - for (let i = contrs.length - 2; i >= 0; i--) { - const curContr = contrs[i]; - const prevContr = i > 0 ? contrs[i - 1] : initialContribution; - if (!await verifyContribution(curve, curContr, prevContr, logger)) return false; - printContribution(curContr, prevContr, logger); - } - if (logger) logger.info("-----------------------------------------------------"); - if (!sections[12] || !sections[13] || !sections[14] || !sections[15]) { - if (logger) logger.warn("this file does not contain phase2 precalculated values. Please run: \n snarkjs \"powersoftau preparephase2\" to prepare this file to be used in the phase2 ceremony."); - } else { - let res; - res = await verifyLagrangeEvaluations("G1", 2, 12, "tauG1", logger); - if (!res) return false; - res = await verifyLagrangeEvaluations("G2", 3, 13, "tauG2", logger); - if (!res) return false; - res = await verifyLagrangeEvaluations("G1", 4, 14, "alphaTauG1", logger); - if (!res) return false; - res = await verifyLagrangeEvaluations("G1", 5, 15, "betaTauG1", logger); - if (!res) return false; - } - await fd.close(); - if (logger) logger.info("Powers of Tau Ok!"); - return true; - function printContribution(curContr, prevContr) { - if (!logger) return; - logger.info("-----------------------------------------------------"); - logger.info(`Contribution #${curContr.id}: ${curContr.name || ""}`); - logger.info(formatHash(curContr.nextChallenge, "Next Challenge: ")); - const buffV = new Uint8Array(curve.G1.F.n8 * 2 * 6 + curve.G2.F.n8 * 2 * 3); - toPtauPubKeyRpr(buffV, 0, curve, curContr.key, false); - const responseHasher = fromPartialHash(curContr.partialHash); - responseHasher.update(buffV); - const responseHash = responseHasher.digest(); - logger.info(formatHash(responseHash, "Response Hash:")); - logger.info(formatHash(prevContr.nextChallenge, "Response Hash:")); - if (curContr.type == 1) { - logger.info(`Beacon generator: ${byteArray2hex(curContr.beaconHash)}`); - logger.info(`Beacon iterations Exp: ${curContr.numIterationsExp}`); - } - } - async function processSectionBetaG2(logger) { - const G = curve.G2; - const sG = G.F.n8 * 2; - const buffUv = new Uint8Array(sG); - if (!sections[6]) { - logger.error("File has no BetaG2 section"); - throw new Error("File has no BetaG2 section"); - } - if (sections[6].length > 1) { - logger.error("File has no BetaG2 section"); - throw new Error("File has more than one GetaG2 section"); - } - fd.pos = sections[6][0].p; - const buff = await fd.read(sG); - const P = G.fromRprLEM(buff); - G.toRprUncompressed(buffUv, 0, P); - nextContributionHasher.update(buffUv); - return P; - } - async function processSection(idSection, groupName, sectionName, nPoints, singularPointIndexes, logger) { - const MAX_CHUNK_SIZE = 65536; - const G = curve[groupName]; - const sG = G.F.n8 * 2; - await _iden3_binfileutils.startReadUniqueSection(fd, sections, idSection); - const singularPoints = []; - let R1 = G.zero; - let R2 = G.zero; - let lastBase = G.zero; - for (let i = 0; i < nPoints; i += MAX_CHUNK_SIZE) { - if (logger) logger.debug(`points relations: ${sectionName}: ${i}/${nPoints} `); - const n = Math.min(nPoints - i, MAX_CHUNK_SIZE); - const bases = await fd.read(n * sG); - const basesU = await G.batchLEMtoU(bases); - nextContributionHasher.update(basesU); - const scalars = getRandomBytes(4 * (n - 1)); - if (i > 0) { - const firstBase = G.fromRprLEM(bases, 0); - const r = readUInt32BE(getRandomBytes(4), 0); - R1 = G.add(R1, G.timesScalar(lastBase, r)); - R2 = G.add(R2, G.timesScalar(firstBase, r)); - } - const r1 = await G.multiExpAffine(bases.slice(0, (n - 1) * sG), scalars); - const r2 = await G.multiExpAffine(bases.slice(sG), scalars); - R1 = G.add(R1, r1); - R2 = G.add(R2, r2); - lastBase = G.fromRprLEM(bases, (n - 1) * sG); - for (let j = 0; j < singularPointIndexes.length; j++) { - const sp = singularPointIndexes[j]; - if (sp >= i && sp < i + n) { - const P = G.fromRprLEM(bases, (sp - i) * sG); - singularPoints.push(P); - } - } - } - await _iden3_binfileutils.endReadSection(fd); - return { - R1, - R2, - singularPoints - }; - } - async function verifyLagrangeEvaluations(gName, tauSection, lagrangeSection, sectionName, logger) { - if (logger) logger.debug(`Verifying phase2 calculated values ${sectionName}...`); - const G = curve[gName]; - const sG = G.F.n8 * 2; - const seed = new Array(8); - for (let i = 0; i < 8; i++) seed[i] = readUInt32BE(getRandomBytes(4), 0); - for (let p = 0; p <= power; p++) if (!await verifyPower(p)) return false; - if (tauSection == 2) { - if (!await verifyPower(power + 1)) return false; - } - return true; - async function verifyPower(p) { - if (logger) logger.debug(`Power ${p}...`); - const n8r = curve.Fr.n8; - const nPoints = 2 ** p; - let buff_r = new Uint32Array(nPoints); - let buffG; - let rng = new ffjavascript.ChaCha(seed); - if (logger) logger.debug(`Creating random numbers Powers${p}...`); - for (let i = 0; i < nPoints; i++) if (p == power + 1 && i == nPoints - 1) buff_r[i] = 0; - else buff_r[i] = rng.nextU32(); - buff_r = new Uint8Array(buff_r.buffer, buff_r.byteOffset, buff_r.byteLength); - if (logger) logger.debug(`reading points Powers${p}...`); - await _iden3_binfileutils.startReadUniqueSection(fd, sections, tauSection); - buffG = new ffjavascript.BigBuffer(nPoints * sG); - if (p == power + 1) { - await fd.readToBuffer(buffG, 0, (nPoints - 1) * sG); - buffG.set(curve.G1.zeroAffine, (nPoints - 1) * sG); - } else await fd.readToBuffer(buffG, 0, nPoints * sG); - await _iden3_binfileutils.endReadSection(fd, true); - const resTau = await G.multiExpAffine(buffG, buff_r, logger, sectionName + "_" + p); - buff_r = new ffjavascript.BigBuffer(nPoints * n8r); - rng = new ffjavascript.ChaCha(seed); - const buff4 = new Uint8Array(4); - const buff4V = new DataView(buff4.buffer); - if (logger) logger.debug(`Creating random numbers Powers${p}...`); - for (let i = 0; i < nPoints; i++) if (i != nPoints - 1 || p != power + 1) { - buff4V.setUint32(0, rng.nextU32(), true); - buff_r.set(buff4, i * n8r); - } - if (logger) logger.debug(`batchToMontgomery ${p}...`); - buff_r = await curve.Fr.batchToMontgomery(buff_r); - if (logger) logger.debug(`fft ${p}...`); - buff_r = await curve.Fr.fft(buff_r); - if (logger) logger.debug(`batchFromMontgomery ${p}...`); - buff_r = await curve.Fr.batchFromMontgomery(buff_r); - if (logger) logger.debug(`reading points Lagrange${p}...`); - await _iden3_binfileutils.startReadUniqueSection(fd, sections, lagrangeSection); - fd.pos += sG * (2 ** p - 1); - await fd.readToBuffer(buffG, 0, nPoints * sG); - await _iden3_binfileutils.endReadSection(fd, true); - const resLagrange = await G.multiExpAffine(buffG, buff_r, logger, sectionName + "_" + p + "_transformed"); - if (!G.eq(resTau, resLagrange)) { - if (logger) logger.error("Phase2 caclutation does not match with powers of tau"); - return false; - } - return true; - } - } - } - //#endregion - //#region src/mpc_applykey.js - async function applyKeyToSection(fdOld, sections, fdNew, idSection, curve, groupName, first, inc, sectionName, logger) { - const MAX_CHUNK_SIZE = 65536; - const G = curve[groupName]; - const sG = G.F.n8 * 2; - const nPoints = sections[idSection][0].size / sG; - await _iden3_binfileutils.startReadUniqueSection(fdOld, sections, idSection); - await _iden3_binfileutils.startWriteSection(fdNew, idSection); - let t = first; - for (let i = 0; i < nPoints; i += MAX_CHUNK_SIZE) { - if (logger) logger.debug(`Applying key: ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints - i, MAX_CHUNK_SIZE); - let buff; - buff = await fdOld.read(n * sG); - buff = await G.batchApplyKey(buff, t, inc); - await fdNew.write(buff); - t = curve.Fr.mul(t, curve.Fr.exp(inc, n)); - } - await _iden3_binfileutils.endWriteSection(fdNew); - await _iden3_binfileutils.endReadSection(fdOld); - } - async function applyKeyToChallengeSection(fdOld, fdNew, responseHasher, curve, groupName, nPoints, first, inc, formatOut, sectionName, logger) { - const G = curve[groupName]; - const sG = G.F.n8 * 2; - const chunkSize = Math.floor((1 << 20) / sG); - let t = first; - for (let i = 0; i < nPoints; i += chunkSize) { - if (logger) logger.debug(`Applying key ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints - i, chunkSize); - const buffInU = await fdOld.read(n * sG); - const buffInLEM = await G.batchUtoLEM(buffInU); - const buffOutLEM = await G.batchApplyKey(buffInLEM, t, inc); - let buffOut; - if (formatOut == "COMPRESSED") buffOut = await G.batchLEMtoC(buffOutLEM); - else buffOut = await G.batchLEMtoU(buffOutLEM); - if (responseHasher) responseHasher.update(buffOut); - await fdNew.write(buffOut); - t = curve.Fr.mul(t, curve.Fr.exp(inc, n)); - } - } - //#endregion - //#region src/powersoftau_challenge_contribute.js - async function challengeContribute(curve, challengeFilename, responseFileName, entropy, logger) { - const fdFrom = await w(challengeFilename); - const sG1 = curve.F1.n64 * 8 * 2; - const sG2 = curve.F2.n64 * 8 * 2; - const domainSize = (fdFrom.totalSize + sG1 - 64 - sG2) / (4 * sG1 + sG2); - let e = domainSize; - let power = 0; - while (e > 1) { - e = e / 2; - power += 1; - } - if (2 ** power != domainSize) throw new Error("Invalid file size"); - if (logger) logger.debug("Power to tau size: " + power); - const rng = await getRandomRng(entropy); - const fdTo = await S(responseFileName); - const challengeHasher = blake2b.create({ dkLen: 64 }); - for (let i = 0; i < fdFrom.totalSize; i += fdFrom.pageSize) { - if (logger) logger.debug(`Hashing challenge ${i}/${fdFrom.totalSize}`); - const s = Math.min(fdFrom.totalSize - i, fdFrom.pageSize); - const buff = await fdFrom.read(s); - challengeHasher.update(buff); - } - const claimedHash = await fdFrom.read(64, 0); - if (logger) logger.info(formatHash(claimedHash, "Claimed Previous Response Hash: ")); - const challengeHash = challengeHasher.digest(); - if (logger) logger.info(formatHash(challengeHash, "Current Challenge Hash: ")); - const key = createPTauKey(curve, challengeHash, rng); - if (logger) [ - "tau", - "alpha", - "beta" - ].forEach((k) => { - logger.debug(k + ".g1_s: " + curve.G1.toString(key[k].g1_s, 16)); - logger.debug(k + ".g1_sx: " + curve.G1.toString(key[k].g1_sx, 16)); - logger.debug(k + ".g2_sp: " + curve.G2.toString(key[k].g2_sp, 16)); - logger.debug(k + ".g2_spx: " + curve.G2.toString(key[k].g2_spx, 16)); - logger.debug(""); - }); - const responseHasher = blake2b.create({ dkLen: 64 }); - await fdTo.write(challengeHash); - responseHasher.update(challengeHash); - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", 2 ** power * 2 - 1, curve.Fr.one, key.tau.prvKey, "COMPRESSED", "tauG1", logger); - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G2", 2 ** power, curve.Fr.one, key.tau.prvKey, "COMPRESSED", "tauG2", logger); - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", 2 ** power, key.alpha.prvKey, key.tau.prvKey, "COMPRESSED", "alphaTauG1", logger); - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", 2 ** power, key.beta.prvKey, key.tau.prvKey, "COMPRESSED", "betaTauG1", logger); - await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G2", 1, key.beta.prvKey, key.tau.prvKey, "COMPRESSED", "betaTauG2", logger); - const buffKey = new Uint8Array(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3); - toPtauPubKeyRpr(buffKey, 0, curve, key, false); - await fdTo.write(buffKey); - responseHasher.update(buffKey); - const responseHash = responseHasher.digest(); - if (logger) logger.info(formatHash(responseHash, "Contribution Response Hash: ")); - await fdTo.close(); - await fdFrom.close(); - } - //#endregion - //#region src/powersoftau_beacon.js - async function beacon$1(oldPtauFilename, newPTauFilename, name, beaconHashStr, numIterationsExp, logger) { - const beaconHash = hex2ByteArray(beaconHashStr); - if (beaconHash.byteLength == 0 || beaconHash.byteLength * 2 != beaconHashStr.length) { - if (logger) logger.error("Invalid Beacon Hash. (It must be a valid hexadecimal sequence)"); - return false; - } - if (beaconHash.length >= 256) { - if (logger) logger.error("Maximum length of beacon hash is 255 bytes"); - return false; - } - numIterationsExp = parseInt(numIterationsExp); - if (numIterationsExp < 10 || numIterationsExp > 63) { - if (logger) logger.error("Invalid numIterationsExp. (Must be between 10 and 63)"); - return false; - } - const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(oldPtauFilename, "ptau", 1); - const { curve, power, ceremonyPower } = await readPTauHeader(fdOld, sections); - if (power != ceremonyPower) { - if (logger) logger.error("This file has been reduced. You cannot contribute into a reduced file."); - return false; - } - if (sections[12]) { - if (logger) logger.warn("Contributing into a file that has phase2 calculated. You will have to prepare phase2 again."); - } - const contributions = await readContributions(fdOld, curve, sections); - const curContribution = { - name, - type: 1, - numIterationsExp, - beaconHash - }; - let lastChallengeHash; - if (contributions.length > 0) lastChallengeHash = contributions[contributions.length - 1].nextChallenge; - else lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); - curContribution.key = await keyFromBeacon(curve, lastChallengeHash, beaconHash, numIterationsExp); - const responseHasher = blake2b.create({ dkLen: 64 }); - responseHasher.update(lastChallengeHash); - const fdNew = await _iden3_binfileutils.createBinFile(newPTauFilename, "ptau", 1, 7); - await writePTauHeader(fdNew, curve, power); - const startSections = []; - let firstPoints; - firstPoints = await processSection(2, "G1", 2 ** power * 2 - 1, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG1", logger); - curContribution.tauG1 = firstPoints[1]; - firstPoints = await processSection(3, "G2", 2 ** power, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG2", logger); - curContribution.tauG2 = firstPoints[1]; - firstPoints = await processSection(4, "G1", 2 ** power, curContribution.key.alpha.prvKey, curContribution.key.tau.prvKey, "alphaTauG1", logger); - curContribution.alphaG1 = firstPoints[0]; - firstPoints = await processSection(5, "G1", 2 ** power, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG1", logger); - curContribution.betaG1 = firstPoints[0]; - firstPoints = await processSection(6, "G2", 1, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG2", logger); - curContribution.betaG2 = firstPoints[0]; - curContribution.partialHash = toPartialHash(responseHasher); - const buffKey = new Uint8Array(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3); - toPtauPubKeyRpr(buffKey, 0, curve, curContribution.key, false); - responseHasher.update(new Uint8Array(buffKey)); - const hashResponse = responseHasher.digest(); - if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); - const nextChallengeHasher = blake2b.create({ dkLen: 64 }); - nextChallengeHasher.update(hashResponse); - await hashSection(fdNew, "G1", 2, 2 ** power * 2 - 1, "tauG1", logger); - await hashSection(fdNew, "G2", 3, 2 ** power, "tauG2", logger); - await hashSection(fdNew, "G1", 4, 2 ** power, "alphaTauG1", logger); - await hashSection(fdNew, "G1", 5, 2 ** power, "betaTauG1", logger); - await hashSection(fdNew, "G2", 6, 1, "betaG2", logger); - curContribution.nextChallenge = nextChallengeHasher.digest(); - if (logger) logger.info(formatHash(curContribution.nextChallenge, "Next Challenge Hash: ")); - contributions.push(curContribution); - await writeContributions(fdNew, curve, contributions); - await fdOld.close(); - await fdNew.close(); - return hashResponse; - async function processSection(sectionId, groupName, NPoints, first, inc, sectionName, logger) { - const res = []; - fdOld.pos = sections[sectionId][0].p; - await _iden3_binfileutils.startWriteSection(fdNew, sectionId); - startSections[sectionId] = fdNew.pos; - const G = curve[groupName]; - const sG = G.F.n8 * 2; - const chunkSize = Math.floor((1 << 20) / sG); - let t = first; - for (let i = 0; i < NPoints; i += chunkSize) { - if (logger) logger.debug(`applying key${sectionName}: ${i}/${NPoints}`); - const n = Math.min(NPoints - i, chunkSize); - const buffIn = await fdOld.read(n * sG); - const buffOutLEM = await G.batchApplyKey(buffIn, t, inc); - const promiseWrite = fdNew.write(buffOutLEM); - const buffOutC = await G.batchLEMtoC(buffOutLEM); - responseHasher.update(buffOutC); - await promiseWrite; - if (i == 0) for (let j = 0; j < Math.min(2, NPoints); j++) res.push(G.fromRprLEM(buffOutLEM, j * sG)); - t = curve.Fr.mul(t, curve.Fr.exp(inc, n)); - } - await _iden3_binfileutils.endWriteSection(fdNew); - return res; - } - async function hashSection(fdTo, groupName, sectionId, nPoints, sectionName, logger) { - const G = curve[groupName]; - const sG = G.F.n8 * 2; - const nPointsChunk = Math.floor((1 << 24) / sG); - const oldPos = fdTo.pos; - fdTo.pos = startSections[sectionId]; - for (let i = 0; i < nPoints; i += nPointsChunk) { - if (logger) logger.debug(`Hashing ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints - i, nPointsChunk); - const buffLEM = await fdTo.read(n * sG); - const buffU = await G.batchLEMtoU(buffLEM); - nextChallengeHasher.update(buffU); - } - fdTo.pos = oldPos; - } - } - //#endregion - //#region src/powersoftau_contribute.js - async function contribute(oldPtauFilename, newPTauFilename, name, entropy, logger) { - const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(oldPtauFilename, "ptau", 1); - const { curve, power, ceremonyPower } = await readPTauHeader(fdOld, sections); - if (power != ceremonyPower) { - if (logger) logger.error("This file has been reduced. You cannot contribute into a reduced file."); - throw new Error("This file has been reduced. You cannot contribute into a reduced file."); - } - if (sections[12]) { - if (logger) logger.warn("WARNING: Contributing into a file that has phase2 calculated. You will have to prepare phase2 again."); - } - const contributions = await readContributions(fdOld, curve, sections); - const curContribution = { - name, - type: 0 - }; - let lastChallengeHash; - const rng = await getRandomRng(entropy); - if (contributions.length > 0) lastChallengeHash = contributions[contributions.length - 1].nextChallenge; - else lastChallengeHash = calculateFirstChallengeHash(curve, power, logger); - curContribution.key = createPTauKey(curve, lastChallengeHash, rng); - const responseHasher = blake2b.create({ dkLen: 64 }); - responseHasher.update(lastChallengeHash); - const fdNew = await _iden3_binfileutils.createBinFile(newPTauFilename, "ptau", 1, 7); - await writePTauHeader(fdNew, curve, power); - const startSections = []; - let firstPoints; - firstPoints = await processSection(2, "G1", 2 ** power * 2 - 1, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG1"); - curContribution.tauG1 = firstPoints[1]; - firstPoints = await processSection(3, "G2", 2 ** power, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG2"); - curContribution.tauG2 = firstPoints[1]; - firstPoints = await processSection(4, "G1", 2 ** power, curContribution.key.alpha.prvKey, curContribution.key.tau.prvKey, "alphaTauG1"); - curContribution.alphaG1 = firstPoints[0]; - firstPoints = await processSection(5, "G1", 2 ** power, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG1"); - curContribution.betaG1 = firstPoints[0]; - firstPoints = await processSection(6, "G2", 1, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG2"); - curContribution.betaG2 = firstPoints[0]; - curContribution.partialHash = toPartialHash(responseHasher); - const buffKey = new Uint8Array(curve.F1.n8 * 2 * 6 + curve.F2.n8 * 2 * 3); - toPtauPubKeyRpr(buffKey, 0, curve, curContribution.key, false); - responseHasher.update(new Uint8Array(buffKey)); - const hashResponse = responseHasher.digest(); - if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: ")); - const nextChallengeHasher = blake2b.create({ dkLen: 64 }); - nextChallengeHasher.update(hashResponse); - await hashSection(fdNew, "G1", 2, 2 ** power * 2 - 1, "tauG1"); - await hashSection(fdNew, "G2", 3, 2 ** power, "tauG2"); - await hashSection(fdNew, "G1", 4, 2 ** power, "alphaTauG1"); - await hashSection(fdNew, "G1", 5, 2 ** power, "betaTauG1"); - await hashSection(fdNew, "G2", 6, 1, "betaG2"); - curContribution.nextChallenge = nextChallengeHasher.digest(); - if (logger) logger.info(formatHash(curContribution.nextChallenge, "Next Challenge Hash: ")); - contributions.push(curContribution); - await writeContributions(fdNew, curve, contributions); - await fdOld.close(); - await fdNew.close(); - return hashResponse; - async function processSection(sectionId, groupName, NPoints, first, inc, sectionName) { - const res = []; - fdOld.pos = sections[sectionId][0].p; - await _iden3_binfileutils.startWriteSection(fdNew, sectionId); - startSections[sectionId] = fdNew.pos; - const G = curve[groupName]; - const sG = G.F.n8 * 2; - const chunkSize = Math.floor((1 << 20) / sG); - let t = first; - for (let i = 0; i < NPoints; i += chunkSize) { - if (logger) logger.debug(`processing: ${sectionName}: ${i}/${NPoints}`); - const n = Math.min(NPoints - i, chunkSize); - const buffIn = await fdOld.read(n * sG); - const buffOutLEM = await G.batchApplyKey(buffIn, t, inc); - const promiseWrite = fdNew.write(buffOutLEM); - const buffOutC = await G.batchLEMtoC(buffOutLEM); - responseHasher.update(buffOutC); - await promiseWrite; - if (i == 0) for (let j = 0; j < Math.min(2, NPoints); j++) res.push(G.fromRprLEM(buffOutLEM, j * sG)); - t = curve.Fr.mul(t, curve.Fr.exp(inc, n)); - } - await _iden3_binfileutils.endWriteSection(fdNew); - return res; - } - async function hashSection(fdTo, groupName, sectionId, nPoints, sectionName) { - const G = curve[groupName]; - const sG = G.F.n8 * 2; - const nPointsChunk = Math.floor((1 << 24) / sG); - const oldPos = fdTo.pos; - fdTo.pos = startSections[sectionId]; - for (let i = 0; i < nPoints; i += nPointsChunk) { - if (logger && i) logger.debug(`Hashing ${sectionName}: ` + i); - const n = Math.min(nPoints - i, nPointsChunk); - const buffLEM = await fdTo.read(n * sG); - const buffU = await G.batchLEMtoU(buffLEM); - nextChallengeHasher.update(buffU); - } - fdTo.pos = oldPos; - } - } - //#endregion - //#region src/powersoftau_preparephase2.js - async function preparePhase2(oldPtauFilename, newPTauFilename, logger) { - const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(oldPtauFilename, "ptau", 1); - const { curve, power } = await readPTauHeader(fdOld, sections); - const fdNew = await _iden3_binfileutils.createBinFile(newPTauFilename, "ptau", 1, 11); - await writePTauHeader(fdNew, curve, power); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 2); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 3); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 4); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 5); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 6); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 7); - await processSection(2, 12, "G1", "tauG1"); - await processSection(3, 13, "G2", "tauG2"); - await processSection(4, 14, "G1", "alphaTauG1"); - await processSection(5, 15, "G1", "betaTauG1"); - await fdOld.close(); - await fdNew.close(); - return; - async function processSection(oldSectionId, newSectionId, Gstr, sectionName) { - if (logger) logger.debug("Starting section: " + sectionName); - await _iden3_binfileutils.startWriteSection(fdNew, newSectionId); - for (let p = 0; p <= power; p++) await processSectionPower(p); - if (oldSectionId == 2) await processSectionPower(power + 1); - await _iden3_binfileutils.endWriteSection(fdNew); - async function processSectionPower(p) { - const nPoints = 2 ** p; - const G = curve[Gstr]; - const sGin = G.F.n8 * 2; - let buff; - buff = new ffjavascript.BigBuffer(nPoints * sGin); - await _iden3_binfileutils.startReadUniqueSection(fdOld, sections, oldSectionId); - if (oldSectionId == 2 && p == power + 1) { - await fdOld.readToBuffer(buff, 0, (nPoints - 1) * sGin); - buff.set(curve.G1.zeroAffine, (nPoints - 1) * sGin); - } else await fdOld.readToBuffer(buff, 0, nPoints * sGin); - await _iden3_binfileutils.endReadSection(fdOld, true); - buff = await G.lagrangeEvaluations(buff, "affine", "affine", logger, sectionName); - await fdNew.write(buff); - } - } - } - //#endregion - //#region src/powersoftau_truncate.js - async function truncate(ptauFilename, template, logger) { - const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(ptauFilename, "ptau", 1); - const { curve, power, ceremonyPower } = await readPTauHeader(fdOld, sections); - const sG1 = curve.G1.F.n8 * 2; - const sG2 = curve.G2.F.n8 * 2; - for (let p = 1; p < power; p++) await generateTruncate(p); - await fdOld.close(); - return true; - async function generateTruncate(p) { - let sP = p.toString(); - while (sP.length < 2) sP = "0" + sP; - if (logger) logger.debug("Writing Power: " + sP); - const fdNew = await _iden3_binfileutils.createBinFile(template + sP + ".ptau", "ptau", 1, 11); - await writePTauHeader(fdNew, curve, p, ceremonyPower); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 2, (2 ** p * 2 - 1) * sG1); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 3, 2 ** p * sG2); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 4, 2 ** p * sG1); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 5, 2 ** p * sG1); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 6, sG2); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 7); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 12, (2 ** (p + 1) * 2 - 1) * sG1); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 13, (2 ** p * 2 - 1) * sG2); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 14, (2 ** p * 2 - 1) * sG1); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 15, (2 ** p * 2 - 1) * sG1); - await fdNew.close(); - } - } - //#endregion - //#region src/powersoftau_convert.js - async function convert(oldPtauFilename, newPTauFilename, logger) { - const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(oldPtauFilename, "ptau", 1); - const { curve, power } = await readPTauHeader(fdOld, sections); - const fdNew = await _iden3_binfileutils.createBinFile(newPTauFilename, "ptau", 1, 11); - await writePTauHeader(fdNew, curve, power); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 2); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 3); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 4); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 5); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 6); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 7); - await processSection(2, 12, "G1", "tauG1"); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 13); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 14); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 15); - await fdOld.close(); - await fdNew.close(); - return; - async function processSection(oldSectionId, newSectionId, Gstr, sectionName) { - if (logger) logger.debug("Starting section: " + sectionName); - await _iden3_binfileutils.startWriteSection(fdNew, newSectionId); - const size = sections[newSectionId][0].size; - const chunkSize = fdOld.pageSize; - await _iden3_binfileutils.startReadUniqueSection(fdOld, sections, newSectionId); - for (let p = 0; p < size; p += chunkSize) { - const l = Math.min(size - p, chunkSize); - const buff = await fdOld.read(l); - await fdNew.write(buff); - } - await _iden3_binfileutils.endReadSection(fdOld); - if (oldSectionId == 2) await processSectionPower(power + 1); - await _iden3_binfileutils.endWriteSection(fdNew); - async function processSectionPower(p) { - const nPoints = 2 ** p; - const G = curve[Gstr]; - const sGin = G.F.n8 * 2; - let buff; - buff = new ffjavascript.BigBuffer(nPoints * sGin); - await _iden3_binfileutils.startReadUniqueSection(fdOld, sections, oldSectionId); - if (oldSectionId == 2 && p == power + 1) { - await fdOld.readToBuffer(buff, 0, (nPoints - 1) * sGin); - buff.set(curve.G1.zeroAffine, (nPoints - 1) * sGin); - } else await fdOld.readToBuffer(buff, 0, nPoints * sGin); - await _iden3_binfileutils.endReadSection(fdOld, true); - buff = await G.lagrangeEvaluations(buff, "affine", "affine", logger, sectionName); - await fdNew.write(buff); - } - } - } - //#endregion - //#region src/powersoftau_export_json.js - async function exportJson(pTauFilename, verbose) { - const { fd, sections } = await _iden3_binfileutils.readBinFile(pTauFilename, "ptau", 1); - const { curve, power } = await readPTauHeader(fd, sections); - const pTau = {}; - pTau.q = curve.q; - pTau.power = power; - pTau.contributions = await readContributions(fd, curve, sections); - pTau.tauG1 = await exportSection(2, "G1", 2 ** power * 2 - 1, "tauG1"); - pTau.tauG2 = await exportSection(3, "G2", 2 ** power, "tauG2"); - pTau.alphaTauG1 = await exportSection(4, "G1", 2 ** power, "alphaTauG1"); - pTau.betaTauG1 = await exportSection(5, "G1", 2 ** power, "betaTauG1"); - pTau.betaG2 = await exportSection(6, "G2", 1, "betaG2"); - pTau.lTauG1 = await exportLagrange(12, "G1", "lTauG1"); - pTau.lTauG2 = await exportLagrange(13, "G2", "lTauG2"); - pTau.lAlphaTauG1 = await exportLagrange(14, "G1", "lAlphaTauG2"); - pTau.lBetaTauG1 = await exportLagrange(15, "G1", "lBetaTauG2"); - await fd.close(); - return stringifyBigIntsWithField(curve.Fr, pTau); - async function exportSection(sectionId, groupName, nPoints, sectionName) { - const G = curve[groupName]; - const sG = G.F.n8 * 2; - const res = []; - await _iden3_binfileutils.startReadUniqueSection(fd, sections, sectionId); - for (let i = 0; i < nPoints; i++) { - if (verbose && i && i % 1e4 == 0) console.log(`${sectionName}: ` + i); - const buff = await fd.read(sG); - res.push(G.fromRprLEM(buff, 0)); - } - await _iden3_binfileutils.endReadSection(fd); - return res; - } - async function exportLagrange(sectionId, groupName, sectionName) { - const G = curve[groupName]; - const sG = G.F.n8 * 2; - const res = []; - await _iden3_binfileutils.startReadUniqueSection(fd, sections, sectionId); - for (let p = 0; p <= power; p++) { - if (verbose) console.log(`${sectionName}: Power: ${p}`); - res[p] = []; - const nPoints = 2 ** p; - for (let i = 0; i < nPoints; i++) { - if (verbose && i && i % 1e4 == 0) console.log(`${sectionName}: ${i}/${nPoints}`); - const buff = await fd.read(sG); - res[p].push(G.fromRprLEM(buff, 0)); - } - } - await _iden3_binfileutils.endReadSection(fd, true); - return res; - } - } - //#endregion - //#region src/powersoftau.js - var powersoftau_exports = /* @__PURE__ */ __exportAll({ - beacon: () => beacon$1, - challengeContribute: () => challengeContribute, - contribute: () => contribute, - convert: () => convert, - exportChallenge: () => exportChallenge, - exportJson: () => exportJson, - importResponse: () => importResponse, - newAccumulator: () => newAccumulator, - preparePhase2: () => preparePhase2, - truncate: () => truncate, - verify: () => verify - }); - //#endregion - //#region src/r1cs_print.js - function r1csPrint(r1cs, syms, logger) { - for (let i = 0; i < r1cs.constraints.length; i++) printCostraint(r1cs.constraints[i]); - function printCostraint(c) { - const lc2str = (lc) => { - let S = ""; - Object.keys(lc).forEach((k) => { - let name = syms.varIdx2Name[k]; - if (name == "one") name = "1"; - let vs = r1cs.curve.Fr.toString(lc[k]); - if (vs == "1") vs = ""; - if (vs == "-1") vs = "-"; - if (S != "" && vs[0] != "-") vs = "+" + vs; - if (S != "") vs = " " + vs; - S = S + vs + name; - }); - return S; - }; - const S = `[ ${lc2str(c[0])} ] * [ ${lc2str(c[1])} ] - [ ${lc2str(c[2])} ] = 0`; - if (logger) logger.info(S); - } - } - //#endregion - //#region src/r1cs_info.js - var bls12381r = ffjavascript.Scalar.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16); - var bn128r = ffjavascript.Scalar.e("21888242871839275222246405745257275088548364400416034343698204186575808495617"); - async function r1csInfo(r1csName, logger) { - const cir = await (0, r1csfile.readR1cs)(r1csName); - if (ffjavascript.Scalar.eq(cir.prime, bn128r)) { - if (logger) logger.info("Curve: bn-128"); - } else if (ffjavascript.Scalar.eq(cir.prime, bls12381r)) { - if (logger) logger.info("Curve: bls12-381"); - } else if (logger) logger.info(`Unknown Curve. Prime: ${ffjavascript.Scalar.toString(cir.prime)}`); - if (logger) logger.info(`# of Wires: ${cir.nVars}`); - if (logger) logger.info(`# of Constraints: ${cir.nConstraints}`); - if (logger) logger.info(`# of Private Inputs: ${cir.nPrvInputs}`); - if (logger) logger.info(`# of Public Inputs: ${cir.nPubInputs}`); - if (logger) logger.info(`# of Labels: ${cir.nLabels}`); - if (logger) logger.info(`# of Outputs: ${cir.nOutputs}`); - return cir; - } - //#endregion - //#region src/r1cs_export_json.js - async function r1csExportJson(r1csFileName, logger) { - const cir = await (0, r1csfile.readR1cs)(r1csFileName, true, true, true, logger); - const Fr = cir.curve.Fr; - delete cir.curve; - delete cir.F; - return stringifyBigIntsWithField(Fr, cir); - } - //#endregion - //#region src/r1cs.js - var r1cs_exports = /* @__PURE__ */ __exportAll({ - exportJson: () => r1csExportJson, - info: () => r1csInfo, - print: () => r1csPrint - }); - //#endregion - //#region src/loadsyms.js - async function loadSymbols(symFileName) { - const sym = { - labelIdx2Name: ["one"], - varIdx2Name: ["one"], - componentIdx2Name: [] - }; - const fd = await w(symFileName); - const buff = await fd.read(fd.totalSize); - const lines = new TextDecoder("utf-8").decode(buff).split("\n"); - for (let i = 0; i < lines.length; i++) { - const arr = lines[i].split(","); - if (arr.length != 4) continue; - if (sym.varIdx2Name[arr[1]]) sym.varIdx2Name[arr[1]] += "|" + arr[3]; - else sym.varIdx2Name[arr[1]] = arr[3]; - sym.labelIdx2Name[arr[0]] = arr[3]; - if (!sym.componentIdx2Name[arr[2]]) sym.componentIdx2Name[arr[2]] = extractComponent(arr[3]); - } - await fd.close(); - return sym; - function extractComponent(name) { - const arr = name.split("."); - arr.pop(); - return arr.join("."); - } - } - //#endregion - //#region src/wtns_debug.js - var { unstringifyBigInts: unstringifyBigInts$6 } = ffjavascript.utils; - async function wtnsDebug(_input, wasmFileName, wtnsFileName, symName, options, logger) { - const input = unstringifyBigInts$6(_input); - const fdWasm = await w(wasmFileName); - const wasm = await fdWasm.read(fdWasm.totalSize); - await fdWasm.close(); - const wcOps = { - ...options, - sanityCheck: true - }; - let sym = await loadSymbols(symName); - if (options.set) { - if (!sym) sym = await loadSymbols(symName); - wcOps.logSetSignal = function(labelIdx, value) { - if (logger) logger.info("SET " + sym.labelIdx2Name[labelIdx] + " <-- " + value.toString()); - }; - } - if (options.get) { - if (!sym) sym = await loadSymbols(symName); - wcOps.logGetSignal = function(varIdx, value) { - if (logger) logger.info("GET " + sym.labelIdx2Name[varIdx] + " --> " + value.toString()); - }; - } - if (options.trigger) { - if (!sym) sym = await loadSymbols(symName); - wcOps.logStartComponent = function(cIdx) { - if (logger) logger.info("START: " + sym.componentIdx2Name[cIdx]); - }; - wcOps.logFinishComponent = function(cIdx) { - if (logger) logger.info("FINISH: " + sym.componentIdx2Name[cIdx]); - }; - } - wcOps.sym = sym; - const wc = await builder(wasm, wcOps); - const w$1 = await wc.calculateWitness(input, true); - const fdWtns = await _iden3_binfileutils.createBinFile(wtnsFileName, "wtns", 2, 2); - await write(fdWtns, w$1, wc.prime); - await fdWtns.close(); - } - //#endregion - //#region src/wtns_export_json.js - async function wtnsExportJson(wtnsFileName) { - return await read(wtnsFileName); - } - //#endregion - //#region src/wtns_check.js - async function wtnsCheck(r1csFilename, wtnsFilename, logger) { - if (logger) logger.info("WITNESS CHECKING STARTED"); - if (logger) logger.info("> Reading r1cs file"); - const { fd: fdR1cs, sections: sectionsR1cs } = await _iden3_binfileutils.readBinFile(r1csFilename, "r1cs", 1, 1 << 22, 1 << 24); - const r1cs = await (0, r1csfile.readR1csFd)(fdR1cs, sectionsR1cs, { - loadConstraints: false, - loadCustomGates: false - }); - if (logger) logger.info("> Reading witness file"); - const { fd: fdWtns, sections: wtnsSections } = await _iden3_binfileutils.readBinFile(wtnsFilename, "wtns", 2, 1 << 22, 1 << 24); - const wtnsHeader = await readHeader(fdWtns, wtnsSections); - if (!ffjavascript.Scalar.eq(r1cs.prime, wtnsHeader.q)) throw new Error("Curve of the witness does not match the curve of the proving key"); - const buffWitness = await _iden3_binfileutils.readSection(fdWtns, wtnsSections, 2); - await fdWtns.close(); - const Fr = (await getCurveFromR(r1cs.prime)).Fr; - const sFr = Fr.n8; - const bR1cs = await _iden3_binfileutils.readSection(fdR1cs, sectionsR1cs, 2); - if (logger) { - logger.info("----------------------------"); - logger.info(" WITNESS CHECK"); - logger.info(` Curve: ${r1cs.curve.name}`); - logger.info(` Vars (wires): ${r1cs.nVars}`); - logger.info(` Outputs: ${r1cs.nOutputs}`); - logger.info(` Public Inputs: ${r1cs.nPubInputs}`); - logger.info(` Private Inputs: ${r1cs.nPrvInputs}`); - logger.info(` Labels: ${r1cs.nLabels}`); - logger.info(` Constraints: ${r1cs.nConstraints}`); - logger.info(` Custom Gates: ${r1cs.useCustomGates}`); - logger.info("----------------------------"); - } - if (logger) logger.info("> Checking witness correctness"); - let bR1csPos = 0; - let res = true; - for (let i = 0; i < r1cs.nConstraints; i++) { - if (logger && i !== 0 && i % 5e5 === 0) logger.info(`··· processing r1cs constraints ${i}/${r1cs.nConstraints}`); - const lcA = readLC(); - const lcB = readLC(); - const lcC = readLC(); - const evalA = EvaluateLinearCombination(lcA); - const evalB = EvaluateLinearCombination(lcB); - const evalC = EvaluateLinearCombination(lcC); - if (!Fr.eq(Fr.sub(Fr.mul(evalA, evalB), evalC), Fr.zero)) { - logger.warn("··· aborting checking process at constraint " + i); - res = false; - break; - } - } - fdR1cs.close(); - if (logger) if (res) { - logger.info("WITNESS IS CORRECT"); - logger.info("WITNESS CHECKING FINISHED SUCCESSFULLY"); - } else { - logger.warn("WITNESS IS NOT CORRECT"); - logger.warn("WITNESS CHECKING FINISHED UNSUCCESSFULLY"); - } - return res; - function EvaluateLinearCombination(lc) { - let res = Fr.zero; - Object.keys(lc).forEach((signalId) => { - const signalValue = getWitnessValue(signalId); - const signalFactor = lc[signalId]; - res = Fr.add(res, Fr.mul(signalValue, signalFactor)); - }); - return res; - } - function readLC() { - const lc = {}; - const buffUL32 = bR1cs.slice(bR1csPos, bR1csPos + 4); - bR1csPos += 4; - const nIdx = new DataView(buffUL32.buffer).getUint32(0, true); - const buff = bR1cs.slice(bR1csPos, bR1csPos + (4 + r1cs.n8) * nIdx); - bR1csPos += (4 + r1cs.n8) * nIdx; - const buffV = new DataView(buff.buffer); - for (let i = 0; i < nIdx; i++) { - const idx = buffV.getUint32(i * (4 + r1cs.n8), true); - lc[idx] = r1cs.F.fromRprLE(buff, i * (4 + r1cs.n8) + 4); - } - return lc; - } - function getWitnessValue(signalId) { - return Fr.fromRprLE(buffWitness.slice(signalId * sFr, signalId * sFr + sFr)); - } - } - //#endregion - //#region src/wtns.js - var wtns_exports = /* @__PURE__ */ __exportAll({ - calculate: () => wtnsCalculate, - check: () => wtnsCheck, - debug: () => wtnsDebug, - exportJson: () => wtnsExportJson - }); - //#endregion - //#region src/bigarray.js - var SUBARRAY_SIZE = 262144; - var BigArrayHandler = { - get: function(obj, prop) { - if (!isNaN(prop)) return obj.getElement(prop); - else return obj[prop]; - }, - set: function(obj, prop, value) { - if (!isNaN(prop)) return obj.setElement(prop, value); - else { - obj[prop] = value; - return true; - } - } - }; - var _BigArray = class { - constructor(initSize) { - this.length = initSize || 0; - this.arr = new Array(SUBARRAY_SIZE); - for (let i = 0; i < initSize; i += SUBARRAY_SIZE) this.arr[i / SUBARRAY_SIZE] = new Array(Math.min(SUBARRAY_SIZE, initSize - i)); - return this; - } - push() { - for (let i = 0; i < arguments.length; i++) this.setElement(this.length, arguments[i]); - } - slice(f, t) { - const arr = new Array(t - f); - for (let i = f; i < t; i++) arr[i - f] = this.getElement(i); - return arr; - } - getElement(idx) { - idx = parseInt(idx); - const idx1 = Math.floor(idx / SUBARRAY_SIZE); - const idx2 = idx % SUBARRAY_SIZE; - return this.arr[idx1] ? this.arr[idx1][idx2] : void 0; - } - setElement(idx, value) { - idx = parseInt(idx); - const idx1 = Math.floor(idx / SUBARRAY_SIZE); - if (!this.arr[idx1]) this.arr[idx1] = new Array(SUBARRAY_SIZE); - const idx2 = idx % SUBARRAY_SIZE; - this.arr[idx1][idx2] = value; - if (idx >= this.length) this.length = idx + 1; - return true; - } - getKeys() { - const newA = new BigArray(); - for (let i = 0; i < this.arr.length; i++) if (this.arr[i]) { - for (let j = 0; j < this.arr[i].length; j++) if (typeof this.arr[i][j] !== "undefined") newA.push(i * SUBARRAY_SIZE + j); - } - return newA; - } - }; - var BigArray = class { - constructor(initSize) { - const obj = new _BigArray(initSize); - return new Proxy(obj, BigArrayHandler); - } - }; - //#endregion - //#region src/zkey_new.js - async function newZKey(r1csName, ptauName, zkeyName, logger) { - const TAU_G1 = 0; - const TAU_G2 = 1; - const ALPHATAU_G1 = 2; - const BETATAU_G1 = 3; - const csHasher = blake2b.create({ dkLen: 64 }); - const { fd: fdPTau, sections: sectionsPTau } = await (0, _iden3_binfileutils.readBinFile)(ptauName, "ptau", 1, 1 << 22, 1 << 24); - const { curve, power } = await readPTauHeader(fdPTau, sectionsPTau); - const { fd: fdR1cs, sections: sectionsR1cs } = await (0, _iden3_binfileutils.readBinFile)(r1csName, "r1cs", 1, 1 << 22, 1 << 24); - const r1cs = await (0, r1csfile.readR1csHeader)(fdR1cs, sectionsR1cs, false); - const fdZKey = await (0, _iden3_binfileutils.createBinFile)(zkeyName, "zkey", 1, 10, 1 << 22, 1 << 24); - const sG1 = curve.G1.F.n8 * 2; - const sG2 = curve.G2.F.n8 * 2; - if (r1cs.prime != curve.r) { - if (logger) logger.error("r1cs curve does not match powers of tau ceremony curve"); - return -1; - } - const cirPower = log2(r1cs.nConstraints + r1cs.nPubInputs + r1cs.nOutputs + 1 - 1) + 1; - if (cirPower > power) { - if (logger) logger.error(`circuit too big for this power of tau ceremony. ${r1cs.nConstraints}*2 > 2**${power}`); - return -1; - } - if (!sectionsPTau[12]) { - if (logger) logger.error("Powers of tau is not prepared."); - return -1; - } - const nPublic = r1cs.nOutputs + r1cs.nPubInputs; - const domainSize = 2 ** cirPower; - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 1); - await fdZKey.writeULE32(1); - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 2); - const primeQ = curve.q; - const n8q = (Math.floor((ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) + 1) * 8; - const primeR = curve.r; - const n8r = (Math.floor((ffjavascript.Scalar.bitLength(primeR) - 1) / 64) + 1) * 8; - const Rr = ffjavascript.Scalar.mod(ffjavascript.Scalar.shl(1, n8r * 8), primeR); - const R2r = curve.Fr.e(ffjavascript.Scalar.mod(ffjavascript.Scalar.mul(Rr, Rr), primeR)); - await fdZKey.writeULE32(n8q); - await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeQ, n8q); - await fdZKey.writeULE32(n8r); - await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeR, n8r); - await fdZKey.writeULE32(r1cs.nVars); - await fdZKey.writeULE32(nPublic); - await fdZKey.writeULE32(domainSize); - let bAlpha1; - bAlpha1 = await fdPTau.read(sG1, sectionsPTau[4][0].p); - await fdZKey.write(bAlpha1); - bAlpha1 = await curve.G1.batchLEMtoU(bAlpha1); - csHasher.update(bAlpha1); - let bBeta1; - bBeta1 = await fdPTau.read(sG1, sectionsPTau[5][0].p); - await fdZKey.write(bBeta1); - bBeta1 = await curve.G1.batchLEMtoU(bBeta1); - csHasher.update(bBeta1); - let bBeta2; - bBeta2 = await fdPTau.read(sG2, sectionsPTau[6][0].p); - await fdZKey.write(bBeta2); - bBeta2 = await curve.G2.batchLEMtoU(bBeta2); - csHasher.update(bBeta2); - const bg1 = new Uint8Array(sG1); - curve.G1.toRprLEM(bg1, 0, curve.G1.g); - const bg2 = new Uint8Array(sG2); - curve.G2.toRprLEM(bg2, 0, curve.G2.g); - const bg1U = new Uint8Array(sG1); - curve.G1.toRprUncompressed(bg1U, 0, curve.G1.g); - const bg2U = new Uint8Array(sG2); - curve.G2.toRprUncompressed(bg2U, 0, curve.G2.g); - await fdZKey.write(bg2); - await fdZKey.write(bg1); - await fdZKey.write(bg2); - csHasher.update(bg2U); - csHasher.update(bg1U); - csHasher.update(bg2U); - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - if (logger) logger.info(memUsage()); - if (logger) logger.info("Reading r1cs"); - let sR1cs = await (0, _iden3_binfileutils.readSection)(fdR1cs, sectionsR1cs, 2); - await fdR1cs.close(); - let A = new BigArray(r1cs.nVars); - let B1 = new BigArray(r1cs.nVars); - let B2 = new BigArray(r1cs.nVars); - let C = new BigArray(r1cs.nVars - nPublic - 1); - let IC = new Array(nPublic + 1); - if (logger) logger.info(memUsage()); - if (logger) logger.info("Reading tauG1"); - let sTauG1 = await (0, _iden3_binfileutils.readSection)(fdPTau, sectionsPTau, 12, (domainSize - 1) * sG1, domainSize * sG1); - if (logger) logger.info("Reading tauG2"); - let sTauG2 = await (0, _iden3_binfileutils.readSection)(fdPTau, sectionsPTau, 13, (domainSize - 1) * sG2, domainSize * sG2); - if (logger) logger.info("Reading alphatauG1"); - let sAlphaTauG1 = await (0, _iden3_binfileutils.readSection)(fdPTau, sectionsPTau, 14, (domainSize - 1) * sG1, domainSize * sG1); - if (logger) logger.info("Reading betatauG1"); - let sBetaTauG1 = await (0, _iden3_binfileutils.readSection)(fdPTau, sectionsPTau, 15, (domainSize - 1) * sG1, domainSize * sG1); - if (logger) logger.info(memUsage()); - if (logger) logger.info("processConstraints"); - await processConstraints(); - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints"); - await composeAndWritePoints(3, "G1", IC, "IC"); - IC = null; - if (logger) logger.info(memUsage()); - if (logger) logger.info("writeHs"); - await writeHs(); - if (logger) logger.info(memUsage()); - if (logger) logger.info("hashHPoints"); - await hashHPoints(); - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints 8 G1 C"); - await composeAndWritePoints(8, "G1", C, "C"); - C = null; - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints 5 G1 A"); - await composeAndWritePoints(5, "G1", A, "A"); - A = null; - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints 6 G1 B1"); - await composeAndWritePoints(6, "G1", B1, "B1"); - B1 = null; - if (logger) logger.info(memUsage()); - if (logger) logger.info("composeAndWritePoints 7 G2 B2"); - await composeAndWritePoints(7, "G2", B2, "B2"); - B2 = null; - if (logger) logger.info(memUsage()); - if (logger) logger.info("Contributions section"); - const csHash = csHasher.digest(); - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 10); - await fdZKey.write(csHash); - await fdZKey.writeULE32(0); - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - if (logger) logger.info(formatHash(csHash, "Circuit hash: ")); - await fdZKey.close(); - await fdPTau.close(); - return csHash; - async function writeHs() { - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 9); - const buffOut = new ffjavascript.BigBuffer(domainSize * sG1); - if (cirPower < curve.Fr.s) { - let sTauG1 = await (0, _iden3_binfileutils.readSection)(fdPTau, sectionsPTau, 12, (domainSize * 2 - 1) * sG1, domainSize * 2 * sG1); - for (let i = 0; i < domainSize; i++) { - if (logger && i % 1e4 == 0) logger.debug(`splitting buffer: ${i}/${domainSize}`); - const buff = sTauG1.slice((i * 2 + 1) * sG1, (i * 2 + 1) * sG1 + sG1); - buffOut.set(buff, i * sG1); - } - } else if (cirPower == curve.Fr.s) { - const o = sectionsPTau[12][0].p + (2 ** (cirPower + 1) - 1) * sG1; - await fdPTau.readToBuffer(buffOut, 0, domainSize * sG1, o + domainSize * sG1); - } else { - if (logger) logger.error("Circuit too big"); - throw new Error("Circuit too big for this curve"); - } - await fdZKey.write(buffOut); - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - } - async function processConstraints() { - const buffCoeff = new Uint8Array(12 + curve.Fr.n8); - const buffCoeffV = new DataView(buffCoeff.buffer); - const bOne = new Uint8Array(curve.Fr.n8); - curve.Fr.toRprLE(bOne, 0, curve.Fr.e(1)); - let r1csPos = 0; - function r1cs_readULE32() { - const buff = sR1cs.slice(r1csPos, r1csPos + 4); - r1csPos += 4; - return new DataView(buff.buffer).getUint32(0, true); - } - const coefs = new BigArray(); - for (let c = 0; c < r1cs.nConstraints; c++) { - if (logger && c % 1e4 == 0) logger.debug(`processing constraints: ${c}/${r1cs.nConstraints}`); - const nA = r1cs_readULE32(); - for (let i = 0; i < nA; i++) { - const s = r1cs_readULE32(); - const coefp = r1csPos; - r1csPos += curve.Fr.n8; - const l1t = TAU_G1; - const l1 = sG1 * c; - const l2t = BETATAU_G1; - const l2 = sG1 * c; - if (typeof A[s] === "undefined") A[s] = []; - A[s].push([ - l1t, - l1, - coefp - ]); - if (s <= nPublic) { - if (typeof IC[s] === "undefined") IC[s] = []; - IC[s].push([ - l2t, - l2, - coefp - ]); - } else { - if (typeof C[s - nPublic - 1] === "undefined") C[s - nPublic - 1] = []; - C[s - nPublic - 1].push([ - l2t, - l2, - coefp - ]); - } - coefs.push([ - 0, - c, - s, - coefp - ]); - } - const nB = r1cs_readULE32(); - for (let i = 0; i < nB; i++) { - const s = r1cs_readULE32(); - const coefp = r1csPos; - r1csPos += curve.Fr.n8; - const l1t = TAU_G1; - const l1 = sG1 * c; - const l2t = TAU_G2; - const l2 = sG2 * c; - const l3t = ALPHATAU_G1; - const l3 = sG1 * c; - if (typeof B1[s] === "undefined") B1[s] = []; - B1[s].push([ - l1t, - l1, - coefp - ]); - if (typeof B2[s] === "undefined") B2[s] = []; - B2[s].push([ - l2t, - l2, - coefp - ]); - if (s <= nPublic) { - if (typeof IC[s] === "undefined") IC[s] = []; - IC[s].push([ - l3t, - l3, - coefp - ]); - } else { - if (typeof C[s - nPublic - 1] === "undefined") C[s - nPublic - 1] = []; - C[s - nPublic - 1].push([ - l3t, - l3, - coefp - ]); - } - coefs.push([ - 1, - c, - s, - coefp - ]); - } - const nC = r1cs_readULE32(); - for (let i = 0; i < nC; i++) { - const s = r1cs_readULE32(); - const coefp = r1csPos; - r1csPos += curve.Fr.n8; - const l1t = TAU_G1; - const l1 = sG1 * c; - if (s <= nPublic) { - if (typeof IC[s] === "undefined") IC[s] = []; - IC[s].push([ - l1t, - l1, - coefp - ]); - } else { - if (typeof C[s - nPublic - 1] === "undefined") C[s - nPublic - 1] = []; - C[s - nPublic - 1].push([ - l1t, - l1, - coefp - ]); - } - } - } - for (let s = 0; s <= nPublic; s++) { - const l1t = TAU_G1; - const l1 = sG1 * (r1cs.nConstraints + s); - const l2t = BETATAU_G1; - const l2 = sG1 * (r1cs.nConstraints + s); - if (typeof A[s] === "undefined") A[s] = []; - A[s].push([ - l1t, - l1, - -1 - ]); - if (typeof IC[s] === "undefined") IC[s] = []; - IC[s].push([ - l2t, - l2, - -1 - ]); - coefs.push([ - 0, - r1cs.nConstraints + s, - s, - -1 - ]); - } - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 4); - const buffSection = new ffjavascript.BigBuffer(coefs.length * (12 + curve.Fr.n8) + 4); - const buff4 = new Uint8Array(4); - new DataView(buff4.buffer).setUint32(0, coefs.length, true); - buffSection.set(buff4); - let coefsPos = 4; - for (let i = 0; i < coefs.length; i++) { - if (logger && i % 1e5 == 0) logger.debug(`writing coeffs: ${i}/${coefs.length}`); - writeCoef(coefs[i]); - } - await fdZKey.write(buffSection); - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - function writeCoef(c) { - buffCoeffV.setUint32(0, c[0], true); - buffCoeffV.setUint32(4, c[1], true); - buffCoeffV.setUint32(8, c[2], true); - let n; - if (c[3] >= 0) n = curve.Fr.fromRprLE(sR1cs.slice(c[3], c[3] + curve.Fr.n8), 0); - else n = curve.Fr.fromRprLE(bOne, 0); - const nR2 = curve.Fr.mul(n, R2r); - curve.Fr.toRprLE(buffCoeff, 12, nR2); - buffSection.set(buffCoeff, coefsPos); - coefsPos += buffCoeff.length; - } - } - async function composeAndWritePoints(idSection, groupName, arr, sectionName) { - const CHUNK_SIZE = 32768; - const G = curve[groupName]; - hashU32(arr.length); - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, idSection); - let opPromises = []; - let i = 0; - while (i < arr.length) { - let t = 0; - while (i < arr.length && t < curve.tm.concurrency) { - if (logger) logger.debug(`Writing points start ${sectionName}: ${i}/${arr.length}`); - let n = 1; - let nP = arr[i] ? arr[i].length : 0; - while (i + n < arr.length && nP + (arr[i + n] ? arr[i + n].length : 0) < CHUNK_SIZE && n < CHUNK_SIZE) { - nP += arr[i + n] ? arr[i + n].length : 0; - n++; - } - if (logger) logger.info("before slice:"); - if (logger) logger.info(memUsage()); - const subArr = arr.slice(i, i + n); - if (logger) logger.info("after slice:"); - if (logger) logger.info(memUsage()); - const _i = i; - opPromises.push(composeAndWritePointsThread(groupName, subArr, logger, sectionName).then((r) => { - if (logger) logger.debug(`Writing points end ${sectionName}: ${_i}/${arr.length}`); - return r; - })); - i += n; - t++; - } - const result = await Promise.all(opPromises); - for (let k = 0; k < result.length; k++) { - await fdZKey.write(result[k][0]); - const buff = await G.batchLEMtoU(result[k][0]); - csHasher.update(buff); - } - opPromises = []; - } - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - } - async function composeAndWritePointsThread(groupName, arr, logger, sectionName) { - const G = curve[groupName]; - const sGin = G.F.n8 * 2; - const sGmid = G.F.n8 * 3; - const sGout = G.F.n8 * 2; - let fnExp, fnMultiExp, fnBatchToAffine, fnZero; - if (groupName == "G1") { - fnExp = "g1m_timesScalarAffine"; - fnMultiExp = "g1m_multiexpAffine"; - fnBatchToAffine = "g1m_batchToAffine"; - fnZero = "g1m_zero"; - } else if (groupName == "G2") { - fnExp = "g2m_timesScalarAffine"; - fnMultiExp = "g2m_multiexpAffine"; - fnBatchToAffine = "g2m_batchToAffine"; - fnZero = "g2m_zero"; - } else throw new Error("Invalid group"); - let acc = 0; - for (let i = 0; i < arr.length; i++) acc += arr[i] ? arr[i].length : 0; - let bBases, bScalars; - if (acc > 32768) { - bBases = new ffjavascript.BigBuffer(acc * sGin); - bScalars = new ffjavascript.BigBuffer(acc * curve.Fr.n8); - } else { - bBases = new Uint8Array(acc * sGin); - bScalars = new Uint8Array(acc * curve.Fr.n8); - } - let pB; - let pS; - const sBuffs = [ - sTauG1, - sTauG2, - sAlphaTauG1, - sBetaTauG1 - ]; - const bOne = new Uint8Array(curve.Fr.n8); - curve.Fr.toRprLE(bOne, 0, curve.Fr.e(1)); - let offset = 0; - for (let i = 0; i < arr.length; i++) { - if (!arr[i]) continue; - for (let j = 0; j < arr[i].length; j++) { - if (logger && j && j % 1e4 == 0) logger.debug(`Configuring big array ${sectionName}: ${j}/${arr[i].length}`); - bBases.set(sBuffs[arr[i][j][0]].slice(arr[i][j][1], arr[i][j][1] + sGin), offset * sGin); - if (arr[i][j][2] >= 0) bScalars.set(sR1cs.slice(arr[i][j][2], arr[i][j][2] + curve.Fr.n8), offset * curve.Fr.n8); - else bScalars.set(bOne, offset * curve.Fr.n8); - offset++; - } - } - if (arr.length > 1) { - const task = []; - task.push({ - cmd: "ALLOCSET", - var: 0, - buff: bBases - }); - task.push({ - cmd: "ALLOCSET", - var: 1, - buff: bScalars - }); - task.push({ - cmd: "ALLOC", - var: 2, - len: arr.length * sGmid - }); - pB = 0; - pS = 0; - let pD = 0; - for (let i = 0; i < arr.length; i++) { - if (!arr[i]) { - task.push({ - cmd: "CALL", - fnName: fnZero, - params: [{ - var: 2, - offset: pD - }] - }); - pD += sGmid; - continue; - } - if (arr[i].length == 1) task.push({ - cmd: "CALL", - fnName: fnExp, - params: [ - { - var: 0, - offset: pB - }, - { - var: 1, - offset: pS - }, - { val: curve.Fr.n8 }, - { - var: 2, - offset: pD - } - ] - }); - else task.push({ - cmd: "CALL", - fnName: fnMultiExp, - params: [ - { - var: 0, - offset: pB - }, - { - var: 1, - offset: pS - }, - { val: curve.Fr.n8 }, - { val: arr[i].length }, - { - var: 2, - offset: pD - } - ] - }); - pB += sGin * arr[i].length; - pS += curve.Fr.n8 * arr[i].length; - pD += sGmid; - } - task.push({ - cmd: "CALL", - fnName: fnBatchToAffine, - params: [ - { var: 2 }, - { val: arr.length }, - { var: 2 } - ] - }); - task.push({ - cmd: "GET", - out: 0, - var: 2, - len: arr.length * sGout - }); - return await curve.tm.queueAction(task); - } else { - let res = await G.multiExpAffine(bBases, bScalars, logger, sectionName); - res = [G.toAffine(res)]; - return res; - } - } - async function hashHPoints() { - const CHUNK_SIZE = 16384; - hashU32(domainSize - 1); - for (let i = 0; i < domainSize - 1; i += CHUNK_SIZE) { - if (logger) logger.debug(`HashingHPoints: ${i}/${domainSize}`); - const n = Math.min(domainSize - 1, CHUNK_SIZE); - await hashHPointsChunk(i, n); - } - } - async function hashHPointsChunk(offset, nPoints) { - const buff1 = await fdPTau.read(nPoints * sG1, sectionsPTau[2][0].p + (offset + domainSize) * sG1); - const buff2 = await fdPTau.read(nPoints * sG1, sectionsPTau[2][0].p + offset * sG1); - const concurrency = curve.tm.concurrency; - const nPointsPerThread = Math.floor(nPoints / concurrency); - const opPromises = []; - for (let i = 0; i < concurrency; i++) { - let n; - if (i < concurrency - 1) n = nPointsPerThread; - else n = nPoints - i * nPointsPerThread; - if (n == 0) continue; - const subBuff1 = buff1.slice(i * nPointsPerThread * sG1, (i * nPointsPerThread + n) * sG1); - const subBuff2 = buff2.slice(i * nPointsPerThread * sG1, (i * nPointsPerThread + n) * sG1); - opPromises.push(hashHPointsThread(subBuff1, subBuff2)); - } - const result = await Promise.all(opPromises); - for (let i = 0; i < result.length; i++) csHasher.update(result[i][0]); - } - async function hashHPointsThread(buff1, buff2) { - const nPoints = buff1.byteLength / sG1; - const sGmid = curve.G1.F.n8 * 3; - const task = []; - task.push({ - cmd: "ALLOCSET", - var: 0, - buff: buff1 - }); - task.push({ - cmd: "ALLOCSET", - var: 1, - buff: buff2 - }); - task.push({ - cmd: "ALLOC", - var: 2, - len: nPoints * sGmid - }); - for (let i = 0; i < nPoints; i++) task.push({ - cmd: "CALL", - fnName: "g1m_subAffine", - params: [ - { - var: 0, - offset: i * sG1 - }, - { - var: 1, - offset: i * sG1 - }, - { - var: 2, - offset: i * sGmid - } - ] - }); - task.push({ - cmd: "CALL", - fnName: "g1m_batchToAffine", - params: [ - { var: 2 }, - { val: nPoints }, - { var: 2 } - ] - }); - task.push({ - cmd: "CALL", - fnName: "g1m_batchLEMtoU", - params: [ - { var: 2 }, - { val: nPoints }, - { var: 2 } - ] - }); - task.push({ - cmd: "GET", - out: 0, - var: 2, - len: nPoints * sG1 - }); - return await curve.tm.queueAction(task); - } - function hashU32(n) { - const buff = new Uint8Array(4); - new DataView(buff.buffer, buff.byteOffset, buff.byteLength).setUint32(0, n, false); - csHasher.update(buff); - } - function memUsage() { - if (typeof process === "undefined" || !process.memoryUsage) return {}; - let m = process.memoryUsage(); - for (const i in m) m[i] = Math.round(m[i] / (1024 * 1024)); - return m; - } - } - //#endregion - //#region src/zkey_export_bellman.js - async function phase2exportMPCParams(zkeyName, mpcparamsName, logger) { - const { fd: fdZKey, sections: sectionsZKey } = await _iden3_binfileutils.readBinFile(zkeyName, "zkey", 2); - const zkey = await readHeader$1(fdZKey, sectionsZKey); - if (zkey.protocol != "groth16") throw new Error("zkey file is not groth16"); - const curve = await getCurveFromQ(zkey.q); - const sG1 = curve.G1.F.n8 * 2; - const sG2 = curve.G2.F.n8 * 2; - const mpcParams = await readMPCParams(fdZKey, curve, sectionsZKey); - const fdMPCParams = await S(mpcparamsName); - await writeG1(zkey.vk_alpha_1); - await writeG1(zkey.vk_beta_1); - await writeG2(zkey.vk_beta_2); - await writeG2(zkey.vk_gamma_2); - await writeG1(zkey.vk_delta_1); - await writeG2(zkey.vk_delta_2); - let buffBasesIC; - buffBasesIC = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 3); - buffBasesIC = await curve.G1.batchLEMtoU(buffBasesIC); - await writePointArray("G1", buffBasesIC); - const buffBasesH_Lodd = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 9); - let buffBasesH_Tau; - buffBasesH_Tau = await curve.G1.fft(buffBasesH_Lodd, "affine", "jacobian", logger); - buffBasesH_Tau = await curve.G1.batchApplyKey(buffBasesH_Tau, curve.Fr.neg(curve.Fr.e(2)), curve.Fr.w[zkey.power + 1], "jacobian", "affine", logger); - buffBasesH_Tau = buffBasesH_Tau.slice(0, buffBasesH_Tau.byteLength - sG1); - buffBasesH_Tau = await curve.G1.batchLEMtoU(buffBasesH_Tau); - await writePointArray("G1", buffBasesH_Tau); - let buffBasesC; - buffBasesC = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 8); - buffBasesC = await curve.G1.batchLEMtoU(buffBasesC); - await writePointArray("G1", buffBasesC); - let buffBasesA; - buffBasesA = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 5); - buffBasesA = await curve.G1.batchLEMtoU(buffBasesA); - await writePointArray("G1", buffBasesA); - let buffBasesB1; - buffBasesB1 = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 6); - buffBasesB1 = await curve.G1.batchLEMtoU(buffBasesB1); - await writePointArray("G1", buffBasesB1); - let buffBasesB2; - buffBasesB2 = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 7); - buffBasesB2 = await curve.G2.batchLEMtoU(buffBasesB2); - await writePointArray("G2", buffBasesB2); - await fdMPCParams.write(mpcParams.csHash); - await writeU32(mpcParams.contributions.length); - for (let i = 0; i < mpcParams.contributions.length; i++) { - const c = mpcParams.contributions[i]; - await writeG1(c.deltaAfter); - await writeG1(c.delta.g1_s); - await writeG1(c.delta.g1_sx); - await writeG2(c.delta.g2_spx); - await fdMPCParams.write(c.transcript); - } - await fdZKey.close(); - await fdMPCParams.close(); - async function writeG1(P) { - const buff = new Uint8Array(sG1); - curve.G1.toRprUncompressed(buff, 0, P); - await fdMPCParams.write(buff); - } - async function writeG2(P) { - const buff = new Uint8Array(sG2); - curve.G2.toRprUncompressed(buff, 0, P); - await fdMPCParams.write(buff); - } - async function writePointArray(groupName, buff) { - let sG; - if (groupName == "G1") sG = sG1; - else sG = sG2; - const buffSize = new Uint8Array(4); - new DataView(buffSize.buffer, buffSize.byteOffset, buffSize.byteLength).setUint32(0, buff.byteLength / sG, false); - await fdMPCParams.write(buffSize); - await fdMPCParams.write(buff); - } - async function writeU32(n) { - const buffSize = new Uint8Array(4); - new DataView(buffSize.buffer, buffSize.byteOffset, buffSize.byteLength).setUint32(0, n, false); - await fdMPCParams.write(buffSize); - } - } - //#endregion - //#region src/zkey_import_bellman.js - async function phase2importMPCParams(zkeyNameOld, mpcparamsName, zkeyNameNew, name, logger) { - const { fd: fdZKeyOld, sections: sectionsZKeyOld } = await _iden3_binfileutils.readBinFile(zkeyNameOld, "zkey", 2); - const zkeyHeader = await readHeader$1(fdZKeyOld, sectionsZKeyOld, false); - if (zkeyHeader.protocol != "groth16") throw new Error("zkey file is not groth16"); - const curve = await getCurveFromQ(zkeyHeader.q); - const sG1 = curve.G1.F.n8 * 2; - const sG2 = curve.G2.F.n8 * 2; - const oldMPCParams = await readMPCParams(fdZKeyOld, curve, sectionsZKeyOld); - const newMPCParams = {}; - const fdMPCParams = await w(mpcparamsName); - fdMPCParams.pos = sG1 * 3 + sG2 * 3 + 8 + sG1 * zkeyHeader.nVars + 4 + sG1 * (zkeyHeader.domainSize - 1) + 4 + sG1 * zkeyHeader.nVars + 4 + sG1 * zkeyHeader.nVars + 4 + sG2 * zkeyHeader.nVars; - newMPCParams.csHash = await fdMPCParams.read(64); - const nContributions = await fdMPCParams.readUBE32(); - newMPCParams.contributions = []; - for (let i = 0; i < nContributions; i++) { - const c = { delta: {} }; - c.deltaAfter = await readG1(fdMPCParams); - c.delta.g1_s = await readG1(fdMPCParams); - c.delta.g1_sx = await readG1(fdMPCParams); - c.delta.g2_spx = await readG2(fdMPCParams); - c.transcript = await fdMPCParams.read(64); - if (i < oldMPCParams.contributions.length) { - c.type = oldMPCParams.contributions[i].type; - if (c.type == 1) { - c.beaconHash = oldMPCParams.contributions[i].beaconHash; - c.numIterationsExp = oldMPCParams.contributions[i].numIterationsExp; - } - if (oldMPCParams.contributions[i].name) c.name = oldMPCParams.contributions[i].name; - } - newMPCParams.contributions.push(c); - } - if (!hashIsEqual(newMPCParams.csHash, oldMPCParams.csHash)) { - if (logger) logger.error("Hash of the original circuit does not match with the MPC one"); - return false; - } - if (oldMPCParams.contributions.length > newMPCParams.contributions.length) { - if (logger) logger.error("The impoerted file does not include new contributions"); - return false; - } - for (let i = 0; i < oldMPCParams.contributions.length; i++) if (!contributionIsEqual(oldMPCParams.contributions[i], newMPCParams.contributions[i])) { - if (logger) logger.error(`Previous contribution ${i} does not match`); - return false; - } - if (name) for (let i = oldMPCParams.contributions.length; i < newMPCParams.contributions.length; i++) newMPCParams.contributions[i].name = name; - const fdZKeyNew = await _iden3_binfileutils.createBinFile(zkeyNameNew, "zkey", 1, 10); - fdMPCParams.pos = 0; - fdMPCParams.pos += sG1; - fdMPCParams.pos += sG1; - fdMPCParams.pos += sG2; - fdMPCParams.pos += sG2; - zkeyHeader.vk_delta_1 = await readG1(fdMPCParams); - zkeyHeader.vk_delta_2 = await readG2(fdMPCParams); - await writeHeader(fdZKeyNew, zkeyHeader); - if (await fdMPCParams.readUBE32() != zkeyHeader.nPublic + 1) { - if (logger) logger.error("Invalid number of points in IC"); - await fdZKeyNew.discard(); - return false; - } - fdMPCParams.pos += sG1 * (zkeyHeader.nPublic + 1); - await _iden3_binfileutils.copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 3); - await _iden3_binfileutils.copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 4); - if (await fdMPCParams.readUBE32() != zkeyHeader.domainSize - 1) { - if (logger) logger.error("Invalid number of points in H"); - await fdZKeyNew.discard(); - return false; - } - let buffH; - const buffTauU = await fdMPCParams.read(sG1 * (zkeyHeader.domainSize - 1)); - const buffTauLEM = await curve.G1.batchUtoLEM(buffTauU); - buffH = new Uint8Array(zkeyHeader.domainSize * sG1); - buffH.set(buffTauLEM); - curve.G1.toRprLEM(buffH, sG1 * (zkeyHeader.domainSize - 1), curve.G1.zeroAffine); - const n2Inv = curve.Fr.neg(curve.Fr.inv(curve.Fr.e(2))); - const wInv = curve.Fr.inv(curve.Fr.w[zkeyHeader.power + 1]); - buffH = await curve.G1.batchApplyKey(buffH, n2Inv, wInv, "affine", "jacobian", logger); - buffH = await curve.G1.ifft(buffH, "jacobian", "affine", logger); - await _iden3_binfileutils.startWriteSection(fdZKeyNew, 9); - await fdZKeyNew.write(buffH); - await _iden3_binfileutils.endWriteSection(fdZKeyNew); - if (await fdMPCParams.readUBE32() != zkeyHeader.nVars - zkeyHeader.nPublic - 1) { - if (logger) logger.error("Invalid number of points in L"); - await fdZKeyNew.discard(); - return false; - } - let buffL; - buffL = await fdMPCParams.read(sG1 * (zkeyHeader.nVars - zkeyHeader.nPublic - 1)); - buffL = await curve.G1.batchUtoLEM(buffL); - await _iden3_binfileutils.startWriteSection(fdZKeyNew, 8); - await fdZKeyNew.write(buffL); - await _iden3_binfileutils.endWriteSection(fdZKeyNew); - if (await fdMPCParams.readUBE32() != zkeyHeader.nVars) { - if (logger) logger.error("Invalid number of points in A"); - await fdZKeyNew.discard(); - return false; - } - fdMPCParams.pos += sG1 * zkeyHeader.nVars; - await _iden3_binfileutils.copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 5); - if (await fdMPCParams.readUBE32() != zkeyHeader.nVars) { - if (logger) logger.error("Invalid number of points in B1"); - await fdZKeyNew.discard(); - return false; - } - fdMPCParams.pos += sG1 * zkeyHeader.nVars; - await _iden3_binfileutils.copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 6); - if (await fdMPCParams.readUBE32() != zkeyHeader.nVars) { - if (logger) logger.error("Invalid number of points in B2"); - await fdZKeyNew.discard(); - return false; - } - fdMPCParams.pos += sG2 * zkeyHeader.nVars; - await _iden3_binfileutils.copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 7); - await writeMPCParams(fdZKeyNew, curve, newMPCParams); - await fdMPCParams.close(); - await fdZKeyNew.close(); - await fdZKeyOld.close(); - return true; - async function readG1(fd) { - const buff = await fd.read(curve.G1.F.n8 * 2); - return curve.G1.fromRprUncompressed(buff, 0); - } - async function readG2(fd) { - const buff = await fd.read(curve.G2.F.n8 * 2); - return curve.G2.fromRprUncompressed(buff, 0); - } - function contributionIsEqual(c1, c2) { - if (!curve.G1.eq(c1.deltaAfter, c2.deltaAfter)) return false; - if (!curve.G1.eq(c1.delta.g1_s, c2.delta.g1_s)) return false; - if (!curve.G1.eq(c1.delta.g1_sx, c2.delta.g1_sx)) return false; - if (!curve.G2.eq(c1.delta.g2_spx, c2.delta.g2_spx)) return false; - if (!hashIsEqual(c1.transcript, c2.transcript)) return false; - return true; - } - } - //#endregion - //#region src/zkey_verify_frominit.js - var sameRatio = sameRatio$2; - async function phase2verifyFromInit(initFileName, pTauFileName, zkeyFileName, logger) { - let sr; - const { fd, sections } = await _iden3_binfileutils.readBinFile(zkeyFileName, "zkey", 2); - const zkey = await readHeader$1(fd, sections, false); - if (zkey.protocol != "groth16") throw new Error("zkey file is not groth16"); - const curve = await getCurveFromQ(zkey.q); - const sG1 = curve.G1.F.n8 * 2; - const mpcParams = await readMPCParams(fd, curve, sections); - const accumulatedHasher = blake2b.create({ dkLen: 64 }); - accumulatedHasher.update(mpcParams.csHash); - let curDelta = curve.G1.g; - for (let i = 0; i < mpcParams.contributions.length; i++) { - const c = mpcParams.contributions[i]; - const ourHasher = cloneHasher(accumulatedHasher); - hashG1(ourHasher, curve, c.delta.g1_s); - hashG1(ourHasher, curve, c.delta.g1_sx); - if (!hashIsEqual(ourHasher.digest(), c.transcript)) { - console.log(`INVALID(${i}): Inconsistent transcript `); - return false; - } - const delta_g2_sp = hashToG2(curve, c.transcript); - sr = await sameRatio(curve, c.delta.g1_s, c.delta.g1_sx, delta_g2_sp, c.delta.g2_spx); - if (sr !== true) { - console.log(`INVALID(${i}): public key G1 and G2 do not have the same ration `); - return false; - } - sr = await sameRatio(curve, curDelta, c.deltaAfter, delta_g2_sp, c.delta.g2_spx); - if (sr !== true) { - console.log(`INVALID(${i}): deltaAfter does not fillow the public key `); - return false; - } - if (c.type == 1) { - const rng = await rngFromBeaconParams(c.beaconHash, c.numIterationsExp); - const expected_prvKey = curve.Fr.fromRng(rng); - const expected_g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); - const expected_g1_sx = curve.G1.toAffine(curve.G1.timesFr(expected_g1_s, expected_prvKey)); - if (curve.G1.eq(expected_g1_s, c.delta.g1_s) !== true) { - console.log(`INVALID(${i}): Key of the beacon does not match. g1_s `); - return false; - } - if (curve.G1.eq(expected_g1_sx, c.delta.g1_sx) !== true) { - console.log(`INVALID(${i}): Key of the beacon does not match. g1_sx `); - return false; - } - } - hashPubKey(accumulatedHasher, curve, c); - const contributionHasher = blake2b.create({ dkLen: 64 }); - hashPubKey(contributionHasher, curve, c); - c.contributionHash = contributionHasher.digest(); - curDelta = c.deltaAfter; - } - const { fd: fdInit, sections: sectionsInit } = await _iden3_binfileutils.readBinFile(initFileName, "zkey", 2); - const zkeyInit = await readHeader$1(fdInit, sectionsInit, false); - if (zkeyInit.protocol != "groth16") throw new Error("zkeyinit file is not groth16"); - if (!ffjavascript.Scalar.eq(zkeyInit.q, zkey.q) || !ffjavascript.Scalar.eq(zkeyInit.r, zkey.r) || zkeyInit.n8q != zkey.n8q || zkeyInit.n8r != zkey.n8r) { - if (logger) logger.error("INVALID: Different curves"); - return false; - } - if (zkeyInit.nVars != zkey.nVars || zkeyInit.nPublic != zkey.nPublic || zkeyInit.domainSize != zkey.domainSize) { - if (logger) logger.error("INVALID: Different circuit parameters"); - return false; - } - if (!curve.G1.eq(zkey.vk_alpha_1, zkeyInit.vk_alpha_1)) { - if (logger) logger.error("INVALID: Invalid alpha1"); - return false; - } - if (!curve.G1.eq(zkey.vk_beta_1, zkeyInit.vk_beta_1)) { - if (logger) logger.error("INVALID: Invalid beta1"); - return false; - } - if (!curve.G2.eq(zkey.vk_beta_2, zkeyInit.vk_beta_2)) { - if (logger) logger.error("INVALID: Invalid beta2"); - return false; - } - if (!curve.G2.eq(zkey.vk_gamma_2, zkeyInit.vk_gamma_2)) { - if (logger) logger.error("INVALID: Invalid gamma2"); - return false; - } - if (!curve.G1.eq(zkey.vk_delta_1, curDelta)) { - if (logger) logger.error("INVALID: Invalid delta1"); - return false; - } - sr = await sameRatio(curve, curve.G1.g, curDelta, curve.G2.g, zkey.vk_delta_2); - if (sr !== true) { - if (logger) logger.error("INVALID: Invalid delta2"); - return false; - } - const mpcParamsInit = await readMPCParams(fdInit, curve, sectionsInit); - if (!hashIsEqual(mpcParams.csHash, mpcParamsInit.csHash)) { - if (logger) logger.error("INVALID: Circuit does not match"); - return false; - } - if (sections[8][0].size != sG1 * (zkey.nVars - zkey.nPublic - 1)) { - if (logger) logger.error("INVALID: Invalid L section size"); - return false; - } - if (sections[9][0].size != sG1 * zkey.domainSize) { - if (logger) logger.error("INVALID: Invalid H section size"); - return false; - } - let ss; - ss = await _iden3_binfileutils.sectionIsEqual(fd, sections, fdInit, sectionsInit, 3); - if (!ss) { - if (logger) logger.error("INVALID: IC section is not identical"); - return false; - } - ss = await _iden3_binfileutils.sectionIsEqual(fd, sections, fdInit, sectionsInit, 4); - if (!ss) { - if (logger) logger.error("Coeffs section is not identical"); - return false; - } - ss = await _iden3_binfileutils.sectionIsEqual(fd, sections, fdInit, sectionsInit, 5); - if (!ss) { - if (logger) logger.error("A section is not identical"); - return false; - } - ss = await _iden3_binfileutils.sectionIsEqual(fd, sections, fdInit, sectionsInit, 6); - if (!ss) { - if (logger) logger.error("B1 section is not identical"); - return false; - } - ss = await _iden3_binfileutils.sectionIsEqual(fd, sections, fdInit, sectionsInit, 7); - if (!ss) { - if (logger) logger.error("B2 section is not identical"); - return false; - } - sr = await sectionHasSameRatio("G1", fdInit, sectionsInit, fd, sections, 8, zkey.vk_delta_2, zkeyInit.vk_delta_2, "L section"); - if (sr !== true) { - if (logger) logger.error("L section does not match"); - return false; - } - sr = await sameRatioH(); - if (sr !== true) { - if (logger) logger.error("H section does not match"); - return false; - } - if (logger) logger.info(formatHash(mpcParams.csHash, "Circuit Hash: ")); - await fd.close(); - await fdInit.close(); - for (let i = mpcParams.contributions.length - 1; i >= 0; i--) { - const c = mpcParams.contributions[i]; - if (logger) logger.info("-------------------------"); - if (logger) logger.info(formatHash(c.contributionHash, `contribution #${i + 1} ${c.name ? c.name : ""}:`)); - if (c.type == 1) { - if (logger) logger.info(`Beacon generator: ${byteArray2hex(c.beaconHash)}`); - if (logger) logger.info(`Beacon iterations Exp: ${c.numIterationsExp}`); - } - } - if (logger) logger.info("-------------------------"); - if (logger) logger.info("ZKey Ok!"); - return true; - async function sectionHasSameRatio(groupName, fd1, sections1, fd2, sections2, idSection, g2sp, g2spx, sectionName) { - const MAX_CHUNK_SIZE = 1 << 20; - const G = curve[groupName]; - const sG = G.F.n8 * 2; - await _iden3_binfileutils.startReadUniqueSection(fd1, sections1, idSection); - await _iden3_binfileutils.startReadUniqueSection(fd2, sections2, idSection); - let R1 = G.zero; - let R2 = G.zero; - const nPoints = sections1[idSection][0].size / sG; - for (let i = 0; i < nPoints; i += MAX_CHUNK_SIZE) { - if (logger) logger.debug(`Same ratio check ${sectionName}: ${i}/${nPoints}`); - const n = Math.min(nPoints - i, MAX_CHUNK_SIZE); - const bases1 = await fd1.read(n * sG); - const bases2 = await fd2.read(n * sG); - const scalars = getRandomBytes(4 * n); - const r1 = await G.multiExpAffine(bases1, scalars); - const r2 = await G.multiExpAffine(bases2, scalars); - R1 = G.add(R1, r1); - R2 = G.add(R2, r2); - } - await _iden3_binfileutils.endReadSection(fd1); - await _iden3_binfileutils.endReadSection(fd2); - if (nPoints == 0) return true; - sr = await sameRatio(curve, R1, R2, g2sp, g2spx); - if (sr !== true) return false; - return true; - } - async function sameRatioH() { - const MAX_CHUNK_SIZE = 1 << 20; - const G = curve.G1; - const Fr = curve.Fr; - const sG = G.F.n8 * 2; - const { fd: fdPTau, sections: sectionsPTau } = await _iden3_binfileutils.readBinFile(pTauFileName, "ptau", 1); - let buff_r = new ffjavascript.BigBuffer(zkey.domainSize * zkey.n8r); - const seed = new Array(8); - for (let i = 0; i < 8; i++) seed[i] = readUInt32BE(getRandomBytes(4), 0); - const rng = new ffjavascript.ChaCha(seed); - for (let i = 0; i < zkey.domainSize - 1; i++) { - const e = Fr.fromRng(rng); - Fr.toRprLE(buff_r, i * zkey.n8r, e); - } - Fr.toRprLE(buff_r, (zkey.domainSize - 1) * zkey.n8r, Fr.zero); - let R1 = G.zero; - for (let i = 0; i < zkey.domainSize; i += MAX_CHUNK_SIZE) { - if (logger) logger.debug(`H Verification(tau): ${i}/${zkey.domainSize}`); - const n = Math.min(zkey.domainSize - i, MAX_CHUNK_SIZE); - const buffB = await batchSubtract(await fdPTau.read(sG * n, sectionsPTau[2][0].p + zkey.domainSize * sG + i * sG), await fdPTau.read(sG * n, sectionsPTau[2][0].p + i * sG)); - const buffS = buff_r.slice(i * zkey.n8r, (i + n) * zkey.n8r); - const r = await G.multiExpAffine(buffB, buffS); - R1 = G.add(R1, r); - } - buff_r = await Fr.batchToMontgomery(buff_r); - let first; - if (zkey.power < Fr.s) first = Fr.neg(Fr.e(2)); - else { - const small_m = 2 ** Fr.s; - const shift_to_small_m = Fr.exp(Fr.shift, small_m); - first = Fr.sub(shift_to_small_m, Fr.one); - } - const inc = zkey.power < Fr.s ? Fr.w[zkey.power + 1] : Fr.shift; - buff_r = await Fr.batchApplyKey(buff_r, first, inc); - buff_r = await Fr.fft(buff_r); - buff_r = await Fr.batchFromMontgomery(buff_r); - await _iden3_binfileutils.startReadUniqueSection(fd, sections, 9); - let R2 = G.zero; - for (let i = 0; i < zkey.domainSize; i += MAX_CHUNK_SIZE) { - if (logger) logger.debug(`H Verification(lagrange): ${i}/${zkey.domainSize}`); - const n = Math.min(zkey.domainSize - i, MAX_CHUNK_SIZE); - const buff = await fd.read(sG * n); - const buffS = buff_r.slice(i * zkey.n8r, (i + n) * zkey.n8r); - const r = await G.multiExpAffine(buff, buffS); - R2 = G.add(R2, r); - } - await _iden3_binfileutils.endReadSection(fd); - sr = await sameRatio(curve, R1, R2, zkey.vk_delta_2, zkeyInit.vk_delta_2); - if (sr !== true) return false; - return true; - } - async function batchSubtract(buff1, buff2) { - const sG = curve.G1.F.n8 * 2; - const nPoints = buff1.byteLength / sG; - const concurrency = curve.tm.concurrency; - const nPointsPerThread = Math.floor(nPoints / concurrency); - const opPromises = []; - for (let i = 0; i < concurrency; i++) { - let n; - if (i < concurrency - 1) n = nPointsPerThread; - else n = nPoints - i * nPointsPerThread; - if (n == 0) continue; - const subBuff1 = buff1.slice(i * nPointsPerThread * sG1, (i * nPointsPerThread + n) * sG1); - const subBuff2 = buff2.slice(i * nPointsPerThread * sG1, (i * nPointsPerThread + n) * sG1); - opPromises.push(batchSubtractThread(subBuff1, subBuff2)); - } - const result = await Promise.all(opPromises); - const fullBuffOut = new Uint8Array(nPoints * sG); - let p = 0; - for (let i = 0; i < result.length; i++) { - fullBuffOut.set(result[i][0], p); - p += result[i][0].byteLength; - } - return fullBuffOut; - } - async function batchSubtractThread(buff1, buff2) { - const sG1 = curve.G1.F.n8 * 2; - const sGmid = curve.G1.F.n8 * 3; - const nPoints = buff1.byteLength / sG1; - const task = []; - task.push({ - cmd: "ALLOCSET", - var: 0, - buff: buff1 - }); - task.push({ - cmd: "ALLOCSET", - var: 1, - buff: buff2 - }); - task.push({ - cmd: "ALLOC", - var: 2, - len: nPoints * sGmid - }); - for (let i = 0; i < nPoints; i++) task.push({ - cmd: "CALL", - fnName: "g1m_subAffine", - params: [ - { - var: 0, - offset: i * sG1 - }, - { - var: 1, - offset: i * sG1 - }, - { - var: 2, - offset: i * sGmid - } - ] - }); - task.push({ - cmd: "CALL", - fnName: "g1m_batchToAffine", - params: [ - { var: 2 }, - { val: nPoints }, - { var: 2 } - ] - }); - task.push({ - cmd: "GET", - out: 0, - var: 2, - len: nPoints * sG1 - }); - return await curve.tm.queueAction(task); - } - } - //#endregion - //#region src/zkey_verify_fromr1cs.js - async function phase2verifyFromR1cs(r1csFileName, pTauFileName, zkeyFileName, logger) { - const initFileName = { type: "bigMem" }; - await newZKey(r1csFileName, pTauFileName, initFileName, logger); - return await phase2verifyFromInit(initFileName, pTauFileName, zkeyFileName, logger); - } - //#endregion - //#region src/zkey_contribute.js - async function phase2contribute(zkeyNameOld, zkeyNameNew, name, entropy, logger) { - const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(zkeyNameOld, "zkey", 2); - const zkey = await readHeader$1(fdOld, sections); - if (zkey.protocol != "groth16") throw new Error("zkey file is not groth16"); - const curve = await getCurveFromQ(zkey.q); - const mpcParams = await readMPCParams(fdOld, curve, sections); - const fdNew = await _iden3_binfileutils.createBinFile(zkeyNameNew, "zkey", 1, 10); - const rng = await getRandomRng(entropy); - const transcriptHasher = blake2b.create({ dkLen: 64 }); - transcriptHasher.update(mpcParams.csHash); - for (let i = 0; i < mpcParams.contributions.length; i++) hashPubKey(transcriptHasher, curve, mpcParams.contributions[i]); - const curContribution = {}; - curContribution.delta = {}; - curContribution.delta.prvKey = curve.Fr.fromRng(rng); - curContribution.delta.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); - curContribution.delta.g1_sx = curve.G1.toAffine(curve.G1.timesFr(curContribution.delta.g1_s, curContribution.delta.prvKey)); - hashG1(transcriptHasher, curve, curContribution.delta.g1_s); - hashG1(transcriptHasher, curve, curContribution.delta.g1_sx); - curContribution.transcript = transcriptHasher.digest(); - curContribution.delta.g2_sp = hashToG2(curve, curContribution.transcript); - curContribution.delta.g2_spx = curve.G2.toAffine(curve.G2.timesFr(curContribution.delta.g2_sp, curContribution.delta.prvKey)); - zkey.vk_delta_1 = curve.G1.timesFr(zkey.vk_delta_1, curContribution.delta.prvKey); - zkey.vk_delta_2 = curve.G2.timesFr(zkey.vk_delta_2, curContribution.delta.prvKey); - curContribution.deltaAfter = zkey.vk_delta_1; - curContribution.type = 0; - if (name) curContribution.name = name; - mpcParams.contributions.push(curContribution); - await writeHeader(fdNew, zkey); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 3); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 4); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 5); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 6); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 7); - const invDelta = curve.Fr.inv(curContribution.delta.prvKey); - await applyKeyToSection(fdOld, sections, fdNew, 8, curve, "G1", invDelta, curve.Fr.e(1), "L Section", logger); - await applyKeyToSection(fdOld, sections, fdNew, 9, curve, "G1", invDelta, curve.Fr.e(1), "H Section", logger); - await writeMPCParams(fdNew, curve, mpcParams); - await fdOld.close(); - await fdNew.close(); - const contributionHasher = blake2b.create({ dkLen: 64 }); - hashPubKey(contributionHasher, curve, curContribution); - const contributionHash = contributionHasher.digest(); - if (logger) logger.info(formatHash(mpcParams.csHash, "Circuit Hash: ")); - if (logger) logger.info(formatHash(contributionHash, "Contribution Hash: ")); - return contributionHash; - } - //#endregion - //#region src/zkey_beacon.js - async function beacon(zkeyNameOld, zkeyNameNew, name, beaconHashStr, numIterationsExp, logger) { - const beaconHash = hex2ByteArray(beaconHashStr); - if (beaconHash.byteLength == 0 || beaconHash.byteLength * 2 != beaconHashStr.length) { - if (logger) logger.error("Invalid Beacon Hash. (It must be a valid hexadecimal sequence)"); - return false; - } - if (beaconHash.length >= 256) { - if (logger) logger.error("Maximum length of beacon hash is 255 bytes"); - return false; - } - numIterationsExp = parseInt(numIterationsExp); - if (numIterationsExp < 10 || numIterationsExp > 63) { - if (logger) logger.error("Invalid numIterationsExp. (Must be between 10 and 63)"); - return false; - } - const { fd: fdOld, sections } = await _iden3_binfileutils.readBinFile(zkeyNameOld, "zkey", 2); - const zkey = await readHeader$1(fdOld, sections); - if (zkey.protocol != "groth16") throw new Error("zkey file is not groth16"); - const curve = await getCurveFromQ(zkey.q); - const mpcParams = await readMPCParams(fdOld, curve, sections); - const fdNew = await _iden3_binfileutils.createBinFile(zkeyNameNew, "zkey", 1, 10); - const rng = await rngFromBeaconParams(beaconHash, numIterationsExp); - const transcriptHasher = blake2b.create({ dkLen: 64 }); - transcriptHasher.update(mpcParams.csHash); - for (let i = 0; i < mpcParams.contributions.length; i++) hashPubKey(transcriptHasher, curve, mpcParams.contributions[i]); - const curContribution = {}; - curContribution.delta = {}; - curContribution.delta.prvKey = curve.Fr.fromRng(rng); - curContribution.delta.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); - curContribution.delta.g1_sx = curve.G1.toAffine(curve.G1.timesFr(curContribution.delta.g1_s, curContribution.delta.prvKey)); - hashG1(transcriptHasher, curve, curContribution.delta.g1_s); - hashG1(transcriptHasher, curve, curContribution.delta.g1_sx); - curContribution.transcript = transcriptHasher.digest(); - curContribution.delta.g2_sp = hashToG2(curve, curContribution.transcript); - curContribution.delta.g2_spx = curve.G2.toAffine(curve.G2.timesFr(curContribution.delta.g2_sp, curContribution.delta.prvKey)); - zkey.vk_delta_1 = curve.G1.timesFr(zkey.vk_delta_1, curContribution.delta.prvKey); - zkey.vk_delta_2 = curve.G2.timesFr(zkey.vk_delta_2, curContribution.delta.prvKey); - curContribution.deltaAfter = zkey.vk_delta_1; - curContribution.type = 1; - curContribution.numIterationsExp = numIterationsExp; - curContribution.beaconHash = beaconHash; - if (name) curContribution.name = name; - mpcParams.contributions.push(curContribution); - await writeHeader(fdNew, zkey); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 3); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 4); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 5); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 6); - await _iden3_binfileutils.copySection(fdOld, sections, fdNew, 7); - const invDelta = curve.Fr.inv(curContribution.delta.prvKey); - await applyKeyToSection(fdOld, sections, fdNew, 8, curve, "G1", invDelta, curve.Fr.e(1), "L Section", logger); - await applyKeyToSection(fdOld, sections, fdNew, 9, curve, "G1", invDelta, curve.Fr.e(1), "H Section", logger); - await writeMPCParams(fdNew, curve, mpcParams); - await fdOld.close(); - await fdNew.close(); - const contributionHasher = blake2b.create({ dkLen: 64 }); - hashPubKey(contributionHasher, curve, curContribution); - const contributionHash = contributionHasher.digest(); - if (logger) logger.info(formatHash(contributionHash, "Contribution Hash: ")); - return contributionHash; - } - //#endregion - //#region src/zkey_export_json.js - async function zkeyExportJson(zkeyFileName) { - const zKey = await readZKey(zkeyFileName, true); - delete zKey.curve; - delete zKey.F; - return ffjavascript.utils.stringifyBigInts(zKey); - } - //#endregion - //#region src/zkey_bellman_contribute.js - async function bellmanContribute(curve, challengeFilename, responseFileName, entropy, logger) { - const rng = await getRandomRng(entropy); - const delta = curve.Fr.fromRng(rng); - const invDelta = curve.Fr.inv(delta); - const sG1 = curve.G1.F.n8 * 2; - const sG2 = curve.G2.F.n8 * 2; - const fdFrom = await w(challengeFilename); - const fdTo = await S(responseFileName); - await copy(sG1); - await copy(sG1); - await copy(sG2); - await copy(sG2); - const oldDelta1 = await readG1(); - const delta1 = curve.G1.timesFr(oldDelta1, delta); - await writeG1(delta1); - const oldDelta2 = await readG2(); - await writeG2(curve.G2.timesFr(oldDelta2, delta)); - const nIC = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nIC); - await copy(nIC * sG1); - const nH = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nH); - await applyKeyToChallengeSection(fdFrom, fdTo, null, curve, "G1", nH, invDelta, curve.Fr.e(1), "UNCOMPRESSED", "H", logger); - const nL = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nL); - await applyKeyToChallengeSection(fdFrom, fdTo, null, curve, "G1", nL, invDelta, curve.Fr.e(1), "UNCOMPRESSED", "L", logger); - const nA = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nA); - await copy(nA * sG1); - const nB1 = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nB1); - await copy(nB1 * sG1); - const nB2 = await fdFrom.readUBE32(); - await fdTo.writeUBE32(nB2); - await copy(nB2 * sG2); - const transcriptHasher = blake2b.create({ dkLen: 64 }); - const mpcParams = {}; - mpcParams.csHash = await fdFrom.read(64); - transcriptHasher.update(mpcParams.csHash); - const nContributions = await fdFrom.readUBE32(); - mpcParams.contributions = []; - for (let i = 0; i < nContributions; i++) { - const c = { delta: {} }; - c.deltaAfter = await readG1(); - c.delta.g1_s = await readG1(); - c.delta.g1_sx = await readG1(); - c.delta.g2_spx = await readG2(); - c.transcript = await fdFrom.read(64); - mpcParams.contributions.push(c); - hashPubKey(transcriptHasher, curve, c); - } - const curContribution = {}; - curContribution.delta = {}; - curContribution.delta.prvKey = delta; - curContribution.delta.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng)); - curContribution.delta.g1_sx = curve.G1.toAffine(curve.G1.timesFr(curContribution.delta.g1_s, delta)); - hashG1(transcriptHasher, curve, curContribution.delta.g1_s); - hashG1(transcriptHasher, curve, curContribution.delta.g1_sx); - curContribution.transcript = transcriptHasher.digest(); - curContribution.delta.g2_sp = hashToG2(curve, curContribution.transcript); - curContribution.delta.g2_spx = curve.G2.toAffine(curve.G2.timesFr(curContribution.delta.g2_sp, delta)); - curContribution.deltaAfter = delta1; - curContribution.type = 0; - mpcParams.contributions.push(curContribution); - await fdTo.write(mpcParams.csHash); - await fdTo.writeUBE32(mpcParams.contributions.length); - for (let i = 0; i < mpcParams.contributions.length; i++) { - const c = mpcParams.contributions[i]; - await writeG1(c.deltaAfter); - await writeG1(c.delta.g1_s); - await writeG1(c.delta.g1_sx); - await writeG2(c.delta.g2_spx); - await fdTo.write(c.transcript); - } - const contributionHasher = blake2b.create({ dkLen: 64 }); - hashPubKey(contributionHasher, curve, curContribution); - const contributionHash = contributionHasher.digest(); - if (logger) logger.info(formatHash(contributionHash, "Contribution Hash: ")); - await fdTo.close(); - await fdFrom.close(); - return contributionHash; - async function copy(nBytes) { - const CHUNK_SIZE = fdFrom.pageSize * 2; - for (let i = 0; i < nBytes; i += CHUNK_SIZE) { - const n = Math.min(nBytes - i, CHUNK_SIZE); - const buff = await fdFrom.read(n); - await fdTo.write(buff); - } - } - async function readG1() { - const buff = await fdFrom.read(curve.G1.F.n8 * 2); - return curve.G1.fromRprUncompressed(buff, 0); - } - async function readG2() { - const buff = await fdFrom.read(curve.G2.F.n8 * 2); - return curve.G2.fromRprUncompressed(buff, 0); - } - async function writeG1(P) { - const buff = new Uint8Array(sG1); - curve.G1.toRprUncompressed(buff, 0, P); - await fdTo.write(buff); - } - async function writeG2(P) { - const buff = new Uint8Array(sG2); - curve.G2.toRprUncompressed(buff, 0, P); - await fdTo.write(buff); - } - } - //#endregion - //#region src/zkey_export_verificationkey.js - var { stringifyBigInts: stringifyBigInts$2 } = ffjavascript.utils; - async function zkeyExportVerificationKey(zkeyName, logger) { - if (logger) logger.info("EXPORT VERIFICATION KEY STARTED"); - const { fd, sections } = await _iden3_binfileutils.readBinFile(zkeyName, "zkey", 2); - const zkey = await readHeader$1(fd, sections); - if (logger) logger.info("> Detected protocol: " + zkey.protocol); - let res; - if (zkey.protocol === "groth16") res = await groth16Vk(zkey, fd, sections); - else if (zkey.protocol === "plonk") res = await plonkVk(zkey); - else if (zkey.protocolId && zkey.protocolId === 10) res = await exportFFlonkVk(zkey, logger); - else throw new Error("zkey file protocol unrecognized"); - await fd.close(); - if (logger) logger.info("EXPORT VERIFICATION KEY FINISHED"); - return res; - } - async function groth16Vk(zkey, fd, sections) { - const curve = await getCurveFromQ(zkey.q); - const sG1 = curve.G1.F.n8 * 2; - const alphaBeta = await curve.pairing(zkey.vk_alpha_1, zkey.vk_beta_2); - let vKey = { - protocol: zkey.protocol, - curve: curve.name, - nPublic: zkey.nPublic, - vk_alpha_1: curve.G1.toObject(zkey.vk_alpha_1), - vk_beta_2: curve.G2.toObject(zkey.vk_beta_2), - vk_gamma_2: curve.G2.toObject(zkey.vk_gamma_2), - vk_delta_2: curve.G2.toObject(zkey.vk_delta_2), - vk_alphabeta_12: curve.Gt.toObject(alphaBeta) - }; - await _iden3_binfileutils.startReadUniqueSection(fd, sections, 3); - vKey.IC = []; - for (let i = 0; i <= zkey.nPublic; i++) { - const buff = await fd.read(sG1); - const P = curve.G1.toObject(buff); - vKey.IC.push(P); - } - await _iden3_binfileutils.endReadSection(fd); - vKey = stringifyBigInts$2(vKey); - return vKey; - } - async function plonkVk(zkey) { - const curve = await getCurveFromQ(zkey.q); - let vKey = { - protocol: zkey.protocol, - curve: curve.name, - nPublic: zkey.nPublic, - power: zkey.power, - k1: curve.Fr.toObject(zkey.k1), - k2: curve.Fr.toObject(zkey.k2), - Qm: curve.G1.toObject(zkey.Qm), - Ql: curve.G1.toObject(zkey.Ql), - Qr: curve.G1.toObject(zkey.Qr), - Qo: curve.G1.toObject(zkey.Qo), - Qc: curve.G1.toObject(zkey.Qc), - S1: curve.G1.toObject(zkey.S1), - S2: curve.G1.toObject(zkey.S2), - S3: curve.G1.toObject(zkey.S3), - X_2: curve.G2.toObject(zkey.X_2), - w: curve.Fr.toObject(curve.Fr.w[zkey.power]) - }; - vKey = stringifyBigInts$2(vKey); - return vKey; - } - async function exportFFlonkVk(zkey, _logger) { - const curve = await getCurveFromQ(zkey.q); - return stringifyBigInts$2({ - protocol: zkey.protocol, - curve: curve.name, - nPublic: zkey.nPublic, - power: zkey.power, - k1: curve.Fr.toObject(zkey.k1), - k2: curve.Fr.toObject(zkey.k2), - w: curve.Fr.toObject(curve.Fr.w[zkey.power]), - w3: curve.Fr.toObject(zkey.w3), - w4: curve.Fr.toObject(zkey.w4), - w8: curve.Fr.toObject(zkey.w8), - wr: curve.Fr.toObject(zkey.wr), - X_2: curve.G2.toObject(zkey.X_2), - C0: curve.G1.toObject(zkey.C0) - }); - } - //#endregion - //#region src/zkey.js - var zkey_exports = /* @__PURE__ */ __exportAll({ - beacon: () => beacon, - bellmanContribute: () => bellmanContribute, - contribute: () => phase2contribute, - exportBellman: () => phase2exportMPCParams, - exportJson: () => zkeyExportJson, - exportSolidityVerifier: () => null, - exportVerificationKey: () => zkeyExportVerificationKey, - importBellman: () => phase2importMPCParams, - newZKey: () => newZKey, - verifyFromInit: () => phase2verifyFromInit, - verifyFromR1cs: () => phase2verifyFromR1cs - }); - //#endregion - //#region src/plonk_setup.js - async function plonkSetup(r1csName, ptauName, zkeyName, logger) { - if (globalThis.gc) globalThis.gc(); - const { fd: fdPTau, sections: sectionsPTau } = await (0, _iden3_binfileutils.readBinFile)(ptauName, "ptau", 1, 1 << 22, 1 << 24); - const { curve, power } = await readPTauHeader(fdPTau, sectionsPTau); - const { fd: fdR1cs, sections: sectionsR1cs } = await (0, _iden3_binfileutils.readBinFile)(r1csName, "r1cs", 1, 1 << 22, 1 << 24); - const r1cs = await (0, r1csfile.readR1csFd)(fdR1cs, sectionsR1cs, { - loadConstraints: true, - loadCustomGates: true - }); - const sG1 = curve.G1.F.n8 * 2; - const G1 = curve.G1; - const sG2 = curve.G2.F.n8 * 2; - const Fr = curve.Fr; - const n8r = curve.Fr.n8; - if (logger) logger.info("Reading r1cs"); - await (0, _iden3_binfileutils.readSection)(fdR1cs, sectionsR1cs, 2); - const plonkConstraints = new BigArray(); - const plonkAdditions = new BigArray(); - let plonkNVars = r1cs.nVars; - const nPublic = r1cs.nOutputs + r1cs.nPubInputs; - await processConstraints(curve.Fr, r1cs, logger); - if (globalThis.gc) globalThis.gc(); - const fdZKey = await (0, _iden3_binfileutils.createBinFile)(zkeyName, "zkey", 1, 14, 1 << 22, 1 << 24); - if (r1cs.prime != curve.r) { - if (logger) logger.error("r1cs curve does not match powers of tau ceremony curve"); - return -1; - } - let cirPower = log2(plonkConstraints.length - 1) + 1; - if (cirPower < 3) cirPower = 3; - const domainSize = 2 ** cirPower; - if (logger) logger.info("Plonk constraints: " + plonkConstraints.length); - if (cirPower > power) { - if (logger) logger.error(`circuit too big for this power of tau ceremony. ${plonkConstraints.length} > 2**${power}`); - return -1; - } - if (!sectionsPTau[12]) { - if (logger) logger.error("Powers of tau is not prepared."); - return -1; - } - const LPoints = new ffjavascript.BigBuffer(domainSize * sG1); - const o = sectionsPTau[12][0].p + (2 ** cirPower - 1) * sG1; - await fdPTau.readToBuffer(LPoints, 0, domainSize * sG1, o); - const [k1, k2] = getK1K2(); - const vk = {}; - await writeAdditions(3, "Additions"); - if (globalThis.gc) globalThis.gc(); - await writeWitnessMap(4, 0, "Amap"); - if (globalThis.gc) globalThis.gc(); - await writeWitnessMap(5, 1, "Bmap"); - if (globalThis.gc) globalThis.gc(); - await writeWitnessMap(6, 2, "Cmap"); - if (globalThis.gc) globalThis.gc(); - await writeQMap(7, 3, "Qm"); - if (globalThis.gc) globalThis.gc(); - await writeQMap(8, 4, "Ql"); - if (globalThis.gc) globalThis.gc(); - await writeQMap(9, 5, "Qr"); - if (globalThis.gc) globalThis.gc(); - await writeQMap(10, 6, "Qo"); - if (globalThis.gc) globalThis.gc(); - await writeQMap(11, 7, "Qc"); - if (globalThis.gc) globalThis.gc(); - await writeSigma(12, "sigma"); - if (globalThis.gc) globalThis.gc(); - await writeLs(13, "lagrange polynomials"); - if (globalThis.gc) globalThis.gc(); - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 14); - const buffOut = new ffjavascript.BigBuffer((domainSize + 6) * sG1); - await fdPTau.readToBuffer(buffOut, 0, (domainSize + 6) * sG1, sectionsPTau[2][0].p); - await fdZKey.write(buffOut); - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - if (globalThis.gc) globalThis.gc(); - await writeHeaders(); - await fdZKey.close(); - await fdR1cs.close(); - await fdPTau.close(); - if (logger) logger.info("Setup Finished"); - return; - async function processConstraints(Fr, r1cs, logger) { - function normalize(linearComb) { - const ss = Object.keys(linearComb); - for (let i = 0; i < ss.length; i++) if (linearComb[ss[i]] == 0n) delete linearComb[ss[i]]; - } - function join(linearComb1, k, linearComb2) { - const res = {}; - for (let s in linearComb1) if (typeof res[s] == "undefined") res[s] = Fr.mul(k, linearComb1[s]); - else res[s] = Fr.add(res[s], Fr.mul(k, linearComb1[s])); - for (let s in linearComb2) if (typeof res[s] == "undefined") res[s] = linearComb2[s]; - else res[s] = Fr.add(res[s], linearComb2[s]); - normalize(res); - return res; - } - function reduceCoefs(linearComb, maxC) { - const res = { - k: Fr.zero, - s: [], - coefs: [] - }; - const cs = []; - for (let s in linearComb) if (s == 0) res.k = Fr.add(res.k, linearComb[s]); - else if (linearComb[s] != 0n) cs.push([Number(s), linearComb[s]]); - while (cs.length > maxC) { - const c1 = cs.shift(); - const c2 = cs.shift(); - const sl = c1[0]; - const sr = c2[0]; - const so = plonkNVars++; - const qm = Fr.zero; - const ql = Fr.neg(c1[1]); - const qr = Fr.neg(c2[1]); - const qo = Fr.one; - const qc = Fr.zero; - plonkConstraints.push([ - sl, - sr, - so, - qm, - ql, - qr, - qo, - qc - ]); - plonkAdditions.push([ - sl, - sr, - c1[1], - c2[1] - ]); - cs.push([so, Fr.one]); - } - for (let i = 0; i < cs.length; i++) { - res.s[i] = cs[i][0]; - res.coefs[i] = cs[i][1]; - } - while (res.coefs.length < maxC) { - res.s.push(0); - res.coefs.push(Fr.zero); - } - return res; - } - function addConstraintSum(lc) { - const C = reduceCoefs(lc, 3); - const sl = C.s[0]; - const sr = C.s[1]; - const so = C.s[2]; - const qm = Fr.zero; - const ql = C.coefs[0]; - const qr = C.coefs[1]; - const qo = C.coefs[2]; - const qc = C.k; - plonkConstraints.push([ - sl, - sr, - so, - qm, - ql, - qr, - qo, - qc - ]); - } - function addConstraintMul(lcA, lcB, lcC) { - const A = reduceCoefs(lcA, 1); - const B = reduceCoefs(lcB, 1); - const C = reduceCoefs(lcC, 1); - const sl = A.s[0]; - const sr = B.s[0]; - const so = C.s[0]; - const qm = Fr.mul(A.coefs[0], B.coefs[0]); - const ql = Fr.mul(A.coefs[0], B.k); - const qr = Fr.mul(A.k, B.coefs[0]); - const qo = Fr.neg(C.coefs[0]); - const qc = Fr.sub(Fr.mul(A.k, B.k), C.k); - plonkConstraints.push([ - sl, - sr, - so, - qm, - ql, - qr, - qo, - qc - ]); - } - function getLinearCombinationType(lc) { - let k = Fr.zero; - let n = 0; - const ss = Object.keys(lc); - for (let i = 0; i < ss.length; i++) if (lc[ss[i]] == 0n) delete lc[ss[i]]; - else if (ss[i] == 0) k = Fr.add(k, lc[ss[i]]); - else n++; - if (n > 0) return n.toString(); - if (k != Fr.zero) return "k"; - return "0"; - } - function process(lcA, lcB, lcC) { - const lctA = getLinearCombinationType(lcA); - const lctB = getLinearCombinationType(lcB); - if (lctA === "0" || lctB === "0") { - normalize(lcC); - addConstraintSum(lcC); - } else if (lctA === "k") addConstraintSum(join(lcB, lcA[0], lcC)); - else if (lctB === "k") addConstraintSum(join(lcA, lcB[0], lcC)); - else addConstraintMul(lcA, lcB, lcC); - } - for (let s = 1; s <= nPublic; s++) { - const sl = s; - const sr = 0; - const so = 0; - const qm = Fr.zero; - const ql = Fr.one; - const qr = Fr.zero; - const qo = Fr.zero; - const qc = Fr.zero; - plonkConstraints.push([ - sl, - sr, - so, - qm, - ql, - qr, - qo, - qc - ]); - } - for (let c = 0; c < r1cs.constraints.length; c++) { - if (logger && c % 1e4 === 0) logger.debug(`processing constraints: ${c}/${r1cs.nConstraints}`); - process(...r1cs.constraints[c]); - } - } - async function writeWitnessMap(sectionNum, posConstraint, name) { - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); - for (let i = 0; i < plonkConstraints.length; i++) { - await fdZKey.writeULE32(plonkConstraints[i][posConstraint]); - if (logger && i % 1e6 == 0) logger.debug(`writing ${name}: ${i}/${plonkConstraints.length}`); - } - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - } - async function writeQMap(sectionNum, posConstraint, name) { - let Q = new ffjavascript.BigBuffer(domainSize * n8r); - for (let i = 0; i < plonkConstraints.length; i++) { - Q.set(plonkConstraints[i][posConstraint], i * n8r); - if (logger && i % 1e6 == 0) logger.debug(`writing ${name}: ${i}/${plonkConstraints.length}`); - } - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); - await writeP4(Q); - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - Q = await Fr.batchFromMontgomery(Q); - vk[name] = await curve.G1.multiExpAffine(LPoints, Q, logger, "multiexp " + name); - } - async function writeP4(buff) { - const q = await Fr.ifft(buff); - const q4 = new ffjavascript.BigBuffer(domainSize * n8r * 4); - q4.set(q, 0); - const Q4 = await Fr.fft(q4); - await fdZKey.write(q); - await fdZKey.write(Q4); - } - async function writeAdditions(sectionNum, name) { - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); - const buffOut = new Uint8Array(8 + 2 * n8r); - const buffOutV = new DataView(buffOut.buffer); - for (let i = 0; i < plonkAdditions.length; i++) { - const addition = plonkAdditions[i]; - let o = 0; - buffOutV.setUint32(o, addition[0], true); - o += 4; - buffOutV.setUint32(o, addition[1], true); - o += 4; - buffOut.set(addition[2], o); - o += n8r; - buffOut.set(addition[3], o); - await fdZKey.write(buffOut); - if (logger && i % 1e6 == 0) logger.debug(`writing ${name}: ${i}/${plonkAdditions.length}`); - } - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - } - async function writeSigma(sectionNum, name) { - const sigma = new ffjavascript.BigBuffer(n8r * domainSize * 3); - const lastAparence = new BigArray(plonkNVars); - const firstPos = new BigArray(plonkNVars); - let w = Fr.one; - for (let i = 0; i < domainSize; i++) { - if (i < plonkConstraints.length) { - buildSigma(plonkConstraints[i][0], i); - buildSigma(plonkConstraints[i][1], domainSize + i); - buildSigma(plonkConstraints[i][2], domainSize * 2 + i); - } else { - buildSigma(0, i); - buildSigma(0, domainSize + i); - buildSigma(0, domainSize * 2 + i); - } - w = Fr.mul(w, Fr.w[cirPower]); - if (logger && i % 1e6 == 0) logger.debug(`writing ${name} phase1: ${i}/${plonkConstraints.length}`); - } - for (let s = 0; s < plonkNVars; s++) { - if (typeof firstPos[s] !== "undefined") sigma.set(lastAparence[s], firstPos[s] * n8r); - else console.log("Variable not used"); - if (logger && s % 1e6 == 0) logger.debug(`writing ${name} phase2: ${s}/${plonkNVars}`); - } - if (globalThis.gc) globalThis.gc(); - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); - let S1 = sigma.slice(0, domainSize * n8r); - await writeP4(S1); - if (globalThis.gc) globalThis.gc(); - let S2 = sigma.slice(domainSize * n8r, domainSize * n8r * 2); - await writeP4(S2); - if (globalThis.gc) globalThis.gc(); - let S3 = sigma.slice(domainSize * n8r * 2, domainSize * n8r * 3); - await writeP4(S3); - if (globalThis.gc) globalThis.gc(); - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - S1 = await Fr.batchFromMontgomery(S1); - S2 = await Fr.batchFromMontgomery(S2); - S3 = await Fr.batchFromMontgomery(S3); - vk.S1 = await curve.G1.multiExpAffine(LPoints, S1, logger, "multiexp S1"); - if (globalThis.gc) globalThis.gc(); - vk.S2 = await curve.G1.multiExpAffine(LPoints, S2, logger, "multiexp S2"); - if (globalThis.gc) globalThis.gc(); - vk.S3 = await curve.G1.multiExpAffine(LPoints, S3, logger, "multiexp S3"); - if (globalThis.gc) globalThis.gc(); - function buildSigma(s, p) { - if (typeof lastAparence[s] === "undefined") firstPos[s] = p; - else sigma.set(lastAparence[s], p * n8r); - let v; - if (p < domainSize) v = w; - else if (p < 2 * domainSize) v = Fr.mul(w, k1); - else v = Fr.mul(w, k2); - lastAparence[s] = v; - } - } - async function writeLs(sectionNum, name) { - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); - const l = Math.max(nPublic, 1); - for (let i = 0; i < l; i++) { - let buff = new ffjavascript.BigBuffer(domainSize * n8r); - buff.set(Fr.one, i * n8r); - await writeP4(buff); - if (logger) logger.debug(`writing ${name} ${i}/${l}`); - } - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - } - async function writeHeaders() { - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 1); - await fdZKey.writeULE32(2); - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 2); - const primeQ = curve.q; - const n8q = (Math.floor((ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) + 1) * 8; - const primeR = curve.r; - const n8r = (Math.floor((ffjavascript.Scalar.bitLength(primeR) - 1) / 64) + 1) * 8; - await fdZKey.writeULE32(n8q); - await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeQ, n8q); - await fdZKey.writeULE32(n8r); - await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeR, n8r); - await fdZKey.writeULE32(plonkNVars); - await fdZKey.writeULE32(nPublic); - await fdZKey.writeULE32(domainSize); - await fdZKey.writeULE32(plonkAdditions.length); - await fdZKey.writeULE32(plonkConstraints.length); - await fdZKey.write(k1); - await fdZKey.write(k2); - await fdZKey.write(G1.toAffine(vk.Qm)); - await fdZKey.write(G1.toAffine(vk.Ql)); - await fdZKey.write(G1.toAffine(vk.Qr)); - await fdZKey.write(G1.toAffine(vk.Qo)); - await fdZKey.write(G1.toAffine(vk.Qc)); - await fdZKey.write(G1.toAffine(vk.S1)); - await fdZKey.write(G1.toAffine(vk.S2)); - await fdZKey.write(G1.toAffine(vk.S3)); - let bX_2; - bX_2 = await fdPTau.read(sG2, sectionsPTau[3][0].p + sG2); - await fdZKey.write(bX_2); - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - } - function getK1K2() { - let k1 = Fr.two; - while (isIncluded(k1, [], cirPower)) Fr.add(k1, Fr.one); - let k2 = Fr.add(k1, Fr.one); - while (isIncluded(k2, [k1], cirPower)) Fr.add(k2, Fr.one); - return [k1, k2]; - function isIncluded(k, kArr, pow) { - const domainSize = 2 ** pow; - let w = Fr.one; - for (let i = 0; i < domainSize; i++) { - if (Fr.eq(k, w)) return true; - for (let j = 0; j < kArr.length; j++) if (Fr.eq(k, Fr.mul(kArr[j], w))) return true; - w = Fr.mul(w, Fr.w[pow]); - } - return false; - } - } - } - //#endregion - //#region src/proof.js - var Proof = class { - constructor(curve, logger) { - this.curve = curve; - this.logger = logger; - this.resetProof(); - } - resetProof() { - this.polynomials = {}; - this.evaluations = {}; - } - addPolynomial(key, polynomial) { - if (key in this.polynomials) this.logger.warn(`proof: polynomial.${key} already exist in proof`); - this.polynomials[key] = polynomial; - } - getPolynomial(key) { - if (!(key in this.polynomials)) this.logger.warn(`proof: polynomial ${key} does not exist in proof`); - return this.polynomials[key]; - } - addEvaluation(key, evaluation) { - if (key in this.evaluations) this.logger.warn(`proof: evaluations.${key} already exist in proof`); - this.evaluations[key] = evaluation; - } - getEvaluation(key) { - if (!(key in this.evaluations)) this.logger.warn(`proof: evaluation ${key} does not exist in proof`); - return this.evaluations[key]; - } - toObjectProof(splitFields = true) { - let res = splitFields ? { - polynomials: {}, - evaluations: {} - } : {}; - Object.keys(this.polynomials).forEach((key) => { - const value = this.curve.G1.toObject(this.polynomials[key]); - if (splitFields) res.polynomials[key] = value; - else res[key] = value; - }); - Object.keys(this.evaluations).forEach((key) => { - const value = this.curve.Fr.toObject(this.evaluations[key]); - if (splitFields) res.evaluations[key] = value; - else res[key] = value; - }); - return res; - } - fromObjectProof(objectProof) { - this.resetProof(); - Object.keys(objectProof.polynomials).forEach((key) => { - this.polynomials[key] = this.curve.G1.fromObject(objectProof.polynomials[key]); - }); - Object.keys(objectProof.evaluations).forEach((key) => { - this.evaluations[key] = this.curve.Fr.fromObject(objectProof.evaluations[key]); - }); - } - }; - //#endregion - //#region node_modules/@noble/hashes/sha3.js - /** - * SHA3 (keccak) hash function, based on a new "Sponge function" design. - * Different from older hashes, the internal state is bigger than output size. - * - * Check out - * {@link https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf | FIPS-202}, - * {@link https://keccak.team/keccak.html | Website}, and - * {@link https://crypto.stackexchange.com/q/15727 | the differences between - * SHA-3 and Keccak}. - * - * Check out `sha3-addons` module for cSHAKE, k12, and others. - * @module - */ - var _0n = BigInt(0); - var _1n = BigInt(1); - var _2n = BigInt(2); - var _7n = BigInt(7); - var _256n = BigInt(256); - var _0x71n = BigInt(113); - var SHA3_PI = []; - var SHA3_ROTL = []; - var _SHA3_IOTA = []; - for (let round = 0, R = _1n, x = 1, y = 0; round < 24; round++) { - [x, y] = [y, (2 * x + 3 * y) % 5]; - SHA3_PI.push(2 * (5 * y + x)); - SHA3_ROTL.push((round + 1) * (round + 2) / 2 % 64); - let t = _0n; - for (let j = 0; j < 7; j++) { - R = (R << _1n ^ (R >> _7n) * _0x71n) % _256n; - if (R & _2n) t ^= _1n << (_1n << BigInt(j)) - _1n; - } - _SHA3_IOTA.push(t); - } - var IOTAS = split(_SHA3_IOTA, true); - var SHA3_IOTA_H = IOTAS[0]; - var SHA3_IOTA_L = IOTAS[1]; - var rotlH = (h, l, s) => s > 32 ? rotlBH(h, l, s) : rotlSH(h, l, s); - var rotlL = (h, l, s) => s > 32 ? rotlBL(h, l, s) : rotlSL(h, l, s); - /** - * `keccakf1600` internal permutation, additionally allows adjusting the round count. - * @param s - 5x5 Keccak state encoded as 25 lanes split into 50 uint32 words - * in this file's local little-endian lane-word order - * @param rounds - number of rounds to execute - * @throws If `rounds` is outside the supported `1..24` range. {@link Error} - * @example - * Permute a Keccak state with the default 24 rounds. - * ```ts - * keccakP(new Uint32Array(50)); - * ``` - */ - function keccakP(s, rounds = 24) { - anumber(rounds, "rounds"); - if (rounds < 1 || rounds > 24) throw new Error("\"rounds\" expected integer 1..24"); - const B = new Uint32Array(10); - for (let round = 24 - rounds; round < 24; round++) { - for (let x = 0; x < 10; x++) B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40]; - for (let x = 0; x < 10; x += 2) { - const idx1 = (x + 8) % 10; - const idx0 = (x + 2) % 10; - const B0 = B[idx0]; - const B1 = B[idx0 + 1]; - const Th = rotlH(B0, B1, 1) ^ B[idx1]; - const Tl = rotlL(B0, B1, 1) ^ B[idx1 + 1]; - for (let y = 0; y < 50; y += 10) { - s[x + y] ^= Th; - s[x + y + 1] ^= Tl; - } - } - let curH = s[2]; - let curL = s[3]; - for (let t = 0; t < 24; t++) { - const shift = SHA3_ROTL[t]; - const Th = rotlH(curH, curL, shift); - const Tl = rotlL(curH, curL, shift); - const PI = SHA3_PI[t]; - curH = s[PI]; - curL = s[PI + 1]; - s[PI] = Th; - s[PI + 1] = Tl; - } - for (let y = 0; y < 50; y += 10) { - const b0 = s[y], b1 = s[y + 1], b2 = s[y + 2], b3 = s[y + 3]; - s[y] ^= ~s[y + 2] & s[y + 4]; - s[y + 1] ^= ~s[y + 3] & s[y + 5]; - s[y + 2] ^= ~s[y + 4] & s[y + 6]; - s[y + 3] ^= ~s[y + 5] & s[y + 7]; - s[y + 4] ^= ~s[y + 6] & s[y + 8]; - s[y + 5] ^= ~s[y + 7] & s[y + 9]; - s[y + 6] ^= ~s[y + 8] & b0; - s[y + 7] ^= ~s[y + 9] & b1; - s[y + 8] ^= ~b0 & b2; - s[y + 9] ^= ~b1 & b3; - } - s[0] ^= SHA3_IOTA_H[round]; - s[1] ^= SHA3_IOTA_L[round]; - } - clean(B); - } - /** - * Keccak sponge function. - * @param blockLen - absorb/squeeze rate in bytes - * @param suffix - domain separation suffix byte - * @param outputLen - default digest length in bytes. This base sponge only - * requires a non-negative integer; wrappers that need positive output - * lengths must enforce that themselves. - * @param enableXOF - whether XOF output is allowed - * @param rounds - number of Keccak-f rounds - * @example - * Build a sponge state, absorb bytes, then finalize a digest. - * ```ts - * const hash = new Keccak(136, 0x06, 32); - * hash.update(new Uint8Array([1, 2, 3])); - * hash.digest(); - * ``` - */ - var Keccak = class Keccak { - state; - pos = 0; - posOut = 0; - finished = false; - state32; - destroyed = false; - blockLen; - suffix; - outputLen; - canXOF; - enableXOF = false; - rounds; - constructor(blockLen, suffix, outputLen, enableXOF = false, rounds = 24) { - this.blockLen = blockLen; - this.suffix = suffix; - this.outputLen = outputLen; - this.enableXOF = enableXOF; - this.canXOF = enableXOF; - this.rounds = rounds; - anumber(outputLen, "outputLen"); - if (!(0 < blockLen && blockLen < 200)) throw new Error("only keccak-f1600 function is supported"); - this.state = new Uint8Array(200); - this.state32 = u32(this.state); - } - clone() { - return this._cloneInto(); - } - keccak() { - swap32IfBE(this.state32); - keccakP(this.state32, this.rounds); - swap32IfBE(this.state32); - this.posOut = 0; - this.pos = 0; - } - update(data) { - aexists(this); - abytes(data); - const { blockLen, state } = this; - const len = data.length; - for (let pos = 0; pos < len;) { - const take = Math.min(blockLen - this.pos, len - pos); - for (let i = 0; i < take; i++) state[this.pos++] ^= data[pos++]; - if (this.pos === blockLen) this.keccak(); - } - return this; - } - finish() { - if (this.finished) return; - this.finished = true; - const { state, suffix, pos, blockLen } = this; - state[pos] ^= suffix; - if ((suffix & 128) !== 0 && pos === blockLen - 1) this.keccak(); - state[blockLen - 1] ^= 128; - this.keccak(); - } - writeInto(out) { - aexists(this, false); - abytes(out); - this.finish(); - const bufferOut = this.state; - const { blockLen } = this; - for (let pos = 0, len = out.length; pos < len;) { - if (this.posOut >= blockLen) this.keccak(); - const take = Math.min(blockLen - this.posOut, len - pos); - out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos); - this.posOut += take; - pos += take; - } - return out; - } - xofInto(out) { - if (!this.enableXOF) throw new Error("XOF is not possible for this instance"); - return this.writeInto(out); - } - xof(bytes) { - anumber(bytes); - return this.xofInto(new Uint8Array(bytes)); - } - digestInto(out) { - aoutput(out, this); - if (this.finished) throw new Error("digest() was already called"); - this.writeInto(out.subarray(0, this.outputLen)); - this.destroy(); - } - digest() { - const out = new Uint8Array(this.outputLen); - this.digestInto(out); - return out; - } - destroy() { - this.destroyed = true; - clean(this.state); - } - _cloneInto(to) { - const { blockLen, suffix, outputLen, rounds, enableXOF } = this; - to ||= new Keccak(blockLen, suffix, outputLen, enableXOF, rounds); - to.blockLen = blockLen; - to.state32.set(this.state32); - to.pos = this.pos; - to.posOut = this.posOut; - to.finished = this.finished; - to.rounds = rounds; - to.suffix = suffix; - to.outputLen = outputLen; - to.enableXOF = enableXOF; - to.canXOF = this.canXOF; - to.destroyed = this.destroyed; - return to; - } - }; - var genKeccak = (suffix, blockLen, outputLen, info = {}) => createHasher(() => new Keccak(blockLen, suffix, outputLen), info); - /** - * Keccak-256 hash function. Different from SHA3-256. - * @param msg - message bytes to hash - * @returns Digest bytes. - * @example - * Hash a message with Keccak-256. - * ```ts - * keccak_256(new Uint8Array([97, 98, 99])); - * ``` - */ - var keccak_256 = /* @__PURE__ */ genKeccak(1, 136, 32); - //#endregion - //#region src/Keccak256Transcript.js - var POLYNOMIAL = 0; - var SCALAR = 1; - var Keccak256Transcript = class { - constructor(curve) { - this.G1 = curve.G1; - this.Fr = curve.Fr; - this.reset(); - } - reset() { - this.data = []; - } - addPolCommitment(polynomialCommitment) { - this.data.push({ - type: POLYNOMIAL, - data: polynomialCommitment - }); - } - addScalar(scalar) { - this.data.push({ - type: SCALAR, - data: scalar - }); - } - getChallenge() { - if (0 === this.data.length) throw new Error("Keccak256Transcript: No data to generate a transcript"); - let nPolynomials = 0; - let nScalars = 0; - this.data.forEach((element) => POLYNOMIAL === element.type ? nPolynomials++ : nScalars++); - let buffer = new Uint8Array(nScalars * this.Fr.n8 + nPolynomials * this.G1.F.n8 * 2); - let offset = 0; - for (let i = 0; i < this.data.length; i++) if (POLYNOMIAL === this.data[i].type) { - this.G1.toRprUncompressed(buffer, offset, this.data[i].data); - offset += this.G1.F.n8 * 2; - } else { - this.Fr.toRprBE(buffer, offset, this.data[i].data); - offset += this.Fr.n8; - } - const value = ffjavascript.Scalar.fromRprBE(keccak_256(buffer)); - return this.Fr.e(value); - } - }; - //#endregion - //#region src/mul_z.js - var MulZ = class { - static getZ1(Fr) { - return [ - Fr.zero, - Fr.add(Fr.e(-1), Fr.w[2]), - Fr.e(-2), - Fr.sub(Fr.e(-1), Fr.w[2]) - ]; - } - static getZ2(Fr) { - return [ - Fr.zero, - Fr.add(Fr.zero, Fr.mul(Fr.e(-2), Fr.w[2])), - Fr.e(4), - Fr.sub(Fr.zero, Fr.mul(Fr.e(-2), Fr.w[2])) - ]; - } - static getZ3(Fr) { - return [ - Fr.zero, - Fr.add(Fr.e(2), Fr.mul(Fr.e(2), Fr.w[2])), - Fr.e(-8), - Fr.sub(Fr.e(2), Fr.mul(Fr.e(2), Fr.w[2])) - ]; - } - static mul2(a, b, ap, bp, p, Fr) { - const Z1 = this.getZ1(Fr); - let r, rz; - const a_b = Fr.mul(a, b); - const a_bp = Fr.mul(a, bp); - const ap_b = Fr.mul(ap, b); - const ap_bp = Fr.mul(ap, bp); - r = a_b; - let a0 = Fr.add(a_bp, ap_b); - let a1 = ap_bp; - rz = a0; - if (p) rz = Fr.add(rz, Fr.mul(Z1[p], a1)); - return [r, rz]; - } - static mul3(a, b, c, ap, bp, cp, p, Fr) { - const Z1 = this.getZ1(Fr); - const Z2 = this.getZ2(Fr); - let r, rz; - const a_b = Fr.mul(a, b); - const a_bp = Fr.mul(a, bp); - const ap_b = Fr.mul(ap, b); - const ap_bp = Fr.mul(ap, bp); - r = Fr.mul(a_b, c); - let a0 = Fr.mul(ap_b, c); - a0 = Fr.add(a0, Fr.mul(a_bp, c)); - a0 = Fr.add(a0, Fr.mul(a_b, cp)); - let a1 = Fr.mul(ap_bp, c); - a1 = Fr.add(a1, Fr.mul(a_bp, cp)); - a1 = Fr.add(a1, Fr.mul(ap_b, cp)); - rz = a0; - if (p) { - const a2 = Fr.mul(ap_bp, cp); - rz = Fr.add(rz, Fr.mul(Z1[p], a1)); - rz = Fr.add(rz, Fr.mul(Z2[p], a2)); - } - return [r, rz]; - } - static mul4(a, b, c, d, ap, bp, cp, dp, p, Fr) { - const Z1 = this.getZ1(Fr); - const Z2 = this.getZ2(Fr); - const Z3 = this.getZ3(Fr); - let r, rz; - const a_b = Fr.mul(a, b); - const a_bp = Fr.mul(a, bp); - const ap_b = Fr.mul(ap, b); - const ap_bp = Fr.mul(ap, bp); - const c_d = Fr.mul(c, d); - const c_dp = Fr.mul(c, dp); - const cp_d = Fr.mul(cp, d); - const cp_dp = Fr.mul(cp, dp); - r = Fr.mul(a_b, c_d); - let a0 = Fr.mul(ap_b, c_d); - a0 = Fr.add(a0, Fr.mul(a_bp, c_d)); - a0 = Fr.add(a0, Fr.mul(a_b, cp_d)); - a0 = Fr.add(a0, Fr.mul(a_b, c_dp)); - let a1 = Fr.mul(ap_bp, c_d); - a1 = Fr.add(a1, Fr.mul(ap_b, cp_d)); - a1 = Fr.add(a1, Fr.mul(ap_b, c_dp)); - a1 = Fr.add(a1, Fr.mul(a_bp, cp_d)); - a1 = Fr.add(a1, Fr.mul(a_bp, c_dp)); - a1 = Fr.add(a1, Fr.mul(a_b, cp_dp)); - let a2 = Fr.mul(a_bp, cp_dp); - a2 = Fr.add(a2, Fr.mul(ap_b, cp_dp)); - a2 = Fr.add(a2, Fr.mul(ap_bp, c_dp)); - a2 = Fr.add(a2, Fr.mul(ap_bp, cp_d)); - let a3 = Fr.mul(ap_bp, cp_dp); - rz = a0; - if (p) { - rz = Fr.add(rz, Fr.mul(Z1[p], a1)); - rz = Fr.add(rz, Fr.mul(Z2[p], a2)); - rz = Fr.add(rz, Fr.mul(Z3[p], a3)); - } - return [r, rz]; - } - }; - //#endregion - //#region src/polynomial/polynomial.js - var Polynomial = class Polynomial { - constructor(coefficients, curve, logger) { - this.coef = coefficients; - this.curve = curve; - this.Fr = curve.Fr; - this.G1 = curve.G1; - this.logger = logger; - } - static async fromEvaluations(buffer, curve, logger) { - return new Polynomial(await curve.Fr.ifft(buffer), curve, logger); - } - static fromCoefficientsArray(array, curve, logger) { - const Fr = curve.Fr; - let buff = array.length > 32768 ? new ffjavascript.BigBuffer(array.length * Fr.n8) : new Uint8Array(array.length * Fr.n8); - for (let i = 0; i < array.length; i++) buff.set(array[i], i * Fr.n8); - return new Polynomial(buff, curve, logger); - } - static fromPolynomial(polynomial, curve, logger) { - let length = polynomial.length(); - let Fr = curve.Fr; - let buff = length > 32768 ? new ffjavascript.BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8); - buff.set(polynomial.coef.slice(), 0); - return new Polynomial(buff, curve, logger); - } - isEqual(polynomial) { - const degree = this.degree(); - if (degree !== polynomial.degree()) return false; - for (let i = 0; i < degree + 1; i++) if (!this.Fr.eq(this.getCoef(i), polynomial.getCoef(i))) return false; - return true; - } - blindCoefficients(blindingFactors) { - blindingFactors = blindingFactors || []; - const blindedCoefficients = this.length() + blindingFactors.length > 32768 ? new ffjavascript.BigBuffer((this.length() + blindingFactors.length) * this.Fr.n8) : new Uint8Array((this.length() + blindingFactors.length) * this.Fr.n8); - blindedCoefficients.set(this.coef, 0); - for (let i = 0; i < blindingFactors.length; i++) { - blindedCoefficients.set(this.Fr.add(blindedCoefficients.slice((this.length() + i) * this.Fr.n8, (this.length() + i + 1) * this.Fr.n8), blindingFactors[i]), (this.length() + i) * this.Fr.n8); - blindedCoefficients.set(this.Fr.sub(blindedCoefficients.slice(i * this.Fr.n8, (i + 1) * this.Fr.n8), blindingFactors[i]), i * this.Fr.n8); - } - this.coef = blindedCoefficients; - } - getCoef(index) { - const i_n8 = index * this.Fr.n8; - if (i_n8 + this.Fr.n8 > this.coef.byteLength) return this.Fr.zero; - return this.coef.slice(i_n8, i_n8 + this.Fr.n8); - } - setCoef(index, value) { - if (index > this.length() - 1) throw new Error("Coef index is not available"); - this.coef.set(value, index * this.Fr.n8); - } - static async to4T(buffer, domainSize, blindingFactors, Fr) { - blindingFactors = blindingFactors || []; - let a = await Fr.ifft(buffer); - const a4 = domainSize * 4 > 32768 ? new ffjavascript.BigBuffer(domainSize * 4 * Fr.n8) : new Uint8Array(domainSize * 4 * Fr.n8); - a4.set(a, 0); - const A4 = await Fr.fft(a4); - if (blindingFactors.length === 0) return [a, A4]; - const a1 = domainSize + blindingFactors.length > 32768 ? new ffjavascript.BigBuffer((domainSize + blindingFactors.length) * Fr.n8) : new Uint8Array((domainSize + blindingFactors.length) * Fr.n8); - a1.set(a, 0); - for (let i = 0; i < blindingFactors.length; i++) { - a1.set(Fr.add(a1.slice((domainSize + i) * Fr.n8, (domainSize + i + 1) * Fr.n8), blindingFactors[i]), (domainSize + i) * Fr.n8); - a1.set(Fr.sub(a1.slice(i * Fr.n8, (i + 1) * Fr.n8), blindingFactors[i]), i * Fr.n8); - } - return [a1, A4]; - } - length() { - let length = this.coef.byteLength / this.Fr.n8; - if (length !== Math.floor(this.coef.byteLength / this.Fr.n8)) throw new Error("Polynomial coefficients buffer has incorrect size"); - if (0 === length) { - if (this.logger) this.logger.warn("Polynomial has length zero"); - } - return length; - } - degree() { - for (let i = this.length() - 1; i > 0; i--) { - const i_n8 = i * this.Fr.n8; - if (!this.Fr.eq(this.Fr.zero, this.coef.slice(i_n8, i_n8 + this.Fr.n8))) return i; - } - return 0; - } - evaluate(point) { - let res = this.Fr.zero; - for (let i = this.degree() + 1; i > 0; i--) { - let i_n8 = i * this.Fr.n8; - const currentCoefficient = this.coef.slice(i_n8 - this.Fr.n8, i_n8); - res = this.Fr.add(currentCoefficient, this.Fr.mul(res, point)); - } - return res; - } - fastEvaluate(point) { - const Fr = this.Fr; - let nThreads = 3; - let nCoefs = this.degree() + 1; - let coefsThread = parseInt(nCoefs / nThreads); - let residualCoefs = nCoefs - coefsThread * nThreads; - let res = []; - let xN = []; - xN[0] = Fr.one; - for (let i = 0; i < nThreads; i++) { - res[i] = Fr.zero; - let nCoefs = i === nThreads - 1 ? coefsThread + residualCoefs : coefsThread; - for (let j = nCoefs; j > 0; j--) { - res[i] = Fr.add(this.getCoef(i * coefsThread + j - 1), Fr.mul(res[i], point)); - if (i === 0) xN[0] = Fr.mul(xN[0], point); - } - } - for (let i = 1; i < nThreads; i++) { - res[0] = Fr.add(res[0], Fr.mul(xN[i - 1], res[i])); - xN[i] = Fr.mul(xN[i - 1], xN[0]); - } - return res[0]; - } - add(polynomial, blindingValue) { - let other = false; - if (polynomial.length() > this.length()) other = true; - const thisLength = this.length(); - const polyLength = polynomial.length(); - for (let i = 0; i < Math.max(thisLength, polyLength); i++) { - const i_n8 = i * this.Fr.n8; - const a = i < thisLength ? this.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; - let b = i < polyLength ? polynomial.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; - if (blindingValue !== void 0) b = this.Fr.mul(b, blindingValue); - if (other) polynomial.coef.set(this.Fr.add(a, b), i_n8); - else this.coef.set(this.Fr.add(a, b), i_n8); - } - if (other) { - delete this.coef; - this.coef = polynomial.coef; - } - } - sub(polynomial, blindingValue) { - let other = false; - if (polynomial.length() > this.length()) other = true; - const thisLength = this.length(); - const polyLength = polynomial.length(); - for (let i = 0; i < Math.max(thisLength, polyLength); i++) { - const i_n8 = i * this.Fr.n8; - const a = i < thisLength ? this.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; - let b = i < polyLength ? polynomial.coef.slice(i_n8, i_n8 + this.Fr.n8) : this.Fr.zero; - if (blindingValue !== void 0) b = this.Fr.mul(b, blindingValue); - if (other) polynomial.coef.set(this.Fr.sub(a, b), i_n8); - else this.coef.set(this.Fr.sub(a, b), i_n8); - } - if (other) { - delete this.coef; - this.coef = polynomial.coef; - } - } - mulScalar(value) { - for (let i = 0; i < this.length(); i++) { - const i_n8 = i * this.Fr.n8; - this.coef.set(this.Fr.mul(this.coef.slice(i_n8, i_n8 + this.Fr.n8), value), i_n8); - } - } - addScalar(value) { - const currentValue = 0 === this.length() ? this.Fr.zero : this.coef.slice(0, this.Fr.n8); - this.coef.set(this.Fr.add(currentValue, value), 0); - } - subScalar(value) { - const currentValue = 0 === this.length() ? this.Fr.zero : this.coef.slice(0, this.Fr.n8); - this.coef.set(this.Fr.sub(currentValue, value), 0); - } - byXSubValue(value) { - const Fr = this.Fr; - const length = !Fr.eq(Fr.zero, this.getCoef(this.length() - 1)) ? this.length() + 1 : this.length(); - let pol = new Polynomial(length > 32768 ? new ffjavascript.BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8), this.curve, this.logger); - pol.coef.set(this.coef.slice(0, (length - 1) * Fr.n8), 32); - this.mulScalar(Fr.neg(value)); - pol.add(this); - this.coef = pol.coef; - } - byXNSubValue(n, value) { - const Fr = this.Fr; - const length = !(this.length() - n - 1 >= this.degree()) ? this.length() + n : this.length(); - let pol = new Polynomial(length > 32768 ? new ffjavascript.BigBuffer(length * Fr.n8) : new Uint8Array(length * Fr.n8), this.curve, this.logger); - pol.coef.set(this.coef.slice(0, (this.degree() + 1) * 32), n * 32); - this.mulScalar(value); - pol.add(this); - this.coef = pol.coef; - } - divBy(polynomial) { - const Fr = this.Fr; - const degreeA = this.degree(); - const degreeB = polynomial.degree(); - let polR = new Polynomial(this.coef, this.curve, this.logger); - this.coef = this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); - for (let i = degreeA - degreeB; i >= 0; i--) { - this.setCoef(i, Fr.div(polR.getCoef(i + degreeB), polynomial.getCoef(degreeB))); - for (let j = 0; j <= degreeB; j++) polR.setCoef(i + j, Fr.sub(polR.getCoef(i + j), Fr.mul(this.getCoef(i), polynomial.getCoef(j)))); - } - return polR; - } - divByMonic(m, beta) { - const Fr = this.Fr; - let d = this.degree(); - let quotient = new Polynomial(this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8), this.curve, this.logger); - let bArr = []; - for (let i = 0; i < m; i++) { - quotient.setCoef(d - i - m, this.getCoef(d - i)); - bArr[i] = this.getCoef(d - i); - } - let nThreads = m; - let j = 0; - for (let k = 0; k < nThreads; k++) for (let i = d - 2 * m - k; i >= 0; i = i - nThreads) { - if (i < 0) break; - let idx = k; - bArr[idx] = Fr.add(this.getCoef(i + m), Fr.mul(bArr[idx], beta)); - quotient.setCoef(i, bArr[idx]); - j = (j + 1) % m; - } - this.coef = quotient.coef; - } - divByVanishing(n, beta) { - if (this.degree() < n) throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); - const Fr = this.Fr; - let polR = new Polynomial(this.coef, this.curve, this.logger); - this.coef = this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); - for (let i = this.length() - 1; i >= n; i--) { - let leadingCoef = polR.getCoef(i); - if (Fr.eq(Fr.zero, leadingCoef)) continue; - polR.setCoef(i, Fr.zero); - polR.setCoef(i - n, Fr.add(polR.getCoef(i - n), Fr.mul(beta, leadingCoef))); - this.setCoef(i - n, Fr.add(this.getCoef(i - n), leadingCoef)); - } - return polR; - } - divByVanishing2(m, beta) { - if (this.degree() < m) throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); - const Fr = this.Fr; - let polR = new Polynomial(this.coef, this.curve, this.logger); - this.coef = this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8); - let nThreads = 3; - let nTotal = this.length() - m; - let nElementsChunk = Math.floor(nTotal / nThreads); - let nElementsLast = nTotal - (nThreads - 1) * nElementsChunk; - console.log(nTotal); - console.log(nElementsChunk + " " + nElementsLast); - for (let k = 0; k < nThreads; k++) { - console.log("> Thread " + k); - for (let i = k === 0 ? nElementsLast : nElementsChunk; i > 0; i--) { - let idxDst = i - 1; - if (k !== 0) idxDst += (k - 1) * nElementsChunk + nElementsLast; - let idxSrc = idxDst + m; - let leadingCoef = polR.getCoef(idxSrc); - if (Fr.eq(Fr.zero, leadingCoef)) continue; - polR.setCoef(idxSrc, Fr.zero); - polR.setCoef(idxDst, Fr.add(polR.getCoef(idxDst), Fr.mul(beta, leadingCoef))); - this.setCoef(idxDst, Fr.add(this.getCoef(idxDst), leadingCoef)); - console.log(idxDst + " <-- " + idxSrc); - } - } - this.print(); - return polR; - } - fastDivByVanishing(data) { - const Fr = this.Fr; - for (let i = 0; i < data.length; i++) { - let m = data[i][0]; - let beta = data[i][1]; - if (this.degree() < m) throw new Error("divByVanishing polynomial divisor must be of degree lower than the dividend polynomial"); - let nThreads = 5; - let nElements = this.length() - m; - let nElementsBucket = Math.floor(nElements / nThreads / m); - let nElementsChunk = nElementsBucket * m; - let nElementsLast = nElements - nThreads * nElementsChunk; - let polTmp = new Polynomial(this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * Fr.n8) : new Uint8Array(this.length() * Fr.n8), this.curve, this.logger); - let ptr = this.coef; - this.coef = polTmp.coef; - polTmp.coef = ptr; - for (let k = 0; k < nThreads; k++) { - let idx0 = (k + 1) * nElementsChunk + nElementsLast; - for (let i = 0; i < m; i++) this.setCoef(idx0 + i - m, polTmp.getCoef(idx0 + i)); - for (let i = 0; i < nElementsChunk - m; i++) { - let offset = idx0 - i - 1; - let val = Fr.add(polTmp.getCoef(offset), Fr.mul(beta, this.getCoef(offset))); - this.setCoef(offset - m, val); - } - } - let idx0 = nElementsLast; - let pending = nElementsLast; - for (let i = 0; i < m && pending; i++) { - this.setCoef(idx0 - i - 1, polTmp.getCoef(idx0 + m - i - 1)); - pending--; - } - for (let i = 0; i < pending; i++) { - let offset = idx0 - i - 1; - let val = Fr.add(polTmp.getCoef(offset), Fr.mul(beta, this.getCoef(offset))); - this.setCoef(offset - m, val); - } - let acc = []; - let betaPow = Fr.one; - for (let i = 0; i < nElementsBucket; i++) betaPow = Fr.mul(betaPow, beta); - let currentBeta = Fr.one; - for (let k = nThreads; k > 0; k--) { - let idThread = k - 1; - let idx0 = idThread * nElementsChunk + nElementsLast; - acc[idThread] = []; - for (let i = 0; i < m; i++) { - acc[idThread][i] = this.getCoef(idx0 + i); - if (k !== nThreads) acc[idThread][i] = Fr.add(acc[idThread][i], Fr.mul(betaPow, acc[idThread + 1][i])); - } - currentBeta = Fr.mul(currentBeta, betaPow); - } - for (let k = 0; k < nThreads; k++) { - let idx0 = k * nElementsChunk + nElementsLast; - let currentBeta = beta; - let currentM = m - 1; - let limit = k === 0 ? nElementsLast : nElementsChunk; - for (let i = 0; i < limit; i++) { - let offset = idx0 - i - 1; - let val = Fr.add(this.getCoef(offset), Fr.mul(currentBeta, acc[k][currentM])); - this.setCoef(offset, val); - if (currentM === 0) { - currentM = m - 1; - currentBeta = Fr.mul(currentBeta, beta); - } else currentM--; - } - } - } - } - divByXSubValue(value) { - const coefs = this.length() > 32768 ? new ffjavascript.BigBuffer(this.length() * this.Fr.n8) : new Uint8Array(this.length() * this.Fr.n8); - coefs.set(this.Fr.zero, (this.length() - 1) * this.Fr.n8); - coefs.set(this.coef.slice((this.length() - 1) * this.Fr.n8, this.length() * this.Fr.n8), (this.length() - 2) * this.Fr.n8); - for (let i = this.length() - 3; i >= 0; i--) { - let i_n8 = i * this.Fr.n8; - coefs.set(this.Fr.add(this.coef.slice(i_n8 + this.Fr.n8, i_n8 + 2 * this.Fr.n8), this.Fr.mul(value, coefs.slice(i_n8 + this.Fr.n8, i_n8 + 2 * this.Fr.n8))), i * this.Fr.n8); - } - if (!this.Fr.eq(this.coef.slice(0, this.Fr.n8), this.Fr.mul(this.Fr.neg(value), coefs.slice(0, this.Fr.n8)))) throw new Error("Polynomial does not divide"); - this.coef = coefs; - } - divZh(domainSize, extensions = 4) { - for (let i = 0; i < domainSize; i++) { - const i_n8 = i * this.Fr.n8; - this.coef.set(this.Fr.neg(this.coef.slice(i_n8, i_n8 + this.Fr.n8)), i_n8); - } - const upperBound = this.coef.byteLength / this.Fr.n8; - for (let i = domainSize; i < upperBound; i++) { - const i_n8 = i * this.Fr.n8; - const a = this.Fr.sub(this.coef.slice((i - domainSize) * this.Fr.n8, (i - domainSize) * this.Fr.n8 + this.Fr.n8), this.coef.slice(i_n8, i_n8 + this.Fr.n8)); - this.coef.set(a, i_n8); - if (i > domainSize * (extensions - 1) - extensions) { - if (!this.Fr.isZero(a)) throw new Error("Polynomial is not divisible"); - } - } - return this; - } - divByZerofier(n, beta) { - let Fr = this.Fr; - const invBeta = Fr.inv(beta); - const invBetaNeg = Fr.neg(invBeta); - let isOne = Fr.eq(Fr.one, invBetaNeg); - let isNegOne = Fr.eq(Fr.negone, invBetaNeg); - if (!isOne) for (let i = 0; i < n; i++) { - const i_n8 = i * this.Fr.n8; - let element; - if (isNegOne) element = Fr.neg(this.coef.slice(i_n8, i_n8 + this.Fr.n8)); - else element = Fr.mul(invBetaNeg, this.coef.slice(i_n8, i_n8 + this.Fr.n8)); - this.coef.set(element, i_n8); - } - isOne = Fr.eq(Fr.one, invBeta); - isNegOne = Fr.eq(Fr.negone, invBeta); - for (let i = n; i < this.length(); i++) { - const i_n8 = i * this.Fr.n8; - const i_prev_n8 = (i - n) * this.Fr.n8; - let element = this.Fr.sub(this.coef.slice(i_prev_n8, i_prev_n8 + this.Fr.n8), this.coef.slice(i_n8, i_n8 + this.Fr.n8)); - if (!isOne) if (isNegOne) element = Fr.neg(element); - else element = Fr.mul(invBeta, element); - this.coef.set(element, i_n8); - if (i > this.length() - n - 1) { - if (!this.Fr.isZero(element)) throw new Error("Polynomial is not divisible"); - } - } - return this; - } - byX() { - const coefs = this.length() + 1 > 32768 ? new ffjavascript.BigBuffer(this.coef.byteLength + this.Fr.n8) : new Uint8Array(this.coef.byteLength + this.Fr.n8); - coefs.set(this.Fr.zero, 0); - coefs.set(this.coef, this.Fr.n8); - this.coef = coefs; - } - static async expX(polynomial, n, truncate = false) { - const Fr = polynomial.Fr; - if (n < 1) throw new Error("Compute a new polynomial to a zero or negative number is not allowed"); - else if (1 === n) return await Polynomial.fromEvaluations(polynomial.coef, polynomial.curve, polynomial.logger); - const length = truncate ? polynomial.degree() : polynomial.length() - 1; - const bufferDst = length * n + 1 > 32768 ? new ffjavascript.BigBuffer((length * n + 1) * Fr.n8) : new Uint8Array((length * n + 1) * Fr.n8); - bufferDst.set(polynomial.getCoef(0), 0); - for (let i = 1; i <= length; i++) { - const i_sFr = i * Fr.n8; - const coef = polynomial.getCoef(i); - bufferDst.set(coef, i_sFr * n); - } - return new Polynomial(bufferDst, polynomial.curve, polynomial.logger); - } - split(numPols, degPols, blindingFactors) { - if (numPols < 1) throw new Error(`Polynomials can't be split in ${numPols} parts`); - else if (1 === numPols) return [this]; - if (0 !== blindingFactors.length && blindingFactors.length < numPols - 1) throw new Error(`Blinding factors length must be ${numPols - 1}`); - const chunkByteLength = (degPols + 1) * this.Fr.n8; - let res = []; - const numRealPols = Math.ceil((this.degree() + 1) * this.Fr.n8 / chunkByteLength); - if (numRealPols < numPols) for (let i = numRealPols; i < numPols; i++) res[i] = new Polynomial(new Uint8Array(this.Fr.n8), this.curve, this.logger); - numPols = Math.min(numPols, numRealPols); - for (let i = 0; i < numPols; i++) { - const isLast = numPols - 1 === i; - const byteLength = isLast ? this.coef.byteLength - (numPols - 1) * chunkByteLength : chunkByteLength + this.Fr.n8; - res[i] = new Polynomial(byteLength / this.Fr.n8 > 32768 ? new ffjavascript.BigBuffer(byteLength) : new Uint8Array(byteLength), this.curve, this.logger); - const fr = i * chunkByteLength; - const to = isLast ? this.coef.byteLength : (i + 1) * chunkByteLength; - res[i].coef.set(this.coef.slice(fr, to), 0); - if (!isLast) res[i].coef.set(blindingFactors[i], chunkByteLength); - if (0 !== i) { - const lowestDegree = this.Fr.sub(res[i].coef.slice(0, this.Fr.n8), blindingFactors[i - 1]); - res[i].coef.set(lowestDegree, 0); - } - if (isLast) res[i].truncate(); - } - return res; - } - truncate() { - const deg = this.degree(); - if (deg + 1 < this.coef.byteLength / this.Fr.n8) { - const newCoefs = deg + 1 > 32768 ? new ffjavascript.BigBuffer((deg + 1) * this.Fr.n8) : new Uint8Array((deg + 1) * this.Fr.n8); - newCoefs.set(this.coef.slice(0, (deg + 1) * this.Fr.n8), 0); - this.coef = newCoefs; - } - } - static lagrangePolynomialInterpolation(xArr, yArr, curve) { - const Fr = curve.Fr; - let polynomial = computeLagrangePolynomial(0); - for (let i = 1; i < xArr.length; i++) polynomial.add(computeLagrangePolynomial(i)); - return polynomial; - function computeLagrangePolynomial(i) { - let polynomial; - for (let j = 0; j < xArr.length; j++) { - if (j === i) continue; - if (polynomial === void 0) { - polynomial = new Polynomial(xArr.length > 32768 ? new ffjavascript.BigBuffer(xArr.length * Fr.n8) : new Uint8Array(xArr.length * Fr.n8), curve); - polynomial.setCoef(0, Fr.neg(xArr[j])); - polynomial.setCoef(1, Fr.one); - } else polynomial.byXSubValue(xArr[j]); - } - let denominator = polynomial.evaluate(xArr[i]); - denominator = Fr.inv(denominator); - const mulFactor = Fr.mul(yArr[i], denominator); - polynomial.mulScalar(mulFactor); - return polynomial; - } - } - static zerofierPolynomial(xArr, curve) { - const Fr = curve.Fr; - let polynomial = new Polynomial(xArr.length + 1 > 32768 ? new ffjavascript.BigBuffer((xArr.length + 1) * Fr.n8) : new Uint8Array((xArr.length + 1) * Fr.n8), curve); - polynomial.setCoef(0, Fr.neg(xArr[0])); - polynomial.setCoef(1, Fr.one); - for (let i = 1; i < xArr.length; i++) polynomial.byXSubValue(xArr[i]); - return polynomial; - } - print() { - const Fr = this.Fr; - let res = ""; - for (let i = this.degree(); i >= 0; i--) { - const coef = this.getCoef(i); - if (!Fr.eq(Fr.zero, coef)) { - if (Fr.isNegative(coef)) res += " - "; - else if (i !== this.degree()) res += " + "; - res += Fr.toString(coef); - if (i > 0) res += i > 1 ? "x^" + i : "x"; - } - } - console.log(res); - } - async multiExponentiation(PTau, name) { - const n = this.coef.byteLength / this.Fr.n8; - const PTauN = PTau.slice(0, n * this.G1.F.n8 * 2); - const bm = await this.Fr.batchFromMontgomery(this.coef); - let res = await this.G1.multiExpAffine(PTauN, bm, this.logger, name); - res = this.G1.toAffine(res); - return res; - } - }; - //#endregion - //#region src/polynomial/evaluations.js - var Evaluations = class Evaluations { - constructor(evaluations, curve, logger) { - this.eval = evaluations; - this.curve = curve; - this.Fr = curve.Fr; - this.logger = logger; - } - static async fromPolynomial(polynomial, extension, curve, logger) { - const coefficientsN = new ffjavascript.BigBuffer(polynomial.length() * extension * curve.Fr.n8); - coefficientsN.set(polynomial.coef, 0); - return new Evaluations(await curve.Fr.fft(coefficientsN), curve, logger); - } - getEvaluation(index) { - const i_n8 = index * this.Fr.n8; - if (i_n8 + this.Fr.n8 > this.eval.byteLength) throw new Error("Evaluations.getEvaluation() out of bounds"); - return this.eval.slice(i_n8, i_n8 + this.Fr.n8); - } - length() { - let length = this.eval.byteLength / this.Fr.n8; - if (length !== Math.floor(this.eval.byteLength / this.Fr.n8)) throw new Error("Polynomial evaluations buffer has incorrect size"); - if (0 === length) this.logger.warn("Polynomial has length zero"); - return length; - } - }; - //#endregion - //#region src/plonk_prove.js - var { stringifyBigInts: stringifyBigInts$1 } = ffjavascript.utils; - async function plonk16Prove(zkeyFileName, witnessFileName, logger, options) { - const { fd: fdWtns, sections: sectionsWtns } = await _iden3_binfileutils.readBinFile(witnessFileName, "wtns", 2, 1 << 25, 1 << 23); - if (logger) logger.debug("> Reading witness file"); - const wtns = await readHeader(fdWtns, sectionsWtns); - if (logger) logger.debug("> Reading zkey file"); - const { fd: fdZKey, sections: zkeySections } = await _iden3_binfileutils.readBinFile(zkeyFileName, "zkey", 2, 1 << 25, 1 << 23); - const zkey = await readHeader$1(fdZKey, zkeySections, void 0, options); - if (zkey.protocol != "plonk") throw new Error("zkey file is not plonk"); - if (!ffjavascript.Scalar.eq(zkey.r, wtns.q)) throw new Error("Curve of the witness does not match the curve of the proving key"); - if (wtns.nWitness != zkey.nVars - zkey.nAdditions) throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}, ${zkey.nAdditions}`); - const curve = zkey.curve; - const Fr = curve.Fr; - const n8r = curve.Fr.n8; - const sDomain = zkey.domainSize * n8r; - if (logger) { - logger.debug("----------------------------"); - logger.debug(" PLONK PROVE SETTINGS"); - logger.debug(` Curve: ${curve.name}`); - logger.debug(` Circuit power: ${zkey.power}`); - logger.debug(` Domain size: ${zkey.domainSize}`); - logger.debug(` Vars: ${zkey.nVars}`); - logger.debug(` Public vars: ${zkey.nPublic}`); - logger.debug(` Constraints: ${zkey.nConstraints}`); - logger.debug(` Additions: ${zkey.nAdditions}`); - logger.debug("----------------------------"); - } - if (logger) logger.debug("> Reading witness file data"); - const buffWitness = await _iden3_binfileutils.readSection(fdWtns, sectionsWtns, 2); - buffWitness.set(Fr.zero, 0); - const buffInternalWitness = new ffjavascript.BigBuffer(n8r * zkey.nAdditions); - let buffers = {}; - let polynomials = {}; - let evaluations = {}; - let challenges = {}; - let proof = new Proof(curve, logger); - const transcript = new Keccak256Transcript(curve); - if (logger) logger.debug(`> Reading Section 3. Additions`); - await calculateAdditions(); - if (logger) logger.debug(`> Reading Section 12. Sigma1, Sigma2 & Sigma 3`); - if (logger) logger.debug("··· Reading Sigma polynomials "); - polynomials.Sigma1 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.Sigma2 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.Sigma3 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - await fdZKey.readToBuffer(polynomials.Sigma1.coef, 0, sDomain, zkeySections[12][0].p); - await fdZKey.readToBuffer(polynomials.Sigma2.coef, 0, sDomain, zkeySections[12][0].p + 5 * sDomain); - await fdZKey.readToBuffer(polynomials.Sigma3.coef, 0, sDomain, zkeySections[12][0].p + 10 * sDomain); - if (logger) logger.debug("··· Reading Sigma evaluations"); - evaluations.Sigma1 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.Sigma2 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.Sigma3 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - await fdZKey.readToBuffer(evaluations.Sigma1.eval, 0, sDomain * 4, zkeySections[12][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.Sigma2.eval, 0, sDomain * 4, zkeySections[12][0].p + 6 * sDomain); - await fdZKey.readToBuffer(evaluations.Sigma3.eval, 0, sDomain * 4, zkeySections[12][0].p + 11 * sDomain); - if (logger) logger.debug(`> Reading Section 14. Powers of Tau`); - const PTau = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 14); - let publicSignals = []; - for (let i = 1; i <= zkey.nPublic; i++) { - const pub = buffWitness.slice(i * Fr.n8, i * Fr.n8 + Fr.n8); - publicSignals.push(ffjavascript.Scalar.fromRprLE(pub)); - } - if (logger) logger.debug(""); - if (logger) logger.debug("> ROUND 1"); - await round1(); - if (logger) logger.debug("> ROUND 2"); - await round2(); - if (logger) logger.debug("> ROUND 3"); - await round3(); - if (logger) logger.debug("> ROUND 4"); - await round4(); - if (logger) logger.debug("> ROUND 5"); - await round5(); - await fdZKey.close(); - await fdWtns.close(); - let _proof = proof.toObjectProof(false); - _proof.protocol = "plonk"; - _proof.curve = curve.name; - if (logger) logger.debug("PLONK PROVER FINISHED"); - return { - proof: stringifyBigInts$1(_proof), - publicSignals: stringifyBigInts$1(publicSignals) - }; - async function calculateAdditions() { - if (logger) logger.debug("··· Computing additions"); - const additionsBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 3); - const sSum = 8 + n8r * 2; - for (let i = 0; i < zkey.nAdditions; i++) { - if (logger && 0 !== i && i % 1e5 === 0) logger.debug(` addition ${i}/${zkey.nAdditions}`); - let offset = i * sSum; - const signalId1 = readUInt32(additionsBuff, offset); - offset += 4; - const signalId2 = readUInt32(additionsBuff, offset); - offset += 4; - const factor1 = additionsBuff.slice(offset, offset + n8r); - offset += n8r; - const factor2 = additionsBuff.slice(offset, offset + n8r); - const witness1 = getWitness(signalId1); - const witness2 = getWitness(signalId2); - const result = Fr.add(Fr.mul(factor1, witness1), Fr.mul(factor2, witness2)); - buffInternalWitness.set(result, n8r * i); - } - } - function readUInt32(b, o) { - const buff = b.slice(o, o + 4); - return new DataView(buff.buffer, buff.byteOffset, buff.byteLength).getUint32(0, true); - } - function getWitness(idx) { - if (idx < zkey.nVars - zkey.nAdditions) return buffWitness.slice(idx * n8r, idx * n8r + n8r); - else if (idx < zkey.nVars) return buffInternalWitness.slice((idx - (zkey.nVars - zkey.nAdditions)) * n8r, (idx - (zkey.nVars - zkey.nAdditions)) * n8r + n8r); - else return curve.Fr.zero; - } - async function round1() { - challenges.b = []; - for (let i = 1; i <= 11; i++) challenges.b[i] = curve.Fr.random(); - if (logger) logger.debug("> Computing A, B, C wire polynomials"); - await computeWirePolynomials(); - if (logger) logger.debug("> Computing A, B, C MSM"); - let commitA = await polynomials.A.multiExponentiation(PTau, "A"); - let commitB = await polynomials.B.multiExponentiation(PTau, "B"); - let commitC = await polynomials.C.multiExponentiation(PTau, "C"); - proof.addPolynomial("A", commitA); - proof.addPolynomial("B", commitB); - proof.addPolynomial("C", commitC); - return 0; - } - async function computeWirePolynomials() { - if (logger) logger.debug("··· Reading data from zkey file"); - buffers.A = new ffjavascript.BigBuffer(sDomain); - buffers.B = new ffjavascript.BigBuffer(sDomain); - buffers.C = new ffjavascript.BigBuffer(sDomain); - const aMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 4); - const bMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 5); - const cMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 6); - for (let i = 0; i < zkey.nConstraints; i++) { - const i_sFr = i * n8r; - const offset = i * 4; - const signalIdA = readUInt32(aMapBuff, offset); - buffers.A.set(getWitness(signalIdA), i_sFr); - const signalIdB = readUInt32(bMapBuff, offset); - buffers.B.set(getWitness(signalIdB), i_sFr); - const signalIdC = readUInt32(cMapBuff, offset); - buffers.C.set(getWitness(signalIdC), i_sFr); - } - buffers.A = await Fr.batchToMontgomery(buffers.A); - buffers.B = await Fr.batchToMontgomery(buffers.B); - buffers.C = await Fr.batchToMontgomery(buffers.C); - if (logger) logger.debug("··· Computing A ifft"); - polynomials.A = await Polynomial.fromEvaluations(buffers.A, curve, logger); - if (logger) logger.debug("··· Computing B ifft"); - polynomials.B = await Polynomial.fromEvaluations(buffers.B, curve, logger); - if (logger) logger.debug("··· Computing C ifft"); - polynomials.C = await Polynomial.fromEvaluations(buffers.C, curve, logger); - if (logger) logger.debug("··· Computing A fft"); - evaluations.A = await Evaluations.fromPolynomial(polynomials.A, 4, curve, logger); - if (logger) logger.debug("··· Computing B fft"); - evaluations.B = await Evaluations.fromPolynomial(polynomials.B, 4, curve, logger); - if (logger) logger.debug("··· Computing C fft"); - evaluations.C = await Evaluations.fromPolynomial(polynomials.C, 4, curve, logger); - polynomials.A.blindCoefficients([challenges.b[2], challenges.b[1]]); - polynomials.B.blindCoefficients([challenges.b[4], challenges.b[3]]); - polynomials.C.blindCoefficients([challenges.b[6], challenges.b[5]]); - if (polynomials.A.degree() >= zkey.domainSize + 2) throw new Error("A Polynomial is not well calculated"); - if (polynomials.B.degree() >= zkey.domainSize + 2) throw new Error("B Polynomial is not well calculated"); - if (polynomials.C.degree() >= zkey.domainSize + 2) throw new Error("C Polynomial is not well calculated"); - } - async function round2() { - if (logger) logger.debug("> Computing challenges beta and gamma"); - transcript.reset(); - transcript.addPolCommitment(zkey.Qm); - transcript.addPolCommitment(zkey.Ql); - transcript.addPolCommitment(zkey.Qr); - transcript.addPolCommitment(zkey.Qo); - transcript.addPolCommitment(zkey.Qc); - transcript.addPolCommitment(zkey.S1); - transcript.addPolCommitment(zkey.S2); - transcript.addPolCommitment(zkey.S3); - for (let i = 0; i < zkey.nPublic; i++) transcript.addScalar(buffers.A.slice(i * n8r, i * n8r + n8r)); - transcript.addPolCommitment(proof.getPolynomial("A")); - transcript.addPolCommitment(proof.getPolynomial("B")); - transcript.addPolCommitment(proof.getPolynomial("C")); - challenges.beta = transcript.getChallenge(); - if (logger) logger.debug("··· challenges.beta: " + Fr.toString(challenges.beta, 16)); - transcript.reset(); - transcript.addScalar(challenges.beta); - challenges.gamma = transcript.getChallenge(); - if (logger) logger.debug("··· challenges.gamma: " + Fr.toString(challenges.gamma, 16)); - if (logger) logger.debug("> Computing Z polynomial"); - await computeZ(); - if (logger) logger.debug("> Computing Z MSM"); - let commitZ = await polynomials.Z.multiExponentiation(PTau, "Z"); - proof.addPolynomial("Z", commitZ); - } - async function computeZ() { - if (logger) logger.debug("··· Computing Z evaluations"); - let numArr = new ffjavascript.BigBuffer(sDomain); - let denArr = new ffjavascript.BigBuffer(sDomain); - numArr.set(Fr.one, 0); - denArr.set(Fr.one, 0); - let w = Fr.one; - for (let i = 0; i < zkey.domainSize; i++) { - const i_n8r = i * n8r; - const a = buffers.A.slice(i_n8r, i_n8r + n8r); - const b = buffers.B.slice(i_n8r, i_n8r + n8r); - const c = buffers.C.slice(i_n8r, i_n8r + n8r); - const betaw = Fr.mul(challenges.beta, w); - let n1 = Fr.add(a, betaw); - n1 = Fr.add(n1, challenges.gamma); - let n2 = Fr.add(b, Fr.mul(zkey.k1, betaw)); - n2 = Fr.add(n2, challenges.gamma); - let n3 = Fr.add(c, Fr.mul(zkey.k2, betaw)); - n3 = Fr.add(n3, challenges.gamma); - let num = Fr.mul(n1, Fr.mul(n2, n3)); - let d1 = Fr.add(a, Fr.mul(evaluations.Sigma1.getEvaluation(i * 4), challenges.beta)); - d1 = Fr.add(d1, challenges.gamma); - let d2 = Fr.add(b, Fr.mul(evaluations.Sigma2.getEvaluation(i * 4), challenges.beta)); - d2 = Fr.add(d2, challenges.gamma); - let d3 = Fr.add(c, Fr.mul(evaluations.Sigma3.getEvaluation(i * 4), challenges.beta)); - d3 = Fr.add(d3, challenges.gamma); - let den = Fr.mul(d1, Fr.mul(d2, d3)); - num = Fr.mul(numArr.slice(i_n8r, i_n8r + n8r), num); - numArr.set(num, (i + 1) % zkey.domainSize * n8r); - den = Fr.mul(denArr.slice(i_n8r, i_n8r + n8r), den); - denArr.set(den, (i + 1) % zkey.domainSize * n8r); - w = Fr.mul(w, Fr.w[zkey.power]); - } - denArr = await Fr.batchInverse(denArr); - for (let i = 0; i < zkey.domainSize; i++) { - const i_sFr = i * n8r; - const z = Fr.mul(numArr.slice(i_sFr, i_sFr + n8r), denArr.slice(i_sFr, i_sFr + n8r)); - numArr.set(z, i_sFr); - } - buffers.Z = numArr; - if (!Fr.eq(numArr.slice(0, n8r), Fr.one)) throw new Error("Copy constraints does not match"); - if (logger) logger.debug("··· Computing Z ifft"); - polynomials.Z = await Polynomial.fromEvaluations(buffers.Z, curve, logger); - if (logger) logger.debug("··· Computing Z fft"); - evaluations.Z = await Evaluations.fromPolynomial(polynomials.Z, 4, curve, logger); - polynomials.Z.blindCoefficients([ - challenges.b[9], - challenges.b[8], - challenges.b[7] - ]); - if (polynomials.Z.degree() >= zkey.domainSize + 3) throw new Error("Z Polynomial is not well calculated"); - delete buffers.Z; - } - async function round3() { - if (logger) logger.debug("> Computing challenge alpha"); - transcript.reset(); - transcript.addScalar(challenges.beta); - transcript.addScalar(challenges.gamma); - transcript.addPolCommitment(proof.getPolynomial("Z")); - challenges.alpha = transcript.getChallenge(); - challenges.alpha2 = Fr.square(challenges.alpha); - if (logger) logger.debug("··· challenges.alpha: " + Fr.toString(challenges.alpha, 16)); - if (logger) logger.debug("> Computing T polynomial"); - await computeT(); - if (logger) logger.debug("> Computing T MSM"); - let commitT1 = await polynomials.T1.multiExponentiation(PTau, "T1"); - let commitT2 = await polynomials.T2.multiExponentiation(PTau, "T2"); - let commitT3 = await polynomials.T3.multiExponentiation(PTau, "T3"); - proof.addPolynomial("T1", commitT1); - proof.addPolynomial("T2", commitT2); - proof.addPolynomial("T3", commitT3); - } - async function computeT() { - if (logger) logger.debug(`··· Reading sections 8, 9, 7, 10, 11. Q selectors`); - evaluations.QL = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QR = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QM = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QO = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QC = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - await fdZKey.readToBuffer(evaluations.QL.eval, 0, sDomain * 4, zkeySections[8][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QR.eval, 0, sDomain * 4, zkeySections[9][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QM.eval, 0, sDomain * 4, zkeySections[7][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QO.eval, 0, sDomain * 4, zkeySections[10][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QC.eval, 0, sDomain * 4, zkeySections[11][0].p + sDomain); - evaluations.Lagrange = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4 * zkey.nPublic), curve, logger); - for (let i = 0; i < zkey.nPublic; i++) await fdZKey.readToBuffer(evaluations.Lagrange.eval, i * sDomain * 4, sDomain * 4, zkeySections[13][0].p + i * 5 * sDomain + sDomain); - buffers.T = new ffjavascript.BigBuffer(sDomain * 4); - buffers.Tz = new ffjavascript.BigBuffer(sDomain * 4); - if (logger) logger.debug("··· Computing T evaluations"); - let w = Fr.one; - for (let i = 0; i < zkey.domainSize * 4; i++) { - if (logger && 0 !== i && i % 1e5 === 0) logger.debug(` T evaluation ${i}/${zkey.domainSize * 4}`); - const a = evaluations.A.getEvaluation(i); - const b = evaluations.B.getEvaluation(i); - const c = evaluations.C.getEvaluation(i); - const z = evaluations.Z.getEvaluation(i); - const zw = evaluations.Z.getEvaluation((zkey.domainSize * 4 + 4 + i) % (zkey.domainSize * 4)); - const qm = evaluations.QM.getEvaluation(i); - const ql = evaluations.QL.getEvaluation(i); - const qr = evaluations.QR.getEvaluation(i); - const qo = evaluations.QO.getEvaluation(i); - const qc = evaluations.QC.getEvaluation(i); - const s1 = evaluations.Sigma1.getEvaluation(i); - const s2 = evaluations.Sigma2.getEvaluation(i); - const s3 = evaluations.Sigma3.getEvaluation(i); - const ap = Fr.add(challenges.b[2], Fr.mul(challenges.b[1], w)); - const bp = Fr.add(challenges.b[4], Fr.mul(challenges.b[3], w)); - const cp = Fr.add(challenges.b[6], Fr.mul(challenges.b[5], w)); - const w2 = Fr.square(w); - const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], w2), Fr.mul(challenges.b[8], w)), challenges.b[9]); - const wW = Fr.mul(w, Fr.w[zkey.power]); - const wW2 = Fr.square(wW); - const zWp = Fr.add(Fr.add(Fr.mul(challenges.b[7], wW2), Fr.mul(challenges.b[8], wW)), challenges.b[9]); - let pi = Fr.zero; - for (let j = 0; j < zkey.nPublic; j++) { - const offset = j * 4 * zkey.domainSize + i; - const lPol = evaluations.Lagrange.getEvaluation(offset); - const aVal = buffers.A.slice(j * n8r, (j + 1) * n8r); - pi = Fr.sub(pi, Fr.mul(lPol, aVal)); - } - let [e1, e1z] = MulZ.mul2(a, b, ap, bp, i % 4, Fr); - e1 = Fr.mul(e1, qm); - e1z = Fr.mul(e1z, qm); - e1 = Fr.add(e1, Fr.mul(a, ql)); - e1z = Fr.add(e1z, Fr.mul(ap, ql)); - e1 = Fr.add(e1, Fr.mul(b, qr)); - e1z = Fr.add(e1z, Fr.mul(bp, qr)); - e1 = Fr.add(e1, Fr.mul(c, qo)); - e1z = Fr.add(e1z, Fr.mul(cp, qo)); - e1 = Fr.add(e1, pi); - e1 = Fr.add(e1, qc); - const betaw = Fr.mul(challenges.beta, w); - let e2a = a; - e2a = Fr.add(e2a, betaw); - e2a = Fr.add(e2a, challenges.gamma); - let e2b = b; - e2b = Fr.add(e2b, Fr.mul(betaw, zkey.k1)); - e2b = Fr.add(e2b, challenges.gamma); - let e2c = c; - e2c = Fr.add(e2c, Fr.mul(betaw, zkey.k2)); - e2c = Fr.add(e2c, challenges.gamma); - let e2d = z; - let [e2, e2z] = MulZ.mul4(e2a, e2b, e2c, e2d, ap, bp, cp, zp, i % 4, Fr); - e2 = Fr.mul(e2, challenges.alpha); - e2z = Fr.mul(e2z, challenges.alpha); - let e3a = a; - e3a = Fr.add(e3a, Fr.mul(challenges.beta, s1)); - e3a = Fr.add(e3a, challenges.gamma); - let e3b = b; - e3b = Fr.add(e3b, Fr.mul(challenges.beta, s2)); - e3b = Fr.add(e3b, challenges.gamma); - let e3c = c; - e3c = Fr.add(e3c, Fr.mul(challenges.beta, s3)); - e3c = Fr.add(e3c, challenges.gamma); - let e3d = zw; - let [e3, e3z] = MulZ.mul4(e3a, e3b, e3c, e3d, ap, bp, cp, zWp, i % 4, Fr); - e3 = Fr.mul(e3, challenges.alpha); - e3z = Fr.mul(e3z, challenges.alpha); - let e4 = Fr.sub(z, Fr.one); - e4 = Fr.mul(e4, evaluations.Lagrange.getEvaluation(i)); - e4 = Fr.mul(e4, challenges.alpha2); - let e4z = Fr.mul(zp, evaluations.Lagrange.getEvaluation(i)); - e4z = Fr.mul(e4z, challenges.alpha2); - let t = Fr.add(Fr.sub(Fr.add(e1, e2), e3), e4); - let tz = Fr.add(Fr.sub(Fr.add(e1z, e2z), e3z), e4z); - buffers.T.set(t, i * n8r); - buffers.Tz.set(tz, i * n8r); - w = Fr.mul(w, Fr.w[zkey.power + 2]); - } - if (logger) logger.debug("··· Computing T ifft"); - polynomials.T = await Polynomial.fromEvaluations(buffers.T, curve, logger); - if (logger) logger.debug("··· Computing T / ZH"); - polynomials.T.divZh(zkey.domainSize, 4); - if (logger) logger.debug("··· Computing Tz ifft"); - polynomials.Tz = await Polynomial.fromEvaluations(buffers.Tz, curve, logger); - polynomials.T.add(polynomials.Tz); - if (polynomials.T.degree() >= zkey.domainSize * 3 + 6) throw new Error("T Polynomial is not well calculated"); - if (logger) logger.debug("··· Computing T1, T2, T3 polynomials"); - polynomials.T1 = new Polynomial(new ffjavascript.BigBuffer((zkey.domainSize + 1) * n8r), curve, logger); - polynomials.T2 = new Polynomial(new ffjavascript.BigBuffer((zkey.domainSize + 1) * n8r), curve, logger); - polynomials.T3 = new Polynomial(new ffjavascript.BigBuffer((zkey.domainSize + 6) * n8r), curve, logger); - polynomials.T1.coef.set(polynomials.T.coef.slice(0, sDomain), 0); - polynomials.T2.coef.set(polynomials.T.coef.slice(sDomain, sDomain * 2), 0); - polynomials.T3.coef.set(polynomials.T.coef.slice(sDomain * 2, sDomain * 3 + 6 * n8r), 0); - polynomials.T1.setCoef(zkey.domainSize, challenges.b[10]); - const lowestMid = Fr.sub(polynomials.T2.getCoef(0), challenges.b[10]); - polynomials.T2.setCoef(0, lowestMid); - polynomials.T2.setCoef(zkey.domainSize, challenges.b[11]); - const lowestHigh = Fr.sub(polynomials.T3.getCoef(0), challenges.b[11]); - polynomials.T3.setCoef(0, lowestHigh); - } - async function round4() { - if (logger) logger.debug("> Computing challenge xi"); - transcript.reset(); - transcript.addScalar(challenges.alpha); - transcript.addPolCommitment(proof.getPolynomial("T1")); - transcript.addPolCommitment(proof.getPolynomial("T2")); - transcript.addPolCommitment(proof.getPolynomial("T3")); - challenges.xi = transcript.getChallenge(); - challenges.xiw = Fr.mul(challenges.xi, Fr.w[zkey.power]); - if (logger) logger.debug("··· challenges.xi: " + Fr.toString(challenges.xi, 16)); - proof.addEvaluation("eval_a", polynomials.A.evaluate(challenges.xi)); - proof.addEvaluation("eval_b", polynomials.B.evaluate(challenges.xi)); - proof.addEvaluation("eval_c", polynomials.C.evaluate(challenges.xi)); - proof.addEvaluation("eval_s1", polynomials.Sigma1.evaluate(challenges.xi)); - proof.addEvaluation("eval_s2", polynomials.Sigma2.evaluate(challenges.xi)); - proof.addEvaluation("eval_zw", polynomials.Z.evaluate(challenges.xiw)); - } - async function round5() { - if (logger) logger.debug("> Computing challenge v"); - transcript.reset(); - transcript.addScalar(challenges.xi); - transcript.addScalar(proof.getEvaluation("eval_a")); - transcript.addScalar(proof.getEvaluation("eval_b")); - transcript.addScalar(proof.getEvaluation("eval_c")); - transcript.addScalar(proof.getEvaluation("eval_s1")); - transcript.addScalar(proof.getEvaluation("eval_s2")); - transcript.addScalar(proof.getEvaluation("eval_zw")); - challenges.v = []; - challenges.v[1] = transcript.getChallenge(); - if (logger) logger.debug("··· challenges.v: " + Fr.toString(challenges.v[1], 16)); - for (let i = 2; i < 6; i++) challenges.v[i] = Fr.mul(challenges.v[i - 1], challenges.v[1]); - if (logger) logger.debug("> Computing linearisation polynomial R(X)"); - await computeR(); - if (logger) logger.debug("> Computing opening proof polynomial Wxi(X) polynomial"); - computeWxi(); - if (logger) logger.debug("> Computing opening proof polynomial Wxiw(X) polynomial"); - computeWxiw(); - if (logger) logger.debug("> Computing Wxi, Wxiw MSM"); - let commitWxi = await polynomials.Wxi.multiExponentiation(PTau, "Wxi"); - let commitWxiw = await polynomials.Wxiw.multiExponentiation(PTau, "Wxiw"); - proof.addPolynomial("Wxi", commitWxi); - proof.addPolynomial("Wxiw", commitWxiw); - } - async function computeR() { - const Fr = curve.Fr; - polynomials.QL = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QR = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QM = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QO = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QC = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - await fdZKey.readToBuffer(polynomials.QL.coef, 0, sDomain, zkeySections[8][0].p); - await fdZKey.readToBuffer(polynomials.QR.coef, 0, sDomain, zkeySections[9][0].p); - await fdZKey.readToBuffer(polynomials.QM.coef, 0, sDomain, zkeySections[7][0].p); - await fdZKey.readToBuffer(polynomials.QO.coef, 0, sDomain, zkeySections[10][0].p); - await fdZKey.readToBuffer(polynomials.QC.coef, 0, sDomain, zkeySections[11][0].p); - challenges.xin = challenges.xi; - for (let i = 0; i < zkey.power; i++) challenges.xin = Fr.square(challenges.xin); - challenges.zh = Fr.sub(challenges.xin, Fr.one); - const L = []; - const n = Fr.e(zkey.domainSize); - let w = Fr.one; - for (let i = 1; i <= Math.max(1, zkey.nPublic); i++) { - L[i] = Fr.div(Fr.mul(w, challenges.zh), Fr.mul(n, Fr.sub(challenges.xi, w))); - w = Fr.mul(w, Fr.w[zkey.power]); - } - const eval_l1 = Fr.div(Fr.sub(challenges.xin, Fr.one), Fr.mul(n, Fr.sub(challenges.xi, Fr.one))); - if (logger) { - logger.debug("Lagrange Evaluations: "); - for (let i = 1; i < L.length; i++) logger.debug(`L${i}(xi)=` + Fr.toString(L[i], 16)); - } - let eval_pi = Fr.zero; - for (let i = 0; i < publicSignals.length; i++) { - const w = Fr.e(publicSignals[i]); - eval_pi = Fr.sub(eval_pi, Fr.mul(w, L[i + 1])); - } - if (logger) logger.debug("PI: " + Fr.toString(eval_pi, 16)); - const coef_ab = Fr.mul(proof.evaluations.eval_a, proof.evaluations.eval_b); - let e2a = proof.evaluations.eval_a; - const betaxi = Fr.mul(challenges.beta, challenges.xi); - e2a = Fr.add(e2a, betaxi); - e2a = Fr.add(e2a, challenges.gamma); - let e2b = proof.evaluations.eval_b; - e2b = Fr.add(e2b, Fr.mul(betaxi, zkey.k1)); - e2b = Fr.add(e2b, challenges.gamma); - let e2c = proof.evaluations.eval_c; - e2c = Fr.add(e2c, Fr.mul(betaxi, zkey.k2)); - e2c = Fr.add(e2c, challenges.gamma); - const e2 = Fr.mul(Fr.mul(Fr.mul(e2a, e2b), e2c), challenges.alpha); - let e3a = proof.evaluations.eval_a; - e3a = Fr.add(e3a, Fr.mul(challenges.beta, proof.evaluations.eval_s1)); - e3a = Fr.add(e3a, challenges.gamma); - let e3b = proof.evaluations.eval_b; - e3b = Fr.add(e3b, Fr.mul(challenges.beta, proof.evaluations.eval_s2)); - e3b = Fr.add(e3b, challenges.gamma); - let e3 = Fr.mul(e3a, e3b); - e3 = Fr.mul(e3, proof.evaluations.eval_zw); - e3 = Fr.mul(e3, challenges.alpha); - const e4 = Fr.mul(eval_l1, challenges.alpha2); - polynomials.R = new Polynomial(new ffjavascript.BigBuffer((zkey.domainSize + 6) * n8r), curve, logger); - polynomials.R.add(polynomials.QM, coef_ab); - polynomials.R.add(polynomials.QL, proof.evaluations.eval_a); - polynomials.R.add(polynomials.QR, proof.evaluations.eval_b); - polynomials.R.add(polynomials.QO, proof.evaluations.eval_c); - polynomials.R.add(polynomials.QC); - polynomials.R.add(polynomials.Z, e2); - polynomials.R.sub(polynomials.Sigma3, Fr.mul(e3, challenges.beta)); - polynomials.R.add(polynomials.Z, e4); - let tmp = Polynomial.fromPolynomial(polynomials.T3, curve, logger); - tmp.mulScalar(Fr.square(challenges.xin)); - tmp.add(polynomials.T2, challenges.xin); - tmp.add(polynomials.T1); - tmp.mulScalar(challenges.zh); - polynomials.R.sub(tmp); - let r0 = Fr.sub(eval_pi, Fr.mul(e3, Fr.add(proof.evaluations.eval_c, challenges.gamma))); - r0 = Fr.sub(r0, e4); - if (logger) logger.debug("r0: " + Fr.toString(r0, 16)); - polynomials.R.addScalar(r0); - } - function computeWxi() { - polynomials.Wxi = new Polynomial(new ffjavascript.BigBuffer(sDomain + 6 * n8r), curve, logger); - polynomials.Wxi.add(polynomials.R); - polynomials.Wxi.add(polynomials.A, challenges.v[1]); - polynomials.Wxi.add(polynomials.B, challenges.v[2]); - polynomials.Wxi.add(polynomials.C, challenges.v[3]); - polynomials.Wxi.add(polynomials.Sigma1, challenges.v[4]); - polynomials.Wxi.add(polynomials.Sigma2, challenges.v[5]); - polynomials.Wxi.subScalar(Fr.mul(challenges.v[1], proof.evaluations.eval_a)); - polynomials.Wxi.subScalar(Fr.mul(challenges.v[2], proof.evaluations.eval_b)); - polynomials.Wxi.subScalar(Fr.mul(challenges.v[3], proof.evaluations.eval_c)); - polynomials.Wxi.subScalar(Fr.mul(challenges.v[4], proof.evaluations.eval_s1)); - polynomials.Wxi.subScalar(Fr.mul(challenges.v[5], proof.evaluations.eval_s2)); - polynomials.Wxi.divByZerofier(1, challenges.xi); - } - async function computeWxiw() { - polynomials.Wxiw = Polynomial.fromPolynomial(polynomials.Z, curve, logger); - polynomials.Wxiw.subScalar(proof.evaluations.eval_zw); - polynomials.Wxiw.divByZerofier(1, challenges.xiw); - } - } - //#endregion - //#region src/plonk_fullprove.js - var { unstringifyBigInts: unstringifyBigInts$5 } = ffjavascript.utils; - async function plonkFullProve(_input, wasmFile, zkeyFileName, logger, wtnsCalcOptions, proverOptions) { - const input = unstringifyBigInts$5(_input); - const wtns = { type: "mem" }; - await wtnsCalculate(input, wasmFile, wtns, wtnsCalcOptions); - return await plonk16Prove(zkeyFileName, wtns, logger, proverOptions); - } - //#endregion - //#region src/plonk_verify.js - var { unstringifyBigInts: unstringifyBigInts$4 } = ffjavascript.utils; - async function plonkVerify(_vk_verifier, _publicSignals, _proof, logger) { - let vk_verifier = unstringifyBigInts$4(_vk_verifier); - _proof = unstringifyBigInts$4(_proof); - let publicSignals = unstringifyBigInts$4(_publicSignals); - const curve = await getCurveFromName(vk_verifier.curve); - const Fr = curve.Fr; - const G1 = curve.G1; - if (logger) logger.info("PLONK VERIFIER STARTED"); - let proof = fromObjectProof(curve, _proof); - vk_verifier = fromObjectVk$1(curve, vk_verifier); - if (!isWellConstructed(curve, proof)) { - logger.error("Proof commitments are not valid."); - return false; - } - if (publicSignals.length != vk_verifier.nPublic) { - if (logger) logger.error("Invalid number of public inputs"); - return false; - } - if (!evaluationsAreValid$1(curve, proof)) { - if (logger) logger.error("Proof evaluations are not valid"); - return false; - } - if (!publicInputsAreValid$1(curve, publicSignals)) { - if (logger) logger.error("Public inputs are not valid."); - return false; - } - const challenges = calculatechallenges(curve, proof, publicSignals, vk_verifier); - if (logger) { - logger.debug("beta: " + Fr.toString(challenges.beta, 16)); - logger.debug("gamma: " + Fr.toString(challenges.gamma, 16)); - logger.debug("alpha: " + Fr.toString(challenges.alpha, 16)); - logger.debug("xi: " + Fr.toString(challenges.xi, 16)); - for (let i = 1; i < 6; i++) if (logger) logger.debug("v: " + Fr.toString(challenges.v[i], 16)); - logger.debug("u: " + Fr.toString(challenges.u, 16)); - } - const L = calculateLagrangeEvaluations(curve, challenges, vk_verifier); - if (logger) for (let i = 1; i < L.length; i++) logger.debug(`L${i}(xi)=` + Fr.toString(L[i], 16)); - if (publicSignals.length != vk_verifier.nPublic) { - logger.error("Number of public signals does not match with vk"); - return false; - } - const pi = calculatePI$1(curve, publicSignals, L); - if (logger) logger.debug("PI(xi): " + Fr.toString(pi, 16)); - const r0 = calculateR0(curve, proof, challenges, pi, L[1]); - if (logger) logger.debug("r0: " + Fr.toString(r0, 16)); - const D = calculateD(curve, proof, challenges, vk_verifier, L[1]); - if (logger) logger.debug("D: " + G1.toString(G1.toAffine(D), 16)); - const F = calculateF(curve, proof, challenges, vk_verifier, D); - if (logger) logger.debug("F: " + G1.toString(G1.toAffine(F), 16)); - const E = calculateE(curve, proof, challenges, r0); - if (logger) logger.debug("E: " + G1.toString(G1.toAffine(E), 16)); - const res = await isValidPairing$1(curve, proof, challenges, vk_verifier, E, F); - if (logger) if (res) logger.info("OK!"); - else logger.warn("Invalid Proof"); - return res; - } - function fromObjectProof(curve, proof) { - const G1 = curve.G1; - const Fr = curve.Fr; - const res = {}; - res.A = G1.fromObject(proof.A); - res.B = G1.fromObject(proof.B); - res.C = G1.fromObject(proof.C); - res.Z = G1.fromObject(proof.Z); - res.T1 = G1.fromObject(proof.T1); - res.T2 = G1.fromObject(proof.T2); - res.T3 = G1.fromObject(proof.T3); - res.eval_a = Fr.fromObject(proof.eval_a); - res.eval_b = Fr.fromObject(proof.eval_b); - res.eval_c = Fr.fromObject(proof.eval_c); - res.eval_zw = Fr.fromObject(proof.eval_zw); - res.eval_s1 = Fr.fromObject(proof.eval_s1); - res.eval_s2 = Fr.fromObject(proof.eval_s2); - res.Wxi = G1.fromObject(proof.Wxi); - res.Wxiw = G1.fromObject(proof.Wxiw); - return res; - } - function fromObjectVk$1(curve, vk) { - const G1 = curve.G1; - const G2 = curve.G2; - const Fr = curve.Fr; - const res = vk; - res.Qm = G1.fromObject(vk.Qm); - res.Ql = G1.fromObject(vk.Ql); - res.Qr = G1.fromObject(vk.Qr); - res.Qo = G1.fromObject(vk.Qo); - res.Qc = G1.fromObject(vk.Qc); - res.S1 = G1.fromObject(vk.S1); - res.S2 = G1.fromObject(vk.S2); - res.S3 = G1.fromObject(vk.S3); - res.k1 = Fr.fromObject(vk.k1); - res.k2 = Fr.fromObject(vk.k2); - res.X_2 = G2.fromObject(vk.X_2); - return res; - } - function isWellConstructed(curve, proof) { - const G1 = curve.G1; - if (!G1.isValid(proof.A)) return false; - if (!G1.isValid(proof.B)) return false; - if (!G1.isValid(proof.C)) return false; - if (!G1.isValid(proof.Z)) return false; - if (!G1.isValid(proof.T1)) return false; - if (!G1.isValid(proof.T2)) return false; - if (!G1.isValid(proof.T3)) return false; - if (!G1.isValid(proof.Wxi)) return false; - if (!G1.isValid(proof.Wxiw)) return false; - return true; - } - function checkValueBelongToField$1(curve, value) { - return ffjavascript.Scalar.geq(value, 0) && ffjavascript.Scalar.lt(value, curve.r); - } - function checkEvaluationIsValid$1(curve, evaluation) { - return checkValueBelongToField$1(curve, ffjavascript.Scalar.fromRprLE(evaluation)); - } - function evaluationsAreValid$1(curve, proof) { - return checkEvaluationIsValid$1(curve, proof.eval_a) && checkEvaluationIsValid$1(curve, proof.eval_b) && checkEvaluationIsValid$1(curve, proof.eval_c) && checkEvaluationIsValid$1(curve, proof.eval_s1) && checkEvaluationIsValid$1(curve, proof.eval_s2) && checkEvaluationIsValid$1(curve, proof.eval_zw); - } - function publicInputsAreValid$1(curve, publicInputs) { - for (let i = 0; i < publicInputs.length; i++) if (!checkValueBelongToField$1(curve, publicInputs[i])) return false; - return true; - } - function calculatechallenges(curve, proof, publicSignals, vk) { - const Fr = curve.Fr; - const res = {}; - const transcript = new Keccak256Transcript(curve); - transcript.addPolCommitment(vk.Qm); - transcript.addPolCommitment(vk.Ql); - transcript.addPolCommitment(vk.Qr); - transcript.addPolCommitment(vk.Qo); - transcript.addPolCommitment(vk.Qc); - transcript.addPolCommitment(vk.S1); - transcript.addPolCommitment(vk.S2); - transcript.addPolCommitment(vk.S3); - for (let i = 0; i < publicSignals.length; i++) transcript.addScalar(Fr.e(publicSignals[i])); - transcript.addPolCommitment(proof.A); - transcript.addPolCommitment(proof.B); - transcript.addPolCommitment(proof.C); - res.beta = transcript.getChallenge(); - transcript.reset(); - transcript.addScalar(res.beta); - res.gamma = transcript.getChallenge(); - transcript.reset(); - transcript.addScalar(res.beta); - transcript.addScalar(res.gamma); - transcript.addPolCommitment(proof.Z); - res.alpha = transcript.getChallenge(); - transcript.reset(); - transcript.addScalar(res.alpha); - transcript.addPolCommitment(proof.T1); - transcript.addPolCommitment(proof.T2); - transcript.addPolCommitment(proof.T3); - res.xi = transcript.getChallenge(); - transcript.reset(); - transcript.addScalar(res.xi); - transcript.addScalar(proof.eval_a); - transcript.addScalar(proof.eval_b); - transcript.addScalar(proof.eval_c); - transcript.addScalar(proof.eval_s1); - transcript.addScalar(proof.eval_s2); - transcript.addScalar(proof.eval_zw); - res.v = []; - res.v[1] = transcript.getChallenge(); - for (let i = 2; i < 6; i++) res.v[i] = Fr.mul(res.v[i - 1], res.v[1]); - transcript.reset(); - transcript.addPolCommitment(proof.Wxi); - transcript.addPolCommitment(proof.Wxiw); - res.u = transcript.getChallenge(); - return res; - } - function calculateLagrangeEvaluations(curve, challenges, vk) { - const Fr = curve.Fr; - let xin = challenges.xi; - let domainSize = 1; - for (let i = 0; i < vk.power; i++) { - xin = Fr.square(xin); - domainSize *= 2; - } - challenges.xin = xin; - challenges.zh = Fr.sub(xin, Fr.one); - const L = []; - const n = Fr.e(domainSize); - let w = Fr.one; - for (let i = 1; i <= Math.max(1, vk.nPublic); i++) { - L[i] = Fr.div(Fr.mul(w, challenges.zh), Fr.mul(n, Fr.sub(challenges.xi, w))); - w = Fr.mul(w, Fr.w[vk.power]); - } - return L; - } - function calculatePI$1(curve, publicSignals, L) { - const Fr = curve.Fr; - let pi = Fr.zero; - for (let i = 0; i < publicSignals.length; i++) { - const w = Fr.e(publicSignals[i]); - pi = Fr.sub(pi, Fr.mul(w, L[i + 1])); - } - return pi; - } - function calculateR0(curve, proof, challenges, pi, l1) { - const Fr = curve.Fr; - const e1 = pi; - const e2 = Fr.mul(l1, Fr.square(challenges.alpha)); - let e3a = Fr.add(proof.eval_a, Fr.mul(challenges.beta, proof.eval_s1)); - e3a = Fr.add(e3a, challenges.gamma); - let e3b = Fr.add(proof.eval_b, Fr.mul(challenges.beta, proof.eval_s2)); - e3b = Fr.add(e3b, challenges.gamma); - let e3c = Fr.add(proof.eval_c, challenges.gamma); - let e3 = Fr.mul(Fr.mul(e3a, e3b), e3c); - e3 = Fr.mul(e3, proof.eval_zw); - e3 = Fr.mul(e3, challenges.alpha); - return Fr.sub(Fr.sub(e1, e2), e3); - } - function calculateD(curve, proof, challenges, vk, l1) { - const G1 = curve.G1; - const Fr = curve.Fr; - let d1 = G1.timesFr(vk.Qm, Fr.mul(proof.eval_a, proof.eval_b)); - d1 = G1.add(d1, G1.timesFr(vk.Ql, proof.eval_a)); - d1 = G1.add(d1, G1.timesFr(vk.Qr, proof.eval_b)); - d1 = G1.add(d1, G1.timesFr(vk.Qo, proof.eval_c)); - d1 = G1.add(d1, vk.Qc); - const betaxi = Fr.mul(challenges.beta, challenges.xi); - const d2a1 = Fr.add(Fr.add(proof.eval_a, betaxi), challenges.gamma); - const d2a2 = Fr.add(Fr.add(proof.eval_b, Fr.mul(betaxi, vk.k1)), challenges.gamma); - const d2a3 = Fr.add(Fr.add(proof.eval_c, Fr.mul(betaxi, vk.k2)), challenges.gamma); - const d2a = Fr.mul(Fr.mul(Fr.mul(d2a1, d2a2), d2a3), challenges.alpha); - const d2b = Fr.mul(l1, Fr.square(challenges.alpha)); - const d2 = G1.timesFr(proof.Z, Fr.add(Fr.add(d2a, d2b), challenges.u)); - const d3a = Fr.add(Fr.add(proof.eval_a, Fr.mul(challenges.beta, proof.eval_s1)), challenges.gamma); - const d3b = Fr.add(Fr.add(proof.eval_b, Fr.mul(challenges.beta, proof.eval_s2)), challenges.gamma); - const d3c = Fr.mul(Fr.mul(challenges.alpha, challenges.beta), proof.eval_zw); - const d3 = G1.timesFr(vk.S3, Fr.mul(Fr.mul(d3a, d3b), d3c)); - const d4low = proof.T1; - const d4mid = G1.timesFr(proof.T2, challenges.xin); - const d4high = G1.timesFr(proof.T3, Fr.square(challenges.xin)); - let d4 = G1.add(d4low, G1.add(d4mid, d4high)); - d4 = G1.timesFr(d4, challenges.zh); - return G1.sub(G1.sub(G1.add(d1, d2), d3), d4); - } - function calculateF(curve, proof, challenges, vk, D) { - const G1 = curve.G1; - let res = G1.add(D, G1.timesFr(proof.A, challenges.v[1])); - res = G1.add(res, G1.timesFr(proof.B, challenges.v[2])); - res = G1.add(res, G1.timesFr(proof.C, challenges.v[3])); - res = G1.add(res, G1.timesFr(vk.S1, challenges.v[4])); - res = G1.add(res, G1.timesFr(vk.S2, challenges.v[5])); - return res; - } - function calculateE(curve, proof, challenges, r0) { - const G1 = curve.G1; - const Fr = curve.Fr; - let e = Fr.add(Fr.neg(r0), Fr.mul(challenges.v[1], proof.eval_a)); - e = Fr.add(e, Fr.mul(challenges.v[2], proof.eval_b)); - e = Fr.add(e, Fr.mul(challenges.v[3], proof.eval_c)); - e = Fr.add(e, Fr.mul(challenges.v[4], proof.eval_s1)); - e = Fr.add(e, Fr.mul(challenges.v[5], proof.eval_s2)); - e = Fr.add(e, Fr.mul(challenges.u, proof.eval_zw)); - return G1.timesFr(G1.one, e); - } - async function isValidPairing$1(curve, proof, challenges, vk, E, F) { - const G1 = curve.G1; - const Fr = curve.Fr; - let A1 = proof.Wxi; - A1 = G1.add(A1, G1.timesFr(proof.Wxiw, challenges.u)); - let B1 = G1.timesFr(proof.Wxi, challenges.xi); - const s = Fr.mul(Fr.mul(challenges.u, challenges.xi), Fr.w[vk.power]); - B1 = G1.add(B1, G1.timesFr(proof.Wxiw, s)); - B1 = G1.add(B1, F); - B1 = G1.sub(B1, E); - return await curve.pairingEq(G1.neg(A1), vk.X_2, B1, curve.G2.one); - } - //#endregion - //#region src/plonk_exportsoliditycalldata.js - var { unstringifyBigInts: unstringifyBigInts$3 } = ffjavascript.utils; - function p256$1(n) { - let nstr = n.toString(16); - while (nstr.length < 64) nstr = "0" + nstr; - nstr = `"0x${nstr}"`; - return nstr; - } - async function plonkExportSolidityCallData(_proof, _pub) { - const proof = unstringifyBigInts$3(_proof); - const pub = unstringifyBigInts$3(_pub); - await getCurveFromName(proof.curve); - let inputs = ""; - for (let i = 0; i < pub.length; i++) { - if (inputs != "") inputs = inputs + ","; - inputs = inputs + p256$1(pub[i]); - } - return `[${p256$1(proof.A[0])}, ${p256$1(proof.A[1])},${p256$1(proof.B[0])},${p256$1(proof.B[1])},${p256$1(proof.C[0])},${p256$1(proof.C[1])},${p256$1(proof.Z[0])},${p256$1(proof.Z[1])},${p256$1(proof.T1[0])},${p256$1(proof.T1[1])},${p256$1(proof.T2[0])},${p256$1(proof.T2[1])},${p256$1(proof.T3[0])},${p256$1(proof.T3[1])},${p256$1(proof.Wxi[0])},${p256$1(proof.Wxi[1])},${p256$1(proof.Wxiw[0])},${p256$1(proof.Wxiw[1])},${p256$1(proof.eval_a)},${p256$1(proof.eval_b)},${p256$1(proof.eval_c)},${p256$1(proof.eval_s1)},${p256$1(proof.eval_s2)},${p256$1(proof.eval_zw)}][${inputs}]`; - } - //#endregion - //#region src/plonk.js - var plonk_exports = /* @__PURE__ */ __exportAll({ - exportSolidityCallData: () => plonkExportSolidityCallData, - fullProve: () => plonkFullProve, - prove: () => plonk16Prove, - setup: () => plonkSetup, - verify: () => plonkVerify - }); - //#endregion - //#region src/plonk_equation.js - function getFFlonkConstantConstraint(signal1, Fr) { - return [ - signal1, - 0, - 0, - Fr.one, - Fr.zero, - Fr.zero, - Fr.zero, - Fr.zero - ]; - } - function getFFlonkAdditionConstraint(signal1, signal2, signalOut, ql, qr, qm, qo, qc) { - return [ - signal1, - signal2, - signalOut, - ql, - qr, - qm, - qo, - qc - ]; - } - function getFFlonkMultiplicationConstraint(signal1, signal2, signalOut, ql, qr, qm, qo, qc, _Fr) { - return [ - signal1, - signal2, - signalOut, - ql, - qr, - qm, - qo, - qc - ]; - } - //#endregion - //#region src/r1cs_constraint_processor.js - var LINEAR_COMBINATION_NULLABLE = 0; - var LINEAR_COMBINATION_CONSTANT = 1; - var LINEAR_COMBINATION_VARIABLE = 2; - var r1csConstraintProcessor = class { - constructor(Fr, fnGetConstantConstraint, fnGetAdditionConstraint, fnGetMultiplicationConstraint, logger) { - this.Fr = Fr; - this.logger = logger; - this.fnGetAdditionConstraint = fnGetAdditionConstraint; - this.fnGetMultiplicationConstraint = fnGetMultiplicationConstraint; - } - processR1csConstraint(settings, lcA, lcB, lcC) { - this.normalizeLinearCombination(lcA); - this.normalizeLinearCombination(lcB); - this.normalizeLinearCombination(lcC); - const lctA = this.getLinearCombinationType(lcA); - const lctB = this.getLinearCombinationType(lcB); - if (lctA === LINEAR_COMBINATION_NULLABLE || lctB === LINEAR_COMBINATION_NULLABLE) return this.processR1csAdditionConstraint(settings, lcC); - else if (lctA === LINEAR_COMBINATION_CONSTANT) { - const lcCC = this.joinLinearCombinations(lcB, lcC, lcA[0]); - return this.processR1csAdditionConstraint(settings, lcCC); - } else if (lctB === LINEAR_COMBINATION_CONSTANT) { - const lcCC = this.joinLinearCombinations(lcA, lcC, lcB[0]); - return this.processR1csAdditionConstraint(settings, lcCC); - } else return this.processR1csMultiplicationConstraint(settings, lcA, lcB, lcC); - } - getLinearCombinationType(linCom) { - let k = this.Fr.zero; - let n = 0; - const ss = Object.keys(linCom); - for (let i = 0; i < ss.length; i++) if (linCom[ss[i]] == 0n) delete linCom[ss[i]]; - else if (ss[i] == 0) k = this.Fr.add(k, linCom[ss[i]]); - else n++; - if (n > 0) return LINEAR_COMBINATION_VARIABLE; - if (!this.Fr.isZero(k)) return LINEAR_COMBINATION_CONSTANT; - return LINEAR_COMBINATION_NULLABLE; - } - normalizeLinearCombination(linCom) { - const signalIds = Object.keys(linCom); - for (let i = 0; i < signalIds.length; i++) if (this.Fr.isZero(linCom[signalIds[i]])) delete linCom[signalIds[i]]; - return linCom; - } - joinLinearCombinations(linCom1, linCom2, k) { - const res = {}; - for (let s in linCom1) if (typeof res[s] == "undefined") res[s] = this.Fr.mul(k, linCom1[s]); - else res[s] = this.Fr.add(res[s], this.Fr.mul(k, linCom1[s])); - for (let s in linCom2) if (typeof res[s] == "undefined") res[s] = linCom2[s]; - else res[s] = this.Fr.add(res[s], linCom2[s]); - return this.normalizeLinearCombination(res); - } - reduceCoefs(settings, constraintsArr, additionsArr, linCom, maxC) { - const res = { - k: this.Fr.zero, - signals: [], - coefs: [] - }; - const cs = []; - for (let signalId in linCom) if (signalId == 0) res.k = this.Fr.add(res.k, linCom[signalId]); - else if (linCom[signalId] != 0n) cs.push([Number(signalId), linCom[signalId]]); - while (cs.length > maxC) { - const c1 = cs.shift(); - const c2 = cs.shift(); - const so = settings.nVars++; - const constraints = this.fnGetAdditionConstraint(c1[0], c2[0], so, this.Fr.neg(c1[1]), this.Fr.neg(c2[1]), this.Fr.zero, this.Fr.one, this.Fr.zero); - constraintsArr.push(constraints); - additionsArr.push([ - c1[0], - c2[0], - c1[1], - c2[1] - ]); - cs.push([so, this.Fr.one]); - } - for (let i = 0; i < cs.length; i++) { - res.signals[i] = cs[i][0]; - res.coefs[i] = cs[i][1]; - } - while (res.coefs.length < maxC) { - res.signals.push(0); - res.coefs.push(this.Fr.zero); - } - return res; - } - processR1csAdditionConstraint(settings, linCom) { - const constraintsArr = []; - const additionsArr = []; - const C = this.reduceCoefs(settings, constraintsArr, additionsArr, linCom, 3); - const constraints = this.fnGetAdditionConstraint(C.signals[0], C.signals[1], C.signals[2], C.coefs[0], C.coefs[1], this.Fr.zero, C.coefs[2], C.k); - constraintsArr.push(constraints); - return [constraintsArr, additionsArr]; - } - processR1csMultiplicationConstraint(settings, lcA, lcB, lcC) { - const constraintsArr = []; - const additionsArr = []; - const A = this.reduceCoefs(settings, constraintsArr, additionsArr, lcA, 1); - const B = this.reduceCoefs(settings, constraintsArr, additionsArr, lcB, 1); - const C = this.reduceCoefs(settings, constraintsArr, additionsArr, lcC, 1); - const constraints = this.fnGetMultiplicationConstraint(A.signals[0], B.signals[0], C.signals[0], this.Fr.mul(A.coefs[0], B.k), this.Fr.mul(A.k, B.coefs[0]), this.Fr.mul(A.coefs[0], B.coefs[0]), this.Fr.neg(C.coefs[0]), this.Fr.sub(this.Fr.mul(A.k, B.k), C.k)); - constraintsArr.push(constraints); - return [constraintsArr, additionsArr]; - } - }; - //#endregion - //#region src/polynomial/cpolynomial.js - var CPolynomial = class { - constructor(n, curve, logger) { - this.n = n; - this.polynomials = Array(n).fill(void 0); - this.curve = curve; - this.Fr = curve.Fr; - this.G1 = curve.G1; - this.logger = logger; - } - addPolynomial(position, polynomial) { - if (position > this.n - 1) throw new Error("CPolynomial:addPolynomial, cannot add a polynomial to a position greater than n-1"); - this.polynomials[position] = polynomial; - } - degree() { - let degrees = this.polynomials.map((polynomial, index) => polynomial === void 0 ? 0 : polynomial.degree() * this.n + index); - return Math.max(...degrees); - } - getPolynomial() { - let degrees = this.polynomials.map((polynomial) => polynomial === void 0 ? 0 : polynomial.degree()); - const maxDegree = this.degree(); - const lengthBuffer = 2 ** (log2(maxDegree - 1) + 1); - const sFr = this.Fr.n8; - let polynomial = new Polynomial(new ffjavascript.BigBuffer(lengthBuffer * sFr), this.curve, this.logger); - for (let i = 0; i < maxDegree; i++) { - const i_n8 = i * sFr; - const i_sFr = i_n8 * this.n; - for (let j = 0; j < this.n; j++) if (this.polynomials[j] !== void 0) { - if (i <= degrees[j]) polynomial.coef.set(this.polynomials[j].coef.slice(i_n8, i_n8 + sFr), i_sFr + j * sFr); - } - } - return polynomial; - } - async multiExponentiation(PTau, name) { - let polynomial = this.getPolynomial(); - const n = polynomial.coef.byteLength / this.Fr.n8; - const PTauN = PTau.slice(0, n * this.G1.F.n8 * 2); - const bm = await this.Fr.batchFromMontgomery(polynomial.coef); - let res = await this.G1.multiExpAffine(PTauN, bm, this.logger, name); - res = this.G1.toAffine(res); - return res; - } - }; - //#endregion - //#region src/fflonk_setup.js - async function fflonkSetup(r1csFilename, ptauFilename, zkeyFilename, logger) { - if (logger) logger.info("FFLONK SETUP STARTED"); - if (globalThis.gc) globalThis.gc(); - if (logger) logger.info("> Reading PTau file"); - const { fd: fdPTau, sections: pTauSections } = await (0, _iden3_binfileutils.readBinFile)(ptauFilename, "ptau", 1, 1 << 22, 1 << 24); - if (!pTauSections[12]) throw new Error("Powers of Tau is not well prepared. Section 12 missing."); - if (logger) logger.info("> Getting curve from PTau settings"); - const { curve } = await readPTauHeader(fdPTau, pTauSections); - if (logger) logger.info("> Reading r1cs file"); - const { fd: fdR1cs, sections: sectionsR1cs } = await (0, _iden3_binfileutils.readBinFile)(r1csFilename, "r1cs", 1, 1 << 22, 1 << 24); - const r1cs = await (0, r1csfile.readR1csFd)(fdR1cs, sectionsR1cs, { - loadConstraints: false, - loadCustomGates: true - }); - if (r1cs.prime !== curve.r) throw new Error("r1cs curve does not match powers of tau ceremony curve"); - const Fr = curve.Fr; - const sFr = curve.Fr.n8; - const sG1 = curve.G1.F.n8 * 2; - const sG2 = curve.G2.F.n8 * 2; - let polynomials = {}; - let evaluations = {}; - let PTau; - let settings = { - nVars: r1cs.nVars, - nPublic: r1cs.nOutputs + r1cs.nPubInputs - }; - const plonkConstraints = new BigArray(); - let plonkAdditions = new BigArray(); - if (logger) logger.info("> Processing FFlonk constraints"); - await computeFFConstraints(curve.Fr, r1cs, logger); - if (globalThis.gc) globalThis.gc(); - settings.cirPower = Math.max(3, log2(plonkConstraints.length + 2 - 1) + 1); - settings.domainSize = 2 ** settings.cirPower; - if (pTauSections[2][0].size < (settings.domainSize * 9 + 18) * sG1) throw new Error("Powers of Tau is not big enough for this circuit size. Section 2 too small."); - if (pTauSections[3][0].size < sG2) throw new Error("Powers of Tau is not well prepared. Section 3 too small."); - if (logger) { - logger.info("----------------------------"); - logger.info(" FFLONK SETUP SETTINGS"); - logger.info(` Curve: ${curve.name}`); - logger.info(` Circuit power: ${settings.cirPower}`); - logger.info(` Domain size: ${settings.domainSize}`); - logger.info(` Vars: ${settings.nVars}`); - logger.info(` Public vars: ${settings.nPublic}`); - logger.info(` Constraints: ${plonkConstraints.length}`); - logger.info(` Additions: ${plonkAdditions.length}`); - logger.info("----------------------------"); - } - if (logger) logger.info("> computing k1 and k2"); - const [k1, k2] = computeK1K2(); - if (logger) logger.info("> computing w3"); - const w3 = computeW3(); - if (logger) logger.info("> computing w4"); - const w4 = computeW4(); - if (logger) logger.info("> computing w8"); - const w8 = computeW8(); - if (logger) logger.info("> computing wr"); - const wr = getOmegaCubicRoot(settings.cirPower, curve.Fr); - await writeZkeyFile(); - await fdR1cs.close(); - await fdPTau.close(); - if (logger) logger.info("FFLONK SETUP FINISHED"); - return 0; - async function computeFFConstraints(Fr, r1cs, logger) { - for (let i = 0; i < settings.nPublic; i++) plonkConstraints.push(getFFlonkConstantConstraint(i + 1, Fr)); - const r1csProcessor = new r1csConstraintProcessor(Fr, getFFlonkConstantConstraint, getFFlonkAdditionConstraint, getFFlonkMultiplicationConstraint, logger); - const bR1cs = await _iden3_binfileutils.readSection(fdR1cs, sectionsR1cs, 2); - let bR1csPos = 0; - for (let i = 0; i < r1cs.nConstraints; i++) { - if (logger && i !== 0 && i % 5e5 === 0) logger.info(` processing r1cs constraints ${i}/${r1cs.nConstraints}`); - const [constraints, additions] = r1csProcessor.processR1csConstraint(settings, ...readConstraint()); - plonkConstraints.push(...constraints); - plonkAdditions.push(...additions); - } - function readConstraint() { - const c = []; - c[0] = readLC(); - c[1] = readLC(); - c[2] = readLC(); - return c; - } - function readLC() { - const lc = {}; - const buffUL32 = bR1cs.slice(bR1csPos, bR1csPos + 4); - bR1csPos += 4; - const nIdx = new DataView(buffUL32.buffer).getUint32(0, true); - const buff = bR1cs.slice(bR1csPos, bR1csPos + (4 + r1cs.n8) * nIdx); - bR1csPos += (4 + r1cs.n8) * nIdx; - const buffV = new DataView(buff.buffer); - for (let i = 0; i < nIdx; i++) { - const idx = buffV.getUint32(i * (4 + r1cs.n8), true); - lc[idx] = r1cs.F.fromRprLE(buff, i * (4 + r1cs.n8) + 4); - } - return lc; - } - return 0; - } - async function writeZkeyFile() { - if (logger) logger.info("> Writing the zkey file"); - const fdZKey = await (0, _iden3_binfileutils.createBinFile)(zkeyFilename, "zkey", 1, 17, 1 << 22, 1 << 24); - if (logger) logger.info(`··· Writing Section 1. Zkey Header`); - await writeZkeyHeader(fdZKey); - if (logger) logger.info(`··· Writing Section 3. Additions`); - await writeAdditions(fdZKey); - if (globalThis.gc) globalThis.gc(); - if (logger) logger.info(`··· Writing Section 4. A Map`); - await writeWitnessMap(fdZKey, 4, 0, "A map"); - if (globalThis.gc) globalThis.gc(); - if (logger) logger.info(`··· Writing Section 5. B Map`); - await writeWitnessMap(fdZKey, 5, 1, "B map"); - if (globalThis.gc) globalThis.gc(); - if (logger) logger.info(`··· Writing Section 6. C Map`); - await writeWitnessMap(fdZKey, 6, 2, "C map"); - if (globalThis.gc) globalThis.gc(); - if (logger) logger.info(`··· Writing Section 7. QL`); - await writeQMap(fdZKey, 7, 3, "QL"); - if (globalThis.gc) globalThis.gc(); - if (logger) logger.info(`··· Writing Section 8. QR`); - await writeQMap(fdZKey, 8, 4, "QR"); - if (globalThis.gc) globalThis.gc(); - if (logger) logger.info(`··· Writing Section 9. QM`); - await writeQMap(fdZKey, 9, 5, "QM"); - if (globalThis.gc) globalThis.gc(); - if (logger) logger.info(`··· Writing Section 10. QO`); - await writeQMap(fdZKey, 10, 6, "QO"); - if (globalThis.gc) globalThis.gc(); - if (logger) logger.info(`··· Writing Section 11. QC`); - await writeQMap(fdZKey, 11, 7, "QC"); - if (globalThis.gc) globalThis.gc(); - if (logger) logger.info(`··· Writing Sections 12,13,14. Sigma1, Sigma2 & Sigma 3`); - await writeSigma(fdZKey); - if (globalThis.gc) globalThis.gc(); - if (logger) logger.info(`··· Writing Section 15. Lagrange Polynomials`); - await writeLagrangePolynomials(fdZKey); - if (globalThis.gc) globalThis.gc(); - if (logger) logger.info(`··· Writing Section 16. Powers of Tau`); - await writePtau(fdZKey); - if (globalThis.gc) globalThis.gc(); - if (logger) logger.info(`··· Writing Section 17. C0`); - await writeC0(fdZKey); - if (globalThis.gc) globalThis.gc(); - if (logger) logger.info(`··· Writing Section 2. FFlonk Header`); - await writeFFlonkHeader(fdZKey); - if (globalThis.gc) globalThis.gc(); - if (logger) logger.info("> Writing the zkey file finished"); - await fdZKey.close(); - } - async function writeZkeyHeader(fdZKey) { - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 1); - await fdZKey.writeULE32(10); - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - } - async function writeAdditions(fdZKey) { - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 3); - const buffOut = new Uint8Array(8 + 2 * sFr); - const buffOutV = new DataView(buffOut.buffer); - for (let i = 0; i < plonkAdditions.length; i++) { - if (logger && i !== 0 && i % 5e5 === 0) logger.info(` writing Additions: ${i}/${plonkAdditions.length}`); - const addition = plonkAdditions[i]; - buffOutV.setUint32(0, addition[0], true); - buffOutV.setUint32(4, addition[1], true); - buffOut.set(addition[2], 8); - buffOut.set(addition[3], 8 + sFr); - await fdZKey.write(buffOut); - } - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - } - async function writeWitnessMap(fdZKey, sectionNum, posConstraint, name) { - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); - for (let i = 0; i < plonkConstraints.length; i++) { - if (logger && i !== 0 && i % 5e5 === 0) logger.info(` writing witness ${name}: ${i}/${plonkConstraints.length}`); - await fdZKey.writeULE32(plonkConstraints[i][posConstraint]); - } - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - } - async function writeQMap(fdZKey, sectionNum, posConstraint, name) { - let Q = new ffjavascript.BigBuffer(settings.domainSize * sFr); - for (let i = 0; i < plonkConstraints.length; i++) { - Q.set(plonkConstraints[i][posConstraint], i * sFr); - if (logger && i !== 0 && i % 5e5 === 0) logger.info(` writing ${name}: ${i}/${plonkConstraints.length}`); - } - polynomials[name] = await Polynomial.fromEvaluations(Q, curve, logger); - evaluations[name] = await Evaluations.fromPolynomial(polynomials[name], 4, curve, logger); - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionNum); - await fdZKey.write(polynomials[name].coef); - await fdZKey.write(evaluations[name].eval); - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - } - async function writeSigma(fdZKey) { - const sigma = new ffjavascript.BigBuffer(sFr * settings.domainSize * 3); - const lastSeen = new BigArray(settings.nVars); - const firstPos = new BigArray(settings.nVars); - let w = Fr.one; - for (let i = 0; i < settings.domainSize; i++) { - if (i < plonkConstraints.length) { - buildSigma(plonkConstraints[i][0], i); - buildSigma(plonkConstraints[i][1], settings.domainSize + i); - buildSigma(plonkConstraints[i][2], settings.domainSize * 2 + i); - } else if (i < settings.domainSize - 2) { - buildSigma(0, i); - buildSigma(0, settings.domainSize + i); - buildSigma(0, settings.domainSize * 2 + i); - } else { - sigma.set(w, i * sFr); - sigma.set(Fr.mul(w, k1), (settings.domainSize + i) * sFr); - sigma.set(Fr.mul(w, k2), (settings.domainSize * 2 + i) * sFr); - } - w = Fr.mul(w, Fr.w[settings.cirPower]); - if (logger && i !== 0 && i % 5e5 === 0) logger.info(` writing sigma phase1: ${i}/${plonkConstraints.length}`); - } - for (let i = 0; i < settings.nVars; i++) { - if (typeof firstPos[i] !== "undefined") sigma.set(lastSeen[i], firstPos[i] * sFr); - else console.log("Variable not used"); - if (logger && i !== 0 && i % 5e5 === 0) logger.info(` writing sigma phase2: ${i}/${settings.nVars}`); - } - if (globalThis.gc) globalThis.gc(); - for (let i = 0; i < 3; i++) { - const sectionId = 0 === i ? 12 : 1 === i ? 13 : 14; - let name = "S" + (i + 1); - polynomials[name] = await Polynomial.fromEvaluations(sigma.slice(settings.domainSize * sFr * i, settings.domainSize * sFr * (i + 1)), curve, logger); - evaluations[name] = await Evaluations.fromPolynomial(polynomials[name], 4, curve, logger); - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, sectionId); - await fdZKey.write(polynomials[name].coef); - await fdZKey.write(evaluations[name].eval); - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - if (globalThis.gc) globalThis.gc(); - } - return 0; - function buildSigma(signalId, idx) { - if (typeof lastSeen[signalId] === "undefined") firstPos[signalId] = idx; - else sigma.set(lastSeen[signalId], idx * sFr); - let v; - if (idx < settings.domainSize) v = w; - else if (idx < 2 * settings.domainSize) v = Fr.mul(w, k1); - else v = Fr.mul(w, k2); - lastSeen[signalId] = v; - } - } - async function writeLagrangePolynomials(fdZKey) { - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 15); - const l = Math.max(settings.nPublic, 1); - for (let i = 0; i < l; i++) { - let buff = new ffjavascript.BigBuffer(settings.domainSize * sFr); - buff.set(Fr.one, i * sFr); - await writeP4(fdZKey, buff); - } - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - } - async function writePtau(fdZKey) { - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 16); - PTau = new ffjavascript.BigBuffer((settings.domainSize * 9 + 18) * sG1); - await fdPTau.readToBuffer(PTau, 0, (settings.domainSize * 9 + 18) * sG1, pTauSections[2][0].p); - await fdZKey.write(PTau); - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - } - async function writeC0(fdZKey) { - let C0 = new CPolynomial(8, curve, logger); - C0.addPolynomial(0, polynomials.QL); - C0.addPolynomial(1, polynomials.QR); - C0.addPolynomial(2, polynomials.QO); - C0.addPolynomial(3, polynomials.QM); - C0.addPolynomial(4, polynomials.QC); - C0.addPolynomial(5, polynomials.S1); - C0.addPolynomial(6, polynomials.S2); - C0.addPolynomial(7, polynomials.S3); - polynomials.C0 = C0.getPolynomial(); - if (polynomials.C0.degree() >= 8 * settings.domainSize) throw new Error("C0 Polynomial is not well calculated"); - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 17); - await fdZKey.write(polynomials.C0.coef); - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - } - async function writeFFlonkHeader(fdZKey) { - await (0, _iden3_binfileutils.startWriteSection)(fdZKey, 2); - const primeQ = curve.q; - const n8q = (Math.floor((ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) + 1) * 8; - await fdZKey.writeULE32(n8q); - await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeQ, n8q); - const primeR = curve.r; - const n8r = (Math.floor((ffjavascript.Scalar.bitLength(primeR) - 1) / 64) + 1) * 8; - await fdZKey.writeULE32(n8r); - await (0, _iden3_binfileutils.writeBigInt)(fdZKey, primeR, n8r); - await fdZKey.writeULE32(settings.nVars); - await fdZKey.writeULE32(settings.nPublic); - await fdZKey.writeULE32(settings.domainSize); - await fdZKey.writeULE32(plonkAdditions.length); - await fdZKey.writeULE32(plonkConstraints.length); - await fdZKey.write(k1); - await fdZKey.write(k2); - await fdZKey.write(w3); - await fdZKey.write(w4); - await fdZKey.write(w8); - await fdZKey.write(wr); - let bX_2; - bX_2 = await fdPTau.read(sG2, pTauSections[3][0].p + sG2); - await fdZKey.write(bX_2); - let commitC0 = await polynomials.C0.multiExponentiation(PTau, "C0"); - await fdZKey.write(commitC0); - await (0, _iden3_binfileutils.endWriteSection)(fdZKey); - } - async function writeP4(fdZKey, buff) { - const [coefficients, evaluations4] = await Polynomial.to4T(buff, settings.domainSize, [], Fr); - await fdZKey.write(coefficients); - await fdZKey.write(evaluations4); - return [coefficients, evaluations4]; - } - function computeK1K2() { - let k1 = Fr.two; - while (isIncluded(k1, [], settings.cirPower)) Fr.add(k1, Fr.one); - let k2 = Fr.add(k1, Fr.one); - while (isIncluded(k2, [k1], settings.cirPower)) Fr.add(k2, Fr.one); - return [k1, k2]; - function isIncluded(k, kArr, pow) { - const domainSize = 2 ** pow; - let w = Fr.one; - for (let i = 0; i < domainSize; i++) { - if (Fr.eq(k, w)) return true; - for (let j = 0; j < kArr.length; j++) if (Fr.eq(k, Fr.mul(kArr[j], w))) return true; - w = Fr.mul(w, Fr.w[pow]); - } - return false; - } - } - function computeW3() { - let generator = Fr.e(31624); - let exponent = ffjavascript.Scalar.div(3648040478639879203707734290876212514758060733402672390616367364429301415936n, ffjavascript.Scalar.e(3)); - return Fr.exp(generator, exponent); - } - function computeW4() { - return Fr.w[2]; - } - function computeW8() { - return Fr.w[3]; - } - function getOmegaCubicRoot(power, Fr) { - const firstRoot = Fr.e(467799165886069610036046866799264026481344299079011762026774533774345988080n); - return Fr.exp(firstRoot, 2 ** (28 - power)); - } - } - //#endregion - //#region src/fflonk_prove.js - var { stringifyBigInts } = ffjavascript.utils; - async function fflonkProve(zkeyFileName, witnessFileName, logger, options) { - if (logger) logger.info("FFLONK PROVER STARTED"); - if (logger) logger.info("> Reading witness file"); - const { fd: fdWtns, sections: wtnsSections } = await _iden3_binfileutils.readBinFile(witnessFileName, "wtns", 2, 1 << 25, 1 << 23); - const wtns = await readHeader(fdWtns, wtnsSections); - if (logger) logger.info("> Reading zkey file"); - const { fd: fdZKey, sections: zkeySections } = await _iden3_binfileutils.readBinFile(zkeyFileName, "zkey", 2, 1 << 25, 1 << 23); - const zkey = await readHeader$1(fdZKey, zkeySections, void 0, options); - if (zkey.protocolId !== 10) throw new Error("zkey file is not fflonk"); - if (!ffjavascript.Scalar.eq(zkey.r, wtns.q)) throw new Error("Curve of the witness does not match the curve of the proving key"); - if (wtns.nWitness !== zkey.nVars - zkey.nAdditions) throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}, ${zkey.nAdditions}`); - const curve = zkey.curve; - const Fr = curve.Fr; - const sFr = curve.Fr.n8; - const sG1 = curve.G1.F.n8 * 2; - const sDomain = zkey.domainSize * sFr; - if (logger) { - logger.info("----------------------------"); - logger.info(" FFLONK PROVE SETTINGS"); - logger.info(` Curve: ${curve.name}`); - logger.info(` Circuit power: ${zkey.power}`); - logger.info(` Domain size: ${zkey.domainSize}`); - logger.info(` Vars: ${zkey.nVars}`); - logger.info(` Public vars: ${zkey.nPublic}`); - logger.info(` Constraints: ${zkey.nConstraints}`); - logger.info(` Additions: ${zkey.nAdditions}`); - logger.info("----------------------------"); - } - if (logger) logger.info("> Reading witness file data"); - const buffWitness = await _iden3_binfileutils.readSection(fdWtns, wtnsSections, 2); - await fdWtns.close(); - buffWitness.set(Fr.zero, 0); - const buffInternalWitness = new ffjavascript.BigBuffer(zkey.nAdditions * sFr); - let buffers = {}; - let polynomials = {}; - let evaluations = {}; - let toInverse = {}; - let challenges = {}; - let roots = {}; - let proof = new Proof(curve, logger); - if (logger) logger.info(`> Reading Section 3. Additions`); - await calculateAdditions(); - if (logger) logger.info(`> Reading Sections 12,13,14. Sigma1, Sigma2 & Sigma 3`); - if (logger) logger.info("··· Reading Sigma polynomials "); - polynomials.Sigma1 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.Sigma2 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.Sigma3 = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - await fdZKey.readToBuffer(polynomials.Sigma1.coef, 0, sDomain, zkeySections[12][0].p); - await fdZKey.readToBuffer(polynomials.Sigma2.coef, 0, sDomain, zkeySections[13][0].p); - await fdZKey.readToBuffer(polynomials.Sigma3.coef, 0, sDomain, zkeySections[14][0].p); - if (logger) logger.info("··· Reading Sigma evaluations"); - evaluations.Sigma1 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.Sigma2 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.Sigma3 = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - await fdZKey.readToBuffer(evaluations.Sigma1.eval, 0, sDomain * 4, zkeySections[12][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.Sigma2.eval, 0, sDomain * 4, zkeySections[13][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.Sigma3.eval, 0, sDomain * 4, zkeySections[14][0].p + sDomain); - if (logger) logger.info(`> Reading Section 16. Powers of Tau`); - const PTau = new ffjavascript.BigBuffer(zkey.domainSize * 16 * sG1); - await fdZKey.readToBuffer(PTau, 0, (zkey.domainSize * 9 + 18) * sG1, zkeySections[16][0].p); - if (globalThis.gc) globalThis.gc(); - if (logger) logger.info(""); - if (logger) logger.info("> ROUND 1"); - await round1(); - delete polynomials.T0; - delete evaluations.QL; - delete evaluations.QR; - delete evaluations.QM; - delete evaluations.QO; - delete evaluations.QC; - if (globalThis.gc) globalThis.gc(); - if (logger) logger.info("> ROUND 2"); - await round2(); - delete buffers.A; - delete buffers.B; - delete buffers.C; - delete evaluations.A; - delete evaluations.B; - delete evaluations.C; - delete evaluations.Sigma1; - delete evaluations.Sigma2; - delete evaluations.Sigma3; - delete evaluations.lagrange1; - delete evaluations.Z; - if (globalThis.gc) globalThis.gc(); - if (logger) logger.info("> ROUND 3"); - await round3(); - delete polynomials.A; - delete polynomials.B; - delete polynomials.C; - delete polynomials.Z; - delete polynomials.T1; - delete polynomials.T2; - delete polynomials.Sigma1; - delete polynomials.Sigma2; - delete polynomials.Sigma3; - delete polynomials.QL; - delete polynomials.QR; - delete polynomials.QM; - delete polynomials.QC; - delete polynomials.QO; - if (globalThis.gc) globalThis.gc(); - if (logger) logger.info("> ROUND 4"); - await round4(); - if (globalThis.gc) globalThis.gc(); - if (logger) logger.info("> ROUND 5"); - await round5(); - delete polynomials.C0; - delete polynomials.C1; - delete polynomials.C2; - delete polynomials.R1; - delete polynomials.R2; - delete polynomials.F; - delete polynomials.L; - delete polynomials.ZT; - delete polynomials.ZTS2; - await fdZKey.close(); - if (globalThis.gc) globalThis.gc(); - proof.addEvaluation("inv", getMontgomeryBatchedInverse()); - let _proof = proof.toObjectProof(); - _proof.protocol = "fflonk"; - _proof.curve = curve.name; - let publicSignals = []; - for (let i = 1; i <= zkey.nPublic; i++) { - const i_sFr = i * sFr; - const pub = buffWitness.slice(i_sFr, i_sFr + sFr); - publicSignals.push(ffjavascript.Scalar.fromRprLE(pub)); - } - if (logger) logger.info("FFLONK PROVER FINISHED"); - return { - proof: stringifyBigInts(_proof), - publicSignals: stringifyBigInts(publicSignals) - }; - async function calculateAdditions() { - if (logger) logger.info("··· Computing additions"); - const additionsBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 3); - const sSum = 8 + sFr * 2; - for (let i = 0; i < zkey.nAdditions; i++) { - if (logger && 0 !== i && i % 1e5 === 0) logger.info(` addition ${i}/${zkey.nAdditions}`); - let offset = i * sSum; - const signalId1 = readUInt32(additionsBuff, offset); - offset += 4; - const signalId2 = readUInt32(additionsBuff, offset); - offset += 4; - const factor1 = additionsBuff.slice(offset, offset + sFr); - offset += sFr; - const factor2 = additionsBuff.slice(offset, offset + sFr); - const witness1 = getWitness(signalId1); - const witness2 = getWitness(signalId2); - const result = Fr.add(Fr.mul(factor1, witness1), Fr.mul(factor2, witness2)); - buffInternalWitness.set(result, sFr * i); - } - } - function readUInt32(b, o) { - const buff = b.slice(o, o + 4); - return new DataView(buff.buffer, buff.byteOffset, buff.byteLength).getUint32(0, true); - } - function getWitness(idx) { - let diff = zkey.nVars - zkey.nAdditions; - if (idx < diff) return buffWitness.slice(idx * sFr, idx * sFr + sFr); - else if (idx < zkey.nVars) { - const offset = (idx - diff) * sFr; - return buffInternalWitness.slice(offset, offset + sFr); - } - return Fr.zero; - } - async function round1() { - challenges.b = []; - for (let i = 1; i <= 9; i++) challenges.b[i] = Fr.random(); - if (logger) logger.info("> Computing A, B, C wire polynomials"); - await computeWirePolynomials(); - if (logger) logger.info("> Computing T0 polynomial"); - await computeT0(); - if (logger) logger.info("> Computing C1 polynomial"); - await computeC1(); - if (logger) logger.info("> Computing C1 multi exponentiation"); - let commitC1 = await polynomials.C1.multiExponentiation(PTau, "C1"); - proof.addPolynomial("C1", commitC1); - return 0; - async function computeWirePolynomials() { - if (logger) logger.info("··· Reading data from zkey file"); - buffers.A = new ffjavascript.BigBuffer(sDomain); - buffers.B = new ffjavascript.BigBuffer(sDomain); - buffers.C = new ffjavascript.BigBuffer(sDomain); - const aMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 4); - const bMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 5); - const cMapBuff = await _iden3_binfileutils.readSection(fdZKey, zkeySections, 6); - for (let i = 0; i < zkey.nConstraints; i++) { - const i_sFr = i * sFr; - const offset = i * 4; - const signalIdA = readUInt32(aMapBuff, offset); - buffers.A.set(getWitness(signalIdA), i_sFr); - const signalIdB = readUInt32(bMapBuff, offset); - buffers.B.set(getWitness(signalIdB), i_sFr); - const signalIdC = readUInt32(cMapBuff, offset); - buffers.C.set(getWitness(signalIdC), i_sFr); - } - buffers.A.set(challenges.b[1], sDomain - 64); - buffers.A.set(challenges.b[2], sDomain - 32); - buffers.B.set(challenges.b[3], sDomain - 64); - buffers.B.set(challenges.b[4], sDomain - 32); - buffers.C.set(challenges.b[5], sDomain - 64); - buffers.C.set(challenges.b[6], sDomain - 32); - buffers.A = await Fr.batchToMontgomery(buffers.A); - buffers.B = await Fr.batchToMontgomery(buffers.B); - buffers.C = await Fr.batchToMontgomery(buffers.C); - if (logger) logger.info("··· Computing A ifft"); - polynomials.A = await Polynomial.fromEvaluations(buffers.A, curve, logger); - if (logger) logger.info("··· Computing B ifft"); - polynomials.B = await Polynomial.fromEvaluations(buffers.B, curve, logger); - if (logger) logger.info("··· Computing C ifft"); - polynomials.C = await Polynomial.fromEvaluations(buffers.C, curve, logger); - if (logger) logger.info("··· Computing A fft"); - evaluations.A = await Evaluations.fromPolynomial(polynomials.A, 4, curve, logger); - if (logger) logger.info("··· Computing B fft"); - evaluations.B = await Evaluations.fromPolynomial(polynomials.B, 4, curve, logger); - if (logger) logger.info("··· Computing C fft"); - evaluations.C = await Evaluations.fromPolynomial(polynomials.C, 4, curve, logger); - if (polynomials.A.degree() >= zkey.domainSize) throw new Error("A Polynomial is not well calculated"); - if (polynomials.B.degree() >= zkey.domainSize) throw new Error("B Polynomial is not well calculated"); - if (polynomials.C.degree() >= zkey.domainSize) throw new Error("C Polynomial is not well calculated"); - } - async function computeT0() { - if (logger) logger.info(`··· Reading sections 7, 8, 9, 10, 11. Q selectors`); - evaluations.QL = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QR = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QM = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QO = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - evaluations.QC = new Evaluations(new ffjavascript.BigBuffer(sDomain * 4), curve, logger); - await fdZKey.readToBuffer(evaluations.QL.eval, 0, sDomain * 4, zkeySections[7][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QR.eval, 0, sDomain * 4, zkeySections[8][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QM.eval, 0, sDomain * 4, zkeySections[9][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QO.eval, 0, sDomain * 4, zkeySections[10][0].p + sDomain); - await fdZKey.readToBuffer(evaluations.QC.eval, 0, sDomain * 4, zkeySections[11][0].p + sDomain); - evaluations.lagrange1 = new Evaluations(await _iden3_binfileutils.readSection(fdZKey, zkeySections, 15), curve, logger); - buffers.T0 = new ffjavascript.BigBuffer(sDomain * 4); - if (logger) logger.info("··· Computing T0 evaluations"); - for (let i = 0; i < zkey.domainSize * 4; i++) { - if (logger && 0 !== i && i % 1e5 === 0) logger.info(` T0 evaluation ${i}/${zkey.domainSize * 4}`); - const a = evaluations.A.getEvaluation(i); - const b = evaluations.B.getEvaluation(i); - const c = evaluations.C.getEvaluation(i); - const ql = evaluations.QL.getEvaluation(i); - const qr = evaluations.QR.getEvaluation(i); - const qm = evaluations.QM.getEvaluation(i); - const qo = evaluations.QO.getEvaluation(i); - const qc = evaluations.QC.getEvaluation(i); - let pi = Fr.zero; - for (let j = 0; j < zkey.nPublic; j++) { - const offset = j * 5 * zkey.domainSize + zkey.domainSize + i; - const lPol = evaluations.lagrange1.getEvaluation(offset); - const aVal = buffers.A.slice(j * sFr, (j + 1) * sFr); - pi = Fr.sub(pi, Fr.mul(lPol, aVal)); - } - const e1 = Fr.mul(a, ql); - const e2 = Fr.mul(b, qr); - const e3 = Fr.mul(Fr.mul(a, b), qm); - const e4 = Fr.mul(c, qo); - const t0 = Fr.add(e1, Fr.add(e2, Fr.add(e3, Fr.add(e4, Fr.add(qc, pi))))); - buffers.T0.set(t0, i * sFr); - } - if (logger) logger.info("buffer T0: " + buffers.T0.byteLength / sFr); - if (logger) logger.info("··· Computing T0 ifft"); - polynomials.T0 = await Polynomial.fromEvaluations(buffers.T0, curve, logger); - if (logger) logger.info("T0 length: " + polynomials.T0.length()); - if (logger) logger.info("T0 degree: " + polynomials.T0.degree()); - if (logger) logger.info("··· Computing T0 / ZH"); - polynomials.T0.divByZerofier(zkey.domainSize, Fr.one); - if (polynomials.T0.degree() >= 2 * zkey.domainSize - 2) throw new Error(`T0 Polynomial is not well calculated (degree is ${polynomials.T0.degree()} and must be less than ${2 * zkey.domainSize + 2}`); - delete buffers.T0; - } - async function computeC1() { - let C1 = new CPolynomial(4, curve, logger); - C1.addPolynomial(0, polynomials.A); - C1.addPolynomial(1, polynomials.B); - C1.addPolynomial(2, polynomials.C); - C1.addPolynomial(3, polynomials.T0); - polynomials.C1 = C1.getPolynomial(); - if (polynomials.C1.degree() >= 8 * zkey.domainSize - 8) throw new Error("C1 Polynomial is not well calculated"); - } - } - async function round2() { - if (logger) logger.info("> Computing challenges beta and gamma"); - const transcript = new Keccak256Transcript(curve); - transcript.addPolCommitment(zkey.C0); - for (let i = 0; i < zkey.nPublic; i++) transcript.addScalar(buffers.A.slice(i * sFr, i * sFr + sFr)); - transcript.addPolCommitment(proof.getPolynomial("C1")); - challenges.beta = transcript.getChallenge(); - if (logger) logger.info("··· challenges.beta: " + Fr.toString(challenges.beta)); - transcript.reset(); - transcript.addScalar(challenges.beta); - challenges.gamma = transcript.getChallenge(); - if (logger) logger.info("··· challenges.gamma: " + Fr.toString(challenges.gamma)); - if (logger) logger.info("> Computing Z polynomial"); - await computeZ(); - if (logger) logger.info("> Computing T1 polynomial"); - await computeT1(); - if (logger) logger.info("> Computing T2 polynomial"); - await computeT2(); - if (logger) logger.info("> Computing C2 polynomial"); - await computeC2(); - if (logger) logger.info("> Computing C2 multi exponentiation"); - let commitC2 = await polynomials.C2.multiExponentiation(PTau, "C2"); - proof.addPolynomial("C2", commitC2); - return 0; - async function computeZ() { - if (logger) logger.info("··· Computing Z evaluations"); - let numArr = new ffjavascript.BigBuffer(sDomain); - let denArr = new ffjavascript.BigBuffer(sDomain); - numArr.set(Fr.one, 0); - denArr.set(Fr.one, 0); - let w = Fr.one; - for (let i = 0; i < zkey.domainSize; i++) { - if (logger && 0 !== i && i % 1e5 === 0) logger.info(` Z evaluation ${i}/${zkey.domainSize}`); - const i_sFr = i * sFr; - const betaw = Fr.mul(challenges.beta, w); - let num1 = buffers.A.slice(i_sFr, i_sFr + sFr); - num1 = Fr.add(num1, betaw); - num1 = Fr.add(num1, challenges.gamma); - let num2 = buffers.B.slice(i_sFr, i_sFr + sFr); - num2 = Fr.add(num2, Fr.mul(zkey.k1, betaw)); - num2 = Fr.add(num2, challenges.gamma); - let num3 = buffers.C.slice(i_sFr, i_sFr + sFr); - num3 = Fr.add(num3, Fr.mul(zkey.k2, betaw)); - num3 = Fr.add(num3, challenges.gamma); - let num = Fr.mul(num1, Fr.mul(num2, num3)); - let den1 = buffers.A.slice(i_sFr, i_sFr + sFr); - den1 = Fr.add(den1, Fr.mul(challenges.beta, evaluations.Sigma1.getEvaluation(i * 4))); - den1 = Fr.add(den1, challenges.gamma); - let den2 = buffers.B.slice(i_sFr, i_sFr + sFr); - den2 = Fr.add(den2, Fr.mul(challenges.beta, evaluations.Sigma2.getEvaluation(i * 4))); - den2 = Fr.add(den2, challenges.gamma); - let den3 = buffers.C.slice(i_sFr, i_sFr + sFr); - den3 = Fr.add(den3, Fr.mul(challenges.beta, evaluations.Sigma3.getEvaluation(i * 4))); - den3 = Fr.add(den3, challenges.gamma); - let den = Fr.mul(den1, Fr.mul(den2, den3)); - num = Fr.mul(numArr.slice(i_sFr, i_sFr + sFr), num); - numArr.set(num, (i + 1) % zkey.domainSize * sFr); - den = Fr.mul(denArr.slice(i_sFr, i_sFr + sFr), den); - denArr.set(den, (i + 1) % zkey.domainSize * sFr); - w = Fr.mul(w, Fr.w[zkey.power]); - } - denArr = await Fr.batchInverse(denArr); - for (let i = 0; i < zkey.domainSize; i++) { - const i_sFr = i * sFr; - const z = Fr.mul(numArr.slice(i_sFr, i_sFr + sFr), denArr.slice(i_sFr, i_sFr + sFr)); - numArr.set(z, i_sFr); - } - buffers.Z = numArr; - if (!Fr.eq(numArr.slice(0, sFr), Fr.one)) throw new Error("Copy constraints does not match"); - if (logger) logger.info("··· Computing Z ifft"); - polynomials.Z = await Polynomial.fromEvaluations(buffers.Z, curve, logger); - if (logger) logger.info("··· Computing Z fft"); - evaluations.Z = await Evaluations.fromPolynomial(polynomials.Z, 4, curve, logger); - polynomials.Z.blindCoefficients([ - challenges.b[9], - challenges.b[8], - challenges.b[7] - ]); - if (polynomials.Z.degree() >= zkey.domainSize + 3) throw new Error("Z Polynomial is not well calculated"); - delete buffers.Z; - } - async function computeT1() { - if (logger) logger.info("··· Computing T1 evaluations"); - buffers.T1 = new ffjavascript.BigBuffer(sDomain * 2); - buffers.T1z = new ffjavascript.BigBuffer(sDomain * 2); - let omega = Fr.one; - for (let i = 0; i < zkey.domainSize * 2; i++) { - if (logger && 0 !== i && i % 1e5 === 0) logger.info(` T1 evaluation ${i}/${zkey.domainSize * 4}`); - const omega2 = Fr.square(omega); - const z = evaluations.Z.getEvaluation(i * 2); - const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omega2), Fr.mul(challenges.b[8], omega)), challenges.b[9]); - const lagrange1 = evaluations.lagrange1.getEvaluation(zkey.domainSize + i * 2); - let t1 = Fr.mul(Fr.sub(z, Fr.one), lagrange1); - let t1z = Fr.mul(zp, lagrange1); - buffers.T1.set(t1, i * sFr); - buffers.T1z.set(t1z, i * sFr); - omega = Fr.mul(omega, Fr.w[zkey.power + 1]); - } - if (logger) logger.info("··· Computing T1 ifft"); - polynomials.T1 = await Polynomial.fromEvaluations(buffers.T1, curve, logger); - polynomials.T1.divByZerofier(zkey.domainSize, Fr.one); - if (logger) logger.info("··· Computing T1z ifft"); - polynomials.T1z = await Polynomial.fromEvaluations(buffers.T1z, curve, logger); - polynomials.T1.add(polynomials.T1z); - if (polynomials.T1.degree() >= zkey.domainSize + 2) throw new Error("T1 Polynomial is not well calculated"); - delete buffers.T1; - delete buffers.T1z; - delete polynomials.T1z; - } - async function computeT2() { - if (logger) logger.info("··· Computing T2 evaluations"); - buffers.T2 = new ffjavascript.BigBuffer(sDomain * 4); - buffers.T2z = new ffjavascript.BigBuffer(sDomain * 4); - let omega = Fr.one; - for (let i = 0; i < zkey.domainSize * 4; i++) { - if (logger && 0 !== i && i % 1e5 === 0) logger.info(` T2 evaluation ${i}/${zkey.domainSize * 4}`); - const omega2 = Fr.square(omega); - const omegaW = Fr.mul(omega, Fr.w[zkey.power]); - const omegaW2 = Fr.square(omegaW); - const a = evaluations.A.getEvaluation(i); - const b = evaluations.B.getEvaluation(i); - const c = evaluations.C.getEvaluation(i); - const z = evaluations.Z.getEvaluation(i); - const zW = evaluations.Z.getEvaluation((zkey.domainSize * 4 + 4 + i) % (zkey.domainSize * 4)); - const zp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omega2), Fr.mul(challenges.b[8], omega)), challenges.b[9]); - const zWp = Fr.add(Fr.add(Fr.mul(challenges.b[7], omegaW2), Fr.mul(challenges.b[8], omegaW)), challenges.b[9]); - const sigma1 = evaluations.Sigma1.getEvaluation(i); - const sigma2 = evaluations.Sigma2.getEvaluation(i); - const sigma3 = evaluations.Sigma3.getEvaluation(i); - const betaX = Fr.mul(challenges.beta, omega); - let e11 = Fr.add(a, betaX); - e11 = Fr.add(e11, challenges.gamma); - let e12 = Fr.add(b, Fr.mul(betaX, zkey.k1)); - e12 = Fr.add(e12, challenges.gamma); - let e13 = Fr.add(c, Fr.mul(betaX, zkey.k2)); - e13 = Fr.add(e13, challenges.gamma); - let e1 = Fr.mul(Fr.mul(Fr.mul(e11, e12), e13), z); - let e1z = Fr.mul(Fr.mul(Fr.mul(e11, e12), e13), zp); - let e21 = Fr.add(a, Fr.mul(challenges.beta, sigma1)); - e21 = Fr.add(e21, challenges.gamma); - let e22 = Fr.add(b, Fr.mul(challenges.beta, sigma2)); - e22 = Fr.add(e22, challenges.gamma); - let e23 = Fr.add(c, Fr.mul(challenges.beta, sigma3)); - e23 = Fr.add(e23, challenges.gamma); - let e2 = Fr.mul(Fr.mul(Fr.mul(e21, e22), e23), zW); - let e2z = Fr.mul(Fr.mul(Fr.mul(e21, e22), e23), zWp); - let t2 = Fr.sub(e1, e2); - let t2z = Fr.sub(e1z, e2z); - buffers.T2.set(t2, i * sFr); - buffers.T2z.set(t2z, i * sFr); - omega = Fr.mul(omega, Fr.w[zkey.power + 2]); - } - if (logger) logger.info("··· Computing T2 ifft"); - polynomials.T2 = await Polynomial.fromEvaluations(buffers.T2, curve, logger); - if (logger) logger.info("··· Computing T2 / ZH"); - polynomials.T2.divByZerofier(zkey.domainSize, Fr.one); - if (logger) logger.info("··· Computing T2z ifft"); - polynomials.T2z = await Polynomial.fromEvaluations(buffers.T2z, curve, logger); - polynomials.T2.add(polynomials.T2z); - if (polynomials.T2.degree() >= 3 * zkey.domainSize) throw new Error("T2 Polynomial is not well calculated"); - delete buffers.T2; - delete buffers.T2z; - delete polynomials.T2z; - } - async function computeC2() { - let C2 = new CPolynomial(3, curve, logger); - C2.addPolynomial(0, polynomials.Z); - C2.addPolynomial(1, polynomials.T1); - C2.addPolynomial(2, polynomials.T2); - polynomials.C2 = C2.getPolynomial(); - if (polynomials.C2.degree() >= 9 * zkey.domainSize) throw new Error("C2 Polynomial is not well calculated"); - } - } - async function round3() { - if (logger) logger.info("> Computing challenge xi"); - const transcript = new Keccak256Transcript(curve); - transcript.addScalar(challenges.gamma); - transcript.addPolCommitment(proof.getPolynomial("C2")); - challenges.xiSeed = transcript.getChallenge(); - const xiSeed2 = Fr.square(challenges.xiSeed); - roots.w8 = []; - roots.w8[0] = Fr.one; - for (let i = 1; i < 8; i++) roots.w8[i] = Fr.mul(roots.w8[i - 1], zkey.w8); - roots.w4 = []; - roots.w4[0] = Fr.one; - for (let i = 1; i < 4; i++) roots.w4[i] = Fr.mul(roots.w4[i - 1], zkey.w4); - roots.w3 = []; - roots.w3[0] = Fr.one; - roots.w3[1] = zkey.w3; - roots.w3[2] = Fr.square(zkey.w3); - roots.S0 = {}; - roots.S0.h0w8 = []; - roots.S0.h0w8[0] = Fr.mul(xiSeed2, challenges.xiSeed); - for (let i = 1; i < 8; i++) roots.S0.h0w8[i] = Fr.mul(roots.S0.h0w8[0], roots.w8[i]); - roots.S1 = {}; - roots.S1.h1w4 = []; - roots.S1.h1w4[0] = Fr.square(roots.S0.h0w8[0]); - for (let i = 1; i < 4; i++) roots.S1.h1w4[i] = Fr.mul(roots.S1.h1w4[0], roots.w4[i]); - roots.S2 = {}; - roots.S2.h2w3 = []; - roots.S2.h2w3[0] = Fr.mul(roots.S1.h1w4[0], xiSeed2); - roots.S2.h2w3[1] = Fr.mul(roots.S2.h2w3[0], roots.w3[1]); - roots.S2.h2w3[2] = Fr.mul(roots.S2.h2w3[0], roots.w3[2]); - roots.S2.h3w3 = []; - roots.S2.h3w3[0] = Fr.mul(roots.S2.h2w3[0], zkey.wr); - roots.S2.h3w3[1] = Fr.mul(roots.S2.h3w3[0], roots.w3[1]); - roots.S2.h3w3[2] = Fr.mul(roots.S2.h3w3[0], roots.w3[2]); - challenges.xi = Fr.mul(Fr.square(roots.S2.h2w3[0]), roots.S2.h2w3[0]); - if (logger) logger.info("··· challenges.xi: " + Fr.toString(challenges.xi)); - polynomials.QL = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QR = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QM = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QO = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - polynomials.QC = new Polynomial(new ffjavascript.BigBuffer(sDomain), curve, logger); - await fdZKey.readToBuffer(polynomials.QL.coef, 0, sDomain, zkeySections[7][0].p); - await fdZKey.readToBuffer(polynomials.QR.coef, 0, sDomain, zkeySections[8][0].p); - await fdZKey.readToBuffer(polynomials.QM.coef, 0, sDomain, zkeySections[9][0].p); - await fdZKey.readToBuffer(polynomials.QO.coef, 0, sDomain, zkeySections[10][0].p); - await fdZKey.readToBuffer(polynomials.QC.coef, 0, sDomain, zkeySections[11][0].p); - if (logger) logger.info("··· Computing evaluations"); - proof.addEvaluation("ql", polynomials.QL.evaluate(challenges.xi)); - proof.addEvaluation("qr", polynomials.QR.evaluate(challenges.xi)); - proof.addEvaluation("qm", polynomials.QM.evaluate(challenges.xi)); - proof.addEvaluation("qo", polynomials.QO.evaluate(challenges.xi)); - proof.addEvaluation("qc", polynomials.QC.evaluate(challenges.xi)); - proof.addEvaluation("s1", polynomials.Sigma1.evaluate(challenges.xi)); - proof.addEvaluation("s2", polynomials.Sigma2.evaluate(challenges.xi)); - proof.addEvaluation("s3", polynomials.Sigma3.evaluate(challenges.xi)); - proof.addEvaluation("a", polynomials.A.evaluate(challenges.xi)); - proof.addEvaluation("b", polynomials.B.evaluate(challenges.xi)); - proof.addEvaluation("c", polynomials.C.evaluate(challenges.xi)); - proof.addEvaluation("z", polynomials.Z.evaluate(challenges.xi)); - challenges.xiw = Fr.mul(challenges.xi, Fr.w[zkey.power]); - proof.addEvaluation("zw", polynomials.Z.evaluate(challenges.xiw)); - proof.addEvaluation("t1w", polynomials.T1.evaluate(challenges.xiw)); - proof.addEvaluation("t2w", polynomials.T2.evaluate(challenges.xiw)); - } - async function round4() { - if (logger) logger.info("> Computing challenge alpha"); - const transcript = new Keccak256Transcript(curve); - transcript.addScalar(challenges.xiSeed); - transcript.addScalar(proof.getEvaluation("ql")); - transcript.addScalar(proof.getEvaluation("qr")); - transcript.addScalar(proof.getEvaluation("qm")); - transcript.addScalar(proof.getEvaluation("qo")); - transcript.addScalar(proof.getEvaluation("qc")); - transcript.addScalar(proof.getEvaluation("s1")); - transcript.addScalar(proof.getEvaluation("s2")); - transcript.addScalar(proof.getEvaluation("s3")); - transcript.addScalar(proof.getEvaluation("a")); - transcript.addScalar(proof.getEvaluation("b")); - transcript.addScalar(proof.getEvaluation("c")); - transcript.addScalar(proof.getEvaluation("z")); - transcript.addScalar(proof.getEvaluation("zw")); - transcript.addScalar(proof.getEvaluation("t1w")); - transcript.addScalar(proof.getEvaluation("t2w")); - challenges.alpha = transcript.getChallenge(); - if (logger) logger.info("··· challenges.alpha: " + Fr.toString(challenges.alpha)); - if (logger) logger.info("> Reading C0 polynomial"); - polynomials.C0 = new Polynomial(new ffjavascript.BigBuffer(sDomain * 8), curve, logger); - await fdZKey.readToBuffer(polynomials.C0.coef, 0, sDomain * 8, zkeySections[17][0].p); - if (logger) logger.info("> Computing R0 polynomial"); - computeR0(); - if (logger) logger.info("> Computing R1 polynomial"); - computeR1(); - if (logger) logger.info("> Computing R2 polynomial"); - computeR2(); - if (logger) logger.info("> Computing F polynomial"); - await computeF(); - if (logger) logger.info("> Computing W1 multi exponentiation"); - let commitW1 = await polynomials.F.multiExponentiation(PTau, "W1"); - proof.addPolynomial("W1", commitW1); - return 0; - function computeR0() { - polynomials.R0 = Polynomial.lagrangePolynomialInterpolation([ - roots.S0.h0w8[0], - roots.S0.h0w8[1], - roots.S0.h0w8[2], - roots.S0.h0w8[3], - roots.S0.h0w8[4], - roots.S0.h0w8[5], - roots.S0.h0w8[6], - roots.S0.h0w8[7] - ], [ - polynomials.C0.evaluate(roots.S0.h0w8[0]), - polynomials.C0.evaluate(roots.S0.h0w8[1]), - polynomials.C0.evaluate(roots.S0.h0w8[2]), - polynomials.C0.evaluate(roots.S0.h0w8[3]), - polynomials.C0.evaluate(roots.S0.h0w8[4]), - polynomials.C0.evaluate(roots.S0.h0w8[5]), - polynomials.C0.evaluate(roots.S0.h0w8[6]), - polynomials.C0.evaluate(roots.S0.h0w8[7]) - ], curve); - if (polynomials.R0.degree() > 7) throw new Error("R0 Polynomial is not well calculated"); - } - function computeR1() { - polynomials.R1 = Polynomial.lagrangePolynomialInterpolation([ - roots.S1.h1w4[0], - roots.S1.h1w4[1], - roots.S1.h1w4[2], - roots.S1.h1w4[3] - ], [ - polynomials.C1.evaluate(roots.S1.h1w4[0]), - polynomials.C1.evaluate(roots.S1.h1w4[1]), - polynomials.C1.evaluate(roots.S1.h1w4[2]), - polynomials.C1.evaluate(roots.S1.h1w4[3]) - ], curve); - if (polynomials.R1.degree() > 3) throw new Error("R1 Polynomial is not well calculated"); - } - function computeR2() { - polynomials.R2 = Polynomial.lagrangePolynomialInterpolation([ - roots.S2.h2w3[0], - roots.S2.h2w3[1], - roots.S2.h2w3[2], - roots.S2.h3w3[0], - roots.S2.h3w3[1], - roots.S2.h3w3[2] - ], [ - polynomials.C2.evaluate(roots.S2.h2w3[0]), - polynomials.C2.evaluate(roots.S2.h2w3[1]), - polynomials.C2.evaluate(roots.S2.h2w3[2]), - polynomials.C2.evaluate(roots.S2.h3w3[0]), - polynomials.C2.evaluate(roots.S2.h3w3[1]), - polynomials.C2.evaluate(roots.S2.h3w3[2]) - ], curve); - if (polynomials.R2.degree() > 5) throw new Error("R2 Polynomial is not well calculated"); - } - async function computeF() { - if (logger) logger.info("··· Computing F polynomial"); - polynomials.F = Polynomial.fromPolynomial(polynomials.C0, curve, logger); - polynomials.F.sub(polynomials.R0); - polynomials.F.divByZerofier(8, challenges.xi); - let f2 = Polynomial.fromPolynomial(polynomials.C1, curve, logger); - f2.sub(polynomials.R1); - f2.mulScalar(challenges.alpha); - f2.divByZerofier(4, challenges.xi); - let f3 = Polynomial.fromPolynomial(polynomials.C2, curve, logger); - f3.sub(polynomials.R2); - f3.mulScalar(Fr.square(challenges.alpha)); - f3.divByZerofier(3, challenges.xi); - f3.divByZerofier(3, challenges.xiw); - polynomials.F.add(f2); - polynomials.F.add(f3); - if (polynomials.F.degree() >= 9 * zkey.domainSize - 6) throw new Error("F Polynomial is not well calculated"); - } - } - async function round5() { - if (logger) logger.info("> Computing challenge y"); - const transcript = new Keccak256Transcript(curve); - transcript.addScalar(challenges.alpha); - transcript.addPolCommitment(proof.getPolynomial("W1")); - challenges.y = transcript.getChallenge(); - if (logger) logger.info("··· challenges.y: " + Fr.toString(challenges.y)); - if (logger) logger.info("> Computing L polynomial"); - await computeL(); - if (logger) logger.info("> Computing ZTS2 polynomial"); - await computeZTS2(); - let ZTS2Y = polynomials.ZTS2.evaluate(challenges.y); - ZTS2Y = Fr.inv(ZTS2Y); - polynomials.L.mulScalar(ZTS2Y); - const polDividend = Polynomial.fromCoefficientsArray([Fr.neg(challenges.y), Fr.one], curve); - if (logger) logger.info("> Computing W' = L / ZTS2 polynomial"); - const polRemainder = polynomials.L.divBy(polDividend); - if (polRemainder.degree() > 0) throw new Error(`Degree of L(X)/(ZTS2(y)(X-y)) remainder is ${polRemainder.degree()} and should be 0`); - if (polynomials.L.degree() >= 9 * zkey.domainSize - 1) throw new Error("Degree of L(X)/(ZTS2(y)(X-y)) is not correct"); - if (logger) logger.info("> Computing W' multi exponentiation"); - let commitW2 = await polynomials.L.multiExponentiation(PTau, "W2"); - proof.addPolynomial("W2", commitW2); - return 0; - async function computeL() { - if (logger) logger.info("··· Computing L polynomial"); - const evalR0Y = polynomials.R0.evaluate(challenges.y); - const evalR1Y = polynomials.R1.evaluate(challenges.y); - const evalR2Y = polynomials.R2.evaluate(challenges.y); - let mulL0 = Fr.sub(challenges.y, roots.S0.h0w8[0]); - for (let i = 1; i < 8; i++) mulL0 = Fr.mul(mulL0, Fr.sub(challenges.y, roots.S0.h0w8[i])); - let mulL1 = Fr.sub(challenges.y, roots.S1.h1w4[0]); - for (let i = 1; i < 4; i++) mulL1 = Fr.mul(mulL1, Fr.sub(challenges.y, roots.S1.h1w4[i])); - let mulL2 = Fr.sub(challenges.y, roots.S2.h2w3[0]); - for (let i = 1; i < 3; i++) mulL2 = Fr.mul(mulL2, Fr.sub(challenges.y, roots.S2.h2w3[i])); - for (let i = 0; i < 3; i++) mulL2 = Fr.mul(mulL2, Fr.sub(challenges.y, roots.S2.h3w3[i])); - let preL0 = Fr.mul(mulL1, mulL2); - let preL1 = Fr.mul(challenges.alpha, Fr.mul(mulL0, mulL2)); - let preL2 = Fr.mul(Fr.square(challenges.alpha), Fr.mul(mulL0, mulL1)); - toInverse["denH1"] = mulL1; - toInverse["denH2"] = mulL2; - polynomials.L = Polynomial.fromPolynomial(polynomials.C0, curve, logger); - polynomials.L.subScalar(evalR0Y); - polynomials.L.mulScalar(preL0); - let l2 = Polynomial.fromPolynomial(polynomials.C1, curve, logger); - l2.subScalar(evalR1Y); - l2.mulScalar(preL1); - let l3 = Polynomial.fromPolynomial(polynomials.C2, curve, logger); - l3.subScalar(evalR2Y); - l3.mulScalar(preL2); - polynomials.L.add(l2); - polynomials.L.add(l3); - if (logger) logger.info("> Computing ZT polynomial"); - await computeZT(); - const evalZTY = polynomials.ZT.evaluate(challenges.y); - polynomials.F.mulScalar(evalZTY); - polynomials.L.sub(polynomials.F); - if (polynomials.L.degree() >= 9 * zkey.domainSize) throw new Error("L Polynomial is not well calculated"); - delete buffers.L; - } - async function computeZT() { - polynomials.ZT = Polynomial.zerofierPolynomial([ - roots.S0.h0w8[0], - roots.S0.h0w8[1], - roots.S0.h0w8[2], - roots.S0.h0w8[3], - roots.S0.h0w8[4], - roots.S0.h0w8[5], - roots.S0.h0w8[6], - roots.S0.h0w8[7], - roots.S1.h1w4[0], - roots.S1.h1w4[1], - roots.S1.h1w4[2], - roots.S1.h1w4[3], - roots.S2.h2w3[0], - roots.S2.h2w3[1], - roots.S2.h2w3[2], - roots.S2.h3w3[0], - roots.S2.h3w3[1], - roots.S2.h3w3[2] - ], curve); - } - async function computeZTS2() { - polynomials.ZTS2 = Polynomial.zerofierPolynomial([ - roots.S1.h1w4[0], - roots.S1.h1w4[1], - roots.S1.h1w4[2], - roots.S1.h1w4[3], - roots.S2.h2w3[0], - roots.S2.h2w3[1], - roots.S2.h2w3[2], - roots.S2.h3w3[0], - roots.S2.h3w3[1], - roots.S2.h3w3[2] - ], curve); - } - } - function getMontgomeryBatchedInverse() { - let xiN = challenges.xi; - for (let i = 0; i < zkey.power; i++) xiN = Fr.square(xiN); - toInverse["zh"] = Fr.sub(xiN, Fr.one); - computeLiS0(toInverse, roots.S0.h0w8, challenges.y, curve); - computeLiS1(toInverse, roots.S1.h1w4, challenges.y, curve); - computeLiS2(toInverse, roots.S2.h2w3, roots.S2.h3w3, challenges.y, challenges.xi, challenges.xiw, curve); - const size = Math.max(1, zkey.nPublic); - let w = Fr.one; - for (let i = 0; i < size; i++) { - toInverse["Li_" + (i + 1)] = Fr.mul(Fr.e(zkey.domainSize), Fr.sub(challenges.xi, w)); - w = Fr.mul(w, Fr.w[zkey.power]); - } - let mulAccumulator = Fr.one; - for (const element of Object.values(toInverse)) if (Array.isArray(element)) for (const subElement of element) mulAccumulator = Fr.mul(mulAccumulator, subElement); - else mulAccumulator = Fr.mul(mulAccumulator, element); - return Fr.inv(mulAccumulator); - function computeLiS0(toInverse, roots, x, curve) { - const Fr = curve.Fr; - const len = roots.length; - const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); - const Li = []; - for (let i = 0; i < len; i++) { - const den2 = roots[(len - 1) * i % len]; - const den3 = Fr.sub(x, roots[i]); - toInverse[["LiS0_" + (i + 1)]] = Fr.mul(Fr.mul(den1, den2), den3); - } - return Li; - } - function computeLiS1(toInverse, roots, x, curve) { - const Fr = curve.Fr; - const len = roots.length; - const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); - const Li = []; - for (let i = 0; i < len; i++) { - const den2 = roots[(len - 1) * i % len]; - const den3 = Fr.sub(x, roots[i]); - toInverse[["LiS1_" + (i + 1)]] = Fr.mul(Fr.mul(den1, den2), den3); - } - return Li; - } - function computeLiS2(toInverse, S2, S2p, value, xi, xiw, curve) { - const Fr = curve.Fr; - const Li = []; - const _3h2 = Fr.mul(Fr.e(3), S2[0]); - const xisubxiw = Fr.sub(xi, xiw); - let den1 = Fr.mul(_3h2, xisubxiw); - for (let i = 0; i < 3; i++) { - const den2 = S2[2 * i % 3]; - const den3 = Fr.sub(value, S2[i]); - toInverse[["LiS2_" + (i + 1)]] = Fr.mul(den1, Fr.mul(den2, den3)); - } - const _3h3 = Fr.mul(Fr.e(3), S2p[0]); - const xiwsubxi = Fr.sub(xiw, xi); - den1 = Fr.mul(_3h3, xiwsubxi); - for (let i = 0; i < 3; i++) { - const den2 = S2p[2 * i % 3]; - const den3 = Fr.sub(value, S2p[i]); - toInverse[["LiS2_" + (i + 1 + 3)]] = Fr.mul(den1, Fr.mul(den2, den3)); - } - return Li; - } - } - } - //#endregion - //#region src/fflonk_full_prove.js - var { unstringifyBigInts: unstringifyBigInts$2 } = ffjavascript.utils; - async function fflonkFullProve(_input, wasmFilename, zkeyFilename, logger, wtnsCalcOptions, proverOptions) { - const input = unstringifyBigInts$2(_input); - const wtns = { type: "mem" }; - await wtnsCalculate(input, wasmFilename, wtns, wtnsCalcOptions); - return await fflonkProve(zkeyFilename, wtns, logger, proverOptions); - } - //#endregion - //#region src/fflonk_verify.js - var { unstringifyBigInts: unstringifyBigInts$1 } = ffjavascript.utils; - async function fflonkVerify(_vk_verifier, _publicSignals, _proof, logger) { - if (logger) logger.info("FFLONK VERIFIER STARTED"); - _vk_verifier = unstringifyBigInts$1(_vk_verifier); - _proof = unstringifyBigInts$1(_proof); - const curve = await getCurveFromName(_vk_verifier.curve); - const vk = fromObjectVk(curve, _vk_verifier); - const proof = new Proof(curve, logger); - proof.fromObjectProof(_proof); - const publicSignals = unstringifyBigInts$1(_publicSignals); - if (publicSignals.length !== vk.nPublic) { - logger.error("Number of public signals does not match with vk"); - return false; - } - const Fr = curve.Fr; - if (logger) { - logger.info("----------------------------"); - logger.info(" FFLONK VERIFY SETTINGS"); - logger.info(` Curve: ${curve.name}`); - logger.info(` Circuit power: ${vk.power}`); - logger.info(` Domain size: ${2 ** vk.power}`); - logger.info(` Public vars: ${vk.nPublic}`); - logger.info("----------------------------"); - } - if (logger) logger.info("> Checking commitments belong to G1"); - if (!commitmentsBelongToG1(curve, proof, vk)) { - if (logger) logger.error("Proof commitments are not valid"); - return false; - } - if (logger) logger.info("> Checking evaluations belong to F"); - if (!evaluationsAreValid(curve, proof)) { - if (logger) logger.error("Proof evaluations are not valid."); - return false; - } - if (logger) logger.info("> Checking public inputs belong to F"); - if (!publicInputsAreValid(curve, publicSignals)) { - if (logger) logger.error("Public inputs are not valid."); - return false; - } - if (logger) logger.info("> Computing challenges"); - const { challenges, roots } = computeChallenges(curve, proof, vk, publicSignals, logger); - if (logger) logger.info("> Computing Zero polynomial evaluation Z_H(xi)"); - challenges.zh = Fr.sub(challenges.xiN, Fr.one); - challenges.invzh = Fr.inv(challenges.zh); - if (logger) logger.info("> Computing Lagrange evaluations"); - const lagrangeEvals = await computeLagrangeEvaluations(curve, challenges, vk); - if (logger) logger.info("> Computing polynomial identities PI(X)"); - const pi = calculatePI(curve, publicSignals, lagrangeEvals); - if (logger) logger.info("> Computing r0(y)"); - const r0 = computeR0(proof, challenges, roots, curve, logger); - if (logger) logger.info("> Computing r1(y)"); - const r1 = computeR1(proof, challenges, roots, pi, curve, logger); - if (logger) logger.info("> Computing r2(y)"); - const r2 = computeR2(proof, challenges, roots, lagrangeEvals[1], vk, curve, logger); - if (logger) logger.info("> Computing F"); - const F = computeF(curve, proof, vk, challenges, roots); - if (logger) logger.info("> Computing E"); - const E = computeE(curve, proof, challenges, vk, r0, r1, r2); - if (logger) logger.info("> Computing J"); - const J = computeJ(curve, proof, challenges); - if (logger) logger.info("> Validate all evaluations with a pairing"); - const res = await isValidPairing(curve, proof, challenges, vk, F, E, J); - if (logger) if (res) logger.info("PROOF VERIFIED SUCCESSFULLY"); - else logger.warn("Invalid Proof"); - if (logger) logger.info("FFLONK VERIFIER FINISHED"); - return res; - } - function fromObjectVk(curve, vk) { - const res = vk; - res.k1 = curve.Fr.fromObject(vk.k1); - res.k2 = curve.Fr.fromObject(vk.k2); - res.w = curve.Fr.fromObject(vk.w); - res.w3 = curve.Fr.fromObject(vk.w3); - res.w4 = curve.Fr.fromObject(vk.w4); - res.w8 = curve.Fr.fromObject(vk.w8); - res.wr = curve.Fr.fromObject(vk.wr); - res.X_2 = curve.G2.fromObject(vk.X_2); - res.C0 = curve.G1.fromObject(vk.C0); - return res; - } - function commitmentsBelongToG1(curve, proof, vk) { - const G1 = curve.G1; - return G1.isValid(proof.polynomials.C1) && G1.isValid(proof.polynomials.C2) && G1.isValid(proof.polynomials.W1) && G1.isValid(proof.polynomials.W2) && G1.isValid(vk.C0); - } - function checkValueBelongToField(curve, value) { - return ffjavascript.Scalar.geq(value, 0) && ffjavascript.Scalar.lt(value, curve.r); - } - function checkEvaluationIsValid(curve, evaluation) { - return checkValueBelongToField(curve, ffjavascript.Scalar.fromRprLE(evaluation)); - } - function evaluationsAreValid(curve, proof) { - return checkEvaluationIsValid(curve, proof.evaluations.ql) && checkEvaluationIsValid(curve, proof.evaluations.qr) && checkEvaluationIsValid(curve, proof.evaluations.qm) && checkEvaluationIsValid(curve, proof.evaluations.qo) && checkEvaluationIsValid(curve, proof.evaluations.qc) && checkEvaluationIsValid(curve, proof.evaluations.s1) && checkEvaluationIsValid(curve, proof.evaluations.s2) && checkEvaluationIsValid(curve, proof.evaluations.s3) && checkEvaluationIsValid(curve, proof.evaluations.a) && checkEvaluationIsValid(curve, proof.evaluations.b) && checkEvaluationIsValid(curve, proof.evaluations.c) && checkEvaluationIsValid(curve, proof.evaluations.z) && checkEvaluationIsValid(curve, proof.evaluations.zw) && checkEvaluationIsValid(curve, proof.evaluations.t1w) && checkEvaluationIsValid(curve, proof.evaluations.t2w); - } - function publicInputsAreValid(curve, publicInputs) { - for (let i = 0; i < publicInputs.length; i++) if (!checkValueBelongToField(curve, publicInputs[i])) return false; - return true; - } - function computeChallenges(curve, proof, vk, publicSignals, logger) { - const Fr = curve.Fr; - const challenges = {}; - const roots = {}; - const transcript = new Keccak256Transcript(curve); - transcript.addPolCommitment(vk.C0); - for (let i = 0; i < publicSignals.length; i++) transcript.addScalar(Fr.e(publicSignals[i])); - transcript.addPolCommitment(proof.polynomials.C1); - challenges.beta = transcript.getChallenge(); - transcript.reset(); - transcript.addScalar(challenges.beta); - challenges.gamma = transcript.getChallenge(); - transcript.reset(); - transcript.addScalar(challenges.gamma); - transcript.addPolCommitment(proof.polynomials.C2); - const xiSeed = transcript.getChallenge(); - const xiSeed2 = Fr.square(xiSeed); - let w8 = []; - w8[1] = vk.w8; - w8[2] = Fr.square(vk.w8); - w8[3] = Fr.mul(w8[2], vk.w8); - w8[4] = Fr.mul(w8[3], vk.w8); - w8[5] = Fr.mul(w8[4], vk.w8); - w8[6] = Fr.mul(w8[5], vk.w8); - w8[7] = Fr.mul(w8[6], vk.w8); - let w4 = []; - w4[1] = vk.w4; - w4[2] = Fr.square(vk.w4); - w4[3] = Fr.mul(w4[2], vk.w4); - let w3 = []; - w3[1] = vk.w3; - w3[2] = Fr.square(vk.w3); - roots.S0 = {}; - roots.S0.h0w8 = []; - roots.S0.h0w8[0] = Fr.mul(xiSeed2, xiSeed); - for (let i = 1; i < 8; i++) roots.S0.h0w8[i] = Fr.mul(roots.S0.h0w8[0], w8[i]); - roots.S1 = {}; - roots.S1.h1w4 = []; - roots.S1.h1w4[0] = Fr.square(roots.S0.h0w8[0]); - for (let i = 1; i < 4; i++) roots.S1.h1w4[i] = Fr.mul(roots.S1.h1w4[0], w4[i]); - roots.S2 = {}; - roots.S2.h2w3 = []; - roots.S2.h2w3[0] = Fr.mul(roots.S1.h1w4[0], xiSeed2); - roots.S2.h2w3[1] = Fr.mul(roots.S2.h2w3[0], w3[1]); - roots.S2.h2w3[2] = Fr.mul(roots.S2.h2w3[0], w3[2]); - roots.S2.h3w3 = []; - roots.S2.h3w3[0] = Fr.mul(roots.S2.h2w3[0], vk.wr); - roots.S2.h3w3[1] = Fr.mul(roots.S2.h3w3[0], w3[1]); - roots.S2.h3w3[2] = Fr.mul(roots.S2.h3w3[0], w3[2]); - challenges.xi = Fr.mul(Fr.square(roots.S2.h2w3[0]), roots.S2.h2w3[0]); - challenges.xiw = Fr.mul(challenges.xi, Fr.w[vk.power]); - challenges.xiN = challenges.xi; - vk.domainSize = 1; - for (let i = 0; i < vk.power; i++) { - challenges.xiN = Fr.square(challenges.xiN); - vk.domainSize *= 2; - } - transcript.reset(); - transcript.addScalar(xiSeed); - transcript.addScalar(proof.evaluations.ql); - transcript.addScalar(proof.evaluations.qr); - transcript.addScalar(proof.evaluations.qm); - transcript.addScalar(proof.evaluations.qo); - transcript.addScalar(proof.evaluations.qc); - transcript.addScalar(proof.evaluations.s1); - transcript.addScalar(proof.evaluations.s2); - transcript.addScalar(proof.evaluations.s3); - transcript.addScalar(proof.evaluations.a); - transcript.addScalar(proof.evaluations.b); - transcript.addScalar(proof.evaluations.c); - transcript.addScalar(proof.evaluations.z); - transcript.addScalar(proof.evaluations.zw); - transcript.addScalar(proof.evaluations.t1w); - transcript.addScalar(proof.evaluations.t2w); - challenges.alpha = transcript.getChallenge(); - transcript.reset(); - transcript.addScalar(challenges.alpha); - transcript.addPolCommitment(proof.polynomials.W1); - challenges.y = transcript.getChallenge(); - if (logger) { - logger.info("··· challenges.beta: " + Fr.toString(challenges.beta)); - logger.info("··· challenges.gamma: " + Fr.toString(challenges.gamma)); - logger.info("··· challenges.xi: " + Fr.toString(challenges.xi)); - logger.info("··· challenges.alpha: " + Fr.toString(challenges.alpha)); - logger.info("··· challenges.y: " + Fr.toString(challenges.y)); - } - return { - challenges, - roots - }; - } - async function computeLagrangeEvaluations(curve, challenges, vk) { - const Fr = curve.Fr; - const size = Math.max(1, vk.nPublic); - const numArr = new ffjavascript.BigBuffer(size * Fr.n8); - let denArr = new ffjavascript.BigBuffer(size * Fr.n8); - let w = Fr.one; - for (let i = 0; i < size; i++) { - const i_sFr = i * Fr.n8; - numArr.set(Fr.mul(w, challenges.zh), i_sFr); - denArr.set(Fr.mul(Fr.e(vk.domainSize), Fr.sub(challenges.xi, w)), i_sFr); - w = Fr.mul(w, vk.w); - } - denArr = await Fr.batchInverse(denArr); - let L = []; - for (let i = 0; i < size; i++) { - const i_sFr = i * Fr.n8; - L[i + 1] = Fr.mul(numArr.slice(i_sFr, i_sFr + Fr.n8), denArr.slice(i_sFr, i_sFr + Fr.n8)); - } - return L; - } - function calculatePI(curve, publicSignals, lagrangeEvals) { - const Fr = curve.Fr; - let pi = Fr.zero; - for (let i = 0; i < publicSignals.length; i++) { - const w = Fr.e(publicSignals[i]); - pi = Fr.sub(pi, Fr.mul(w, lagrangeEvals[i + 1])); - } - return pi; - } - function computeR0(proof, challenges, roots, curve, logger) { - const Fr = curve.Fr; - const Li = computeLagrangeLiSi(roots.S0.h0w8, challenges.y, challenges.xi, curve); - if (logger) logger.info("··· Computing r0(y)"); - let res = Fr.zero; - for (let i = 0; i < 8; i++) { - let coefValues = []; - coefValues[1] = roots.S0.h0w8[i]; - for (let j = 2; j < 8; j++) coefValues[j] = Fr.mul(coefValues[j - 1], roots.S0.h0w8[i]); - let c0 = Fr.add(proof.evaluations.ql, Fr.mul(proof.evaluations.qr, coefValues[1])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.qo, coefValues[2])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.qm, coefValues[3])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.qc, coefValues[4])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.s1, coefValues[5])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.s2, coefValues[6])); - c0 = Fr.add(c0, Fr.mul(proof.evaluations.s3, coefValues[7])); - res = Fr.add(res, Fr.mul(c0, Li[i])); - } - return res; - } - function computeR1(proof, challenges, roots, pi, curve, logger) { - const Fr = curve.Fr; - const Li = computeLagrangeLiSi(roots.S1.h1w4, challenges.y, challenges.xi, curve); - if (logger) logger.info("··· Computing T0(xi)"); - let t0 = Fr.mul(proof.evaluations.ql, proof.evaluations.a); - t0 = Fr.add(t0, Fr.mul(proof.evaluations.qr, proof.evaluations.b)); - t0 = Fr.add(t0, Fr.mul(proof.evaluations.qm, Fr.mul(proof.evaluations.a, proof.evaluations.b))); - t0 = Fr.add(t0, Fr.mul(proof.evaluations.qo, proof.evaluations.c)); - t0 = Fr.add(t0, proof.evaluations.qc); - t0 = Fr.add(t0, pi); - t0 = Fr.mul(t0, challenges.invzh); - if (logger) logger.info("··· Computing C1(h_1ω_4^i) values"); - let res = Fr.zero; - for (let i = 0; i < 4; i++) { - let c1 = proof.evaluations.a; - c1 = Fr.add(c1, Fr.mul(roots.S1.h1w4[i], proof.evaluations.b)); - const h1w4Squared = Fr.square(roots.S1.h1w4[i]); - c1 = Fr.add(c1, Fr.mul(h1w4Squared, proof.evaluations.c)); - c1 = Fr.add(c1, Fr.mul(Fr.mul(h1w4Squared, roots.S1.h1w4[i]), t0)); - res = Fr.add(res, Fr.mul(c1, Li[i])); - } - return res; - } - function computeR2(proof, challenges, roots, lagrange1, vk, curve, logger) { - const Fr = curve.Fr; - const LiS2 = computeLagrangeLiS2([roots.S2.h2w3, roots.S2.h3w3], challenges.y, challenges.xi, challenges.xiw, curve); - if (logger) logger.info("··· Computing T1(xi)"); - let t1 = Fr.sub(proof.evaluations.z, Fr.one); - t1 = Fr.mul(t1, lagrange1); - t1 = Fr.mul(t1, challenges.invzh); - if (logger) logger.info("··· Computing T2(xi)"); - const betaxi = Fr.mul(challenges.beta, challenges.xi); - const t211 = Fr.add(proof.evaluations.a, Fr.add(betaxi, challenges.gamma)); - const t212 = Fr.add(proof.evaluations.b, Fr.add(Fr.mul(betaxi, vk.k1), challenges.gamma)); - const t213 = Fr.add(proof.evaluations.c, Fr.add(Fr.mul(betaxi, vk.k2), challenges.gamma)); - const t21 = Fr.mul(t211, Fr.mul(t212, Fr.mul(t213, proof.evaluations.z))); - const t221 = Fr.add(proof.evaluations.a, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s1), challenges.gamma)); - const t222 = Fr.add(proof.evaluations.b, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s2), challenges.gamma)); - const t223 = Fr.add(proof.evaluations.c, Fr.add(Fr.mul(challenges.beta, proof.evaluations.s3), challenges.gamma)); - const t22 = Fr.mul(t221, Fr.mul(t222, Fr.mul(t223, proof.evaluations.zw))); - let t2 = Fr.sub(t21, t22); - t2 = Fr.mul(t2, challenges.invzh); - if (logger) logger.info("··· Computing C2(h_2ω_3^i) values"); - let res = Fr.zero; - for (let i = 0; i < 3; i++) { - let c2 = Fr.add(proof.evaluations.z, Fr.mul(roots.S2.h2w3[i], t1)); - c2 = Fr.add(c2, Fr.mul(Fr.square(roots.S2.h2w3[i]), t2)); - res = Fr.add(res, Fr.mul(c2, LiS2[i])); - } - if (logger) logger.info("··· Computing C2(h_3ω_3^i) values"); - for (let i = 0; i < 3; i++) { - let c2 = Fr.add(proof.evaluations.zw, Fr.mul(roots.S2.h3w3[i], proof.evaluations.t1w)); - c2 = Fr.add(c2, Fr.mul(Fr.square(roots.S2.h3w3[i]), proof.evaluations.t2w)); - res = Fr.add(res, Fr.mul(c2, LiS2[i + 3])); - } - return res; - } - function computeF(curve, proof, vk, challenges, roots) { - const G1 = curve.G1; - const Fr = curve.Fr; - let mulH0 = Fr.sub(challenges.y, roots.S0.h0w8[0]); - for (let i = 1; i < 8; i++) mulH0 = Fr.mul(mulH0, Fr.sub(challenges.y, roots.S0.h0w8[i])); - challenges.temp = mulH0; - let mulH1 = Fr.sub(challenges.y, roots.S1.h1w4[0]); - for (let i = 1; i < 4; i++) mulH1 = Fr.mul(mulH1, Fr.sub(challenges.y, roots.S1.h1w4[i])); - let mulH2 = Fr.sub(challenges.y, roots.S2.h2w3[0]); - for (let i = 1; i < 3; i++) mulH2 = Fr.mul(mulH2, Fr.sub(challenges.y, roots.S2.h2w3[i])); - for (let i = 0; i < 3; i++) mulH2 = Fr.mul(mulH2, Fr.sub(challenges.y, roots.S2.h3w3[i])); - challenges.quotient1 = Fr.mul(challenges.alpha, Fr.div(mulH0, mulH1)); - challenges.quotient2 = Fr.mul(Fr.square(challenges.alpha), Fr.div(mulH0, mulH2)); - let F2 = G1.timesFr(proof.polynomials.C1, challenges.quotient1); - let F3 = G1.timesFr(proof.polynomials.C2, challenges.quotient2); - return G1.add(vk.C0, G1.add(F2, F3)); - } - function computeE(curve, proof, challenges, vk, r0, r1, r2) { - const G1 = curve.G1; - const Fr = curve.Fr; - let E2 = Fr.mul(r1, challenges.quotient1); - let E3 = Fr.mul(r2, challenges.quotient2); - return G1.timesFr(G1.one, Fr.add(r0, Fr.add(E2, E3))); - } - function computeJ(curve, proof, challenges) { - return curve.G1.timesFr(proof.polynomials.W1, challenges.temp); - } - async function isValidPairing(curve, proof, challenges, vk, F, E, J) { - const G1 = curve.G1; - let A1 = G1.timesFr(proof.polynomials.W2, challenges.y); - A1 = G1.add(G1.sub(G1.sub(F, E), J), A1); - const A2 = curve.G2.one; - const B1 = proof.polynomials.W2; - const B2 = vk.X_2; - return await curve.pairingEq(G1.neg(A1), A2, B1, B2); - } - function computeLagrangeLiSi(roots, x, xi, curve) { - const Fr = curve.Fr; - const len = roots.length; - const num = Fr.sub(Fr.exp(x, len), xi); - const den1 = Fr.mul(Fr.e(len), Fr.exp(roots[0], len - 2)); - const Li = []; - for (let i = 0; i < len; i++) { - const den2 = roots[(len - 1) * i % len]; - const den3 = Fr.sub(x, roots[i]); - Li[i] = Fr.div(num, Fr.mul(Fr.mul(den1, den2), den3)); - } - return Li; - } - function computeLagrangeLiS2(roots, value, xi0, xi1, curve) { - const Fr = curve.Fr; - const Li = []; - const len = roots[0].length; - const n = len * roots.length; - const num1 = Fr.exp(value, n); - const num2 = Fr.mul(Fr.add(xi0, xi1), Fr.exp(value, len)); - const num3 = Fr.mul(xi0, xi1); - const num = Fr.add(Fr.sub(num1, num2), num3); - let den1 = Fr.mul(Fr.mul(Fr.e(len), roots[0][0]), Fr.sub(xi0, xi1)); - for (let i = 0; i < len; i++) { - const den2 = roots[0][(len - 1) * i % len]; - const den3 = Fr.sub(value, roots[0][i]); - const den = Fr.mul(den1, Fr.mul(den2, den3)); - Li[i] = Fr.div(num, den); - } - den1 = Fr.mul(Fr.mul(Fr.e(len), roots[1][0]), Fr.sub(xi1, xi0)); - for (let i = 0; i < len; i++) { - const den2 = roots[1][(len - 1) * i % len]; - const den3 = Fr.sub(value, roots[1][i]); - const den = Fr.mul(den1, Fr.mul(den2, den3)); - Li[i + len] = Fr.div(num, den); - } - return Li; - } - //#endregion - //#region src/fflonk_export_calldata.js - var { unstringifyBigInts } = ffjavascript.utils; - function p256(n) { - let nstr = n.toString(16); - while (nstr.length < 64) nstr = "0" + nstr; - nstr = `0x${nstr}`; - return nstr; - } - async function fflonkExportCallData(_pub, _proof) { - const proof = unstringifyBigInts(_proof); - const pub = unstringifyBigInts(_pub); - await getCurveFromName(proof.curve); - let inputs = ""; - for (let i = 0; i < pub.length; i++) { - if (inputs !== "") inputs = inputs + ","; - inputs = inputs + p256(pub[i]); - } - return `[${p256(proof.polynomials.C1[0])}, ${p256(proof.polynomials.C1[1])},${p256(proof.polynomials.C2[0])},${p256(proof.polynomials.C2[1])},${p256(proof.polynomials.W1[0])},${p256(proof.polynomials.W1[1])},${p256(proof.polynomials.W2[0])},${p256(proof.polynomials.W2[1])},${p256(proof.evaluations.ql)},${p256(proof.evaluations.qr)},${p256(proof.evaluations.qm)},${p256(proof.evaluations.qo)},${p256(proof.evaluations.qc)},${p256(proof.evaluations.s1)},${p256(proof.evaluations.s2)},${p256(proof.evaluations.s3)},${p256(proof.evaluations.a)},${p256(proof.evaluations.b)},${p256(proof.evaluations.c)},${p256(proof.evaluations.z)},${p256(proof.evaluations.zw)},${p256(proof.evaluations.t1w)},${p256(proof.evaluations.t2w)},${p256(proof.evaluations.inv)}],[${inputs}]`; - } - //#endregion - //#region src/fflonk.js - var fflonk_exports = /* @__PURE__ */ __exportAll({ - exportSolidityCallData: () => fflonkExportCallData, - exportSolidityVerifier: () => null, - fullProve: () => fflonkFullProve, - prove: () => fflonkProve, - setup: () => fflonkSetup, - verify: () => fflonkVerify - }); - //#endregion - Object.defineProperty(exports, "curves", { - enumerable: true, - get: function() { - return curves_exports; - } - }); - Object.defineProperty(exports, "fflonk", { - enumerable: true, - get: function() { - return fflonk_exports; - } - }); - Object.defineProperty(exports, "groth16", { - enumerable: true, - get: function() { - return groth16_exports; - } - }); - Object.defineProperty(exports, "plonk", { - enumerable: true, - get: function() { - return plonk_exports; - } - }); - Object.defineProperty(exports, "powersOfTau", { - enumerable: true, - get: function() { - return powersoftau_exports; - } - }); - Object.defineProperty(exports, "r1cs", { - enumerable: true, - get: function() { - return r1cs_exports; - } - }); - Object.defineProperty(exports, "wtns", { - enumerable: true, - get: function() { - return wtns_exports; - } - }); - Object.defineProperty(exports, "zKey", { - enumerable: true, - get: function() { - return zkey_exports; - } - }); - return exports; -})({}, _iden3_binfileutils, ffjavascript, r1csfile); +var snarkjs=(function(e,t,n,r){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var i=Object.create,a=Object.defineProperty,o=Object.getOwnPropertyDescriptor,s=Object.getOwnPropertyNames,c=Object.getPrototypeOf,l=Object.prototype.hasOwnProperty,u=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),d=(e,t)=>{let n={};for(var r in e)a(n,r,{get:e[r],enumerable:!0});return t||a(n,Symbol.toStringTag,{value:`Module`}),n},f=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=s(t),c=0,u=i.length,d;ct[e]).bind(null,d),enumerable:!(r=o(t,d))||r.enumerable});return e};t=((e,t,n)=>(n=e==null?{}:i(c(e)),f(t||!e||!e.__esModule?a(n,`default`,{value:e,enumerable:!0}):n,e)))(t,1);var p=d({getCurveFromName:()=>b,getCurveFromQ:()=>y,getCurveFromR:()=>v}),m=n.Scalar.e(`73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001`,16),h=n.Scalar.e(`21888242871839275222246405745257275088548364400416034343698204186575808495617`),g=n.Scalar.e(`1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab`,16),_=n.Scalar.e(`21888242871839275222246405745257275088696311157297823662689037894645226208583`);async function v(e,t){let r,i=t&&t.singleThread;if(n.Scalar.eq(e,h))r=await(0,n.buildBn128)(i);else if(n.Scalar.eq(e,m))r=await(0,n.buildBls12381)(i);else throw Error(`Curve not supported: ${n.Scalar.toString(e)}`);return r}async function y(e,t){let r,i=t&&t.singleThread;if(n.Scalar.eq(e,_))r=await(0,n.buildBn128)(i);else if(n.Scalar.eq(e,g))r=await(0,n.buildBls12381)(i);else throw Error(`Curve not supported: ${n.Scalar.toString(e)}`);return r}async function b(e,t){let r,i=t&&t.singleThread,a=o(e);if([`BN128`,`BN254`,`ALTBN128`].indexOf(a)>=0)r=await(0,n.buildBn128)(i);else if([`BLS12381`].indexOf(a)>=0)r=await(0,n.buildBls12381)(i);else throw Error(`Curve not supported: ${e}`);return r;function o(e){return e.toUpperCase().match(/[A-Za-z0-9]+/g).join(``)}}function x(e){return e instanceof Uint8Array||ArrayBuffer.isView(e)&&e.constructor.name===`Uint8Array`&&`BYTES_PER_ELEMENT`in e&&e.BYTES_PER_ELEMENT===1}function S(e,t=``){if(typeof e!=`number`){let n=t&&`"${t}" `;throw TypeError(`${n}expected number, got ${typeof e}`)}if(!Number.isSafeInteger(e)||e<0){let n=t&&`"${t}" `;throw RangeError(`${n}expected integer >= 0, got ${e}`)}}function C(e,t,n=``){let r=x(e),i=e?.length,a=t!==void 0;if(!r||a&&i!==t){let o=n&&`"${n}" `,s=a?` of length ${t}`:``,c=r?`length=${i}`:`type=${typeof e}`,l=o+`expected Uint8Array`+s+`, got `+c;throw r?RangeError(l):TypeError(l)}return e}function w(e,t=!0){if(e.destroyed)throw Error(`Hash instance has been destroyed`);if(t&&e.finished)throw Error(`Hash#digest() has already been called`)}function T(e,t){C(e,void 0,`digestInto() output`);let n=t.outputLen;if(e.length=`+n)}function E(e){return new Uint32Array(e.buffer,e.byteOffset,Math.floor(e.byteLength/4))}function D(...e){for(let t=0;t>>8&65280|e>>>24&255}var A=O?e=>e:e=>k(e)>>>0;function j(e){for(let t=0;te:j;function N(e,t={}){let n=(t,n)=>e(n).update(t).digest(),r=e(void 0);return n.outputLen=r.outputLen,n.blockLen=r.blockLen,n.canXOF=r.canXOF,n.create=t=>e(t),Object.assign(n,t),Object.freeze(n)}var P=Uint8Array.from([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3,11,8,12,0,5,2,15,13,10,14,3,6,7,1,9,4,7,9,3,1,13,12,11,14,2,6,5,10,4,0,15,8,9,0,5,7,2,4,10,15,14,1,11,12,6,8,3,13,2,12,6,10,0,11,8,3,4,13,7,5,15,14,1,9,12,5,1,15,14,13,4,10,0,7,6,3,9,2,8,11,13,11,7,14,12,1,3,9,5,0,15,4,8,6,2,10,6,15,14,9,11,3,0,8,12,2,13,7,1,4,10,5,10,2,8,4,7,6,1,5,15,11,9,14,3,12,13,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3,11,8,12,0,5,2,15,13,10,14,3,6,7,1,9,4,7,9,3,1,13,12,11,14,2,6,5,10,4,0,15,8,9,0,5,7,2,4,10,15,14,1,11,12,6,8,3,13,2,12,6,10,0,11,8,3,4,13,7,5,15,14,1,9]),F=BigInt(2**32-1),I=BigInt(32);function L(e,t=!1){return t?{h:Number(e&F),l:Number(e>>I&F)}:{h:Number(e>>I&F)|0,l:Number(e&F)|0}}function R(e,t=!1){let n=e.length,r=new Uint32Array(n),i=new Uint32Array(n);for(let a=0;ae>>>n|t<<32-n,ee=(e,t,n)=>e<<32-n|t>>>n,te=(e,t,n)=>e<<64-n|t>>>n-32,ne=(e,t,n)=>e>>>n-32|t<<64-n,re=(e,t)=>t,ie=(e,t)=>e,ae=(e,t,n)=>e<>>32-n,oe=(e,t,n)=>t<>>32-n,se=(e,t,n)=>t<>>64-n,ce=(e,t,n)=>e<>>64-n;function le(e,t,n,r){let i=(t>>>0)+(r>>>0);return{h:e+n+(i/2**32|0)|0,l:i|0}}var ue=(e,t,n)=>(e>>>0)+(t>>>0)+(n>>>0),de=(e,t,n,r)=>t+n+r+(e/2**32|0)|0,B=Uint32Array.from([4089235720,1779033703,2227873595,3144134277,4271175723,1013904242,1595750129,2773480762,2917565137,1359893119,725511199,2600822924,4215389547,528734635,327033209,1541459225]),V=new Uint32Array(32);function fe(e,t,n,r,i,a){let o=i[a],s=i[a+1],c=V[2*e],l=V[2*e+1],u=V[2*t],d=V[2*t+1],f=V[2*n],p=V[2*n+1],m=V[2*r],h=V[2*r+1],g=ue(c,u,o);l=de(g,l,d,s),c=g|0,{Dh:h,Dl:m}={Dh:h^l,Dl:m^c},{Dh:h,Dl:m}={Dh:re(h,m),Dl:ie(h,m)},{h:p,l:f}=le(p,f,h,m),{Bh:d,Bl:u}={Bh:d^p,Bl:u^f},{Bh:d,Bl:u}={Bh:z(d,u,24),Bl:ee(d,u,24)},V[2*e]=c,V[2*e+1]=l,V[2*t]=u,V[2*t+1]=d,V[2*n]=f,V[2*n+1]=p,V[2*r]=m,V[2*r+1]=h}function pe(e,t,n,r,i,a){let o=i[a],s=i[a+1],c=V[2*e],l=V[2*e+1],u=V[2*t],d=V[2*t+1],f=V[2*n],p=V[2*n+1],m=V[2*r],h=V[2*r+1],g=ue(c,u,o);l=de(g,l,d,s),c=g|0,{Dh:h,Dl:m}={Dh:h^l,Dl:m^c},{Dh:h,Dl:m}={Dh:z(h,m,16),Dl:ee(h,m,16)},{h:p,l:f}=le(p,f,h,m),{Bh:d,Bl:u}={Bh:d^p,Bl:u^f},{Bh:d,Bl:u}={Bh:te(d,u,63),Bl:ne(d,u,63)},V[2*e]=c,V[2*e+1]=l,V[2*t]=u,V[2*t+1]=d,V[2*n]=f,V[2*n+1]=p,V[2*r]=m,V[2*r+1]=h}function me(e,t={},n,r,i){if(S(n),e<=0||e>n)throw Error(`outputLen bigger than keyLen`);let{key:a,salt:o,personalization:s}=t;if(a!==void 0&&(a.length<1||a.length>n))throw Error(`"key" expected to be undefined or of length=1..`+n);o!==void 0&&C(o,r,`salt`),s!==void 0&&C(s,i,`personalization`)}var he=class{buffer;buffer32;finished=!1;destroyed=!1;length=0;pos=0;blockLen;outputLen;canXOF=!1;constructor(e,t){S(e),S(t),this.blockLen=e,this.outputLen=t,this.buffer=new Uint8Array(e),this.buffer32=E(this.buffer)}update(e){w(this),C(e);let{blockLen:t,buffer:n,buffer32:r}=this,i=e.length,a=e.byteOffset,o=e.buffer;for(let s=0;s>>8*t}digest(){let{buffer:e,outputLen:t}=this;this.digestInto(e);let n=e.slice(0,t);return this.destroy(),n}_cloneInto(e){let{buffer:t,length:n,finished:r,destroyed:i,outputLen:a,pos:o}=this;return e||=new this.constructor({dkLen:a}),e.set(...this.get()),e.buffer.set(t),e.destroyed=i,e.finished=r,e.length=n,e.pos=o,e.outputLen=a,e}clone(){return this._cloneInto()}},ge=class extends he{v0l=B[0]|0;v0h=B[1]|0;v1l=B[2]|0;v1h=B[3]|0;v2l=B[4]|0;v2h=B[5]|0;v3l=B[6]|0;v3h=B[7]|0;v4l=B[8]|0;v4h=B[9]|0;v5l=B[10]|0;v5h=B[11]|0;v6l=B[12]|0;v6h=B[13]|0;v7l=B[14]|0;v7h=B[15]|0;constructor(e={}){let t=e.dkLen===void 0?64:e.dkLen;super(128,t),me(t,e,64,16,16);let{key:n,personalization:r,salt:i}=e,a=0;if(n!==void 0&&(C(n,void 0,`key`),a=n.length),this.v0l^=this.outputLen|a<<8|16842752,i!==void 0){C(i,void 0,`salt`);let e=E(i);this.v4l^=A(e[0]),this.v4h^=A(e[1]),this.v5l^=A(e[2]),this.v5h^=A(e[3])}if(r!==void 0){C(r,void 0,`personalization`);let e=E(r);this.v6l^=A(e[0]),this.v6h^=A(e[1]),this.v7l^=A(e[2]),this.v7h^=A(e[3])}if(n!==void 0){let e=new Uint8Array(this.blockLen);e.set(n),this.update(e)}}get(){let{v0l:e,v0h:t,v1l:n,v1h:r,v2l:i,v2h:a,v3l:o,v3h:s,v4l:c,v4h:l,v5l:u,v5h:d,v6l:f,v6h:p,v7l:m,v7h:h}=this;return[e,t,n,r,i,a,o,s,c,l,u,d,f,p,m,h]}set(e,t,n,r,i,a,o,s,c,l,u,d,f,p,m,h){this.v0l=e|0,this.v0h=t|0,this.v1l=n|0,this.v1h=r|0,this.v2l=i|0,this.v2h=a|0,this.v3l=o|0,this.v3h=s|0,this.v4l=c|0,this.v4h=l|0,this.v5l=u|0,this.v5h=d|0,this.v6l=f|0,this.v6h=p|0,this.v7l=m|0,this.v7h=h|0}compress(e,t,n){this.get().forEach((e,t)=>V[t]=e),V.set(B,16);let{h:r,l:i}=L(BigInt(this.length));V[24]=B[8]^i,V[25]=B[9]^r,n&&(V[28]=~V[28],V[29]=~V[29]);let a=0,o=P;for(let n=0;n<12;n++)fe(0,4,8,12,e,t+2*o[a++]),pe(0,4,8,12,e,t+2*o[a++]),fe(1,5,9,13,e,t+2*o[a++]),pe(1,5,9,13,e,t+2*o[a++]),fe(2,6,10,14,e,t+2*o[a++]),pe(2,6,10,14,e,t+2*o[a++]),fe(3,7,11,15,e,t+2*o[a++]),pe(3,7,11,15,e,t+2*o[a++]),fe(0,5,10,15,e,t+2*o[a++]),pe(0,5,10,15,e,t+2*o[a++]),fe(1,6,11,12,e,t+2*o[a++]),pe(1,6,11,12,e,t+2*o[a++]),fe(2,7,8,13,e,t+2*o[a++]),pe(2,7,8,13,e,t+2*o[a++]),fe(3,4,9,14,e,t+2*o[a++]),pe(3,4,9,14,e,t+2*o[a++]);this.v0l^=V[0]^V[16],this.v0h^=V[1]^V[17],this.v1l^=V[2]^V[18],this.v1h^=V[3]^V[19],this.v2l^=V[4]^V[20],this.v2h^=V[5]^V[21],this.v3l^=V[6]^V[22],this.v3h^=V[7]^V[23],this.v4l^=V[8]^V[24],this.v4h^=V[9]^V[25],this.v5l^=V[10]^V[26],this.v5h^=V[11]^V[27],this.v6l^=V[12]^V[28],this.v6h^=V[13]^V[29],this.v7l^=V[14]^V[30],this.v7h^=V[15]^V[31],D(V)}destroy(){this.destroyed=!0,D(this.buffer32),this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)}},H=N(e=>new ge(e));u(((e,t)=>{t.exports={}}))();var _e=[];for(let e=0;e<256;e++)_e[e]=ve(e,8);function ve(e,t){let n=0,r=e;for(let e=0;e>=1;return n}function ye(e){return(e&4294901760?(e&=4294901760,16):0)|(e&4278255360?(e&=4278255360,8):0)|(e&4042322160?(e&=4042322160,4):0)|(e&3435973836?(e&=3435973836,2):0)|(e&2863311530)!=0}function U(e,t){let n=new DataView(e.buffer,e.byteOffset,e.byteLength),r=``;for(let e=0;e<4;e++){e>0&&(r+=` +`),r+=` `;for(let t=0;t<4;t++)t>0&&(r+=` `),r+=n.getUint32(e*16+t*4).toString(16).padStart(8,`0`)}return t&&(r=t+` +`+r),r}function be(e,t){if(e.byteLength!=t.byteLength)return!1;for(var n=new Int8Array(e),r=new Int8Array(t),i=0;i!=e.byteLength;i++)if(n[i]!=r[i])return!1;return!0}function xe(e){return e.clone()}function Se(e){let t=e.subarray(0,128),n=E(e.subarray(128)),r=H.create({dkLen:64});r.buffer.set(t),r.v0l=n[0]|0,r.v0h=n[1]|0,r.v1l=n[2]|0,r.v1h=n[3]|0,r.v2l=n[4]|0,r.v2h=n[5]|0,r.v3l=n[6]|0,r.v3h=n[7]|0,r.v4l=n[8]|0,r.v4h=n[9]|0,r.v5l=n[10]|0,r.v5h=n[11]|0,r.v6l=n[12]|0,r.v6h=n[13]|0,r.v7l=n[14]|0,r.v7h=n[15]|0;let i=2**32,a=n[16]+n[17]*i,o=n[18]+n[19]*i;return r.length=a+o,r.pos=o,r}function Ce(e){let t=new Uint8Array(216),n=E(t.subarray(128));return t.set(e.buffer),n[0]=e.v0l,n[1]=e.v0h,n[2]=e.v1l,n[3]=e.v1h,n[4]=e.v2l,n[5]=e.v2h,n[6]=e.v3l,n[7]=e.v3h,n[8]=e.v4l,n[9]=e.v4h,n[10]=e.v5l,n[11]=e.v5h,n[12]=e.v6l,n[13]=e.v6h,n[14]=e.v7l,n[15]=e.v7h,n[18]=e.pos,n[16]=e.length-e.pos,t}async function we(e,t,n,r,i){return e.G1.isZero(t)||e.G1.isZero(n)||e.G2.isZero(r)||e.G2.isZero(i)?!1:await e.pairingEq(t,i,e.G1.neg(n),r)}function Te(){return window.prompt(`Enter a random text. (Entropy): `,``)}function Ee(e){let t=new Uint8Array(e);return globalThis.crypto.getRandomValues(t),t}async function De(e){{let t=await globalThis.crypto.subtle.digest(`SHA-256`,e.buffer);return new Uint8Array(t)}}function Oe(e,t){return new DataView(e.buffer).getUint32(t,!1)}async function ke(e){for(;!e;)e=await Te();let t=H.create(64);t.update(Ee(64));let r=new TextEncoder;t.update(r.encode(e));let i=t.digest(),a=[];for(let e=0;e<8;e++)a[e]=Oe(i,e*4);return new n.ChaCha(a)}async function Ae(e,t){let r,i;t<32?(r=1<>>0,i=1):(r=4294967296,i=1<>>0);let a=e;for(let e=0;e{n[r]=Ne(e,t[r])}),n}else if(typeof t==`bigint`||t.eq!==void 0)return t.toString(10);else return t}async function Pe(e,r){await t.startWriteSection(e,1),await e.writeULE32(1),await t.endWriteSection(e);let i=await y(r.q);await t.startWriteSection(e,2);let a=i.q,o=(Math.floor((n.Scalar.bitLength(a)-1)/64)+1)*8,s=i.r,c=(Math.floor((n.Scalar.bitLength(s)-1)/64)+1)*8;await e.writeULE32(o),await t.writeBigInt(e,a,o),await e.writeULE32(c),await t.writeBigInt(e,s,c),await e.writeULE32(r.nVars),await e.writeULE32(r.nPublic),await e.writeULE32(r.domainSize),await Fe(e,i,r.vk_alpha_1),await Fe(e,i,r.vk_beta_1),await Ie(e,i,r.vk_beta_2),await Ie(e,i,r.vk_gamma_2),await Fe(e,i,r.vk_delta_1),await Ie(e,i,r.vk_delta_2),await t.endWriteSection(e)}async function Fe(e,t,n){let r=new Uint8Array(t.G1.F.n8*2);t.G1.toRprLEM(r,0,n),await e.write(r)}async function Ie(e,t,n){let r=new Uint8Array(t.G2.F.n8*2);t.G2.toRprLEM(r,0,n),await e.write(r)}async function W(e,t,n){let r=await e.read(t.G1.F.n8*2),i=t.G1.fromRprLEM(r,0);return n?t.G1.toObject(i):i}async function Le(e,t,n){let r=await e.read(t.G2.F.n8*2),i=t.G2.fromRprLEM(r,0);return n?t.G2.toObject(i):i}async function Re(e,n,r,i){await t.startReadUniqueSection(e,n,1);let a=await e.readULE32();if(await t.endReadSection(e),a===1)return await ze(e,n,r,i);if(a===2)return await Be(e,n,r,i);if(a===10)return await Ve(e,n,r,i);throw Error(`Protocol not supported: `)}async function ze(e,n,r,i){let a={};a.protocol=`groth16`,await t.startReadUniqueSection(e,n,2);let o=await e.readULE32();a.n8q=o,a.q=await t.readBigInt(e,o);let s=await e.readULE32();return a.n8r=s,a.r=await t.readBigInt(e,s),a.curve=await y(a.q,i),a.nVars=await e.readULE32(),a.nPublic=await e.readULE32(),a.domainSize=await e.readULE32(),a.power=ye(a.domainSize),a.vk_alpha_1=await W(e,a.curve,r),a.vk_beta_1=await W(e,a.curve,r),a.vk_beta_2=await Le(e,a.curve,r),a.vk_gamma_2=await Le(e,a.curve,r),a.vk_delta_1=await W(e,a.curve,r),a.vk_delta_2=await Le(e,a.curve,r),await t.endReadSection(e),a}async function Be(e,n,r,i){let a={};a.protocol=`plonk`,await t.startReadUniqueSection(e,n,2);let o=await e.readULE32();a.n8q=o,a.q=await t.readBigInt(e,o);let s=await e.readULE32();return a.n8r=s,a.r=await t.readBigInt(e,s),a.curve=await y(a.q,i),a.nVars=await e.readULE32(),a.nPublic=await e.readULE32(),a.domainSize=await e.readULE32(),a.power=ye(a.domainSize),a.nAdditions=await e.readULE32(),a.nConstraints=await e.readULE32(),a.k1=await e.read(s),a.k2=await e.read(s),a.Qm=await W(e,a.curve,r),a.Ql=await W(e,a.curve,r),a.Qr=await W(e,a.curve,r),a.Qo=await W(e,a.curve,r),a.Qc=await W(e,a.curve,r),a.S1=await W(e,a.curve,r),a.S2=await W(e,a.curve,r),a.S3=await W(e,a.curve,r),a.X_2=await Le(e,a.curve,r),await t.endReadSection(e),a}async function Ve(e,n,r,i){let a={};a.protocol=`fflonk`,a.protocolId=10,await t.startReadUniqueSection(e,n,2);let o=await e.readULE32();a.n8q=o,a.q=await t.readBigInt(e,o),a.curve=await y(a.q,i);let s=await e.readULE32();return a.n8r=s,a.r=await t.readBigInt(e,s),a.nVars=await e.readULE32(),a.nPublic=await e.readULE32(),a.domainSize=await e.readULE32(),a.power=ye(a.domainSize),a.nAdditions=await e.readULE32(),a.nConstraints=await e.readULE32(),a.k1=await e.read(s),a.k2=await e.read(s),a.w3=await e.read(s),a.w4=await e.read(s),a.w8=await e.read(s),a.wr=await e.read(s),a.X_2=await Le(e,a.curve,r),a.C0=await W(e,a.curve,r),await t.endReadSection(e),a}async function He(e,r){let{fd:i,sections:a}=await t.readBinFile(e,`zkey`,1),o=await Re(i,a,r),s=new n.F1Field(o.r),c=n.Scalar.mod(n.Scalar.shl(1,o.n8r*8),o.r),l=s.inv(c),u=s.mul(l,l),d=await y(o.q);await t.startReadUniqueSection(i,a,3),o.IC=[];for(let e=0;e<=o.nPublic;e++){let e=await W(i,d,r);o.IC.push(e)}await t.endReadSection(i),await t.startReadUniqueSection(i,a,4);let f=await i.readULE32();o.ccoefs=[];for(let e=0;e0){let t=new Uint8Array(r);await e.writeULE32(t.byteLength),await e.write(t)}else await e.writeULE32(0)}async function Ke(e,n,r){await t.startWriteSection(e,10),await e.write(r.csHash),await e.writeULE32(r.contributions.length);for(let t=0;t2**16;)o*=2,l=Math.floor(t.domainSize/o);console.log(`@@@ new elementsPerChunk`,l);let u=[],d=[];for(let e=0;e1){let t=[];for(let n=0;ne?n=r-1:i1){let t=[];for(let n=0;n<1;n++){let r=[];r.push({cmd:`ALLOC`,var:0,len:f[n][0].byteLength}),r.push({cmd:`ALLOC`,var:1,len:f[n][0].byteLength});for(let t=0;t<3;t++){r.push({cmd:`SET`,var:0,buff:f[n][t]});for(let i=1;ie?n=r-1:i`u`||!process.memoryUsage)return;let t=process.memoryUsage();e.debug(` `,`\x1B[0m Heap:\x1B[32m`,`${Math.round(t.heapUsed/1024/1024*100)/100} MB`.padEnd(12),`\x1B[0m / \x1B[32m`,`${Math.round(t.heapTotal/1024/1024*100)/100} MB`.padEnd(12),`\x1B[0m RSS:\x1B[32m`,`${Math.round(t.rss/1024/1024*100)/100} MB`.padEnd(12),`\x1B[0m External:\x1B[32m`,`${Math.round(t.external/1024/1024*100)/100} MB`.padEnd(12),`\x1B[0m ArrBuffers:\x1B[32m`,`${Math.round(t.arrayBuffers/1024/1024*100)/100} MB`.padEnd(12),`\x1B[0m`)}function st(e,t=5e3){return setInterval(()=>{ot(e)},t)}function ct(e){let t=e.initialSize||1<<20,n=new mt;return n.o=e,n.o.data=new Uint8Array(t),n.allocSize=t,n.totalSize=0,n.readOnly=!1,n.pos=0,n}function lt(e){let t=new mt;return t.o=e,t.allocSize=e.data.byteLength,t.totalSize=e.data.byteLength,t.readOnly=!0,t.pos=0,t}var ut=new Uint8Array(4),dt=new DataView(ut.buffer),ft=new Uint8Array(8),pt=new DataView(ft.buffer),mt=class{constructor(){this.pageSize=16384}_resizeIfNeeded(e){if(e>this.allocSize){let t=Math.max(this.allocSize+(1<<20),Math.floor(this.allocSize*1.1),e),n=new Uint8Array(t);n.set(this.o.data),this.o.data=n,this.allocSize=t}}async write(e,t){if(t===void 0&&(t=this.pos),this.readOnly)throw Error(`Writing a read only file`);this._resizeIfNeeded(t+e.byteLength),this.o.data.set(e.slice(),t),t+e.byteLength>this.totalSize&&(this.totalSize=t+e.byteLength),this.pos=t+e.byteLength}async readToBuffer(e,t,n,r){if(r===void 0&&(r=this.pos),this.readOnly&&r+n>this.totalSize)throw Error(`Reading out of bounds`);this._resizeIfNeeded(r+n);let i=new Uint8Array(this.o.data.buffer,this.o.data.byteOffset+r,n);e.set(i,t),this.pos=r+n}async read(e,t){let n=this,r=new Uint8Array(e);return await n.readToBuffer(r,0,e,t),r}close(){this.o.data.byteLength!=this.totalSize&&(this.o.data=this.o.data.slice(0,this.totalSize))}async discard(){}async writeULE32(e,t){let n=this;dt.setUint32(0,e,!0),await n.write(ut,t)}async writeUBE32(e,t){let n=this;dt.setUint32(0,e,!1),await n.write(ut,t)}async writeULE64(e,t){let n=this;pt.setUint32(0,e&4294967295,!0),pt.setUint32(4,Math.floor(e/4294967296),!0),await n.write(ft,t)}async readULE32(e){let t=await this.read(4,e);return new Uint32Array(t.buffer)[0]}async readUBE32(e){let t=await this.read(4,e);return new DataView(t.buffer).getUint32(0,!1)}async readULE64(e){let t=await this.read(8,e),n=new Uint32Array(t.buffer);return n[1]*4294967296+n[0]}async readString(e){let t=this,n=e===void 0?t.pos:e;if(n>this.totalSize){if(this.readOnly)throw Error(`Reading out of bounds`);this._resizeIfNeeded(e)}let r=new Uint8Array(t.o.data.buffer,n,this.totalSize-n),i=r.findIndex(e=>e===0),a=i!==-1,o=``;return a?(o=new TextDecoder().decode(r.slice(0,i)),t.pos=n+i+1):t.pos=n,o}},G=1<<22;function ht(e){let t=e.initialSize||0,n=new xt;n.o=e;let r=t?Math.floor((t-1)/G)+1:0;n.o.data=[];for(let e=0;e0;){let t=i+a>G?G-i:a,o=e.slice(e.byteLength-a,e.byteLength-a+t);new Uint8Array(n.o.data[r].buffer,i,t).set(o),a-=t,r++,i=0}this.pos=t+e.byteLength}async readToBuffer(e,t,n,r){let i=this;if(r===void 0&&(r=i.pos),this.readOnly&&r+n>this.totalSize)throw Error(`Reading out of bounds`);this._resizeIfNeeded(r+n);let a=Math.floor(r/G),o=r%G,s=n;for(;s>0;){let r=o+s>G?G-o:s,c=new Uint8Array(i.o.data[a].buffer,o,r);e.set(c,t+n-s),s-=r,a++,o=0}this.pos=r+n}async read(e,t){let n=this,r=new Uint8Array(e);return await n.readToBuffer(r,0,e,t),r}close(){}async discard(){}async writeULE32(e,t){let n=this;vt.setUint32(0,e,!0),await n.write(_t,t)}async writeUBE32(e,t){let n=this;vt.setUint32(0,e,!1),await n.write(_t,t)}async writeULE64(e,t){let n=this;bt.setUint32(0,e&4294967295,!0),bt.setUint32(4,Math.floor(e/4294967296),!0),await n.write(yt,t)}async readULE32(e){let t=await this.read(4,e);return new Uint32Array(t.buffer)[0]}async readUBE32(e){let t=await this.read(4,e);return new DataView(t.buffer).getUint32(0,!1)}async readULE64(e){let t=await this.read(8,e),n=new Uint32Array(t.buffer);return n[1]*4294967296+n[0]}async readString(e){let t=this,n=e===void 0?t.pos:e;if(n>this.totalSize){if(this.readOnly)throw Error(`Reading out of bounds`);this._resizeIfNeeded(e)}let r=!1,i=``;for(;!r;){let e=Math.floor(n/G),a=n%G;if(t.o.data[e]===void 0)throw Error(`ERROR`);let o=Math.min(2048,t.o.data[e].length-a),s=new Uint8Array(t.o.data[e].buffer,a,o),c=s.findIndex(e=>e===0);r=c!==-1,r?(i+=new TextDecoder().decode(s.slice(0,c)),t.pos=e*G+a+c+1):(i+=new TextDecoder().decode(s),t.pos=e*G+a+s.length),n=t.pos}return i}},St=65536;function Ct(){throw Error(`File I/O is not supported in the browser`)}function wt(e,t){return e instanceof Uint8Array?{type:`mem`,data:e}:typeof e==`string`?{type:`mem`,initialSize:t||St}:e}async function Tt(e){let t=await fetch(e).then(e=>e.arrayBuffer());return{type:`mem`,data:new Uint8Array(t)}}function Et(e,t,n){if(e.type===`file`&&Ct(),e.type===`mem`)return t(e);if(e.type===`bigMem`)return n(e);throw Error(`Invalid FastFile type: `+e.type)}function Dt(e,t){return Et(wt(e,t),ct,ht)}async function Ot(e){return e=typeof e==`string`?await Tt(e):wt(e),Et(e,lt,gt)}function kt(e){let t=[];return n(t,e),t;function n(e,t){if(Array.isArray(t))for(let r=0;r0;)n.unshift(0),e--}return n}async function Nt(e,t){let r,i,a;t||={};let o=1,s=0,c=0,l=!1;if(e instanceof WebAssembly.Instance)r=e,l=!0;else{let l=32767;if(t.memorySize&&(l=parseInt(t.memorySize),l<0))throw Error(`Invalid memory size`);let u=!1;for(;!u;)try{a=new WebAssembly.Memory({initial:l}),u=!0}catch(e){if(l<=1)throw e;console.warn(`Could not allocate `+l*1024*64+` bytes. This may cause severe instability. Trying with `+l*1024*64/2+` bytes`),l=Math.floor(l/2)}let p=await WebAssembly.compile(e),m=``,h=``;r=await WebAssembly.instantiate(p,{env:{memory:a},runtime:{printDebug:function(e){console.log(`printDebug:`,e)},exceptionHandler:function(e){let t;throw t=e===1?`Signal not found. `:e===2?`Too many signals set. `:e===3?`Signal already set. `:e===4?`Assert Failed. `:e===5?`Not enough memory. `:e===6?`Input signal array access exceeds the size. `:`Unknown error. `,console.error(`ERROR: `,e,m),Error(t+m)},printErrorMessage:function(){m+=d()+` +`},writeBufferMessage:function(){let e=d();e===` +`?(console.log(h),h=``):(h!==``&&(h+=` `),h+=e)},showSharedRWMemory:function(){let e=r.exports.getFieldNumLen32(),t=new Uint32Array(e);for(let n=0;n=2&&(s>=1||c>=7)){h!==``&&(h+=` `);let e=n.Scalar.fromArray(t,4294967296).toString();h+=e}else console.log(n.Scalar.fromArray(t,4294967296))},error:function(e,n,r,a,o,s){let c;throw c=e===7?f(n)+` `+i.getFr(a).toString()+` != `+i.getFr(o).toString()+` `+f(s):e===9?f(n)+` `+i.getFr(a).toString()+` `+f(o):e===5&&t.sym?f(n)+` `+t.sym.labelIdx2Name[o]:f(n)+` `+r+` `+a+` `+o+` `+s,console.log(`ERROR: `,e,c),Error(c)},log:function(e){console.log(i.getFr(e).toString())},logGetSignal:function(e,n){t.logGetSignal&&t.logGetSignal(e,i.getFr(n))},logSetSignal:function(e,n){t.logSetSignal&&t.logSetSignal(e,i.getFr(n))},logStartComponent:function(e){t.logStartComponent&&t.logStartComponent(e)},logFinishComponent:function(e){t.logFinishComponent&&t.logFinishComponent(e)}}})}typeof r.exports.getVersion==`function`&&(o=r.exports.getVersion()),typeof r.exports.getMinorVersion==`function`&&(s=r.exports.getMinorVersion()),typeof r.exports.getPatchVersion==`function`&&(c=r.exports.getPatchVersion());let u=t&&(t.sanityCheck||t.logGetSignal||t.logSetSignal||t.logStartComponent||t.logFinishComponent);if(o===2)i=new Ft(r,u);else if(o===1){if(l)throw Error(`Loading code from WebAssembly instance is not supported for circom version 1`);i=new Pt(a,r,u)}else throw Error(`Unsupported circom version: ${o}`);return i;function d(){let e=``,t=r.exports.getMessageChar();for(;t!==0;)e+=String.fromCharCode(t),t=r.exports.getMessageChar();return e}function f(e){let t=new Uint8Array(a.buffer),n=[];for(let r=0;t[e+r]>0;r++)n.push(t[e+r]);return String.fromCharCode.apply(null,n)}}var Pt=class{constructor(e,t,r){this.memory=e,this.i32=new Uint32Array(e.buffer),this.instance=t,this.n32=(this.instance.exports.getFrLen()>>2)-2;let i=this.instance.exports.getPRawPrime(),a=Array(this.n32);for(let e=0;e>2)+e];this.prime=n.Scalar.fromArray(a,4294967296),this.Fr=new n.F1Field(this.prime),this.mask32=n.Scalar.fromString(`FFFFFFFF`,16),this.NVars=this.instance.exports.getNVars(),this.n64=Math.floor((this.Fr.bitLength-1)/64)+1,this.R=this.Fr.e(n.Scalar.shiftLeft(1,this.n64*64)),this.RInv=this.Fr.inv(this.R),this.sanityCheck=r}circom_version(){return 1}async _doCalculateWitness(e,t){this.instance.exports.init(this.sanityCheck||t?1:0);let n=this.allocInt(),r=this.allocFr();Object.keys(e).forEach(t=>{let i=jt(t),a=parseInt(i.slice(0,8),16),o=parseInt(i.slice(8,16),16);try{this.instance.exports.getSignalOffset32(n,0,a,o)}catch{throw Error(`Signal ${t} is not an input of the circuit.`)}let s=this.getInt(n),c=kt(e[t]);for(let e=0;e>2]}setInt(e,t){this.i32[e>>2]=t}getFr(e){let t=this,r=e>>2;if(t.i32[r+1]&2147483648){let e=Array(t.n32);for(let n=0;n>2]=a,r.i32[(e>>2)+1]=0;return}r.i32[e>>2]=0,r.i32[(e>>2)+1]=2147483648;let o=n.Scalar.toArray(t,4294967296);for(let t=0;t=0?r.i32[(e>>2)+2+t]=o[n]:r.i32[(e>>2)+2+t]=0}}},Ft=class{constructor(e,t){this.instance=e,this.version=this.instance.exports.getVersion(),this.n32=this.instance.exports.getFieldNumLen32(),this.instance.exports.getRawPrime();let r=new Uint32Array(this.n32);for(let e=0;e{let n=jt(t),i=parseInt(n.slice(0,8),16),a=parseInt(n.slice(8,16),16),o=kt(e[t]);if(typeof this.instance.exports.getInputSignalSize==`function`){let e=this.instance.exports.getInputSignalSize(i,a);if(e<0)throw Error(`Signal ${t} not found\n`);if(o.lengthe)throw Error(`Too many values for input signal ${t}\n`)}for(let e=0;eqt,fullProve:()=>zt,prove:()=>tt,verify:()=>Vt});function Yt(e,t){let r=new DataView(t.buffer,t.byteOffset,t.byteLength),i=[];for(let e=0;e<8;e++)i[e]=r.getUint32(e*4);let a=new n.ChaCha(i);return e.G2.fromRng(a)}function Xt(e,t,n,r,i){let a=H.create({dkLen:64}),o=new Uint8Array([t]);a.update(o),a.update(n);let s=e.G1.toUncompressed(r);a.update(s);let c=e.G1.toUncompressed(i);return a.update(c),Yt(e,a.digest())}function Zt(e,t,n,r,i){return e.g1_s=t.G1.toAffine(t.G1.fromRng(i)),e.g1_sx=t.G1.toAffine(t.G1.timesFr(e.g1_s,e.prvKey)),e.g2_sp=t.G2.toAffine(Xt(t,n,r,e.g1_s,e.g1_sx)),e.g2_spx=t.G2.toAffine(t.G2.timesFr(e.g2_sp,e.prvKey)),e}function Qt(e,t,n){let r={tau:{},alpha:{},beta:{}};return r.tau.prvKey=e.Fr.fromRng(n),r.alpha.prvKey=e.Fr.fromRng(n),r.beta.prvKey=e.Fr.fromRng(n),Zt(r.tau,e,0,t,n),Zt(r.alpha,e,1,t,n),Zt(r.beta,e,2,t,n),r}async function $t(e,t,r,i){i||=r,await e.writeULE32(1);let a=e.pos;await e.writeULE64(0),await e.writeULE32(t.F1.n64*8);let o=new Uint8Array(t.F1.n8);n.Scalar.toRprLE(o,0,t.q,t.F1.n8),await e.write(o),await e.writeULE32(r),await e.writeULE32(i);let s=e.pos-a-8,c=e.pos;await e.writeULE64(s,a),e.pos=c}async function K(e,t){if(!t[1])throw Error(e.fileName+`: File has no header`);if(t[1].length>1)throw Error(e.fileName+`: File has more than one header`);e.pos=t[1][0].p;let r=await e.readULE32(),i=await e.read(r),a=await y(n.Scalar.fromRprLE(i));if(a.F1.n64*8!=r)throw Error(e.fileName+`: Invalid size`);let o=await e.readULE32(),s=await e.readULE32();if(e.pos-t[1][0].p!=t[1][0].size)throw Error(`Invalid PTau header size`);return{curve:a,power:o,ceremonyPower:s}}async function en(e,t,n){return tn(await e.read(t.F1.n8*2*6+t.F2.n8*2*3),0,t,n)}function tn(e,t,n,r){let i={tau:{},alpha:{},beta:{}};return i.tau.g1_s=a(),i.tau.g1_sx=a(),i.alpha.g1_s=a(),i.alpha.g1_sx=a(),i.beta.g1_s=a(),i.beta.g1_sx=a(),i.tau.g2_spx=o(),i.alpha.g2_spx=o(),i.beta.g2_spx=o(),i;function a(){let i;return i=r?n.G1.fromRprLEM(e,t):n.G1.fromRprUncompressed(e,t),t+=n.G1.F.n8*2,i}function o(){let i;return i=r?n.G2.fromRprLEM(e,t):n.G2.fromRprUncompressed(e,t),t+=n.G2.F.n8*2,i}}function nn(e,t,n,r,i){a(r.tau.g1_s),a(r.tau.g1_sx),a(r.alpha.g1_s),a(r.alpha.g1_sx),a(r.beta.g1_s),a(r.beta.g1_sx),o(r.tau.g2_spx),o(r.alpha.g2_spx),o(r.beta.g2_spx);async function a(r){i?n.G1.toRprLEM(e,t,r):n.G1.toRprUncompressed(e,t,r),t+=n.F1.n8*2}async function o(r){i?n.G2.toRprLEM(e,t,r):n.G2.toRprUncompressed(e,t,r),t+=n.F2.n8*2}return e}async function rn(e,t,n,r){let i=new Uint8Array(t.F1.n8*2*6+t.F2.n8*2*3);nn(i,0,t,n,r),await e.write(i)}async function an(e,t){let n={};n.tauG1=await c(),n.tauG2=await l(),n.alphaG1=await c(),n.betaG1=await c(),n.betaG2=await l(),n.key=await en(e,t,!0),n.partialHash=await e.read(216),n.nextChallenge=await e.read(64),n.type=await e.readULE32();let r=new Uint8Array(t.G1.F.n8*2*6+t.G2.F.n8*2*3);nn(r,0,t,n.key,!1);let i=Se(n.partialHash);i.update(r),n.responseHash=i.digest();let a=await e.readULE32(),o=e.pos,s=0;for(;e.pos-o1)throw Error(e.fileName+`: File has more than one contributions section`);e.pos=n[7][0].p;let r=await e.readULE32(),i=[];for(let n=0;n0){let t=new Uint8Array(a);await e.writeULE32(t.byteLength),await e.write(t)}else await e.writeULE32(0);async function o(n){t.G1.toRprLEM(r,0,n),await e.write(r)}async function s(n){t.G2.toRprLEM(i,0,n),await e.write(i)}}async function cn(e,t,n){await e.writeULE32(7);let r=e.pos;await e.writeULE64(0),await e.writeULE32(n.length);for(let r=0;r0?f[f.length-1].nextChallenge:ln(u,d,o);let b=await t.createBinFile(r,`ptau`,1,a?7:2);await $t(b,u,d);let x=await v.read(64);if(be(s,y)&&(y=x,f[f.length-1].nextChallenge=y),!be(x,y))throw Error(`Wrong contribution. This contribution is not based on the previous hash`);let S=H.create({dkLen:64});S.update(x);let C=[],w;w=await D(v,b,`G1`,2,2**d*2-1,[1],`tauG1`),p.tauG1=w[0],w=await D(v,b,`G2`,3,2**d,[1],`tauG2`),p.tauG2=w[0],w=await D(v,b,`G1`,4,2**d,[0],`alphaG1`),p.alphaG1=w[0],w=await D(v,b,`G1`,5,2**d,[0],`betaG1`),p.betaG1=w[0],w=await D(v,b,`G2`,6,1,[0],`betaG2`),p.betaG2=w[0],p.partialHash=Ce(S);let T=await v.read(u.F1.n8*2*6+u.F2.n8*2*3);p.key=tn(T,0,u,!1),S.update(new Uint8Array(T));let E=S.digest();if(o&&o.info(U(E,`Contribution Response Hash imported: `)),a){let e=H.create({dkLen:64});e.update(E),await A(e,b,`G1`,2,2**d*2-1,`tauG1`,o),await A(e,b,`G2`,3,2**d,`tauG2`,o),await A(e,b,`G1`,4,2**d,`alphaTauG1`,o),await A(e,b,`G1`,5,2**d,`betaTauG1`,o),await A(e,b,`G2`,6,1,`betaG2`,o),p.nextChallenge=e.digest(),o&&o.info(U(p.nextChallenge,`Next Challenge Hash: `))}else p.nextChallenge=s;return f.push(p),await cn(b,u,f),await v.close(),await b.close(),await c.close(),p.nextChallenge;async function D(e,t,n,r,i,o,s){return a?await O(e,t,n,r,i,o,s):await k(e,t,n,r,i,o,s)}async function O(e,n,r,i,a,s,c){let l=u[r],d=l.F.n8,f=l.F.n8*2,p=[];await t.startWriteSection(n,i);let m=Math.floor((1<<24)/f);C[i]=n.pos;for(let t=0;t=t&&n=t&&i1?u[u.length-2]:d;let p=u[u.length-1];if(r&&r.debug(`Validating contribution #`+u[u.length-1].id),!await mn(s,p,f,r))return!1;let m=H.create({dkLen:64});m.update(p.responseHash),r&&r.debug(`Verifying powers in tau*G1 section`);let h=await C(2,`G1`,`tauG1`,2**c*2-1,[0,1],r);if(i=await q(s,h.R1,h.R2,s.G2.g,p.tauG2),i!==!0)return r&&r.error(`tauG1 section. Powers do not match`),!1;if(!s.G1.eq(s.G1.g,h.singularPoints[0]))return r&&r.error(`First element of tau*G1 section must be the generator`),!1;if(!s.G1.eq(p.tauG1,h.singularPoints[1]))return r&&r.error(`Second element of tau*G1 section does not match the one in the contribution section`),!1;r&&r.debug(`Verifying powers in tau*G2 section`);let g=await C(3,`G2`,`tauG2`,2**c,[0,1],r);if(i=await q(s,s.G1.g,p.tauG1,g.R1,g.R2),i!==!0)return r&&r.error(`tauG2 section. Powers do not match`),!1;if(!s.G2.eq(s.G2.g,g.singularPoints[0]))return r&&r.error(`First element of tau*G2 section must be the generator`),!1;if(!s.G2.eq(p.tauG2,g.singularPoints[1]))return r&&r.error(`Second element of tau*G2 section does not match the one in the contribution section`),!1;r&&r.debug(`Verifying powers in alpha*tau*G1 section`);let _=await C(4,`G1`,`alphatauG1`,2**c,[0],r);if(i=await q(s,_.R1,_.R2,s.G2.g,p.tauG2),i!==!0)return r&&r.error(`alphaTauG1 section. Powers do not match`),!1;if(!s.G1.eq(p.alphaG1,_.singularPoints[0]))return r&&r.error(`First element of alpha*tau*G1 section (alpha*G1) does not match the one in the contribution section`),!1;r&&r.debug(`Verifying powers in beta*tau*G1 section`);let v=await C(5,`G1`,`betatauG1`,2**c,[0],r);if(i=await q(s,v.R1,v.R2,s.G2.g,p.tauG2),i!==!0)return r&&r.error(`betaTauG1 section. Powers do not match`),!1;if(!s.G1.eq(p.betaG1,v.singularPoints[0]))return r&&r.error(`First element of beta*tau*G1 section (beta*G1) does not match the one in the contribution section`),!1;let y=await S(r);if(!s.G2.eq(p.betaG2,y))return r&&r.error(`betaG2 element in betaG2 section does not match the one in the contribution section`),!1;let b=m.digest();if(c==l&&!be(b,p.nextChallenge))return r&&r.error(`Hash of the values does not match the next challenge of the last contributor in the contributions section`),!1;r&&r.info(U(b,`Next challenge hash: `)),x(p,f);for(let e=u.length-2;e>=0;e--){let t=u[e],n=e>0?u[e-1]:d;if(!await mn(s,t,n,r))return!1;x(t,n,r)}if(r&&r.info(`-----------------------------------------------------`),!o[12]||!o[13]||!o[14]||!o[15])r&&r.warn(`this file does not contain phase2 precalculated values. Please run: + snarkjs "powersoftau preparephase2" to prepare this file to be used in the phase2 ceremony.`);else{let e;if(e=await w(`G1`,2,12,`tauG1`,r),!e||(e=await w(`G2`,3,13,`tauG2`,r),!e)||(e=await w(`G1`,4,14,`alphaTauG1`,r),!e)||(e=await w(`G1`,5,15,`betaTauG1`,r),!e))return!1}return await a.close(),r&&r.info(`Powers of Tau Ok!`),!0;function x(e,t){if(!r)return;r.info(`-----------------------------------------------------`),r.info(`Contribution #${e.id}: ${e.name||``}`),r.info(U(e.nextChallenge,`Next Challenge: `));let n=new Uint8Array(s.G1.F.n8*2*6+s.G2.F.n8*2*3);nn(n,0,s,e.key,!1);let i=Se(e.partialHash);i.update(n);let a=i.digest();r.info(U(a,`Response Hash:`)),r.info(U(t.nextChallenge,`Response Hash:`)),e.type==1&&(r.info(`Beacon generator: ${Me(e.beaconHash)}`),r.info(`Beacon iterations Exp: ${e.numIterationsExp}`))}async function S(e){let t=s.G2,n=t.F.n8*2,r=new Uint8Array(n);if(!o[6])throw e.error(`File has no BetaG2 section`),Error(`File has no BetaG2 section`);if(o[6].length>1)throw e.error(`File has no BetaG2 section`),Error(`File has more than one GetaG2 section`);a.pos=o[6][0].p;let i=await a.read(n),c=t.fromRprLEM(i);return t.toRprUncompressed(r,0,c),m.update(r),c}async function C(e,n,r,i,c,l){let u=65536,d=s[n],f=d.F.n8*2;await t.startReadUniqueSection(a,o,e);let p=[],h=d.zero,g=d.zero,_=d.zero;for(let e=0;e0){let e=d.fromRprLEM(n,0),t=Oe(Ee(4),0);h=d.add(h,d.timesScalar(_,t)),g=d.add(g,d.timesScalar(e,t))}let v=await d.multiExpAffine(n.slice(0,(t-1)*f),s),y=await d.multiExpAffine(n.slice(f),s);h=d.add(h,v),g=d.add(g,y),_=d.fromRprLEM(n,(t-1)*f);for(let r=0;r=e&&i1;)l/=2,u+=1;if(2**u!=c)throw Error(`Invalid file size`);i&&i.debug(`Power to tau size: `+u);let d=await ke(r),f=await Dt(n),p=H.create({dkLen:64});for(let e=0;e{i.debug(t+`.g1_s: `+e.G1.toString(g[t].g1_s,16)),i.debug(t+`.g1_sx: `+e.G1.toString(g[t].g1_sx,16)),i.debug(t+`.g2_sp: `+e.G2.toString(g[t].g2_sp,16)),i.debug(t+`.g2_spx: `+e.G2.toString(g[t].g2_spx,16)),i.debug(``)});let _=H.create({dkLen:64});await f.write(h),_.update(h),await _n(a,f,_,e,`G1`,2**u*2-1,e.Fr.one,g.tau.prvKey,`COMPRESSED`,`tauG1`,i),await _n(a,f,_,e,`G2`,2**u,e.Fr.one,g.tau.prvKey,`COMPRESSED`,`tauG2`,i),await _n(a,f,_,e,`G1`,2**u,g.alpha.prvKey,g.tau.prvKey,`COMPRESSED`,`alphaTauG1`,i),await _n(a,f,_,e,`G1`,2**u,g.beta.prvKey,g.tau.prvKey,`COMPRESSED`,`betaTauG1`,i),await _n(a,f,_,e,`G2`,1,g.beta.prvKey,g.tau.prvKey,`COMPRESSED`,`betaTauG2`,i);let v=new Uint8Array(e.F1.n8*2*6+e.F2.n8*2*3);nn(v,0,e,g,!1),await f.write(v),_.update(v);let y=_.digest();i&&i.info(U(y,`Contribution Response Hash: `)),await f.close(),await a.close()}async function yn(e,n,r,i,a,o){let s=je(i);if(s.byteLength==0||s.byteLength*2!=i.length)return o&&o.error(`Invalid Beacon Hash. (It must be a valid hexadecimal sequence)`),!1;if(s.length>=256)return o&&o.error(`Maximum length of beacon hash is 255 bytes`),!1;if(a=parseInt(a),a<10||a>63)return o&&o.error(`Invalid numIterationsExp. (Must be between 10 and 63)`),!1;let{fd:c,sections:l}=await t.readBinFile(e,`ptau`,1),{curve:u,power:d,ceremonyPower:f}=await K(c,l);if(d!=f)return o&&o.error(`This file has been reduced. You cannot contribute into a reduced file.`),!1;l[12]&&o&&o.warn(`Contributing into a file that has phase2 calculated. You will have to prepare phase2 again.`);let p=await on(c,u,l),m={name:r,type:1,numIterationsExp:a,beaconHash:s},h;h=p.length>0?p[p.length-1].nextChallenge:ln(u,d,o),m.key=await un(u,h,s,a);let g=H.create({dkLen:64});g.update(h);let _=await t.createBinFile(n,`ptau`,1,7);await $t(_,u,d);let v=[],y;y=await C(2,`G1`,2**d*2-1,u.Fr.e(1),m.key.tau.prvKey,`tauG1`,o),m.tauG1=y[1],y=await C(3,`G2`,2**d,u.Fr.e(1),m.key.tau.prvKey,`tauG2`,o),m.tauG2=y[1],y=await C(4,`G1`,2**d,m.key.alpha.prvKey,m.key.tau.prvKey,`alphaTauG1`,o),m.alphaG1=y[0],y=await C(5,`G1`,2**d,m.key.beta.prvKey,m.key.tau.prvKey,`betaTauG1`,o),m.betaG1=y[0],y=await C(6,`G2`,1,m.key.beta.prvKey,m.key.tau.prvKey,`betaTauG2`,o),m.betaG2=y[0],m.partialHash=Ce(g);let b=new Uint8Array(u.F1.n8*2*6+u.F2.n8*2*3);nn(b,0,u,m.key,!1),g.update(new Uint8Array(b));let x=g.digest();o&&o.info(U(x,`Contribution Response Hash imported: `));let S=H.create({dkLen:64});return S.update(x),await w(_,`G1`,2,2**d*2-1,`tauG1`,o),await w(_,`G2`,3,2**d,`tauG2`,o),await w(_,`G1`,4,2**d,`alphaTauG1`,o),await w(_,`G1`,5,2**d,`betaTauG1`,o),await w(_,`G2`,6,1,`betaG2`,o),m.nextChallenge=S.digest(),o&&o.info(U(m.nextChallenge,`Next Challenge Hash: `)),p.push(m),await cn(_,u,p),await c.close(),await _.close(),x;async function C(e,n,r,i,a,o,s){let d=[];c.pos=l[e][0].p,await t.startWriteSection(_,e),v[e]=_.pos;let f=u[n],p=f.F.n8*2,m=Math.floor((1<<20)/p),h=i;for(let e=0;e0?d[d.length-1].nextChallenge:ln(c,l,a),f.key=Qt(c,p,m);let h=H.create({dkLen:64});h.update(p);let g=await t.createBinFile(n,`ptau`,1,7);await $t(g,c,l);let _=[],v;v=await S(2,`G1`,2**l*2-1,c.Fr.e(1),f.key.tau.prvKey,`tauG1`),f.tauG1=v[1],v=await S(3,`G2`,2**l,c.Fr.e(1),f.key.tau.prvKey,`tauG2`),f.tauG2=v[1],v=await S(4,`G1`,2**l,f.key.alpha.prvKey,f.key.tau.prvKey,`alphaTauG1`),f.alphaG1=v[0],v=await S(5,`G1`,2**l,f.key.beta.prvKey,f.key.tau.prvKey,`betaTauG1`),f.betaG1=v[0],v=await S(6,`G2`,1,f.key.beta.prvKey,f.key.tau.prvKey,`betaTauG2`),f.betaG2=v[0],f.partialHash=Ce(h);let y=new Uint8Array(c.F1.n8*2*6+c.F2.n8*2*3);nn(y,0,c,f.key,!1),h.update(new Uint8Array(y));let b=h.digest();a&&a.info(U(b,`Contribution Response Hash imported: `));let x=H.create({dkLen:64});return x.update(b),await C(g,`G1`,2,2**l*2-1,`tauG1`),await C(g,`G2`,3,2**l,`tauG2`),await C(g,`G1`,4,2**l,`alphaTauG1`),await C(g,`G1`,5,2**l,`betaTauG1`),await C(g,`G2`,6,1,`betaG2`),f.nextChallenge=x.digest(),a&&a.info(U(f.nextChallenge,`Next Challenge Hash: `)),d.push(f),await cn(g,c,d),await o.close(),await g.close(),b;async function S(e,n,r,i,l,u){let d=[];o.pos=s[e][0].p,await t.startWriteSection(g,e),_[e]=g.pos;let f=c[n],p=f.F.n8*2,m=Math.floor((1<<20)/p),v=i;for(let e=0;eyn,challengeContribute:()=>vn,contribute:()=>bn,convert:()=>Cn,exportChallenge:()=>fn,exportJson:()=>wn,importResponse:()=>pn,newAccumulator:()=>dn,preparePhase2:()=>xn,truncate:()=>Sn,verify:()=>hn});function En(e,t,n){for(let t=0;t{let r=``;return Object.keys(n).forEach(i=>{let a=t.varIdx2Name[i];a==`one`&&(a=`1`);let o=e.curve.Fr.toString(n[i]);o==`1`&&(o=``),o==`-1`&&(o=`-`),r!=``&&o[0]!=`-`&&(o=`+`+o),r!=``&&(o=` `+o),r=r+o+a}),r},a=`[ ${i(r[0])} ] * [ ${i(r[1])} ] - [ ${i(r[2])} ] = 0`;n&&n.info(a)}}var Dn=n.Scalar.e(`73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001`,16),On=n.Scalar.e(`21888242871839275222246405745257275088548364400416034343698204186575808495617`);async function kn(e,t){let i=await(0,r.readR1cs)(e);return n.Scalar.eq(i.prime,On)?t&&t.info(`Curve: bn-128`):n.Scalar.eq(i.prime,Dn)?t&&t.info(`Curve: bls12-381`):t&&t.info(`Unknown Curve. Prime: ${n.Scalar.toString(i.prime)}`),t&&t.info(`# of Wires: ${i.nVars}`),t&&t.info(`# of Constraints: ${i.nConstraints}`),t&&t.info(`# of Private Inputs: ${i.nPrvInputs}`),t&&t.info(`# of Public Inputs: ${i.nPubInputs}`),t&&t.info(`# of Labels: ${i.nLabels}`),t&&t.info(`# of Outputs: ${i.nOutputs}`),i}async function An(e,t){let n=await(0,r.readR1cs)(e,!0,!0,!0,t),i=n.curve.Fr;return delete n.curve,delete n.F,Ne(i,n)}var jn=d({exportJson:()=>An,info:()=>kn,print:()=>En});async function Mn(e){let t={labelIdx2Name:[`one`],varIdx2Name:[`one`],componentIdx2Name:[]},n=await Ot(e),r=await n.read(n.totalSize),i=new TextDecoder(`utf-8`).decode(r).split(` +`);for(let e=0;e `+t.toString())}),a.trigger&&(d||=await Mn(i),u.logStartComponent=function(e){o&&o.info(`START: `+d.componentIdx2Name[e])},u.logFinishComponent=function(e){o&&o.info(`FINISH: `+d.componentIdx2Name[e])}),u.sym=d;let f=await Nt(l,u),p=await f.calculateWitness(s,!0),m=await t.createBinFile(r,`wtns`,2,2);await Xe(m,p,f.prime),await m.close()}async function Fn(e){return await $e(e)}async function In(e,i,a){a&&a.info(`WITNESS CHECKING STARTED`),a&&a.info(`> Reading r1cs file`);let{fd:o,sections:s}=await t.readBinFile(e,`r1cs`,1,1<<22,1<<24),c=await(0,r.readR1csFd)(o,s,{loadConstraints:!1,loadCustomGates:!1});a&&a.info(`> Reading witness file`);let{fd:l,sections:u}=await t.readBinFile(i,`wtns`,2,1<<22,1<<24),d=await Qe(l,u);if(!n.Scalar.eq(c.prime,d.q))throw Error(`Curve of the witness does not match the curve of the proving key`);let f=await t.readSection(l,u,2);await l.close();let p=(await v(c.prime)).Fr,m=p.n8,h=await t.readSection(o,s,2);a&&(a.info(`----------------------------`),a.info(` WITNESS CHECK`),a.info(` Curve: ${c.curve.name}`),a.info(` Vars (wires): ${c.nVars}`),a.info(` Outputs: ${c.nOutputs}`),a.info(` Public Inputs: ${c.nPubInputs}`),a.info(` Private Inputs: ${c.nPrvInputs}`),a.info(` Labels: ${c.nLabels}`),a.info(` Constraints: ${c.nConstraints}`),a.info(` Custom Gates: ${c.useCustomGates}`),a.info(`----------------------------`)),a&&a.info(`> Checking witness correctness`);let g=0,_=!0;for(let e=0;e{let r=x(n),i=e[n];t=p.add(t,p.mul(r,i))}),t}function b(){let e={},t=h.slice(g,g+4);g+=4;let n=new DataView(t.buffer).getUint32(0,!0),r=h.slice(g,g+(4+c.n8)*n);g+=(4+c.n8)*n;let i=new DataView(r.buffer);for(let t=0;tLt,check:()=>In,debug:()=>Pn,exportJson:()=>Fn}),Rn=262144,zn={get:function(e,t){return isNaN(t)?e[t]:e.getElement(t)},set:function(e,t,n){return isNaN(t)?(e[t]=n,!0):e.setElement(t,n)}},Bn=class{constructor(e){this.length=e||0,this.arr=Array(Rn);for(let t=0;t=this.length&&(this.length=e+1),!0}getKeys(){let e=new J;for(let t=0;td)return o&&o.error(`circuit too big for this power of tau ceremony. ${m.nConstraints}*2 > 2**${d}`),-1;if(!l[12])return o&&o.error(`Powers of tau is not prepared.`),-1;let y=m.nOutputs+m.nPubInputs,b=2**v;await(0,t.startWriteSection)(h,1),await h.writeULE32(1),await(0,t.endWriteSection)(h),await(0,t.startWriteSection)(h,2);let x=u.q,S=(Math.floor((n.Scalar.bitLength(x)-1)/64)+1)*8,C=u.r,w=(Math.floor((n.Scalar.bitLength(C)-1)/64)+1)*8,T=n.Scalar.mod(n.Scalar.shl(1,w*8),C),E=u.Fr.e(n.Scalar.mod(n.Scalar.mul(T,T),C));await h.writeULE32(S),await(0,t.writeBigInt)(h,x,S),await h.writeULE32(w),await(0,t.writeBigInt)(h,C,w),await h.writeULE32(m.nVars),await h.writeULE32(y),await h.writeULE32(b);let D;D=await c.read(g,l[4][0].p),await h.write(D),D=await u.G1.batchLEMtoU(D),s.update(D);let O;O=await c.read(g,l[5][0].p),await h.write(O),O=await u.G1.batchLEMtoU(O),s.update(O);let k;k=await c.read(_,l[6][0].p),await h.write(k),k=await u.G2.batchLEMtoU(k),s.update(k);let A=new Uint8Array(g);u.G1.toRprLEM(A,0,u.G1.g);let j=new Uint8Array(_);u.G2.toRprLEM(j,0,u.G2.g);let M=new Uint8Array(g);u.G1.toRprUncompressed(M,0,u.G1.g);let N=new Uint8Array(_);u.G2.toRprUncompressed(N,0,u.G2.g),await h.write(j),await h.write(A),await h.write(j),s.update(N),s.update(M),s.update(N),await(0,t.endWriteSection)(h),o&&o.info(V()),o&&o.info(`Reading r1cs`);let P=await(0,t.readSection)(f,p,2);await f.close();let F=new J(m.nVars),I=new J(m.nVars),L=new J(m.nVars),R=new J(m.nVars-y-1),z=Array(y+1);o&&o.info(V()),o&&o.info(`Reading tauG1`);let ee=await(0,t.readSection)(c,l,12,(b-1)*g,b*g);o&&o.info(`Reading tauG2`);let te=await(0,t.readSection)(c,l,13,(b-1)*_,b*_);o&&o.info(`Reading alphatauG1`);let ne=await(0,t.readSection)(c,l,14,(b-1)*g,b*g);o&&o.info(`Reading betatauG1`);let re=await(0,t.readSection)(c,l,15,(b-1)*g,b*g);o&&o.info(V()),o&&o.info(`processConstraints`),await oe(),o&&o.info(V()),o&&o.info(`composeAndWritePoints`),await se(3,`G1`,z,`IC`),z=null,o&&o.info(V()),o&&o.info(`writeHs`),await ae(),o&&o.info(V()),o&&o.info(`hashHPoints`),await le(),o&&o.info(V()),o&&o.info(`composeAndWritePoints 8 G1 C`),await se(8,`G1`,R,`C`),R=null,o&&o.info(V()),o&&o.info(`composeAndWritePoints 5 G1 A`),await se(5,`G1`,F,`A`),F=null,o&&o.info(V()),o&&o.info(`composeAndWritePoints 6 G1 B1`),await se(6,`G1`,I,`B1`),I=null,o&&o.info(V()),o&&o.info(`composeAndWritePoints 7 G2 B2`),await se(7,`G2`,L,`B2`),L=null,o&&o.info(V()),o&&o.info(`Contributions section`);let ie=s.digest();return await(0,t.startWriteSection)(h,10),await h.write(ie),await h.writeULE32(0),await(0,t.endWriteSection)(h),o&&o.info(U(ie,`Circuit hash: `)),await h.close(),await c.close(),ie;async function ae(){await(0,t.startWriteSection)(h,9);let e=new n.BigBuffer(b*g);if(v=0?u.Fr.fromRprLE(P.slice(t[3],t[3]+u.Fr.n8),0):u.Fr.fromRprLE(i,0);let a=u.Fr.mul(n,E);u.Fr.toRprLE(e,12,a),l.set(e,f),f+=e.length}}async function se(e,n,r,i){let a=32768,c=u[n];B(r.length),await(0,t.startWriteSection)(h,e);let l=[],d=0;for(;d(o&&o.debug(`Writing points end ${i}: ${u}/${r.length}`),e))),d+=t,e++}let t=await Promise.all(l);for(let e=0;e32768?(h=new n.BigBuffer(m*o),g=new n.BigBuffer(m*u.Fr.n8)):(h=new Uint8Array(m*o),g=new Uint8Array(m*u.Fr.n8));let _,v,y=[ee,te,ne,re],b=new Uint8Array(u.Fr.n8);u.Fr.toRprLE(b,0,u.Fr.e(1));let x=0;for(let e=0;e=0?g.set(P.slice(t[e][n][2],t[e][n][2]+u.Fr.n8),x*u.Fr.n8):g.set(b,x*u.Fr.n8),x++;if(t.length>1){let e=[];e.push({cmd:`ALLOCSET`,var:0,buff:h}),e.push({cmd:`ALLOCSET`,var:1,buff:g}),e.push({cmd:`ALLOC`,var:2,len:t.length*s}),_=0,v=0;let n=0;for(let r=0;r`u`||!process.memoryUsage)return{};let e=process.memoryUsage();for(let t in e)e[t]=Math.round(e[t]/(1024*1024));return e}}async function Hn(e,n,r){let{fd:i,sections:a}=await t.readBinFile(e,`zkey`,2),o=await Re(i,a);if(o.protocol!=`groth16`)throw Error(`zkey file is not groth16`);let s=await y(o.q),c=s.G1.F.n8*2,l=s.G2.F.n8*2,u=await We(i,s,a),d=await Dt(n);await b(o.vk_alpha_1),await b(o.vk_beta_1),await x(o.vk_beta_2),await x(o.vk_gamma_2),await b(o.vk_delta_1),await x(o.vk_delta_2);let f;f=await t.readSection(i,a,3),f=await s.G1.batchLEMtoU(f),await S(`G1`,f);let p=await t.readSection(i,a,9),m;m=await s.G1.fft(p,`affine`,`jacobian`,r),m=await s.G1.batchApplyKey(m,s.Fr.neg(s.Fr.e(2)),s.Fr.w[o.power+1],`jacobian`,`affine`,r),m=m.slice(0,m.byteLength-c),m=await s.G1.batchLEMtoU(m),await S(`G1`,m);let h;h=await t.readSection(i,a,8),h=await s.G1.batchLEMtoU(h),await S(`G1`,h);let g;g=await t.readSection(i,a,5),g=await s.G1.batchLEMtoU(g),await S(`G1`,g);let _;_=await t.readSection(i,a,6),_=await s.G1.batchLEMtoU(_),await S(`G1`,_);let v;v=await t.readSection(i,a,7),v=await s.G2.batchLEMtoU(v),await S(`G2`,v),await d.write(u.csHash),await C(u.contributions.length);for(let e=0;ep.contributions.length)return a&&a.error(`The impoerted file does not include new contributions`),!1;for(let e=0;e=0;e--){let t=f.contributions[e];a&&a.info(`-------------------------`),a&&a.info(U(t.contributionHash,`contribution #${e+1} ${t.name?t.name:``}:`)),t.type==1&&(a&&a.info(`Beacon generator: ${Me(t.beaconHash)}`),a&&a.info(`Beacon iterations Exp: ${t.numIterationsExp}`))}return a&&a.info(`-------------------------`),a&&a.info(`ZKey Ok!`),!0;async function x(e,n,r,i,s,c,l,d,f){let p=1<<20,m=u[e],h=m.F.n8*2;await t.startReadUniqueSection(n,r,c),await t.startReadUniqueSection(i,s,c);let g=m.zero,_=m.zero,v=r[c][0].size/h;for(let e=0;e=256)return o&&o.error(`Maximum length of beacon hash is 255 bytes`),!1;if(a=parseInt(a),a<10||a>63)return o&&o.error(`Invalid numIterationsExp. (Must be between 10 and 63)`),!1;let{fd:c,sections:l}=await t.readBinFile(e,`zkey`,2),u=await Re(c,l);if(u.protocol!=`groth16`)throw Error(`zkey file is not groth16`);let d=await y(u.q),f=await We(c,d,l),p=await t.createBinFile(n,`zkey`,1,10),m=await Ae(s,a),h=H.create({dkLen:64});h.update(f.csHash);for(let e=0;e Detected protocol: `+a.protocol);let o;if(a.protocol===`groth16`)o=await $n(a,r,i);else if(a.protocol===`plonk`)o=await er(a);else if(a.protocolId&&a.protocolId===10)o=await tr(a,n);else throw Error(`zkey file protocol unrecognized`);return await r.close(),n&&n.info(`EXPORT VERIFICATION KEY FINISHED`),o}async function $n(e,n,r){let i=await y(e.q),a=i.G1.F.n8*2,o=await i.pairing(e.vk_alpha_1,e.vk_beta_2),s={protocol:e.protocol,curve:i.name,nPublic:e.nPublic,vk_alpha_1:i.G1.toObject(e.vk_alpha_1),vk_beta_2:i.G2.toObject(e.vk_beta_2),vk_gamma_2:i.G2.toObject(e.vk_gamma_2),vk_delta_2:i.G2.toObject(e.vk_delta_2),vk_alphabeta_12:i.Gt.toObject(o)};await t.startReadUniqueSection(n,r,3),s.IC=[];for(let t=0;t<=e.nPublic;t++){let e=await n.read(a),t=i.G1.toObject(e);s.IC.push(t)}return await t.endReadSection(n),s=Zn(s),s}async function er(e){let t=await y(e.q),n={protocol:e.protocol,curve:t.name,nPublic:e.nPublic,power:e.power,k1:t.Fr.toObject(e.k1),k2:t.Fr.toObject(e.k2),Qm:t.G1.toObject(e.Qm),Ql:t.G1.toObject(e.Ql),Qr:t.G1.toObject(e.Qr),Qo:t.G1.toObject(e.Qo),Qc:t.G1.toObject(e.Qc),S1:t.G1.toObject(e.S1),S2:t.G1.toObject(e.S2),S3:t.G1.toObject(e.S3),X_2:t.G2.toObject(e.X_2),w:t.Fr.toObject(t.Fr.w[e.power])};return n=Zn(n),n}async function tr(e,t){let n=await y(e.q);return Zn({protocol:e.protocol,curve:n.name,nPublic:e.nPublic,power:e.power,k1:n.Fr.toObject(e.k1),k2:n.Fr.toObject(e.k2),w:n.Fr.toObject(n.Fr.w[e.power]),w3:n.Fr.toObject(e.w3),w4:n.Fr.toObject(e.w4),w8:n.Fr.toObject(e.w8),wr:n.Fr.toObject(e.wr),X_2:n.G2.toObject(e.X_2),C0:n.G1.toObject(e.C0)})}var nr=d({beacon:()=>Jn,bellmanContribute:()=>Xn,contribute:()=>qn,exportBellman:()=>Hn,exportJson:()=>Yn,exportSolidityVerifier:()=>null,exportVerificationKey:()=>Qn,importBellman:()=>Un,newZKey:()=>Vn,verifyFromInit:()=>Gn,verifyFromR1cs:()=>Kn});async function rr(e,i,a,o){globalThis.gc&&globalThis.gc();let{fd:s,sections:c}=await(0,t.readBinFile)(i,`ptau`,1,1<<22,1<<24),{curve:l,power:u}=await K(s,c),{fd:d,sections:f}=await(0,t.readBinFile)(e,`r1cs`,1,1<<22,1<<24),p=await(0,r.readR1csFd)(d,f,{loadConstraints:!0,loadCustomGates:!0}),m=l.G1.F.n8*2,h=l.G1,g=l.G2.F.n8*2,_=l.Fr,v=l.Fr.n8;o&&o.info(`Reading r1cs`),await(0,t.readSection)(d,f,2);let y=new J,b=new J,x=p.nVars,S=p.nOutputs+p.nPubInputs;await M(l.Fr,p,o),globalThis.gc&&globalThis.gc();let C=await(0,t.createBinFile)(a,`zkey`,1,14,1<<22,1<<24);if(p.prime!=l.r)return o&&o.error(`r1cs curve does not match powers of tau ceremony curve`),-1;let w=ye(y.length-1)+1;w<3&&(w=3);let T=2**w;if(o&&o.info(`Plonk constraints: `+y.length),w>u)return o&&o.error(`circuit too big for this power of tau ceremony. ${y.length} > 2**${u}`),-1;if(!c[12])return o&&o.error(`Powers of tau is not prepared.`),-1;let E=new n.BigBuffer(T*m),D=c[12][0].p+(2**w-1)*m;await s.readToBuffer(E,0,T*m,D);let[O,k]=ee(),A={};await I(3,`Additions`),globalThis.gc&&globalThis.gc(),await N(4,0,`Amap`),globalThis.gc&&globalThis.gc(),await N(5,1,`Bmap`),globalThis.gc&&globalThis.gc(),await N(6,2,`Cmap`),globalThis.gc&&globalThis.gc(),await P(7,3,`Qm`),globalThis.gc&&globalThis.gc(),await P(8,4,`Ql`),globalThis.gc&&globalThis.gc(),await P(9,5,`Qr`),globalThis.gc&&globalThis.gc(),await P(10,6,`Qo`),globalThis.gc&&globalThis.gc(),await P(11,7,`Qc`),globalThis.gc&&globalThis.gc(),await L(12,`sigma`),globalThis.gc&&globalThis.gc(),await R(13,`lagrange polynomials`),globalThis.gc&&globalThis.gc(),await(0,t.startWriteSection)(C,14);let j=new n.BigBuffer((T+6)*m);await s.readToBuffer(j,0,(T+6)*m,c[2][0].p),await C.write(j),await(0,t.endWriteSection)(C),globalThis.gc&&globalThis.gc(),await z(),await C.close(),await d.close(),await s.close(),o&&o.info(`Setup Finished`);return;async function M(e,t,n){function r(e){let t=Object.keys(e);for(let n=0;nn;){let t=i.shift(),n=i.shift(),r=t[0],a=n[0],o=x++,s=e.zero,c=e.neg(t[1]),l=e.neg(n[1]),u=e.one,d=e.zero;y.push([r,a,o,s,c,l,u,d]),b.push([r,a,t[1],n[1]]),i.push([o,e.one])}for(let e=0;e0?r.toString():n==e.zero?`0`:`k`}function l(e,t,n){let a=c(e),l=c(t);a===`0`||l===`0`?(r(n),o(n)):a===`k`?o(i(t,e[0],n)):l===`k`?o(i(e,t[0],n)):s(e,t,n)}for(let t=1;t<=S;t++){let n=t,r=e.zero,i=e.one,a=e.zero,o=e.zero,s=e.zero;y.push([n,0,0,r,i,a,o,s])}for(let e=0;e{let r=this.curve.G1.toObject(this.polynomials[n]);e?t.polynomials[n]=r:t[n]=r}),Object.keys(this.evaluations).forEach(n=>{let r=this.curve.Fr.toObject(this.evaluations[n]);e?t.evaluations[n]=r:t[n]=r}),t}fromObjectProof(e){this.resetProof(),Object.keys(e.polynomials).forEach(t=>{this.polynomials[t]=this.curve.G1.fromObject(e.polynomials[t])}),Object.keys(e.evaluations).forEach(t=>{this.evaluations[t]=this.curve.Fr.fromObject(e.evaluations[t])})}},ar=BigInt(0),or=BigInt(1),sr=BigInt(2),cr=BigInt(7),lr=BigInt(256),ur=BigInt(113),dr=[],fr=[],pr=[];for(let e=0,t=or,n=1,r=0;e<24;e++){[n,r]=[r,(2*n+3*r)%5],dr.push(2*(5*r+n)),fr.push((e+1)*(e+2)/2%64);let i=ar;for(let e=0;e<7;e++)t=(t<>cr)*ur)%lr,t&sr&&(i^=or<<(or<n>32?se(e,t,n):ae(e,t,n),vr=(e,t,n)=>n>32?ce(e,t,n):oe(e,t,n);function yr(e,t=24){if(S(t,`rounds`),t<1||t>24)throw Error(`"rounds" expected integer 1..24`);let n=new Uint32Array(10);for(let r=24-t;r<24;r++){for(let t=0;t<10;t++)n[t]=e[t]^e[t+10]^e[t+20]^e[t+30]^e[t+40];for(let t=0;t<10;t+=2){let r=(t+8)%10,i=(t+2)%10,a=n[i],o=n[i+1],s=_r(a,o,1)^n[r],c=vr(a,o,1)^n[r+1];for(let n=0;n<50;n+=10)e[t+n]^=s,e[t+n+1]^=c}let t=e[2],i=e[3];for(let n=0;n<24;n++){let r=fr[n],a=_r(t,i,r),o=vr(t,i,r),s=dr[n];t=e[s],i=e[s+1],e[s]=a,e[s+1]=o}for(let t=0;t<50;t+=10){let n=e[t],r=e[t+1],i=e[t+2],a=e[t+3];e[t]^=~e[t+2]&e[t+4],e[t+1]^=~e[t+3]&e[t+5],e[t+2]^=~e[t+4]&e[t+6],e[t+3]^=~e[t+5]&e[t+7],e[t+4]^=~e[t+6]&e[t+8],e[t+5]^=~e[t+7]&e[t+9],e[t+6]^=~e[t+8]&n,e[t+7]^=~e[t+9]&r,e[t+8]^=~n&i,e[t+9]^=~r&a}e[0]^=hr[r],e[1]^=gr[r]}D(n)}var br=class e{state;pos=0;posOut=0;finished=!1;state32;destroyed=!1;blockLen;suffix;outputLen;canXOF;enableXOF=!1;rounds;constructor(e,t,n,r=!1,i=24){if(this.blockLen=e,this.suffix=t,this.outputLen=n,this.enableXOF=r,this.canXOF=r,this.rounds=i,S(n,`outputLen`),!(0=n&&this.keccak();let a=Math.min(n-this.posOut,i-r);e.set(t.subarray(this.posOut,this.posOut+a),r),this.posOut+=a,r+=a}return e}xofInto(e){if(!this.enableXOF)throw Error(`XOF is not possible for this instance`);return this.writeInto(e)}xof(e){return S(e),this.xofInto(new Uint8Array(e))}digestInto(e){if(T(e,this),this.finished)throw Error(`digest() was already called`);this.writeInto(e.subarray(0,this.outputLen)),this.destroy()}digest(){let e=new Uint8Array(this.outputLen);return this.digestInto(e),e}destroy(){this.destroyed=!0,D(this.state)}_cloneInto(t){let{blockLen:n,suffix:r,outputLen:i,rounds:a,enableXOF:o}=this;return t||=new e(n,r,i,o,a),t.blockLen=n,t.state32.set(this.state32),t.pos=this.pos,t.posOut=this.posOut,t.finished=this.finished,t.rounds=a,t.suffix=r,t.outputLen=i,t.enableXOF=o,t.canXOF=this.canXOF,t.destroyed=this.destroyed,t}},xr=((e,t,n,r={})=>N(()=>new br(t,e,n),r))(1,136,32),Sr=0,Cr=1,wr=class{constructor(e){this.G1=e.G1,this.Fr=e.Fr,this.reset()}reset(){this.data=[]}addPolCommitment(e){this.data.push({type:Sr,data:e})}addScalar(e){this.data.push({type:Cr,data:e})}getChallenge(){if(this.data.length===0)throw Error(`Keccak256Transcript: No data to generate a transcript`);let e=0,t=0;this.data.forEach(n=>Sr===n.type?e++:t++);let r=new Uint8Array(t*this.Fr.n8+e*this.G1.F.n8*2),i=0;for(let e=0;e32768?new n.BigBuffer(t.length*a.n8):new Uint8Array(t.length*a.n8);for(let e=0;e32768?new n.BigBuffer(a*o.n8):new Uint8Array(a*o.n8);return s.set(t.coef.slice(),0),new e(s,r,i)}isEqual(e){let t=this.degree();if(t!==e.degree())return!1;for(let n=0;n32768?new n.BigBuffer((this.length()+e.length)*this.Fr.n8):new Uint8Array((this.length()+e.length)*this.Fr.n8);t.set(this.coef,0);for(let n=0;nthis.coef.byteLength?this.Fr.zero:this.coef.slice(t,t+this.Fr.n8)}setCoef(e,t){if(e>this.length()-1)throw Error(`Coef index is not available`);this.coef.set(t,e*this.Fr.n8)}static async to4T(e,t,r,i){r||=[];let a=await i.ifft(e),o=t*4>32768?new n.BigBuffer(t*4*i.n8):new Uint8Array(t*4*i.n8);o.set(a,0);let s=await i.fft(o);if(r.length===0)return[a,s];let c=t+r.length>32768?new n.BigBuffer((t+r.length)*i.n8):new Uint8Array((t+r.length)*i.n8);c.set(a,0);for(let e=0;e0;e--){let t=e*this.Fr.n8;if(!this.Fr.eq(this.Fr.zero,this.coef.slice(t,t+this.Fr.n8)))return e}return 0}evaluate(e){let t=this.Fr.zero;for(let n=this.degree()+1;n>0;n--){let r=n*this.Fr.n8,i=this.coef.slice(r-this.Fr.n8,r);t=this.Fr.add(i,this.Fr.mul(t,e))}return t}fastEvaluate(e){let t=this.Fr,n=this.degree()+1,r=parseInt(n/3),i=n-r*3,a=[],o=[];o[0]=t.one;for(let n=0;n<3;n++){a[n]=t.zero;let s=n===2?r+i:r;for(let i=s;i>0;i--)a[n]=t.add(this.getCoef(n*r+i-1),t.mul(a[n],e)),n===0&&(o[0]=t.mul(o[0],e))}for(let e=1;e<3;e++)a[0]=t.add(a[0],t.mul(o[e-1],a[e])),o[e]=t.mul(o[e-1],o[0]);return a[0]}add(e,t){let n=!1;e.length()>this.length()&&(n=!0);let r=this.length(),i=e.length();for(let a=0;athis.length()&&(n=!0);let r=this.length(),i=e.length();for(let a=0;a32768?new n.BigBuffer(i*r.n8):new Uint8Array(i*r.n8),this.curve,this.logger);a.coef.set(this.coef.slice(0,(i-1)*r.n8),32),this.mulScalar(r.neg(t)),a.add(this),this.coef=a.coef}byXNSubValue(t,r){let i=this.Fr,a=this.length()-t-1>=this.degree()?this.length():this.length()+t,o=new e(a>32768?new n.BigBuffer(a*i.n8):new Uint8Array(a*i.n8),this.curve,this.logger);o.coef.set(this.coef.slice(0,(this.degree()+1)*32),t*32),this.mulScalar(r),o.add(this),this.coef=o.coef}divBy(t){let r=this.Fr,i=this.degree(),a=t.degree(),o=new e(this.coef,this.curve,this.logger);this.coef=this.length()>32768?new n.BigBuffer(this.length()*r.n8):new Uint8Array(this.length()*r.n8);for(let e=i-a;e>=0;e--){this.setCoef(e,r.div(o.getCoef(e+a),t.getCoef(a)));for(let n=0;n<=a;n++)o.setCoef(e+n,r.sub(o.getCoef(e+n),r.mul(this.getCoef(e),t.getCoef(n))))}return o}divByMonic(t,r){let i=this.Fr,a=this.degree(),o=new e(this.length()>32768?new n.BigBuffer(this.length()*i.n8):new Uint8Array(this.length()*i.n8),this.curve,this.logger),s=[];for(let e=0;e=0&&!(n<0);n-=c){let a=e;s[a]=i.add(this.getCoef(n+t),i.mul(s[a],r)),o.setCoef(n,s[a]),l=(l+1)%t}this.coef=o.coef}divByVanishing(t,r){if(this.degree()32768?new n.BigBuffer(this.length()*i.n8):new Uint8Array(this.length()*i.n8);for(let e=this.length()-1;e>=t;e--){let n=a.getCoef(e);i.eq(i.zero,n)||(a.setCoef(e,i.zero),a.setCoef(e-t,i.add(a.getCoef(e-t),i.mul(r,n))),this.setCoef(e-t,i.add(this.getCoef(e-t),n)))}return a}divByVanishing2(t,r){if(this.degree()32768?new n.BigBuffer(this.length()*i.n8):new Uint8Array(this.length()*i.n8);let o=this.length()-t,s=Math.floor(o/3),c=o-2*s;console.log(o),console.log(s+` `+c);for(let e=0;e<3;e++){console.log(`> Thread `+e);for(let n=e===0?c:s;n>0;n--){let o=n-1;e!==0&&(o+=(e-1)*s+c);let l=o+t,u=a.getCoef(l);i.eq(i.zero,u)||(a.setCoef(l,i.zero),a.setCoef(o,i.add(a.getCoef(o),i.mul(r,u))),this.setCoef(o,i.add(this.getCoef(o),u)),console.log(o+` <-- `+l))}}return this.print(),a}fastDivByVanishing(t){let r=this.Fr;for(let i=0;i32768?new n.BigBuffer(this.length()*r.n8):new Uint8Array(this.length()*r.n8),this.curve,this.logger),f=this.coef;this.coef=d.coef,d.coef=f;for(let e=0;e<5;e++){let t=(e+1)*l+u;for(let e=0;e0;e--){let t=e-1,n=t*l+u;h[t]=[];for(let i=0;i32768?new n.BigBuffer(this.length()*this.Fr.n8):new Uint8Array(this.length()*this.Fr.n8);t.set(this.Fr.zero,(this.length()-1)*this.Fr.n8),t.set(this.coef.slice((this.length()-1)*this.Fr.n8,this.length()*this.Fr.n8),(this.length()-2)*this.Fr.n8);for(let n=this.length()-3;n>=0;n--){let r=n*this.Fr.n8;t.set(this.Fr.add(this.coef.slice(r+this.Fr.n8,r+2*this.Fr.n8),this.Fr.mul(e,t.slice(r+this.Fr.n8,r+2*this.Fr.n8))),n*this.Fr.n8)}if(!this.Fr.eq(this.coef.slice(0,this.Fr.n8),this.Fr.mul(this.Fr.neg(e),t.slice(0,this.Fr.n8))))throw Error(`Polynomial does not divide`);this.coef=t}divZh(e,t=4){for(let t=0;te*(t-1)-t&&!this.Fr.isZero(i))throw Error(`Polynomial is not divisible`)}return this}divByZerofier(e,t){let n=this.Fr,r=n.inv(t),i=n.neg(r),a=n.eq(n.one,i),o=n.eq(n.negone,i);if(!a)for(let t=0;tthis.length()-e-1&&!this.Fr.isZero(c))throw Error(`Polynomial is not divisible`)}return this}byX(){let e=this.length()+1>32768?new n.BigBuffer(this.coef.byteLength+this.Fr.n8):new Uint8Array(this.coef.byteLength+this.Fr.n8);e.set(this.Fr.zero,0),e.set(this.coef,this.Fr.n8),this.coef=e}static async expX(t,r,i=!1){let a=t.Fr;if(r<1)throw Error(`Compute a new polynomial to a zero or negative number is not allowed`);if(r===1)return await e.fromEvaluations(t.coef,t.curve,t.logger);let o=i?t.degree():t.length()-1,s=o*r+1>32768?new n.BigBuffer((o*r+1)*a.n8):new Uint8Array((o*r+1)*a.n8);s.set(t.getCoef(0),0);for(let e=1;e<=o;e++){let n=e*a.n8,i=t.getCoef(e);s.set(i,n*r)}return new e(s,t.curve,t.logger)}split(t,r,i){if(t<1)throw Error(`Polynomials can't be split in ${t} parts`);if(t===1)return[this];if(i.length!==0&&i.length32768?new n.BigBuffer(c):new Uint8Array(c),this.curve,this.logger);let l=r*a,u=s?this.coef.byteLength:(r+1)*a;if(o[r].coef.set(this.coef.slice(l,u),0),s||o[r].coef.set(i[r],a),r!==0){let e=this.Fr.sub(o[r].coef.slice(0,this.Fr.n8),i[r-1]);o[r].coef.set(e,0)}s&&o[r].truncate()}return o}truncate(){let e=this.degree();if(e+132768?new n.BigBuffer((e+1)*this.Fr.n8):new Uint8Array((e+1)*this.Fr.n8);t.set(this.coef.slice(0,(e+1)*this.Fr.n8),0),this.coef=t}}static lagrangePolynomialInterpolation(t,r,i){let a=i.Fr,o=s(0);for(let e=1;e32768?new n.BigBuffer(t.length*a.n8):new Uint8Array(t.length*a.n8),i),s.setCoef(0,a.neg(t[r])),s.setCoef(1,a.one)):s.byXSubValue(t[r]));let c=s.evaluate(t[o]);c=a.inv(c);let l=a.mul(r[o],c);return s.mulScalar(l),s}}static zerofierPolynomial(t,r){let i=r.Fr,a=new e(t.length+1>32768?new n.BigBuffer((t.length+1)*i.n8):new Uint8Array((t.length+1)*i.n8),r);a.setCoef(0,i.neg(t[0])),a.setCoef(1,i.one);for(let e=1;e=0;n--){let r=this.getCoef(n);e.eq(e.zero,r)||(e.isNegative(r)?t+=` - `:n!==this.degree()&&(t+=` + `),t+=e.toString(r),n>0&&(t+=n>1?`x^`+n:`x`))}console.log(t)}async multiExponentiation(e,t){let n=this.coef.byteLength/this.Fr.n8,r=e.slice(0,n*this.G1.F.n8*2),i=await this.Fr.batchFromMontgomery(this.coef),a=await this.G1.multiExpAffine(r,i,this.logger,t);return a=this.G1.toAffine(a),a}},X=class e{constructor(e,t,n){this.eval=e,this.curve=t,this.Fr=t.Fr,this.logger=n}static async fromPolynomial(t,r,i,a){let o=new n.BigBuffer(t.length()*r*i.Fr.n8);return o.set(t.coef,0),new e(await i.Fr.fft(o),i,a)}getEvaluation(e){let t=e*this.Fr.n8;if(t+this.Fr.n8>this.eval.byteLength)throw Error(`Evaluations.getEvaluation() out of bounds`);return this.eval.slice(t,t+this.Fr.n8)}length(){let e=this.eval.byteLength/this.Fr.n8;if(e!==Math.floor(this.eval.byteLength/this.Fr.n8))throw Error(`Polynomial evaluations buffer has incorrect size`);return e===0&&this.logger.warn(`Polynomial has length zero`),e}},{stringifyBigInts:Er}=n.utils;async function Dr(e,r,i,a){let{fd:o,sections:s}=await t.readBinFile(r,`wtns`,2,1<<25,1<<23);i&&i.debug(`> Reading witness file`);let c=await Qe(o,s);i&&i.debug(`> Reading zkey file`);let{fd:l,sections:u}=await t.readBinFile(e,`zkey`,2,1<<25,1<<23),d=await Re(l,u,void 0,a);if(d.protocol!=`plonk`)throw Error(`zkey file is not plonk`);if(!n.Scalar.eq(d.r,c.q))throw Error(`Curve of the witness does not match the curve of the proving key`);if(c.nWitness!=d.nVars-d.nAdditions)throw Error(`Invalid witness length. Circuit: ${d.nVars}, witness: ${c.nWitness}, ${d.nAdditions}`);let f=d.curve,p=f.Fr,m=f.Fr.n8,h=d.domainSize*m;i&&(i.debug(`----------------------------`),i.debug(` PLONK PROVE SETTINGS`),i.debug(` Curve: ${f.name}`),i.debug(` Circuit power: ${d.power}`),i.debug(` Domain size: ${d.domainSize}`),i.debug(` Vars: ${d.nVars}`),i.debug(` Public vars: ${d.nPublic}`),i.debug(` Constraints: ${d.nConstraints}`),i.debug(` Additions: ${d.nAdditions}`),i.debug(`----------------------------`)),i&&i.debug(`> Reading witness file data`);let g=await t.readSection(o,s,2);g.set(p.zero,0);let _=new n.BigBuffer(m*d.nAdditions),v={},y={},b={},x={},S=new ir(f,i),C=new wr(f);i&&i.debug(`> Reading Section 3. Additions`),await D(),i&&i.debug(`> Reading Section 12. Sigma1, Sigma2 & Sigma 3`),i&&i.debug(`··· Reading Sigma polynomials `),y.Sigma1=new Y(new n.BigBuffer(h),f,i),y.Sigma2=new Y(new n.BigBuffer(h),f,i),y.Sigma3=new Y(new n.BigBuffer(h),f,i),await l.readToBuffer(y.Sigma1.coef,0,h,u[12][0].p),await l.readToBuffer(y.Sigma2.coef,0,h,u[12][0].p+5*h),await l.readToBuffer(y.Sigma3.coef,0,h,u[12][0].p+10*h),i&&i.debug(`··· Reading Sigma evaluations`),b.Sigma1=new X(new n.BigBuffer(h*4),f,i),b.Sigma2=new X(new n.BigBuffer(h*4),f,i),b.Sigma3=new X(new n.BigBuffer(h*4),f,i),await l.readToBuffer(b.Sigma1.eval,0,h*4,u[12][0].p+h),await l.readToBuffer(b.Sigma2.eval,0,h*4,u[12][0].p+6*h),await l.readToBuffer(b.Sigma3.eval,0,h*4,u[12][0].p+11*h),i&&i.debug(`> Reading Section 14. Powers of Tau`);let w=await t.readSection(l,u,14),T=[];for(let e=1;e<=d.nPublic;e++){let t=g.slice(e*p.n8,e*p.n8+p.n8);T.push(n.Scalar.fromRprLE(t))}i&&i.debug(``),i&&i.debug(`> ROUND 1`),await A(),i&&i.debug(`> ROUND 2`),await M(),i&&i.debug(`> ROUND 3`),await P(),i&&i.debug(`> ROUND 4`),await I(),i&&i.debug(`> ROUND 5`),await L(),await l.close(),await o.close();let E=S.toObjectProof(!1);return E.protocol=`plonk`,E.curve=f.name,i&&i.debug(`PLONK PROVER FINISHED`),{proof:Er(E),publicSignals:Er(T)};async function D(){i&&i.debug(`··· Computing additions`);let e=await t.readSection(l,u,3),n=8+m*2;for(let t=0;t Computing A, B, C wire polynomials`),await j(),i&&i.debug(`> Computing A, B, C MSM`);let e=await y.A.multiExponentiation(w,`A`),t=await y.B.multiExponentiation(w,`B`),n=await y.C.multiExponentiation(w,`C`);return S.addPolynomial(`A`,e),S.addPolynomial(`B`,t),S.addPolynomial(`C`,n),0}async function j(){i&&i.debug(`··· Reading data from zkey file`),v.A=new n.BigBuffer(h),v.B=new n.BigBuffer(h),v.C=new n.BigBuffer(h);let e=await t.readSection(l,u,4),r=await t.readSection(l,u,5),a=await t.readSection(l,u,6);for(let t=0;t=d.domainSize+2)throw Error(`A Polynomial is not well calculated`);if(y.B.degree()>=d.domainSize+2)throw Error(`B Polynomial is not well calculated`);if(y.C.degree()>=d.domainSize+2)throw Error(`C Polynomial is not well calculated`)}async function M(){i&&i.debug(`> Computing challenges beta and gamma`),C.reset(),C.addPolCommitment(d.Qm),C.addPolCommitment(d.Ql),C.addPolCommitment(d.Qr),C.addPolCommitment(d.Qo),C.addPolCommitment(d.Qc),C.addPolCommitment(d.S1),C.addPolCommitment(d.S2),C.addPolCommitment(d.S3);for(let e=0;e Computing Z polynomial`),await N(),i&&i.debug(`> Computing Z MSM`);let e=await y.Z.multiExponentiation(w,`Z`);S.addPolynomial(`Z`,e)}async function N(){i&&i.debug(`··· Computing Z evaluations`);let e=new n.BigBuffer(h),t=new n.BigBuffer(h);e.set(p.one,0),t.set(p.one,0);let r=p.one;for(let n=0;n=d.domainSize+3)throw Error(`Z Polynomial is not well calculated`);delete v.Z}async function P(){i&&i.debug(`> Computing challenge alpha`),C.reset(),C.addScalar(x.beta),C.addScalar(x.gamma),C.addPolCommitment(S.getPolynomial(`Z`)),x.alpha=C.getChallenge(),x.alpha2=p.square(x.alpha),i&&i.debug(`··· challenges.alpha: `+p.toString(x.alpha,16)),i&&i.debug(`> Computing T polynomial`),await F(),i&&i.debug(`> Computing T MSM`);let e=await y.T1.multiExponentiation(w,`T1`),t=await y.T2.multiExponentiation(w,`T2`),n=await y.T3.multiExponentiation(w,`T3`);S.addPolynomial(`T1`,e),S.addPolynomial(`T2`,t),S.addPolynomial(`T3`,n)}async function F(){i&&i.debug(`··· Reading sections 8, 9, 7, 10, 11. Q selectors`),b.QL=new X(new n.BigBuffer(h*4),f,i),b.QR=new X(new n.BigBuffer(h*4),f,i),b.QM=new X(new n.BigBuffer(h*4),f,i),b.QO=new X(new n.BigBuffer(h*4),f,i),b.QC=new X(new n.BigBuffer(h*4),f,i),await l.readToBuffer(b.QL.eval,0,h*4,u[8][0].p+h),await l.readToBuffer(b.QR.eval,0,h*4,u[9][0].p+h),await l.readToBuffer(b.QM.eval,0,h*4,u[7][0].p+h),await l.readToBuffer(b.QO.eval,0,h*4,u[10][0].p+h),await l.readToBuffer(b.QC.eval,0,h*4,u[11][0].p+h),b.Lagrange=new X(new n.BigBuffer(h*4*d.nPublic),f,i);for(let e=0;e=d.domainSize*3+6)throw Error(`T Polynomial is not well calculated`);i&&i.debug(`··· Computing T1, T2, T3 polynomials`),y.T1=new Y(new n.BigBuffer((d.domainSize+1)*m),f,i),y.T2=new Y(new n.BigBuffer((d.domainSize+1)*m),f,i),y.T3=new Y(new n.BigBuffer((d.domainSize+6)*m),f,i),y.T1.coef.set(y.T.coef.slice(0,h),0),y.T2.coef.set(y.T.coef.slice(h,h*2),0),y.T3.coef.set(y.T.coef.slice(h*2,h*3+6*m),0),y.T1.setCoef(d.domainSize,x.b[10]);let t=p.sub(y.T2.getCoef(0),x.b[10]);y.T2.setCoef(0,t),y.T2.setCoef(d.domainSize,x.b[11]);let r=p.sub(y.T3.getCoef(0),x.b[11]);y.T3.setCoef(0,r)}async function I(){i&&i.debug(`> Computing challenge xi`),C.reset(),C.addScalar(x.alpha),C.addPolCommitment(S.getPolynomial(`T1`)),C.addPolCommitment(S.getPolynomial(`T2`)),C.addPolCommitment(S.getPolynomial(`T3`)),x.xi=C.getChallenge(),x.xiw=p.mul(x.xi,p.w[d.power]),i&&i.debug(`··· challenges.xi: `+p.toString(x.xi,16)),S.addEvaluation(`eval_a`,y.A.evaluate(x.xi)),S.addEvaluation(`eval_b`,y.B.evaluate(x.xi)),S.addEvaluation(`eval_c`,y.C.evaluate(x.xi)),S.addEvaluation(`eval_s1`,y.Sigma1.evaluate(x.xi)),S.addEvaluation(`eval_s2`,y.Sigma2.evaluate(x.xi)),S.addEvaluation(`eval_zw`,y.Z.evaluate(x.xiw))}async function L(){i&&i.debug(`> Computing challenge v`),C.reset(),C.addScalar(x.xi),C.addScalar(S.getEvaluation(`eval_a`)),C.addScalar(S.getEvaluation(`eval_b`)),C.addScalar(S.getEvaluation(`eval_c`)),C.addScalar(S.getEvaluation(`eval_s1`)),C.addScalar(S.getEvaluation(`eval_s2`)),C.addScalar(S.getEvaluation(`eval_zw`)),x.v=[],x.v[1]=C.getChallenge(),i&&i.debug(`··· challenges.v: `+p.toString(x.v[1],16));for(let e=2;e<6;e++)x.v[e]=p.mul(x.v[e-1],x.v[1]);i&&i.debug(`> Computing linearisation polynomial R(X)`),await R(),i&&i.debug(`> Computing opening proof polynomial Wxi(X) polynomial`),z(),i&&i.debug(`> Computing opening proof polynomial Wxiw(X) polynomial`),ee(),i&&i.debug(`> Computing Wxi, Wxiw MSM`);let e=await y.Wxi.multiExponentiation(w,`Wxi`),t=await y.Wxiw.multiExponentiation(w,`Wxiw`);S.addPolynomial(`Wxi`,e),S.addPolynomial(`Wxiw`,t)}async function R(){let e=f.Fr;y.QL=new Y(new n.BigBuffer(h),f,i),y.QR=new Y(new n.BigBuffer(h),f,i),y.QM=new Y(new n.BigBuffer(h),f,i),y.QO=new Y(new n.BigBuffer(h),f,i),y.QC=new Y(new n.BigBuffer(h),f,i),await l.readToBuffer(y.QL.coef,0,h,u[8][0].p),await l.readToBuffer(y.QR.coef,0,h,u[9][0].p),await l.readToBuffer(y.QM.coef,0,h,u[7][0].p),await l.readToBuffer(y.QO.coef,0,h,u[10][0].p),await l.readToBuffer(y.QC.coef,0,h,u[11][0].p),x.xin=x.xi;for(let t=0;tJr,fullProve:()=>kr,prove:()=>Dr,setup:()=>rr,verify:()=>jr});function Xr(e,t){return[e,0,0,t.one,t.zero,t.zero,t.zero,t.zero]}function Zr(e,t,n,r,i,a,o,s){return[e,t,n,r,i,a,o,s]}function Qr(e,t,n,r,i,a,o,s,c){return[e,t,n,r,i,a,o,s]}var $r=0,ei=1,ti=2,ni=class{constructor(e,t,n,r,i){this.Fr=e,this.logger=i,this.fnGetAdditionConstraint=n,this.fnGetMultiplicationConstraint=r}processR1csConstraint(e,t,n,r){this.normalizeLinearCombination(t),this.normalizeLinearCombination(n),this.normalizeLinearCombination(r);let i=this.getLinearCombinationType(t),a=this.getLinearCombinationType(n);if(i===$r||a===$r)return this.processR1csAdditionConstraint(e,r);if(i===ei){let i=this.joinLinearCombinations(n,r,t[0]);return this.processR1csAdditionConstraint(e,i)}else if(a===ei){let i=this.joinLinearCombinations(t,r,n[0]);return this.processR1csAdditionConstraint(e,i)}else return this.processR1csMultiplicationConstraint(e,t,n,r)}getLinearCombinationType(e){let t=this.Fr.zero,n=0,r=Object.keys(e);for(let i=0;i0?ti:this.Fr.isZero(t)?$r:ei}normalizeLinearCombination(e){let t=Object.keys(e);for(let n=0;ni;){let r=o.shift(),i=o.shift(),a=e.nVars++,s=this.fnGetAdditionConstraint(r[0],i[0],a,this.Fr.neg(r[1]),this.Fr.neg(i[1]),this.Fr.zero,this.Fr.one,this.Fr.zero);t.push(s),n.push([r[0],i[0],r[1],i[1]]),o.push([a,this.Fr.one])}for(let e=0;ethis.n-1)throw Error(`CPolynomial:addPolynomial, cannot add a polynomial to a position greater than n-1`);this.polynomials[e]=t}degree(){let e=this.polynomials.map((e,t)=>e===void 0?0:e.degree()*this.n+t);return Math.max(...e)}getPolynomial(){let e=this.polynomials.map(e=>e===void 0?0:e.degree()),t=this.degree(),r=2**(ye(t-1)+1),i=this.Fr.n8,a=new Y(new n.BigBuffer(r*i),this.curve,this.logger);for(let n=0;n Reading PTau file`);let{fd:s,sections:c}=await(0,t.readBinFile)(i,`ptau`,1,1<<22,1<<24);if(!c[12])throw Error(`Powers of Tau is not well prepared. Section 12 missing.`);o&&o.info(`> Getting curve from PTau settings`);let{curve:l}=await K(s,c);o&&o.info(`> Reading r1cs file`);let{fd:u,sections:d}=await(0,t.readBinFile)(e,`r1cs`,1,1<<22,1<<24),f=await(0,r.readR1csFd)(u,d,{loadConstraints:!1,loadCustomGates:!0});if(f.prime!==l.r)throw Error(`r1cs curve does not match powers of tau ceremony curve`);let p=l.Fr,m=l.Fr.n8,h=l.G1.F.n8*2,g=l.G2.F.n8*2,_={},v={},y,b={nVars:f.nVars,nPublic:f.nOutputs+f.nPubInputs},x=new J,S=new J;if(o&&o.info(`> Processing FFlonk constraints`),await k(l.Fr,f,o),globalThis.gc&&globalThis.gc(),b.cirPower=Math.max(3,ye(x.length+2-1)+1),b.domainSize=2**b.cirPower,c[2][0].size<(b.domainSize*9+18)*h)throw Error(`Powers of Tau is not big enough for this circuit size. Section 2 too small.`);if(c[3][0].size computing k1 and k2`);let[C,w]=te();o&&o.info(`> computing w3`);let T=ne();o&&o.info(`> computing w4`);let E=re();o&&o.info(`> computing w8`);let D=ie();o&&o.info(`> computing wr`);let O=ae(b.cirPower,l.Fr);return await A(),await u.close(),await s.close(),o&&o.info(`FFLONK SETUP FINISHED`),0;async function k(e,n,r){for(let t=0;t Writing the zkey file`);let e=await(0,t.createBinFile)(a,`zkey`,1,17,1<<22,1<<24);o&&o.info(`··· Writing Section 1. Zkey Header`),await j(e),o&&o.info(`··· Writing Section 3. Additions`),await M(e),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 4. A Map`),await N(e,4,0,`A map`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 5. B Map`),await N(e,5,1,`B map`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 6. C Map`),await N(e,6,2,`C map`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 7. QL`),await P(e,7,3,`QL`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 8. QR`),await P(e,8,4,`QR`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 9. QM`),await P(e,9,5,`QM`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 10. QO`),await P(e,10,6,`QO`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 11. QC`),await P(e,11,7,`QC`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Sections 12,13,14. Sigma1, Sigma2 & Sigma 3`),await F(e),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 15. Lagrange Polynomials`),await I(e),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 16. Powers of Tau`),await L(e),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 17. C0`),await R(e),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 2. FFlonk Header`),await z(e),globalThis.gc&&globalThis.gc(),o&&o.info(`> Writing the zkey file finished`),await e.close()}async function j(e){await(0,t.startWriteSection)(e,1),await e.writeULE32(10),await(0,t.endWriteSection)(e)}async function M(e){await(0,t.startWriteSection)(e,3);let n=new Uint8Array(8+2*m),r=new DataView(n.buffer);for(let t=0;t=8*b.domainSize)throw Error(`C0 Polynomial is not well calculated`);await(0,t.startWriteSection)(e,17),await e.write(_.C0.coef),await(0,t.endWriteSection)(e)}async function z(e){await(0,t.startWriteSection)(e,2);let r=l.q,i=(Math.floor((n.Scalar.bitLength(r)-1)/64)+1)*8;await e.writeULE32(i),await(0,t.writeBigInt)(e,r,i);let a=l.r,o=(Math.floor((n.Scalar.bitLength(a)-1)/64)+1)*8;await e.writeULE32(o),await(0,t.writeBigInt)(e,a,o),await e.writeULE32(b.nVars),await e.writeULE32(b.nPublic),await e.writeULE32(b.domainSize),await e.writeULE32(S.length),await e.writeULE32(x.length),await e.write(C),await e.write(w),await e.write(T),await e.write(E),await e.write(D),await e.write(O);let u;u=await s.read(g,c[3][0].p+g),await e.write(u);let d=await _.C0.multiExponentiation(y,`C0`);await e.write(d),await(0,t.endWriteSection)(e)}async function ee(e,t){let[n,r]=await Y.to4T(t,b.domainSize,[],p);return await e.write(n),await e.write(r),[n,r]}function te(){let e=p.two;for(;n(e,[],b.cirPower);)p.add(e,p.one);let t=p.add(e,p.one);for(;n(t,[e],b.cirPower);)p.add(t,p.one);return[e,t];function n(e,t,n){let r=2**n,i=p.one;for(let a=0;a Reading witness file`);let{fd:o,sections:s}=await t.readBinFile(r,`wtns`,2,1<<25,1<<23),c=await Qe(o,s);i&&i.info(`> Reading zkey file`);let{fd:l,sections:u}=await t.readBinFile(e,`zkey`,2,1<<25,1<<23),d=await Re(l,u,void 0,a);if(d.protocolId!==10)throw Error(`zkey file is not fflonk`);if(!n.Scalar.eq(d.r,c.q))throw Error(`Curve of the witness does not match the curve of the proving key`);if(c.nWitness!==d.nVars-d.nAdditions)throw Error(`Invalid witness length. Circuit: ${d.nVars}, witness: ${c.nWitness}, ${d.nAdditions}`);let f=d.curve,p=f.Fr,m=f.Fr.n8,h=f.G1.F.n8*2,g=d.domainSize*m;i&&(i.info(`----------------------------`),i.info(` FFLONK PROVE SETTINGS`),i.info(` Curve: ${f.name}`),i.info(` Circuit power: ${d.power}`),i.info(` Domain size: ${d.domainSize}`),i.info(` Vars: ${d.nVars}`),i.info(` Public vars: ${d.nPublic}`),i.info(` Constraints: ${d.nConstraints}`),i.info(` Additions: ${d.nAdditions}`),i.info(`----------------------------`)),i&&i.info(`> Reading witness file data`);let _=await t.readSection(o,s,2);await o.close(),_.set(p.zero,0);let v=new n.BigBuffer(d.nAdditions*m),y={},b={},x={},S={},C={},w={},T=new ir(f,i);i&&i.info(`> Reading Section 3. Additions`),await k(),i&&i.info(`> Reading Sections 12,13,14. Sigma1, Sigma2 & Sigma 3`),i&&i.info(`··· Reading Sigma polynomials `),b.Sigma1=new Y(new n.BigBuffer(g),f,i),b.Sigma2=new Y(new n.BigBuffer(g),f,i),b.Sigma3=new Y(new n.BigBuffer(g),f,i),await l.readToBuffer(b.Sigma1.coef,0,g,u[12][0].p),await l.readToBuffer(b.Sigma2.coef,0,g,u[13][0].p),await l.readToBuffer(b.Sigma3.coef,0,g,u[14][0].p),i&&i.info(`··· Reading Sigma evaluations`),x.Sigma1=new X(new n.BigBuffer(g*4),f,i),x.Sigma2=new X(new n.BigBuffer(g*4),f,i),x.Sigma3=new X(new n.BigBuffer(g*4),f,i),await l.readToBuffer(x.Sigma1.eval,0,g*4,u[12][0].p+g),await l.readToBuffer(x.Sigma2.eval,0,g*4,u[13][0].p+g),await l.readToBuffer(x.Sigma3.eval,0,g*4,u[14][0].p+g),i&&i.info(`> Reading Section 16. Powers of Tau`);let E=new n.BigBuffer(d.domainSize*16*h);await l.readToBuffer(E,0,(d.domainSize*9+18)*h,u[16][0].p),globalThis.gc&&globalThis.gc(),i&&i.info(``),i&&i.info(`> ROUND 1`),await M(),delete b.T0,delete x.QL,delete x.QR,delete x.QM,delete x.QO,delete x.QC,globalThis.gc&&globalThis.gc(),i&&i.info(`> ROUND 2`),await N(),delete y.A,delete y.B,delete y.C,delete x.A,delete x.B,delete x.C,delete x.Sigma1,delete x.Sigma2,delete x.Sigma3,delete x.lagrange1,delete x.Z,globalThis.gc&&globalThis.gc(),i&&i.info(`> ROUND 3`),await P(),delete b.A,delete b.B,delete b.C,delete b.Z,delete b.T1,delete b.T2,delete b.Sigma1,delete b.Sigma2,delete b.Sigma3,delete b.QL,delete b.QR,delete b.QM,delete b.QC,delete b.QO,globalThis.gc&&globalThis.gc(),i&&i.info(`> ROUND 4`),await F(),globalThis.gc&&globalThis.gc(),i&&i.info(`> ROUND 5`),await I(),delete b.C0,delete b.C1,delete b.C2,delete b.R1,delete b.R2,delete b.F,delete b.L,delete b.ZT,delete b.ZTS2,await l.close(),globalThis.gc&&globalThis.gc(),T.addEvaluation(`inv`,L());let D=T.toObjectProof();D.protocol=`fflonk`,D.curve=f.name;let O=[];for(let e=1;e<=d.nPublic;e++){let t=e*m,r=_.slice(t,t+m);O.push(n.Scalar.fromRprLE(r))}return i&&i.info(`FFLONK PROVER FINISHED`),{proof:ai(D),publicSignals:ai(O)};async function k(){i&&i.info(`··· Computing additions`);let e=await t.readSection(l,u,3),n=8+m*2;for(let t=0;t Computing A, B, C wire polynomials`),await r(),i&&i.info(`> Computing T0 polynomial`),await a(),i&&i.info(`> Computing C1 polynomial`),await o(),i&&i.info(`> Computing C1 multi exponentiation`);let e=await b.C1.multiExponentiation(E,`C1`);return T.addPolynomial(`C1`,e),0;async function r(){i&&i.info(`··· Reading data from zkey file`),y.A=new n.BigBuffer(g),y.B=new n.BigBuffer(g),y.C=new n.BigBuffer(g);let e=await t.readSection(l,u,4),r=await t.readSection(l,u,5),a=await t.readSection(l,u,6);for(let t=0;t=d.domainSize)throw Error(`A Polynomial is not well calculated`);if(b.B.degree()>=d.domainSize)throw Error(`B Polynomial is not well calculated`);if(b.C.degree()>=d.domainSize)throw Error(`C Polynomial is not well calculated`)}async function a(){i&&i.info(`··· Reading sections 7, 8, 9, 10, 11. Q selectors`),x.QL=new X(new n.BigBuffer(g*4),f,i),x.QR=new X(new n.BigBuffer(g*4),f,i),x.QM=new X(new n.BigBuffer(g*4),f,i),x.QO=new X(new n.BigBuffer(g*4),f,i),x.QC=new X(new n.BigBuffer(g*4),f,i),await l.readToBuffer(x.QL.eval,0,g*4,u[7][0].p+g),await l.readToBuffer(x.QR.eval,0,g*4,u[8][0].p+g),await l.readToBuffer(x.QM.eval,0,g*4,u[9][0].p+g),await l.readToBuffer(x.QO.eval,0,g*4,u[10][0].p+g),await l.readToBuffer(x.QC.eval,0,g*4,u[11][0].p+g),x.lagrange1=new X(await t.readSection(l,u,15),f,i),y.T0=new n.BigBuffer(g*4),i&&i.info(`··· Computing T0 evaluations`);for(let e=0;e=2*d.domainSize-2)throw Error(`T0 Polynomial is not well calculated (degree is ${b.T0.degree()} and must be less than ${2*d.domainSize+2}`);delete y.T0}async function o(){let e=new ri(4,f,i);if(e.addPolynomial(0,b.A),e.addPolynomial(1,b.B),e.addPolynomial(2,b.C),e.addPolynomial(3,b.T0),b.C1=e.getPolynomial(),b.C1.degree()>=8*d.domainSize-8)throw Error(`C1 Polynomial is not well calculated`)}}async function N(){i&&i.info(`> Computing challenges beta and gamma`);let e=new wr(f);e.addPolCommitment(d.C0);for(let t=0;t Computing Z polynomial`),await r(),i&&i.info(`> Computing T1 polynomial`),await a(),i&&i.info(`> Computing T2 polynomial`),await o(),i&&i.info(`> Computing C2 polynomial`),await s(),i&&i.info(`> Computing C2 multi exponentiation`);let t=await b.C2.multiExponentiation(E,`C2`);return T.addPolynomial(`C2`,t),0;async function r(){i&&i.info(`··· Computing Z evaluations`);let e=new n.BigBuffer(g),t=new n.BigBuffer(g);e.set(p.one,0),t.set(p.one,0);let r=p.one;for(let n=0;n=d.domainSize+3)throw Error(`Z Polynomial is not well calculated`);delete y.Z}async function a(){i&&i.info(`··· Computing T1 evaluations`),y.T1=new n.BigBuffer(g*2),y.T1z=new n.BigBuffer(g*2);let e=p.one;for(let t=0;t=d.domainSize+2)throw Error(`T1 Polynomial is not well calculated`);delete y.T1,delete y.T1z,delete b.T1z}async function o(){i&&i.info(`··· Computing T2 evaluations`),y.T2=new n.BigBuffer(g*4),y.T2z=new n.BigBuffer(g*4);let e=p.one;for(let t=0;t=3*d.domainSize)throw Error(`T2 Polynomial is not well calculated`);delete y.T2,delete y.T2z,delete b.T2z}async function s(){let e=new ri(3,f,i);if(e.addPolynomial(0,b.Z),e.addPolynomial(1,b.T1),e.addPolynomial(2,b.T2),b.C2=e.getPolynomial(),b.C2.degree()>=9*d.domainSize)throw Error(`C2 Polynomial is not well calculated`)}}async function P(){i&&i.info(`> Computing challenge xi`);let e=new wr(f);e.addScalar(C.gamma),e.addPolCommitment(T.getPolynomial(`C2`)),C.xiSeed=e.getChallenge();let t=p.square(C.xiSeed);w.w8=[],w.w8[0]=p.one;for(let e=1;e<8;e++)w.w8[e]=p.mul(w.w8[e-1],d.w8);w.w4=[],w.w4[0]=p.one;for(let e=1;e<4;e++)w.w4[e]=p.mul(w.w4[e-1],d.w4);w.w3=[],w.w3[0]=p.one,w.w3[1]=d.w3,w.w3[2]=p.square(d.w3),w.S0={},w.S0.h0w8=[],w.S0.h0w8[0]=p.mul(t,C.xiSeed);for(let e=1;e<8;e++)w.S0.h0w8[e]=p.mul(w.S0.h0w8[0],w.w8[e]);w.S1={},w.S1.h1w4=[],w.S1.h1w4[0]=p.square(w.S0.h0w8[0]);for(let e=1;e<4;e++)w.S1.h1w4[e]=p.mul(w.S1.h1w4[0],w.w4[e]);w.S2={},w.S2.h2w3=[],w.S2.h2w3[0]=p.mul(w.S1.h1w4[0],t),w.S2.h2w3[1]=p.mul(w.S2.h2w3[0],w.w3[1]),w.S2.h2w3[2]=p.mul(w.S2.h2w3[0],w.w3[2]),w.S2.h3w3=[],w.S2.h3w3[0]=p.mul(w.S2.h2w3[0],d.wr),w.S2.h3w3[1]=p.mul(w.S2.h3w3[0],w.w3[1]),w.S2.h3w3[2]=p.mul(w.S2.h3w3[0],w.w3[2]),C.xi=p.mul(p.square(w.S2.h2w3[0]),w.S2.h2w3[0]),i&&i.info(`··· challenges.xi: `+p.toString(C.xi)),b.QL=new Y(new n.BigBuffer(g),f,i),b.QR=new Y(new n.BigBuffer(g),f,i),b.QM=new Y(new n.BigBuffer(g),f,i),b.QO=new Y(new n.BigBuffer(g),f,i),b.QC=new Y(new n.BigBuffer(g),f,i),await l.readToBuffer(b.QL.coef,0,g,u[7][0].p),await l.readToBuffer(b.QR.coef,0,g,u[8][0].p),await l.readToBuffer(b.QM.coef,0,g,u[9][0].p),await l.readToBuffer(b.QO.coef,0,g,u[10][0].p),await l.readToBuffer(b.QC.coef,0,g,u[11][0].p),i&&i.info(`··· Computing evaluations`),T.addEvaluation(`ql`,b.QL.evaluate(C.xi)),T.addEvaluation(`qr`,b.QR.evaluate(C.xi)),T.addEvaluation(`qm`,b.QM.evaluate(C.xi)),T.addEvaluation(`qo`,b.QO.evaluate(C.xi)),T.addEvaluation(`qc`,b.QC.evaluate(C.xi)),T.addEvaluation(`s1`,b.Sigma1.evaluate(C.xi)),T.addEvaluation(`s2`,b.Sigma2.evaluate(C.xi)),T.addEvaluation(`s3`,b.Sigma3.evaluate(C.xi)),T.addEvaluation(`a`,b.A.evaluate(C.xi)),T.addEvaluation(`b`,b.B.evaluate(C.xi)),T.addEvaluation(`c`,b.C.evaluate(C.xi)),T.addEvaluation(`z`,b.Z.evaluate(C.xi)),C.xiw=p.mul(C.xi,p.w[d.power]),T.addEvaluation(`zw`,b.Z.evaluate(C.xiw)),T.addEvaluation(`t1w`,b.T1.evaluate(C.xiw)),T.addEvaluation(`t2w`,b.T2.evaluate(C.xiw))}async function F(){i&&i.info(`> Computing challenge alpha`);let e=new wr(f);e.addScalar(C.xiSeed),e.addScalar(T.getEvaluation(`ql`)),e.addScalar(T.getEvaluation(`qr`)),e.addScalar(T.getEvaluation(`qm`)),e.addScalar(T.getEvaluation(`qo`)),e.addScalar(T.getEvaluation(`qc`)),e.addScalar(T.getEvaluation(`s1`)),e.addScalar(T.getEvaluation(`s2`)),e.addScalar(T.getEvaluation(`s3`)),e.addScalar(T.getEvaluation(`a`)),e.addScalar(T.getEvaluation(`b`)),e.addScalar(T.getEvaluation(`c`)),e.addScalar(T.getEvaluation(`z`)),e.addScalar(T.getEvaluation(`zw`)),e.addScalar(T.getEvaluation(`t1w`)),e.addScalar(T.getEvaluation(`t2w`)),C.alpha=e.getChallenge(),i&&i.info(`··· challenges.alpha: `+p.toString(C.alpha)),i&&i.info(`> Reading C0 polynomial`),b.C0=new Y(new n.BigBuffer(g*8),f,i),await l.readToBuffer(b.C0.coef,0,g*8,u[17][0].p),i&&i.info(`> Computing R0 polynomial`),r(),i&&i.info(`> Computing R1 polynomial`),a(),i&&i.info(`> Computing R2 polynomial`),o(),i&&i.info(`> Computing F polynomial`),await s(),i&&i.info(`> Computing W1 multi exponentiation`);let t=await b.F.multiExponentiation(E,`W1`);return T.addPolynomial(`W1`,t),0;function r(){if(b.R0=Y.lagrangePolynomialInterpolation([w.S0.h0w8[0],w.S0.h0w8[1],w.S0.h0w8[2],w.S0.h0w8[3],w.S0.h0w8[4],w.S0.h0w8[5],w.S0.h0w8[6],w.S0.h0w8[7]],[b.C0.evaluate(w.S0.h0w8[0]),b.C0.evaluate(w.S0.h0w8[1]),b.C0.evaluate(w.S0.h0w8[2]),b.C0.evaluate(w.S0.h0w8[3]),b.C0.evaluate(w.S0.h0w8[4]),b.C0.evaluate(w.S0.h0w8[5]),b.C0.evaluate(w.S0.h0w8[6]),b.C0.evaluate(w.S0.h0w8[7])],f),b.R0.degree()>7)throw Error(`R0 Polynomial is not well calculated`)}function a(){if(b.R1=Y.lagrangePolynomialInterpolation([w.S1.h1w4[0],w.S1.h1w4[1],w.S1.h1w4[2],w.S1.h1w4[3]],[b.C1.evaluate(w.S1.h1w4[0]),b.C1.evaluate(w.S1.h1w4[1]),b.C1.evaluate(w.S1.h1w4[2]),b.C1.evaluate(w.S1.h1w4[3])],f),b.R1.degree()>3)throw Error(`R1 Polynomial is not well calculated`)}function o(){if(b.R2=Y.lagrangePolynomialInterpolation([w.S2.h2w3[0],w.S2.h2w3[1],w.S2.h2w3[2],w.S2.h3w3[0],w.S2.h3w3[1],w.S2.h3w3[2]],[b.C2.evaluate(w.S2.h2w3[0]),b.C2.evaluate(w.S2.h2w3[1]),b.C2.evaluate(w.S2.h2w3[2]),b.C2.evaluate(w.S2.h3w3[0]),b.C2.evaluate(w.S2.h3w3[1]),b.C2.evaluate(w.S2.h3w3[2])],f),b.R2.degree()>5)throw Error(`R2 Polynomial is not well calculated`)}async function s(){i&&i.info(`··· Computing F polynomial`),b.F=Y.fromPolynomial(b.C0,f,i),b.F.sub(b.R0),b.F.divByZerofier(8,C.xi);let e=Y.fromPolynomial(b.C1,f,i);e.sub(b.R1),e.mulScalar(C.alpha),e.divByZerofier(4,C.xi);let t=Y.fromPolynomial(b.C2,f,i);if(t.sub(b.R2),t.mulScalar(p.square(C.alpha)),t.divByZerofier(3,C.xi),t.divByZerofier(3,C.xiw),b.F.add(e),b.F.add(t),b.F.degree()>=9*d.domainSize-6)throw Error(`F Polynomial is not well calculated`)}}async function I(){i&&i.info(`> Computing challenge y`);let e=new wr(f);e.addScalar(C.alpha),e.addPolCommitment(T.getPolynomial(`W1`)),C.y=e.getChallenge(),i&&i.info(`··· challenges.y: `+p.toString(C.y)),i&&i.info(`> Computing L polynomial`),await o(),i&&i.info(`> Computing ZTS2 polynomial`),await c();let t=b.ZTS2.evaluate(C.y);t=p.inv(t),b.L.mulScalar(t);let n=Y.fromCoefficientsArray([p.neg(C.y),p.one],f);i&&i.info(`> Computing W' = L / ZTS2 polynomial`);let r=b.L.divBy(n);if(r.degree()>0)throw Error(`Degree of L(X)/(ZTS2(y)(X-y)) remainder is ${r.degree()} and should be 0`);if(b.L.degree()>=9*d.domainSize-1)throw Error(`Degree of L(X)/(ZTS2(y)(X-y)) is not correct`);i&&i.info(`> Computing W' multi exponentiation`);let a=await b.L.multiExponentiation(E,`W2`);return T.addPolynomial(`W2`,a),0;async function o(){i&&i.info(`··· Computing L polynomial`);let e=b.R0.evaluate(C.y),t=b.R1.evaluate(C.y),n=b.R2.evaluate(C.y),r=p.sub(C.y,w.S0.h0w8[0]);for(let e=1;e<8;e++)r=p.mul(r,p.sub(C.y,w.S0.h0w8[e]));let a=p.sub(C.y,w.S1.h1w4[0]);for(let e=1;e<4;e++)a=p.mul(a,p.sub(C.y,w.S1.h1w4[e]));let o=p.sub(C.y,w.S2.h2w3[0]);for(let e=1;e<3;e++)o=p.mul(o,p.sub(C.y,w.S2.h2w3[e]));for(let e=0;e<3;e++)o=p.mul(o,p.sub(C.y,w.S2.h3w3[e]));let c=p.mul(a,o),l=p.mul(C.alpha,p.mul(r,o)),u=p.mul(p.square(C.alpha),p.mul(r,a));S.denH1=a,S.denH2=o,b.L=Y.fromPolynomial(b.C0,f,i),b.L.subScalar(e),b.L.mulScalar(c);let m=Y.fromPolynomial(b.C1,f,i);m.subScalar(t),m.mulScalar(l);let h=Y.fromPolynomial(b.C2,f,i);h.subScalar(n),h.mulScalar(u),b.L.add(m),b.L.add(h),i&&i.info(`> Computing ZT polynomial`),await s();let g=b.ZT.evaluate(C.y);if(b.F.mulScalar(g),b.L.sub(b.F),b.L.degree()>=9*d.domainSize)throw Error(`L Polynomial is not well calculated`);delete y.L}async function s(){b.ZT=Y.zerofierPolynomial([w.S0.h0w8[0],w.S0.h0w8[1],w.S0.h0w8[2],w.S0.h0w8[3],w.S0.h0w8[4],w.S0.h0w8[5],w.S0.h0w8[6],w.S0.h0w8[7],w.S1.h1w4[0],w.S1.h1w4[1],w.S1.h1w4[2],w.S1.h1w4[3],w.S2.h2w3[0],w.S2.h2w3[1],w.S2.h2w3[2],w.S2.h3w3[0],w.S2.h3w3[1],w.S2.h3w3[2]],f)}async function c(){b.ZTS2=Y.zerofierPolynomial([w.S1.h1w4[0],w.S1.h1w4[1],w.S1.h1w4[2],w.S1.h1w4[3],w.S2.h2w3[0],w.S2.h2w3[1],w.S2.h2w3[2],w.S2.h3w3[0],w.S2.h3w3[1],w.S2.h3w3[2]],f)}}function L(){let e=C.xi;for(let t=0;t Checking commitments belong to G1`),!fi(i,o,a))return r&&r.error(`Proof commitments are not valid`),!1;if(r&&r.info(`> Checking evaluations belong to F`),!mi(i,o))return r&&r.error(`Proof evaluations are not valid.`),!1;if(r&&r.info(`> Checking public inputs belong to F`),!hi(i,s))return r&&r.error(`Public inputs are not valid.`),!1;r&&r.info(`> Computing challenges`);let{challenges:l,roots:u}=gi(i,o,a,s,r);r&&r.info(`> Computing Zero polynomial evaluation Z_H(xi)`),l.zh=c.sub(l.xiN,c.one),l.invzh=c.inv(l.zh),r&&r.info(`> Computing Lagrange evaluations`);let d=await _i(i,l,a);r&&r.info(`> Computing polynomial identities PI(X)`);let f=vi(i,s,d);r&&r.info(`> Computing r0(y)`);let p=yi(o,l,u,i,r);r&&r.info(`> Computing r1(y)`);let m=bi(o,l,u,f,i,r);r&&r.info(`> Computing r2(y)`);let h=xi(o,l,u,d[1],a,i,r);r&&r.info(`> Computing F`);let g=Si(i,o,a,l,u);r&&r.info(`> Computing E`);let _=Ci(i,o,l,a,p,m,h);r&&r.info(`> Computing J`);let v=wi(i,o,l);r&&r.info(`> Validate all evaluations with a pairing`);let y=await Ti(i,o,l,a,g,_,v);return r&&(y?r.info(`PROOF VERIFIED SUCCESSFULLY`):r.warn(`Invalid Proof`)),r&&r.info(`FFLONK VERIFIER FINISHED`),y}function di(e,t){let n=t;return n.k1=e.Fr.fromObject(t.k1),n.k2=e.Fr.fromObject(t.k2),n.w=e.Fr.fromObject(t.w),n.w3=e.Fr.fromObject(t.w3),n.w4=e.Fr.fromObject(t.w4),n.w8=e.Fr.fromObject(t.w8),n.wr=e.Fr.fromObject(t.wr),n.X_2=e.G2.fromObject(t.X_2),n.C0=e.G1.fromObject(t.C0),n}function fi(e,t,n){let r=e.G1;return r.isValid(t.polynomials.C1)&&r.isValid(t.polynomials.C2)&&r.isValid(t.polynomials.W1)&&r.isValid(t.polynomials.W2)&&r.isValid(n.C0)}function pi(e,t){return n.Scalar.geq(t,0)&&n.Scalar.lt(t,e.r)}function Q(e,t){return pi(e,n.Scalar.fromRprLE(t))}function mi(e,t){return Q(e,t.evaluations.ql)&&Q(e,t.evaluations.qr)&&Q(e,t.evaluations.qm)&&Q(e,t.evaluations.qo)&&Q(e,t.evaluations.qc)&&Q(e,t.evaluations.s1)&&Q(e,t.evaluations.s2)&&Q(e,t.evaluations.s3)&&Q(e,t.evaluations.a)&&Q(e,t.evaluations.b)&&Q(e,t.evaluations.c)&&Q(e,t.evaluations.z)&&Q(e,t.evaluations.zw)&&Q(e,t.evaluations.t1w)&&Q(e,t.evaluations.t2w)}function hi(e,t){for(let n=0;nki,exportSolidityVerifier:()=>null,fullProve:()=>ci,prove:()=>oi,setup:()=>ii,verify:()=>ui});return Object.defineProperty(e,"curves",{enumerable:!0,get:function(){return p}}),Object.defineProperty(e,"fflonk",{enumerable:!0,get:function(){return Ai}}),Object.defineProperty(e,"groth16",{enumerable:!0,get:function(){return Jt}}),Object.defineProperty(e,"plonk",{enumerable:!0,get:function(){return Yr}}),Object.defineProperty(e,"powersOfTau",{enumerable:!0,get:function(){return Tn}}),Object.defineProperty(e,"r1cs",{enumerable:!0,get:function(){return jn}}),Object.defineProperty(e,"wtns",{enumerable:!0,get:function(){return Ln}}),Object.defineProperty(e,"zKey",{enumerable:!0,get:function(){return nr}}),e})({},_iden3_binfileutils,ffjavascript,r1csfile); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 50188892..3a3a8110 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52,9 +52,9 @@ "license": "MIT" }, "node_modules/@emnapi/core": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", - "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", "dev": true, "license": "MIT", "optional": true, @@ -65,9 +65,9 @@ } }, "node_modules/@emnapi/runtime": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", - "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", "dev": true, "license": "MIT", "optional": true, @@ -88,9 +88,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", - "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz", + "integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==", "cpu": [ "ppc64" ], @@ -105,9 +105,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", - "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.0.tgz", + "integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==", "cpu": [ "arm" ], @@ -122,9 +122,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", - "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz", + "integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==", "cpu": [ "arm64" ], @@ -139,9 +139,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", - "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.0.tgz", + "integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==", "cpu": [ "x64" ], @@ -156,9 +156,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", - "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz", + "integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==", "cpu": [ "arm64" ], @@ -173,9 +173,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", - "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz", + "integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==", "cpu": [ "x64" ], @@ -190,9 +190,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", - "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz", + "integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==", "cpu": [ "arm64" ], @@ -207,9 +207,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", - "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz", + "integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==", "cpu": [ "x64" ], @@ -224,9 +224,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", - "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz", + "integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==", "cpu": [ "arm" ], @@ -241,9 +241,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", - "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz", + "integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==", "cpu": [ "arm64" ], @@ -258,9 +258,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", - "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz", + "integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==", "cpu": [ "ia32" ], @@ -275,9 +275,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", - "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz", + "integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==", "cpu": [ "loong64" ], @@ -292,9 +292,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", - "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz", + "integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==", "cpu": [ "mips64el" ], @@ -309,9 +309,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", - "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz", + "integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==", "cpu": [ "ppc64" ], @@ -326,9 +326,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", - "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz", + "integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==", "cpu": [ "riscv64" ], @@ -343,9 +343,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", - "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz", + "integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==", "cpu": [ "s390x" ], @@ -360,9 +360,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", - "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz", + "integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==", "cpu": [ "x64" ], @@ -377,9 +377,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", - "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz", + "integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==", "cpu": [ "arm64" ], @@ -394,9 +394,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", - "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz", + "integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==", "cpu": [ "x64" ], @@ -411,9 +411,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", - "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz", + "integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==", "cpu": [ "arm64" ], @@ -428,9 +428,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", - "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz", + "integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==", "cpu": [ "x64" ], @@ -445,9 +445,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", - "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz", + "integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==", "cpu": [ "arm64" ], @@ -462,9 +462,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", - "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz", + "integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==", "cpu": [ "x64" ], @@ -479,9 +479,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", - "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz", + "integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==", "cpu": [ "arm64" ], @@ -496,9 +496,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", - "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz", + "integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==", "cpu": [ "ia32" ], @@ -513,9 +513,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", - "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz", + "integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==", "cpu": [ "x64" ], @@ -587,9 +587,9 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.5.tgz", - "integrity": "sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.6.0.tgz", + "integrity": "sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -644,9 +644,9 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.1.tgz", - "integrity": "sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz", + "integrity": "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -658,29 +658,43 @@ } }, "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", "dev": true, "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, "engines": { "node": ">=18.18.0" } }, "node_modules/@humanfs/node": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", - "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@humanfs/core": "^0.19.1", + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", "@humanwhocodes/retry": "^0.4.0" }, "engines": { "node": ">=18.18.0" } }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -717,7 +731,7 @@ }, "node_modules/@iden3/binfileutils": { "version": "0.0.12", - "resolved": "git+ssh://git@github.com/iden3/binfileutils.git#c0de22052590168d7c28fee62dc4042bac4c96bf", + "resolved": "git+ssh://git@github.com/iden3/binfileutils.git#9c3b84283b47d1a7655e6ff6b6d45cdc337a2c20", "license": "GPL-3.0", "dependencies": { "fastfile": "https://github.com/iden3/fastfile.git#feat/esm-migration", @@ -732,9 +746,9 @@ "license": "MIT" }, "node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.3.tgz", - "integrity": "sha512-xK9sGVbJWYb08+mTJt3/YV24WxvxpXcXtP6B172paPZ+Ts69Re9dAr7lKwJoeIx8OoeuimEiRZ7umkiUVClmmQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", + "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", "dev": true, "license": "MIT", "optional": true, @@ -789,28 +803,28 @@ } }, "node_modules/@nomicfoundation/edr": { - "version": "0.12.0-next.29", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.12.0-next.29.tgz", - "integrity": "sha512-/c1LbBC3EFgOIKRup0lQ2SIqL9MLdqdOHDM9Mta5CyDOk9cQFlBSTpWCGDrh+p1BIsPFpVHqa4yjkBmZyL1aZA==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.12.0.tgz", + "integrity": "sha512-dVfrB70L//W05s+s+/c6n52Fct+kVKoXYT+/CKL9ZsNdq/yLr5LaPNsvpVkQHP1JdAiOrubUzA/MwZIk4gRxAQ==", "dev": true, "license": "MIT", "dependencies": { - "@nomicfoundation/edr-darwin-arm64": "0.12.0-next.29", - "@nomicfoundation/edr-darwin-x64": "0.12.0-next.29", - "@nomicfoundation/edr-linux-arm64-gnu": "0.12.0-next.29", - "@nomicfoundation/edr-linux-arm64-musl": "0.12.0-next.29", - "@nomicfoundation/edr-linux-x64-gnu": "0.12.0-next.29", - "@nomicfoundation/edr-linux-x64-musl": "0.12.0-next.29", - "@nomicfoundation/edr-win32-x64-msvc": "0.12.0-next.29" + "@nomicfoundation/edr-darwin-arm64": "0.12.0", + "@nomicfoundation/edr-darwin-x64": "0.12.0", + "@nomicfoundation/edr-linux-arm64-gnu": "0.12.0", + "@nomicfoundation/edr-linux-arm64-musl": "0.12.0", + "@nomicfoundation/edr-linux-x64-gnu": "0.12.0", + "@nomicfoundation/edr-linux-x64-musl": "0.12.0", + "@nomicfoundation/edr-win32-x64-msvc": "0.12.0" }, "engines": { "node": ">= 20" } }, "node_modules/@nomicfoundation/edr-darwin-arm64": { - "version": "0.12.0-next.29", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.12.0-next.29.tgz", - "integrity": "sha512-qzVcAkUsrVT2Za9pLzTYL/eNLS09R+JSG+4LpQ56Wg3mkjbwItn/F6C/XbGqMbNiEGfLi5kVvtYOtT7yu04/Tg==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.12.0.tgz", + "integrity": "sha512-z/8jU2dgZjhY2iLtJ1DGi3t/N2xbmjgok9K3R0f7+UZxSSJ5LbXCFn5So33fVh47RzGzOqEB+Yk4SdyUq2odqw==", "dev": true, "license": "MIT", "engines": { @@ -818,9 +832,9 @@ } }, "node_modules/@nomicfoundation/edr-darwin-x64": { - "version": "0.12.0-next.29", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.12.0-next.29.tgz", - "integrity": "sha512-P2BSYLsDoM1dGi/0NO3ps3l76NbvFDAnmCUS5SLLLdG/b8RUvWKHtfZFrQgy1KCPDFiiG5IlwzcmAwsPjsyOVQ==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.12.0.tgz", + "integrity": "sha512-F9RrA60mEtxfKFiGB7QsydoUwzz4ckoustVMFegcIKmjRxRVb1qrRYiAc9oQiKMdJWIZKDYsOpHABJ9Um4U/+g==", "dev": true, "license": "MIT", "engines": { @@ -828,9 +842,9 @@ } }, "node_modules/@nomicfoundation/edr-linux-arm64-gnu": { - "version": "0.12.0-next.29", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.12.0-next.29.tgz", - "integrity": "sha512-3SKZIaZCCuY6fAHj6GpTYpQPj3S0LFO6YUUZw3aSg1joBmM9FkP9a1IiYQOBZnZqk0Fa+pHy2dHMVWDczQHX7g==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.12.0.tgz", + "integrity": "sha512-EtGRZbh1d4BF/1SIG5rVrKQ9R0nuNvPgCYiU5fCmY3bojAFOUf4m7I2ezIhim1vb1QBlXmFaoFNPZFIdMltBGA==", "dev": true, "license": "MIT", "engines": { @@ -838,9 +852,9 @@ } }, "node_modules/@nomicfoundation/edr-linux-arm64-musl": { - "version": "0.12.0-next.29", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.12.0-next.29.tgz", - "integrity": "sha512-GGDJX3We8+XQ0L1Yy2i6ulbucQPO7HpQ5IYkxFLKL0H611ErErHLawrGIvfcfaDYfnFrC/3uxWEqMQ4GhrWbBQ==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.12.0.tgz", + "integrity": "sha512-5gWtmKuVfftcO1OUbF/3KTPVSR6klC7RI9Z96G5lDO325jQhYqOG+hkvDPKtM+nbYf+A0veOndghqbUgAX+E4A==", "dev": true, "license": "MIT", "engines": { @@ -848,9 +862,9 @@ } }, "node_modules/@nomicfoundation/edr-linux-x64-gnu": { - "version": "0.12.0-next.29", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.12.0-next.29.tgz", - "integrity": "sha512-d92L55iy/EzMlu341RgFG1Pqd6Mpd1MmcYi48Na2VtMs7rqRIcAUGeLgoooScLinM5JqTIb1uYVghehFrx98gA==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.12.0.tgz", + "integrity": "sha512-0Ty0fov3/NFL0dIshNTGCi06sjVzsgB7k+n9LAoj+57OsqP9X4e3P5XwjlTSNuyYshv8JdYMHqY+1ZIZ8SHsyQ==", "dev": true, "license": "MIT", "engines": { @@ -858,9 +872,9 @@ } }, "node_modules/@nomicfoundation/edr-linux-x64-musl": { - "version": "0.12.0-next.29", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.12.0-next.29.tgz", - "integrity": "sha512-oOupaxyR6KUzvhJ0zsVU0yfeepB3hcTKxvowq2lPPwp6cMFzPY8PFe6uck+7+rXwog0dDkEa4R/RPEE9DtUelw==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.12.0.tgz", + "integrity": "sha512-e5du3t17vdB3tAY0kl3Ip1cu8CcwiaeJeUC4mMPmL91HDM//AQehqpyIP8upam4AeIl1H6FA3xIUIDA6VOZSxg==", "dev": true, "license": "MIT", "engines": { @@ -868,9 +882,9 @@ } }, "node_modules/@nomicfoundation/edr-win32-x64-msvc": { - "version": "0.12.0-next.29", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.12.0-next.29.tgz", - "integrity": "sha512-QWvz4tTt1Z5JYKXODtqqdxfIQMiWFPGLVIeVJlXl2HSPJAIWTMU+EiBhlGGxP0qoUotUbdJbe7lpG4gw3yKIcA==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.12.0.tgz", + "integrity": "sha512-wD8YxhFdlY2IXb7uVrSF7VHartFKXEYeiE6ISJOV10Y7YOUE1IzfwB0QOdKtLUepwB+HXis+KRy4h22dWEbT0A==", "dev": true, "license": "MIT", "engines": { @@ -878,41 +892,39 @@ } }, "node_modules/@nomicfoundation/hardhat-errors": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-errors/-/hardhat-errors-3.0.10.tgz", - "integrity": "sha512-jfQ75/t21674cIQPbQmzRSY8YdusvQhKMsT+IGEoXlJuAzw+ngWsD7y7nHT8UKQ+liHWgMA+Am2843KwP0KtiA==", + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-errors/-/hardhat-errors-3.0.15.tgz", + "integrity": "sha512-h3r32RzpmWEcB2bz6aqZKlKOP8tzyvHLkPFleFFqwVvjO5AUfSoMUxm8OjaTuNgPF35mXPYRISh+kNCwmsKVOA==", "dev": true, "license": "MIT", "dependencies": { - "@nomicfoundation/hardhat-utils": "^4.0.2" + "@nomicfoundation/hardhat-utils": "^4.1.3" } }, "node_modules/@nomicfoundation/hardhat-ethers": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-4.0.7.tgz", - "integrity": "sha512-7wT4/ikhnL44fzJpe4Bh+bnsuWN55P02rbULCvhmcOOCbh/vouIrfVd008Te4+gwx+rYmJtL92vthj/I9dUd0g==", + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-4.0.13.tgz", + "integrity": "sha512-HBiWoMFf7tLr1X3T82mKHXUSEuHU7PVUibWmfP6gSn5l38RQbcrt/f64zoNbyHh6pdiC7WwQPJHP3bCAfbd2oA==", "dev": true, "license": "MIT", "dependencies": { - "@nomicfoundation/hardhat-errors": "^3.0.10", - "@nomicfoundation/hardhat-utils": "^4.0.2", - "debug": "^4.3.2", + "@nomicfoundation/hardhat-errors": "^3.0.15", + "@nomicfoundation/hardhat-utils": "^4.1.2", "ethereum-cryptography": "^2.2.1", "ethers": "^6.14.0" }, "peerDependencies": { - "hardhat": "^3.1.11" + "hardhat": "^3.8.0" } }, "node_modules/@nomicfoundation/hardhat-utils": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-utils/-/hardhat-utils-4.0.2.tgz", - "integrity": "sha512-6lK0+9ygB7wGDlu11DAmTuZxhnoGbyGZC2aRaKKehW0vDNTS9iT7GUimgVvlO3B23E/HwwRKOOLmSVPC4qmmQw==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-utils/-/hardhat-utils-4.1.3.tgz", + "integrity": "sha512-SYDKX6SCdzs/5mC/S1D+AjNSQJrhxevHTI24TIouIjO0Xs0dB0+S4cYCqHWOgvnHLshrcrJ7XGUjS7+apWa1Tw==", "dev": true, "license": "MIT", "dependencies": { "@streamparser/json-node": "^0.0.22", - "debug": "^4.3.2", "env-paths": "^2.2.0", "ethereum-cryptography": "^2.2.1", "fast-equals": "^5.4.0", @@ -922,21 +934,21 @@ } }, "node_modules/@nomicfoundation/hardhat-vendored": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-vendored/-/hardhat-vendored-3.0.1.tgz", - "integrity": "sha512-jBOAqmEAMJ8zdfiQmTLV+c0IaSyySqkDSJ9spTy8Ts/m/mO8w364TClyfn+p4ZpxBjyX4LMa3NfC402hoDtwCg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-vendored/-/hardhat-vendored-3.0.4.tgz", + "integrity": "sha512-RO8Otj1FvRvxJmXzkxh1vTwK/+cqSVPYLqY6RrWkmzHEEcxnAwAFsBYdW7xyTEyW/pVbSSNd2gs3aoGdGZaoNA==", "dev": true, "license": "MIT" }, "node_modules/@nomicfoundation/hardhat-zod-utils": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-zod-utils/-/hardhat-zod-utils-3.0.3.tgz", - "integrity": "sha512-WER4/UKLpm7/nz1asvNR7EKZKKBW+48Hw7GOdcd3Rhdr3VTNuTaeIxCJpl6YxTTg+Eq/sPAWX0mr25+USs6KWw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-zod-utils/-/hardhat-zod-utils-3.0.5.tgz", + "integrity": "sha512-A1G9Jcizf/vYcGMtqkf+st94zBPTDB+bXXlojOMu77gmBZYbywY0k7hdRM2B4uJY+8nM0oe0sNVGVkARITXdcw==", "dev": true, "license": "MIT", "dependencies": { - "@nomicfoundation/hardhat-errors": "^3.0.7", - "@nomicfoundation/hardhat-utils": "^4.0.0" + "@nomicfoundation/hardhat-errors": "^3.0.13", + "@nomicfoundation/hardhat-utils": "^4.1.2" }, "peerDependencies": { "zod": "^3.23.8" @@ -1039,9 +1051,9 @@ } }, "node_modules/@oxc-project/types": { - "version": "0.124.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.124.0.tgz", - "integrity": "sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==", + "version": "0.133.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.133.0.tgz", + "integrity": "sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==", "dev": true, "license": "MIT", "funding": { @@ -1056,9 +1068,9 @@ "license": "MIT" }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.15.tgz", - "integrity": "sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.3.tgz", + "integrity": "sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==", "cpu": [ "arm64" ], @@ -1073,9 +1085,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.15.tgz", - "integrity": "sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.3.tgz", + "integrity": "sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==", "cpu": [ "arm64" ], @@ -1090,9 +1102,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.15.tgz", - "integrity": "sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.3.tgz", + "integrity": "sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==", "cpu": [ "x64" ], @@ -1107,9 +1119,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.15.tgz", - "integrity": "sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.3.tgz", + "integrity": "sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==", "cpu": [ "x64" ], @@ -1124,9 +1136,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.15.tgz", - "integrity": "sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.3.tgz", + "integrity": "sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==", "cpu": [ "arm" ], @@ -1141,9 +1153,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.15.tgz", - "integrity": "sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.3.tgz", + "integrity": "sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==", "cpu": [ "arm64" ], @@ -1158,9 +1170,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.15.tgz", - "integrity": "sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.3.tgz", + "integrity": "sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==", "cpu": [ "arm64" ], @@ -1175,9 +1187,9 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.15.tgz", - "integrity": "sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.3.tgz", + "integrity": "sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==", "cpu": [ "ppc64" ], @@ -1192,9 +1204,9 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.15.tgz", - "integrity": "sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.3.tgz", + "integrity": "sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==", "cpu": [ "s390x" ], @@ -1209,9 +1221,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.15.tgz", - "integrity": "sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.3.tgz", + "integrity": "sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==", "cpu": [ "x64" ], @@ -1226,9 +1238,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.15.tgz", - "integrity": "sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.3.tgz", + "integrity": "sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==", "cpu": [ "x64" ], @@ -1243,9 +1255,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.15.tgz", - "integrity": "sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.3.tgz", + "integrity": "sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==", "cpu": [ "arm64" ], @@ -1260,9 +1272,9 @@ } }, "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.15.tgz", - "integrity": "sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.3.tgz", + "integrity": "sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==", "cpu": [ "wasm32" ], @@ -1270,18 +1282,18 @@ "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "1.9.2", - "@emnapi/runtime": "1.9.2", - "@napi-rs/wasm-runtime": "^1.1.3" + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" }, "engines": { - "node": ">=14.0.0" + "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.15.tgz", - "integrity": "sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.3.tgz", + "integrity": "sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==", "cpu": [ "arm64" ], @@ -1296,9 +1308,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.15.tgz", - "integrity": "sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.3.tgz", + "integrity": "sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==", "cpu": [ "x64" ], @@ -1313,9 +1325,9 @@ } }, "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.15.tgz", - "integrity": "sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", "dev": true, "license": "MIT" }, @@ -1419,9 +1431,9 @@ } }, "node_modules/@tybys/wasm-util": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", - "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", + "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", "dev": true, "license": "MIT", "optional": true, @@ -1455,9 +1467,9 @@ "license": "MIT" }, "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "dev": true, "license": "MIT" }, @@ -1469,27 +1481,27 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "25.6.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.0.tgz", - "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==", + "version": "25.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz", + "integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==", "dev": true, "license": "MIT", "optional": true, "peer": true, "dependencies": { - "undici-types": "~7.19.0" + "undici-types": ">=7.24.0 <7.24.7" } }, "node_modules/@vitest/browser": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-4.1.4.tgz", - "integrity": "sha512-TrNaY/yVOwxtrxNsDUC/wQ56xSwplpytTeRAqF/197xV/ZddxxulBsxR6TrhVMyniJmp9in8d5u0AcDaNRY30w==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-4.1.8.tgz", + "integrity": "sha512-u21VzX07HzlJYpFgkxmjEXar/tG2UqWGgyGG/46SrrPc7rSdCTPw5vuowopO9CIqF8UCUQzDFdbVnNpw6N0BfQ==", "dev": true, "license": "MIT", "dependencies": { "@blazediff/core": "1.9.1", - "@vitest/mocker": "4.1.4", - "@vitest/utils": "4.1.4", + "@vitest/mocker": "4.1.8", + "@vitest/utils": "4.1.8", "magic-string": "^0.30.21", "pngjs": "^7.0.0", "sirv": "^3.0.2", @@ -1500,19 +1512,19 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "4.1.4" + "vitest": "4.1.8" } }, "node_modules/@vitest/browser-playwright": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/browser-playwright/-/browser-playwright-4.1.4.tgz", - "integrity": "sha512-q3PchVhZINX23Pv+RERgAtDlp6wzVkID/smOPnZ5YGWpeWUe3jMNYppeVh15j4il3G7JIJty1d1Kicpm0HSMig==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/browser-playwright/-/browser-playwright-4.1.8.tgz", + "integrity": "sha512-SR7FqgegaexEg73xvf3ArtygXegagMdXnL0EZMpxrWvvhQxvicD/E8p0ib0J91riPRtQUViyh67Xjw3NqvyhVg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@vitest/browser": "4.1.4", - "@vitest/mocker": "4.1.4", + "@vitest/browser": "4.1.8", + "@vitest/mocker": "4.1.8", "tinyrainbow": "^3.1.0" }, "funding": { @@ -1520,7 +1532,7 @@ }, "peerDependencies": { "playwright": "*", - "vitest": "4.1.4" + "vitest": "4.1.8" }, "peerDependenciesMeta": { "playwright": { @@ -1529,16 +1541,16 @@ } }, "node_modules/@vitest/expect": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.4.tgz", - "integrity": "sha512-iPBpra+VDuXmBFI3FMKHSFXp3Gx5HfmSCE8X67Dn+bwephCnQCaB7qWK2ldHa+8ncN8hJU8VTMcxjPpyMkUjww==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.8.tgz", + "integrity": "sha512-h3nDO677RDLEGlBxyQ5CW8RlMThSKSRLUePLOx09gNIWRL40edgA1GCZSZgf1W55MFAG6/Sw14KeaAnqv0NKdQ==", "dev": true, "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", - "@vitest/spy": "4.1.4", - "@vitest/utils": "4.1.4", + "@vitest/spy": "4.1.8", + "@vitest/utils": "4.1.8", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" }, @@ -1547,13 +1559,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.4.tgz", - "integrity": "sha512-R9HTZBhW6yCSGbGQnDnH3QHfJxokKN4KB+Yvk9Q1le7eQNYwiCyKxmLmurSpFy6BzJanSLuEUDrD+j97Q+ZLPg==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.8.tgz", + "integrity": "sha512-LEiN/xe4OSIbKe9HQIp5OC24agGD9J5CnmMgsLohVVoOPWL9a2sBoR6VBx43jQZb7Kr1l4RCuyCJzcAa0+dojw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.1.4", + "@vitest/spy": "4.1.8", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, @@ -1574,9 +1586,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.4.tgz", - "integrity": "sha512-ddmDHU0gjEUyEVLxtZa7xamrpIefdEETu3nZjWtHeZX4QxqJ7tRxSteHVXJOcr8jhiLoGAhkK4WJ3WqBpjx42A==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.8.tgz", + "integrity": "sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA==", "dev": true, "license": "MIT", "dependencies": { @@ -1587,13 +1599,13 @@ } }, "node_modules/@vitest/runner": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.4.tgz", - "integrity": "sha512-xTp7VZ5aXP5ZJrn15UtJUWlx6qXLnGtF6jNxHepdPHpMfz/aVPx+htHtgcAL2mDXJgKhpoo2e9/hVJsIeFbytQ==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.8.tgz", + "integrity": "sha512-EmVxeBAfMJvycdjd6Hm+RbFBbA9fKvo0Kx37hNpBYoYeavH3RNsBXWDooR1mgD52dCrxIIuP7UotpfiwOikvcg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.1.4", + "@vitest/utils": "4.1.8", "pathe": "^2.0.3" }, "funding": { @@ -1601,14 +1613,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.4.tgz", - "integrity": "sha512-MCjCFgaS8aZz+m5nTcEcgk/xhWv0rEH4Yl53PPlMXOZ1/Ka2VcZU6CJ+MgYCZbcJvzGhQRjVrGQNZqkGPttIKw==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.8.tgz", + "integrity": "sha512-acfZboRmAIf05DEKcBQy33VXojFJjtUdLyo7oOmV9kebb2xdU01UknNiPuPZoJZQyO7DF0gZdTGTpeAzET9QPQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.1.4", - "@vitest/utils": "4.1.4", + "@vitest/pretty-format": "4.1.8", + "@vitest/utils": "4.1.8", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, @@ -1617,9 +1629,9 @@ } }, "node_modules/@vitest/spy": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.4.tgz", - "integrity": "sha512-XxNdAsKW7C+FLydqFJLb5KhJtl3PGCMmYwFRfhvIgxJvLSXhhVI1zM8f1qD3Zg7RCjTSzDVyct6sghs9UEgBEQ==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.8.tgz", + "integrity": "sha512-6EevtBp6OZOPF7bmz36HrGMeP3txgVSrgebWxHOafDXGkhIzfXK14f8KF6MuFfgXXUeHxmpD3BQxkV00/3s5mA==", "dev": true, "license": "MIT", "funding": { @@ -1627,13 +1639,13 @@ } }, "node_modules/@vitest/utils": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.4.tgz", - "integrity": "sha512-13QMT+eysM5uVGa1rG4kegGYNp6cnQcsTc67ELFbhNLQO+vgsygtYJx2khvdt4gVQqSSpC/KT5FZZxUpP3Oatw==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.8.tgz", + "integrity": "sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.1.4", + "@vitest/pretty-format": "4.1.8", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" }, @@ -1683,9 +1695,9 @@ "license": "MIT" }, "node_modules/ajv": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", - "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "license": "MIT", "dependencies": { @@ -1755,9 +1767,9 @@ } }, "node_modules/brace-expansion": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", - "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, "license": "MIT", "dependencies": { @@ -1777,19 +1789,6 @@ "node": ">=18" } }, - "node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/check-types": { "version": "11.2.3", "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.3.tgz", @@ -1930,16 +1929,16 @@ } }, "node_modules/es-module-lexer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", - "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", "dev": true, "license": "MIT" }, "node_modules/esbuild": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", - "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz", + "integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -1950,32 +1949,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.7", - "@esbuild/android-arm": "0.27.7", - "@esbuild/android-arm64": "0.27.7", - "@esbuild/android-x64": "0.27.7", - "@esbuild/darwin-arm64": "0.27.7", - "@esbuild/darwin-x64": "0.27.7", - "@esbuild/freebsd-arm64": "0.27.7", - "@esbuild/freebsd-x64": "0.27.7", - "@esbuild/linux-arm": "0.27.7", - "@esbuild/linux-arm64": "0.27.7", - "@esbuild/linux-ia32": "0.27.7", - "@esbuild/linux-loong64": "0.27.7", - "@esbuild/linux-mips64el": "0.27.7", - "@esbuild/linux-ppc64": "0.27.7", - "@esbuild/linux-riscv64": "0.27.7", - "@esbuild/linux-s390x": "0.27.7", - "@esbuild/linux-x64": "0.27.7", - "@esbuild/netbsd-arm64": "0.27.7", - "@esbuild/netbsd-x64": "0.27.7", - "@esbuild/openbsd-arm64": "0.27.7", - "@esbuild/openbsd-x64": "0.27.7", - "@esbuild/openharmony-arm64": "0.27.7", - "@esbuild/sunos-x64": "0.27.7", - "@esbuild/win32-arm64": "0.27.7", - "@esbuild/win32-ia32": "0.27.7", - "@esbuild/win32-x64": "0.27.7" + "@esbuild/aix-ppc64": "0.28.0", + "@esbuild/android-arm": "0.28.0", + "@esbuild/android-arm64": "0.28.0", + "@esbuild/android-x64": "0.28.0", + "@esbuild/darwin-arm64": "0.28.0", + "@esbuild/darwin-x64": "0.28.0", + "@esbuild/freebsd-arm64": "0.28.0", + "@esbuild/freebsd-x64": "0.28.0", + "@esbuild/linux-arm": "0.28.0", + "@esbuild/linux-arm64": "0.28.0", + "@esbuild/linux-ia32": "0.28.0", + "@esbuild/linux-loong64": "0.28.0", + "@esbuild/linux-mips64el": "0.28.0", + "@esbuild/linux-ppc64": "0.28.0", + "@esbuild/linux-riscv64": "0.28.0", + "@esbuild/linux-s390x": "0.28.0", + "@esbuild/linux-x64": "0.28.0", + "@esbuild/netbsd-arm64": "0.28.0", + "@esbuild/netbsd-x64": "0.28.0", + "@esbuild/openbsd-arm64": "0.28.0", + "@esbuild/openbsd-x64": "0.28.0", + "@esbuild/openharmony-arm64": "0.28.0", + "@esbuild/sunos-x64": "0.28.0", + "@esbuild/win32-arm64": "0.28.0", + "@esbuild/win32-ia32": "0.28.0", + "@esbuild/win32-x64": "0.28.0" } }, "node_modules/escape-string-regexp": { @@ -1992,19 +1991,19 @@ } }, "node_modules/eslint": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.2.0.tgz", - "integrity": "sha512-+L0vBFYGIpSNIt/KWTpFonPrqYvgKw1eUI5Vn7mEogrQcWtWYtNQ7dNqC+px/J0idT3BAkiWrhfS7k+Tum8TUA==", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.4.1.tgz", + "integrity": "sha512-AyIKhnOBuOAdueD7RB3xB+YeAWScb9jHsJBgH2Hcde8InP5JYhqrRR6iTMHyTEwgENK54Cp44e4v8BwNhsuHuw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", - "@eslint/config-array": "^0.23.4", - "@eslint/config-helpers": "^0.5.4", - "@eslint/core": "^1.2.0", - "@eslint/plugin-kit": "^0.7.0", + "@eslint/config-array": "^0.23.5", + "@eslint/config-helpers": "^0.6.0", + "@eslint/core": "^1.2.1", + "@eslint/plugin-kit": "^0.7.2", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", @@ -2317,7 +2316,7 @@ }, "node_modules/fastfile": { "version": "0.0.20", - "resolved": "git+ssh://git@github.com/iden3/fastfile.git#60a5733f36bba8063258d30c76e55c746fafae87", + "resolved": "git+ssh://git@github.com/iden3/fastfile.git#972c2763703d488007c444249809d26d5b1487ce", "license": "GPL-3.0" }, "node_modules/fdir": { @@ -2414,19 +2413,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/get-tsconfig": { - "version": "4.13.7", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.7.tgz", - "integrity": "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, "node_modules/glob": { "version": "13.0.6", "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", @@ -2459,9 +2445,9 @@ } }, "node_modules/globals": { - "version": "17.5.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-17.5.0.tgz", - "integrity": "sha512-qoV+HK2yFl/366t2/Cb3+xxPUo5BuMynomoDmiaZBIdbs+0pYbjfZU+twLhGKp4uCZ/+NbtpVepH5bGCxRyy2g==", + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.6.0.tgz", + "integrity": "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==", "dev": true, "license": "MIT", "engines": { @@ -2472,24 +2458,22 @@ } }, "node_modules/hardhat": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-3.3.0.tgz", - "integrity": "sha512-TtejTl3ZeELwlcProbWtnsnPE2wUP2VDxzsTZp/IAgQ277kz3eQtXMpRnacefNmSve/oUAYYHxZtNQEQvaLzHg==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-3.8.0.tgz", + "integrity": "sha512-luWXeLA4dcEoj3QrJhmnf+kRyGn9SrrUN9zf2KlrysXt9U3VIhLYZ8vNIA8HP4fZuvrlKMXHRdLDu0+9Gnmrkg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@nomicfoundation/edr": "0.12.0-next.29", - "@nomicfoundation/hardhat-errors": "^3.0.10", - "@nomicfoundation/hardhat-utils": "^4.0.2", - "@nomicfoundation/hardhat-vendored": "^3.0.1", - "@nomicfoundation/hardhat-zod-utils": "^3.0.3", + "@nomicfoundation/edr": "0.12.0", + "@nomicfoundation/hardhat-errors": "^3.0.15", + "@nomicfoundation/hardhat-utils": "^4.1.3", + "@nomicfoundation/hardhat-vendored": "^3.0.4", + "@nomicfoundation/hardhat-zod-utils": "^3.0.5", "@nomicfoundation/solidity-analyzer": "^0.1.1", "@sentry/core": "^9.4.0", "adm-zip": "^0.4.16", - "chalk": "^5.3.0", "chokidar": "^4.0.3", - "debug": "^4.3.2", "enquirer": "^2.3.0", "ethereum-cryptography": "^2.2.1", "micro-eth-signer": "^0.14.0", @@ -2903,9 +2887,9 @@ "license": "MIT" }, "node_modules/lru-cache": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.3.tgz", - "integrity": "sha512-JvNw9Y81y33E+BEYPr0U7omo+U9AySnsMsEiXgwT6yqd31VQWTLNQqmT4ou5eqPFUrTfIDFta2wKhB1hyohtAQ==", + "version": "11.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz", + "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -3030,9 +3014,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", "dev": true, "funding": [ { @@ -3056,15 +3040,18 @@ "license": "MIT" }, "node_modules/obug": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", - "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.2.tgz", + "integrity": "sha512-AWGB9WFcRXOQs48Z/udjI5ZcZMHXwX8XPByNpOydgcGsDLIzjGizhoMWJyKAWze7AVW/2W1i+/gPX4YtKe5cyg==", "dev": true, "funding": [ "https://github.com/sponsors/sxzz", "https://opencollective.com/debug" ], - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } }, "node_modules/optionator": { "version": "0.9.4", @@ -3202,14 +3189,14 @@ } }, "node_modules/playwright": { - "version": "1.59.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.59.1.tgz", - "integrity": "sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==", + "version": "1.60.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.60.0.tgz", + "integrity": "sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==", "dev": true, "license": "Apache-2.0", "peer": true, "dependencies": { - "playwright-core": "1.59.1" + "playwright-core": "1.60.0" }, "bin": { "playwright": "cli.js" @@ -3222,9 +3209,9 @@ } }, "node_modules/playwright-core": { - "version": "1.59.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.59.1.tgz", - "integrity": "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==", + "version": "1.60.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.60.0.tgz", + "integrity": "sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==", "dev": true, "license": "Apache-2.0", "bin": { @@ -3245,9 +3232,9 @@ } }, "node_modules/postcss": { - "version": "8.5.9", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.9.tgz", - "integrity": "sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==", + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "dev": true, "funding": [ { @@ -3265,7 +3252,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", + "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -3295,13 +3282,16 @@ }, "node_modules/r1csfile": { "version": "0.0.48", - "resolved": "git+ssh://git@github.com/iden3/r1csfile.git#9af98fb578157010a02fb302bde8628bebcef87e", + "resolved": "git+ssh://git@github.com/iden3/r1csfile.git#cd3a2332cfac643dce347173a8d10244c1c9a104", "license": "GPL-3.0", "dependencies": { "@iden3/bigarray": "0.0.2", "@iden3/binfileutils": "https://github.com/iden3/binfileutils.git#feat/esm-migration", "fastfile": "https://github.com/iden3/fastfile.git#feat/esm-migration", "ffjavascript": "https://github.com/iden3/ffjavascript.git#feat/esm-migration" + }, + "engines": { + "node": ">=20" } }, "node_modules/readdirp": { @@ -3318,16 +3308,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, "node_modules/resolve.exports": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", @@ -3366,14 +3346,14 @@ } }, "node_modules/rolldown": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.15.tgz", - "integrity": "sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.3.tgz", + "integrity": "sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.124.0", - "@rolldown/pluginutils": "1.0.0-rc.15" + "@oxc-project/types": "=0.133.0", + "@rolldown/pluginutils": "^1.0.0" }, "bin": { "rolldown": "bin/cli.mjs" @@ -3382,27 +3362,27 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.0-rc.15", - "@rolldown/binding-darwin-arm64": "1.0.0-rc.15", - "@rolldown/binding-darwin-x64": "1.0.0-rc.15", - "@rolldown/binding-freebsd-x64": "1.0.0-rc.15", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.15", - "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.15", - "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.15", - "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.15", - "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.15", - "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.15", - "@rolldown/binding-linux-x64-musl": "1.0.0-rc.15", - "@rolldown/binding-openharmony-arm64": "1.0.0-rc.15", - "@rolldown/binding-wasm32-wasi": "1.0.0-rc.15", - "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.15", - "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.15" + "@rolldown/binding-android-arm64": "1.0.3", + "@rolldown/binding-darwin-arm64": "1.0.3", + "@rolldown/binding-darwin-x64": "1.0.3", + "@rolldown/binding-freebsd-x64": "1.0.3", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.3", + "@rolldown/binding-linux-arm64-gnu": "1.0.3", + "@rolldown/binding-linux-arm64-musl": "1.0.3", + "@rolldown/binding-linux-ppc64-gnu": "1.0.3", + "@rolldown/binding-linux-s390x-gnu": "1.0.3", + "@rolldown/binding-linux-x64-gnu": "1.0.3", + "@rolldown/binding-linux-x64-musl": "1.0.3", + "@rolldown/binding-openharmony-arm64": "1.0.3", + "@rolldown/binding-wasm32-wasi": "1.0.3", + "@rolldown/binding-win32-arm64-msvc": "1.0.3", + "@rolldown/binding-win32-x64-msvc": "1.0.3" } }, "node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz", + "integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==", "dev": true, "license": "ISC", "bin": { @@ -3475,9 +3455,9 @@ "license": "MIT" }, "node_modules/std-env": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz", - "integrity": "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.1.0.tgz", + "integrity": "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==", "dev": true, "license": "MIT" }, @@ -3502,9 +3482,9 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.1.tgz", - "integrity": "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", + "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", "dev": true, "license": "MIT", "engines": { @@ -3512,9 +3492,9 @@ } }, "node_modules/tinyglobby": { - "version": "0.2.16", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", - "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "license": "MIT", "dependencies": { @@ -3563,14 +3543,13 @@ "license": "0BSD" }, "node_modules/tsx": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", - "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.4.tgz", + "integrity": "sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "~0.27.0", - "get-tsconfig": "^4.7.5" + "esbuild": "~0.28.0" }, "bin": { "tsx": "dist/cli.mjs" @@ -3611,9 +3590,9 @@ } }, "node_modules/undici": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.24.1.tgz", - "integrity": "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA==", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.26.0.tgz", + "integrity": "sha512-4yqz8a3n5HmGTlsbADNtr/dJlhkh/55Rq798G6ibiULcXbDtaLpTl1pvdqcbFfeoj3iSi52lePFM7h9H21cw/A==", "dev": true, "license": "MIT", "engines": { @@ -3621,9 +3600,9 @@ } }, "node_modules/undici-types": { - "version": "7.19.2", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz", - "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==", + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", "dev": true, "license": "MIT", "optional": true @@ -3639,17 +3618,17 @@ } }, "node_modules/vite": { - "version": "8.0.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.8.tgz", - "integrity": "sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw==", + "version": "8.0.16", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.16.tgz", + "integrity": "sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==", "dev": true, "license": "MIT", "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", - "postcss": "^8.5.8", - "rolldown": "1.0.0-rc.15", - "tinyglobby": "^0.2.15" + "postcss": "^8.5.15", + "rolldown": "1.0.3", + "tinyglobby": "^0.2.17" }, "bin": { "vite": "bin/vite.js" @@ -3665,7 +3644,7 @@ }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.1.0", + "@vitejs/devtools": "^0.1.18", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", @@ -3732,20 +3711,20 @@ } }, "node_modules/vitest": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.4.tgz", - "integrity": "sha512-tFuJqTxKb8AvfyqMfnavXdzfy3h3sWZRWwfluGbkeR7n0HUev+FmNgZ8SDrRBTVrVCjgH5cA21qGbCffMNtWvg==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.8.tgz", + "integrity": "sha512-flY6ScbCIt9HThs+C5HS7jvGOB560DJtk/Z15IQROTA6zEy49Nh8T/dofWTQL+n3vswqn87sbJNiuqw1SDp5Ig==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@vitest/expect": "4.1.4", - "@vitest/mocker": "4.1.4", - "@vitest/pretty-format": "4.1.4", - "@vitest/runner": "4.1.4", - "@vitest/snapshot": "4.1.4", - "@vitest/spy": "4.1.4", - "@vitest/utils": "4.1.4", + "@vitest/expect": "4.1.8", + "@vitest/mocker": "4.1.8", + "@vitest/pretty-format": "4.1.8", + "@vitest/runner": "4.1.8", + "@vitest/snapshot": "4.1.8", + "@vitest/spy": "4.1.8", + "@vitest/utils": "4.1.8", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", @@ -3773,12 +3752,12 @@ "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.1.4", - "@vitest/browser-preview": "4.1.4", - "@vitest/browser-webdriverio": "4.1.4", - "@vitest/coverage-istanbul": "4.1.4", - "@vitest/coverage-v8": "4.1.4", - "@vitest/ui": "4.1.4", + "@vitest/browser-playwright": "4.1.8", + "@vitest/browser-preview": "4.1.8", + "@vitest/browser-webdriverio": "4.1.8", + "@vitest/coverage-istanbul": "4.1.8", + "@vitest/coverage-v8": "4.1.8", + "@vitest/ui": "4.1.8", "happy-dom": "*", "jsdom": "*", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -3830,7 +3809,7 @@ }, "node_modules/wasmcurves": { "version": "0.2.2", - "resolved": "git+ssh://git@github.com/iden3/wasmcurves.git#6601f20df1059e29f98ea595ca12e35545c321f1", + "resolved": "git+ssh://git@github.com/iden3/wasmcurves.git#e9f34e706d7458f0a7b82d19940bc3c40b8f2457", "license": "GPL-3.0", "dependencies": { "wasmbuilder": "0.0.16" @@ -3892,9 +3871,9 @@ "license": "Apache-2.0" }, "node_modules/ws": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", - "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", "dev": true, "license": "MIT", "engines": { diff --git a/test/smart_contracts.test.js b/test/smart_contracts.test.js index 83b2696d..17fc2d23 100644 --- a/test/smart_contracts.test.js +++ b/test/smart_contracts.test.js @@ -42,7 +42,7 @@ async function groth16Verify(r1csFilename, wtnsFilename) { await tasks.getTask("compile").run(); await artifacts.clearCache(); const { ethers } = await network.connect(); - const verifier = await (await ethers.getContractFactory("Groth16Verifier")).deploy(); + const verifier = await (await ethers.getContractFactory("contracts/Groth16Verifier.sol:Groth16Verifier")).deploy(); return verifier.verifyProof( [proof.pi_a[0], proof.pi_a[1]], @@ -68,7 +68,7 @@ async function groth16VerifyAliased(r1csFilename, wtnsFilename) { await tasks.getTask("compile").run(); await artifacts.clearCache(); const { ethers } = await network.connect(); - const verifier = await (await ethers.getContractFactory("Groth16Verifier")).deploy(); + const verifier = await (await ethers.getContractFactory("contracts/Groth16Verifier.sol:Groth16Verifier")).deploy(); // Shift the second public signal by the curve order — verifier must reject this const aliasedSignals = [...publicSignals]; @@ -98,7 +98,7 @@ async function plonkVerify(r1csFilename, wtnsFilename) { await tasks.getTask("compile").run(); await artifacts.clearCache(); const { ethers } = await network.connect(); - const verifier = await (await ethers.getContractFactory("PlonkVerifier")).deploy(); + const verifier = await (await ethers.getContractFactory("contracts/PlonkVerifier.sol:PlonkVerifier")).deploy(); const proof = encodeFields([ p.A[0], p.A[1], @@ -133,7 +133,7 @@ async function fflonkVerify(r1csFilename, wtnsFilename) { await tasks.getTask("compile").run(); await artifacts.clearCache(); const { ethers } = await network.connect(); - const verifier = await (await ethers.getContractFactory("FflonkVerifier")).deploy(); + const verifier = await (await ethers.getContractFactory("contracts/FflonkVerifier.sol:FflonkVerifier")).deploy(); const { evaluations: e, polynomials: poly } = p; const proof = encodeFields([ diff --git a/vite.config.js b/vite.config.js index 171956f0..62945cf5 100644 --- a/vite.config.js +++ b/vite.config.js @@ -104,7 +104,7 @@ export default defineConfig(({ mode }) => { }, outDir: "build", emptyOutDir: false, - minify: false, + minify: true, rollupOptions: { external: isBrowserExternal, output: { From 1605ae91bd4f84bfe347140b6306844ae9a5de27 Mon Sep 17 00:00:00 2001 From: d5k9 Date: Mon, 15 Jun 2026 16:51:54 +0700 Subject: [PATCH 7/8] refactor: remove console.log statements for cleaner code --- src/groth16_prove.js | 19 ------------------- src/plonk_setup.js | 1 - src/polynomial/polynomial.js | 4 ---- 3 files changed, 24 deletions(-) diff --git a/src/groth16_prove.js b/src/groth16_prove.js index 773139ce..401b8c09 100644 --- a/src/groth16_prove.js +++ b/src/groth16_prove.js @@ -319,12 +319,10 @@ async function buildABC(curve, zkey, witness, coeffs, logger) { } let elementsPerChunk = Math.floor(zkey.domainSize/concurrency); - console.log("@@@ elementsPerChunk", elementsPerChunk); while (elementsPerChunk > 2**16) { concurrency*=2; elementsPerChunk = Math.floor(zkey.domainSize/concurrency); } - console.log("@@@ new elementsPerChunk", elementsPerChunk); const promises = []; @@ -472,17 +470,10 @@ async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { //const chunkSize = 2**18; const chunkSize = elementsPerChunk; - console.log("zkey.domainSize", zkey.domainSize); - console.log("concurrency", concurrency); - console.log("elementsPerChunk", elementsPerChunk); - console.log("chunkSize", chunkSize); - for (let s = 0; s < zkey.nVars; s += chunkSize) { if (logger) logger.debug(`QAP: ${s}/${zkey.nVars}`); const ns = Math.min(zkey.nVars - s, chunkSize); - console.log("ns", ns); - //let i=0; for (let i = 0; i < concurrency; i++) { let n; @@ -528,14 +519,8 @@ async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { let result = await Promise.all(promises); - - console.log("result.length", result.length); - console.log("result", result); - const nGroups = result.length / concurrency; - console.log("nGroups", nGroups); - let result2; if (nGroups > 1) { const promises2 = []; @@ -561,17 +546,13 @@ async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { task.push({cmd: "GET", out: m, var: 0, len: result[i][m].length}); //task.push({cmd: "TERMINATE"}); // to free memory immediately } - console.log("task.length", task.length); //promises2.push(curve.tm.queueAction(task)); promises2.push(curve.tm.queueAction(task, result.buffer)); } - console.log("promises2.length", promises2.length); result2 = await Promise.all(promises2); result = result2; } - //console.log("result", result); - //console.log("result2", result2); //result = result2 || result; const outBuffA = new BigBuffer(zkey.domainSize * curve.Fr.n8); diff --git a/src/plonk_setup.js b/src/plonk_setup.js index 7ebce029..5330ac57 100644 --- a/src/plonk_setup.js +++ b/src/plonk_setup.js @@ -373,7 +373,6 @@ export default async function plonkSetup(r1csName, ptauName, zkeyName, logger) { sigma.set(lastAparence[s], firstPos[s]*n8r); } else { // throw new Error("Variable not used"); - console.log("Variable not used"); } if ((logger)&&(s%1000000 == 0)) logger.debug(`writing ${name} phase2: ${s}/${plonkNVars}`); } diff --git a/src/polynomial/polynomial.js b/src/polynomial/polynomial.js index 110210a8..d3d612f5 100644 --- a/src/polynomial/polynomial.js +++ b/src/polynomial/polynomial.js @@ -434,10 +434,7 @@ export class Polynomial { let nElementsChunk = Math.floor(nTotal / nThreads); let nElementsLast = nTotal - (nThreads - 1) * nElementsChunk; - console.log(nTotal); - console.log(nElementsChunk + " " + nElementsLast); for (let k = 0; k < nThreads; k++) { - console.log("> Thread " + k); for (let i = (k === 0 ? nElementsLast : nElementsChunk); i > 0; i--) { let idxDst = i - 1; if (k !== 0) idxDst += (k - 1) * nElementsChunk + nElementsLast; @@ -449,7 +446,6 @@ export class Polynomial { polR.setCoef(idxSrc, Fr.zero); polR.setCoef(idxDst, Fr.add(polR.getCoef(idxDst), Fr.mul(beta, leadingCoef))); this.setCoef(idxDst, Fr.add(this.getCoef(idxDst), leadingCoef)); - console.log(idxDst + " <-- " + idxSrc); } } From 53e8438e92331df1a4ce5996a7c60cd96541b93a Mon Sep 17 00:00:00 2001 From: d5k9 Date: Mon, 15 Jun 2026 20:26:47 +0700 Subject: [PATCH 8/8] Remove unnecessary timing logs in groth16Prove and related functions for cleaner output --- build/browser.esm.js | 57 +++++++++++++++++--------------------------- build/cli.cjs | 55 +++++++----------------------------------- build/main.cjs | 55 +++++++----------------------------------- build/snarkjs.min.js | 4 ++-- src/groth16_prove.js | 20 ---------------- 5 files changed, 42 insertions(+), 149 deletions(-) diff --git a/build/browser.esm.js b/build/browser.esm.js index 855aade6..52814250 100644 --- a/build/browser.esm.js +++ b/build/browser.esm.js @@ -879,10 +879,10 @@ async function it(t, n, r, i) { let _ = await e.readSection(a, o, 2), v, y, b, x = (async function() { let t, n, a; await (async function() { - r && r.debug("Reading Coeffs"), console.time("buildABC_outer"); + r && r.debug("Reading Coeffs"); let o = await e.readSection(c, l, 4); - r && r.debug("Building ABC"), i ||= {}, i && i.buildABC === "wasm" ? [t, n, a] = await ot(f, d, _, o, r) : i && i.buildABC === "wasm1" ? [t, n, a] = await st(f, d, _, o, r) : [t, n, a] = await at(f, d, _, o, r), console.timeEnd("buildABC_outer"); - })(), console.time("abcPromise"), globalThis.gc && globalThis.gc(); + r && r.debug("Building ABC"), i ||= {}, i && i.buildABC === "wasm" ? [t, n, a] = await ot(f, d, _, o, r) : i && i.buildABC === "wasm1" ? [t, n, a] = await st(f, d, _, o, r) : [t, n, a] = await at(f, d, _, o, r); + })(), globalThis.gc && globalThis.gc(); let o = g === p.s ? f.Fr.shift : f.Fr.w[g + 1], s; await (async function() { let e = await p.ifft(t, "", "", r, "IFFT_A"); @@ -903,34 +903,34 @@ async function it(t, n, r, i) { a = null; let t = await p.batchApplyKey(e, p.e(1), o); m = await p.fft(t, "", "", r, "FFT_C"); - })(), r && r.debug("Join ABC"), b = await ct(f, d, s, u, m, r), r && r.debug("Join ABC finished"), s = null, u = null, m = null, globalThis.gc && globalThis.gc(), console.timeEnd("abcPromise"); + })(), r && r.debug("Join ABC"), b = await ct(f, d, s, u, m, r), r && r.debug("Join ABC finished"), s = null, u = null, m = null, globalThis.gc && globalThis.gc(); })(), S = {}; async function C() { r && r.debug("Reading A Points"); let t = await e.readSection(c, l, 5); - console.time("Calculate PiA"), S.pi_a = await f.G1.multiExpAffine(t, _, r, "multiexp A"), console.timeEnd("Calculate PiA"); + S.pi_a = await f.G1.multiExpAffine(t, _, r, "multiexp A"); } let w = C(), T; async function E() { r && r.debug("Reading B1 Points"); let t = await e.readSection(c, l, 6); - console.time("Calculate PiB1"), T = await f.G1.multiExpAffine(t, _, r, "multiexp B1"), console.timeEnd("Calculate PiB1"); + T = await f.G1.multiExpAffine(t, _, r, "multiexp B1"); } let D = E(); async function O() { r && r.debug("Reading B2 Points"); let t = await e.readSection(c, l, 7); - console.time("Calculate PiB"), S.pi_b = await f.G2.multiExpAffine(t, _, r, "multiexp B2"), console.timeEnd("Calculate PiB"); + S.pi_b = await f.G2.multiExpAffine(t, _, r, "multiexp B2"); } let k = O(), A = (async function() { r && r.debug("Reading C Points"); let t = await e.readSection(c, l, 8); - console.time("Calculate PiC"), S.pi_c = await f.G1.multiExpAffine(t, _.slice((d.nPublic + 1) * f.Fr.n8), r, "multiexp C"), console.timeEnd("Calculate PiC"); + S.pi_c = await f.G1.multiExpAffine(t, _.slice((d.nPublic + 1) * f.Fr.n8), r, "multiexp C"); })(); y = (async function() { - r && r.debug("Reading H Points"), await x, console.time("resHPromise"); + r && r.debug("Reading H Points"), await x; let t = await e.readSection(c, l, 9); - v = await f.G1.multiExpAffine(t, b, r, "multiexp H"), console.timeEnd("resHPromise"); + v = await f.G1.multiExpAffine(t, b, r, "multiexp H"); })(); let j = f.Fr.random(), M = f.Fr.random(); await w, S.pi_a = m.add(S.pi_a, d.vk_alpha_1), S.pi_a = m.add(S.pi_a, m.timesFr(d.vk_delta_1, j)), await k, S.pi_b = h.add(S.pi_b, d.vk_beta_2), S.pi_b = h.add(S.pi_b, h.timesFr(d.vk_delta_2, M)), await D, T = m.add(T, d.vk_beta_1), T = m.add(T, m.timesFr(d.vk_delta_1, M)), await Promise.all([A, y]), S.pi_c = m.add(S.pi_c, v), S.pi_c = m.add(S.pi_c, m.timesFr(S.pi_a, M)), S.pi_c = m.add(S.pi_c, m.timesFr(T, j)), S.pi_c = m.add(S.pi_c, m.timesFr(d.vk_delta_1, p.neg(p.mul(j, M)))); @@ -981,8 +981,7 @@ async function ot(e, t, n, r, i) { }; } let l = Math.floor(t.domainSize / a); - for (console.log("@@@ elementsPerChunk", l); l > 2 ** 16;) a *= 2, l = Math.floor(t.domainSize / a); - console.log("@@@ new elementsPerChunk", l); + for (; l > 2 ** 16;) a *= 2, l = Math.floor(t.domainSize / a); let u = [], d = []; for (let e = 0; e < a; e++) d.push(y(Math.floor(e * l))); d.push(r.byteLength); @@ -1110,7 +1109,6 @@ async function ot(e, t, n, r, i) { } } async function st(e, t, n, r, i) { - console.time("buildABC"); let a = 12 + t.n8r, o; if (r instanceof s) { let e = [], t = r.buffers[0].length; @@ -1128,11 +1126,9 @@ async function st(e, t, n, r, i) { for (let e = 0; e < 1; e++) u.push(y(Math.floor(e * c))); u.push(r.byteLength); let d = c; - console.log("zkey.domainSize", t.domainSize), console.log("concurrency", 1), console.log("elementsPerChunk", c), console.log("chunkSize", d); for (let o = 0; o < t.nVars; o += d) { i && i.debug(`QAP: ${o}/${t.nVars}`); let s = Math.min(t.nVars - o, d); - console.log("ns", s); for (let i = 0; i < 1; i++) { let d; if (d = i < 0 ? c : t.domainSize - i * c, d === 0) continue; @@ -1190,11 +1186,7 @@ async function st(e, t, n, r, i) { }), l.push(e.tm.queueAction(f, [p.buffer, m.buffer])); } } - let f = await Promise.all(l); - console.log("result.length", f.length), console.log("result", f); - let p = f.length / 1; - console.log("nGroups", p); - let m; + let f = await Promise.all(l), p = f.length / 1, m; if (p > 1) { let t = []; for (let n = 0; n < 1; n++) { @@ -1235,13 +1227,13 @@ async function st(e, t, n, r, i) { len: f[n][t].length }); } - console.log("task.length", r.length), t.push(e.tm.queueAction(r, f.buffer)); + t.push(e.tm.queueAction(r, f.buffer)); } - console.log("promises2.length", t.length), m = await Promise.all(t), f = m; + m = await Promise.all(t), f = m; } let h = new s(t.domainSize * e.Fr.n8), g = new s(t.domainSize * e.Fr.n8), _ = new s(t.domainSize * e.Fr.n8), v = 0; for (let e = 0; e < f.length; e++) h.set(f[e][0], v), g.set(f[e][1], v), _.set(f[e][2], v), v += f[e][0].byteLength; - return console.timeEnd("buildABC"), [ + return [ h, g, _ @@ -1256,7 +1248,6 @@ async function st(e, t, n, r, i) { } } async function ct(e, t, n, r, i, a) { - console.time("joinABC"); let o = 65536, c = e.Fr.n8, l = Math.floor(n.byteLength / e.Fr.n8), u = []; for (let t = 0; t < l; t += o) { a && a.debug(`JoinABC: ${t}/${l}`); @@ -1310,7 +1301,7 @@ async function ct(e, t, n, r, i, a) { f = n instanceof s ? new s(n.byteLength) : new Uint8Array(n.byteLength); let p = 0; for (let e = 0; e < d.length; e++) f.set(d[e][0], p), p += d[e][0].byteLength; - return console.timeEnd("joinABC"), f; + return f; } function lt(e) { if (!e || typeof process > "u" || !process.memoryUsage) return; @@ -3685,7 +3676,7 @@ async function lr(e, c, l, d) { async function te(e, t) { let r = new s(w * j * 3), i = new Kn(D), o = new Kn(D), c = C.one; for (let e = 0; e < j; e++) e < T.length ? (p(T[e][0], e), p(T[e][1], j + e), p(T[e][2], j * 2 + e)) : (p(0, e), p(0, j + e), p(0, j * 2 + e)), c = C.mul(c, C.w[A]), d && e % 1e6 == 0 && d.debug(`writing ${t} phase1: ${e}/${T.length}`); - for (let e = 0; e < D; e++) o[e] === void 0 ? console.log("Variable not used") : r.set(i[e], o[e] * w), d && e % 1e6 == 0 && d.debug(`writing ${t} phase2: ${e}/${D}`); + for (let e = 0; e < D; e++) o[e] !== void 0 && r.set(i[e], o[e] * w), d && e % 1e6 == 0 && d.debug(`writing ${t} phase2: ${e}/${D}`); globalThis.gc && globalThis.gc(), await a(k, e); let l = r.slice(0, j * w); await B(l), globalThis.gc && globalThis.gc(); @@ -4112,15 +4103,11 @@ var Er = class e { let r = this.Fr, i = new e(this.coef, this.curve, this.logger); this.coef = this.length() > 32768 ? new s(this.length() * r.n8) : new Uint8Array(this.length() * r.n8); let a = this.length() - t, o = Math.floor(a / 3), c = a - 2 * o; - console.log(a), console.log(o + " " + c); - for (let e = 0; e < 3; e++) { - console.log("> Thread " + e); - for (let a = e === 0 ? c : o; a > 0; a--) { - let s = a - 1; - e !== 0 && (s += (e - 1) * o + c); - let l = s + t, u = i.getCoef(l); - r.eq(r.zero, u) || (i.setCoef(l, r.zero), i.setCoef(s, r.add(i.getCoef(s), r.mul(n, u))), this.setCoef(s, r.add(this.getCoef(s), u)), console.log(s + " <-- " + l)); - } + for (let e = 0; e < 3; e++) for (let a = e === 0 ? c : o; a > 0; a--) { + let s = a - 1; + e !== 0 && (s += (e - 1) * o + c); + let l = s + t, u = i.getCoef(l); + r.eq(r.zero, u) || (i.setCoef(l, r.zero), i.setCoef(s, r.add(i.getCoef(s), r.mul(n, u))), this.setCoef(s, r.add(this.getCoef(s), u))); } return this.print(), i; } diff --git a/build/cli.cjs b/build/cli.cjs index ca2c0468..ce067f8a 100644 --- a/build/cli.cjs +++ b/build/cli.cjs @@ -3788,16 +3788,13 @@ async function groth16Prove$1(zkeyFileName, witnessFileName, logger, options) { let buffA_T, buffB_T, buffC_T; await (async function() { if (logger) logger.debug("Reading Coeffs"); - console.time("buildABC_outer"); const buffCoeffs = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 4); if (logger) logger.debug("Building ABC"); options = options || {}; if (options && options.buildABC === "wasm") [buffA_T, buffB_T, buffC_T] = await buildABC(curve, zkey, buffWitness, buffCoeffs, logger); else if (options && options.buildABC === "wasm1") [buffA_T, buffB_T, buffC_T] = await buildABCWASM1(curve, zkey, buffWitness, buffCoeffs, logger); else [buffA_T, buffB_T, buffC_T] = await buildABC1(curve, zkey, buffWitness, buffCoeffs, logger); - console.timeEnd("buildABC_outer"); })(); - console.time("abcPromise"); if (globalThis.gc) globalThis.gc(); const inc = power === Fr.s ? curve.Fr.shift : curve.Fr.w[power + 1]; let buffAodd_T; @@ -3828,48 +3825,37 @@ async function groth16Prove$1(zkeyFileName, witnessFileName, logger, options) { buffBodd_T = null; buffCodd_T = null; if (globalThis.gc) globalThis.gc(); - console.timeEnd("abcPromise"); })(); let proof = {}; async function calcPiA() { if (logger) logger.debug("Reading A Points"); const buffBasesA = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 5); - console.time("Calculate PiA"); proof.pi_a = await curve.G1.multiExpAffine(buffBasesA, buffWitness, logger, "multiexp A"); - console.timeEnd("Calculate PiA"); } let piaPromise = calcPiA(); let pib1; async function calcPiB1() { if (logger) logger.debug("Reading B1 Points"); const buffBasesB1 = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 6); - console.time("Calculate PiB1"); pib1 = await curve.G1.multiExpAffine(buffBasesB1, buffWitness, logger, "multiexp B1"); - console.timeEnd("Calculate PiB1"); } let pib1Promise = calcPiB1(); async function calcPiB() { if (logger) logger.debug("Reading B2 Points"); const buffBasesB2 = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 7); - console.time("Calculate PiB"); proof.pi_b = await curve.G2.multiExpAffine(buffBasesB2, buffWitness, logger, "multiexp B2"); - console.timeEnd("Calculate PiB"); } let pibPromise = calcPiB(); let picPromise = (async function() { if (logger) logger.debug("Reading C Points"); const buffBasesC = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 8); - console.time("Calculate PiC"); proof.pi_c = await curve.G1.multiExpAffine(buffBasesC, buffWitness.slice((zkey.nPublic + 1) * curve.Fr.n8), logger, "multiexp C"); - console.timeEnd("Calculate PiC"); })(); resHPromise = (async function() { if (logger) logger.debug("Reading H Points"); await abcPromise; - console.time("resHPromise"); const buffBasesH = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 9); resH = await curve.G1.multiExpAffine(buffBasesH, buffPodd_T, logger, "multiexp H"); - console.timeEnd("resHPromise"); })(); const r = curve.Fr.random(); const s = curve.Fr.random(); @@ -3960,12 +3946,10 @@ async function buildABC(curve, zkey, witness, coeffs, logger) { }; } let elementsPerChunk = Math.floor(zkey.domainSize / concurrency); - console.log("@@@ elementsPerChunk", elementsPerChunk); while (elementsPerChunk > 2 ** 16) { concurrency *= 2; elementsPerChunk = Math.floor(zkey.domainSize / concurrency); } - console.log("@@@ new elementsPerChunk", elementsPerChunk); const promises = []; const cutPoints = []; for (let i = 0; i < concurrency; i++) cutPoints.push(getCutPoint(Math.floor(i * elementsPerChunk))); @@ -4121,7 +4105,6 @@ async function buildABC(curve, zkey, witness, coeffs, logger) { } } async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { - console.time("buildABC"); const concurrency = 1; const sCoef = 12 + zkey.n8r; let getUint32; @@ -4144,14 +4127,9 @@ async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { for (let i = 0; i < concurrency; i++) cutPoints.push(getCutPoint(Math.floor(i * elementsPerChunk))); cutPoints.push(coeffs.byteLength); const chunkSize = elementsPerChunk; - console.log("zkey.domainSize", zkey.domainSize); - console.log("concurrency", concurrency); - console.log("elementsPerChunk", elementsPerChunk); - console.log("chunkSize", chunkSize); for (let s = 0; s < zkey.nVars; s += chunkSize) { if (logger) logger.debug(`QAP: ${s}/${zkey.nVars}`); const ns = Math.min(zkey.nVars - s, chunkSize); - console.log("ns", ns); for (let i = 0; i < concurrency; i++) { let n; if (i < concurrency - 1) n = elementsPerChunk; @@ -4223,10 +4201,7 @@ async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { } } let result = await Promise.all(promises); - console.log("result.length", result.length); - console.log("result", result); const nGroups = result.length / concurrency; - console.log("nGroups", nGroups); let result2; if (nGroups > 1) { const promises2 = []; @@ -4272,10 +4247,8 @@ async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { len: result[i][m].length }); } - console.log("task.length", task.length); promises2.push(curve.tm.queueAction(task, result.buffer)); } - console.log("promises2.length", promises2.length); result2 = await Promise.all(promises2); result = result2; } @@ -4289,7 +4262,6 @@ async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { outBuffC.set(result[i][2], p); p += result[i][0].byteLength; } - console.timeEnd("buildABC"); return [ outBuffA, outBuffB, @@ -4309,7 +4281,6 @@ async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { } } async function joinABC(curve, zkey, a, b, c, logger) { - console.time("joinABC"); const MAX_CHUNK_SIZE = 65536; const n8 = curve.Fr.n8; const nElements = Math.floor(a.byteLength / curve.Fr.n8); @@ -4382,7 +4353,6 @@ async function joinABC(curve, zkey, a, b, c, logger) { outBuff.set(result[i][0], p); p += result[i][0].byteLength; } - console.timeEnd("joinABC"); return outBuff; } function memUsage(logger) { @@ -4801,7 +4771,6 @@ async function plonkSetup$1(r1csName, ptauName, zkeyName, logger) { } for (let s = 0; s < plonkNVars; s++) { if (typeof firstPos[s] !== "undefined") sigma.set(lastAparence[s], firstPos[s] * n8r); - else console.log("Variable not used"); if (logger && s % 1e6 == 0) logger.debug(`writing ${name} phase2: ${s}/${plonkNVars}`); } if (globalThis.gc) globalThis.gc(); @@ -5333,21 +5302,15 @@ var Polynomial = class Polynomial { let nTotal = this.length() - m; let nElementsChunk = Math.floor(nTotal / nThreads); let nElementsLast = nTotal - (nThreads - 1) * nElementsChunk; - console.log(nTotal); - console.log(nElementsChunk + " " + nElementsLast); - for (let k = 0; k < nThreads; k++) { - console.log("> Thread " + k); - for (let i = k === 0 ? nElementsLast : nElementsChunk; i > 0; i--) { - let idxDst = i - 1; - if (k !== 0) idxDst += (k - 1) * nElementsChunk + nElementsLast; - let idxSrc = idxDst + m; - let leadingCoef = polR.getCoef(idxSrc); - if (Fr.eq(Fr.zero, leadingCoef)) continue; - polR.setCoef(idxSrc, Fr.zero); - polR.setCoef(idxDst, Fr.add(polR.getCoef(idxDst), Fr.mul(beta, leadingCoef))); - this.setCoef(idxDst, Fr.add(this.getCoef(idxDst), leadingCoef)); - console.log(idxDst + " <-- " + idxSrc); - } + for (let k = 0; k < nThreads; k++) for (let i = k === 0 ? nElementsLast : nElementsChunk; i > 0; i--) { + let idxDst = i - 1; + if (k !== 0) idxDst += (k - 1) * nElementsChunk + nElementsLast; + let idxSrc = idxDst + m; + let leadingCoef = polR.getCoef(idxSrc); + if (Fr.eq(Fr.zero, leadingCoef)) continue; + polR.setCoef(idxSrc, Fr.zero); + polR.setCoef(idxDst, Fr.add(polR.getCoef(idxDst), Fr.mul(beta, leadingCoef))); + this.setCoef(idxDst, Fr.add(this.getCoef(idxDst), leadingCoef)); } this.print(); return polR; diff --git a/build/main.cjs b/build/main.cjs index cb8ff0fa..0661627b 100644 --- a/build/main.cjs +++ b/build/main.cjs @@ -633,16 +633,13 @@ async function groth16Prove(zkeyFileName, witnessFileName, logger, options) { let buffA_T, buffB_T, buffC_T; await (async function() { if (logger) logger.debug("Reading Coeffs"); - console.time("buildABC_outer"); const buffCoeffs = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 4); if (logger) logger.debug("Building ABC"); options = options || {}; if (options && options.buildABC === "wasm") [buffA_T, buffB_T, buffC_T] = await buildABC(curve, zkey, buffWitness, buffCoeffs, logger); else if (options && options.buildABC === "wasm1") [buffA_T, buffB_T, buffC_T] = await buildABCWASM1(curve, zkey, buffWitness, buffCoeffs, logger); else [buffA_T, buffB_T, buffC_T] = await buildABC1(curve, zkey, buffWitness, buffCoeffs, logger); - console.timeEnd("buildABC_outer"); })(); - console.time("abcPromise"); if (globalThis.gc) globalThis.gc(); const inc = power === Fr.s ? curve.Fr.shift : curve.Fr.w[power + 1]; let buffAodd_T; @@ -673,48 +670,37 @@ async function groth16Prove(zkeyFileName, witnessFileName, logger, options) { buffBodd_T = null; buffCodd_T = null; if (globalThis.gc) globalThis.gc(); - console.timeEnd("abcPromise"); })(); let proof = {}; async function calcPiA() { if (logger) logger.debug("Reading A Points"); const buffBasesA = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 5); - console.time("Calculate PiA"); proof.pi_a = await curve.G1.multiExpAffine(buffBasesA, buffWitness, logger, "multiexp A"); - console.timeEnd("Calculate PiA"); } let piaPromise = calcPiA(); let pib1; async function calcPiB1() { if (logger) logger.debug("Reading B1 Points"); const buffBasesB1 = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 6); - console.time("Calculate PiB1"); pib1 = await curve.G1.multiExpAffine(buffBasesB1, buffWitness, logger, "multiexp B1"); - console.timeEnd("Calculate PiB1"); } let pib1Promise = calcPiB1(); async function calcPiB() { if (logger) logger.debug("Reading B2 Points"); const buffBasesB2 = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 7); - console.time("Calculate PiB"); proof.pi_b = await curve.G2.multiExpAffine(buffBasesB2, buffWitness, logger, "multiexp B2"); - console.timeEnd("Calculate PiB"); } let pibPromise = calcPiB(); let picPromise = (async function() { if (logger) logger.debug("Reading C Points"); const buffBasesC = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 8); - console.time("Calculate PiC"); proof.pi_c = await curve.G1.multiExpAffine(buffBasesC, buffWitness.slice((zkey.nPublic + 1) * curve.Fr.n8), logger, "multiexp C"); - console.timeEnd("Calculate PiC"); })(); resHPromise = (async function() { if (logger) logger.debug("Reading H Points"); await abcPromise; - console.time("resHPromise"); const buffBasesH = await _iden3_binfileutils.readSection(fdZKey, sectionsZKey, 9); resH = await curve.G1.multiExpAffine(buffBasesH, buffPodd_T, logger, "multiexp H"); - console.timeEnd("resHPromise"); })(); const r = curve.Fr.random(); const s = curve.Fr.random(); @@ -805,12 +791,10 @@ async function buildABC(curve, zkey, witness, coeffs, logger) { }; } let elementsPerChunk = Math.floor(zkey.domainSize / concurrency); - console.log("@@@ elementsPerChunk", elementsPerChunk); while (elementsPerChunk > 2 ** 16) { concurrency *= 2; elementsPerChunk = Math.floor(zkey.domainSize / concurrency); } - console.log("@@@ new elementsPerChunk", elementsPerChunk); const promises = []; const cutPoints = []; for (let i = 0; i < concurrency; i++) cutPoints.push(getCutPoint(Math.floor(i * elementsPerChunk))); @@ -966,7 +950,6 @@ async function buildABC(curve, zkey, witness, coeffs, logger) { } } async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { - console.time("buildABC"); const concurrency = 1; const sCoef = 12 + zkey.n8r; let getUint32; @@ -989,14 +972,9 @@ async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { for (let i = 0; i < concurrency; i++) cutPoints.push(getCutPoint(Math.floor(i * elementsPerChunk))); cutPoints.push(coeffs.byteLength); const chunkSize = elementsPerChunk; - console.log("zkey.domainSize", zkey.domainSize); - console.log("concurrency", concurrency); - console.log("elementsPerChunk", elementsPerChunk); - console.log("chunkSize", chunkSize); for (let s = 0; s < zkey.nVars; s += chunkSize) { if (logger) logger.debug(`QAP: ${s}/${zkey.nVars}`); const ns = Math.min(zkey.nVars - s, chunkSize); - console.log("ns", ns); for (let i = 0; i < concurrency; i++) { let n; if (i < concurrency - 1) n = elementsPerChunk; @@ -1068,10 +1046,7 @@ async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { } } let result = await Promise.all(promises); - console.log("result.length", result.length); - console.log("result", result); const nGroups = result.length / concurrency; - console.log("nGroups", nGroups); let result2; if (nGroups > 1) { const promises2 = []; @@ -1117,10 +1092,8 @@ async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { len: result[i][m].length }); } - console.log("task.length", task.length); promises2.push(curve.tm.queueAction(task, result.buffer)); } - console.log("promises2.length", promises2.length); result2 = await Promise.all(promises2); result = result2; } @@ -1134,7 +1107,6 @@ async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { outBuffC.set(result[i][2], p); p += result[i][0].byteLength; } - console.timeEnd("buildABC"); return [ outBuffA, outBuffB, @@ -1154,7 +1126,6 @@ async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { } } async function joinABC(curve, zkey, a, b, c, logger) { - console.time("joinABC"); const MAX_CHUNK_SIZE = 65536; const n8 = curve.Fr.n8; const nElements = Math.floor(a.byteLength / curve.Fr.n8); @@ -1227,7 +1198,6 @@ async function joinABC(curve, zkey, a, b, c, logger) { outBuff.set(result[i][0], p); p += result[i][0].byteLength; } - console.timeEnd("joinABC"); return outBuff; } function memUsage(logger) { @@ -4806,7 +4776,6 @@ async function plonkSetup(r1csName, ptauName, zkeyName, logger) { } for (let s = 0; s < plonkNVars; s++) { if (typeof firstPos[s] !== "undefined") sigma.set(lastAparence[s], firstPos[s] * n8r); - else console.log("Variable not used"); if (logger && s % 1e6 == 0) logger.debug(`writing ${name} phase2: ${s}/${plonkNVars}`); } if (globalThis.gc) globalThis.gc(); @@ -5338,21 +5307,15 @@ var Polynomial = class Polynomial { let nTotal = this.length() - m; let nElementsChunk = Math.floor(nTotal / nThreads); let nElementsLast = nTotal - (nThreads - 1) * nElementsChunk; - console.log(nTotal); - console.log(nElementsChunk + " " + nElementsLast); - for (let k = 0; k < nThreads; k++) { - console.log("> Thread " + k); - for (let i = k === 0 ? nElementsLast : nElementsChunk; i > 0; i--) { - let idxDst = i - 1; - if (k !== 0) idxDst += (k - 1) * nElementsChunk + nElementsLast; - let idxSrc = idxDst + m; - let leadingCoef = polR.getCoef(idxSrc); - if (Fr.eq(Fr.zero, leadingCoef)) continue; - polR.setCoef(idxSrc, Fr.zero); - polR.setCoef(idxDst, Fr.add(polR.getCoef(idxDst), Fr.mul(beta, leadingCoef))); - this.setCoef(idxDst, Fr.add(this.getCoef(idxDst), leadingCoef)); - console.log(idxDst + " <-- " + idxSrc); - } + for (let k = 0; k < nThreads; k++) for (let i = k === 0 ? nElementsLast : nElementsChunk; i > 0; i--) { + let idxDst = i - 1; + if (k !== 0) idxDst += (k - 1) * nElementsChunk + nElementsLast; + let idxSrc = idxDst + m; + let leadingCoef = polR.getCoef(idxSrc); + if (Fr.eq(Fr.zero, leadingCoef)) continue; + polR.setCoef(idxSrc, Fr.zero); + polR.setCoef(idxDst, Fr.add(polR.getCoef(idxDst), Fr.mul(beta, leadingCoef))); + this.setCoef(idxDst, Fr.add(this.getCoef(idxDst), leadingCoef)); } this.print(); return polR; diff --git a/build/snarkjs.min.js b/build/snarkjs.min.js index f2e6a35d..1b8973bc 100644 --- a/build/snarkjs.min.js +++ b/build/snarkjs.min.js @@ -1,7 +1,7 @@ var snarkjs=(function(e,t,n,r){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var i=Object.create,a=Object.defineProperty,o=Object.getOwnPropertyDescriptor,s=Object.getOwnPropertyNames,c=Object.getPrototypeOf,l=Object.prototype.hasOwnProperty,u=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),d=(e,t)=>{let n={};for(var r in e)a(n,r,{get:e[r],enumerable:!0});return t||a(n,Symbol.toStringTag,{value:`Module`}),n},f=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=s(t),c=0,u=i.length,d;ct[e]).bind(null,d),enumerable:!(r=o(t,d))||r.enumerable});return e};t=((e,t,n)=>(n=e==null?{}:i(c(e)),f(t||!e||!e.__esModule?a(n,`default`,{value:e,enumerable:!0}):n,e)))(t,1);var p=d({getCurveFromName:()=>b,getCurveFromQ:()=>y,getCurveFromR:()=>v}),m=n.Scalar.e(`73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001`,16),h=n.Scalar.e(`21888242871839275222246405745257275088548364400416034343698204186575808495617`),g=n.Scalar.e(`1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab`,16),_=n.Scalar.e(`21888242871839275222246405745257275088696311157297823662689037894645226208583`);async function v(e,t){let r,i=t&&t.singleThread;if(n.Scalar.eq(e,h))r=await(0,n.buildBn128)(i);else if(n.Scalar.eq(e,m))r=await(0,n.buildBls12381)(i);else throw Error(`Curve not supported: ${n.Scalar.toString(e)}`);return r}async function y(e,t){let r,i=t&&t.singleThread;if(n.Scalar.eq(e,_))r=await(0,n.buildBn128)(i);else if(n.Scalar.eq(e,g))r=await(0,n.buildBls12381)(i);else throw Error(`Curve not supported: ${n.Scalar.toString(e)}`);return r}async function b(e,t){let r,i=t&&t.singleThread,a=o(e);if([`BN128`,`BN254`,`ALTBN128`].indexOf(a)>=0)r=await(0,n.buildBn128)(i);else if([`BLS12381`].indexOf(a)>=0)r=await(0,n.buildBls12381)(i);else throw Error(`Curve not supported: ${e}`);return r;function o(e){return e.toUpperCase().match(/[A-Za-z0-9]+/g).join(``)}}function x(e){return e instanceof Uint8Array||ArrayBuffer.isView(e)&&e.constructor.name===`Uint8Array`&&`BYTES_PER_ELEMENT`in e&&e.BYTES_PER_ELEMENT===1}function S(e,t=``){if(typeof e!=`number`){let n=t&&`"${t}" `;throw TypeError(`${n}expected number, got ${typeof e}`)}if(!Number.isSafeInteger(e)||e<0){let n=t&&`"${t}" `;throw RangeError(`${n}expected integer >= 0, got ${e}`)}}function C(e,t,n=``){let r=x(e),i=e?.length,a=t!==void 0;if(!r||a&&i!==t){let o=n&&`"${n}" `,s=a?` of length ${t}`:``,c=r?`length=${i}`:`type=${typeof e}`,l=o+`expected Uint8Array`+s+`, got `+c;throw r?RangeError(l):TypeError(l)}return e}function w(e,t=!0){if(e.destroyed)throw Error(`Hash instance has been destroyed`);if(t&&e.finished)throw Error(`Hash#digest() has already been called`)}function T(e,t){C(e,void 0,`digestInto() output`);let n=t.outputLen;if(e.length=`+n)}function E(e){return new Uint32Array(e.buffer,e.byteOffset,Math.floor(e.byteLength/4))}function D(...e){for(let t=0;t>>8&65280|e>>>24&255}var A=O?e=>e:e=>k(e)>>>0;function j(e){for(let t=0;te:j;function N(e,t={}){let n=(t,n)=>e(n).update(t).digest(),r=e(void 0);return n.outputLen=r.outputLen,n.blockLen=r.blockLen,n.canXOF=r.canXOF,n.create=t=>e(t),Object.assign(n,t),Object.freeze(n)}var P=Uint8Array.from([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3,11,8,12,0,5,2,15,13,10,14,3,6,7,1,9,4,7,9,3,1,13,12,11,14,2,6,5,10,4,0,15,8,9,0,5,7,2,4,10,15,14,1,11,12,6,8,3,13,2,12,6,10,0,11,8,3,4,13,7,5,15,14,1,9,12,5,1,15,14,13,4,10,0,7,6,3,9,2,8,11,13,11,7,14,12,1,3,9,5,0,15,4,8,6,2,10,6,15,14,9,11,3,0,8,12,2,13,7,1,4,10,5,10,2,8,4,7,6,1,5,15,11,9,14,3,12,13,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3,11,8,12,0,5,2,15,13,10,14,3,6,7,1,9,4,7,9,3,1,13,12,11,14,2,6,5,10,4,0,15,8,9,0,5,7,2,4,10,15,14,1,11,12,6,8,3,13,2,12,6,10,0,11,8,3,4,13,7,5,15,14,1,9]),F=BigInt(2**32-1),I=BigInt(32);function L(e,t=!1){return t?{h:Number(e&F),l:Number(e>>I&F)}:{h:Number(e>>I&F)|0,l:Number(e&F)|0}}function R(e,t=!1){let n=e.length,r=new Uint32Array(n),i=new Uint32Array(n);for(let a=0;ae>>>n|t<<32-n,ee=(e,t,n)=>e<<32-n|t>>>n,te=(e,t,n)=>e<<64-n|t>>>n-32,ne=(e,t,n)=>e>>>n-32|t<<64-n,re=(e,t)=>t,ie=(e,t)=>e,ae=(e,t,n)=>e<>>32-n,oe=(e,t,n)=>t<>>32-n,se=(e,t,n)=>t<>>64-n,ce=(e,t,n)=>e<>>64-n;function le(e,t,n,r){let i=(t>>>0)+(r>>>0);return{h:e+n+(i/2**32|0)|0,l:i|0}}var ue=(e,t,n)=>(e>>>0)+(t>>>0)+(n>>>0),de=(e,t,n,r)=>t+n+r+(e/2**32|0)|0,B=Uint32Array.from([4089235720,1779033703,2227873595,3144134277,4271175723,1013904242,1595750129,2773480762,2917565137,1359893119,725511199,2600822924,4215389547,528734635,327033209,1541459225]),V=new Uint32Array(32);function fe(e,t,n,r,i,a){let o=i[a],s=i[a+1],c=V[2*e],l=V[2*e+1],u=V[2*t],d=V[2*t+1],f=V[2*n],p=V[2*n+1],m=V[2*r],h=V[2*r+1],g=ue(c,u,o);l=de(g,l,d,s),c=g|0,{Dh:h,Dl:m}={Dh:h^l,Dl:m^c},{Dh:h,Dl:m}={Dh:re(h,m),Dl:ie(h,m)},{h:p,l:f}=le(p,f,h,m),{Bh:d,Bl:u}={Bh:d^p,Bl:u^f},{Bh:d,Bl:u}={Bh:z(d,u,24),Bl:ee(d,u,24)},V[2*e]=c,V[2*e+1]=l,V[2*t]=u,V[2*t+1]=d,V[2*n]=f,V[2*n+1]=p,V[2*r]=m,V[2*r+1]=h}function pe(e,t,n,r,i,a){let o=i[a],s=i[a+1],c=V[2*e],l=V[2*e+1],u=V[2*t],d=V[2*t+1],f=V[2*n],p=V[2*n+1],m=V[2*r],h=V[2*r+1],g=ue(c,u,o);l=de(g,l,d,s),c=g|0,{Dh:h,Dl:m}={Dh:h^l,Dl:m^c},{Dh:h,Dl:m}={Dh:z(h,m,16),Dl:ee(h,m,16)},{h:p,l:f}=le(p,f,h,m),{Bh:d,Bl:u}={Bh:d^p,Bl:u^f},{Bh:d,Bl:u}={Bh:te(d,u,63),Bl:ne(d,u,63)},V[2*e]=c,V[2*e+1]=l,V[2*t]=u,V[2*t+1]=d,V[2*n]=f,V[2*n+1]=p,V[2*r]=m,V[2*r+1]=h}function me(e,t={},n,r,i){if(S(n),e<=0||e>n)throw Error(`outputLen bigger than keyLen`);let{key:a,salt:o,personalization:s}=t;if(a!==void 0&&(a.length<1||a.length>n))throw Error(`"key" expected to be undefined or of length=1..`+n);o!==void 0&&C(o,r,`salt`),s!==void 0&&C(s,i,`personalization`)}var he=class{buffer;buffer32;finished=!1;destroyed=!1;length=0;pos=0;blockLen;outputLen;canXOF=!1;constructor(e,t){S(e),S(t),this.blockLen=e,this.outputLen=t,this.buffer=new Uint8Array(e),this.buffer32=E(this.buffer)}update(e){w(this),C(e);let{blockLen:t,buffer:n,buffer32:r}=this,i=e.length,a=e.byteOffset,o=e.buffer;for(let s=0;s>>8*t}digest(){let{buffer:e,outputLen:t}=this;this.digestInto(e);let n=e.slice(0,t);return this.destroy(),n}_cloneInto(e){let{buffer:t,length:n,finished:r,destroyed:i,outputLen:a,pos:o}=this;return e||=new this.constructor({dkLen:a}),e.set(...this.get()),e.buffer.set(t),e.destroyed=i,e.finished=r,e.length=n,e.pos=o,e.outputLen=a,e}clone(){return this._cloneInto()}},ge=class extends he{v0l=B[0]|0;v0h=B[1]|0;v1l=B[2]|0;v1h=B[3]|0;v2l=B[4]|0;v2h=B[5]|0;v3l=B[6]|0;v3h=B[7]|0;v4l=B[8]|0;v4h=B[9]|0;v5l=B[10]|0;v5h=B[11]|0;v6l=B[12]|0;v6h=B[13]|0;v7l=B[14]|0;v7h=B[15]|0;constructor(e={}){let t=e.dkLen===void 0?64:e.dkLen;super(128,t),me(t,e,64,16,16);let{key:n,personalization:r,salt:i}=e,a=0;if(n!==void 0&&(C(n,void 0,`key`),a=n.length),this.v0l^=this.outputLen|a<<8|16842752,i!==void 0){C(i,void 0,`salt`);let e=E(i);this.v4l^=A(e[0]),this.v4h^=A(e[1]),this.v5l^=A(e[2]),this.v5h^=A(e[3])}if(r!==void 0){C(r,void 0,`personalization`);let e=E(r);this.v6l^=A(e[0]),this.v6h^=A(e[1]),this.v7l^=A(e[2]),this.v7h^=A(e[3])}if(n!==void 0){let e=new Uint8Array(this.blockLen);e.set(n),this.update(e)}}get(){let{v0l:e,v0h:t,v1l:n,v1h:r,v2l:i,v2h:a,v3l:o,v3h:s,v4l:c,v4h:l,v5l:u,v5h:d,v6l:f,v6h:p,v7l:m,v7h:h}=this;return[e,t,n,r,i,a,o,s,c,l,u,d,f,p,m,h]}set(e,t,n,r,i,a,o,s,c,l,u,d,f,p,m,h){this.v0l=e|0,this.v0h=t|0,this.v1l=n|0,this.v1h=r|0,this.v2l=i|0,this.v2h=a|0,this.v3l=o|0,this.v3h=s|0,this.v4l=c|0,this.v4h=l|0,this.v5l=u|0,this.v5h=d|0,this.v6l=f|0,this.v6h=p|0,this.v7l=m|0,this.v7h=h|0}compress(e,t,n){this.get().forEach((e,t)=>V[t]=e),V.set(B,16);let{h:r,l:i}=L(BigInt(this.length));V[24]=B[8]^i,V[25]=B[9]^r,n&&(V[28]=~V[28],V[29]=~V[29]);let a=0,o=P;for(let n=0;n<12;n++)fe(0,4,8,12,e,t+2*o[a++]),pe(0,4,8,12,e,t+2*o[a++]),fe(1,5,9,13,e,t+2*o[a++]),pe(1,5,9,13,e,t+2*o[a++]),fe(2,6,10,14,e,t+2*o[a++]),pe(2,6,10,14,e,t+2*o[a++]),fe(3,7,11,15,e,t+2*o[a++]),pe(3,7,11,15,e,t+2*o[a++]),fe(0,5,10,15,e,t+2*o[a++]),pe(0,5,10,15,e,t+2*o[a++]),fe(1,6,11,12,e,t+2*o[a++]),pe(1,6,11,12,e,t+2*o[a++]),fe(2,7,8,13,e,t+2*o[a++]),pe(2,7,8,13,e,t+2*o[a++]),fe(3,4,9,14,e,t+2*o[a++]),pe(3,4,9,14,e,t+2*o[a++]);this.v0l^=V[0]^V[16],this.v0h^=V[1]^V[17],this.v1l^=V[2]^V[18],this.v1h^=V[3]^V[19],this.v2l^=V[4]^V[20],this.v2h^=V[5]^V[21],this.v3l^=V[6]^V[22],this.v3h^=V[7]^V[23],this.v4l^=V[8]^V[24],this.v4h^=V[9]^V[25],this.v5l^=V[10]^V[26],this.v5h^=V[11]^V[27],this.v6l^=V[12]^V[28],this.v6h^=V[13]^V[29],this.v7l^=V[14]^V[30],this.v7h^=V[15]^V[31],D(V)}destroy(){this.destroyed=!0,D(this.buffer32),this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)}},H=N(e=>new ge(e));u(((e,t)=>{t.exports={}}))();var _e=[];for(let e=0;e<256;e++)_e[e]=ve(e,8);function ve(e,t){let n=0,r=e;for(let e=0;e>=1;return n}function ye(e){return(e&4294901760?(e&=4294901760,16):0)|(e&4278255360?(e&=4278255360,8):0)|(e&4042322160?(e&=4042322160,4):0)|(e&3435973836?(e&=3435973836,2):0)|(e&2863311530)!=0}function U(e,t){let n=new DataView(e.buffer,e.byteOffset,e.byteLength),r=``;for(let e=0;e<4;e++){e>0&&(r+=` `),r+=` `;for(let t=0;t<4;t++)t>0&&(r+=` `),r+=n.getUint32(e*16+t*4).toString(16).padStart(8,`0`)}return t&&(r=t+` -`+r),r}function be(e,t){if(e.byteLength!=t.byteLength)return!1;for(var n=new Int8Array(e),r=new Int8Array(t),i=0;i!=e.byteLength;i++)if(n[i]!=r[i])return!1;return!0}function xe(e){return e.clone()}function Se(e){let t=e.subarray(0,128),n=E(e.subarray(128)),r=H.create({dkLen:64});r.buffer.set(t),r.v0l=n[0]|0,r.v0h=n[1]|0,r.v1l=n[2]|0,r.v1h=n[3]|0,r.v2l=n[4]|0,r.v2h=n[5]|0,r.v3l=n[6]|0,r.v3h=n[7]|0,r.v4l=n[8]|0,r.v4h=n[9]|0,r.v5l=n[10]|0,r.v5h=n[11]|0,r.v6l=n[12]|0,r.v6h=n[13]|0,r.v7l=n[14]|0,r.v7h=n[15]|0;let i=2**32,a=n[16]+n[17]*i,o=n[18]+n[19]*i;return r.length=a+o,r.pos=o,r}function Ce(e){let t=new Uint8Array(216),n=E(t.subarray(128));return t.set(e.buffer),n[0]=e.v0l,n[1]=e.v0h,n[2]=e.v1l,n[3]=e.v1h,n[4]=e.v2l,n[5]=e.v2h,n[6]=e.v3l,n[7]=e.v3h,n[8]=e.v4l,n[9]=e.v4h,n[10]=e.v5l,n[11]=e.v5h,n[12]=e.v6l,n[13]=e.v6h,n[14]=e.v7l,n[15]=e.v7h,n[18]=e.pos,n[16]=e.length-e.pos,t}async function we(e,t,n,r,i){return e.G1.isZero(t)||e.G1.isZero(n)||e.G2.isZero(r)||e.G2.isZero(i)?!1:await e.pairingEq(t,i,e.G1.neg(n),r)}function Te(){return window.prompt(`Enter a random text. (Entropy): `,``)}function Ee(e){let t=new Uint8Array(e);return globalThis.crypto.getRandomValues(t),t}async function De(e){{let t=await globalThis.crypto.subtle.digest(`SHA-256`,e.buffer);return new Uint8Array(t)}}function Oe(e,t){return new DataView(e.buffer).getUint32(t,!1)}async function ke(e){for(;!e;)e=await Te();let t=H.create(64);t.update(Ee(64));let r=new TextEncoder;t.update(r.encode(e));let i=t.digest(),a=[];for(let e=0;e<8;e++)a[e]=Oe(i,e*4);return new n.ChaCha(a)}async function Ae(e,t){let r,i;t<32?(r=1<>>0,i=1):(r=4294967296,i=1<>>0);let a=e;for(let e=0;e{n[r]=Ne(e,t[r])}),n}else if(typeof t==`bigint`||t.eq!==void 0)return t.toString(10);else return t}async function Pe(e,r){await t.startWriteSection(e,1),await e.writeULE32(1),await t.endWriteSection(e);let i=await y(r.q);await t.startWriteSection(e,2);let a=i.q,o=(Math.floor((n.Scalar.bitLength(a)-1)/64)+1)*8,s=i.r,c=(Math.floor((n.Scalar.bitLength(s)-1)/64)+1)*8;await e.writeULE32(o),await t.writeBigInt(e,a,o),await e.writeULE32(c),await t.writeBigInt(e,s,c),await e.writeULE32(r.nVars),await e.writeULE32(r.nPublic),await e.writeULE32(r.domainSize),await Fe(e,i,r.vk_alpha_1),await Fe(e,i,r.vk_beta_1),await Ie(e,i,r.vk_beta_2),await Ie(e,i,r.vk_gamma_2),await Fe(e,i,r.vk_delta_1),await Ie(e,i,r.vk_delta_2),await t.endWriteSection(e)}async function Fe(e,t,n){let r=new Uint8Array(t.G1.F.n8*2);t.G1.toRprLEM(r,0,n),await e.write(r)}async function Ie(e,t,n){let r=new Uint8Array(t.G2.F.n8*2);t.G2.toRprLEM(r,0,n),await e.write(r)}async function W(e,t,n){let r=await e.read(t.G1.F.n8*2),i=t.G1.fromRprLEM(r,0);return n?t.G1.toObject(i):i}async function Le(e,t,n){let r=await e.read(t.G2.F.n8*2),i=t.G2.fromRprLEM(r,0);return n?t.G2.toObject(i):i}async function Re(e,n,r,i){await t.startReadUniqueSection(e,n,1);let a=await e.readULE32();if(await t.endReadSection(e),a===1)return await ze(e,n,r,i);if(a===2)return await Be(e,n,r,i);if(a===10)return await Ve(e,n,r,i);throw Error(`Protocol not supported: `)}async function ze(e,n,r,i){let a={};a.protocol=`groth16`,await t.startReadUniqueSection(e,n,2);let o=await e.readULE32();a.n8q=o,a.q=await t.readBigInt(e,o);let s=await e.readULE32();return a.n8r=s,a.r=await t.readBigInt(e,s),a.curve=await y(a.q,i),a.nVars=await e.readULE32(),a.nPublic=await e.readULE32(),a.domainSize=await e.readULE32(),a.power=ye(a.domainSize),a.vk_alpha_1=await W(e,a.curve,r),a.vk_beta_1=await W(e,a.curve,r),a.vk_beta_2=await Le(e,a.curve,r),a.vk_gamma_2=await Le(e,a.curve,r),a.vk_delta_1=await W(e,a.curve,r),a.vk_delta_2=await Le(e,a.curve,r),await t.endReadSection(e),a}async function Be(e,n,r,i){let a={};a.protocol=`plonk`,await t.startReadUniqueSection(e,n,2);let o=await e.readULE32();a.n8q=o,a.q=await t.readBigInt(e,o);let s=await e.readULE32();return a.n8r=s,a.r=await t.readBigInt(e,s),a.curve=await y(a.q,i),a.nVars=await e.readULE32(),a.nPublic=await e.readULE32(),a.domainSize=await e.readULE32(),a.power=ye(a.domainSize),a.nAdditions=await e.readULE32(),a.nConstraints=await e.readULE32(),a.k1=await e.read(s),a.k2=await e.read(s),a.Qm=await W(e,a.curve,r),a.Ql=await W(e,a.curve,r),a.Qr=await W(e,a.curve,r),a.Qo=await W(e,a.curve,r),a.Qc=await W(e,a.curve,r),a.S1=await W(e,a.curve,r),a.S2=await W(e,a.curve,r),a.S3=await W(e,a.curve,r),a.X_2=await Le(e,a.curve,r),await t.endReadSection(e),a}async function Ve(e,n,r,i){let a={};a.protocol=`fflonk`,a.protocolId=10,await t.startReadUniqueSection(e,n,2);let o=await e.readULE32();a.n8q=o,a.q=await t.readBigInt(e,o),a.curve=await y(a.q,i);let s=await e.readULE32();return a.n8r=s,a.r=await t.readBigInt(e,s),a.nVars=await e.readULE32(),a.nPublic=await e.readULE32(),a.domainSize=await e.readULE32(),a.power=ye(a.domainSize),a.nAdditions=await e.readULE32(),a.nConstraints=await e.readULE32(),a.k1=await e.read(s),a.k2=await e.read(s),a.w3=await e.read(s),a.w4=await e.read(s),a.w8=await e.read(s),a.wr=await e.read(s),a.X_2=await Le(e,a.curve,r),a.C0=await W(e,a.curve,r),await t.endReadSection(e),a}async function He(e,r){let{fd:i,sections:a}=await t.readBinFile(e,`zkey`,1),o=await Re(i,a,r),s=new n.F1Field(o.r),c=n.Scalar.mod(n.Scalar.shl(1,o.n8r*8),o.r),l=s.inv(c),u=s.mul(l,l),d=await y(o.q);await t.startReadUniqueSection(i,a,3),o.IC=[];for(let e=0;e<=o.nPublic;e++){let e=await W(i,d,r);o.IC.push(e)}await t.endReadSection(i),await t.startReadUniqueSection(i,a,4);let f=await i.readULE32();o.ccoefs=[];for(let e=0;e0){let t=new Uint8Array(r);await e.writeULE32(t.byteLength),await e.write(t)}else await e.writeULE32(0)}async function Ke(e,n,r){await t.startWriteSection(e,10),await e.write(r.csHash),await e.writeULE32(r.contributions.length);for(let t=0;t2**16;)o*=2,l=Math.floor(t.domainSize/o);console.log(`@@@ new elementsPerChunk`,l);let u=[],d=[];for(let e=0;e1){let t=[];for(let n=0;ne?n=r-1:i1){let t=[];for(let n=0;n<1;n++){let r=[];r.push({cmd:`ALLOC`,var:0,len:f[n][0].byteLength}),r.push({cmd:`ALLOC`,var:1,len:f[n][0].byteLength});for(let t=0;t<3;t++){r.push({cmd:`SET`,var:0,buff:f[n][t]});for(let i=1;ie?n=r-1:i`u`||!process.memoryUsage)return;let t=process.memoryUsage();e.debug(` `,`\x1B[0m Heap:\x1B[32m`,`${Math.round(t.heapUsed/1024/1024*100)/100} MB`.padEnd(12),`\x1B[0m / \x1B[32m`,`${Math.round(t.heapTotal/1024/1024*100)/100} MB`.padEnd(12),`\x1B[0m RSS:\x1B[32m`,`${Math.round(t.rss/1024/1024*100)/100} MB`.padEnd(12),`\x1B[0m External:\x1B[32m`,`${Math.round(t.external/1024/1024*100)/100} MB`.padEnd(12),`\x1B[0m ArrBuffers:\x1B[32m`,`${Math.round(t.arrayBuffers/1024/1024*100)/100} MB`.padEnd(12),`\x1B[0m`)}function st(e,t=5e3){return setInterval(()=>{ot(e)},t)}function ct(e){let t=e.initialSize||1<<20,n=new mt;return n.o=e,n.o.data=new Uint8Array(t),n.allocSize=t,n.totalSize=0,n.readOnly=!1,n.pos=0,n}function lt(e){let t=new mt;return t.o=e,t.allocSize=e.data.byteLength,t.totalSize=e.data.byteLength,t.readOnly=!0,t.pos=0,t}var ut=new Uint8Array(4),dt=new DataView(ut.buffer),ft=new Uint8Array(8),pt=new DataView(ft.buffer),mt=class{constructor(){this.pageSize=16384}_resizeIfNeeded(e){if(e>this.allocSize){let t=Math.max(this.allocSize+(1<<20),Math.floor(this.allocSize*1.1),e),n=new Uint8Array(t);n.set(this.o.data),this.o.data=n,this.allocSize=t}}async write(e,t){if(t===void 0&&(t=this.pos),this.readOnly)throw Error(`Writing a read only file`);this._resizeIfNeeded(t+e.byteLength),this.o.data.set(e.slice(),t),t+e.byteLength>this.totalSize&&(this.totalSize=t+e.byteLength),this.pos=t+e.byteLength}async readToBuffer(e,t,n,r){if(r===void 0&&(r=this.pos),this.readOnly&&r+n>this.totalSize)throw Error(`Reading out of bounds`);this._resizeIfNeeded(r+n);let i=new Uint8Array(this.o.data.buffer,this.o.data.byteOffset+r,n);e.set(i,t),this.pos=r+n}async read(e,t){let n=this,r=new Uint8Array(e);return await n.readToBuffer(r,0,e,t),r}close(){this.o.data.byteLength!=this.totalSize&&(this.o.data=this.o.data.slice(0,this.totalSize))}async discard(){}async writeULE32(e,t){let n=this;dt.setUint32(0,e,!0),await n.write(ut,t)}async writeUBE32(e,t){let n=this;dt.setUint32(0,e,!1),await n.write(ut,t)}async writeULE64(e,t){let n=this;pt.setUint32(0,e&4294967295,!0),pt.setUint32(4,Math.floor(e/4294967296),!0),await n.write(ft,t)}async readULE32(e){let t=await this.read(4,e);return new Uint32Array(t.buffer)[0]}async readUBE32(e){let t=await this.read(4,e);return new DataView(t.buffer).getUint32(0,!1)}async readULE64(e){let t=await this.read(8,e),n=new Uint32Array(t.buffer);return n[1]*4294967296+n[0]}async readString(e){let t=this,n=e===void 0?t.pos:e;if(n>this.totalSize){if(this.readOnly)throw Error(`Reading out of bounds`);this._resizeIfNeeded(e)}let r=new Uint8Array(t.o.data.buffer,n,this.totalSize-n),i=r.findIndex(e=>e===0),a=i!==-1,o=``;return a?(o=new TextDecoder().decode(r.slice(0,i)),t.pos=n+i+1):t.pos=n,o}},G=1<<22;function ht(e){let t=e.initialSize||0,n=new xt;n.o=e;let r=t?Math.floor((t-1)/G)+1:0;n.o.data=[];for(let e=0;e0;){let t=i+a>G?G-i:a,o=e.slice(e.byteLength-a,e.byteLength-a+t);new Uint8Array(n.o.data[r].buffer,i,t).set(o),a-=t,r++,i=0}this.pos=t+e.byteLength}async readToBuffer(e,t,n,r){let i=this;if(r===void 0&&(r=i.pos),this.readOnly&&r+n>this.totalSize)throw Error(`Reading out of bounds`);this._resizeIfNeeded(r+n);let a=Math.floor(r/G),o=r%G,s=n;for(;s>0;){let r=o+s>G?G-o:s,c=new Uint8Array(i.o.data[a].buffer,o,r);e.set(c,t+n-s),s-=r,a++,o=0}this.pos=r+n}async read(e,t){let n=this,r=new Uint8Array(e);return await n.readToBuffer(r,0,e,t),r}close(){}async discard(){}async writeULE32(e,t){let n=this;vt.setUint32(0,e,!0),await n.write(_t,t)}async writeUBE32(e,t){let n=this;vt.setUint32(0,e,!1),await n.write(_t,t)}async writeULE64(e,t){let n=this;bt.setUint32(0,e&4294967295,!0),bt.setUint32(4,Math.floor(e/4294967296),!0),await n.write(yt,t)}async readULE32(e){let t=await this.read(4,e);return new Uint32Array(t.buffer)[0]}async readUBE32(e){let t=await this.read(4,e);return new DataView(t.buffer).getUint32(0,!1)}async readULE64(e){let t=await this.read(8,e),n=new Uint32Array(t.buffer);return n[1]*4294967296+n[0]}async readString(e){let t=this,n=e===void 0?t.pos:e;if(n>this.totalSize){if(this.readOnly)throw Error(`Reading out of bounds`);this._resizeIfNeeded(e)}let r=!1,i=``;for(;!r;){let e=Math.floor(n/G),a=n%G;if(t.o.data[e]===void 0)throw Error(`ERROR`);let o=Math.min(2048,t.o.data[e].length-a),s=new Uint8Array(t.o.data[e].buffer,a,o),c=s.findIndex(e=>e===0);r=c!==-1,r?(i+=new TextDecoder().decode(s.slice(0,c)),t.pos=e*G+a+c+1):(i+=new TextDecoder().decode(s),t.pos=e*G+a+s.length),n=t.pos}return i}},St=65536;function Ct(){throw Error(`File I/O is not supported in the browser`)}function wt(e,t){return e instanceof Uint8Array?{type:`mem`,data:e}:typeof e==`string`?{type:`mem`,initialSize:t||St}:e}async function Tt(e){let t=await fetch(e).then(e=>e.arrayBuffer());return{type:`mem`,data:new Uint8Array(t)}}function Et(e,t,n){if(e.type===`file`&&Ct(),e.type===`mem`)return t(e);if(e.type===`bigMem`)return n(e);throw Error(`Invalid FastFile type: `+e.type)}function Dt(e,t){return Et(wt(e,t),ct,ht)}async function Ot(e){return e=typeof e==`string`?await Tt(e):wt(e),Et(e,lt,gt)}function kt(e){let t=[];return n(t,e),t;function n(e,t){if(Array.isArray(t))for(let r=0;r0;)n.unshift(0),e--}return n}async function Nt(e,t){let r,i,a;t||={};let o=1,s=0,c=0,l=!1;if(e instanceof WebAssembly.Instance)r=e,l=!0;else{let l=32767;if(t.memorySize&&(l=parseInt(t.memorySize),l<0))throw Error(`Invalid memory size`);let u=!1;for(;!u;)try{a=new WebAssembly.Memory({initial:l}),u=!0}catch(e){if(l<=1)throw e;console.warn(`Could not allocate `+l*1024*64+` bytes. This may cause severe instability. Trying with `+l*1024*64/2+` bytes`),l=Math.floor(l/2)}let p=await WebAssembly.compile(e),m=``,h=``;r=await WebAssembly.instantiate(p,{env:{memory:a},runtime:{printDebug:function(e){console.log(`printDebug:`,e)},exceptionHandler:function(e){let t;throw t=e===1?`Signal not found. `:e===2?`Too many signals set. `:e===3?`Signal already set. `:e===4?`Assert Failed. `:e===5?`Not enough memory. `:e===6?`Input signal array access exceeds the size. `:`Unknown error. `,console.error(`ERROR: `,e,m),Error(t+m)},printErrorMessage:function(){m+=d()+` +`+r),r}function be(e,t){if(e.byteLength!=t.byteLength)return!1;for(var n=new Int8Array(e),r=new Int8Array(t),i=0;i!=e.byteLength;i++)if(n[i]!=r[i])return!1;return!0}function xe(e){return e.clone()}function Se(e){let t=e.subarray(0,128),n=E(e.subarray(128)),r=H.create({dkLen:64});r.buffer.set(t),r.v0l=n[0]|0,r.v0h=n[1]|0,r.v1l=n[2]|0,r.v1h=n[3]|0,r.v2l=n[4]|0,r.v2h=n[5]|0,r.v3l=n[6]|0,r.v3h=n[7]|0,r.v4l=n[8]|0,r.v4h=n[9]|0,r.v5l=n[10]|0,r.v5h=n[11]|0,r.v6l=n[12]|0,r.v6h=n[13]|0,r.v7l=n[14]|0,r.v7h=n[15]|0;let i=2**32,a=n[16]+n[17]*i,o=n[18]+n[19]*i;return r.length=a+o,r.pos=o,r}function Ce(e){let t=new Uint8Array(216),n=E(t.subarray(128));return t.set(e.buffer),n[0]=e.v0l,n[1]=e.v0h,n[2]=e.v1l,n[3]=e.v1h,n[4]=e.v2l,n[5]=e.v2h,n[6]=e.v3l,n[7]=e.v3h,n[8]=e.v4l,n[9]=e.v4h,n[10]=e.v5l,n[11]=e.v5h,n[12]=e.v6l,n[13]=e.v6h,n[14]=e.v7l,n[15]=e.v7h,n[18]=e.pos,n[16]=e.length-e.pos,t}async function we(e,t,n,r,i){return e.G1.isZero(t)||e.G1.isZero(n)||e.G2.isZero(r)||e.G2.isZero(i)?!1:await e.pairingEq(t,i,e.G1.neg(n),r)}function Te(){return window.prompt(`Enter a random text. (Entropy): `,``)}function Ee(e){let t=new Uint8Array(e);return globalThis.crypto.getRandomValues(t),t}async function De(e){{let t=await globalThis.crypto.subtle.digest(`SHA-256`,e.buffer);return new Uint8Array(t)}}function Oe(e,t){return new DataView(e.buffer).getUint32(t,!1)}async function ke(e){for(;!e;)e=await Te();let t=H.create(64);t.update(Ee(64));let r=new TextEncoder;t.update(r.encode(e));let i=t.digest(),a=[];for(let e=0;e<8;e++)a[e]=Oe(i,e*4);return new n.ChaCha(a)}async function Ae(e,t){let r,i;t<32?(r=1<>>0,i=1):(r=4294967296,i=1<>>0);let a=e;for(let e=0;e{n[r]=Ne(e,t[r])}),n}else if(typeof t==`bigint`||t.eq!==void 0)return t.toString(10);else return t}async function Pe(e,r){await t.startWriteSection(e,1),await e.writeULE32(1),await t.endWriteSection(e);let i=await y(r.q);await t.startWriteSection(e,2);let a=i.q,o=(Math.floor((n.Scalar.bitLength(a)-1)/64)+1)*8,s=i.r,c=(Math.floor((n.Scalar.bitLength(s)-1)/64)+1)*8;await e.writeULE32(o),await t.writeBigInt(e,a,o),await e.writeULE32(c),await t.writeBigInt(e,s,c),await e.writeULE32(r.nVars),await e.writeULE32(r.nPublic),await e.writeULE32(r.domainSize),await Fe(e,i,r.vk_alpha_1),await Fe(e,i,r.vk_beta_1),await Ie(e,i,r.vk_beta_2),await Ie(e,i,r.vk_gamma_2),await Fe(e,i,r.vk_delta_1),await Ie(e,i,r.vk_delta_2),await t.endWriteSection(e)}async function Fe(e,t,n){let r=new Uint8Array(t.G1.F.n8*2);t.G1.toRprLEM(r,0,n),await e.write(r)}async function Ie(e,t,n){let r=new Uint8Array(t.G2.F.n8*2);t.G2.toRprLEM(r,0,n),await e.write(r)}async function W(e,t,n){let r=await e.read(t.G1.F.n8*2),i=t.G1.fromRprLEM(r,0);return n?t.G1.toObject(i):i}async function Le(e,t,n){let r=await e.read(t.G2.F.n8*2),i=t.G2.fromRprLEM(r,0);return n?t.G2.toObject(i):i}async function Re(e,n,r,i){await t.startReadUniqueSection(e,n,1);let a=await e.readULE32();if(await t.endReadSection(e),a===1)return await ze(e,n,r,i);if(a===2)return await Be(e,n,r,i);if(a===10)return await Ve(e,n,r,i);throw Error(`Protocol not supported: `)}async function ze(e,n,r,i){let a={};a.protocol=`groth16`,await t.startReadUniqueSection(e,n,2);let o=await e.readULE32();a.n8q=o,a.q=await t.readBigInt(e,o);let s=await e.readULE32();return a.n8r=s,a.r=await t.readBigInt(e,s),a.curve=await y(a.q,i),a.nVars=await e.readULE32(),a.nPublic=await e.readULE32(),a.domainSize=await e.readULE32(),a.power=ye(a.domainSize),a.vk_alpha_1=await W(e,a.curve,r),a.vk_beta_1=await W(e,a.curve,r),a.vk_beta_2=await Le(e,a.curve,r),a.vk_gamma_2=await Le(e,a.curve,r),a.vk_delta_1=await W(e,a.curve,r),a.vk_delta_2=await Le(e,a.curve,r),await t.endReadSection(e),a}async function Be(e,n,r,i){let a={};a.protocol=`plonk`,await t.startReadUniqueSection(e,n,2);let o=await e.readULE32();a.n8q=o,a.q=await t.readBigInt(e,o);let s=await e.readULE32();return a.n8r=s,a.r=await t.readBigInt(e,s),a.curve=await y(a.q,i),a.nVars=await e.readULE32(),a.nPublic=await e.readULE32(),a.domainSize=await e.readULE32(),a.power=ye(a.domainSize),a.nAdditions=await e.readULE32(),a.nConstraints=await e.readULE32(),a.k1=await e.read(s),a.k2=await e.read(s),a.Qm=await W(e,a.curve,r),a.Ql=await W(e,a.curve,r),a.Qr=await W(e,a.curve,r),a.Qo=await W(e,a.curve,r),a.Qc=await W(e,a.curve,r),a.S1=await W(e,a.curve,r),a.S2=await W(e,a.curve,r),a.S3=await W(e,a.curve,r),a.X_2=await Le(e,a.curve,r),await t.endReadSection(e),a}async function Ve(e,n,r,i){let a={};a.protocol=`fflonk`,a.protocolId=10,await t.startReadUniqueSection(e,n,2);let o=await e.readULE32();a.n8q=o,a.q=await t.readBigInt(e,o),a.curve=await y(a.q,i);let s=await e.readULE32();return a.n8r=s,a.r=await t.readBigInt(e,s),a.nVars=await e.readULE32(),a.nPublic=await e.readULE32(),a.domainSize=await e.readULE32(),a.power=ye(a.domainSize),a.nAdditions=await e.readULE32(),a.nConstraints=await e.readULE32(),a.k1=await e.read(s),a.k2=await e.read(s),a.w3=await e.read(s),a.w4=await e.read(s),a.w8=await e.read(s),a.wr=await e.read(s),a.X_2=await Le(e,a.curve,r),a.C0=await W(e,a.curve,r),await t.endReadSection(e),a}async function He(e,r){let{fd:i,sections:a}=await t.readBinFile(e,`zkey`,1),o=await Re(i,a,r),s=new n.F1Field(o.r),c=n.Scalar.mod(n.Scalar.shl(1,o.n8r*8),o.r),l=s.inv(c),u=s.mul(l,l),d=await y(o.q);await t.startReadUniqueSection(i,a,3),o.IC=[];for(let e=0;e<=o.nPublic;e++){let e=await W(i,d,r);o.IC.push(e)}await t.endReadSection(i),await t.startReadUniqueSection(i,a,4);let f=await i.readULE32();o.ccoefs=[];for(let e=0;e0){let t=new Uint8Array(r);await e.writeULE32(t.byteLength),await e.write(t)}else await e.writeULE32(0)}async function Ke(e,n,r){await t.startWriteSection(e,10),await e.write(r.csHash),await e.writeULE32(r.contributions.length);for(let t=0;t2**16;)o*=2,l=Math.floor(t.domainSize/o);let u=[],d=[];for(let e=0;e1){let t=[];for(let n=0;ne?n=r-1:i1){let t=[];for(let n=0;n<1;n++){let r=[];r.push({cmd:`ALLOC`,var:0,len:f[n][0].byteLength}),r.push({cmd:`ALLOC`,var:1,len:f[n][0].byteLength});for(let t=0;t<3;t++){r.push({cmd:`SET`,var:0,buff:f[n][t]});for(let i=1;ie?n=r-1:i`u`||!process.memoryUsage)return;let t=process.memoryUsage();e.debug(` `,`\x1B[0m Heap:\x1B[32m`,`${Math.round(t.heapUsed/1024/1024*100)/100} MB`.padEnd(12),`\x1B[0m / \x1B[32m`,`${Math.round(t.heapTotal/1024/1024*100)/100} MB`.padEnd(12),`\x1B[0m RSS:\x1B[32m`,`${Math.round(t.rss/1024/1024*100)/100} MB`.padEnd(12),`\x1B[0m External:\x1B[32m`,`${Math.round(t.external/1024/1024*100)/100} MB`.padEnd(12),`\x1B[0m ArrBuffers:\x1B[32m`,`${Math.round(t.arrayBuffers/1024/1024*100)/100} MB`.padEnd(12),`\x1B[0m`)}function st(e,t=5e3){return setInterval(()=>{ot(e)},t)}function ct(e){let t=e.initialSize||1<<20,n=new mt;return n.o=e,n.o.data=new Uint8Array(t),n.allocSize=t,n.totalSize=0,n.readOnly=!1,n.pos=0,n}function lt(e){let t=new mt;return t.o=e,t.allocSize=e.data.byteLength,t.totalSize=e.data.byteLength,t.readOnly=!0,t.pos=0,t}var ut=new Uint8Array(4),dt=new DataView(ut.buffer),ft=new Uint8Array(8),pt=new DataView(ft.buffer),mt=class{constructor(){this.pageSize=16384}_resizeIfNeeded(e){if(e>this.allocSize){let t=Math.max(this.allocSize+(1<<20),Math.floor(this.allocSize*1.1),e),n=new Uint8Array(t);n.set(this.o.data),this.o.data=n,this.allocSize=t}}async write(e,t){if(t===void 0&&(t=this.pos),this.readOnly)throw Error(`Writing a read only file`);this._resizeIfNeeded(t+e.byteLength),this.o.data.set(e.slice(),t),t+e.byteLength>this.totalSize&&(this.totalSize=t+e.byteLength),this.pos=t+e.byteLength}async readToBuffer(e,t,n,r){if(r===void 0&&(r=this.pos),this.readOnly&&r+n>this.totalSize)throw Error(`Reading out of bounds`);this._resizeIfNeeded(r+n);let i=new Uint8Array(this.o.data.buffer,this.o.data.byteOffset+r,n);e.set(i,t),this.pos=r+n}async read(e,t){let n=this,r=new Uint8Array(e);return await n.readToBuffer(r,0,e,t),r}close(){this.o.data.byteLength!=this.totalSize&&(this.o.data=this.o.data.slice(0,this.totalSize))}async discard(){}async writeULE32(e,t){let n=this;dt.setUint32(0,e,!0),await n.write(ut,t)}async writeUBE32(e,t){let n=this;dt.setUint32(0,e,!1),await n.write(ut,t)}async writeULE64(e,t){let n=this;pt.setUint32(0,e&4294967295,!0),pt.setUint32(4,Math.floor(e/4294967296),!0),await n.write(ft,t)}async readULE32(e){let t=await this.read(4,e);return new Uint32Array(t.buffer)[0]}async readUBE32(e){let t=await this.read(4,e);return new DataView(t.buffer).getUint32(0,!1)}async readULE64(e){let t=await this.read(8,e),n=new Uint32Array(t.buffer);return n[1]*4294967296+n[0]}async readString(e){let t=this,n=e===void 0?t.pos:e;if(n>this.totalSize){if(this.readOnly)throw Error(`Reading out of bounds`);this._resizeIfNeeded(e)}let r=new Uint8Array(t.o.data.buffer,n,this.totalSize-n),i=r.findIndex(e=>e===0),a=i!==-1,o=``;return a?(o=new TextDecoder().decode(r.slice(0,i)),t.pos=n+i+1):t.pos=n,o}},G=1<<22;function ht(e){let t=e.initialSize||0,n=new xt;n.o=e;let r=t?Math.floor((t-1)/G)+1:0;n.o.data=[];for(let e=0;e0;){let t=i+a>G?G-i:a,o=e.slice(e.byteLength-a,e.byteLength-a+t);new Uint8Array(n.o.data[r].buffer,i,t).set(o),a-=t,r++,i=0}this.pos=t+e.byteLength}async readToBuffer(e,t,n,r){let i=this;if(r===void 0&&(r=i.pos),this.readOnly&&r+n>this.totalSize)throw Error(`Reading out of bounds`);this._resizeIfNeeded(r+n);let a=Math.floor(r/G),o=r%G,s=n;for(;s>0;){let r=o+s>G?G-o:s,c=new Uint8Array(i.o.data[a].buffer,o,r);e.set(c,t+n-s),s-=r,a++,o=0}this.pos=r+n}async read(e,t){let n=this,r=new Uint8Array(e);return await n.readToBuffer(r,0,e,t),r}close(){}async discard(){}async writeULE32(e,t){let n=this;vt.setUint32(0,e,!0),await n.write(_t,t)}async writeUBE32(e,t){let n=this;vt.setUint32(0,e,!1),await n.write(_t,t)}async writeULE64(e,t){let n=this;bt.setUint32(0,e&4294967295,!0),bt.setUint32(4,Math.floor(e/4294967296),!0),await n.write(yt,t)}async readULE32(e){let t=await this.read(4,e);return new Uint32Array(t.buffer)[0]}async readUBE32(e){let t=await this.read(4,e);return new DataView(t.buffer).getUint32(0,!1)}async readULE64(e){let t=await this.read(8,e),n=new Uint32Array(t.buffer);return n[1]*4294967296+n[0]}async readString(e){let t=this,n=e===void 0?t.pos:e;if(n>this.totalSize){if(this.readOnly)throw Error(`Reading out of bounds`);this._resizeIfNeeded(e)}let r=!1,i=``;for(;!r;){let e=Math.floor(n/G),a=n%G;if(t.o.data[e]===void 0)throw Error(`ERROR`);let o=Math.min(2048,t.o.data[e].length-a),s=new Uint8Array(t.o.data[e].buffer,a,o),c=s.findIndex(e=>e===0);r=c!==-1,r?(i+=new TextDecoder().decode(s.slice(0,c)),t.pos=e*G+a+c+1):(i+=new TextDecoder().decode(s),t.pos=e*G+a+s.length),n=t.pos}return i}},St=65536;function Ct(){throw Error(`File I/O is not supported in the browser`)}function wt(e,t){return e instanceof Uint8Array?{type:`mem`,data:e}:typeof e==`string`?{type:`mem`,initialSize:t||St}:e}async function Tt(e){let t=await fetch(e).then(e=>e.arrayBuffer());return{type:`mem`,data:new Uint8Array(t)}}function Et(e,t,n){if(e.type===`file`&&Ct(),e.type===`mem`)return t(e);if(e.type===`bigMem`)return n(e);throw Error(`Invalid FastFile type: `+e.type)}function Dt(e,t){return Et(wt(e,t),ct,ht)}async function Ot(e){return e=typeof e==`string`?await Tt(e):wt(e),Et(e,lt,gt)}function kt(e){let t=[];return n(t,e),t;function n(e,t){if(Array.isArray(t))for(let r=0;r0;)n.unshift(0),e--}return n}async function Nt(e,t){let r,i,a;t||={};let o=1,s=0,c=0,l=!1;if(e instanceof WebAssembly.Instance)r=e,l=!0;else{let l=32767;if(t.memorySize&&(l=parseInt(t.memorySize),l<0))throw Error(`Invalid memory size`);let u=!1;for(;!u;)try{a=new WebAssembly.Memory({initial:l}),u=!0}catch(e){if(l<=1)throw e;console.warn(`Could not allocate `+l*1024*64+` bytes. This may cause severe instability. Trying with `+l*1024*64/2+` bytes`),l=Math.floor(l/2)}let p=await WebAssembly.compile(e),m=``,h=``;r=await WebAssembly.instantiate(p,{env:{memory:a},runtime:{printDebug:function(e){console.log(`printDebug:`,e)},exceptionHandler:function(e){let t;throw t=e===1?`Signal not found. `:e===2?`Too many signals set. `:e===3?`Signal already set. `:e===4?`Assert Failed. `:e===5?`Not enough memory. `:e===6?`Input signal array access exceeds the size. `:`Unknown error. `,console.error(`ERROR: `,e,m),Error(t+m)},printErrorMessage:function(){m+=d()+` `},writeBufferMessage:function(){let e=d();e===` `?(console.log(h),h=``):(h!==``&&(h+=` `),h+=e)},showSharedRWMemory:function(){let e=r.exports.getFieldNumLen32(),t=new Uint32Array(e);for(let n=0;n=2&&(s>=1||c>=7)){h!==``&&(h+=` `);let e=n.Scalar.fromArray(t,4294967296).toString();h+=e}else console.log(n.Scalar.fromArray(t,4294967296))},error:function(e,n,r,a,o,s){let c;throw c=e===7?f(n)+` `+i.getFr(a).toString()+` != `+i.getFr(o).toString()+` `+f(s):e===9?f(n)+` `+i.getFr(a).toString()+` `+f(o):e===5&&t.sym?f(n)+` `+t.sym.labelIdx2Name[o]:f(n)+` `+r+` `+a+` `+o+` `+s,console.log(`ERROR: `,e,c),Error(c)},log:function(e){console.log(i.getFr(e).toString())},logGetSignal:function(e,n){t.logGetSignal&&t.logGetSignal(e,i.getFr(n))},logSetSignal:function(e,n){t.logSetSignal&&t.logSetSignal(e,i.getFr(n))},logStartComponent:function(e){t.logStartComponent&&t.logStartComponent(e)},logFinishComponent:function(e){t.logFinishComponent&&t.logFinishComponent(e)}}})}typeof r.exports.getVersion==`function`&&(o=r.exports.getVersion()),typeof r.exports.getMinorVersion==`function`&&(s=r.exports.getMinorVersion()),typeof r.exports.getPatchVersion==`function`&&(c=r.exports.getPatchVersion());let u=t&&(t.sanityCheck||t.logGetSignal||t.logSetSignal||t.logStartComponent||t.logFinishComponent);if(o===2)i=new Ft(r,u);else if(o===1){if(l)throw Error(`Loading code from WebAssembly instance is not supported for circom version 1`);i=new Pt(a,r,u)}else throw Error(`Unsupported circom version: ${o}`);return i;function d(){let e=``,t=r.exports.getMessageChar();for(;t!==0;)e+=String.fromCharCode(t),t=r.exports.getMessageChar();return e}function f(e){let t=new Uint8Array(a.buffer),n=[];for(let r=0;t[e+r]>0;r++)n.push(t[e+r]);return String.fromCharCode.apply(null,n)}}var Pt=class{constructor(e,t,r){this.memory=e,this.i32=new Uint32Array(e.buffer),this.instance=t,this.n32=(this.instance.exports.getFrLen()>>2)-2;let i=this.instance.exports.getPRawPrime(),a=Array(this.n32);for(let e=0;e>2)+e];this.prime=n.Scalar.fromArray(a,4294967296),this.Fr=new n.F1Field(this.prime),this.mask32=n.Scalar.fromString(`FFFFFFFF`,16),this.NVars=this.instance.exports.getNVars(),this.n64=Math.floor((this.Fr.bitLength-1)/64)+1,this.R=this.Fr.e(n.Scalar.shiftLeft(1,this.n64*64)),this.RInv=this.Fr.inv(this.R),this.sanityCheck=r}circom_version(){return 1}async _doCalculateWitness(e,t){this.instance.exports.init(this.sanityCheck||t?1:0);let n=this.allocInt(),r=this.allocFr();Object.keys(e).forEach(t=>{let i=jt(t),a=parseInt(i.slice(0,8),16),o=parseInt(i.slice(8,16),16);try{this.instance.exports.getSignalOffset32(n,0,a,o)}catch{throw Error(`Signal ${t} is not an input of the circuit.`)}let s=this.getInt(n),c=kt(e[t]);for(let e=0;e>2]}setInt(e,t){this.i32[e>>2]=t}getFr(e){let t=this,r=e>>2;if(t.i32[r+1]&2147483648){let e=Array(t.n32);for(let n=0;n>2]=a,r.i32[(e>>2)+1]=0;return}r.i32[e>>2]=0,r.i32[(e>>2)+1]=2147483648;let o=n.Scalar.toArray(t,4294967296);for(let t=0;t=0?r.i32[(e>>2)+2+t]=o[n]:r.i32[(e>>2)+2+t]=0}}},Ft=class{constructor(e,t){this.instance=e,this.version=this.instance.exports.getVersion(),this.n32=this.instance.exports.getFieldNumLen32(),this.instance.exports.getRawPrime();let r=new Uint32Array(this.n32);for(let e=0;e{let n=jt(t),i=parseInt(n.slice(0,8),16),a=parseInt(n.slice(8,16),16),o=kt(e[t]);if(typeof this.instance.exports.getInputSignalSize==`function`){let e=this.instance.exports.getInputSignalSize(i,a);if(e<0)throw Error(`Signal ${t} not found\n`);if(o.lengthe)throw Error(`Too many values for input signal ${t}\n`)}for(let e=0;eqt,fullProve:()=>zt,prove:()=>tt,verify:()=>Vt});function Yt(e,t){let r=new DataView(t.buffer,t.byteOffset,t.byteLength),i=[];for(let e=0;e<8;e++)i[e]=r.getUint32(e*4);let a=new n.ChaCha(i);return e.G2.fromRng(a)}function Xt(e,t,n,r,i){let a=H.create({dkLen:64}),o=new Uint8Array([t]);a.update(o),a.update(n);let s=e.G1.toUncompressed(r);a.update(s);let c=e.G1.toUncompressed(i);return a.update(c),Yt(e,a.digest())}function Zt(e,t,n,r,i){return e.g1_s=t.G1.toAffine(t.G1.fromRng(i)),e.g1_sx=t.G1.toAffine(t.G1.timesFr(e.g1_s,e.prvKey)),e.g2_sp=t.G2.toAffine(Xt(t,n,r,e.g1_s,e.g1_sx)),e.g2_spx=t.G2.toAffine(t.G2.timesFr(e.g2_sp,e.prvKey)),e}function Qt(e,t,n){let r={tau:{},alpha:{},beta:{}};return r.tau.prvKey=e.Fr.fromRng(n),r.alpha.prvKey=e.Fr.fromRng(n),r.beta.prvKey=e.Fr.fromRng(n),Zt(r.tau,e,0,t,n),Zt(r.alpha,e,1,t,n),Zt(r.beta,e,2,t,n),r}async function $t(e,t,r,i){i||=r,await e.writeULE32(1);let a=e.pos;await e.writeULE64(0),await e.writeULE32(t.F1.n64*8);let o=new Uint8Array(t.F1.n8);n.Scalar.toRprLE(o,0,t.q,t.F1.n8),await e.write(o),await e.writeULE32(r),await e.writeULE32(i);let s=e.pos-a-8,c=e.pos;await e.writeULE64(s,a),e.pos=c}async function K(e,t){if(!t[1])throw Error(e.fileName+`: File has no header`);if(t[1].length>1)throw Error(e.fileName+`: File has more than one header`);e.pos=t[1][0].p;let r=await e.readULE32(),i=await e.read(r),a=await y(n.Scalar.fromRprLE(i));if(a.F1.n64*8!=r)throw Error(e.fileName+`: Invalid size`);let o=await e.readULE32(),s=await e.readULE32();if(e.pos-t[1][0].p!=t[1][0].size)throw Error(`Invalid PTau header size`);return{curve:a,power:o,ceremonyPower:s}}async function en(e,t,n){return tn(await e.read(t.F1.n8*2*6+t.F2.n8*2*3),0,t,n)}function tn(e,t,n,r){let i={tau:{},alpha:{},beta:{}};return i.tau.g1_s=a(),i.tau.g1_sx=a(),i.alpha.g1_s=a(),i.alpha.g1_sx=a(),i.beta.g1_s=a(),i.beta.g1_sx=a(),i.tau.g2_spx=o(),i.alpha.g2_spx=o(),i.beta.g2_spx=o(),i;function a(){let i;return i=r?n.G1.fromRprLEM(e,t):n.G1.fromRprUncompressed(e,t),t+=n.G1.F.n8*2,i}function o(){let i;return i=r?n.G2.fromRprLEM(e,t):n.G2.fromRprUncompressed(e,t),t+=n.G2.F.n8*2,i}}function nn(e,t,n,r,i){a(r.tau.g1_s),a(r.tau.g1_sx),a(r.alpha.g1_s),a(r.alpha.g1_sx),a(r.beta.g1_s),a(r.beta.g1_sx),o(r.tau.g2_spx),o(r.alpha.g2_spx),o(r.beta.g2_spx);async function a(r){i?n.G1.toRprLEM(e,t,r):n.G1.toRprUncompressed(e,t,r),t+=n.F1.n8*2}async function o(r){i?n.G2.toRprLEM(e,t,r):n.G2.toRprUncompressed(e,t,r),t+=n.F2.n8*2}return e}async function rn(e,t,n,r){let i=new Uint8Array(t.F1.n8*2*6+t.F2.n8*2*3);nn(i,0,t,n,r),await e.write(i)}async function an(e,t){let n={};n.tauG1=await c(),n.tauG2=await l(),n.alphaG1=await c(),n.betaG1=await c(),n.betaG2=await l(),n.key=await en(e,t,!0),n.partialHash=await e.read(216),n.nextChallenge=await e.read(64),n.type=await e.readULE32();let r=new Uint8Array(t.G1.F.n8*2*6+t.G2.F.n8*2*3);nn(r,0,t,n.key,!1);let i=Se(n.partialHash);i.update(r),n.responseHash=i.digest();let a=await e.readULE32(),o=e.pos,s=0;for(;e.pos-o1)throw Error(e.fileName+`: File has more than one contributions section`);e.pos=n[7][0].p;let r=await e.readULE32(),i=[];for(let n=0;n0){let t=new Uint8Array(a);await e.writeULE32(t.byteLength),await e.write(t)}else await e.writeULE32(0);async function o(n){t.G1.toRprLEM(r,0,n),await e.write(r)}async function s(n){t.G2.toRprLEM(i,0,n),await e.write(i)}}async function cn(e,t,n){await e.writeULE32(7);let r=e.pos;await e.writeULE64(0),await e.writeULE32(n.length);for(let r=0;r0?f[f.length-1].nextChallenge:ln(u,d,o);let b=await t.createBinFile(r,`ptau`,1,a?7:2);await $t(b,u,d);let x=await v.read(64);if(be(s,y)&&(y=x,f[f.length-1].nextChallenge=y),!be(x,y))throw Error(`Wrong contribution. This contribution is not based on the previous hash`);let S=H.create({dkLen:64});S.update(x);let C=[],w;w=await D(v,b,`G1`,2,2**d*2-1,[1],`tauG1`),p.tauG1=w[0],w=await D(v,b,`G2`,3,2**d,[1],`tauG2`),p.tauG2=w[0],w=await D(v,b,`G1`,4,2**d,[0],`alphaG1`),p.alphaG1=w[0],w=await D(v,b,`G1`,5,2**d,[0],`betaG1`),p.betaG1=w[0],w=await D(v,b,`G2`,6,1,[0],`betaG2`),p.betaG2=w[0],p.partialHash=Ce(S);let T=await v.read(u.F1.n8*2*6+u.F2.n8*2*3);p.key=tn(T,0,u,!1),S.update(new Uint8Array(T));let E=S.digest();if(o&&o.info(U(E,`Contribution Response Hash imported: `)),a){let e=H.create({dkLen:64});e.update(E),await A(e,b,`G1`,2,2**d*2-1,`tauG1`,o),await A(e,b,`G2`,3,2**d,`tauG2`,o),await A(e,b,`G1`,4,2**d,`alphaTauG1`,o),await A(e,b,`G1`,5,2**d,`betaTauG1`,o),await A(e,b,`G2`,6,1,`betaG2`,o),p.nextChallenge=e.digest(),o&&o.info(U(p.nextChallenge,`Next Challenge Hash: `))}else p.nextChallenge=s;return f.push(p),await cn(b,u,f),await v.close(),await b.close(),await c.close(),p.nextChallenge;async function D(e,t,n,r,i,o,s){return a?await O(e,t,n,r,i,o,s):await k(e,t,n,r,i,o,s)}async function O(e,n,r,i,a,s,c){let l=u[r],d=l.F.n8,f=l.F.n8*2,p=[];await t.startWriteSection(n,i);let m=Math.floor((1<<24)/f);C[i]=n.pos;for(let t=0;t=t&&n=t&&i1?u[u.length-2]:d;let p=u[u.length-1];if(r&&r.debug(`Validating contribution #`+u[u.length-1].id),!await mn(s,p,f,r))return!1;let m=H.create({dkLen:64});m.update(p.responseHash),r&&r.debug(`Verifying powers in tau*G1 section`);let h=await C(2,`G1`,`tauG1`,2**c*2-1,[0,1],r);if(i=await q(s,h.R1,h.R2,s.G2.g,p.tauG2),i!==!0)return r&&r.error(`tauG1 section. Powers do not match`),!1;if(!s.G1.eq(s.G1.g,h.singularPoints[0]))return r&&r.error(`First element of tau*G1 section must be the generator`),!1;if(!s.G1.eq(p.tauG1,h.singularPoints[1]))return r&&r.error(`Second element of tau*G1 section does not match the one in the contribution section`),!1;r&&r.debug(`Verifying powers in tau*G2 section`);let g=await C(3,`G2`,`tauG2`,2**c,[0,1],r);if(i=await q(s,s.G1.g,p.tauG1,g.R1,g.R2),i!==!0)return r&&r.error(`tauG2 section. Powers do not match`),!1;if(!s.G2.eq(s.G2.g,g.singularPoints[0]))return r&&r.error(`First element of tau*G2 section must be the generator`),!1;if(!s.G2.eq(p.tauG2,g.singularPoints[1]))return r&&r.error(`Second element of tau*G2 section does not match the one in the contribution section`),!1;r&&r.debug(`Verifying powers in alpha*tau*G1 section`);let _=await C(4,`G1`,`alphatauG1`,2**c,[0],r);if(i=await q(s,_.R1,_.R2,s.G2.g,p.tauG2),i!==!0)return r&&r.error(`alphaTauG1 section. Powers do not match`),!1;if(!s.G1.eq(p.alphaG1,_.singularPoints[0]))return r&&r.error(`First element of alpha*tau*G1 section (alpha*G1) does not match the one in the contribution section`),!1;r&&r.debug(`Verifying powers in beta*tau*G1 section`);let v=await C(5,`G1`,`betatauG1`,2**c,[0],r);if(i=await q(s,v.R1,v.R2,s.G2.g,p.tauG2),i!==!0)return r&&r.error(`betaTauG1 section. Powers do not match`),!1;if(!s.G1.eq(p.betaG1,v.singularPoints[0]))return r&&r.error(`First element of beta*tau*G1 section (beta*G1) does not match the one in the contribution section`),!1;let y=await S(r);if(!s.G2.eq(p.betaG2,y))return r&&r.error(`betaG2 element in betaG2 section does not match the one in the contribution section`),!1;let b=m.digest();if(c==l&&!be(b,p.nextChallenge))return r&&r.error(`Hash of the values does not match the next challenge of the last contributor in the contributions section`),!1;r&&r.info(U(b,`Next challenge hash: `)),x(p,f);for(let e=u.length-2;e>=0;e--){let t=u[e],n=e>0?u[e-1]:d;if(!await mn(s,t,n,r))return!1;x(t,n,r)}if(r&&r.info(`-----------------------------------------------------`),!o[12]||!o[13]||!o[14]||!o[15])r&&r.warn(`this file does not contain phase2 precalculated values. Please run: snarkjs "powersoftau preparephase2" to prepare this file to be used in the phase2 ceremony.`);else{let e;if(e=await w(`G1`,2,12,`tauG1`,r),!e||(e=await w(`G2`,3,13,`tauG2`,r),!e)||(e=await w(`G1`,4,14,`alphaTauG1`,r),!e)||(e=await w(`G1`,5,15,`betaTauG1`,r),!e))return!1}return await a.close(),r&&r.info(`Powers of Tau Ok!`),!0;function x(e,t){if(!r)return;r.info(`-----------------------------------------------------`),r.info(`Contribution #${e.id}: ${e.name||``}`),r.info(U(e.nextChallenge,`Next Challenge: `));let n=new Uint8Array(s.G1.F.n8*2*6+s.G2.F.n8*2*3);nn(n,0,s,e.key,!1);let i=Se(e.partialHash);i.update(n);let a=i.digest();r.info(U(a,`Response Hash:`)),r.info(U(t.nextChallenge,`Response Hash:`)),e.type==1&&(r.info(`Beacon generator: ${Me(e.beaconHash)}`),r.info(`Beacon iterations Exp: ${e.numIterationsExp}`))}async function S(e){let t=s.G2,n=t.F.n8*2,r=new Uint8Array(n);if(!o[6])throw e.error(`File has no BetaG2 section`),Error(`File has no BetaG2 section`);if(o[6].length>1)throw e.error(`File has no BetaG2 section`),Error(`File has more than one GetaG2 section`);a.pos=o[6][0].p;let i=await a.read(n),c=t.fromRprLEM(i);return t.toRprUncompressed(r,0,c),m.update(r),c}async function C(e,n,r,i,c,l){let u=65536,d=s[n],f=d.F.n8*2;await t.startReadUniqueSection(a,o,e);let p=[],h=d.zero,g=d.zero,_=d.zero;for(let e=0;e0){let e=d.fromRprLEM(n,0),t=Oe(Ee(4),0);h=d.add(h,d.timesScalar(_,t)),g=d.add(g,d.timesScalar(e,t))}let v=await d.multiExpAffine(n.slice(0,(t-1)*f),s),y=await d.multiExpAffine(n.slice(f),s);h=d.add(h,v),g=d.add(g,y),_=d.fromRprLEM(n,(t-1)*f);for(let r=0;r=e&&i1;)l/=2,u+=1;if(2**u!=c)throw Error(`Invalid file size`);i&&i.debug(`Power to tau size: `+u);let d=await ke(r),f=await Dt(n),p=H.create({dkLen:64});for(let e=0;e{i.debug(t+`.g1_s: `+e.G1.toString(g[t].g1_s,16)),i.debug(t+`.g1_sx: `+e.G1.toString(g[t].g1_sx,16)),i.debug(t+`.g2_sp: `+e.G2.toString(g[t].g2_sp,16)),i.debug(t+`.g2_spx: `+e.G2.toString(g[t].g2_spx,16)),i.debug(``)});let _=H.create({dkLen:64});await f.write(h),_.update(h),await _n(a,f,_,e,`G1`,2**u*2-1,e.Fr.one,g.tau.prvKey,`COMPRESSED`,`tauG1`,i),await _n(a,f,_,e,`G2`,2**u,e.Fr.one,g.tau.prvKey,`COMPRESSED`,`tauG2`,i),await _n(a,f,_,e,`G1`,2**u,g.alpha.prvKey,g.tau.prvKey,`COMPRESSED`,`alphaTauG1`,i),await _n(a,f,_,e,`G1`,2**u,g.beta.prvKey,g.tau.prvKey,`COMPRESSED`,`betaTauG1`,i),await _n(a,f,_,e,`G2`,1,g.beta.prvKey,g.tau.prvKey,`COMPRESSED`,`betaTauG2`,i);let v=new Uint8Array(e.F1.n8*2*6+e.F2.n8*2*3);nn(v,0,e,g,!1),await f.write(v),_.update(v);let y=_.digest();i&&i.info(U(y,`Contribution Response Hash: `)),await f.close(),await a.close()}async function yn(e,n,r,i,a,o){let s=je(i);if(s.byteLength==0||s.byteLength*2!=i.length)return o&&o.error(`Invalid Beacon Hash. (It must be a valid hexadecimal sequence)`),!1;if(s.length>=256)return o&&o.error(`Maximum length of beacon hash is 255 bytes`),!1;if(a=parseInt(a),a<10||a>63)return o&&o.error(`Invalid numIterationsExp. (Must be between 10 and 63)`),!1;let{fd:c,sections:l}=await t.readBinFile(e,`ptau`,1),{curve:u,power:d,ceremonyPower:f}=await K(c,l);if(d!=f)return o&&o.error(`This file has been reduced. You cannot contribute into a reduced file.`),!1;l[12]&&o&&o.warn(`Contributing into a file that has phase2 calculated. You will have to prepare phase2 again.`);let p=await on(c,u,l),m={name:r,type:1,numIterationsExp:a,beaconHash:s},h;h=p.length>0?p[p.length-1].nextChallenge:ln(u,d,o),m.key=await un(u,h,s,a);let g=H.create({dkLen:64});g.update(h);let _=await t.createBinFile(n,`ptau`,1,7);await $t(_,u,d);let v=[],y;y=await C(2,`G1`,2**d*2-1,u.Fr.e(1),m.key.tau.prvKey,`tauG1`,o),m.tauG1=y[1],y=await C(3,`G2`,2**d,u.Fr.e(1),m.key.tau.prvKey,`tauG2`,o),m.tauG2=y[1],y=await C(4,`G1`,2**d,m.key.alpha.prvKey,m.key.tau.prvKey,`alphaTauG1`,o),m.alphaG1=y[0],y=await C(5,`G1`,2**d,m.key.beta.prvKey,m.key.tau.prvKey,`betaTauG1`,o),m.betaG1=y[0],y=await C(6,`G2`,1,m.key.beta.prvKey,m.key.tau.prvKey,`betaTauG2`,o),m.betaG2=y[0],m.partialHash=Ce(g);let b=new Uint8Array(u.F1.n8*2*6+u.F2.n8*2*3);nn(b,0,u,m.key,!1),g.update(new Uint8Array(b));let x=g.digest();o&&o.info(U(x,`Contribution Response Hash imported: `));let S=H.create({dkLen:64});return S.update(x),await w(_,`G1`,2,2**d*2-1,`tauG1`,o),await w(_,`G2`,3,2**d,`tauG2`,o),await w(_,`G1`,4,2**d,`alphaTauG1`,o),await w(_,`G1`,5,2**d,`betaTauG1`,o),await w(_,`G2`,6,1,`betaG2`,o),m.nextChallenge=S.digest(),o&&o.info(U(m.nextChallenge,`Next Challenge Hash: `)),p.push(m),await cn(_,u,p),await c.close(),await _.close(),x;async function C(e,n,r,i,a,o,s){let d=[];c.pos=l[e][0].p,await t.startWriteSection(_,e),v[e]=_.pos;let f=u[n],p=f.F.n8*2,m=Math.floor((1<<20)/p),h=i;for(let e=0;e0?d[d.length-1].nextChallenge:ln(c,l,a),f.key=Qt(c,p,m);let h=H.create({dkLen:64});h.update(p);let g=await t.createBinFile(n,`ptau`,1,7);await $t(g,c,l);let _=[],v;v=await S(2,`G1`,2**l*2-1,c.Fr.e(1),f.key.tau.prvKey,`tauG1`),f.tauG1=v[1],v=await S(3,`G2`,2**l,c.Fr.e(1),f.key.tau.prvKey,`tauG2`),f.tauG2=v[1],v=await S(4,`G1`,2**l,f.key.alpha.prvKey,f.key.tau.prvKey,`alphaTauG1`),f.alphaG1=v[0],v=await S(5,`G1`,2**l,f.key.beta.prvKey,f.key.tau.prvKey,`betaTauG1`),f.betaG1=v[0],v=await S(6,`G2`,1,f.key.beta.prvKey,f.key.tau.prvKey,`betaTauG2`),f.betaG2=v[0],f.partialHash=Ce(h);let y=new Uint8Array(c.F1.n8*2*6+c.F2.n8*2*3);nn(y,0,c,f.key,!1),h.update(new Uint8Array(y));let b=h.digest();a&&a.info(U(b,`Contribution Response Hash imported: `));let x=H.create({dkLen:64});return x.update(b),await C(g,`G1`,2,2**l*2-1,`tauG1`),await C(g,`G2`,3,2**l,`tauG2`),await C(g,`G1`,4,2**l,`alphaTauG1`),await C(g,`G1`,5,2**l,`betaTauG1`),await C(g,`G2`,6,1,`betaG2`),f.nextChallenge=x.digest(),a&&a.info(U(f.nextChallenge,`Next Challenge Hash: `)),d.push(f),await cn(g,c,d),await o.close(),await g.close(),b;async function S(e,n,r,i,l,u){let d=[];o.pos=s[e][0].p,await t.startWriteSection(g,e),_[e]=g.pos;let f=c[n],p=f.F.n8*2,m=Math.floor((1<<20)/p),v=i;for(let e=0;eyn,challengeContribute:()=>vn,contribute:()=>bn,convert:()=>Cn,exportChallenge:()=>fn,exportJson:()=>wn,importResponse:()=>pn,newAccumulator:()=>dn,preparePhase2:()=>xn,truncate:()=>Sn,verify:()=>hn});function En(e,t,n){for(let t=0;t{let r=``;return Object.keys(n).forEach(i=>{let a=t.varIdx2Name[i];a==`one`&&(a=`1`);let o=e.curve.Fr.toString(n[i]);o==`1`&&(o=``),o==`-1`&&(o=`-`),r!=``&&o[0]!=`-`&&(o=`+`+o),r!=``&&(o=` `+o),r=r+o+a}),r},a=`[ ${i(r[0])} ] * [ ${i(r[1])} ] - [ ${i(r[2])} ] = 0`;n&&n.info(a)}}var Dn=n.Scalar.e(`73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001`,16),On=n.Scalar.e(`21888242871839275222246405745257275088548364400416034343698204186575808495617`);async function kn(e,t){let i=await(0,r.readR1cs)(e);return n.Scalar.eq(i.prime,On)?t&&t.info(`Curve: bn-128`):n.Scalar.eq(i.prime,Dn)?t&&t.info(`Curve: bls12-381`):t&&t.info(`Unknown Curve. Prime: ${n.Scalar.toString(i.prime)}`),t&&t.info(`# of Wires: ${i.nVars}`),t&&t.info(`# of Constraints: ${i.nConstraints}`),t&&t.info(`# of Private Inputs: ${i.nPrvInputs}`),t&&t.info(`# of Public Inputs: ${i.nPubInputs}`),t&&t.info(`# of Labels: ${i.nLabels}`),t&&t.info(`# of Outputs: ${i.nOutputs}`),i}async function An(e,t){let n=await(0,r.readR1cs)(e,!0,!0,!0,t),i=n.curve.Fr;return delete n.curve,delete n.F,Ne(i,n)}var jn=d({exportJson:()=>An,info:()=>kn,print:()=>En});async function Mn(e){let t={labelIdx2Name:[`one`],varIdx2Name:[`one`],componentIdx2Name:[]},n=await Ot(e),r=await n.read(n.totalSize),i=new TextDecoder(`utf-8`).decode(r).split(` -`);for(let e=0;e `+t.toString())}),a.trigger&&(d||=await Mn(i),u.logStartComponent=function(e){o&&o.info(`START: `+d.componentIdx2Name[e])},u.logFinishComponent=function(e){o&&o.info(`FINISH: `+d.componentIdx2Name[e])}),u.sym=d;let f=await Nt(l,u),p=await f.calculateWitness(s,!0),m=await t.createBinFile(r,`wtns`,2,2);await Xe(m,p,f.prime),await m.close()}async function Fn(e){return await $e(e)}async function In(e,i,a){a&&a.info(`WITNESS CHECKING STARTED`),a&&a.info(`> Reading r1cs file`);let{fd:o,sections:s}=await t.readBinFile(e,`r1cs`,1,1<<22,1<<24),c=await(0,r.readR1csFd)(o,s,{loadConstraints:!1,loadCustomGates:!1});a&&a.info(`> Reading witness file`);let{fd:l,sections:u}=await t.readBinFile(i,`wtns`,2,1<<22,1<<24),d=await Qe(l,u);if(!n.Scalar.eq(c.prime,d.q))throw Error(`Curve of the witness does not match the curve of the proving key`);let f=await t.readSection(l,u,2);await l.close();let p=(await v(c.prime)).Fr,m=p.n8,h=await t.readSection(o,s,2);a&&(a.info(`----------------------------`),a.info(` WITNESS CHECK`),a.info(` Curve: ${c.curve.name}`),a.info(` Vars (wires): ${c.nVars}`),a.info(` Outputs: ${c.nOutputs}`),a.info(` Public Inputs: ${c.nPubInputs}`),a.info(` Private Inputs: ${c.nPrvInputs}`),a.info(` Labels: ${c.nLabels}`),a.info(` Constraints: ${c.nConstraints}`),a.info(` Custom Gates: ${c.useCustomGates}`),a.info(`----------------------------`)),a&&a.info(`> Checking witness correctness`);let g=0,_=!0;for(let e=0;e{let r=x(n),i=e[n];t=p.add(t,p.mul(r,i))}),t}function b(){let e={},t=h.slice(g,g+4);g+=4;let n=new DataView(t.buffer).getUint32(0,!0),r=h.slice(g,g+(4+c.n8)*n);g+=(4+c.n8)*n;let i=new DataView(r.buffer);for(let t=0;tLt,check:()=>In,debug:()=>Pn,exportJson:()=>Fn}),Rn=262144,zn={get:function(e,t){return isNaN(t)?e[t]:e.getElement(t)},set:function(e,t,n){return isNaN(t)?(e[t]=n,!0):e.setElement(t,n)}},Bn=class{constructor(e){this.length=e||0,this.arr=Array(Rn);for(let t=0;t=this.length&&(this.length=e+1),!0}getKeys(){let e=new J;for(let t=0;td)return o&&o.error(`circuit too big for this power of tau ceremony. ${m.nConstraints}*2 > 2**${d}`),-1;if(!l[12])return o&&o.error(`Powers of tau is not prepared.`),-1;let y=m.nOutputs+m.nPubInputs,b=2**v;await(0,t.startWriteSection)(h,1),await h.writeULE32(1),await(0,t.endWriteSection)(h),await(0,t.startWriteSection)(h,2);let x=u.q,S=(Math.floor((n.Scalar.bitLength(x)-1)/64)+1)*8,C=u.r,w=(Math.floor((n.Scalar.bitLength(C)-1)/64)+1)*8,T=n.Scalar.mod(n.Scalar.shl(1,w*8),C),E=u.Fr.e(n.Scalar.mod(n.Scalar.mul(T,T),C));await h.writeULE32(S),await(0,t.writeBigInt)(h,x,S),await h.writeULE32(w),await(0,t.writeBigInt)(h,C,w),await h.writeULE32(m.nVars),await h.writeULE32(y),await h.writeULE32(b);let D;D=await c.read(g,l[4][0].p),await h.write(D),D=await u.G1.batchLEMtoU(D),s.update(D);let O;O=await c.read(g,l[5][0].p),await h.write(O),O=await u.G1.batchLEMtoU(O),s.update(O);let k;k=await c.read(_,l[6][0].p),await h.write(k),k=await u.G2.batchLEMtoU(k),s.update(k);let A=new Uint8Array(g);u.G1.toRprLEM(A,0,u.G1.g);let j=new Uint8Array(_);u.G2.toRprLEM(j,0,u.G2.g);let M=new Uint8Array(g);u.G1.toRprUncompressed(M,0,u.G1.g);let N=new Uint8Array(_);u.G2.toRprUncompressed(N,0,u.G2.g),await h.write(j),await h.write(A),await h.write(j),s.update(N),s.update(M),s.update(N),await(0,t.endWriteSection)(h),o&&o.info(V()),o&&o.info(`Reading r1cs`);let P=await(0,t.readSection)(f,p,2);await f.close();let F=new J(m.nVars),I=new J(m.nVars),L=new J(m.nVars),R=new J(m.nVars-y-1),z=Array(y+1);o&&o.info(V()),o&&o.info(`Reading tauG1`);let ee=await(0,t.readSection)(c,l,12,(b-1)*g,b*g);o&&o.info(`Reading tauG2`);let te=await(0,t.readSection)(c,l,13,(b-1)*_,b*_);o&&o.info(`Reading alphatauG1`);let ne=await(0,t.readSection)(c,l,14,(b-1)*g,b*g);o&&o.info(`Reading betatauG1`);let re=await(0,t.readSection)(c,l,15,(b-1)*g,b*g);o&&o.info(V()),o&&o.info(`processConstraints`),await oe(),o&&o.info(V()),o&&o.info(`composeAndWritePoints`),await se(3,`G1`,z,`IC`),z=null,o&&o.info(V()),o&&o.info(`writeHs`),await ae(),o&&o.info(V()),o&&o.info(`hashHPoints`),await le(),o&&o.info(V()),o&&o.info(`composeAndWritePoints 8 G1 C`),await se(8,`G1`,R,`C`),R=null,o&&o.info(V()),o&&o.info(`composeAndWritePoints 5 G1 A`),await se(5,`G1`,F,`A`),F=null,o&&o.info(V()),o&&o.info(`composeAndWritePoints 6 G1 B1`),await se(6,`G1`,I,`B1`),I=null,o&&o.info(V()),o&&o.info(`composeAndWritePoints 7 G2 B2`),await se(7,`G2`,L,`B2`),L=null,o&&o.info(V()),o&&o.info(`Contributions section`);let ie=s.digest();return await(0,t.startWriteSection)(h,10),await h.write(ie),await h.writeULE32(0),await(0,t.endWriteSection)(h),o&&o.info(U(ie,`Circuit hash: `)),await h.close(),await c.close(),ie;async function ae(){await(0,t.startWriteSection)(h,9);let e=new n.BigBuffer(b*g);if(v=0?u.Fr.fromRprLE(P.slice(t[3],t[3]+u.Fr.n8),0):u.Fr.fromRprLE(i,0);let a=u.Fr.mul(n,E);u.Fr.toRprLE(e,12,a),l.set(e,f),f+=e.length}}async function se(e,n,r,i){let a=32768,c=u[n];B(r.length),await(0,t.startWriteSection)(h,e);let l=[],d=0;for(;d(o&&o.debug(`Writing points end ${i}: ${u}/${r.length}`),e))),d+=t,e++}let t=await Promise.all(l);for(let e=0;e32768?(h=new n.BigBuffer(m*o),g=new n.BigBuffer(m*u.Fr.n8)):(h=new Uint8Array(m*o),g=new Uint8Array(m*u.Fr.n8));let _,v,y=[ee,te,ne,re],b=new Uint8Array(u.Fr.n8);u.Fr.toRprLE(b,0,u.Fr.e(1));let x=0;for(let e=0;e=0?g.set(P.slice(t[e][n][2],t[e][n][2]+u.Fr.n8),x*u.Fr.n8):g.set(b,x*u.Fr.n8),x++;if(t.length>1){let e=[];e.push({cmd:`ALLOCSET`,var:0,buff:h}),e.push({cmd:`ALLOCSET`,var:1,buff:g}),e.push({cmd:`ALLOC`,var:2,len:t.length*s}),_=0,v=0;let n=0;for(let r=0;r`u`||!process.memoryUsage)return{};let e=process.memoryUsage();for(let t in e)e[t]=Math.round(e[t]/(1024*1024));return e}}async function Hn(e,n,r){let{fd:i,sections:a}=await t.readBinFile(e,`zkey`,2),o=await Re(i,a);if(o.protocol!=`groth16`)throw Error(`zkey file is not groth16`);let s=await y(o.q),c=s.G1.F.n8*2,l=s.G2.F.n8*2,u=await We(i,s,a),d=await Dt(n);await b(o.vk_alpha_1),await b(o.vk_beta_1),await x(o.vk_beta_2),await x(o.vk_gamma_2),await b(o.vk_delta_1),await x(o.vk_delta_2);let f;f=await t.readSection(i,a,3),f=await s.G1.batchLEMtoU(f),await S(`G1`,f);let p=await t.readSection(i,a,9),m;m=await s.G1.fft(p,`affine`,`jacobian`,r),m=await s.G1.batchApplyKey(m,s.Fr.neg(s.Fr.e(2)),s.Fr.w[o.power+1],`jacobian`,`affine`,r),m=m.slice(0,m.byteLength-c),m=await s.G1.batchLEMtoU(m),await S(`G1`,m);let h;h=await t.readSection(i,a,8),h=await s.G1.batchLEMtoU(h),await S(`G1`,h);let g;g=await t.readSection(i,a,5),g=await s.G1.batchLEMtoU(g),await S(`G1`,g);let _;_=await t.readSection(i,a,6),_=await s.G1.batchLEMtoU(_),await S(`G1`,_);let v;v=await t.readSection(i,a,7),v=await s.G2.batchLEMtoU(v),await S(`G2`,v),await d.write(u.csHash),await C(u.contributions.length);for(let e=0;ep.contributions.length)return a&&a.error(`The impoerted file does not include new contributions`),!1;for(let e=0;e=0;e--){let t=f.contributions[e];a&&a.info(`-------------------------`),a&&a.info(U(t.contributionHash,`contribution #${e+1} ${t.name?t.name:``}:`)),t.type==1&&(a&&a.info(`Beacon generator: ${Me(t.beaconHash)}`),a&&a.info(`Beacon iterations Exp: ${t.numIterationsExp}`))}return a&&a.info(`-------------------------`),a&&a.info(`ZKey Ok!`),!0;async function x(e,n,r,i,s,c,l,d,f){let p=1<<20,m=u[e],h=m.F.n8*2;await t.startReadUniqueSection(n,r,c),await t.startReadUniqueSection(i,s,c);let g=m.zero,_=m.zero,v=r[c][0].size/h;for(let e=0;e=256)return o&&o.error(`Maximum length of beacon hash is 255 bytes`),!1;if(a=parseInt(a),a<10||a>63)return o&&o.error(`Invalid numIterationsExp. (Must be between 10 and 63)`),!1;let{fd:c,sections:l}=await t.readBinFile(e,`zkey`,2),u=await Re(c,l);if(u.protocol!=`groth16`)throw Error(`zkey file is not groth16`);let d=await y(u.q),f=await We(c,d,l),p=await t.createBinFile(n,`zkey`,1,10),m=await Ae(s,a),h=H.create({dkLen:64});h.update(f.csHash);for(let e=0;e Detected protocol: `+a.protocol);let o;if(a.protocol===`groth16`)o=await $n(a,r,i);else if(a.protocol===`plonk`)o=await er(a);else if(a.protocolId&&a.protocolId===10)o=await tr(a,n);else throw Error(`zkey file protocol unrecognized`);return await r.close(),n&&n.info(`EXPORT VERIFICATION KEY FINISHED`),o}async function $n(e,n,r){let i=await y(e.q),a=i.G1.F.n8*2,o=await i.pairing(e.vk_alpha_1,e.vk_beta_2),s={protocol:e.protocol,curve:i.name,nPublic:e.nPublic,vk_alpha_1:i.G1.toObject(e.vk_alpha_1),vk_beta_2:i.G2.toObject(e.vk_beta_2),vk_gamma_2:i.G2.toObject(e.vk_gamma_2),vk_delta_2:i.G2.toObject(e.vk_delta_2),vk_alphabeta_12:i.Gt.toObject(o)};await t.startReadUniqueSection(n,r,3),s.IC=[];for(let t=0;t<=e.nPublic;t++){let e=await n.read(a),t=i.G1.toObject(e);s.IC.push(t)}return await t.endReadSection(n),s=Zn(s),s}async function er(e){let t=await y(e.q),n={protocol:e.protocol,curve:t.name,nPublic:e.nPublic,power:e.power,k1:t.Fr.toObject(e.k1),k2:t.Fr.toObject(e.k2),Qm:t.G1.toObject(e.Qm),Ql:t.G1.toObject(e.Ql),Qr:t.G1.toObject(e.Qr),Qo:t.G1.toObject(e.Qo),Qc:t.G1.toObject(e.Qc),S1:t.G1.toObject(e.S1),S2:t.G1.toObject(e.S2),S3:t.G1.toObject(e.S3),X_2:t.G2.toObject(e.X_2),w:t.Fr.toObject(t.Fr.w[e.power])};return n=Zn(n),n}async function tr(e,t){let n=await y(e.q);return Zn({protocol:e.protocol,curve:n.name,nPublic:e.nPublic,power:e.power,k1:n.Fr.toObject(e.k1),k2:n.Fr.toObject(e.k2),w:n.Fr.toObject(n.Fr.w[e.power]),w3:n.Fr.toObject(e.w3),w4:n.Fr.toObject(e.w4),w8:n.Fr.toObject(e.w8),wr:n.Fr.toObject(e.wr),X_2:n.G2.toObject(e.X_2),C0:n.G1.toObject(e.C0)})}var nr=d({beacon:()=>Jn,bellmanContribute:()=>Xn,contribute:()=>qn,exportBellman:()=>Hn,exportJson:()=>Yn,exportSolidityVerifier:()=>null,exportVerificationKey:()=>Qn,importBellman:()=>Un,newZKey:()=>Vn,verifyFromInit:()=>Gn,verifyFromR1cs:()=>Kn});async function rr(e,i,a,o){globalThis.gc&&globalThis.gc();let{fd:s,sections:c}=await(0,t.readBinFile)(i,`ptau`,1,1<<22,1<<24),{curve:l,power:u}=await K(s,c),{fd:d,sections:f}=await(0,t.readBinFile)(e,`r1cs`,1,1<<22,1<<24),p=await(0,r.readR1csFd)(d,f,{loadConstraints:!0,loadCustomGates:!0}),m=l.G1.F.n8*2,h=l.G1,g=l.G2.F.n8*2,_=l.Fr,v=l.Fr.n8;o&&o.info(`Reading r1cs`),await(0,t.readSection)(d,f,2);let y=new J,b=new J,x=p.nVars,S=p.nOutputs+p.nPubInputs;await M(l.Fr,p,o),globalThis.gc&&globalThis.gc();let C=await(0,t.createBinFile)(a,`zkey`,1,14,1<<22,1<<24);if(p.prime!=l.r)return o&&o.error(`r1cs curve does not match powers of tau ceremony curve`),-1;let w=ye(y.length-1)+1;w<3&&(w=3);let T=2**w;if(o&&o.info(`Plonk constraints: `+y.length),w>u)return o&&o.error(`circuit too big for this power of tau ceremony. ${y.length} > 2**${u}`),-1;if(!c[12])return o&&o.error(`Powers of tau is not prepared.`),-1;let E=new n.BigBuffer(T*m),D=c[12][0].p+(2**w-1)*m;await s.readToBuffer(E,0,T*m,D);let[O,k]=ee(),A={};await I(3,`Additions`),globalThis.gc&&globalThis.gc(),await N(4,0,`Amap`),globalThis.gc&&globalThis.gc(),await N(5,1,`Bmap`),globalThis.gc&&globalThis.gc(),await N(6,2,`Cmap`),globalThis.gc&&globalThis.gc(),await P(7,3,`Qm`),globalThis.gc&&globalThis.gc(),await P(8,4,`Ql`),globalThis.gc&&globalThis.gc(),await P(9,5,`Qr`),globalThis.gc&&globalThis.gc(),await P(10,6,`Qo`),globalThis.gc&&globalThis.gc(),await P(11,7,`Qc`),globalThis.gc&&globalThis.gc(),await L(12,`sigma`),globalThis.gc&&globalThis.gc(),await R(13,`lagrange polynomials`),globalThis.gc&&globalThis.gc(),await(0,t.startWriteSection)(C,14);let j=new n.BigBuffer((T+6)*m);await s.readToBuffer(j,0,(T+6)*m,c[2][0].p),await C.write(j),await(0,t.endWriteSection)(C),globalThis.gc&&globalThis.gc(),await z(),await C.close(),await d.close(),await s.close(),o&&o.info(`Setup Finished`);return;async function M(e,t,n){function r(e){let t=Object.keys(e);for(let n=0;nn;){let t=i.shift(),n=i.shift(),r=t[0],a=n[0],o=x++,s=e.zero,c=e.neg(t[1]),l=e.neg(n[1]),u=e.one,d=e.zero;y.push([r,a,o,s,c,l,u,d]),b.push([r,a,t[1],n[1]]),i.push([o,e.one])}for(let e=0;e0?r.toString():n==e.zero?`0`:`k`}function l(e,t,n){let a=c(e),l=c(t);a===`0`||l===`0`?(r(n),o(n)):a===`k`?o(i(t,e[0],n)):l===`k`?o(i(e,t[0],n)):s(e,t,n)}for(let t=1;t<=S;t++){let n=t,r=e.zero,i=e.one,a=e.zero,o=e.zero,s=e.zero;y.push([n,0,0,r,i,a,o,s])}for(let e=0;e{let r=this.curve.G1.toObject(this.polynomials[n]);e?t.polynomials[n]=r:t[n]=r}),Object.keys(this.evaluations).forEach(n=>{let r=this.curve.Fr.toObject(this.evaluations[n]);e?t.evaluations[n]=r:t[n]=r}),t}fromObjectProof(e){this.resetProof(),Object.keys(e.polynomials).forEach(t=>{this.polynomials[t]=this.curve.G1.fromObject(e.polynomials[t])}),Object.keys(e.evaluations).forEach(t=>{this.evaluations[t]=this.curve.Fr.fromObject(e.evaluations[t])})}},ar=BigInt(0),or=BigInt(1),sr=BigInt(2),cr=BigInt(7),lr=BigInt(256),ur=BigInt(113),dr=[],fr=[],pr=[];for(let e=0,t=or,n=1,r=0;e<24;e++){[n,r]=[r,(2*n+3*r)%5],dr.push(2*(5*r+n)),fr.push((e+1)*(e+2)/2%64);let i=ar;for(let e=0;e<7;e++)t=(t<>cr)*ur)%lr,t&sr&&(i^=or<<(or<n>32?se(e,t,n):ae(e,t,n),vr=(e,t,n)=>n>32?ce(e,t,n):oe(e,t,n);function yr(e,t=24){if(S(t,`rounds`),t<1||t>24)throw Error(`"rounds" expected integer 1..24`);let n=new Uint32Array(10);for(let r=24-t;r<24;r++){for(let t=0;t<10;t++)n[t]=e[t]^e[t+10]^e[t+20]^e[t+30]^e[t+40];for(let t=0;t<10;t+=2){let r=(t+8)%10,i=(t+2)%10,a=n[i],o=n[i+1],s=_r(a,o,1)^n[r],c=vr(a,o,1)^n[r+1];for(let n=0;n<50;n+=10)e[t+n]^=s,e[t+n+1]^=c}let t=e[2],i=e[3];for(let n=0;n<24;n++){let r=fr[n],a=_r(t,i,r),o=vr(t,i,r),s=dr[n];t=e[s],i=e[s+1],e[s]=a,e[s+1]=o}for(let t=0;t<50;t+=10){let n=e[t],r=e[t+1],i=e[t+2],a=e[t+3];e[t]^=~e[t+2]&e[t+4],e[t+1]^=~e[t+3]&e[t+5],e[t+2]^=~e[t+4]&e[t+6],e[t+3]^=~e[t+5]&e[t+7],e[t+4]^=~e[t+6]&e[t+8],e[t+5]^=~e[t+7]&e[t+9],e[t+6]^=~e[t+8]&n,e[t+7]^=~e[t+9]&r,e[t+8]^=~n&i,e[t+9]^=~r&a}e[0]^=hr[r],e[1]^=gr[r]}D(n)}var br=class e{state;pos=0;posOut=0;finished=!1;state32;destroyed=!1;blockLen;suffix;outputLen;canXOF;enableXOF=!1;rounds;constructor(e,t,n,r=!1,i=24){if(this.blockLen=e,this.suffix=t,this.outputLen=n,this.enableXOF=r,this.canXOF=r,this.rounds=i,S(n,`outputLen`),!(0=n&&this.keccak();let a=Math.min(n-this.posOut,i-r);e.set(t.subarray(this.posOut,this.posOut+a),r),this.posOut+=a,r+=a}return e}xofInto(e){if(!this.enableXOF)throw Error(`XOF is not possible for this instance`);return this.writeInto(e)}xof(e){return S(e),this.xofInto(new Uint8Array(e))}digestInto(e){if(T(e,this),this.finished)throw Error(`digest() was already called`);this.writeInto(e.subarray(0,this.outputLen)),this.destroy()}digest(){let e=new Uint8Array(this.outputLen);return this.digestInto(e),e}destroy(){this.destroyed=!0,D(this.state)}_cloneInto(t){let{blockLen:n,suffix:r,outputLen:i,rounds:a,enableXOF:o}=this;return t||=new e(n,r,i,o,a),t.blockLen=n,t.state32.set(this.state32),t.pos=this.pos,t.posOut=this.posOut,t.finished=this.finished,t.rounds=a,t.suffix=r,t.outputLen=i,t.enableXOF=o,t.canXOF=this.canXOF,t.destroyed=this.destroyed,t}},xr=((e,t,n,r={})=>N(()=>new br(t,e,n),r))(1,136,32),Sr=0,Cr=1,wr=class{constructor(e){this.G1=e.G1,this.Fr=e.Fr,this.reset()}reset(){this.data=[]}addPolCommitment(e){this.data.push({type:Sr,data:e})}addScalar(e){this.data.push({type:Cr,data:e})}getChallenge(){if(this.data.length===0)throw Error(`Keccak256Transcript: No data to generate a transcript`);let e=0,t=0;this.data.forEach(n=>Sr===n.type?e++:t++);let r=new Uint8Array(t*this.Fr.n8+e*this.G1.F.n8*2),i=0;for(let e=0;e32768?new n.BigBuffer(t.length*a.n8):new Uint8Array(t.length*a.n8);for(let e=0;e32768?new n.BigBuffer(a*o.n8):new Uint8Array(a*o.n8);return s.set(t.coef.slice(),0),new e(s,r,i)}isEqual(e){let t=this.degree();if(t!==e.degree())return!1;for(let n=0;n32768?new n.BigBuffer((this.length()+e.length)*this.Fr.n8):new Uint8Array((this.length()+e.length)*this.Fr.n8);t.set(this.coef,0);for(let n=0;nthis.coef.byteLength?this.Fr.zero:this.coef.slice(t,t+this.Fr.n8)}setCoef(e,t){if(e>this.length()-1)throw Error(`Coef index is not available`);this.coef.set(t,e*this.Fr.n8)}static async to4T(e,t,r,i){r||=[];let a=await i.ifft(e),o=t*4>32768?new n.BigBuffer(t*4*i.n8):new Uint8Array(t*4*i.n8);o.set(a,0);let s=await i.fft(o);if(r.length===0)return[a,s];let c=t+r.length>32768?new n.BigBuffer((t+r.length)*i.n8):new Uint8Array((t+r.length)*i.n8);c.set(a,0);for(let e=0;e0;e--){let t=e*this.Fr.n8;if(!this.Fr.eq(this.Fr.zero,this.coef.slice(t,t+this.Fr.n8)))return e}return 0}evaluate(e){let t=this.Fr.zero;for(let n=this.degree()+1;n>0;n--){let r=n*this.Fr.n8,i=this.coef.slice(r-this.Fr.n8,r);t=this.Fr.add(i,this.Fr.mul(t,e))}return t}fastEvaluate(e){let t=this.Fr,n=this.degree()+1,r=parseInt(n/3),i=n-r*3,a=[],o=[];o[0]=t.one;for(let n=0;n<3;n++){a[n]=t.zero;let s=n===2?r+i:r;for(let i=s;i>0;i--)a[n]=t.add(this.getCoef(n*r+i-1),t.mul(a[n],e)),n===0&&(o[0]=t.mul(o[0],e))}for(let e=1;e<3;e++)a[0]=t.add(a[0],t.mul(o[e-1],a[e])),o[e]=t.mul(o[e-1],o[0]);return a[0]}add(e,t){let n=!1;e.length()>this.length()&&(n=!0);let r=this.length(),i=e.length();for(let a=0;athis.length()&&(n=!0);let r=this.length(),i=e.length();for(let a=0;a32768?new n.BigBuffer(i*r.n8):new Uint8Array(i*r.n8),this.curve,this.logger);a.coef.set(this.coef.slice(0,(i-1)*r.n8),32),this.mulScalar(r.neg(t)),a.add(this),this.coef=a.coef}byXNSubValue(t,r){let i=this.Fr,a=this.length()-t-1>=this.degree()?this.length():this.length()+t,o=new e(a>32768?new n.BigBuffer(a*i.n8):new Uint8Array(a*i.n8),this.curve,this.logger);o.coef.set(this.coef.slice(0,(this.degree()+1)*32),t*32),this.mulScalar(r),o.add(this),this.coef=o.coef}divBy(t){let r=this.Fr,i=this.degree(),a=t.degree(),o=new e(this.coef,this.curve,this.logger);this.coef=this.length()>32768?new n.BigBuffer(this.length()*r.n8):new Uint8Array(this.length()*r.n8);for(let e=i-a;e>=0;e--){this.setCoef(e,r.div(o.getCoef(e+a),t.getCoef(a)));for(let n=0;n<=a;n++)o.setCoef(e+n,r.sub(o.getCoef(e+n),r.mul(this.getCoef(e),t.getCoef(n))))}return o}divByMonic(t,r){let i=this.Fr,a=this.degree(),o=new e(this.length()>32768?new n.BigBuffer(this.length()*i.n8):new Uint8Array(this.length()*i.n8),this.curve,this.logger),s=[];for(let e=0;e=0&&!(n<0);n-=c){let a=e;s[a]=i.add(this.getCoef(n+t),i.mul(s[a],r)),o.setCoef(n,s[a]),l=(l+1)%t}this.coef=o.coef}divByVanishing(t,r){if(this.degree()32768?new n.BigBuffer(this.length()*i.n8):new Uint8Array(this.length()*i.n8);for(let e=this.length()-1;e>=t;e--){let n=a.getCoef(e);i.eq(i.zero,n)||(a.setCoef(e,i.zero),a.setCoef(e-t,i.add(a.getCoef(e-t),i.mul(r,n))),this.setCoef(e-t,i.add(this.getCoef(e-t),n)))}return a}divByVanishing2(t,r){if(this.degree()32768?new n.BigBuffer(this.length()*i.n8):new Uint8Array(this.length()*i.n8);let o=this.length()-t,s=Math.floor(o/3),c=o-2*s;console.log(o),console.log(s+` `+c);for(let e=0;e<3;e++){console.log(`> Thread `+e);for(let n=e===0?c:s;n>0;n--){let o=n-1;e!==0&&(o+=(e-1)*s+c);let l=o+t,u=a.getCoef(l);i.eq(i.zero,u)||(a.setCoef(l,i.zero),a.setCoef(o,i.add(a.getCoef(o),i.mul(r,u))),this.setCoef(o,i.add(this.getCoef(o),u)),console.log(o+` <-- `+l))}}return this.print(),a}fastDivByVanishing(t){let r=this.Fr;for(let i=0;i32768?new n.BigBuffer(this.length()*r.n8):new Uint8Array(this.length()*r.n8),this.curve,this.logger),f=this.coef;this.coef=d.coef,d.coef=f;for(let e=0;e<5;e++){let t=(e+1)*l+u;for(let e=0;e0;e--){let t=e-1,n=t*l+u;h[t]=[];for(let i=0;i32768?new n.BigBuffer(this.length()*this.Fr.n8):new Uint8Array(this.length()*this.Fr.n8);t.set(this.Fr.zero,(this.length()-1)*this.Fr.n8),t.set(this.coef.slice((this.length()-1)*this.Fr.n8,this.length()*this.Fr.n8),(this.length()-2)*this.Fr.n8);for(let n=this.length()-3;n>=0;n--){let r=n*this.Fr.n8;t.set(this.Fr.add(this.coef.slice(r+this.Fr.n8,r+2*this.Fr.n8),this.Fr.mul(e,t.slice(r+this.Fr.n8,r+2*this.Fr.n8))),n*this.Fr.n8)}if(!this.Fr.eq(this.coef.slice(0,this.Fr.n8),this.Fr.mul(this.Fr.neg(e),t.slice(0,this.Fr.n8))))throw Error(`Polynomial does not divide`);this.coef=t}divZh(e,t=4){for(let t=0;te*(t-1)-t&&!this.Fr.isZero(i))throw Error(`Polynomial is not divisible`)}return this}divByZerofier(e,t){let n=this.Fr,r=n.inv(t),i=n.neg(r),a=n.eq(n.one,i),o=n.eq(n.negone,i);if(!a)for(let t=0;tthis.length()-e-1&&!this.Fr.isZero(c))throw Error(`Polynomial is not divisible`)}return this}byX(){let e=this.length()+1>32768?new n.BigBuffer(this.coef.byteLength+this.Fr.n8):new Uint8Array(this.coef.byteLength+this.Fr.n8);e.set(this.Fr.zero,0),e.set(this.coef,this.Fr.n8),this.coef=e}static async expX(t,r,i=!1){let a=t.Fr;if(r<1)throw Error(`Compute a new polynomial to a zero or negative number is not allowed`);if(r===1)return await e.fromEvaluations(t.coef,t.curve,t.logger);let o=i?t.degree():t.length()-1,s=o*r+1>32768?new n.BigBuffer((o*r+1)*a.n8):new Uint8Array((o*r+1)*a.n8);s.set(t.getCoef(0),0);for(let e=1;e<=o;e++){let n=e*a.n8,i=t.getCoef(e);s.set(i,n*r)}return new e(s,t.curve,t.logger)}split(t,r,i){if(t<1)throw Error(`Polynomials can't be split in ${t} parts`);if(t===1)return[this];if(i.length!==0&&i.length32768?new n.BigBuffer(c):new Uint8Array(c),this.curve,this.logger);let l=r*a,u=s?this.coef.byteLength:(r+1)*a;if(o[r].coef.set(this.coef.slice(l,u),0),s||o[r].coef.set(i[r],a),r!==0){let e=this.Fr.sub(o[r].coef.slice(0,this.Fr.n8),i[r-1]);o[r].coef.set(e,0)}s&&o[r].truncate()}return o}truncate(){let e=this.degree();if(e+132768?new n.BigBuffer((e+1)*this.Fr.n8):new Uint8Array((e+1)*this.Fr.n8);t.set(this.coef.slice(0,(e+1)*this.Fr.n8),0),this.coef=t}}static lagrangePolynomialInterpolation(t,r,i){let a=i.Fr,o=s(0);for(let e=1;e32768?new n.BigBuffer(t.length*a.n8):new Uint8Array(t.length*a.n8),i),s.setCoef(0,a.neg(t[r])),s.setCoef(1,a.one)):s.byXSubValue(t[r]));let c=s.evaluate(t[o]);c=a.inv(c);let l=a.mul(r[o],c);return s.mulScalar(l),s}}static zerofierPolynomial(t,r){let i=r.Fr,a=new e(t.length+1>32768?new n.BigBuffer((t.length+1)*i.n8):new Uint8Array((t.length+1)*i.n8),r);a.setCoef(0,i.neg(t[0])),a.setCoef(1,i.one);for(let e=1;e=0;n--){let r=this.getCoef(n);e.eq(e.zero,r)||(e.isNegative(r)?t+=` - `:n!==this.degree()&&(t+=` + `),t+=e.toString(r),n>0&&(t+=n>1?`x^`+n:`x`))}console.log(t)}async multiExponentiation(e,t){let n=this.coef.byteLength/this.Fr.n8,r=e.slice(0,n*this.G1.F.n8*2),i=await this.Fr.batchFromMontgomery(this.coef),a=await this.G1.multiExpAffine(r,i,this.logger,t);return a=this.G1.toAffine(a),a}},X=class e{constructor(e,t,n){this.eval=e,this.curve=t,this.Fr=t.Fr,this.logger=n}static async fromPolynomial(t,r,i,a){let o=new n.BigBuffer(t.length()*r*i.Fr.n8);return o.set(t.coef,0),new e(await i.Fr.fft(o),i,a)}getEvaluation(e){let t=e*this.Fr.n8;if(t+this.Fr.n8>this.eval.byteLength)throw Error(`Evaluations.getEvaluation() out of bounds`);return this.eval.slice(t,t+this.Fr.n8)}length(){let e=this.eval.byteLength/this.Fr.n8;if(e!==Math.floor(this.eval.byteLength/this.Fr.n8))throw Error(`Polynomial evaluations buffer has incorrect size`);return e===0&&this.logger.warn(`Polynomial has length zero`),e}},{stringifyBigInts:Er}=n.utils;async function Dr(e,r,i,a){let{fd:o,sections:s}=await t.readBinFile(r,`wtns`,2,1<<25,1<<23);i&&i.debug(`> Reading witness file`);let c=await Qe(o,s);i&&i.debug(`> Reading zkey file`);let{fd:l,sections:u}=await t.readBinFile(e,`zkey`,2,1<<25,1<<23),d=await Re(l,u,void 0,a);if(d.protocol!=`plonk`)throw Error(`zkey file is not plonk`);if(!n.Scalar.eq(d.r,c.q))throw Error(`Curve of the witness does not match the curve of the proving key`);if(c.nWitness!=d.nVars-d.nAdditions)throw Error(`Invalid witness length. Circuit: ${d.nVars}, witness: ${c.nWitness}, ${d.nAdditions}`);let f=d.curve,p=f.Fr,m=f.Fr.n8,h=d.domainSize*m;i&&(i.debug(`----------------------------`),i.debug(` PLONK PROVE SETTINGS`),i.debug(` Curve: ${f.name}`),i.debug(` Circuit power: ${d.power}`),i.debug(` Domain size: ${d.domainSize}`),i.debug(` Vars: ${d.nVars}`),i.debug(` Public vars: ${d.nPublic}`),i.debug(` Constraints: ${d.nConstraints}`),i.debug(` Additions: ${d.nAdditions}`),i.debug(`----------------------------`)),i&&i.debug(`> Reading witness file data`);let g=await t.readSection(o,s,2);g.set(p.zero,0);let _=new n.BigBuffer(m*d.nAdditions),v={},y={},b={},x={},S=new ir(f,i),C=new wr(f);i&&i.debug(`> Reading Section 3. Additions`),await D(),i&&i.debug(`> Reading Section 12. Sigma1, Sigma2 & Sigma 3`),i&&i.debug(`··· Reading Sigma polynomials `),y.Sigma1=new Y(new n.BigBuffer(h),f,i),y.Sigma2=new Y(new n.BigBuffer(h),f,i),y.Sigma3=new Y(new n.BigBuffer(h),f,i),await l.readToBuffer(y.Sigma1.coef,0,h,u[12][0].p),await l.readToBuffer(y.Sigma2.coef,0,h,u[12][0].p+5*h),await l.readToBuffer(y.Sigma3.coef,0,h,u[12][0].p+10*h),i&&i.debug(`··· Reading Sigma evaluations`),b.Sigma1=new X(new n.BigBuffer(h*4),f,i),b.Sigma2=new X(new n.BigBuffer(h*4),f,i),b.Sigma3=new X(new n.BigBuffer(h*4),f,i),await l.readToBuffer(b.Sigma1.eval,0,h*4,u[12][0].p+h),await l.readToBuffer(b.Sigma2.eval,0,h*4,u[12][0].p+6*h),await l.readToBuffer(b.Sigma3.eval,0,h*4,u[12][0].p+11*h),i&&i.debug(`> Reading Section 14. Powers of Tau`);let w=await t.readSection(l,u,14),T=[];for(let e=1;e<=d.nPublic;e++){let t=g.slice(e*p.n8,e*p.n8+p.n8);T.push(n.Scalar.fromRprLE(t))}i&&i.debug(``),i&&i.debug(`> ROUND 1`),await A(),i&&i.debug(`> ROUND 2`),await M(),i&&i.debug(`> ROUND 3`),await P(),i&&i.debug(`> ROUND 4`),await I(),i&&i.debug(`> ROUND 5`),await L(),await l.close(),await o.close();let E=S.toObjectProof(!1);return E.protocol=`plonk`,E.curve=f.name,i&&i.debug(`PLONK PROVER FINISHED`),{proof:Er(E),publicSignals:Er(T)};async function D(){i&&i.debug(`··· Computing additions`);let e=await t.readSection(l,u,3),n=8+m*2;for(let t=0;t Computing A, B, C wire polynomials`),await j(),i&&i.debug(`> Computing A, B, C MSM`);let e=await y.A.multiExponentiation(w,`A`),t=await y.B.multiExponentiation(w,`B`),n=await y.C.multiExponentiation(w,`C`);return S.addPolynomial(`A`,e),S.addPolynomial(`B`,t),S.addPolynomial(`C`,n),0}async function j(){i&&i.debug(`··· Reading data from zkey file`),v.A=new n.BigBuffer(h),v.B=new n.BigBuffer(h),v.C=new n.BigBuffer(h);let e=await t.readSection(l,u,4),r=await t.readSection(l,u,5),a=await t.readSection(l,u,6);for(let t=0;t=d.domainSize+2)throw Error(`A Polynomial is not well calculated`);if(y.B.degree()>=d.domainSize+2)throw Error(`B Polynomial is not well calculated`);if(y.C.degree()>=d.domainSize+2)throw Error(`C Polynomial is not well calculated`)}async function M(){i&&i.debug(`> Computing challenges beta and gamma`),C.reset(),C.addPolCommitment(d.Qm),C.addPolCommitment(d.Ql),C.addPolCommitment(d.Qr),C.addPolCommitment(d.Qo),C.addPolCommitment(d.Qc),C.addPolCommitment(d.S1),C.addPolCommitment(d.S2),C.addPolCommitment(d.S3);for(let e=0;e Computing Z polynomial`),await N(),i&&i.debug(`> Computing Z MSM`);let e=await y.Z.multiExponentiation(w,`Z`);S.addPolynomial(`Z`,e)}async function N(){i&&i.debug(`··· Computing Z evaluations`);let e=new n.BigBuffer(h),t=new n.BigBuffer(h);e.set(p.one,0),t.set(p.one,0);let r=p.one;for(let n=0;n=d.domainSize+3)throw Error(`Z Polynomial is not well calculated`);delete v.Z}async function P(){i&&i.debug(`> Computing challenge alpha`),C.reset(),C.addScalar(x.beta),C.addScalar(x.gamma),C.addPolCommitment(S.getPolynomial(`Z`)),x.alpha=C.getChallenge(),x.alpha2=p.square(x.alpha),i&&i.debug(`··· challenges.alpha: `+p.toString(x.alpha,16)),i&&i.debug(`> Computing T polynomial`),await F(),i&&i.debug(`> Computing T MSM`);let e=await y.T1.multiExponentiation(w,`T1`),t=await y.T2.multiExponentiation(w,`T2`),n=await y.T3.multiExponentiation(w,`T3`);S.addPolynomial(`T1`,e),S.addPolynomial(`T2`,t),S.addPolynomial(`T3`,n)}async function F(){i&&i.debug(`··· Reading sections 8, 9, 7, 10, 11. Q selectors`),b.QL=new X(new n.BigBuffer(h*4),f,i),b.QR=new X(new n.BigBuffer(h*4),f,i),b.QM=new X(new n.BigBuffer(h*4),f,i),b.QO=new X(new n.BigBuffer(h*4),f,i),b.QC=new X(new n.BigBuffer(h*4),f,i),await l.readToBuffer(b.QL.eval,0,h*4,u[8][0].p+h),await l.readToBuffer(b.QR.eval,0,h*4,u[9][0].p+h),await l.readToBuffer(b.QM.eval,0,h*4,u[7][0].p+h),await l.readToBuffer(b.QO.eval,0,h*4,u[10][0].p+h),await l.readToBuffer(b.QC.eval,0,h*4,u[11][0].p+h),b.Lagrange=new X(new n.BigBuffer(h*4*d.nPublic),f,i);for(let e=0;e=d.domainSize*3+6)throw Error(`T Polynomial is not well calculated`);i&&i.debug(`··· Computing T1, T2, T3 polynomials`),y.T1=new Y(new n.BigBuffer((d.domainSize+1)*m),f,i),y.T2=new Y(new n.BigBuffer((d.domainSize+1)*m),f,i),y.T3=new Y(new n.BigBuffer((d.domainSize+6)*m),f,i),y.T1.coef.set(y.T.coef.slice(0,h),0),y.T2.coef.set(y.T.coef.slice(h,h*2),0),y.T3.coef.set(y.T.coef.slice(h*2,h*3+6*m),0),y.T1.setCoef(d.domainSize,x.b[10]);let t=p.sub(y.T2.getCoef(0),x.b[10]);y.T2.setCoef(0,t),y.T2.setCoef(d.domainSize,x.b[11]);let r=p.sub(y.T3.getCoef(0),x.b[11]);y.T3.setCoef(0,r)}async function I(){i&&i.debug(`> Computing challenge xi`),C.reset(),C.addScalar(x.alpha),C.addPolCommitment(S.getPolynomial(`T1`)),C.addPolCommitment(S.getPolynomial(`T2`)),C.addPolCommitment(S.getPolynomial(`T3`)),x.xi=C.getChallenge(),x.xiw=p.mul(x.xi,p.w[d.power]),i&&i.debug(`··· challenges.xi: `+p.toString(x.xi,16)),S.addEvaluation(`eval_a`,y.A.evaluate(x.xi)),S.addEvaluation(`eval_b`,y.B.evaluate(x.xi)),S.addEvaluation(`eval_c`,y.C.evaluate(x.xi)),S.addEvaluation(`eval_s1`,y.Sigma1.evaluate(x.xi)),S.addEvaluation(`eval_s2`,y.Sigma2.evaluate(x.xi)),S.addEvaluation(`eval_zw`,y.Z.evaluate(x.xiw))}async function L(){i&&i.debug(`> Computing challenge v`),C.reset(),C.addScalar(x.xi),C.addScalar(S.getEvaluation(`eval_a`)),C.addScalar(S.getEvaluation(`eval_b`)),C.addScalar(S.getEvaluation(`eval_c`)),C.addScalar(S.getEvaluation(`eval_s1`)),C.addScalar(S.getEvaluation(`eval_s2`)),C.addScalar(S.getEvaluation(`eval_zw`)),x.v=[],x.v[1]=C.getChallenge(),i&&i.debug(`··· challenges.v: `+p.toString(x.v[1],16));for(let e=2;e<6;e++)x.v[e]=p.mul(x.v[e-1],x.v[1]);i&&i.debug(`> Computing linearisation polynomial R(X)`),await R(),i&&i.debug(`> Computing opening proof polynomial Wxi(X) polynomial`),z(),i&&i.debug(`> Computing opening proof polynomial Wxiw(X) polynomial`),ee(),i&&i.debug(`> Computing Wxi, Wxiw MSM`);let e=await y.Wxi.multiExponentiation(w,`Wxi`),t=await y.Wxiw.multiExponentiation(w,`Wxiw`);S.addPolynomial(`Wxi`,e),S.addPolynomial(`Wxiw`,t)}async function R(){let e=f.Fr;y.QL=new Y(new n.BigBuffer(h),f,i),y.QR=new Y(new n.BigBuffer(h),f,i),y.QM=new Y(new n.BigBuffer(h),f,i),y.QO=new Y(new n.BigBuffer(h),f,i),y.QC=new Y(new n.BigBuffer(h),f,i),await l.readToBuffer(y.QL.coef,0,h,u[8][0].p),await l.readToBuffer(y.QR.coef,0,h,u[9][0].p),await l.readToBuffer(y.QM.coef,0,h,u[7][0].p),await l.readToBuffer(y.QO.coef,0,h,u[10][0].p),await l.readToBuffer(y.QC.coef,0,h,u[11][0].p),x.xin=x.xi;for(let t=0;tJr,fullProve:()=>kr,prove:()=>Dr,setup:()=>rr,verify:()=>jr});function Xr(e,t){return[e,0,0,t.one,t.zero,t.zero,t.zero,t.zero]}function Zr(e,t,n,r,i,a,o,s){return[e,t,n,r,i,a,o,s]}function Qr(e,t,n,r,i,a,o,s,c){return[e,t,n,r,i,a,o,s]}var $r=0,ei=1,ti=2,ni=class{constructor(e,t,n,r,i){this.Fr=e,this.logger=i,this.fnGetAdditionConstraint=n,this.fnGetMultiplicationConstraint=r}processR1csConstraint(e,t,n,r){this.normalizeLinearCombination(t),this.normalizeLinearCombination(n),this.normalizeLinearCombination(r);let i=this.getLinearCombinationType(t),a=this.getLinearCombinationType(n);if(i===$r||a===$r)return this.processR1csAdditionConstraint(e,r);if(i===ei){let i=this.joinLinearCombinations(n,r,t[0]);return this.processR1csAdditionConstraint(e,i)}else if(a===ei){let i=this.joinLinearCombinations(t,r,n[0]);return this.processR1csAdditionConstraint(e,i)}else return this.processR1csMultiplicationConstraint(e,t,n,r)}getLinearCombinationType(e){let t=this.Fr.zero,n=0,r=Object.keys(e);for(let i=0;i0?ti:this.Fr.isZero(t)?$r:ei}normalizeLinearCombination(e){let t=Object.keys(e);for(let n=0;ni;){let r=o.shift(),i=o.shift(),a=e.nVars++,s=this.fnGetAdditionConstraint(r[0],i[0],a,this.Fr.neg(r[1]),this.Fr.neg(i[1]),this.Fr.zero,this.Fr.one,this.Fr.zero);t.push(s),n.push([r[0],i[0],r[1],i[1]]),o.push([a,this.Fr.one])}for(let e=0;ethis.n-1)throw Error(`CPolynomial:addPolynomial, cannot add a polynomial to a position greater than n-1`);this.polynomials[e]=t}degree(){let e=this.polynomials.map((e,t)=>e===void 0?0:e.degree()*this.n+t);return Math.max(...e)}getPolynomial(){let e=this.polynomials.map(e=>e===void 0?0:e.degree()),t=this.degree(),r=2**(ye(t-1)+1),i=this.Fr.n8,a=new Y(new n.BigBuffer(r*i),this.curve,this.logger);for(let n=0;n Reading PTau file`);let{fd:s,sections:c}=await(0,t.readBinFile)(i,`ptau`,1,1<<22,1<<24);if(!c[12])throw Error(`Powers of Tau is not well prepared. Section 12 missing.`);o&&o.info(`> Getting curve from PTau settings`);let{curve:l}=await K(s,c);o&&o.info(`> Reading r1cs file`);let{fd:u,sections:d}=await(0,t.readBinFile)(e,`r1cs`,1,1<<22,1<<24),f=await(0,r.readR1csFd)(u,d,{loadConstraints:!1,loadCustomGates:!0});if(f.prime!==l.r)throw Error(`r1cs curve does not match powers of tau ceremony curve`);let p=l.Fr,m=l.Fr.n8,h=l.G1.F.n8*2,g=l.G2.F.n8*2,_={},v={},y,b={nVars:f.nVars,nPublic:f.nOutputs+f.nPubInputs},x=new J,S=new J;if(o&&o.info(`> Processing FFlonk constraints`),await k(l.Fr,f,o),globalThis.gc&&globalThis.gc(),b.cirPower=Math.max(3,ye(x.length+2-1)+1),b.domainSize=2**b.cirPower,c[2][0].size<(b.domainSize*9+18)*h)throw Error(`Powers of Tau is not big enough for this circuit size. Section 2 too small.`);if(c[3][0].size computing k1 and k2`);let[C,w]=te();o&&o.info(`> computing w3`);let T=ne();o&&o.info(`> computing w4`);let E=re();o&&o.info(`> computing w8`);let D=ie();o&&o.info(`> computing wr`);let O=ae(b.cirPower,l.Fr);return await A(),await u.close(),await s.close(),o&&o.info(`FFLONK SETUP FINISHED`),0;async function k(e,n,r){for(let t=0;t Writing the zkey file`);let e=await(0,t.createBinFile)(a,`zkey`,1,17,1<<22,1<<24);o&&o.info(`··· Writing Section 1. Zkey Header`),await j(e),o&&o.info(`··· Writing Section 3. Additions`),await M(e),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 4. A Map`),await N(e,4,0,`A map`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 5. B Map`),await N(e,5,1,`B map`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 6. C Map`),await N(e,6,2,`C map`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 7. QL`),await P(e,7,3,`QL`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 8. QR`),await P(e,8,4,`QR`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 9. QM`),await P(e,9,5,`QM`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 10. QO`),await P(e,10,6,`QO`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 11. QC`),await P(e,11,7,`QC`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Sections 12,13,14. Sigma1, Sigma2 & Sigma 3`),await F(e),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 15. Lagrange Polynomials`),await I(e),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 16. Powers of Tau`),await L(e),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 17. C0`),await R(e),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 2. FFlonk Header`),await z(e),globalThis.gc&&globalThis.gc(),o&&o.info(`> Writing the zkey file finished`),await e.close()}async function j(e){await(0,t.startWriteSection)(e,1),await e.writeULE32(10),await(0,t.endWriteSection)(e)}async function M(e){await(0,t.startWriteSection)(e,3);let n=new Uint8Array(8+2*m),r=new DataView(n.buffer);for(let t=0;t=8*b.domainSize)throw Error(`C0 Polynomial is not well calculated`);await(0,t.startWriteSection)(e,17),await e.write(_.C0.coef),await(0,t.endWriteSection)(e)}async function z(e){await(0,t.startWriteSection)(e,2);let r=l.q,i=(Math.floor((n.Scalar.bitLength(r)-1)/64)+1)*8;await e.writeULE32(i),await(0,t.writeBigInt)(e,r,i);let a=l.r,o=(Math.floor((n.Scalar.bitLength(a)-1)/64)+1)*8;await e.writeULE32(o),await(0,t.writeBigInt)(e,a,o),await e.writeULE32(b.nVars),await e.writeULE32(b.nPublic),await e.writeULE32(b.domainSize),await e.writeULE32(S.length),await e.writeULE32(x.length),await e.write(C),await e.write(w),await e.write(T),await e.write(E),await e.write(D),await e.write(O);let u;u=await s.read(g,c[3][0].p+g),await e.write(u);let d=await _.C0.multiExponentiation(y,`C0`);await e.write(d),await(0,t.endWriteSection)(e)}async function ee(e,t){let[n,r]=await Y.to4T(t,b.domainSize,[],p);return await e.write(n),await e.write(r),[n,r]}function te(){let e=p.two;for(;n(e,[],b.cirPower);)p.add(e,p.one);let t=p.add(e,p.one);for(;n(t,[e],b.cirPower);)p.add(t,p.one);return[e,t];function n(e,t,n){let r=2**n,i=p.one;for(let a=0;a Reading witness file`);let{fd:o,sections:s}=await t.readBinFile(r,`wtns`,2,1<<25,1<<23),c=await Qe(o,s);i&&i.info(`> Reading zkey file`);let{fd:l,sections:u}=await t.readBinFile(e,`zkey`,2,1<<25,1<<23),d=await Re(l,u,void 0,a);if(d.protocolId!==10)throw Error(`zkey file is not fflonk`);if(!n.Scalar.eq(d.r,c.q))throw Error(`Curve of the witness does not match the curve of the proving key`);if(c.nWitness!==d.nVars-d.nAdditions)throw Error(`Invalid witness length. Circuit: ${d.nVars}, witness: ${c.nWitness}, ${d.nAdditions}`);let f=d.curve,p=f.Fr,m=f.Fr.n8,h=f.G1.F.n8*2,g=d.domainSize*m;i&&(i.info(`----------------------------`),i.info(` FFLONK PROVE SETTINGS`),i.info(` Curve: ${f.name}`),i.info(` Circuit power: ${d.power}`),i.info(` Domain size: ${d.domainSize}`),i.info(` Vars: ${d.nVars}`),i.info(` Public vars: ${d.nPublic}`),i.info(` Constraints: ${d.nConstraints}`),i.info(` Additions: ${d.nAdditions}`),i.info(`----------------------------`)),i&&i.info(`> Reading witness file data`);let _=await t.readSection(o,s,2);await o.close(),_.set(p.zero,0);let v=new n.BigBuffer(d.nAdditions*m),y={},b={},x={},S={},C={},w={},T=new ir(f,i);i&&i.info(`> Reading Section 3. Additions`),await k(),i&&i.info(`> Reading Sections 12,13,14. Sigma1, Sigma2 & Sigma 3`),i&&i.info(`··· Reading Sigma polynomials `),b.Sigma1=new Y(new n.BigBuffer(g),f,i),b.Sigma2=new Y(new n.BigBuffer(g),f,i),b.Sigma3=new Y(new n.BigBuffer(g),f,i),await l.readToBuffer(b.Sigma1.coef,0,g,u[12][0].p),await l.readToBuffer(b.Sigma2.coef,0,g,u[13][0].p),await l.readToBuffer(b.Sigma3.coef,0,g,u[14][0].p),i&&i.info(`··· Reading Sigma evaluations`),x.Sigma1=new X(new n.BigBuffer(g*4),f,i),x.Sigma2=new X(new n.BigBuffer(g*4),f,i),x.Sigma3=new X(new n.BigBuffer(g*4),f,i),await l.readToBuffer(x.Sigma1.eval,0,g*4,u[12][0].p+g),await l.readToBuffer(x.Sigma2.eval,0,g*4,u[13][0].p+g),await l.readToBuffer(x.Sigma3.eval,0,g*4,u[14][0].p+g),i&&i.info(`> Reading Section 16. Powers of Tau`);let E=new n.BigBuffer(d.domainSize*16*h);await l.readToBuffer(E,0,(d.domainSize*9+18)*h,u[16][0].p),globalThis.gc&&globalThis.gc(),i&&i.info(``),i&&i.info(`> ROUND 1`),await M(),delete b.T0,delete x.QL,delete x.QR,delete x.QM,delete x.QO,delete x.QC,globalThis.gc&&globalThis.gc(),i&&i.info(`> ROUND 2`),await N(),delete y.A,delete y.B,delete y.C,delete x.A,delete x.B,delete x.C,delete x.Sigma1,delete x.Sigma2,delete x.Sigma3,delete x.lagrange1,delete x.Z,globalThis.gc&&globalThis.gc(),i&&i.info(`> ROUND 3`),await P(),delete b.A,delete b.B,delete b.C,delete b.Z,delete b.T1,delete b.T2,delete b.Sigma1,delete b.Sigma2,delete b.Sigma3,delete b.QL,delete b.QR,delete b.QM,delete b.QC,delete b.QO,globalThis.gc&&globalThis.gc(),i&&i.info(`> ROUND 4`),await F(),globalThis.gc&&globalThis.gc(),i&&i.info(`> ROUND 5`),await I(),delete b.C0,delete b.C1,delete b.C2,delete b.R1,delete b.R2,delete b.F,delete b.L,delete b.ZT,delete b.ZTS2,await l.close(),globalThis.gc&&globalThis.gc(),T.addEvaluation(`inv`,L());let D=T.toObjectProof();D.protocol=`fflonk`,D.curve=f.name;let O=[];for(let e=1;e<=d.nPublic;e++){let t=e*m,r=_.slice(t,t+m);O.push(n.Scalar.fromRprLE(r))}return i&&i.info(`FFLONK PROVER FINISHED`),{proof:ai(D),publicSignals:ai(O)};async function k(){i&&i.info(`··· Computing additions`);let e=await t.readSection(l,u,3),n=8+m*2;for(let t=0;t Computing A, B, C wire polynomials`),await r(),i&&i.info(`> Computing T0 polynomial`),await a(),i&&i.info(`> Computing C1 polynomial`),await o(),i&&i.info(`> Computing C1 multi exponentiation`);let e=await b.C1.multiExponentiation(E,`C1`);return T.addPolynomial(`C1`,e),0;async function r(){i&&i.info(`··· Reading data from zkey file`),y.A=new n.BigBuffer(g),y.B=new n.BigBuffer(g),y.C=new n.BigBuffer(g);let e=await t.readSection(l,u,4),r=await t.readSection(l,u,5),a=await t.readSection(l,u,6);for(let t=0;t=d.domainSize)throw Error(`A Polynomial is not well calculated`);if(b.B.degree()>=d.domainSize)throw Error(`B Polynomial is not well calculated`);if(b.C.degree()>=d.domainSize)throw Error(`C Polynomial is not well calculated`)}async function a(){i&&i.info(`··· Reading sections 7, 8, 9, 10, 11. Q selectors`),x.QL=new X(new n.BigBuffer(g*4),f,i),x.QR=new X(new n.BigBuffer(g*4),f,i),x.QM=new X(new n.BigBuffer(g*4),f,i),x.QO=new X(new n.BigBuffer(g*4),f,i),x.QC=new X(new n.BigBuffer(g*4),f,i),await l.readToBuffer(x.QL.eval,0,g*4,u[7][0].p+g),await l.readToBuffer(x.QR.eval,0,g*4,u[8][0].p+g),await l.readToBuffer(x.QM.eval,0,g*4,u[9][0].p+g),await l.readToBuffer(x.QO.eval,0,g*4,u[10][0].p+g),await l.readToBuffer(x.QC.eval,0,g*4,u[11][0].p+g),x.lagrange1=new X(await t.readSection(l,u,15),f,i),y.T0=new n.BigBuffer(g*4),i&&i.info(`··· Computing T0 evaluations`);for(let e=0;e=2*d.domainSize-2)throw Error(`T0 Polynomial is not well calculated (degree is ${b.T0.degree()} and must be less than ${2*d.domainSize+2}`);delete y.T0}async function o(){let e=new ri(4,f,i);if(e.addPolynomial(0,b.A),e.addPolynomial(1,b.B),e.addPolynomial(2,b.C),e.addPolynomial(3,b.T0),b.C1=e.getPolynomial(),b.C1.degree()>=8*d.domainSize-8)throw Error(`C1 Polynomial is not well calculated`)}}async function N(){i&&i.info(`> Computing challenges beta and gamma`);let e=new wr(f);e.addPolCommitment(d.C0);for(let t=0;t Computing Z polynomial`),await r(),i&&i.info(`> Computing T1 polynomial`),await a(),i&&i.info(`> Computing T2 polynomial`),await o(),i&&i.info(`> Computing C2 polynomial`),await s(),i&&i.info(`> Computing C2 multi exponentiation`);let t=await b.C2.multiExponentiation(E,`C2`);return T.addPolynomial(`C2`,t),0;async function r(){i&&i.info(`··· Computing Z evaluations`);let e=new n.BigBuffer(g),t=new n.BigBuffer(g);e.set(p.one,0),t.set(p.one,0);let r=p.one;for(let n=0;n=d.domainSize+3)throw Error(`Z Polynomial is not well calculated`);delete y.Z}async function a(){i&&i.info(`··· Computing T1 evaluations`),y.T1=new n.BigBuffer(g*2),y.T1z=new n.BigBuffer(g*2);let e=p.one;for(let t=0;t=d.domainSize+2)throw Error(`T1 Polynomial is not well calculated`);delete y.T1,delete y.T1z,delete b.T1z}async function o(){i&&i.info(`··· Computing T2 evaluations`),y.T2=new n.BigBuffer(g*4),y.T2z=new n.BigBuffer(g*4);let e=p.one;for(let t=0;t=3*d.domainSize)throw Error(`T2 Polynomial is not well calculated`);delete y.T2,delete y.T2z,delete b.T2z}async function s(){let e=new ri(3,f,i);if(e.addPolynomial(0,b.Z),e.addPolynomial(1,b.T1),e.addPolynomial(2,b.T2),b.C2=e.getPolynomial(),b.C2.degree()>=9*d.domainSize)throw Error(`C2 Polynomial is not well calculated`)}}async function P(){i&&i.info(`> Computing challenge xi`);let e=new wr(f);e.addScalar(C.gamma),e.addPolCommitment(T.getPolynomial(`C2`)),C.xiSeed=e.getChallenge();let t=p.square(C.xiSeed);w.w8=[],w.w8[0]=p.one;for(let e=1;e<8;e++)w.w8[e]=p.mul(w.w8[e-1],d.w8);w.w4=[],w.w4[0]=p.one;for(let e=1;e<4;e++)w.w4[e]=p.mul(w.w4[e-1],d.w4);w.w3=[],w.w3[0]=p.one,w.w3[1]=d.w3,w.w3[2]=p.square(d.w3),w.S0={},w.S0.h0w8=[],w.S0.h0w8[0]=p.mul(t,C.xiSeed);for(let e=1;e<8;e++)w.S0.h0w8[e]=p.mul(w.S0.h0w8[0],w.w8[e]);w.S1={},w.S1.h1w4=[],w.S1.h1w4[0]=p.square(w.S0.h0w8[0]);for(let e=1;e<4;e++)w.S1.h1w4[e]=p.mul(w.S1.h1w4[0],w.w4[e]);w.S2={},w.S2.h2w3=[],w.S2.h2w3[0]=p.mul(w.S1.h1w4[0],t),w.S2.h2w3[1]=p.mul(w.S2.h2w3[0],w.w3[1]),w.S2.h2w3[2]=p.mul(w.S2.h2w3[0],w.w3[2]),w.S2.h3w3=[],w.S2.h3w3[0]=p.mul(w.S2.h2w3[0],d.wr),w.S2.h3w3[1]=p.mul(w.S2.h3w3[0],w.w3[1]),w.S2.h3w3[2]=p.mul(w.S2.h3w3[0],w.w3[2]),C.xi=p.mul(p.square(w.S2.h2w3[0]),w.S2.h2w3[0]),i&&i.info(`··· challenges.xi: `+p.toString(C.xi)),b.QL=new Y(new n.BigBuffer(g),f,i),b.QR=new Y(new n.BigBuffer(g),f,i),b.QM=new Y(new n.BigBuffer(g),f,i),b.QO=new Y(new n.BigBuffer(g),f,i),b.QC=new Y(new n.BigBuffer(g),f,i),await l.readToBuffer(b.QL.coef,0,g,u[7][0].p),await l.readToBuffer(b.QR.coef,0,g,u[8][0].p),await l.readToBuffer(b.QM.coef,0,g,u[9][0].p),await l.readToBuffer(b.QO.coef,0,g,u[10][0].p),await l.readToBuffer(b.QC.coef,0,g,u[11][0].p),i&&i.info(`··· Computing evaluations`),T.addEvaluation(`ql`,b.QL.evaluate(C.xi)),T.addEvaluation(`qr`,b.QR.evaluate(C.xi)),T.addEvaluation(`qm`,b.QM.evaluate(C.xi)),T.addEvaluation(`qo`,b.QO.evaluate(C.xi)),T.addEvaluation(`qc`,b.QC.evaluate(C.xi)),T.addEvaluation(`s1`,b.Sigma1.evaluate(C.xi)),T.addEvaluation(`s2`,b.Sigma2.evaluate(C.xi)),T.addEvaluation(`s3`,b.Sigma3.evaluate(C.xi)),T.addEvaluation(`a`,b.A.evaluate(C.xi)),T.addEvaluation(`b`,b.B.evaluate(C.xi)),T.addEvaluation(`c`,b.C.evaluate(C.xi)),T.addEvaluation(`z`,b.Z.evaluate(C.xi)),C.xiw=p.mul(C.xi,p.w[d.power]),T.addEvaluation(`zw`,b.Z.evaluate(C.xiw)),T.addEvaluation(`t1w`,b.T1.evaluate(C.xiw)),T.addEvaluation(`t2w`,b.T2.evaluate(C.xiw))}async function F(){i&&i.info(`> Computing challenge alpha`);let e=new wr(f);e.addScalar(C.xiSeed),e.addScalar(T.getEvaluation(`ql`)),e.addScalar(T.getEvaluation(`qr`)),e.addScalar(T.getEvaluation(`qm`)),e.addScalar(T.getEvaluation(`qo`)),e.addScalar(T.getEvaluation(`qc`)),e.addScalar(T.getEvaluation(`s1`)),e.addScalar(T.getEvaluation(`s2`)),e.addScalar(T.getEvaluation(`s3`)),e.addScalar(T.getEvaluation(`a`)),e.addScalar(T.getEvaluation(`b`)),e.addScalar(T.getEvaluation(`c`)),e.addScalar(T.getEvaluation(`z`)),e.addScalar(T.getEvaluation(`zw`)),e.addScalar(T.getEvaluation(`t1w`)),e.addScalar(T.getEvaluation(`t2w`)),C.alpha=e.getChallenge(),i&&i.info(`··· challenges.alpha: `+p.toString(C.alpha)),i&&i.info(`> Reading C0 polynomial`),b.C0=new Y(new n.BigBuffer(g*8),f,i),await l.readToBuffer(b.C0.coef,0,g*8,u[17][0].p),i&&i.info(`> Computing R0 polynomial`),r(),i&&i.info(`> Computing R1 polynomial`),a(),i&&i.info(`> Computing R2 polynomial`),o(),i&&i.info(`> Computing F polynomial`),await s(),i&&i.info(`> Computing W1 multi exponentiation`);let t=await b.F.multiExponentiation(E,`W1`);return T.addPolynomial(`W1`,t),0;function r(){if(b.R0=Y.lagrangePolynomialInterpolation([w.S0.h0w8[0],w.S0.h0w8[1],w.S0.h0w8[2],w.S0.h0w8[3],w.S0.h0w8[4],w.S0.h0w8[5],w.S0.h0w8[6],w.S0.h0w8[7]],[b.C0.evaluate(w.S0.h0w8[0]),b.C0.evaluate(w.S0.h0w8[1]),b.C0.evaluate(w.S0.h0w8[2]),b.C0.evaluate(w.S0.h0w8[3]),b.C0.evaluate(w.S0.h0w8[4]),b.C0.evaluate(w.S0.h0w8[5]),b.C0.evaluate(w.S0.h0w8[6]),b.C0.evaluate(w.S0.h0w8[7])],f),b.R0.degree()>7)throw Error(`R0 Polynomial is not well calculated`)}function a(){if(b.R1=Y.lagrangePolynomialInterpolation([w.S1.h1w4[0],w.S1.h1w4[1],w.S1.h1w4[2],w.S1.h1w4[3]],[b.C1.evaluate(w.S1.h1w4[0]),b.C1.evaluate(w.S1.h1w4[1]),b.C1.evaluate(w.S1.h1w4[2]),b.C1.evaluate(w.S1.h1w4[3])],f),b.R1.degree()>3)throw Error(`R1 Polynomial is not well calculated`)}function o(){if(b.R2=Y.lagrangePolynomialInterpolation([w.S2.h2w3[0],w.S2.h2w3[1],w.S2.h2w3[2],w.S2.h3w3[0],w.S2.h3w3[1],w.S2.h3w3[2]],[b.C2.evaluate(w.S2.h2w3[0]),b.C2.evaluate(w.S2.h2w3[1]),b.C2.evaluate(w.S2.h2w3[2]),b.C2.evaluate(w.S2.h3w3[0]),b.C2.evaluate(w.S2.h3w3[1]),b.C2.evaluate(w.S2.h3w3[2])],f),b.R2.degree()>5)throw Error(`R2 Polynomial is not well calculated`)}async function s(){i&&i.info(`··· Computing F polynomial`),b.F=Y.fromPolynomial(b.C0,f,i),b.F.sub(b.R0),b.F.divByZerofier(8,C.xi);let e=Y.fromPolynomial(b.C1,f,i);e.sub(b.R1),e.mulScalar(C.alpha),e.divByZerofier(4,C.xi);let t=Y.fromPolynomial(b.C2,f,i);if(t.sub(b.R2),t.mulScalar(p.square(C.alpha)),t.divByZerofier(3,C.xi),t.divByZerofier(3,C.xiw),b.F.add(e),b.F.add(t),b.F.degree()>=9*d.domainSize-6)throw Error(`F Polynomial is not well calculated`)}}async function I(){i&&i.info(`> Computing challenge y`);let e=new wr(f);e.addScalar(C.alpha),e.addPolCommitment(T.getPolynomial(`W1`)),C.y=e.getChallenge(),i&&i.info(`··· challenges.y: `+p.toString(C.y)),i&&i.info(`> Computing L polynomial`),await o(),i&&i.info(`> Computing ZTS2 polynomial`),await c();let t=b.ZTS2.evaluate(C.y);t=p.inv(t),b.L.mulScalar(t);let n=Y.fromCoefficientsArray([p.neg(C.y),p.one],f);i&&i.info(`> Computing W' = L / ZTS2 polynomial`);let r=b.L.divBy(n);if(r.degree()>0)throw Error(`Degree of L(X)/(ZTS2(y)(X-y)) remainder is ${r.degree()} and should be 0`);if(b.L.degree()>=9*d.domainSize-1)throw Error(`Degree of L(X)/(ZTS2(y)(X-y)) is not correct`);i&&i.info(`> Computing W' multi exponentiation`);let a=await b.L.multiExponentiation(E,`W2`);return T.addPolynomial(`W2`,a),0;async function o(){i&&i.info(`··· Computing L polynomial`);let e=b.R0.evaluate(C.y),t=b.R1.evaluate(C.y),n=b.R2.evaluate(C.y),r=p.sub(C.y,w.S0.h0w8[0]);for(let e=1;e<8;e++)r=p.mul(r,p.sub(C.y,w.S0.h0w8[e]));let a=p.sub(C.y,w.S1.h1w4[0]);for(let e=1;e<4;e++)a=p.mul(a,p.sub(C.y,w.S1.h1w4[e]));let o=p.sub(C.y,w.S2.h2w3[0]);for(let e=1;e<3;e++)o=p.mul(o,p.sub(C.y,w.S2.h2w3[e]));for(let e=0;e<3;e++)o=p.mul(o,p.sub(C.y,w.S2.h3w3[e]));let c=p.mul(a,o),l=p.mul(C.alpha,p.mul(r,o)),u=p.mul(p.square(C.alpha),p.mul(r,a));S.denH1=a,S.denH2=o,b.L=Y.fromPolynomial(b.C0,f,i),b.L.subScalar(e),b.L.mulScalar(c);let m=Y.fromPolynomial(b.C1,f,i);m.subScalar(t),m.mulScalar(l);let h=Y.fromPolynomial(b.C2,f,i);h.subScalar(n),h.mulScalar(u),b.L.add(m),b.L.add(h),i&&i.info(`> Computing ZT polynomial`),await s();let g=b.ZT.evaluate(C.y);if(b.F.mulScalar(g),b.L.sub(b.F),b.L.degree()>=9*d.domainSize)throw Error(`L Polynomial is not well calculated`);delete y.L}async function s(){b.ZT=Y.zerofierPolynomial([w.S0.h0w8[0],w.S0.h0w8[1],w.S0.h0w8[2],w.S0.h0w8[3],w.S0.h0w8[4],w.S0.h0w8[5],w.S0.h0w8[6],w.S0.h0w8[7],w.S1.h1w4[0],w.S1.h1w4[1],w.S1.h1w4[2],w.S1.h1w4[3],w.S2.h2w3[0],w.S2.h2w3[1],w.S2.h2w3[2],w.S2.h3w3[0],w.S2.h3w3[1],w.S2.h3w3[2]],f)}async function c(){b.ZTS2=Y.zerofierPolynomial([w.S1.h1w4[0],w.S1.h1w4[1],w.S1.h1w4[2],w.S1.h1w4[3],w.S2.h2w3[0],w.S2.h2w3[1],w.S2.h2w3[2],w.S2.h3w3[0],w.S2.h3w3[1],w.S2.h3w3[2]],f)}}function L(){let e=C.xi;for(let t=0;t Checking commitments belong to G1`),!fi(i,o,a))return r&&r.error(`Proof commitments are not valid`),!1;if(r&&r.info(`> Checking evaluations belong to F`),!mi(i,o))return r&&r.error(`Proof evaluations are not valid.`),!1;if(r&&r.info(`> Checking public inputs belong to F`),!hi(i,s))return r&&r.error(`Public inputs are not valid.`),!1;r&&r.info(`> Computing challenges`);let{challenges:l,roots:u}=gi(i,o,a,s,r);r&&r.info(`> Computing Zero polynomial evaluation Z_H(xi)`),l.zh=c.sub(l.xiN,c.one),l.invzh=c.inv(l.zh),r&&r.info(`> Computing Lagrange evaluations`);let d=await _i(i,l,a);r&&r.info(`> Computing polynomial identities PI(X)`);let f=vi(i,s,d);r&&r.info(`> Computing r0(y)`);let p=yi(o,l,u,i,r);r&&r.info(`> Computing r1(y)`);let m=bi(o,l,u,f,i,r);r&&r.info(`> Computing r2(y)`);let h=xi(o,l,u,d[1],a,i,r);r&&r.info(`> Computing F`);let g=Si(i,o,a,l,u);r&&r.info(`> Computing E`);let _=Ci(i,o,l,a,p,m,h);r&&r.info(`> Computing J`);let v=wi(i,o,l);r&&r.info(`> Validate all evaluations with a pairing`);let y=await Ti(i,o,l,a,g,_,v);return r&&(y?r.info(`PROOF VERIFIED SUCCESSFULLY`):r.warn(`Invalid Proof`)),r&&r.info(`FFLONK VERIFIER FINISHED`),y}function di(e,t){let n=t;return n.k1=e.Fr.fromObject(t.k1),n.k2=e.Fr.fromObject(t.k2),n.w=e.Fr.fromObject(t.w),n.w3=e.Fr.fromObject(t.w3),n.w4=e.Fr.fromObject(t.w4),n.w8=e.Fr.fromObject(t.w8),n.wr=e.Fr.fromObject(t.wr),n.X_2=e.G2.fromObject(t.X_2),n.C0=e.G1.fromObject(t.C0),n}function fi(e,t,n){let r=e.G1;return r.isValid(t.polynomials.C1)&&r.isValid(t.polynomials.C2)&&r.isValid(t.polynomials.W1)&&r.isValid(t.polynomials.W2)&&r.isValid(n.C0)}function pi(e,t){return n.Scalar.geq(t,0)&&n.Scalar.lt(t,e.r)}function Q(e,t){return pi(e,n.Scalar.fromRprLE(t))}function mi(e,t){return Q(e,t.evaluations.ql)&&Q(e,t.evaluations.qr)&&Q(e,t.evaluations.qm)&&Q(e,t.evaluations.qo)&&Q(e,t.evaluations.qc)&&Q(e,t.evaluations.s1)&&Q(e,t.evaluations.s2)&&Q(e,t.evaluations.s3)&&Q(e,t.evaluations.a)&&Q(e,t.evaluations.b)&&Q(e,t.evaluations.c)&&Q(e,t.evaluations.z)&&Q(e,t.evaluations.zw)&&Q(e,t.evaluations.t1w)&&Q(e,t.evaluations.t2w)}function hi(e,t){for(let n=0;nki,exportSolidityVerifier:()=>null,fullProve:()=>ci,prove:()=>oi,setup:()=>ii,verify:()=>ui});return Object.defineProperty(e,"curves",{enumerable:!0,get:function(){return p}}),Object.defineProperty(e,"fflonk",{enumerable:!0,get:function(){return Ai}}),Object.defineProperty(e,"groth16",{enumerable:!0,get:function(){return Jt}}),Object.defineProperty(e,"plonk",{enumerable:!0,get:function(){return Yr}}),Object.defineProperty(e,"powersOfTau",{enumerable:!0,get:function(){return Tn}}),Object.defineProperty(e,"r1cs",{enumerable:!0,get:function(){return jn}}),Object.defineProperty(e,"wtns",{enumerable:!0,get:function(){return Ln}}),Object.defineProperty(e,"zKey",{enumerable:!0,get:function(){return nr}}),e})({},_iden3_binfileutils,ffjavascript,r1csfile); \ No newline at end of file +`);for(let e=0;e `+t.toString())}),a.trigger&&(d||=await Mn(i),u.logStartComponent=function(e){o&&o.info(`START: `+d.componentIdx2Name[e])},u.logFinishComponent=function(e){o&&o.info(`FINISH: `+d.componentIdx2Name[e])}),u.sym=d;let f=await Nt(l,u),p=await f.calculateWitness(s,!0),m=await t.createBinFile(r,`wtns`,2,2);await Xe(m,p,f.prime),await m.close()}async function Fn(e){return await $e(e)}async function In(e,i,a){a&&a.info(`WITNESS CHECKING STARTED`),a&&a.info(`> Reading r1cs file`);let{fd:o,sections:s}=await t.readBinFile(e,`r1cs`,1,1<<22,1<<24),c=await(0,r.readR1csFd)(o,s,{loadConstraints:!1,loadCustomGates:!1});a&&a.info(`> Reading witness file`);let{fd:l,sections:u}=await t.readBinFile(i,`wtns`,2,1<<22,1<<24),d=await Qe(l,u);if(!n.Scalar.eq(c.prime,d.q))throw Error(`Curve of the witness does not match the curve of the proving key`);let f=await t.readSection(l,u,2);await l.close();let p=(await v(c.prime)).Fr,m=p.n8,h=await t.readSection(o,s,2);a&&(a.info(`----------------------------`),a.info(` WITNESS CHECK`),a.info(` Curve: ${c.curve.name}`),a.info(` Vars (wires): ${c.nVars}`),a.info(` Outputs: ${c.nOutputs}`),a.info(` Public Inputs: ${c.nPubInputs}`),a.info(` Private Inputs: ${c.nPrvInputs}`),a.info(` Labels: ${c.nLabels}`),a.info(` Constraints: ${c.nConstraints}`),a.info(` Custom Gates: ${c.useCustomGates}`),a.info(`----------------------------`)),a&&a.info(`> Checking witness correctness`);let g=0,_=!0;for(let e=0;e{let r=x(n),i=e[n];t=p.add(t,p.mul(r,i))}),t}function b(){let e={},t=h.slice(g,g+4);g+=4;let n=new DataView(t.buffer).getUint32(0,!0),r=h.slice(g,g+(4+c.n8)*n);g+=(4+c.n8)*n;let i=new DataView(r.buffer);for(let t=0;tLt,check:()=>In,debug:()=>Pn,exportJson:()=>Fn}),Rn=262144,zn={get:function(e,t){return isNaN(t)?e[t]:e.getElement(t)},set:function(e,t,n){return isNaN(t)?(e[t]=n,!0):e.setElement(t,n)}},Bn=class{constructor(e){this.length=e||0,this.arr=Array(Rn);for(let t=0;t=this.length&&(this.length=e+1),!0}getKeys(){let e=new J;for(let t=0;td)return o&&o.error(`circuit too big for this power of tau ceremony. ${m.nConstraints}*2 > 2**${d}`),-1;if(!l[12])return o&&o.error(`Powers of tau is not prepared.`),-1;let y=m.nOutputs+m.nPubInputs,b=2**v;await(0,t.startWriteSection)(h,1),await h.writeULE32(1),await(0,t.endWriteSection)(h),await(0,t.startWriteSection)(h,2);let x=u.q,S=(Math.floor((n.Scalar.bitLength(x)-1)/64)+1)*8,C=u.r,w=(Math.floor((n.Scalar.bitLength(C)-1)/64)+1)*8,T=n.Scalar.mod(n.Scalar.shl(1,w*8),C),E=u.Fr.e(n.Scalar.mod(n.Scalar.mul(T,T),C));await h.writeULE32(S),await(0,t.writeBigInt)(h,x,S),await h.writeULE32(w),await(0,t.writeBigInt)(h,C,w),await h.writeULE32(m.nVars),await h.writeULE32(y),await h.writeULE32(b);let D;D=await c.read(g,l[4][0].p),await h.write(D),D=await u.G1.batchLEMtoU(D),s.update(D);let O;O=await c.read(g,l[5][0].p),await h.write(O),O=await u.G1.batchLEMtoU(O),s.update(O);let k;k=await c.read(_,l[6][0].p),await h.write(k),k=await u.G2.batchLEMtoU(k),s.update(k);let A=new Uint8Array(g);u.G1.toRprLEM(A,0,u.G1.g);let j=new Uint8Array(_);u.G2.toRprLEM(j,0,u.G2.g);let M=new Uint8Array(g);u.G1.toRprUncompressed(M,0,u.G1.g);let N=new Uint8Array(_);u.G2.toRprUncompressed(N,0,u.G2.g),await h.write(j),await h.write(A),await h.write(j),s.update(N),s.update(M),s.update(N),await(0,t.endWriteSection)(h),o&&o.info(V()),o&&o.info(`Reading r1cs`);let P=await(0,t.readSection)(f,p,2);await f.close();let F=new J(m.nVars),I=new J(m.nVars),L=new J(m.nVars),R=new J(m.nVars-y-1),z=Array(y+1);o&&o.info(V()),o&&o.info(`Reading tauG1`);let ee=await(0,t.readSection)(c,l,12,(b-1)*g,b*g);o&&o.info(`Reading tauG2`);let te=await(0,t.readSection)(c,l,13,(b-1)*_,b*_);o&&o.info(`Reading alphatauG1`);let ne=await(0,t.readSection)(c,l,14,(b-1)*g,b*g);o&&o.info(`Reading betatauG1`);let re=await(0,t.readSection)(c,l,15,(b-1)*g,b*g);o&&o.info(V()),o&&o.info(`processConstraints`),await oe(),o&&o.info(V()),o&&o.info(`composeAndWritePoints`),await se(3,`G1`,z,`IC`),z=null,o&&o.info(V()),o&&o.info(`writeHs`),await ae(),o&&o.info(V()),o&&o.info(`hashHPoints`),await le(),o&&o.info(V()),o&&o.info(`composeAndWritePoints 8 G1 C`),await se(8,`G1`,R,`C`),R=null,o&&o.info(V()),o&&o.info(`composeAndWritePoints 5 G1 A`),await se(5,`G1`,F,`A`),F=null,o&&o.info(V()),o&&o.info(`composeAndWritePoints 6 G1 B1`),await se(6,`G1`,I,`B1`),I=null,o&&o.info(V()),o&&o.info(`composeAndWritePoints 7 G2 B2`),await se(7,`G2`,L,`B2`),L=null,o&&o.info(V()),o&&o.info(`Contributions section`);let ie=s.digest();return await(0,t.startWriteSection)(h,10),await h.write(ie),await h.writeULE32(0),await(0,t.endWriteSection)(h),o&&o.info(U(ie,`Circuit hash: `)),await h.close(),await c.close(),ie;async function ae(){await(0,t.startWriteSection)(h,9);let e=new n.BigBuffer(b*g);if(v=0?u.Fr.fromRprLE(P.slice(t[3],t[3]+u.Fr.n8),0):u.Fr.fromRprLE(i,0);let a=u.Fr.mul(n,E);u.Fr.toRprLE(e,12,a),l.set(e,f),f+=e.length}}async function se(e,n,r,i){let a=32768,c=u[n];B(r.length),await(0,t.startWriteSection)(h,e);let l=[],d=0;for(;d(o&&o.debug(`Writing points end ${i}: ${u}/${r.length}`),e))),d+=t,e++}let t=await Promise.all(l);for(let e=0;e32768?(h=new n.BigBuffer(m*o),g=new n.BigBuffer(m*u.Fr.n8)):(h=new Uint8Array(m*o),g=new Uint8Array(m*u.Fr.n8));let _,v,y=[ee,te,ne,re],b=new Uint8Array(u.Fr.n8);u.Fr.toRprLE(b,0,u.Fr.e(1));let x=0;for(let e=0;e=0?g.set(P.slice(t[e][n][2],t[e][n][2]+u.Fr.n8),x*u.Fr.n8):g.set(b,x*u.Fr.n8),x++;if(t.length>1){let e=[];e.push({cmd:`ALLOCSET`,var:0,buff:h}),e.push({cmd:`ALLOCSET`,var:1,buff:g}),e.push({cmd:`ALLOC`,var:2,len:t.length*s}),_=0,v=0;let n=0;for(let r=0;r`u`||!process.memoryUsage)return{};let e=process.memoryUsage();for(let t in e)e[t]=Math.round(e[t]/(1024*1024));return e}}async function Hn(e,n,r){let{fd:i,sections:a}=await t.readBinFile(e,`zkey`,2),o=await Re(i,a);if(o.protocol!=`groth16`)throw Error(`zkey file is not groth16`);let s=await y(o.q),c=s.G1.F.n8*2,l=s.G2.F.n8*2,u=await We(i,s,a),d=await Dt(n);await b(o.vk_alpha_1),await b(o.vk_beta_1),await x(o.vk_beta_2),await x(o.vk_gamma_2),await b(o.vk_delta_1),await x(o.vk_delta_2);let f;f=await t.readSection(i,a,3),f=await s.G1.batchLEMtoU(f),await S(`G1`,f);let p=await t.readSection(i,a,9),m;m=await s.G1.fft(p,`affine`,`jacobian`,r),m=await s.G1.batchApplyKey(m,s.Fr.neg(s.Fr.e(2)),s.Fr.w[o.power+1],`jacobian`,`affine`,r),m=m.slice(0,m.byteLength-c),m=await s.G1.batchLEMtoU(m),await S(`G1`,m);let h;h=await t.readSection(i,a,8),h=await s.G1.batchLEMtoU(h),await S(`G1`,h);let g;g=await t.readSection(i,a,5),g=await s.G1.batchLEMtoU(g),await S(`G1`,g);let _;_=await t.readSection(i,a,6),_=await s.G1.batchLEMtoU(_),await S(`G1`,_);let v;v=await t.readSection(i,a,7),v=await s.G2.batchLEMtoU(v),await S(`G2`,v),await d.write(u.csHash),await C(u.contributions.length);for(let e=0;ep.contributions.length)return a&&a.error(`The impoerted file does not include new contributions`),!1;for(let e=0;e=0;e--){let t=f.contributions[e];a&&a.info(`-------------------------`),a&&a.info(U(t.contributionHash,`contribution #${e+1} ${t.name?t.name:``}:`)),t.type==1&&(a&&a.info(`Beacon generator: ${Me(t.beaconHash)}`),a&&a.info(`Beacon iterations Exp: ${t.numIterationsExp}`))}return a&&a.info(`-------------------------`),a&&a.info(`ZKey Ok!`),!0;async function x(e,n,r,i,s,c,l,d,f){let p=1<<20,m=u[e],h=m.F.n8*2;await t.startReadUniqueSection(n,r,c),await t.startReadUniqueSection(i,s,c);let g=m.zero,_=m.zero,v=r[c][0].size/h;for(let e=0;e=256)return o&&o.error(`Maximum length of beacon hash is 255 bytes`),!1;if(a=parseInt(a),a<10||a>63)return o&&o.error(`Invalid numIterationsExp. (Must be between 10 and 63)`),!1;let{fd:c,sections:l}=await t.readBinFile(e,`zkey`,2),u=await Re(c,l);if(u.protocol!=`groth16`)throw Error(`zkey file is not groth16`);let d=await y(u.q),f=await We(c,d,l),p=await t.createBinFile(n,`zkey`,1,10),m=await Ae(s,a),h=H.create({dkLen:64});h.update(f.csHash);for(let e=0;e Detected protocol: `+a.protocol);let o;if(a.protocol===`groth16`)o=await $n(a,r,i);else if(a.protocol===`plonk`)o=await er(a);else if(a.protocolId&&a.protocolId===10)o=await tr(a,n);else throw Error(`zkey file protocol unrecognized`);return await r.close(),n&&n.info(`EXPORT VERIFICATION KEY FINISHED`),o}async function $n(e,n,r){let i=await y(e.q),a=i.G1.F.n8*2,o=await i.pairing(e.vk_alpha_1,e.vk_beta_2),s={protocol:e.protocol,curve:i.name,nPublic:e.nPublic,vk_alpha_1:i.G1.toObject(e.vk_alpha_1),vk_beta_2:i.G2.toObject(e.vk_beta_2),vk_gamma_2:i.G2.toObject(e.vk_gamma_2),vk_delta_2:i.G2.toObject(e.vk_delta_2),vk_alphabeta_12:i.Gt.toObject(o)};await t.startReadUniqueSection(n,r,3),s.IC=[];for(let t=0;t<=e.nPublic;t++){let e=await n.read(a),t=i.G1.toObject(e);s.IC.push(t)}return await t.endReadSection(n),s=Zn(s),s}async function er(e){let t=await y(e.q),n={protocol:e.protocol,curve:t.name,nPublic:e.nPublic,power:e.power,k1:t.Fr.toObject(e.k1),k2:t.Fr.toObject(e.k2),Qm:t.G1.toObject(e.Qm),Ql:t.G1.toObject(e.Ql),Qr:t.G1.toObject(e.Qr),Qo:t.G1.toObject(e.Qo),Qc:t.G1.toObject(e.Qc),S1:t.G1.toObject(e.S1),S2:t.G1.toObject(e.S2),S3:t.G1.toObject(e.S3),X_2:t.G2.toObject(e.X_2),w:t.Fr.toObject(t.Fr.w[e.power])};return n=Zn(n),n}async function tr(e,t){let n=await y(e.q);return Zn({protocol:e.protocol,curve:n.name,nPublic:e.nPublic,power:e.power,k1:n.Fr.toObject(e.k1),k2:n.Fr.toObject(e.k2),w:n.Fr.toObject(n.Fr.w[e.power]),w3:n.Fr.toObject(e.w3),w4:n.Fr.toObject(e.w4),w8:n.Fr.toObject(e.w8),wr:n.Fr.toObject(e.wr),X_2:n.G2.toObject(e.X_2),C0:n.G1.toObject(e.C0)})}var nr=d({beacon:()=>Jn,bellmanContribute:()=>Xn,contribute:()=>qn,exportBellman:()=>Hn,exportJson:()=>Yn,exportSolidityVerifier:()=>null,exportVerificationKey:()=>Qn,importBellman:()=>Un,newZKey:()=>Vn,verifyFromInit:()=>Gn,verifyFromR1cs:()=>Kn});async function rr(e,i,a,o){globalThis.gc&&globalThis.gc();let{fd:s,sections:c}=await(0,t.readBinFile)(i,`ptau`,1,1<<22,1<<24),{curve:l,power:u}=await K(s,c),{fd:d,sections:f}=await(0,t.readBinFile)(e,`r1cs`,1,1<<22,1<<24),p=await(0,r.readR1csFd)(d,f,{loadConstraints:!0,loadCustomGates:!0}),m=l.G1.F.n8*2,h=l.G1,g=l.G2.F.n8*2,_=l.Fr,v=l.Fr.n8;o&&o.info(`Reading r1cs`),await(0,t.readSection)(d,f,2);let y=new J,b=new J,x=p.nVars,S=p.nOutputs+p.nPubInputs;await M(l.Fr,p,o),globalThis.gc&&globalThis.gc();let C=await(0,t.createBinFile)(a,`zkey`,1,14,1<<22,1<<24);if(p.prime!=l.r)return o&&o.error(`r1cs curve does not match powers of tau ceremony curve`),-1;let w=ye(y.length-1)+1;w<3&&(w=3);let T=2**w;if(o&&o.info(`Plonk constraints: `+y.length),w>u)return o&&o.error(`circuit too big for this power of tau ceremony. ${y.length} > 2**${u}`),-1;if(!c[12])return o&&o.error(`Powers of tau is not prepared.`),-1;let E=new n.BigBuffer(T*m),D=c[12][0].p+(2**w-1)*m;await s.readToBuffer(E,0,T*m,D);let[O,k]=ee(),A={};await I(3,`Additions`),globalThis.gc&&globalThis.gc(),await N(4,0,`Amap`),globalThis.gc&&globalThis.gc(),await N(5,1,`Bmap`),globalThis.gc&&globalThis.gc(),await N(6,2,`Cmap`),globalThis.gc&&globalThis.gc(),await P(7,3,`Qm`),globalThis.gc&&globalThis.gc(),await P(8,4,`Ql`),globalThis.gc&&globalThis.gc(),await P(9,5,`Qr`),globalThis.gc&&globalThis.gc(),await P(10,6,`Qo`),globalThis.gc&&globalThis.gc(),await P(11,7,`Qc`),globalThis.gc&&globalThis.gc(),await L(12,`sigma`),globalThis.gc&&globalThis.gc(),await R(13,`lagrange polynomials`),globalThis.gc&&globalThis.gc(),await(0,t.startWriteSection)(C,14);let j=new n.BigBuffer((T+6)*m);await s.readToBuffer(j,0,(T+6)*m,c[2][0].p),await C.write(j),await(0,t.endWriteSection)(C),globalThis.gc&&globalThis.gc(),await z(),await C.close(),await d.close(),await s.close(),o&&o.info(`Setup Finished`);return;async function M(e,t,n){function r(e){let t=Object.keys(e);for(let n=0;nn;){let t=i.shift(),n=i.shift(),r=t[0],a=n[0],o=x++,s=e.zero,c=e.neg(t[1]),l=e.neg(n[1]),u=e.one,d=e.zero;y.push([r,a,o,s,c,l,u,d]),b.push([r,a,t[1],n[1]]),i.push([o,e.one])}for(let e=0;e0?r.toString():n==e.zero?`0`:`k`}function l(e,t,n){let a=c(e),l=c(t);a===`0`||l===`0`?(r(n),o(n)):a===`k`?o(i(t,e[0],n)):l===`k`?o(i(e,t[0],n)):s(e,t,n)}for(let t=1;t<=S;t++){let n=t,r=e.zero,i=e.one,a=e.zero,o=e.zero,s=e.zero;y.push([n,0,0,r,i,a,o,s])}for(let e=0;e{let r=this.curve.G1.toObject(this.polynomials[n]);e?t.polynomials[n]=r:t[n]=r}),Object.keys(this.evaluations).forEach(n=>{let r=this.curve.Fr.toObject(this.evaluations[n]);e?t.evaluations[n]=r:t[n]=r}),t}fromObjectProof(e){this.resetProof(),Object.keys(e.polynomials).forEach(t=>{this.polynomials[t]=this.curve.G1.fromObject(e.polynomials[t])}),Object.keys(e.evaluations).forEach(t=>{this.evaluations[t]=this.curve.Fr.fromObject(e.evaluations[t])})}},ar=BigInt(0),or=BigInt(1),sr=BigInt(2),cr=BigInt(7),lr=BigInt(256),ur=BigInt(113),dr=[],fr=[],pr=[];for(let e=0,t=or,n=1,r=0;e<24;e++){[n,r]=[r,(2*n+3*r)%5],dr.push(2*(5*r+n)),fr.push((e+1)*(e+2)/2%64);let i=ar;for(let e=0;e<7;e++)t=(t<>cr)*ur)%lr,t&sr&&(i^=or<<(or<n>32?se(e,t,n):ae(e,t,n),vr=(e,t,n)=>n>32?ce(e,t,n):oe(e,t,n);function yr(e,t=24){if(S(t,`rounds`),t<1||t>24)throw Error(`"rounds" expected integer 1..24`);let n=new Uint32Array(10);for(let r=24-t;r<24;r++){for(let t=0;t<10;t++)n[t]=e[t]^e[t+10]^e[t+20]^e[t+30]^e[t+40];for(let t=0;t<10;t+=2){let r=(t+8)%10,i=(t+2)%10,a=n[i],o=n[i+1],s=_r(a,o,1)^n[r],c=vr(a,o,1)^n[r+1];for(let n=0;n<50;n+=10)e[t+n]^=s,e[t+n+1]^=c}let t=e[2],i=e[3];for(let n=0;n<24;n++){let r=fr[n],a=_r(t,i,r),o=vr(t,i,r),s=dr[n];t=e[s],i=e[s+1],e[s]=a,e[s+1]=o}for(let t=0;t<50;t+=10){let n=e[t],r=e[t+1],i=e[t+2],a=e[t+3];e[t]^=~e[t+2]&e[t+4],e[t+1]^=~e[t+3]&e[t+5],e[t+2]^=~e[t+4]&e[t+6],e[t+3]^=~e[t+5]&e[t+7],e[t+4]^=~e[t+6]&e[t+8],e[t+5]^=~e[t+7]&e[t+9],e[t+6]^=~e[t+8]&n,e[t+7]^=~e[t+9]&r,e[t+8]^=~n&i,e[t+9]^=~r&a}e[0]^=hr[r],e[1]^=gr[r]}D(n)}var br=class e{state;pos=0;posOut=0;finished=!1;state32;destroyed=!1;blockLen;suffix;outputLen;canXOF;enableXOF=!1;rounds;constructor(e,t,n,r=!1,i=24){if(this.blockLen=e,this.suffix=t,this.outputLen=n,this.enableXOF=r,this.canXOF=r,this.rounds=i,S(n,`outputLen`),!(0=n&&this.keccak();let a=Math.min(n-this.posOut,i-r);e.set(t.subarray(this.posOut,this.posOut+a),r),this.posOut+=a,r+=a}return e}xofInto(e){if(!this.enableXOF)throw Error(`XOF is not possible for this instance`);return this.writeInto(e)}xof(e){return S(e),this.xofInto(new Uint8Array(e))}digestInto(e){if(T(e,this),this.finished)throw Error(`digest() was already called`);this.writeInto(e.subarray(0,this.outputLen)),this.destroy()}digest(){let e=new Uint8Array(this.outputLen);return this.digestInto(e),e}destroy(){this.destroyed=!0,D(this.state)}_cloneInto(t){let{blockLen:n,suffix:r,outputLen:i,rounds:a,enableXOF:o}=this;return t||=new e(n,r,i,o,a),t.blockLen=n,t.state32.set(this.state32),t.pos=this.pos,t.posOut=this.posOut,t.finished=this.finished,t.rounds=a,t.suffix=r,t.outputLen=i,t.enableXOF=o,t.canXOF=this.canXOF,t.destroyed=this.destroyed,t}},xr=((e,t,n,r={})=>N(()=>new br(t,e,n),r))(1,136,32),Sr=0,Cr=1,wr=class{constructor(e){this.G1=e.G1,this.Fr=e.Fr,this.reset()}reset(){this.data=[]}addPolCommitment(e){this.data.push({type:Sr,data:e})}addScalar(e){this.data.push({type:Cr,data:e})}getChallenge(){if(this.data.length===0)throw Error(`Keccak256Transcript: No data to generate a transcript`);let e=0,t=0;this.data.forEach(n=>Sr===n.type?e++:t++);let r=new Uint8Array(t*this.Fr.n8+e*this.G1.F.n8*2),i=0;for(let e=0;e32768?new n.BigBuffer(t.length*a.n8):new Uint8Array(t.length*a.n8);for(let e=0;e32768?new n.BigBuffer(a*o.n8):new Uint8Array(a*o.n8);return s.set(t.coef.slice(),0),new e(s,r,i)}isEqual(e){let t=this.degree();if(t!==e.degree())return!1;for(let n=0;n32768?new n.BigBuffer((this.length()+e.length)*this.Fr.n8):new Uint8Array((this.length()+e.length)*this.Fr.n8);t.set(this.coef,0);for(let n=0;nthis.coef.byteLength?this.Fr.zero:this.coef.slice(t,t+this.Fr.n8)}setCoef(e,t){if(e>this.length()-1)throw Error(`Coef index is not available`);this.coef.set(t,e*this.Fr.n8)}static async to4T(e,t,r,i){r||=[];let a=await i.ifft(e),o=t*4>32768?new n.BigBuffer(t*4*i.n8):new Uint8Array(t*4*i.n8);o.set(a,0);let s=await i.fft(o);if(r.length===0)return[a,s];let c=t+r.length>32768?new n.BigBuffer((t+r.length)*i.n8):new Uint8Array((t+r.length)*i.n8);c.set(a,0);for(let e=0;e0;e--){let t=e*this.Fr.n8;if(!this.Fr.eq(this.Fr.zero,this.coef.slice(t,t+this.Fr.n8)))return e}return 0}evaluate(e){let t=this.Fr.zero;for(let n=this.degree()+1;n>0;n--){let r=n*this.Fr.n8,i=this.coef.slice(r-this.Fr.n8,r);t=this.Fr.add(i,this.Fr.mul(t,e))}return t}fastEvaluate(e){let t=this.Fr,n=this.degree()+1,r=parseInt(n/3),i=n-r*3,a=[],o=[];o[0]=t.one;for(let n=0;n<3;n++){a[n]=t.zero;let s=n===2?r+i:r;for(let i=s;i>0;i--)a[n]=t.add(this.getCoef(n*r+i-1),t.mul(a[n],e)),n===0&&(o[0]=t.mul(o[0],e))}for(let e=1;e<3;e++)a[0]=t.add(a[0],t.mul(o[e-1],a[e])),o[e]=t.mul(o[e-1],o[0]);return a[0]}add(e,t){let n=!1;e.length()>this.length()&&(n=!0);let r=this.length(),i=e.length();for(let a=0;athis.length()&&(n=!0);let r=this.length(),i=e.length();for(let a=0;a32768?new n.BigBuffer(i*r.n8):new Uint8Array(i*r.n8),this.curve,this.logger);a.coef.set(this.coef.slice(0,(i-1)*r.n8),32),this.mulScalar(r.neg(t)),a.add(this),this.coef=a.coef}byXNSubValue(t,r){let i=this.Fr,a=this.length()-t-1>=this.degree()?this.length():this.length()+t,o=new e(a>32768?new n.BigBuffer(a*i.n8):new Uint8Array(a*i.n8),this.curve,this.logger);o.coef.set(this.coef.slice(0,(this.degree()+1)*32),t*32),this.mulScalar(r),o.add(this),this.coef=o.coef}divBy(t){let r=this.Fr,i=this.degree(),a=t.degree(),o=new e(this.coef,this.curve,this.logger);this.coef=this.length()>32768?new n.BigBuffer(this.length()*r.n8):new Uint8Array(this.length()*r.n8);for(let e=i-a;e>=0;e--){this.setCoef(e,r.div(o.getCoef(e+a),t.getCoef(a)));for(let n=0;n<=a;n++)o.setCoef(e+n,r.sub(o.getCoef(e+n),r.mul(this.getCoef(e),t.getCoef(n))))}return o}divByMonic(t,r){let i=this.Fr,a=this.degree(),o=new e(this.length()>32768?new n.BigBuffer(this.length()*i.n8):new Uint8Array(this.length()*i.n8),this.curve,this.logger),s=[];for(let e=0;e=0&&!(n<0);n-=c){let a=e;s[a]=i.add(this.getCoef(n+t),i.mul(s[a],r)),o.setCoef(n,s[a]),l=(l+1)%t}this.coef=o.coef}divByVanishing(t,r){if(this.degree()32768?new n.BigBuffer(this.length()*i.n8):new Uint8Array(this.length()*i.n8);for(let e=this.length()-1;e>=t;e--){let n=a.getCoef(e);i.eq(i.zero,n)||(a.setCoef(e,i.zero),a.setCoef(e-t,i.add(a.getCoef(e-t),i.mul(r,n))),this.setCoef(e-t,i.add(this.getCoef(e-t),n)))}return a}divByVanishing2(t,r){if(this.degree()32768?new n.BigBuffer(this.length()*i.n8):new Uint8Array(this.length()*i.n8);let o=this.length()-t,s=Math.floor(o/3),c=o-2*s;for(let e=0;e<3;e++)for(let n=e===0?c:s;n>0;n--){let o=n-1;e!==0&&(o+=(e-1)*s+c);let l=o+t,u=a.getCoef(l);i.eq(i.zero,u)||(a.setCoef(l,i.zero),a.setCoef(o,i.add(a.getCoef(o),i.mul(r,u))),this.setCoef(o,i.add(this.getCoef(o),u)))}return this.print(),a}fastDivByVanishing(t){let r=this.Fr;for(let i=0;i32768?new n.BigBuffer(this.length()*r.n8):new Uint8Array(this.length()*r.n8),this.curve,this.logger),f=this.coef;this.coef=d.coef,d.coef=f;for(let e=0;e<5;e++){let t=(e+1)*l+u;for(let e=0;e0;e--){let t=e-1,n=t*l+u;h[t]=[];for(let i=0;i32768?new n.BigBuffer(this.length()*this.Fr.n8):new Uint8Array(this.length()*this.Fr.n8);t.set(this.Fr.zero,(this.length()-1)*this.Fr.n8),t.set(this.coef.slice((this.length()-1)*this.Fr.n8,this.length()*this.Fr.n8),(this.length()-2)*this.Fr.n8);for(let n=this.length()-3;n>=0;n--){let r=n*this.Fr.n8;t.set(this.Fr.add(this.coef.slice(r+this.Fr.n8,r+2*this.Fr.n8),this.Fr.mul(e,t.slice(r+this.Fr.n8,r+2*this.Fr.n8))),n*this.Fr.n8)}if(!this.Fr.eq(this.coef.slice(0,this.Fr.n8),this.Fr.mul(this.Fr.neg(e),t.slice(0,this.Fr.n8))))throw Error(`Polynomial does not divide`);this.coef=t}divZh(e,t=4){for(let t=0;te*(t-1)-t&&!this.Fr.isZero(i))throw Error(`Polynomial is not divisible`)}return this}divByZerofier(e,t){let n=this.Fr,r=n.inv(t),i=n.neg(r),a=n.eq(n.one,i),o=n.eq(n.negone,i);if(!a)for(let t=0;tthis.length()-e-1&&!this.Fr.isZero(c))throw Error(`Polynomial is not divisible`)}return this}byX(){let e=this.length()+1>32768?new n.BigBuffer(this.coef.byteLength+this.Fr.n8):new Uint8Array(this.coef.byteLength+this.Fr.n8);e.set(this.Fr.zero,0),e.set(this.coef,this.Fr.n8),this.coef=e}static async expX(t,r,i=!1){let a=t.Fr;if(r<1)throw Error(`Compute a new polynomial to a zero or negative number is not allowed`);if(r===1)return await e.fromEvaluations(t.coef,t.curve,t.logger);let o=i?t.degree():t.length()-1,s=o*r+1>32768?new n.BigBuffer((o*r+1)*a.n8):new Uint8Array((o*r+1)*a.n8);s.set(t.getCoef(0),0);for(let e=1;e<=o;e++){let n=e*a.n8,i=t.getCoef(e);s.set(i,n*r)}return new e(s,t.curve,t.logger)}split(t,r,i){if(t<1)throw Error(`Polynomials can't be split in ${t} parts`);if(t===1)return[this];if(i.length!==0&&i.length32768?new n.BigBuffer(c):new Uint8Array(c),this.curve,this.logger);let l=r*a,u=s?this.coef.byteLength:(r+1)*a;if(o[r].coef.set(this.coef.slice(l,u),0),s||o[r].coef.set(i[r],a),r!==0){let e=this.Fr.sub(o[r].coef.slice(0,this.Fr.n8),i[r-1]);o[r].coef.set(e,0)}s&&o[r].truncate()}return o}truncate(){let e=this.degree();if(e+132768?new n.BigBuffer((e+1)*this.Fr.n8):new Uint8Array((e+1)*this.Fr.n8);t.set(this.coef.slice(0,(e+1)*this.Fr.n8),0),this.coef=t}}static lagrangePolynomialInterpolation(t,r,i){let a=i.Fr,o=s(0);for(let e=1;e32768?new n.BigBuffer(t.length*a.n8):new Uint8Array(t.length*a.n8),i),s.setCoef(0,a.neg(t[r])),s.setCoef(1,a.one)):s.byXSubValue(t[r]));let c=s.evaluate(t[o]);c=a.inv(c);let l=a.mul(r[o],c);return s.mulScalar(l),s}}static zerofierPolynomial(t,r){let i=r.Fr,a=new e(t.length+1>32768?new n.BigBuffer((t.length+1)*i.n8):new Uint8Array((t.length+1)*i.n8),r);a.setCoef(0,i.neg(t[0])),a.setCoef(1,i.one);for(let e=1;e=0;n--){let r=this.getCoef(n);e.eq(e.zero,r)||(e.isNegative(r)?t+=` - `:n!==this.degree()&&(t+=` + `),t+=e.toString(r),n>0&&(t+=n>1?`x^`+n:`x`))}console.log(t)}async multiExponentiation(e,t){let n=this.coef.byteLength/this.Fr.n8,r=e.slice(0,n*this.G1.F.n8*2),i=await this.Fr.batchFromMontgomery(this.coef),a=await this.G1.multiExpAffine(r,i,this.logger,t);return a=this.G1.toAffine(a),a}},X=class e{constructor(e,t,n){this.eval=e,this.curve=t,this.Fr=t.Fr,this.logger=n}static async fromPolynomial(t,r,i,a){let o=new n.BigBuffer(t.length()*r*i.Fr.n8);return o.set(t.coef,0),new e(await i.Fr.fft(o),i,a)}getEvaluation(e){let t=e*this.Fr.n8;if(t+this.Fr.n8>this.eval.byteLength)throw Error(`Evaluations.getEvaluation() out of bounds`);return this.eval.slice(t,t+this.Fr.n8)}length(){let e=this.eval.byteLength/this.Fr.n8;if(e!==Math.floor(this.eval.byteLength/this.Fr.n8))throw Error(`Polynomial evaluations buffer has incorrect size`);return e===0&&this.logger.warn(`Polynomial has length zero`),e}},{stringifyBigInts:Er}=n.utils;async function Dr(e,r,i,a){let{fd:o,sections:s}=await t.readBinFile(r,`wtns`,2,1<<25,1<<23);i&&i.debug(`> Reading witness file`);let c=await Qe(o,s);i&&i.debug(`> Reading zkey file`);let{fd:l,sections:u}=await t.readBinFile(e,`zkey`,2,1<<25,1<<23),d=await Re(l,u,void 0,a);if(d.protocol!=`plonk`)throw Error(`zkey file is not plonk`);if(!n.Scalar.eq(d.r,c.q))throw Error(`Curve of the witness does not match the curve of the proving key`);if(c.nWitness!=d.nVars-d.nAdditions)throw Error(`Invalid witness length. Circuit: ${d.nVars}, witness: ${c.nWitness}, ${d.nAdditions}`);let f=d.curve,p=f.Fr,m=f.Fr.n8,h=d.domainSize*m;i&&(i.debug(`----------------------------`),i.debug(` PLONK PROVE SETTINGS`),i.debug(` Curve: ${f.name}`),i.debug(` Circuit power: ${d.power}`),i.debug(` Domain size: ${d.domainSize}`),i.debug(` Vars: ${d.nVars}`),i.debug(` Public vars: ${d.nPublic}`),i.debug(` Constraints: ${d.nConstraints}`),i.debug(` Additions: ${d.nAdditions}`),i.debug(`----------------------------`)),i&&i.debug(`> Reading witness file data`);let g=await t.readSection(o,s,2);g.set(p.zero,0);let _=new n.BigBuffer(m*d.nAdditions),v={},y={},b={},x={},S=new ir(f,i),C=new wr(f);i&&i.debug(`> Reading Section 3. Additions`),await D(),i&&i.debug(`> Reading Section 12. Sigma1, Sigma2 & Sigma 3`),i&&i.debug(`··· Reading Sigma polynomials `),y.Sigma1=new Y(new n.BigBuffer(h),f,i),y.Sigma2=new Y(new n.BigBuffer(h),f,i),y.Sigma3=new Y(new n.BigBuffer(h),f,i),await l.readToBuffer(y.Sigma1.coef,0,h,u[12][0].p),await l.readToBuffer(y.Sigma2.coef,0,h,u[12][0].p+5*h),await l.readToBuffer(y.Sigma3.coef,0,h,u[12][0].p+10*h),i&&i.debug(`··· Reading Sigma evaluations`),b.Sigma1=new X(new n.BigBuffer(h*4),f,i),b.Sigma2=new X(new n.BigBuffer(h*4),f,i),b.Sigma3=new X(new n.BigBuffer(h*4),f,i),await l.readToBuffer(b.Sigma1.eval,0,h*4,u[12][0].p+h),await l.readToBuffer(b.Sigma2.eval,0,h*4,u[12][0].p+6*h),await l.readToBuffer(b.Sigma3.eval,0,h*4,u[12][0].p+11*h),i&&i.debug(`> Reading Section 14. Powers of Tau`);let w=await t.readSection(l,u,14),T=[];for(let e=1;e<=d.nPublic;e++){let t=g.slice(e*p.n8,e*p.n8+p.n8);T.push(n.Scalar.fromRprLE(t))}i&&i.debug(``),i&&i.debug(`> ROUND 1`),await A(),i&&i.debug(`> ROUND 2`),await M(),i&&i.debug(`> ROUND 3`),await P(),i&&i.debug(`> ROUND 4`),await I(),i&&i.debug(`> ROUND 5`),await L(),await l.close(),await o.close();let E=S.toObjectProof(!1);return E.protocol=`plonk`,E.curve=f.name,i&&i.debug(`PLONK PROVER FINISHED`),{proof:Er(E),publicSignals:Er(T)};async function D(){i&&i.debug(`··· Computing additions`);let e=await t.readSection(l,u,3),n=8+m*2;for(let t=0;t Computing A, B, C wire polynomials`),await j(),i&&i.debug(`> Computing A, B, C MSM`);let e=await y.A.multiExponentiation(w,`A`),t=await y.B.multiExponentiation(w,`B`),n=await y.C.multiExponentiation(w,`C`);return S.addPolynomial(`A`,e),S.addPolynomial(`B`,t),S.addPolynomial(`C`,n),0}async function j(){i&&i.debug(`··· Reading data from zkey file`),v.A=new n.BigBuffer(h),v.B=new n.BigBuffer(h),v.C=new n.BigBuffer(h);let e=await t.readSection(l,u,4),r=await t.readSection(l,u,5),a=await t.readSection(l,u,6);for(let t=0;t=d.domainSize+2)throw Error(`A Polynomial is not well calculated`);if(y.B.degree()>=d.domainSize+2)throw Error(`B Polynomial is not well calculated`);if(y.C.degree()>=d.domainSize+2)throw Error(`C Polynomial is not well calculated`)}async function M(){i&&i.debug(`> Computing challenges beta and gamma`),C.reset(),C.addPolCommitment(d.Qm),C.addPolCommitment(d.Ql),C.addPolCommitment(d.Qr),C.addPolCommitment(d.Qo),C.addPolCommitment(d.Qc),C.addPolCommitment(d.S1),C.addPolCommitment(d.S2),C.addPolCommitment(d.S3);for(let e=0;e Computing Z polynomial`),await N(),i&&i.debug(`> Computing Z MSM`);let e=await y.Z.multiExponentiation(w,`Z`);S.addPolynomial(`Z`,e)}async function N(){i&&i.debug(`··· Computing Z evaluations`);let e=new n.BigBuffer(h),t=new n.BigBuffer(h);e.set(p.one,0),t.set(p.one,0);let r=p.one;for(let n=0;n=d.domainSize+3)throw Error(`Z Polynomial is not well calculated`);delete v.Z}async function P(){i&&i.debug(`> Computing challenge alpha`),C.reset(),C.addScalar(x.beta),C.addScalar(x.gamma),C.addPolCommitment(S.getPolynomial(`Z`)),x.alpha=C.getChallenge(),x.alpha2=p.square(x.alpha),i&&i.debug(`··· challenges.alpha: `+p.toString(x.alpha,16)),i&&i.debug(`> Computing T polynomial`),await F(),i&&i.debug(`> Computing T MSM`);let e=await y.T1.multiExponentiation(w,`T1`),t=await y.T2.multiExponentiation(w,`T2`),n=await y.T3.multiExponentiation(w,`T3`);S.addPolynomial(`T1`,e),S.addPolynomial(`T2`,t),S.addPolynomial(`T3`,n)}async function F(){i&&i.debug(`··· Reading sections 8, 9, 7, 10, 11. Q selectors`),b.QL=new X(new n.BigBuffer(h*4),f,i),b.QR=new X(new n.BigBuffer(h*4),f,i),b.QM=new X(new n.BigBuffer(h*4),f,i),b.QO=new X(new n.BigBuffer(h*4),f,i),b.QC=new X(new n.BigBuffer(h*4),f,i),await l.readToBuffer(b.QL.eval,0,h*4,u[8][0].p+h),await l.readToBuffer(b.QR.eval,0,h*4,u[9][0].p+h),await l.readToBuffer(b.QM.eval,0,h*4,u[7][0].p+h),await l.readToBuffer(b.QO.eval,0,h*4,u[10][0].p+h),await l.readToBuffer(b.QC.eval,0,h*4,u[11][0].p+h),b.Lagrange=new X(new n.BigBuffer(h*4*d.nPublic),f,i);for(let e=0;e=d.domainSize*3+6)throw Error(`T Polynomial is not well calculated`);i&&i.debug(`··· Computing T1, T2, T3 polynomials`),y.T1=new Y(new n.BigBuffer((d.domainSize+1)*m),f,i),y.T2=new Y(new n.BigBuffer((d.domainSize+1)*m),f,i),y.T3=new Y(new n.BigBuffer((d.domainSize+6)*m),f,i),y.T1.coef.set(y.T.coef.slice(0,h),0),y.T2.coef.set(y.T.coef.slice(h,h*2),0),y.T3.coef.set(y.T.coef.slice(h*2,h*3+6*m),0),y.T1.setCoef(d.domainSize,x.b[10]);let t=p.sub(y.T2.getCoef(0),x.b[10]);y.T2.setCoef(0,t),y.T2.setCoef(d.domainSize,x.b[11]);let r=p.sub(y.T3.getCoef(0),x.b[11]);y.T3.setCoef(0,r)}async function I(){i&&i.debug(`> Computing challenge xi`),C.reset(),C.addScalar(x.alpha),C.addPolCommitment(S.getPolynomial(`T1`)),C.addPolCommitment(S.getPolynomial(`T2`)),C.addPolCommitment(S.getPolynomial(`T3`)),x.xi=C.getChallenge(),x.xiw=p.mul(x.xi,p.w[d.power]),i&&i.debug(`··· challenges.xi: `+p.toString(x.xi,16)),S.addEvaluation(`eval_a`,y.A.evaluate(x.xi)),S.addEvaluation(`eval_b`,y.B.evaluate(x.xi)),S.addEvaluation(`eval_c`,y.C.evaluate(x.xi)),S.addEvaluation(`eval_s1`,y.Sigma1.evaluate(x.xi)),S.addEvaluation(`eval_s2`,y.Sigma2.evaluate(x.xi)),S.addEvaluation(`eval_zw`,y.Z.evaluate(x.xiw))}async function L(){i&&i.debug(`> Computing challenge v`),C.reset(),C.addScalar(x.xi),C.addScalar(S.getEvaluation(`eval_a`)),C.addScalar(S.getEvaluation(`eval_b`)),C.addScalar(S.getEvaluation(`eval_c`)),C.addScalar(S.getEvaluation(`eval_s1`)),C.addScalar(S.getEvaluation(`eval_s2`)),C.addScalar(S.getEvaluation(`eval_zw`)),x.v=[],x.v[1]=C.getChallenge(),i&&i.debug(`··· challenges.v: `+p.toString(x.v[1],16));for(let e=2;e<6;e++)x.v[e]=p.mul(x.v[e-1],x.v[1]);i&&i.debug(`> Computing linearisation polynomial R(X)`),await R(),i&&i.debug(`> Computing opening proof polynomial Wxi(X) polynomial`),z(),i&&i.debug(`> Computing opening proof polynomial Wxiw(X) polynomial`),ee(),i&&i.debug(`> Computing Wxi, Wxiw MSM`);let e=await y.Wxi.multiExponentiation(w,`Wxi`),t=await y.Wxiw.multiExponentiation(w,`Wxiw`);S.addPolynomial(`Wxi`,e),S.addPolynomial(`Wxiw`,t)}async function R(){let e=f.Fr;y.QL=new Y(new n.BigBuffer(h),f,i),y.QR=new Y(new n.BigBuffer(h),f,i),y.QM=new Y(new n.BigBuffer(h),f,i),y.QO=new Y(new n.BigBuffer(h),f,i),y.QC=new Y(new n.BigBuffer(h),f,i),await l.readToBuffer(y.QL.coef,0,h,u[8][0].p),await l.readToBuffer(y.QR.coef,0,h,u[9][0].p),await l.readToBuffer(y.QM.coef,0,h,u[7][0].p),await l.readToBuffer(y.QO.coef,0,h,u[10][0].p),await l.readToBuffer(y.QC.coef,0,h,u[11][0].p),x.xin=x.xi;for(let t=0;tJr,fullProve:()=>kr,prove:()=>Dr,setup:()=>rr,verify:()=>jr});function Xr(e,t){return[e,0,0,t.one,t.zero,t.zero,t.zero,t.zero]}function Zr(e,t,n,r,i,a,o,s){return[e,t,n,r,i,a,o,s]}function Qr(e,t,n,r,i,a,o,s,c){return[e,t,n,r,i,a,o,s]}var $r=0,ei=1,ti=2,ni=class{constructor(e,t,n,r,i){this.Fr=e,this.logger=i,this.fnGetAdditionConstraint=n,this.fnGetMultiplicationConstraint=r}processR1csConstraint(e,t,n,r){this.normalizeLinearCombination(t),this.normalizeLinearCombination(n),this.normalizeLinearCombination(r);let i=this.getLinearCombinationType(t),a=this.getLinearCombinationType(n);if(i===$r||a===$r)return this.processR1csAdditionConstraint(e,r);if(i===ei){let i=this.joinLinearCombinations(n,r,t[0]);return this.processR1csAdditionConstraint(e,i)}else if(a===ei){let i=this.joinLinearCombinations(t,r,n[0]);return this.processR1csAdditionConstraint(e,i)}else return this.processR1csMultiplicationConstraint(e,t,n,r)}getLinearCombinationType(e){let t=this.Fr.zero,n=0,r=Object.keys(e);for(let i=0;i0?ti:this.Fr.isZero(t)?$r:ei}normalizeLinearCombination(e){let t=Object.keys(e);for(let n=0;ni;){let r=o.shift(),i=o.shift(),a=e.nVars++,s=this.fnGetAdditionConstraint(r[0],i[0],a,this.Fr.neg(r[1]),this.Fr.neg(i[1]),this.Fr.zero,this.Fr.one,this.Fr.zero);t.push(s),n.push([r[0],i[0],r[1],i[1]]),o.push([a,this.Fr.one])}for(let e=0;ethis.n-1)throw Error(`CPolynomial:addPolynomial, cannot add a polynomial to a position greater than n-1`);this.polynomials[e]=t}degree(){let e=this.polynomials.map((e,t)=>e===void 0?0:e.degree()*this.n+t);return Math.max(...e)}getPolynomial(){let e=this.polynomials.map(e=>e===void 0?0:e.degree()),t=this.degree(),r=2**(ye(t-1)+1),i=this.Fr.n8,a=new Y(new n.BigBuffer(r*i),this.curve,this.logger);for(let n=0;n Reading PTau file`);let{fd:s,sections:c}=await(0,t.readBinFile)(i,`ptau`,1,1<<22,1<<24);if(!c[12])throw Error(`Powers of Tau is not well prepared. Section 12 missing.`);o&&o.info(`> Getting curve from PTau settings`);let{curve:l}=await K(s,c);o&&o.info(`> Reading r1cs file`);let{fd:u,sections:d}=await(0,t.readBinFile)(e,`r1cs`,1,1<<22,1<<24),f=await(0,r.readR1csFd)(u,d,{loadConstraints:!1,loadCustomGates:!0});if(f.prime!==l.r)throw Error(`r1cs curve does not match powers of tau ceremony curve`);let p=l.Fr,m=l.Fr.n8,h=l.G1.F.n8*2,g=l.G2.F.n8*2,_={},v={},y,b={nVars:f.nVars,nPublic:f.nOutputs+f.nPubInputs},x=new J,S=new J;if(o&&o.info(`> Processing FFlonk constraints`),await k(l.Fr,f,o),globalThis.gc&&globalThis.gc(),b.cirPower=Math.max(3,ye(x.length+2-1)+1),b.domainSize=2**b.cirPower,c[2][0].size<(b.domainSize*9+18)*h)throw Error(`Powers of Tau is not big enough for this circuit size. Section 2 too small.`);if(c[3][0].size computing k1 and k2`);let[C,w]=te();o&&o.info(`> computing w3`);let T=ne();o&&o.info(`> computing w4`);let E=re();o&&o.info(`> computing w8`);let D=ie();o&&o.info(`> computing wr`);let O=ae(b.cirPower,l.Fr);return await A(),await u.close(),await s.close(),o&&o.info(`FFLONK SETUP FINISHED`),0;async function k(e,n,r){for(let t=0;t Writing the zkey file`);let e=await(0,t.createBinFile)(a,`zkey`,1,17,1<<22,1<<24);o&&o.info(`··· Writing Section 1. Zkey Header`),await j(e),o&&o.info(`··· Writing Section 3. Additions`),await M(e),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 4. A Map`),await N(e,4,0,`A map`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 5. B Map`),await N(e,5,1,`B map`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 6. C Map`),await N(e,6,2,`C map`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 7. QL`),await P(e,7,3,`QL`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 8. QR`),await P(e,8,4,`QR`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 9. QM`),await P(e,9,5,`QM`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 10. QO`),await P(e,10,6,`QO`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 11. QC`),await P(e,11,7,`QC`),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Sections 12,13,14. Sigma1, Sigma2 & Sigma 3`),await F(e),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 15. Lagrange Polynomials`),await I(e),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 16. Powers of Tau`),await L(e),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 17. C0`),await R(e),globalThis.gc&&globalThis.gc(),o&&o.info(`··· Writing Section 2. FFlonk Header`),await z(e),globalThis.gc&&globalThis.gc(),o&&o.info(`> Writing the zkey file finished`),await e.close()}async function j(e){await(0,t.startWriteSection)(e,1),await e.writeULE32(10),await(0,t.endWriteSection)(e)}async function M(e){await(0,t.startWriteSection)(e,3);let n=new Uint8Array(8+2*m),r=new DataView(n.buffer);for(let t=0;t=8*b.domainSize)throw Error(`C0 Polynomial is not well calculated`);await(0,t.startWriteSection)(e,17),await e.write(_.C0.coef),await(0,t.endWriteSection)(e)}async function z(e){await(0,t.startWriteSection)(e,2);let r=l.q,i=(Math.floor((n.Scalar.bitLength(r)-1)/64)+1)*8;await e.writeULE32(i),await(0,t.writeBigInt)(e,r,i);let a=l.r,o=(Math.floor((n.Scalar.bitLength(a)-1)/64)+1)*8;await e.writeULE32(o),await(0,t.writeBigInt)(e,a,o),await e.writeULE32(b.nVars),await e.writeULE32(b.nPublic),await e.writeULE32(b.domainSize),await e.writeULE32(S.length),await e.writeULE32(x.length),await e.write(C),await e.write(w),await e.write(T),await e.write(E),await e.write(D),await e.write(O);let u;u=await s.read(g,c[3][0].p+g),await e.write(u);let d=await _.C0.multiExponentiation(y,`C0`);await e.write(d),await(0,t.endWriteSection)(e)}async function ee(e,t){let[n,r]=await Y.to4T(t,b.domainSize,[],p);return await e.write(n),await e.write(r),[n,r]}function te(){let e=p.two;for(;n(e,[],b.cirPower);)p.add(e,p.one);let t=p.add(e,p.one);for(;n(t,[e],b.cirPower);)p.add(t,p.one);return[e,t];function n(e,t,n){let r=2**n,i=p.one;for(let a=0;a Reading witness file`);let{fd:o,sections:s}=await t.readBinFile(r,`wtns`,2,1<<25,1<<23),c=await Qe(o,s);i&&i.info(`> Reading zkey file`);let{fd:l,sections:u}=await t.readBinFile(e,`zkey`,2,1<<25,1<<23),d=await Re(l,u,void 0,a);if(d.protocolId!==10)throw Error(`zkey file is not fflonk`);if(!n.Scalar.eq(d.r,c.q))throw Error(`Curve of the witness does not match the curve of the proving key`);if(c.nWitness!==d.nVars-d.nAdditions)throw Error(`Invalid witness length. Circuit: ${d.nVars}, witness: ${c.nWitness}, ${d.nAdditions}`);let f=d.curve,p=f.Fr,m=f.Fr.n8,h=f.G1.F.n8*2,g=d.domainSize*m;i&&(i.info(`----------------------------`),i.info(` FFLONK PROVE SETTINGS`),i.info(` Curve: ${f.name}`),i.info(` Circuit power: ${d.power}`),i.info(` Domain size: ${d.domainSize}`),i.info(` Vars: ${d.nVars}`),i.info(` Public vars: ${d.nPublic}`),i.info(` Constraints: ${d.nConstraints}`),i.info(` Additions: ${d.nAdditions}`),i.info(`----------------------------`)),i&&i.info(`> Reading witness file data`);let _=await t.readSection(o,s,2);await o.close(),_.set(p.zero,0);let v=new n.BigBuffer(d.nAdditions*m),y={},b={},x={},S={},C={},w={},T=new ir(f,i);i&&i.info(`> Reading Section 3. Additions`),await k(),i&&i.info(`> Reading Sections 12,13,14. Sigma1, Sigma2 & Sigma 3`),i&&i.info(`··· Reading Sigma polynomials `),b.Sigma1=new Y(new n.BigBuffer(g),f,i),b.Sigma2=new Y(new n.BigBuffer(g),f,i),b.Sigma3=new Y(new n.BigBuffer(g),f,i),await l.readToBuffer(b.Sigma1.coef,0,g,u[12][0].p),await l.readToBuffer(b.Sigma2.coef,0,g,u[13][0].p),await l.readToBuffer(b.Sigma3.coef,0,g,u[14][0].p),i&&i.info(`··· Reading Sigma evaluations`),x.Sigma1=new X(new n.BigBuffer(g*4),f,i),x.Sigma2=new X(new n.BigBuffer(g*4),f,i),x.Sigma3=new X(new n.BigBuffer(g*4),f,i),await l.readToBuffer(x.Sigma1.eval,0,g*4,u[12][0].p+g),await l.readToBuffer(x.Sigma2.eval,0,g*4,u[13][0].p+g),await l.readToBuffer(x.Sigma3.eval,0,g*4,u[14][0].p+g),i&&i.info(`> Reading Section 16. Powers of Tau`);let E=new n.BigBuffer(d.domainSize*16*h);await l.readToBuffer(E,0,(d.domainSize*9+18)*h,u[16][0].p),globalThis.gc&&globalThis.gc(),i&&i.info(``),i&&i.info(`> ROUND 1`),await M(),delete b.T0,delete x.QL,delete x.QR,delete x.QM,delete x.QO,delete x.QC,globalThis.gc&&globalThis.gc(),i&&i.info(`> ROUND 2`),await N(),delete y.A,delete y.B,delete y.C,delete x.A,delete x.B,delete x.C,delete x.Sigma1,delete x.Sigma2,delete x.Sigma3,delete x.lagrange1,delete x.Z,globalThis.gc&&globalThis.gc(),i&&i.info(`> ROUND 3`),await P(),delete b.A,delete b.B,delete b.C,delete b.Z,delete b.T1,delete b.T2,delete b.Sigma1,delete b.Sigma2,delete b.Sigma3,delete b.QL,delete b.QR,delete b.QM,delete b.QC,delete b.QO,globalThis.gc&&globalThis.gc(),i&&i.info(`> ROUND 4`),await F(),globalThis.gc&&globalThis.gc(),i&&i.info(`> ROUND 5`),await I(),delete b.C0,delete b.C1,delete b.C2,delete b.R1,delete b.R2,delete b.F,delete b.L,delete b.ZT,delete b.ZTS2,await l.close(),globalThis.gc&&globalThis.gc(),T.addEvaluation(`inv`,L());let D=T.toObjectProof();D.protocol=`fflonk`,D.curve=f.name;let O=[];for(let e=1;e<=d.nPublic;e++){let t=e*m,r=_.slice(t,t+m);O.push(n.Scalar.fromRprLE(r))}return i&&i.info(`FFLONK PROVER FINISHED`),{proof:ai(D),publicSignals:ai(O)};async function k(){i&&i.info(`··· Computing additions`);let e=await t.readSection(l,u,3),n=8+m*2;for(let t=0;t Computing A, B, C wire polynomials`),await r(),i&&i.info(`> Computing T0 polynomial`),await a(),i&&i.info(`> Computing C1 polynomial`),await o(),i&&i.info(`> Computing C1 multi exponentiation`);let e=await b.C1.multiExponentiation(E,`C1`);return T.addPolynomial(`C1`,e),0;async function r(){i&&i.info(`··· Reading data from zkey file`),y.A=new n.BigBuffer(g),y.B=new n.BigBuffer(g),y.C=new n.BigBuffer(g);let e=await t.readSection(l,u,4),r=await t.readSection(l,u,5),a=await t.readSection(l,u,6);for(let t=0;t=d.domainSize)throw Error(`A Polynomial is not well calculated`);if(b.B.degree()>=d.domainSize)throw Error(`B Polynomial is not well calculated`);if(b.C.degree()>=d.domainSize)throw Error(`C Polynomial is not well calculated`)}async function a(){i&&i.info(`··· Reading sections 7, 8, 9, 10, 11. Q selectors`),x.QL=new X(new n.BigBuffer(g*4),f,i),x.QR=new X(new n.BigBuffer(g*4),f,i),x.QM=new X(new n.BigBuffer(g*4),f,i),x.QO=new X(new n.BigBuffer(g*4),f,i),x.QC=new X(new n.BigBuffer(g*4),f,i),await l.readToBuffer(x.QL.eval,0,g*4,u[7][0].p+g),await l.readToBuffer(x.QR.eval,0,g*4,u[8][0].p+g),await l.readToBuffer(x.QM.eval,0,g*4,u[9][0].p+g),await l.readToBuffer(x.QO.eval,0,g*4,u[10][0].p+g),await l.readToBuffer(x.QC.eval,0,g*4,u[11][0].p+g),x.lagrange1=new X(await t.readSection(l,u,15),f,i),y.T0=new n.BigBuffer(g*4),i&&i.info(`··· Computing T0 evaluations`);for(let e=0;e=2*d.domainSize-2)throw Error(`T0 Polynomial is not well calculated (degree is ${b.T0.degree()} and must be less than ${2*d.domainSize+2}`);delete y.T0}async function o(){let e=new ri(4,f,i);if(e.addPolynomial(0,b.A),e.addPolynomial(1,b.B),e.addPolynomial(2,b.C),e.addPolynomial(3,b.T0),b.C1=e.getPolynomial(),b.C1.degree()>=8*d.domainSize-8)throw Error(`C1 Polynomial is not well calculated`)}}async function N(){i&&i.info(`> Computing challenges beta and gamma`);let e=new wr(f);e.addPolCommitment(d.C0);for(let t=0;t Computing Z polynomial`),await r(),i&&i.info(`> Computing T1 polynomial`),await a(),i&&i.info(`> Computing T2 polynomial`),await o(),i&&i.info(`> Computing C2 polynomial`),await s(),i&&i.info(`> Computing C2 multi exponentiation`);let t=await b.C2.multiExponentiation(E,`C2`);return T.addPolynomial(`C2`,t),0;async function r(){i&&i.info(`··· Computing Z evaluations`);let e=new n.BigBuffer(g),t=new n.BigBuffer(g);e.set(p.one,0),t.set(p.one,0);let r=p.one;for(let n=0;n=d.domainSize+3)throw Error(`Z Polynomial is not well calculated`);delete y.Z}async function a(){i&&i.info(`··· Computing T1 evaluations`),y.T1=new n.BigBuffer(g*2),y.T1z=new n.BigBuffer(g*2);let e=p.one;for(let t=0;t=d.domainSize+2)throw Error(`T1 Polynomial is not well calculated`);delete y.T1,delete y.T1z,delete b.T1z}async function o(){i&&i.info(`··· Computing T2 evaluations`),y.T2=new n.BigBuffer(g*4),y.T2z=new n.BigBuffer(g*4);let e=p.one;for(let t=0;t=3*d.domainSize)throw Error(`T2 Polynomial is not well calculated`);delete y.T2,delete y.T2z,delete b.T2z}async function s(){let e=new ri(3,f,i);if(e.addPolynomial(0,b.Z),e.addPolynomial(1,b.T1),e.addPolynomial(2,b.T2),b.C2=e.getPolynomial(),b.C2.degree()>=9*d.domainSize)throw Error(`C2 Polynomial is not well calculated`)}}async function P(){i&&i.info(`> Computing challenge xi`);let e=new wr(f);e.addScalar(C.gamma),e.addPolCommitment(T.getPolynomial(`C2`)),C.xiSeed=e.getChallenge();let t=p.square(C.xiSeed);w.w8=[],w.w8[0]=p.one;for(let e=1;e<8;e++)w.w8[e]=p.mul(w.w8[e-1],d.w8);w.w4=[],w.w4[0]=p.one;for(let e=1;e<4;e++)w.w4[e]=p.mul(w.w4[e-1],d.w4);w.w3=[],w.w3[0]=p.one,w.w3[1]=d.w3,w.w3[2]=p.square(d.w3),w.S0={},w.S0.h0w8=[],w.S0.h0w8[0]=p.mul(t,C.xiSeed);for(let e=1;e<8;e++)w.S0.h0w8[e]=p.mul(w.S0.h0w8[0],w.w8[e]);w.S1={},w.S1.h1w4=[],w.S1.h1w4[0]=p.square(w.S0.h0w8[0]);for(let e=1;e<4;e++)w.S1.h1w4[e]=p.mul(w.S1.h1w4[0],w.w4[e]);w.S2={},w.S2.h2w3=[],w.S2.h2w3[0]=p.mul(w.S1.h1w4[0],t),w.S2.h2w3[1]=p.mul(w.S2.h2w3[0],w.w3[1]),w.S2.h2w3[2]=p.mul(w.S2.h2w3[0],w.w3[2]),w.S2.h3w3=[],w.S2.h3w3[0]=p.mul(w.S2.h2w3[0],d.wr),w.S2.h3w3[1]=p.mul(w.S2.h3w3[0],w.w3[1]),w.S2.h3w3[2]=p.mul(w.S2.h3w3[0],w.w3[2]),C.xi=p.mul(p.square(w.S2.h2w3[0]),w.S2.h2w3[0]),i&&i.info(`··· challenges.xi: `+p.toString(C.xi)),b.QL=new Y(new n.BigBuffer(g),f,i),b.QR=new Y(new n.BigBuffer(g),f,i),b.QM=new Y(new n.BigBuffer(g),f,i),b.QO=new Y(new n.BigBuffer(g),f,i),b.QC=new Y(new n.BigBuffer(g),f,i),await l.readToBuffer(b.QL.coef,0,g,u[7][0].p),await l.readToBuffer(b.QR.coef,0,g,u[8][0].p),await l.readToBuffer(b.QM.coef,0,g,u[9][0].p),await l.readToBuffer(b.QO.coef,0,g,u[10][0].p),await l.readToBuffer(b.QC.coef,0,g,u[11][0].p),i&&i.info(`··· Computing evaluations`),T.addEvaluation(`ql`,b.QL.evaluate(C.xi)),T.addEvaluation(`qr`,b.QR.evaluate(C.xi)),T.addEvaluation(`qm`,b.QM.evaluate(C.xi)),T.addEvaluation(`qo`,b.QO.evaluate(C.xi)),T.addEvaluation(`qc`,b.QC.evaluate(C.xi)),T.addEvaluation(`s1`,b.Sigma1.evaluate(C.xi)),T.addEvaluation(`s2`,b.Sigma2.evaluate(C.xi)),T.addEvaluation(`s3`,b.Sigma3.evaluate(C.xi)),T.addEvaluation(`a`,b.A.evaluate(C.xi)),T.addEvaluation(`b`,b.B.evaluate(C.xi)),T.addEvaluation(`c`,b.C.evaluate(C.xi)),T.addEvaluation(`z`,b.Z.evaluate(C.xi)),C.xiw=p.mul(C.xi,p.w[d.power]),T.addEvaluation(`zw`,b.Z.evaluate(C.xiw)),T.addEvaluation(`t1w`,b.T1.evaluate(C.xiw)),T.addEvaluation(`t2w`,b.T2.evaluate(C.xiw))}async function F(){i&&i.info(`> Computing challenge alpha`);let e=new wr(f);e.addScalar(C.xiSeed),e.addScalar(T.getEvaluation(`ql`)),e.addScalar(T.getEvaluation(`qr`)),e.addScalar(T.getEvaluation(`qm`)),e.addScalar(T.getEvaluation(`qo`)),e.addScalar(T.getEvaluation(`qc`)),e.addScalar(T.getEvaluation(`s1`)),e.addScalar(T.getEvaluation(`s2`)),e.addScalar(T.getEvaluation(`s3`)),e.addScalar(T.getEvaluation(`a`)),e.addScalar(T.getEvaluation(`b`)),e.addScalar(T.getEvaluation(`c`)),e.addScalar(T.getEvaluation(`z`)),e.addScalar(T.getEvaluation(`zw`)),e.addScalar(T.getEvaluation(`t1w`)),e.addScalar(T.getEvaluation(`t2w`)),C.alpha=e.getChallenge(),i&&i.info(`··· challenges.alpha: `+p.toString(C.alpha)),i&&i.info(`> Reading C0 polynomial`),b.C0=new Y(new n.BigBuffer(g*8),f,i),await l.readToBuffer(b.C0.coef,0,g*8,u[17][0].p),i&&i.info(`> Computing R0 polynomial`),r(),i&&i.info(`> Computing R1 polynomial`),a(),i&&i.info(`> Computing R2 polynomial`),o(),i&&i.info(`> Computing F polynomial`),await s(),i&&i.info(`> Computing W1 multi exponentiation`);let t=await b.F.multiExponentiation(E,`W1`);return T.addPolynomial(`W1`,t),0;function r(){if(b.R0=Y.lagrangePolynomialInterpolation([w.S0.h0w8[0],w.S0.h0w8[1],w.S0.h0w8[2],w.S0.h0w8[3],w.S0.h0w8[4],w.S0.h0w8[5],w.S0.h0w8[6],w.S0.h0w8[7]],[b.C0.evaluate(w.S0.h0w8[0]),b.C0.evaluate(w.S0.h0w8[1]),b.C0.evaluate(w.S0.h0w8[2]),b.C0.evaluate(w.S0.h0w8[3]),b.C0.evaluate(w.S0.h0w8[4]),b.C0.evaluate(w.S0.h0w8[5]),b.C0.evaluate(w.S0.h0w8[6]),b.C0.evaluate(w.S0.h0w8[7])],f),b.R0.degree()>7)throw Error(`R0 Polynomial is not well calculated`)}function a(){if(b.R1=Y.lagrangePolynomialInterpolation([w.S1.h1w4[0],w.S1.h1w4[1],w.S1.h1w4[2],w.S1.h1w4[3]],[b.C1.evaluate(w.S1.h1w4[0]),b.C1.evaluate(w.S1.h1w4[1]),b.C1.evaluate(w.S1.h1w4[2]),b.C1.evaluate(w.S1.h1w4[3])],f),b.R1.degree()>3)throw Error(`R1 Polynomial is not well calculated`)}function o(){if(b.R2=Y.lagrangePolynomialInterpolation([w.S2.h2w3[0],w.S2.h2w3[1],w.S2.h2w3[2],w.S2.h3w3[0],w.S2.h3w3[1],w.S2.h3w3[2]],[b.C2.evaluate(w.S2.h2w3[0]),b.C2.evaluate(w.S2.h2w3[1]),b.C2.evaluate(w.S2.h2w3[2]),b.C2.evaluate(w.S2.h3w3[0]),b.C2.evaluate(w.S2.h3w3[1]),b.C2.evaluate(w.S2.h3w3[2])],f),b.R2.degree()>5)throw Error(`R2 Polynomial is not well calculated`)}async function s(){i&&i.info(`··· Computing F polynomial`),b.F=Y.fromPolynomial(b.C0,f,i),b.F.sub(b.R0),b.F.divByZerofier(8,C.xi);let e=Y.fromPolynomial(b.C1,f,i);e.sub(b.R1),e.mulScalar(C.alpha),e.divByZerofier(4,C.xi);let t=Y.fromPolynomial(b.C2,f,i);if(t.sub(b.R2),t.mulScalar(p.square(C.alpha)),t.divByZerofier(3,C.xi),t.divByZerofier(3,C.xiw),b.F.add(e),b.F.add(t),b.F.degree()>=9*d.domainSize-6)throw Error(`F Polynomial is not well calculated`)}}async function I(){i&&i.info(`> Computing challenge y`);let e=new wr(f);e.addScalar(C.alpha),e.addPolCommitment(T.getPolynomial(`W1`)),C.y=e.getChallenge(),i&&i.info(`··· challenges.y: `+p.toString(C.y)),i&&i.info(`> Computing L polynomial`),await o(),i&&i.info(`> Computing ZTS2 polynomial`),await c();let t=b.ZTS2.evaluate(C.y);t=p.inv(t),b.L.mulScalar(t);let n=Y.fromCoefficientsArray([p.neg(C.y),p.one],f);i&&i.info(`> Computing W' = L / ZTS2 polynomial`);let r=b.L.divBy(n);if(r.degree()>0)throw Error(`Degree of L(X)/(ZTS2(y)(X-y)) remainder is ${r.degree()} and should be 0`);if(b.L.degree()>=9*d.domainSize-1)throw Error(`Degree of L(X)/(ZTS2(y)(X-y)) is not correct`);i&&i.info(`> Computing W' multi exponentiation`);let a=await b.L.multiExponentiation(E,`W2`);return T.addPolynomial(`W2`,a),0;async function o(){i&&i.info(`··· Computing L polynomial`);let e=b.R0.evaluate(C.y),t=b.R1.evaluate(C.y),n=b.R2.evaluate(C.y),r=p.sub(C.y,w.S0.h0w8[0]);for(let e=1;e<8;e++)r=p.mul(r,p.sub(C.y,w.S0.h0w8[e]));let a=p.sub(C.y,w.S1.h1w4[0]);for(let e=1;e<4;e++)a=p.mul(a,p.sub(C.y,w.S1.h1w4[e]));let o=p.sub(C.y,w.S2.h2w3[0]);for(let e=1;e<3;e++)o=p.mul(o,p.sub(C.y,w.S2.h2w3[e]));for(let e=0;e<3;e++)o=p.mul(o,p.sub(C.y,w.S2.h3w3[e]));let c=p.mul(a,o),l=p.mul(C.alpha,p.mul(r,o)),u=p.mul(p.square(C.alpha),p.mul(r,a));S.denH1=a,S.denH2=o,b.L=Y.fromPolynomial(b.C0,f,i),b.L.subScalar(e),b.L.mulScalar(c);let m=Y.fromPolynomial(b.C1,f,i);m.subScalar(t),m.mulScalar(l);let h=Y.fromPolynomial(b.C2,f,i);h.subScalar(n),h.mulScalar(u),b.L.add(m),b.L.add(h),i&&i.info(`> Computing ZT polynomial`),await s();let g=b.ZT.evaluate(C.y);if(b.F.mulScalar(g),b.L.sub(b.F),b.L.degree()>=9*d.domainSize)throw Error(`L Polynomial is not well calculated`);delete y.L}async function s(){b.ZT=Y.zerofierPolynomial([w.S0.h0w8[0],w.S0.h0w8[1],w.S0.h0w8[2],w.S0.h0w8[3],w.S0.h0w8[4],w.S0.h0w8[5],w.S0.h0w8[6],w.S0.h0w8[7],w.S1.h1w4[0],w.S1.h1w4[1],w.S1.h1w4[2],w.S1.h1w4[3],w.S2.h2w3[0],w.S2.h2w3[1],w.S2.h2w3[2],w.S2.h3w3[0],w.S2.h3w3[1],w.S2.h3w3[2]],f)}async function c(){b.ZTS2=Y.zerofierPolynomial([w.S1.h1w4[0],w.S1.h1w4[1],w.S1.h1w4[2],w.S1.h1w4[3],w.S2.h2w3[0],w.S2.h2w3[1],w.S2.h2w3[2],w.S2.h3w3[0],w.S2.h3w3[1],w.S2.h3w3[2]],f)}}function L(){let e=C.xi;for(let t=0;t Checking commitments belong to G1`),!fi(i,o,a))return r&&r.error(`Proof commitments are not valid`),!1;if(r&&r.info(`> Checking evaluations belong to F`),!mi(i,o))return r&&r.error(`Proof evaluations are not valid.`),!1;if(r&&r.info(`> Checking public inputs belong to F`),!hi(i,s))return r&&r.error(`Public inputs are not valid.`),!1;r&&r.info(`> Computing challenges`);let{challenges:l,roots:u}=gi(i,o,a,s,r);r&&r.info(`> Computing Zero polynomial evaluation Z_H(xi)`),l.zh=c.sub(l.xiN,c.one),l.invzh=c.inv(l.zh),r&&r.info(`> Computing Lagrange evaluations`);let d=await _i(i,l,a);r&&r.info(`> Computing polynomial identities PI(X)`);let f=vi(i,s,d);r&&r.info(`> Computing r0(y)`);let p=yi(o,l,u,i,r);r&&r.info(`> Computing r1(y)`);let m=bi(o,l,u,f,i,r);r&&r.info(`> Computing r2(y)`);let h=xi(o,l,u,d[1],a,i,r);r&&r.info(`> Computing F`);let g=Si(i,o,a,l,u);r&&r.info(`> Computing E`);let _=Ci(i,o,l,a,p,m,h);r&&r.info(`> Computing J`);let v=wi(i,o,l);r&&r.info(`> Validate all evaluations with a pairing`);let y=await Ti(i,o,l,a,g,_,v);return r&&(y?r.info(`PROOF VERIFIED SUCCESSFULLY`):r.warn(`Invalid Proof`)),r&&r.info(`FFLONK VERIFIER FINISHED`),y}function di(e,t){let n=t;return n.k1=e.Fr.fromObject(t.k1),n.k2=e.Fr.fromObject(t.k2),n.w=e.Fr.fromObject(t.w),n.w3=e.Fr.fromObject(t.w3),n.w4=e.Fr.fromObject(t.w4),n.w8=e.Fr.fromObject(t.w8),n.wr=e.Fr.fromObject(t.wr),n.X_2=e.G2.fromObject(t.X_2),n.C0=e.G1.fromObject(t.C0),n}function fi(e,t,n){let r=e.G1;return r.isValid(t.polynomials.C1)&&r.isValid(t.polynomials.C2)&&r.isValid(t.polynomials.W1)&&r.isValid(t.polynomials.W2)&&r.isValid(n.C0)}function pi(e,t){return n.Scalar.geq(t,0)&&n.Scalar.lt(t,e.r)}function Q(e,t){return pi(e,n.Scalar.fromRprLE(t))}function mi(e,t){return Q(e,t.evaluations.ql)&&Q(e,t.evaluations.qr)&&Q(e,t.evaluations.qm)&&Q(e,t.evaluations.qo)&&Q(e,t.evaluations.qc)&&Q(e,t.evaluations.s1)&&Q(e,t.evaluations.s2)&&Q(e,t.evaluations.s3)&&Q(e,t.evaluations.a)&&Q(e,t.evaluations.b)&&Q(e,t.evaluations.c)&&Q(e,t.evaluations.z)&&Q(e,t.evaluations.zw)&&Q(e,t.evaluations.t1w)&&Q(e,t.evaluations.t2w)}function hi(e,t){for(let n=0;nki,exportSolidityVerifier:()=>null,fullProve:()=>ci,prove:()=>oi,setup:()=>ii,verify:()=>ui});return Object.defineProperty(e,"curves",{enumerable:!0,get:function(){return p}}),Object.defineProperty(e,"fflonk",{enumerable:!0,get:function(){return Ai}}),Object.defineProperty(e,"groth16",{enumerable:!0,get:function(){return Jt}}),Object.defineProperty(e,"plonk",{enumerable:!0,get:function(){return Yr}}),Object.defineProperty(e,"powersOfTau",{enumerable:!0,get:function(){return Tn}}),Object.defineProperty(e,"r1cs",{enumerable:!0,get:function(){return jn}}),Object.defineProperty(e,"wtns",{enumerable:!0,get:function(){return Ln}}),Object.defineProperty(e,"zKey",{enumerable:!0,get:function(){return nr}}),e})({},_iden3_binfileutils,ffjavascript,r1csfile); \ No newline at end of file diff --git a/src/groth16_prove.js b/src/groth16_prove.js index 401b8c09..463cf30b 100644 --- a/src/groth16_prove.js +++ b/src/groth16_prove.js @@ -66,7 +66,6 @@ export default async function groth16Prove(zkeyFileName, witnessFileName, logger await (async function (){ if (logger) logger.debug("Reading Coeffs"); - console.time("buildABC_outer"); const buffCoeffs = await binFileUtils.readSection(fdZKey, sectionsZKey, 4); if (logger) logger.debug("Building ABC"); @@ -84,11 +83,8 @@ export default async function groth16Prove(zkeyFileName, witnessFileName, logger // default, build ABC in JS [buffA_T, buffB_T, buffC_T] = await buildABC1(curve, zkey, buffWitness, buffCoeffs, logger); } - console.timeEnd("buildABC_outer"); })(); - console.time("abcPromise"); - if (globalThis.gc) {globalThis.gc();} const inc = power === Fr.s ? curve.Fr.shift : curve.Fr.w[power+1]; @@ -128,7 +124,6 @@ export default async function groth16Prove(zkeyFileName, witnessFileName, logger buffCodd_T = null; if (globalThis.gc) {globalThis.gc();} - console.timeEnd("abcPromise"); })(); //await abcPromise; @@ -137,9 +132,7 @@ export default async function groth16Prove(zkeyFileName, witnessFileName, logger async function calcPiA(){ if (logger) logger.debug("Reading A Points"); const buffBasesA = await binFileUtils.readSection(fdZKey, sectionsZKey, 5); - console.time("Calculate PiA"); proof.pi_a = await curve.G1.multiExpAffine(buffBasesA, buffWitness, logger, "multiexp A"); - console.timeEnd("Calculate PiA"); } let piaPromise = calcPiA(); @@ -150,9 +143,7 @@ export default async function groth16Prove(zkeyFileName, witnessFileName, logger async function calcPiB1() { if (logger) logger.debug("Reading B1 Points"); const buffBasesB1 = await binFileUtils.readSection(fdZKey, sectionsZKey, 6); - console.time("Calculate PiB1"); pib1 = await curve.G1.multiExpAffine(buffBasesB1, buffWitness, logger, "multiexp B1"); - console.timeEnd("Calculate PiB1"); } let pib1Promise = calcPiB1(); @@ -161,9 +152,7 @@ export default async function groth16Prove(zkeyFileName, witnessFileName, logger async function calcPiB() { if (logger) logger.debug("Reading B2 Points"); const buffBasesB2 = await binFileUtils.readSection(fdZKey, sectionsZKey, 7); - console.time("Calculate PiB"); proof.pi_b = await curve.G2.multiExpAffine(buffBasesB2, buffWitness, logger, "multiexp B2"); - console.timeEnd("Calculate PiB"); } let pibPromise = calcPiB(); @@ -172,9 +161,7 @@ export default async function groth16Prove(zkeyFileName, witnessFileName, logger let picPromise = (async function (){ if (logger) logger.debug("Reading C Points"); const buffBasesC = await binFileUtils.readSection(fdZKey, sectionsZKey, 8); - console.time("Calculate PiC"); proof.pi_c = await curve.G1.multiExpAffine(buffBasesC, buffWitness.slice((zkey.nPublic+1)*curve.Fr.n8), logger, "multiexp C"); - console.timeEnd("Calculate PiC"); })(); //await picPromise; @@ -182,12 +169,10 @@ export default async function groth16Prove(zkeyFileName, witnessFileName, logger resHPromise = (async function (){ if (logger) logger.debug("Reading H Points"); await abcPromise; - console.time("resHPromise"); const buffBasesH = await binFileUtils.readSection(fdZKey, sectionsZKey, 9); //await Promise.all([abcPromise, piaPromise, pib1Promise, pibPromise, picPromise]); resH = await curve.G1.multiExpAffine(buffBasesH, buffPodd_T, logger, "multiexp H"); //buffPodd_T = null; - console.timeEnd("resHPromise"); })(); //await resHPromise; @@ -436,7 +421,6 @@ async function buildABC(curve, zkey, witness, coeffs, logger) { // It has much better memory usage than multithreaded wasm implementation. // It's much faster than pure js one, but uses much more memory. async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { - console.time("buildABC"); const concurrency = 1;//curve.tm.concurrency; const sCoef = 4 * 3 + zkey.n8r; @@ -566,8 +550,6 @@ async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { p += result[i][0].byteLength; } - console.timeEnd("buildABC"); - return [outBuffA, outBuffB, outBuffC]; function getCutPoint(v) { @@ -590,7 +572,6 @@ async function buildABCWASM1(curve, zkey, witness, coeffs, logger) { async function joinABC(curve, zkey, a, b, c, logger) { - console.time("joinABC"); const MAX_CHUNK_SIZE = 1 << 16; const n8 = curve.Fr.n8; @@ -643,7 +624,6 @@ async function joinABC(curve, zkey, a, b, c, logger) { p += result[i][0].byteLength; } - console.timeEnd("joinABC"); return outBuff; }