diff --git a/.config/cspell.json b/.config/cspell.json index e0e3673f5e..568865256b 100644 --- a/.config/cspell.json +++ b/.config/cspell.json @@ -58,6 +58,7 @@ "doccomments", "docstrings", "dont", + "dtolnay", "dxdy", "dynlink", "eddsa", @@ -142,6 +143,7 @@ "minascan", "modul", "Muls", + "napi", "Nexts", "nixbuild", "nixfmt", @@ -186,6 +188,7 @@ "revspec", "RIGHTSHIFT", "rimraf", + "Rminus", "rnew", "rngs", "rotr", @@ -194,7 +197,6 @@ "RUSTDIR", "rustlib", "rustup", - "Rminus", "SBOX", "Schnorr", "Schönhage", @@ -232,18 +234,18 @@ "tweakable", "twoadic", "twoadicity", + "uints", "underconstraint", "underflowed", "underflows", "unew", - "uints", - "untar", "unhash", "unhashing", "unintuitively", "unpackaging", "unreconstructable", "Unshifted", + "untar", "Vanstone", "Varbase", "varfields", diff --git a/.github/workflows/publish_native.yml b/.github/workflows/publish_native.yml new file mode 100644 index 0000000000..903cb90ce4 --- /dev/null +++ b/.github/workflows/publish_native.yml @@ -0,0 +1,70 @@ +name: Native +on: + workflow_dispatch: + +jobs: + publish-native-packages: + name: Publish + strategy: + matrix: + os: [ + macos-latest, + macos-15-intel, + ubuntu-latest, + ubuntu-22.04-arm, + # windows-latest, + ] + runs-on: ${{ matrix.os }} + permissions: + contents: read + id-token: write # required for npm publish --provenance + steps: + - uses: actions/checkout@v5 + with: + submodules: recursive + - uses: actions/setup-node@v6 + with: + node-version: 24 + registry-url: "https://registry.npmjs.org" + - run: npm ci + + - uses: ocaml/setup-ocaml@v3 + with: + ocaml-compiler: 4.14.2 + - uses: actions/cache@v4 + id: cache-opam + with: + path: ./_opam/ + key: ${{ runner.OS }}-${{ runner.arch }}-opam-${{ hashFiles('./scripts/prepublish/native/prepublish-native-package.opam') }} + - name: opam install + if: ${{ steps.cache-opam.outputs.cache-hit != 'true' }} + run: | + opam install \ + --deps-only \ + -y \ + ./scripts/prepublish/native/prepublish-native-package.opam + + - uses: dtolnay/rust-toolchain@master + with: + toolchain: nightly-2024-09-05 + targets: wasm32-unknown-unknown + components: rust-src + + - name: Build native package + run: | + set -Eeuxo pipefail + eval $(opam env) + npm run build:native + + - name: Prepare native package + run: | + set -Eeuxo pipefail + npm run native:prepublish + + - name: Publish native package + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + run: | + set -Eeuxo pipefail + + npm run native:publish \ No newline at end of file diff --git a/.gitignore b/.gitignore index 67c500da69..87c530581f 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,7 @@ result # precompiled bindings src/bindings/compiled .bindings_download +/native + +# rust-analyzer +target/ \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b21da24eba..14ea9bfb29 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ }, "devDependencies": { "@influxdata/influxdb-client": "^1.33.2", + "@napi-rs/cli": "^3.4.1", "@noble/curves": "1.8.1", "@noble/hashes": "^1.3.2", "@playwright/test": "^1.48.0", @@ -29,6 +30,7 @@ "@types/libsodium-wrappers-sumo": "^0.7.8", "@types/minimist": "^1.2.5", "@types/node": "^18.14.2", + "@types/semver": "^7.7.1", "esbuild": "^0.25.5", "expect": "^29.0.1", "fs-extra": "^10.0.0", @@ -44,6 +46,7 @@ "prettier-plugin-organize-imports": "^4.3.0", "replace-in-file": "^6.3.5", "rimraf": "^3.0.2", + "semver": "^7.7.3", "ts-jest": "^28.0.8", "typedoc": "^0.28.5", "typedoc-plugin-markdown": "^4.6.4", @@ -52,8 +55,34 @@ }, "engines": { "node": ">=18.14.0" + }, + "optionalDependencies": { + "@o1js/native-darwin-arm64": "file:./native/darwin-arm64", + "@o1js/native-darwin-x64": "file:./native/darwin-x64", + "@o1js/native-linux-arm64": "file:./native/linux-arm64", + "@o1js/native-win32-x64": "file:./native/win32-x64" } }, + "native/darwin-arm64": { + "name": "@o1js/native-darwin-arm64", + "version": "0.0.0", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "native/darwin-x64": { + "optional": true + }, + "native/linux-arm64": { + "optional": true + }, + "native/win32-x64": { + "optional": true + }, "node_modules/@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -560,6 +589,40 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "node_modules/@emnapi/core": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.0.tgz", + "integrity": "sha512-pJdKGq/1iquWYtv1RRSljZklxHCOCAJFJrImO5ZLKPJVJlVUcs8yFwNQlqS0Lo8xT1VAXXTCZocF9n26FWEKsw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.0.tgz", + "integrity": "sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", + "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.5", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", @@ -1005,184 +1068,562 @@ "integrity": "sha512-RT5SxH+grHAazo/YK3UTuWK/frPWRM0N7vkrCUyqVprDgQzlLP+bSK4ak2Jv3QVF/pazTnsxWjvtKZdwskV5Xw==", "dev": true }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "node_modules/@inquirer/ansi": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.1.tgz", + "integrity": "sha512-yqq0aJW/5XPhi5xOAL1xRCpe1eh8UFVgYFpFsjEqmIR8rKLyP+HINvFXwUaxYICflJrVlxnp7lLN6As735kVpw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/checkbox": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.3.0.tgz", + "integrity": "sha512-5+Q3PKH35YsnoPTh75LucALdAxom6xh5D1oeY561x4cqBuH24ZFVyFREPe14xgnrtmGu3EEt1dIi60wRVSnGCw==", "dev": true, + "license": "MIT", "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" + "@inquirer/ansi": "^1.0.1", + "@inquirer/core": "^10.3.0", + "@inquirer/figures": "^1.0.14", + "@inquirer/type": "^3.0.9", + "yoctocolors-cjs": "^2.1.2" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@inquirer/confirm": { + "version": "5.1.19", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.19.tgz", + "integrity": "sha512-wQNz9cfcxrtEnUyG5PndC8g3gZ7lGDBzmWiXZkX8ot3vfZ+/BLjR8EvyGX4YzQLeVqtAlY/YScZpW7CW8qMoDQ==", "dev": true, + "license": "MIT", "dependencies": { - "sprintf-js": "~1.0.2" + "@inquirer/core": "^10.3.0", + "@inquirer/type": "^3.0.9" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/@inquirer/core": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.0.tgz", + "integrity": "sha512-Uv2aPPPSK5jeCplQmQ9xadnFx2Zhj9b5Dj7bU6ZeCdDNNY11nhYy4btcSdtDguHqCT2h5oNeQTcUNSGGLA7NTA==", "dev": true, + "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "@inquirer/ansi": "^1.0.1", + "@inquirer/figures": "^1.0.14", + "@inquirer/type": "^3.0.9", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/@inquirer/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "license": "ISC", + "engines": { + "node": ">=14" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, + "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/@inquirer/editor": { + "version": "4.2.21", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.21.tgz", + "integrity": "sha512-MjtjOGjr0Kh4BciaFShYpZ1s9400idOdvQ5D7u7lE6VztPFoyLcVNE5dXBmEEIQq5zi4B9h2kU+q7AVBxJMAkQ==", "dev": true, + "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "@inquirer/core": "^10.3.0", + "@inquirer/external-editor": "^1.0.2", + "@inquirer/type": "^3.0.9" }, "engines": { - "node": ">=6" + "node": ">=18" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/@inquirer/expand": { + "version": "4.0.21", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.21.tgz", + "integrity": "sha512-+mScLhIcbPFmuvU3tAGBed78XvYHSvCl6dBiYMlzCLhpr0bzGzd8tfivMMeqND6XZiaZ1tgusbUHJEfc6YzOdA==", "dev": true, + "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" + "@inquirer/core": "^10.3.0", + "@inquirer/type": "^3.0.9", + "yoctocolors-cjs": "^2.1.2" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/@inquirer/external-editor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.2.tgz", + "integrity": "sha512-yy9cOoBnx58TlsPrIxauKIFQTiyH+0MK4e97y4sV9ERbI+zDxw7i2hxHLCIEGIE/8PPvDxGhgzIOTSOWcs6/MQ==", "dev": true, + "license": "MIT", + "dependencies": { + "chardet": "^2.1.0", + "iconv-lite": "^0.7.0" + }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "node_modules/@inquirer/figures": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.14.tgz", + "integrity": "sha512-DbFgdt+9/OZYFM+19dbpXOSeAstPy884FPy1KjDu4anWwymZeOYhMY1mdFri172htv6mvc/uvIAAi7b7tvjJBQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/@jest/console": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", - "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", + "node_modules/@inquirer/input": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.2.5.tgz", + "integrity": "sha512-7GoWev7P6s7t0oJbenH0eQ0ThNdDJbEAEtVt9vsrYZ9FulIokvd823yLyhQlWHJPGce1wzP53ttfdCZmonMHyA==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/types": "^28.1.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^28.1.3", - "jest-util": "^28.1.3", - "slash": "^3.0.0" + "@inquirer/core": "^10.3.0", + "@inquirer/type": "^3.0.9" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@jest/console/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "node_modules/@inquirer/number": { + "version": "3.0.21", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.21.tgz", + "integrity": "sha512-5QWs0KGaNMlhbdhOSCFfKsW+/dcAVC2g4wT/z2MCiZM47uLgatC5N20kpkDQf7dHx+XFct/MJvvNGy6aYJn4Pw==", "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.0", + "@inquirer/type": "^3.0.9" + }, "engines": { - "node": ">=10" + "node": ">=18" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@jest/console/node_modules/jest-message-util": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", - "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", + "node_modules/@inquirer/password": { + "version": "4.0.21", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.21.tgz", + "integrity": "sha512-xxeW1V5SbNFNig2pLfetsDb0svWlKuhmr7MPJZMYuDnCTkpVBI+X/doudg4pznc1/U+yYmWFFOi4hNvGgUo7EA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^28.1.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^28.1.3", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "@inquirer/ansi": "^1.0.1", + "@inquirer/core": "^10.3.0", + "@inquirer/type": "^3.0.9" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@jest/console/node_modules/jest-util": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", + "node_modules/@inquirer/prompts": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.9.0.tgz", + "integrity": "sha512-X7/+dG9SLpSzRkwgG5/xiIzW0oMrV3C0HOa7YHG1WnrLK+vCQHfte4k/T80059YBdei29RBC3s+pSMvPJDU9/A==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/types": "^28.1.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "@inquirer/checkbox": "^4.3.0", + "@inquirer/confirm": "^5.1.19", + "@inquirer/editor": "^4.2.21", + "@inquirer/expand": "^4.0.21", + "@inquirer/input": "^4.2.5", + "@inquirer/number": "^3.0.21", + "@inquirer/password": "^4.0.21", + "@inquirer/rawlist": "^4.1.9", + "@inquirer/search": "^3.2.0", + "@inquirer/select": "^4.4.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@jest/console/node_modules/pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "node_modules/@inquirer/rawlist": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.9.tgz", + "integrity": "sha512-AWpxB7MuJrRiSfTKGJ7Y68imYt8P9N3Gaa7ySdkFj1iWjr6WfbGAhdZvw/UnhFXTHITJzxGUI9k8IX7akAEBCg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.0", + "@inquirer/type": "^3.0.9", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/search": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.2.0.tgz", + "integrity": "sha512-a5SzB/qrXafDX1Z4AZW3CsVoiNxcIYCzYP7r9RzrfMpaLpB+yWi5U8BWagZyLmwR0pKbbL5umnGRd0RzGVI8bQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.0", + "@inquirer/figures": "^1.0.14", + "@inquirer/type": "^3.0.9", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/select": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.4.0.tgz", + "integrity": "sha512-kaC3FHsJZvVyIjYBs5Ih8y8Bj4P/QItQWrZW22WJax7zTN+ZPXVGuOM55vzbdCP9zKUiBd9iEJVdesujfF+cAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.1", + "@inquirer/core": "^10.3.0", + "@inquirer/figures": "^1.0.14", + "@inquirer/type": "^3.0.9", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/type": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.9.tgz", + "integrity": "sha512-QPaNt/nmE2bLGQa9b7wwyRJoLZ7pN6rcyXvzU0YCmivmJyq1BVo94G98tStRWkoD1RgDX5C+dPlhhHzNdu/W/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", + "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3", + "slash": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/console/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/jest-message-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", + "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^28.1.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.3", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/console/node_modules/jest-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", + "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/console/node_modules/pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", "dev": true, "dependencies": { "@jest/schemas": "^28.1.3", @@ -1884,39 +2325,1024 @@ "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true, "engines": { - "node": ">=6.0.0" + "node": ">=6.0.0" + } + }, + "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.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jsdevtools/ez-spawn": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@jsdevtools/ez-spawn/-/ez-spawn-3.0.4.tgz", + "integrity": "sha512-f5DRIOZf7wxogefH03RjMPMdBF7ADTWUMoOs9kaJo06EfwF+aFhMZMDZxHg/Xe12hptN9xoZjGso2fdjapBRIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-me-maybe": "^1.0.1", + "cross-spawn": "^7.0.3", + "string-argv": "^0.3.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@napi-rs/cli": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-3.4.1.tgz", + "integrity": "sha512-ayhm+NfrP5Hmh7vy5pfyYm/ktYtLh2PrgdLuqHTAubO7RoO2JkUE4F991AtgYxNewwXI8+guZLxU8itV7QnDrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/prompts": "^7.8.4", + "@napi-rs/cross-toolchain": "^1.0.3", + "@napi-rs/wasm-tools": "^1.0.1", + "@octokit/rest": "^22.0.0", + "clipanion": "^4.0.0-rc.4", + "colorette": "^2.0.20", + "debug": "^4.4.1", + "emnapi": "^1.5.0", + "es-toolkit": "^1.39.10", + "js-yaml": "^4.1.0", + "semver": "^7.7.2", + "typanion": "^3.14.0" + }, + "bin": { + "napi": "dist/cli.js", + "napi-raw": "cli.mjs" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/runtime": "^1.5.0" + }, + "peerDependenciesMeta": { + "@emnapi/runtime": { + "optional": true + }, + "emnapi": { + "optional": true + } + } + }, + "node_modules/@napi-rs/cross-toolchain": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@napi-rs/cross-toolchain/-/cross-toolchain-1.0.3.tgz", + "integrity": "sha512-ENPfLe4937bsKVTDA6zdABx4pq9w0tHqRrJHyaGxgaPq03a2Bd1unD5XSKjXJjebsABJ+MjAv1A2OvCgK9yehg==", + "dev": true, + "license": "MIT", + "workspaces": [ + ".", + "arm64/*", + "x64/*" + ], + "dependencies": { + "@napi-rs/lzma": "^1.4.5", + "@napi-rs/tar": "^1.1.0", + "debug": "^4.4.1" + }, + "peerDependencies": { + "@napi-rs/cross-toolchain-arm64-target-aarch64": "^1.0.3", + "@napi-rs/cross-toolchain-arm64-target-armv7": "^1.0.3", + "@napi-rs/cross-toolchain-arm64-target-ppc64le": "^1.0.3", + "@napi-rs/cross-toolchain-arm64-target-s390x": "^1.0.3", + "@napi-rs/cross-toolchain-arm64-target-x86_64": "^1.0.3", + "@napi-rs/cross-toolchain-x64-target-aarch64": "^1.0.3", + "@napi-rs/cross-toolchain-x64-target-armv7": "^1.0.3", + "@napi-rs/cross-toolchain-x64-target-ppc64le": "^1.0.3", + "@napi-rs/cross-toolchain-x64-target-s390x": "^1.0.3", + "@napi-rs/cross-toolchain-x64-target-x86_64": "^1.0.3" + }, + "peerDependenciesMeta": { + "@napi-rs/cross-toolchain-arm64-target-aarch64": { + "optional": true + }, + "@napi-rs/cross-toolchain-arm64-target-armv7": { + "optional": true + }, + "@napi-rs/cross-toolchain-arm64-target-ppc64le": { + "optional": true + }, + "@napi-rs/cross-toolchain-arm64-target-s390x": { + "optional": true + }, + "@napi-rs/cross-toolchain-arm64-target-x86_64": { + "optional": true + }, + "@napi-rs/cross-toolchain-x64-target-aarch64": { + "optional": true + }, + "@napi-rs/cross-toolchain-x64-target-armv7": { + "optional": true + }, + "@napi-rs/cross-toolchain-x64-target-ppc64le": { + "optional": true + }, + "@napi-rs/cross-toolchain-x64-target-s390x": { + "optional": true + }, + "@napi-rs/cross-toolchain-x64-target-x86_64": { + "optional": true + } + } + }, + "node_modules/@napi-rs/lzma": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma/-/lzma-1.4.5.tgz", + "integrity": "sha512-zS5LuN1OBPAyZpda2ZZgYOEDC+xecUdAGnrvbYzjnLXkrq/OBC3B9qcRvlxbDR3k5H/gVfvef1/jyUqPknqjbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "optionalDependencies": { + "@napi-rs/lzma-android-arm-eabi": "1.4.5", + "@napi-rs/lzma-android-arm64": "1.4.5", + "@napi-rs/lzma-darwin-arm64": "1.4.5", + "@napi-rs/lzma-darwin-x64": "1.4.5", + "@napi-rs/lzma-freebsd-x64": "1.4.5", + "@napi-rs/lzma-linux-arm-gnueabihf": "1.4.5", + "@napi-rs/lzma-linux-arm64-gnu": "1.4.5", + "@napi-rs/lzma-linux-arm64-musl": "1.4.5", + "@napi-rs/lzma-linux-ppc64-gnu": "1.4.5", + "@napi-rs/lzma-linux-riscv64-gnu": "1.4.5", + "@napi-rs/lzma-linux-s390x-gnu": "1.4.5", + "@napi-rs/lzma-linux-x64-gnu": "1.4.5", + "@napi-rs/lzma-linux-x64-musl": "1.4.5", + "@napi-rs/lzma-wasm32-wasi": "1.4.5", + "@napi-rs/lzma-win32-arm64-msvc": "1.4.5", + "@napi-rs/lzma-win32-ia32-msvc": "1.4.5", + "@napi-rs/lzma-win32-x64-msvc": "1.4.5" + } + }, + "node_modules/@napi-rs/lzma-android-arm-eabi": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-android-arm-eabi/-/lzma-android-arm-eabi-1.4.5.tgz", + "integrity": "sha512-Up4gpyw2SacmyKWWEib06GhiDdF+H+CCU0LAV8pnM4aJIDqKKd5LHSlBht83Jut6frkB0vwEPmAkv4NjQ5u//Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/lzma-android-arm64": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-android-arm64/-/lzma-android-arm64-1.4.5.tgz", + "integrity": "sha512-uwa8sLlWEzkAM0MWyoZJg0JTD3BkPknvejAFG2acUA1raXM8jLrqujWCdOStisXhqQjZ2nDMp3FV6cs//zjfuQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/lzma-darwin-arm64": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-darwin-arm64/-/lzma-darwin-arm64-1.4.5.tgz", + "integrity": "sha512-0Y0TQLQ2xAjVabrMDem1NhIssOZzF/y/dqetc6OT8mD3xMTDtF8u5BqZoX3MyPc9FzpsZw4ksol+w7DsxHrpMA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/lzma-darwin-x64": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-darwin-x64/-/lzma-darwin-x64-1.4.5.tgz", + "integrity": "sha512-vR2IUyJY3En+V1wJkwmbGWcYiT8pHloTAWdW4pG24+51GIq+intst6Uf6D/r46citObGZrlX0QvMarOkQeHWpw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/lzma-freebsd-x64": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-freebsd-x64/-/lzma-freebsd-x64-1.4.5.tgz", + "integrity": "sha512-XpnYQC5SVovO35tF0xGkbHYjsS6kqyNCjuaLQ2dbEblFRr5cAZVvsJ/9h7zj/5FluJPJRDojVNxGyRhTp4z2lw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/lzma-linux-arm-gnueabihf": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-arm-gnueabihf/-/lzma-linux-arm-gnueabihf-1.4.5.tgz", + "integrity": "sha512-ic1ZZMoRfRMwtSwxkyw4zIlbDZGC6davC9r+2oX6x9QiF247BRqqT94qGeL5ZP4Vtz0Hyy7TEViWhx5j6Bpzvw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/lzma-linux-arm64-gnu": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-arm64-gnu/-/lzma-linux-arm64-gnu-1.4.5.tgz", + "integrity": "sha512-asEp7FPd7C1Yi6DQb45a3KPHKOFBSfGuJWXcAd4/bL2Fjetb2n/KK2z14yfW8YC/Fv6x3rBM0VAZKmJuz4tysg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/lzma-linux-arm64-musl": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-arm64-musl/-/lzma-linux-arm64-musl-1.4.5.tgz", + "integrity": "sha512-yWjcPDgJ2nIL3KNvi4536dlT/CcCWO0DUyEOlBs/SacG7BeD6IjGh6yYzd3/X1Y3JItCbZoDoLUH8iB1lTXo3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/lzma-linux-ppc64-gnu": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-ppc64-gnu/-/lzma-linux-ppc64-gnu-1.4.5.tgz", + "integrity": "sha512-0XRhKuIU/9ZjT4WDIG/qnX7Xz7mSQHYZo9Gb3MP2gcvBgr6BA4zywQ9k3gmQaPn9ECE+CZg2V7DV7kT+x2pUMQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/lzma-linux-riscv64-gnu": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-riscv64-gnu/-/lzma-linux-riscv64-gnu-1.4.5.tgz", + "integrity": "sha512-QrqDIPEUUB23GCpyQj/QFyMlr8SGxxyExeZz9OWFnHfb70kXdTLWrHS/hEI1Ru+lSbQ/6xRqeoGyQ4Aqdg+/RA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/lzma-linux-s390x-gnu": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-s390x-gnu/-/lzma-linux-s390x-gnu-1.4.5.tgz", + "integrity": "sha512-k8RVM5aMhW86E9H0QXdquwojew4H3SwPxbRVbl49/COJQWCUjGi79X6mYruMnMPEznZinUiT1jgKbFo2A00NdA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/lzma-linux-x64-gnu": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.4.5.tgz", + "integrity": "sha512-6rMtBgnIq2Wcl1rQdZsnM+rtCcVCbws1nF8S2NzaUsVaZv8bjrPiAa0lwg4Eqnn1d9lgwqT+cZgm5m+//K08Kw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/lzma-linux-x64-musl": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-x64-musl/-/lzma-linux-x64-musl-1.4.5.tgz", + "integrity": "sha512-eiadGBKi7Vd0bCArBUOO/qqRYPHt/VQVvGyYvDFt6C2ZSIjlD+HuOl+2oS1sjf4CFjK4eDIog6EdXnL0NE6iyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/lzma-wasm32-wasi": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-wasm32-wasi/-/lzma-wasm32-wasi-1.4.5.tgz", + "integrity": "sha512-+VyHHlr68dvey6fXc2hehw9gHVFIW3TtGF1XkcbAu65qVXsA9D/T+uuoRVqhE+JCyFHFrO0ixRbZDRK1XJt1sA==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.0.3" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@napi-rs/lzma-win32-arm64-msvc": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-win32-arm64-msvc/-/lzma-win32-arm64-msvc-1.4.5.tgz", + "integrity": "sha512-eewnqvIyyhHi3KaZtBOJXohLvwwN27gfS2G/YDWdfHlbz1jrmfeHAmzMsP5qv8vGB+T80TMHNkro4kYjeh6Deg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/lzma-win32-ia32-msvc": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-win32-ia32-msvc/-/lzma-win32-ia32-msvc-1.4.5.tgz", + "integrity": "sha512-OeacFVRCJOKNU/a0ephUfYZ2Yt+NvaHze/4TgOwJ0J0P4P7X1mHzN+ig9Iyd74aQDXYqc7kaCXA2dpAOcH87Cg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/lzma-win32-x64-msvc": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-win32-x64-msvc/-/lzma-win32-x64-msvc-1.4.5.tgz", + "integrity": "sha512-T4I1SamdSmtyZgDXGAGP+y5LEK5vxHUFwe8mz6D4R7Sa5/WCxTcCIgPJ9BD7RkpO17lzhlaM2vmVvMy96Lvk9Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/tar": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@napi-rs/tar/-/tar-1.1.0.tgz", + "integrity": "sha512-7cmzIu+Vbupriudo7UudoMRH2OA3cTw67vva8MxeoAe5S7vPFI7z0vp0pMXiA25S8IUJefImQ90FeJjl8fjEaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@napi-rs/tar-android-arm-eabi": "1.1.0", + "@napi-rs/tar-android-arm64": "1.1.0", + "@napi-rs/tar-darwin-arm64": "1.1.0", + "@napi-rs/tar-darwin-x64": "1.1.0", + "@napi-rs/tar-freebsd-x64": "1.1.0", + "@napi-rs/tar-linux-arm-gnueabihf": "1.1.0", + "@napi-rs/tar-linux-arm64-gnu": "1.1.0", + "@napi-rs/tar-linux-arm64-musl": "1.1.0", + "@napi-rs/tar-linux-ppc64-gnu": "1.1.0", + "@napi-rs/tar-linux-s390x-gnu": "1.1.0", + "@napi-rs/tar-linux-x64-gnu": "1.1.0", + "@napi-rs/tar-linux-x64-musl": "1.1.0", + "@napi-rs/tar-wasm32-wasi": "1.1.0", + "@napi-rs/tar-win32-arm64-msvc": "1.1.0", + "@napi-rs/tar-win32-ia32-msvc": "1.1.0", + "@napi-rs/tar-win32-x64-msvc": "1.1.0" + } + }, + "node_modules/@napi-rs/tar-android-arm-eabi": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@napi-rs/tar-android-arm-eabi/-/tar-android-arm-eabi-1.1.0.tgz", + "integrity": "sha512-h2Ryndraj/YiKgMV/r5by1cDusluYIRT0CaE0/PekQ4u+Wpy2iUVqvzVU98ZPnhXaNeYxEvVJHNGafpOfaD0TA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/tar-android-arm64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@napi-rs/tar-android-arm64/-/tar-android-arm64-1.1.0.tgz", + "integrity": "sha512-DJFyQHr1ZxNZorm/gzc1qBNLF/FcKzcH0V0Vwan5P+o0aE2keQIGEjJ09FudkF9v6uOuJjHCVDdK6S6uHtShAw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/tar-darwin-arm64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@napi-rs/tar-darwin-arm64/-/tar-darwin-arm64-1.1.0.tgz", + "integrity": "sha512-Zz2sXRzjIX4e532zD6xm2SjXEym6MkvfCvL2RMpG2+UwNVDVscHNcz3d47Pf3sysP2e2af7fBB3TIoK2f6trPw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/tar-darwin-x64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@napi-rs/tar-darwin-x64/-/tar-darwin-x64-1.1.0.tgz", + "integrity": "sha512-EI+CptIMNweT0ms9S3mkP/q+J6FNZ1Q6pvpJOEcWglRfyfQpLqjlC0O+dptruTPE8VamKYuqdjxfqD8hifZDOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/tar-freebsd-x64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@napi-rs/tar-freebsd-x64/-/tar-freebsd-x64-1.1.0.tgz", + "integrity": "sha512-J0PIqX+pl6lBIAckL/c87gpodLbjZB1OtIK+RDscKC9NLdpVv6VGOxzUV/fYev/hctcE8EfkLbgFOfpmVQPg2g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/tar-linux-arm-gnueabihf": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@napi-rs/tar-linux-arm-gnueabihf/-/tar-linux-arm-gnueabihf-1.1.0.tgz", + "integrity": "sha512-SLgIQo3f3EjkZ82ZwvrEgFvMdDAhsxCYjyoSuWfHCz0U16qx3SuGCp8+FYOPYCECHN3ZlGjXnoAIt9ERd0dEUg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/tar-linux-arm64-gnu": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@napi-rs/tar-linux-arm64-gnu/-/tar-linux-arm64-gnu-1.1.0.tgz", + "integrity": "sha512-d014cdle52EGaH6GpYTQOP9Py7glMO1zz/+ynJPjjzYFSxvdYx0byrjumZk2UQdIyGZiJO2MEFpCkEEKFSgPYA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/tar-linux-arm64-musl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@napi-rs/tar-linux-arm64-musl/-/tar-linux-arm64-musl-1.1.0.tgz", + "integrity": "sha512-L/y1/26q9L/uBqiW/JdOb/Dc94egFvNALUZV2WCGKQXc6UByPBMgdiEyW2dtoYxYYYYc+AKD+jr+wQPcvX2vrQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/tar-linux-ppc64-gnu": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@napi-rs/tar-linux-ppc64-gnu/-/tar-linux-ppc64-gnu-1.1.0.tgz", + "integrity": "sha512-EPE1K/80RQvPbLRJDJs1QmCIcH+7WRi0F73+oTe1582y9RtfGRuzAkzeBuAGRXAQEjRQw/RjtNqr6UTJ+8UuWQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/tar-linux-s390x-gnu": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@napi-rs/tar-linux-s390x-gnu/-/tar-linux-s390x-gnu-1.1.0.tgz", + "integrity": "sha512-B2jhWiB1ffw1nQBqLUP1h4+J1ovAxBOoe5N2IqDMOc63fsPZKNqF1PvO/dIem8z7LL4U4bsfmhy3gBfu547oNQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/tar-linux-x64-gnu": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@napi-rs/tar-linux-x64-gnu/-/tar-linux-x64-gnu-1.1.0.tgz", + "integrity": "sha512-tbZDHnb9617lTnsDMGo/eAMZxnsQFnaRe+MszRqHguKfMwkisc9CCJnks/r1o84u5fECI+J/HOrKXgczq/3Oww==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/tar-linux-x64-musl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@napi-rs/tar-linux-x64-musl/-/tar-linux-x64-musl-1.1.0.tgz", + "integrity": "sha512-dV6cODlzbO8u6Anmv2N/ilQHq/AWz0xyltuXoLU3yUyXbZcnWYZuB2rL8OBGPmqNcD+x9NdScBNXh7vWN0naSQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/tar-wasm32-wasi": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@napi-rs/tar-wasm32-wasi/-/tar-wasm32-wasi-1.1.0.tgz", + "integrity": "sha512-jIa9nb2HzOrfH0F8QQ9g3WE4aMH5vSI5/1NYVNm9ysCmNjCCtMXCAhlI3WKCdm/DwHf0zLqdrrtDFXODcNaqMw==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.0.3" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@napi-rs/tar-win32-arm64-msvc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@napi-rs/tar-win32-arm64-msvc/-/tar-win32-arm64-msvc-1.1.0.tgz", + "integrity": "sha512-vfpG71OB0ijtjemp3WTdmBKJm9R70KM8vsSExMsIQtV0lVzP07oM1CW6JbNRPXNLhRoue9ofYLiUDk8bE0Hckg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/tar-win32-ia32-msvc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@napi-rs/tar-win32-ia32-msvc/-/tar-win32-ia32-msvc-1.1.0.tgz", + "integrity": "sha512-hGPyPW60YSpOSgzfy68DLBHgi6HxkAM+L59ZZZPMQ0TOXjQg+p2EW87+TjZfJOkSpbYiEkULwa/f4a2hcVjsqQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/tar-win32-x64-msvc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@napi-rs/tar-win32-x64-msvc/-/tar-win32-x64-msvc-1.1.0.tgz", + "integrity": "sha512-L6Ed1DxXK9YSCMyvpR8MiNAyKNkQLjsHsHK9E0qnHa8NzLFqzDKhvs5LfnWxM2kJ+F7m/e5n9zPm24kHb3LsVw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.7.tgz", + "integrity": "sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.5.0", + "@emnapi/runtime": "^1.5.0", + "@tybys/wasm-util": "^0.10.1" + } + }, + "node_modules/@napi-rs/wasm-tools": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-tools/-/wasm-tools-1.0.1.tgz", + "integrity": "sha512-enkZYyuCdo+9jneCPE/0fjIta4wWnvVN9hBo2HuiMpRF0q3lzv1J6b/cl7i0mxZUKhBrV3aCKDBQnCOhwKbPmQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@napi-rs/wasm-tools-android-arm-eabi": "1.0.1", + "@napi-rs/wasm-tools-android-arm64": "1.0.1", + "@napi-rs/wasm-tools-darwin-arm64": "1.0.1", + "@napi-rs/wasm-tools-darwin-x64": "1.0.1", + "@napi-rs/wasm-tools-freebsd-x64": "1.0.1", + "@napi-rs/wasm-tools-linux-arm64-gnu": "1.0.1", + "@napi-rs/wasm-tools-linux-arm64-musl": "1.0.1", + "@napi-rs/wasm-tools-linux-x64-gnu": "1.0.1", + "@napi-rs/wasm-tools-linux-x64-musl": "1.0.1", + "@napi-rs/wasm-tools-wasm32-wasi": "1.0.1", + "@napi-rs/wasm-tools-win32-arm64-msvc": "1.0.1", + "@napi-rs/wasm-tools-win32-ia32-msvc": "1.0.1", + "@napi-rs/wasm-tools-win32-x64-msvc": "1.0.1" + } + }, + "node_modules/@napi-rs/wasm-tools-android-arm-eabi": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-tools-android-arm-eabi/-/wasm-tools-android-arm-eabi-1.0.1.tgz", + "integrity": "sha512-lr07E/l571Gft5v4aA1dI8koJEmF1F0UigBbsqg9OWNzg80H3lDPO+auv85y3T/NHE3GirDk7x/D3sLO57vayw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/wasm-tools-android-arm64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-tools-android-arm64/-/wasm-tools-android-arm64-1.0.1.tgz", + "integrity": "sha512-WDR7S+aRLV6LtBJAg5fmjKkTZIdrEnnQxgdsb7Cf8pYiMWBHLU+LC49OUVppQ2YSPY0+GeYm9yuZWW3kLjJ7Bg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/wasm-tools-darwin-arm64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-tools-darwin-arm64/-/wasm-tools-darwin-arm64-1.0.1.tgz", + "integrity": "sha512-qWTI+EEkiN0oIn/N2gQo7+TVYil+AJ20jjuzD2vATS6uIjVz+Updeqmszi7zq7rdFTLp6Ea3/z4kDKIfZwmR9g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/wasm-tools-darwin-x64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-tools-darwin-x64/-/wasm-tools-darwin-x64-1.0.1.tgz", + "integrity": "sha512-bA6hubqtHROR5UI3tToAF/c6TDmaAgF0SWgo4rADHtQ4wdn0JeogvOk50gs2TYVhKPE2ZD2+qqt7oBKB+sxW3A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/wasm-tools-freebsd-x64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-tools-freebsd-x64/-/wasm-tools-freebsd-x64-1.0.1.tgz", + "integrity": "sha512-90+KLBkD9hZEjPQW1MDfwSt5J1L46EUKacpCZWyRuL6iIEO5CgWU0V/JnEgFsDOGyyYtiTvHc5bUdUTWd4I9Vg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/wasm-tools-linux-arm64-gnu": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-tools-linux-arm64-gnu/-/wasm-tools-linux-arm64-gnu-1.0.1.tgz", + "integrity": "sha512-rG0QlS65x9K/u3HrKafDf8cFKj5wV2JHGfl8abWgKew0GVPyp6vfsDweOwHbWAjcHtp2LHi6JHoW80/MTHm52Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/wasm-tools-linux-arm64-musl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-tools-linux-arm64-musl/-/wasm-tools-linux-arm64-musl-1.0.1.tgz", + "integrity": "sha512-jAasbIvjZXCgX0TCuEFQr+4D6Lla/3AAVx2LmDuMjgG4xoIXzjKWl7c4chuaD+TI+prWT0X6LJcdzFT+ROKGHQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/wasm-tools-linux-x64-gnu": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-tools-linux-x64-gnu/-/wasm-tools-linux-x64-gnu-1.0.1.tgz", + "integrity": "sha512-Plgk5rPqqK2nocBGajkMVbGm010Z7dnUgq0wtnYRZbzWWxwWcXfZMPa8EYxrK4eE8SzpI7VlZP1tdVsdjgGwMw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/wasm-tools-linux-x64-musl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-tools-linux-x64-musl/-/wasm-tools-linux-x64-musl-1.0.1.tgz", + "integrity": "sha512-GW7AzGuWxtQkyHknHWYFdR0CHmW6is8rG2Rf4V6GNmMpmwtXt/ItWYWtBe4zqJWycMNazpfZKSw/BpT7/MVCXQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/wasm-tools-wasm32-wasi": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-tools-wasm32-wasi/-/wasm-tools-wasm32-wasi-1.0.1.tgz", + "integrity": "sha512-/nQVSTrqSsn7YdAc2R7Ips/tnw5SPUcl3D7QrXCNGPqjbatIspnaexvaOYNyKMU6xPu+pc0BTnKVmqhlJJCPLA==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.0.3" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@napi-rs/wasm-tools-win32-arm64-msvc": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-tools-win32-arm64-msvc/-/wasm-tools-win32-arm64-msvc-1.0.1.tgz", + "integrity": "sha512-PFi7oJIBu5w7Qzh3dwFea3sHRO3pojMsaEnUIy22QvsW+UJfNQwJCryVrpoUt8m4QyZXI+saEq/0r4GwdoHYFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" } }, - "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.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "node_modules/@napi-rs/wasm-tools-win32-ia32-msvc": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-tools-win32-ia32-msvc/-/wasm-tools-win32-ia32-msvc-1.0.1.tgz", + "integrity": "sha512-gXkuYzxQsgkj05Zaq+KQTkHIN83dFAwMcTKa2aQcpYPRImFm2AQzEyLtpXmyCWzJ0F9ZYAOmbSyrNew8/us6bw==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@jsdevtools/ez-spawn": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@jsdevtools/ez-spawn/-/ez-spawn-3.0.4.tgz", - "integrity": "sha512-f5DRIOZf7wxogefH03RjMPMdBF7ADTWUMoOs9kaJo06EfwF+aFhMZMDZxHg/Xe12hptN9xoZjGso2fdjapBRIA==", + "node_modules/@napi-rs/wasm-tools-win32-x64-msvc": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-tools-win32-x64-msvc/-/wasm-tools-win32-x64-msvc-1.0.1.tgz", + "integrity": "sha512-rEAf05nol3e3eei2sRButmgXP+6ATgm0/38MKhz9Isne82T4rPIMYsCIFj0kOisaGeVwoi2fnm7O9oWp5YVnYQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "call-me-maybe": "^1.0.1", - "cross-spawn": "^7.0.3", - "string-argv": "^0.3.1", - "type-detect": "^4.0.8" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=10" + "node": ">= 10" } }, "node_modules/@noble/curves": { @@ -1981,6 +3407,22 @@ "node": ">= 8" } }, + "node_modules/@o1js/native-darwin-arm64": { + "resolved": "native/darwin-arm64", + "link": true + }, + "node_modules/@o1js/native-darwin-x64": { + "resolved": "native/darwin-x64", + "link": true + }, + "node_modules/@o1js/native-linux-arm64": { + "resolved": "native/linux-arm64", + "link": true + }, + "node_modules/@o1js/native-win32-x64": { + "resolved": "native/win32-x64", + "link": true + }, "node_modules/@octokit/action": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@octokit/action/-/action-6.1.0.tgz", @@ -2243,6 +3685,186 @@ "@octokit/openapi-types": "^22.2.0" } }, + "node_modules/@octokit/rest": { + "version": "22.0.1", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-22.0.1.tgz", + "integrity": "sha512-Jzbhzl3CEexhnivb1iQ0KJ7s5vvjMWcmRtq5aUsKmKDrRW6z3r84ngmiFKFvpZjpiU/9/S6ITPFRpn5s/3uQJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/core": "^7.0.6", + "@octokit/plugin-paginate-rest": "^14.0.0", + "@octokit/plugin-request-log": "^6.0.0", + "@octokit/plugin-rest-endpoint-methods": "^17.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/auth-token": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-6.0.0.tgz", + "integrity": "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/core": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.6.tgz", + "integrity": "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/auth-token": "^6.0.0", + "@octokit/graphql": "^9.0.3", + "@octokit/request": "^10.0.6", + "@octokit/request-error": "^7.0.2", + "@octokit/types": "^16.0.0", + "before-after-hook": "^4.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/endpoint": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.2.tgz", + "integrity": "sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^16.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/graphql": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-9.0.3.tgz", + "integrity": "sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/request": "^10.0.6", + "@octokit/types": "^16.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/openapi-types": { + "version": "27.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-27.0.0.tgz", + "integrity": "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/rest/node_modules/@octokit/plugin-paginate-rest": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-14.0.0.tgz", + "integrity": "sha512-fNVRE7ufJiAA3XUrha2omTA39M6IXIc6GIZLvlbsm8QOQCYvpq/LkMNGyFlB1d8hTDzsAXa3OKtybdMAYsV/fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^16.0.0" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/plugin-request-log": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-6.0.0.tgz", + "integrity": "sha512-UkOzeEN3W91/eBq9sPZNQ7sUBvYCqYbrrD8gTbBuGtHEuycE4/awMXcYvx6sVYo7LypPhmQwwpUe4Yyu4QZN5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-17.0.0.tgz", + "integrity": "sha512-B5yCyIlOJFPqUUeiD0cnBJwWJO8lkJs5d8+ze9QDP6SvfiXSz1BF+91+0MeI1d2yxgOhU/O+CvtiZ9jSkHhFAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^16.0.0" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/request": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.6.tgz", + "integrity": "sha512-FO+UgZCUu+pPnZAR+iKdUt64kPE7QW7ciqpldaMXaNzixz5Jld8dJ31LAUewk0cfSRkNSRKyqG438ba9c/qDlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^11.0.2", + "@octokit/request-error": "^7.0.2", + "@octokit/types": "^16.0.0", + "fast-content-type-parse": "^3.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/request-error": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-7.0.2.tgz", + "integrity": "sha512-U8piOROoQQUyExw5c6dTkU3GKxts5/ERRThIauNL7yaRoeXW0q/5bgHWT7JfWBw1UyrbK8ERId2wVkcB32n0uQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^16.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/types": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-16.0.0.tgz", + "integrity": "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^27.0.0" + } + }, + "node_modules/@octokit/rest/node_modules/before-after-hook": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-4.0.0.tgz", + "integrity": "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@octokit/rest/node_modules/universal-user-agent": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", + "integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==", + "dev": true, + "license": "ISC" + }, "node_modules/@octokit/types": { "version": "12.6.0", "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", @@ -2453,6 +4075,17 @@ "@sinonjs/commons": "^1.7.0" } }, + "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/babel__core": { "version": "7.20.4", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.4.tgz", @@ -2584,6 +4217,13 @@ "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", "dev": true }, + "node_modules/@types/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -2964,6 +4604,13 @@ "node": ">=10" } }, + "node_modules/chardet": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz", + "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==", + "dev": true, + "license": "MIT" + }, "node_modules/ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", @@ -2985,6 +4632,32 @@ "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, + "node_modules/clipanion": { + "version": "4.0.0-rc.4", + "resolved": "https://registry.npmjs.org/clipanion/-/clipanion-4.0.0-rc.4.tgz", + "integrity": "sha512-CXkMQxU6s9GklO/1f714dkKBMu1lopS1WFF0B8o4AxPykR1hpozxSiUZ5ZUeBjfPgCWqbcNOtZVFhB8Lkfp1+Q==", + "dev": true, + "license": "MIT", + "workspaces": [ + "website" + ], + "dependencies": { + "typanion": "^3.8.0" + }, + "peerDependencies": { + "typanion": "*" + } + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -3033,6 +4706,13 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -3067,12 +4747,13 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "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.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -3151,6 +4832,21 @@ "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, + "node_modules/emnapi": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/emnapi/-/emnapi-1.7.0.tgz", + "integrity": "sha512-d/RB4oJJu56sOxx+ooK4978jUvnoUo3iRob1/U3N+QnCr91IRQ2QNpAGa3/ZSEZqDWgdhfB1Er5jarfYzjvghg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "node-addon-api": ">= 6.1.0" + }, + "peerDependenciesMeta": { + "node-addon-api": { + "optional": true + } + } + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -3187,6 +4883,17 @@ "stackframe": "^1.3.4" } }, + "node_modules/es-toolkit": { + "version": "1.41.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.41.0.tgz", + "integrity": "sha512-bDd3oRmbVgqZCJS6WmeQieOrzpl3URcWBUVDXxOELlUW2FuW+0glPOz1n0KnRie+PdyvUZcXz2sOn00c6pPRIA==", + "dev": true, + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, "node_modules/esbuild": { "version": "0.25.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", @@ -3387,6 +5094,23 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, + "node_modules/fast-content-type-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-3.0.0.tgz", + "integrity": "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -3658,6 +5382,23 @@ "url": "https://github.com/sponsors/typicode" } }, + "node_modules/iconv-lite": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -5302,6 +7043,19 @@ "dev": true, "license": "MIT" }, + "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, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -5545,10 +7299,21 @@ } }, "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 + "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/mute-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } }, "node_modules/natural-compare": { "version": "1.4.0", @@ -6198,14 +7963,19 @@ "queue-microtask": "^1.2.2" } }, + "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, + "license": "MIT" + }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -6213,24 +7983,6 @@ "node": ">=10" } }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -6621,6 +8373,16 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, + "node_modules/typanion": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/typanion/-/typanion-3.14.0.tgz", + "integrity": "sha512-ZW/lVMRabETuYCd9O9ZvMhAh8GslSqaUjxmK/JLPCh6l73CvLBiuXswj/+7LdnWOgYsQ130FqLzFz5aGT4I3Ug==", + "dev": true, + "license": "MIT", + "workspaces": [ + "website" + ] + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -6959,6 +8721,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", + "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/zod": { "version": "3.23.8", "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", diff --git a/package.json b/package.json index a6c348c5df..c417854d31 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "build:jsoo": "npm run build:jsoo:web && npm run build:jsoo:node", "build:jsoo:web": "./scripts/build/jsoo/build-web.sh", "build:jsoo:node": "./scripts/build/jsoo/build-node.sh", + "build:native": "./scripts/build/native/build.sh", "build:docs": "typedoc", "prepublish:web": "./scripts/prepublish/prepublish-web.sh", "prepublish:node": "./scripts/prepublish/prepublish-node.sh", @@ -92,11 +93,14 @@ "e2e:install": "npx playwright install --with-deps", "e2e:show-report": "npx playwright show-report tests/report", "update-changelog": "./scripts/changelog/update-changelog.sh", - "prepare": "husky" + "prepare": "husky", + "native:prepublish": "./scripts/prepublish/native/prepublish-native-package.sh", + "native:publish": "./scripts/publish/native/publish-native-package.sh" }, "author": "O(1) Labs", "devDependencies": { "@influxdata/influxdb-client": "^1.33.2", + "@napi-rs/cli": "^3.4.1", "@noble/curves": "1.8.1", "@noble/hashes": "^1.3.2", "@playwright/test": "^1.48.0", @@ -104,6 +108,7 @@ "@types/libsodium-wrappers-sumo": "^0.7.8", "@types/minimist": "^1.2.5", "@types/node": "^18.14.2", + "@types/semver": "^7.7.1", "esbuild": "^0.25.5", "expect": "^29.0.1", "fs-extra": "^10.0.0", @@ -119,6 +124,7 @@ "prettier-plugin-organize-imports": "^4.3.0", "replace-in-file": "^6.3.5", "rimraf": "^3.0.2", + "semver": "^7.7.3", "ts-jest": "^28.0.8", "typedoc": "^0.28.5", "typedoc-plugin-markdown": "^4.6.4", @@ -133,5 +139,14 @@ "reflect-metadata": "^0.1.13", "stacktrace-js": "^2.0.2", "tslib": "^2.3.0" + }, + "optionalDependencies": { + "@o1js/native-darwin-arm64": "file:./native/darwin-arm64", + "@o1js/native-darwin-x64": "file:./native/darwin-x64", + "@o1js/native-linux-arm64": "file:./native/linux-arm64", + "@o1js/native-win32-x64": "file:./native/win32-x64" + }, + "o1js-internal": { + "native-version": "0.0.1-dev.4" } } diff --git a/scripts/build/native/build.sh b/scripts/build/native/build.sh new file mode 100755 index 0000000000..631344bcbf --- /dev/null +++ b/scripts/build/native/build.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +source ./scripts/lib/ux.sh + +setup_script "native-build" "native build" + +NODE_PLATFORM=$(node -e 'console.log(process.platform)') +NODE_ARCH=$(node -e 'console.log(process.arch)') +TARGET_SLUG=$NODE_PLATFORM-$NODE_ARCH + +info "building bindings for $TARGET_SLUG" + +KIMCHI_PATH=./src/mina/src/lib/crypto/kimchi_bindings/js/native +BUILT_PATH=./src/mina/src/lib/crypto/kimchi_bindings/js/native/artifacts +BINDINGS_PATH=./native/$TARGET_SLUG/ + +mkdir -p $BINDINGS_PATH + +info "building native Kimchi bindings..." + +dune build $KIMCHI_PATH + +info "creating package for $TARGET_SLUG bindings..." + +cat > $BINDINGS_PATH/package.json < $BINDINGS_PATH/README.md < $BINDINGS_PATH/index.js + +info "copying artifacts into the right place..." +cp $BUILT_PATH/plonk_napi.node $BINDINGS_PATH/plonk_napi.node +chmod 660 $BINDINGS_PATH/plonk_napi.node +cp $BUILT_PATH/index.d.ts $BINDINGS_PATH/index.d.ts +chmod 660 $BINDINGS_PATH/index.d.ts + +success "Native build success!" \ No newline at end of file diff --git a/scripts/prepublish/native/prepublish-native-package.opam b/scripts/prepublish/native/prepublish-native-package.opam new file mode 100644 index 0000000000..aaa0efc72b --- /dev/null +++ b/scripts/prepublish/native/prepublish-native-package.opam @@ -0,0 +1,5 @@ +opam-version: "2.0" +depends: [ + "dune" + "js_of_ocaml-ppx" +] \ No newline at end of file diff --git a/scripts/prepublish/native/prepublish-native-package.sh b/scripts/prepublish/native/prepublish-native-package.sh new file mode 100755 index 0000000000..00343f9547 --- /dev/null +++ b/scripts/prepublish/native/prepublish-native-package.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +source ./scripts/lib/ux.sh +setup_script "npm-publish-native" "NPM publish native" + +NODE_PLATFORM=$(node -e 'console.log(process.platform)') +NODE_ARCH=$(node -e 'console.log(process.arch)') +TARGET_SLUG=$NODE_PLATFORM-$NODE_ARCH +BINDINGS_PATH=./native/$TARGET_SLUG + +./run ./scripts/prepublish/native/prepublish-native-package.ts \ + --bundle \ + --write \ + $BINDINGS_PATH \ + ./ + +cat $BINDINGS_PATH/package.json \ No newline at end of file diff --git a/scripts/prepublish/native/prepublish-native-package.ts b/scripts/prepublish/native/prepublish-native-package.ts new file mode 100644 index 0000000000..eb964da72a --- /dev/null +++ b/scripts/prepublish/native/prepublish-native-package.ts @@ -0,0 +1,34 @@ +import minimist from 'minimist'; +import { readFile, writeFile } from 'node:fs/promises'; +import { join } from 'node:path'; +import semver from 'semver'; + +const { + write, + _: [packagePath, basePackagePath], +} = minimist(process.argv.slice(3), { + boolean: 'write', +}); + +const basePackageJsonPath = join(basePackagePath, 'package.json'); +const basePkgJson = await readFile(basePackageJsonPath, 'utf8').then(JSON.parse); +const o1jsInternalCfg = basePkgJson['o1js-internal']; +const nativeVersionIn = o1jsInternalCfg['native-version']; + +const nativeVersion = semver.valid(nativeVersionIn); +if (nativeVersion === null) { + console.error(`${nativeVersionIn} is not valid semver`); + process.exit(1); +} + +const packageJsonPath = join(packagePath, 'package.json'); +const pkgJson = await readFile(packageJsonPath, 'utf8').then(JSON.parse); + +pkgJson.version = nativeVersion; + +if (write) { + await writeFile(packageJsonPath, JSON.stringify(pkgJson, null, 2)); +} else { + console.log(pkgJson); + console.log('dry run, use --write to commit file.'); +} diff --git a/scripts/prepublish/prepublish-full.sh b/scripts/prepublish/prepublish-full.sh index efd917b224..8a4033b757 100755 --- a/scripts/prepublish/prepublish-full.sh +++ b/scripts/prepublish/prepublish-full.sh @@ -24,4 +24,8 @@ info "Running node prepublish..." run_cmd npm run prepublish:node ok "Node prepublish finished" +info "Running native prepublish..." +run_cmd npm run prepublish:native +ok "Native prepublish finished" + success "Prepublish tasks complete" diff --git a/scripts/prepublish/prepublish-native.sh b/scripts/prepublish/prepublish-native.sh new file mode 100755 index 0000000000..cb4c1d262f --- /dev/null +++ b/scripts/prepublish/prepublish-native.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +source ./scripts/lib/ux.sh +setup_script "prepublish-native" "prepublish native" + +./run ./scripts/prepublish/prepublish-native.ts --bundle --write ./ \ No newline at end of file diff --git a/scripts/prepublish/prepublish-native.ts b/scripts/prepublish/prepublish-native.ts new file mode 100644 index 0000000000..cb8d56e7fc --- /dev/null +++ b/scripts/prepublish/prepublish-native.ts @@ -0,0 +1,48 @@ +import minimist from 'minimist'; +import { readFile, writeFile } from 'node:fs/promises'; +import { join } from 'node:path'; +import semver from 'semver'; +import { targetToSlug } from './slug'; + +const nativeTargets = [ + { platform: 'darwin', arch: 'arm64' }, + { platform: 'darwin', arch: 'x64' }, + { platform: 'linux', arch: 'arm64' }, + { platform: 'win32', arch: 'x64' }, +]; + +const { + write, + _: [packagePath], +} = minimist(process.argv.slice(3), { + boolean: 'write', +}); + +const packageJsonPath = join(packagePath, 'package.json'); + +const pkgJson = await readFile(packageJsonPath, 'utf8').then(JSON.parse); + +const o1jsInternalCfg = pkgJson['o1js-internal']; + +const nativeVersionIn = o1jsInternalCfg['native-version']; + +const nativeVersion = semver.valid(nativeVersionIn); +if (nativeVersion === null) { + console.error(`${nativeVersionIn} is not valid semver`); + process.exit(1); +} + +for (const target of nativeTargets) { + const slug = targetToSlug(target); + + if (slug in pkgJson.optionalDependencies) { + pkgJson.optionalDependencies[slug] = nativeVersion; + } +} + +if (write) { + await writeFile(packageJsonPath, JSON.stringify(pkgJson, null, 2)); +} else { + console.log(pkgJson); + console.log('dry run, use --write to commit file.'); +} diff --git a/scripts/prepublish/slug.ts b/scripts/prepublish/slug.ts new file mode 100644 index 0000000000..1af6428cf1 --- /dev/null +++ b/scripts/prepublish/slug.ts @@ -0,0 +1,3 @@ +export function targetToSlug(target: { platform: string; arch: string }) { + return `@o1js/native-${target.platform}-${target.arch}`; +} diff --git a/scripts/publish/native/publish-native-package.sh b/scripts/publish/native/publish-native-package.sh new file mode 100755 index 0000000000..7dda61b12f --- /dev/null +++ b/scripts/publish/native/publish-native-package.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +NODE_PLATFORM=$(node -e 'console.log(process.platform)') +NODE_ARCH=$(node -e 'console.log(process.arch)') +TARGET_SLUG=$NODE_PLATFORM-$NODE_ARCH +BINDINGS_PATH=./native/$TARGET_SLUG + +PACKAGE_NAME=@o1js/native-$TARGET_SLUG + +pushd $BINDINGS_PATH + VERSION=$(cat ./package.json | jq -r .version) + if npm view $PACKAGE_NAME@$VERSION >/dev/null 2>&1; then + echo "$PACKAGE_NAME@$VERSION already exists. Skipping publish step." + exit 0 + fi + + npm publish --provenance --access public --tag experimental +popd \ No newline at end of file diff --git a/src/bindings/crypto/bindings.ts b/src/bindings/crypto/bindings.ts index 8e9fcb35ff..5f45a4039c 100644 --- a/src/bindings/crypto/bindings.ts +++ b/src/bindings/crypto/bindings.ts @@ -3,21 +3,36 @@ * It is exposed to JSOO by populating a global variable with an object. * It gets imported as the first thing in ../../bindings.js so that the global variable is ready by the time JSOO code gets executed. */ +import type * as napiNamespace from '../compiled/node_bindings/plonk_wasm.cjs'; +import type * as wasmNamespace from '../compiled/node_bindings/plonk_wasm.cjs'; import { prefixHashes, prefixHashesLegacy } from '../crypto/constants.js'; import { Bigint256Bindings } from './bindings/bigint256.js'; -import { PallasBindings, VestaBindings } from './bindings/curve.js'; -import { FpBindings, FqBindings } from './bindings/field.js'; -import { FpVectorBindings, FqVectorBindings } from './bindings/vector.js'; -import type * as wasmNamespace from '../compiled/node_bindings/plonk_wasm.cjs'; import { fieldsFromRustFlat, fieldsToRustFlat } from './bindings/conversion-base.js'; -import { proofConversion } from './bindings/conversion-proof.js'; import { conversionCore } from './bindings/conversion-core.js'; -import { verifierIndexConversion } from './bindings/conversion-verifier-index.js'; import { oraclesConversion } from './bindings/conversion-oracles.js'; +import { proofConversion } from './bindings/conversion-proof.js'; +import { verifierIndexConversion } from './bindings/conversion-verifier-index.js'; +import { PallasBindings, VestaBindings } from './bindings/curve.js'; import { jsEnvironment } from './bindings/env.js'; +import { FpBindings, FqBindings } from './bindings/field.js'; +import { FpVectorBindings, FqVectorBindings } from './bindings/vector.js'; import { srs } from './bindings/srs.js'; +import { srs as napiSrs } from './napi-srs.js'; +import { napiConversionCore } from './napi-conversion-core.js'; +import { napiProofConversion } from './napi-conversion-proof.js'; +import { napiVerifierIndexConversion } from './napi-conversion-verifier-index.js'; +import { napiOraclesConversion } from './bindings/napi-conversion-oracles.js'; -export { getRustConversion, RustConversion, Wasm }; +export { Napi, RustConversion, Wasm, createNativeRustConversion, getRustConversion }; + +/* TODO: Uncomment in phase 2 of conversion layer +import { conversionCore as conversionCoreNative } from './native/conversion-core.js'; +import { fieldsFromRustFlat as fieldsFromRustFlatNative, fieldsToRustFlat as fieldsToRustFlatNative } from './native/conversion-base.js'; +import { proofConversion as proofConversionNative } from './native/conversion-proof.js'; +import { verifierIndexConversion as verifierIndexConversionNative } from './native/conversion-verifier-index.js'; +import { oraclesConversion as oraclesConversionNative } from './native/conversion-oracles.js'; + +export { getRustConversion, type RustConversion, type NativeConversion, type Wasm };*/ const tsBindings = { jsEnvironment, @@ -31,15 +46,33 @@ const tsBindings = { ...FpVectorBindings, ...FqVectorBindings, rustConversion: createRustConversion, + nativeRustConversion: createNativeRustConversion, + /* TODO: Uncomment in phase 2 of conversion layer + srs: (wasm: Wasm) => { + const bundle = getConversionBundle(wasm); + return bundle.srsFactory(wasm, bundle.conversion); + },*/ srs: (wasm: Wasm) => srs(wasm, getRustConversion(wasm)), + srsNative: (napi: Napi) => napiSrs(napi, createNativeRustConversion(napi) as any), }; // this is put in a global variable so that mina/src/lib/crypto/kimchi_bindings/js/bindings.js finds it (globalThis as any).__snarkyTsBindings = tsBindings; type Wasm = typeof wasmNamespace; +type Napi = typeof napiNamespace; + +type RustConversion = ReturnType; + +function getRustConversion(wasm: Wasm): RustConversion { + return createRustConversion(wasm); +} function createRustConversion(wasm: Wasm) { + return buildWasmConversion(wasm); +} + +function buildWasmConversion(wasm: Wasm) { let core = conversionCore(wasm); let verifierIndex = verifierIndexConversion(wasm, core); let oracles = oraclesConversion(wasm); @@ -55,10 +88,75 @@ function createRustConversion(wasm: Wasm) { }; } -type RustConversion = ReturnType; +function createNativeRustConversion(napi: any) { + let core = napiConversionCore(napi); + let proof = napiProofConversion(napi, core); + let verif = napiVerifierIndexConversion(napi, core); + let oracles = napiOraclesConversion(napi); + return { + fp: { ...core.fp, ...proof.fp, ...verif.fp, ...oracles.fp }, + fq: { ...core.fq, ...proof.fq, ...verif.fq, ...oracles.fq }, + }; +} + +/* TODO: Uncomment in phase 2 of conversion layer + +function shouldUseNativeConversion(wasm: Wasm): boolean { + const marker = (wasm as any).__kimchi_use_native; + const globalMarker = + typeof globalThis !== 'undefined' && + (globalThis as any).__kimchi_use_native; + return Boolean(marker || globalMarker); +} + +function createRustConversion(wasm: Wasm): RustConversion { + return shouldUseNativeConversion(wasm) + ? createNativeConversion(wasm) + : createWasmConversion(wasm); +} + +function createWasmConversion(wasm: Wasm) { + const core = conversionCore(wasm); + const verifierIndex = verifierIndexConversion(wasm, core); + const oracles = oraclesConversion(wasm); + const proof = proofConversion(wasm, core); + + return { + fp: { ...core.fp, ...verifierIndex.fp, ...oracles.fp, ...proof.fp }, + fq: { ...core.fq, ...verifierIndex.fq, ...oracles.fq, ...proof.fq }, + fieldsToRustFlat, + fieldsFromRustFlat, + wireToRust: core.wireToRust, + mapMlArrayToRustVector: core.mapMlArrayToRustVector, + }; +} + +type RustConversion = ReturnType; + +function createNativeConversion(wasm: Wasm) { + const core = conversionCoreNative(wasm); + const verifierIndex = verifierIndexConversionNative(wasm, core); + const oracles = oraclesConversionNative(wasm); + const proof = proofConversionNative(wasm, core); + + return { + fp: { ...core.fp, ...verifierIndex.fp, ...oracles.fp, ...proof.fp }, + fq: { ...core.fq, ...verifierIndex.fq, ...oracles.fq, ...proof.fq }, + fieldsToRustFlatNative, + fieldsFromRustFlatNative, + wireToRust: core.wireToRust, + mapMlArrayToRustVector: core.mapMlArrayToRustVector, + }; +} -let rustConversion: RustConversion | undefined; +type ConversionBundle = + | { conversion: WasmConversion; srsFactory: typeof srs } + | { conversion: NativeConversion; srsFactory: typeof srsNative }; -function getRustConversion(wasm: Wasm) { - return rustConversion ?? (rustConversion = createRustConversion(wasm)); +function getConversionBundle(wasm: Wasm): ConversionBundle { + if (shouldUseNativeConversion(wasm)) { + return { conversion: createNativeConversion(wasm), srsFactory: srsNative }; + } + return { conversion: createWasmConversion(wasm), srsFactory: srs }; } +*/ diff --git a/src/bindings/crypto/bindings/conversion-base.ts b/src/bindings/crypto/bindings/conversion-base.ts index 9f67829df3..5b8cdd601d 100644 --- a/src/bindings/crypto/bindings/conversion-base.ts +++ b/src/bindings/crypto/bindings/conversion-base.ts @@ -1,24 +1,24 @@ -import { Field } from './field.js'; -import { bigintToBytes32, bytesToBigint32 } from '../bigint-helpers.js'; +import type { MlArray } from '../../../lib/ml/base.js'; import type { WasmGPallas, WasmGVesta, WasmPallasGProjective, WasmVestaGProjective, } from '../../compiled/node_bindings/plonk_wasm.cjs'; -import type { MlArray } from '../../../lib/ml/base.js'; -import { OrInfinity, Infinity } from './curve.js'; +import { bigintToBytes32, bytesToBigint32 } from '../bigint-helpers.js'; +import { Infinity, OrInfinity } from './curve.js'; +import { Field } from './field.js'; export { - fieldToRust, + WasmAffine, + WasmProjective, + affineFromRust, + affineToRust, fieldFromRust, - fieldsToRustFlat, + fieldToRust, fieldsFromRustFlat, + fieldsToRustFlat, maybeFieldToRust, - affineToRust, - affineFromRust, - WasmAffine, - WasmProjective, }; // TODO: Hardcoding this is a little brittle diff --git a/src/bindings/crypto/bindings/conversion-core.ts b/src/bindings/crypto/bindings/conversion-core.ts index 1628f3db39..ea5002e6df 100644 --- a/src/bindings/crypto/bindings/conversion-core.ts +++ b/src/bindings/crypto/bindings/conversion-core.ts @@ -1,3 +1,5 @@ +import { MlArray } from '../../../lib/ml/base.js'; +import type * as wasmNamespace from '../../compiled/node_bindings/plonk_wasm.cjs'; import type { WasmFpGate, WasmFpPolyComm, @@ -6,10 +8,6 @@ import type { WasmGPallas, WasmGVesta, } from '../../compiled/node_bindings/plonk_wasm.cjs'; -import { OrInfinity, Gate, PolyComm, Wire } from './kimchi-types.js'; -import type * as wasmNamespace from '../../compiled/node_bindings/plonk_wasm.cjs'; -import { MlArray } from '../../../lib/ml/base.js'; -import { mapTuple } from './util.js'; import { WasmAffine, affineFromRust, @@ -17,16 +15,18 @@ import { fieldsFromRustFlat, fieldsToRustFlat, } from './conversion-base.js'; +import { Gate, OrInfinity, PolyComm, Wire } from './kimchi-types.js'; +import { mapTuple } from './util.js'; export { ConversionCore, ConversionCores, conversionCore, freeOnFinalize, - wrap, - unwrap, mapFromUintArray, mapToUint32Array, + unwrap, + wrap, }; // basic conversion functions for each field @@ -116,7 +116,9 @@ function conversionCorePerField( return new PolyComm(rustUnshifted, rustShifted); }, polyCommFromRust(polyComm: WasmPolyComm): PolyComm { + console.log('polyComm old', polyComm); let rustUnshifted = polyComm.unshifted; + console.log('rustUnshifted', rustUnshifted); let mlUnshifted = mapFromUintArray(rustUnshifted, (ptr) => { return affineFromRust(wrap(ptr, CommitmentCurve)); }); @@ -174,6 +176,7 @@ function freeOnFinalize(instance: T) { } function mapFromUintArray(array: Uint32Array | Uint8Array, map: (i: number) => T) { + console.log('array', array); let n = array.length; let result: T[] = Array(n); for (let i = 0; i < n; i++) { diff --git a/src/bindings/crypto/bindings/conversion-proof.ts b/src/bindings/crypto/bindings/conversion-proof.ts index ee106fb940..5fdc45e6ce 100644 --- a/src/bindings/crypto/bindings/conversion-proof.ts +++ b/src/bindings/crypto/bindings/conversion-proof.ts @@ -1,46 +1,46 @@ +import { MlArray, MlOption, MlTuple } from '../../../lib/ml/base.js'; +import type * as wasmNamespace from '../../compiled/node_bindings/plonk_wasm.cjs'; import type { WasmFpLookupCommitments, - WasmPastaFpLookupTable, WasmFpOpeningProof, WasmFpProverCommitments, WasmFpProverProof, WasmFpRuntimeTable, - WasmPastaFpRuntimeTableCfg, WasmFqLookupCommitments, WasmFqOpeningProof, WasmFqProverCommitments, - WasmPastaFqLookupTable, WasmFqProverProof, WasmFqRuntimeTable, + WasmPastaFpLookupTable, + WasmPastaFpRuntimeTableCfg, + WasmPastaFqLookupTable, WasmPastaFqRuntimeTableCfg, WasmVecVecFp, WasmVecVecFq, } from '../../compiled/node_bindings/plonk_wasm.cjs'; -import type * as wasmNamespace from '../../compiled/node_bindings/plonk_wasm.cjs'; +import { + fieldFromRust, + fieldToRust, + fieldsFromRustFlat, + fieldsToRustFlat, +} from './conversion-base.js'; +import { ConversionCore, ConversionCores, mapToUint32Array, unwrap } from './conversion-core.js'; import type { + Field, + LookupCommitments, + LookupTable, + OpeningProof, OrInfinity, PointEvaluations, PolyComm, - ProverProof, - ProofWithPublic, ProofEvaluations, + ProofWithPublic, ProverCommitments, - OpeningProof, + ProverProof, RecursionChallenge, - LookupCommitments, RuntimeTable, RuntimeTableCfg, - LookupTable, - Field, } from './kimchi-types.js'; -import { MlArray, MlOption, MlTuple } from '../../../lib/ml/base.js'; -import { - fieldToRust, - fieldFromRust, - fieldsToRustFlat, - fieldsFromRustFlat, -} from './conversion-base.js'; -import { ConversionCore, ConversionCores, mapToUint32Array, unwrap } from './conversion-core.js'; export { proofConversion }; @@ -178,6 +178,7 @@ function proofConversionPerField( } function runtimeTableToRust([, id, data]: RuntimeTable): WasmRuntimeTable { + console.log('old runtime table to rust!'); return new RuntimeTable(id, core.vectorToRust(data)); } diff --git a/src/bindings/crypto/bindings/conversion-verifier-index.ts b/src/bindings/crypto/bindings/conversion-verifier-index.ts index ac4cb71821..a5353a1316 100644 --- a/src/bindings/crypto/bindings/conversion-verifier-index.ts +++ b/src/bindings/crypto/bindings/conversion-verifier-index.ts @@ -1,3 +1,5 @@ +import { MlArray, MlBool, MlOption } from '../../../lib/ml/base.js'; +import type * as wasmNamespace from '../../compiled/node_bindings/plonk_wasm.cjs'; import type { WasmFpDomain, WasmFpLookupSelectors, @@ -13,11 +15,9 @@ import type { WasmFqShifts, LookupInfo as WasmLookupInfo, } from '../../compiled/node_bindings/plonk_wasm.cjs'; -import type * as wasmNamespace from '../../compiled/node_bindings/plonk_wasm.cjs'; -import { MlBool, MlArray, MlOption } from '../../../lib/ml/base.js'; -import { Field, VerifierIndex, Domain, VerificationEvals, PolyComm } from './kimchi-types.js'; import { fieldFromRust, fieldToRust } from './conversion-base.js'; import { ConversionCore, ConversionCores, freeOnFinalize } from './conversion-core.js'; +import { Domain, Field, PolyComm, VerificationEvals, VerifierIndex } from './kimchi-types.js'; import { Lookup, LookupInfo, LookupSelectors } from './lookup.js'; export { verifierIndexConversion }; diff --git a/src/bindings/crypto/bindings/gate-vector-napi.unit-test.ts b/src/bindings/crypto/bindings/gate-vector-napi.unit-test.ts new file mode 100644 index 0000000000..9b85604c4e --- /dev/null +++ b/src/bindings/crypto/bindings/gate-vector-napi.unit-test.ts @@ -0,0 +1,84 @@ +import { expect } from 'expect'; +import { createRequire } from 'node:module'; +import { napiConversionCore } from '../napi-conversion-core.js'; +import type { Field, Gate, Wire } from './kimchi-types.js'; + +const require = createRequire(import.meta.url); + +function loadNative() { + const slug = `${process.platform}-${process.arch}`; + const candidates = [ + `../../../../../native/${slug}/plonk_napi.node`, + '../../compiled/node_bindings/plonk_napi.node', + '../../compiled/_node_bindings/plonk_napi.node', + ]; + for (const path of candidates) { + try { + // eslint-disable-next-line @typescript-eslint/no-var-requires + return require(path); + } catch (err) { + if ((err as any).code !== 'MODULE_NOT_FOUND') throw err; + } + } + throw new Error('plonk_napi.node not found in compiled bindings'); +} + +const native: any = loadNative(); + +const gateVectorCreate = + native.caml_pasta_fp_plonk_gate_vector_create ?? native.camlPastaFpPlonkGateVectorCreate; +const gateVectorLen = + native.caml_pasta_fp_plonk_gate_vector_len ?? native.camlPastaFpPlonkGateVectorLen; +const gateVectorAdd = + native.caml_pasta_fp_plonk_gate_vector_add ?? native.camlPastaFpPlonkGateVectorAdd; +const gateVectorGet = + native.caml_pasta_fp_plonk_gate_vector_get ?? native.camlPastaFpPlonkGateVectorGet; +const gateVectorWrap = + native.caml_pasta_fp_plonk_gate_vector_wrap ?? native.camlPastaFpPlonkGateVectorWrap; +const gateVectorDigest = + native.caml_pasta_fp_plonk_gate_vector_digest ?? native.camlPastaFpPlonkGateVectorDigest; +const circuitSerialize = + native.caml_pasta_fp_plonk_circuit_serialize ?? native.camlPastaFpPlonkCircuitSerialize; + +const { fp } = napiConversionCore(native); + +const zeroField: Field = [0, 0n]; +const mlWire = (row: number, col: number): Wire => [0, row, col]; + +const sampleGate: Gate = [ + 0, + 1, + [ + 0, + mlWire(0, 0), + mlWire(0, 1), + mlWire(0, 2), + mlWire(0, 3), + mlWire(0, 4), + mlWire(0, 5), + mlWire(0, 6), + ], + [0, zeroField, zeroField, zeroField, zeroField, zeroField, zeroField, zeroField], +]; + +const vector = gateVectorCreate(); +expect(gateVectorLen(vector)).toBe(0); + +gateVectorAdd(vector, fp.gateToRust(sampleGate)); +expect(gateVectorLen(vector)).toBe(1); + +const gate0 = gateVectorGet(vector, 0); +expect(gate0.typ).toBe(sampleGate[1]); + +const rustTarget = fp.wireToRust(mlWire(0, 0)); +const rustHead = fp.wireToRust(mlWire(1, 2)); +gateVectorWrap(vector, rustTarget, rustHead); +const wrapped = gateVectorGet(vector, 0); +expect(wrapped.wires.w0).toEqual({ row: 1, col: 2 }); + +gateVectorDigest(0, vector); +circuitSerialize(0, vector); + +console.log('{}', gateVectorDigest(0, vector)); + +console.log('gate vector napi bindings (fp) are working ✔️'); diff --git a/src/bindings/crypto/bindings/napi-conversion-oracles.ts b/src/bindings/crypto/bindings/napi-conversion-oracles.ts new file mode 100644 index 0000000000..13bcb42f96 --- /dev/null +++ b/src/bindings/crypto/bindings/napi-conversion-oracles.ts @@ -0,0 +1,123 @@ +import { MlOption } from '../../../lib/ml/base.js'; +import type * as napiNamespace from '../../compiled/node_bindings/plonk_wasm.cjs'; +import type { + WasmFpOracles, + WasmFpRandomOracles, + WasmFqOracles, + WasmFqRandomOracles, +} from '../../compiled/node_bindings/plonk_wasm.cjs'; +import { + fieldFromRust, + fieldToRust, + fieldsFromRustFlat, + fieldsToRustFlat, + maybeFieldToRust, +} from './conversion-base.js'; +import { Field, Oracles, RandomOracles, ScalarChallenge } from './kimchi-types.js'; + +export { napiOraclesConversion }; + +type napi = typeof napiNamespace; + +type NapiRandomOracles = WasmFpRandomOracles | WasmFqRandomOracles; +type NapiOracles = WasmFpOracles | WasmFqOracles; + +type NapiClasses = { + RandomOracles: typeof WasmFpRandomOracles | typeof WasmFqRandomOracles; + Oracles: typeof WasmFpOracles | typeof WasmFqOracles; +}; + +function napiOraclesConversion(napi: napi) { + return { + fp: oraclesConversionPerField({ + RandomOracles: napi.WasmFpRandomOracles, + Oracles: napi.WasmFpOracles, + }), + fq: oraclesConversionPerField({ + RandomOracles: napi.WasmFqRandomOracles, + Oracles: napi.WasmFqOracles, + }), + }; +} + +function oraclesConversionPerField({ RandomOracles, Oracles }: NapiClasses) { + function randomOraclesToRust(ro: RandomOracles): NapiRandomOracles { + let jointCombinerMl = MlOption.from(ro[1]); + let jointCombinerChal = maybeFieldToRust(jointCombinerMl?.[1][1]); + let jointCombiner = maybeFieldToRust(jointCombinerMl?.[2]); + let beta = fieldToRust(ro[2]); + let gamma = fieldToRust(ro[3]); + let alphaChal = fieldToRust(ro[4][1]); + let alpha = fieldToRust(ro[5]); + let zeta = fieldToRust(ro[6]); + let v = fieldToRust(ro[7]); + let u = fieldToRust(ro[8]); + let zetaChal = fieldToRust(ro[9][1]); + let vChal = fieldToRust(ro[10][1]); + let uChal = fieldToRust(ro[11][1]); + return new RandomOracles( + jointCombinerChal, + jointCombiner, + beta, + gamma, + alphaChal, + alpha, + zeta, + v, + u, + zetaChal, + vChal, + uChal + ); + } + function randomOraclesFromRust(ro: NapiRandomOracles): RandomOracles { + let jointCombinerChal = ro.joint_combiner_chal; + let jointCombiner = ro.joint_combiner; + let jointCombinerOption = MlOption<[0, ScalarChallenge, Field]>( + jointCombinerChal && + jointCombiner && [0, [0, fieldFromRust(jointCombinerChal)], fieldFromRust(jointCombiner)] + ); + let mlRo: RandomOracles = [ + 0, + jointCombinerOption, + fieldFromRust(ro.beta), + fieldFromRust(ro.gamma), + [0, fieldFromRust(ro.alpha_chal)], + fieldFromRust(ro.alpha), + fieldFromRust(ro.zeta), + fieldFromRust(ro.v), + fieldFromRust(ro.u), + [0, fieldFromRust(ro.zeta_chal)], + [0, fieldFromRust(ro.v_chal)], + [0, fieldFromRust(ro.u_chal)], + ]; + // TODO: do we not want to free? + // ro.free(); + return mlRo; + } + + return { + oraclesToRust(oracles: Oracles): NapiOracles { + let [, o, pEval, openingPrechallenges, digestBeforeEvaluations] = oracles; + return new Oracles( + randomOraclesToRust(o), + fieldToRust(pEval[1]), + fieldToRust(pEval[2]), + fieldsToRustFlat(openingPrechallenges), + fieldToRust(digestBeforeEvaluations) + ); + }, + oraclesFromRust(oracles: NapiOracles): Oracles { + let mlOracles: Oracles = [ + 0, + randomOraclesFromRust(oracles.o), + [0, fieldFromRust(oracles.p_eval0), fieldFromRust(oracles.p_eval1)], + fieldsFromRustFlat(oracles.opening_prechallenges), + fieldFromRust(oracles.digest_before_evaluations), + ]; + // TODO: do we not want to free? + // oracles.free(); + return mlOracles; + }, + }; +} diff --git a/src/bindings/crypto/bindings/srs.ts b/src/bindings/crypto/bindings/srs.ts index 0354fa6217..3c8e9fef4b 100644 --- a/src/bindings/crypto/bindings/srs.ts +++ b/src/bindings/crypto/bindings/srs.ts @@ -1,18 +1,18 @@ -import type { Wasm, RustConversion } from '../bindings.js'; -import { type WasmFpSrs, type WasmFqSrs } from '../../compiled/node_bindings/plonk_wasm.cjs'; -import { PolyComm } from './kimchi-types.js'; +import { MlArray } from '../../../lib/ml/base.js'; import { - type CacheHeader, - type Cache, + readCache, withVersion, writeCache, - readCache, + type Cache, + type CacheHeader, } from '../../../lib/proof-system/cache.js'; import { assert } from '../../../lib/util/errors.js'; -import { MlArray } from '../../../lib/ml/base.js'; +import { type WasmFpSrs, type WasmFqSrs } from '../../compiled/node_bindings/plonk_wasm.cjs'; +import type { RustConversion, Wasm } from '../bindings.js'; import { OrInfinity, OrInfinityJson } from './curve.js'; +import { PolyComm } from './kimchi-types.js'; -export { srs, setSrsCache, unsetSrsCache }; +export { setSrsCache, srs, unsetSrsCache }; type WasmSrs = WasmFpSrs | WasmFqSrs; @@ -71,20 +71,117 @@ function srs(wasm: Wasm, conversion: RustConversion) { function srsPerField(f: 'fp' | 'fq', wasm: Wasm, conversion: RustConversion) { // note: these functions are properly typed, thanks to TS template literal types - let createSrs = (s: number) => wasm[`caml_${f}_srs_create_parallel`](s); - let getSrs = wasm[`caml_${f}_srs_get`]; - let setSrs = wasm[`caml_${f}_srs_set`]; + let createSrs = (size: number) => { + try { + console.log(0); + return wasm[`caml_${f}_srs_create_parallel`](size); + } catch (error) { + console.error(`Error in SRS get for field ${f}`); + throw error; + } + }; + let getSrs = (srs: WasmSrs) => { + try { + console.log(1); + let v = wasm[`caml_${f}_srs_get`](srs); + console.log(2); + return v; + } catch (error) { + console.error(`Error in SRS get for field ${f}`); + throw error; + } + }; + let setSrs = (bytes: any) => { + try { + console.log(2); + return wasm[`caml_${f}_srs_set`](bytes); + } catch (error) { + console.error(`Error in SRS set for field ${f} args ${bytes}`); + throw error; + } + }; + + let maybeLagrangeCommitment = (srs: WasmSrs, domain_size: number, i: number) => { + try { + console.log(3); + console.log('srs wasm', srs); + let bytes = (wasm as any)[`caml_${f}_srs_to_bytes_external`](srs); + console.log('bytes', bytes); + let wasmSrs = undefined; + if (f === 'fp') wasmSrs = wasm.WasmFpSrs.deserialize(bytes); + else wasmSrs = wasm.WasmFqSrs.deserialize(bytes); + let s = wasm[`caml_${f}_srs_maybe_lagrange_commitment`](wasmSrs, domain_size, i); + console.log('S', s); + return s; + } catch (error) { + console.error(`Error in SRS maybe lagrange commitment for field ${f}`); + throw error; + } + }; + let lagrangeCommitment = (srs: WasmSrs, domain_size: number, i: number) => { + try { + console.log(4); + console.log('srs', srs); + let bytes = (wasm as any)[`caml_${f}_srs_to_bytes_external`](srs); + console.log('bytes', bytes); + let wasmSrs = undefined; + if (f === 'fp') wasmSrs = wasm.WasmFpSrs.deserialize(bytes); + else wasmSrs = wasm.WasmFqSrs.deserialize(bytes); + return wasm[`caml_${f}_srs_lagrange_commitment`](wasmSrs, domain_size, i); + } catch (error) { + console.error(`Error in SRS lagrange commitment for field ${f}`); + throw error; + } + }; + let lagrangeCommitmentsWholeDomainPtr = (srs: WasmSrs, domain_size: number) => { + try { + console.log(5); + console.log('srs', srs); + let bytes = (wasm as any)[`caml_${f}_srs_to_bytes_external`](srs); + console.log('bytes', bytes); + let wasmSrs = undefined; + if (f === 'fp') wasmSrs = wasm.WasmFpSrs.deserialize(bytes); + else wasmSrs = wasm.WasmFqSrs.deserialize(bytes); + return wasm[`caml_${f}_srs_lagrange_commitments_whole_domain_ptr`](wasmSrs, domain_size); + } catch (error) { + console.error(`Error in SRS lagrange commitments whole domain ptr for field ${f}`); + throw error; + } + }; + let setLagrangeBasis = (srs: WasmSrs, domain_size: number, input: any) => { + try { + console.log(6); + return wasm[`caml_${f}_srs_set_lagrange_basis`](srs, domain_size, input); + } catch (error) { + console.error(`Error in SRS set lagrange basis for field ${f}`); + throw error; + } + }; + let getLagrangeBasis = (srs: WasmSrs, n: number) => { + try { + console.log(7); + console.log('srs', srs); + let bytes = (wasm as any)[`caml_${f}_srs_to_bytes_external`](srs); + console.log('bytes', bytes); + let wasmSrs = undefined; + if (f === 'fp') wasmSrs = wasm.WasmFpSrs.deserialize(bytes); + else wasmSrs = wasm.WasmFqSrs.deserialize(bytes); + return wasm[`caml_${f}_srs_get_lagrange_basis`](wasmSrs, n); + } catch (error) { + console.error(`Error in SRS get lagrange basis for field ${f}`); + throw error; + } + }; + let getCommitmentsWholeDomainByPtr = (ptr: number) => { + try { + console.log(8); + return wasm[`caml_${f}_srs_lagrange_commitments_whole_domain_read_from_ptr`](ptr); + } catch (error) { + console.error(`Error in SRS get commitments whole domain by ptr for field ${f}`); + throw error; + } + }; - let maybeLagrangeCommitment = wasm[`caml_${f}_srs_maybe_lagrange_commitment`]; - let lagrangeCommitment = (srs: WasmFpSrs, domain_size: number, i: number) => - wasm[`caml_${f}_srs_lagrange_commitment`](srs, domain_size, i); - let lagrangeCommitmentsWholeDomainPtr = (srs: WasmSrs, domain_size: number) => - wasm[`caml_${f}_srs_lagrange_commitments_whole_domain_ptr`](srs, domain_size); - let setLagrangeBasis = wasm[`caml_${f}_srs_set_lagrange_basis`]; - let getLagrangeBasis = (srs: WasmSrs, n: number) => - wasm[`caml_${f}_srs_get_lagrange_basis`](srs, n); - let getCommitmentsWholeDomainByPtr = - wasm[`caml_${f}_srs_lagrange_commitments_whole_domain_read_from_ptr`]; return { /** * returns existing stored SRS or falls back to creating a new one @@ -95,11 +192,14 @@ function srsPerField(f: 'fp' | 'fq', wasm: Wasm, conversion: RustConversion) { if (srs === undefined) { if (cache === undefined) { // if there is no cache, create SRS in memory + console.log('Creating SRS without cache'); srs = createSrs(size); + console.log('SRS created without cache:', srs); } else { let header = cacheHeaderSrs(f, size); // try to read SRS from cache / recompute and write if not found + console.log('Reading SRS from cache'); srs = readCache(cache, header, (bytes) => { // TODO: this takes a bit too long, about 300ms for 2^16 // `pointsToRust` is the clear bottleneck @@ -108,13 +208,17 @@ function srsPerField(f: 'fp' | 'fq', wasm: Wasm, conversion: RustConversion) { let wasmSrs = conversion[f].pointsToRust(mlSrs); return setSrs(wasmSrs); }); - + console.log('SRS read from cache:', srs); if (srs === undefined) { // not in cache + console.log(1); srs = createSrs(size); + console.log('Writing SRS to cache', srs); if (cache.canWrite) { + console.log(2); let wasmSrs = getSrs(srs); + console.log(3); let mlSrs = conversion[f].pointsFromRust(wasmSrs); let jsonSrs = MlArray.mapFrom(mlSrs, OrInfinity.toJSON); let bytes = new TextEncoder().encode(JSON.stringify(jsonSrs)); @@ -123,11 +227,13 @@ function srsPerField(f: 'fp' | 'fq', wasm: Wasm, conversion: RustConversion) { } } } - + console.log('Storing SRS in memory'); srsStore[f][size] = srs; + console.log('SRS stored in memory:', srs); } // TODO should we call freeOnFinalize() and expose a function to clean the SRS cache? + console.trace('Returning SRS:', srs); return srsStore[f][size]; }, @@ -135,6 +241,7 @@ function srsPerField(f: 'fp' | 'fq', wasm: Wasm, conversion: RustConversion) { * returns ith Lagrange basis commitment for a given domain size */ lagrangeCommitment(srs: WasmSrs, domainSize: number, i: number): PolyComm { + console.log('lagrangeCommitment'); // happy, fast case: if basis is already stored on the srs, return the ith commitment let commitment = maybeLagrangeCommitment(srs, domainSize, i); @@ -160,7 +267,9 @@ function srsPerField(f: 'fp' | 'fq', wasm: Wasm, conversion: RustConversion) { // TODO: this code path will throw on the web since `caml_${f}_srs_get_lagrange_basis` is not properly implemented // using a writable cache in the browser seems to be fairly uncommon though, so it's at least an 80/20 solution let wasmComms = getLagrangeBasis(srs, domainSize); + console.log('wasmComms', wasmComms); let mlComms = conversion[f].polyCommsFromRust(wasmComms); + console.log('mlComms', mlComms); let comms = polyCommsToJSON(mlComms); let bytes = new TextEncoder().encode(JSON.stringify(comms)); writeCache(cache, header, bytes); @@ -208,6 +317,8 @@ function srsPerField(f: 'fp' | 'fq', wasm: Wasm, conversion: RustConversion) { * Returns the Lagrange basis commitments for the whole domain */ lagrangeCommitmentsWholeDomain(srs: WasmSrs, domainSize: number) { + console.log('lagrangeCommitmentsWholeDomain'); + // instead of getting the entire commitment directly (which works for nodejs/servers), we get a pointer to the commitment // and then read the commitment from the pointer // this is because the web worker implementation currently does not support returning UintXArray's directly @@ -224,6 +335,7 @@ function srsPerField(f: 'fp' | 'fq', wasm: Wasm, conversion: RustConversion) { * adds Lagrange basis for a given domain size */ addLagrangeBasis(srs: WasmSrs, logSize: number) { + console.log('addLagrangeBasis'); // this ensures that basis is stored on the srs, no need to duplicate caching logic this.lagrangeCommitment(srs, 1 << logSize, 0); }, @@ -270,3 +382,13 @@ function readCacheLazy( return true; }); } +function runInTryCatch any>(fn: T): T { + return function (...args: Parameters): ReturnType { + try { + return fn(...args); + } catch (e) { + console.error(`Error in SRS function ${fn.name} with args:`, args); + throw e; + } + } as T; +} diff --git a/src/bindings/crypto/napi-conversion-core.ts b/src/bindings/crypto/napi-conversion-core.ts new file mode 100644 index 0000000000..8e5c1e3a55 --- /dev/null +++ b/src/bindings/crypto/napi-conversion-core.ts @@ -0,0 +1,227 @@ +import { MlArray } from '../../lib/ml/base.js'; +import type * as napiNamespace from '../compiled/node_bindings/plonk_wasm.cjs'; +import { + fieldFromRust, + fieldToRust, + fieldsFromRustFlat, + fieldsToRustFlat, +} from './bindings/conversion-base.js'; +import { Field, Gate, LookupTable, OrInfinity, PolyComm, Wire } from './bindings/kimchi-types.js'; +import { mapTuple } from './bindings/util.js'; + +export { ConversionCore, ConversionCores, napiConversionCore }; + +type ConversionCore = ReturnType; +type ConversionCores = ReturnType; + +type NapiAffine = napiNamespace.WasmGVesta | napiNamespace.WasmGPallas; +type NapiPolyComm = { unshifted: unknown; shifted?: NapiAffine | undefined }; +type PolyCommCtor = new (unshifted: unknown, shifted?: NapiAffine | undefined) => NapiPolyComm; + +type NapiClasses = { + CommitmentCurve: typeof napiNamespace.WasmGVesta | typeof napiNamespace.WasmGPallas; + makeAffine: () => NapiAffine; + PolyComm: napiNamespace.WasmFpPolyComm | napiNamespace.WasmFqPolyComm; +}; + +function napiConversionCore(napi: any) { + const fpCore = conversionCorePerField({ + CommitmentCurve: napi.WasmGVesta, + makeAffine: napi.caml_vesta_affine_one, + PolyComm: napi.WasmFpPolyComm, + }); + const fqCore = conversionCorePerField({ + CommitmentCurve: napi.WasmGPallas, + makeAffine: napi.caml_pallas_affine_one, + PolyComm: napi.WasmFqPolyComm, + }); + + const shared = { + vectorToRust: (fields: any) => fieldsToRustFlat(fields), + vectorFromRust: fieldsFromRustFlat, + wireToRust([, row, col]: Wire) { + return { row, col }; + }, + lookupTablesToRust([, ...tables]: MlArray) { + return tables; + }, + runtimeTableCfgsToRust([, ...tables]: MlArray) { + return tables.map((table) => Array.from(table)); + }, + gateToRust(gate: Gate): any { + const [, typ, [, ...wires], coeffs] = gate; + const mapped = mapTuple(wires, (wire) => this.wireToRust(wire)); + const nativeWires = { + w0: mapped[0], + w1: mapped[1], + w2: mapped[2], + w3: mapped[3], + w4: mapped[4], + w5: mapped[5], + w6: mapped[6], + } as const; + return { + typ, + wires: nativeWires, + coeffs: Array.from(fieldsToRustFlat(coeffs)), + }; + }, + }; + + return { + fp: { + ...fpCore, + }, + fq: { + ...fqCore, + }, + ...shared, + }; +} + +function conversionCorePerField({ makeAffine, PolyComm }: NapiClasses) { + const vectorToRust = (fields: MlArray) => fieldsToRustFlat(fields); + const vectorFromRust = fieldsFromRustFlat; + + const wireToRust = ([, row, col]: Wire) => ({ row, col }); + const wireFromRust = ({ row, col }: { row: number; col: number }): Wire => [0, row, col]; + + const gateToRust = (gate: Gate) => { + const [, typ, [, ...wires], coeffs] = gate; + const mapped = mapTuple(wires, wireToRust); + const nativeWires = { + w0: mapped[0], + w1: mapped[1], + w2: mapped[2], + w3: mapped[3], + w4: mapped[4], + w5: mapped[5], + w6: mapped[6], + } as const; + return { + typ, + wires: nativeWires, + coeffs: Array.from(fieldsToRustFlat(coeffs)), + }; + }; + + const gateFromRust = (gate: { + typ: number; + wires: { + w0: { row: number; col: number }; + w1: { row: number; col: number }; + w2: { row: number; col: number }; + w3: { row: number; col: number }; + w4: { row: number; col: number }; + w5: { row: number; col: number }; + w6: { row: number; col: number }; + }; + coeffs: Uint8Array | number[]; + }): Gate => { + const { w0, w1, w2, w3, w4, w5, w6 } = gate.wires; + const wiresTuple: [0, Wire, Wire, Wire, Wire, Wire, Wire, Wire] = [ + 0, + wireFromRust(w0), + wireFromRust(w1), + wireFromRust(w2), + wireFromRust(w3), + wireFromRust(w4), + wireFromRust(w5), + wireFromRust(w6), + ]; + const coeffBytes = + gate.coeffs instanceof Uint8Array ? gate.coeffs : Uint8Array.from(gate.coeffs); + const coeffs = fieldsFromRustFlat(coeffBytes); + return [0, gate.typ, wiresTuple, coeffs]; + }; + + const affineToRust = (pt: OrInfinity): NapiAffine => { + function isFinitePoint(point: OrInfinity): point is [0, [0, Field, Field]] { + return Array.isArray(point); + } + let res = makeAffine(); + if (!isFinitePoint(pt)) { + res.infinity = true; + } else { + const tmpBytes = new Uint8Array(32); + const [, pair] = pt; + const [, x, y] = pair; + res.x = fieldToRust(x, tmpBytes); + res.y = fieldToRust(y, tmpBytes); + } + return res; + }; + const affineFromRust = (pt: NapiAffine): OrInfinity => { + if (pt.infinity) return 0; + // console.log('pt', pt); + // console.log('pt.x', pt.x); + // console.log('pt.y', pt.y); + + const xField = fieldFromRust(pt.x); + const yField = fieldFromRust(pt.y); + return [0, [0, xField, yField]]; + }; + + const pointToRust = (point: OrInfinity): NapiAffine => affineToRust(point); + const pointFromRust = (point: NapiAffine): OrInfinity => affineFromRust(point); + + const pointsToRust = ([, ...points]: MlArray): NapiAffine[] => + points.map(affineToRust); + const pointsFromRust = (points: NapiAffine[]): MlArray => [ + 0, + ...points.map(affineFromRust), + ]; + + const polyCommToRust = (polyComm: PolyComm): NapiPolyComm => { + const [, camlElems] = polyComm; + const unshifted = pointsToRust(camlElems); + const PolyCommClass = PolyComm as unknown as PolyCommCtor; + return new PolyCommClass(unshifted as unknown, undefined); + }; + + const polyCommFromRust = (polyComm: any): any => { + if (polyComm == null) return undefined; + // console.log('polyComm', polyComm); + const rustUnshifted = asArrayLike(polyComm.unshifted, 'polyComm.unshifted'); + // console.log('rustUnshifted', rustUnshifted); + const mlUnshifted = rustUnshifted.map(affineFromRust); + return [0, [0, ...mlUnshifted]]; + }; + + const polyCommsToRust = ([, ...comms]: MlArray): NapiPolyComm[] => + comms.map(polyCommToRust); + + const polyCommsFromRust = (rustComms: unknown): MlArray => { + const comms = asArrayLike(rustComms, 'polyCommsFromRust'); + return [0, ...comms.map(polyCommFromRust)]; + }; + + return { + vectorToRust, + vectorFromRust, + wireToRust, + gateToRust, + gateFromRust, + affineToRust, + affineFromRust, + pointToRust, + pointFromRust, + pointsToRust, + pointsFromRust, + polyCommToRust, + polyCommFromRust, + polyCommsToRust, + polyCommsFromRust, + }; +} + +function asArrayLike(value: unknown, context: string): T[] { + if (value == null) return []; + if (Array.isArray(value)) return value as T[]; + if (ArrayBuffer.isView(value)) return Array.from(value as unknown as ArrayLike); + if (typeof value === 'object' && value !== null && 'length' in (value as { length: unknown })) { + const { length } = value as { length: unknown }; + if (typeof length === 'number') return Array.from(value as ArrayLike); + } + throw Error(`${context}: expected array-like native values`); +} diff --git a/src/bindings/crypto/napi-conversion-proof.ts b/src/bindings/crypto/napi-conversion-proof.ts new file mode 100644 index 0000000000..789aafb6ed --- /dev/null +++ b/src/bindings/crypto/napi-conversion-proof.ts @@ -0,0 +1,351 @@ +import { MlArray, MlOption, MlTuple } from '../../lib/ml/base.js'; +import type * as napiNamespace from '../compiled/node_bindings/plonk_wasm.cjs'; +import type { + WasmFpLookupCommitments, + WasmFpOpeningProof, + WasmFpProverCommitments, + WasmFpProverProof, + WasmFpRuntimeTable, + WasmFqLookupCommitments, + WasmFqOpeningProof, + WasmFqProverCommitments, + WasmFqProverProof, + WasmFqRuntimeTable, + WasmPastaFpLookupTable, + WasmPastaFpRuntimeTableCfg, + WasmPastaFqLookupTable, + WasmPastaFqRuntimeTableCfg, + WasmVecVecFp, + WasmVecVecFq, +} from '../compiled/node_bindings/plonk_wasm.cjs'; +import { + fieldFromRust, + fieldToRust, + fieldsFromRustFlat, + fieldsToRustFlat, +} from './bindings/conversion-base.js'; +import type { Field } from './bindings/field.js'; +import type { + LookupCommitments, + LookupTable, + OpeningProof, + OrInfinity, + PointEvaluations, + PolyComm, + ProofEvaluations, + ProofWithPublic, + ProverCommitments, + ProverProof, + RecursionChallenge, + RuntimeTable, + RuntimeTableCfg, +} from './bindings/kimchi-types.js'; +import { ConversionCore, ConversionCores } from './napi-conversion-core.js'; + +export { napiProofConversion }; + +const fieldToRust_ = (x: Field) => fieldToRust(x); +const proofEvaluationsToRust = mapProofEvaluations(fieldToRust_); +const proofEvaluationsFromRust = mapProofEvaluations(fieldFromRust); +const pointEvalsOptionToRust = mapPointEvalsOption(fieldToRust_); +const pointEvalsOptionFromRust = mapPointEvalsOption(fieldFromRust); + +type NapiProofEvaluations = [ + 0, + MlOption>, + ...RemoveLeadingZero>, +]; + +type napi = typeof napiNamespace; + +type NapiProverCommitments = WasmFpProverCommitments | WasmFqProverCommitments; +type NapiOpeningProof = WasmFpOpeningProof | WasmFqOpeningProof; +type NapiProverProof = WasmFpProverProof | WasmFqProverProof; +type NapiLookupCommitments = WasmFpLookupCommitments | WasmFqLookupCommitments; +type NapiRuntimeTable = WasmFpRuntimeTable | WasmFqRuntimeTable; +type NapiRuntimeTableCfg = WasmPastaFpRuntimeTableCfg | WasmPastaFqRuntimeTableCfg; +type NapiLookupTable = WasmPastaFpLookupTable | WasmPastaFqLookupTable; + +type NapiClasses = { + ProverCommitments: typeof WasmFpProverCommitments | typeof WasmFqProverCommitments; + OpeningProof: typeof WasmFpOpeningProof | typeof WasmFqOpeningProof; + VecVec: typeof WasmVecVecFp | typeof WasmVecVecFq; + ProverProof: typeof WasmFpProverProof | typeof WasmFqProverProof; + LookupCommitments: typeof WasmFpLookupCommitments | typeof WasmFqLookupCommitments; + RuntimeTable: typeof WasmFpRuntimeTable | typeof WasmFqRuntimeTable; + RuntimeTableCfg: typeof WasmPastaFpRuntimeTableCfg | typeof WasmPastaFqRuntimeTableCfg; + LookupTable: typeof WasmPastaFpLookupTable | typeof WasmPastaFqLookupTable; +}; + +function napiProofConversion(napi: napi, core: ConversionCores) { + return { + fp: proofConversionPerField(core.fp, { + ProverCommitments: napi.WasmFpProverCommitments, + OpeningProof: napi.WasmFpOpeningProof, + VecVec: napi.WasmVecVecFp, + ProverProof: napi.WasmFpProverProof, + LookupCommitments: napi.WasmFpLookupCommitments, + RuntimeTable: napi.WasmFpRuntimeTable, + RuntimeTableCfg: napi.WasmPastaFpRuntimeTableCfg, + LookupTable: napi.WasmPastaFpLookupTable, + }), + fq: proofConversionPerField(core.fq, { + ProverCommitments: napi.WasmFqProverCommitments, + OpeningProof: napi.WasmFqOpeningProof, + VecVec: napi.WasmVecVecFq, + ProverProof: napi.WasmFqProverProof, + LookupCommitments: napi.WasmFqLookupCommitments, + RuntimeTable: napi.WasmFqRuntimeTable, + RuntimeTableCfg: napi.WasmPastaFqRuntimeTableCfg, + LookupTable: napi.WasmPastaFqLookupTable, + }), + }; +} + +function proofConversionPerField( + core: ConversionCore, + { + ProverCommitments, + OpeningProof, + VecVec, + ProverProof, + LookupCommitments, + RuntimeTable, + RuntimeTableCfg, + LookupTable, + }: NapiClasses +) { + function commitmentsToRust(commitments: ProverCommitments): NapiProverCommitments { + let wComm = core.polyCommsToRust(commitments[1]); + let zComm = core.polyCommToRust(commitments[2]); + let tComm = core.polyCommToRust(commitments[3]); + let lookup = MlOption.mapFrom(commitments[4], lookupCommitmentsToRust); + return new ProverCommitments(wComm as any, zComm as any, tComm as any, lookup as any); + } + function commitmentsFromRust(commitments: NapiProverCommitments): ProverCommitments { + let wComm = core.polyCommsFromRust(commitments.w_comm); + let zComm = core.polyCommFromRust(commitments.z_comm); + let tComm = core.polyCommFromRust(commitments.t_comm); + let lookup = MlOption.mapTo(commitments.lookup, lookupCommitmentsFromRust); + commitments.free(); + return [0, wComm as MlTuple, zComm, tComm, lookup]; + } + + function lookupCommitmentsToRust(lookup: LookupCommitments): NapiLookupCommitments { + let sorted = core.polyCommsToRust(lookup[1]); + let aggreg = core.polyCommToRust(lookup[2]); + let runtime = MlOption.mapFrom(lookup[3], core.polyCommToRust); + return new LookupCommitments(sorted as any, aggreg as any, runtime as any); + } + function lookupCommitmentsFromRust(lookup: NapiLookupCommitments): LookupCommitments { + let sorted = core.polyCommsFromRust(lookup.sorted); + let aggreg = core.polyCommFromRust(lookup.aggreg); + let runtime = MlOption.mapTo(lookup.runtime, core.polyCommFromRust); + lookup.free(); + return [0, sorted, aggreg, runtime]; + } + + function openingProofToRust(proof: OpeningProof): NapiOpeningProof { + let [_, [, ...lr], delta, z1, z2, sg] = proof; + // We pass l and r as separate vectors over the FFI + let l: MlArray = [0]; + let r: MlArray = [0]; + for (let [, li, ri] of lr) { + l.push(li); + r.push(ri); + } + return new OpeningProof( + core.pointsToRust(l) as any, + core.pointsToRust(r) as any, + core.pointToRust(delta), + fieldToRust(z1), + fieldToRust(z2), + core.pointToRust(sg) + ); + } + function openingProofFromRust(proof: any): OpeningProof { + let [, ...l] = core.pointsFromRust(proof.lr_0); + let [, ...r] = core.pointsFromRust(proof.lr_1); + let n = l.length; + if (n !== r.length) throw Error('openingProofFromRust: l and r length mismatch.'); + let lr = l.map<[0, OrInfinity, OrInfinity]>((li, i) => [0, li, r[i]]); + let delta = core.pointFromRust(proof.delta); + let z1 = fieldFromRust(proof.z1); + let z2 = fieldFromRust(proof.z2); + let sg = core.pointFromRust(proof.sg); + proof.free(); + return [0, [0, ...lr], delta, z1, z2, sg]; + } + + function runtimeTableToRust([, id, data]: RuntimeTable): NapiRuntimeTable { + console.log('runtime table'); + return new RuntimeTable(id, core.vectorToRust(data)); + } + + function runtimeTableCfgToRust([, id, firstColumn]: RuntimeTableCfg): NapiRuntimeTableCfg { + return new RuntimeTableCfg(id, core.vectorToRust(firstColumn)); + } + + function lookupTableToRust([, id, [, ...data]]: LookupTable): NapiLookupTable { + let n = data.length; + let wasmData = new VecVec(n); + for (let i = 0; i < n; i++) { + wasmData.push(fieldsToRustFlat(data[i])); + } + return new LookupTable(id, wasmData); + } + + return { + proofToRust([, public_evals, proof]: ProofWithPublic): NapiProverProof { + let commitments = commitmentsToRust(proof[1]); + let openingProof = openingProofToRust(proof[2]); + let [, ...evals] = proofEvaluationsToRust(proof[3]); + let publicEvals = pointEvalsOptionToRust(public_evals); + // TODO typed as `any` in wasm-bindgen, this has the correct type + let evalsActual: NapiProofEvaluations = [0, publicEvals, ...evals]; + + let ftEval1 = fieldToRust(proof[4]); + let public_ = fieldsToRustFlat(proof[5]); + let [, ...prevChallenges] = proof[6]; + let n = prevChallenges.length; + let prevChallengeScalars = new VecVec(n); + let prevChallengeCommsMl: MlArray = [0]; + for (let [, scalars, comms] of prevChallenges) { + prevChallengeScalars.push(fieldsToRustFlat(scalars)); + prevChallengeCommsMl.push(comms); + } + let prevChallengeComms = core.polyCommsToRust(prevChallengeCommsMl); + return new ProverProof( + commitments, + openingProof, + evalsActual, + ftEval1, + public_, + prevChallengeScalars, + prevChallengeComms as any + ); + }, + proofFromRust(wasmProof: NapiProverProof): ProofWithPublic { + let commitments = commitmentsFromRust(wasmProof.commitments); + let openingProof = openingProofFromRust(wasmProof.proof); + // TODO typed as `any` in wasm-bindgen, this is the correct type + let [, wasmPublicEvals, ...wasmEvals]: NapiProofEvaluations = wasmProof.evals; + let publicEvals = pointEvalsOptionFromRust(wasmPublicEvals); + let evals = proofEvaluationsFromRust([0, ...wasmEvals]); + + let ftEval1 = fieldFromRust(wasmProof.ft_eval1); + let public_ = fieldsFromRustFlat(wasmProof.public_); + let prevChallengeScalars = wasmProof.prev_challenges_scalars; + let [, ...prevChallengeComms] = core.polyCommsFromRust(wasmProof.prev_challenges_comms); + let prevChallenges = prevChallengeComms.map((comms, i) => { + let scalars = fieldsFromRustFlat(prevChallengeScalars.get(i)); + return [0, scalars, comms]; + }); + let proof: ProverProof = [ + 0, + commitments, + openingProof, + evals, + ftEval1, + public_, + [0, ...prevChallenges], + ]; + return [0, publicEvals, proof]; + }, + + runtimeTablesToRust([, ...tables]: MlArray): NapiRuntimeTable[] { + return tables.map(runtimeTableToRust); + }, + + runtimeTableCfgsToRust([, ...tableCfgs]: MlArray): NapiRuntimeTableCfg[] { + return tableCfgs.map(runtimeTableCfgToRust); + }, + + lookupTablesToRust([, ...tables]: MlArray): NapiLookupTable[] { + return tables.map(lookupTableToRust); + }, + }; +} + +function createMapPointEvals(map: (x: Field1) => Field2) { + return (evals: PointEvaluations): PointEvaluations => { + let [, zeta, zeta_omega] = evals; + return [0, MlArray.map(zeta, map), MlArray.map(zeta_omega, map)]; + }; +} + +function mapPointEvalsOption(map: (x: Field1) => Field2) { + return (evals: MlOption>) => + MlOption.map(evals, createMapPointEvals(map)); +} + +function mapProofEvaluations(map: (x: Field1) => Field2) { + const mapPointEvals = createMapPointEvals(map); + + const mapPointEvalsOption = ( + evals: MlOption> + ): MlOption> => MlOption.map(evals, mapPointEvals); + + return function mapProofEvaluations(evals: ProofEvaluations): ProofEvaluations { + let [ + , + w, + z, + s, + coeffs, + genericSelector, + poseidonSelector, + completeAddSelector, + mulSelector, + emulSelector, + endomulScalarSelector, + rangeCheck0Selector, + rangeCheck1Selector, + foreignFieldAddSelector, + foreignFieldMulSelector, + xorSelector, + rotSelector, + lookupAggregation, + lookupTable, + lookupSorted, + runtimeLookupTable, + runtimeLookupTableSelector, + xorLookupSelector, + lookupGateLookupSelector, + rangeCheckLookupSelector, + foreignFieldMulLookupSelector, + ] = evals; + return [ + 0, + MlTuple.map(w, mapPointEvals), + mapPointEvals(z), + MlTuple.map(s, mapPointEvals), + MlTuple.map(coeffs, mapPointEvals), + mapPointEvals(genericSelector), + mapPointEvals(poseidonSelector), + mapPointEvals(completeAddSelector), + mapPointEvals(mulSelector), + mapPointEvals(emulSelector), + mapPointEvals(endomulScalarSelector), + mapPointEvalsOption(rangeCheck0Selector), + mapPointEvalsOption(rangeCheck1Selector), + mapPointEvalsOption(foreignFieldAddSelector), + mapPointEvalsOption(foreignFieldMulSelector), + mapPointEvalsOption(xorSelector), + mapPointEvalsOption(rotSelector), + mapPointEvalsOption(lookupAggregation), + mapPointEvalsOption(lookupTable), + MlArray.map(lookupSorted, mapPointEvalsOption), + mapPointEvalsOption(runtimeLookupTable), + mapPointEvalsOption(runtimeLookupTableSelector), + mapPointEvalsOption(xorLookupSelector), + mapPointEvalsOption(lookupGateLookupSelector), + mapPointEvalsOption(rangeCheckLookupSelector), + mapPointEvalsOption(foreignFieldMulLookupSelector), + ]; + }; +} + +// helper + +type RemoveLeadingZero = T extends [0, ...infer U] ? U : never; diff --git a/src/bindings/crypto/napi-conversion-verifier-index.ts b/src/bindings/crypto/napi-conversion-verifier-index.ts new file mode 100644 index 0000000000..443097305d --- /dev/null +++ b/src/bindings/crypto/napi-conversion-verifier-index.ts @@ -0,0 +1,287 @@ +import { MlArray, MlBool, MlOption } from '../../lib/ml/base.js'; +import type * as napiNamespace from '../compiled/node_bindings/plonk_wasm.cjs'; +import type { + WasmFpDomain, + WasmFpLookupSelectors, + WasmFpLookupVerifierIndex, + WasmFpPlonkVerificationEvals, + WasmFpPlonkVerifierIndex, + WasmFpShifts, + WasmFqDomain, + WasmFqLookupSelectors, + WasmFqLookupVerifierIndex, + WasmFqPlonkVerificationEvals, + WasmFqPlonkVerifierIndex, + WasmFqShifts, + LookupInfo as WasmLookupInfo, +} from '../compiled/node_bindings/plonk_wasm.cjs'; +import { fieldFromRust, fieldToRust } from './bindings/conversion-base.js'; +import { + Domain, + Field, + PolyComm, + VerificationEvals, + VerifierIndex, +} from './bindings/kimchi-types.js'; +import { ConversionCore, ConversionCores } from './napi-conversion-core.js'; +import { Lookup, LookupInfo, LookupSelectors } from './bindings/lookup.js'; + +export { napiVerifierIndexConversion }; + +type napi = typeof napiNamespace; + +type NapiDomain = WasmFpDomain | WasmFqDomain; +type NapiVerificationEvals = WasmFpPlonkVerificationEvals | WasmFqPlonkVerificationEvals; +type NapiShifts = WasmFpShifts | WasmFqShifts; +type NapiVerifierIndex = WasmFpPlonkVerifierIndex | WasmFqPlonkVerifierIndex; +type NapiLookupVerifierIndex = WasmFpLookupVerifierIndex | WasmFqLookupVerifierIndex; +type NapiLookupSelector = WasmFpLookupSelectors | WasmFqLookupSelectors; + +type NapiClasses = { + Domain: typeof WasmFpDomain | typeof WasmFqDomain; + VerificationEvals: typeof WasmFpPlonkVerificationEvals | typeof WasmFqPlonkVerificationEvals; + Shifts: typeof WasmFpShifts | typeof WasmFqShifts; + VerifierIndex: typeof WasmFpPlonkVerifierIndex | typeof WasmFqPlonkVerifierIndex; + LookupVerifierIndex: typeof WasmFpLookupVerifierIndex | typeof WasmFqLookupVerifierIndex; + LookupSelector: typeof WasmFpLookupSelectors | typeof WasmFqLookupSelectors; +}; + +function napiVerifierIndexConversion(napi: any, core: ConversionCores) { + return { + fp: verifierIndexConversionPerField(napi, core.fp, { + Domain: napi.WasmFpDomain, + VerificationEvals: napi.WasmFpPlonkVerificationEvals, + Shifts: napi.WasmFpShifts, + VerifierIndex: napi.WasmFpPlonkVerifierIndex, + LookupVerifierIndex: napi.WasmFpLookupVerifierIndex, + LookupSelector: napi.WasmFpLookupSelectors, + }), + fq: verifierIndexConversionPerField(napi, core.fq, { + Domain: napi.WasmFqDomain, + VerificationEvals: napi.WasmFqPlonkVerificationEvals, + Shifts: napi.WasmFqShifts, + VerifierIndex: napi.WasmFqPlonkVerifierIndex, + LookupVerifierIndex: napi.WasmFqLookupVerifierIndex, + LookupSelector: napi.WasmFqLookupSelectors, + }), + }; +} + +function verifierIndexConversionPerField( + napi: any, + core: ConversionCore, + { + Domain, + VerificationEvals, + Shifts, + VerifierIndex, + LookupVerifierIndex, + LookupSelector, + }: NapiClasses +) { + function domainToRust([, logSizeOfGroup, groupGen]: Domain): NapiDomain { + return new Domain(logSizeOfGroup, fieldToRust(groupGen)); + } + function domainFromRust(domain: NapiDomain): Domain { + return [0, domain.log_size_of_group, fieldFromRust(domain.group_gen)]; + } + + function verificationEvalsToRust(evals: VerificationEvals): NapiVerificationEvals { + let sigmaComm = core.polyCommsToRust(evals[1]); + let coefficientsComm = core.polyCommsToRust(evals[2]); + let genericComm = core.polyCommToRust(evals[3]); + let psmComm = core.polyCommToRust(evals[4]); + let completeAddComm = core.polyCommToRust(evals[5]); + let mulComm = core.polyCommToRust(evals[6]); + let emulComm = core.polyCommToRust(evals[7]); + let endomulScalarComm = core.polyCommToRust(evals[8]); + let xorComm = MlOption.mapFrom(evals[9], core.polyCommToRust); + let rangeCheck0Comm = MlOption.mapFrom(evals[10], core.polyCommToRust); + let rangeCheck1Comm = MlOption.mapFrom(evals[11], core.polyCommToRust); + let foreignFieldAddComm = MlOption.mapFrom(evals[12], core.polyCommToRust); + let foreignFieldMulComm = MlOption.mapFrom(evals[13], core.polyCommToRust); + let rotComm = MlOption.mapFrom(evals[14], core.polyCommToRust); + return new VerificationEvals( + sigmaComm as any, + coefficientsComm as any, + genericComm as any, + psmComm as any, + completeAddComm as any, + mulComm as any, + emulComm as any, + endomulScalarComm as any, + xorComm as any, + rangeCheck0Comm as any, + rangeCheck1Comm as any, + foreignFieldAddComm as any, + foreignFieldMulComm as any, + rotComm as any + ); + } + function verificationEvalsFromRust(evals: NapiVerificationEvals): VerificationEvals { + let mlEvals: VerificationEvals = [ + 0, + core.polyCommsFromRust(evals.sigma_comm), + core.polyCommsFromRust(evals.coefficients_comm), + core.polyCommFromRust(evals.generic_comm), + core.polyCommFromRust(evals.psm_comm), + core.polyCommFromRust(evals.complete_add_comm), + core.polyCommFromRust(evals.mul_comm), + core.polyCommFromRust(evals.emul_comm), + core.polyCommFromRust(evals.endomul_scalar_comm), + MlOption.mapTo(evals.xor_comm, core.polyCommFromRust), + MlOption.mapTo(evals.range_check0_comm, core.polyCommFromRust), + MlOption.mapTo(evals.range_check1_comm, core.polyCommFromRust), + MlOption.mapTo(evals.foreign_field_add_comm, core.polyCommFromRust), + MlOption.mapTo(evals.foreign_field_mul_comm, core.polyCommFromRust), + MlOption.mapTo(evals.rot_comm, core.polyCommFromRust), + ]; + return mlEvals; + } + + function lookupVerifierIndexToRust(lookup: Lookup): NapiLookupVerifierIndex { + let [ + , + joint_lookup_used, + lookup_table, + selectors, + table_ids, + lookup_info, + runtime_tables_selector, + ] = lookup; + return new LookupVerifierIndex( + MlBool.from(joint_lookup_used), + core.polyCommsToRust(lookup_table) as any, + lookupSelectorsToRust(selectors), + MlOption.mapFrom(table_ids, core.polyCommToRust) as any, + lookupInfoToRust(lookup_info), + MlOption.mapFrom(runtime_tables_selector, core.polyCommToRust) as any + ); + } + function lookupVerifierIndexFromRust(lookup: NapiLookupVerifierIndex): Lookup { + console.log('lookup: ', lookup); + let mlLookup: Lookup = [ + 0, + MlBool(lookup.joint_lookup_used), + core.polyCommsFromRust(lookup.lookup_table), + lookupSelectorsFromRust(lookup.lookup_selectors), + MlOption.mapTo(lookup.table_ids, core.polyCommFromRust), + lookupInfoFromRust(lookup.lookup_info), + MlOption.mapTo(lookup.runtime_tables_selector, core.polyCommFromRust), + ]; + return mlLookup; + } + + function lookupSelectorsToRust([ + , + lookup, + xor, + range_check, + ffmul, + ]: LookupSelectors): NapiLookupSelector { + return new LookupSelector( + MlOption.mapFrom(xor, core.polyCommToRust) as any, + MlOption.mapFrom(lookup, core.polyCommToRust) as any, + MlOption.mapFrom(range_check, core.polyCommToRust) as any, + MlOption.mapFrom(ffmul, core.polyCommToRust) as any + ); + } + function lookupSelectorsFromRust(selector: NapiLookupSelector): LookupSelectors { + let lookup = MlOption.mapTo(selector.lookup, core.polyCommFromRust); + let xor = MlOption.mapTo(selector.xor, core.polyCommFromRust); + let range_check = MlOption.mapTo(selector.range_check, core.polyCommFromRust); + let ffmul = MlOption.mapTo(selector.ffmul, core.polyCommFromRust); + return [0, lookup, xor, range_check, ffmul]; + } + + function lookupInfoToRust([, maxPerRow, maxJointSize, features]: LookupInfo): WasmLookupInfo { + let [, patterns, joint_lookup_used, uses_runtime_tables] = features; + let [, xor, lookup, range_check, foreign_field_mul] = patterns; + let napiPatterns = new napi.LookupPatterns( + MlBool.from(xor), + MlBool.from(lookup), + MlBool.from(range_check), + MlBool.from(foreign_field_mul) + ); + let napiFeatures = new napi.LookupFeatures( + napiPatterns, + MlBool.from(joint_lookup_used), + MlBool.from(uses_runtime_tables) + ); + return new napi.LookupInfo(maxPerRow, maxJointSize, napiFeatures); + } + function lookupInfoFromRust(info: WasmLookupInfo): LookupInfo { + let features = info.features; + let patterns = features.patterns; + let mlInfo: LookupInfo = [ + 0, + info.max_per_row, + info.max_joint_size, + [ + 0, + [ + 0, + MlBool(patterns.xor), + MlBool(patterns.lookup), + MlBool(patterns.range_check), + MlBool(patterns.foreign_field_mul), + ], + MlBool(features.joint_lookup_used), + MlBool(features.uses_runtime_tables), + ], + ]; + return mlInfo; + } + + let self = { + shiftsToRust([, ...shifts]: MlArray): NapiShifts { + let s = shifts.map((s) => fieldToRust(s)); + return new Shifts(s[0], s[1], s[2], s[3], s[4], s[5], s[6]); + }, + shiftsFromRust(s: NapiShifts): MlArray { + let shifts = [s.s0, s.s1, s.s2, s.s3, s.s4, s.s5, s.s6]; + return [0, ...shifts.map(fieldFromRust)]; + }, + + verifierIndexToRust(vk: VerifierIndex): NapiVerifierIndex { + let domain = domainToRust(vk[1]); + let maxPolySize = vk[2]; + let nPublic = vk[3]; + let prevChallenges = vk[4]; + let srs = vk[5]; + let evals = verificationEvalsToRust(vk[6]); + let shifts = self.shiftsToRust(vk[7]); + let lookupIndex = MlOption.mapFrom(vk[8], lookupVerifierIndexToRust); + let zkRows = vk[9]; + return new VerifierIndex( + domain, + maxPolySize, + nPublic, + prevChallenges, + srs, + evals, + shifts, + lookupIndex, + zkRows + ); + }, + verifierIndexFromRust(vk: NapiVerifierIndex): VerifierIndex { + console.log('vk lookup index from rust', vk.lookup_index); + let mlVk: VerifierIndex = [ + 0, + domainFromRust(vk.domain), + vk.max_poly_size, + vk.public_, + vk.prev_challenges, + vk.srs, + verificationEvalsFromRust(vk.evals), + self.shiftsFromRust(vk.shifts), + MlOption.mapTo(vk.lookup_index, lookupVerifierIndexFromRust), + vk.zk_rows, + ]; + return mlVk; + }, + }; + + return self; +} diff --git a/src/bindings/crypto/napi-srs.ts b/src/bindings/crypto/napi-srs.ts new file mode 100644 index 0000000000..cbbae328aa --- /dev/null +++ b/src/bindings/crypto/napi-srs.ts @@ -0,0 +1,358 @@ +import { MlArray } from '../../lib/ml/base.js'; +import { + readCache, + withVersion, + writeCache, + type Cache, + type CacheHeader, +} from '../../lib/proof-system/cache.js'; +import { assert } from '../../lib/util/errors.js'; +import { type WasmFpSrs, type WasmFqSrs } from '../compiled/node_bindings/plonk_wasm.cjs'; +import type { Napi, RustConversion } from './bindings.js'; +import { OrInfinity, OrInfinityJson } from './bindings/curve.js'; +import { PolyComm } from './bindings/kimchi-types.js'; + +export { setSrsCache, srs, unsetSrsCache }; + +type NapiSrs = WasmFpSrs | WasmFqSrs; + +type SrsStore = Record; + +function empty(): SrsStore { + return {}; +} + +const srsStore = { fp: empty(), fq: empty() }; + +const CacheReadRegister = new Map(); + +let cache: Cache | undefined; + +function setSrsCache(c: Cache) { + cache = c; +} +function unsetSrsCache() { + cache = undefined; +} + +const srsVersion = 1; + +function cacheHeaderLagrange(f: 'fp' | 'fq', domainSize: number): CacheHeader { + let id = `lagrange-basis-${f}-${domainSize}`; + return withVersion( + { + kind: 'lagrange-basis', + persistentId: id, + uniqueId: id, + dataType: 'string', + }, + srsVersion + ); +} +function cacheHeaderSrs(f: 'fp' | 'fq', domainSize: number): CacheHeader { + let id = `srs-${f}-${domainSize}`; + return withVersion( + { + kind: 'srs', + persistentId: id, + uniqueId: id, + dataType: 'string', + }, + srsVersion + ); +} + +function srs(napi: Napi, conversion: RustConversion) { + return { + fp: srsPerField('fp', napi, conversion), + fq: srsPerField('fq', napi, conversion), + }; +} + +function srsPerField(f: 'fp' | 'fq', napi: Napi, conversion: RustConversion) { + // note: these functions are properly typed, thanks to TS template literal types + let createSrs = (size: number) => { + try { + console.log(0); + return napi[`caml_${f}_srs_create_parallel`](size); + } catch (error) { + console.error(`Error in SRS get for field ${f}`); + throw error; + } + }; + let getSrs = (srs: NapiSrs) => { + try { + console.log(1); + let v = napi[`caml_${f}_srs_get`](srs); + console.log(2); + return v; + } catch (error) { + console.error(`Error in SRS get for field ${f}`); + throw error; + } + }; + let setSrs = (bytes: any) => { + try { + console.log(2); + return napi[`caml_${f}_srs_set`](bytes); + } catch (error) { + console.error(`Error in SRS set for field ${f} args ${bytes}`); + throw error; + } + }; + + let maybeLagrangeCommitment = (srs: NapiSrs, domain_size: number, i: number) => { + try { + console.log(3); + console.log('srs napi', srs); + /*let bytes = (napi as any)[`caml_${f}_srs_to_bytes`](srs); + console.log('bytes', bytes); + let wasmSrs = undefined; + if (f === 'fp') wasmSrs = (napi as any)[`caml_${f}_srs_from_bytes`](bytes); + else wasmSrs = (napi as any)[`caml_fq_srs_from_bytes`](bytes); + */ + let s = napi[`caml_${f}_srs_maybe_lagrange_commitment`](srs, domain_size, i); + console.log('S', s); + return s; + } catch (error) { + console.error(`Error in SRS maybe lagrange commitment for field ${f}`); + throw error; + } + }; + let lagrangeCommitment = (srs: NapiSrs, domain_size: number, i: number) => { + try { + return napi[`caml_${f}_srs_lagrange_commitment`](srs, domain_size, i); + } catch (error) { + console.error(`Error in SRS lagrange commitment for field ${f}`); + throw error; + } + }; + let setLagrangeBasis = (srs: NapiSrs, domain_size: number, input: any) => { + try { + console.log(6); + return napi[`caml_${f}_srs_set_lagrange_basis`](srs, domain_size, input); + } catch (error) { + console.error(`Error in SRS set lagrange basis for field ${f}`); + throw error; + } + }; + let getLagrangeBasis = (srs: NapiSrs, n: number) => { + try { + return napi[`caml_${f}_srs_get_lagrange_basis`](srs, n); + } catch (error) { + console.error(`Error in SRS get lagrange basis for field ${f}`); + throw error; + } + }; + return { + /** + * returns existing stored SRS or falls back to creating a new one + */ + create(size: number): NapiSrs { + let srs = srsStore[f][size] satisfies NapiSrs as NapiSrs | undefined; + + if (srs === undefined) { + if (cache === undefined) { + // if there is no cache, create SRS in memory + console.log('Creating SRS without cache'); + srs = createSrs(size); + console.log('SRS created without cache:', srs); + } else { + let header = cacheHeaderSrs(f, size); + + // try to read SRS from cache / recompute and write if not found + console.log('Reading SRS from cache'); + srs = readCache(cache, header, (bytes) => { + // TODO: this takes a bit too long, about 300ms for 2^16 + // `pointsToRust` is the clear bottleneck + let jsonSrs: OrInfinityJson[] = JSON.parse(new TextDecoder().decode(bytes)); + let mlSrs = MlArray.mapTo(jsonSrs, OrInfinity.fromJSON); + let wasmSrs = conversion[f].pointsToRust(mlSrs); + return setSrs(wasmSrs); + }); + console.log('SRS read from cache:', srs); + if (srs === undefined) { + // not in cache + console.log(1); + srs = createSrs(size); + console.log('Writing SRS to cache', srs); + + if (cache.canWrite) { + console.log(2); + let wasmSrs = getSrs(srs); + console.log(3); + let mlSrs = conversion[f].pointsFromRust(wasmSrs); + let jsonSrs = MlArray.mapFrom(mlSrs, OrInfinity.toJSON); + let bytes = new TextEncoder().encode(JSON.stringify(jsonSrs)); + + writeCache(cache, header, bytes); + } + } + } + console.log('Storing SRS in memory'); + srsStore[f][size] = srs; + console.log('SRS stored in memory:', srs); + } + + // TODO should we call freeOnFinalize() and expose a function to clean the SRS cache? + console.trace('Returning SRS:', srs); + return srsStore[f][size]; + }, + + /** + * returns ith Lagrange basis commitment for a given domain size + */ + lagrangeCommitment(srs: NapiSrs, domainSize: number, i: number): PolyComm { + console.log('lagrangeCommitment'); + // happy, fast case: if basis is already stored on the srs, return the ith commitment + let commitment = maybeLagrangeCommitment(srs, domainSize, i); + + if (commitment === undefined || commitment === null) { + console.log('comm was undefined'); + if (cache === undefined) { + // if there is no cache, recompute and store basis in memory + commitment = lagrangeCommitment(srs, domainSize, i); + } else { + // try to read lagrange basis from cache / recompute and write if not found + let header = cacheHeaderLagrange(f, domainSize); + let didRead = readCacheLazy( + cache, + header, + conversion, + f, + srs, + domainSize, + setLagrangeBasis + ); + if (didRead !== true) { + // not in cache + if (cache.canWrite) { + // TODO: this code path will throw on the web since `caml_${f}_srs_get_lagrange_basis` is not properly implemented + // using a writable cache in the browser seems to be fairly uncommon though, so it's at least an 80/20 solution + let napiComms = getLagrangeBasis(srs, domainSize); + console.log('napiComms', napiComms); + let mlComms = conversion[f].polyCommsFromRust(napiComms); + console.log('mlComms', mlComms); + let comms = polyCommsToJSON(mlComms); + let bytes = new TextEncoder().encode(JSON.stringify(comms)); + writeCache(cache, header, bytes); + } else { + lagrangeCommitment(srs, domainSize, i); + } + } + // here, basis is definitely stored on the srs + let c = maybeLagrangeCommitment(srs, domainSize, i); + assert(c !== undefined, 'commitment exists after setting'); + commitment = c; + } + } + console.log('commitment was not undefined'); + + // edge case for when we have a writeable cache and the basis was already stored on the srs + // but we didn't store it in the cache separately yet + if (commitment && cache && cache.canWrite) { + let header = cacheHeaderLagrange(f, domainSize); + let didRead = readCacheLazy( + cache, + header, + conversion, + f, + srs, + domainSize, + setLagrangeBasis + ); + // only proceed for entries we haven't written to the cache yet + if (didRead !== true) { + // same code as above - write the lagrange basis to the cache if it wasn't there already + // currently we re-generate the basis via `getLagrangeBasis` - we could derive this from the + // already existing `commitment` instead, but this is simpler and the performance impact is negligible + let napiComms = getLagrangeBasis(srs, domainSize); + let mlComms = conversion[f].polyCommsFromRust(napiComms); + let comms = polyCommsToJSON(mlComms); + let bytes = new TextEncoder().encode(JSON.stringify(comms)); + + writeCache(cache, header, bytes); + } + } + return conversion[f].polyCommFromRust(commitment); + }, + + /** + * Returns the Lagrange basis commitments for the whole domain + */ + lagrangeCommitmentsWholeDomain(srs: NapiSrs, domainSize: number) { + console.log('lagrangeCommitmentsWholeDomain'); + try { + let napiComms = napi[`caml_${f}_srs_lagrange_commitments_whole_domain_ptr`]( + srs, + domainSize + ); + let mlComms = conversion[f].polyCommsFromRust(napiComms as any); + return mlComms; + } catch (error) { + console.error(`Error in SRS lagrange commitments whole domain ptr for field ${f}`); + throw error; + } + }, + + /** + * adds Lagrange basis for a given domain size + */ + addLagrangeBasis(srs: NapiSrs, logSize: number) { + console.log('addLagrangeBasis'); + // this ensures that basis is stored on the srs, no need to duplicate caching logic + this.lagrangeCommitment(srs, 1 << logSize, 0); + }, + }; +} + +type PolyCommJson = { + shifted: OrInfinityJson[]; + unshifted: OrInfinityJson | undefined; +}; + +function polyCommsToJSON(comms: MlArray): PolyCommJson[] { + return MlArray.mapFrom(comms, ([, elems]) => { + return { + shifted: MlArray.mapFrom(elems, OrInfinity.toJSON), + unshifted: undefined, + }; + }); +} + +function polyCommsFromJSON(json: PolyCommJson[]): MlArray { + return MlArray.mapTo(json, ({ shifted, unshifted }) => { + return [0, MlArray.mapTo(shifted, OrInfinity.fromJSON)]; + }); +} + +function readCacheLazy( + cache: Cache, + header: CacheHeader, + conversion: RustConversion, + f: 'fp' | 'fq', + srs: NapiSrs, + domainSize: number, + setLagrangeBasis: (srs: NapiSrs, domainSize: number, comms: Uint32Array) => void +) { + if (CacheReadRegister.get(header.uniqueId) === true) return true; + return readCache(cache, header, (bytes) => { + let comms: PolyCommJson[] = JSON.parse(new TextDecoder().decode(bytes)); + let mlComms = polyCommsFromJSON(comms); + let napiComms = conversion[f].polyCommsToRust(mlComms); + + setLagrangeBasis(srs, domainSize, napiComms); + CacheReadRegister.set(header.uniqueId, true); + return true; + }); +} +function runInTryCatch any>(fn: T): T { + return function (...args: Parameters): ReturnType { + try { + return fn(...args); + } catch (e) { + console.error(`Error in SRS function ${fn.name} with args:`, args); + throw e; + } + } as T; +} diff --git a/src/bindings/ocaml/jsoo_exports/dune b/src/bindings/ocaml/jsoo_exports/dune index 801324c5d6..d2c3233a2b 100644 --- a/src/bindings/ocaml/jsoo_exports/dune +++ b/src/bindings/ocaml/jsoo_exports/dune @@ -70,7 +70,10 @@ (flags +toplevel.js +dynlink.js --pretty --source-map) (link_flags --source-map) (javascript_files overrides.js)) - (libraries o1js_bindings.lib bindings_js.node_backend) + (libraries + o1js_bindings.lib + bindings_js.node_backend + bindings_js.native_backend) (link_deps node_js_plonk_wasm.js node_js_plonk_wasm_bg.wasm) (instrumentation (backend bisect_ppx)) diff --git a/src/bindings/scripts/build-o1js-node-artifacts.sh b/src/bindings/scripts/build-o1js-node-artifacts.sh index 0748a0bd4a..2c5fcc1fee 100755 --- a/src/bindings/scripts/build-o1js-node-artifacts.sh +++ b/src/bindings/scripts/build-o1js-node-artifacts.sh @@ -33,6 +33,7 @@ ok "Mina config files copied" npm run build:wasm:node npm run build:jsoo:node +npm run build:native info "Building transaction layout TypeScript definitions..." run_cmd dune b src/bindings/mina-transaction/gen/v1/js-layout.ts \ diff --git a/src/build/copy-to-dist.js b/src/build/copy-to-dist.js index d2786c8582..6a3db7a1bd 100644 --- a/src/build/copy-to-dist.js +++ b/src/build/copy-to-dist.js @@ -5,6 +5,7 @@ await copyFromTo( [ 'src/bindings.d.ts', 'src/bindings/compiled/_node_bindings', + 'src/bindings/compiled/native', 'src/bindings/compiled/node_bindings/plonk_wasm.d.cts', ], 'src/', diff --git a/src/examples/zkfunction/preimage.ts b/src/examples/zkfunction/preimage.ts index f0e621ba40..bcd48adc5b 100644 --- a/src/examples/zkfunction/preimage.ts +++ b/src/examples/zkfunction/preimage.ts @@ -1,4 +1,4 @@ -import { Poseidon, Field, Experimental } from 'o1js'; +import { Experimental, Field, Poseidon } from 'o1js'; const { ZkFunction } = Experimental; /** @@ -16,17 +16,8 @@ const main = ZkFunction({ }, }); -console.log('compile...'); -const { verificationKey } = await main.compile(); - -const preimage = Field(1); -const hash = Poseidon.hash([preimage]); - -console.log('prove...'); -const pi = await main.prove(hash, preimage); - -console.log('verify...'); -let ok = await main.verify(pi, verificationKey); -console.log('ok?', ok); - -if (!ok) throw Error('verification failed'); +await main.compile(); +console.log('analyze'); +let res = await main.analyzeMethod(); +console.log('done'); +console.log(res); diff --git a/src/lib/proof-system/prover-keys.ts b/src/lib/proof-system/prover-keys.ts index 6b871848d9..122d8bf27b 100644 --- a/src/lib/proof-system/prover-keys.ts +++ b/src/lib/proof-system/prover-keys.ts @@ -5,18 +5,19 @@ * * The inputs are `SnarkKeyHeader` and `SnarkKey`, which are OCaml tagged enums defined in pickles_bindings.ml */ +import { Pickles, wasm } from '../../bindings.js'; import { WasmPastaFpPlonkIndex, WasmPastaFqPlonkIndex, } from '../../bindings/compiled/node_bindings/plonk_wasm.cjs'; -import { Pickles, wasm } from '../../bindings.js'; +// TODO: include conversion bundle to decide between wasm and napi conversion +import { createNativeRustConversion } from '../../bindings/crypto/bindings.js'; import { VerifierIndex } from '../../bindings/crypto/bindings/kimchi-types.js'; -import { getRustConversion } from '../../bindings/crypto/bindings.js'; import { MlString } from '../ml/base.js'; import { CacheHeader, cacheHeaderVersion } from './cache.js'; import type { MethodInterface } from './zkprogram.js'; -export { parseHeader, encodeProverKey, decodeProverKey, SnarkKeyHeader, SnarkKey }; +export { SnarkKey, SnarkKeyHeader, decodeProverKey, encodeProverKey, parseHeader }; export type { MlWrapVerificationKey }; // there are 4 types of snark keys in Pickles which we all handle at once @@ -94,19 +95,23 @@ function encodeProverKey(value: SnarkKey): Uint8Array { switch (value[0]) { case KeyType.StepProvingKey: { let index = value[1][1]; - let encoded = wasm.caml_pasta_fp_plonk_index_encode(index); + let encoded = wasm.caml_pasta_fp_plonk_index_encode( + (wasm as any).prover_index_fp_deserialize((wasm as any).prover_index_fp_serialize(index)) + ); return encoded; } case KeyType.StepVerificationKey: { let vkMl = value[1]; - const rustConversion = getRustConversion(wasm); + const rustConversion = createNativeRustConversion(wasm); let vkWasm = rustConversion.fp.verifierIndexToRust(vkMl); let string = wasm.caml_pasta_fp_plonk_verifier_index_serialize(vkWasm); return new TextEncoder().encode(string); } case KeyType.WrapProvingKey: { let index = value[1][1]; - let encoded = wasm.caml_pasta_fq_plonk_index_encode(index); + let encoded = wasm.caml_pasta_fq_plonk_index_encode( + (wasm as any).prover_index_fq_deserialize((wasm as any).prover_index_fq_serialize(index)) + ); return encoded; } case KeyType.WrapVerificationKey: { @@ -135,7 +140,7 @@ function decodeProverKey(header: SnarkKeyHeader, bytes: Uint8Array): SnarkKey { let srs = Pickles.loadSrsFp(); let string = new TextDecoder().decode(bytes); let vkWasm = wasm.caml_pasta_fp_plonk_verifier_index_deserialize(srs, string); - const rustConversion = getRustConversion(wasm); + const rustConversion = createNativeRustConversion(wasm); let vkMl = rustConversion.fp.verifierIndexFromRust(vkWasm); return [KeyType.StepVerificationKey, vkMl]; } diff --git a/src/mina b/src/mina index 569e99c958..ebfe5d874f 160000 --- a/src/mina +++ b/src/mina @@ -1 +1 @@ -Subproject commit 569e99c95834841d64858644c5d80ac7e63d0157 +Subproject commit ebfe5d874f09b5562d40e9eed6c647310cf9d2f1 diff --git a/src/native/native.ts b/src/native/native.ts new file mode 100644 index 0000000000..59ab905f7d --- /dev/null +++ b/src/native/native.ts @@ -0,0 +1,15 @@ +import { createRequire } from 'node:module'; +const require = createRequire(import.meta.url); + +const { platform, arch } = process; +const slug = `@o1js/native-${platform}-${arch}`; + +export default (() => { + try { + return require(slug); + } catch (e) { + if (process.env.O1JS_REQUIRE_NATIVE_BINDINGS) { + throw e; + } + } +})(); diff --git a/tests/native/native-integration.ts b/tests/native/native-integration.ts new file mode 100644 index 0000000000..a00753f720 --- /dev/null +++ b/tests/native/native-integration.ts @@ -0,0 +1,31 @@ +import native from '../../src/native/native'; +import { Field, ZkProgram, verify } from 'o1js'; + +let MyProgram = ZkProgram({ + name: 'example-with-output', + publicOutput: Field, + methods: { + baseCase: { + privateInputs: [], + async method() { + return { + publicOutput: Field(1), + }; + }, + }, + }, +}); + +console.time('compile (with cache)'); +let { verificationKey } = await MyProgram.compile(); +console.timeEnd('compile (with cache)'); + +console.time('proving'); +let result = await MyProgram.baseCase(); +console.timeEnd('proving'); + +console.log('verifying'); +let ok = await verify(result.proof, verificationKey); +console.log('ok', ok); + +console.log('native calls:', native.getNativeCalls()); diff --git a/tests/native/native.ts b/tests/native/native.ts new file mode 100644 index 0000000000..1b6da18c17 --- /dev/null +++ b/tests/native/native.ts @@ -0,0 +1,17 @@ +import assert from 'node:assert'; +import native from '../../src/native/native'; + +// run with `./run tests/native/native.ts --bundle` + +console.log(native); + +assert(native.getNativeCalls() == 0n, 'native module starts with no calls'); + +// make any call +try { + native.prover_index_fp_from_bytes(new Uint8Array()); +} catch {} + +assert(native.getNativeCalls() >= 1n, 'native module has become active'); + +console.log('assertion of native module activity ok');